|
@@ -123,6 +123,7 @@ enum {
|
|
|
ONLINE = (1 << 31),
|
|
|
GOING_OFFLINE = (1 << 30),
|
|
|
BIST_ERR = (1 << 29),
|
|
|
+ CLEAR_ERROR = (1 << 27),
|
|
|
|
|
|
FATAL_ERR_HC_MASTER_ERR = (1 << 18),
|
|
|
FATAL_ERR_PARITY_ERR_TX = (1 << 17),
|
|
@@ -143,6 +144,7 @@ enum {
|
|
|
FATAL_ERR_CRC_ERR_RX |
|
|
|
FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
|
|
|
|
|
|
+ INT_ON_DATA_LENGTH_MISMATCH = (1 << 12),
|
|
|
INT_ON_FATAL_ERR = (1 << 5),
|
|
|
INT_ON_PHYRDY_CHG = (1 << 4),
|
|
|
|
|
@@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
|
|
u32 hstatus, done_mask = 0;
|
|
|
struct ata_queued_cmd *qc;
|
|
|
u32 SError;
|
|
|
+ u32 tag;
|
|
|
+ u32 status_mask = INT_ON_ERROR;
|
|
|
|
|
|
hstatus = ioread32(hcr_base + HSTATUS);
|
|
|
|
|
|
sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
|
|
|
|
|
|
+ /* Read command completed register */
|
|
|
+ done_mask = ioread32(hcr_base + CC);
|
|
|
+
|
|
|
+ /* Workaround for data length mismatch errata */
|
|
|
+ if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
|
|
|
+ for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
|
|
+ qc = ata_qc_from_tag(ap, tag);
|
|
|
+ if (qc && ata_is_atapi(qc->tf.protocol)) {
|
|
|
+ u32 hcontrol;
|
|
|
+ /* Set HControl[27] to clear error registers */
|
|
|
+ hcontrol = ioread32(hcr_base + HCONTROL);
|
|
|
+ iowrite32(hcontrol | CLEAR_ERROR,
|
|
|
+ hcr_base + HCONTROL);
|
|
|
+
|
|
|
+ /* Clear HControl[27] */
|
|
|
+ iowrite32(hcontrol & ~CLEAR_ERROR,
|
|
|
+ hcr_base + HCONTROL);
|
|
|
+
|
|
|
+ /* Clear SError[E] bit */
|
|
|
+ sata_fsl_scr_write(&ap->link, SCR_ERROR,
|
|
|
+ SError);
|
|
|
+
|
|
|
+ /* Ignore fatal error and device error */
|
|
|
+ status_mask &= ~(INT_ON_SINGL_DEVICE_ERR
|
|
|
+ | INT_ON_FATAL_ERR);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (unlikely(SError & 0xFFFF0000)) {
|
|
|
DPRINTK("serror @host_intr : 0x%x\n", SError);
|
|
|
sata_fsl_error_intr(ap);
|
|
|
}
|
|
|
|
|
|
- if (unlikely(hstatus & INT_ON_ERROR)) {
|
|
|
+ if (unlikely(hstatus & status_mask)) {
|
|
|
DPRINTK("error interrupt!!\n");
|
|
|
sata_fsl_error_intr(ap);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /* Read command completed register */
|
|
|
- done_mask = ioread32(hcr_base + CC);
|
|
|
-
|
|
|
VPRINTK("Status of all queues :\n");
|
|
|
VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
|
|
|
done_mask,
|