Message ID | 1346905686-27912-1-git-send-email-Shaohui.Xie@freescale.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Hello. On 06-09-2012 8:28, Shaohui Xie wrote: > The freescale V2 SATA controller checks if the received data length matches > the programmed length 'ttl', if not, it assumes that this is an error. > In ATAPI, the 'ttl' is based on max allocation length and not the actual > data transfer length, controller will raise 'DLM' (Data length Mismatch) > error bit in Hstatus register. Along with 'DLM', DE (Device error) and > FE (fatal Error) bits are also set in Hstatus register, 'E' (Internal Error) > bit is set in Serror register and CE (Command Error) and DE (Device error) > registers have the corresponding bit set. In this condition, we need to > clear errors in following way: in the service routine, based on 'DLM' flag, > HCONTROL[27] operation clears Hstatus, CE and DE registers, clear Serror > register. > Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com> > Signed-off-by: Anju Bhartiya <Anju.Bhartiya@freescale.com> > --- > changes for V2: > 1. remove the using of quirk; > 2. wrap errata codes in condition; > drivers/ata/sata_fsl.c | 40 +++++++++++++++++++++++++++++++++++----- > 1 files changed, 35 insertions(+), 5 deletions(-) > diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c > index d6577b9..6b7b73e 100644 > --- a/drivers/ata/sata_fsl.c > +++ b/drivers/ata/sata_fsl.c [...] > @@ -1180,26 +1181,55 @@ static void sata_fsl_host_intr(struct ata_port *ap) > void __iomem *hcr_base = host_priv->hcr_base; > u32 hstatus, done_mask = 0; > struct ata_queued_cmd *qc; > - u32 SError; > + u32 SError, 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; No uppercase in variable names please. Besides, you have 'hstatus' variable already and that would be inconsistent. > +#define HCONTROL_CLEAR_ERROR (1 << 27) > + /* Set HControl[27] to clear error registers */ > + Hcontrol = ioread32(hcr_base + HCONTROL); > + iowrite32(Hcontrol | HCONTROL_CLEAR_ERROR, > + hcr_base + HCONTROL); > + > + /* Clear HControl[27] */ > + iowrite32(Hcontrol & (~HCONTROL_CLEAR_ERROR), Parens not needed around ~HCONTROL_CLEAR_ERROR. > + hcr_base + HCONTROL); MBR, Sergei
> > > > 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; > > No uppercase in variable names please. [S.H] OK. Besides, you have 'hstatus' > variable already and that would be inconsistent. [S.H] Yes, but I ignored fatal error and device error, so this won't be an issue. > > > +#define HCONTROL_CLEAR_ERROR (1 << 27) > > + /* Set HControl[27] to clear error registers */ > > + Hcontrol = ioread32(hcr_base + HCONTROL); > > + iowrite32(Hcontrol | HCONTROL_CLEAR_ERROR, > > + hcr_base + HCONTROL); > > + > > + /* Clear HControl[27] */ > > + iowrite32(Hcontrol & (~HCONTROL_CLEAR_ERROR), > > Parens not needed around ~HCONTROL_CLEAR_ERROR. [S.H] OK. Best Regards, Shaohui Xie
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index d6577b9..6b7b73e 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -143,6 +143,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), @@ -1180,26 +1181,55 @@ static void sata_fsl_host_intr(struct ata_port *ap) void __iomem *hcr_base = host_priv->hcr_base; u32 hstatus, done_mask = 0; struct ata_queued_cmd *qc; - u32 SError; + u32 SError, 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; +#define HCONTROL_CLEAR_ERROR (1 << 27) + /* Set HControl[27] to clear error registers */ + Hcontrol = ioread32(hcr_base + HCONTROL); + iowrite32(Hcontrol | HCONTROL_CLEAR_ERROR, + hcr_base + HCONTROL); + + /* Clear HControl[27] */ + iowrite32(Hcontrol & (~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,