* [PATCH 0/5] devres: Add functions + migrate Xillybus driver
@ 2014-05-16 8:26 Eli Billauer
2014-05-16 8:26 ` [PATCH 1/5] devres: Add devm_get_free_pages API Eli Billauer
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
This patchset consists of new functions to the managed device resource
API, followed by patches for the Xillybus driver that now relies on these.
Rationale: While migrating the staging/xillybus driver to rely completely on
managed resources, some functionalities were missing, and hence added:
* devm_get_free_pages()
* devm_free_pages()
* dmam_map_single()
* dmam_unmap_single()
* pcim_map_single()
* pcim_unmap_single()
After applying these patches, the Xillybus driver uses all six functions,
and has been hardware tested on arm and x86_32. A compilation check went
cleanly on x86_64 as well.
Dependencies:
Patch #3 relies on patch #2 (quite obviously).
Patch #5 relies on all previous patches.
Thanks,
Eli
Eli Billauer (5):
devres: Add devm_get_free_pages API
dma-mapping: Add devm_ interface for dma_map_single()
dma-mapping: pci: Add devm_ interface for pci_map_single
staging: xillybus: Use devm_ API on probe and remove
staging: xillybus: Use devm_ API for memory allocation and DMA
mapping
Documentation/driver-model/devres.txt | 6 +
drivers/base/devres.c | 76 ++++++++++++++
drivers/base/dma-mapping.c | 80 +++++++++++++++
drivers/staging/xillybus/xillybus.h | 32 +------
drivers/staging/xillybus/xillybus_core.c | 162 ++++++++----------------------
drivers/staging/xillybus/xillybus_of.c | 99 ++----------------
drivers/staging/xillybus/xillybus_pcie.c | 111 ++++-----------------
include/asm-generic/pci-dma-compat.h | 17 +++
include/linux/device.h | 4 +
include/linux/dma-mapping.h | 5 +-
10 files changed, 261 insertions(+), 331 deletions(-)
--
1.7.2.3
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/5] devres: Add devm_get_free_pages API
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
@ 2014-05-16 8:26 ` Eli Billauer
2014-05-16 21:01 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single() Eli Billauer
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
devm_get_free_pages() and devm_free_pages() are the managed counterparts
for __get_free_pages() and free_pages().
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
Documentation/driver-model/devres.txt | 2 +
drivers/base/devres.c | 76 +++++++++++++++++++++++++++++++++
include/linux/device.h | 4 ++
3 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 4999518..e1a2707 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -237,6 +237,8 @@ MEM
devm_kzalloc()
devm_kfree()
devm_kmemdup()
+ devm_get_free_pages()
+ devm_free_pages()
IIO
devm_iio_device_alloc()
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index d0914cb..5230294 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -852,3 +852,79 @@ void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
return p;
}
EXPORT_SYMBOL_GPL(devm_kmemdup);
+
+struct pages_devres {
+ unsigned long addr;
+ unsigned int order;
+};
+
+static int devm_pages_match(struct device *dev, void *res, void *p)
+{
+ struct pages_devres *devres = res;
+ struct pages_devres *target = p;
+
+ return devres->addr == target->addr;
+}
+
+static void devm_pages_release(struct device *dev, void *res)
+{
+ struct pages_devres *devres = res;
+
+ free_pages(devres->addr, devres->order);
+}
+
+/**
+ * devm_get_free_pages - Resource-managed __get_free_pages
+ * @dev: Device to allocate memory for
+ * @gfp_mask: Allocation gfp flags
+ * @order: Allocation size is (1 << order) pages
+ *
+ * Managed get_free_pages. Memory allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * RETURNS:
+ * Address of allocated memory on success, 0 on failure.
+ */
+
+unsigned long devm_get_free_pages(struct device *dev,
+ gfp_t gfp_mask, unsigned int order)
+{
+ struct pages_devres *devres;
+ unsigned long addr;
+
+ addr = __get_free_pages(gfp_mask, order);
+
+ if (unlikely(!addr))
+ return 0;
+
+ devres = devres_alloc(devm_pages_release,
+ sizeof(struct pages_devres), GFP_KERNEL);
+ if (unlikely(!devres)) {
+ free_pages(addr, order);
+ return 0;
+ }
+
+ devres->addr = addr;
+ devres->order = order;
+
+ devres_add(dev, devres);
+ return addr;
+}
+EXPORT_SYMBOL_GPL(devm_get_free_pages);
+
+/**
+ * devm_free_pages - Resource-managed free_pages
+ * @dev: Device this memory belongs to
+ * @addr: Memory to free
+ *
+ * Free memory allocated with devm_get_free_pages(). Unlike free_pages,
+ * there is no need to supply the @order.
+ */
+void devm_free_pages(struct device *dev, unsigned long addr)
+{
+ struct pages_devres devres = { .addr = addr };
+
+ WARN_ON(devres_release(dev, devm_pages_release, devm_pages_match,
+ &devres));
+}
+EXPORT_SYMBOL_GPL(devm_free_pages);
diff --git a/include/linux/device.h b/include/linux/device.h
index ab87158..3dc69a2 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -626,6 +626,10 @@ extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
gfp_t gfp);
+extern unsigned long devm_get_free_pages(struct device *dev,
+ gfp_t gfp_mask, unsigned int order);
+extern void devm_free_pages(struct device *dev, unsigned long addr);
+
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
void __iomem *devm_request_and_ioremap(struct device *dev,
struct resource *res);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
2014-05-16 8:26 ` [PATCH 1/5] devres: Add devm_get_free_pages API Eli Billauer
@ 2014-05-16 8:26 ` Eli Billauer
2014-05-16 21:08 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single Eli Billauer
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
dmam_map_single() and dmam_unmap_single() are the managed counterparts
for the respective dma_* functions.
Note that dmam_map_single() returns zero on failure, and not a value to
be handled by dma_mapping_error(): The error check is done by
dmam_map_single() to avoid the registration of a mapping that failed.
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
Documentation/driver-model/devres.txt | 2 +
drivers/base/dma-mapping.c | 80 +++++++++++++++++++++++++++++++++
include/linux/dma-mapping.h | 5 ++-
3 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index e1a2707..13b8be0 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -266,6 +266,8 @@ DMA
dmam_declare_coherent_memory()
dmam_pool_create()
dmam_pool_destroy()
+ dmam_map_single()
+ dmam_unmap_single()
PCI
pcim_enable_device() : after success, all PCI ops become managed
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 0ce39a3..db1c496 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -19,6 +19,7 @@ struct dma_devres {
size_t size;
void *vaddr;
dma_addr_t dma_handle;
+ enum dma_data_direction direction;
};
static void dmam_coherent_release(struct device *dev, void *res)
@@ -267,3 +268,82 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
return ret;
}
EXPORT_SYMBOL(dma_common_mmap);
+
+static int dmam_map_match(struct device *dev, void *res, void *match_data)
+{
+ struct dma_devres *this = res, *match = match_data;
+
+ if (this->dma_handle == match->dma_handle) {
+ WARN_ON(this->size != match->size ||
+ this->direction != match->direction);
+ return 1;
+ }
+ return 0;
+}
+
+static void dmam_map_single_release(struct device *dev, void *res)
+{
+ struct dma_devres *this = res;
+
+ dma_unmap_single(dev, this->dma_handle, this->size, this->direction);
+}
+
+/**
+ * dmam_map_single - Managed dma_map_single()
+ * @dev: Device to map DMA region for
+ * @ptr: Pointer to region
+ * @size: Size to map
+ * @direction: The mapping's direction
+ *
+ * Managed dma_map_single(). The region mapped using this
+ * function will be automatically unmapped on driver detach.
+ *
+ * RETURNS:
+ * The DMA handle of the mapped region upon success, 0 otherwise.
+ */
+dma_addr_t dmam_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+
+{
+ struct dma_devres *dr;
+ dma_addr_t dma_handle;
+
+ dr = devres_alloc(dmam_map_single_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return 0;
+
+ dma_handle = dma_map_single(dev, ptr, size, direction);
+ if (dma_mapping_error(dev, dma_handle)) {
+ devres_free(dr);
+ return 0;
+ }
+
+ dr->vaddr = ptr;
+ dr->dma_handle = dma_handle;
+ dr->size = size;
+ dr->direction = direction;
+
+ devres_add(dev, dr);
+
+ return dma_handle;
+}
+EXPORT_SYMBOL(dmam_map_single);
+
+/**
+ * dmam_unmap_single - Managed dma_unmap_single()
+ * @dev: Device to map DMA region for
+ * @dma_handle: DMA handle of the region to unmap
+ * @size: Size to unmap
+ * @direction: The mapping's direction
+ *
+ * Managed dma_unmap_single().
+ */
+void dmam_unmap_single(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ struct dma_devres match_data = { size, NULL, dma_handle, direction };
+
+ WARN_ON(devres_release(dev, dmam_map_single_release, dmam_map_match,
+ &match_data));
+}
+EXPORT_SYMBOL(dmam_unmap_single);
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index fd4aee2..cdb14a8 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -233,7 +233,10 @@ static inline void dmam_release_declared_memory(struct device *dev)
{
}
#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
-
+dma_addr_t dmam_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction);
+void dmam_unmap_single(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction);
#ifndef CONFIG_HAVE_DMA_ATTRS
struct dma_attrs;
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
2014-05-16 8:26 ` [PATCH 1/5] devres: Add devm_get_free_pages API Eli Billauer
2014-05-16 8:26 ` [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single() Eli Billauer
@ 2014-05-16 8:26 ` Eli Billauer
2014-05-16 21:09 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 4/5] staging: xillybus: Use devm_ API on probe and remove Eli Billauer
2014-05-16 8:26 ` [PATCH 5/5] staging: xillybus: Use devm_ API for memory allocation and DMA mapping Eli Billauer
4 siblings, 1 reply; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
Documentation/driver-model/devres.txt | 2 ++
include/asm-generic/pci-dma-compat.h | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 13b8be0..09b03c9 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -272,6 +272,8 @@ DMA
PCI
pcim_enable_device() : after success, all PCI ops become managed
pcim_pin_device() : keep PCI device enabled after release
+ pcim_map_single()
+ pcim_unmap_single()
IOMAP
devm_ioport_map()
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h
index 1437b7d..444e598 100644
--- a/include/asm-generic/pci-dma-compat.h
+++ b/include/asm-generic/pci-dma-compat.h
@@ -113,4 +113,21 @@ static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
}
#endif
+/*
+ * Managed DMA API
+ */
+
+static inline dma_addr_t
+pcim_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+{
+ return dmam_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pcim_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+ dmam_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
+}
+
#endif
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/5] staging: xillybus: Use devm_ API on probe and remove
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
` (2 preceding siblings ...)
2014-05-16 8:26 ` [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single Eli Billauer
@ 2014-05-16 8:26 ` Eli Billauer
2014-05-16 8:26 ` [PATCH 5/5] staging: xillybus: Use devm_ API for memory allocation and DMA mapping Eli Billauer
4 siblings, 0 replies; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
Suggested-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
drivers/staging/xillybus/xillybus.h | 1 -
drivers/staging/xillybus/xillybus_core.c | 2 +-
drivers/staging/xillybus/xillybus_of.c | 47 ++++-----------------
drivers/staging/xillybus/xillybus_pcie.c | 65 ++++++++----------------------
4 files changed, 27 insertions(+), 88 deletions(-)
diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h
index e5e91d6..78a749a 100644
--- a/drivers/staging/xillybus/xillybus.h
+++ b/drivers/staging/xillybus/xillybus.h
@@ -116,7 +116,6 @@ struct xilly_endpoint {
*/
struct pci_dev *pdev;
struct device *dev;
- struct resource res; /* OF devices only */
struct xilly_endpoint_hardware *ephw;
struct list_head ep_list;
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c
index b0a6696..fe8f9d2 100644
--- a/drivers/staging/xillybus/xillybus_core.c
+++ b/drivers/staging/xillybus/xillybus_core.c
@@ -2094,7 +2094,7 @@ struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
{
struct xilly_endpoint *endpoint;
- endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+ endpoint = devm_kzalloc(dev, sizeof(*endpoint), GFP_KERNEL);
if (!endpoint) {
dev_err(dev, "Failed to allocate memory. Aborting.\n");
return NULL;
diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c
index 23a609b..46ea010 100644
--- a/drivers/staging/xillybus/xillybus_of.c
+++ b/drivers/staging/xillybus/xillybus_of.c
@@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
+#include <linux/err.h>
#include "xillybus.h"
MODULE_DESCRIPTION("Xillybus driver for Open Firmware");
@@ -123,6 +124,7 @@ static int xilly_drv_probe(struct platform_device *op)
struct xilly_endpoint *endpoint;
int rc = 0;
int irq;
+ struct resource res;
struct xilly_endpoint_hardware *ephw = &of_hw;
if (of_property_read_bool(dev->of_node, "dma-coherent"))
@@ -135,38 +137,26 @@ static int xilly_drv_probe(struct platform_device *op)
dev_set_drvdata(dev, endpoint);
- rc = of_address_to_resource(dev->of_node, 0, &endpoint->res);
+ rc = of_address_to_resource(dev->of_node, 0, &res);
if (rc) {
dev_warn(endpoint->dev,
"Failed to obtain device tree resource\n");
- goto failed_request_regions;
+ return rc;
}
- if (!request_mem_region(endpoint->res.start,
- resource_size(&endpoint->res), xillyname)) {
- dev_err(endpoint->dev,
- "request_mem_region failed. Aborting.\n");
- rc = -EBUSY;
- goto failed_request_regions;
- }
+ endpoint->registers = devm_ioremap_resource(dev, &res);
- endpoint->registers = of_iomap(dev->of_node, 0);
- if (!endpoint->registers) {
- dev_err(endpoint->dev,
- "Failed to map I/O memory. Aborting.\n");
- rc = -EIO;
- goto failed_iomap0;
- }
+ if (IS_ERR(endpoint->registers))
+ return PTR_ERR(endpoint->registers);
irq = irq_of_parse_and_map(dev->of_node, 0);
- rc = request_irq(irq, xillybus_isr, 0, xillyname, endpoint);
+ rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint);
if (rc) {
dev_err(endpoint->dev,
"Failed to register IRQ handler. Aborting.\n");
- rc = -ENODEV;
- goto failed_register_irq;
+ return -ENODEV;
}
rc = xillybus_endpoint_discovery(endpoint);
@@ -174,18 +164,8 @@ static int xilly_drv_probe(struct platform_device *op)
if (!rc)
return 0;
- free_irq(irq, endpoint);
-
-failed_register_irq:
- iounmap(endpoint->registers);
-failed_iomap0:
- release_mem_region(endpoint->res.start,
- resource_size(&endpoint->res));
-
-failed_request_regions:
xillybus_do_cleanup(&endpoint->cleanup, endpoint);
- kfree(endpoint);
return rc;
}
@@ -193,20 +173,11 @@ static int xilly_drv_remove(struct platform_device *op)
{
struct device *dev = &op->dev;
struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
- int irq = irq_of_parse_and_map(dev->of_node, 0);
xillybus_endpoint_remove(endpoint);
- free_irq(irq, endpoint);
-
- iounmap(endpoint->registers);
- release_mem_region(endpoint->res.start,
- resource_size(&endpoint->res));
-
xillybus_do_cleanup(&endpoint->cleanup, endpoint);
- kfree(endpoint);
-
return 0;
}
diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c
index 51426d8..a4fe51c 100644
--- a/drivers/staging/xillybus/xillybus_pcie.c
+++ b/drivers/staging/xillybus/xillybus_pcie.c
@@ -141,38 +141,32 @@ static int xilly_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, endpoint);
- rc = pci_enable_device(pdev);
-
- /* L0s has caused packet drops. No power saving, thank you. */
-
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+ rc = pcim_enable_device(pdev);
if (rc) {
dev_err(endpoint->dev,
- "pci_enable_device() failed. Aborting.\n");
- goto no_enable;
+ "pcim_enable_device() failed. Aborting.\n");
+ return rc;
}
+ /* L0s has caused packet drops. No power saving, thank you. */
+
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
dev_err(endpoint->dev,
"Incorrect BAR configuration. Aborting.\n");
- rc = -ENODEV;
- goto bad_bar;
+ return -ENODEV;
}
- rc = pci_request_regions(pdev, xillyname);
+ rc = pcim_iomap_regions(pdev, 0x01, xillyname);
if (rc) {
dev_err(endpoint->dev,
- "pci_request_regions() failed. Aborting.\n");
- goto failed_request_regions;
+ "pcim_iomap_regions() failed. Aborting.\n");
+ return rc;
}
- endpoint->registers = pci_iomap(pdev, 0, 128);
- if (!endpoint->registers) {
- dev_err(endpoint->dev, "Failed to map BAR 0. Aborting.\n");
- rc = -EIO;
- goto failed_iomap0;
- }
+ endpoint->registers = pcim_iomap_table(pdev)[0];
pci_set_master(pdev);
@@ -180,16 +174,15 @@ static int xilly_probe(struct pci_dev *pdev,
if (pci_enable_msi(pdev)) {
dev_err(endpoint->dev,
"Failed to enable MSI interrupts. Aborting.\n");
- rc = -ENODEV;
- goto failed_enable_msi;
+ return -ENODEV;
}
- rc = request_irq(pdev->irq, xillybus_isr, 0, xillyname, endpoint);
+ rc = devm_request_irq(&pdev->dev, pdev->irq, xillybus_isr, 0,
+ xillyname, endpoint);
if (rc) {
dev_err(endpoint->dev,
"Failed to register MSI handler. Aborting.\n");
- rc = -ENODEV;
- goto failed_register_msi;
+ return -ENODEV;
}
/*
@@ -203,8 +196,7 @@ static int xilly_probe(struct pci_dev *pdev,
endpoint->dma_using_dac = 0;
else {
dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
- rc = -ENODEV;
- goto failed_dmamask;
+ return -ENODEV;
}
rc = xillybus_endpoint_discovery(endpoint);
@@ -212,22 +204,8 @@ static int xilly_probe(struct pci_dev *pdev,
if (!rc)
return 0;
-failed_dmamask:
- free_irq(pdev->irq, endpoint);
-failed_register_msi:
- pci_disable_msi(pdev);
-failed_enable_msi:
- /* pci_clear_master(pdev); Nobody else seems to do this */
- pci_iounmap(pdev, endpoint->registers);
-failed_iomap0:
- pci_release_regions(pdev);
-failed_request_regions:
-bad_bar:
- pci_disable_device(pdev);
-no_enable:
xillybus_do_cleanup(&endpoint->cleanup, endpoint);
- kfree(endpoint);
return rc;
}
@@ -237,16 +215,7 @@ static void xilly_remove(struct pci_dev *pdev)
xillybus_endpoint_remove(endpoint);
- free_irq(pdev->irq, endpoint);
-
- pci_disable_msi(pdev);
- pci_iounmap(pdev, endpoint->registers);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
-
xillybus_do_cleanup(&endpoint->cleanup, endpoint);
-
- kfree(endpoint);
}
MODULE_DEVICE_TABLE(pci, xillyids);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/5] staging: xillybus: Use devm_ API for memory allocation and DMA mapping
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
` (3 preceding siblings ...)
2014-05-16 8:26 ` [PATCH 4/5] staging: xillybus: Use devm_ API on probe and remove Eli Billauer
@ 2014-05-16 8:26 ` Eli Billauer
4 siblings, 0 replies; 13+ messages in thread
From: Eli Billauer @ 2014-05-16 8:26 UTC (permalink / raw)
To: gregkh; +Cc: devel, tj, linux-kernel, Eli Billauer
Managed device resource API replaces code that reinvents it for memory
allocation, page allocation and DMA mapping.
Suggested-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
---
drivers/staging/xillybus/xillybus.h | 31 +------
drivers/staging/xillybus/xillybus_core.c | 160 ++++++++----------------------
drivers/staging/xillybus/xillybus_of.c | 54 +----------
drivers/staging/xillybus/xillybus_pcie.c | 46 +--------
4 files changed, 48 insertions(+), 243 deletions(-)
diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h
index 78a749a..88bb6e5 100644
--- a/drivers/staging/xillybus/xillybus.h
+++ b/drivers/staging/xillybus/xillybus.h
@@ -25,33 +25,12 @@
struct xilly_endpoint_hardware;
-struct xilly_page {
- struct list_head node;
- unsigned long addr;
- unsigned int order;
-};
-
-struct xilly_dma {
- struct list_head node;
- struct pci_dev *pdev;
- struct device *dev;
- dma_addr_t dma_addr;
- size_t size;
- int direction;
-};
-
struct xilly_buffer {
void *addr;
dma_addr_t dma_addr;
int end_offset; /* Counting elements, not bytes */
};
-struct xilly_cleanup {
- struct list_head to_kfree;
- struct list_head to_pagefree;
- struct list_head to_unmap;
-};
-
struct xilly_idt_handle {
unsigned char *chandesc;
unsigned char *idt;
@@ -126,9 +105,6 @@ struct xilly_endpoint {
struct mutex register_mutex;
wait_queue_head_t ep_wait;
- /* List of memory allocations, to make release easy */
- struct xilly_cleanup cleanup;
-
/* Channels and message handling */
struct cdev cdev;
@@ -156,19 +132,14 @@ struct xilly_endpoint_hardware {
dma_addr_t,
size_t,
int);
- dma_addr_t (*map_single)(struct xilly_cleanup *,
- struct xilly_endpoint *,
+ dma_addr_t (*map_single)(struct xilly_endpoint *,
void *,
size_t,
int);
- void (*unmap_single)(struct xilly_dma *entry);
};
irqreturn_t xillybus_isr(int irq, void *data);
-void xillybus_do_cleanup(struct xilly_cleanup *mem,
- struct xilly_endpoint *endpoint);
-
struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
struct device *dev,
struct xilly_endpoint_hardware
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c
index fe8f9d2..ff78937 100644
--- a/drivers/staging/xillybus/xillybus_core.c
+++ b/drivers/staging/xillybus/xillybus_core.c
@@ -311,85 +311,14 @@ EXPORT_SYMBOL(xillybus_isr);
* no locks are applied!
*/
-void xillybus_do_cleanup(struct xilly_cleanup *mem,
- struct xilly_endpoint *endpoint)
-{
- struct list_head *this, *next;
-
- list_for_each_safe(this, next, &mem->to_unmap) {
- struct xilly_dma *entry =
- list_entry(this, struct xilly_dma, node);
-
- endpoint->ephw->unmap_single(entry);
- kfree(entry);
- }
-
- INIT_LIST_HEAD(&mem->to_unmap);
-
- list_for_each_safe(this, next, &mem->to_kfree)
- kfree(this);
-
- INIT_LIST_HEAD(&mem->to_kfree);
-
- list_for_each_safe(this, next, &mem->to_pagefree) {
- struct xilly_page *entry =
- list_entry(this, struct xilly_page, node);
-
- free_pages(entry->addr, entry->order);
- kfree(entry);
- }
- INIT_LIST_HEAD(&mem->to_pagefree);
-}
-EXPORT_SYMBOL(xillybus_do_cleanup);
-
-static void *xilly_malloc(struct xilly_cleanup *mem, size_t size)
-{
- void *ptr;
-
- ptr = kzalloc(sizeof(struct list_head) + size, GFP_KERNEL);
-
- if (!ptr)
- return ptr;
-
- list_add_tail((struct list_head *) ptr, &mem->to_kfree);
-
- return ptr + sizeof(struct list_head);
-}
-
-static unsigned long xilly_pagealloc(struct xilly_cleanup *mem,
- unsigned long order)
-{
- unsigned long addr;
- struct xilly_page *this;
-
- this = kmalloc(sizeof(struct xilly_page), GFP_KERNEL);
- if (!this)
- return 0;
-
- addr = __get_free_pages(GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO, order);
-
- if (!addr) {
- kfree(this);
- return 0;
- }
-
- this->addr = addr;
- this->order = order;
-
- list_add_tail(&this->node, &mem->to_pagefree);
-
- return addr;
-}
-
-
static void xillybus_autoflush(struct work_struct *work);
static int xilly_setupchannels(struct xilly_endpoint *ep,
- struct xilly_cleanup *mem,
unsigned char *chandesc,
int entries
)
{
+ struct device *dev = ep->dev;
int i, entry, wr_nbuffer, rd_nbuffer;
struct xilly_channel *channel;
int channelnum, bufnum, bufsize, format, is_writebuf;
@@ -402,17 +331,19 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
int left_of_rd_salami = 0;
dma_addr_t dma_addr;
int msg_buf_done = 0;
+ const gfp_t gfp_mask = GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO;
struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */
- channel = xilly_malloc(mem, ep->num_channels *
- sizeof(struct xilly_channel));
+ channel = devm_kzalloc(dev, ep->num_channels *
+ sizeof(struct xilly_channel), GFP_KERNEL);
if (!channel)
goto memfail;
- ep->channels = xilly_malloc(mem, (ep->num_channels + 1) *
- sizeof(struct xilly_channel *));
+ ep->channels = devm_kzalloc(dev, (ep->num_channels + 1) *
+ sizeof(struct xilly_channel *),
+ GFP_KERNEL);
if (!ep->channels)
goto memfail;
@@ -501,16 +432,16 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
channel->rd_exclusive_open = exclusive_open;
channel->seekable = seekable;
- channel->rd_buffers = xilly_malloc(
- mem,
- bufnum * sizeof(struct xilly_buffer *));
+ channel->rd_buffers = devm_kzalloc(dev,
+ bufnum * sizeof(struct xilly_buffer *),
+ GFP_KERNEL);
if (!channel->rd_buffers)
goto memfail;
- this_buffer = xilly_malloc(
- mem,
- bufnum * sizeof(struct xilly_buffer));
+ this_buffer = devm_kzalloc(dev,
+ bufnum * sizeof(struct xilly_buffer),
+ GFP_KERNEL);
if (!this_buffer)
goto memfail;
@@ -530,16 +461,16 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
channel->wr_synchronous = synchronous;
channel->wr_exclusive_open = exclusive_open;
- channel->wr_buffers = xilly_malloc(
- mem,
- bufnum * sizeof(struct xilly_buffer *));
+ channel->wr_buffers = devm_kzalloc(dev,
+ bufnum * sizeof(struct xilly_buffer *),
+ GFP_KERNEL);
if (!channel->wr_buffers)
goto memfail;
- this_buffer = xilly_malloc(
- mem,
- bufnum * sizeof(struct xilly_buffer));
+ this_buffer = devm_kzalloc(dev,
+ bufnum * sizeof(struct xilly_buffer),
+ GFP_KERNEL);
if (!this_buffer)
goto memfail;
@@ -576,15 +507,16 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
}
wr_salami = (void *)
- xilly_pagealloc(mem,
- allocorder);
+ devm_get_free_pages(
+ dev, gfp_mask,
+ allocorder);
+
if (!wr_salami)
goto memfail;
left_of_wr_salami = allocsize;
}
dma_addr = ep->ephw->map_single(
- mem,
ep,
wr_salami,
bytebufsize,
@@ -654,8 +586,8 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
}
rd_salami = (void *)
- xilly_pagealloc(
- mem,
+ devm_get_free_pages(
+ dev, gfp_mask,
allocorder);
if (!rd_salami)
@@ -664,7 +596,6 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
}
dma_addr = ep->ephw->map_single(
- mem,
ep,
rd_salami,
bytebufsize,
@@ -2103,9 +2034,6 @@ struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
endpoint->pdev = pdev;
endpoint->dev = dev;
endpoint->ephw = ephw;
- INIT_LIST_HEAD(&endpoint->cleanup.to_kfree);
- INIT_LIST_HEAD(&endpoint->cleanup.to_pagefree);
- INIT_LIST_HEAD(&endpoint->cleanup.to_unmap);
endpoint->msg_counter = 0x0b;
endpoint->failed_messages = 0;
endpoint->fatal_error = 0;
@@ -2131,7 +2059,7 @@ static int xilly_quiesce(struct xilly_endpoint *endpoint)
if (endpoint->idtlen < 0) {
dev_err(endpoint->dev,
- "Failed to quiesce the device on exit. Quitting while leaving a mess.\n");
+ "Failed to quiesce the device on exit.\n");
return -ENODEV;
}
return 0; /* Success */
@@ -2141,8 +2069,9 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
{
int rc = 0;
- struct xilly_cleanup tmpmem;
+ void *bootstrap_resources;
int idtbuffersize = (1 << PAGE_SHIFT);
+ struct device *dev = endpoint->dev;
/*
* The bogus IDT is used during bootstrap for allocating the initial
@@ -2155,10 +2084,6 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
3, 192, PAGE_SHIFT, 0 };
struct xilly_idt_handle idt_handle;
- INIT_LIST_HEAD(&tmpmem.to_kfree);
- INIT_LIST_HEAD(&tmpmem.to_pagefree);
- INIT_LIST_HEAD(&tmpmem.to_unmap);
-
/*
* Writing the value 0x00000001 to Endianness register signals which
* endianness this processor is using, so the FPGA can swap words as
@@ -2170,12 +2095,16 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
/* Bootstrap phase I: Allocate temporary message buffer */
+ bootstrap_resources = devres_open_group(dev, NULL, GFP_KERNEL);
+ if (!bootstrap_resources)
+ return -ENOMEM;
+
endpoint->num_channels = 0;
- rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 1);
+ rc = xilly_setupchannels(endpoint, bogus_idt, 1);
if (rc)
- goto failed_buffers;
+ return rc;
/* Clear the message subsystem (and counter in particular) */
iowrite32(0x04, &endpoint->registers[fpga_msg_ctrl_reg]);
@@ -2199,8 +2128,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
if (endpoint->idtlen < 0) {
dev_err(endpoint->dev, "No response from FPGA. Aborting.\n");
- rc = -ENODEV;
- goto failed_quiesce;
+ return -ENODEV;
}
/* Enable DMA */
@@ -2216,7 +2144,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
endpoint->num_channels = 1;
- rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 2);
+ rc = xilly_setupchannels(endpoint, bogus_idt, 2);
if (rc)
goto failed_idt;
@@ -2234,10 +2162,12 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
rc = -ENODEV;
goto failed_idt;
}
+
+ devres_close_group(dev, bootstrap_resources);
+
/* Bootstrap phase III: Allocate buffers according to IDT */
rc = xilly_setupchannels(endpoint,
- &endpoint->cleanup,
idt_handle.chandesc,
idt_handle.entries);
@@ -2260,7 +2190,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
if (rc)
goto failed_chrdevs;
- xillybus_do_cleanup(&tmpmem, endpoint);
+ devres_release_group(dev, bootstrap_resources);
return 0;
@@ -2270,16 +2200,8 @@ failed_chrdevs:
mutex_unlock(&ep_list_lock);
failed_idt:
- /* Quiesce the device. Now it's serious to do it */
- rc = xilly_quiesce(endpoint);
-
- if (rc)
- return rc; /* FPGA may still DMA, so no release */
-
+ xilly_quiesce(endpoint);
flush_workqueue(xillybus_wq);
-failed_quiesce:
-failed_buffers:
- xillybus_do_cleanup(&tmpmem, endpoint);
return rc;
}
diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c
index 46ea010..0e4a67c 100644
--- a/drivers/staging/xillybus/xillybus_of.c
+++ b/drivers/staging/xillybus/xillybus_of.c
@@ -62,44 +62,13 @@ static void xilly_dma_sync_single_nop(struct xilly_endpoint *ep,
{
}
-static dma_addr_t xilly_map_single_of(struct xilly_cleanup *mem,
- struct xilly_endpoint *ep,
+static dma_addr_t xilly_map_single_of(struct xilly_endpoint *ep,
void *ptr,
size_t size,
int direction
)
{
-
- dma_addr_t addr = 0;
- struct xilly_dma *this;
-
- this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL);
- if (!this)
- return 0;
-
- addr = dma_map_single(ep->dev, ptr, size, direction);
- this->direction = direction;
-
- if (dma_mapping_error(ep->dev, addr)) {
- kfree(this);
- return 0;
- }
-
- this->dma_addr = addr;
- this->dev = ep->dev;
- this->size = size;
-
- list_add_tail(&this->node, &mem->to_unmap);
-
- return addr;
-}
-
-static void xilly_unmap_single_of(struct xilly_dma *entry)
-{
- dma_unmap_single(entry->dev,
- entry->dma_addr,
- entry->size,
- entry->direction);
+ return dmam_map_single(ep->dev, ptr, size, direction);
}
static struct xilly_endpoint_hardware of_hw = {
@@ -107,7 +76,6 @@ static struct xilly_endpoint_hardware of_hw = {
.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
.map_single = xilly_map_single_of,
- .unmap_single = xilly_unmap_single_of
};
static struct xilly_endpoint_hardware of_hw_coherent = {
@@ -115,7 +83,6 @@ static struct xilly_endpoint_hardware of_hw_coherent = {
.hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop,
.hw_sync_sgl_for_device = xilly_dma_sync_single_nop,
.map_single = xilly_map_single_of,
- .unmap_single = xilly_unmap_single_of
};
static int xilly_drv_probe(struct platform_device *op)
@@ -138,12 +105,6 @@ static int xilly_drv_probe(struct platform_device *op)
dev_set_drvdata(dev, endpoint);
rc = of_address_to_resource(dev->of_node, 0, &res);
- if (rc) {
- dev_warn(endpoint->dev,
- "Failed to obtain device tree resource\n");
- return rc;
- }
-
endpoint->registers = devm_ioremap_resource(dev, &res);
if (IS_ERR(endpoint->registers))
@@ -159,14 +120,7 @@ static int xilly_drv_probe(struct platform_device *op)
return -ENODEV;
}
- rc = xillybus_endpoint_discovery(endpoint);
-
- if (!rc)
- return 0;
-
- xillybus_do_cleanup(&endpoint->cleanup, endpoint);
-
- return rc;
+ return xillybus_endpoint_discovery(endpoint);
}
static int xilly_drv_remove(struct platform_device *op)
@@ -176,8 +130,6 @@ static int xilly_drv_remove(struct platform_device *op)
xillybus_endpoint_remove(endpoint);
- xillybus_do_cleanup(&endpoint->cleanup, endpoint);
-
return 0;
}
diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c
index a4fe51c..a7d60c7 100644
--- a/drivers/staging/xillybus/xillybus_pcie.c
+++ b/drivers/staging/xillybus/xillybus_pcie.c
@@ -78,46 +78,16 @@ static void xilly_dma_sync_single_for_device_pci(struct xilly_endpoint *ep,
* but that can change.
*/
-static dma_addr_t xilly_map_single_pci(struct xilly_cleanup *mem,
- struct xilly_endpoint *ep,
+static dma_addr_t xilly_map_single_pci(struct xilly_endpoint *ep,
void *ptr,
size_t size,
int direction
)
{
-
- dma_addr_t addr = 0;
- struct xilly_dma *this;
int pci_direction;
- this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL);
- if (!this)
- return 0;
-
pci_direction = xilly_pci_direction(direction);
- addr = pci_map_single(ep->pdev, ptr, size, pci_direction);
- this->direction = pci_direction;
-
- if (pci_dma_mapping_error(ep->pdev, addr)) {
- kfree(this);
- return 0;
- }
-
- this->dma_addr = addr;
- this->pdev = ep->pdev;
- this->size = size;
-
- list_add_tail(&this->node, &mem->to_unmap);
-
- return addr;
-}
-
-static void xilly_unmap_single_pci(struct xilly_dma *entry)
-{
- pci_unmap_single(entry->pdev,
- entry->dma_addr,
- entry->size,
- entry->direction);
+ return pcim_map_single(ep->pdev, ptr, size, pci_direction);
}
static struct xilly_endpoint_hardware pci_hw = {
@@ -125,7 +95,6 @@ static struct xilly_endpoint_hardware pci_hw = {
.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_pci,
.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_pci,
.map_single = xilly_map_single_pci,
- .unmap_single = xilly_unmap_single_pci
};
static int xilly_probe(struct pci_dev *pdev,
@@ -199,14 +168,7 @@ static int xilly_probe(struct pci_dev *pdev,
return -ENODEV;
}
- rc = xillybus_endpoint_discovery(endpoint);
-
- if (!rc)
- return 0;
-
- xillybus_do_cleanup(&endpoint->cleanup, endpoint);
-
- return rc;
+ return xillybus_endpoint_discovery(endpoint);
}
static void xilly_remove(struct pci_dev *pdev)
@@ -214,8 +176,6 @@ static void xilly_remove(struct pci_dev *pdev)
struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);
xillybus_endpoint_remove(endpoint);
-
- xillybus_do_cleanup(&endpoint->cleanup, endpoint);
}
MODULE_DEVICE_TABLE(pci, xillyids);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/5] devres: Add devm_get_free_pages API
2014-05-16 8:26 ` [PATCH 1/5] devres: Add devm_get_free_pages API Eli Billauer
@ 2014-05-16 21:01 ` Tejun Heo
0 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2014-05-16 21:01 UTC (permalink / raw)
To: Eli Billauer; +Cc: gregkh, devel, linux-kernel
On Fri, May 16, 2014 at 11:26:35AM +0300, Eli Billauer wrote:
> devm_get_free_pages() and devm_free_pages() are the managed counterparts
> for __get_free_pages() and free_pages().
>
> Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-16 8:26 ` [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single() Eli Billauer
@ 2014-05-16 21:08 ` Tejun Heo
2014-05-17 12:19 ` Eli Billauer
0 siblings, 1 reply; 13+ messages in thread
From: Tejun Heo @ 2014-05-16 21:08 UTC (permalink / raw)
To: Eli Billauer; +Cc: gregkh, devel, linux-kernel
Hello,
On Fri, May 16, 2014 at 11:26:36AM +0300, Eli Billauer wrote:
> +dma_addr_t dmam_map_single(struct device *dev, void *ptr, size_t size,
> + enum dma_data_direction direction)
> +
> +{
> + struct dma_devres *dr;
> + dma_addr_t dma_handle;
> +
> + dr = devres_alloc(dmam_map_single_release, sizeof(*dr), GFP_KERNEL);
> + if (!dr)
> + return 0;
> +
> + dma_handle = dma_map_single(dev, ptr, size, direction);
Don't we wanna map the underlying operation - dma_map_single_attrs() -
instead?
> + if (dma_mapping_error(dev, dma_handle)) {
> + devres_free(dr);
> + return 0;
Can't we just keep returning dma_handle? Even if that means invoking
->mapping_error() twice? It's yucky to have subtly different error
return especially because in most cases it won't fail.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single
2014-05-16 8:26 ` [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single Eli Billauer
@ 2014-05-16 21:09 ` Tejun Heo
0 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2014-05-16 21:09 UTC (permalink / raw)
To: Eli Billauer; +Cc: gregkh, devel, linux-kernel
On Fri, May 16, 2014 at 11:26:37AM +0300, Eli Billauer wrote:
>
> Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
> ---
> Documentation/driver-model/devres.txt | 2 ++
> include/asm-generic/pci-dma-compat.h | 17 +++++++++++++++++
> 2 files changed, 19 insertions(+), 0 deletions(-)
The patch looks fine to me but can you please cc PCI subsystem
maintainer and please do so for other patches too.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-16 21:08 ` Tejun Heo
@ 2014-05-17 12:19 ` Eli Billauer
2014-05-19 20:17 ` Tejun Heo
0 siblings, 1 reply; 13+ messages in thread
From: Eli Billauer @ 2014-05-17 12:19 UTC (permalink / raw)
To: Tejun Heo; +Cc: gregkh, devel, linux-kernel
Hello Tejun,
On 17/05/14 00:08, Tejun Heo wrote:
>
> Don't we wanna map the underlying operation - dma_map_single_attrs() -
> instead?
>
I'll resubmit this patch promptly, with a follow-up patch for the diff
to implement dmam_map_single_attrs() instead. Plus a define-statement
for dmam_map_single(). I can't test the case of a non-NULL value for
@attrs however.
>
>> + if (dma_mapping_error(dev, dma_handle)) {
>> + devres_free(dr);
>> + return 0;
>>
> Can't we just keep returning dma_handle? Even if that means invoking
> ->mapping_error() twice? It's yucky to have subtly different error
> return especially because in most cases it won't fail.
>
Yucky it is indeed. There are however two problems with keeping the
existing API:
* What to do if devres_alloc() fails. How do I signal back an error? The
only way I can think of is returning zero. But if the caller should know
that zero means failure, I've already broken the API. I might as well
return zero for any kind of failure.
* It seems like a lot of dma_mapping_error() implementations always
return no-error, since the DMA mapping can't fail on specific
architectures. If callers use dma_mapping_error(), the possible
devres_alloc() failure will be missed.
By the way, where I've seen dma_mapping_error() doing something, it
checks for dma_handle == 0.
Submitting updated patches for the DMA mapping part soon.
Regards,
Eli
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-17 12:19 ` Eli Billauer
@ 2014-05-19 20:17 ` Tejun Heo
2014-05-20 5:54 ` Eli Billauer
0 siblings, 1 reply; 13+ messages in thread
From: Tejun Heo @ 2014-05-19 20:17 UTC (permalink / raw)
To: Eli Billauer; +Cc: gregkh, devel, linux-kernel
Hello, Eli.
On Sat, May 17, 2014 at 03:19:21PM +0300, Eli Billauer wrote:
> >>+ if (dma_mapping_error(dev, dma_handle)) {
> >>+ devres_free(dr);
> >>+ return 0;
> >Can't we just keep returning dma_handle? Even if that means invoking
> >->mapping_error() twice? It's yucky to have subtly different error
> >return especially because in most cases it won't fail.
> Yucky it is indeed. There are however two problems with keeping the existing
> API:
>
> * What to do if devres_alloc() fails. How do I signal back an error? The
> only way I can think of is returning zero. But if the caller should know
> that zero means failure, I've already broken the API. I might as well return
> zero for any kind of failure.
What can't it just do the following?
if (dma_mapping_error(dev, dma_handle)) {
devres_free(dr);
return dma_handle;
}
The caller would have to invoke dma_mapping_error() again but is that
a problem?
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-19 20:17 ` Tejun Heo
@ 2014-05-20 5:54 ` Eli Billauer
2014-05-20 15:05 ` Tejun Heo
0 siblings, 1 reply; 13+ messages in thread
From: Eli Billauer @ 2014-05-20 5:54 UTC (permalink / raw)
To: Tejun Heo; +Cc: gregkh, devel, linux-kernel
Hello, Tejun.
On 19/05/14 23:17, Tejun Heo wrote:
>
> What can't it just do the following?
>
> if (dma_mapping_error(dev, dma_handle)) {
> devres_free(dr);
> return dma_handle;
> }
>
> The caller would have to invoke dma_mapping_error() again but is that
> a problem?
>
That seems OK to me, but the problem I'm concerned with is this: In
devm_get_free_pages() it says
devres = devres_alloc(devm_pages_release,
sizeof(struct pages_devres), GFP_KERNEL);
if (unlikely(!devres)) {
free_pages(addr, order);
return 0;
}
What should I put instead of this "return 0" to conform with the current
API?
And to make things even worse, on some architectures,
dma_mapping_error() always returns success, regardless of dma_handle. So
if we stick to the current API, the caller of devm_get_free_pages() will
never know it failed on these architectures.
So my conclusion was that the caller must be aware that if
devm_get_free_pages() returns zero it's an error, regardless of
dma_mapping_error(). That breaks the API. Once it's broken, why not
return zero on all possible errors?
Maybe I didn't understand what you suggested.
Regards,
Eli
> Thanks.
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single()
2014-05-20 5:54 ` Eli Billauer
@ 2014-05-20 15:05 ` Tejun Heo
0 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2014-05-20 15:05 UTC (permalink / raw)
To: Eli Billauer; +Cc: gregkh, devel, linux-kernel
Hello,
On Tue, May 20, 2014 at 08:54:09AM +0300, Eli Billauer wrote:
> That seems OK to me, but the problem I'm concerned with is this: In
> devm_get_free_pages() it says
>
> devres = devres_alloc(devm_pages_release,
> sizeof(struct pages_devres), GFP_KERNEL);
> if (unlikely(!devres)) {
> free_pages(addr, order);
> return 0;
> }
>
> What should I put instead of this "return 0" to conform with the current
> API?
Ah, okay. No idea.
> And to make things even worse, on some architectures, dma_mapping_error()
> always returns success, regardless of dma_handle. So if we stick to the
> current API, the caller of devm_get_free_pages() will never know it failed
> on these architectures.
>
> So my conclusion was that the caller must be aware that if
> devm_get_free_pages() returns zero it's an error, regardless of
> dma_mapping_error(). That breaks the API. Once it's broken, why not return
> zero on all possible errors?
What if 0 is a valid return for the architecture? Isn't that the
whole point of dma_mapping_error() interface? Maybe the right thing
to do is using a separate out argument for dma_handle?
int dmam_map_single(blah blah, dma_addr_t *out_addr);
So that it can return -errno like other non-crazy functions? We'll
probably ask somebody who knows this code better.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2014-05-20 15:05 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-16 8:26 [PATCH 0/5] devres: Add functions + migrate Xillybus driver Eli Billauer
2014-05-16 8:26 ` [PATCH 1/5] devres: Add devm_get_free_pages API Eli Billauer
2014-05-16 21:01 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 2/5] dma-mapping: Add devm_ interface for dma_map_single() Eli Billauer
2014-05-16 21:08 ` Tejun Heo
2014-05-17 12:19 ` Eli Billauer
2014-05-19 20:17 ` Tejun Heo
2014-05-20 5:54 ` Eli Billauer
2014-05-20 15:05 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 3/5] dma-mapping: pci: Add devm_ interface for pci_map_single Eli Billauer
2014-05-16 21:09 ` Tejun Heo
2014-05-16 8:26 ` [PATCH 4/5] staging: xillybus: Use devm_ API on probe and remove Eli Billauer
2014-05-16 8:26 ` [PATCH 5/5] staging: xillybus: Use devm_ API for memory allocation and DMA mapping Eli Billauer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.