Skip to content

Commit 7509657

Browse files
Thierry Redinggregkh
authored andcommitted
lib: devres: Introduce devm_ioremap_resource()
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. Signed-off-by: Thierry Reding <[email protected]> Cc: Arnd Bergmann <[email protected]> Acked-by: Dmitry Torokhov <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 771d394 commit 7509657

File tree

4 files changed

+137
-14
lines changed

4 files changed

+137
-14
lines changed

Documentation/driver-model/devres.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ IOMAP
266266
devm_ioremap()
267267
devm_ioremap_nocache()
268268
devm_iounmap()
269-
devm_request_and_ioremap() : checks resource, requests region, ioremaps
269+
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
270+
devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
270271
pcim_iomap()
271272
pcim_iounmap()
272273
pcim_iomap_table() : array of mapped addresses indexed by BAR

include/linux/device.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ extern int devres_release_group(struct device *dev, void *id);
573573
extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
574574
extern void devm_kfree(struct device *dev, void *p);
575575

576+
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
576577
void __iomem *devm_request_and_ioremap(struct device *dev,
577578
struct resource *res);
578579

lib/devres.c

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,24 @@ void devm_iounmap(struct device *dev, void __iomem *addr)
8686
EXPORT_SYMBOL(devm_iounmap);
8787

8888
/**
89-
* devm_request_and_ioremap() - Check, request region, and ioremap resource
90-
* @dev: Generic device to handle the resource for
89+
* devm_ioremap_resource() - check, request region, and ioremap resource
90+
* @dev: generic device to handle the resource for
9191
* @res: resource to be handled
9292
*
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:
93+
* Checks that a resource is a valid memory region, requests the memory region
94+
* and ioremaps it either as cacheable or as non-cacheable memory depending on
95+
* the resource's flags. All operations are managed and will be undone on
96+
* driver detach.
97+
*
98+
* Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
99+
* on failure. Usage example:
97100
*
98101
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
99-
* base = devm_request_and_ioremap(&pdev->dev, res);
100-
* if (!base)
101-
* return -EADDRNOTAVAIL;
102+
* base = devm_ioremap_resource(&pdev->dev, res);
103+
* if (IS_ERR(base))
104+
* return PTR_ERR(base);
102105
*/
103-
void __iomem *devm_request_and_ioremap(struct device *dev,
104-
struct resource *res)
106+
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
105107
{
106108
resource_size_t size;
107109
const char *name;
@@ -111,15 +113,15 @@ void __iomem *devm_request_and_ioremap(struct device *dev,
111113

112114
if (!res || resource_type(res) != IORESOURCE_MEM) {
113115
dev_err(dev, "invalid resource\n");
114-
return NULL;
116+
return ERR_PTR(-EINVAL);
115117
}
116118

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

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

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

135138
return dest_ptr;
136139
}
140+
EXPORT_SYMBOL(devm_ioremap_resource);
141+
142+
/**
143+
* devm_request_and_ioremap() - Check, request region, and ioremap resource
144+
* @dev: Generic device to handle the resource for
145+
* @res: resource to be handled
146+
*
147+
* Takes all necessary steps to ioremap a mem resource. Uses managed device, so
148+
* everything is undone on driver detach. Checks arguments, so you can feed
149+
* it the result from e.g. platform_get_resource() directly. Returns the
150+
* remapped pointer or NULL on error. Usage example:
151+
*
152+
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
153+
* base = devm_request_and_ioremap(&pdev->dev, res);
154+
* if (!base)
155+
* return -EADDRNOTAVAIL;
156+
*/
157+
void __iomem *devm_request_and_ioremap(struct device *device,
158+
struct resource *res)
159+
{
160+
void __iomem *dest_ptr;
161+
162+
dest_ptr = devm_ioremap_resource(device, res);
163+
if (IS_ERR(dest_ptr))
164+
return NULL;
165+
166+
return dest_ptr;
167+
}
137168
EXPORT_SYMBOL(devm_request_and_ioremap);
138169

139170
#ifdef CONFIG_HAS_IOPORT
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
virtual patch
2+
virtual report
3+
4+
@depends on patch@
5+
expression base, dev, res;
6+
@@
7+
8+
-base = devm_request_and_ioremap(dev, res);
9+
+base = devm_ioremap_resource(dev, res);
10+
...
11+
if (
12+
-base == NULL
13+
+IS_ERR(base)
14+
|| ...) {
15+
<...
16+
- return ...;
17+
+ return PTR_ERR(base);
18+
...>
19+
}
20+
21+
@depends on patch@
22+
expression e, E, ret;
23+
identifier l;
24+
@@
25+
26+
e = devm_ioremap_resource(...);
27+
...
28+
if (IS_ERR(e) || ...) {
29+
... when any
30+
- ret = E;
31+
+ ret = PTR_ERR(e);
32+
...
33+
(
34+
return ret;
35+
|
36+
goto l;
37+
)
38+
}
39+
40+
@depends on patch@
41+
expression e;
42+
@@
43+
44+
e = devm_ioremap_resource(...);
45+
...
46+
if (IS_ERR(e) || ...) {
47+
...
48+
- \(dev_dbg\|dev_err\|pr_debug\|pr_err\|DRM_ERROR\)(...);
49+
...
50+
}
51+
52+
@depends on patch@
53+
expression e;
54+
identifier l;
55+
@@
56+
57+
e = devm_ioremap_resource(...);
58+
...
59+
if (IS_ERR(e) || ...)
60+
-{
61+
(
62+
return ...;
63+
|
64+
goto l;
65+
)
66+
-}
67+
68+
@r depends on report@
69+
expression e;
70+
identifier l;
71+
position p1;
72+
@@
73+
74+
*e = devm_request_and_ioremap@p1(...);
75+
...
76+
if (e == NULL || ...) {
77+
...
78+
(
79+
return ...;
80+
|
81+
goto l;
82+
)
83+
}
84+
85+
@script:python depends on r@
86+
p1 << r.p1;
87+
@@
88+
89+
msg = "ERROR: deprecated devm_request_and_ioremap() API used on line %s" % (p1[0].line)
90+
coccilib.report.print_report(p1[0], msg)

0 commit comments

Comments
 (0)