pci_child_fixup()
Adds a fresh pci_fixup_child() hook for physical bus numbers in bus number registers that don't match the bus numbers in the MP tables. It basically allows for arbitrary bus number twiddling for children.
vs. 2.5.59-mm1
arch/i386/pci/numa.c | 9 +++++++++ drivers/pci/probe.c | 5 +---- include/asm-i386/pci.h | 11 +++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-)
arch/i386/pci/numa.c +9 -0
@@ -88,6 +88,15 @@ static struct pci_ops pci_direct_conf1_m .write = pci_conf1_mq_write }; +void pci_child_fixup (struct pci_bus *parent,struct pci_bus *child,int buses) +{ +int quad =BUS2QUAD (parent->number); + child->primary =QUADLOCAL2BUS (quad, buses &0xFF ); + child->secondary =QUADLOCAL2BUS (quad, (buses >>8 ) &0xFF ); + child->subordinate =QUADLOCAL2BUS (quad, (buses >>16 ) &0xFF ); + child->number = child->secondary; +} +static void __devinit pci_fixup_i450nx (struct pci_dev *d) {
drivers/pci/probe.c +1 -4
@@ -271,10 +271,7 @@ int __devinit pci_scan_bridge(struct pciif (pass)return max; child =pci_add_new_bus (bus, dev,0 ); - child->primary = buses &0xFF ; - child->secondary = (buses >>8 ) &0xFF ; - child->subordinate = (buses >>16 ) &0xFF ; - child->number = child->secondary; +pci_child_fixup (bus, child, buses); cmax =pci_do_scan_bus (child);if (cmax > max) max = cmax; }else {
include/asm-i386/pci.h +11 -0
@@ -100,6 +100,17 @@ static inline int pci_controller_num(strextern 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_X86_NUMAQ +void pci_child_fixup (struct pci_bus *,struct pci_bus *,int ); +#else +static inline void pci_child_fixup (struct pci_bus *parent,struct pci_bus *child,int buses) +{ + child->primary = buses &0xFF ; + child->secondary = (buses >>8 ) &0xFF ; + child->subordinate = (buses >>16 ) &0xFF ; + child->number = child->secondary; +} +#endif #endif /* __KERNEL__ */ /* implement the pci_ DMA API in terms of the generic device dma_ one */
drivers/pci/probe.c int __devinit pci_scan_bridge(struct pci · line 274
Quoted 6 lines · William Lee Irwin III
drivers/pci/probe.c +1
-4child =pci_add_new_bus (bus, dev,0 ); - child->primary = buses &0xFF ; - child->secondary = (buses >>8 ) &0xFF ; - child->subordinate = (buses >>16 ) &0xFF ; - child->number = child->secondary; +pci_child_fixup (bus, child, buses);
The "bus" argument seems to be redundant. Why not use "child->parent" just filled in by pci_add_new_bus() instead?
Ivan.
Quoted 6 lines · William Lee Irwin III
Quoted 6 lines
(quoted diff) +1
-4child = pci_add_new_bus(bus, dev, 0); - child->primary = buses & 0xFF; - child->secondary = (buses >> 8) & 0xFF; - child->subordinate = (buses >> 16) & 0xFF; - child->number = child->secondary; + pci_child_fixup(bus, child, buses);
Quoted 3 lines · Ivan Kokshaysky
The "bus" argument seems to be redundant. Why not use "
child->parent" just filled in bypci_add_new_bus()instead?
Ivan.
Good point. Here's an adjusted patch. I added gregkh to the cc: list in case he's interested (he generally seems to be wrt. PCI).
Thanks,
Bill
The NUMA-Q BIOS reports bus numbers different from the physical ones programmed into PCI-PCI bridges etc. PCI config cycles (and almost everything else) are meant to use translation tables handed to us by the BIOS. No other extant i386 port has such a beast, and there's currently no way to override bus numbers gotten from bus number registers in a meaningful way; bus number conflicts error out prior to any call into arch code. All of the IRQ routing, interrupt assignment, IO-APIC, PCI bus, etc. etc. MP table entries use these numbers, so we're stuck with them.
This provides a fixup hook so it's possible to override the standard interpretation of the bus number registers in PCI-PCI bridges.
arch/i386/pci/numa.c | 9 +++++++++ drivers/pci/probe.c | 5 +---- include/asm-i386/pci.h | 11 +++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-)
arch/i386/pci/numa.c +9 -0
@@ -88,6 +88,15 @@ static struct pci_ops pci_direct_conf1_m .write = pci_conf1_mq_write }; +void pci_child_fixup (struct pci_bus *child,int buses) +{ +int quad =BUS2QUAD (child->parent->number); + child->primary =QUADLOCAL2BUS (quad, buses &0xFF ); + child->secondary =QUADLOCAL2BUS (quad, (buses >>8 ) &0xFF ); + child->subordinate =QUADLOCAL2BUS (quad, (buses >>16 ) &0xFF ); + child->number = child->secondary; +} +static void __devinit pci_fixup_i450nx (struct pci_dev *d) {
drivers/pci/probe.c +1 -4
@@ -271,10 +271,7 @@ int __devinit pci_scan_bridge(struct pciif (pass)return max; child =pci_add_new_bus (bus, dev,0 ); - child->primary = buses &0xFF ; - child->secondary = (buses >>8 ) &0xFF ; - child->subordinate = (buses >>16 ) &0xFF ; - child->number = child->secondary; +pci_child_fixup (child, buses); cmax =pci_do_scan_bus (child);if (cmax > max) max = cmax; }else {
include/asm-i386/pci.h +11 -0
@@ -100,6 +100,17 @@ static inline int pci_controller_num(strextern 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_X86_NUMAQ +void pci_child_fixup (struct pci_bus *,int ); +#else +static inline void pci_child_fixup (struct pci_bus *child,int buses) +{ + child->primary = buses &0xFF ; + child->secondary = (buses >>8 ) &0xFF ; + child->subordinate = (buses >>16 ) &0xFF ; + child->number = child->secondary; +} +#endif #endif /* __KERNEL__ */ /* implement the pci_ DMA API in terms of the generic device dma_ one */