From: Christoph Hellwig Date: Tue, 11 Aug 2015 03:07:07 +0000 (-0400) Subject: devres: add devm_memremap X-Git-Tag: v4.1.12-92~18^2^2~137 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=e552cedd857b42c8306465613c60d503c81fcf14;p=users%2Fjedix%2Flinux-maple.git devres: add devm_memremap Orabug: 22913653 Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams (cherry picked from commit 7d3dcf26a6559fa82af3f53e2c8b163cec95fdaf) Signed-off-by: Dan Duval --- diff --git a/include/linux/io.h b/include/linux/io.h index 5b512a7891bbd..0be925e7d1130 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -79,6 +79,10 @@ int check_signature(const volatile void __iomem *io_addr, const unsigned char *signature, int length); void devm_ioremap_release(struct device *dev, void *res); +void *devm_memremap(struct device *dev, resource_size_t offset, + size_t size, unsigned long flags); +void devm_memunmap(struct device *dev, void *addr); + /* * Some systems do not have legacy ISA devices. * /dev/port is not a valid interface on these systems. diff --git a/kernel/memremap.c b/kernel/memremap.c index a293de52e8379..5c9b55eaf121a 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 #include #include #include @@ -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);