aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorSinan Kaya <okaya@codeaurora.org>2015-12-09 11:18:27 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-31 21:02:47 -0500
commitb5bd0269547105046f2236d9895bd5e3038cc8bc (patch)
tree15ebdccc315ba174d71015ebc449ff00c1172fca /drivers/acpi
parent74bf8efb5fa6e958d2d7c7917b8bb672085ec0c6 (diff)
ACPI, PCI, irq: remove interrupt count restriction
Code currently supports 256 maximum interrupts at this moment. The patch is reconfiguring the penalty array as a dynamic list to remove this limitation. A new penalty linklist has been added for all other interrupts greater than 16. If an IRQ is not found in the link list, an IRQ info structure will be dynamically allocated on the first access and will be placed on the list for further reuse. The list will grow by the number of supported interrupts in the ACPI table rather than having a 256 hard limitation. Acked-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Sinan Kaya <okaya@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/pci_link.c136
1 files changed, 102 insertions, 34 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 7c8408b946ca..0286f17f0fa5 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> 6 * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
7 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
7 * 8 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * 10 *
@@ -437,7 +438,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
437 * enabled system. 438 * enabled system.
438 */ 439 */
439 440
440#define ACPI_MAX_IRQS 256
441#define ACPI_MAX_ISA_IRQ 16 441#define ACPI_MAX_ISA_IRQ 16
442 442
443#define PIRQ_PENALTY_PCI_AVAILABLE (0) 443#define PIRQ_PENALTY_PCI_AVAILABLE (0)
@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
447#define PIRQ_PENALTY_ISA_USED (16*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) 448#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
449 449
450static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 450static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
451 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ 451 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
452 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ 452 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
453 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ 453 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
@@ -464,9 +464,68 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
464 PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ 464 PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
465 PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ 465 PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
466 PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ 466 PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
467 /* >IRQ15 */
468}; 467};
469 468
469struct irq_penalty_info {
470 int irq;
471 int penalty;
472 struct list_head node;
473};
474
475static LIST_HEAD(acpi_irq_penalty_list);
476
477static int acpi_irq_get_penalty(int irq)
478{
479 struct irq_penalty_info *irq_info;
480
481 if (irq < ACPI_MAX_ISA_IRQ)
482 return acpi_irq_isa_penalty[irq];
483
484 list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
485 if (irq_info->irq == irq)
486 return irq_info->penalty;
487 }
488
489 return 0;
490}
491
492static int acpi_irq_set_penalty(int irq, int new_penalty)
493{
494 struct irq_penalty_info *irq_info;
495
496 /* see if this is a ISA IRQ */
497 if (irq < ACPI_MAX_ISA_IRQ) {
498 acpi_irq_isa_penalty[irq] = new_penalty;
499 return 0;
500 }
501
502 /* next, try to locate from the dynamic list */
503 list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
504 if (irq_info->irq == irq) {
505 irq_info->penalty = new_penalty;
506 return 0;
507 }
508 }
509
510 /* nope, let's allocate a slot for this IRQ */
511 irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
512 if (!irq_info)
513 return -ENOMEM;
514
515 irq_info->irq = irq;
516 irq_info->penalty = new_penalty;
517 list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
518
519 return 0;
520}
521
522static void acpi_irq_add_penalty(int irq, int penalty)
523{
524 int curpen = acpi_irq_get_penalty(irq);
525
526 acpi_irq_set_penalty(irq, curpen + penalty);
527}
528
470int __init acpi_irq_penalty_init(void) 529int __init acpi_irq_penalty_init(void)
471{ 530{
472 struct acpi_pci_link *link; 531 struct acpi_pci_link *link;
@@ -487,15 +546,16 @@ int __init acpi_irq_penalty_init(void)
487 link->irq.possible_count; 546 link->irq.possible_count;
488 547
489 for (i = 0; i < link->irq.possible_count; i++) { 548 for (i = 0; i < link->irq.possible_count; i++) {
490 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) 549 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
491 acpi_irq_penalty[link->irq. 550 int irqpos = link->irq.possible[i];
492 possible[i]] += 551
493 penalty; 552 acpi_irq_add_penalty(irqpos, penalty);
553 }
494 } 554 }
495 555
496 } else if (link->irq.active) { 556 } else if (link->irq.active) {
497 acpi_irq_penalty[link->irq.active] += 557 acpi_irq_add_penalty(link->irq.active,
498 PIRQ_PENALTY_PCI_POSSIBLE; 558 PIRQ_PENALTY_PCI_POSSIBLE);
499 } 559 }
500 } 560 }
501 561
@@ -547,12 +607,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
547 * the use of IRQs 9, 10, 11, and >15. 607 * the use of IRQs 9, 10, 11, and >15.
548 */ 608 */
549 for (i = (link->irq.possible_count - 1); i >= 0; i--) { 609 for (i = (link->irq.possible_count - 1); i >= 0; i--) {
550 if (acpi_irq_penalty[irq] > 610 if (acpi_irq_get_penalty(irq) >
551 acpi_irq_penalty[link->irq.possible[i]]) 611 acpi_irq_get_penalty(link->irq.possible[i]))
552 irq = link->irq.possible[i]; 612 irq = link->irq.possible[i];
553 } 613 }
554 } 614 }
555 if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { 615 if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
556 printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " 616 printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
557 "Try pci=noacpi or acpi=off\n", 617 "Try pci=noacpi or acpi=off\n",
558 acpi_device_name(link->device), 618 acpi_device_name(link->device),
@@ -568,7 +628,8 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
568 acpi_device_bid(link->device)); 628 acpi_device_bid(link->device));
569 return -ENODEV; 629 return -ENODEV;
570 } else { 630 } else {
571 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; 631 acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
632
572 printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", 633 printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
573 acpi_device_name(link->device), 634 acpi_device_name(link->device),
574 acpi_device_bid(link->device), link->irq.active); 635 acpi_device_bid(link->device), link->irq.active);
@@ -778,7 +839,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
778} 839}
779 840
780/* 841/*
781 * modify acpi_irq_penalty[] from cmdline 842 * modify penalty from cmdline
782 */ 843 */
783static int __init acpi_irq_penalty_update(char *str, int used) 844static int __init acpi_irq_penalty_update(char *str, int used)
784{ 845{
@@ -796,13 +857,10 @@ static int __init acpi_irq_penalty_update(char *str, int used)
796 if (irq < 0) 857 if (irq < 0)
797 continue; 858 continue;
798 859
799 if (irq >= ARRAY_SIZE(acpi_irq_penalty))
800 continue;
801
802 if (used) 860 if (used)
803 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; 861 acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
804 else 862 else
805 acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; 863 acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
806 864
807 if (retval != 2) /* no next number */ 865 if (retval != 2) /* no next number */
808 break; 866 break;
@@ -819,18 +877,23 @@ static int __init acpi_irq_penalty_update(char *str, int used)
819 */ 877 */
820void acpi_penalize_isa_irq(int irq, int active) 878void acpi_penalize_isa_irq(int irq, int active)
821{ 879{
822 if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { 880 int penalty;
823 if (active) 881
824 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; 882 if (irq < 0)
825 else 883 return;
826 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; 884
827 } 885 if (active)
886 penalty = PIRQ_PENALTY_ISA_USED;
887 else
888 penalty = PIRQ_PENALTY_PCI_USING;
889
890 acpi_irq_add_penalty(irq, penalty);
828} 891}
829 892
830bool acpi_isa_irq_available(int irq) 893bool acpi_isa_irq_available(int irq)
831{ 894{
832 return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || 895 return irq >= 0 &&
833 acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); 896 (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
834} 897}
835 898
836/* 899/*
@@ -840,13 +903,18 @@ bool acpi_isa_irq_available(int irq)
840 */ 903 */
841void acpi_penalize_sci_irq(int irq, int trigger, int polarity) 904void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
842{ 905{
843 if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { 906 int penalty;
844 if (trigger != ACPI_MADT_TRIGGER_LEVEL || 907
845 polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) 908 if (irq < 0)
846 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS; 909 return;
847 else 910
848 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; 911 if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
849 } 912 polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
913 penalty = PIRQ_PENALTY_ISA_ALWAYS;
914 else
915 penalty = PIRQ_PENALTY_PCI_USING;
916
917 acpi_irq_add_penalty(irq, penalty);
850} 918}
851 919
852/* 920/*