From patchwork Fri Sep 5 06:37:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 4851311 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id EA3529F2EC for ; Fri, 5 Sep 2014 10:23:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AF9FF20176 for ; Fri, 5 Sep 2014 10:23:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5922420211 for ; Fri, 5 Sep 2014 10:23:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 806316E845; Fri, 5 Sep 2014 03:23:49 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.11.231]) by gabe.freedesktop.org (Postfix) with ESMTP id 55DB96E22B for ; Thu, 4 Sep 2014 23:37:54 -0700 (PDT) Received: from smtp.codeaurora.org (localhost [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id 8073D13FC1D; Fri, 5 Sep 2014 06:37:53 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 486) id 6C00113FC20; Fri, 5 Sep 2014 06:37:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-5.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from sboyd-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: sboyd@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 5DA7A13FC1D; Fri, 5 Sep 2014 06:37:52 +0000 (UTC) From: Stephen Boyd To: Rob Clark Subject: [PATCH v2] clk: Don't hold prepare_lock across debugfs creation Date: Thu, 4 Sep 2014 23:37:49 -0700 Message-Id: <1409899069-13313-1-git-send-email-sboyd@codeaurora.org> X-Mailer: git-send-email 2.1.0.rc2.4.g1a517f0 In-Reply-To: References: X-Virus-Scanned: ClamAV using ClamSMTP X-Mailman-Approved-At: Fri, 05 Sep 2014 03:23:46 -0700 Cc: Mike Turquette , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Rob Clark reports a lockdep splat that involves the prepare_lock chained with the mmap semaphore. ====================================================== [ INFO: possible circular locking dependency detected ] 3.17.0-rc1-00050-g07a489b #802 Tainted: G W ------------------------------------------------------- Xorg.bin/5413 is trying to acquire lock: (prepare_lock){+.+.+.}, at: [] clk_prepare_lock+0x88/0xfc but task is already holding lock: (qcom_iommu_lock){+.+...}, at: [] qcom_iommu_unmap+0x1c/0x1f0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #4 (qcom_iommu_lock){+.+...}: [] qcom_iommu_map+0x28/0x450 [] iommu_map+0xc8/0x12c [] msm_iommu_map+0xb4/0x130 [] msm_gem_get_iova_locked+0x9c/0xe8 [] msm_gem_get_iova+0x4c/0x64 [] mdp4_kms_init+0x4c4/0x6c0 [] msm_load+0x2ac/0x34c [] drm_dev_register+0xac/0x108 [] drm_platform_init+0x50/0xf0 [] try_to_bring_up_master.part.3+0xc8/0x108 [] component_master_add_with_match+0xa8/0x104 [] msm_pdev_probe+0x64/0x70 [] platform_drv_probe+0x2c/0x60 [] driver_probe_device+0x108/0x234 [] bus_for_each_drv+0x64/0x98 [] device_attach+0x78/0x8c [] bus_probe_device+0x88/0xac [] deferred_probe_work_func+0x68/0x9c [] process_one_work+0x1a0/0x40c [] worker_thread+0x44/0x4d8 [] kthread+0xd8/0xec [] ret_from_fork+0x14/0x2c -> #3 (&dev->struct_mutex){+.+.+.}: [] drm_gem_mmap+0x38/0xd0 [] msm_gem_mmap+0xc/0x5c [] mmap_region+0x35c/0x6c8 [] do_mmap_pgoff+0x314/0x398 [] vm_mmap_pgoff+0x84/0xb4 [] SyS_mmap_pgoff+0x94/0xbc [] ret_fast_syscall+0x0/0x48 -> #2 (&mm->mmap_sem){++++++}: [] filldir64+0x68/0x180 [] dcache_readdir+0x188/0x22c [] iterate_dir+0x9c/0x11c [] SyS_getdents64+0x78/0xe8 [] ret_fast_syscall+0x0/0x48 -> #1 (&sb->s_type->i_mutex_key#3){+.+.+.}: [] __create_file+0x58/0x1dc [] debugfs_create_dir+0x1c/0x24 [] clk_debug_create_subtree+0x20/0x170 [] clk_debug_init+0xec/0x14c [] do_one_initcall+0x8c/0x1c8 [] kernel_init_freeable+0x13c/0x1dc [] kernel_init+0x8/0xe8 [] ret_from_fork+0x14/0x2c -> #0 (prepare_lock){+.+.+.}: [] mutex_lock_nested+0x70/0x3e8 [] clk_prepare_lock+0x88/0xfc [] clk_prepare+0xc/0x24 [] __enable_clocks.isra.4+0x18/0xa4 [] __flush_iotlb_va+0xe0/0x114 [] qcom_iommu_unmap+0xac/0x1f0 [] iommu_unmap+0x9c/0xe8 [] msm_iommu_unmap+0x64/0x84 [] msm_gem_free_object+0x11c/0x338 [] drm_gem_object_handle_unreference_unlocked+0xfc/0x130 [] drm_gem_object_release_handle+0x50/0x68 [] idr_for_each+0xa8/0xdc [] drm_gem_release+0x1c/0x28 [] drm_release+0x370/0x428 [] __fput+0x98/0x1e8 [] task_work_run+0xb0/0xfc [] do_exit+0x2ec/0x948 [] do_group_exit+0x4c/0xb8 [] get_signal+0x28c/0x6ac [] do_signal+0xc4/0x3e4 [] do_work_pending+0xb4/0xc4 [] work_pending+0xc/0x20 other info that might help us debug this: Chain exists of: prepare_lock --> &dev->struct_mutex --> qcom_iommu_lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(qcom_iommu_lock); lock(&dev->struct_mutex); lock(qcom_iommu_lock); lock(prepare_lock); *** DEADLOCK *** 3 locks held by Xorg.bin/5413: #0: (drm_global_mutex){+.+.+.}, at: [] drm_release+0x34/0x428 #1: (&dev->struct_mutex){+.+.+.}, at: [] drm_gem_object_handle_unreference_unlocked+0xcc/0x130 #2: (qcom_iommu_lock){+.+...}, at: [] qcom_iommu_unmap+0x1c/0x1f0 stack backtrace: CPU: 1 PID: 5413 Comm: Xorg.bin Tainted: G W 3.17.0-rc1-00050-g07a489b #802 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x98/0xb8) [] (dump_stack) from [] (print_circular_bug+0x218/0x340) [] (print_circular_bug) from [] (__lock_acquire+0x1d24/0x20b8) [] (__lock_acquire) from [] (lock_acquire+0x9c/0xbc) [] (lock_acquire) from [] (mutex_lock_nested+0x70/0x3e8) [] (mutex_lock_nested) from [] (clk_prepare_lock+0x88/0xfc) [] (clk_prepare_lock) from [] (clk_prepare+0xc/0x24) [] (clk_prepare) from [] (__enable_clocks.isra.4+0x18/0xa4) [] (__enable_clocks.isra.4) from [] (__flush_iotlb_va+0xe0/0x114) [] (__flush_iotlb_va) from [] (qcom_iommu_unmap+0xac/0x1f0) [] (qcom_iommu_unmap) from [] (iommu_unmap+0x9c/0xe8) [] (iommu_unmap) from [] (msm_iommu_unmap+0x64/0x84) [] (msm_iommu_unmap) from [] (msm_gem_free_object+0x11c/0x338) [] (msm_gem_free_object) from [] (drm_gem_object_handle_unreference_unlocked+0xfc/0x130) [] (drm_gem_object_handle_unreference_unlocked) from [] (drm_gem_object_release_handle+0x50/0x68) [] (drm_gem_object_release_handle) from [] (idr_for_each+0xa8/0xdc) [] (idr_for_each) from [] (drm_gem_release+0x1c/0x28) [] (drm_gem_release) from [] (drm_release+0x370/0x428) [] (drm_release) from [] (__fput+0x98/0x1e8) [] (__fput) from [] (task_work_run+0xb0/0xfc) [] (task_work_run) from [] (do_exit+0x2ec/0x948) [] (do_exit) from [] (do_group_exit+0x4c/0xb8) [] (do_group_exit) from [] (get_signal+0x28c/0x6ac) [] (get_signal) from [] (do_signal+0xc4/0x3e4) [] (do_signal) from [] (do_work_pending+0xb4/0xc4) [] (do_work_pending) from [] (work_pending+0xc/0x20) We can break this chain if we don't hold the prepare_lock while creating debugfs directories. We only hold the prepare_lock right now because we're traversing the clock tree recursively and we don't want the hierarchy to change during the traversal. Replacing this traversal with a simple linked list walk allows us to only grab a list lock instead of the prepare_lock, thus breaking the lock chain. Signed-off-by: Stephen Boyd --- I don't understand why we need to hold the prepare lock around the kref_put(), so I changed the flow so that we don't do this when we unregister a clock. Changes since v1: * Squashed two patches into one * Focused entirely on debugfs now drivers/clk/clk.c | 66 +++++++++++++++------------------------------ include/linux/clk-private.h | 1 + 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b76fa69b44cb..3c04d0d69b96 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -100,6 +100,8 @@ static void clk_enable_unlock(unsigned long flags) static struct dentry *rootdir; static int inited = 0; +static DEFINE_MUTEX(clk_debug_lock); +static HLIST_HEAD(clk_debug_list); static struct hlist_head *all_lists[] = { &clk_root_list, @@ -300,28 +302,6 @@ out: return ret; } -/* caller must hold prepare_lock */ -static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) -{ - struct clk *child; - int ret = -EINVAL;; - - if (!clk || !pdentry) - goto out; - - ret = clk_debug_create_one(clk, pdentry); - - if (ret) - goto out; - - hlist_for_each_entry(child, &clk->children, child_node) - clk_debug_create_subtree(child, pdentry); - - ret = 0; -out: - return ret; -} - /** * clk_debug_register - add a clk node to the debugfs clk tree * @clk: the clk being added to the debugfs clk tree @@ -329,20 +309,21 @@ out: * Dynamically adds a clk to the debugfs clk tree if debugfs has been * initialized. Otherwise it bails out early since the debugfs clk tree * will be created lazily by clk_debug_init as part of a late_initcall. - * - * Caller must hold prepare_lock. Only clk_init calls this function (so - * far) so this is taken care. */ static int clk_debug_register(struct clk *clk) { int ret = 0; + mutex_lock(&clk_debug_lock); + hlist_add_head(&clk->debug_node, &clk_debug_list); + if (!inited) - goto out; + goto unlock; - ret = clk_debug_create_subtree(clk, rootdir); + ret = clk_debug_create_one(clk, rootdir); +unlock: + mutex_unlock(&clk_debug_lock); -out: return ret; } @@ -353,11 +334,13 @@ out: * Dynamically removes a clk and all it's children clk nodes from the * debugfs clk tree if clk->dentry points to debugfs created by * clk_debug_register in __clk_init. - * - * Caller must hold prepare_lock. */ static void clk_debug_unregister(struct clk *clk) { + mutex_lock(&clk_debug_lock); + hlist_del_init(&clk->debug_node); + mutex_unlock(&clk_debug_lock); + debugfs_remove_recursive(clk->dentry); } @@ -415,17 +398,12 @@ static int __init clk_debug_init(void) if (!d) return -ENOMEM; - clk_prepare_lock(); - - hlist_for_each_entry(clk, &clk_root_list, child_node) - clk_debug_create_subtree(clk, rootdir); - - hlist_for_each_entry(clk, &clk_orphan_list, child_node) - clk_debug_create_subtree(clk, rootdir); + mutex_lock(&clk_debug_lock); + hlist_for_each_entry(clk, &clk_debug_list, debug_node) + clk_debug_create_one(clk, rootdir); inited = 1; - - clk_prepare_unlock(); + mutex_unlock(&clk_debug_lock); return 0; } @@ -2094,7 +2072,8 @@ void clk_unregister(struct clk *clk) if (clk->ops == &clk_nodrv_ops) { pr_err("%s: unregistered clock: %s\n", __func__, clk->name); - goto out; + clk_prepare_unlock(); + return; } /* * Assign empty clock ops for consumers that might still hold @@ -2113,17 +2092,16 @@ void clk_unregister(struct clk *clk) clk_set_parent(child, NULL); } - clk_debug_unregister(clk); - hlist_del_init(&clk->child_node); if (clk->prepare_count) pr_warn("%s: unregistering prepared clock: %s\n", __func__, clk->name); + clk_prepare_unlock(); + + clk_debug_unregister(clk); kref_put(&clk->ref, __clk_release); -out: - clk_prepare_unlock(); } EXPORT_SYMBOL_GPL(clk_unregister); diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index efbf70b9fd84..4ed34105c371 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -48,6 +48,7 @@ struct clk { unsigned long accuracy; struct hlist_head children; struct hlist_node child_node; + struct hlist_node debug_node; unsigned int notifier_count; #ifdef CONFIG_DEBUG_FS struct dentry *dentry;