Commit 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0

Authored by Wolfram Sang
Committed by Greg Kroah-Hartman
1 parent 571806a9f7

lib: devres: add convenience function to remap a resource

Almost every platform_driver does the three steps get_resource,
request_mem_region, ioremap. This does not only lead to a lot of code
duplication, but also a huge number of similar error strings and
inconsistent error codes on failure. So, introduce a helper function
which simplifies remapping a resource and make it hard to do something
wrong and add documentation for it.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 55 additions and 0 deletions Side-by-side Diff

Documentation/driver-model/devres.txt
... ... @@ -262,6 +262,7 @@
262 262 devm_ioremap()
263 263 devm_ioremap_nocache()
264 264 devm_iounmap()
  265 + devm_request_and_ioremap() : checks resource, requests region, ioremaps
265 266 pcim_iomap()
266 267 pcim_iounmap()
267 268 pcim_iomap_table() : array of mapped addresses indexed by BAR
include/linux/device.h
... ... @@ -490,6 +490,9 @@
490 490 extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
491 491 extern void devm_kfree(struct device *dev, void *p);
492 492  
  493 +void __iomem *devm_request_and_ioremap(struct device *dev,
  494 + struct resource *res);
  495 +
493 496 struct device_dma_parameters {
494 497 /*
495 498 * a low level driver may set these to teach IOMMU code about
... ... @@ -85,6 +85,57 @@
85 85 }
86 86 EXPORT_SYMBOL(devm_iounmap);
87 87  
  88 +/**
  89 + * devm_request_and_ioremap() - Check, request region, and ioremap resource
  90 + * @dev: Generic device to handle the resource for
  91 + * @res: resource to be handled
  92 + *
  93 + * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
  94 + * everything is undone on driver detach. Checks arguments, so you can feed
  95 + * it the result from e.g. platform_get_resource() directly. Returns the
  96 + * remapped pointer or NULL on error. Usage example:
  97 + *
  98 + * res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  99 + * base = devm_request_and_ioremap(&pdev->dev, res);
  100 + * if (!base)
  101 + * return -EADDRNOTAVAIL;
  102 + */
  103 +void __iomem *devm_request_and_ioremap(struct device *dev,
  104 + struct resource *res)
  105 +{
  106 + resource_size_t size;
  107 + const char *name;
  108 + void __iomem *dest_ptr;
  109 +
  110 + BUG_ON(!dev);
  111 +
  112 + if (!res || resource_type(res) != IORESOURCE_MEM) {
  113 + dev_err(dev, "invalid resource\n");
  114 + return NULL;
  115 + }
  116 +
  117 + size = resource_size(res);
  118 + name = res->name ?: dev_name(dev);
  119 +
  120 + if (!devm_request_mem_region(dev, res->start, size, name)) {
  121 + dev_err(dev, "can't request region for resource %pR\n", res);
  122 + return NULL;
  123 + }
  124 +
  125 + if (res->flags & IORESOURCE_CACHEABLE)
  126 + dest_ptr = devm_ioremap(dev, res->start, size);
  127 + else
  128 + dest_ptr = devm_ioremap_nocache(dev, res->start, size);
  129 +
  130 + if (!dest_ptr) {
  131 + dev_err(dev, "ioremap failed for resource %pR\n", res);
  132 + devm_release_mem_region(dev, res->start, size);
  133 + }
  134 +
  135 + return dest_ptr;
  136 +}
  137 +EXPORT_SYMBOL(devm_request_and_ioremap);
  138 +
88 139 #ifdef CONFIG_HAS_IOPORT
89 140 /*
90 141 * Generic iomap devres