diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2006-04-01 04:38:43 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-01 14:29:21 -0500 |
commit | eee6c32f5f114f9b9f2d94862f0dc0d3ff523864 (patch) | |
tree | 76cae31872925fd2e66aeab833fed6b293f9af2d /drivers/scsi/libata-core.c | |
parent | 6e07e16404deafadf45895a7d2aeb5feba53b479 (diff) |
[PATCH] libata-dev: handle DRQ=1 ERR=1 (revised)
Handle DRQ=1 ERR=1 situation. Revised according to what IDE try_to_flush_leftover_data() does.
Changes:
- For ATA PIO writes and ATAPI devices, just stop the HSM and let EH handle it.
- For ATA PIO reads, read only one block of junk data and then let EH handle it.
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r-- | drivers/scsi/libata-core.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6fc25f60db97..da13deccc0e0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -3640,13 +3640,16 @@ fsm_start: | |||
3640 | 3640 | ||
3641 | /* Device should not ask for data transfer (DRQ=1) | 3641 | /* Device should not ask for data transfer (DRQ=1) |
3642 | * when it finds something wrong. | 3642 | * when it finds something wrong. |
3643 | * Anyway, we respect DRQ here and let HSM go on | 3643 | * We ignore DRQ here and stop the HSM by |
3644 | * without changing hsm_task_state to HSM_ST_ERR. | 3644 | * changing hsm_task_state to HSM_ST_ERR and |
3645 | * let the EH abort the command or reset the device. | ||
3645 | */ | 3646 | */ |
3646 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | 3647 | if (unlikely(status & (ATA_ERR | ATA_DF))) { |
3647 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", | 3648 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", |
3648 | ap->id, status); | 3649 | ap->id, status); |
3649 | qc->err_mask |= AC_ERR_DEV; | 3650 | qc->err_mask |= AC_ERR_DEV; |
3651 | ap->hsm_task_state = HSM_ST_ERR; | ||
3652 | goto fsm_start; | ||
3650 | } | 3653 | } |
3651 | 3654 | ||
3652 | /* Send the CDB (atapi) or the first data block (ata pio out). | 3655 | /* Send the CDB (atapi) or the first data block (ata pio out). |
@@ -3693,13 +3696,16 @@ fsm_start: | |||
3693 | 3696 | ||
3694 | /* Device should not ask for data transfer (DRQ=1) | 3697 | /* Device should not ask for data transfer (DRQ=1) |
3695 | * when it finds something wrong. | 3698 | * when it finds something wrong. |
3696 | * Anyway, we respect DRQ here and let HSM go on | 3699 | * We ignore DRQ here and stop the HSM by |
3697 | * without changing hsm_task_state to HSM_ST_ERR. | 3700 | * changing hsm_task_state to HSM_ST_ERR and |
3701 | * let the EH abort the command or reset the device. | ||
3698 | */ | 3702 | */ |
3699 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | 3703 | if (unlikely(status & (ATA_ERR | ATA_DF))) { |
3700 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", | 3704 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", |
3701 | ap->id, status); | 3705 | ap->id, status); |
3702 | qc->err_mask |= AC_ERR_DEV; | 3706 | qc->err_mask |= AC_ERR_DEV; |
3707 | ap->hsm_task_state = HSM_ST_ERR; | ||
3708 | goto fsm_start; | ||
3703 | } | 3709 | } |
3704 | 3710 | ||
3705 | atapi_pio_bytes(qc); | 3711 | atapi_pio_bytes(qc); |
@@ -3717,20 +3723,32 @@ fsm_start: | |||
3717 | goto fsm_start; | 3723 | goto fsm_start; |
3718 | } | 3724 | } |
3719 | 3725 | ||
3720 | /* Some devices may ask for data transfer (DRQ=1) | 3726 | /* For PIO reads, some devices may ask for |
3721 | * alone with ERR=1 for PIO reads. | 3727 | * data transfer (DRQ=1) alone with ERR=1. |
3722 | * We respect DRQ here and let HSM go on without | 3728 | * We respect DRQ here and transfer one |
3723 | * changing hsm_task_state to HSM_ST_ERR. | 3729 | * block of junk data before changing the |
3730 | * hsm_task_state to HSM_ST_ERR. | ||
3731 | * | ||
3732 | * For PIO writes, ERR=1 DRQ=1 doesn't make | ||
3733 | * sense since the data block has been | ||
3734 | * transferred to the device. | ||
3724 | */ | 3735 | */ |
3725 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | 3736 | if (unlikely(status & (ATA_ERR | ATA_DF))) { |
3726 | /* For writes, ERR=1 DRQ=1 doesn't make | ||
3727 | * sense since the data block has been | ||
3728 | * transferred to the device. | ||
3729 | */ | ||
3730 | WARN_ON(qc->tf.flags & ATA_TFLAG_WRITE); | ||
3731 | |||
3732 | /* data might be corrputed */ | 3737 | /* data might be corrputed */ |
3733 | qc->err_mask |= AC_ERR_DEV; | 3738 | qc->err_mask |= AC_ERR_DEV; |
3739 | |||
3740 | if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { | ||
3741 | ata_pio_sectors(qc); | ||
3742 | ata_altstatus(ap); | ||
3743 | status = ata_wait_idle(ap); | ||
3744 | } | ||
3745 | |||
3746 | /* ata_pio_sectors() might change the | ||
3747 | * state to HSM_ST_LAST. so, the state | ||
3748 | * is changed after ata_pio_sectors(). | ||
3749 | */ | ||
3750 | ap->hsm_task_state = HSM_ST_ERR; | ||
3751 | goto fsm_start; | ||
3734 | } | 3752 | } |
3735 | 3753 | ||
3736 | ata_pio_sectors(qc); | 3754 | ata_pio_sectors(qc); |