diff options
-rw-r--r-- | Documentation/driver-model/devres.txt | 1 | ||||
-rw-r--r-- | include/linux/device.h | 3 | ||||
-rw-r--r-- | lib/devres.c | 51 |
3 files changed, 55 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index d79aead9418b..10c64c8a13d4 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
@@ -262,6 +262,7 @@ IOMAP | |||
262 | devm_ioremap() | 262 | devm_ioremap() |
263 | devm_ioremap_nocache() | 263 | devm_ioremap_nocache() |
264 | devm_iounmap() | 264 | devm_iounmap() |
265 | devm_request_and_ioremap() : checks resource, requests region, ioremaps | ||
265 | pcim_iomap() | 266 | pcim_iomap() |
266 | pcim_iounmap() | 267 | pcim_iounmap() |
267 | pcim_iomap_table() : array of mapped addresses indexed by BAR | 268 | pcim_iomap_table() : array of mapped addresses indexed by BAR |
diff --git a/include/linux/device.h b/include/linux/device.h index ffbcf95cd97d..c6335982774c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -490,6 +490,9 @@ extern int devres_release_group(struct device *dev, void *id); | |||
490 | extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); | 490 | extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); |
491 | extern void devm_kfree(struct device *dev, void *p); | 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 | struct device_dma_parameters { | 496 | struct device_dma_parameters { |
494 | /* | 497 | /* |
495 | * a low level driver may set these to teach IOMMU code about | 498 | * a low level driver may set these to teach IOMMU code about |
diff --git a/lib/devres.c b/lib/devres.c index 78777aea5b34..4fbc09e6e9e6 100644 --- a/lib/devres.c +++ b/lib/devres.c | |||
@@ -85,6 +85,57 @@ void devm_iounmap(struct device *dev, void __iomem *addr) | |||
85 | } | 85 | } |
86 | EXPORT_SYMBOL(devm_iounmap); | 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 | #ifdef CONFIG_HAS_IOPORT | 139 | #ifdef CONFIG_HAS_IOPORT |
89 | /* | 140 | /* |
90 | * Generic iomap devres | 141 | * Generic iomap devres |