|
@@ -3640,13 +3640,16 @@ fsm_start:
|
|
|
|
|
|
/* Device should not ask for data transfer (DRQ=1)
|
|
|
* when it finds something wrong.
|
|
|
- * Anyway, we respect DRQ here and let HSM go on
|
|
|
- * without changing hsm_task_state to HSM_ST_ERR.
|
|
|
+ * We ignore DRQ here and stop the HSM by
|
|
|
+ * changing hsm_task_state to HSM_ST_ERR and
|
|
|
+ * let the EH abort the command or reset the device.
|
|
|
*/
|
|
|
if (unlikely(status & (ATA_ERR | ATA_DF))) {
|
|
|
printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
|
|
|
ap->id, status);
|
|
|
qc->err_mask |= AC_ERR_DEV;
|
|
|
+ ap->hsm_task_state = HSM_ST_ERR;
|
|
|
+ goto fsm_start;
|
|
|
}
|
|
|
|
|
|
/* Send the CDB (atapi) or the first data block (ata pio out).
|
|
@@ -3693,13 +3696,16 @@ fsm_start:
|
|
|
|
|
|
/* Device should not ask for data transfer (DRQ=1)
|
|
|
* when it finds something wrong.
|
|
|
- * Anyway, we respect DRQ here and let HSM go on
|
|
|
- * without changing hsm_task_state to HSM_ST_ERR.
|
|
|
+ * We ignore DRQ here and stop the HSM by
|
|
|
+ * changing hsm_task_state to HSM_ST_ERR and
|
|
|
+ * let the EH abort the command or reset the device.
|
|
|
*/
|
|
|
if (unlikely(status & (ATA_ERR | ATA_DF))) {
|
|
|
printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
|
|
|
ap->id, status);
|
|
|
qc->err_mask |= AC_ERR_DEV;
|
|
|
+ ap->hsm_task_state = HSM_ST_ERR;
|
|
|
+ goto fsm_start;
|
|
|
}
|
|
|
|
|
|
atapi_pio_bytes(qc);
|
|
@@ -3717,20 +3723,32 @@ fsm_start:
|
|
|
goto fsm_start;
|
|
|
}
|
|
|
|
|
|
- /* Some devices may ask for data transfer (DRQ=1)
|
|
|
- * alone with ERR=1 for PIO reads.
|
|
|
- * We respect DRQ here and let HSM go on without
|
|
|
- * changing hsm_task_state to HSM_ST_ERR.
|
|
|
+ /* For PIO reads, some devices may ask for
|
|
|
+ * data transfer (DRQ=1) alone with ERR=1.
|
|
|
+ * We respect DRQ here and transfer one
|
|
|
+ * block of junk data before changing the
|
|
|
+ * hsm_task_state to HSM_ST_ERR.
|
|
|
+ *
|
|
|
+ * For PIO writes, ERR=1 DRQ=1 doesn't make
|
|
|
+ * sense since the data block has been
|
|
|
+ * transferred to the device.
|
|
|
*/
|
|
|
if (unlikely(status & (ATA_ERR | ATA_DF))) {
|
|
|
- /* For writes, ERR=1 DRQ=1 doesn't make
|
|
|
- * sense since the data block has been
|
|
|
- * transferred to the device.
|
|
|
- */
|
|
|
- WARN_ON(qc->tf.flags & ATA_TFLAG_WRITE);
|
|
|
-
|
|
|
/* data might be corrputed */
|
|
|
qc->err_mask |= AC_ERR_DEV;
|
|
|
+
|
|
|
+ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
|
|
|
+ ata_pio_sectors(qc);
|
|
|
+ ata_altstatus(ap);
|
|
|
+ status = ata_wait_idle(ap);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ata_pio_sectors() might change the
|
|
|
+ * state to HSM_ST_LAST. so, the state
|
|
|
+ * is changed after ata_pio_sectors().
|
|
|
+ */
|
|
|
+ ap->hsm_task_state = HSM_ST_ERR;
|
|
|
+ goto fsm_start;
|
|
|
}
|
|
|
|
|
|
ata_pio_sectors(qc);
|