Problem: Kernel got "irq 5: nobody cared" when using libata + polling IDENTIFY + Promise 20275 adapter + Benq DW1620 drive. Detail message available in bug 8441 (http://bugzilla.kernel.org/show_bug.cgi?id=8441). Cause: The Benq DW1620 drive raises INTRQ during polling IDENTIFY PACKET DEVICE, even if nIEN = 1. Proposed fix: Ack the possibly unexpected irq in ata_interrupt(). Signed-off-by: Albert Lee <albertcc@xxxxxxxxxx> --- Patch revised per Tejun's advice to ack the unexpected INTRQ in ata_interrupt(). Also, ap->lock is held when transfering PIO data from/to the port in case the device doesn't like the status register to be read during data transfer. Patch against 2.6.21.1 for your review, thanks. diff -Nrup linux-2.6.21.1-ori/drivers/ata/libata-core.c linux-2.6.21.1-mod6/drivers/ata/libata-core.c --- linux-2.6.21.1-ori/drivers/ata/libata-core.c 2007-05-04 11:22:23.000000000 +0800 +++ linux-2.6.21.1-mod6/drivers/ata/libata-core.c 2007-05-08 19:25:58.000000000 +0800 @@ -4490,8 +4490,17 @@ fsm_start: goto fsm_start; } + /* prevent ata_interrupt() from reading + * status when transfering data for safty + */ + if (in_wq) + spin_lock_irqsave(ap->lock, flags); + atapi_pio_bytes(qc); + if (in_wq) + spin_unlock_irqrestore(ap->lock, flags); + if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) /* bad ireason reported by device */ goto fsm_start; @@ -4529,12 +4538,21 @@ fsm_start: /* data might be corrputed */ qc->err_mask |= AC_ERR_DEV; + /* prevent ata_interrupt() from reading + * status when transfering data for safty + */ + if (in_wq) + spin_lock_irqsave(ap->lock, flags); + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { ata_pio_sectors(qc); ata_altstatus(ap); status = ata_wait_idle(ap); } + if (in_wq) + spin_unlock_irqrestore(ap->lock, flags); + if (status & (ATA_BUSY | ATA_DRQ)) qc->err_mask |= AC_ERR_HSM; @@ -4546,8 +4564,17 @@ fsm_start: goto fsm_start; } + /* prevent ata_interrupt() from reading status + * when transfering data for safty + */ + if (in_wq) + spin_lock_irqsave(ap->lock, flags); + ata_pio_sectors(qc); + if (in_wq) + spin_unlock_irqrestore(ap->lock, flags); + if (ap->hsm_task_state == HSM_ST_LAST && (!(qc->tf.flags & ATA_TFLAG_WRITE))) { /* all data read */ @@ -5227,6 +5254,9 @@ irqreturn_t ata_interrupt (int irq, void if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && (qc->flags & ATA_QCFLAG_ACTIVE)) handled |= ata_host_intr(ap, qc); + else + /* ack possibly unexpected irq */ + ata_chk_status(ap); } } - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html