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