x86: get mp_bus_to_node early
[linux-block.git] / arch / x86 / pci / k8-bus_64.c
index 9cc813e29706d3febdd70aacf5b4aa2d6e4940af..3903efbca535e7cd5c0d5db4118a95362a66fe8a 100644 (file)
@@ -1,7 +1,9 @@
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <asm/pci-direct.h>
 #include <asm/mpspec.h>
 #include <linux/cpumask.h>
+#include <linux/topology.h>
 
 /*
  * This discovers the pcibus <-> node mapping on AMD K8.
 #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
 #define PCI_DEVICE_ID_K8HTCONFIG 0x1100
 
+#ifdef CONFIG_NUMA
+
+#define BUS_NR 256
+
+static int mp_bus_to_node[BUS_NR];
+
+void set_mp_bus_to_node(int busnum, int node)
+{
+       if (busnum >= 0 &&  busnum < BUS_NR)
+               mp_bus_to_node[busnum] = node;
+}
+
+int get_mp_bus_to_node(int busnum)
+{
+       int node = -1;
+
+       if (busnum < 0 || busnum > (BUS_NR - 1))
+               return node;
+
+       node = mp_bus_to_node[busnum];
+
+       /*
+        * let numa_node_id to decide it later in dma_alloc_pages
+        * if there is no ram on that node
+        */
+       if (node != -1 && !node_online(node))
+               node = -1;
+
+       return node;
+}
+
+#endif
+
 /**
- * fill_mp_bus_to_cpumask()
+ * early_fill_mp_bus_to_node()
+ * called before pcibios_scan_root and pci_scan_bus
  * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
  * Registers found in the K8 northbridge
  */
 __init static int
-fill_mp_bus_to_cpumask(void)
+early_fill_mp_bus_to_node(void)
 {
-       struct pci_dev *nb_dev = NULL;
+#ifdef CONFIG_NUMA
        int i, j;
+       unsigned slot;
        u32 ldtbus, nid;
+       u32 id;
        static int lbnr[3] = {
                LDT_BUS_NUMBER_REGISTER_0,
                LDT_BUS_NUMBER_REGISTER_1,
                LDT_BUS_NUMBER_REGISTER_2
        };
 
-       while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-                       PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
-               pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
+       for (i = 0; i < BUS_NR; i++)
+               mp_bus_to_node[i] = -1;
+
+       if (!early_pci_allowed())
+               return -1;
+
+       for (slot = 0x18; slot < 0x20; slot++) {
+               id = read_pci_config(0, slot, 0, PCI_VENDOR_ID);
+               if (id != (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_K8HTCONFIG<<16)))
+                       break;
+               nid = read_pci_config(0, slot, 0, NODE_ID_REGISTER);
 
                for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
-                       pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
+                       ldtbus = read_pci_config(0, slot, 0, lbnr[i]);
                        /*
                         * if there are no busses hanging off of the current
                         * ldt link then both the secondary and subordinate
                         * bus number fields are set to 0.
-                        * 
+                        *
                         * RED-PEN
                         * This is slightly broken because it assumes
-                        * HT node IDs == Linux node ids, which is not always
+                        * HT node IDs == Linux node ids, which is not always
                         * true. However it is probably mostly true.
                         */
                        if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
                                && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
                                for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
                                     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
-                                    j++) { 
-                                       struct pci_bus *bus;
-                                       struct pci_sysdata *sd;
-
-                                       long node = NODE_ID(nid);
-                                       /* Algorithm a bit dumb, but
-                                          it shouldn't matter here */
-                                       bus = pci_find_bus(0, j);
-                                       if (!bus)
-                                               continue;
-                                       if (!node_online(node))
-                                               node = 0;
-
-                                       sd = bus->sysdata;
-                                       sd->node = node;
-                               }               
+                                    j++) {
+                                       int node = NODE_ID(nid);
+                                       mp_bus_to_node[j] = (unsigned char)node;
+                               }
                        }
                }
        }
 
+       for (i = 0; i < BUS_NR; i++) {
+               int node = mp_bus_to_node[i];
+               if (node >= 0)
+                       printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node);
+       }
+#endif
        return 0;
 }
 
-fs_initcall(fill_mp_bus_to_cpumask);
+postcore_initcall(early_fill_mp_bus_to_node);