--- io_apic.c.zby 2010-05-16 23:17:36.000000000 +0200 +++ io_apic.c 2010-07-10 21:27:55.000000000 +0200 @@ -74,6 +74,10 @@ */ int sis_apic_bug = -1; +bool noFastEoiHandler = 0; +#define MAX_LVL_IRQS_NR 24 +int irq_lvl_required[MAX_LVL_IRQS_NR]; + static DEFINE_RAW_SPINLOCK(ioapic_lock); static DEFINE_RAW_SPINLOCK(vector_lock); @@ -123,6 +127,27 @@ } early_param("noapic", parse_noapic); +static int __init parse_NoFastEoiApic(char *str) +{ + /* replace the default fasteoi interrupt handler with level one */ + noFastEoiHandler = 1; + return 0; +} +early_param("nofasteoiapic", parse_NoFastEoiApic); + +static int __init parse_NoFastEoiApicAt(char *str) +{ + /* Reset level int table to default -1 */ + int i; + for(i = 0; i < 24; i++) irq_lvl_required[i] = -1; + /* force level handler for irqs instead default fasteoi */ + get_options(&str, MAX_LVL_IRQS_NR, irq_lvl_required); + for(i = 0; i < 24; i++) apic_printk(APIC_VERBOSE, KERN_INFO + "Interrupt table: position %d value %d\n", i, irq_lvl_required[i]); + return 0; +} +early_param("nofasteoiapic=", parse_NoFastEoiApicAt); + struct irq_pin_list { int apic, pin; struct irq_pin_list *next; @@ -1326,6 +1351,21 @@ } #endif +int CheckLevelNeeded(int irq) +{ +/* Looks if level irq is on the list */ + int i, result = 0; + for(i = 0; i < MAX_LVL_IRQS_NR; i++) + { + if(irq_lvl_required[i] == irq) result = irq; + if(irq_lvl_required[i] < 1) result = 0; + } + apic_printk(APIC_VERBOSE, KERN_INFO, "Interrupt found %d.\n", result); + return result; +} + + + static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger) { @@ -1348,10 +1388,21 @@ } if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || - trigger == IOAPIC_LEVEL) + trigger == IOAPIC_LEVEL) { + if (noFastEoiHandler) + set_irq_chip_and_handler_name(irq, &ioapic_chip, + handle_level_irq, + "level"); + else if (CheckLevelNeeded(irq)) { + set_irq_chip_and_handler_name(irq, &ioapic_chip, + handle_level_irq, + "level"); + } + else set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_fasteoi_irq, "fasteoi"); + } else set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge");