diff options
-rw-r--r-- | packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff | 118 | ||||
-rw-r--r-- | packages/linux/linux-omap2_git.bb | 3 |
2 files changed, 120 insertions, 1 deletions
diff --git a/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff b/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff new file mode 100644 index 0000000000..6eb33f76b7 --- /dev/null +++ b/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff @@ -0,0 +1,118 @@ +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 + diff --git a/packages/linux/linux-omap2_git.bb b/packages/linux/linux-omap2_git.bb index 53bcd297d9..800a0eb02e 100644 --- a/packages/linux/linux-omap2_git.bb +++ b/packages/linux/linux-omap2_git.bb @@ -5,7 +5,7 @@ FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/linux-omap2-git/${MA SRCREV = "7786cd7a00ae0b18923185789380a88052f4eee7" PV = "2.6.25+2.6.26-rc9+${PR}+git${SRCREV}" -PR = "r44" +PR = "r45" SRC_URI = "git://source.mvista.com/git/linux-omap-2.6.git;protocol=git \ file://defconfig" @@ -30,6 +30,7 @@ SRC_URI_append_beagleboard = " file://no-harry-potter.diff;patch=1 \ file://07-set-burst-size.diff;patch=1 \ file://cache-display-fix.patch;patch=1 \ file://serialfix.diff;patch=1 \ + file://i2c-omap-race-fix.diff;patch=1 \ " SRC_URI_append_omap3evm = " file://no-harry-potter.diff;patch=1 \ |