Commit 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0
Committed by
Greg Kroah-Hartman
1 parent
571806a9f7
Exists in
master
and in
38 other branches
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
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 |
lib/devres.c
... | ... | @@ -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 |