diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2006-03-25 05:11:12 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-29 17:22:36 -0500 |
commit | 71601958f73b952281f2b02e16d1f11c99ee0a8b (patch) | |
tree | 87d7c55a27f0553f901b0c3ef4dfef792a3f946c /drivers/scsi/libata-core.c | |
parent | 999bb6f4260f9499fdeab3f8fdcd8b9013eca39e (diff) |
[PATCH] libata-dev: fix the device err check sequence (respin)
Current irq-pio checks ERR bit and stops on ERR before it does anything else.
This behavior doesn't look right.
The DRQ bit should take higher precedence than the ERR bit.
Changes:
- Let the HSM do the data transfer whenever the
device asks for DRQ bit, even if the ERR bit is set.
- For DRQ=1 ERR=1, don't trust the data
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 | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d68f5d5b423a..59cb12993f95 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -3587,12 +3587,6 @@ static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, | |||
3587 | */ | 3587 | */ |
3588 | WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc)); | 3588 | WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc)); |
3589 | 3589 | ||
3590 | /* check error */ | ||
3591 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | ||
3592 | qc->err_mask |= AC_ERR_DEV; | ||
3593 | ap->hsm_task_state = HSM_ST_ERR; | ||
3594 | } | ||
3595 | |||
3596 | fsm_start: | 3590 | fsm_start: |
3597 | DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", | 3591 | DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", |
3598 | ap->id, qc->tf.protocol, ap->hsm_task_state, status); | 3592 | ap->id, qc->tf.protocol, ap->hsm_task_state, status); |
@@ -3615,6 +3609,17 @@ fsm_start: | |||
3615 | goto fsm_start; | 3609 | goto fsm_start; |
3616 | } | 3610 | } |
3617 | 3611 | ||
3612 | /* Device should not ask for data transfer (DRQ=1) | ||
3613 | * when it finds something wrong. | ||
3614 | * Anyway, we respect DRQ here and let HSM go on | ||
3615 | * without changing hsm_task_state to HSM_ST_ERR. | ||
3616 | */ | ||
3617 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | ||
3618 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", | ||
3619 | ap->id, status); | ||
3620 | qc->err_mask |= AC_ERR_DEV; | ||
3621 | } | ||
3622 | |||
3618 | /* Send the CDB (atapi) or the first data block (ata pio out). | 3623 | /* Send the CDB (atapi) or the first data block (ata pio out). |
3619 | * During the state transition, interrupt handler shouldn't | 3624 | * During the state transition, interrupt handler shouldn't |
3620 | * be invoked before the data transfer is complete and | 3625 | * be invoked before the data transfer is complete and |
@@ -3657,6 +3662,17 @@ fsm_start: | |||
3657 | goto fsm_start; | 3662 | goto fsm_start; |
3658 | } | 3663 | } |
3659 | 3664 | ||
3665 | /* Device should not ask for data transfer (DRQ=1) | ||
3666 | * when it finds something wrong. | ||
3667 | * Anyway, we respect DRQ here and let HSM go on | ||
3668 | * without changing hsm_task_state to HSM_ST_ERR. | ||
3669 | */ | ||
3670 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | ||
3671 | printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", | ||
3672 | ap->id, status); | ||
3673 | qc->err_mask |= AC_ERR_DEV; | ||
3674 | } | ||
3675 | |||
3660 | atapi_pio_bytes(qc); | 3676 | atapi_pio_bytes(qc); |
3661 | 3677 | ||
3662 | if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) | 3678 | if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) |
@@ -3672,6 +3688,22 @@ fsm_start: | |||
3672 | goto fsm_start; | 3688 | goto fsm_start; |
3673 | } | 3689 | } |
3674 | 3690 | ||
3691 | /* Some devices may ask for data transfer (DRQ=1) | ||
3692 | * alone with ERR=1 for PIO reads. | ||
3693 | * We respect DRQ here and let HSM go on without | ||
3694 | * changing hsm_task_state to HSM_ST_ERR. | ||
3695 | */ | ||
3696 | if (unlikely(status & (ATA_ERR | ATA_DF))) { | ||
3697 | /* For writes, ERR=1 DRQ=1 doesn't make | ||
3698 | * sense since the data block has been | ||
3699 | * transferred to the device. | ||
3700 | */ | ||
3701 | WARN_ON(qc->tf.flags & ATA_TFLAG_WRITE); | ||
3702 | |||
3703 | /* data might be corrputed */ | ||
3704 | qc->err_mask |= AC_ERR_DEV; | ||
3705 | } | ||
3706 | |||
3675 | ata_pio_sectors(qc); | 3707 | ata_pio_sectors(qc); |
3676 | 3708 | ||
3677 | if (ap->hsm_task_state == HSM_ST_LAST && | 3709 | if (ap->hsm_task_state == HSM_ST_LAST && |