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 <dwmw@amazon.co.uk> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
03a064b431
commit
ae749c7ab4
|
@ -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
|
||||
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
|
||||
wishing to support legacy functionality should define it and provide
|
||||
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;
|
|||
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
|
||||
|
||||
#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
|
||||
|
|
|
@ -81,8 +81,9 @@ struct vm_area_struct;
|
|||
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
|
||||
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() and it does WC */
|
||||
#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,
|
||||
size_t count);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pat.h>
|
||||
#include <asm/x86_init.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -1211,9 +1211,9 @@ static int pci_create_resource_files(struct pci_dev *pdev)
|
|||
|
||||
retval = pci_create_attr(pdev, i, 0);
|
||||
/* 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);
|
||||
|
||||
if (retval) {
|
||||
pci_remove_resource_files(pdev);
|
||||
return retval;
|
||||
|
|
|
@ -210,14 +210,15 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
|
|||
break;
|
||||
|
||||
case PCIIOC_WRITE_COMBINE:
|
||||
if (arg)
|
||||
fpriv->write_combine = 1;
|
||||
else
|
||||
fpriv->write_combine = 0;
|
||||
break;
|
||||
|
||||
if (arch_can_pci_mmap_wc()) {
|
||||
if (arg)
|
||||
fpriv->write_combine = 1;
|
||||
else
|
||||
fpriv->write_combine = 0;
|
||||
break;
|
||||
}
|
||||
/* If arch decided it can't, fall through... */
|
||||
#endif /* HAVE_PCI_MMAP */
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
|
|
@ -1626,6 +1626,10 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
|
|||
|
||||
#include <asm/pci.h>
|
||||
|
||||
#ifndef arch_can_pci_mmap_wc
|
||||
#define arch_can_pci_mmap_wc() 0
|
||||
#endif
|
||||
|
||||
#ifndef pci_root_bus_fwnode
|
||||
#define pci_root_bus_fwnode(bus) NULL
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue