From patchwork Thu Sep 14 15:39:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudio Foellmi X-Patchwork-Id: 813889 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xtNJL61Glz9s9Y for ; Fri, 15 Sep 2017 01:49:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751370AbdINPtg (ORCPT ); Thu, 14 Sep 2017 11:49:36 -0400 Received: from mx2.ergon.ch ([87.239.214.74]:56363 "EHLO mx2.ergon.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751255AbdINPtg (ORCPT ); Thu, 14 Sep 2017 11:49:36 -0400 X-Greylist: delayed 588 seconds by postgrey-1.27 at vger.kernel.org; Thu, 14 Sep 2017 11:49:35 EDT X-IronPort-AV: E=Sophos;i="5.42,393,1500933600"; d="scan'208";a="469001" Received: from mahler.ergon.ch ([87.239.208.18]) by mx2.ergon.ch with ESMTP; 14 Sep 2017 17:39:46 +0200 Received: from crespo.ergon.ch (crespo.ergon.ch [87.239.211.231]) by mahler.ergon.ch (Postfix) with ESMTP id 6A71BEE83; Thu, 14 Sep 2017 17:39:46 +0200 (MEST) From: Claudio Foellmi To: Tony Lindgren Cc: Claudio Foellmi , Aaro Koskinen , Wolfram Sang , linux-omap@vger.kernel.org, linux-i2c@vger.kernel.org Subject: [PATCH] i2c-omap: Trigger bus recovery in lockup case Date: Thu, 14 Sep 2017 17:39:09 +0200 Message-Id: <1505403549-12992-1-git-send-email-claudio.foellmi@ergon.ch> X-Mailer: git-send-email 2.7.4 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org A very conservative check for bus activity (to prevent interference in multimaster setups) prevented the bus recovery methods from being triggered in the case that SDA or SCL was stuck low. This defeats the purpose of the recovery mechanism, which was introduced for exactly this situation (a slave device keeping SDA pulled down). Note that bus lockups can persist across reboots. The only other options are to reset or power cycle the offending slave device, and many i2c slaves do not even have a reset pin. If we see that one of the lines is low for the entire timeout duration, we can actually be sure that there is no other master driving the bus. It is therefore save for us to attempt a bus recovery. Signed-off-by: Claudio Foellmi Reviewed-by: Grygorii Strashko Signed-off-by: Claudio Foellmi --- Caveat: It turns out I don't have the hardware to fully test the recovery mechanism. My faulty i2c slave device actually pulls down SCL, not SDA (so the recovery will not succeed in my case). But by directly connecting SDA to ground, I could at least make sure the recovery function gets called after applying this patch. drivers/i2c/busses/i2c-omap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 1ebb5e9..4b25fd1 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -563,8 +563,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap) } if (time_after(jiffies, timeout)) { + /* + * SDA or SCL were low for the entire timeout without + * any activity detected. Most likely, a slave is + * locking up the bus with no master driving the clock. + */ dev_warn(omap->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; + return i2c_recover_bus(&omap->adapter); } msleep(1);