# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1145 -> 1.1146 # Documentation/kernel-parameters.txt 1.11 -> 1.12 # drivers/acpi/pci_link.c 1.11 -> 1.12 # arch/i386/kernel/acpi.c 1.16 -> 1.17 # arch/x86_64/kernel/acpi.c 1.4 -> 1.5 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/11/18 len.brown@intel.com 1.1146 # [ACPI] # Re-enable IRQ balacning if IOAPIC mode # http://bugzilla.kernel.org/show_bug.cgi?id=1440 # # Also allow IRQ balancing in PIC mode if "acpi_irq_balance" # http://bugzilla.kernel.org/show_bug.cgi?id=1391 # -------------------------------------------- # diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Tue Nov 18 06:25:03 2003 +++ b/Documentation/kernel-parameters.txt Tue Nov 18 06:25:03 2003 @@ -78,6 +78,11 @@ level Force PIC-mode SCI to Level Trigger (default) edge Force PIC-mode SCI to Edge Trigger + acpi_irq_balance ACPI will balance active IRQs + acpi_irq_nobalance ACPI will not move active IRQs + acpi_irq_pci= If irq_balance, Clear listed IRQs for use by PCI + acpi_irq_isa= If irq_balance, Mark listed IRQs used by ISA + ad1816= [HW,SOUND] ad1848= [HW,SOUND] diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c Tue Nov 18 06:25:03 2003 +++ b/arch/i386/kernel/acpi.c Tue Nov 18 06:25:03 2003 @@ -459,6 +459,8 @@ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; if (acpi_lapic && acpi_ioapic) diff -Nru a/arch/x86_64/kernel/acpi.c b/arch/x86_64/kernel/acpi.c --- a/arch/x86_64/kernel/acpi.c Tue Nov 18 06:25:03 2003 +++ b/arch/x86_64/kernel/acpi.c Tue Nov 18 06:25:03 2003 @@ -531,6 +531,8 @@ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; #endif /*CONFIG_X86_IO_APIC*/ diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c Tue Nov 18 06:25:03 2003 +++ b/drivers/acpi/pci_link.c Tue Nov 18 06:25:03 2003 @@ -95,7 +95,7 @@ void *context) { struct acpi_pci_link *link = (struct acpi_pci_link *) context; - int i = 0; + u32 i = 0; ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible"); @@ -290,7 +290,10 @@ if (!link->irq.active) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); - printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device)); + printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for" + "device (%s [%s]).\n", irq, + acpi_device_name(link->device), + acpi_device_bid(link->device)); link->irq.active = irq; } @@ -428,30 +431,67 @@ PCI Link IRQ Management -------------------------------------------------------------------------- */ -#define ACPI_MAX_IRQS 256 -#define ACPI_MAX_ISA_IRQ 16 - /* - * IRQ penalties are used to promote PCI IRQ balancing. We set each ISA- - * possible IRQ (0-15) with a default penalty relative to its feasibility - * for PCI's use: + * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt + * Link Devices to move the PIRQs around to minimize sharing. + * + * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs + * that the BIOS has already set to active. This is necessary because + * ACPI has no automatic means of knowing what ISA IRQs are used. Note that + * if the BIOS doesn't set a Link Device active, ACPI needs to program it + * even if acpi_irq_nobalance is set. + * + * A tables of penalties avoids directing PCI interrupts to well known + * ISA IRQs. Boot params are available to over-ride the default table: * - * Never use: 0, 1, 2 (timer, keyboard, and cascade) - * Avoid using: 13, 14, and 15 (FP error and IDE) - * Penalize: 3, 4, 6, 7, 12 (known ISA uses) + * List interrupts that are free for PCI use. + * acpi_irq_pci=n[,m] * - * Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC) - * as 'best bets' for PCI use. + * List interrupts that should not be used for PCI: + * acpi_irq_isa=n[,m] + * + * Note that PCI IRQ routers have a list of possible IRQs, + * which may not include the IRQs this table says are available. + * + * Since this heuristic can't tell the difference between a link + * that no device will attach to, vs. a link which may be shared + * by multiple active devices -- it is not optimal. + * + * If interrupt performance is that important, get an IO-APIC system + * with a pin dedicated to each device. Or for that matter, an MSI + * enabled system. */ +#define ACPI_MAX_IRQS 256 +#define ACPI_MAX_ISA_IRQ 16 + +#define PIRQ_PENALTY_PCI_AVAILABLE (0) +#define PIRQ_PENALTY_PCI_POSSIBLE (16*16) +#define PIRQ_PENALTY_PCI_USING (16*16*16) +#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) +#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) +#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) + static int acpi_irq_penalty[ACPI_MAX_IRQS] = { - 1000000, 1000000, 1000000, 10000, - 10000, 0, 10000, 10000, - 10000, 0, 0, 0, - 10000, 100000, 100000, 100000, + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ12 mouse */ + PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ + PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ + PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + /* >IRQ15 */ }; - int acpi_pci_link_check (void) { @@ -472,20 +512,30 @@ continue; } - if (link->irq.active) - acpi_irq_penalty[link->irq.active] += 100; - else if (link->irq.possible_count) { - int penalty = 100 / link->irq.possible_count; - for (i=0; iirq.possible_count; i++) { + /* + * reflect the possible and active irqs in the penalty table -- + * useful for breaking ties. + */ + if (link->irq.possible_count) { + int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count; + + for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) acpi_irq_penalty[link->irq.possible[i]] += penalty; } + + } else if (link->irq.active) { + acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE; } } + /* Add a penalty for the SCI */ + acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING; return_VALUE(0); } +static int acpi_irq_balance; /* 0: static, 1: balance */ + static int acpi_pci_link_allocate(struct acpi_pci_link* link) { int irq; int i; @@ -499,12 +549,14 @@ irq = link->irq.active; } else { irq = link->irq.possible[0]; + } + if (acpi_irq_balance || !link->irq.active) { /* * Select the best IRQ. This is done in reverse to promote * the use of IRQs 9, 10, 11, and >15. */ - for (i=(link->irq.possible_count-1); i>0; i--) { + for (i = (link->irq.possible_count - 1); i >= 0; i--) { if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) irq = link->irq.possible[i]; } @@ -517,13 +569,14 @@ acpi_device_bid(link->device)); return_VALUE(-ENODEV); } else { - acpi_irq_penalty[link->irq.active] += 100; + acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; printk(PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); } link->irq.setonboot = 1; + return_VALUE(0); } @@ -606,9 +659,12 @@ if (result) goto end; + /* query and set link->irq.active */ acpi_pci_link_get_current(link); - printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device)); +//#ifdef CONFIG_ACPI_DEBUG + printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), + acpi_device_bid(device)); for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.active == link->irq.possible[i]) { printk(" *%d", link->irq.possible[i]); @@ -618,6 +674,7 @@ printk(" %d", link->irq.possible[i]); } printk(")\n"); +//#endif /* CONFIG_ACPI_DEBUG */ /* TBD: Acquire/release lock */ list_add_tail(&link->node, &acpi_link.entries); @@ -652,6 +709,77 @@ return_VALUE(0); } + +/* + * modify acpi_irq_penalty[] from cmdline + */ +static int __init acpi_irq_penalty_update(char *str, int used) +{ + int i; + + for (i = 0; i < 16; i++) { + int retval; + int irq; + + retval = get_option(&str,&irq); + + if (!retval) + break; /* no number found */ + + if (irq < 0) + continue; + + if (irq >= ACPI_MAX_IRQS) + continue; + + if (used) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + else + acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; + + if (retval != 2) /* no next number */ + break; + } + return 1; +} + +/* + * Over-ride default table to reserve additional IRQs for use by ISA + * e.g. acpi_irq_isa=5 + * Useful for telling ACPI how not to interfere with your ISA sound card. + */ +static int __init acpi_irq_isa(char *str) +{ + return(acpi_irq_penalty_update(str, 1)); +} +__setup("acpi_irq_isa=", acpi_irq_isa); + +/* + * Over-ride default table to free additional IRQs for use by PCI + * e.g. acpi_irq_pci=7,15 + * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing. + */ +static int __init acpi_irq_pci(char *str) +{ + return(acpi_irq_penalty_update(str, 0)); +} +__setup("acpi_irq_pci=", acpi_irq_pci); + +static int __init acpi_irq_nobalance_set(char *str) +{ +printk("ACPI STATIC SET\n"); + acpi_irq_balance = 0; + return(1); +} +__setup("acpi_irq_nobalance", acpi_irq_nobalance_set); + +int __init acpi_irq_balance_set(char *str) +{ +printk("ACPI BALANCE SET\n"); + acpi_irq_balance = 1; + return(1); +} +__setup("acpi_irq_balance", acpi_irq_balance_set); int __init