Merge tag 'v3.10.107' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / x86 / pci / acpi.c
CommitLineData
1da177e4
LT
1#include <linux/pci.h>
2#include <linux/acpi.h>
3#include <linux/init.h>
b33fa1f3 4#include <linux/irq.h>
036fff4c 5#include <linux/dmi.h>
5a0e3ad6 6#include <linux/slab.h>
69e1a33f 7#include <asm/numa.h>
82487711 8#include <asm/pci_x86.h>
1da177e4 9
62f420f8 10struct pci_root_info {
42887b29 11 struct acpi_device *bridge;
fe05725f 12 char name[16];
62f420f8
GH
13 unsigned int res_num;
14 struct resource *res;
b4873931 15 resource_size_t *res_offset;
35cb05e5 16 struct pci_sysdata sd;
c0fa4078
JL
17#ifdef CONFIG_PCI_MMCONFIG
18 bool mcfg_added;
19 u16 segment;
20 u8 start_bus;
21 u8 end_bus;
22#endif
62f420f8
GH
23};
24
7bc5e3f2 25static bool pci_use_crs = true;
1f09b09b 26static bool pci_ignore_seg = false;
7bc5e3f2
BH
27
28static int __init set_use_crs(const struct dmi_system_id *id)
29{
30 pci_use_crs = true;
31 return 0;
32}
33
28c3c05d
DJ
34static int __init set_nouse_crs(const struct dmi_system_id *id)
35{
36 pci_use_crs = false;
37 return 0;
38}
39
1f09b09b
BH
40static int __init set_ignore_seg(const struct dmi_system_id *id)
41{
42 printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
43 pci_ignore_seg = true;
44 return 0;
45}
46
47static const struct dmi_system_id pci_crs_quirks[] __initconst = {
7bc5e3f2
BH
48 /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
49 {
50 .callback = set_use_crs,
51 .ident = "IBM System x3800",
52 .matches = {
53 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
54 DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
55 },
56 },
2491762c
BH
57 /* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */
58 /* 2006 AMD HT/VIA system with two host bridges */
59 {
60 .callback = set_use_crs,
61 .ident = "ASRock ALiveSATA2-GLAN",
62 .matches = {
63 DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"),
64 },
65 },
29cf7a30
PM
66 /* https://bugzilla.kernel.org/show_bug.cgi?id=30552 */
67 /* 2006 AMD HT/VIA system with two host bridges */
68 {
69 .callback = set_use_crs,
70 .ident = "ASUS M2V-MX SE",
71 .matches = {
72 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
73 DMI_MATCH(DMI_BOARD_NAME, "M2V-MX SE"),
74 DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
75 },
76 },
84113717
JN
77 /* https://bugzilla.kernel.org/show_bug.cgi?id=42619 */
78 {
79 .callback = set_use_crs,
80 .ident = "MSI MS-7253",
81 .matches = {
82 DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
83 DMI_MATCH(DMI_BOARD_NAME, "MS-7253"),
84 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
84113717
JN
85 },
86 },
dc86cafe
BH
87 /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/931368 */
88 /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1033299 */
89 {
90 .callback = set_use_crs,
91 .ident = "Foxconn K8M890-8237A",
92 .matches = {
93 DMI_MATCH(DMI_BOARD_VENDOR, "Foxconn"),
94 DMI_MATCH(DMI_BOARD_NAME, "K8M890-8237A"),
95 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
96 },
97 },
28c3c05d 98
e702781f
DJ
99 /* Now for the blacklist.. */
100
101 /* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
102 {
103 .callback = set_nouse_crs,
104 .ident = "Dell Studio 1557",
105 .matches = {
106 DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."),
107 DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"),
108 DMI_MATCH(DMI_BIOS_VERSION, "A09"),
109 },
110 },
8b6a5af9
DJ
111 /* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
112 {
113 .callback = set_nouse_crs,
114 .ident = "Thinkpad SL510",
115 .matches = {
116 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
117 DMI_MATCH(DMI_BOARD_NAME, "2847DFG"),
118 DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
119 },
120 },
369ca806
BH
121 /* https://bugzilla.kernel.org/show_bug.cgi?id=42606 */
122 {
123 .callback = set_nouse_crs,
124 .ident = "Supermicro X8DTH",
125 .matches = {
126 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
127 DMI_MATCH(DMI_PRODUCT_NAME, "X8DTH-i/6/iF/6F"),
128 DMI_MATCH(DMI_BIOS_VERSION, "2.0a"),
129 },
130 },
1f09b09b
BH
131
132 /* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
133 {
134 .callback = set_ignore_seg,
135 .ident = "HP xw9300",
136 .matches = {
137 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
138 DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
139 },
140 },
7bc5e3f2
BH
141 {}
142};
143
144void __init pci_acpi_crs_quirks(void)
145{
146 int year;
147
148 if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
149 pci_use_crs = false;
150
1f09b09b 151 dmi_check_system(pci_crs_quirks);
7bc5e3f2
BH
152
153 /*
154 * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
155 * takes precedence over anything we figured out above.
156 */
157 if (pci_probe & PCI_ROOT_NO_CRS)
158 pci_use_crs = false;
159 else if (pci_probe & PCI_USE__CRS)
160 pci_use_crs = true;
161
162 printk(KERN_INFO "PCI: %s host bridge windows from ACPI; "
163 "if necessary, use \"pci=%s\" and report a bug\n",
164 pci_use_crs ? "Using" : "Ignoring",
165 pci_use_crs ? "nocrs" : "use_crs");
166}
167
c0fa4078 168#ifdef CONFIG_PCI_MMCONFIG
a18e3690 169static int check_segment(u16 seg, struct device *dev, char *estr)
c0fa4078
JL
170{
171 if (seg) {
172 dev_err(dev,
173 "%s can't access PCI configuration "
174 "space under this host bridge.\n",
175 estr);
176 return -EIO;
177 }
178
179 /*
180 * Failure in adding MMCFG information is not fatal,
181 * just can't access extended configuration space of
182 * devices under this host bridge.
183 */
184 dev_warn(dev,
185 "%s can't access extended PCI configuration "
186 "space under this bridge.\n",
187 estr);
188
189 return 0;
190}
191
a18e3690
GKH
192static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
193 u8 end, phys_addr_t addr)
c0fa4078
JL
194{
195 int result;
196 struct device *dev = &info->bridge->dev;
197
198 info->start_bus = start;
199 info->end_bus = end;
200 info->mcfg_added = false;
201
202 /* return success if MMCFG is not in use */
203 if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
204 return 0;
205
206 if (!(pci_probe & PCI_PROBE_MMCONF))
207 return check_segment(seg, dev, "MMCONFIG is disabled,");
208
209 result = pci_mmconfig_insert(dev, seg, start, end, addr);
210 if (result == 0) {
211 /* enable MMCFG if it hasn't been enabled yet */
212 if (raw_pci_ext_ops == NULL)
213 raw_pci_ext_ops = &pci_mmcfg;
214 info->mcfg_added = true;
215 } else if (result != -EEXIST)
216 return check_segment(seg, dev,
217 "fail to add MMCONFIG information,");
218
219 return 0;
220}
221
222static void teardown_mcfg_map(struct pci_root_info *info)
223{
224 if (info->mcfg_added) {
225 pci_mmconfig_delete(info->segment, info->start_bus,
226 info->end_bus);
227 info->mcfg_added = false;
228 }
229}
230#else
a18e3690 231static int setup_mcfg_map(struct pci_root_info *info,
c0fa4078
JL
232 u16 seg, u8 start, u8 end,
233 phys_addr_t addr)
234{
235 return 0;
236}
237static void teardown_mcfg_map(struct pci_root_info *info)
238{
239}
240#endif
241
62f420f8
GH
242static acpi_status
243resource_to_addr(struct acpi_resource *resource,
244 struct acpi_resource_address64 *addr)
245{
246 acpi_status status;
66528fdd
BH
247 struct acpi_resource_memory24 *memory24;
248 struct acpi_resource_memory32 *memory32;
249 struct acpi_resource_fixed_memory32 *fixed_memory32;
62f420f8 250
66528fdd
BH
251 memset(addr, 0, sizeof(*addr));
252 switch (resource->type) {
253 case ACPI_RESOURCE_TYPE_MEMORY24:
254 memory24 = &resource->data.memory24;
255 addr->resource_type = ACPI_MEMORY_RANGE;
256 addr->minimum = memory24->minimum;
257 addr->address_length = memory24->address_length;
258 addr->maximum = addr->minimum + addr->address_length - 1;
62f420f8 259 return AE_OK;
66528fdd
BH
260 case ACPI_RESOURCE_TYPE_MEMORY32:
261 memory32 = &resource->data.memory32;
262 addr->resource_type = ACPI_MEMORY_RANGE;
263 addr->minimum = memory32->minimum;
264 addr->address_length = memory32->address_length;
265 addr->maximum = addr->minimum + addr->address_length - 1;
266 return AE_OK;
267 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
268 fixed_memory32 = &resource->data.fixed_memory32;
269 addr->resource_type = ACPI_MEMORY_RANGE;
270 addr->minimum = fixed_memory32->address;
271 addr->address_length = fixed_memory32->address_length;
272 addr->maximum = addr->minimum + addr->address_length - 1;
273 return AE_OK;
274 case ACPI_RESOURCE_TYPE_ADDRESS16:
275 case ACPI_RESOURCE_TYPE_ADDRESS32:
276 case ACPI_RESOURCE_TYPE_ADDRESS64:
277 status = acpi_resource_to_address64(resource, addr);
278 if (ACPI_SUCCESS(status) &&
279 (addr->resource_type == ACPI_MEMORY_RANGE ||
280 addr->resource_type == ACPI_IO_RANGE) &&
281 addr->address_length > 0) {
282 return AE_OK;
283 }
284 break;
62f420f8
GH
285 }
286 return AE_ERROR;
287}
288
289static acpi_status
290count_resource(struct acpi_resource *acpi_res, void *data)
291{
292 struct pci_root_info *info = data;
293 struct acpi_resource_address64 addr;
294 acpi_status status;
295
296 status = resource_to_addr(acpi_res, &addr);
297 if (ACPI_SUCCESS(status))
298 info->res_num++;
299 return AE_OK;
300}
301
302static acpi_status
303setup_resource(struct acpi_resource *acpi_res, void *data)
304{
305 struct pci_root_info *info = data;
306 struct resource *res;
307 struct acpi_resource_address64 addr;
308 acpi_status status;
309 unsigned long flags;
ae5cd864 310 u64 start, orig_end, end;
2cdb3f1d 311
62f420f8
GH
312 status = resource_to_addr(acpi_res, &addr);
313 if (!ACPI_SUCCESS(status))
314 return AE_OK;
315
316 if (addr.resource_type == ACPI_MEMORY_RANGE) {
62f420f8
GH
317 flags = IORESOURCE_MEM;
318 if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
319 flags |= IORESOURCE_PREFETCH;
320 } else if (addr.resource_type == ACPI_IO_RANGE) {
62f420f8
GH
321 flags = IORESOURCE_IO;
322 } else
323 return AE_OK;
324
2cdb3f1d 325 start = addr.minimum + addr.translation_offset;
ae5cd864
GH
326 orig_end = end = addr.maximum + addr.translation_offset;
327
328 /* Exclude non-addressable range or non-addressable portion of range */
329 end = min(end, (u64)iomem_resource.end);
330 if (end <= start) {
331 dev_info(&info->bridge->dev,
332 "host bridge window [%#llx-%#llx] "
333 "(ignored, not CPU addressable)\n", start, orig_end);
334 return AE_OK;
335 } else if (orig_end != end) {
336 dev_info(&info->bridge->dev,
337 "host bridge window [%#llx-%#llx] "
338 "([%#llx-%#llx] ignored, not CPU addressable)\n",
339 start, orig_end, end + 1, orig_end);
340 }
f9cde5ff 341
2cdb3f1d
YL
342 res = &info->res[info->res_num];
343 res->name = info->name;
344 res->flags = flags;
345 res->start = start;
346 res->end = end;
b4873931 347 info->res_offset[info->res_num] = addr.translation_offset;
2cdb3f1d 348
7bc5e3f2 349 if (!pci_use_crs) {
f1db6fde
BH
350 dev_printk(KERN_DEBUG, &info->bridge->dev,
351 "host bridge window %pR (ignored)\n", res);
352 return AE_OK;
353 }
354
4723d0f2 355 info->res_num++;
4723d0f2
BH
356
357 return AE_OK;
358}
359
6e33a852 360static void coalesce_windows(struct pci_root_info *info, unsigned long type)
4723d0f2
BH
361{
362 int i, j;
363 struct resource *res1, *res2;
364
365 for (i = 0; i < info->res_num; i++) {
366 res1 = &info->res[i];
367 if (!(res1->flags & type))
368 continue;
369
370 for (j = i + 1; j < info->res_num; j++) {
371 res2 = &info->res[j];
372 if (!(res2->flags & type))
373 continue;
374
375 /*
376 * I don't like throwing away windows because then
377 * our resources no longer match the ACPI _CRS, but
378 * the kernel resource tree doesn't allow overlaps.
379 */
74d24b21 380 if (resource_overlaps(res1, res2)) {
4723d0f2
BH
381 res1->start = min(res1->start, res2->start);
382 res1->end = max(res1->end, res2->end);
383 dev_info(&info->bridge->dev,
384 "host bridge window expanded to %pR; %pR ignored\n",
385 res1, res2);
386 res2->flags = 0;
387 }
388 }
389 }
390}
391
9a03d28d
YL
392static void add_resources(struct pci_root_info *info,
393 struct list_head *resources)
4723d0f2
BH
394{
395 int i;
396 struct resource *res, *root, *conflict;
397
4723d0f2
BH
398 coalesce_windows(info, IORESOURCE_MEM);
399 coalesce_windows(info, IORESOURCE_IO);
400
401 for (i = 0; i < info->res_num; i++) {
402 res = &info->res[i];
403
404 if (res->flags & IORESOURCE_MEM)
405 root = &iomem_resource;
406 else if (res->flags & IORESOURCE_IO)
407 root = &ioport_resource;
42887b29 408 else
4723d0f2
BH
409 continue;
410
411 conflict = insert_resource_conflict(root, res);
412 if (conflict)
43d786ed
BH
413 dev_info(&info->bridge->dev,
414 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
415 res, conflict->name, conflict);
4723d0f2 416 else
b4873931
MY
417 pci_add_resource_offset(resources, res,
418 info->res_offset[i]);
62f420f8 419 }
62f420f8
GH
420}
421
fd3b0c1e 422static void free_pci_root_info_res(struct pci_root_info *info)
baa495d9 423{
baa495d9 424 kfree(info->res);
fd3b0c1e 425 info->res = NULL;
b4873931
MY
426 kfree(info->res_offset);
427 info->res_offset = NULL;
fd3b0c1e
YL
428 info->res_num = 0;
429}
430
431static void __release_pci_root_info(struct pci_root_info *info)
432{
433 int i;
434 struct resource *res;
435
436 for (i = 0; i < info->res_num; i++) {
437 res = &info->res[i];
438
439 if (!res->parent)
440 continue;
441
442 if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
443 continue;
444
445 release_resource(res);
446 }
447
448 free_pci_root_info_res(info);
449
c0fa4078
JL
450 teardown_mcfg_map(info);
451
fd3b0c1e
YL
452 kfree(info);
453}
c0fa4078 454
fd3b0c1e
YL
455static void release_pci_root_info(struct pci_host_bridge *bridge)
456{
457 struct pci_root_info *info = bridge->release_data;
458
459 __release_pci_root_info(info);
baa495d9
YL
460}
461
62f420f8 462static void
9a03d28d
YL
463probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
464 int busnum, int domain)
62f420f8 465{
62f420f8
GH
466 size_t size;
467
5c1d81d1 468 sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
baa495d9 469 info->bridge = device;
5c1d81d1 470
baa495d9 471 info->res_num = 0;
62f420f8 472 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
baa495d9
YL
473 info);
474 if (!info->res_num)
62f420f8
GH
475 return;
476
baa495d9 477 size = sizeof(*info->res) * info->res_num;
4cd8daf0 478 info->res = kzalloc(size, GFP_KERNEL);
b4873931
MY
479 if (!info->res) {
480 info->res_num = 0;
481 return;
482 }
483
484 size = sizeof(*info->res_offset) * info->res_num;
485 info->res_num = 0;
486 info->res_offset = kzalloc(size, GFP_KERNEL);
487 if (!info->res_offset) {
488 kfree(info->res);
489 info->res = NULL;
2cd6975a 490 return;
b4873931 491 }
62f420f8 492
62f420f8 493 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
baa495d9 494 info);
62f420f8
GH
495}
496
a18e3690 497struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
1da177e4 498{
57283776 499 struct acpi_device *device = root->device;
fd3b0c1e 500 struct pci_root_info *info = NULL;
57283776
BH
501 int domain = root->segment;
502 int busnum = root->secondary.start;
2cd6975a 503 LIST_HEAD(resources);
c0fa4078 504 struct pci_bus *bus = NULL;
08f1c192 505 struct pci_sysdata *sd;
871d5f8d
YL
506 int node;
507#ifdef CONFIG_ACPI_NUMA
08f1c192 508 int pxm;
871d5f8d 509#endif
08f1c192 510
1f09b09b
BH
511 if (pci_ignore_seg)
512 domain = 0;
513
a79e4198 514 if (domain && !pci_domains_supported) {
2a6bed83
BH
515 printk(KERN_WARNING "pci_bus %04x:%02x: "
516 "ignored (multiple domains not supported)\n",
517 domain, busnum);
a79e4198
JG
518 return NULL;
519 }
520
871d5f8d
YL
521 node = -1;
522#ifdef CONFIG_ACPI_NUMA
523 pxm = acpi_get_pxm(device->handle);
524 if (pxm >= 0)
525 node = pxm_to_node(pxm);
526 if (node != -1)
527 set_mp_bus_to_node(busnum, node);
528 else
871d5f8d 529#endif
871d5f8d 530 node = get_mp_bus_to_node(busnum);
b755de8d
YL
531
532 if (node != -1 && !node_online(node))
533 node = -1;
871d5f8d 534
35cb05e5
YL
535 info = kzalloc(sizeof(*info), GFP_KERNEL);
536 if (!info) {
2a6bed83
BH
537 printk(KERN_WARNING "pci_bus %04x:%02x: "
538 "ignored (out of memory)\n", domain, busnum);
08f1c192
MBY
539 return NULL;
540 }
69e1a33f 541
35cb05e5 542 sd = &info->sd;
a79e4198 543 sd->domain = domain;
871d5f8d 544 sd->node = node;
6c0cc950 545 sd->acpi = device->handle;
b87e81e5 546 /*
547 * Maybe the desired pci bus has been already scanned. In such case
548 * it is unnecessary to scan the pci bus with the given domain,busnum.
549 */
550 bus = pci_find_bus(domain, busnum);
551 if (bus) {
552 /*
553 * If the desired bus exits, the content of bus->sysdata will
554 * be replaced by sd.
555 */
556 memcpy(bus->sysdata, sd, sizeof(*sd));
fd3b0c1e 557 kfree(info);
626fdfec 558 } else {
fd3b0c1e 559 probe_pci_root_info(info, device, busnum, domain);
316d86fe 560
5c1d81d1
YL
561 /* insert busn res at first */
562 pci_add_resource(&resources, &root->secondary);
316d86fe
BH
563 /*
564 * _CRS with no apertures is normal, so only fall back to
565 * defaults or native bridge info if we're ignoring _CRS.
566 */
9a03d28d 567 if (pci_use_crs)
fd3b0c1e 568 add_resources(info, &resources);
9a03d28d 569 else {
fd3b0c1e 570 free_pci_root_info_res(info);
2cd6975a 571 x86_pci_root_bus_resources(busnum, &resources);
9a03d28d 572 }
fd3b0c1e 573
c0fa4078
JL
574 if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
575 (u8)root->secondary.end, root->mcfg_addr))
576 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
577 sd, &resources);
578
fd3b0c1e 579 if (bus) {
5c1d81d1 580 pci_scan_child_bus(bus);
fd3b0c1e
YL
581 pci_set_host_bridge_release(
582 to_pci_host_bridge(bus->bridge),
583 release_pci_root_info, info);
584 } else {
2cd6975a 585 pci_free_resource_list(&resources);
fd3b0c1e
YL
586 __release_pci_root_info(info);
587 }
626fdfec 588 }
08f1c192 589
b03e7495
JM
590 /* After the PCI-E bus has been walked and all devices discovered,
591 * configure any settings of the fabric that might be necessary.
592 */
593 if (bus) {
594 struct pci_bus *child;
5307f6d5
SI
595 list_for_each_entry(child, &bus->children, node) {
596 struct pci_dev *self = child->self;
597 if (!self)
598 continue;
599
600 pcie_bus_configure_settings(child, self->pcie_mpss);
601 }
b03e7495
JM
602 }
603
dbb6152e 604 if (bus && node != -1) {
69e1a33f 605#ifdef CONFIG_ACPI_NUMA
dbb6152e 606 if (pxm >= 0)
2b8c2efe
BH
607 dev_printk(KERN_DEBUG, &bus->dev,
608 "on NUMA node %d (pxm %d)\n", node, pxm);
dbb6152e 609#else
2b8c2efe 610 dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
69e1a33f 611#endif
dbb6152e 612 }
62f420f8 613
69e1a33f 614 return bus;
1da177e4
LT
615}
616
6c0cc950
RW
617int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
618{
619 struct pci_sysdata *sd = bridge->bus->sysdata;
620
621 ACPI_HANDLE_SET(&bridge->dev, sd->acpi);
622 return 0;
623}
624
8dd779b1 625int __init pci_acpi_init(void)
1da177e4
LT
626{
627 struct pci_dev *dev = NULL;
628
1da177e4 629 if (acpi_noirq)
b72d0db9 630 return -ENODEV;
1da177e4
LT
631
632 printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
633 acpi_irq_penalty_init();
1da177e4 634 pcibios_enable_irq = acpi_pci_irq_enable;
87bec66b 635 pcibios_disable_irq = acpi_pci_irq_disable;
ab3b3793 636 x86_init.pci.init_irq = x86_init_noop;
1da177e4
LT
637
638 if (pci_routeirq) {
639 /*
640 * PCI IRQ routing is set up by pci_enable_device(), but we
641 * also do it here in case there are still broken drivers that
642 * don't use pci_enable_device().
643 */
644 printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
fb37fb96 645 for_each_pci_dev(dev)
1da177e4 646 acpi_pci_irq_enable(dev);
657472e9 647 }
1da177e4 648
1da177e4
LT
649 return 0;
650}