Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 62400
b: refs/heads/master
c: ef3e28c
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman authored and Linus Torvalds committed Jul 22, 2007
1 parent addb610 commit 35943e7
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 22293e5806f58a9682267139678a5cc117fd3dcf
refs/heads/master: ef3e28c5b956cbb3b17531c85b698a27e83d5cf2
58 changes: 56 additions & 2 deletions trunk/arch/x86_64/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@ static inline void io_apic_modify(unsigned int apic, unsigned int value)
writel(value, &io_apic->data);
}

static int io_apic_level_ack_pending(unsigned int irq)
{
struct irq_pin_list *entry;
unsigned long flags;
int pending = 0;

spin_lock_irqsave(&ioapic_lock, flags);
entry = irq_2_pin + irq;
for (;;) {
unsigned int reg;
int pin;

pin = entry->pin;
if (pin == -1)
break;
reg = io_apic_read(entry->apic, 0x10 + pin*2);
/* Is the remote IRR bit set? */
pending |= (reg >> 14) & 1;
if (!entry->next)
break;
entry = irq_2_pin + entry->next;
}
spin_unlock_irqrestore(&ioapic_lock, flags);
return pending;
}

/*
* Synchronize the IO-APIC and the CPU by doing
* a dummy read from the IO-APIC
Expand Down Expand Up @@ -1418,9 +1444,37 @@ static void ack_apic_level(unsigned int irq)
ack_APIC_irq();

/* Now we can move and renable the irq */
move_masked_irq(irq);
if (unlikely(do_unmask_irq))
if (unlikely(do_unmask_irq)) {
/* Only migrate the irq if the ack has been received.
*
* On rare occasions the broadcast level triggered ack gets
* delayed going to ioapics, and if we reprogram the
* vector while Remote IRR is still set the irq will never
* fire again.
*
* To prevent this scenario we read the Remote IRR bit
* of the ioapic. This has two effects.
* - On any sane system the read of the ioapic will
* flush writes (and acks) going to the ioapic from
* this cpu.
* - We get to see if the ACK has actually been delivered.
*
* Based on failed experiments of reprogramming the
* ioapic entry from outside of irq context starting
* with masking the ioapic entry and then polling until
* Remote IRR was clear before reprogramming the
* ioapic I don't trust the Remote IRR bit to be
* completey accurate.
*
* However there appears to be no other way to plug
* this race, so if the Remote IRR bit is not
* accurate and is causing problems then it is a hardware bug
* and you can go talk to the chipset vendor about it.
*/
if (!io_apic_level_ack_pending(irq))
move_masked_irq(irq);
unmask_IO_APIC_irq(irq);
}
}

static struct irq_chip ioapic_chip __read_mostly = {
Expand Down

0 comments on commit 35943e7

Please sign in to comment.