Explorar o código

Merge branch 'upstream'

Jeff Garzik %!s(int64=19) %!d(string=hai) anos
pai
achega
d2927cbe40

+ 2 - 2
drivers/scsi/ahci.c

@@ -600,7 +600,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
 	 	 * not being called from the SCSI EH.
 	 	 * not being called from the SCSI EH.
 	 	 */
 	 	 */
 		qc->scsidone = scsi_finish_command;
 		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);
 	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) {
 	if (status & PORT_IRQ_FATAL) {
 		ahci_intr_error(ap, status);
 		ahci_intr_error(ap, status);
 		if (qc)
 		if (qc)
-			ata_qc_complete(qc, ATA_ERR);
+			ata_qc_complete(qc, AC_ERR_OTHER);
 	}
 	}
 
 
 	return 1;
 	return 1;

+ 15 - 16
drivers/scsi/libata-core.c

@@ -2663,7 +2663,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
  *	None.  (grabs host lock)
  *	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;
 	struct ata_port *ap = qc->ap;
 	unsigned long flags;
 	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);
 	spin_lock_irqsave(&ap->host_set->lock, flags);
 	ap->flags &= ~ATA_FLAG_NOINTR;
 	ap->flags &= ~ATA_FLAG_NOINTR;
 	ata_irq_on(ap);
 	ata_irq_on(ap);
-	ata_qc_complete(qc, drv_stat);
+	ata_qc_complete(qc, err_mask);
 	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	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;
 	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 */
 	/* 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)
 static void ata_pio_error(struct ata_port *ap)
 {
 {
 	struct ata_queued_cmd *qc;
 	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);
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 	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;
 	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)
 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);
 		       ap->id, qc->tf.command, drv_stat, host_stat);
 
 
 		/* complete taskfile transaction */
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 		break;
 	}
 	}
 
 
@@ -3375,7 +3372,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 	return qc;
 	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;
 	return 0;
 }
 }
@@ -3434,7 +3431,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
  *	spin_lock_irqsave(host_set lock)
  *	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;
 	int rc;
 
 
@@ -3451,7 +3448,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 
 	/* call completion callback */
 	/* 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),
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
 	 * return immediately
@@ -3889,7 +3886,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
 		ap->ops->irq_clear(ap);
 		ap->ops->irq_clear(ap);
 
 
 		/* complete taskfile transaction */
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, status);
+		ata_qc_complete(qc, ac_err_mask(status));
 		break;
 		break;
 
 
 	default:
 	default:
@@ -3984,7 +3981,7 @@ static void atapi_packet_task(void *_data)
 	/* sleep-wait for BSY to clear */
 	/* sleep-wait for BSY to clear */
 	DPRINTK("busy wait\n");
 	DPRINTK("busy wait\n");
 	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
 	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-		goto err_out;
+		goto err_out_status;
 
 
 	/* make sure DRQ is set */
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
 	status = ata_chk_status(ap);
@@ -4021,8 +4018,10 @@ static void atapi_packet_task(void *_data)
 
 
 	return;
 	return;
 
 
+err_out_status:
+	status = ata_chk_status(ap);
 err_out:
 err_out:
-	ata_poll_qc_complete(qc, ATA_ERR);
+	ata_poll_qc_complete(qc, __ac_err_mask(status));
 }
 }
 
 
 
 

+ 28 - 18
drivers/scsi/libata-scsi.c

@@ -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
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 * 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,
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 				   &sb[1], &sb[2], &sb[3]);
 				   &sb[1], &sb[2], &sb[3]);
 		sb[1] &= 0x0f;
 		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
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 * 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,
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 				   &sb[2], &sb[12], &sb[13]);
 				   &sb[2], &sb[12], &sb[13]);
 		sb[2] &= 0x0f;
 		sb[2] &= 0x0f;
@@ -644,7 +644,11 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 	sb[0] = 0x70;
 	sb[0] = 0x70;
 	sb[7] = 0x0a;
 	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 */
 		/* A small (28b) LBA will fit in the 32b info field */
 		sb[0] |= 0x80;		/* set valid bit */
 		sb[0] |= 0x80;		/* set valid bit */
 		sb[3] = tf->device & 0x0f;
 		sb[3] = tf->device & 0x0f;
@@ -652,6 +656,10 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 		sb[5] = tf->lbam;
 		sb[5] = tf->lbam;
 		sb[6] = tf->lbal;
 		sb[6] = tf->lbal;
 	}
 	}
+
+	else {
+		/* TODO: C/H/S */
+	}
 }
 }
 
 
 /**
 /**
@@ -1193,10 +1201,12 @@ nothing_to_do:
 	return 1;
 	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;
 	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
 	/* For ATA pass thru (SAT) commands, generate a sense block if
 	 * user mandated it or if there's an error.  Note that if we
 	 * user mandated it or if there's an error.  Note that if we
@@ -1205,8 +1215,8 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 	 * whether the command completed successfully or not. If there
 	 * whether the command completed successfully or not. If there
 	 * was no error, SK, ASC and ASCQ will all be zero.
 	 * 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);
  		ata_gen_ata_desc_sense(qc);
 	} else {
 	} else {
 		if (!need_sense) {
 		if (!need_sense) {
@@ -1989,21 +1999,13 @@ void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
 	DPRINTK("EXIT\n");
 	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;
 	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");
 		DPRINTK("request check condition\n");
 
 
 		/* FIXME: command completion with check condition
 		/* FIXME: command completion with check condition
@@ -2020,6 +2022,14 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 		return 1;
 		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 {
 	else {
 		u8 *scsicmd = cmd->cmnd;
 		u8 *scsicmd = cmd->cmnd;
 
 

+ 1 - 1
drivers/scsi/libata.h

@@ -39,7 +39,7 @@ struct ata_scsi_args {
 
 
 /* libata-core.c */
 /* libata-core.c */
 extern int atapi_enabled;
 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,
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 				      struct ata_device *dev);
 extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
 extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);

+ 8 - 5
drivers/scsi/pdc_adma.c

@@ -451,7 +451,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
 		struct adma_port_priv *pp;
 		struct adma_port_priv *pp;
 		struct ata_queued_cmd *qc;
 		struct ata_queued_cmd *qc;
 		void __iomem *chan = ADMA_REGS(mmio_base, port_no);
 		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)
 		if (status == 0)
 			continue;
 			continue;
@@ -464,11 +464,14 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
 			continue;
 			continue;
 		qc = ata_qc_from_tag(ap, ap->active_tag);
 		qc = ata_qc_from_tag(ap, ap->active_tag);
 		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+			unsigned int err_mask = 0;
+
 			if ((status & (aPERR | aPSD | aUIRQ)))
 			if ((status & (aPERR | aPSD | aUIRQ)))
-				drv_stat = ATA_ERR;
+				err_mask = AC_ERR_OTHER;
 			else if (pp->pkt[0] != cDONE)
 			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;
 	return handled;
@@ -498,7 +501,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
 		
 		
 				/* complete taskfile transaction */
 				/* complete taskfile transaction */
 				pp->state = adma_state_idle;
 				pp->state = adma_state_idle;
-				ata_qc_complete(qc, status);
+				ata_qc_complete(qc, ac_err_mask(status));
 				handled = 1;
 				handled = 1;
 			}
 			}
 		}
 		}

+ 6 - 5
drivers/scsi/sata_mv.c

@@ -1065,6 +1065,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 	struct ata_queued_cmd *qc;
 	struct ata_queued_cmd *qc;
 	u32 hc_irq_cause;
 	u32 hc_irq_cause;
 	int shift, port, port0, hard_port, handled;
 	int shift, port, port0, hard_port, handled;
+	unsigned int err_mask;
 	u8 ata_status = 0;
 	u8 ata_status = 0;
 
 
 	if (hc == 0) {
 	if (hc == 0) {
@@ -1100,15 +1101,15 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 			handled++;
 			handled++;
 		}
 		}
 
 
+		err_mask = ac_err_mask(ata_status);
+
 		shift = port << 1;		/* (port * 2) */
 		shift = port << 1;		/* (port * 2) */
 		if (port >= MV_PORTS_PER_HC) {
 		if (port >= MV_PORTS_PER_HC) {
 			shift++;	/* skip bit 8 in the HC Main IRQ reg */
 			shift++;	/* skip bit 8 in the HC Main IRQ reg */
 		}
 		}
 		if ((PORT0_ERR << shift) & relevant) {
 		if ((PORT0_ERR << shift) & relevant) {
 			mv_err_intr(ap);
 			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++;
 			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, "
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
 					"ata_status 0x%x\n", port,ata_status);
 				/* mark qc status appropriately */
 				/* 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);
 		spin_lock_irqsave(&ap->host_set->lock, flags);
 		qc->scsidone = scsi_finish_command;
 		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);
 		spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	}
 	}
 }
 }

+ 7 - 9
drivers/scsi/sata_promise.c

@@ -399,7 +399,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
 	case ATA_PROT_DMA:
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 		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;
 		break;
 
 
 	default:
 	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",
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 		       ap->id, qc->tf.command, drv_stat);
 
 
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 		break;
 	}
 	}
 
 
@@ -420,24 +421,21 @@ out:
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
                                           struct ata_queued_cmd *qc)
 {
 {
-	u8 status;
-	unsigned int handled = 0, have_err = 0;
+	unsigned int handled = 0, err_mask = 0;
 	u32 tmp;
 	u32 tmp;
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 
 	tmp = readl(mmio);
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
 	if (tmp & PDC_ERR_MASK) {
-		have_err = 1;
+		err_mask = AC_ERR_DEV;
 		pdc_reset_port(ap);
 		pdc_reset_port(ap);
 	}
 	}
 
 
 	switch (qc->tf.protocol) {
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 	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;
 		handled = 1;
 		break;
 		break;
 
 

+ 4 - 3
drivers/scsi/sata_qstor.c

@@ -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);
 				qc = ata_qc_from_tag(ap, ap->active_tag);
 				if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 				if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 					switch (sHST) {
 					switch (sHST) {
-					case 0: /* sucessful CPB */
+					case 0: /* successful CPB */
 					case 3: /* device error */
 					case 3: /* device error */
 						pp->state = qs_state_idle;
 						pp->state = qs_state_idle;
 						qs_enter_reg_mode(qc->ap);
 						qs_enter_reg_mode(qc->ap);
-						ata_qc_complete(qc, sDST);
+						ata_qc_complete(qc,
+							ac_err_mask(sDST));
 						break;
 						break;
 					default:
 					default:
 						break;
 						break;
@@ -441,7 +442,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
 
 
 				/* complete taskfile transaction */
 				/* complete taskfile transaction */
 				pp->state = qs_state_idle;
 				pp->state = qs_state_idle;
-				ata_qc_complete(qc, status);
+				ata_qc_complete(qc, ac_err_mask(status));
 				handled = 1;
 				handled = 1;
 			}
 			}
 		}
 		}

+ 7 - 5
drivers/scsi/sata_sil24.c

@@ -498,7 +498,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
 
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	if (!qc) {
 	if (!qc) {
-		printk(KERN_ERR "ata%u: BUG: tiemout without command\n",
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
 		       ap->id);
 		       ap->id);
 		return;
 		return;
 	}
 	}
@@ -512,7 +512,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
 	 */
 	 */
 	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 	qc->scsidone = scsi_finish_command;
 	qc->scsidone = scsi_finish_command;
-	ata_qc_complete(qc, ATA_ERR);
+	ata_qc_complete(qc, AC_ERR_OTHER);
 
 
 	sil24_reset_controller(ap);
 	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;
 	struct sil24_port_priv *pp = ap->private_data;
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	u32 irq_stat, cmd_err, sstatus, serror;
 	u32 irq_stat, cmd_err, sstatus, serror;
+	unsigned int err_mask;
 
 
 	irq_stat = readl(port + PORT_IRQ_STAT);
 	irq_stat = readl(port + PORT_IRQ_STAT);
 	writel(irq_stat, port + PORT_IRQ_STAT);		/* clear irq */
 	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.
 		 * Device is reporting error, tf registers are valid.
 		 */
 		 */
 		sil24_update_tf(ap);
 		sil24_update_tf(ap);
+		err_mask = ac_err_mask(pp->tf.command);
 	} else {
 	} else {
 		/*
 		/*
 		 * Other errors.  libata currently doesn't have any
 		 * Other errors.  libata currently doesn't have any
 		 * mechanism to report these errors.  Just turn on
 		 * mechanism to report these errors.  Just turn on
 		 * ATA_ERR.
 		 * ATA_ERR.
 		 */
 		 */
-		pp->tf.command = ATA_ERR;
+		err_mask = AC_ERR_OTHER;
 	}
 	}
 
 
 	if (qc)
 	if (qc)
-		ata_qc_complete(qc, pp->tf.command);
+		ata_qc_complete(qc, err_mask);
 
 
 	sil24_reset_controller(ap);
 	sil24_reset_controller(ap);
 }
 }
@@ -585,7 +587,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
 		sil24_update_tf(ap);
 		sil24_update_tf(ap);
 
 
 		if (qc)
 		if (qc)
-			ata_qc_complete(qc, pp->tf.command);
+			ata_qc_complete(qc, ac_err_mask(pp->tf.command));
 	} else
 	} else
 		sil24_error_intr(ap, slot_stat);
 		sil24_error_intr(ap, slot_stat);
 }
 }

+ 5 - 5
drivers/scsi/sata_sx4.c

@@ -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,
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
 			/* 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);
 			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,
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
 			/* 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);
 			pdc20621_pop_hdma(qc);
 		}
 		}
 		handled = 1;
 		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);
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-		ata_qc_complete(qc, status);
+		ata_qc_complete(qc, ac_err_mask(status));
 		handled = 1;
 		handled = 1;
 
 
 	} else {
 	} else {
@@ -881,7 +881,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
 	case ATA_PROT_DMA:
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 		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;
 		break;
 
 
 	default:
 	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",
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 		       ap->id, qc->tf.command, drv_stat);
 
 
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 		break;
 	}
 	}
 
 

+ 26 - 2
include/linux/libata.h

@@ -172,6 +172,13 @@ enum hsm_task_states {
 	HSM_ST_ERR,
 	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 */
 /* forward declarations */
 struct scsi_device;
 struct scsi_device;
 struct ata_port_operations;
 struct ata_port_operations;
@@ -179,7 +186,7 @@ struct ata_port;
 struct ata_queued_cmd;
 struct ata_queued_cmd;
 
 
 /* typedefs */
 /* 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 {
 struct ata_ioports {
 	unsigned long		cmd_addr;
 	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 void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(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_eng_timeout(struct ata_port *ap);
 extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
 extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
 			      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);
 	       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__ */
 #endif /* __LINUX_LIBATA_H__ */