diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2006-05-18 23:43:04 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-05-20 00:37:01 -0400 |
commit | 3655d1d323386e001c786af10f0a3f39f438f03b (patch) | |
tree | 16fd30cc6d255e5aaad4a5372cb8ec140c5b9736 | |
parent | 3d71b3b0b634b1a5ba8632fd9ec998e0e4aedfdb (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.c | 31 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
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 | ||
1063 | static inline unsigned int ac_err_mask(u8 status) | 1063 | static 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; |