Skip to content

Commit 2311b1f

Browse files
mpegregkh
authored andcommitted
[PATCH] PCI: fix-pci-mmap-on-ppc-and-ppc64.patch
This is an updated version of Ben's fix-pci-mmap-on-ppc-and-ppc64.patch which is in 2.6.12-rc4-mm1. It fixes the patch to work on PPC iSeries, removes some debug printks at Ben's request, and incorporates your fix-pci-mmap-on-ppc-and-ppc64-fix.patch also. Originally from Benjamin Herrenschmidt <[email protected]> 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 <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a0d399a commit 2311b1f

File tree

7 files changed

+97
-13
lines changed

7 files changed

+97
-13
lines changed

arch/ppc/kernel/pci.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,7 +1495,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
14951495
*offset += hose->pci_mem_offset;
14961496
res_bit = IORESOURCE_MEM;
14971497
} else {
1498-
io_offset = (unsigned long)hose->io_base_virt;
1498+
io_offset = hose->io_base_virt - ___IO_BASE;
14991499
*offset += io_offset;
15001500
res_bit = IORESOURCE_IO;
15011501
}
@@ -1522,7 +1522,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
15221522

15231523
/* found it! construct the final physical address */
15241524
if (mmap_state == pci_mmap_io)
1525-
*offset += hose->io_base_phys - _IO_BASE;
1525+
*offset += hose->io_base_phys - io_offset;
15261526
return rp;
15271527
}
15281528

@@ -1739,6 +1739,23 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
17391739
return result;
17401740
}
17411741

1742+
void pci_resource_to_user(const struct pci_dev *dev, int bar,
1743+
const struct resource *rsrc,
1744+
u64 *start, u64 *end)
1745+
{
1746+
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
1747+
unsigned long offset = 0;
1748+
1749+
if (hose == NULL)
1750+
return;
1751+
1752+
if (rsrc->flags & IORESOURCE_IO)
1753+
offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
1754+
1755+
*start = rsrc->start + offset;
1756+
*end = rsrc->end + offset;
1757+
}
1758+
17421759
void __init
17431760
pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
17441761
int flags, char *name)

arch/ppc64/kernel/pci.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
351351
*offset += hose->pci_mem_offset;
352352
res_bit = IORESOURCE_MEM;
353353
} else {
354-
io_offset = (unsigned long)hose->io_base_virt;
354+
io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
355355
*offset += io_offset;
356356
res_bit = IORESOURCE_IO;
357357
}
@@ -378,7 +378,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
378378

379379
/* found it! construct the final physical address */
380380
if (mmap_state == pci_mmap_io)
381-
*offset += hose->io_base_phys - io_offset;
381+
*offset += hose->io_base_phys - io_offset;
382382
return rp;
383383
}
384384

@@ -944,4 +944,22 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
944944
}
945945
EXPORT_SYMBOL(pci_read_irq_line);
946946

947+
void pci_resource_to_user(const struct pci_dev *dev, int bar,
948+
const struct resource *rsrc,
949+
u64 *start, u64 *end)
950+
{
951+
struct pci_controller *hose = pci_bus_to_host(dev->bus);
952+
unsigned long offset = 0;
953+
954+
if (hose == NULL)
955+
return;
956+
957+
if (rsrc->flags & IORESOURCE_IO)
958+
offset = pci_io_base - (unsigned long)hose->io_base_virt +
959+
hose->io_base_phys;
960+
961+
*start = rsrc->start + offset;
962+
*end = rsrc->end + offset;
963+
}
964+
947965
#endif /* CONFIG_PPC_MULTIPLATFORM */

drivers/pci/pci-sysfs.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,18 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)
6060
char * str = buf;
6161
int i;
6262
int max = 7;
63+
u64 start, end;
6364

6465
if (pci_dev->subordinate)
6566
max = DEVICE_COUNT_RESOURCE;
6667

6768
for (i = 0; i < max; i++) {
68-
str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
69-
pci_resource_start(pci_dev,i),
70-
pci_resource_end(pci_dev,i),
71-
pci_resource_flags(pci_dev,i));
69+
struct resource *res = &pci_dev->resource[i];
70+
pci_resource_to_user(pci_dev, i, res, &start, &end);
71+
str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
72+
(unsigned long long)start,
73+
(unsigned long long)end,
74+
(unsigned long long)res->flags);
7275
}
7376
return (str - buf);
7477
}
@@ -313,8 +316,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
313316
struct device, kobj));
314317
struct resource *res = (struct resource *)attr->private;
315318
enum pci_mmap_state mmap_type;
319+
u64 start, end;
320+
int i;
316321

317-
vma->vm_pgoff += res->start >> PAGE_SHIFT;
322+
for (i = 0; i < PCI_ROM_RESOURCE; i++)
323+
if (res == &pdev->resource[i])
324+
break;
325+
if (i >= PCI_ROM_RESOURCE)
326+
return -ENODEV;
327+
328+
/* pci_mmap_page_range() expects the same kind of entry as coming
329+
* from /proc/bus/pci/ which is a "user visible" value. If this is
330+
* different from the resource itself, arch will do necessary fixup.
331+
*/
332+
pci_resource_to_user(pdev, i, res, &start, &end);
333+
vma->vm_pgoff += start >> PAGE_SHIFT;
318334
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
319335

320336
return pci_mmap_page_range(pdev, vma, mmap_type, 0);

drivers/pci/proc.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,20 @@ static int show_device(struct seq_file *m, void *v)
355355
dev->device,
356356
dev->irq);
357357
/* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
358-
for(i=0; i<7; i++)
358+
for (i=0; i<7; i++) {
359+
u64 start, end;
360+
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
359361
seq_printf(m, LONG_FORMAT,
360-
dev->resource[i].start |
362+
((unsigned long)start) |
361363
(dev->resource[i].flags & PCI_REGION_FLAG_MASK));
362-
for(i=0; i<7; i++)
364+
}
365+
for (i=0; i<7; i++) {
366+
u64 start, end;
367+
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
363368
seq_printf(m, LONG_FORMAT,
364369
dev->resource[i].start < dev->resource[i].end ?
365-
dev->resource[i].end - dev->resource[i].start + 1 : 0);
370+
(unsigned long)(end - start) + 1 : 0);
371+
}
366372
seq_putc(m, '\t');
367373
if (drv)
368374
seq_printf(m, "%s", drv->name);

include/asm-ppc/pci.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
103103
unsigned long size,
104104
pgprot_t prot);
105105

106+
#define HAVE_ARCH_PCI_RESOURCE_TO_USER
107+
extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
108+
const struct resource *rsrc,
109+
u64 *start, u64 *end);
110+
111+
106112
#endif /* __KERNEL__ */
107113

108114
#endif /* __PPC_PCI_H */

include/asm-ppc64/pci.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
136136
unsigned long size,
137137
pgprot_t prot);
138138

139+
#ifdef CONFIG_PPC_MULTIPLATFORM
140+
#define HAVE_ARCH_PCI_RESOURCE_TO_USER
141+
extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
142+
const struct resource *rsrc,
143+
u64 *start, u64 *end);
144+
#endif /* CONFIG_PPC_MULTIPLATFORM */
145+
139146

140147
#endif /* __KERNEL__ */
141148

include/linux/pci.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,20 @@ static inline char *pci_name(struct pci_dev *pdev)
10201020
#define pci_pretty_name(dev) ""
10211021
#endif
10221022

1023+
1024+
/* Some archs don't want to expose struct resource to userland as-is
1025+
* in sysfs and /proc
1026+
*/
1027+
#ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
1028+
static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
1029+
const struct resource *rsrc, u64 *start, u64 *end)
1030+
{
1031+
*start = rsrc->start;
1032+
*end = rsrc->end;
1033+
}
1034+
#endif /* HAVE_ARCH_PCI_RESOURCE_TO_USER */
1035+
1036+
10231037
/*
10241038
* The world is not perfect and supplies us with broken PCI devices.
10251039
* For at least a part of these bugs we need a work-around, so both

0 commit comments

Comments
 (0)