* [PATCH] Fix PCI mmap on ppc and ppc64
@ 2005-05-10 4:53 Benjamin Herrenschmidt
2005-05-10 13:18 ` Andreas Schwab
0 siblings, 1 reply; 3+ messages in thread
From: Benjamin Herrenschmidt @ 2005-05-10 4:53 UTC (permalink / raw)
To: Andrew Morton; +Cc: Linux Kernel list, linux-pci
Hi Andrew !
This patch was discussed at length on linux-pci and so far, the last
iteration of it didn't raise any comment. It's effect is a nop on
architecture that don't define the new pci_resource_to_user() callback
anyway. It allows architecture like ppc who put weird things inside of
PCI resource structures to convert to some different value for user
visible ones. It also fixes mmap'ing of IO space on those archs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Index: linux-work/arch/ppc64/kernel/pci.c
===================================================================
--- linux-work.orig/arch/ppc64/kernel/pci.c 2005-05-06
15:39:24.000000000 +1000
+++ linux-work/arch/ppc64/kernel/pci.c 2005-05-09 12:00:54.000000000
+1000
@@ -351,9 +351,12 @@
*offset += hose->pci_mem_offset;
res_bit = IORESOURCE_MEM;
} else {
- io_offset = (unsigned long)hose->io_base_virt;
+ io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
+ printk("offset: %lx, io_base_virt: %p, pci_io_base: %lx, io_offset: %
lx\n",
+ *offset, hose->io_base_virt, pci_io_base, io_offset);
*offset += io_offset;
res_bit = IORESOURCE_IO;
+ printk(" -> offset: %lx\n", *offset);
}
/*
@@ -373,12 +376,15 @@
continue;
/* In the range of this resource? */
+ printk(" r%d: %lx -> %lx\n", i, rp->start, rp->end);
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;
+ if (mmap_state == pci_mmap_io) {
+ *offset += hose->io_base_phys - io_offset;
+ printk(" result: %lx\n", *offset);
+ }
return rp;
}
@@ -941,4 +947,22 @@
}
EXPORT_SYMBOL(pci_read_irq_line);
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ unsigned long offset = 0;
+
+ if (hose == NULL)
+ return;
+
+ if (rsrc->flags & IORESOURCE_IO)
+ offset = pci_io_base - (unsigned long)hose->io_base_virt +
+ hose->io_base_phys;
+
+ *start = rsrc->start + offset;
+ *end = rsrc->end + offset;
+}
+
#endif /* CONFIG_PPC_MULTIPLATFORM */
Index: linux-work/drivers/pci/pci-sysfs.c
===================================================================
--- linux-work.orig/drivers/pci/pci-sysfs.c 2005-05-05
15:56:37.000000000 +1000
+++ linux-work/drivers/pci/pci-sysfs.c 2005-05-09 12:00:54.000000000
+1000
@@ -60,15 +60,18 @@
char * str = buf;
int i;
int max = 7;
+ u64 start, end;
if (pci_dev->subordinate)
max = DEVICE_COUNT_RESOURCE;
for (i = 0; i < max; i++) {
- str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
- pci_resource_start(pci_dev,i),
- pci_resource_end(pci_dev,i),
- pci_resource_flags(pci_dev,i));
+ struct resource *res = &pci_dev->resource[i];
+ pci_resource_to_user(pci_dev, i, res, &start, &end);
+ str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
+ (unsigned long long)start,
+ (unsigned long long)end,
+ (unsigned long long)res->flags);
}
return (str - buf);
}
@@ -301,8 +304,21 @@
struct device, kobj));
struct resource *res = (struct resource *)attr->private;
enum pci_mmap_state mmap_type;
+ u64 start, end;
+ int i;
- vma->vm_pgoff += res->start >> PAGE_SHIFT;
+ for (i = 0; i < PCI_ROM_RESOURCE; i++)
+ if (res == &pdev->resource[i])
+ break;
+ if (i >= PCI_ROM_RESOURCE)
+ return -ENODEV;
+
+ /* 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;
return pci_mmap_page_range(pdev, vma, mmap_type, 0);
Index: linux-work/include/asm-ppc64/pci.h
===================================================================
--- linux-work.orig/include/asm-ppc64/pci.h 2005-05-02
10:50:01.000000000 +1000
+++ linux-work/include/asm-ppc64/pci.h 2005-05-09 12:00:54.000000000
+1000
@@ -135,6 +135,11 @@
unsigned long offset,
unsigned long size,
pgprot_t prot);
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end);
+
#endif /* __KERNEL__ */
Index: linux-work/drivers/pci/proc.c
===================================================================
--- linux-work.orig/drivers/pci/proc.c 2005-05-05 15:56:37.000000000
+1000
+++ linux-work/drivers/pci/proc.c 2005-05-09 12:00:54.000000000 +1000
@@ -355,14 +355,20 @@
dev->device,
dev->irq);
/* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve
compatibility */
- for(i=0; i<7; i++)
+ for(i=0; i<7; i++) {
+ u64 start, end;
+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, LONG_FORMAT,
- dev->resource[i].start |
+ ((unsigned long)start) |
(dev->resource[i].flags & PCI_REGION_FLAG_MASK));
- for(i=0; i<7; i++)
+ }
+ for(i=0; i<7; i++) {
+ u64 start, end;
+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, LONG_FORMAT,
dev->resource[i].start < dev->resource[i].end ?
- dev->resource[i].end - dev->resource[i].start + 1 : 0);
+ (unsigned long)(end - start) + 1 : 0);
+ }
seq_putc(m, '\t');
if (drv)
seq_printf(m, "%s", drv->name);
Index: linux-work/drivers/pci/pci.c
===================================================================
--- linux-work.orig/drivers/pci/pci.c 2005-05-05 15:56:37.000000000
+1000
+++ linux-work/drivers/pci/pci.c 2005-05-09 12:00:54.000000000 +1000
@@ -759,7 +759,7 @@
return 0;
}
#endif
-
+
static int __devinit pci_init(void)
{
struct pci_dev *dev = NULL;
Index: linux-work/include/linux/pci.h
===================================================================
--- linux-work.orig/include/linux/pci.h 2005-05-05 15:56:38.000000000
+1000
+++ linux-work/include/linux/pci.h 2005-05-09 12:00:55.000000000 +1000
@@ -1016,6 +1016,21 @@
#define pci_pretty_name(dev) ""
#endif
+
+/* Some archs don't want to expose struct resource to userland as-is
+ * in sysfs and /proc
+ */
+#ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
+static void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end)
+{
+ *start = rsrc->start;
+ *end = rsrc->end;
+}
+#endif /* HAVE_ARCH_PCI_RESOURCE_TO_USER */
+
+
/*
* The world is not perfect and supplies us with broken PCI devices.
* For at least a part of these bugs we need a work-around, so both
Index: linux-work/include/asm-ppc/pci.h
===================================================================
--- linux-work.orig/include/asm-ppc/pci.h 2005-05-02 10:49:57.000000000
+1000
+++ linux-work/include/asm-ppc/pci.h 2005-05-09 12:00:55.000000000 +1000
@@ -103,6 +103,12 @@
unsigned long size,
pgprot_t prot);
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end);
+
+
#endif /* __KERNEL__ */
#endif /* __PPC_PCI_H */
Index: linux-work/arch/ppc/kernel/pci.c
===================================================================
--- linux-work.orig/arch/ppc/kernel/pci.c 2005-05-02 10:48:08.000000000
+1000
+++ linux-work/arch/ppc/kernel/pci.c 2005-05-09 12:00:55.000000000 +1000
@@ -1495,7 +1495,7 @@
*offset += hose->pci_mem_offset;
res_bit = IORESOURCE_MEM;
} else {
- io_offset = (unsigned long)hose->io_base_virt;
+ io_offset = hose->io_base_virt - ___IO_BASE;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
@@ -1522,7 +1522,7 @@
/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - _IO_BASE;
+ *offset += hose->io_base_phys - io_offset;
return rp;
}
@@ -1739,6 +1739,23 @@
return result;
}
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ unsigned long offset = 0;
+
+ if (hose == NULL)
+ return;
+
+ if (rsrc->flags & IORESOURCE_IO)
+ offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+
+ *start = rsrc->start + offset;
+ *end = rsrc->end + offset;
+}
+
void __init
pci_init_resource(struct resource *res, unsigned long start, unsigned
long end,
int flags, char *name)
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Fix PCI mmap on ppc and ppc64
2005-05-10 4:53 [PATCH] Fix PCI mmap on ppc and ppc64 Benjamin Herrenschmidt
@ 2005-05-10 13:18 ` Andreas Schwab
2005-05-10 13:57 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 3+ messages in thread
From: Andreas Schwab @ 2005-05-10 13:18 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Andrew Morton, Linux Kernel list, linux-pci
Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
> @@ -351,9 +351,12 @@
> *offset += hose->pci_mem_offset;
> res_bit = IORESOURCE_MEM;
> } else {
> - io_offset = (unsigned long)hose->io_base_virt;
> + io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
> + printk("offset: %lx, io_base_virt: %p, pci_io_base: %lx, io_offset: %
> lx\n",
> + *offset, hose->io_base_virt, pci_io_base, io_offset);
> *offset += io_offset;
> res_bit = IORESOURCE_IO;
> + printk(" -> offset: %lx\n", *offset);
I don't think you want those debugging printks be left here.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Fix PCI mmap on ppc and ppc64
2005-05-10 13:18 ` Andreas Schwab
@ 2005-05-10 13:57 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 3+ messages in thread
From: Benjamin Herrenschmidt @ 2005-05-10 13:57 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Andrew Morton, Linux Kernel list, linux-pci
On Tue, 2005-05-10 at 15:18 +0200, Andreas Schwab wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
>
> > @@ -351,9 +351,12 @@
> > *offset += hose->pci_mem_offset;
> > res_bit = IORESOURCE_MEM;
> > } else {
> > - io_offset = (unsigned long)hose->io_base_virt;
> > + io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
> > + printk("offset: %lx, io_base_virt: %p, pci_io_base: %lx, io_offset: %
> > lx\n",
> > + *offset, hose->io_base_virt, pci_io_base, io_offset);
> > *offset += io_offset;
> > res_bit = IORESOURCE_IO;
> > + printk(" -> offset: %lx\n", *offset);
>
> I don't think you want those debugging printks be left here.
Good point, looks like I got really sloppy on this patch. I'll send a
fix tomorrow unless andrew beats me at it as this isn't yet in any
released -mm
Ben.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-05-10 14:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-10 4:53 [PATCH] Fix PCI mmap on ppc and ppc64 Benjamin Herrenschmidt
2005-05-10 13:18 ` Andreas Schwab
2005-05-10 13:57 ` Benjamin Herrenschmidt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox