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