diff options
-rw-r--r-- | arch/mips/Kconfig | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/pgtable.h | 13 | ||||
-rw-r--r-- | arch/mips/loongson/common/mem.c | 58 |
3 files changed, 74 insertions, 0 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 51e4e5b02f9..e2116b1f968 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1336,6 +1336,7 @@ config SYS_HAS_CPU_LOONGSON2F bool select CPU_SUPPORTS_CPUFREQ select CPU_SUPPORTS_ADDRWINCFG if 64BIT + select CPU_SUPPORTS_UNCACHED_ACCELERATED config SYS_HAS_CPU_MIPS32_R1 bool @@ -1451,6 +1452,8 @@ config CPU_SUPPORTS_ADDRWINCFG bool config CPU_SUPPORTS_HUGEPAGES bool +config CPU_SUPPORTS_UNCACHED_ACCELERATED + bool config MIPS_PGD_C0_CONTEXT bool default y if 64BIT && CPU_MIPSR2 diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index d6eb6134abe..1854336e56a 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -390,6 +390,19 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma, #include <asm-generic/pgtable.h> /* + * uncached accelerated TLB map for video memory access + */ +#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED +#define __HAVE_PHYS_MEM_ACCESS_PROT + +struct file; +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); +int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t *vma_prot); +#endif + +/* * We provide our own get_unmapped area to cope with the virtual aliasing * constraints placed on us by the cache architecture. */ diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index 981e9190f39..ceacd092b44 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -58,3 +58,61 @@ int __uncached_access(struct file *file, unsigned long addr) ((addr >= LOONGSON_MMIO_MEM_START) && (addr < LOONGSON_MMIO_MEM_END)); } + +#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED + +#include <linux/pci.h> +#include <linux/sched.h> +#include <asm/current.h> + +static unsigned long uca_start, uca_end; + +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot) +{ + unsigned long offset = pfn << PAGE_SHIFT; + unsigned long end = offset + size; + + if (__uncached_access(file, offset)) { + if (((uca_start && offset) >= uca_start) && + (end <= uca_end)) + return __pgprot((pgprot_val(vma_prot) & + ~_CACHE_MASK) | + _CACHE_UNCACHED_ACCELERATED); + else + return pgprot_noncached(vma_prot); + } + return vma_prot; +} + +static int __init find_vga_mem_init(void) +{ + struct pci_dev *dev = 0; + struct resource *r; + int idx; + + if (uca_start) + return 0; + + for_each_pci_dev(dev) { + if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { + for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) + continue; + if (r->flags & IORESOURCE_IO) + continue; + if (r->flags & IORESOURCE_MEM) { + uca_start = r->start; + uca_end = r->end; + return 0; + } + } + } + } + + return 0; +} + +late_initcall(find_vga_mem_init); +#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */ |