From 8c7ea50c010b2f1e006ad37c43f98202a31de2cb Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 9 Jul 2015 17:28:16 -0700 Subject: x86/mm, asm-generic: Add IOMMU ioremap_uc() variant default We currently have no safe way of currently defining architecture agnostic IOMMU ioremap_*() variants. The trend is for folks to *assume* that ioremap_nocache() should be the default everywhere and then add this mapping on each architectures -- this is not correct today for a variety of reasons. We have two options: 1) Sit and wait for every architecture in Linux to get a an ioremap_*() variant defined before including it upstream. 2) Gather consensus on a safe architecture agnostic ioremap_*() default. Approach 1) introduces development latencies, and since 2) will take time and work on clarifying semantics the only remaining sensible thing to do to avoid issues is returning NULL on ioremap_*() variants. In order for this to work we must have all architectures declare their own ioremap_*() variants as defined. This will take some work, do this for ioremp_uc() to set the example as its only currently implemented on x86. Document all this. We only provide implementation support for ioremap_uc() as the other ioremap_*() variants are well defined all over the kernel for other architectures already. Signed-off-by: Luis R. Rodriguez Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: arnd@arndb.de Cc: benh@kernel.crashing.org Cc: bp@suse.de Cc: dan.j.williams@intel.com Cc: geert@linux-m68k.org Cc: hch@lst.de Cc: hmh@hmh.eng.br Cc: jgross@suse.com Cc: linux-mm@kvack.org Cc: luto@amacapital.net Cc: mpe@ellerman.id.au Cc: mst@redhat.com Cc: ralf@linux-mips.org Cc: ross.zwisler@linux.intel.com Cc: stefan.bader@canonical.com Cc: tj@kernel.org Cc: tomi.valkeinen@ti.com Cc: toshi.kani@hp.com Link: http://lkml.kernel.org/r/1436488096-3165-1-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- include/asm-generic/io.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index f56094cfdeff..eed3bbe88c8a 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -736,6 +736,35 @@ static inline void *phys_to_virt(unsigned long address) } #endif +/** + * DOC: ioremap() and ioremap_*() variants + * + * If you have an IOMMU your architecture is expected to have both ioremap() + * and iounmap() implemented otherwise the asm-generic helpers will provide a + * direct mapping. + * + * There are ioremap_*() call variants, if you have no IOMMU we naturally will + * default to direct mapping for all of them, you can override these defaults. + * If you have an IOMMU you are highly encouraged to provide your own + * ioremap variant implementation as there currently is no safe architecture + * agnostic default. To avoid possible improper behaviour default asm-generic + * ioremap_*() variants all return NULL when an IOMMU is available. If you've + * defined your own ioremap_*() variant you must then declare your own + * ioremap_*() variant as defined to itself to avoid the default NULL return. + */ + +#ifdef CONFIG_MMU + +#ifndef ioremap_uc +#define ioremap_uc ioremap_uc +static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size) +{ + return NULL; +} +#endif + +#else /* !CONFIG_MMU */ + /* * Change "struct page" to physical address. * @@ -743,7 +772,6 @@ static inline void *phys_to_virt(unsigned long address) * you'll need to provide your own definitions. */ -#ifndef CONFIG_MMU #ifndef ioremap #define ioremap ioremap static inline void __iomem *ioremap(phys_addr_t offset, size_t size) -- cgit v1.2.3 From c43996f4001de629af4a4d6713782e883677e5b9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 24 Aug 2015 12:13:23 -0700 Subject: PCI: Add pci_ioremap_wc_bar() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets drivers take advantage of PAT when available. It should help with the transition of converting video drivers over to ioremap_wc() to help with the goal of eventually using _PAGE_CACHE_UC over _PAGE_CACHE_UC_MINUS on x86 on ioremap_nocache(), see: de33c442ed2a ("x86 PAT: fix performance drop for glx, use UC minus for ioremap(), ioremap_nocache() and pci_mmap_page_range()") Signed-off-by: Luis R. Rodriguez Signed-off-by: Borislav Petkov Acked-by: Arnd Bergmann Cc: Cc: Andrew Morton Cc: Andy Lutomirski Cc: Antonino Daplas Cc: Bjorn Helgaas Cc: Daniel Vetter Cc: Dave Airlie Cc: Davidlohr Bueso Cc: H. Peter Anvin Cc: Jean-Christophe Plagniol-Villard Cc: Juergen Gross Cc: Linus Torvalds Cc: Mel Gorman Cc: Peter Zijlstra Cc: Suresh Siddha Cc: Thomas Gleixner Cc: Tomi Valkeinen Cc: Toshi Kani Cc: Ville Syrjälä Cc: Vlastimil Babka Cc: airlied@linux.ie Cc: benh@kernel.crashing.org Cc: dan.j.williams@intel.com Cc: konrad.wilk@oracle.com Cc: linux-fbdev@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: mst@redhat.com Cc: vinod.koul@intel.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1440443613-13696-2-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/pci.h b/include/linux/pci.h index 8a0321a8fb59..985dd392e5f2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1661,6 +1661,7 @@ static inline void pci_mmcfg_late_init(void) { } int pci_ext_cfg_avail(void); void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); +void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar); #ifdef CONFIG_PCI_IOV int pci_iov_virtfn_bus(struct pci_dev *dev, int id); -- cgit v1.2.3 From 9e517ac88b2443bebc0499c0b477b155d63648a7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 24 Aug 2015 12:13:25 -0700 Subject: drivers/video/fbdev/kyrofb: Use arch_phys_wc_add() and pci_ioremap_wc_bar() Convert the driver from using the x86-specific MTRR code to the architecture-agnostic arch_phys_wc_add(). It will avoid MTRR if write-combining is available, in order to take advantage of that also ensure the ioremapped area is requested as write-combining. There are a few motivations for this: a) Take advantage of PAT when available b) Help bury MTRR code away, MTRR is architecture-specific and on x86 it is being replaced by PAT. c) Help with the goal of eventually using _PAGE_CACHE_UC over _PAGE_CACHE_UC_MINUS on x86 on ioremap_nocache() (see commit de33c442e titled "x86 PAT: fix performance drop for glx, use UC minus for ioremap(), ioremap_nocache() and pci_mmap_page_range()") The conversion done is expressed by the following Coccinelle SmPL patch, it additionally required manual intervention to address all the ifdeffery and removal of redundant things which arch_phys_wc_add() already addresses such as verbose message about when MTRR fails and doing nothing when we didn't get an MTRR. @ mtrr_found @ expression index, base, size; @@ -index = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1); +index = arch_phys_wc_add(base, size); @ mtrr_rm depends on mtrr_found @ expression mtrr_found.index, mtrr_found.base, mtrr_found.size; @@ -mtrr_del(index, base, size); +arch_phys_wc_del(index); @ mtrr_rm_zero_arg depends on mtrr_found @ expression mtrr_found.index; @@ -mtrr_del(index, 0, 0); +arch_phys_wc_del(index); @ mtrr_rm_fb_info depends on mtrr_found @ struct fb_info *info; expression mtrr_found.index; @@ -mtrr_del(index, info->fix.smem_start, info->fix.smem_len); +arch_phys_wc_del(index); @ ioremap_replace_nocache depends on mtrr_found @ struct fb_info *info; expression base, size; @@ -info->screen_base = ioremap_nocache(base, size); +info->screen_base = ioremap_wc(base, size); @ ioremap_replace_default depends on mtrr_found @ struct fb_info *info; expression base, size; @@ -info->screen_base = ioremap(base, size); +info->screen_base = ioremap_wc(base, size); Signed-off-by: Luis R. Rodriguez Signed-off-by: Borislav Petkov Acked-by: Tomi Valkeinen Cc: Andrew Morton Cc: Andy Lutomirski Cc: Antonino Daplas Cc: Arnd Bergmann Cc: Daniel Vetter Cc: Dave Airlie Cc: Geert Uytterhoeven Cc: H. Peter Anvin Cc: Jean-Christophe Plagniol-Villard Cc: Jingoo Han Cc: Juergen Gross Cc: Laurent Pinchart Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Suresh Siddha Cc: Thomas Gleixner Cc: airlied@linux.ie Cc: benh@kernel.crashing.org Cc: bhelgaas@google.com Cc: dan.j.williams@intel.com Cc: konrad.wilk@oracle.com Cc: linux-fbdev@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: mst@redhat.com Cc: toshi.kani@hp.com Cc: vinod.koul@intel.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1440443613-13696-4-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- include/video/kyro.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/include/video/kyro.h b/include/video/kyro.h index c563968e926c..b958c2e9c915 100644 --- a/include/video/kyro.h +++ b/include/video/kyro.h @@ -35,9 +35,7 @@ struct kyrofb_info { /* Useful to hold depth here for Linux */ u8 PIXDEPTH; -#ifdef CONFIG_MTRR - int mtrr_handle; -#endif + int wc_cookie; }; extern int kyro_dev_init(void); -- cgit v1.2.3 From 1b3d4200c1e00a3fb5e0aea428de5b07079a37e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 24 Aug 2015 12:13:27 -0700 Subject: PCI: Add pci_iomap_wc() variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PCI BARs tell us whether prefetching is safe, but they don't say anything about write combining (WC). WC changes ordering rules and allows writes to be collapsed, so it's not safe in general to use it on a prefetchable region. Add pci_iomap_wc() and pci_iomap_wc_range() so drivers can take advantage of write combining when they know it's safe. On architectures that don't fully support WC, e.g., x86 without PAT, drivers for legacy framebuffers may get some of the benefit by using arch_phys_wc_add() in addition to pci_iomap_wc(). But arch_phys_wc_add() is unreliable and should be avoided in general. On x86, it uses MTRRs, which are limited in number and size, so the results will vary based on driver loading order. The goals of adding pci_iomap_wc() are to: - Give drivers an architecture-independent way to use WC so they can stop using interfaces like mtrr_add() (on x86, pci_iomap_wc() uses PAT when available). - Move toward using _PAGE_CACHE_MODE_UC, not _PAGE_CACHE_MODE_UC_MINUS, on x86 on ioremap_nocache() (see de33c442ed2a ("x86 PAT: fix performance drop for glx, use UC minus for ioremap(), ioremap_nocache() and pci_mmap_page_range()"). Signed-off-by: Luis R. Rodriguez [ Move IORESOURCE_IO check up, space out statements for better readability. ] Signed-off-by: Borislav Petkov Acked-by: Arnd Bergmann Cc: Cc: Cc: Andrew Morton Cc: Andy Lutomirski Cc: Antonino Daplas Cc: Bjorn Helgaas Cc: Daniel Vetter Cc: Dave Airlie Cc: Dave Hansen Cc: Davidlohr Bueso Cc: H. Peter Anvin Cc: Jean-Christophe Plagniol-Villard Cc: Juergen Gross Cc: Linus Torvalds Cc: Mel Gorman Cc: Michael S. Tsirkin Cc: Peter Zijlstra Cc: Roger Pau Monné Cc: Rusty Russell Cc: Stefan Bader Cc: Suresh Siddha Cc: Thomas Gleixner Cc: Tomi Valkeinen Cc: Toshi Kani Cc: Ville Syrjälä Cc: Vlastimil Babka Cc: airlied@linux.ie Cc: benh@kernel.crashing.org Cc: dan.j.williams@intel.com Cc: david.vrabel@citrix.com Cc: jbeulich@suse.com Cc: konrad.wilk@oracle.com Cc: linux-arch@vger.kernel.org Cc: linux-fbdev@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: venkatesh.pallipadi@intel.com Cc: vinod.koul@intel.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1440443613-13696-6-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- include/asm-generic/pci_iomap.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/asm-generic/pci_iomap.h b/include/asm-generic/pci_iomap.h index 7389c87116a0..b1e17fcee2d0 100644 --- a/include/asm-generic/pci_iomap.h +++ b/include/asm-generic/pci_iomap.h @@ -15,9 +15,13 @@ struct pci_dev; #ifdef CONFIG_PCI /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +extern void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long max); extern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, unsigned long offset, unsigned long maxlen); +extern void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, + unsigned long offset, + unsigned long maxlen); /* Create a virtual mapping cookie for a port on a given PCI device. * Do not call this directly, it exists to make it easier for architectures * to override */ @@ -34,12 +38,22 @@ static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned lon return NULL; } +static inline void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long max) +{ + return NULL; +} static inline void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, unsigned long offset, unsigned long maxlen) { return NULL; } +static inline void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, + unsigned long offset, + unsigned long maxlen) +{ + return NULL; +} #endif #endif /* __ASM_GENERIC_IO_H */ -- cgit v1.2.3