summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-08-10 23:07:07 -0400
committerDan Williams <dan.j.williams@intel.com>2015-08-14 16:01:21 -0400
commit7d3dcf26a6559fa82af3f53e2c8b163cec95fdaf (patch)
tree6175706fabf462830edfbfbbc041a89384b3a36e
parente836a256e8fd579c9d7a3685f22981225a1ca451 (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.h4
-rw-r--r--kernel/memremap.c39
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);
81void devm_ioremap_release(struct device *dev, void *res); 81void devm_ioremap_release(struct device *dev, void *res);
82 82
83void *devm_memremap(struct device *dev, resource_size_t offset,
84 size_t size, unsigned long flags);
85void 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}
98EXPORT_SYMBOL(memunmap); 99EXPORT_SYMBOL(memunmap);
100
101static void devm_memremap_release(struct device *dev, void *res)
102{
103 memunmap(res);
104}
105
106static int devm_memremap_match(struct device *dev, void *res, void *match_data)
107{
108 return *(void **)res == match_data;
109}
110
111void *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}
129EXPORT_SYMBOL(devm_memremap);
130
131void 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}
137EXPORT_SYMBOL(devm_memunmap);