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: disable_irq() during polling IDENTIFY to work around, the same as what IDE subsystem does. Signed-off-by: Albert Lee <albertcc@xxxxxxxxxx> --- Some controller like Intel ICH4 is immune from the problem, with the same kernel and the same Benq DW1620 drive. So, adding the ATA_FLAG_IDENT_IRQ_OFF flag for those adapters that needs the workaround. 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-mod2/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-mod2/drivers/ata/libata-core.c 2007-05-07 11:00:02.000000000 +0800 @@ -1427,6 +1427,7 @@ int ata_dev_read_id(struct ata_device *d unsigned int flags, u16 *id) { struct ata_port *ap = dev->ap; + struct ata_host *host = ap->host; unsigned int class = *p_class; struct ata_taskfile tf; unsigned int err_mask = 0; @@ -1466,8 +1467,29 @@ int ata_dev_read_id(struct ata_device *d */ tf.flags |= ATA_TFLAG_POLLING; + /* Disable IRQ since some devices like Benq DW1620 raises INTRQ + * when IDENTIFY PACKET DEVICE, even with polling IDENTIFY. + */ + if (ap->flags & ATA_FLAG_IDENT_IRQ_OFF) { + if (host->irq) + disable_irq(host->irq); + + if (host->irq2) + disable_irq(host->irq2); + } + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); + + /* Re-enable IRQ */ + if (ap->flags & ATA_FLAG_IDENT_IRQ_OFF) { + if (host->irq) + enable_irq(host->irq); + + if (host->irq2) + enable_irq(host->irq2); + } + if (err_mask) { if (err_mask & AC_ERR_NODEV_HINT) { DPRINTK("ata%u.%d: NODEV after polling detection\n", diff -Nrup linux-2.6.21.1-ori/drivers/ata/pata_pdc2027x.c linux-2.6.21.1-mod2/drivers/ata/pata_pdc2027x.c --- linux-2.6.21.1-ori/drivers/ata/pata_pdc2027x.c 2007-04-28 05:49:26.000000000 +0800 +++ linux-2.6.21.1-mod2/drivers/ata/pata_pdc2027x.c 2007-05-07 10:44:33.000000000 +0800 @@ -214,7 +214,7 @@ static struct ata_port_info pdc2027x_por { .sht = &pdc2027x_sht, .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_IDENT_IRQ_OFF, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ @@ -224,7 +224,7 @@ static struct ata_port_info pdc2027x_por { .sht = &pdc2027x_sht, .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_IDENT_IRQ_OFF, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA6, /* udma0-6 */ diff -Nrup linux-2.6.21.1-ori/include/linux/libata.h linux-2.6.21.1-mod2/include/linux/libata.h --- linux-2.6.21.1-ori/include/linux/libata.h 2007-04-28 05:49:26.000000000 +0800 +++ linux-2.6.21.1-mod2/include/linux/libata.h 2007-05-07 12:25:05.000000000 +0800 @@ -174,6 +174,7 @@ enum { ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ + ATA_FLAG_IDENT_IRQ_OFF = (1 << 17), /* disable irq when IDENTIFY */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be - 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