diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_fsl.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index d6577b93bee3..124b2c1d9c0b 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -123,6 +123,7 @@ enum { | |||
123 | ONLINE = (1 << 31), | 123 | ONLINE = (1 << 31), |
124 | GOING_OFFLINE = (1 << 30), | 124 | GOING_OFFLINE = (1 << 30), |
125 | BIST_ERR = (1 << 29), | 125 | BIST_ERR = (1 << 29), |
126 | CLEAR_ERROR = (1 << 27), | ||
126 | 127 | ||
127 | FATAL_ERR_HC_MASTER_ERR = (1 << 18), | 128 | FATAL_ERR_HC_MASTER_ERR = (1 << 18), |
128 | FATAL_ERR_PARITY_ERR_TX = (1 << 17), | 129 | FATAL_ERR_PARITY_ERR_TX = (1 << 17), |
@@ -143,6 +144,7 @@ enum { | |||
143 | FATAL_ERR_CRC_ERR_RX | | 144 | FATAL_ERR_CRC_ERR_RX | |
144 | FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX, | 145 | FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX, |
145 | 146 | ||
147 | INT_ON_DATA_LENGTH_MISMATCH = (1 << 12), | ||
146 | INT_ON_FATAL_ERR = (1 << 5), | 148 | INT_ON_FATAL_ERR = (1 << 5), |
147 | INT_ON_PHYRDY_CHG = (1 << 4), | 149 | INT_ON_PHYRDY_CHG = (1 << 4), |
148 | 150 | ||
@@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port *ap) | |||
1181 | u32 hstatus, done_mask = 0; | 1183 | u32 hstatus, done_mask = 0; |
1182 | struct ata_queued_cmd *qc; | 1184 | struct ata_queued_cmd *qc; |
1183 | u32 SError; | 1185 | u32 SError; |
1186 | u32 tag; | ||
1187 | u32 status_mask = INT_ON_ERROR; | ||
1184 | 1188 | ||
1185 | hstatus = ioread32(hcr_base + HSTATUS); | 1189 | hstatus = ioread32(hcr_base + HSTATUS); |
1186 | 1190 | ||
1187 | sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); | 1191 | sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); |
1188 | 1192 | ||
1193 | /* Read command completed register */ | ||
1194 | done_mask = ioread32(hcr_base + CC); | ||
1195 | |||
1196 | /* Workaround for data length mismatch errata */ | ||
1197 | if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) { | ||
1198 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | ||
1199 | qc = ata_qc_from_tag(ap, tag); | ||
1200 | if (qc && ata_is_atapi(qc->tf.protocol)) { | ||
1201 | u32 hcontrol; | ||
1202 | /* Set HControl[27] to clear error registers */ | ||
1203 | hcontrol = ioread32(hcr_base + HCONTROL); | ||
1204 | iowrite32(hcontrol | CLEAR_ERROR, | ||
1205 | hcr_base + HCONTROL); | ||
1206 | |||
1207 | /* Clear HControl[27] */ | ||
1208 | iowrite32(hcontrol & ~CLEAR_ERROR, | ||
1209 | hcr_base + HCONTROL); | ||
1210 | |||
1211 | /* Clear SError[E] bit */ | ||
1212 | sata_fsl_scr_write(&ap->link, SCR_ERROR, | ||
1213 | SError); | ||
1214 | |||
1215 | /* Ignore fatal error and device error */ | ||
1216 | status_mask &= ~(INT_ON_SINGL_DEVICE_ERR | ||
1217 | | INT_ON_FATAL_ERR); | ||
1218 | break; | ||
1219 | } | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1189 | if (unlikely(SError & 0xFFFF0000)) { | 1223 | if (unlikely(SError & 0xFFFF0000)) { |
1190 | DPRINTK("serror @host_intr : 0x%x\n", SError); | 1224 | DPRINTK("serror @host_intr : 0x%x\n", SError); |
1191 | sata_fsl_error_intr(ap); | 1225 | sata_fsl_error_intr(ap); |
1192 | } | 1226 | } |
1193 | 1227 | ||
1194 | if (unlikely(hstatus & INT_ON_ERROR)) { | 1228 | if (unlikely(hstatus & status_mask)) { |
1195 | DPRINTK("error interrupt!!\n"); | 1229 | DPRINTK("error interrupt!!\n"); |
1196 | sata_fsl_error_intr(ap); | 1230 | sata_fsl_error_intr(ap); |
1197 | return; | 1231 | return; |
1198 | } | 1232 | } |
1199 | 1233 | ||
1200 | /* Read command completed register */ | ||
1201 | done_mask = ioread32(hcr_base + CC); | ||
1202 | |||
1203 | VPRINTK("Status of all queues :\n"); | 1234 | VPRINTK("Status of all queues :\n"); |
1204 | VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n", | 1235 | VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n", |
1205 | done_mask, | 1236 | done_mask, |