提交 ae749c7a 编写于 作者: D David Woodhouse 提交者: Bjorn Helgaas

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: NDavid Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
上级 03a064b4
...@@ -117,6 +117,10 @@ code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function. ...@@ -117,6 +117,10 @@ code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
Platforms are free to only support subsets of the mmap functionality, but Platforms are free to only support subsets of the mmap functionality, but
useful return codes should be provided. useful return codes should be provided.
Platforms which support write-combining maps of PCI resources must define
arch_can_pci_mmap_wc() which shall evaluate to non-zero at runtime when
write-combining is permitted.
Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms
wishing to support legacy functionality should define it and provide wishing to support legacy functionality should define it and provide
pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions. pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
...@@ -51,6 +51,8 @@ extern unsigned long ia64_max_iommu_merge_mask; ...@@ -51,6 +51,8 @@ extern unsigned long ia64_max_iommu_merge_mask;
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL) #define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
#define HAVE_PCI_MMAP #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, extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine); enum pci_mmap_state mmap_state, int write_combine);
#define HAVE_PCI_LEGACY #define HAVE_PCI_LEGACY
......
...@@ -81,8 +81,9 @@ struct vm_area_struct; ...@@ -81,8 +81,9 @@ struct vm_area_struct;
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine); enum pci_mmap_state mmap_state, int write_combine);
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() and it does WC */
#define HAVE_PCI_MMAP 1 #define HAVE_PCI_MMAP 1
#define arch_can_pci_mmap_wc() 1
extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
size_t count); size_t count);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pat.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -102,6 +103,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); ...@@ -102,6 +103,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
#define HAVE_PCI_MMAP #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, extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, enum pci_mmap_state mmap_state,
int write_combine); int write_combine);
......
...@@ -1211,9 +1211,9 @@ static int pci_create_resource_files(struct pci_dev *pdev) ...@@ -1211,9 +1211,9 @@ static int pci_create_resource_files(struct pci_dev *pdev)
retval = pci_create_attr(pdev, i, 0); retval = pci_create_attr(pdev, i, 0);
/* for prefetchable resources, create a WC mappable file */ /* for prefetchable resources, create a WC mappable file */
if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH) if (!retval && arch_can_pci_mmap_wc() &&
pdev->resource[i].flags & IORESOURCE_PREFETCH)
retval = pci_create_attr(pdev, i, 1); retval = pci_create_attr(pdev, i, 1);
if (retval) { if (retval) {
pci_remove_resource_files(pdev); pci_remove_resource_files(pdev);
return retval; return retval;
......
...@@ -210,14 +210,15 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, ...@@ -210,14 +210,15 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
break; break;
case PCIIOC_WRITE_COMBINE: case PCIIOC_WRITE_COMBINE:
if (arg) if (arch_can_pci_mmap_wc()) {
fpriv->write_combine = 1; if (arg)
else fpriv->write_combine = 1;
fpriv->write_combine = 0; else
break; fpriv->write_combine = 0;
break;
}
/* If arch decided it can't, fall through... */
#endif /* HAVE_PCI_MMAP */ #endif /* HAVE_PCI_MMAP */
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
......
...@@ -1626,6 +1626,10 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; } ...@@ -1626,6 +1626,10 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
#include <asm/pci.h> #include <asm/pci.h>
#ifndef arch_can_pci_mmap_wc
#define arch_can_pci_mmap_wc() 0
#endif
#ifndef pci_root_bus_fwnode #ifndef pci_root_bus_fwnode
#define pci_root_bus_fwnode(bus) NULL #define pci_root_bus_fwnode(bus) NULL
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册