[libata] change ata_qc_complete() to take error mask as second arg
authorJeff Garzik <jgarzik@pobox.com>
Sun, 30 Oct 2005 09:44:42 +0000 (04:44 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Sun, 30 Oct 2005 09:44:42 +0000 (04:44 -0500)
The second argument to ata_qc_complete() was being used for two
purposes: communicate the ATA Status register to the completion
function, and indicate an error.  On legacy PCI IDE hardware, the latter
is often implicit in the former.  On more modern hardware, the driver
often completely emulated a Status register value, passing ATA_ERR as an
indication that something went wrong.

Now that previous code changes have eliminated the need to use drv_stat
arg to communicate the ATA Status register value, we can convert it to a
mask of possible error classes.

This will lead to more flexible error handling in the future.

drivers/scsi/ahci.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/pdc_adma.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_qstor.c
drivers/scsi/sata_sil24.c
drivers/scsi/sata_sx4.c
include/linux/libata.h

index 03829aedfd391149359181dcd3c3709bf5181c24..5efb3c50aa8a19020ee333889c08f2476a588196 100644 (file)
@@ -600,7 +600,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
                 * not being called from the SCSI EH.
                 */
                qc->scsidone = scsi_finish_command;
-               ata_qc_complete(qc, ATA_ERR);
+               ata_qc_complete(qc, AC_ERR_OTHER);
        }
 
        spin_unlock_irqrestore(&host_set->lock, flags);
@@ -629,7 +629,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        if (status & PORT_IRQ_FATAL) {
                ahci_intr_error(ap, status);
                if (qc)
-                       ata_qc_complete(qc, ATA_ERR);
+                       ata_qc_complete(qc, AC_ERR_OTHER);
        }
 
        return 1;
index 771bc7d376bc2e73a7861ce76fae9f8f37663f1a..cc089f1fb1146a2e104661254625ea26cf4e50e9 100644 (file)
@@ -2663,7 +2663,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
  *     None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
        struct ata_port *ap = qc->ap;
        unsigned long flags;
@@ -2671,7 +2671,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
        spin_lock_irqsave(&ap->host_set->lock, flags);
        ap->flags &= ~ATA_FLAG_NOINTR;
        ata_irq_on(ap);
-       ata_qc_complete(qc, drv_stat);
+       ata_qc_complete(qc, err_mask);
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
@@ -2768,7 +2768,7 @@ static int ata_pio_complete (struct ata_port *ap)
 
        ap->hsm_task_state = HSM_ST_IDLE;
 
-       ata_poll_qc_complete(qc, drv_stat);
+       ata_poll_qc_complete(qc, 0);
 
        /* another command may start at this point */
 
@@ -3136,18 +3136,15 @@ static void ata_pio_block(struct ata_port *ap)
 static void ata_pio_error(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
-       u8 drv_stat;
+
+       printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
        assert(qc != NULL);
 
-       drv_stat = ata_chk_status(ap);
-       printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
-              ap->id, drv_stat);
-
        ap->hsm_task_state = HSM_ST_IDLE;
 
-       ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
+       ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
 }
 
 static void ata_pio_task(void *_data)
@@ -3270,7 +3267,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                       ap->id, qc->tf.command, drv_stat, host_stat);
 
                /* complete taskfile transaction */
-               ata_qc_complete(qc, drv_stat);
+               ata_qc_complete(qc, ac_err_mask(drv_stat));
                break;
        }
 
@@ -3375,7 +3372,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
        return qc;
 }
 
-int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
        return 0;
 }
@@ -3434,7 +3431,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
  *     spin_lock_irqsave(host_set lock)
  */
 
-void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
        int rc;
 
@@ -3451,7 +3448,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
        qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* call completion callback */
-       rc = qc->complete_fn(qc, drv_stat);
+       rc = qc->complete_fn(qc, err_mask);
 
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@ -3889,7 +3886,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                ap->ops->irq_clear(ap);
 
                /* complete taskfile transaction */
-               ata_qc_complete(qc, status);
+               ata_qc_complete(qc, ac_err_mask(status));
                break;
 
        default:
@@ -3984,7 +3981,7 @@ static void atapi_packet_task(void *_data)
        /* sleep-wait for BSY to clear */
        DPRINTK("busy wait\n");
        if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-               goto err_out;
+               goto err_out_status;
 
        /* make sure DRQ is set */
        status = ata_chk_status(ap);
@@ -4021,8 +4018,10 @@ static void atapi_packet_task(void *_data)
 
        return;
 
+err_out_status:
+       status = ata_chk_status(ap);
 err_out:
-       ata_poll_qc_complete(qc, ATA_ERR);
+       ata_poll_qc_complete(qc, __ac_err_mask(status));
 }
 
 
index 89a04b1a5a0ef052f6566c6b15f3aed8f3da4b30..1e3792f86fcf4359171d46b6ac326b099844e905 100644 (file)
@@ -560,7 +560,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
         * Use ata_to_sense_error() to map status register bits
         * onto sense key, asc & ascq.
         */
-       if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+       if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
                ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
                                   &sb[1], &sb[2], &sb[3]);
                sb[1] &= 0x0f;
@@ -635,7 +635,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
         * Use ata_to_sense_error() to map status register bits
         * onto sense key, asc & ascq.
         */
-       if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+       if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
                ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
                                   &sb[2], &sb[12], &sb[13]);
                sb[2] &= 0x0f;
@@ -644,7 +644,11 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
        sb[0] = 0x70;
        sb[7] = 0x0a;
 
-       if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) {
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               /* TODO: find solution for LBA48 descriptors */
+       }
+
+       else if (tf->flags & ATA_TFLAG_LBA) {
                /* A small (28b) LBA will fit in the 32b info field */
                sb[0] |= 0x80;          /* set valid bit */
                sb[3] = tf->device & 0x0f;
@@ -652,6 +656,10 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
                sb[5] = tf->lbam;
                sb[6] = tf->lbal;
        }
+
+       else {
+               /* TODO: C/H/S */
+       }
 }
 
 /**
@@ -1199,10 +1207,12 @@ nothing_to_do:
        return 1;
 }
 
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
+                               unsigned int err_mask)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
-       int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ);
+       u8 *cdb = cmd->cmnd;
+       int need_sense = (err_mask != 0);
 
        /* For ATA pass thru (SAT) commands, generate a sense block if
         * user mandated it or if there's an error.  Note that if we
@@ -1211,8 +1221,8 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
         * whether the command completed successfully or not. If there
         * was no error, SK, ASC and ASCQ will all be zero.
         */
-       if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) &&
-           ((cmd->cmnd[2] & 0x20) || need_sense)) {
+       if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
+           ((cdb[2] & 0x20) || need_sense)) {
                ata_gen_ata_desc_sense(qc);
        } else {
                if (!need_sense) {
@@ -1995,21 +2005,13 @@ void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
        DPRINTK("EXIT\n");
 }
 
-static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
 
-       VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat);
-
-       if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ)))
-               /* FIXME: not quite right; we don't want the
-                * translation of taskfile registers into
-                * a sense descriptors, since that's only
-                * correct for ATA, not ATAPI
-                */
-               ata_gen_ata_desc_sense(qc);
+       VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
 
-       else if (unlikely(drv_stat & ATA_ERR)) {
+       if (unlikely(err_mask & AC_ERR_DEV)) {
                DPRINTK("request check condition\n");
 
                /* FIXME: command completion with check condition
@@ -2026,6 +2028,14 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
                return 1;
        }
 
+       else if (unlikely(err_mask))
+               /* FIXME: not quite right; we don't want the
+                * translation of taskfile registers into
+                * a sense descriptors, since that's only
+                * correct for ATA, not ATAPI
+                */
+               ata_gen_ata_desc_sense(qc);
+
        else {
                u8 *scsicmd = cmd->cmnd;
 
index 65c264b911369dfb10864025d2bf004e071f1bb1..10ecd9e15e4fb9296b8a0aa1eeacf99b5aaf2e29 100644 (file)
@@ -39,7 +39,7 @@ struct ata_scsi_args {
 
 /* libata-core.c */
 extern int atapi_enabled;
-extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
+extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
                                      struct ata_device *dev);
 extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
index af99feb9d2375cd2e14cad88b0e2836843b1e144..74b3b2c629b668c86f555344639a93587710dd7f 100644 (file)
@@ -451,7 +451,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
                struct adma_port_priv *pp;
                struct ata_queued_cmd *qc;
                void __iomem *chan = ADMA_REGS(mmio_base, port_no);
-               u8 drv_stat = 0, status = readb(chan + ADMA_STATUS);
+               u8 status = readb(chan + ADMA_STATUS);
 
                if (status == 0)
                        continue;
@@ -464,11 +464,14 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
                        continue;
                qc = ata_qc_from_tag(ap, ap->active_tag);
                if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+                       unsigned int err_mask = 0;
+
                        if ((status & (aPERR | aPSD | aUIRQ)))
-                               drv_stat = ATA_ERR;
+                               err_mask = AC_ERR_OTHER;
                        else if (pp->pkt[0] != cDONE)
-                               drv_stat = ATA_ERR;
-                       ata_qc_complete(qc, drv_stat);
+                               err_mask = AC_ERR_OTHER;
+
+                       ata_qc_complete(qc, err_mask);
                }
        }
        return handled;
@@ -498,7 +501,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
                
                                /* complete taskfile transaction */
                                pp->state = adma_state_idle;
-                               ata_qc_complete(qc, status);
+                               ata_qc_complete(qc, ac_err_mask(status));
                                handled = 1;
                        }
                }
index dcef5fe8600bbee29794969c7f9520655030b6bd..936d1ce5575f1ea98fe33f01230feb61643c4f37 100644 (file)
@@ -1065,6 +1065,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
        struct ata_queued_cmd *qc;
        u32 hc_irq_cause;
        int shift, port, port0, hard_port, handled;
+       unsigned int err_mask;
        u8 ata_status = 0;
 
        if (hc == 0) {
@@ -1100,15 +1101,15 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                        handled++;
                }
 
+               err_mask = ac_err_mask(ata_status);
+
                shift = port << 1;              /* (port * 2) */
                if (port >= MV_PORTS_PER_HC) {
                        shift++;        /* skip bit 8 in the HC Main IRQ reg */
                }
                if ((PORT0_ERR << shift) & relevant) {
                        mv_err_intr(ap);
-                       /* OR in ATA_ERR to ensure libata knows we took one */
-                       ata_status = readb((void __iomem *)
-                                          ap->ioaddr.status_addr) | ATA_ERR;
+                       err_mask |= AC_ERR_OTHER;
                        handled++;
                }
                
@@ -1118,7 +1119,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                                VPRINTK("port %u IRQ found for qc, "
                                        "ata_status 0x%x\n", port,ata_status);
                                /* mark qc status appropriately */
-                               ata_qc_complete(qc, ata_status);
+                               ata_qc_complete(qc, err_mask);
                        }
                }
        }
@@ -1294,7 +1295,7 @@ static void mv_eng_timeout(struct ata_port *ap)
                 */
                spin_lock_irqsave(&ap->host_set->lock, flags);
                qc->scsidone = scsi_finish_command;
-               ata_qc_complete(qc, ATA_ERR);
+               ata_qc_complete(qc, AC_ERR_OTHER);
                spin_unlock_irqrestore(&ap->host_set->lock, flags);
        }
 }
index 63911f16b6ecda3f6559ed9fc4070f39f5644272..8f41702275db9af3ec23c3570988b4fbad5045d7 100644 (file)
@@ -399,7 +399,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
                printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-               ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+               drv_stat = ata_wait_idle(ap);
+               ata_qc_complete(qc, __ac_err_mask(drv_stat));
                break;
 
        default:
@@ -408,7 +409,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
                printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
                       ap->id, qc->tf.command, drv_stat);
 
-               ata_qc_complete(qc, drv_stat);
+               ata_qc_complete(qc, ac_err_mask(drv_stat));
                break;
        }
 
@@ -420,24 +421,21 @@ out:
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
-       u8 status;
-       unsigned int handled = 0, have_err = 0;
+       unsigned int handled = 0, err_mask = 0;
        u32 tmp;
        void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
        tmp = readl(mmio);
        if (tmp & PDC_ERR_MASK) {
-               have_err = 1;
+               err_mask = AC_ERR_DEV;
                pdc_reset_port(ap);
        }
 
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
-               status = ata_wait_idle(ap);
-               if (have_err)
-                       status |= ATA_ERR;
-               ata_qc_complete(qc, status);
+               err_mask |= ac_err_mask(ata_wait_idle(ap));
+               ata_qc_complete(qc, err_mask);
                handled = 1;
                break;
 
index 1aaf3304d397ebfa43ce1ba493ac2fc1867e8531..d95a02fa7afb562df81b17f4995c2dbcba0fad18 100644 (file)
@@ -400,11 +400,12 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
                                qc = ata_qc_from_tag(ap, ap->active_tag);
                                if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
                                        switch (sHST) {
-                                       case 0: /* sucessful CPB */
+                                       case 0: /* successful CPB */
                                        case 3: /* device error */
                                                pp->state = qs_state_idle;
                                                qs_enter_reg_mode(qc->ap);
-                                               ata_qc_complete(qc, sDST);
+                                               ata_qc_complete(qc,
+                                                       ac_err_mask(sDST));
                                                break;
                                        default:
                                                break;
@@ -441,7 +442,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
 
                                /* complete taskfile transaction */
                                pp->state = qs_state_idle;
-                               ata_qc_complete(qc, status);
+                               ata_qc_complete(qc, ac_err_mask(status));
                                handled = 1;
                        }
                }
index e18a1e2bb65e70d55800d497b6fbb10c18be0713..4afe2b15b80326ac2fed0a30ba44864b1fc86c29 100644 (file)
@@ -498,7 +498,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
        if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: tiemout without command\n",
+               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
                       ap->id);
                return;
        }
@@ -512,7 +512,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
         */
        printk(KERN_ERR "ata%u: command timeout\n", ap->id);
        qc->scsidone = scsi_finish_command;
-       ata_qc_complete(qc, ATA_ERR);
+       ata_qc_complete(qc, AC_ERR_OTHER);
 
        sil24_reset_controller(ap);
 }
@@ -523,6 +523,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
        struct sil24_port_priv *pp = ap->private_data;
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        u32 irq_stat, cmd_err, sstatus, serror;
+       unsigned int err_mask;
 
        irq_stat = readl(port + PORT_IRQ_STAT);
        writel(irq_stat, port + PORT_IRQ_STAT);         /* clear irq */
@@ -550,17 +551,18 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
                 * Device is reporting error, tf registers are valid.
                 */
                sil24_update_tf(ap);
+               err_mask = ac_err_mask(pp->tf.command);
        } else {
                /*
                 * Other errors.  libata currently doesn't have any
                 * mechanism to report these errors.  Just turn on
                 * ATA_ERR.
                 */
-               pp->tf.command = ATA_ERR;
+               err_mask = AC_ERR_OTHER;
        }
 
        if (qc)
-               ata_qc_complete(qc, pp->tf.command);
+               ata_qc_complete(qc, err_mask);
 
        sil24_reset_controller(ap);
 }
@@ -585,7 +587,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
                sil24_update_tf(ap);
 
                if (qc)
-                       ata_qc_complete(qc, pp->tf.command);
+                       ata_qc_complete(qc, ac_err_mask(pp->tf.command));
        } else
                sil24_error_intr(ap, slot_stat);
 }
index af08f4f650c1ef6da8526b3524259a4b031fa159..d9a8baff0d4dfc5b9d7ed501421beb6d54212d62 100644 (file)
@@ -718,7 +718,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                        VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
-                       ata_qc_complete(qc, ata_wait_idle(ap));
+                       ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
                        pdc20621_pop_hdma(qc);
                }
 
@@ -756,7 +756,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                        VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
-                       ata_qc_complete(qc, ata_wait_idle(ap));
+                       ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
                        pdc20621_pop_hdma(qc);
                }
                handled = 1;
@@ -766,7 +766,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 
                status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
                DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-               ata_qc_complete(qc, status);
+               ata_qc_complete(qc, ac_err_mask(status));
                handled = 1;
 
        } else {
@@ -881,7 +881,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
                printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-               ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+               ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
                break;
 
        default:
@@ -890,7 +890,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
                printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
                       ap->id, qc->tf.command, drv_stat);
 
-               ata_qc_complete(qc, drv_stat);
+               ata_qc_complete(qc, ac_err_mask(drv_stat));
                break;
        }
 
index a4cce9936a800dc5a6d6473f6b23f89c1df65f18..0ba3af7a1236f448ac886878398da323d559309b 100644 (file)
@@ -172,6 +172,13 @@ enum hsm_task_states {
        HSM_ST_ERR,
 };
 
+enum ata_completion_errors {
+       AC_ERR_OTHER            = (1 << 0),
+       AC_ERR_DEV              = (1 << 1),
+       AC_ERR_ATA_BUS          = (1 << 2),
+       AC_ERR_HOST_BUS         = (1 << 3),
+};
+
 /* forward declarations */
 struct scsi_device;
 struct ata_port_operations;
@@ -179,7 +186,7 @@ struct ata_port;
 struct ata_queued_cmd;
 
 /* typedefs */
-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask);
 
 struct ata_ioports {
        unsigned long           cmd_addr;
@@ -453,7 +460,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
+extern void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern void ata_eng_timeout(struct ata_port *ap);
 extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
                              void (*done)(struct scsi_cmnd *));
@@ -716,4 +723,21 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
               ata_id_has_flush_ext(dev->id);
 }
 
+static inline unsigned int ac_err_mask(u8 status)
+{
+       if (status & ATA_BUSY)
+               return AC_ERR_ATA_BUS;
+       if (status & (ATA_ERR | ATA_DF))
+               return AC_ERR_DEV;
+       return 0;
+}
+
+static inline unsigned int __ac_err_mask(u8 status)
+{
+       unsigned int mask = ac_err_mask(status);
+       if (mask == 0)
+               return AC_ERR_OTHER;
+       return mask;
+}
+
 #endif /* __LINUX_LIBATA_H__ */