Re: [1/3] Revert "ACPI,PCI,IRQ: reduce static IRQ array size to 16"
From: Jonathan Liu
Date: Sun Oct 02 2016 - 07:40:24 EST
On 2 October 2016 at 04:46, Sinan Kaya <okaya@xxxxxxxxxxxxxx> wrote:
> This reverts commit 5c5087a55390 ("ACPI,PCI,IRQ: reduce static IRQ array
> size to 16").
>
> The code maintains a fixed size array for IRQ penalties. The array
> gets updated by external calls such as acpi_penalize_sci_irq,
> acpi_penalize_isa_irq to reflect the actual interrupt usage of the
> system. Since the IRQ distribution is platform specific, this is
> not known ahead of time. The IRQs get updated based on the SCI
> interrupt number BIOS has chosen or the ISA IRQs that were assigned
> to existing peripherals.
>
> By the time ACPI gets initialized, this code tries to determine an
> IRQ number based on penalty values in this array. It will try to locate
> the IRQ with the least penalty assignment so that interrupt sharing is
> avoided if possible.
>
> A couple of notes about the external APIs:
> 1. These API can be called before the ACPI is started. Therefore, one
> cannot assume that the PCI link objects are initialized for calculating
> penalties.
> 2. The polarity and trigger information passed via the
> acpi_penalize_sci_irq from the BIOS may not match what the IRQ subsystem
> is reporting as the call might have been placed before the IRQ is
> registered by the interrupt subsystem.
>
> The previous change was in the direction to remove these external API and
> try to calculate the penalties at runtime for the ISA path as well. This
> didn't work out well with the existing platforms.
>
> Restoring the old behavior for IRQ < 256 and the new behavior will remain
> effective for IRQ >= 256.
>
> Link: http://www.spinics.net/lists/linux-pci/msg54599.html
> Signed-off-by: Sinan Kaya <okaya@xxxxxxxxxxxxxx>
> ---
> drivers/acpi/pci_link.c | 35 ++++++++++++++++++-----------------
> 1 file changed, 18 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index c983bf7..f3792f4 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -438,6 +438,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
> * enabled system.
> */
>
> +#define ACPI_MAX_IRQS 256
> #define ACPI_MAX_ISA_IRQS 16
>
> #define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
> @@ -446,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
> #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
> #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
>
> -static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
> +static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
> PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
> PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
> PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
> @@ -511,7 +512,7 @@ static int acpi_irq_get_penalty(int irq)
> }
>
> if (irq < ACPI_MAX_ISA_IRQS)
> - return penalty + acpi_isa_irq_penalty[irq];
> + return penalty + acpi_irq_penalty[irq];
>
> penalty += acpi_irq_pci_sharing_penalty(irq);
> return penalty;
> @@ -538,14 +539,14 @@ int __init acpi_irq_penalty_init(void)
>
> for (i = 0; i < link->irq.possible_count; i++) {
> if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
> - acpi_isa_irq_penalty[link->irq.
> + acpi_irq_penalty[link->irq.
> possible[i]] +=
> penalty;
> }
>
> } else if (link->irq.active &&
> - (link->irq.active < ACPI_MAX_ISA_IRQS)) {
> - acpi_isa_irq_penalty[link->irq.active] +=
> + (link->irq.active < ACPI_MAX_IRQS)) {
> + acpi_irq_penalty[link->irq.active] +=
> PIRQ_PENALTY_PCI_POSSIBLE;
> }
> }
> @@ -828,7 +829,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
> }
>
> /*
> - * modify acpi_isa_irq_penalty[] from cmdline
> + * modify acpi_irq_penalty[] from cmdline
> */
> static int __init acpi_irq_penalty_update(char *str, int used)
> {
> @@ -837,24 +838,24 @@ static int __init acpi_irq_penalty_update(char *str, int used)
> for (i = 0; i < 16; i++) {
> int retval;
> int irq;
> - int new_penalty;
>
> retval = get_option(&str, &irq);
>
> if (!retval)
> break; /* no number found */
>
> - /* see if this is a ISA IRQ */
> - if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS))
> + if (irq < 0)
> + continue;
> +
> + if (irq >= ARRAY_SIZE(acpi_irq_penalty))
> continue;
>
> if (used)
> - new_penalty = acpi_irq_get_penalty(irq) +
> - PIRQ_PENALTY_ISA_USED;
> + acpi_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
> + PIRQ_PENALTY_ISA_USED;
> else
> - new_penalty = 0;
> + acpi_irq_penalty[irq] = 0;
>
> - acpi_isa_irq_penalty[irq] = new_penalty;
> if (retval != 2) /* no next number */
> break;
> }
> @@ -870,14 +871,14 @@ static int __init acpi_irq_penalty_update(char *str, int used)
> */
> void acpi_penalize_isa_irq(int irq, int active)
> {
> - if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
> - acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
> - (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
> + if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty))
> + acpi_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
> + (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
> }
>
> bool acpi_isa_irq_available(int irq)
> {
> - return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) ||
> + return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
> acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
> }
>
This series fixes one or more network adapters in VirtualBox not
working with Linux 32-bit x86 guest if I have 4 network adapters
enabled. The following message no longer appears in the kernel log:
ACPI: No IRQ available for PCI Interrupt Link [LNKD]. Try pci=noacpi or acpi=off
Tested-by: Jonathan Liu <net147@xxxxxxxxx>