]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/x86/pci/common.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / arch / x86 / pci / common.c
CommitLineData
1da177e4
LT
1/*
2 * Low-Level PCI Support for PC
3 *
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5 */
6
7#include <linux/sched.h>
8#include <linux/pci.h>
9#include <linux/ioport.h>
10#include <linux/init.h>
8c4b2cf9 11#include <linux/dmi.h>
5a0e3ad6 12#include <linux/slab.h>
1da177e4
LT
13
14#include <asm/acpi.h>
15#include <asm/segment.h>
16#include <asm/io.h>
17#include <asm/smp.h>
82487711 18#include <asm/pci_x86.h>
1da177e4 19
1da177e4
LT
20unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
21 PCI_PROBE_MMCONF;
22
e3f2baeb 23unsigned int pci_early_dump_regs;
2b290da0 24static int pci_bf_sort;
1da177e4 25int pci_routeirq;
a9322f64 26int noioapicquirk;
41b9eb26
SA
27#ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
28int noioapicreroute = 0;
29#else
9197979b 30int noioapicreroute = 1;
41b9eb26 31#endif
1da177e4 32int pcibios_last_bus = -1;
120bb424 33unsigned long pirq_table_addr;
34struct pci_bus *pci_root_bus;
1da177e4 35struct pci_raw_ops *raw_pci_ops;
b6ce068a
MW
36struct pci_raw_ops *raw_pci_ext_ops;
37
38int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
39 int reg, int len, u32 *val)
40{
beef3129 41 if (domain == 0 && reg < 256 && raw_pci_ops)
b6ce068a
MW
42 return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
43 if (raw_pci_ext_ops)
44 return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
45 return -EINVAL;
46}
47
48int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
49 int reg, int len, u32 val)
50{
beef3129 51 if (domain == 0 && reg < 256 && raw_pci_ops)
b6ce068a
MW
52 return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
53 if (raw_pci_ext_ops)
54 return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
55 return -EINVAL;
56}
1da177e4
LT
57
58static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
59{
b6ce068a 60 return raw_pci_read(pci_domain_nr(bus), bus->number,
a79e4198 61 devfn, where, size, value);
1da177e4
LT
62}
63
64static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
65{
b6ce068a 66 return raw_pci_write(pci_domain_nr(bus), bus->number,
a79e4198 67 devfn, where, size, value);
1da177e4
LT
68}
69
70struct pci_ops pci_root_ops = {
71 .read = pci_read,
72 .write = pci_write,
73};
74
1da177e4
LT
75/*
76 * This interrupt-safe spinlock protects all accesses to PCI
77 * configuration space.
78 */
79DEFINE_SPINLOCK(pci_config_lock);
80
13a6ddb0
YL
81static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
82{
83 pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
84 printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
85 return 0;
86}
87
821508d4 88static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitconst = {
13a6ddb0
YL
89/*
90 * Systems where PCI IO resource ISA alignment can be skipped
91 * when the ISA enable bit in the bridge control is not set
92 */
93 {
94 .callback = can_skip_ioresource_align,
95 .ident = "IBM System x3800",
96 .matches = {
97 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
98 DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
99 },
100 },
101 {
102 .callback = can_skip_ioresource_align,
103 .ident = "IBM System x3850",
104 .matches = {
105 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
106 DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
107 },
108 },
109 {
110 .callback = can_skip_ioresource_align,
111 .ident = "IBM System x3950",
112 .matches = {
113 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
114 DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
115 },
116 },
117 {}
118};
119
120void __init dmi_check_skip_isa_align(void)
121{
122 dmi_check_system(can_skip_pciprobe_dmi_table);
123}
124
bb71ad88
GH
125static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
126{
127 struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
128
129 if (pci_probe & PCI_NOASSIGN_ROMS) {
130 if (rom_r->parent)
131 return;
132 if (rom_r->start) {
133 /* we deal with BIOS assigned ROM later */
134 return;
135 }
136 rom_r->start = rom_r->end = rom_r->flags = 0;
137 }
138}
139
1da177e4
LT
140/*
141 * Called after each bus is probed, but before its children
142 * are examined.
143 */
144
0bb1be3e 145void __devinit pcibios_fixup_bus(struct pci_bus *b)
1da177e4 146{
bb71ad88
GH
147 struct pci_dev *dev;
148
0e94ecd0
YL
149 /* root bus? */
150 if (!b->parent)
151 x86_pci_root_bus_res_quirks(b);
1da177e4 152 pci_read_bridge_bases(b);
bb71ad88
GH
153 list_for_each_entry(dev, &b->devices, bus_list)
154 pcibios_fixup_device_resources(dev);
1da177e4
LT
155}
156
6b4b78fe
MD
157/*
158 * Only use DMI information to set this if nothing was passed
159 * on the kernel command line (which was parsed earlier).
160 */
161
1855256c 162static int __devinit set_bf_sort(const struct dmi_system_id *d)
6b4b78fe
MD
163{
164 if (pci_bf_sort == pci_bf_sort_default) {
165 pci_bf_sort = pci_dmi_bf;
166 printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
167 }
168 return 0;
169}
170
8c4b2cf9
BK
171/*
172 * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
173 */
174#ifdef __i386__
1855256c 175static int __devinit assign_all_busses(const struct dmi_system_id *d)
8c4b2cf9
BK
176{
177 pci_probe |= PCI_ASSIGN_ALL_BUSSES;
178 printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
179 " (pci=assign-busses)\n", d->ident);
180 return 0;
181}
182#endif
183
821508d4 184static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
6b4b78fe 185#ifdef __i386__
8c4b2cf9
BK
186/*
187 * Laptops which need pci=assign-busses to see Cardbus cards
188 */
8c4b2cf9
BK
189 {
190 .callback = assign_all_busses,
191 .ident = "Samsung X20 Laptop",
192 .matches = {
193 DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
194 DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
195 },
196 },
197#endif /* __i386__ */
6b4b78fe
MD
198 {
199 .callback = set_bf_sort,
200 .ident = "Dell PowerEdge 1950",
201 .matches = {
202 DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
203 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
204 },
205 },
206 {
207 .callback = set_bf_sort,
208 .ident = "Dell PowerEdge 1955",
209 .matches = {
210 DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
211 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
212 },
213 },
214 {
215 .callback = set_bf_sort,
216 .ident = "Dell PowerEdge 2900",
217 .matches = {
218 DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
219 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
220 },
221 },
222 {
223 .callback = set_bf_sort,
224 .ident = "Dell PowerEdge 2950",
225 .matches = {
226 DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
227 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
228 },
229 },
f7a9dae7
MD
230 {
231 .callback = set_bf_sort,
232 .ident = "Dell PowerEdge R900",
233 .matches = {
234 DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
235 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
236 },
237 },
f52383d3
AG
238 {
239 .callback = set_bf_sort,
240 .ident = "HP ProLiant BL20p G3",
241 .matches = {
242 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
243 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
244 },
245 },
246 {
247 .callback = set_bf_sort,
248 .ident = "HP ProLiant BL20p G4",
249 .matches = {
250 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
251 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
252 },
253 },
254 {
255 .callback = set_bf_sort,
256 .ident = "HP ProLiant BL30p G1",
257 .matches = {
258 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
259 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
260 },
261 },
262 {
263 .callback = set_bf_sort,
264 .ident = "HP ProLiant BL25p G1",
265 .matches = {
266 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
267 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
268 },
269 },
270 {
271 .callback = set_bf_sort,
272 .ident = "HP ProLiant BL35p G1",
273 .matches = {
274 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
275 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
276 },
277 },
278 {
279 .callback = set_bf_sort,
280 .ident = "HP ProLiant BL45p G1",
281 .matches = {
282 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
283 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
284 },
285 },
286 {
287 .callback = set_bf_sort,
288 .ident = "HP ProLiant BL45p G2",
289 .matches = {
290 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
291 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
292 },
293 },
294 {
295 .callback = set_bf_sort,
296 .ident = "HP ProLiant BL460c G1",
297 .matches = {
298 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
299 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
300 },
301 },
302 {
303 .callback = set_bf_sort,
304 .ident = "HP ProLiant BL465c G1",
305 .matches = {
306 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
307 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
308 },
309 },
310 {
311 .callback = set_bf_sort,
312 .ident = "HP ProLiant BL480c G1",
313 .matches = {
314 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
315 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
316 },
317 },
318 {
319 .callback = set_bf_sort,
320 .ident = "HP ProLiant BL685c G1",
321 .matches = {
322 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
323 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
324 },
325 },
8f8ae1a7
MS
326 {
327 .callback = set_bf_sort,
8d64c781 328 .ident = "HP ProLiant DL360",
8f8ae1a7
MS
329 .matches = {
330 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
8d64c781 331 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"),
8f8ae1a7
MS
332 },
333 },
334 {
335 .callback = set_bf_sort,
8d64c781 336 .ident = "HP ProLiant DL380",
8f8ae1a7
MS
337 .matches = {
338 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
8d64c781 339 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"),
8f8ae1a7
MS
340 },
341 },
5b1ea82f
JL
342#ifdef __i386__
343 {
344 .callback = assign_all_busses,
345 .ident = "Compaq EVO N800c",
346 .matches = {
347 DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
348 DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"),
349 },
350 },
351#endif
c82bc5ad
MS
352 {
353 .callback = set_bf_sort,
739db07f 354 .ident = "HP ProLiant DL385 G2",
c82bc5ad
MS
355 .matches = {
356 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
739db07f 357 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"),
c82bc5ad
MS
358 },
359 },
360 {
361 .callback = set_bf_sort,
739db07f 362 .ident = "HP ProLiant DL585 G2",
c82bc5ad
MS
363 .matches = {
364 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
739db07f 365 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
c82bc5ad
MS
366 },
367 },
8c4b2cf9
BK
368 {}
369};
1da177e4 370
0df18ff3
YL
371void __init dmi_check_pciprobe(void)
372{
373 dmi_check_system(pciprobe_dmi_table);
374}
375
1da177e4
LT
376struct pci_bus * __devinit pcibios_scan_root(int busnum)
377{
378 struct pci_bus *bus = NULL;
08f1c192 379 struct pci_sysdata *sd;
1da177e4
LT
380
381 while ((bus = pci_find_next_bus(bus)) != NULL) {
382 if (bus->number == busnum) {
383 /* Already scanned */
384 return bus;
385 }
386 }
387
08f1c192
MBY
388 /* Allocate per-root-bus (not per bus) arch-specific data.
389 * TODO: leak; this memory is never freed.
390 * It's arguable whether it's worth the trouble to care.
391 */
392 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
393 if (!sd) {
394 printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
395 return NULL;
396 }
397
871d5f8d
YL
398 sd->node = get_mp_bus_to_node(busnum);
399