aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Lee <albertcc@tw.ibm.com>2006-05-18 23:43:04 -0400
committerJeff Garzik <jeff@garzik.org>2006-05-20 00:37:01 -0400
commit3655d1d323386e001c786af10f0a3f39f438f03b (patch)
tree16fd30cc6d255e5aaad4a5372cb8ec140c5b9736
parent3d71b3b0b634b1a5ba8632fd9ec998e0e4aedfdb (diff)
[PATCH] libata: Fix the HSM error_mask mapping (was: Re: libata-tj and SMART)
Fix the HSM error_mask mapping. Changes: - Better mapping in ac_err_mask() - In HSM_ST_FIRST ans HSM_ST state, check ATA_ERR|ATA_DF and map it to AC_ERR_DEV instead of AC_ERR_HSM. - In HSM_ST_FIRST and HSM_ST state, map DRQ=1 ERR=1 to AC_ERR_HSM. - For PIO data in and DRQ=1 ERR=1, add check after the junk data block is read. Signed-off-by: Albert Lee <albertcc@tw.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/scsi/libata-core.c31
-rw-r--r--include/linux/libata.h2
2 files changed, 25 insertions, 8 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 00881226f8dd..aa38ed3e59a8 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4009,9 +4009,15 @@ fsm_start:
4009 poll_next = (qc->tf.flags & ATA_TFLAG_POLLING); 4009 poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
4010 4010
4011 /* check device status */ 4011 /* check device status */
4012 if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { 4012 if (unlikely((status & ATA_DRQ) == 0)) {
4013 /* Wrong status. Let EH handle this */ 4013 /* handle BSY=0, DRQ=0 as error */
4014 qc->err_mask |= AC_ERR_HSM; 4014 if (likely(status & (ATA_ERR | ATA_DF)))
4015 /* device stops HSM for abort/error */
4016 qc->err_mask |= AC_ERR_DEV;
4017 else
4018 /* HSM violation. Let EH handle this */
4019 qc->err_mask |= AC_ERR_HSM;
4020
4015 ap->hsm_task_state = HSM_ST_ERR; 4021 ap->hsm_task_state = HSM_ST_ERR;
4016 goto fsm_start; 4022 goto fsm_start;
4017 } 4023 }
@@ -4025,7 +4031,7 @@ fsm_start:
4025 if (unlikely(status & (ATA_ERR | ATA_DF))) { 4031 if (unlikely(status & (ATA_ERR | ATA_DF))) {
4026 printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", 4032 printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
4027 ap->id, status); 4033 ap->id, status);
4028 qc->err_mask |= AC_ERR_DEV; 4034 qc->err_mask |= AC_ERR_HSM;
4029 ap->hsm_task_state = HSM_ST_ERR; 4035 ap->hsm_task_state = HSM_ST_ERR;
4030 goto fsm_start; 4036 goto fsm_start;
4031 } 4037 }
@@ -4067,7 +4073,9 @@ fsm_start:
4067 if (qc->tf.protocol == ATA_PROT_ATAPI) { 4073 if (qc->tf.protocol == ATA_PROT_ATAPI) {
4068 /* ATAPI PIO protocol */ 4074 /* ATAPI PIO protocol */
4069 if ((status & ATA_DRQ) == 0) { 4075 if ((status & ATA_DRQ) == 0) {
4070 /* no more data to transfer */ 4076 /* No more data to transfer or device error.
4077 * Device error will be tagged in HSM_ST_LAST.
4078 */
4071 ap->hsm_task_state = HSM_ST_LAST; 4079 ap->hsm_task_state = HSM_ST_LAST;
4072 goto fsm_start; 4080 goto fsm_start;
4073 } 4081 }
@@ -4081,7 +4089,7 @@ fsm_start:
4081 if (unlikely(status & (ATA_ERR | ATA_DF))) { 4089 if (unlikely(status & (ATA_ERR | ATA_DF))) {
4082 printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", 4090 printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
4083 ap->id, status); 4091 ap->id, status);
4084 qc->err_mask |= AC_ERR_DEV; 4092 qc->err_mask |= AC_ERR_HSM;
4085 ap->hsm_task_state = HSM_ST_ERR; 4093 ap->hsm_task_state = HSM_ST_ERR;
4086 goto fsm_start; 4094 goto fsm_start;
4087 } 4095 }
@@ -4096,7 +4104,13 @@ fsm_start:
4096 /* ATA PIO protocol */ 4104 /* ATA PIO protocol */
4097 if (unlikely((status & ATA_DRQ) == 0)) { 4105 if (unlikely((status & ATA_DRQ) == 0)) {
4098 /* handle BSY=0, DRQ=0 as error */ 4106 /* handle BSY=0, DRQ=0 as error */
4099 qc->err_mask |= AC_ERR_HSM; 4107 if (likely(status & (ATA_ERR | ATA_DF)))
4108 /* device stops HSM for abort/error */
4109 qc->err_mask |= AC_ERR_DEV;
4110 else
4111 /* HSM violation. Let EH handle this */
4112 qc->err_mask |= AC_ERR_HSM;
4113
4100 ap->hsm_task_state = HSM_ST_ERR; 4114 ap->hsm_task_state = HSM_ST_ERR;
4101 goto fsm_start; 4115 goto fsm_start;
4102 } 4116 }
@@ -4121,6 +4135,9 @@ fsm_start:
4121 status = ata_wait_idle(ap); 4135 status = ata_wait_idle(ap);
4122 } 4136 }
4123 4137
4138 if (status & (ATA_BUSY | ATA_DRQ))
4139 qc->err_mask |= AC_ERR_HSM;
4140
4124 /* ata_pio_sectors() might change the 4141 /* ata_pio_sectors() might change the
4125 * state to HSM_ST_LAST. so, the state 4142 * state to HSM_ST_LAST. so, the state
4126 * is changed after ata_pio_sectors(). 4143 * is changed after ata_pio_sectors().
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 2803ab8e9243..c51502c047a4 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1062,7 +1062,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
1062 1062
1063static inline unsigned int ac_err_mask(u8 status) 1063static inline unsigned int ac_err_mask(u8 status)
1064{ 1064{
1065 if (status & ATA_BUSY) 1065 if (status & (ATA_BUSY | ATA_DRQ))
1066 return AC_ERR_HSM; 1066 return AC_ERR_HSM;
1067 if (status & (ATA_ERR | ATA_DF)) 1067 if (status & (ATA_ERR | ATA_DF))
1068 return AC_ERR_DEV; 1068 return AC_ERR_DEV;