diff options
author | Sinan Kaya <okaya@codeaurora.org> | 2016-04-17 13:36:53 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-05-04 19:10:31 -0400 |
commit | 103544d86976338057d6a91f721b49d3acc7df7f (patch) | |
tree | 13f2fdbc1667c13a5f83d55b3520c18e745b87a7 | |
parent | 04974df8049fc4240d22759a91e035082ccd18b4 (diff) |
ACPI,PCI,IRQ: reduce resource requirements
Code has been redesigned to calculate penalty requirements on the fly. This
significantly simplifies the implementation and removes some of the init
calls from x86 architecture.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/pci_link.c | 97 |
1 files changed, 68 insertions, 29 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index ededa909df2f..cc0ba1651db1 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
39 | #include <linux/irq.h> | ||
39 | 40 | ||
40 | #include "internal.h" | 41 | #include "internal.h" |
41 | 42 | ||
@@ -440,7 +441,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) | |||
440 | #define ACPI_MAX_IRQS 256 | 441 | #define ACPI_MAX_IRQS 256 |
441 | #define ACPI_MAX_ISA_IRQ 16 | 442 | #define ACPI_MAX_ISA_IRQ 16 |
442 | 443 | ||
443 | #define PIRQ_PENALTY_PCI_AVAILABLE (0) | ||
444 | #define PIRQ_PENALTY_PCI_POSSIBLE (16*16) | 444 | #define PIRQ_PENALTY_PCI_POSSIBLE (16*16) |
445 | #define PIRQ_PENALTY_PCI_USING (16*16*16) | 445 | #define PIRQ_PENALTY_PCI_USING (16*16*16) |
446 | #define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) | 446 | #define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) |
@@ -457,9 +457,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { | |||
457 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ | 457 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ |
458 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ | 458 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ |
459 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ | 459 | PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ |
460 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ | 460 | 0, /* IRQ9 PCI, often acpi */ |
461 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ | 461 | 0, /* IRQ10 PCI */ |
462 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ | 462 | 0, /* IRQ11 PCI */ |
463 | PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ | 463 | PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ |
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 */ |
@@ -467,6 +467,60 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { | |||
467 | /* >IRQ15 */ | 467 | /* >IRQ15 */ |
468 | }; | 468 | }; |
469 | 469 | ||
470 | static int acpi_irq_pci_sharing_penalty(int irq) | ||
471 | { | ||
472 | struct acpi_pci_link *link; | ||
473 | int penalty = 0; | ||
474 | |||
475 | list_for_each_entry(link, &acpi_link_list, list) { | ||
476 | /* | ||
477 | * If a link is active, penalize its IRQ heavily | ||
478 | * so we try to choose a different IRQ. | ||
479 | */ | ||
480 | if (link->irq.active && link->irq.active == irq) | ||
481 | penalty += PIRQ_PENALTY_PCI_USING; | ||
482 | else { | ||
483 | int i; | ||
484 | |||
485 | /* | ||
486 | * If a link is inactive, penalize the IRQs it | ||
487 | * might use, but not as severely. | ||
488 | */ | ||
489 | for (i = 0; i < link->irq.possible_count; i++) | ||
490 | if (link->irq.possible[i] == irq) | ||
491 | penalty += PIRQ_PENALTY_PCI_POSSIBLE / | ||
492 | link->irq.possible_count; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | return penalty; | ||
497 | } | ||
498 | |||
499 | static int acpi_irq_get_penalty(int irq) | ||
500 | { | ||
501 | int penalty = 0; | ||
502 | |||
503 | if (irq < ACPI_MAX_ISA_IRQ) | ||
504 | penalty += acpi_irq_penalty[irq]; | ||
505 | |||
506 | /* | ||
507 | * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict | ||
508 | * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be | ||
509 | * use for PCI IRQs. | ||
510 | */ | ||
511 | if (irq == acpi_gbl_FADT.sci_interrupt) { | ||
512 | u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK; | ||
513 | |||
514 | if (type != IRQ_TYPE_LEVEL_LOW) | ||
515 | penalty += PIRQ_PENALTY_ISA_ALWAYS; | ||
516 | else | ||
517 | penalty += PIRQ_PENALTY_PCI_USING; | ||
518 | } | ||
519 | |||
520 | penalty += acpi_irq_pci_sharing_penalty(irq); | ||
521 | return penalty; | ||
522 | } | ||
523 | |||
470 | int __init acpi_irq_penalty_init(void) | 524 | int __init acpi_irq_penalty_init(void) |
471 | { | 525 | { |
472 | struct acpi_pci_link *link; | 526 | struct acpi_pci_link *link; |
@@ -547,12 +601,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
547 | * the use of IRQs 9, 10, 11, and >15. | 601 | * the use of IRQs 9, 10, 11, and >15. |
548 | */ | 602 | */ |
549 | for (i = (link->irq.possible_count - 1); i >= 0; i--) { | 603 | for (i = (link->irq.possible_count - 1); i >= 0; i--) { |
550 | if (acpi_irq_penalty[irq] > | 604 | if (acpi_irq_get_penalty(irq) > |
551 | acpi_irq_penalty[link->irq.possible[i]]) | 605 | acpi_irq_get_penalty(link->irq.possible[i])) |
552 | irq = link->irq.possible[i]; | 606 | irq = link->irq.possible[i]; |
553 | } | 607 | } |
554 | } | 608 | } |
555 | if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { | 609 | if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) { |
556 | printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " | 610 | printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " |
557 | "Try pci=noacpi or acpi=off\n", | 611 | "Try pci=noacpi or acpi=off\n", |
558 | acpi_device_name(link->device), | 612 | acpi_device_name(link->device), |
@@ -568,7 +622,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
568 | acpi_device_bid(link->device)); | 622 | acpi_device_bid(link->device)); |
569 | return -ENODEV; | 623 | return -ENODEV; |
570 | } else { | 624 | } else { |
571 | acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; | ||
572 | printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", | 625 | printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", |
573 | acpi_device_name(link->device), | 626 | acpi_device_name(link->device), |
574 | acpi_device_bid(link->device), link->irq.active); | 627 | acpi_device_bid(link->device), link->irq.active); |
@@ -800,9 +853,10 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
800 | continue; | 853 | continue; |
801 | 854 | ||
802 | if (used) | 855 | if (used) |
803 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; | 856 | acpi_irq_penalty[irq] = acpi_irq_get_penalty(irq) + |
857 | PIRQ_PENALTY_ISA_USED; | ||
804 | else | 858 | else |
805 | acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; | 859 | acpi_irq_penalty[irq] = 0; |
806 | 860 | ||
807 | if (retval != 2) /* no next number */ | 861 | if (retval != 2) /* no next number */ |
808 | break; | 862 | break; |
@@ -819,34 +873,19 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
819 | */ | 873 | */ |
820 | void acpi_penalize_isa_irq(int irq, int active) | 874 | void acpi_penalize_isa_irq(int irq, int active) |
821 | { | 875 | { |
822 | if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { | 876 | if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) |
823 | if (active) | 877 | acpi_irq_penalty[irq] = acpi_irq_get_penalty(irq) + |
824 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; | 878 | active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING; |
825 | else | ||
826 | acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; | ||
827 | } | ||
828 | } | 879 | } |
829 | 880 | ||
830 | bool acpi_isa_irq_available(int irq) | 881 | bool acpi_isa_irq_available(int irq) |
831 | { | 882 | { |
832 | return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || | 883 | return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || |
833 | acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); | 884 | acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); |
834 | } | 885 | } |
835 | 886 | ||
836 | /* | ||
837 | * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with | ||
838 | * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for | ||
839 | * PCI IRQs. | ||
840 | */ | ||
841 | void acpi_penalize_sci_irq(int irq, int trigger, int polarity) | 887 | void acpi_penalize_sci_irq(int irq, int trigger, int polarity) |
842 | { | 888 | { |
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 | } | 889 | } |
851 | 890 | ||
852 | /* | 891 | /* |