2005-04-17 02:20:36 +04:00
/*
* legacy . c - traditional , old school PCI bus probing
*/
# include <linux/init.h>
# include <linux/pci.h>
# include "pci.h"
/*
* Discover remaining PCI buses in case there are peer host bridges .
* We use the number of last PCI bus provided by the PCI BIOS .
*/
static void __devinit pcibios_fixup_peer_bridges ( void )
{
int n , devfn ;
x86: get mp_bus_to_node early
Currently, on an amd k8 system with multi ht chains, the numa_node of
pci devices under /sys/devices/pci0000:80/* is always 0, even if that
chain is on node 1 or 2 or 3.
Workaround: pcibus_to_node(bus) is used when we want to get the node that
pci_device is on.
In struct device, we already have numa_node member, and we could use
dev_to_node()/set_dev_node() to get and set numa_node in the device.
set_dev_node is called in pci_device_add() with pcibus_to_node(bus),
and pcibus_to_node uses bus->sysdata for nodeid.
The problem is when pci_add_device is called, bus->sysdata is not assigned
correct nodeid yet. The result is that numa_node will always be 0.
pcibios_scan_root and pci_scan_root could take sysdata. So we need to get
mp_bus_to_node mapping before these two are called, and thus
get_mp_bus_to_node could get correct node for sysdata in root bus.
In scanning of the root bus, all child busses will take parent bus sysdata.
So all pci_device->dev.numa_node will be assigned correctly and automatically.
Later we could use dev_to_node(&pci_dev->dev) to get numa_node, and we
could also could make other bus specific device get the correct numa_node
too.
This is an updated version of pci_sysdata and Jeff's pci_domain patch.
[ mingo@elte.hu: build fix ]
Signed-off-by: Yinghai Lu <yinghai.lu@sun.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-02-19 14:20:09 +03:00
long node ;
2005-04-17 02:20:36 +04:00
if ( pcibios_last_bus < = 0 | | pcibios_last_bus > = 0xff )
return ;
DBG ( " PCI: Peer bridge fixup \n " ) ;
for ( n = 0 ; n < = pcibios_last_bus ; n + + ) {
u32 l ;
if ( pci_find_bus ( 0 , n ) )
continue ;
x86: get mp_bus_to_node early
Currently, on an amd k8 system with multi ht chains, the numa_node of
pci devices under /sys/devices/pci0000:80/* is always 0, even if that
chain is on node 1 or 2 or 3.
Workaround: pcibus_to_node(bus) is used when we want to get the node that
pci_device is on.
In struct device, we already have numa_node member, and we could use
dev_to_node()/set_dev_node() to get and set numa_node in the device.
set_dev_node is called in pci_device_add() with pcibus_to_node(bus),
and pcibus_to_node uses bus->sysdata for nodeid.
The problem is when pci_add_device is called, bus->sysdata is not assigned
correct nodeid yet. The result is that numa_node will always be 0.
pcibios_scan_root and pci_scan_root could take sysdata. So we need to get
mp_bus_to_node mapping before these two are called, and thus
get_mp_bus_to_node could get correct node for sysdata in root bus.
In scanning of the root bus, all child busses will take parent bus sysdata.
So all pci_device->dev.numa_node will be assigned correctly and automatically.
Later we could use dev_to_node(&pci_dev->dev) to get numa_node, and we
could also could make other bus specific device get the correct numa_node
too.
This is an updated version of pci_sysdata and Jeff's pci_domain patch.
[ mingo@elte.hu: build fix ]
Signed-off-by: Yinghai Lu <yinghai.lu@sun.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-02-19 14:20:09 +03:00
node = get_mp_bus_to_node ( n ) ;
2005-04-17 02:20:36 +04:00
for ( devfn = 0 ; devfn < 256 ; devfn + = 8 ) {
2008-02-10 17:45:28 +03:00
if ( ! raw_pci_read ( 0 , n , devfn , PCI_VENDOR_ID , 2 , & l ) & &
2005-04-17 02:20:36 +04:00
l ! = 0x0000 & & l ! = 0xffff ) {
DBG ( " Found device at %02x:%02x [%04x] \n " , n , devfn , l ) ;
printk ( KERN_INFO " PCI: Discovered peer bus %02x \n " , n ) ;
x86: get mp_bus_to_node early
Currently, on an amd k8 system with multi ht chains, the numa_node of
pci devices under /sys/devices/pci0000:80/* is always 0, even if that
chain is on node 1 or 2 or 3.
Workaround: pcibus_to_node(bus) is used when we want to get the node that
pci_device is on.
In struct device, we already have numa_node member, and we could use
dev_to_node()/set_dev_node() to get and set numa_node in the device.
set_dev_node is called in pci_device_add() with pcibus_to_node(bus),
and pcibus_to_node uses bus->sysdata for nodeid.
The problem is when pci_add_device is called, bus->sysdata is not assigned
correct nodeid yet. The result is that numa_node will always be 0.
pcibios_scan_root and pci_scan_root could take sysdata. So we need to get
mp_bus_to_node mapping before these two are called, and thus
get_mp_bus_to_node could get correct node for sysdata in root bus.
In scanning of the root bus, all child busses will take parent bus sysdata.
So all pci_device->dev.numa_node will be assigned correctly and automatically.
Later we could use dev_to_node(&pci_dev->dev) to get numa_node, and we
could also could make other bus specific device get the correct numa_node
too.
This is an updated version of pci_sysdata and Jeff's pci_domain patch.
[ mingo@elte.hu: build fix ]
Signed-off-by: Yinghai Lu <yinghai.lu@sun.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-02-19 14:20:09 +03:00
pci_scan_bus_on_node ( n , & pci_root_ops , node ) ;
2005-04-17 02:20:36 +04:00
break ;
}
}
}
}
static int __init pci_legacy_init ( void )
{
if ( ! raw_pci_ops ) {
printk ( " PCI: System does not support PCI \n " ) ;
return 0 ;
}
if ( pcibios_scanned + + )
return 0 ;
printk ( " PCI: Probing PCI hardware \n " ) ;
pci_root_bus = pcibios_scan_root ( 0 ) ;
2005-04-28 11:25:45 +04:00
if ( pci_root_bus )
pci_bus_add_devices ( pci_root_bus ) ;
2005-04-17 02:20:36 +04:00
pcibios_fixup_peer_bridges ( ) ;
return 0 ;
}
subsys_initcall ( pci_legacy_init ) ;