1 #include <linux/init.h>
3 #include <asm/mpspec.h>
4 #include <linux/cpumask.h>
7 * This discovers the pcibus <-> node mapping on AMD K8.
9 * RED-PEN need to call this again on PCI hotplug
10 * RED-PEN empty cpus get reported wrong
13 #define NODE_ID_REGISTER 0x60
14 #define NODE_ID(dword) (dword & 0x07)
15 #define LDT_BUS_NUMBER_REGISTER_0 0x94
16 #define LDT_BUS_NUMBER_REGISTER_1 0xB4
17 #define LDT_BUS_NUMBER_REGISTER_2 0xD4
18 #define NR_LDT_BUS_NUMBER_REGISTERS 3
19 #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
20 #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
21 #define PCI_DEVICE_ID_K8HTCONFIG 0x1100
24 * fill_mp_bus_to_cpumask()
25 * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
26 * Registers found in the K8 northbridge
29 fill_mp_bus_to_cpumask(void)
31 struct pci_dev
*nb_dev
= NULL
;
34 static int lbnr
[3] = {
35 LDT_BUS_NUMBER_REGISTER_0
,
36 LDT_BUS_NUMBER_REGISTER_1
,
37 LDT_BUS_NUMBER_REGISTER_2
40 while ((nb_dev
= pci_get_device(PCI_VENDOR_ID_AMD
,
41 PCI_DEVICE_ID_K8HTCONFIG
, nb_dev
))) {
42 pci_read_config_dword(nb_dev
, NODE_ID_REGISTER
, &nid
);
44 for (i
= 0; i
< NR_LDT_BUS_NUMBER_REGISTERS
; i
++) {
45 pci_read_config_dword(nb_dev
, lbnr
[i
], &ldtbus
);
47 * if there are no busses hanging off of the current
48 * ldt link then both the secondary and subordinate
49 * bus number fields are set to 0.
51 if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus
) == 0
52 && SUBORDINATE_LDT_BUS_NUMBER(ldtbus
) == 0)) {
53 for (j
= SECONDARY_LDT_BUS_NUMBER(ldtbus
);
54 j
<= SUBORDINATE_LDT_BUS_NUMBER(ldtbus
);
56 pci_bus_to_cpumask
[j
] =
57 node_to_cpumask(NODE_ID(nid
));
62 /* quick sanity check */
64 for (i
= 0; i
< 256; i
++) {
65 if (cpus_empty(pci_bus_to_cpumask
[i
])) {
66 pci_bus_to_cpumask
[i
] = CPU_MASK_ALL
;
70 "k8-bus.c: some busses have empty cpu mask\n");
78 fs_initcall(fill_mp_bus_to_cpumask
);