]> err.no Git - linux-2.6/blob - arch/x86/pci/numa.c
x86: remove mpc_oem_pci_bus()
[linux-2.6] / arch / x86 / pci / numa.c
1 /*
2  * numa.c - Low-level PCI access for NUMA-Q machines
3  */
4
5 #include <linux/pci.h>
6 #include <linux/init.h>
7 #include <linux/nodemask.h>
8 #include <mach_apic.h>
9 #include "pci.h"
10
11 #define XQUAD_PORTIO_BASE 0xfe400000
12 #define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
13
14 int mp_bus_id_to_node[MAX_MP_BUSSES];
15 #define BUS2QUAD(global) (mp_bus_id_to_node[global])
16
17 int mp_bus_id_to_local[MAX_MP_BUSSES];
18 #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
19
20 int quad_local_to_mp_bus_id [NR_CPUS/4][4];
21 #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
22 void mpc_oem_pci_bus(struct mpc_config_bus *m,
23         struct mpc_config_translation *translation)
24 {
25         int quad = translation->trans_quad;
26         int local = translation->trans_local;
27
28         quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
29 }
30
31 /* Where the IO area was mapped on multiquad, always 0 otherwise */
32 void *xquad_portio;
33 #ifdef CONFIG_X86_NUMAQ
34 EXPORT_SYMBOL(xquad_portio);
35 #endif
36
37 #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
38
39 #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
40         (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
41
42 static void write_cf8(unsigned bus, unsigned devfn, unsigned reg)
43 {
44         unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg);
45         if (xquad_portio)
46                 writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus)));
47         else
48                 outl(val, 0xCF8);
49 }
50
51 static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
52                              unsigned int devfn, int reg, int len, u32 *value)
53 {
54         unsigned long flags;
55         void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
56
57         if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
58                 return -EINVAL;
59
60         spin_lock_irqsave(&pci_config_lock, flags);
61
62         write_cf8(bus, devfn, reg);
63
64         switch (len) {
65         case 1:
66                 if (xquad_portio)
67                         *value = readb(adr + (reg & 3));
68                 else
69                         *value = inb(0xCFC + (reg & 3));
70                 break;
71         case 2:
72                 if (xquad_portio)
73                         *value = readw(adr + (reg & 2));
74                 else
75                         *value = inw(0xCFC + (reg & 2));
76                 break;
77         case 4:
78                 if (xquad_portio)
79                         *value = readl(adr);
80                 else
81                         *value = inl(0xCFC);
82                 break;
83         }
84
85         spin_unlock_irqrestore(&pci_config_lock, flags);
86
87         return 0;
88 }
89
90 static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
91                               unsigned int devfn, int reg, int len, u32 value)
92 {
93         unsigned long flags;
94         void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
95
96         if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
97                 return -EINVAL;
98
99         spin_lock_irqsave(&pci_config_lock, flags);
100
101         write_cf8(bus, devfn, reg);
102
103         switch (len) {
104         case 1:
105                 if (xquad_portio)
106                         writeb(value, adr + (reg & 3));
107                 else
108                         outb((u8)value, 0xCFC + (reg & 3));
109                 break;
110         case 2:
111                 if (xquad_portio)
112                         writew(value, adr + (reg & 2));
113                 else
114                         outw((u16)value, 0xCFC + (reg & 2));
115                 break;
116         case 4:
117                 if (xquad_portio)
118                         writel(value, adr + reg);
119                 else
120                         outl((u32)value, 0xCFC);
121                 break;
122         }
123
124         spin_unlock_irqrestore(&pci_config_lock, flags);
125
126         return 0;
127 }
128
129 #undef PCI_CONF1_MQ_ADDRESS
130
131 static struct pci_raw_ops pci_direct_conf1_mq = {
132         .read   = pci_conf1_mq_read,
133         .write  = pci_conf1_mq_write
134 };
135
136
137 static void __devinit pci_fixup_i450nx(struct pci_dev *d)
138 {
139         /*
140          * i450NX -- Find and scan all secondary buses on all PXB's.
141          */
142         int pxb, reg;
143         u8 busno, suba, subb;
144         int quad = BUS2QUAD(d->bus->number);
145
146         printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
147         reg = 0xd0;
148         for(pxb=0; pxb<2; pxb++) {
149                 pci_read_config_byte(d, reg++, &busno);
150                 pci_read_config_byte(d, reg++, &suba);
151                 pci_read_config_byte(d, reg++, &subb);
152                 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
153                 if (busno) {
154                         /* Bus A */
155                         pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
156                 }
157                 if (suba < subb) {
158                         /* Bus B */
159                         pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
160                 }
161         }
162         pcibios_last_bus = -1;
163 }
164 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
165
166 static int __init pci_numa_init(void)
167 {
168         int quad;
169
170         raw_pci_ops = &pci_direct_conf1_mq;
171
172         if (pcibios_scanned++)
173                 return 0;
174
175         pci_root_bus = pcibios_scan_root(0);
176         if (pci_root_bus)
177                 pci_bus_add_devices(pci_root_bus);
178         if (num_online_nodes() > 1)
179                 for_each_online_node(quad) {
180                         if (quad == 0)
181                                 continue;
182                         printk("Scanning PCI bus %d for quad %d\n", 
183                                 QUADLOCAL2BUS(quad,0), quad);
184                         pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
185                 }
186         return 0;
187 }
188
189 subsys_initcall(pci_numa_init);