lkml.org 
[lkml]   [1998]   [May]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateThu, 14 May 1998 12:02:09 +0200 (CEST)
FromMOLNAR Ingo <>
Subject[SMP patch] io-apic-patch-2.1.101-J

On Thu, 14 May 1998, Harald Hoyer wrote:

> But not this one, if this is a typo:
>
> - irq_desc[i].handler = &ioapic_level_irq_type;
> + irq_desc[i].handler = &ioapic_edge_irq_type;

no, it's not a typo, it's in the announcement -F, it's a debugging
thing:). We can handle edge triggered IRQs with the new level-triggered
handler. But this does not mean we set it up as level-triggered. If you
think about it, it's valid, but suboptimal for edge-triggered IRQs. But i
wanted to test the new level-triggered part, the edge triggered stuff was
working almost always.

> Besides that the -F and -I patch break serial interrupts, after
> switching console from svga-apps or X-Server on my computer. Only one
> interrupt is served in 2 seconds. pre-2.1.102 works fine...

yes, this is already fixed in io-apic-patch-2.1.101-J. The problem was
setup_x86_irq()/free_irq(), they have to atomically change irq
descriptors, and they have to mask/umask IRQs properly.

this fix also has a chance to fix other problems, most notably maybe the
'double IRQs on NE2000' problem, and/or the BusLogic boot-hang? Please
re-report if there are still problems. The io-apic-patch-2.1.101-J patch
is against vanilla pre-patch-2.1.102.

-- mingo

--- linux/arch/i386/kernel/smp.c.orig Mon May 18 04:41:26 1998
+++ linux/arch/i386/kernel/smp.c Mon May 18 04:57:32 1998
@@ -636,9 +636,16 @@
value = apic_read(APIC_SPIV);
value |= (1<<8); /* Enable APIC (bit==1) */
value &= ~(1<<9); /* Enable focus processor (bit==0) */
+ value |= 0xff; /* Set spurious IRQ vector to 0xff */
apic_write(APIC_SPIV,value);

+ value = apic_read(APIC_TASKPRI);
+ value &= ~APIC_TPRI_MASK; /* Set Task Priority to 'accept all' */
+ apic_write(APIC_TASKPRI,value);
+
udelay(100); /* B safe */
+ ack_APIC_irq();
+ udelay(100);
}

__initfunc(void smp_callin(void))
@@ -1152,12 +1159,6 @@
__restore_flags(flags);
}

-void funny (void)
-{
- send_IPI(APIC_DEST_ALLBUT,0x30 /*IO_APIC_VECTOR(11)*/);
- for(;;)__cli();
-}
-
/*
* A non wait message cannot pass data or cpu source info. This current setup
* is only safe because the kernel lock owner is the only person who can send
@@ -1474,19 +1475,18 @@
}

/*
- * Reschedule call back
+ * Reschedule call back (not used currently)
*/
+
asmlinkage void smp_reschedule_interrupt(void)
{
int cpu = smp_processor_id();

ack_APIC_irq();
- for (;;) __cli();
/*
* This looks silly, but we actually do need to wait
* for the global interrupt lock.
*/
- printk("huh, this is used, where???\n");
irq_enter(cpu, 0);
need_resched = 1;
irq_exit(cpu, 0);
@@ -1519,6 +1519,15 @@
{
ack_APIC_irq ();
if (mtrr_hook) (*mtrr_hook) ();
+}
+
+/*
+ * This interrupt should _never_ happen with our APIC/SMP architecture
+ */
+asmlinkage void smp_spurious_interrupt(void)
+{
+ ack_APIC_irq ();
+ printk("spurious APIC interrupt, ayiee, should never happen.\n");
}

/*
--- linux/arch/i386/kernel/irq.c.orig Mon May 18 04:41:33 1998
+++ linux/arch/i386/kernel/irq.c Wed May 20 00:06:41 1998
@@ -108,7 +108,11 @@

/*
* Level and edge triggered IO-APIC interrupts need different handling,
- * so we use two separate irq descriptors:
+ * so we use two separate irq descriptors. edge triggered IRQs can be
+ * handled with the level-triggered descriptor, but that one has slightly
+ * more overhead. Level-triggered interrupts cannot be handled with the
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
*/

static void do_edge_ioapic_IRQ (unsigned int irq, int cpu,
@@ -207,17 +211,6 @@
}
}

-void unmask_generic_irq(unsigned int irq)
-{
- irq_desc[irq].status = 0;
- if (IO_APIC_IRQ(irq))
- enable_IO_APIC_irq(irq);
- else {
- cached_irq_mask &= ~(1 << irq);
- set_8259A_irq_mask(irq);
- }
-}
-
/*
* This builds up the IRQ handler stubs using some ugly macros in irq.h
*
@@ -277,6 +270,7 @@
BUILD_SMP_INTERRUPT(invalidate_interrupt)
BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
BUILD_SMP_INTERRUPT(mtrr_interrupt)
+BUILD_SMP_INTERRUPT(spurious_interrupt)

/*
* every pentium local APIC has two 'local interrupts', with a
@@ -376,6 +370,7 @@
p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter));
#ifdef __SMP__
p += sprintf(p, "IPI: %10lu\n", ipi_count);
+ print_IO_APIC();
#endif
return p - buf;
}
@@ -695,6 +690,16 @@
set_8259A_irq_mask(irq);
}

+int i8259A_irq_pending (unsigned int irq)
+{
+ unsigned int mask = 1<<irq;
+
+ if (irq < 8)
+ return (inb(0x20) & mask);
+ return (inb(0xA0) & (mask >> 8));
+}
+
+
void make_8259A_irq (unsigned int irq)
{
io_apic_irqs &= ~(1<<irq);
@@ -771,29 +776,20 @@
{
}

-/*
- * if we enable this, why does it cause a hang in the BusLogic
- * driver, when level triggered PCI IRQs are used?
- */
-#define NOT_BROKEN 0
-
static void enable_level_ioapic_irq(unsigned int irq)
{
-#if NOT_BROKEN
enable_IO_APIC_irq(irq);
-#endif
self_IPI(irq);
}

static void disable_level_ioapic_irq(unsigned int irq)
{
-#if NOT_BROKEN
disable_IO_APIC_irq(irq);
-#endif
}

/*
- * Has to be called with the irq controller locked
+ * Has to be called with the irq controller locked, and has to exit
+ * with with the lock held as well.
*/
static void handle_ioapic_event (unsigned int irq, int cpu,
struct pt_regs * regs)
@@ -808,13 +804,18 @@
while (test_bit(0,&global_irq_lock)) barrier();

for (;;) {
- int pending;
+ int pending, handler;

- /* If there is no IRQ handler, exit early, leaving the irq "in progress" */
- if (!handle_IRQ_event(irq, regs))
- goto no_handler;
+ /*
+ * If there is no IRQ handler, exit early, leaving the irq
+ * "in progress"
+ */
+ handler = handle_IRQ_event(irq, regs);

spin_lock(&irq_controller_lock);
+ if (!handler)
+ goto no_handler;
+
pending = desc->events;
desc->events = 0;
if (!pending)
@@ -822,7 +823,6 @@
spin_unlock(&irq_controller_lock);
}
desc->status &= IRQ_DISABLED;
- spin_unlock(&irq_controller_lock);

no_handler:
}
@@ -850,6 +850,7 @@
}

handle_ioapic_event(irq,cpu,regs);
+ spin_unlock(&irq_controller_lock);

hardirq_exit(cpu);
release_irqlock(cpu);
@@ -862,13 +863,14 @@

spin_lock(&irq_controller_lock);
/*
- * in the level triggered case we first disable the IRQ
+ * In the level triggered case we first disable the IRQ
* in the IO-APIC, then we 'early ACK' the IRQ, then we
* handle it and enable the IRQ when finished.
+ *
+ * disable has to happen before the ACK, to avoid IRQ storms.
+ * So this all has to be within the spinlock.
*/
-#if NOT_BROKEN
disable_IO_APIC_irq(irq);
-#endif
ack_APIC_irq();
desc->ipi = 0;

@@ -883,6 +885,10 @@
}

handle_ioapic_event(irq,cpu,regs);
+ /* we still have the spinlock held here */
+
+ enable_IO_APIC_irq(irq);
+ spin_unlock(&irq_controller_lock);

hardirq_exit(cpu);
release_irqlock(cpu);
@@ -981,11 +987,34 @@
struct irqaction *old, **p;
unsigned long flags;

+ /*
+ * Some drivers like serial.c use request_irq() heavily,
+ * so we have to be careful not to interfere with a
+ * running system.
+ */
+ if (new->flags & SA_SAMPLE_RANDOM) {
+ /*
+ * This function might sleep, we want to call it first,
+ * outside of the atomic block.
+ * Yes, this might clear the entropy pool if the wrong
+ * driver is attempted to be loaded, without actually
+ * installing a new handler, but is this really a problem,
+ * only the sysadmin is able to do this.
+ */
+ rand_initialize_irq(irq);
+ }
+
+ /*
+ * The following block of code has to be executed atomically
+ */
+ spin_lock_irqsave(&irq_controller_lock,flags);
p = &irq_desc[irq].action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ))
+ if (!(old->flags & new->flags & SA_SHIRQ)) {
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
return -EBUSY;
+ }

/* add new interrupt at end of irq queue */
do {
@@ -995,15 +1024,9 @@
shared = 1;
}

- if (new->flags & SA_SAMPLE_RANDOM)
- rand_initialize_irq(irq);
-
- save_flags(flags);
- cli();
*p = new;

if (!shared) {
- spin_lock(&irq_controller_lock);
#ifdef __SMP__
if (IO_APIC_IRQ(irq)) {
if (IO_APIC_VECTOR(irq) > 0xfe)
@@ -1016,14 +1039,20 @@
* First disable it in the 8259A:
*/
cached_irq_mask |= 1 << irq;
- if (irq < 16)
+ if (irq < 16) {
set_8259A_irq_mask(irq);
+ /*
+ * transport pending ISA IRQs to
+ * the new descriptor
+ */
+ if (i8259A_irq_pending(irq))
+ irq_desc[irq].events = 1;
+ }
}
#endif
- unmask_generic_irq(irq);
- spin_unlock(&irq_controller_lock);
+ irq_desc[irq].handler->enable(irq);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
return 0;
}

@@ -1065,23 +1094,23 @@
struct irqaction * action, **p;
unsigned long flags;

- if (irq >= NR_IRQS) {
- printk("Trying to free IRQ%d\n",irq);
+ if (irq >= NR_IRQS)
return;
- }
+
+ spin_lock_irqsave(&irq_controller_lock,flags);
for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
if (action->dev_id != dev_id)
continue;

/* Found it - now free it */
- save_flags(flags);
- cli();
*p = action->next;
- restore_flags(flags);
kfree(action);
- return;
+ irq_desc[irq].handler->disable(irq);
+ goto out;
}
printk("Trying to free free IRQ%d\n",irq);
+out:
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
}

/*
@@ -1103,7 +1132,7 @@
spin_lock_irq(&irq_controller_lock);
for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_desc[i].action) {
- unmask_generic_irq(i);
+ irq_desc[i].handler->enable(i);
irqs |= (1 << i);
}
}
@@ -1170,8 +1199,8 @@
(IO_APIC_IRQ(i))) {
if (IO_APIC_irq_trigger(i))
irq_desc[i].handler = &ioapic_level_irq_type;
- else
- irq_desc[i].handler = &ioapic_edge_irq_type;
+ else /* edge */
+ irq_desc[i].handler = &ioapic_level_irq_type;
/*
* disable it in the 8259A:
*/
@@ -1233,6 +1262,8 @@
/* IPI for MTRR control */
set_intr_gate(0x50, mtrr_interrupt);

+ /* IPI vector for APIC spurious interrupts */
+ set_intr_gate(0xff, spurious_interrupt);
#endif
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
--- linux/arch/i386/kernel/io_apic.c.orig Mon May 18 04:41:43 1998
+++ linux/arch/i386/kernel/io_apic.c Wed May 20 00:08:36 1998
@@ -110,6 +110,12 @@
int mpc_default_type = 0; /* non-0 if default (table-less)
MP configuration */

+
+/*
+ * This is performance-critical, we want to do it O(1)
+ */
+static int irq_2_pin[NR_IRQS];
+
unsigned int io_apic_read (unsigned int reg)
{
*IO_APIC_BASE = reg;
@@ -122,32 +128,32 @@
*(IO_APIC_BASE+4) = value;
}

-void enable_IO_APIC_irq (unsigned int irq)
+/*
+ * We disable IO-APIC IRQs by setting their 'destination CPU mask' to
+ * zero. Trick, trick.
+ */
+void disable_IO_APIC_irq(unsigned int irq)
{
+ int pin = irq_2_pin[irq];
struct IO_APIC_route_entry entry;

- /*
- * Enable it in the IO-APIC irq-routing table:
- */
- *(((int *)&entry)+0) = io_apic_read(0x10+irq*2);
- entry.mask = 0;
- io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
+ if (pin != -1) {
+ *(((int *)&entry)+1) = io_apic_read(0x11+pin*2);
+ entry.dest.logical.logical_dest = 0x0;
+ io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
+ }
}

-/*
- * this function is just here to make things complete, otherwise it's
- * unused
- */
-void disable_IO_APIC_irq (unsigned int irq)
+void enable_IO_APIC_irq(unsigned int irq)
{
+ int pin = irq_2_pin[irq];
struct IO_APIC_route_entry entry;

- /*
- * Disable it in the IO-APIC irq-routing table:
- */
- *(((int *)&entry)+0) = io_apic_read(0x10+irq*2);
- entry.mask = 1;
- io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
+ if (pin != -1) {
+ *(((int *)&entry)+1) = io_apic_read(0x11+pin*2);
+ entry.dest.logical.logical_dest = 0xff;
+ io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
+ }
}

void clear_IO_APIC_pin (unsigned int pin)
@@ -163,6 +169,7 @@
io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
}

+
/*
* support for broken MP BIOSes, enables hand-redirection of PIRQ0-7 to
* specific CPU-side IRQs.
@@ -258,129 +265,176 @@
return -1;
}

-static int irq_trigger(int idx)
+/*
+ * There are broken mptables which register ISA+high-active+level IRQs,
+ * these are illegal and are converted here to ISA+high-active+edge
+ * IRQ sources. Careful, ISA+low-active+level is another broken entry
+ * type, it represents PCI IRQs 'embedded into an ISA bus', they have
+ * to be accepted. Yes, ugh.
+ */
+
+static int MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
- int trigger;
+ int polarity;

/*
- * Determine IRQ trigger mode (edge or level sensitive):
+ * Determine IRQ line polarity (high active or low active):
*/
- switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
+ switch (mp_irqs[idx].mpc_irqflag & 3)
{
- case 0: /* conforms, ie. bus-type dependent */
+ case 0: /* conforms, ie. bus-type dependent polarity */
{
switch (mp_bus_id_to_type[bus])
{
- case MP_BUS_ISA: /* ISA pin, edge */
+ case MP_BUS_ISA: /* ISA pin */
{
- trigger = 0;
+ polarity = 0;
break;
}
- case MP_BUS_PCI: /* PCI pin, level */
+ case MP_BUS_PCI: /* PCI pin */
{
- trigger = 1;
+ polarity = 1;
break;
}
default:
{
printk("broken BIOS!!\n");
- trigger = 1;
+ polarity = 1;
break;
}
}
break;
}
- case 1: /* edge */
+ case 1: /* high active */
{
- trigger = 0;
+ polarity = 0;
break;
}
case 2: /* reserved */
{
printk("broken BIOS!!\n");
- trigger = 1;
+ polarity = 1;
break;
}
- case 3: /* level */
+ case 3: /* low active */
{
- trigger = 1;
+ polarity = 1;
break;
}
default: /* invalid */
{
printk("broken BIOS!!\n");
- trigger = 0;
+ polarity = 1;
break;
}
}
- return trigger;
+ return polarity;
}

-__initfunc(static int irq_polarity(int idx))
+
+static int MPBIOS_trigger(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
- int polarity;
+ int trigger;

/*
- * Determine IRQ line polarity (high active or low active):
+ * Determine IRQ trigger mode (edge or level sensitive):
*/
- switch (mp_irqs[idx].mpc_irqflag & 3)
+ switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
{
- case 0: /* conforms, ie. bus-type dependent polarity */
+ case 0: /* conforms, ie. bus-type dependent */
{
switch (mp_bus_id_to_type[bus])
{
- case MP_BUS_ISA: /* ISA pin */
+ case MP_BUS_ISA: /* ISA pin, edge */
{
- polarity = 0;
+ trigger = 0;
break;
}
- case MP_BUS_PCI: /* PCI pin */
+ case MP_BUS_PCI: /* PCI pin, level */
{
- polarity = 1;
+ trigger = 1;
break;
}
default:
{
printk("broken BIOS!!\n");
- polarity = 1;
+ trigger = 1;
break;
}
}
break;
}
- case 1: /* high active */
+ case 1: /* edge */
{
- polarity = 0;
+ trigger = 0;
break;
}
case 2: /* reserved */
{
printk("broken BIOS!!\n");
- polarity = 1;
+ trigger = 1;
break;
}
- case 3: /* low active */
+ case 3: /* level */
{
- polarity = 1;
+ trigger = 1;
break;
}
default: /* invalid */
{
printk("broken BIOS!!\n");
- polarity = 1;
+ trigger = 0;
break;
}
}
- return polarity;
+ return trigger;
+}
+
+static int trigger_flag_broken (int idx)
+{
+ int bus = mp_irqs[idx].mpc_srcbus;
+ int polarity = MPBIOS_polarity(idx);
+ int trigger = MPBIOS_trigger(idx);
+
+ if ( (mp_bus_id_to_type[bus] == MP_BUS_ISA) &&
+ (polarity == 0) /* active-high */ &&
+ (trigger == 1) /* level */ )
+
+ return 1; /* broken */
+
+ return 0;
+}
+
+static int irq_polarity (int idx)
+{
+ /*
+ * There are no known BIOS bugs wrt polarity. yet.
+ */
+ return MPBIOS_polarity(idx);
}

-__initfunc(static int pin_2_irq (int idx, int pin))
+static int irq_trigger (int idx)
+{
+ int trigger = MPBIOS_trigger(idx);
+
+ if (trigger_flag_broken (idx))
+ trigger = 0;
+ return trigger;
+}
+
+static int pin_2_irq (int idx, int pin)
{
int irq;
int bus = mp_irqs[idx].mpc_srcbus;

+ /*
+ * Debugging check, we are in big trouble if this message pops up!
+ */
+ if (mp_irqs[idx].mpc_dstirq != pin)
+ printk("broken BIOS or MPTABLE parser, ayiee!!\n");
+
switch (mp_bus_id_to_type[bus])
{
case MP_BUS_ISA: /* ISA pin */
@@ -423,12 +477,12 @@

int IO_APIC_irq_trigger (int irq)
{
- int idx, i;
+ int idx, pin;

- for (i=0; i<nr_ioapic_registers; i++) {
- idx = find_irq_entry(i,mp_INT);
- if (irq == pin_2_irq(idx,i))
- return irq_trigger(idx);
+ for (pin=0; pin<nr_ioapic_registers; pin++) {
+ idx = find_irq_entry(pin,mp_INT);
+ if ((idx != -1) && (irq == pin_2_irq(idx,pin)))
+ return (irq_trigger(idx));
}
/*
* nonexistant IRQs are edge default
@@ -439,11 +493,11 @@
__initfunc(void setup_IO_APIC_irqs (void))
{
struct IO_APIC_route_entry entry;
- int i, idx, bus, irq, first_notcon=1;
+ int pin, idx, bus, irq, first_notcon=1;

printk("init IO_APIC IRQs\n");

- for (i=0; i<nr_ioapic_registers; i++) {
+ for (pin=0; pin<nr_ioapic_registers; pin++) {

/*
* add it to the IO-APIC irq-routing table:
@@ -455,45 +509,34 @@
entry.mask = 0; /* enable IRQ */
entry.dest.logical.logical_dest = 0xff; /* all CPUs */

- idx = find_irq_entry(i,mp_INT);
+ idx = find_irq_entry(pin,mp_INT);
if (idx == -1) {
if (first_notcon) {
- printk(" IO-APIC pin %d", i);
+ printk(" IO-APIC pin %d", pin);
first_notcon=0;
} else
- printk(", %d", i);
+ printk(", %d", pin);
continue;
}

entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx);

- irq = pin_2_irq(idx,i);
+ irq = pin_2_irq(idx,pin);
+ irq_2_pin[irq] = pin;

if (!IO_APIC_IRQ(irq))
continue;

entry.vector = IO_APIC_VECTOR(irq);

- /*
- * There are broken mptables which register ISA+high-active+level IRQs,
- * these are illegal and are converted here to ISA+high-active+edge
- * IRQ sources. Careful, ISA+low-active+level is another broken entry
- * type, it represents PCI IRQs 'embedded into an ISA bus', they have
- * to be accepted. Yes, ugh.
- */
bus = mp_irqs[idx].mpc_srcbus;

- if ( (mp_bus_id_to_type[bus] == MP_BUS_ISA) &&
- (entry.polarity == 0) /* active-high */ &&
- (entry.trigger == 1) /* level */ )
- {
- printk("broken BIOS, changing pin %d to edge\n", i);
- entry.trigger = 0;
- }
+ if (trigger_flag_broken (idx))
+ printk("broken BIOS, changing pin %d to edge\n", pin);

- io_apic_write(0x10+2*i, *(((int *)&entry)+0));
- io_apic_write(0x11+2*i, *(((int *)&entry)+1));
+ io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
}

if (!first_notcon)
@@ -549,7 +592,7 @@
io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
}

-__initfunc(void print_IO_APIC (void))
+void print_IO_APIC (void)
{
int i;
struct IO_APIC_reg_00 reg_00;
@@ -598,7 +641,7 @@

printk(".... IRQ redirection table:\n");

- printk(" NR Log Phy ");
+ printk(" NR Log Phy ");
printk("Mask Trig IRR Pol Stat Dest Deli Vect: \n");

for (i=0; i<=reg_01.entries; i++) {
@@ -607,7 +650,7 @@
*(((int *)&entry)+0) = io_apic_read(0x10+i*2);
*(((int *)&entry)+1) = io_apic_read(0x11+i*2);

- printk(" %02x %03X %02X ",
+ printk(" %02x %03X %02X ",
i,
entry.dest.logical.logical_dest,
entry.dest.physical.physical_dest
@@ -625,6 +668,11 @@
);
}

+ printk("IRQ to pin mappings:\n");
+ for (i=0; i<NR_IRQS; i++)
+ printk("%d->%d ", i, irq_2_pin[i]);
+ printk("\n");
+
printk(".................................... done.\n");

return;
@@ -632,8 +680,10 @@

__initfunc(static void init_sym_mode (void))
{
- int i;
+ int i, pin;

+ for (i=0; i<NR_IRQS; i++)
+ irq_2_pin[i] = -1;
if (!pirqs_enabled)
for (i=0; i<MAX_PIRQS; i++)
pirq_entries[i]=-1;
@@ -658,8 +708,8 @@
/*
* Do not trust the IO-APIC being empty at bootup
*/
- for (i=0; i<nr_ioapic_registers; i++)
- clear_IO_APIC_pin (i);
+ for (pin=0; pin<nr_ioapic_registers; pin++)
+ clear_IO_APIC_pin (pin);
}

/*
--- linux/arch/i386/kernel/irq.h.orig Mon May 18 05:39:42 1998
+++ linux/arch/i386/kernel/irq.h Tue May 19 22:43:23 1998
@@ -12,7 +12,8 @@
void unmask_irq(unsigned int irq);
void enable_IO_APIC_irq (unsigned int irq);
void disable_IO_APIC_irq (unsigned int irq);
-void set_8259A_irq_mask(unsigned int irq);
+void set_8259A_irq_mask (unsigned int irq);
+int i8259A_irq_pending (unsigned int irq);
void ack_APIC_irq (void);
void setup_IO_APIC (void);
void init_IO_APIC_traps(void);
@@ -21,6 +22,7 @@
void make_8259A_irq (unsigned int irq);
void send_IPI (int dest, int vector);
void init_pic_mode (void);
+void print_IO_APIC (void);

extern unsigned int io_apic_irqs;
\
 
 \ /
  Last update: 2005-03-22 13:42    [from the cache]
©2003-2010