1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/sysdev.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/types.h>
37#include <linux/proc_fs.h>
38#include <linux/spinlock.h>
39#include <linux/pm.h>
40#include <linux/pci.h>
41#include <linux/mutex.h>
42
43#include <acpi/acpi_bus.h>
44#include <acpi/acpi_drivers.h>
45
46#define _COMPONENT ACPI_PCI_COMPONENT
47ACPI_MODULE_NAME("pci_link");
48#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
49#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
50#define ACPI_PCI_LINK_FILE_INFO "info"
51#define ACPI_PCI_LINK_FILE_STATUS "state"
52#define ACPI_PCI_LINK_MAX_POSSIBLE 16
53
54static int acpi_pci_link_add(struct acpi_device *device);
55static int acpi_pci_link_remove(struct acpi_device *device, int type);
56
57static struct acpi_device_id link_device_ids[] = {
58 {"PNP0C0F", 0},
59 {"", 0},
60};
61MODULE_DEVICE_TABLE(acpi, link_device_ids);
62
63static struct acpi_driver acpi_pci_link_driver = {
64 .name = "pci_link",
65 .class = ACPI_PCI_LINK_CLASS,
66 .ids = link_device_ids,
67 .ops = {
68 .add = acpi_pci_link_add,
69 .remove = acpi_pci_link_remove,
70 },
71};
72
73
74
75
76
77struct acpi_pci_link_irq {
78 u8 active;
79 u8 triggering;
80 u8 polarity;
81 u8 resource_type;
82 u8 possible_count;
83 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
84 u8 initialized:1;
85 u8 reserved:7;
86};
87
88struct acpi_pci_link {
89 struct list_head list;
90 struct acpi_device *device;
91 struct acpi_pci_link_irq irq;
92 int refcnt;
93};
94
95static LIST_HEAD(acpi_link_list);
96static DEFINE_MUTEX(acpi_link_lock);
97
98
99
100
101
102
103
104
105static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
106 void *context)
107{
108 struct acpi_pci_link *link = context;
109 u32 i;
110
111 switch (resource->type) {
112 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
113 case ACPI_RESOURCE_TYPE_END_TAG:
114 return AE_OK;
115 case ACPI_RESOURCE_TYPE_IRQ:
116 {
117 struct acpi_resource_irq *p = &resource->data.irq;
118 if (!p || !p->interrupt_count) {
119 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
120 "Blank _PRS IRQ resource\n"));
121 return AE_OK;
122 }
123 for (i = 0;
124 (i < p->interrupt_count
125 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
126 if (!p->interrupts[i]) {
127 printk(KERN_WARNING PREFIX
128 "Invalid _PRS IRQ %d\n",
129 p->interrupts[i]);
130 continue;
131 }
132 link->irq.possible[i] = p->interrupts[i];
133 link->irq.possible_count++;
134 }
135 link->irq.triggering = p->triggering;
136 link->irq.polarity = p->polarity;
137 link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ;
138 break;
139 }
140 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
141 {
142 struct acpi_resource_extended_irq *p =
143 &resource->data.extended_irq;
144 if (!p || !p->interrupt_count) {
145 printk(KERN_WARNING PREFIX
146 "Blank _PRS EXT IRQ resource\n");
147 return AE_OK;
148 }
149 for (i = 0;
150 (i < p->interrupt_count
151 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
152 if (!p->interrupts[i]) {
153 printk(KERN_WARNING PREFIX
154 "Invalid _PRS IRQ %d\n",
155 p->interrupts[i]);
156 continue;
157 }
158 link->irq.possible[i] = p->interrupts[i];
159 link->irq.possible_count++;
160 }
161 link->irq.triggering = p->triggering;
162 link->irq.polarity = p->polarity;
163 link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
164 break;
165 }
166 default:
167 printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n",
168 resource->type);
169 return AE_OK;
170 }
171
172 return AE_CTRL_TERMINATE;
173}
174
175static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
176{
177 acpi_status status;
178
179 status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS,
180 acpi_pci_link_check_possible, link);
181 if (ACPI_FAILURE(status)) {
182 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRS"));
183 return -ENODEV;
184 }
185
186 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
187 "Found %d possible IRQs\n",
188 link->irq.possible_count));
189
190 return 0;
191}
192
193static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
194 void *context)
195{
196 int *irq = context;
197
198 switch (resource->type) {
199 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
200 case ACPI_RESOURCE_TYPE_END_TAG:
201 return AE_OK;
202 case ACPI_RESOURCE_TYPE_IRQ:
203 {
204 struct acpi_resource_irq *p = &resource->data.irq;
205 if (!p || !p->interrupt_count) {
206
207
208
209
210 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
211 "Blank _CRS IRQ resource\n"));
212 return AE_OK;
213 }
214 *irq = p->interrupts[0];
215 break;
216 }
217 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
218 {
219 struct acpi_resource_extended_irq *p =
220 &resource->data.extended_irq;
221 if (!p || !p->interrupt_count) {
222
223
224
225
226 printk(KERN_WARNING PREFIX
227 "Blank _CRS EXT IRQ resource\n");
228 return AE_OK;
229 }
230 *irq = p->interrupts[0];
231 break;
232 }
233 break;
234 default:
235 printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n",
236 resource->type);
237 return AE_OK;
238 }
239
240 return AE_CTRL_TERMINATE;
241}
242
243
244
245
246
247
248
249
250static int acpi_pci_link_get_current(struct acpi_pci_link *link)
251{
252 int result = 0;
253 acpi_status status;
254 int irq = 0;
255
256 link->irq.active = 0;
257
258
259 if (acpi_strict) {
260
261 result = acpi_bus_get_status(link->device);
262 if (result) {
263 printk(KERN_ERR PREFIX "Unable to read status\n");
264 goto end;
265 }
266
267 if (!link->device->status.enabled) {
268 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
269 return 0;
270 }
271 }
272
273
274
275
276
277 status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
278 acpi_pci_link_check_current, &irq);
279 if (ACPI_FAILURE(status)) {
280 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _CRS"));
281 result = -ENODEV;
282 goto end;
283 }
284
285 if (acpi_strict && !irq) {
286 printk(KERN_ERR PREFIX "_CRS returned 0\n");
287 result = -ENODEV;
288 }
289
290 link->irq.active = irq;
291
292 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
293
294 end:
295 return result;
296}
297
298static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
299{
300 int result;
301 acpi_status status;
302 struct {
303 struct acpi_resource res;
304 struct acpi_resource end;
305 } *resource;
306 struct acpi_buffer buffer = { 0, NULL };
307
308 if (!irq)
309 return -EINVAL;
310
311 resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
312 if (!resource)
313 return -ENOMEM;
314
315 buffer.length = sizeof(*resource) + 1;
316 buffer.pointer = resource;
317
318 switch (link->irq.resource_type) {
319 case ACPI_RESOURCE_TYPE_IRQ:
320 resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
321 resource->res.length = sizeof(struct acpi_resource);
322 resource->res.data.irq.triggering = link->irq.triggering;
323 resource->res.data.irq.polarity =
324 link->irq.polarity;
325 if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
326 resource->res.data.irq.sharable =
327 ACPI_EXCLUSIVE;
328 else
329 resource->res.data.irq.sharable = ACPI_SHARED;
330 resource->res.data.irq.interrupt_count = 1;
331 resource->res.data.irq.interrupts[0] = irq;
332 break;
333
334 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
335 resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
336 resource->res.length = sizeof(struct acpi_resource);
337 resource->res.data.extended_irq.producer_consumer =
338 ACPI_CONSUMER;
339 resource->res.data.extended_irq.triggering =
340 link->irq.triggering;
341 resource->res.data.extended_irq.polarity =
342 link->irq.polarity;
343 if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
344 resource->res.data.irq.sharable =
345 ACPI_EXCLUSIVE;
346 else
347 resource->res.data.irq.sharable = ACPI_SHARED;
348 resource->res.data.extended_irq.interrupt_count = 1;
349 resource->res.data.extended_irq.interrupts[0] = irq;
350
351 break;
352 default:
353 printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
354 result = -EINVAL;
355 goto end;
356
357 }
358 resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
359
360
361 status = acpi_set_current_resources(link->device->handle, &buffer);
362
363
364 if (ACPI_FAILURE(status)) {
365 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SRS"));
366 result = -ENODEV;
367 goto end;
368 }
369
370
371 result = acpi_bus_get_status(link->device);
372 if (result) {
373 printk(KERN_ERR PREFIX "Unable to read status\n");
374 goto end;
375 }
376 if (!link->device->status.enabled) {
377 printk(KERN_WARNING PREFIX
378 "%s [%s] disabled and referenced, BIOS bug\n",
379 acpi_device_name(link->device),
380 acpi_device_bid(link->device));
381 }
382
383
384 result = acpi_pci_link_get_current(link);
385 if (result) {
386 goto end;
387 }
388
389
390
391
392
393 if (link->irq.active != irq) {
394
395
396
397
398 printk(KERN_WARNING PREFIX
399 "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
400 acpi_device_name(link->device),
401 acpi_device_bid(link->device), link->irq.active, irq);
402 link->irq.active = irq;
403 }
404
405 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
406
407 end:
408 kfree(resource);
409 return result;
410}
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447#define ACPI_MAX_IRQS 256
448#define ACPI_MAX_ISA_IRQ 16
449
450#define PIRQ_PENALTY_PCI_AVAILABLE (0)
451#define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
452#define PIRQ_PENALTY_PCI_USING (16*16*16)
453#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
454#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
455#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
456
457static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
458 PIRQ_PENALTY_ISA_ALWAYS,
459 PIRQ_PENALTY_ISA_ALWAYS,
460 PIRQ_PENALTY_ISA_ALWAYS,
461 PIRQ_PENALTY_ISA_TYPICAL,
462 PIRQ_PENALTY_ISA_TYPICAL,
463 PIRQ_PENALTY_ISA_TYPICAL,
464 PIRQ_PENALTY_ISA_TYPICAL,
465 PIRQ_PENALTY_ISA_TYPICAL,
466 PIRQ_PENALTY_ISA_TYPICAL,
467 PIRQ_PENALTY_PCI_AVAILABLE,
468 PIRQ_PENALTY_PCI_AVAILABLE,
469 PIRQ_PENALTY_PCI_AVAILABLE,
470 PIRQ_PENALTY_ISA_USED,
471 PIRQ_PENALTY_ISA_USED,
472 PIRQ_PENALTY_ISA_USED,
473 PIRQ_PENALTY_ISA_USED,
474
475};
476
477int __init acpi_irq_penalty_init(void)
478{
479 struct acpi_pci_link *link;
480 int i;
481
482
483
484
485 list_for_each_entry(link, &acpi_link_list, list) {
486
487
488
489
490
491 if (link->irq.possible_count) {
492 int penalty =
493 PIRQ_PENALTY_PCI_POSSIBLE /
494 link->irq.possible_count;
495
496 for (i = 0; i < link->irq.possible_count; i++) {
497 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
498 acpi_irq_penalty[link->irq.
499 possible[i]] +=
500 penalty;
501 }
502
503 } else if (link->irq.active) {
504 acpi_irq_penalty[link->irq.active] +=
505 PIRQ_PENALTY_PCI_POSSIBLE;
506 }
507 }
508
509 acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING;
510 return 0;
511}
512
513static int acpi_irq_balance = -1;
514
515static int acpi_pci_link_allocate(struct acpi_pci_link *link)
516{
517 int irq;
518 int i;
519
520 if (link->irq.initialized) {
521 if (link->refcnt == 0)
522
523 acpi_pci_link_set(link, link->irq.active);
524 return 0;
525 }
526
527
528
529
530 for (i = 0; i < link->irq.possible_count; ++i) {
531 if (link->irq.active == link->irq.possible[i])
532 break;
533 }
534
535
536
537 if (i == link->irq.possible_count) {
538 if (acpi_strict)
539 printk(KERN_WARNING PREFIX "_CRS %d not found"
540 " in _PRS\n", link->irq.active);
541 link->irq.active = 0;
542 }
543
544
545
546
547 if (link->irq.active)
548 irq = link->irq.active;
549 else
550 irq = link->irq.possible[link->irq.possible_count - 1];
551
552 if (acpi_irq_balance || !link->irq.active) {
553
554
555
556
557 for (i = (link->irq.possible_count - 1); i >= 0; i--) {
558 if (acpi_irq_penalty[irq] >
559 acpi_irq_penalty[link->irq.possible[i]])
560 irq = link->irq.possible[i];
561 }
562 }
563
564
565 if (acpi_pci_link_set(link, irq)) {
566 printk(KERN_ERR PREFIX "Unable to set IRQ for %s [%s]. "
567 "Try pci=noacpi or acpi=off\n",
568 acpi_device_name(link->device),
569 acpi_device_bid(link->device));
570 return -ENODEV;
571 } else {
572 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
573 printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
574 acpi_device_name(link->device),
575 acpi_device_bid(link->device), link->irq.active);
576 }
577
578 link->irq.initialized = 1;
579 return 0;
580}
581
582
583
584
585
586
587int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
588 int *polarity, char **name)
589{
590 int result;
591 struct acpi_device *device;
592 struct acpi_pci_link *link;
593
594 result = acpi_bus_get_device(handle, &device);
595 if (result) {
596 printk(KERN_ERR PREFIX "Invalid link device\n");
597 return -1;
598 }
599
600 link = acpi_driver_data(device);
601 if (!link) {
602 printk(KERN_ERR PREFIX "Invalid link context\n");
603 return -1;
604 }
605
606
607 if (index) {
608 printk(KERN_ERR PREFIX "Invalid index %d\n", index);
609 return -1;
610 }
611
612 mutex_lock(&acpi_link_lock);
613 if (acpi_pci_link_allocate(link)) {
614 mutex_unlock(&acpi_link_lock);
615 return -1;
616 }
617
618 if (!link->irq.active) {
619 mutex_unlock(&acpi_link_lock);
620 printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
621 return -1;
622 }
623 link->refcnt++;
624 mutex_unlock(&acpi_link_lock);
625
626 if (triggering)
627 *triggering = link->irq.triggering;
628 if (polarity)
629 *polarity = link->irq.polarity;
630 if (name)
631 *name = acpi_device_bid(link->device);
632 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
633 "Link %s is referenced\n",
634 acpi_device_bid(link->device)));
635 return (link->irq.active);
636}
637
638
639
640
641
642int acpi_pci_link_free_irq(acpi_handle handle)
643{
644 struct acpi_device *device;
645 struct acpi_pci_link *link;
646 acpi_status result;
647
648 result = acpi_bus_get_device(handle, &device);
649 if (result) {
650 printk(KERN_ERR PREFIX "Invalid link device\n");
651 return -1;
652 }
653
654 link = acpi_driver_data(device);
655 if (!link) {
656 printk(KERN_ERR PREFIX "Invalid link context\n");
657 return -1;
658 }
659
660 mutex_lock(&acpi_link_lock);
661 if (!link->irq.initialized) {
662 mutex_unlock(&acpi_link_lock);
663 printk(KERN_ERR PREFIX "Link isn't initialized\n");
664 return -1;
665 }
666#ifdef FUTURE_USE
667
668
669
670
671
672
673
674
675
676 link->refcnt--;
677#endif
678 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
679 "Link %s is dereferenced\n",
680 acpi_device_bid(link->device)));
681
682 if (link->refcnt == 0)
683 acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
684
685 mutex_unlock(&acpi_link_lock);
686 return (link->irq.active);
687}
688
689
690
691
692
693static int acpi_pci_link_add(struct acpi_device *device)
694{
695 int result;
696 struct acpi_pci_link *link;
697 int i;
698 int found = 0;
699
700 link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
701 if (!link)
702 return -ENOMEM;
703
704 link->device = device;
705 strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
706 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
707 device->driver_data = link;
708
709 mutex_lock(&acpi_link_lock);
710 result = acpi_pci_link_get_possible(link);
711 if (result)
712 goto end;
713
714
715 acpi_pci_link_get_current(link);
716
717 printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device),
718 acpi_device_bid(device));
719 for (i = 0; i < link->irq.possible_count; i++) {
720 if (link->irq.active == link->irq.possible[i]) {
721 printk(" *%d", link->irq.possible[i]);
722 found = 1;
723 } else
724 printk(" %d", link->irq.possible[i]);
725 }
726
727 printk(")");
728
729 if (!found)
730 printk(" *%d", link->irq.active);
731
732 if (!link->device->status.enabled)
733 printk(", disabled.");
734
735 printk("\n");
736
737 list_add_tail(&link->list, &acpi_link_list);
738
739 end:
740
741 acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
742 mutex_unlock(&acpi_link_lock);
743
744 if (result)
745 kfree(link);
746
747 return result;
748}
749
750static int acpi_pci_link_resume(struct acpi_pci_link *link)
751{
752 if (link->refcnt && link->irq.active && link->irq.initialized)
753 return (acpi_pci_link_set(link, link->irq.active));
754
755 return 0;
756}
757
758static int irqrouter_resume(struct sys_device *dev)
759{
760 struct acpi_pci_link *link;
761
762 list_for_each_entry(link, &acpi_link_list, list) {
763 acpi_pci_link_resume(link);
764 }
765 return 0;
766}
767
768static int acpi_pci_link_remove(struct acpi_device *device, int type)
769{
770 struct acpi_pci_link *link;
771
772 link = acpi_driver_data(device);
773
774 mutex_lock(&acpi_link_lock);
775 list_del(&link->list);
776 mutex_unlock(&acpi_link_lock);
777
778 kfree(link);
779 return 0;
780}
781
782
783
784
785static int __init acpi_irq_penalty_update(char *str, int used)
786{
787 int i;
788
789 for (i = 0; i < 16; i++) {
790 int retval;
791 int irq;
792
793 retval = get_option(&str, &irq);
794
795 if (!retval)
796 break;
797
798 if (irq < 0)
799 continue;
800
801 if (irq >= ARRAY_SIZE(acpi_irq_penalty))
802 continue;
803
804 if (used)
805 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
806 else
807 acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
808
809 if (retval != 2)
810 break;
811 }
812 return 1;
813}
814
815
816
817
818
819
820
821
822void acpi_penalize_isa_irq(int irq, int active)
823{
824 if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
825 if (active)
826 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
827 else
828 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
829 }
830}
831
832
833
834
835
836
837static int __init acpi_irq_isa(char *str)
838{
839 return acpi_irq_penalty_update(str, 1);
840}
841
842__setup("acpi_irq_isa=", acpi_irq_isa);
843
844
845
846
847
848
849static int __init acpi_irq_pci(char *str)
850{
851 return acpi_irq_penalty_update(str, 0);
852}
853
854__setup("acpi_irq_pci=", acpi_irq_pci);
855
856static int __init acpi_irq_nobalance_set(char *str)
857{
858 acpi_irq_balance = 0;
859 return 1;
860}
861
862__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
863
864static int __init acpi_irq_balance_set(char *str)
865{
866 acpi_irq_balance = 1;
867 return 1;
868}
869
870__setup("acpi_irq_balance", acpi_irq_balance_set);
871
872
873static struct sysdev_class irqrouter_sysdev_class = {
874 .name = "irqrouter",
875 .resume = irqrouter_resume,
876};
877
878static struct sys_device device_irqrouter = {
879 .id = 0,
880 .cls = &irqrouter_sysdev_class,
881};
882
883static int __init irqrouter_init_sysfs(void)
884{
885 int error;
886
887 if (acpi_disabled || acpi_noirq)
888 return 0;
889
890 error = sysdev_class_register(&irqrouter_sysdev_class);
891 if (!error)
892 error = sysdev_register(&device_irqrouter);
893
894 return error;
895}
896
897device_initcall(irqrouter_init_sysfs);
898
899static int __init acpi_pci_link_init(void)
900{
901 if (acpi_noirq)
902 return 0;
903
904 if (acpi_irq_balance == -1) {
905
906 if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
907 acpi_irq_balance = 1;
908 else
909 acpi_irq_balance = 0;
910 }
911
912 if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
913 return -ENODEV;
914
915 return 0;
916}
917
918subsys_initcall(acpi_pci_link_init);
919