Skip to content

Commit

Permalink
lib: devres: Introduce devm_ioremap_resource()
Browse files Browse the repository at this point in the history
The devm_request_and_ioremap() function is very useful and helps avoid a
whole lot of boilerplate. However, one issue that keeps popping up is
its lack of a specific error code to determine which of the steps that
it performs failed. Furthermore, while the function gives an example and
suggests what error code to return on failure, a wide variety of error
codes are used throughout the tree.

In an attempt to fix these problems, this patch adds a new function that
drivers can transition to. The devm_ioremap_resource() returns a pointer
to the remapped I/O memory on success or an ERR_PTR() encoded error code
on failure. Callers can check for failure using IS_ERR() and determine
its cause by extracting the error code using PTR_ERR().

devm_request_and_ioremap() is implemented as a wrapper around the new
API and return NULL on failure as before. This ensures that backwards
compatibility is maintained until all users have been converted to the
new API, at which point the old devm_request_and_ioremap() function
should be removed.

A semantic patch is included which can be used to convert from the old
devm_request_and_ioremap() API to the new devm_ioremap_resource() API.
Some non-trivial cases may require manual intervention, though.

Change-Id: I458afe18768979122c12e95bffe979a31f02f607
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Git-commit: 75096579c3ac39ddc2f8b0d9a8924eba31f4d920
Git-repo: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git
Signed-off-by: Dolev Raviv <draviv@codeaurora.org>
  • Loading branch information
Thierry Reding authored and Dolev Raviv committed Jul 30, 2013
1 parent 3f97a54 commit a2ba5f3
Showing 1 changed file with 44 additions and 13 deletions.
57 changes: 44 additions & 13 deletions lib/devres.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,22 +86,24 @@ void devm_iounmap(struct device *dev, void __iomem *addr)
EXPORT_SYMBOL(devm_iounmap);

/**
* devm_request_and_ioremap() - Check, request region, and ioremap resource
* @dev: Generic device to handle the resource for
* devm_ioremap_resource() - check, request region, and ioremap resource
* @dev: generic device to handle the resource for
* @res: resource to be handled
*
* Takes all necessary steps to ioremap a mem resource. Uses managed device, so
* everything is undone on driver detach. Checks arguments, so you can feed
* it the result from e.g. platform_get_resource() directly. Returns the
* remapped pointer or NULL on error. Usage example:
* Checks that a resource is a valid memory region, requests the memory region
* and ioremaps it either as cacheable or as non-cacheable memory depending on
* the resource's flags. All operations are managed and will be undone on
* driver detach.
*
* Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
* on failure. Usage example:
*
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
* base = devm_request_and_ioremap(&pdev->dev, res);
* if (!base)
* return -EADDRNOTAVAIL;
* base = devm_ioremap_resource(&pdev->dev, res);
* if (IS_ERR(base))
* return PTR_ERR(base);
*/
void __iomem *devm_request_and_ioremap(struct device *dev,
struct resource *res)
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
{
resource_size_t size;
const char *name;
Expand All @@ -111,15 +113,15 @@ void __iomem *devm_request_and_ioremap(struct device *dev,

if (!res || resource_type(res) != IORESOURCE_MEM) {
dev_err(dev, "invalid resource\n");
return NULL;
return ERR_PTR(-EINVAL);
}

size = resource_size(res);
name = res->name ?: dev_name(dev);

if (!devm_request_mem_region(dev, res->start, size, name)) {
dev_err(dev, "can't request region for resource %pR\n", res);
return NULL;
return ERR_PTR(-EBUSY);
}

if (res->flags & IORESOURCE_CACHEABLE)
Expand All @@ -130,10 +132,39 @@ void __iomem *devm_request_and_ioremap(struct device *dev,
if (!dest_ptr) {
dev_err(dev, "ioremap failed for resource %pR\n", res);
devm_release_mem_region(dev, res->start, size);
dest_ptr = ERR_PTR(-ENOMEM);
}

return dest_ptr;
}
EXPORT_SYMBOL(devm_ioremap_resource);

/**
* devm_request_and_ioremap() - Check, request region, and ioremap resource
* @dev: Generic device to handle the resource for
* @res: resource to be handled
*
* Takes all necessary steps to ioremap a mem resource. Uses managed device, so
* everything is undone on driver detach. Checks arguments, so you can feed
* it the result from e.g. platform_get_resource() directly. Returns the
* remapped pointer or NULL on error. Usage example:
*
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
* base = devm_request_and_ioremap(&pdev->dev, res);
* if (!base)
* return -EADDRNOTAVAIL;
*/
void __iomem *devm_request_and_ioremap(struct device *device,
struct resource *res)
{
void __iomem *dest_ptr;

dest_ptr = devm_ioremap_resource(device, res);
if (IS_ERR(dest_ptr))
return NULL;

return dest_ptr;
}
EXPORT_SYMBOL(devm_request_and_ioremap);

#ifdef CONFIG_HAS_IOPORT
Expand Down

0 comments on commit a2ba5f3

Please sign in to comment.