Skip to content

Commit 103544d

Browse files
Sinan Kayarafaeljw
authored andcommitted
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 <[email protected]> Acked-by: Bjorn Helgaas <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 04974df commit 103544d

File tree

1 file changed

+68
-29
lines changed

1 file changed

+68
-29
lines changed

drivers/acpi/pci_link.c

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/mutex.h>
3737
#include <linux/slab.h>
3838
#include <linux/acpi.h>
39+
#include <linux/irq.h>
3940

4041
#include "internal.h"
4142

@@ -440,7 +441,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
440441
#define ACPI_MAX_IRQS 256
441442
#define ACPI_MAX_ISA_IRQ 16
442443

443-
#define PIRQ_PENALTY_PCI_AVAILABLE (0)
444444
#define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
445445
#define PIRQ_PENALTY_PCI_USING (16*16*16)
446446
#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
@@ -457,16 +457,70 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
457457
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
458458
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
459459
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */
460-
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */
461-
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */
462-
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */
460+
0, /* IRQ9 PCI, often acpi */
461+
0, /* IRQ10 PCI */
462+
0, /* IRQ11 PCI */
463463
PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */
464464
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
465465
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
466466
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
467467
/* >IRQ15 */
468468
};
469469

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+
470524
int __init acpi_irq_penalty_init(void)
471525
{
472526
struct acpi_pci_link *link;
@@ -547,12 +601,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
547601
* the use of IRQs 9, 10, 11, and >15.
548602
*/
549603
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
550-
if (acpi_irq_penalty[irq] >
551-
acpi_irq_penalty[link->irq.possible[i]])
604+
if (acpi_irq_get_penalty(irq) >
605+
acpi_irq_get_penalty(link->irq.possible[i]))
552606
irq = link->irq.possible[i];
553607
}
554608
}
555-
if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
609+
if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
556610
printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
557611
"Try pci=noacpi or acpi=off\n",
558612
acpi_device_name(link->device),
@@ -568,7 +622,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
568622
acpi_device_bid(link->device));
569623
return -ENODEV;
570624
} else {
571-
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
572625
printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
573626
acpi_device_name(link->device),
574627
acpi_device_bid(link->device), link->irq.active);
@@ -800,9 +853,10 @@ static int __init acpi_irq_penalty_update(char *str, int used)
800853
continue;
801854

802855
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;
804858
else
805-
acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
859+
acpi_irq_penalty[irq] = 0;
806860

807861
if (retval != 2) /* no next number */
808862
break;
@@ -819,34 +873,19 @@ static int __init acpi_irq_penalty_update(char *str, int used)
819873
*/
820874
void acpi_penalize_isa_irq(int irq, int active)
821875
{
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-
}
876+
if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty))
877+
acpi_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
878+
active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING;
828879
}
829880

830881
bool acpi_isa_irq_available(int irq)
831882
{
832883
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);
834885
}
835886

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-
*/
841887
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
842888
{
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-
}
850889
}
851890

852891
/*

0 commit comments

Comments
 (0)