From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964866AbaEKTkz (ORCPT ); Sun, 11 May 2014 15:40:55 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:48353 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933678AbaEKTY7 (ORCPT ); Sun, 11 May 2014 15:24:59 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Marek Vasut , Shawn Guo , Linus Walleij Subject: [PATCH 3.10 37/48] gpio: mxs: Allow for recursive enable_irq_wake() call Date: Sun, 11 May 2014 21:20:11 +0200 Message-Id: <20140511191953.109596734@linuxfoundation.org> X-Mailer: git-send-email 1.9.0 In-Reply-To: <20140511191948.079900414@linuxfoundation.org> References: <20140511191948.079900414@linuxfoundation.org> User-Agent: quilt/0.60-1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Marek Vasut commit a585f87c863e4e1d496459d382b802bf5ebe3717 upstream. The scenario here is that someone calls enable_irq_wake() from somewhere in the code. This will result in the lockdep producing a backtrace as can be seen below. In my case, this problem is triggered when using the wl1271 (TI WlCore) driver found in drivers/net/wireless/ti/ . The problem cause is rather obvious from the backtrace, but let's outline the dependency. enable_irq_wake() grabs the IRQ buslock in irq_set_irq_wake(), which in turns calls mxs_gpio_set_wake_irq() . But mxs_gpio_set_wake_irq() calls enable_irq_wake() again on the one-level-higher IRQ , thus it tries to grab the IRQ buslock again in irq_set_irq_wake() . Because the spinlock in irq_set_irq_wake()->irq_get_desc_buslock()->__irq_get_desc_lock() is not marked as recursive, lockdep will spew the stuff below. We know we can safely re-enter the lock, so use IRQ_GC_INIT_NESTED_LOCK to fix the spew. ============================================= [ INFO: possible recursive locking detected ] 3.10.33-00012-gf06b763-dirty #61 Not tainted --------------------------------------------- kworker/0:1/18 is trying to acquire lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x48/0x88 but task is already holding lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x48/0x88 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&irq_desc_lock_class); lock(&irq_desc_lock_class); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by kworker/0:1/18: #0: (events){.+.+.+}, at: [] process_one_work+0x134/0x4a4 #1: ((&fw_work->work)){+.+.+.}, at: [] process_one_work+0x134/0x4a4 #2: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x48/0x88 stack backtrace: CPU: 0 PID: 18 Comm: kworker/0:1 Not tainted 3.10.33-00012-gf06b763-dirty #61 Workqueue: events request_firmware_work_func [] (unwind_backtrace+0x0/0xf0) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (__lock_acquire+0x140c/0x1a64) [] (__lock_acquire+0x140c/0x1a64) from [] (lock_acquire+0x9c/0x104) [] (lock_acquire+0x9c/0x104) from [] (_raw_spin_lock_irqsave+0x44/0x58) [] (_raw_spin_lock_irqsave+0x44/0x58) from [] (__irq_get_desc_lock+0x48/0x88) [] (__irq_get_desc_lock+0x48/0x88) from [] (irq_set_irq_wake+0x20/0xf4) [] (irq_set_irq_wake+0x20/0xf4) from [] (mxs_gpio_set_wake_irq+0x1c/0x24) [] (mxs_gpio_set_wake_irq+0x1c/0x24) from [] (set_irq_wake_real+0x30/0x44) [] (set_irq_wake_real+0x30/0x44) from [] (irq_set_irq_wake+0x8c/0xf4) [] (irq_set_irq_wake+0x8c/0xf4) from [] (wlcore_nvs_cb+0x10c/0x97c) [] (wlcore_nvs_cb+0x10c/0x97c) from [] (request_firmware_work_func+0x38/0x58) [] (request_firmware_work_func+0x38/0x58) from [] (process_one_work+0x1c0/0x4a4) [] (process_one_work+0x1c0/0x4a4) from [] (worker_thread+0x138/0x394) [] (worker_thread+0x138/0x394) from [] (kthread+0xa4/0xb0) [] (kthread+0xa4/0xb0) from [] (ret_from_fork+0x14/0x34) wlcore: loaded Signed-off-by: Marek Vasut Acked-by: Shawn Guo Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-mxs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -214,7 +214,8 @@ static void __init mxs_gpio_init_gc(stru ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; ct->regs.mask = PINCTRL_IRQEN(port); - irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); + irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, + IRQ_NOREQUEST, 0); } static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)