--- arch/i386/pci/i386.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) Index: linux/arch/i386/pci/i386.c =================================================================== --- linux.orig/arch/i386/pci/i386.c +++ linux/arch/i386/pci/i386.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "pci.h" @@ -262,9 +264,25 @@ void pcibios_set_master(struct pci_dev * pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } +static void pci_unmap_page_range(struct vm_area_struct *vma) +{ + u64 adr = (u64)vma->vm_pgoff << PAGE_SHIFT; + free_mattr(adr, adr + vma->vm_end - vma->vm_start, + pgprot_val(vma->vm_page_prot) & _PAGE_CACHE_MASK); +} + +static struct vm_operations_struct pci_mmap_ops = { + .close = pci_unmap_page_range +}; + int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { + u64 addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long len = vma->vm_end - vma->vm_start; + unsigned long attr; + int err; + /* I/O space cannot be accessed via normal processor loads and * stores on this platform. */ @@ -279,10 +297,17 @@ int pci_mmap_page_range(struct pci_dev * else vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + attr = pgprot_val(vma->vm_page_prot) & _PAGE_CACHE_MASK; + err = reserve_mattr(addr, addr+len, attr, NULL); + if (err) + return err; + if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + vma->vm_ops = &pci_mmap_ops; + return 0; }