diff options
author | Christoph Hellwig <hch@lst.de> | 2015-08-10 23:07:07 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2015-08-14 16:01:21 -0400 |
commit | 7d3dcf26a6559fa82af3f53e2c8b163cec95fdaf (patch) | |
tree | 6175706fabf462830edfbfbbc041a89384b3a36e | |
parent | e836a256e8fd579c9d7a3685f22981225a1ca451 (diff) |
devres: add devm_memremap
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | include/linux/io.h | 4 | ||||
-rw-r--r-- | kernel/memremap.c | 39 |
2 files changed, 43 insertions, 0 deletions
diff --git a/include/linux/io.h b/include/linux/io.h index 3fcf6256c088..d8d749abd665 100644 --- a/include/linux/io.h +++ b/include/linux/io.h | |||
@@ -80,6 +80,10 @@ int check_signature(const volatile void __iomem *io_addr, | |||
80 | const unsigned char *signature, int length); | 80 | const unsigned char *signature, int length); |
81 | void devm_ioremap_release(struct device *dev, void *res); | 81 | void devm_ioremap_release(struct device *dev, void *res); |
82 | 82 | ||
83 | void *devm_memremap(struct device *dev, resource_size_t offset, | ||
84 | size_t size, unsigned long flags); | ||
85 | void devm_memunmap(struct device *dev, void *addr); | ||
86 | |||
83 | /* | 87 | /* |
84 | * Some systems do not have legacy ISA devices. | 88 | * Some systems do not have legacy ISA devices. |
85 | * /dev/port is not a valid interface on these systems. | 89 | * /dev/port is not a valid interface on these systems. |
diff --git a/kernel/memremap.c b/kernel/memremap.c index a293de52e837..5c9b55eaf121 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 | * General Public License for more details. | 11 | * General Public License for more details. |
12 | */ | 12 | */ |
13 | #include <linux/device.h> | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
15 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
@@ -96,3 +97,41 @@ void memunmap(void *addr) | |||
96 | iounmap((void __iomem *) addr); | 97 | iounmap((void __iomem *) addr); |
97 | } | 98 | } |
98 | EXPORT_SYMBOL(memunmap); | 99 | EXPORT_SYMBOL(memunmap); |
100 | |||
101 | static void devm_memremap_release(struct device *dev, void *res) | ||
102 | { | ||
103 | memunmap(res); | ||
104 | } | ||
105 | |||
106 | static int devm_memremap_match(struct device *dev, void *res, void *match_data) | ||
107 | { | ||
108 | return *(void **)res == match_data; | ||
109 | } | ||
110 | |||
111 | void *devm_memremap(struct device *dev, resource_size_t offset, | ||
112 | size_t size, unsigned long flags) | ||
113 | { | ||
114 | void **ptr, *addr; | ||
115 | |||
116 | ptr = devres_alloc(devm_memremap_release, sizeof(*ptr), GFP_KERNEL); | ||
117 | if (!ptr) | ||
118 | return NULL; | ||
119 | |||
120 | addr = memremap(offset, size, flags); | ||
121 | if (addr) { | ||
122 | *ptr = addr; | ||
123 | devres_add(dev, ptr); | ||
124 | } else | ||
125 | devres_free(ptr); | ||
126 | |||
127 | return addr; | ||
128 | } | ||
129 | EXPORT_SYMBOL(devm_memremap); | ||
130 | |||
131 | void devm_memunmap(struct device *dev, void *addr) | ||
132 | { | ||
133 | WARN_ON(devres_destroy(dev, devm_memremap_release, devm_memremap_match, | ||
134 | addr)); | ||
135 | memunmap(addr); | ||
136 | } | ||
137 | EXPORT_SYMBOL(devm_memunmap); | ||