From patchwork Mon May 30 01:08:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 68819 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp1159867qge; Sun, 29 May 2016 18:10:50 -0700 (PDT) X-Received: by 10.98.103.86 with SMTP id b83mr34658972pfc.141.1464570650625; Sun, 29 May 2016 18:10:50 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ss2si46764056pab.111.2016.05.29.18.10.50; Sun, 29 May 2016 18:10:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753452AbcE3BJc (ORCPT + 30 others); Sun, 29 May 2016 21:09:32 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:33798 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753399AbcE3BJS (ORCPT ); Sun, 29 May 2016 21:09:18 -0400 Received: by mail-pf0-f193.google.com with SMTP id c84so12942603pfc.1; Sun, 29 May 2016 18:09:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=tTwAVBFmwLdNXzczWBftRrDOgJUIXY0nHbtMmdXqUt0=; b=Gq5L8CcSjVIFdudQD5gwMOmKgIK3wqCDZUPoD9qn/FdKQhCV24DD36IbbzGMxSkJjQ wMi7+TSrJgTMvjwL5XElYXRjp8cHDhbPCYB5N0Xkhs35UADMBDpPhpLFo27FhHVYgfPF eTygkw1LqXrgP7tcO91JnzCsnG8HZnlrZB2eqbJJIhlOF7/HRaGEPyg53aHBF7IgVc2y bmBUMKkS+ZTplF4Dx4hC0STyHG1KFKfmp0hb5qwgbqw99XKG1Z+jdQj1kULQSP9Ol0Bv 8H763LWWrTtrIo85XquUyQtenF2sceNA+L9oJNCI+NUmR7tAGihLCAdAT6p5ub3+kfV3 Ij0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=tTwAVBFmwLdNXzczWBftRrDOgJUIXY0nHbtMmdXqUt0=; b=WiWgMJiDeq5hw+hzltwYBcqv0zmwtSctKKKdQoocizRm9kCzQ8UutXc61nVCTByML/ B6bAGMHXZBFHAxJ+dvV486DvbHGENkqPlj2X94CxnVYP/SY3eK5Wcm/Xm3tCYbiRus9W Z6DFZdMkthOf55ag1bGQ6cFBjeYRnK5kGr/2+b263uskmkXiEWu/fh1nROAJ+P0RzRVM tbdF8z8wX7ViwjypVwTQAUjDNsqWY+PwkX41u1QZZZ8qMtW2BA68/ePgQEpVNl702mz+ DELlx8r9AwgAlsr3nCHFEqFumRWiLSl6+WugWycOTXU5+vdnRXlIE41EWr44v42uq5nK 4+jw== X-Gm-Message-State: ALyK8tLWz0wwhe6B1LyCinwM+6zEARvJpMcrxw8tQySG0B59DIjE3+AieD47QebQMCUlww== X-Received: by 10.98.22.141 with SMTP id 135mr41441319pfw.116.1464570557152; Sun, 29 May 2016 18:09:17 -0700 (PDT) Received: from serve.minyard.net ([108.19.215.157]) by smtp.gmail.com with ESMTPSA id a17sm28191454pfa.70.2016.05.29.18.09.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 29 May 2016 18:09:15 -0700 (PDT) Received: from t430.minyard.net (t430m.minyard.net [192.168.27.3]) by serve.minyard.net (Postfix) with ESMTPA id ACD67BB4; Sun, 29 May 2016 20:09:12 -0500 (CDT) Received: by t430.minyard.net (Postfix, from userid 1000) id 095F3300522; Sun, 29 May 2016 20:09:08 -0500 (CDT) From: minyard@acm.org To: Jean Delvare , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, minyard@acm.org Cc: Corey Minyard Subject: [PATCH v2 05/10] i2c-i801: Consolidate calls to i801_check_post Date: Sun, 29 May 2016 20:08:59 -0500 Message-Id: <1464570544-975-6-git-send-email-minyard@acm.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1464570544-975-1-git-send-email-minyard@acm.org> References: <1464570544-975-1-git-send-email-minyard@acm.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Corey Minyard This was almost always called at the end of the transaction. The only time it wasn't called was when a protocol violation occurred, and the error reporting was inconsistent there. So have the transaction functions return positive status or a negative error if they detect an issue. If a protocol violation does occur, always do a kill operation on the bus instead of just trying to finish the operation. If there was a hardware issue, the code that was there to terminate the transaction could loop forever, and the kill seems more appropriate if something goes grossly wrong. Signed-off-by: Corey Minyard --- drivers/i2c/busses/i2c-i801.c | 51 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 26 deletions(-) -- 2.7.4 diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 8794e70..56db310 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -317,7 +317,13 @@ static int i801_check_post(struct i801_priv *priv, int status) * DEV_ERR. */ if (unlikely(status < 0)) { - dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); + result = status; + if (status == -EPROTO) + dev_err(&priv->pci_dev->dev, + "Illegal SMBus block read size %d\n", + priv->len); + else + dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); /* try to stop the current command */ dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, @@ -333,7 +339,7 @@ static int i801_check_post(struct i801_priv *priv, int status) dev_err(&priv->pci_dev->dev, "Failed terminating the transaction\n"); outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); - return -ETIMEDOUT; + return result; } if (status & SMBHSTSTS_FAILED) { @@ -414,15 +420,14 @@ static int i801_transaction(struct i801_priv *priv, int xact) "Timeout waiting for interrupt!\n"); } priv->status = 0; - return i801_check_post(priv, status); + return status; } /* the current contents of SMBHSTCNT can be overwritten, since PEC, * SMBSCMD are passed in xact */ outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); - status = i801_wait_intr(priv); - return i801_check_post(priv, status); + return i801_wait_intr(priv); } static int i801_block_transaction_by_block(struct i801_priv *priv, @@ -444,11 +449,11 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, status = i801_transaction(priv, I801_BLOCK_DATA | (hwpec ? SMBHSTCNT_PEC_EN : 0)); - if (status) + if (status < 0 || status & STATUS_ERROR_FLAGS) return status; if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0(priv)); + len = priv->len = inb_p(SMBHSTDAT0(priv)); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) return -EPROTO; @@ -456,7 +461,7 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, for (i = 0; i < len; i++) data->block[i + 1] = inb_p(SMBBLKDAT(priv)); } - return 0; + return status; } static void i801_isr_byte_done(struct i801_priv *priv) @@ -590,7 +595,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, "Timeout waiting for interrupt!\n"); } priv->status = 0; - return i801_check_post(priv, status); + return status; } for (i = 1; i <= len; i++) { @@ -604,24 +609,14 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, status = i801_wait_byte_done(priv); if (status) - goto exit; + return status; if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&priv->pci_dev->dev, - "Illegal SMBus block read size %d\n", - len); - /* Recover */ - while (inb_p(SMBHSTSTS(priv)) & - SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, - SMBHSTSTS(priv)); - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); + priv->len = inb_p(SMBHSTDAT0(priv)); + if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) return -EPROTO; - } - data->block[0] = len; + data->block[0] = len = priv->len; } /* Retrieve/store value in SMBBLKDAT */ @@ -634,9 +629,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); } - status = i801_wait_intr(priv); -exit: - return i801_check_post(priv, status); + return i801_wait_intr(priv); } static int i801_set_block_buffer_mode(struct i801_priv *priv) @@ -791,6 +784,12 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, else ret = i801_transaction(priv, xact); + /* + * ret can be status if positive or an error if negative. Let + * the post check handle it. + */ + ret = i801_check_post(priv, ret); + if (hostc >= 0) pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);