119 lines
4.8 KiB
Diff
119 lines
4.8 KiB
Diff
From linux-omap-owner@vger.kernel.org Tue Jul 15 21:23:13 2008
|
|
Received: from localhost
|
|
([127.0.0.1] helo=dominion ident=koen)
|
|
by dominion.dominion.void with esmtp (Exim 4.69)
|
|
(envelope-from <linux-omap-owner@vger.kernel.org>)
|
|
id 1KIq7E-0004FX-VS
|
|
for koen@localhost; Tue, 15 Jul 2008 21:23:13 +0200
|
|
Received: from xs.service.utwente.nl [130.89.5.250]
|
|
by dominion with POP3 (fetchmail-6.3.6)
|
|
for <koen@localhost> (single-drop); Tue, 15 Jul 2008 21:23:12 +0200 (CEST)
|
|
Received: from mail.service.utwente.nl ([130.89.5.254]) by exchange.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
|
|
Tue, 15 Jul 2008 21:01:02 +0200
|
|
Received: from mx.utwente.nl ([130.89.2.12]) by mail.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
|
|
Tue, 15 Jul 2008 21:01:01 +0200
|
|
Received: from vger.kernel.org (vger.kernel.org [209.132.176.167])
|
|
by mx.utwente.nl (8.12.10/SuSE Linux 0.7) with ESMTP id m6FJ0qDf031889
|
|
for <k.kooi@student.utwente.nl>; Tue, 15 Jul 2008 21:00:52 +0200
|
|
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
|
id S1756776AbYGOTAV (ORCPT <rfc822;k.kooi@student.utwente.nl>);
|
|
Tue, 15 Jul 2008 15:00:21 -0400
|
|
Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755065AbYGOTAV
|
|
(ORCPT <rfc822;linux-omap-outgoing>);
|
|
Tue, 15 Jul 2008 15:00:21 -0400
|
|
Received: from utopia.booyaka.com ([72.9.107.138]:35569 "EHLO
|
|
utopia.booyaka.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
|
with ESMTP id S1756776AbYGOTAU (ORCPT
|
|
<rfc822;linux-omap@vger.kernel.org>); Tue, 15 Jul 2008 15:00:20 -0400
|
|
Received: (qmail 2982 invoked by uid 526); 15 Jul 2008 19:00:18 -0000
|
|
Date: Tue, 15 Jul 2008 13:00:18 -0600 (MDT)
|
|
From: Paul Walmsley <paul@pwsan.com>
|
|
To: linux-omap@vger.kernel.org
|
|
Subject: [PATCH] i2c-omap: close suspected race between omap_i2c_idle() and
|
|
omap_i2c_isr()
|
|
Message-ID: <alpine.DEB.1.00.0807151259180.467@utopia.booyaka.com>
|
|
User-Agent: Alpine 1.00 (DEB 882 2007-12-20)
|
|
MIME-Version: 1.0
|
|
Content-Type: TEXT/PLAIN; charset=US-ASCII
|
|
Sender: linux-omap-owner@vger.kernel.org
|
|
Precedence: bulk
|
|
List-ID: <linux-omap.vger.kernel.org>
|
|
X-Mailing-List: linux-omap@vger.kernel.org
|
|
X-UTwente-MailScanner-Information: Scanned by MailScanner. Contact servicedesk@icts.utwente.nl for more information.
|
|
X-UTwente-MailScanner: Found to be clean
|
|
X-UTwente-MailScanner-From: linux-omap-owner@vger.kernel.org
|
|
X-Spam-Status: No
|
|
X-OriginalArrivalTime: 15 Jul 2008 19:01:01.0610 (UTC) FILETIME=[1FBA68A0:01C8E6AD]
|
|
|
|
|
|
omap_i2c_idle() sets an internal flag, "dev->idle", instructing its
|
|
ISR to decline interrupts. It sets this flag before it actually masks
|
|
the interrupts on the I2C controller. This is problematic, since an
|
|
I2C interrupt could arrive after dev->idle is set, but before the
|
|
interrupt source is masked. When this happens, Linux disables the I2C
|
|
controller's IRQ, causing all future transactions on the bus to fail.
|
|
|
|
Symptoms, happening on about 7% of boots:
|
|
|
|
irq 56: nobody cared (try booting with the "irqpoll" option)
|
|
<warning traceback here>
|
|
Disabling IRQ #56
|
|
i2c_omap i2c_omap.1: controller timed out
|
|
|
|
In omap_i2c_idle(), this patch sets dev->idle only after the interrupt
|
|
mask write to the I2C controller has left the ARM write buffer.
|
|
That's probably the major offender. For additional prophylaxis, in
|
|
omap_i2c_unidle(), the patch clears the dev->idle flag before
|
|
interrupts are enabled, rather than afterwards.
|
|
|
|
The patch has survived twenty-two reboots on the 3430SDP here without
|
|
wedging I2C1. Not absolutely dispositive, but promising!
|
|
|
|
|
|
Signed-off-by: Paul Walmsley <paul@pwsan.com>
|
|
---
|
|
|
|
drivers/i2c/busses/i2c-omap.c | 10 ++++++++--
|
|
1 files changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
|
|
index 55779f5..ed7e9ad 100644
|
|
--- a/drivers/i2c/busses/i2c-omap.c
|
|
+++ b/drivers/i2c/busses/i2c-omap.c
|
|
@@ -209,22 +209,28 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
|
|
if (dev->iclk != NULL)
|
|
clk_enable(dev->iclk);
|
|
clk_enable(dev->fclk);
|
|
+ dev->idle = 0;
|
|
if (dev->iestate)
|
|
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
|
|
- dev->idle = 0;
|
|
}
|
|
|
|
static void omap_i2c_idle(struct omap_i2c_dev *dev)
|
|
{
|
|
u16 iv;
|
|
|
|
- dev->idle = 1;
|
|
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
|
|
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
|
|
if (dev->rev1)
|
|
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
|
|
else
|
|
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
|
|
+ /*
|
|
+ * The wmb() is to ensure that the I2C interrupt mask write
|
|
+ * reaches the I2C controller before the dev->idle store
|
|
+ * occurs.
|
|
+ */
|
|
+ wmb();
|
|
+ dev->idle = 1;
|
|
clk_disable(dev->fclk);
|
|
if (dev->iclk != NULL)
|
|
clk_disable(dev->iclk);
|
|
--
|
|
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
|
|
the body of a message to majordomo@vger.kernel.org
|
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
|
|