irq: MSI first, and poll the INTx lines that never arrive
PCI drivers took their interrupt from INTERRUPT_LINE. On real hardware that is the 8259's number, not the IOAPIC pin the device is wired to (that is in ACPI _PRT, which needs AML), so nothing ever arrived. xHCI is entirely interrupt-driven, so the USB keyboard and a USB root would have hung even on a clean boot. Under QEMU the two numbers agree, which is why it never showed. - pci_irq_attach()/pci_irq_detach(): MSI, then MSI-X if the driver allows it, then INTx. The handler is registered before MSI is enabled, so no edge is lost. xHCI, e1000, r8169 and rtl8139 use it. - Lines 24-29 are MSI vectors. The LAPIC error vector moves from 19, which is a PCI pin on Intel chipsets, to 30. Nothing is placed at or above vector 64 (T_SYSCALL). - A storming line is masked and its handlers are polled instead of being left to eat the CPU. A level line that has had a handler for 2 s and never fired is polled every tick by a kernel thread. Tested in QEMU q35 with the root on a USB stick: xHCI and e1000e on MSI; then MSI disabled and INTx deliberately misrouted, where xHCI got zero interrupts and the root still mounted through the poller. i440fx INTx and the rtl8139 hand-over are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HH7xukt4aaiGj1nQEAoQf1
This commit is contained in:
parent
94c936ed98
commit
7e8d5e2821
11 changed files with 407 additions and 35 deletions
|
|
@ -360,8 +360,7 @@ rtl8139_probe(struct pci_dev *d)
|
|||
wr16(r, R_IMR, ISR_ROK | ISR_RER | ISR_TOK | ISR_TER |
|
||||
ISR_RXOVW | ISR_FOVW | ISR_LINKCHG);
|
||||
|
||||
if (d->irq != 0xFF && d->irq < 24)
|
||||
irq_register(d->irq, rtl8139_intr, r, "rtl8139", 1);
|
||||
pci_irq_attach(d, rtl8139_intr, r, "rtl8139", 0); // no MSI on this part
|
||||
|
||||
r->ready = 1;
|
||||
kinfo("rtl8139: %x:%x:%x:%x:%x:%x, %s, irq %d\n",
|
||||
|
|
@ -405,8 +404,7 @@ rtl8139_release(struct pci_dev *d)
|
|||
wr8(r, R_CR, 0); // receiver and transmitter off
|
||||
release(&r->lock);
|
||||
|
||||
if (d->irq != 0xFF && d->irq < 24)
|
||||
irq_unregister(d->irq, rtl8139_intr, r);
|
||||
pci_irq_detach(d, rtl8139_intr, r);
|
||||
|
||||
// Reset, and wait for it, so the chip has truly stopped before its buffers
|
||||
// are reused. The reset bit clears itself when the chip is done.
|
||||
|
|
|
|||
Loading…
Reference in a new issue