Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame^] | 1 | #include <linux/init.h> |
| 2 | #include <linux/pci.h> |
| 3 | #include <asm/mpspec.h> |
| 4 | #include <linux/cpumask.h> |
| 5 | |
| 6 | /* |
| 7 | * This discovers the pcibus <-> node mapping on AMD K8. |
| 8 | * |
| 9 | * RED-PEN need to call this again on PCI hotplug |
| 10 | * RED-PEN empty cpus get reported wrong |
| 11 | */ |
| 12 | |
| 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 |
| 22 | |
| 23 | /** |
| 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 |
| 27 | */ |
| 28 | __init static int |
| 29 | fill_mp_bus_to_cpumask(void) |
| 30 | { |
| 31 | struct pci_dev *nb_dev = NULL; |
| 32 | int i, j, printed; |
| 33 | u32 ldtbus, nid; |
| 34 | static int lbnr[3] = { |
| 35 | LDT_BUS_NUMBER_REGISTER_0, |
| 36 | LDT_BUS_NUMBER_REGISTER_1, |
| 37 | LDT_BUS_NUMBER_REGISTER_2 |
| 38 | }; |
| 39 | |
| 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); |
| 43 | |
| 44 | for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) { |
| 45 | pci_read_config_dword(nb_dev, lbnr[i], &ldtbus); |
| 46 | /* |
| 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. |
| 50 | */ |
| 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); |
| 55 | j++) |
| 56 | pci_bus_to_cpumask[j] = |
| 57 | node_to_cpumask(NODE_ID(nid)); |
| 58 | } |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | /* quick sanity check */ |
| 63 | printed = 0; |
| 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; |
| 67 | if (printed) |
| 68 | continue; |
| 69 | printk(KERN_ERR |
| 70 | "k8-bus.c: some busses have empty cpu mask\n"); |
| 71 | printed = 1; |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | return 0; |
| 76 | } |
| 77 | |
| 78 | fs_initcall(fill_mp_bus_to_cpumask); |