From patchwork Wed Jan 20 09:13:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 60013 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp3057942lbb; Wed, 20 Jan 2016 01:14:00 -0800 (PST) X-Received: by 10.66.122.72 with SMTP id lq8mr50918250pab.1.1453281240137; Wed, 20 Jan 2016 01:14:00 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ln6si15696065pab.182.2016.01.20.01.13.59; Wed, 20 Jan 2016 01:14:00 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933913AbcATJN6 (ORCPT + 11 others); Wed, 20 Jan 2016 04:13:58 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:61923 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933901AbcATJNy (ORCPT ); Wed, 20 Jan 2016 04:13:54 -0500 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout1.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O18007BZUZ35R50@mailout1.w1.samsung.com>; Wed, 20 Jan 2016 09:13:51 +0000 (GMT) X-AuditID: cbfec7f5-f79b16d000005389-c2-569f4fcfa0ec Received: from eusync1.samsung.com ( [203.254.199.211]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 10.92.21385.FCF4F965; Wed, 20 Jan 2016 09:13:51 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O18001LCUYZXZ30@eusync1.samsung.com>; Wed, 20 Jan 2016 09:13:51 +0000 (GMT) From: Marek Szyprowski To: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Marek Szyprowski , Ulf Hansson , Kevin Hilman , "Rafael J. Wysocki" , Anand Moon , Bartlomiej Zolnierkiewicz , Daniel Kurtz , Nicolas Boichat Subject: [PATCH RESEND] power: genpd: fix lockdep issue for all subdomains Date: Wed, 20 Jan 2016 10:13:42 +0100 Message-id: <1453281222-19055-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: References: X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrDLMWRmVeSWpSXmKPExsVy+t/xy7rn/eeHGXy/yWuxccZ6VovGGfNZ LVZfWcFi8XTzYyaLy7vmsFl87j3CaLFu4y12i7VH7rJbnDl9idXi+NpwBy6P2Q0XWTx2zrrL 7rFpVSebx51re9g8tlxtZ/Ho27KK0ePzJrkA9igum5TUnMyy1CJ9uwSujK2brrIV7NOquHu/ kb2BcatKFyMnh4SAiURb9wF2CFtM4sK99WxdjFwcQgJLGSUmt91lAUkICTQxSax/CFbEJmAo 0fW2iw3EFhGwkjj9v4MZpIFZ4CKTxOm9C1hBEsICXhKLGo4xg9gsAqoSR368AxvEK+Ah8XfJ LFaIbXIS/1+uYAKxOQWCJU793MEEsSxAYu/zs6wTGHkXMDKsYhRNLU0uKE5KzzXSK07MLS7N S9dLzs/dxAgJw687GJceszrEKMDBqMTDy9g8L0yINbGsuDL3EKMEB7OSCG+K/vwwId6UxMqq 1KL8+KLSnNTiQ4zSHCxK4rwzd70PERJITyxJzU5NLUgtgskycXBKNTC6H6y2tHE49Ozyp3vp CZ3/Z1UX7Pv4assVOSfx67/2ZNbb90mFvj2j27VFf9vTfPus02/9zv6znW8c3Nmd1cNzdsnf smVHGkUeb9JbX2F+6gRf+NEtC77+cKhifnqZq/DPjBXvbwp5/D/Yd/XO9ZNuCSIv1FcVbmL8 dPeQ/ll9pxsrV8ZfqJwuqcRSnJFoqMVcVJwIABXCd50/AgAA Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org During genpd_poweron, genpd->lock is acquired recursively for each parent (master) domain, which are separate objects. This confuses lockdep, which considers every operation on genpd->lock as being done on the same lock class. This leads to the following false positive warning: -- 1.9.2 -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ============================================= [ INFO: possible recursive locking detected ] 4.4.0-rc4-xu3s #32 Not tainted --------------------------------------------- swapper/0/1 is trying to acquire lock: (&genpd->lock){+.+...}, at: [] __genpd_poweron+0x64/0x108 but task is already holding lock: (&genpd->lock){+.+...}, at: [] genpd_dev_pm_attach+0x168/0x1b8 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&genpd->lock); lock(&genpd->lock); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by swapper/0/1: #0: (&dev->mutex){......}, at: [] __driver_attach+0x48/0x98 #1: (&dev->mutex){......}, at: [] __driver_attach+0x58/0x98 #2: (&genpd->lock){+.+...}, at: [] genpd_dev_pm_attach+0x168/0x1b8 stack backtrace: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-rc4-xu3s #32 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x84/0xc4) [] (dump_stack) from [] (__lock_acquire+0x1f88/0x215c) [] (__lock_acquire) from [] (lock_acquire+0xa4/0xd0) [] (lock_acquire) from [] (mutex_lock_nested+0x70/0x4d4) [] (mutex_lock_nested) from [] (__genpd_poweron+0x64/0x108) [] (__genpd_poweron) from [] (genpd_dev_pm_attach+0x170/0x1b8) [] (genpd_dev_pm_attach) from [] (platform_drv_probe+0x2c/0xac) [] (platform_drv_probe) from [] (driver_probe_device+0x208/0x2fc) [] (driver_probe_device) from [] (__driver_attach+0x94/0x98) [] (__driver_attach) from [] (bus_for_each_dev+0x68/0x9c) [] (bus_for_each_dev) from [] (bus_add_driver+0x1a0/0x218) [] (bus_add_driver) from [] (driver_register+0x78/0xf8) [] (driver_register) from [] (exynos_drm_register_drivers+0x28/0x74) [] (exynos_drm_register_drivers) from [] (exynos_drm_init+0x6c/0xc4) [] (exynos_drm_init) from [] (do_one_initcall+0x90/0x1dc) [] (do_one_initcall) from [] (kernel_init_freeable+0x158/0x1f8) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xe8) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) This patch replaces mutex_lock with mutex_lock_nested() and uses recursion depth to annotate each genpd->lock operation with separate lockdep subclass. Reported-by: Anand Moon Signed-off-by: Marek Szyprowski Tested-by: Anand Moon Tested-by: Tobias Jakobi Acked-by: Ulf Hansson --- drivers/base/power/domain.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b803790..e02ddf6 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -170,16 +170,15 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) queue_work(pm_wq, &genpd->power_off_work); } -static int genpd_poweron(struct generic_pm_domain *genpd); - /** * __genpd_poweron - Restore power to a given PM domain and its masters. * @genpd: PM domain to power up. + * @depth: nesting count for lockdep. * * Restore power to @genpd and all of its masters so that it is possible to * resume a device belonging to it. */ -static int __genpd_poweron(struct generic_pm_domain *genpd) +static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) { struct gpd_link *link; int ret = 0; @@ -194,11 +193,16 @@ static int __genpd_poweron(struct generic_pm_domain *genpd) * with it. */ list_for_each_entry(link, &genpd->slave_links, slave_node) { - genpd_sd_counter_inc(link->master); + struct generic_pm_domain *master = link->master; + + genpd_sd_counter_inc(master); + + mutex_lock_nested(&master->lock, depth + 1); + ret = __genpd_poweron(master, depth + 1); + mutex_unlock(&master->lock); - ret = genpd_poweron(link->master); if (ret) { - genpd_sd_counter_dec(link->master); + genpd_sd_counter_dec(master); goto err; } } @@ -230,11 +234,12 @@ static int genpd_poweron(struct generic_pm_domain *genpd) int ret; mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd); + ret = __genpd_poweron(genpd, 0); mutex_unlock(&genpd->lock); return ret; } + static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) { return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); @@ -482,7 +487,7 @@ static int pm_genpd_runtime_resume(struct device *dev) } mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd); + ret = __genpd_poweron(genpd, 0); mutex_unlock(&genpd->lock); if (ret)