From patchwork Tue Aug 18 11:10:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 508263 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A56DC1406A9 for ; Tue, 18 Aug 2015 21:11:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751321AbbHRLLW (ORCPT ); Tue, 18 Aug 2015 07:11:22 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:59485 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752707AbbHRLLU (ORCPT ); Tue, 18 Aug 2015 07:11:20 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id t7IBBBup027491; Tue, 18 Aug 2015 06:11:11 -0500 Received: from DLEE70.ent.ti.com (dlemailx.itg.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id t7IBBBrv012522; Tue, 18 Aug 2015 06:11:11 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.224.2; Tue, 18 Aug 2015 06:11:11 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id t7IBBAdW007177; Tue, 18 Aug 2015 06:11:10 -0500 From: Grygorii Strashko To: Linus Walleij , Alexandre Courbot , , Kevin Hilman , CC: Javier Martinez Canillas , , , , Grygorii Strashko , Subject: [RFC PATCH 6/7] gpio: omap: move pm runtime in irq_chip.irq_bus_lock/sync_unlock Date: Tue, 18 Aug 2015 14:10:57 +0300 Message-ID: <1439896258-26449-7-git-send-email-grygorii.strashko@ti.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1439896258-26449-1-git-send-email-grygorii.strashko@ti.com> References: <1439896258-26449-1-git-send-email-grygorii.strashko@ti.com> MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The PM runtime API can't be used in atomic contex on -RT even if it's configured as irqsafe. As result, below error report can be seen when PM runtime API called from IRQ chip's callbacks irq_startup/irq_shutdown/irq_set_type, because they are protected by RAW spinlock: BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917 in_atomic(): 1, irqs_disabled(): 128, pid: 96, name: insmod 3 locks held by insmod/96: #0: (&dev->mutex){......}, at: [] __driver_attach+0x54/0xa0 #1: (&dev->mutex){......}, at: [] __driver_attach+0x60/0xa0 #2: (class){......}, at: [] __irq_get_desc_lock+0x60/0xa4 irq event stamp: 1834 hardirqs last enabled at (1833): [] _raw_spin_unlock_irqrestore+0x88/0x90 hardirqs last disabled at (1834): [] _raw_spin_lock_irqsave+0x2c/0x64 softirqs last enabled at (0): [] copy_process.part.52+0x410/0x19d8 softirqs last disabled at (0): [< (null)>] (null) Preemption disabled at:[< (null)>] (null) CPU: 1 PID: 96 Comm: insmod Tainted: G W O 4.1.3-rt3-00618-g57e2387-dirty #184 Hardware name: Generic DRA74X (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [] (show_stack) from [] (dump_stack+0x88/0xdc) [] (dump_stack) from [] (___might_sleep+0x198/0x2a8) [] (___might_sleep) from [] (rt_spin_lock+0x30/0x70) [] (rt_spin_lock) from [] (__pm_runtime_resume+0x68/0xa4) [] (__pm_runtime_resume) from [] (omap_gpio_irq_type+0x188/0x1d8) [] (omap_gpio_irq_type) from [] (__irq_set_trigger+0x68/0x130) [] (__irq_set_trigger) from [] (irq_set_irq_type+0x44/0x6c) [] (irq_set_irq_type) from [] (irq_create_of_mapping+0x120/0x174) [] (irq_create_of_mapping) from [] (of_irq_get+0x48/0x58) [] (of_irq_get) from [] (i2c_device_probe+0x54/0x15c) [] (i2c_device_probe) from [] (driver_probe_device+0x184/0x2c8) [] (driver_probe_device) from [] (__driver_attach+0x9c/0xa0) [] (__driver_attach) from [] (bus_for_each_dev+0x7c/0xb0) [] (bus_for_each_dev) from [] (driver_attach+0x28/0x30) [] (driver_attach) from [] (bus_add_driver+0x154/0x200) [] (bus_add_driver) from [] (driver_register+0x88/0x108) [] (driver_register) from [] (i2c_register_driver+0x3c/0x90) [] (i2c_register_driver) from [] (pcf857x_init+0x18/0x24 [gpio_pcf857x]) [] (pcf857x_init [gpio_pcf857x]) from [] (do_one_initcall+0x128/0x1e8) [] (do_one_initcall) from [] (do_init_module+0x6c/0x1bc) [] (do_init_module) from [] (load_module+0x18e8/0x21c4) [] (load_module) from [] (SyS_init_module+0xfc/0x158) [] (SyS_init_module) from [] (ret_fast_syscall+0x0/0x54) The IRQ chip interface defines only two callbacks which are executed in non-atomic contex - irq_bus_lock/irq_bus_sync_unlock, so lets move PM runtime calls there. Cc: Signed-off-by: Grygorii Strashko --- drivers/gpio/gpio-omap.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 2ae0d47..c33595e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -496,9 +496,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) return -EINVAL; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - raw_spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); if (retval) { @@ -521,8 +518,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) return 0; error: - if (!BANK_USED(bank)) - pm_runtime_put(bank->dev); return retval; } @@ -797,9 +792,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) unsigned long flags; unsigned offset = d->hwirq; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - raw_spin_lock_irqsave(&bank->lock, flags); if (!LINE_USED(bank->mod_usage, offset)) @@ -815,8 +807,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) return 0; err: raw_spin_unlock_irqrestore(&bank->lock, flags); - if (!BANK_USED(bank)) - pm_runtime_put(bank->dev); return -EINVAL; } @@ -835,6 +825,19 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) omap_clear_gpio_debounce(bank, offset); omap_disable_gpio_module(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); +} + +static void omap_gpio_irq_bus_lock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); + + if (!BANK_USED(bank)) + pm_runtime_get_sync(bank->dev); +} + +static void gpio_irq_bus_sync_unlock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); /* * If this is the last IRQ to be freed in the bank, @@ -1181,6 +1184,8 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_unmask = omap_gpio_unmask_irq, irqc->irq_set_type = omap_gpio_irq_type, irqc->irq_set_wake = omap_gpio_wake_enable, + irqc->irq_bus_lock = omap_gpio_irq_bus_lock, + irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); bank->irq = platform_get_irq(pdev, 0);