diff options
| author | Eric Anholt <eric@anholt.net> | 2009-01-23 17:14:21 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-01-26 05:14:27 -0500 |
| commit | ef5fa0ab24b87646c7bc98645acbb4b51fc2acd4 (patch) | |
| tree | 212ee811a6271eb77e887d4f63817c01606ae8a2 | |
| parent | e1b4d1143651fb3838be1117785b6e0386fa151f (diff) | |
x86: work around PAGE_KERNEL_WC not getting WC in iomap_atomic_prot_pfn.
In the absence of PAT, PAGE_KERNEL_WC ends up mapping to a memory type that
gets UC behavior even in the presence of a WC MTRR covering the area in
question. By swapping to PAGE_KERNEL_UC_MINUS, we can get the actual
behavior the caller wanted (WC if you can manage it, UC otherwise).
This recovers the 40% performance improvement of using WC in the DRM
to upload vertex data.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
| -rw-r--r-- | arch/x86/mm/iomap_32.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index d0151d8ce452..ca53224fc56c 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <asm/iomap.h> | 19 | #include <asm/iomap.h> |
| 20 | #include <asm/pat.h> | ||
| 20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 21 | 22 | ||
| 22 | /* Map 'pfn' using fixed map 'type' and protections 'prot' | 23 | /* Map 'pfn' using fixed map 'type' and protections 'prot' |
| @@ -29,6 +30,15 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | |||
| 29 | 30 | ||
| 30 | pagefault_disable(); | 31 | pagefault_disable(); |
| 31 | 32 | ||
| 33 | /* | ||
| 34 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. | ||
| 35 | * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the | ||
| 36 | * MTRR is UC or WC. UC_MINUS gets the real intention, of the | ||
| 37 | * user, which is "WC if the MTRR is WC, UC if you can't do that." | ||
| 38 | */ | ||
| 39 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) | ||
| 40 | prot = PAGE_KERNEL_UC_MINUS; | ||
| 41 | |||
| 32 | idx = type + KM_TYPE_NR*smp_processor_id(); | 42 | idx = type + KM_TYPE_NR*smp_processor_id(); |
| 33 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 43 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
| 34 | set_pte(kmap_pte-idx, pfn_pte(pfn, prot)); | 44 | set_pte(kmap_pte-idx, pfn_pte(pfn, prot)); |
