2017-03-22 13:31:26

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 00/17] PCI resource mmap cleanup

This started out as a fairly trivial "add pci_mmap_page_range() for
ARM64" patch. But pci_mmap_page_range() is a vile interface, taking
"user visible" resource addresses converted with pci_resource_to_user()
on those platforms unlucky enough to use that... and even in the *sane*
sysfs-based mmap method, we convert through user addresses to call the
platform-specific method.

In most cases there's just no need for any of this crap. We can migrate
most architectures to a generic implementation without much thought,
and the few that aren't converted in this series can probably be added
fairly easily too but need a little more arch-specific attention.

Utterly untested for now; I'll do some testing while I deal with the
inevitable bikeshedding.

David Woodhouse (17):
pci: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms
pci: Fix another sanity check bug in /proc/pci mmap
pci: Only allow WC mmap on prefetchable resources
pci: Add arch_can_pci_mmap_wc() macro
pci: Move multiple declarations of pci_mmap_page_range() to <linux/pci.h>
pci: Add HAVE_PCI_MMAP_IO to architectures which can mmap() I/O space
pci: Use BAR index in sysfs attr->private instead of resource pointer
pci: Add BAR index argument to pci_mmap_page_range()
pci: Add pci_mmap_resource_range() and use it for ARM64
arm: Use generic pci_mmap_resource_range()
cris: Use generic pci_mmap_resource_range()
mips: Use generic pci_mmap_resource_range()
mn10300: Use generic pci_mmap_resource_range()
parisc: Use generic pci_mmap_resource_range()
sh: Use generic pci_mmap_resource_range()
unicore: Use generic pci_mmap_resource_range()
arm64: Do not expose PCI mmap through procfs

Documentation/filesystems/sysfs-pci.txt | 9 +++-
arch/arm/include/asm/pci.h | 3 +-
arch/arm/kernel/bios32.c | 19 -------
arch/arm64/include/asm/pci.h | 3 ++
arch/cris/arch-v32/drivers/pci/bios.c | 22 --------
arch/cris/include/asm/pci.h | 4 +-
arch/ia64/include/asm/pci.h | 4 +-
arch/ia64/pci/pci.c | 3 +-
arch/microblaze/include/asm/pci.h | 6 +--
arch/microblaze/pci/pci-common.c | 2 +-
arch/mips/include/asm/pci.h | 5 +-
arch/mips/pci/pci.c | 24 ---------
arch/mn10300/include/asm/pci.h | 4 +-
arch/mn10300/unit-asb2305/pci-asb2305.c | 23 ---------
arch/parisc/include/asm/pci.h | 4 +-
arch/parisc/kernel/pci.c | 28 ----------
arch/powerpc/include/asm/pci.h | 9 ++--
arch/powerpc/kernel/pci-common.c | 3 +-
arch/sh/drivers/pci/pci.c | 21 --------
arch/sh/include/asm/pci.h | 4 +-
arch/sparc/include/asm/pci_64.h | 5 +-
arch/sparc/kernel/pci.c | 6 +--
arch/unicore32/include/asm/pci.h | 3 +-
arch/unicore32/kernel/pci.c | 23 ---------
arch/x86/include/asm/pci.h | 6 +--
arch/x86/pci/i386.c | 3 +-
arch/xtensa/include/asm/pci.h | 11 ++--
arch/xtensa/kernel/pci.c | 5 +-
drivers/pci/Makefile | 2 +-
drivers/pci/mmap.c | 90 +++++++++++++++++++++++++++++++++
drivers/pci/pci-sysfs.c | 77 +++++++++++++---------------
drivers/pci/proc.c | 55 ++++++++++++++------
include/linux/pci.h | 19 +++++++
33 files changed, 233 insertions(+), 272 deletions(-)
create mode 100644 drivers/pci/mmap.c

--
2.9.3


2017-03-22 13:25:41

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 07/17] pci: Use BAR index in sysfs attr->private instead of resource pointer

From: David Woodhouse <[email protected]>

We store the pointer, and then on *every* use of it we loop over the
device's resources to find out the index. That's kind of silly.

Signed-off-by: David Woodhouse <[email protected]>
---
drivers/pci/pci-sysfs.c | 38 ++++++++++++++------------------------
1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 07cb2fc..8a2d77b 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1017,26 +1017,20 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma, int write_combine)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- struct resource *res = attr->private;
+ int bar = (unsigned long)attr->private;
enum pci_mmap_state mmap_type;
resource_size_t start, end;
- int i;
-
- for (i = 0; i < PCI_ROM_RESOURCE; i++)
- if (res == &pdev->resource[i])
- break;
- if (i >= PCI_ROM_RESOURCE)
- return -ENODEV;
+ struct resource *res = &pdev->resource[bar];

if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
return -EINVAL;

- if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
+ if (!pci_mmap_fits(pdev, bar, vma, PCI_MMAP_SYSFS)) {
WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
- pci_name(pdev), i,
- (u64)pci_resource_start(pdev, i),
- (u64)pci_resource_len(pdev, i));
+ pci_name(pdev), bar,
+ (u64)pci_resource_start(pdev, bar),
+ (u64)pci_resource_len(pdev, bar));
return -EINVAL;
}

@@ -1044,7 +1038,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
* from /proc/bus/pci/ which is a "user visible" value. If this is
* different from the resource itself, arch will do necessary fixup.
*/
- pci_resource_to_user(pdev, i, res, &start, &end);
+ pci_resource_to_user(pdev, bar, res, &start, &end);
vma->vm_pgoff += start >> PAGE_SHIFT;
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
@@ -1069,22 +1063,18 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
loff_t off, size_t count, bool write)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- struct resource *res = attr->private;
+ int bar = (unsigned long)attr->private;
+ struct resource *res;
unsigned long port = off;
- int i;

- for (i = 0; i < PCI_ROM_RESOURCE; i++)
- if (res == &pdev->resource[i])
- break;
- if (i >= PCI_ROM_RESOURCE)
- return -ENODEV;
+ res = &pdev->resource[bar];

- port += pci_resource_start(pdev, i);
+ port += pci_resource_start(pdev, bar);

- if (port > pci_resource_end(pdev, i))
+ if (port > pci_resource_end(pdev, bar))
return 0;

- if (port + count - 1 > pci_resource_end(pdev, i))
+ if (port + count - 1 > pci_resource_end(pdev, bar))
return -EINVAL;

switch (count) {
@@ -1187,7 +1177,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
res_attr->size = pci_resource_len(pdev, num);
- res_attr->private = &pdev->resource[num];
+ res_attr->private = (void *)(unsigned long)num;
retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
if (retval)
kfree(res_attr);
--
2.9.3

2017-03-22 13:25:51

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 03/17] pci: Only allow WC mmap on prefetchable resources

From: David Woodhouse <[email protected]>

The /proc/bus/pci mmap interface allows the user to specify whether they
want WC or not. Don't let them do so on non-prefetchable BARs.

Signed-off-by: David Woodhouse <[email protected]>
Cc: [email protected]
---
drivers/pci/proc.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 62a0c3e..dc8912e 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -231,7 +231,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
{
struct pci_dev *dev = PDE_DATA(file_inode(file));
struct pci_filp_private *fpriv = file->private_data;
- int i, ret, write_combine, res_bit;
+ int i, ret, write_combine = 0, res_bit;

if (!capable(CAP_SYS_RAWIO))
return -EPERM;
@@ -251,10 +251,13 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
if (i >= PCI_ROM_RESOURCE)
return -ENODEV;

- if (fpriv->mmap_state == pci_mmap_mem)
- write_combine = fpriv->write_combine;
- else
- write_combine = 0;
+ if (fpriv->mmap_state == pci_mmap_mem &&
+ fpriv->write_combine) {
+ if (dev->resource[i].flags & IORESOURCE_PREFETCH)
+ write_combine = 1;
+ else
+ return -EINVAL;
+ }
ret = pci_mmap_page_range(dev, vma,
fpriv->mmap_state, write_combine);
if (ret < 0)
--
2.9.3

2017-03-22 13:26:01

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 14/17] parisc: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/parisc/include/asm/pci.h | 1 +
arch/parisc/kernel/pci.c | 29 -----------------------------
2 files changed, 1 insertion(+), 29 deletions(-)

diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h
index bb9ea90..1de1a3f 100644
--- a/arch/parisc/include/asm/pci.h
+++ b/arch/parisc/include/asm/pci.h
@@ -200,5 +200,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
}

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

#endif /* __ASM_PARISC_PCI_H */
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 6538775..13ee356 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -227,35 +227,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return start;
}

-
-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 can be accessed via normal processor loads and stores on
- * this platform but for now we elect not to do this and portable
- * drivers should not do this anyway.
- */
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- if (write_combine)
- return -EINVAL;
-
- /*
- * Ignore write-combine; for now only return uncached mappings.
- */
- prot = pgprot_val(vma->vm_page_prot);
- prot |= _PAGE_NO_CACHE;
- vma->vm_page_prot = __pgprot(prot);
-
- return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
/*
* A driver is enabling the device. We make sure that all the appropriate
* bits are set to allow the device to operate as the driver is expecting.
--
2.9.3

2017-03-22 13:26:29

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 09/17] pci: Add pci_mmap_resource_range() and use it for ARM64

From: David Woodhouse <[email protected]>

Starting to leave behind the legacy of the pci_mmap_page_range()
interface which takes "user-visible" BAR addresses. This takes just the
resource and offset.

For now, both APIs coexist and depending on the platform, one is
implemented as a wrapper around the other.

Signed-off-by: David Woodhouse <[email protected]>
---
Documentation/filesystems/sysfs-pci.txt | 5 +-
arch/arm64/include/asm/pci.h | 3 ++
drivers/pci/Makefile | 2 +-
drivers/pci/mmap.c | 90 +++++++++++++++++++++++++++++++++
drivers/pci/pci-sysfs.c | 11 +---
include/linux/pci.h | 19 +++++--
6 files changed, 115 insertions(+), 15 deletions(-)
create mode 100644 drivers/pci/mmap.c

diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 25b7f1c..3e1016e 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -113,7 +113,10 @@ Supporting PCI access on new platforms
--------------------------------------

In order to support PCI resource mapping as described above, Linux platform
-code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
+code must define HAVE_PCI_MMAP and either provide a pci_mmap_page_range()
+function or (preferably) also define ARCH_GENERIC_PCI_MMAP_RESOURCE to use
+the generic implementation.
+
Platforms are free to only support subsets of the mmap functionality, but
useful return codes should be provided.

diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
index b9a7ba9..021da94 100644
--- a/arch/arm64/include/asm/pci.h
+++ b/arch/arm64/include/asm/pci.h
@@ -22,6 +22,9 @@
*/
#define PCI_DMA_BUS_IS_PHYS (0)

+#define HAVE_PCI_MMAP 1
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
+
extern int isa_dma_bridge_buggy;

#ifdef CONFIG_PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 8db5079..3d40e41 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@

obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
- irq.o vpd.o setup-bus.o vc.o
+ irq.o vpd.o setup-bus.o vc.o mmap.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o

diff --git a/drivers/pci/mmap.c b/drivers/pci/mmap.c
new file mode 100644
index 0000000..bf28dae
--- /dev/null
+++ b/drivers/pci/mmap.c
@@ -0,0 +1,90 @@
+/*
+ * mmap.c — generic PCI resource mmap helper
+ *
+ * Copyright © 2017 Amazon.com, Inc. or its affiliates.
+ *
+ * Author: David Woodhouse <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#ifdef HAVE_PCI_MMAP
+
+#ifdef ARCH_GENERIC_PCI_MMAP_RESOURCE
+/* Modern setup: generic pci_mmap_resource_range(), and implement the legacy
+ * pci_mmap_page_range() as a wrapper round it. */
+
+#ifdef HAVE_PCI_MMAP_IO
+/* We don't support this (yet), so prevent archietectures from trying it. */
+#error Generic pci_mmap_io not supported
+#endif
+
+static const struct vm_operations_struct pci_phys_vm_ops = {
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+ .access = generic_access_phys,
+#endif
+};
+
+int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
+ struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ unsigned long size;
+
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+ size = ((pci_resource_len(pdev, bar) - 1) >> PAGE_SHIFT) + 1;
+ if (vma->vm_pgoff + vma_pages(vma) > size)
+ return -EINVAL;
+
+ if (write_combine)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
+
+ vma->vm_pgoff += (pci_resource_start(pdev, bar) >> PAGE_SHIFT);
+ vma->vm_ops = &pci_phys_vm_ops;
+
+ return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+int pci_mmap_page_range(struct pci_dev *pdev, int bar,
+ struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ /* Adjust vm_pgoff to be the offset within the resource */
+ resource_size_t start, end;
+
+ pci_resource_to_user(pdev, bar, &pdev->resource[bar], &start, &end);
+ vma->vm_pgoff -= start >> PAGE_SHIFT;
+ return pci_mmap_resource_range(pdev, bar, vma, mmap_state, write_combine);
+}
+
+#else
+/* Legacy setup: Impement pci_mmap_resource_range() as a wrapper around
+ the architecture's pci_mmap_page_range(), converting to "user visible"
+ addresses as necessary. */
+int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
+ struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ resource_size_t start, end;
+ /* pci_mmap_page_range() expects the same kind of entry as coming
+ * from /proc/bus/pci/ which is a "user visible" value. If this is
+ * different from the resource itself, arch will do necessary fixup.
+ */
+ pci_resource_to_user(pdev, bar, &pdev->resource[bar], &start, &end);
+ vma->vm_pgoff += start >> PAGE_SHIFT;
+ return pci_mmap_page_range(pdev, bar, vma, mmap_state, write_combine);
+}
+#endif
+#endif /* HAVE_PCI_MMAP */
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 063310a..9663d38 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1019,7 +1019,6 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
int bar = (unsigned long)attr->private;
enum pci_mmap_state mmap_type;
- resource_size_t start, end;
struct resource *res = &pdev->resource[bar];

if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
@@ -1033,15 +1032,9 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
(u64)pci_resource_len(pdev, bar));
return -EINVAL;
}
-
- /* pci_mmap_page_range() expects the same kind of entry as coming
- * from /proc/bus/pci/ which is a "user visible" value. If this is
- * different from the resource itself, arch will do necessary fixup.
- */
- pci_resource_to_user(pdev, bar, res, &start, &end);
- vma->vm_pgoff += start >> PAGE_SHIFT;
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
- return pci_mmap_page_range(pdev, bar, vma, mmap_type, write_combine);
+
+ return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
}

static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ebc86c1..4dfec16 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1626,10 +1626,21 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }

#include <asm/pci.h>

-/* 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. */
+/* These two functions provide almost identical functionality. Depennding
+ * on the architecture, one will be implemented as a wrapper aroudn the
+ * other (in drivers/pci/mmap.c).
+ *
+ * pci_mmap_resource_range() maps a specific BAR, and vm->vm_pgoff
+ * is expected to be an offset within that region.
+ *
+ * pci_mmap_page_range() is the legacy architecture-specific interface,
+ * which accepts a "user visible" resource address converted by
+ * pci_resource_to_user(), as used in the legacy mmap() interface in
+ * /proc/bus/pci/.
+ */
+int pci_mmap_resource_range(struct pci_dev *dev, int bar,
+ struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
int pci_mmap_page_range(struct pci_dev *pdev, int bar,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
--
2.9.3

2017-03-22 13:26:44

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 01/17] pci: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms

From: David Woodhouse <[email protected]>

In the PCI_MMAP_PROCFS case when the address being passed by the user
is a 'user visible' resource address based on the bus window, and not
the actual contents of the resource, that's what we need to be checking
it against.

Signed-off-by: David Woodhouse <[email protected]>
Cc: [email protected]
---
drivers/pci/pci-sysfs.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 25d010d..7ac258f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -985,15 +985,19 @@ void pci_remove_legacy_files(struct pci_bus *b)
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
enum pci_mmap_api mmap_api)
{
- unsigned long nr, start, size, pci_start;
+ unsigned long nr, start, size;
+ resource_size_t pci_start = 0, pci_end;

if (pci_resource_len(pdev, resno) == 0)
return 0;
nr = vma_pages(vma);
start = vma->vm_pgoff;
size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
- pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
- pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+ if (mmap_api == PCI_MMAP_PROCFS) {
+ pci_resource_to_user(pdev, resno, &pdev->resource[resno],
+ &pci_start, &pci_end);
+ pci_start >>= PAGE_SHIFT;
+ }
if (start >= pci_start && start < pci_start + size &&
start + nr <= pci_start + size)
return 1;
--
2.9.3

2017-03-22 13:26:53

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 02/17] pci: Fix another sanity check bug in /proc/pci mmap

From: David Woodhouse <[email protected]>

Don't match MMIO maps with I/O BARs and vice versa.

Signed-off-by: David Woodhouse <[email protected]>
Cc: [email protected]
---
drivers/pci/proc.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index f82710a..62a0c3e 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -231,14 +231,20 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
{
struct pci_dev *dev = PDE_DATA(file_inode(file));
struct pci_filp_private *fpriv = file->private_data;
- int i, ret, write_combine;
+ int i, ret, write_combine, res_bit;

if (!capable(CAP_SYS_RAWIO))
return -EPERM;

+ if (fpriv->mmap_state == pci_mmap_io)
+ res_bit = IORESOURCE_IO;
+ else
+ res_bit = IORESOURCE_MEM;
+
/* Make sure the caller is mapping a real resource for this device */
for (i = 0; i < PCI_ROM_RESOURCE; i++) {
- if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS))
+ if (dev->resource[i].flags & res_bit &&
+ pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS))
break;
}

--
2.9.3

2017-03-22 13:27:08

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 13/17] mn10300: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

This was setting vma->vm_flags |= VM_LOCKED. Not sure why...

Signed-off-by: David Woodhouse <[email protected]>
---
arch/mn10300/include/asm/pci.h | 1 +
arch/mn10300/unit-asb2305/pci-asb2305.c | 24 ------------------------
2 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h
index 082b6de..d276549 100644
--- a/arch/mn10300/include/asm/pci.h
+++ b/arch/mn10300/include/asm/pci.h
@@ -74,6 +74,7 @@ static inline int pci_controller_num(struct pci_dev *dev)
}

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

#endif /* __KERNEL__ */

diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index 4abbbd5..e0f4617 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -210,27 +210,3 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
}
-
-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;
-
- /* Leave vm_pgoff as-is, the PCI space address is the physical
- * address on this platform.
- */
- vma->vm_flags |= VM_LOCKED;
-
- prot = pgprot_val(vma->vm_page_prot);
- prot &= ~_PAGE_CACHE;
- vma->vm_page_prot = __pgprot(prot);
-
- /* Write-combine setting is ignored */
- if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
--
2.9.3

2017-03-22 13:27:20

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 11/17] cris: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/cris/arch-v32/drivers/pci/bios.c | 23 -----------------------
arch/cris/include/asm/pci.h | 1 +
2 files changed, 1 insertion(+), 23 deletions(-)

diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index a589686d..394c2a73 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -14,29 +14,6 @@ void pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}

-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;
-
- /* Leave vm_pgoff as-is, the PCI space address is the physical
- * address on this platform.
- */
- prot = pgprot_val(vma->vm_page_prot);
- vma->vm_page_prot = __pgprot(prot);
-
- /* Write-combine setting is ignored, it is changed via the mtrr
- * interfaces on this platform.
- */
- if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
-
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index 65198cb..6e50533 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -42,6 +42,7 @@ struct pci_dev;
#define PCI_DMA_BUS_IS_PHYS (1)

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

#endif /* __KERNEL__ */

--
2.9.3

2017-03-22 13:27:30

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 08/17] pci: Add BAR index argument to pci_mmap_page_range()

From: David Woodhouse <[email protected]>

In all cases we know which BAR it is. Passing it in means that arch code
(or generic code; watch this space) won't have to go looking for it again.

Signed-off-by: David Woodhouse <[email protected]>
---
arch/arm/kernel/bios32.c | 3 ++-
arch/cris/arch-v32/drivers/pci/bios.c | 3 ++-
arch/ia64/pci/pci.c | 3 ++-
arch/microblaze/pci/pci-common.c | 2 +-
arch/mips/pci/pci.c | 3 ++-
arch/mn10300/unit-asb2305/pci-asb2305.c | 3 ++-
arch/parisc/kernel/pci.c | 3 ++-
arch/powerpc/kernel/pci-common.c | 3 ++-
arch/sh/drivers/pci/pci.c | 3 ++-
arch/sparc/kernel/pci.c | 6 +++---
arch/unicore32/kernel/pci.c | 3 ++-
arch/x86/pci/i386.c | 3 ++-
arch/xtensa/kernel/pci.c | 3 ++-
drivers/pci/pci-sysfs.c | 2 +-
drivers/pci/proc.c | 2 +-
include/linux/pci.h | 3 ++-
16 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 2f0e077..a4fc3f4 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -597,7 +597,8 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return start;
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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)
{
if (mmap_state == pci_mmap_io)
diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index 212266a..a589686d 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -14,7 +14,8 @@ void pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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;
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 8f6ac2f..053c688 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -419,7 +419,8 @@ pcibios_align_resource (void *data, const struct resource *res,
}

int
-pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
+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 size = vma->vm_end - vma->vm_start;
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 13bc932..404fb38 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -278,7 +278,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
*
* Returns a negative error code on failure, zero on success.
*/
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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)
{
resource_size_t offset =
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index f6325fa..f189502 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -58,7 +58,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
*end = rsrc->start + size;
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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;
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index b7ab837..4abbbd5 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -211,7 +211,8 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1);
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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;
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 0903c6a..6538775 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -228,7 +228,8 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
}


-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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;
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index ffda24a..6dda4a2 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -513,7 +513,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
*
* Returns a negative error code on failure, zero on success.
*/
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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)
{
resource_size_t offset =
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 84563e3..c8b36b7 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -269,7 +269,8 @@ void __ref pcibios_report_status(unsigned int status_mask, int warn)
}
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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)
{
/*
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 015e55a..7eceaa1 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -862,9 +862,9 @@ static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vm
*
* Returns a negative error code on failure, zero on success.
*/
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state,
- int write_combine)
+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)
{
int ret;

diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 62137d1..1b43885 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -357,7 +357,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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 phys;
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 0a9f2ca..8ca5e5d 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -411,7 +411,8 @@ static const struct vm_operations_struct pci_mmap_ops = {
.access = generic_access_phys,
};

-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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;
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index c5944d3..6872646 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -362,7 +362,8 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
*
* Returns a negative error code on failure, zero on success.
*/
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+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)
{
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8a2d77b..063310a 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1041,7 +1041,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
pci_resource_to_user(pdev, bar, res, &start, &end);
vma->vm_pgoff += start >> PAGE_SHIFT;
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
- return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
+ return pci_mmap_page_range(pdev, bar, vma, mmap_type, write_combine);
}

static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index f387231..2d9cfa4 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -267,7 +267,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
else
return -EINVAL;
}
- ret = pci_mmap_page_range(dev, vma,
+ ret = pci_mmap_page_range(dev, i, vma,
fpriv->mmap_state, write_combine);
if (ret < 0)
return ret;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9a94cb8..ebc86c1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1630,7 +1630,8 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
* 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,
+int pci_mmap_page_range(struct pci_dev *pdev, int bar,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);

#ifndef pci_root_bus_fwnode
--
2.9.3

2017-03-22 13:26:18

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 06/17] pci: Add HAVE_PCI_MMAP_IO to architectures which can mmap() I/O space

From: David Woodhouse <[email protected]>

This is relatively esoteric, and knowing that we don't have it makes
life easier in some cases rather than just an eventual -EINVAL from
pci_mmap_page_range().

Signed-off-by: David Woodhouse <[email protected]>
---
arch/microblaze/include/asm/pci.h | 3 ++-
arch/powerpc/include/asm/pci.h | 1 +
arch/sparc/include/asm/pci_64.h | 1 +
arch/xtensa/include/asm/pci.h | 1 +
drivers/pci/pci-sysfs.c | 14 +++++++++-----
drivers/pci/proc.c | 10 ++++++++--
6 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index ab381d2..41f5986 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -48,7 +48,8 @@ extern int pci_proc_domain(struct pci_bus *bus);
struct vm_area_struct;

/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
-#define HAVE_PCI_MMAP 1
+#define HAVE_PCI_MMAP 1
+#define HAVE_PCI_MMAP_IO 1

extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
size_t count);
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 55887d1..849a7dd 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -80,6 +80,7 @@ struct vm_area_struct;

/* 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_IO 1
#define arch_can_pci_mmap_wc() 1

extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index 516fda7..4fe2f05 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -42,6 +42,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
/* Platform support for /proc/bus/pci/X/Y mmap()s. */

#define HAVE_PCI_MMAP
+#define HAVE_PCI_MMAP_IO
#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
#define get_pci_unmapped_area get_fb_unmapped_area

diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index e594eee..e4c1b43e 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -48,6 +48,7 @@ struct pci_dev;

/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
#define HAVE_PCI_MMAP 1
+#define HAVE_PCI_MMAP_IO 1

/* This was wrapped in #if 0 since the first merge of xtensa support...
#define arch_can_pci_mmap_wc() 1
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index cf2c7d8..07cb2fc 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1174,11 +1174,15 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
} else {
pdev->res_attr[num] = res_attr;
sprintf(res_attr_name, "resource%d", num);
- res_attr->mmap = pci_mmap_resource_uc;
- }
- if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
- res_attr->read = pci_read_resource_io;
- res_attr->write = pci_write_resource_io;
+ if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
+ res_attr->read = pci_read_resource_io;
+ res_attr->write = pci_write_resource_io;
+#ifdef HAVE_PCI_MMAP_IO
+ res_attr->mmap = pci_mmap_resource_uc;
+#endif
+ } else {
+ res_attr->mmap = pci_mmap_resource_uc;
+ }
}
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index c49be71..f387231 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -200,11 +200,12 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
ret = pci_domain_nr(dev->bus);
break;

-#ifdef HAVE_PCI_MMAP
+#ifdef HAVE_PCI_MMAP_IO
case PCIIOC_MMAP_IS_IO:
fpriv->mmap_state = pci_mmap_io;
break;
-
+#endif
+#ifdef HAVE_PCI_MMAP
case PCIIOC_MMAP_IS_MEM:
fpriv->mmap_state = pci_mmap_mem;
break;
@@ -239,6 +240,11 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
if (!capable(CAP_SYS_RAWIO))
return -EPERM;

+#ifndef HAVE_PCI_MMAP_IO
+ if (fpriv->mmap_state == pci_mmap_io)
+ return -EINVAL;
+#endif
+
if (fpriv->mmap_state == pci_mmap_io)
res_bit = IORESOURCE_IO;
else
--
2.9.3

2017-03-22 13:29:31

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 12/17] mips: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/mips/include/asm/pci.h | 2 +-
arch/mips/pci/pci.c | 25 -------------------------
2 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 3141e2a..1000c1b 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -110,7 +110,7 @@ extern unsigned long PCIBIOS_MIN_MEM;
extern void pcibios_set_master(struct pci_dev *dev);

#define HAVE_PCI_MMAP
-
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
#define HAVE_ARCH_PCI_RESOURCE_TO_USER

/*
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index f189502..bd67ac7 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -57,28 +57,3 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
*start = fixup_bigphys_addr(rsrc->start, size);
*end = rsrc->start + size;
}
-
-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 can be accessed via normal processor loads and stores on
- * this platform but for now we elect not to do this and portable
- * drivers should not do this anyway.
- */
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- /*
- * Ignore write-combine; for now only return uncached mappings.
- */
- prot = pgprot_val(vma->vm_page_prot);
- prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
- vma->vm_page_prot = __pgprot(prot);
-
- return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
--
2.9.3

2017-03-22 13:29:39

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 16/17] unicore: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/unicore32/include/asm/pci.h | 1 +
arch/unicore32/kernel/pci.c | 24 ------------------------
2 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h
index a5129086..ac5acdf 100644
--- a/arch/unicore32/include/asm/pci.h
+++ b/arch/unicore32/include/asm/pci.h
@@ -17,6 +17,7 @@
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

#endif /* __KERNEL__ */
#endif
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 1b43885..1053bca 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -356,27 +356,3 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
}
return 0;
}
-
-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 phys;
-
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- phys = vma->vm_pgoff;
-
- /*
- * Mark this as IO
- */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- if (remap_pfn_range(vma, vma->vm_start, phys,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
--
2.9.3

2017-03-22 13:29:50

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 05/17] pci: Move multiple declarations of pci_mmap_page_range() to <linux/pci.h>

From: David Woodhouse <[email protected]>

We can declare it <linux/pci.h> even on platforms where it isn't going
to be defined. There's no need to have it littered through the various
<asm/pci.h> files.

Signed-off-by: David Woodhouse <[email protected]>
---
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(-)

diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 057d381..51118a0 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 b1b289d..65198cb 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 6283758..fc60b3d 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 2a120bb..ab381d2 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 30d1129..3141e2a 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 51159ff..082b6de 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 defebd9..bb9ea90 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 b5b68c6..55887d1 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 644314f..46abbc9 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 2303635..516fda7 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 37e55d0..a5129086 100644
--- a/arch/unicore32/include/asm/pci.h
+++ b/arch/unicore32/include/asm/pci.h
@@ -17,8 +17,6 @@
#include <mach/hardware.h> /* 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 f6e22c2..734cc94 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 f106879..e594eee 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 eb3da1a..9a94cb8 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 <asm/pci.h>

+/* 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 pci_root_bus_fwnode
#define pci_root_bus_fwnode(bus) NULL
#endif
--
2.9.3

2017-03-22 13:29:59

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 15/17] sh: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/sh/drivers/pci/pci.c | 22 ----------------------
arch/sh/include/asm/pci.h | 1 +
2 files changed, 1 insertion(+), 22 deletions(-)

diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index c8b36b7..c99ee28 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -269,28 +269,6 @@ void __ref pcibios_report_status(unsigned int status_mask, int warn)
}
}

-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)
-{
- /*
- * I/O space can be accessed via normal processor loads and stores on
- * this platform but for now we elect not to do this and portable
- * drivers should not do this anyway.
- */
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- /*
- * Ignore write-combine; for now only return uncached mappings.
- */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-}
-
#ifndef CONFIG_GENERIC_IOMAP

void __iomem *__pci_ioport_map(struct pci_dev *dev,
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 46abbc9..17fa69b 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -66,6 +66,7 @@ extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
struct pci_dev;

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

extern void pcibios_set_master(struct pci_dev *dev);

--
2.9.3

2017-03-22 13:31:17

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
drivers/pci/proc.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 2d9cfa4..a940f4b 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -17,6 +17,11 @@

static int proc_initialized; /* = 0 */

+#ifdef __aarch64__
+/* ARM64 wants to be special and not expose this through /proc like everyone else */
+#undef HAVE_PCI_MMAP
+#endif
+
static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
{
struct pci_dev *dev = PDE_DATA(file_inode(file));
--
2.9.3

2017-03-22 13:31:40

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 10/17] arm: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
arch/arm/include/asm/pci.h | 1 +
arch/arm/kernel/bios32.c | 20 --------------------
2 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 51118a0..396c92b 100644
--- a/arch/arm/include/asm/pci.h
+++ b/arch/arm/include/asm/pci.h
@@ -29,6 +29,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
#define PCI_DMA_BUS_IS_PHYS (1)

#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE

static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
{
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a4fc3f4..b259956 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -597,26 +597,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return start;
}

-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)
-{
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- /*
- * Mark this as IO
- */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
-
void __init pci_map_io_early(unsigned long pfn)
{
struct map_desc pci_io_desc = {
--
2.9.3

2017-03-22 13:31:51

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 04/17] pci: Add arch_can_pci_mmap_wc() macro

From: David Woodhouse <[email protected]>

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 <[email protected]>
---
Documentation/filesystems/sysfs-pci.txt | 4 ++++
arch/ia64/include/asm/pci.h | 2 ++
arch/powerpc/include/asm/pci.h | 5 +++--
arch/x86/include/asm/pci.h | 2 ++
arch/xtensa/include/asm/pci.h | 6 +++++-
arch/xtensa/kernel/pci.c | 2 +-
drivers/pci/pci-sysfs.c | 6 ++++--
drivers/pci/proc.c | 17 ++++++++++-------
8 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 6ea1ced..25b7f1c 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -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.
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index c0835b0..6283758 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -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
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 93eded8..b5b68c6 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -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);
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 1411dbe..f6e22c2 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -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);
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index 5d6bd93..f106879 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -51,7 +51,11 @@ 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
+#define HAVE_PCI_MMAP 1
+
+/* This was wrapped in #if 0 since the first merge of xtensa support...
+#define arch_can_pci_mmap_wc() 1
+*/

#endif /* __KERNEL__ */

diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index b848cc3..c5944d3 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -345,7 +345,7 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,

/* Set to write-through */
prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT;
-#if 0
+#ifdef arch_can_pci_mmap_wc
if (!write_combine)
prot |= _PAGE_WRITETHRU;
#endif
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7ac258f..cf2c7d8 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1210,10 +1210,12 @@ static int pci_create_resource_files(struct pci_dev *pdev)
continue;

retval = pci_create_attr(pdev, i, 0);
+#ifdef arch_can_pci_mmap_wc
/* 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);
-
+#endif
if (retval) {
pci_remove_resource_files(pdev);
return retval;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index dc8912e..c49be71 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -209,15 +209,18 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
fpriv->mmap_state = pci_mmap_mem;
break;

+#ifdef arch_can_pci_mmap_wc
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 /* arch_can_pci_mmap_wc */
#endif /* HAVE_PCI_MMAP */
-
default:
ret = -EINVAL;
break;
--
2.9.3

2017-03-22 13:34:11

by Jesper Nilsson

[permalink] [raw]
Subject: Re: [PATCH 11/17] cris: Use generic pci_mmap_resource_range()

On Wed, Mar 22, 2017 at 01:25:25PM +0000, David Woodhouse wrote:
> From: David Woodhouse <[email protected]>

Acked-by: Jesper Nilsson <[email protected]>

> Signed-off-by: David Woodhouse <[email protected]>
> ---
> arch/cris/arch-v32/drivers/pci/bios.c | 23 -----------------------
> arch/cris/include/asm/pci.h | 1 +
> 2 files changed, 1 insertion(+), 23 deletions(-)
>
> diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
> index a589686d..394c2a73 100644
> --- a/arch/cris/arch-v32/drivers/pci/bios.c
> +++ b/arch/cris/arch-v32/drivers/pci/bios.c
> @@ -14,29 +14,6 @@ void pcibios_set_master(struct pci_dev *dev)
> pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
> }
>
> -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;
> -
> - /* Leave vm_pgoff as-is, the PCI space address is the physical
> - * address on this platform.
> - */
> - prot = pgprot_val(vma->vm_page_prot);
> - vma->vm_page_prot = __pgprot(prot);
> -
> - /* Write-combine setting is ignored, it is changed via the mtrr
> - * interfaces on this platform.
> - */
> - if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
> - vma->vm_end - vma->vm_start,
> - vma->vm_page_prot))
> - return -EAGAIN;
> -
> - return 0;
> -}
> -
> resource_size_t
> pcibios_align_resource(void *data, const struct resource *res,
> resource_size_t size, resource_size_t align)
> diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
> index 65198cb..6e50533 100644
> --- a/arch/cris/include/asm/pci.h
> +++ b/arch/cris/include/asm/pci.h
> @@ -42,6 +42,7 @@ struct pci_dev;
> #define PCI_DMA_BUS_IS_PHYS (1)
>
> #define HAVE_PCI_MMAP
> +#define ARCH_GENERIC_PCI_MMAP_RESOURCE
>
> #endif /* __KERNEL__ */
>
> --
> 2.9.3

/^JN - Jesper Nilsson
--
Jesper Nilsson -- [email protected]

2017-03-22 13:54:55

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On 3/22/2017 9:25 AM, David Woodhouse wrote:
>
> +#ifdef __aarch64__
> +/* ARM64 wants to be special and not expose this through /proc like everyone else */
> +#undef HAVE_PCI_MMAP
> +#endif
> +

Where is this ARM64 special requirement coming from?

--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

2017-03-22 14:04:45

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Wed, 2017-03-22 at 09:54 -0400, Sinan Kaya wrote:
> On 3/22/2017 9:25 AM, David Woodhouse wrote:
> >
> >  
> > +#ifdef __aarch64__
> > +/* ARM64 wants to be special and not expose this through /proc
> > like everyone else */
> > +#undef HAVE_PCI_MMAP
> > +#endif
> > +
> Where is this ARM64 special requirement coming from?

The idea is that as a new platform, ARM64 shouldn't need to implement
legacy userspace interfaces.

http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/422571.html


Attachments:
smime.p7s (4.82 kB)

2017-03-22 14:15:35

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On 3/22/2017 10:04 AM, David Woodhouse wrote:
> On Wed, 2017-03-22 at 09:54 -0400, Sinan Kaya wrote:
>> On 3/22/2017 9:25 AM, David Woodhouse wrote:
>>>
>>>
>>> +#ifdef __aarch64__
>>> +/* ARM64 wants to be special and not expose this through /proc
>>> like everyone else */
>>> +#undef HAVE_PCI_MMAP
>>> +#endif
>>> +
>> Where is this ARM64 special requirement coming from?
>
> The idea is that as a new platform, ARM64 shouldn't need to implement
> legacy userspace interfaces.
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/422571.html
>

Aren't we breaking an ABI for userspace? I know DPDK relies on this feature.

--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

2017-03-22 14:18:31

by Will Deacon

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Wed, Mar 22, 2017 at 10:15:04AM -0400, Sinan Kaya wrote:
> On 3/22/2017 10:04 AM, David Woodhouse wrote:
> > On Wed, 2017-03-22 at 09:54 -0400, Sinan Kaya wrote:
> >> On 3/22/2017 9:25 AM, David Woodhouse wrote:
> >>>
> >>>
> >>> +#ifdef __aarch64__
> >>> +/* ARM64 wants to be special and not expose this through /proc
> >>> like everyone else */
> >>> +#undef HAVE_PCI_MMAP
> >>> +#endif
> >>> +
> >> Where is this ARM64 special requirement coming from?
> >
> > The idea is that as a new platform, ARM64 shouldn't need to implement
> > legacy userspace interfaces.
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/422571.html
> >
>
> Aren't we breaking an ABI for userspace? I know DPDK relies on this feature.

It relies on the /proc interface? That's the first I've ever heard of that
-- everybody so far has only been interested in the sysfs stuff.

Nothing's more broken than before, because we've never supported the /proc
interface, but if existing arm64 code out there is failing because of that
then I'm of course open to supporting it. I'm just surprised that nobody
else has come up with that before, since DPDK is in common use.

Can you point me at the specific code, please?

Will

2017-03-22 15:41:16

by Sinan Kaya

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On 3/22/2017 10:18 AM, Will Deacon wrote:
> On Wed, Mar 22, 2017 at 10:15:04AM -0400, Sinan Kaya wrote:
>> On 3/22/2017 10:04 AM, David Woodhouse wrote:
>>> On Wed, 2017-03-22 at 09:54 -0400, Sinan Kaya wrote:
>>>> On 3/22/2017 9:25 AM, David Woodhouse wrote:
>>>>>
>>>>>
>>>>> +#ifdef __aarch64__
>>>>> +/* ARM64 wants to be special and not expose this through /proc
>>>>> like everyone else */
>>>>> +#undef HAVE_PCI_MMAP
>>>>> +#endif
>>>>> +
>>>> Where is this ARM64 special requirement coming from?
>>>
>>> The idea is that as a new platform, ARM64 shouldn't need to implement
>>> legacy userspace interfaces.
>>>
>>> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/422571.html
>>>
>>
>> Aren't we breaking an ABI for userspace? I know DPDK relies on this feature.
>
> It relies on the /proc interface? That's the first I've ever heard of that
> -- everybody so far has only been interested in the sysfs stuff.
>
> Nothing's more broken than before, because we've never supported the /proc
> interface, but if existing arm64 code out there is failing because of that
> then I'm of course open to supporting it. I'm just surprised that nobody
> else has come up with that before, since DPDK is in common use.
>
> Can you point me at the specific code, please?

I'm correcting myself. I had to go back my memory from last year.

DPDK requires HAVE_PCI_MMAP to be set. We have been carrying
some old maillist patch around for DPDK customers internally.

When HAVE_PCI_MMAP is set, resource files are created in sysfs and procfs.
DPDK is using the files in sysfs directory not procfs directory.

Having HAVE_PCI_MMAP defined is the DPDK requirement.

>
> Will
>


--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

2017-03-23 14:29:39

by David Woodhouse

[permalink] [raw]
Subject: [PATCH 18/17] x86: Use generic pci_mmap_resource_range()

From: David Woodhouse <[email protected]>

Signed-off-by: David Woodhouse <[email protected]>
---
Actually it turns out this is fairly trivial for x86 too; it just looked
more interesting at first glance. But pgprot_writecombine() and
pgprot_device() will both do the right thing here, and allowing WC
conditionally based on pat_enabled() is already working so we'll never
get asked to do that when we don't want to.

arch/x86/include/asm/pci.h | 1 +
arch/x86/pci/i386.c | 48 ----------------------------------------------
2 files changed, 1 insertion(+), 48 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 734cc94..f513cc2 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 8ca5e5d..68499cf 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;
-}
--
2.9.3

2017-03-24 11:40:54

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 00/17] PCI resource mmap cleanup

On Wed, 2017-03-22 at 13:25 +0000, David Woodhouse wrote:
> This started out as a fairly trivial "add pci_mmap_page_range() for 
> ARM64" patch. But pci_mmap_page_range() is a vile interface, taking 
> "user visible" resource addresses converted with pci_resource_to_user() 
> on those platforms unlucky enough to use that... and even in the *sane* 
> sysfs-based mmap method, we convert through user addresses to call the
> platform-specific method.
>
> In most cases there's just no need for any of this crap. We can migrate
> most architectures to a generic implementation without much thought,
> and the few that aren't converted in this series can probably be added
> fairly easily too but need a little more arch-specific attention.
>
> Utterly untested for now; I'll do some testing while I deal with the
> inevitable bikeshedding.

I added PowerPC too. Rather than posting it here as patches 18/17 and
19/17 I'll just point at 
http://git.infradead.org/users/dwmw2/random-2.6.git/shortlog/refs/heads/pcimmap

To support pci_mmap_io I added a pci_iobar_pfn() function which the
arch must provide, to adjust vma->vm_pgoff to the physical address of
the I/O window of the appropriate PCI host controller. It looks
something like this:

int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
{
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
resource_size_t ioaddr = pci_resource_start(pdev, bar);

if (!hose)
return -EINVAL;

/* Convert to an offset within this PCI controller */
ioaddr -= (unsigned long)hose->io_base_virt - _IO_BASE;

vma->vm_pgoff += (ioaddr + hose->io_base_phys) >> PAGE_SHIFT;
return 0;
}

It looks like SPARC, xtensa and Microblaze can all do the same thing,
as they were all basically the same code in the first place.
That leaves IA64 as the last holdout, as the selection of vm_page_prot
there is rather complicated:

prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
    vma->vm_page_prot);

/*
* If the user requested WC, the kernel uses UC or WC for this region,
* and the chipset supports WC, we can use WC. Otherwise, we have to
* use the same attribute the kernel uses.
*/
if (write_combine &&
    ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
     (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
    efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
else
vma->vm_page_prot = prot;


But I suspect it's *overcomplicated*, as the kernel should only ever be
mapping PCI memory BARs as UC or WC in the first place, so the middle
two checks in the if (write_combine…) condition are redundant.

And if the efi_range_is_wc() check isn't gratuitous, perhaps that
should be in the generic code whenever CONFIG_EFI is set?

Tony?

> David Woodhouse (17):
>   pci: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms
>   pci: Fix another sanity check bug in /proc/pci mmap
>   pci: Only allow WC mmap on prefetchable resources
>   pci: Add arch_can_pci_mmap_wc() macro
>   pci: Move multiple declarations of pci_mmap_page_range() to
>   pci: Add HAVE_PCI_MMAP_IO to architectures which can mmap() I/O space
>   pci: Use BAR index in sysfs attr->private instead of resource pointer
>   pci: Add BAR index argument to pci_mmap_page_range()
>   pci: Add pci_mmap_resource_range() and use it for ARM64
>   arm: Use generic pci_mmap_resource_range()
>   cris: Use generic pci_mmap_resource_range()
>   mips: Use generic pci_mmap_resource_range()
>   mn10300: Use generic pci_mmap_resource_range()
>   parisc: Use generic pci_mmap_resource_range()
>   sh: Use generic pci_mmap_resource_range()
>   unicore: Use generic pci_mmap_resource_range()
>   arm64: Do not expose PCI mmap through procfs
>
>  Documentation/filesystems/sysfs-pci.txt |  9 +++-
>  arch/arm/include/asm/pci.h              |  3 +-
>  arch/arm/kernel/bios32.c                | 19 -------
>  arch/arm64/include/asm/pci.h            |  3 ++
>  arch/cris/arch-v32/drivers/pci/bios.c   | 22 --------
>  arch/cris/include/asm/pci.h             |  4 +-
>  arch/ia64/include/asm/pci.h             |  4 +-
>  arch/ia64/pci/pci.c                     |  3 +-
>  arch/microblaze/include/asm/pci.h       |  6 +--
>  arch/microblaze/pci/pci-common.c        |  2 +-
>  arch/mips/include/asm/pci.h             |  5 +-
>  arch/mips/pci/pci.c                     | 24 ---------
>  arch/mn10300/include/asm/pci.h          |  4 +-
>  arch/mn10300/unit-asb2305/pci-asb2305.c | 23 ---------
>  arch/parisc/include/asm/pci.h           |  4 +-
>  arch/parisc/kernel/pci.c                | 28 ----------
>  arch/powerpc/include/asm/pci.h          |  9 ++--
>  arch/powerpc/kernel/pci-common.c        |  3 +-
>  arch/sh/drivers/pci/pci.c               | 21 --------
>  arch/sh/include/asm/pci.h               |  4 +-
>  arch/sparc/include/asm/pci_64.h         |  5 +-
>  arch/sparc/kernel/pci.c                 |  6 +--
>  arch/unicore32/include/asm/pci.h        |  3 +-
>  arch/unicore32/kernel/pci.c             | 23 ---------
>  arch/x86/include/asm/pci.h              |  6 +--
>  arch/x86/pci/i386.c                     |  3 +-
>  arch/xtensa/include/asm/pci.h           | 11 ++--
>  arch/xtensa/kernel/pci.c                |  5 +-
>  drivers/pci/Makefile                    |  2 +-
>  drivers/pci/mmap.c                      | 90 +++++++++++++++++++++++++++++++++
>  drivers/pci/pci-sysfs.c                 | 77 +++++++++++++---------------
>  drivers/pci/proc.c                      | 55 ++++++++++++++------
>  include/linux/pci.h                     | 19 +++++++
>  33 files changed, 233 insertions(+), 272 deletions(-)
>  create mode 100644 drivers/pci/mmap.c
>


Attachments:
smime.p7s (4.82 kB)

2017-03-24 16:06:09

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 03/17] pci: Only allow WC mmap on prefetchable resources

On Wed, Mar 22, 2017 at 2:25 PM, David Woodhouse <[email protected]> wrote:
> From: David Woodhouse <[email protected]>
>
> The /proc/bus/pci mmap interface allows the user to specify whether they
> want WC or not. Don't let them do so on non-prefetchable BARs.
>
> Signed-off-by: David Woodhouse <[email protected]>
> Cc: [email protected]

Can you explain this a little more? I understand that we usually want to use
WC mappings on prefetchable BARs, and uncached non-WC on
non-prefetchable, but why do we have to force an error here?

Couldn't there be some hardware that allows write-combining access
but no prefetches?

Arnd

2017-03-24 16:16:25

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Wed, Mar 22, 2017 at 2:25 PM, David Woodhouse <[email protected]> wrote:
> From: David Woodhouse <[email protected]>
>
> Signed-off-by: David Woodhouse <[email protected]>
> ---
> drivers/pci/proc.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
> index 2d9cfa4..a940f4b 100644
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -17,6 +17,11 @@
>
> static int proc_initialized; /* = 0 */
>
> +#ifdef __aarch64__
> +/* ARM64 wants to be special and not expose this through /proc like everyone else */
> +#undef HAVE_PCI_MMAP
> +#endif

I'd still prefer this to be a whitelist of the existing architectures using PCI
MMAP in procfs, there is really no reason for arm64 to be special, the
one thing we want to control here is whether new architectures (including
arm64) that have never had either the sysfs or the procfs interface
should get one or both of them.

As it seems that there are important use cases for the sysfs interface
and your patch series will just make that work everywhere, I'd argue
that we should just always provide the sysfs interface now, and use
HAVE_PCI_MMAP only control the procfs interface.

That way, we turn on the sysfs interface on arc, arm64, frv and tile
as well as any future architecture with PCI support, but leave
the procfs support as opt-in.

Arnd

2017-03-24 16:17:07

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Fri, Mar 24, 2017 at 5:13 PM, Arnd Bergmann <[email protected]> wrote:
> On Wed, Mar 22, 2017 at 2:25 PM, David Woodhouse <[email protected]> wrote:
>> From: David Woodhouse <[email protected]>
>>
>> Signed-off-by: David Woodhouse <[email protected]>
>> ---
>> drivers/pci/proc.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
>> index 2d9cfa4..a940f4b 100644
>> --- a/drivers/pci/proc.c
>> +++ b/drivers/pci/proc.c
>> @@ -17,6 +17,11 @@
>>
>> static int proc_initialized; /* = 0 */
>>
>> +#ifdef __aarch64__
>> +/* ARM64 wants to be special and not expose this through /proc like everyone else */
>> +#undef HAVE_PCI_MMAP
>> +#endif
>
> I'd still prefer this to be a whitelist of the existing architectures using PCI
> MMAP in procfs, there is really no reason for arm64 to be special, the
> one thing we want to control here is whether new architectures (including
> arm64) that have never had either the sysfs or the procfs interface
> should get one or both of them.
>
> As it seems that there are important use cases for the sysfs interface
> and your patch series will just make that work everywhere, I'd argue
> that we should just always provide the sysfs interface now, and use
> HAVE_PCI_MMAP only control the procfs interface.
>
> That way, we turn on the sysfs interface on arc, arm64, frv and tile
> as well as any future architecture with PCI support, but leave
> the procfs support as opt-in.

Something alone these lines, to replace your patch 17/17 and the
one that turns on HAVE_PCI_MMAP for arm64.

Signed-off-by: Arnd Bergmann <[email protected]>

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 25d010d449a3..c517f1b724e0 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -980,8 +980,6 @@ void pci_remove_legacy_files(struct pci_bus *b)
}
#endif /* HAVE_PCI_LEGACY */

-#ifdef HAVE_PCI_MMAP
-
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
enum pci_mmap_api mmap_api)
{
@@ -1217,10 +1215,6 @@ static int pci_create_resource_files(struct
pci_dev *pdev)
}
return 0;
}
-#else /* !HAVE_PCI_MMAP */
-int __weak pci_create_resource_files(struct pci_dev *dev) { return 0; }
-void __weak pci_remove_resource_files(struct pci_dev *dev) { return; }
-#endif /* HAVE_PCI_MMAP */

/**
* pci_write_rom - used to enable access to the PCI ROM display
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8dd38e69d6f2..6c2a15d4ebf9 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -21,14 +21,12 @@ void pci_create_firmware_label_files(struct pci_dev *pdev);
void pci_remove_firmware_label_files(struct pci_dev *pdev);
#endif
void pci_cleanup_rom(struct pci_dev *dev);
-#ifdef HAVE_PCI_MMAP
enum pci_mmap_api {
PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
};
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
enum pci_mmap_api mmap_api);
-#endif
int pci_probe_reset_function(struct pci_dev *dev);

/**

2017-03-24 16:20:18

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 00/17] PCI resource mmap cleanup

On Wed, Mar 22, 2017 at 2:25 PM, David Woodhouse <[email protected]> wrote:
> This started out as a fairly trivial "add pci_mmap_page_range() for
> ARM64" patch. But pci_mmap_page_range() is a vile interface, taking
> "user visible" resource addresses converted with pci_resource_to_user()
> on those platforms unlucky enough to use that... and even in the *sane*
> sysfs-based mmap method, we convert through user addresses to call the
> platform-specific method.
>
> In most cases there's just no need for any of this crap. We can migrate
> most architectures to a generic implementation without much thought,
> and the few that aren't converted in this series can probably be added
> fairly easily too but need a little more arch-specific attention.
>
> Utterly untested for now; I'll do some testing while I deal with the
> inevitable bikeshedding.

Looks good to me overall, I have replied with one request for
clarification, and would like the bikeshed in patch 17 in a different
colour.

Arnd

2017-03-24 16:21:01

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Fri, 2017-03-24 at 17:13 +0100, Arnd Bergmann wrote:
>
> I'd still prefer this to be a whitelist of the existing architectures using PCI
> MMAP in procfs, there is really no reason for arm64 to be special, the
> one thing we want to control here is whether new architectures (including
> arm64) that have never had either the sysfs or the procfs interface
> should get one or both of them.
>
> As it seems that there are important use cases for the sysfs interface
> and your patch series will just make that work everywhere, I'd argue
> that we should just always provide the sysfs interface now, and use
> HAVE_PCI_MMAP only control the procfs interface.

I still have no sympathy for the "we don't want <this> tiny part of the
legacy generic non-architecture-specific procfs ABI to exist on ARM64".
Why not just kill /proc/bus/pci *entirely* there?

But sure, I suppose we could refactor things so that the sysfs mmap
bits depend on (HAVE_PCI_MMAP || ARCH_GENERIC_MMAP_RESOURCE_RANGE)
rather than having architectures define the latter in *addition* to the
former.

> That way, we turn on the sysfs interface on arc, arm64, frv and tile
> as well as any future architecture with PCI support, but leave
> the procfs support as opt-in.

OK. My plan was for ARCH_GENERIC_MMAP_RESOURCE_RANGE to go away once
all architectures were converted, and HAVE_PCI_MMAP to be all that's
left. It does make send to do arc, fr-v and tile too though. So we can
do it that way.


Attachments:
smime.p7s (4.82 kB)

2017-03-24 16:23:38

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 17/17] arm64: Do not expose PCI mmap through procfs

On Fri, 2017-03-24 at 17:16 +0100, Arnd Bergmann wrote:
>
> Something alone these lines, to replace your patch 17/17 and the
> one that turns on HAVE_PCI_MMAP for arm64.

No, I think that won't build because you don't have a
pci_mmap_page_range() function. And you didn't define
ARCH_GENERIC_PCI_MMAP_RESOURCE_RANGE. You probably get away with it if
you just fix up the ARCH_GENERIC_PCI_MMAP_RESOURCE_RANGE checks in
drivers/pci/mmap.c to be !HAVE_PCI_MMAP?


Attachments:
smime.p7s (4.82 kB)

2017-03-24 16:57:36

by Tony Luck

[permalink] [raw]
Subject: Re: [PATCH 00/17] PCI resource mmap cleanup

On Fri, Mar 24, 2017 at 11:40:33AM +0000, David Woodhouse wrote:
> That leaves IA64 as the last holdout, as the selection of vm_page_prot
> there is rather complicated:
>
> prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
>     vma->vm_page_prot);
>
> /*
> * If the user requested WC, the kernel uses UC or WC for this region,
> * and the chipset supports WC, we can use WC. Otherwise, we have to
> * use the same attribute the kernel uses.
> */
> if (write_combine &&
>     ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
>      (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
>     efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
> vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
> else
> vma->vm_page_prot = prot;
>
>
> But I suspect it's *overcomplicated*, as the kernel should only ever be
> mapping PCI memory BARs as UC or WC in the first place, so the middle
> two checks in the if (write_combine…) condition are redundant.

Agreed.

> And if the efi_range_is_wc() check isn't gratuitous, perhaps that
> should be in the generic code whenever CONFIG_EFI is set?

Sounds dubious whether EFI could even get this right. The efi
memory map table is static, but we could remap a BAR to a different
spot. Does the efi map have entries for all the places that you
could remap a BAR? Isn't it more likely a property of the device
whether it supports WC?

-Tony

2017-03-24 17:05:01

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 03/17] pci: Only allow WC mmap on prefetchable resources

On Fri, 2017-03-24 at 17:05 +0100, Arnd Bergmann wrote:
> On Wed, Mar 22, 2017 at 2:25 PM, David Woodhouse <[email protected]> wrote:
> >
> > From: David Woodhouse <[email protected]>
> >
> > The /proc/bus/pci mmap interface allows the user to specify whether they
> > want WC or not. Don't let them do so on non-prefetchable BARs.
> >
> > Signed-off-by: David Woodhouse <[email protected]>
> > Cc: [email protected]
> Can you explain this a little more? I understand that we usually want to use
> WC mappings on prefetchable BARs, and uncached non-WC on
> non-prefetchable, but why do we have to force an error here?
>
> Couldn't there be some hardware that allows write-combining access
> but no prefetches?

Note that this is only for the procfs interface. The sysfs interface
already imposes the same restriction by just *not* creating the
'resourceX_wc' attr when the resource isn't prefetchable. So this just
brings procfs into line.


Attachments:
smime.p7s (4.82 kB)

2017-04-04 21:36:37

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 04/17] pci: Add arch_can_pci_mmap_wc() macro

On Wed, Mar 22, 2017 at 01:25:18PM +0000, David Woodhouse wrote:
> From: David Woodhouse <[email protected]>
>
> 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 <[email protected]>
> ---
> Documentation/filesystems/sysfs-pci.txt | 4 ++++
> arch/ia64/include/asm/pci.h | 2 ++
> arch/powerpc/include/asm/pci.h | 5 +++--
> arch/x86/include/asm/pci.h | 2 ++
> arch/xtensa/include/asm/pci.h | 6 +++++-
> arch/xtensa/kernel/pci.c | 2 +-
> drivers/pci/pci-sysfs.c | 6 ++++--
> drivers/pci/proc.c | 17 ++++++++++-------
> 8 files changed, 31 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
> index 6ea1ced..25b7f1c 100644
> --- a/Documentation/filesystems/sysfs-pci.txt
> +++ b/Documentation/filesystems/sysfs-pci.txt
> @@ -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.
> diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
> index c0835b0..6283758 100644
> --- a/arch/ia64/include/asm/pci.h
> +++ b/arch/ia64/include/asm/pci.h
> @@ -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
> diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
> index 93eded8..b5b68c6 100644
> --- a/arch/powerpc/include/asm/pci.h
> +++ b/arch/powerpc/include/asm/pci.h
> @@ -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);
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index 1411dbe..f6e22c2 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -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);
> diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
> index 5d6bd93..f106879 100644
> --- a/arch/xtensa/include/asm/pci.h
> +++ b/arch/xtensa/include/asm/pci.h
> @@ -51,7 +51,11 @@ 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
> +#define HAVE_PCI_MMAP 1
> +
> +/* This was wrapped in #if 0 since the first merge of xtensa support...
> +#define arch_can_pci_mmap_wc() 1
> +*/
>
> #endif /* __KERNEL__ */
>
> diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
> index b848cc3..c5944d3 100644
> --- a/arch/xtensa/kernel/pci.c
> +++ b/arch/xtensa/kernel/pci.c
> @@ -345,7 +345,7 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
>
> /* Set to write-through */
> prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT;
> -#if 0
> +#ifdef arch_can_pci_mmap_wc

This hunk seems like maybe it should be a separate patch.

The rest of the patch:

- skips creation of /sys/.../resourceX_wc if !arch_can_pci_mmap_wc()
- makes PCIIOC_WRITE_COMBINE fail if !arch_can_pci_mmap_wc()

This part seems different -- it changes the way pci_mmap_page_range()
works.

> if (!write_combine)
> prot |= _PAGE_WRITETHRU;
> #endif
> diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
> index 7ac258f..cf2c7d8 100644
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -1210,10 +1210,12 @@ static int pci_create_resource_files(struct pci_dev *pdev)
> continue;
>
> retval = pci_create_attr(pdev, i, 0);
> +#ifdef arch_can_pci_mmap_wc
> /* 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);
> -
> +#endif
> if (retval) {
> pci_remove_resource_files(pdev);
> return retval;
> diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
> index dc8912e..c49be71 100644
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -209,15 +209,18 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
> fpriv->mmap_state = pci_mmap_mem;
> break;
>
> +#ifdef arch_can_pci_mmap_wc

Can we get rid of these #ifdefs in the code by adding this to linux/pci.h?

#ifndef arch_can_pci_mmap_wc
#define arch_can_pci_mmap_wc() 0
#endif

> 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 /* arch_can_pci_mmap_wc */
> #endif /* HAVE_PCI_MMAP */
> -
> default:
> ret = -EINVAL;
> break;
> --
> 2.9.3
>

2017-04-04 22:44:01

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 00/17] PCI resource mmap cleanup

On Wed, Mar 22, 2017 at 01:25:14PM +0000, David Woodhouse wrote:
> This started out as a fairly trivial "add pci_mmap_page_range() for
> ARM64" patch. But pci_mmap_page_range() is a vile interface, taking
> "user visible" resource addresses converted with pci_resource_to_user()
> on those platforms unlucky enough to use that... and even in the *sane*
> sysfs-based mmap method, we convert through user addresses to call the
> platform-specific method.
>
> In most cases there's just no need for any of this crap. We can migrate
> most architectures to a generic implementation without much thought,
> and the few that aren't converted in this series can probably be added
> fairly easily too but need a little more arch-specific attention.
>
> Utterly untested for now; I'll do some testing while I deal with the
> inevitable bikeshedding.

This looks really nice; thanks a lot for doing this!

I agree with Arnd about the __aarch64__ ifdef in pci/proc.c; I'd rather get
rid of that if we can.

I think you had a couple other updates; can you post a v2 when you're done
with those?

> David Woodhouse (17):
> pci: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms
> pci: Fix another sanity check bug in /proc/pci mmap
> pci: Only allow WC mmap on prefetchable resources
> pci: Add arch_can_pci_mmap_wc() macro
> pci: Move multiple declarations of pci_mmap_page_range() to <linux/pci.h>
> pci: Add HAVE_PCI_MMAP_IO to architectures which can mmap() I/O space
> pci: Use BAR index in sysfs attr->private instead of resource pointer
> pci: Add BAR index argument to pci_mmap_page_range()
> pci: Add pci_mmap_resource_range() and use it for ARM64
> arm: Use generic pci_mmap_resource_range()
> cris: Use generic pci_mmap_resource_range()
> mips: Use generic pci_mmap_resource_range()
> mn10300: Use generic pci_mmap_resource_range()
> parisc: Use generic pci_mmap_resource_range()
> sh: Use generic pci_mmap_resource_range()
> unicore: Use generic pci_mmap_resource_range()
> arm64: Do not expose PCI mmap through procfs
>
> Documentation/filesystems/sysfs-pci.txt | 9 +++-
> arch/arm/include/asm/pci.h | 3 +-
> arch/arm/kernel/bios32.c | 19 -------
> arch/arm64/include/asm/pci.h | 3 ++
> arch/cris/arch-v32/drivers/pci/bios.c | 22 --------
> arch/cris/include/asm/pci.h | 4 +-
> arch/ia64/include/asm/pci.h | 4 +-
> arch/ia64/pci/pci.c | 3 +-
> arch/microblaze/include/asm/pci.h | 6 +--
> arch/microblaze/pci/pci-common.c | 2 +-
> arch/mips/include/asm/pci.h | 5 +-
> arch/mips/pci/pci.c | 24 ---------
> arch/mn10300/include/asm/pci.h | 4 +-
> arch/mn10300/unit-asb2305/pci-asb2305.c | 23 ---------
> arch/parisc/include/asm/pci.h | 4 +-
> arch/parisc/kernel/pci.c | 28 ----------
> arch/powerpc/include/asm/pci.h | 9 ++--
> arch/powerpc/kernel/pci-common.c | 3 +-
> arch/sh/drivers/pci/pci.c | 21 --------
> arch/sh/include/asm/pci.h | 4 +-
> arch/sparc/include/asm/pci_64.h | 5 +-
> arch/sparc/kernel/pci.c | 6 +--
> arch/unicore32/include/asm/pci.h | 3 +-
> arch/unicore32/kernel/pci.c | 23 ---------
> arch/x86/include/asm/pci.h | 6 +--
> arch/x86/pci/i386.c | 3 +-
> arch/xtensa/include/asm/pci.h | 11 ++--
> arch/xtensa/kernel/pci.c | 5 +-
> drivers/pci/Makefile | 2 +-
> drivers/pci/mmap.c | 90 +++++++++++++++++++++++++++++++++
> drivers/pci/pci-sysfs.c | 77 +++++++++++++---------------
> drivers/pci/proc.c | 55 ++++++++++++++------
> include/linux/pci.h | 19 +++++++
> 33 files changed, 233 insertions(+), 272 deletions(-)
> create mode 100644 drivers/pci/mmap.c
>
> --
> 2.9.3
>

2017-04-05 07:22:35

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 04/17] pci: Add arch_can_pci_mmap_wc() macro

On Tue, 2017-04-04 at 16:36 -0500, Bjorn Helgaas wrote:
> > --- a/arch/xtensa/kernel/pci.c
> > +++ b/arch/xtensa/kernel/pci.c
> > @@ -345,7 +345,7 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
> >  
> >   /* Set to write-through */
> >   prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT;
> > -#if 0
> > +#ifdef arch_can_pci_mmap_wc
>
> This hunk seems like maybe it should be a separate patch.
>
> ...
>
> This part seems different -- it changes the way pci_mmap_page_range()
> works.

It doesn't, because arch_can_pci_map_wc isn't defined on xtensa. So
it's just a trivial cleanup for future-proofing, turning that 'if 0'
into 'if <something that isn't set>'.

> > diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
> > index dc8912e..c49be71 100644
> > --- a/drivers/pci/proc.c
> > +++ b/drivers/pci/proc.c
> > @@ -209,15 +209,18 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
> >   fpriv->mmap_state = pci_mmap_mem;
> >   break;
> >  
> > +#ifdef arch_can_pci_mmap_wc
> Can we get rid of these #ifdefs in the code by adding this to linux/pci.h?
>
>   #ifndef arch_can_pci_mmap_wc
>   #define arch_can_pci_mmap_wc() 0
>   #endif

Er.... at the time, that was non-trivial because there was something
that actually needed to be *removed* with the preprocessor instead of
just not being called. But after I settled on the incremental approach
of having pci_mmap_resource_range() be a wrapper for
pci_mmap_page_range() *and* vice versa I think that requirement went
away. I'll take another look and see if I can do that now; thanks.

Are you happy with the suggestion that we use HAVE_PCI_MMAP *only* to
control mmap on /proc/bus/pci, and we present mmap through sysfs on all
platforms via the generic code?


Attachments:
smime.p7s (4.82 kB)