ACPI,PCI,IRQ: factor in PCI possible

The change introduced in commit 103544d869 (ACPI,PCI,IRQ: reduce
resource requirements) omitted the initially applied PCI_POSSIBLE
penalty when the IRQ is active.

Incorrect calculation of the penalty leads the ACPI code to assigning
a wrong interrupt number to a PCI INTx interrupt.

This would not be as bad as it sounds in theory.  It would just cause
the interrupts to be shared and result in performance penalty.

However, some drivers (like the parallel port driver) don't like
interrupt sharing and in the above case they will causes all of
the PCI drivers wanting to share the interrupt to be unable to
request it.

The issue has not been caught in testing because the behavior is
platform-specific and depends on the peripherals ending up sharing
the IRQ and their drivers.

Before the above commit the code would add the PCI_POSSIBLE value
divided by the number of possible IRQ users to the IRQ penalty
during initialization.

Later in that code path, if the IRQ is chosen as the active IRQ or
if it is used by ISA; additional penalties are added.

Fixes: 103544d869 (ACPI,PCI,IRQ: reduce resource requirements)
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Tested-by: Wim Osterholt <wim@djo.tudelft.nl>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Sinan Kaya 2016-06-29 04:27:35 -04:00 committed by Rafael J. Wysocki
parent 54794580f5
commit 4a6e68bf96

View File

@ -470,6 +470,7 @@ static int acpi_irq_pci_sharing_penalty(int irq)
{
struct acpi_pci_link *link;
int penalty = 0;
int i;
list_for_each_entry(link, &acpi_link_list, list) {
/*
@ -478,18 +479,14 @@ static int acpi_irq_pci_sharing_penalty(int irq)
*/
if (link->irq.active && link->irq.active == irq)
penalty += PIRQ_PENALTY_PCI_USING;
else {
int i;
/*
* If a link is inactive, penalize the IRQs it
* might use, but not as severely.
*/
for (i = 0; i < link->irq.possible_count; i++)
if (link->irq.possible[i] == irq)
penalty += PIRQ_PENALTY_PCI_POSSIBLE /
link->irq.possible_count;
}
/*
* penalize the IRQs PCI might use, but not as severely.
*/
for (i = 0; i < link->irq.possible_count; i++)
if (link->irq.possible[i] == irq)
penalty += PIRQ_PENALTY_PCI_POSSIBLE /
link->irq.possible_count;
}
return penalty;