* [PATCH][v4] sata_fsl: add workaround for data length mismatch on freescale V2 controller
@ 2012-09-11 2:48 Shaohui Xie
2012-10-15 7:52 ` Xie Shaohui-B21989
0 siblings, 1 reply; 2+ messages in thread
From: Shaohui Xie @ 2012-09-11 2:48 UTC (permalink / raw)
To: jgarzik, linux-ide; +Cc: linuxppc-dev, linux-kernel, Anju Bhartiya, Shaohui Xie
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 v4:
1. put HCONTROL_CLEAR_ERROR to enum and rename it as CLEAR_ERROR;
changes for v3:
1. not using uppercase for variable names;
2. remove unnecessary parens;
changes for v2:
1. remove the using of quirk;
2. wrap errata codes in condition;
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 d6577b9..124b2c1 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -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,
--
1.6.4
^ permalink raw reply related [flat|nested] 2+ messages in thread* RE: [PATCH][v4] sata_fsl: add workaround for data length mismatch on freescale V2 controller
2012-09-11 2:48 [PATCH][v4] sata_fsl: add workaround for data length mismatch on freescale V2 controller Shaohui Xie
@ 2012-10-15 7:52 ` Xie Shaohui-B21989
0 siblings, 0 replies; 2+ messages in thread
From: Xie Shaohui-B21989 @ 2012-10-15 7:52 UTC (permalink / raw)
To: jgarzik@pobox.com, linux-ide@vger.kernel.org
Cc: Bhartiya Anju-B07263, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org, Xie Shaohui-B21989
Hi,
Any comment for this patch? It's been over a month...
Best Regards,=20
Shaohui Xie
> -----Original Message-----
> From: Xie Shaohui-B21989
> Sent: Tuesday, September 11, 2012 10:49 AM
> To: jgarzik@pobox.com; linux-ide@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; Xie
> Shaohui-B21989; Bhartiya Anju-B07263
> Subject: [PATCH][v4] sata_fsl: add workaround for data length mismatch on
> freescale V2 controller
>=20
> 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.
>=20
> Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
> Signed-off-by: Anju Bhartiya <Anju.Bhartiya@freescale.com>
> ---
> changes for v4:
> 1. put HCONTROL_CLEAR_ERROR to enum and rename it as CLEAR_ERROR;
>=20
> changes for v3:
> 1. not using uppercase for variable names; 2. remove unnecessary parens;
>=20
> changes for v2:
> 1. remove the using of quirk;
> 2. wrap errata codes in condition;
>=20
>=20
> drivers/ata/sata_fsl.c | 39 +++++++++++++++++++++++++++++++++++----
> 1 files changed, 35 insertions(+), 4 deletions(-)
>=20
> diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index
> d6577b9..124b2c1 100644
> --- a/drivers/ata/sata_fsl.c
> +++ b/drivers/ata/sata_fsl.c
> @@ -123,6 +123,7 @@ enum {
> ONLINE =3D (1 << 31),
> GOING_OFFLINE =3D (1 << 30),
> BIST_ERR =3D (1 << 29),
> + CLEAR_ERROR =3D (1 << 27),
>=20
> FATAL_ERR_HC_MASTER_ERR =3D (1 << 18),
> FATAL_ERR_PARITY_ERR_TX =3D (1 << 17),
> @@ -143,6 +144,7 @@ enum {
> FATAL_ERR_CRC_ERR_RX |
> FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
>=20
> + INT_ON_DATA_LENGTH_MISMATCH =3D (1 << 12),
> INT_ON_FATAL_ERR =3D (1 << 5),
> INT_ON_PHYRDY_CHG =3D (1 << 4),
>=20
> @@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port
> *ap)
> u32 hstatus, done_mask =3D 0;
> struct ata_queued_cmd *qc;
> u32 SError;
> + u32 tag;
> + u32 status_mask =3D INT_ON_ERROR;
>=20
> hstatus =3D ioread32(hcr_base + HSTATUS);
>=20
> sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
>=20
> + /* Read command completed register */
> + done_mask =3D ioread32(hcr_base + CC);
> +
> + /* Workaround for data length mismatch errata */
> + if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
> + for (tag =3D 0; tag < ATA_MAX_QUEUE; tag++) {
> + qc =3D ata_qc_from_tag(ap, tag);
> + if (qc && ata_is_atapi(qc->tf.protocol)) {
> + u32 hcontrol;
> + /* Set HControl[27] to clear error registers */
> + hcontrol =3D 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 &=3D ~(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);
> }
>=20
> - if (unlikely(hstatus & INT_ON_ERROR)) {
> + if (unlikely(hstatus & status_mask)) {
> DPRINTK("error interrupt!!\n");
> sata_fsl_error_intr(ap);
> return;
> }
>=20
> - /* Read command completed register */
> - done_mask =3D ioread32(hcr_base + CC);
> -
> VPRINTK("Status of all queues :\n");
> VPRINTK("done_mask/CC =3D 0x%x, CA =3D 0x%x,
> CE=3D0x%x,CQ=3D0x%x,apqa=3D0x%x\n",
> done_mask,
> --
> 1.6.4
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-10-15 7:52 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-11 2:48 [PATCH][v4] sata_fsl: add workaround for data length mismatch on freescale V2 controller Shaohui Xie
2012-10-15 7:52 ` Xie Shaohui-B21989
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox