* [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
[not found] <20160604000642.28162-1-yinghai@kernel.org>
@ 2016-06-04 0:06 ` Yinghai Lu
2016-06-07 8:04 ` Jesper Nilsson
2016-06-08 21:03 ` Bjorn Helgaas
2016-06-04 0:06 ` [PATCH v12 02/15] PCI: Let pci_mmap_page_range() take resource address Yinghai Lu
` (2 subsequent siblings)
3 siblings, 2 replies; 9+ messages in thread
From: Yinghai Lu @ 2016-06-04 0:06 UTC (permalink / raw)
To: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds
Cc: Wei Yang, Khalid Aziz, linux-pci, linux-kernel, Yinghai Lu,
linux-arm-kernel, linux-cris-kernel, linux-ia64, linux-mips,
linux-am33-list, linux-parisc, linuxppc-dev, linux-sh, sparclinux,
linux-xtensa
This one is preparing patch for next one:
PCI: Let pci_mmap_page_range() take resource addr
We need to pass extra resource pointer to avoid searching that again
for powerpc and microblaze prot set operation.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-cris-kernel@axis.com
Cc: linux-ia64@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-am33-list@redhat.com
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-sh@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
---
arch/arm/include/asm/pci.h | 2 --
arch/arm/kernel/bios32.c | 3 ++-
arch/cris/arch-v32/drivers/pci/bios.c | 3 ++-
arch/cris/include/asm/pci.h | 3 ---
arch/ia64/include/asm/pci.h | 2 --
arch/ia64/pci/pci.c | 3 ++-
arch/microblaze/include/asm/pci.h | 3 ---
arch/microblaze/pci/pci-common.c | 3 ++-
arch/mips/include/asm/pci.h | 3 ---
arch/mips/pci/pci.c | 3 ++-
arch/mn10300/include/asm/pci.h | 3 ---
arch/mn10300/unit-asb2305/pci-asb2305.c | 3 ++-
arch/parisc/include/asm/pci.h | 3 ---
arch/parisc/kernel/pci.c | 3 ++-
arch/powerpc/include/asm/pci.h | 3 ---
arch/powerpc/kernel/pci-common.c | 3 ++-
arch/sh/drivers/pci/pci.c | 3 ++-
arch/sh/include/asm/pci.h | 2 --
arch/sparc/include/asm/pci_64.h | 4 ----
arch/sparc/kernel/pci.c | 3 ++-
arch/unicore32/include/asm/pci.h | 2 --
arch/unicore32/kernel/pci.c | 3 ++-
arch/x86/include/asm/pci.h | 4 ----
arch/x86/pci/i386.c | 3 ++-
arch/xtensa/include/asm/pci.h | 4 ----
arch/xtensa/kernel/pci.c | 3 ++-
drivers/pci/pci-sysfs.c | 2 +-
drivers/pci/pci.h | 2 +-
drivers/pci/proc.c | 2 +-
include/linux/pci.h | 6 ++++++
30 files changed, 35 insertions(+), 54 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/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 05e61a2..d3245d1 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -602,7 +602,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pci_enable_resources(dev, mask);
}
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+int pci_mmap_page_range(struct pci_dev *dev, struct resource *res,
+ 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 64a5fb9..082efb9 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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long prot;
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 c0835b0..6a2f5d8 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -51,8 +51,6 @@ extern unsigned long ia64_max_iommu_merge_mask;
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
#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_PCI_LEGACY
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma,
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 8f6ac2f..1518d66 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, struct resource *res,
+ 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/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index fc3ecb5..1b93824 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/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 14cba60..95146b0 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -304,7 +304,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, struct resource *rp,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
resource_size_t offset =
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 86b239d..71d2c3b 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -75,9 +75,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
static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index f1b11f0..e620333 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -319,7 +319,8 @@ void pcibios_fixup_bus(struct pci_bus *bus)
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+int pci_mmap_page_range(struct pci_dev *dev, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long prot;
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/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index b7ab837..40efdc6 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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long prot;
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/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 0903c6a..8d5c34c 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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long prot;
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index a6f3ac0..662c1ef 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() */
#define HAVE_PCI_MMAP 1
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0f7a60f..6720b81 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -445,7 +445,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, struct resource *rp,
+ 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 d5462b7..a1bc7ba 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -269,7 +269,8 @@ void __init_refok 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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
/*
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 644314f..8e0fdb9 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -66,8 +66,6 @@ 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 022d160..f7a93df 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/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index c2b202d..86d7dda 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -862,7 +862,8 @@ 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,
+int pci_mmap_page_range(struct pci_dev *dev, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state,
int write_combine)
{
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/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index d45fa5f..ff1b7ef 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -362,7 +362,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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long phys;
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 9ab7507..eb87481 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -88,10 +88,6 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
#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);
-
#ifdef CONFIG_PCI
extern void early_quirks(void);
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 0a9f2ca..36463c7 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, struct resource *res,
+ struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long prot;
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index 5d6bd93..bb5510b 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/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index b848cc3..89c8687 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, struct resource *res,
+ 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 d319a9c..5bbe20c 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1027,7 +1027,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
pci_resource_to_user(pdev, i, 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, res, vma, mmap_type, write_combine);
}
static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index a814bbb..7d339c3 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -30,7 +30,7 @@ enum pci_mmap_api {
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);
+ enum pci_mmap_state mmap_type, enum pci_mmap_api mmap_api);
#endif
int pci_probe_reset_function(struct pci_dev *dev);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 3f155e7..f19ee2a 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -245,7 +245,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
if (i >= PCI_ROM_RESOURCE)
return -ENODEV;
- ret = pci_mmap_page_range(dev, vma,
+ ret = pci_mmap_page_range(dev, &dev->resource[i], vma,
fpriv->mmap_state,
fpriv->write_combine);
if (ret < 0)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index b67e4df..3c1a0f4 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -70,6 +70,12 @@ enum pci_mmap_state {
pci_mmap_mem
};
+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 *dev, struct resource *res,
+ struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
+
/*
* For PCI devices, the region numbers are assigned this way:
*/
--
2.8.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
2016-06-04 0:06 ` [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer Yinghai Lu
@ 2016-06-07 8:04 ` Jesper Nilsson
2016-06-08 21:03 ` Bjorn Helgaas
1 sibling, 0 replies; 9+ messages in thread
From: Jesper Nilsson @ 2016-06-07 8:04 UTC (permalink / raw)
To: Yinghai Lu
Cc: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds, Wei Yang, Khalid Aziz, linux-pci, linux-kernel,
linux-arm-kernel, linux-cris-kernel, linux-ia64, linux-mips,
linux-am33-list, linux-parisc, linuxppc-dev, linux-sh, sparclinux,
linux-xtensa
On Fri, Jun 03, 2016 at 05:06:28PM -0700, Yinghai Lu wrote:
> This one is preparing patch for next one:
> PCI: Let pci_mmap_page_range() take resource addr
>
> We need to pass extra resource pointer to avoid searching that again
> for powerpc and microblaze prot set operation.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: linux-arm-kernel@lists.infradead.org
For the CRIS part:
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
> diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
> index 64a5fb9..082efb9 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, struct resource *res,
> + struct vm_area_struct *vma,
> enum pci_mmap_state mmap_state, int write_combine)
> {
> unsigned long prot;
> 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__ */
/^JN - Jesper Nilsson
--
Jesper Nilsson -- jesper.nilsson@axis.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
2016-06-04 0:06 ` [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer Yinghai Lu
2016-06-07 8:04 ` Jesper Nilsson
@ 2016-06-08 21:03 ` Bjorn Helgaas
2016-06-08 22:35 ` Yinghai Lu
1 sibling, 1 reply; 9+ messages in thread
From: Bjorn Helgaas @ 2016-06-08 21:03 UTC (permalink / raw)
To: Yinghai Lu
Cc: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds, Wei Yang, Khalid Aziz, linux-pci, linux-kernel,
linux-arm-kernel, linux-cris-kernel, linux-ia64, linux-mips,
linux-am33-list, linux-parisc, linuxppc-dev, linux-sh, sparclinux,
linux-xtensa
On Fri, Jun 03, 2016 at 05:06:28PM -0700, Yinghai Lu wrote:
> This one is preparing patch for next one:
> PCI: Let pci_mmap_page_range() take resource addr
>
> We need to pass extra resource pointer to avoid searching that again
> for powerpc and microblaze prot set operation.
I'm not convinced yet that the extra resource pointer is necessary.
Microblaze does look up the resource in pci_mmap_page_range(), but it
never actually uses it. It *looks* like it uses it, but that code is
actually dead and I think we should apply the first patch below.
That leaves powerpc as the only arch that would use this extra
resource pointer. It uses it in __pci_mmap_set_pgprot() to help
decide whether to make a normal uncacheable mapping or a write-
combining one. There's nothing here that's specific to the powerpc
architecture, and I don't think we should add this parameter just to
cater to powerpc.
There are two cases where __pci_mmap_set_pgprot() on powerpc does
something based on the resource:
1) We're using procfs to mmap I/O port space after we requested
write-combining, e.g., we did this:
ioctl(fd, PCIIOC_MMAP_IS_IO); # request I/O port space
ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
mmap(fd, ...)
On powerpc, we ignore the write-combining request in this case.
I think we can handle this case by applying the second patch
below to ignore write-combining on I/O space for all arches, not
just powerpc.
2) We're using sysfs to mmap resourceN (not resourceN_wc), and
the resource is prefetchable. On powerpc, we turn *on*
write-combining, even though the user didn't ask for it.
I'm not sure this case is actually safe, because it changes the
ordering properties. If it *is* safe, we could enable write-
combining in pci_mmap_resource(), where we already have the
resource and it could be done for all arches.
This case is not strictly necessary, except to avoid a
performance regression, because the user could have mapped
resourceN_wc to explicitly request write-combining.
> diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
> index d319a9c..5bbe20c 100644
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -1027,7 +1027,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
> pci_resource_to_user(pdev, i, 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, res, 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 3f155e7..f19ee2a 100644
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -245,7 +245,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
> if (i >= PCI_ROM_RESOURCE)
> return -ENODEV;
>
> - ret = pci_mmap_page_range(dev, vma,
> + ret = pci_mmap_page_range(dev, &dev->resource[i], vma,
> fpriv->mmap_state,
> fpriv->write_combine);
> if (ret < 0)
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index b67e4df..3c1a0f4 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -70,6 +70,12 @@ enum pci_mmap_state {
> pci_mmap_mem
> };
>
> +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 *dev, struct resource *res,
> + struct vm_area_struct *vma,
> + enum pci_mmap_state mmap_state, int write_combine);
> +
> /*
> * For PCI devices, the region numbers are assigned this way:
> */
commit 4e712b691abc5b579e3e4327f56b0b7988bdd1cb
Author: Bjorn Helgaas <bhelgaas@google.com>
Date: Wed Jun 8 14:00:14 2016 -0500
microblaze/PCI: Remove useless __pci_mmap_set_pgprot()
The microblaze __pci_mmap_set_pgprot() was apparently copied from powerpc,
where it computes either an uncacheable pgprot_t or a write-combining one.
But on microblaze, we always use the regular uncacheable pgprot_t.
Remove the useless code in __pci_mmap_set_pgprot() and inline the
pgprot_noncached() at the only caller.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 14cba60..1974567 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -219,33 +219,6 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
}
/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- pgprot_t prot = protection;
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- return pgprot_noncached(prot);
-}
-
-/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
@@ -317,9 +290,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
commit 962972ee5e0ba6ceb680cb182bad65f8886586a6
Author: Bjorn Helgaas <bhelgaas@google.com>
Date: Wed Jun 8 14:46:54 2016 -0500
PCI: Ignore write-combining when mapping I/O port space
PCI exposes files like /proc/bus/pci/00/00.0 in procfs. These files
support operations like this:
ioctl(fd, PCIIOC_MMAP_IS_IO); # request I/O port space
ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
mmap(fd, ...)
Many architectures don't allow mmap of I/O port space at all, but I don't
think it makes sense to do a write-combining mapping on the ones that do.
We could change proc_bus_pci_ioctl() so the user could never enable write-
combining for I/O port space, but that would break the following sequence,
which is currently legal:
mmap(fd, ...) # default is I/O, non-combining
ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
ioctl(fd, PCIIOC_MMAP_IS_MEM); # request memory space
mmap(fd, ...)
Ignore the write-combining flag when mapping I/O port space.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 3f155e7..21f8d613 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -247,7 +247,8 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
ret = pci_mmap_page_range(dev, vma,
fpriv->mmap_state,
- fpriv->write_combine);
+ (fpriv->mmap_state == pci_mmap_mem) ?
+ fpriv->write_combine : 0);
if (ret < 0)
return ret;
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
2016-06-08 21:03 ` Bjorn Helgaas
@ 2016-06-08 22:35 ` Yinghai Lu
2016-06-09 0:00 ` Yinghai Lu
0 siblings, 1 reply; 9+ messages in thread
From: Yinghai Lu @ 2016-06-08 22:35 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds, Wei Yang, Khalid Aziz, linux-pci@vger.kernel.org,
Linux Kernel Mailing List, linux-arm-kernel@lists.infradead.org,
linux-cris-kernel, linux-ia64@vger.kernel.org,
linux-mips@linux-mips.org, linux-am33-list, linux-parisc,
linuxppc-dev, linux-sh, sparclinux@vger.kernel.org, linux-xtensa
On Wed, Jun 8, 2016 at 2:03 PM, Bjorn Helgaas <helgaas@kernel.org> wrote:
>
> Microblaze does look up the resource in pci_mmap_page_range(), but it
> never actually uses it. It *looks* like it uses it, but that code is
> actually dead and I think we should apply the first patch below.
Good one.
>
> That leaves powerpc as the only arch that would use this extra
> resource pointer. It uses it in __pci_mmap_set_pgprot() to help
> decide whether to make a normal uncacheable mapping or a write-
> combining one. There's nothing here that's specific to the powerpc
> architecture, and I don't think we should add this parameter just to
> cater to powerpc.
>
> There are two cases where __pci_mmap_set_pgprot() on powerpc does
> something based on the resource:
>
> 1) We're using procfs to mmap I/O port space after we requested
> write-combining, e.g., we did this:
>
> ioctl(fd, PCIIOC_MMAP_IS_IO); # request I/O port space
> ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
> mmap(fd, ...)
>
> On powerpc, we ignore the write-combining request in this case.
>
> I think we can handle this case by applying the second patch
> below to ignore write-combining on I/O space for all arches, not
> just powerpc.
>
> 2) We're using sysfs to mmap resourceN (not resourceN_wc), and
> the resource is prefetchable. On powerpc, we turn *on*
> write-combining, even though the user didn't ask for it.
>
> I'm not sure this case is actually safe, because it changes the
> ordering properties. If it *is* safe, we could enable write-
> combining in pci_mmap_resource(), where we already have the
> resource and it could be done for all arches.
>
> This case is not strictly necessary, except to avoid a
> performance regression, because the user could have mapped
> resourceN_wc to explicitly request write-combining.
>
Agreed.
>
> commit 4e712b691abc5b579e3e4327f56b0b7988bdd1cb
> Author: Bjorn Helgaas <bhelgaas@google.com>
> Date: Wed Jun 8 14:00:14 2016 -0500
>
> microblaze/PCI: Remove useless __pci_mmap_set_pgprot()
>
> The microblaze __pci_mmap_set_pgprot() was apparently copied from powerpc,
> where it computes either an uncacheable pgprot_t or a write-combining one.
> But on microblaze, we always use the regular uncacheable pgprot_t.
>
> Remove the useless code in __pci_mmap_set_pgprot() and inline the
> pgprot_noncached() at the only caller.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>
> diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
> index 14cba60..1974567 100644
> --- a/arch/microblaze/pci/pci-common.c
> +++ b/arch/microblaze/pci/pci-common.c
> @@ -219,33 +219,6 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
> }
>
> /*
> - * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
> - * device mapping.
> - */
> -static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
> - pgprot_t protection,
> - enum pci_mmap_state mmap_state,
> - int write_combine)
> -{
> - pgprot_t prot = protection;
> -
> - /* Write combine is always 0 on non-memory space mappings. On
> - * memory space, if the user didn't pass 1, we check for a
> - * "prefetchable" resource. This is a bit hackish, but we use
> - * this to workaround the inability of /sysfs to provide a write
> - * combine bit
> - */
> - if (mmap_state != pci_mmap_mem)
> - write_combine = 0;
> - else if (write_combine == 0) {
> - if (rp->flags & IORESOURCE_PREFETCH)
> - write_combine = 1;
> - }
> -
> - return pgprot_noncached(prot);
> -}
> -
> -/*
> * This one is used by /dev/mem and fbdev who have no clue about the
> * PCI device, it tries to find the PCI device first and calls the
> * above routine
> @@ -317,9 +290,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
> return -EINVAL;
>
> vma->vm_pgoff = offset >> PAGE_SHIFT;
> - vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
> - vma->vm_page_prot,
> - mmap_state, write_combine);
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>
> ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
> vma->vm_end - vma->vm_start, vma->vm_page_prot);
>
Acked-by: Yinghai Lu <yinghai@kernel.org>
>
>
> commit 962972ee5e0ba6ceb680cb182bad65f8886586a6
> Author: Bjorn Helgaas <bhelgaas@google.com>
> Date: Wed Jun 8 14:46:54 2016 -0500
>
> PCI: Ignore write-combining when mapping I/O port space
>
> PCI exposes files like /proc/bus/pci/00/00.0 in procfs. These files
> support operations like this:
>
> ioctl(fd, PCIIOC_MMAP_IS_IO); # request I/O port space
> ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
> mmap(fd, ...)
>
> Many architectures don't allow mmap of I/O port space at all, but I don't
> think it makes sense to do a write-combining mapping on the ones that do.
> We could change proc_bus_pci_ioctl() so the user could never enable write-
> combining for I/O port space, but that would break the following sequence,
> which is currently legal:
>
> mmap(fd, ...) # default is I/O, non-combining
> ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
> ioctl(fd, PCIIOC_MMAP_IS_MEM); # request memory space
> mmap(fd, ...)
>
> Ignore the write-combining flag when mapping I/O port space.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>
> diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
> index 3f155e7..21f8d613 100644
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -247,7 +247,8 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
>
> ret = pci_mmap_page_range(dev, vma,
> fpriv->mmap_state,
> - fpriv->write_combine);
> + (fpriv->mmap_state == pci_mmap_mem) ?
> + fpriv->write_combine : 0);
> if (ret < 0)
> return ret;
>
ok to me.
At the same time, can you kill __pci_mmap_set_pgprot() for powerpc.
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0f7a60f..0d0148d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -356,36 +356,6 @@ static struct resource
*__pci_mmap_make_offset(struct pci_dev *dev,
}
/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- /* XXX would be nice to have a way to ask for write-through */
- if (write_combine)
- return pgprot_noncached_wc(protection);
- else
- return pgprot_noncached(protection);
-}
-
-/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
@@ -458,9 +428,10 @@ int pci_mmap_page_range(struct pci_dev *dev,
struct vm_area_struct *vma,
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
+ if (write_combine)
+ vma->vm_page_prot = pgprot_noncached_wc(protection);
+ else
+ vma->vm_page_prot = pgprot_noncached(protection);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
2016-06-08 22:35 ` Yinghai Lu
@ 2016-06-09 0:00 ` Yinghai Lu
2016-06-09 22:36 ` Yinghai Lu
0 siblings, 1 reply; 9+ messages in thread
From: Yinghai Lu @ 2016-06-09 0:00 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds, Wei Yang, Khalid Aziz, linux-pci@vger.kernel.org,
Linux Kernel Mailing List, linux-arm-kernel@lists.infradead.org,
linux-cris-kernel, linux-ia64@vger.kernel.org,
linux-mips@linux-mips.org, linux-am33-list, linux-parisc,
linuxppc-dev, linux-sh, sparclinux@vger.kernel.org, linux-xtensa
[-- Attachment #1: Type: text/plain, Size: 317 bytes --]
On Wed, Jun 8, 2016 at 3:35 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> At the same time, can you kill __pci_mmap_set_pgprot() for powerpc.
Can you please put your two patches and this attached one into to pci/next?
Then I could send updated PCI: Let pci_mmap_page_range() take resource address.
Thanks
Yinghai
[-- Attachment #2: remove_powerpc_pci_prot.patch --]
[-- Type: text/x-patch, Size: 2652 bytes --]
From: Bjorn Helgaas <bhelgaas@google.com>
Subject: [PATCH] powerpc/PCI: Remove __pci_mmap_set_pgprot()
PCI: Ignore write-combining when mapping I/O port space
already handle the io port mmap path.
For mmio mmap path, caller should state that correctly if write_combine
is really needed.
via proc path it should look like:
mmap(fd, ...) # default is I/O, non-combining
ioctl(fd, PCIIOC_WRITE_COMBINE, 1); # request write-combining
ioctl(fd, PCIIOC_MMAP_IS_MEM); # request memory space
mmap(fd, ...)
sysfs path, it should use resource]?]_wc.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
arch/powerpc/kernel/pci-common.c | 37 ++++---------------------------------
1 file changed, 4 insertions(+), 33 deletions(-)
Index: linux-2.6/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/pci-common.c
+++ linux-2.6/arch/powerpc/kernel/pci-common.c
@@ -356,36 +356,6 @@ static struct resource *__pci_mmap_make_
}
/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- /* XXX would be nice to have a way to ask for write-through */
- if (write_combine)
- return pgprot_noncached_wc(protection);
- else
- return pgprot_noncached(protection);
-}
-
-/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
@@ -458,9 +428,10 @@ int pci_mmap_page_range(struct pci_dev *
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
+ if (write_combine)
+ vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer
2016-06-09 0:00 ` Yinghai Lu
@ 2016-06-09 22:36 ` Yinghai Lu
0 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2016-06-09 22:36 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds, Wei Yang, Khalid Aziz, linux-pci@vger.kernel.org,
Linux Kernel Mailing List, linux-arm-kernel@lists.infradead.org,
linux-cris-kernel, linux-ia64@vger.kernel.org,
linux-mips@linux-mips.org, linux-am33-list, linux-parisc,
linuxppc-dev, linux-sh, sparclinux@vger.kernel.org, linux-xtensa
On Wed, Jun 8, 2016 at 5:00 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Wed, Jun 8, 2016 at 3:35 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>
>> At the same time, can you kill __pci_mmap_set_pgprot() for powerpc.
>
> Can you please put your two patches and this attached one into to pci/next?
>
> Then I could send updated PCI: Let pci_mmap_page_range() take resource address.
Thanks for putting those patches in pci/resource branch.
I just re post updated for second patch.
[v12.update2,02/15] PCI: Let pci_mmap_page_range() take resource address
http://patchwork.ozlabs.org/patch/633399/
And the [v12 01/15] is not needed anymore.
patch3 to patch15 should still can be applied to pci/resource without problem.
Thanks
Yinghai
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v12 02/15] PCI: Let pci_mmap_page_range() take resource address
[not found] <20160604000642.28162-1-yinghai@kernel.org>
2016-06-04 0:06 ` [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer Yinghai Lu
@ 2016-06-04 0:06 ` Yinghai Lu
2016-06-04 0:06 ` [PATCH v12 08/15] powerpc/PCI: Keep resource idx order with bridge register number Yinghai Lu
2016-06-04 0:06 ` [PATCH v12 09/15] powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing Yinghai Lu
3 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2016-06-04 0:06 UTC (permalink / raw)
To: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds
Cc: Wei Yang, Khalid Aziz, linux-pci, linux-kernel, Yinghai Lu,
linuxppc-dev, sparclinux, linux-xtensa
In 8c05cd08a7 ("PCI: fix offset check for sysfs mmapped files"), try
to check exposed value with resource start/end in proc mmap path.
| 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 (start >= pci_start && start < pci_start + size &&
| start + nr <= pci_start + size)
That breaks sparc that exposed value is BAR value, and need to be offseted
to resource address.
Original pci_mmap_page_range() is taking PCI BAR value aka usr_address.
Bjorn found out that it would be much simple to pass resource address
directly and avoid extra those __pci_mmap_make_offset.
In this patch:
1. in proc path: proc_bus_pci_mmap, try convert back to resource
before calling pci_mmap_page_range
2. in sysfs path: pci_mmap_resource will just offset with resource start.
3. all pci_mmap_page_range will have vma->vm_pgoff with in resource
range instead of BAR value.
4. remove __pci_mmap_make_offset, as the checking is done
in pci_mmap_fits().
-v2: add pci_user_to_resource and remove __pci_mmap_make_offset
-v3: pass resource pointer with pci_mmap_page_range()
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: sparclinux@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
---
arch/microblaze/pci/pci-common.c | 78 +++-----------------------
arch/powerpc/kernel/pci-common.c | 78 +++-----------------------
arch/sparc/kernel/pci.c | 117 ---------------------------------------
arch/xtensa/kernel/pci.c | 75 ++++---------------------
drivers/pci/pci-sysfs.c | 33 ++++++++---
drivers/pci/proc.c | 63 ++++++++++++++++++---
6 files changed, 104 insertions(+), 340 deletions(-)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 95146b0..4e21993 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -156,69 +156,6 @@ void pcibios_set_master(struct pci_dev *dev)
*/
/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- resource_size_t *offset,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (!hose)
- return NULL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
- *offset += hose->pci_mem_offset;
-#endif
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
- *offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
- return rp;
- }
-
- return NULL;
-}
-
-/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
@@ -310,12 +247,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct resource *rp,
{
resource_size_t offset =
((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT;
- struct resource *rp;
int ret;
- rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
- if (rp == NULL)
- return -EINVAL;
+ if (mmap_state == pci_mmap_io) {
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ /* hose should never be NULL */
+ *offset += hose->io_base_phys -
+ ((unsigned long)hose->io_base_virt - _IO_BASE);
+ }
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
@@ -494,9 +434,7 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
*
* Hopefully, the sysfs insterface is immune to that gunk. Once X
* has been fixed (and the fix spread enough), we can re-enable the
- * 2 lines below and pass down a BAR value to userland. In that case
- * we'll also have to re-enable the matching code in
- * __pci_mmap_make_offset().
+ * 2 lines below and pass down a BAR value to userland.
*
* BenH.
*/
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 6720b81..7c7f652 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -293,69 +293,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
*/
/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- resource_size_t *offset,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (hose == NULL)
- return NULL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
- *offset += hose->pci_mem_offset;
-#endif
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
- *offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
- return rp;
- }
-
- return NULL;
-}
-
-/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
@@ -451,12 +388,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct resource *rp,
{
resource_size_t offset =
((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT;
- struct resource *rp;
int ret;
- rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
- if (rp == NULL)
- return -EINVAL;
+ if (mmap_state == pci_mmap_io) {
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ /* hose should never be NULL */
+ offset += hose->io_base_phys -
+ ((unsigned long)hose->io_base_virt - _IO_BASE);
+ }
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
@@ -631,9 +571,7 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
*
* Hopefully, the sysfs insterface is immune to that gunk. Once X
* has been fixed (and the fix spread enough), we can re-enable the
- * 2 lines below and pass down a BAR value to userland. In that case
- * we'll also have to re-enable the matching code in
- * __pci_mmap_make_offset().
+ * 2 lines below and pass down a BAR value to userland.
*
* BenH.
*/
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 86d7dda..4dbdad4 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -732,119 +732,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
/* Platform support for /proc/bus/pci/X/Y mmap()s. */
-/* If the user uses a host-bridge as the PCI device, he may use
- * this to perform a raw mmap() of the I/O or MEM space behind
- * that controller.
- *
- * This can be useful for execution of x86 PCI bios initialization code
- * on a PCI card, like the xfree86 int10 stuff does.
- */
-static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
- unsigned long space_size, user_offset, user_size;
-
- if (mmap_state == pci_mmap_io) {
- space_size = resource_size(&pbm->io_space);
- } else {
- space_size = resource_size(&pbm->mem_space);
- }
-
- /* Make sure the request is in range. */
- user_offset = vma->vm_pgoff << PAGE_SHIFT;
- user_size = vma->vm_end - vma->vm_start;
-
- if (user_offset >= space_size ||
- (user_offset + user_size) > space_size)
- return -EINVAL;
-
- if (mmap_state == pci_mmap_io) {
- vma->vm_pgoff = (pbm->io_space.start +
- user_offset) >> PAGE_SHIFT;
- } else {
- vma->vm_pgoff = (pbm->mem_space.start +
- user_offset) >> PAGE_SHIFT;
- }
-
- return 0;
-}
-
-/* Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static int __pci_mmap_make_offset(struct pci_dev *pdev,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- unsigned long user_paddr, user_size;
- int i, err;
-
- /* First compute the physical address in vma->vm_pgoff,
- * making sure the user offset is within range in the
- * appropriate PCI space.
- */
- err = __pci_mmap_make_offset_bus(pdev, vma, mmap_state);
- if (err)
- return err;
-
- /* If this is a mapping on a host bridge, any address
- * is OK.
- */
- if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
- return err;
-
- /* Otherwise make sure it's in the range for one of the
- * device's resources.
- */
- user_paddr = vma->vm_pgoff << PAGE_SHIFT;
- user_size = vma->vm_end - vma->vm_start;
-
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &pdev->resource[i];
- resource_size_t aligned_end;
-
- /* Active? */
- if (!rp->flags)
- continue;
-
- /* Same type? */
- if (i == PCI_ROM_RESOURCE) {
- if (mmap_state != pci_mmap_mem)
- continue;
- } else {
- if ((mmap_state == pci_mmap_io &&
- (rp->flags & IORESOURCE_IO) == 0) ||
- (mmap_state == pci_mmap_mem &&
- (rp->flags & IORESOURCE_MEM) == 0))
- continue;
- }
-
- /* Align the resource end to the next page address.
- * PAGE_SIZE intentionally added instead of (PAGE_SIZE - 1),
- * because actually we need the address of the next byte
- * after rp->end.
- */
- aligned_end = (rp->end + PAGE_SIZE) & PAGE_MASK;
-
- if ((rp->start <= user_paddr) &&
- (user_paddr + user_size) <= aligned_end)
- break;
- }
-
- if (i > PCI_ROM_RESOURCE)
- return -EINVAL;
-
- return 0;
-}
-
/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
@@ -869,10 +756,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct resource *res,
{
int ret;
- ret = __pci_mmap_make_offset(dev, vma, mmap_state);
- if (ret < 0)
- return ret;
-
__pci_mmap_set_pgprot(dev, vma, mmap_state);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 89c8687..a0e5d8d 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -272,68 +272,6 @@ pci_controller_num(struct pci_dev *dev)
*/
/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static __inline__ int
-__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (pci_ctrl == 0)
- return -EINVAL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = (unsigned long)pci_ctrl->io_space.base;
- offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- offset += pci_ctrl->io_space.start - io_offset;
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- return 0;
- }
-
- return -EINVAL;
-}
-
-/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
@@ -367,11 +305,18 @@ int pci_mmap_page_range(struct pci_dev *dev, struct resource *res,
enum pci_mmap_state mmap_state,
int write_combine)
{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
int ret;
- ret = __pci_mmap_make_offset(dev, vma, mmap_state);
- if (ret < 0)
- return ret;
+ if (mmap_state == pci_mmap_io) {
+ struct pci_controller *pci_ctrl =
+ (struct pci_controller *)dev->sysdata;
+
+ /* pci_ctrl should never be NULL */
+ offset += pci_ctrl->io_space.start - pci_ctrl->io_space.base;
+ }
+
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
__pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5bbe20c..307b3c0 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -967,12 +967,23 @@ void pci_remove_legacy_files(struct pci_bus *b)
#ifdef HAVE_PCI_MMAP
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_type,
enum pci_mmap_api mmap_api)
{
unsigned long nr, start, size, pci_start;
+ int flags;
if (pci_resource_len(pdev, resno) == 0)
return 0;
+
+ if (mmap_type == pci_mmap_mem)
+ flags = IORESOURCE_MEM;
+ else
+ flags = IORESOURCE_IO;
+
+ if (!(pci_resource_flags(pdev, resno) & flags))
+ return 0;
+
nr = vma_pages(vma);
start = vma->vm_pgoff;
size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
@@ -999,7 +1010,6 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
struct resource *res = attr->private;
enum pci_mmap_state mmap_type;
- resource_size_t start, end;
int i;
for (i = 0; i < PCI_ROM_RESOURCE; i++)
@@ -1008,10 +1018,21 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
if (i >= PCI_ROM_RESOURCE)
return -ENODEV;
+ /*
+ * resource start have to be PAGE_SIZE aligned, as we pass
+ * back virt address include round down of resource_start,
+ * that caller can not figure out directly.
+ * when it is not aligned, that mean it is io port, should go
+ * pci_read_resource_io()/pci_write_resource_io() path.
+ */
+ if (res->start & ~PAGE_MASK)
+ return -EINVAL;
+
if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
return -EINVAL;
- if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
+ mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+ if (!pci_mmap_fits(pdev, i, vma, mmap_type, 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,
@@ -1020,13 +1041,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
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, i, res, &start, &end);
- vma->vm_pgoff += start >> PAGE_SHIFT;
- mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+ vma->vm_pgoff += res->start >> PAGE_SHIFT;
return pci_mmap_page_range(pdev, res, vma, mmap_type, write_combine);
}
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index f19ee2a..7291635 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -227,26 +227,71 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
}
#ifdef HAVE_PCI_MMAP
+
+static int pci_user_to_resource(struct pci_dev *dev, resource_size_t *offset,
+ int flags)
+{
+ int i;
+
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ resource_size_t start, end;
+ struct resource *res = &dev->resource[i];
+
+ if (!(res->flags & flags))
+ continue;
+
+ if (pci_resource_len(dev, i) == 0)
+ continue;
+
+ /*
+ * here *offset is PAGE_SIZE aligned from caller.
+ * need align start/end for io port resource that is
+ * usually not PAGE_SIZE aligned.
+ * that means we let it go if they falls in same page.
+ */
+ pci_resource_to_user(dev, i, res, &start, &end);
+ if ((start & PAGE_MASK) <= *offset &&
+ *offset <= (end & PAGE_MASK)) {
+ *offset = res->start + (*offset - start);
+ return i;
+ }
+ }
+
+ return -ENODEV;
+}
+
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;
+ enum pci_mmap_state mmap_type = fpriv->mmap_state;
+ resource_size_t offset;
+ int i, ret, flags;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- /* 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))
- break;
- }
-
- if (i >= PCI_ROM_RESOURCE)
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+ if (mmap_type == pci_mmap_mem)
+ flags = IORESOURCE_MEM;
+ else
+ flags = IORESOURCE_IO;
+ i = pci_user_to_resource(dev, &offset, flags);
+ if (i < 0)
return -ENODEV;
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
+ if (!pci_mmap_fits(dev, i, vma, mmap_type, PCI_MMAP_PROCFS)) {
+ 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(dev), i,
+ (u64)pci_resource_start(dev, i),
+ (u64)pci_resource_len(dev, i));
+ return -EINVAL;
+ }
+
ret = pci_mmap_page_range(dev, &dev->resource[i], vma,
- fpriv->mmap_state,
+ mmap_type,
fpriv->write_combine);
if (ret < 0)
return ret;
--
2.8.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v12 08/15] powerpc/PCI: Keep resource idx order with bridge register number
[not found] <20160604000642.28162-1-yinghai@kernel.org>
2016-06-04 0:06 ` [PATCH v12 01/15] PCI: Let pci_mmap_page_range() take extra resource pointer Yinghai Lu
2016-06-04 0:06 ` [PATCH v12 02/15] PCI: Let pci_mmap_page_range() take resource address Yinghai Lu
@ 2016-06-04 0:06 ` Yinghai Lu
2016-06-04 0:06 ` [PATCH v12 09/15] powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing Yinghai Lu
3 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2016-06-04 0:06 UTC (permalink / raw)
To: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds
Cc: Wei Yang, Khalid Aziz, linux-pci, linux-kernel, Yinghai Lu,
linuxppc-dev
Same as sparc version.
Make resource with consistent sequence
like other arch or directly from pci_read_bridge_bases(),
even when non-pref mmio is missing, or out of ordering in firmware reporting.
Just hold i = 1 for non pref mmio, and i = 2 for pref mmio.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/kernel/pci_of_scan.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 526ac67..719f225 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -252,7 +252,7 @@ void of_scan_pci_bridge(struct pci_dev *dev)
bus->resource[i] = res;
++res;
}
- i = 1;
+ i = 3;
for (; len >= 32; len -= 32, ranges += 8) {
flags = pci_parse_of_flags(of_read_number(ranges, 1), 1);
size = of_read_number(&ranges[6], 2);
@@ -265,6 +265,12 @@ void of_scan_pci_bridge(struct pci_dev *dev)
" for bridge %s\n", node->full_name);
continue;
}
+ } else if ((flags & IORESOURCE_PREFETCH) &&
+ !bus->resource[2]->flags) {
+ res = bus->resource[2];
+ } else if (((flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) ==
+ IORESOURCE_MEM) && !bus->resource[1]->flags) {
+ res = bus->resource[1];
} else {
if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
printk(KERN_ERR "PCI: too many memory ranges"
--
2.8.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v12 09/15] powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing
[not found] <20160604000642.28162-1-yinghai@kernel.org>
` (2 preceding siblings ...)
2016-06-04 0:06 ` [PATCH v12 08/15] powerpc/PCI: Keep resource idx order with bridge register number Yinghai Lu
@ 2016-06-04 0:06 ` Yinghai Lu
3 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2016-06-04 0:06 UTC (permalink / raw)
To: Bjorn Helgaas, David Miller, Benjamin Herrenschmidt,
Linus Torvalds
Cc: Wei Yang, Khalid Aziz, linux-pci, linux-kernel, Yinghai Lu,
Paul Mackerras, Michael Ellerman, Gavin Shan, Yijing Wang,
Anton Blanchard, linuxppc-dev
For device resource PREF bit setting under bridge 64-bit pref resource,
we need to make sure only set PREF for 64bit resource.
This patch set IORESOUCE_MEM_64 for 64bit resource during OF device resource
flags parsing.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=96261
Link: https://bugzilla.kernel.org/show_bug.cgi?id=96241
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Gavin Shan <gwshan@linux.vnet.ibm.com>
Cc: Yijing Wang <wangyijing@huawei.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/kernel/pci_of_scan.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 719f225..476b8ac5 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -44,8 +44,10 @@ static unsigned int pci_parse_of_flags(u32 addr0, int bridge)
if (addr0 & 0x02000000) {
flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
- flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;
flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;
+ if (addr0 & 0x01000000)
+ flags |= IORESOURCE_MEM_64
+ | PCI_BASE_ADDRESS_MEM_TYPE_64;
if (addr0 & 0x40000000)
flags |= IORESOURCE_PREFETCH
| PCI_BASE_ADDRESS_MEM_PREFETCH;
--
2.8.3
^ permalink raw reply related [flat|nested] 9+ messages in thread