x86: PAT add ioremap_wc() interface
authorvenkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com>
Wed, 19 Mar 2008 00:00:24 +0000 (17:00 -0700)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:41:20 +0000 (17:41 +0200)
Introduce ioremap_wc for wc remap.

(generic wrapper is in a later patch)

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/mm/ioremap.c
include/asm-x86/io.h
include/asm-x86/pgtable.h

index 0cdb7f1..51cd395 100644 (file)
@@ -97,6 +97,9 @@ int ioremap_change_attr(unsigned long vaddr, unsigned long size,
        default:
                err = _set_memory_uc(vaddr, nrpages);
                break;
+       case _PAGE_CACHE_WC:
+               err = _set_memory_wc(vaddr, nrpages);
+               break;
        case _PAGE_CACHE_WB:
                err = _set_memory_wb(vaddr, nrpages);
                break;
@@ -166,8 +169,13 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
                 * Do not fallback to certain memory types with certain
                 * requested type:
                 * - request is uncached, return cannot be write-back
+                * - request is uncached, return cannot be write-combine
+                * - request is write-combine, return cannot be write-back
                 */
                if ((prot_val == _PAGE_CACHE_UC &&
+                    (new_prot_val == _PAGE_CACHE_WB ||
+                     new_prot_val == _PAGE_CACHE_WC)) ||
+                   (prot_val == _PAGE_CACHE_WC &&
                     new_prot_val == _PAGE_CACHE_WB)) {
                        free_memtype(phys_addr, phys_addr + size);
                        return NULL;
@@ -180,6 +188,9 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
        default:
                prot = PAGE_KERNEL_NOCACHE;
                break;
+       case _PAGE_CACHE_WC:
+               prot = PAGE_KERNEL_WC;
+               break;
        case _PAGE_CACHE_WB:
                prot = PAGE_KERNEL;
                break;
@@ -235,6 +246,25 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 }
 EXPORT_SYMBOL(ioremap_nocache);
 
+/**
+ * ioremap_wc  -       map memory into CPU space write combined
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * This version of ioremap ensures that the memory is marked write combining.
+ * Write combining allows faster writes to some hardware devices.
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
+{
+       if (pat_wc_enabled)
+               return __ioremap(phys_addr, size, _PAGE_CACHE_WC);
+       else
+               return ioremap_nocache(phys_addr, size);
+}
+EXPORT_SYMBOL(ioremap_wc);
+
 void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
 {
        return __ioremap(phys_addr, size, _PAGE_CACHE_WB);
index 6fa150f..599cad3 100644 (file)
@@ -1,3 +1,5 @@
+#define ARCH_HAS_IOREMAP_WC
+
 #ifdef CONFIG_X86_32
 # include "io_32.h"
 #else
@@ -5,4 +7,5 @@
 #endif
 extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
                                unsigned long prot_val);
+extern void __iomem * ioremap_wc(unsigned long offset, unsigned long size);
 
index ca6deb3..e814cfe 100644 (file)
@@ -90,6 +90,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
 #define __PAGE_KERNEL_RO               (__PAGE_KERNEL & ~_PAGE_RW)
 #define __PAGE_KERNEL_RX               (__PAGE_KERNEL_EXEC & ~_PAGE_RW)
 #define __PAGE_KERNEL_EXEC_NOCACHE     (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_WC               (__PAGE_KERNEL | _PAGE_CACHE_WC)
 #define __PAGE_KERNEL_NOCACHE          (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
 #define __PAGE_KERNEL_UC_MINUS         (__PAGE_KERNEL | _PAGE_PCD)
 #define __PAGE_KERNEL_VSYSCALL         (__PAGE_KERNEL_RX | _PAGE_USER)
@@ -107,6 +108,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
 #define PAGE_KERNEL_RO                 MAKE_GLOBAL(__PAGE_KERNEL_RO)
 #define PAGE_KERNEL_EXEC               MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
 #define PAGE_KERNEL_RX                 MAKE_GLOBAL(__PAGE_KERNEL_RX)
+#define PAGE_KERNEL_WC                 MAKE_GLOBAL(__PAGE_KERNEL_WC)
 #define PAGE_KERNEL_NOCACHE            MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
 #define PAGE_KERNEL_UC_MINUS           MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
 #define PAGE_KERNEL_EXEC_NOCACHE       MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)