From ae749c7ab475de2c9c427058db19921c91846e89 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:25:54 +0100 Subject: PCI: Add arch_can_pci_mmap_wc() macro Most of the almost-identical versions of pci_mmap_page_range() silently ignore the 'write_combine' argument and give uncached mappings. Yet we allow the PCIIOC_WRITE_COMBINE ioctl in /proc/bus/pci, expose the 'resourceX_wc' file in sysfs, and allow an attempted mapping to apparently succeed. To fix this, introduce a macro arch_can_pci_mmap_wc() which indicates whether the platform can do a write-combining mapping. On x86 this ends up being pat_enabled(), while the few other platforms that support it can just set it to a literal '1'. Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86/include/asm/pci.h') diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 1411dbed5e5e..f6e22c271efa 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #ifdef __KERNEL__ @@ -102,6 +103,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); #define HAVE_PCI_MMAP +#define arch_can_pci_mmap_wc() pat_enabled() extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); -- cgit v1.2.3 From 11df19546fe4a6135cdae62e96a1e25b3fabf6ea Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:25:55 +0100 Subject: PCI: Move multiple declarations of pci_mmap_page_range() to We can declare it even on platforms where it isn't going to be defined. There's no need to have it littered through the various files. Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas --- arch/arm/include/asm/pci.h | 2 -- arch/cris/include/asm/pci.h | 3 --- arch/ia64/include/asm/pci.h | 2 -- arch/microblaze/include/asm/pci.h | 3 --- arch/mips/include/asm/pci.h | 3 --- arch/mn10300/include/asm/pci.h | 3 --- arch/parisc/include/asm/pci.h | 3 --- arch/powerpc/include/asm/pci.h | 3 --- arch/sh/include/asm/pci.h | 3 +-- arch/sparc/include/asm/pci_64.h | 4 ---- arch/unicore32/include/asm/pci.h | 2 -- arch/x86/include/asm/pci.h | 4 ---- arch/xtensa/include/asm/pci.h | 4 ---- include/linux/pci.h | 7 +++++++ 14 files changed, 8 insertions(+), 38 deletions(-) (limited to 'arch/x86/include/asm/pci.h') diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 057d381f4e57..51118a0cabbc 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -29,8 +29,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) #define PCI_DMA_BUS_IS_PHYS (1) #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) { diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h index b1b289df04c7..65198cb46c85 100644 --- a/arch/cris/include/asm/pci.h +++ b/arch/cris/include/asm/pci.h @@ -42,9 +42,6 @@ struct pci_dev; #define PCI_DMA_BUS_IS_PHYS (1) #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); - #endif /* __KERNEL__ */ diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 6283758474ad..fc60b3d139f4 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h @@ -53,8 +53,6 @@ extern unsigned long ia64_max_iommu_merge_mask; #define HAVE_PCI_MMAP #define arch_can_pci_mmap_wc() 1 -extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); #define HAVE_PCI_LEGACY extern int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma, diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 2a120bb70e54..ab381d283fb9 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -46,9 +46,6 @@ extern int pci_domain_nr(struct pci_bus *bus); extern int pci_proc_domain(struct pci_bus *bus); struct vm_area_struct; -/* Map a range of PCI memory or I/O space for a device into user space */ -int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ #define HAVE_PCI_MMAP 1 diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 30d1129d8624..3141e2a8113a 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -111,9 +111,6 @@ extern void pcibios_set_master(struct pci_dev *dev); #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); - #define HAVE_ARCH_PCI_RESOURCE_TO_USER /* diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h index 51159fff025a..082b6de90936 100644 --- a/arch/mn10300/include/asm/pci.h +++ b/arch/mn10300/include/asm/pci.h @@ -74,9 +74,6 @@ static inline int pci_controller_num(struct pci_dev *dev) } #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, - int write_combine); #endif /* __KERNEL__ */ diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index defebd956585..bb9ea9003e08 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h @@ -201,7 +201,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); - #endif /* __ASM_PARISC_PCI_H */ diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index b5b68c6a10b1..55887d171205 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -77,9 +77,6 @@ extern int pci_domain_nr(struct pci_bus *bus); extern int pci_proc_domain(struct pci_bus *bus); struct vm_area_struct; -/* Map a range of PCI memory or I/O space for a device into user space */ -int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() and it does WC */ #define HAVE_PCI_MMAP 1 diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 644314f2b1ef..46abbc9983c9 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h @@ -66,8 +66,7 @@ extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; struct pci_dev; #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); + extern void pcibios_set_master(struct pci_dev *dev); /* Dynamic DMA mapping stuff. diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h index 2303635158f5..516fda70a1bb 100644 --- a/arch/sparc/include/asm/pci_64.h +++ b/arch/sparc/include/asm/pci_64.h @@ -45,10 +45,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) #define HAVE_ARCH_PCI_GET_UNMAPPED_AREA #define get_pci_unmapped_area get_fb_unmapped_area -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, - int write_combine); - static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) { return PCI_IRQ_NONE; diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h index 37e55d018de5..a51290862acd 100644 --- a/arch/unicore32/include/asm/pci.h +++ b/arch/unicore32/include/asm/pci.h @@ -17,8 +17,6 @@ #include /* for PCIBIOS_MIN_* */ #define HAVE_PCI_MMAP -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); #endif /* __KERNEL__ */ #endif diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index f6e22c271efa..734cc9411b3a 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -104,10 +104,6 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); #define HAVE_PCI_MMAP #define arch_can_pci_mmap_wc() pat_enabled() -extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, - int write_combine); - #ifdef CONFIG_PCI extern void early_quirks(void); diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h index 5d6bd932ba4e..bb5510b28754 100644 --- a/arch/xtensa/include/asm/pci.h +++ b/arch/xtensa/include/asm/pci.h @@ -46,10 +46,6 @@ struct pci_dev; #define PCI_DMA_BUS_IS_PHYS (1) -/* Map a range of PCI memory or I/O space for a device into user space */ -int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); - /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ #define HAVE_PCI_MMAP 1 diff --git a/include/linux/pci.h b/include/linux/pci.h index e614fb42d8bb..e7bb4b62cc97 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1626,6 +1626,13 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; } #include +/* Map a range of PCI memory or I/O space for a device into user space. + * Architectures provide this function if they set HAVE_PCI_MMAP, and + * it accepts the 'write_combine' argument when arch_can_pci_mmap_wc() + * evaluates to nonzero. */ +int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine); + #ifndef arch_can_pci_mmap_wc #define arch_can_pci_mmap_wc() 0 #endif -- cgit v1.2.3 From 5c2d5ce2ab4bd716b2125f15b2e0879143ac0563 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:26:07 +0100 Subject: x86/PCI: Use generic pci_mmap_resource_range() Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci.h | 1 + arch/x86/pci/i386.c | 48 ---------------------------------------------- 2 files changed, 1 insertion(+), 48 deletions(-) (limited to 'arch/x86/include/asm/pci.h') diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 734cc9411b3a..f513cc231151 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -104,6 +104,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); #define HAVE_PCI_MMAP #define arch_can_pci_mmap_wc() pat_enabled() +#define ARCH_GENERIC_PCI_MMAP_RESOURCE #ifdef CONFIG_PCI extern void early_quirks(void); diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 8ca5e5d9f251..68499cf82ccf 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -406,51 +406,3 @@ void __init pcibios_resource_survey(void) */ ioapic_insert_resources(); } - -static const struct vm_operations_struct pci_mmap_ops = { - .access = generic_access_phys, -}; - -int pci_mmap_page_range(struct pci_dev *dev, int bar, - struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - unsigned long prot; - - /* I/O space cannot be accessed via normal processor loads and - * stores on this platform. - */ - if (mmap_state == pci_mmap_io) - return -EINVAL; - - prot = pgprot_val(vma->vm_page_prot); - - /* - * Return error if pat is not enabled and write_combine is requested. - * Caller can followup with UC MINUS request and add a WC mtrr if there - * is a free mtrr slot. - */ - if (!pat_enabled() && write_combine) - return -EINVAL; - - if (pat_enabled() && write_combine) - prot |= cachemode2protval(_PAGE_CACHE_MODE_WC); - else if (pat_enabled() || boot_cpu_data.x86 > 3) - /* - * ioremap() and ioremap_nocache() defaults to UC MINUS for now. - * To avoid attribute conflicts, request UC MINUS here - * as well. - */ - prot |= cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS); - - vma->vm_page_prot = __pgprot(prot); - - 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; -} -- cgit v1.2.3