From patchwork Sun Dec 18 14:06:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 132064 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:4978:20e::2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C352EB7013 for ; Mon, 19 Dec 2011 01:08:54 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1RcHNj-00068v-6u; Sun, 18 Dec 2011 14:06:27 +0000 Received: from mail-ee0-f49.google.com ([74.125.83.49]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1RcHNg-00068h-4L for linux-arm-kernel@lists.infradead.org; Sun, 18 Dec 2011 14:06:25 +0000 Received: by eekc13 with SMTP id c13so3442498eek.36 for ; Sun, 18 Dec 2011 06:06:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; bh=rVhBRWhtq/uw9f3FVjYM91W4SwYyB8g+Q6RM4HEPoJQ=; b=pxdwZ674opmHMBRTVDJZmHbsgWZ8awiOtuWnkbdTeY1zVE/IPNfDyn4uY9+a8I2aU1 ea/AzHDjC1sc8LTIdtaiSZQAzHc0NNH21nia9w9esNFJJVmtPCzXPXwJ3eCqLcZlyNaE XhYpRSwYCC9/jXLcZCM6ZDewuRKT4m3exLSn4= Received: by 10.14.49.132 with SMTP id x4mr2662719eeb.115.1324217182087; Sun, 18 Dec 2011 06:06:22 -0800 (PST) Received: from mashiro.kolej.mff.cuni.cz (vasut.kolej.mff.cuni.cz. [78.128.198.52]) by mx.google.com with ESMTPS id q28sm30456271eea.6.2011.12.18.06.06.20 (version=SSLv3 cipher=OTHER); Sun, 18 Dec 2011 06:06:20 -0800 (PST) From: Marek Vasut To: linux-kernel@vger.kernel.org Subject: [PATCH] MXS: Convert mutexes in clock.c to spinlocks Date: Sun, 18 Dec 2011 15:06:13 +0100 Message-Id: <1324217174-6574-1-git-send-email-marek.vasut@gmail.com> X-Mailer: git-send-email 1.7.7.3 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (marek.vasut[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Wolfgang Denk , Huang Shijie , Sascha Hauer , Marek Vasut , linux-arm-kernel@lists.infradead.org, Shawn Guo , Stefano Babic X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org The mutexes can't be safely used under certain circumstances. I noticed this issue during some network instability at home: 1) I received information about duplicate ipv6 address 2) I use amba-pl011 driver for console output Backtrace produced (not 80-per-line aligned): eth0: IPv6 duplicate address XXXX::YYYY:ZZZZ:WWWW:0 detected! ------------[ cut here ]------------ WARNING: at kernel/mutex.c:198 mutex_lock_nested+0x284/0x2c0() Modules linked in: [] (unwind_backtrace+0x0/0xf0) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (mutex_lock_nested+0x284/0x2c0) [] (mutex_lock_nested+0x284/0x2c0) from [] (clk_enable+0x20/0x48) [] (clk_enable+0x20/0x48) from [] (pl011_console_write+0x20/0x74) [] (pl011_console_write+0x20/0x74) from [] (__call_console_drivers+0x7c/0x94) [] (__call_console_drivers+0x7c/0x94) from [] (console_unlock+0xf8/0x244) [] (console_unlock+0xf8/0x244) from [] (vprintk+0x29c/0x484) [] (vprintk+0x29c/0x484) from [] (printk+0x20/0x30) [] (printk+0x20/0x30) from [] (addrconf_dad_failure+0x148/0x158) [] (addrconf_dad_failure+0x148/0x158) from [] (ndisc_rcv+0xb38/0xdb0) [] (ndisc_rcv+0xb38/0xdb0) from [] (icmpv6_rcv+0x6ec/0x9c4) [] (icmpv6_rcv+0x6ec/0x9c4) from [] (ip6_input_finish+0x144/0x4e0) [] (ip6_input_finish+0x144/0x4e0) from [] (ip6_mc_input+0xb8/0x154) [] (ip6_mc_input+0xb8/0x154) from [] (ipv6_rcv+0x300/0x53c) [] (ipv6_rcv+0x300/0x53c) from [] (__netif_receive_skb+0x240/0x420) [] (__netif_receive_skb+0x240/0x420) from [] (process_backlog+0x90/0x150) [] (process_backlog+0x90/0x150) from [] (net_rx_action+0xc0/0x264) [] (net_rx_action+0xc0/0x264) from [] (__do_softirq+0xa8/0x214) [] (__do_softirq+0xa8/0x214) from [] (irq_exit+0x8c/0x94) [] (irq_exit+0x8c/0x94) from [] (handle_IRQ+0x34/0x84) [] (handle_IRQ+0x34/0x84) from [] (__irq_usr+0x38/0x80) ---[ end trace 32eab6a8dcdca9c0 ]--- So the problem summary: 1) ICMPv6 packet is received 2) Interrupt is produced, packet is actually received 3) Packet processing goes on (in tasklet) 4) Duplicate ipv6 address detected, warning produced 5) printk() called, calls pl011_console_write() 6) pl011_console_write() calls clk_enable() 7) clk_enable() for mxs does a mutex_lock(), which is wrong in this context Signed-off-by: Marek Vasut Cc: Wolfgang Denk Cc: Stefano Babic Cc: Shawn Guo Cc: Huang Shijie Cc: Sascha Hauer --- arch/arm/mach-mxs/clock.c | 25 +++++++++++++++---------- 1 files changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-mxs/clock.c b/arch/arm/mach-mxs/clock.c index a7093c8..677ecff 100644 --- a/arch/arm/mach-mxs/clock.c +++ b/arch/arm/mach-mxs/clock.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -41,7 +41,7 @@ #include static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); +static DEFINE_SPINLOCK(clocks_lock); /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h @@ -80,13 +80,14 @@ static int __clk_enable(struct clk *clk) int clk_enable(struct clk *clk) { int ret = 0; + unsigned long flags; if (clk == NULL || IS_ERR(clk)) return -EINVAL; - mutex_lock(&clocks_mutex); + spin_lock_irqsave(&clocks_lock, flags); ret = __clk_enable(clk); - mutex_unlock(&clocks_mutex); + spin_unlock_irqrestore(&clocks_lock, flags); return ret; } @@ -98,12 +99,14 @@ EXPORT_SYMBOL(clk_enable); */ void clk_disable(struct clk *clk) { + unsigned long flags; + if (clk == NULL || IS_ERR(clk)) return; - mutex_lock(&clocks_mutex); + spin_lock_irqsave(&clocks_lock, flags); __clk_disable(clk); - mutex_unlock(&clocks_mutex); + spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -142,14 +145,15 @@ EXPORT_SYMBOL(clk_round_rate); */ int clk_set_rate(struct clk *clk, unsigned long rate) { + unsigned long flags; int ret = -EINVAL; if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0) return ret; - mutex_lock(&clocks_mutex); + spin_lock_irqsave(&clocks_lock, flags); ret = clk->set_rate(clk, rate); - mutex_unlock(&clocks_mutex); + spin_unlock_irqrestore(&clocks_lock, flags); return ret; } @@ -160,6 +164,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) { int ret = -EINVAL; struct clk *old; + unsigned long flags; if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent) || clk->set_parent == NULL) @@ -168,7 +173,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) if (clk->usecount) clk_enable(parent); - mutex_lock(&clocks_mutex); + spin_lock_irqsave(&clocks_lock, flags); ret = clk->set_parent(clk, parent); if (ret == 0) { old = clk->parent; @@ -176,7 +181,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) } else { old = parent; } - mutex_unlock(&clocks_mutex); + spin_unlock_irqrestore(&clocks_lock, flags); if (clk->usecount) clk_disable(old);