Linus,

Please pull the latest x86-mm-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-mm-for-linus

   # HEAD: 2baa891e42d84159b693eadd44f6fe1486285bdc x86/mm/mtrr: Remove kernel 
internal MTRR interfaces: unexport mtrr_add() and mtrr_del()

The dominant change in this cycle was the continued work to isolate kernel 
drivers 
from MTRR legacies: this tree gets rid of all kernel internal driver interfaces 
to 
MTRRs (mostly by rewriting it to proper PAT interfaces), the only access left 
is 
the /proc/mtrr ABI.

This work was done by Luis R. Rodriguez.

There's also some related PCI interface additions for which I've Cc:-ed Bjorn.

  out-of-topic modifications in x86-mm-for-linus:
  -------------------------------------------------
  arch/avr32/include/asm/io.h        # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/frv/include/asm/io.h          # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/m32r/include/asm/io.h         # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/m68k/include/asm/io_mm.h      # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/mn10300/include/asm/io.h      # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/powerpc/include/asm/io.h      # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/s390/include/asm/io.h         # ee03c5868e74: s390/io: Add 
pci_iomap_wc() 
  arch/sh/include/asm/io.h           # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  arch/tile/include/asm/io.h         # 4c73e8926623: arch/*/io.h: Add 
ioremap_uc(
  drivers/dma/iop-adma.c             # 39c33704420b: drivers/dma/iop-adma: Use 
dm
  drivers/pci/pci.c                  # c43996f4001d: PCI: Add 
pci_ioremap_wc_bar(
  drivers/video/fbdev/arkfb.c        # c823a48ac47f: 
drivers/video/fbdev/arkfb.c:
  drivers/video/fbdev/aty/atyfb.h    # 7d89a3cb159a: drivers/video/fbdev/atyfb: 
U
                                   # 3cc2dac5be3f: drivers/video/fbdev/atyfb: R
  drivers/video/fbdev/aty/atyfb_base.c# 7d89a3cb159a: 
drivers/video/fbdev/atyfb: U
                                   # 3cc2dac5be3f: drivers/video/fbdev/atyfb: R
                                   # f55de6ec375d: drivers/video/fbdev/atyfb: C
                                   # eacd2d542610: drivers/video/fbdev/atyfb: C
  drivers/video/fbdev/gxt4500.c      # f3adccbd7583: 
drivers/video/fbdev/gxt4500:
  drivers/video/fbdev/i740fb.c       # c112709809b2: 
drivers/video/fbdev/i740fb: 
  drivers/video/fbdev/kyro/fbdev.c   # 9e517ac88b24: 
drivers/video/fbdev/kyrofb: 
  drivers/video/fbdev/s3fb.c         # 4edcd2ab1255: drivers/video/fbdev/s3fb: 
Us
  drivers/video/fbdev/vt8623fb.c     # 81bdef04d3bc: 
drivers/video/fbdev/vt8623fb
  include/asm-generic/io.h           # 8c7ea50c010b: x86/mm, asm-generic: Add 
IOM
  include/asm-generic/pci_iomap.h    # 1b3d4200c1e0: PCI: Add pci_iomap_wc() 
vari
  include/linux/pci.h                # c43996f4001d: PCI: Add 
pci_ioremap_wc_bar(
  include/video/kyro.h               # 9e517ac88b24: 
drivers/video/fbdev/kyrofb: 
  lib/pci_iomap.c                    # 1b3d4200c1e0: PCI: Add pci_iomap_wc() 
vari

 Thanks,

        Ingo

------------------>
Luis R. Rodriguez (17):
      x86/mm, asm-generic: Add IOMMU ioremap_uc() variant default
      drivers/video/fbdev/atyfb: Carve out framebuffer length fudging into a 
helper
      drivers/video/fbdev/atyfb: Clarify ioremap() base and length used
      drivers/video/fbdev/atyfb: Replace MTRR UC hole with strong UC
      drivers/video/fbdev/atyfb: Use arch_phys_wc_add() and ioremap_wc()
      arch/*/io.h: Add ioremap_uc() to all architectures
      PCI: Add pci_ioremap_wc_bar()
      drivers/video/fbdev/i740fb: Use arch_phys_wc_add() and 
pci_ioremap_wc_bar()
      drivers/video/fbdev/kyrofb: Use arch_phys_wc_add() and 
pci_ioremap_wc_bar()
      drivers/video/fbdev/gxt4500: Use pci_ioremap_wc_bar() to map framebuffer
      PCI: Add pci_iomap_wc() variants
      drivers/video/fbdev/arkfb.c: Use arch_phys_wc_add() and pci_iomap_wc()
      drivers/video/fbdev/s3fb: Use arch_phys_wc_add() and pci_iomap_wc()
      drivers/video/fbdev/vt8623fb: Use arch_phys_wc_add() and pci_iomap_wc()
      drivers/dma/iop-adma: Use dma_alloc_writecombine() kernel-style
      s390/io: Add pci_iomap_wc() and pci_iomap_wc_range()
      x86/mm/mtrr: Remove kernel internal MTRR interfaces: unexport mtrr_add() 
and mtrr_del()

Minfei Huang (1):
      x86/mm: Initialize pmd_idx in page_table_range_init_count()

Paul Gortmaker (2):
      x86/mm/pat: Make mm/pageattr[-test].c explicitly non-modular
      x86/mm: Make kernel/check.c explicitly non-modular

Toshi Kani (1):
      x86/mm/pat: Add comments to cachemode translation tables


 Documentation/x86/mtrr.txt           |  20 +++++--
 arch/avr32/include/asm/io.h          |   1 +
 arch/frv/include/asm/io.h            |   1 +
 arch/m32r/include/asm/io.h           |   1 +
 arch/m68k/include/asm/io_mm.h        |   1 +
 arch/mn10300/include/asm/io.h        |   1 +
 arch/powerpc/include/asm/io.h        |   1 +
 arch/s390/include/asm/io.h           |   2 +
 arch/sh/include/asm/io.h             |   1 +
 arch/tile/include/asm/io.h           |   1 +
 arch/x86/include/asm/io.h            |   2 +
 arch/x86/kernel/check.c              |   5 +-
 arch/x86/kernel/cpu/mtrr/main.c      |   2 -
 arch/x86/mm/init.c                   |   7 ++-
 arch/x86/mm/init_32.c                |   1 +
 arch/x86/mm/pageattr-test.c          |   4 +-
 arch/x86/mm/pageattr.c               |   1 -
 drivers/dma/iop-adma.c               |   9 +--
 drivers/pci/pci.c                    |  14 +++++
 drivers/video/fbdev/arkfb.c          |  36 ++----------
 drivers/video/fbdev/aty/atyfb.h      |   5 +-
 drivers/video/fbdev/aty/atyfb_base.c | 109 ++++++++++++++++-------------------
 drivers/video/fbdev/gxt4500.c        |   2 +-
 drivers/video/fbdev/i740fb.c         |  35 ++---------
 drivers/video/fbdev/kyro/fbdev.c     |  33 ++++-------
 drivers/video/fbdev/s3fb.c           |  35 ++---------
 drivers/video/fbdev/vt8623fb.c       |  31 ++--------
 include/asm-generic/io.h             |  30 +++++++++-
 include/asm-generic/pci_iomap.h      |  14 +++++
 include/linux/pci.h                  |   1 +
 include/video/kyro.h                 |   4 +-
 lib/pci_iomap.c                      |  66 +++++++++++++++++++++
 32 files changed, 254 insertions(+), 222 deletions(-)

diff --git a/Documentation/x86/mtrr.txt b/Documentation/x86/mtrr.txt
index 860bc3adc223..dc3e703913ac 100644
--- a/Documentation/x86/mtrr.txt
+++ b/Documentation/x86/mtrr.txt
@@ -6,10 +6,22 @@ Luis R. Rodriguez <[email protected]> - April 9, 2015
 ===============================================================================
 Phasing out MTRR use
 
-MTRR use is replaced on modern x86 hardware with PAT. Over time the only type
-of effective MTRR that is expected to be supported will be for write-combining.
-As MTRR use is phased out device drivers should use arch_phys_wc_add() to make
-MTRR effective on non-PAT systems while a no-op on PAT enabled systems.
+MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
+drivers on Linux is now completely phased out, device drivers should use
+arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
+non-PAT systems while a no-op but equally effective on PAT enabled systems.
+
+Even if Linux does not use MTRRs directly, some x86 platform firmware may still
+set up MTRRs early before booting the OS. They do this as some platform
+firmware may still have implemented access to MTRRs which would be controlled
+and handled by the platform firmware directly. An example of platform use of
+MTRRs is through the use of SMI handlers, one case could be for fan control,
+the platform code would need uncachable access to some of its fan control
+registers. Such platform access does not need any Operating System MTRR code in
+place other than mtrr_type_lookup() to ensure any OS specific mapping requests
+are aligned with platform MTRR setup. If MTRRs are only set up by the platform
+firmware code though and the OS does not make any specific MTRR mapping
+requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.
 
 For details refer to Documentation/x86/pat.txt.
 
diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h
index e998ff5d8e1a..f855646e0db7 100644
--- a/arch/avr32/include/asm/io.h
+++ b/arch/avr32/include/asm/io.h
@@ -297,6 +297,7 @@ extern void __iounmap(void __iomem *addr);
 
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache
+#define ioremap_uc ioremap_nocache
 
 #define cached(addr) P1SEGADDR(addr)
 #define uncached(addr) P2SEGADDR(addr)
diff --git a/arch/frv/include/asm/io.h b/arch/frv/include/asm/io.h
index a31b63ec4930..70dfbea8c8d7 100644
--- a/arch/frv/include/asm/io.h
+++ b/arch/frv/include/asm/io.h
@@ -278,6 +278,7 @@ static inline void __iomem *ioremap_fullcache(unsigned long 
physaddr, unsigned l
 }
 
 #define ioremap_wc ioremap_nocache
+#define ioremap_uc ioremap_nocache
 
 extern void iounmap(void volatile __iomem *addr);
 
diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h
index f8de767ce2bc..61b8931bc192 100644
--- a/arch/m32r/include/asm/io.h
+++ b/arch/m32r/include/asm/io.h
@@ -69,6 +69,7 @@ extern void iounmap(volatile void __iomem *addr);
 #define ioremap_nocache(off,size) ioremap(off,size)
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache
+#define ioremap_uc ioremap_nocache
 
 /*
  * IO bus memory addresses are also 1:1 with the physical address
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index f55cad529400..c98ac81582ac 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -468,6 +468,7 @@ static inline void __iomem *ioremap_nocache(unsigned long 
physaddr, unsigned lon
 {
        return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
 }
+#define ioremap_uc ioremap_nocache
 static inline void __iomem *ioremap_wt(unsigned long physaddr,
                                         unsigned long size)
 {
diff --git a/arch/mn10300/include/asm/io.h b/arch/mn10300/include/asm/io.h
index 07c5b4a3903b..62189353d2f6 100644
--- a/arch/mn10300/include/asm/io.h
+++ b/arch/mn10300/include/asm/io.h
@@ -283,6 +283,7 @@ static inline void __iomem *ioremap_nocache(unsigned long 
offset, unsigned long
 
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache
+#define ioremap_uc ioremap_nocache
 
 static inline void iounmap(void __iomem *addr)
 {
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index a8d2ef30d473..5879fde56f3c 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -721,6 +721,7 @@ extern void __iomem *ioremap_prot(phys_addr_t address, 
unsigned long size,
                                  unsigned long flags);
 extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size);
 #define ioremap_nocache(addr, size)    ioremap((addr), (size))
+#define ioremap_uc(addr, size)         ioremap((addr), (size))
 
 extern void iounmap(volatile void __iomem *addr);
 
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index cb5fdf3a78fc..437e9af96688 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -57,6 +57,8 @@ static inline void ioport_unmap(void __iomem *p)
  */
 #define pci_iomap pci_iomap
 #define pci_iounmap pci_iounmap
+#define pci_iomap_wc pci_iomap
+#define pci_iomap_wc_range pci_iomap_range
 
 #define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
 #define memcpy_toio(dst, src, count)   zpci_memcpy_toio(dst, src, count)
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 728c4c571f40..93ec9066dbef 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -368,6 +368,7 @@ static inline int iounmap_fixed(void __iomem *addr) { 
return -EINVAL; }
 #endif
 
 #define ioremap_nocache        ioremap
+#define ioremap_uc     ioremap
 #define iounmap                __iounmap
 
 /*
diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h
index dc61de15c1f9..322b5fe94781 100644
--- a/arch/tile/include/asm/io.h
+++ b/arch/tile/include/asm/io.h
@@ -55,6 +55,7 @@ extern void iounmap(volatile void __iomem *addr);
 #define ioremap_nocache(physaddr, size)                ioremap(physaddr, size)
 #define ioremap_wc(physaddr, size)             ioremap(physaddr, size)
 #define ioremap_wt(physaddr, size)             ioremap(physaddr, size)
+#define ioremap_uc(physaddr, size)             ioremap(physaddr, size)
 #define ioremap_fullcache(physaddr, size)      ioremap(physaddr, size)
 
 #define mmiowb()
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index cc9c61bc1abe..7cfc085b6879 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -180,6 +180,8 @@ static inline unsigned int isa_virt_to_bus(volatile void 
*address)
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long 
size);
 extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
+#define ioremap_uc ioremap_uc
+
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
                                unsigned long prot_val);
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index 58118e207a69..145863d4d343 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/workqueue.h>
@@ -163,6 +163,5 @@ static int start_periodic_check_for_corruption(void)
        schedule_delayed_work(&bios_check_work, 0);
        return 0;
 }
-
-module_init(start_periodic_check_for_corruption);
+device_initcall(start_periodic_check_for_corruption);
 
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index e7ed0d8ebacb..f891b4750f04 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -448,7 +448,6 @@ int mtrr_add(unsigned long base, unsigned long size, 
unsigned int type,
        return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
                             increment);
 }
-EXPORT_SYMBOL(mtrr_add);
 
 /**
  * mtrr_del_page - delete a memory type region
@@ -537,7 +536,6 @@ int mtrr_del(int reg, unsigned long base, unsigned long 
size)
                return -EINVAL;
        return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
 }
-EXPORT_SYMBOL(mtrr_del);
 
 /**
  * arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 8533b46e6bee..1d8a83df153a 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -30,8 +30,11 @@
 /*
  * Tables translating between page_cache_type_t and pte encoding.
  *
- * Minimal supported modes are defined statically, they are modified
- * during bootup if more supported cache modes are available.
+ * The default values are defined statically as minimal supported mode;
+ * WC and WT fall back to UC-.  pat_init() updates these values to support
+ * more cache modes, WC and WT, when it is safe to do so.  See pat_init()
+ * for the details.  Note, __early_ioremap() used during early boot-time
+ * takes pgprot_t (pte encoding) and does not use these tables.
  *
  *   Index into __cachemode2pte_tbl[] is the cachemode.
  *
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 8340e45c891a..68aec42545c2 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -137,6 +137,7 @@ page_table_range_init_count(unsigned long start, unsigned 
long end)
 
        vaddr = start;
        pgd_idx = pgd_index(vaddr);
+       pmd_idx = pmd_index(vaddr);
 
        for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd_idx++) {
                for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index 8ff686aa7e8c..5f169d5d76a8 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -8,6 +8,7 @@
 #include <linux/kthread.h>
 #include <linux/random.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 
@@ -256,5 +257,4 @@ static int start_pageattr_test(void)
 
        return 0;
 }
-
-module_init(start_pageattr_test);
+device_initcall(start_pageattr_test);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 727158cb3b3c..2c44c0792301 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -4,7 +4,6 @@
  */
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 998826854fdd..e4f43125e0fb 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1300,10 +1300,11 @@ static int iop_adma_probe(struct platform_device *pdev)
         * note: writecombine gives slightly better performance, but
         * requires that we explicitly flush the writes
         */
-       if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
-                                       plat_data->pool_size,
-                                       &adev->dma_desc_pool,
-                                       GFP_KERNEL)) == NULL) {
+       adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+                                                         plat_data->pool_size,
+                                                         &adev->dma_desc_pool,
+                                                         GFP_KERNEL);
+       if (!adev->dma_desc_pool_virt) {
                ret = -ENOMEM;
                goto err_free_adev;
        }
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0008c950452c..fdae37b473f8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -138,6 +138,20 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int 
bar)
        return ioremap_nocache(res->start, resource_size(res));
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_bar);
+
+void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar)
+{
+       /*
+        * Make sure the BAR is actually a memory resource, not an IO resource
+        */
+       if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
+               WARN_ON(1);
+               return NULL;
+       }
+       return ioremap_wc(pci_resource_start(pdev, bar),
+                         pci_resource_len(pdev, bar));
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar);
 #endif
 
 #define PCI_FIND_CAP_TTL       48
diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c
index b305a1e7cc76..6a317de7082c 100644
--- a/drivers/video/fbdev/arkfb.c
+++ b/drivers/video/fbdev/arkfb.c
@@ -26,13 +26,9 @@
 #include <linux/console.h> /* Why should fb driver call console functions? 
because console_lock() */
 #include <video/vga.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 struct arkfb_info {
        int mclk_freq;
-       int mtrr_reg;
+       int wc_cookie;
 
        struct dac_info *dac;
        struct vgastate state;
@@ -102,10 +98,6 @@ static const struct svga_timing_regs ark_timing_regs     = {
 
 static char *mode_option = "640x480-8@60";
 
-#ifdef CONFIG_MTRR
-static int mtrr = 1;
-#endif
-
 MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <[email protected]>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
@@ -115,11 +107,6 @@ MODULE_PARM_DESC(mode_option, "Default video mode 
('640x480-8@60', etc)");
 module_param_named(mode, mode_option, charp, 0444);
 MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) 
(deprecated)");
 
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0444);
-MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, 
default=1)");
-#endif
-
 static int threshold = 4;
 
 module_param(threshold, int, 0644);
@@ -1002,7 +989,7 @@ static int ark_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
        info->fix.smem_len = pci_resource_len(dev, 0);
 
        /* Map physical IO memory address into kernel space */
-       info->screen_base = pci_iomap(dev, 0, 0);
+       info->screen_base = pci_iomap_wc(dev, 0, 0);
        if (! info->screen_base) {
                rc = -ENOMEM;
                dev_err(info->device, "iomap for framebuffer failed\n");
@@ -1057,14 +1044,8 @@ static int ark_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
 
        /* Record a reference to the driver data */
        pci_set_drvdata(dev, info);
-
-#ifdef CONFIG_MTRR
-       if (mtrr) {
-               par->mtrr_reg = -1;
-               par->mtrr_reg = mtrr_add(info->fix.smem_start, 
info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-       }
-#endif
-
+       par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
+                                         info->fix.smem_len);
        return 0;
 
        /* Error handling */
@@ -1092,14 +1073,7 @@ static void ark_pci_remove(struct pci_dev *dev)
 
        if (info) {
                struct arkfb_info *par = info->par;
-
-#ifdef CONFIG_MTRR
-               if (par->mtrr_reg >= 0) {
-                       mtrr_del(par->mtrr_reg, 0, 0);
-                       par->mtrr_reg = -1;
-               }
-#endif
-
+               arch_phys_wc_del(par->wc_cookie);
                dac_release(par->dac);
                unregister_framebuffer(info);
                fb_dealloc_cmap(&info->cmap);
diff --git a/drivers/video/fbdev/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h
index 1f39a62f899b..63c4842eb224 100644
--- a/drivers/video/fbdev/aty/atyfb.h
+++ b/drivers/video/fbdev/aty/atyfb.h
@@ -182,10 +182,7 @@ struct atyfb_par {
        unsigned long irq_flags;
        unsigned int irq;
        spinlock_t int_lock;
-#ifdef CONFIG_MTRR
-       int mtrr_aper;
-       int mtrr_reg;
-#endif
+       int wc_cookie;
        u32 mem_cntl;
        struct crtc saved_crtc;
        union aty_pll saved_pll;
diff --git a/drivers/video/fbdev/aty/atyfb_base.c 
b/drivers/video/fbdev/aty/atyfb_base.c
index 8789e487b96e..f34ed47fcaf8 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -98,9 +98,6 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
 
 /*
  * Debug flags.
@@ -303,9 +300,7 @@ static struct fb_ops atyfb_ops = {
 };
 
 static bool noaccel;
-#ifdef CONFIG_MTRR
 static bool nomtrr;
-#endif
 static int vram;
 static int pll;
 static int mclk;
@@ -427,6 +422,20 @@ static struct {
 #endif /* CONFIG_FB_ATY_CT */
 };
 
+/*
+ * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+ * unless the auxiliary register aperture is used.
+ */
+static void aty_fudge_framebuffer_len(struct fb_info *info)
+{
+       struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+       if (!par->aux_start &&
+           (info->fix.smem_len == 0x800000 ||
+            (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
+               info->fix.smem_len -= GUI_RESERVE;
+}
+
 static int correct_chipset(struct atyfb_par *par)
 {
        u8 rev;
@@ -2603,14 +2612,7 @@ static int aty_init(struct fb_info *info)
        if (par->pll_ops->resume_pll)
                par->pll_ops->resume_pll(info, &par->pll);
 
-       /*
-        * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
-        * unless the auxiliary register aperture is used.
-        */
-       if (!par->aux_start &&
-           (info->fix.smem_len == 0x800000 ||
-            (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
-               info->fix.smem_len -= GUI_RESERVE;
+       aty_fudge_framebuffer_len(info);
 
        /*
         * Disable register access through the linear aperture
@@ -2621,25 +2623,13 @@ static int aty_init(struct fb_info *info)
                aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
                            BUS_APER_REG_DIS, par);
 
-#ifdef CONFIG_MTRR
-       par->mtrr_aper = -1;
-       par->mtrr_reg = -1;
-       if (!nomtrr) {
-               /* Cover the whole resource. */
-               par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
-                                         MTRR_TYPE_WRCOMB, 1);
-               if (par->mtrr_aper >= 0 && !par->aux_start) {
-                       /* Make a hole for mmio. */
-                       par->mtrr_reg = mtrr_add(par->res_start + 0x800000 -
-                                                GUI_RESERVE, GUI_RESERVE,
-                                                MTRR_TYPE_UNCACHABLE, 1);
-                       if (par->mtrr_reg < 0) {
-                               mtrr_del(par->mtrr_aper, 0, 0);
-                               par->mtrr_aper = -1;
-                       }
-               }
-       }
-#endif
+       if (!nomtrr)
+               /*
+                * Only the ioremap_wc()'d area will get WC here
+                * since ioremap_uc() was used on the entire PCI BAR.
+                */
+               par->wc_cookie = arch_phys_wc_add(par->res_start,
+                                                 par->res_size);
 
        info->fbops = &atyfb_ops;
        info->pseudo_palette = par->pseudo_palette;
@@ -2767,17 +2757,8 @@ static int aty_init(struct fb_info *info)
        /* restore video mode */
        aty_set_crtc(par, &par->saved_crtc);
        par->pll_ops->set_pll(info, &par->saved_pll);
+       arch_phys_wc_del(par->wc_cookie);
 
-#ifdef CONFIG_MTRR
-       if (par->mtrr_reg >= 0) {
-               mtrr_del(par->mtrr_reg, 0, 0);
-               par->mtrr_reg = -1;
-       }
-       if (par->mtrr_aper >= 0) {
-               mtrr_del(par->mtrr_aper, 0, 0);
-               par->mtrr_aper = -1;
-       }
-#endif
        return ret;
 }
 
@@ -3459,7 +3440,11 @@ static int atyfb_setup_generic(struct pci_dev *pdev, 
struct fb_info *info,
        }
 
        info->fix.mmio_start = raddr;
-       par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
+       /*
+        * By using strong UC we force the MTRR to never have an
+        * effect on the MMIO region on both non-PAT and PAT systems.
+        */
+       par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000);
        if (par->ati_regbase == NULL)
                return -ENOMEM;
 
@@ -3482,7 +3467,24 @@ static int atyfb_setup_generic(struct pci_dev *pdev, 
struct fb_info *info,
 
        /* Map in frame buffer */
        info->fix.smem_start = addr;
-       info->screen_base = ioremap(addr, 0x800000);
+
+       /*
+        * The framebuffer is not always 8 MiB, that's just the size of the
+        * PCI BAR. We temporarily abuse smem_len here to store the size
+        * of the BAR. aty_init() will later correct it to match the actual
+        * framebuffer size.
+        *
+        * On devices that don't have the auxiliary register aperture, the
+        * registers are housed at the top end of the framebuffer PCI BAR.
+        * aty_fudge_framebuffer_len() is used to reduce smem_len to not
+        * overlap with the registers.
+        */
+       info->fix.smem_len = 0x800000;
+
+       aty_fudge_framebuffer_len(info);
+
+       info->screen_base = ioremap_wc(info->fix.smem_start,
+                                      info->fix.smem_len);
        if (info->screen_base == NULL) {
                ret = -ENOMEM;
                goto atyfb_setup_generic_fail;
@@ -3554,6 +3556,7 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
                return -ENOMEM;
        }
        par = info->par;
+       par->bus_type = PCI;
        info->fix = atyfb_fix;
        info->device = &pdev->dev;
        par->pci_id = pdev->device;
@@ -3655,7 +3658,8 @@ static int __init atyfb_atari_probe(void)
                 * Map the video memory (physical address given)
                 * to somewhere in the kernel address space.
                 */
-               info->screen_base = ioremap(phys_vmembase[m64_num], 
phys_size[m64_num]);
+               info->screen_base = ioremap_wc(phys_vmembase[m64_num],
+                                              phys_size[m64_num]);
                info->fix.smem_start = (unsigned long)info->screen_base; /* 
Fake! */
                par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
                                                0xFC00ul;
@@ -3721,17 +3725,8 @@ static void atyfb_remove(struct fb_info *info)
        if (M64_HAS(MOBIL_BUS))
                aty_bl_exit(info->bl_dev);
 #endif
+       arch_phys_wc_del(par->wc_cookie);
 
-#ifdef CONFIG_MTRR
-       if (par->mtrr_reg >= 0) {
-               mtrr_del(par->mtrr_reg, 0, 0);
-               par->mtrr_reg = -1;
-       }
-       if (par->mtrr_aper >= 0) {
-               mtrr_del(par->mtrr_aper, 0, 0);
-               par->mtrr_aper = -1;
-       }
-#endif
 #ifndef __sparc__
        if (par->ati_regbase)
                iounmap(par->ati_regbase);
@@ -3847,10 +3842,8 @@ static int __init atyfb_setup(char *options)
        while ((this_opt = strsep(&options, ",")) != NULL) {
                if (!strncmp(this_opt, "noaccel", 7)) {
                        noaccel = 1;
-#ifdef CONFIG_MTRR
                } else if (!strncmp(this_opt, "nomtrr", 6)) {
                        nomtrr = 1;
-#endif
                } else if (!strncmp(this_opt, "vram:", 5))
                        vram = simple_strtoul(this_opt + 5, NULL, 0);
                else if (!strncmp(this_opt, "pll:", 4))
@@ -4020,7 +4013,5 @@ module_param(comp_sync, int, 0);
 MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high 
(1)");
 module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode, "Specify resolution as 
\"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
-#endif
diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c
index 135d78a02588..f19133a80e8c 100644
--- a/drivers/video/fbdev/gxt4500.c
+++ b/drivers/video/fbdev/gxt4500.c
@@ -662,7 +662,7 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
 
        info->fix.smem_start = fb_phys;
        info->fix.smem_len = pci_resource_len(pdev, 1);
-       info->screen_base = pci_ioremap_bar(pdev, 1);
+       info->screen_base = pci_ioremap_wc_bar(pdev, 1);
        if (!info->screen_base) {
                dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n");
                goto err_unmap_regs;
diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c
index a2b4204b42bb..452e1163ad02 100644
--- a/drivers/video/fbdev/i740fb.c
+++ b/drivers/video/fbdev/i740fb.c
@@ -27,24 +27,15 @@
 #include <linux/console.h>
 #include <video/vga.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 #include "i740_reg.h"
 
 static char *mode_option;
-
-#ifdef CONFIG_MTRR
 static int mtrr = 1;
-#endif
 
 struct i740fb_par {
        unsigned char __iomem *regs;
        bool has_sgram;
-#ifdef CONFIG_MTRR
-       int mtrr_reg;
-#endif
+       int wc_cookie;
        bool ddc_registered;
        struct i2c_adapter ddc_adapter;
        struct i2c_algo_bit_data ddc_algo;
@@ -1040,7 +1031,7 @@ static int i740fb_probe(struct pci_dev *dev, const struct 
pci_device_id *ent)
                goto err_request_regions;
        }
 
-       info->screen_base = pci_ioremap_bar(dev, 0);
+       info->screen_base = pci_ioremap_wc_bar(dev, 0);
        if (!info->screen_base) {
                dev_err(info->device, "error remapping base\n");
                ret = -ENOMEM;
@@ -1144,13 +1135,9 @@ static int i740fb_probe(struct pci_dev *dev, const 
struct pci_device_id *ent)
 
        fb_info(info, "%s frame buffer device\n", info->fix.id);
        pci_set_drvdata(dev, info);
-#ifdef CONFIG_MTRR
-       if (mtrr) {
-               par->mtrr_reg = -1;
-               par->mtrr_reg = mtrr_add(info->fix.smem_start,
-                               info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-       }
-#endif
+       if (mtrr)
+               par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
+                                                 info->fix.smem_len);
        return 0;
 
 err_reg_framebuffer:
@@ -1177,13 +1164,7 @@ static void i740fb_remove(struct pci_dev *dev)
 
        if (info) {
                struct i740fb_par *par = info->par;
-
-#ifdef CONFIG_MTRR
-               if (par->mtrr_reg >= 0) {
-                       mtrr_del(par->mtrr_reg, 0, 0);
-                       par->mtrr_reg = -1;
-               }
-#endif
+               arch_phys_wc_del(par->wc_cookie);
                unregister_framebuffer(info);
                fb_dealloc_cmap(&info->cmap);
                if (par->ddc_registered)
@@ -1287,10 +1268,8 @@ static int  __init i740fb_setup(char *options)
        while ((opt = strsep(&options, ",")) != NULL) {
                if (!*opt)
                        continue;
-#ifdef CONFIG_MTRR
                else if (!strncmp(opt, "mtrr:", 5))
                        mtrr = simple_strtoul(opt + 5, NULL, 0);
-#endif
                else
                        mode_option = opt;
        }
@@ -1327,7 +1306,5 @@ MODULE_DESCRIPTION("fbdev driver for Intel740");
 module_param(mode_option, charp, 0444);
 MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
 
-#ifdef CONFIG_MTRR
 module_param(mtrr, int, 0444);
 MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, 
default=1)");
-#endif
diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
index 65041e15fd59..5bb01533271e 100644
--- a/drivers/video/fbdev/kyro/fbdev.c
+++ b/drivers/video/fbdev/kyro/fbdev.c
@@ -22,9 +22,6 @@
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <linux/uaccess.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
 
 #include <video/kyro.h>
 
@@ -84,9 +81,7 @@ static device_info_t deviceInfo;
 static char *mode_option = NULL;
 static int nopan = 0;
 static int nowrap = 1;
-#ifdef CONFIG_MTRR
 static int nomtrr = 0;
-#endif
 
 /* PCI driver prototypes */
 static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -570,10 +565,8 @@ static int __init kyrofb_setup(char *options)
                        nopan = 1;
                } else if (strcmp(this_opt, "nowrap") == 0) {
                        nowrap = 1;
-#ifdef CONFIG_MTRR
                } else if (strcmp(this_opt, "nomtrr") == 0) {
                        nomtrr = 1;
-#endif
                } else {
                        mode_option = this_opt;
                }
@@ -691,17 +684,16 @@ static int kyrofb_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
 
        currentpar->regbase = deviceInfo.pSTGReg =
                ioremap_nocache(kyro_fix.mmio_start, kyro_fix.mmio_len);
+       if (!currentpar->regbase)
+               goto out_free_fb;
 
-       info->screen_base = ioremap_nocache(kyro_fix.smem_start,
-                                           kyro_fix.smem_len);
+       info->screen_base = pci_ioremap_wc_bar(pdev, 0);
+       if (!info->screen_base)
+               goto out_unmap_regs;
 
-#ifdef CONFIG_MTRR
        if (!nomtrr)
-               currentpar->mtrr_handle =
-                       mtrr_add(kyro_fix.smem_start,
-                                kyro_fix.smem_len,
-                                MTRR_TYPE_WRCOMB, 1);
-#endif
+               currentpar->wc_cookie = arch_phys_wc_add(kyro_fix.smem_start,
+                                                        kyro_fix.smem_len);
 
        kyro_fix.ypanstep       = nopan ? 0 : 1;
        kyro_fix.ywrapstep      = nowrap ? 0 : 1;
@@ -745,8 +737,10 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
        return 0;
 
 out_unmap:
-       iounmap(currentpar->regbase);
        iounmap(info->screen_base);
+out_unmap_regs:
+       iounmap(currentpar->regbase);
+out_free_fb:
        framebuffer_release(info);
 
        return -EINVAL;
@@ -770,12 +764,7 @@ static void kyrofb_remove(struct pci_dev *pdev)
        iounmap(info->screen_base);
        iounmap(par->regbase);
 
-#ifdef CONFIG_MTRR
-       if (par->mtrr_handle)
-               mtrr_del(par->mtrr_handle,
-                        info->fix.smem_start,
-                        info->fix.smem_len);
-#endif
+       arch_phys_wc_del(par->wc_cookie);
 
        unregister_framebuffer(info);
        framebuffer_release(info);
diff --git a/drivers/video/fbdev/s3fb.c b/drivers/video/fbdev/s3fb.c
index f0ae61a37f04..13b109073c63 100644
--- a/drivers/video/fbdev/s3fb.c
+++ b/drivers/video/fbdev/s3fb.c
@@ -28,13 +28,9 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 struct s3fb_info {
        int chip, rev, mclk_freq;
-       int mtrr_reg;
+       int wc_cookie;
        struct vgastate state;
        struct mutex open_lock;
        unsigned int ref_count;
@@ -154,11 +150,7 @@ static const struct svga_timing_regs s3_timing_regs     = {
 
 
 static char *mode_option;
-
-#ifdef CONFIG_MTRR
 static int mtrr = 1;
-#endif
-
 static int fasttext = 1;
 
 
@@ -170,11 +162,8 @@ module_param(mode_option, charp, 0444);
 MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
 module_param_named(mode, mode_option, charp, 0444);
 MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) 
(deprecated)");
-
-#ifdef CONFIG_MTRR
 module_param(mtrr, int, 0444);
 MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, 
default=1)");
-#endif
 
 module_param(fasttext, int, 0644);
 MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, 
default=1)");
@@ -1168,7 +1157,7 @@ static int s3_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
        info->fix.smem_len = pci_resource_len(dev, 0);
 
        /* Map physical IO memory address into kernel space */
-       info->screen_base = pci_iomap(dev, 0, 0);
+       info->screen_base = pci_iomap_wc(dev, 0, 0);
        if (! info->screen_base) {
                rc = -ENOMEM;
                dev_err(info->device, "iomap for framebuffer failed\n");
@@ -1365,12 +1354,9 @@ static int s3_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
        /* Record a reference to the driver data */
        pci_set_drvdata(dev, info);
 
-#ifdef CONFIG_MTRR
-       if (mtrr) {
-               par->mtrr_reg = -1;
-               par->mtrr_reg = mtrr_add(info->fix.smem_start, 
info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-       }
-#endif
+       if (mtrr)
+               par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
+                                                 info->fix.smem_len);
 
        return 0;
 
@@ -1405,14 +1391,7 @@ static void s3_pci_remove(struct pci_dev *dev)
 
        if (info) {
                par = info->par;
-
-#ifdef CONFIG_MTRR
-               if (par->mtrr_reg >= 0) {
-                       mtrr_del(par->mtrr_reg, 0, 0);
-                       par->mtrr_reg = -1;
-               }
-#endif
-
+               arch_phys_wc_del(par->wc_cookie);
                unregister_framebuffer(info);
                fb_dealloc_cmap(&info->cmap);
 
@@ -1551,10 +1530,8 @@ static int  __init s3fb_setup(char *options)
 
                if (!*opt)
                        continue;
-#ifdef CONFIG_MTRR
                else if (!strncmp(opt, "mtrr:", 5))
                        mtrr = simple_strtoul(opt + 5, NULL, 0);
-#endif
                else if (!strncmp(opt, "fasttext:", 9))
                        fasttext = simple_strtoul(opt + 9, NULL, 0);
                else
diff --git a/drivers/video/fbdev/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c
index 8bac309c24b9..dd0f18e42d3e 100644
--- a/drivers/video/fbdev/vt8623fb.c
+++ b/drivers/video/fbdev/vt8623fb.c
@@ -26,13 +26,9 @@
 #include <linux/console.h> /* Why should fb driver call console functions? 
because console_lock() */
 #include <video/vga.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 struct vt8623fb_info {
        char __iomem *mmio_base;
-       int mtrr_reg;
+       int wc_cookie;
        struct vgastate state;
        struct mutex open_lock;
        unsigned int ref_count;
@@ -99,10 +95,7 @@ static struct svga_timing_regs vt8623_timing_regs     = {
 /* Module parameters */
 
 static char *mode_option = "640x480-8@60";
-
-#ifdef CONFIG_MTRR
 static int mtrr = 1;
-#endif
 
 MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <[email protected]>");
 MODULE_LICENSE("GPL");
@@ -112,11 +105,8 @@ module_param(mode_option, charp, 0644);
 MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
 module_param_named(mode, mode_option, charp, 0);
 MODULE_PARM_DESC(mode, "Default video mode e.g. '648x480-8@60' (deprecated)");
-
-#ifdef CONFIG_MTRR
 module_param(mtrr, int, 0444);
 MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, 
default=1)");
-#endif
 
 
 /* ------------------------------------------------------------------------- */
@@ -710,7 +700,7 @@ static int vt8623_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
        info->fix.mmio_len = pci_resource_len(dev, 1);
 
        /* Map physical IO memory address into kernel space */
-       info->screen_base = pci_iomap(dev, 0, 0);
+       info->screen_base = pci_iomap_wc(dev, 0, 0);
        if (! info->screen_base) {
                rc = -ENOMEM;
                dev_err(info->device, "iomap for framebuffer failed\n");
@@ -781,12 +771,9 @@ static int vt8623_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
        /* Record a reference to the driver data */
        pci_set_drvdata(dev, info);
 
-#ifdef CONFIG_MTRR
-       if (mtrr) {
-               par->mtrr_reg = -1;
-               par->mtrr_reg = mtrr_add(info->fix.smem_start, 
info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-       }
-#endif
+       if (mtrr)
+               par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
+                                                 info->fix.smem_len);
 
        return 0;
 
@@ -816,13 +803,7 @@ static void vt8623_pci_remove(struct pci_dev *dev)
        if (info) {
                struct vt8623fb_info *par = info->par;
 
-#ifdef CONFIG_MTRR
-               if (par->mtrr_reg >= 0) {
-                       mtrr_del(par->mtrr_reg, 0, 0);
-                       par->mtrr_reg = -1;
-               }
-#endif
-
+               arch_phys_wc_del(par->wc_cookie);
                unregister_framebuffer(info);
                fb_dealloc_cmap(&info->cmap);
 
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)
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 */
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);
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);
diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c
index bcce5f149310..5f5d24d1d53f 100644
--- a/lib/pci_iomap.c
+++ b/lib/pci_iomap.c
@@ -52,6 +52,51 @@ void __iomem *pci_iomap_range(struct pci_dev *dev,
 EXPORT_SYMBOL(pci_iomap_range);
 
 /**
+ * pci_iomap_wc_range - create a virtual WC mapping cookie for a PCI BAR
+ * @dev: PCI device that owns the BAR
+ * @bar: BAR number
+ * @offset: map memory at the given offset in BAR
+ * @maxlen: max length of the memory to map
+ *
+ * Using this function you will get a __iomem address to your device BAR.
+ * You can access it using ioread*() and iowrite*(). These functions hide
+ * the details if this is a MMIO or PIO address space and will just do what
+ * you expect from them in the correct way. When possible write combining
+ * is used.
+ *
+ * @maxlen specifies the maximum length to map. If you want to get access to
+ * the complete BAR from offset to the end, pass %0 here.
+ * */
+void __iomem *pci_iomap_wc_range(struct pci_dev *dev,
+                                int bar,
+                                unsigned long offset,
+                                unsigned long maxlen)
+{
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+
+       if (flags & IORESOURCE_IO)
+               return NULL;
+
+       if (len <= offset || !start)
+               return NULL;
+
+       len -= offset;
+       start += offset;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+
+       if (flags & IORESOURCE_MEM)
+               return ioremap_wc(start, len);
+
+       /* What? */
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(pci_iomap_wc_range);
+
+/**
  * pci_iomap - create a virtual mapping cookie for a PCI BAR
  * @dev: PCI device that owns the BAR
  * @bar: BAR number
@@ -70,4 +115,25 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, 
unsigned long maxlen)
        return pci_iomap_range(dev, bar, 0, maxlen);
 }
 EXPORT_SYMBOL(pci_iomap);
+
+/**
+ * pci_iomap_wc - create a virtual WC mapping cookie for a PCI BAR
+ * @dev: PCI device that owns the BAR
+ * @bar: BAR number
+ * @maxlen: length of the memory to map
+ *
+ * Using this function you will get a __iomem address to your device BAR.
+ * You can access it using ioread*() and iowrite*(). These functions hide
+ * the details if this is a MMIO or PIO address space and will just do what
+ * you expect from them in the correct way. When possible write combining
+ * is used.
+ *
+ * @maxlen specifies the maximum length to map. If you want to get access to
+ * the complete BAR without checking for its length first, pass %0 here.
+ * */
+void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       return pci_iomap_wc_range(dev, bar, 0, maxlen);
+}
+EXPORT_SYMBOL_GPL(pci_iomap_wc);
 #endif /* CONFIG_PCI */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to