From cafaf14a5d8f152ed3c984ecd48dee6e824446bc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 19 Aug 2016 16:54:26 +0100 Subject: io-mapping: Always create a struct to hold metadata about the io-mapping Currently, we only allocate a structure to hold metadata if we need to allocate an ioremap for every access, such as on x86-32. However, it would be useful to store basic information about the io-mapping, such as its page protection, on all platforms. Signed-off-by: Chris Wilson Cc: linux-mm@kvack.org Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160819155428.1670-4-chris@chris-wilson.co.uk --- include/linux/io-mapping.h | 92 ++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 35 deletions(-) (limited to 'include/linux/io-mapping.h') diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index 645ad06b5d52..b4c4b5c4216d 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -31,16 +31,16 @@ * See Documentation/io-mapping.txt */ -#ifdef CONFIG_HAVE_ATOMIC_IOMAP - -#include - struct io_mapping { resource_size_t base; unsigned long size; pgprot_t prot; + void __iomem *iomem; }; +#ifdef CONFIG_HAVE_ATOMIC_IOMAP + +#include /* * For small address space machines, mapping large objects * into the kernel virtual space isn't practical. Where @@ -49,34 +49,25 @@ struct io_mapping { */ static inline struct io_mapping * -io_mapping_create_wc(resource_size_t base, unsigned long size) +io_mapping_init_wc(struct io_mapping *iomap, + resource_size_t base, + unsigned long size) { - struct io_mapping *iomap; pgprot_t prot; - iomap = kmalloc(sizeof(*iomap), GFP_KERNEL); - if (!iomap) - goto out_err; - if (iomap_create_wc(base, size, &prot)) - goto out_free; + return NULL; iomap->base = base; iomap->size = size; iomap->prot = prot; return iomap; - -out_free: - kfree(iomap); -out_err: - return NULL; } static inline void -io_mapping_free(struct io_mapping *mapping) +io_mapping_fini(struct io_mapping *mapping) { iomap_free(mapping->base, mapping->size); - kfree(mapping); } /* Atomic map/unmap */ @@ -121,21 +112,40 @@ io_mapping_unmap(void __iomem *vaddr) #else #include - -/* this struct isn't actually defined anywhere */ -struct io_mapping; +#include /* Create the io_mapping object*/ static inline struct io_mapping * -io_mapping_create_wc(resource_size_t base, unsigned long size) +io_mapping_init_wc(struct io_mapping *iomap, + resource_size_t base, + unsigned long size) +{ + iomap->base = base; + iomap->size = size; + iomap->iomem = ioremap_wc(base, size); + iomap->prot = pgprot_writecombine(PAGE_KERNEL_IO); + + return iomap; +} + +static inline void +io_mapping_fini(struct io_mapping *mapping) +{ + iounmap(mapping->iomem); +} + +/* Non-atomic map/unmap */ +static inline void __iomem * +io_mapping_map_wc(struct io_mapping *mapping, + unsigned long offset, + unsigned long size) { - return (struct io_mapping __force *) ioremap_wc(base, size); + return mapping->iomem + offset; } static inline void -io_mapping_free(struct io_mapping *mapping) +io_mapping_unmap(void __iomem *vaddr) { - iounmap((void __force __iomem *) mapping); } /* Atomic map/unmap */ @@ -145,30 +155,42 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping, { preempt_disable(); pagefault_disable(); - return ((char __force __iomem *) mapping) + offset; + return io_mapping_map_wc(mapping, offset, PAGE_SIZE); } static inline void io_mapping_unmap_atomic(void __iomem *vaddr) { + io_mapping_unmap(vaddr); pagefault_enable(); preempt_enable(); } -/* Non-atomic map/unmap */ -static inline void __iomem * -io_mapping_map_wc(struct io_mapping *mapping, - unsigned long offset, - unsigned long size) +#endif /* HAVE_ATOMIC_IOMAP */ + +static inline struct io_mapping * +io_mapping_create_wc(resource_size_t base, + unsigned long size) { - return ((char __force __iomem *) mapping) + offset; + struct io_mapping *iomap; + + iomap = kmalloc(sizeof(*iomap), GFP_KERNEL); + if (!iomap) + return NULL; + + if (!io_mapping_init_wc(iomap, base, size)) { + kfree(iomap); + return NULL; + } + + return iomap; } static inline void -io_mapping_unmap(void __iomem *vaddr) +io_mapping_free(struct io_mapping *iomap) { + io_mapping_fini(iomap); + kfree(iomap); } -#endif /* HAVE_ATOMIC_IOMAP */ - #endif /* _LINUX_IO_MAPPING_H */ -- cgit From bcaaa0c4310ebe1ab04274594916bbb2d82a49c8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 23 Aug 2016 16:50:24 +0100 Subject: io-mapping.h: s/PAGE_KERNEL_IO/PAGE_KERNEL/ PAGE_KERNEL_IO is an x86-ism. Though it is used to define the pgprot_t used for the iomapped region, it itself is just PAGE_KERNEL. On all other arches, PAGE_KERNEL_IO is undefined so in a general header we must refrain from using it. v2: include pgtable for pgprot_combine() Reported-by: Stephen Rothwell Fixes: cafaf14a5d8f ("io-mapping: Always create a struct to hold metadata about the io-mapping") Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Joonas Lahtinen Cc: linux-mm@kvack.org Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20160823155024.22379-1-chris@chris-wilson.co.uk (cherry picked from commit ac96b5566926af83463ddcf4655856033c092f26) --- include/linux/io-mapping.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux/io-mapping.h') diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index b4c4b5c4216d..a87dd7fffc0a 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -112,7 +112,7 @@ io_mapping_unmap(void __iomem *vaddr) #else #include -#include +#include /* Create the io_mapping object*/ static inline struct io_mapping * @@ -123,7 +123,7 @@ io_mapping_init_wc(struct io_mapping *iomap, iomap->base = base; iomap->size = size; iomap->iomem = ioremap_wc(base, size); - iomap->prot = pgprot_writecombine(PAGE_KERNEL_IO); + iomap->prot = pgprot_writecombine(PAGE_KERNEL); return iomap; } -- cgit From 351243897b15aba02ad15317724d616aeaf00c7d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 23 Aug 2016 22:15:02 +0200 Subject: io-mapping: Fixup for different names of writecombine Somehow architectures can't agree on this. And for good measure make sure we have a fallback which should work everywhere (fingers crossed). v2: Make it compile properly, needs a defined() for the #elif. Fixes: ac96b5566926 ("io-mapping.h: s/PAGE_KERNEL_IO/PAGE_KERNEL/") Cc: Chris Wilson Cc: Daniel Vetter Cc: Joonas Lahtinen Cc: linux-mm@kvack.org Reviewed-by: Chris Wilson Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20160823202233.4681-1-daniel.vetter@ffwll.ch (cherry picked from commit 80c33624e4723c4e22d9917cd676067ebf652dc2) --- include/linux/io-mapping.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/io-mapping.h') diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index a87dd7fffc0a..58df02bd93c9 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -123,7 +123,13 @@ io_mapping_init_wc(struct io_mapping *iomap, iomap->base = base; iomap->size = size; iomap->iomem = ioremap_wc(base, size); +#if defined(pgprot_noncached_wc) /* archs can't agree on a name ... */ + iomap->prot = pgprot_noncached_wc(PAGE_KERNEL); +#elif defined(pgprot_writecombine) iomap->prot = pgprot_writecombine(PAGE_KERNEL); +#else + iomap->prot = pgprot_noncached(PAGE_KERNEL); +#endif return iomap; } -- cgit