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 /kernel/memremap.c | |
parent | e836a256e8fd579c9d7a3685f22981225a1ca451 (diff) | |
download | linux-7d3dcf26a6559fa82af3f53e2c8b163cec95fdaf.tar.bz2 |
devres: add devm_memremap
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'kernel/memremap.c')
-rw-r--r-- | kernel/memremap.c | 39 |
1 files changed, 39 insertions, 0 deletions
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 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ +#include <linux/device.h> #include <linux/types.h> #include <linux/io.h> #include <linux/mm.h> @@ -96,3 +97,41 @@ void memunmap(void *addr) iounmap((void __iomem *) addr); } EXPORT_SYMBOL(memunmap); + +static void devm_memremap_release(struct device *dev, void *res) +{ + memunmap(res); +} + +static int devm_memremap_match(struct device *dev, void *res, void *match_data) +{ + return *(void **)res == match_data; +} + +void *devm_memremap(struct device *dev, resource_size_t offset, + size_t size, unsigned long flags) +{ + void **ptr, *addr; + + ptr = devres_alloc(devm_memremap_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + addr = memremap(offset, size, flags); + if (addr) { + *ptr = addr; + devres_add(dev, ptr); + } else + devres_free(ptr); + + return addr; +} +EXPORT_SYMBOL(devm_memremap); + +void devm_memunmap(struct device *dev, void *addr) +{ + WARN_ON(devres_destroy(dev, devm_memremap_release, devm_memremap_match, + addr)); + memunmap(addr); +} +EXPORT_SYMBOL(devm_memunmap); |