From patchwork Mon Oct 15 01:51:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Walmsley X-Patchwork-Id: 1591931 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id D7BAE40135 for ; Mon, 15 Oct 2012 01:53:09 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TNZpr-0005Wb-MQ; Mon, 15 Oct 2012 01:51:15 +0000 Received: from utopia.booyaka.com ([74.50.51.50]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TNZpn-0005WI-2H for linux-arm-kernel@lists.infradead.org; Mon, 15 Oct 2012 01:51:13 +0000 Received: (qmail 12050 invoked by uid 1019); 15 Oct 2012 01:51:08 -0000 Date: Mon, 15 Oct 2012 01:51:08 +0000 (UTC) From: Paul Walmsley To: linux-i2c@vger.kernel.org Subject: [PATCH] i2c: omap: revert "i2c: omap: switch to threaded IRQ support" Message-ID: User-Agent: Alpine 2.00 (DEB 1167 2008-08-23) MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Wolfram Sang , Felipe Balbi , Ben Dooks , linux-omap@vger.kernel.org, Shubhrajyoti D , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Commit 3b2f8f82dad7d1f79cdc8fc05bd1c94baf109bde ("i2c: omap: switch to threaded IRQ support") causes communication with I2C devices to fail after system suspend/resume on all OMAP3 devices: ... [ 40.228576] PM: noirq resume of devices complete after 3.723 msecs [ 40.233184] PM: early resume of devices complete after 3.173 msecs [ 40.242736] [sched_delayed] sched: RT throttling activated [ 41.235046] omap_i2c omap_i2c.1: controller timed out [ 41.235351] twl: i2c_read failed to transfer all messages [ 41.235382] omap_hsmmc omap_hsmmc.0: could not set regulator OCR (-110) [ 41.396453] mmc0: error -110 during resume (card was removed?) [ 42.391754] omap_i2c omap_i2c.1: controller timed out [ 42.391876] twl: i2c_write failed to transfer all messages [ 42.391906] twl_rtc: Could not write TWLregister F - error -110 [ 43.391326] omap_i2c omap_i2c.1: controller timed out [ 43.391479] twl: i2c_read failed to transfer all messages [ 43.391510] twl_rtc: Could not read TWLregister D - error -110 [ 43.391540] twl_rtc twl_rtc: twl_rtc_read_time: reading CTRL_REG, error -110 [ 43.392364] PM: resume of devices complete after 3158.935 msecs When the root filesystem is on MMC, as in the above example, the card's voltage regulator is not re-enabled and the filesystem becomes inaccessible after resume. Fix by reverting the conversion to a threaded IRQ handler. Signed-off-by: Paul Walmsley Cc: Felipe Balbi Cc: Shubhrajyoti D Cc: Wolfram Sang Cc: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 44 +++++++---------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index db31eae..e001c2a 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -180,7 +180,6 @@ enum { #define I2C_OMAP_ERRATA_I462 (1 << 1) struct omap_i2c_dev { - spinlock_t lock; /* IRQ synchronization */ struct device *dev; void __iomem *base; /* virtual */ int irq; @@ -865,35 +864,13 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes, } static irqreturn_t -omap_i2c_isr(int irq, void *dev_id) +omap_i2c_isr(int this_irq, void *dev_id) { struct omap_i2c_dev *dev = dev_id; - irqreturn_t ret = IRQ_HANDLED; - u16 mask; - u16 stat; - - spin_lock(&dev->lock); - mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); - - if (stat & mask) - ret = IRQ_WAKE_THREAD; - - spin_unlock(&dev->lock); - - return ret; -} - -static irqreturn_t -omap_i2c_isr_thread(int this_irq, void *dev_id) -{ - struct omap_i2c_dev *dev = dev_id; - unsigned long flags; u16 bits; u16 stat; int err = 0, count = 0; - spin_lock_irqsave(&dev->lock, flags); do { bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); @@ -907,7 +884,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) if (!stat) { /* my work here is done */ - goto out; + return IRQ_HANDLED; } dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); @@ -1016,8 +993,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) omap_i2c_complete_cmd(dev, err); out: - spin_unlock_irqrestore(&dev->lock, flags); - return IRQ_HANDLED; } @@ -1062,6 +1037,7 @@ omap_i2c_probe(struct platform_device *pdev) pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; const struct of_device_id *match; + irq_handler_t isr; int irq; int r; @@ -1110,8 +1086,6 @@ omap_i2c_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->irq = irq; - spin_lock_init(&dev->lock); - platform_set_drvdata(pdev, dev); init_completion(&dev->cmd_complete); @@ -1166,14 +1140,10 @@ omap_i2c_probe(struct platform_device *pdev) /* reset ASAP, clearing any IRQs */ omap_i2c_init(dev); - if (dev->rev < OMAP_I2C_OMAP1_REV_2) - r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr, - IRQF_NO_SUSPEND, pdev->name, dev); - else - r = devm_request_threaded_irq(&pdev->dev, dev->irq, - omap_i2c_isr, omap_i2c_isr_thread, - IRQF_NO_SUSPEND | IRQF_ONESHOT, - pdev->name, dev); + isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr : + omap_i2c_isr; + r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND, + pdev->name, dev); if (r) { dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);