diff --git a/drivers/storage/ahcid/src/main.rs b/drivers/storage/ahcid/src/main.rs index 1f130a2974..e3b82d612d 100644 --- a/drivers/storage/ahcid/src/main.rs +++ b/drivers/storage/ahcid/src/main.rs @@ -91,11 +91,22 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { } } hba_mem.is.write(is); + } - irq_file - .write(&irq) - .expect("ahcid: failed to write irq file"); + // The kernel masks the IRQ line when it delivers the interrupt to us and + // only re-enables it once we write the count back (that write maps to + // acknowledge() -> pic_unmask()/ioapic_unmask()). IRQ lines are shared, so + // an interrupt raised by a *different* device arrives here with is == 0. + // Acking only inside the `is > 0` branch meant one foreign interrupt left + // the line masked forever: every later AHCI completion was lost and all + // disk I/O blocked permanently. Always re-arm the line, whether or not the + // interrupt turned out to be ours. Device-level status is cleared above + // before we unmask, so this cannot re-trigger a storm. + irq_file + .write(&irq) + .expect("ahcid: failed to write irq file"); + if is > 0 { FuturesExecutor.block_on(scheme.tick()).unwrap(); } }