From patchwork Thu Sep 6 04:28:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: shaohui xie X-Patchwork-Id: 182005 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 246F52C0336 for ; Thu, 6 Sep 2012 15:01:31 +1000 (EST) Received: from ch1outboundpool.messaging.microsoft.com (ch1ehsobe005.messaging.microsoft.com [216.32.181.185]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (Client CN "mail.global.frontbridge.com", Issuer "Microsoft Secure Server Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 8363A2C0095 for ; Thu, 6 Sep 2012 15:00:58 +1000 (EST) Received: from mail14-ch1-R.bigfish.com (10.43.68.240) by CH1EHSOBE013.bigfish.com (10.43.70.63) with Microsoft SMTP Server id 14.1.225.23; Thu, 6 Sep 2012 05:00:53 +0000 Received: from mail14-ch1 (localhost [127.0.0.1]) by mail14-ch1-R.bigfish.com (Postfix) with ESMTP id EB24926017A; Thu, 6 Sep 2012 05:00:52 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275bhz2dh2a8h668h839he5bhf0ah107ah1155h) Received: from mail14-ch1 (localhost.localdomain [127.0.0.1]) by mail14-ch1 (MessageSwitch) id 1346907650490249_19838; Thu, 6 Sep 2012 05:00:50 +0000 (UTC) Received: from CH1EHSMHS005.bigfish.com (snatpool3.int.messaging.microsoft.com [10.43.68.227]) by mail14-ch1.bigfish.com (Postfix) with ESMTP id 6B8601A003F; Thu, 6 Sep 2012 05:00:50 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CH1EHSMHS005.bigfish.com (10.43.70.5) with Microsoft SMTP Server (TLS) id 14.1.225.23; Thu, 6 Sep 2012 05:00:48 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.2.309.3; Thu, 6 Sep 2012 00:00:47 -0500 Received: from localhost.localdomain (rock.ap.freescale.net [10.193.20.106]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id q8650iLX003615; Wed, 5 Sep 2012 22:00:44 -0700 From: Shaohui Xie To: , Subject: [PATCH] [v2] sata_fsl: add workaround for data length mismatch on freescale V2 controller Date: Thu, 6 Sep 2012 12:28:06 +0800 Message-ID: <1346905686-27912-1-git-send-email-Shaohui.Xie@freescale.com> X-Mailer: git-send-email 1.6.4 MIME-Version: 1.0 X-OriginatorOrg: freescale.com Cc: David.Laight@ACULAB.COM, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, Anju Bhartiya , Shaohui Xie X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" 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 Signed-off-by: Anju Bhartiya --- 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 @@ -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,