x86: use bus conf in NB conf fun1 to get bus range on, on 64-bit
[linux-block.git] / arch / x86 / pci / k8-bus_64.c
CommitLineData
1da177e4
LT
1#include <linux/init.h>
2#include <linux/pci.h>
871d5f8d 3#include <asm/pci-direct.h>
1da177e4
LT
4#include <asm/mpspec.h>
5#include <linux/cpumask.h>
871d5f8d 6#include <linux/topology.h>
1da177e4
LT
7
8/*
9 * This discovers the pcibus <-> node mapping on AMD K8.
10 *
11 * RED-PEN need to call this again on PCI hotplug
12 * RED-PEN empty cpus get reported wrong
13 */
14
35ddd068
YL
15#define NODE_ID(dword) ((dword>>4) & 0x07)
16#define LDT_BUS_NUMBER_REGISTER_0 0xE0
17#define LDT_BUS_NUMBER_REGISTER_1 0xE4
18#define LDT_BUS_NUMBER_REGISTER_2 0xE8
19#define LDT_BUS_NUMBER_REGISTER_3 0xEC
20#define NR_LDT_BUS_NUMBER_REGISTERS 4
21#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
22#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 24) & 0xFF)
23
355540f3 24#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
35ddd068
YL
25#define PCI_DEVICE_ID_K8_10H_HTCONFIG 0x1200
26#define PCI_DEVICE_ID_K8_11H_HTCONFIG 0x1300
1da177e4 27
871d5f8d
YL
28#ifdef CONFIG_NUMA
29
30#define BUS_NR 256
31
32static int mp_bus_to_node[BUS_NR];
33
34void set_mp_bus_to_node(int busnum, int node)
35{
36 if (busnum >= 0 && busnum < BUS_NR)
37 mp_bus_to_node[busnum] = node;
38}
39
40int get_mp_bus_to_node(int busnum)
41{
42 int node = -1;
43
44 if (busnum < 0 || busnum > (BUS_NR - 1))
45 return node;
46
47 node = mp_bus_to_node[busnum];
48
49 /*
50 * let numa_node_id to decide it later in dma_alloc_pages
51 * if there is no ram on that node
52 */
53 if (node != -1 && !node_online(node))
54 node = -1;
55
56 return node;
57}
58
59#endif
60
1da177e4 61/**
871d5f8d
YL
62 * early_fill_mp_bus_to_node()
63 * called before pcibios_scan_root and pci_scan_bus
1da177e4
LT
64 * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
65 * Registers found in the K8 northbridge
66 */
67__init static int
871d5f8d 68early_fill_mp_bus_to_node(void)
1da177e4 69{
871d5f8d 70#ifdef CONFIG_NUMA
355540f3 71 int i, j;
871d5f8d 72 unsigned slot;
35ddd068 73 u32 ldtbus;
871d5f8d 74 u32 id;
35ddd068
YL
75 int node;
76 u16 deviceid;
77 u16 vendorid;
78 int min_bus;
79 int max_bus;
80
81 static int lbnr[NR_LDT_BUS_NUMBER_REGISTERS] = {
1da177e4
LT
82 LDT_BUS_NUMBER_REGISTER_0,
83 LDT_BUS_NUMBER_REGISTER_1,
35ddd068
YL
84 LDT_BUS_NUMBER_REGISTER_2,
85 LDT_BUS_NUMBER_REGISTER_3
1da177e4
LT
86 };
87
871d5f8d
YL
88 for (i = 0; i < BUS_NR; i++)
89 mp_bus_to_node[i] = -1;
90
91 if (!early_pci_allowed())
92 return -1;
93
35ddd068
YL
94 slot = 0x18;
95 id = read_pci_config(0, slot, 0, PCI_VENDOR_ID);
96
97 vendorid = id & 0xffff;
98 if (vendorid != PCI_VENDOR_ID_AMD)
99 goto out;
100
101 deviceid = (id>>16) & 0xffff;
102 if ((deviceid != PCI_DEVICE_ID_K8HTCONFIG) &&
103 (deviceid != PCI_DEVICE_ID_K8_10H_HTCONFIG) &&
104 (deviceid != PCI_DEVICE_ID_K8_11H_HTCONFIG))
105 goto out;
106
107 for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
108 ldtbus = read_pci_config(0, slot, 1, lbnr[i]);
109
110 /* Check if that register is enabled for bus range */
111 if ((ldtbus & 7) != 3)
112 continue;
113
114 min_bus = SECONDARY_LDT_BUS_NUMBER(ldtbus);
115 max_bus = SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
116 node = NODE_ID(ldtbus);
117 for (j = min_bus; j <= max_bus; j++)
118 mp_bus_to_node[j] = (unsigned char) node;
1da177e4
LT
119 }
120
35ddd068 121out:
871d5f8d 122 for (i = 0; i < BUS_NR; i++) {
35ddd068 123 node = mp_bus_to_node[i];
871d5f8d
YL
124 if (node >= 0)
125 printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node);
126 }
127#endif
1da177e4
LT
128 return 0;
129}
130
871d5f8d 131postcore_initcall(early_fill_mp_bus_to_node);