From patchwork Fri Dec 11 14:38:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 7830501 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C0A58BEEE1 for ; Fri, 11 Dec 2015 14:40:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BC57320570 for ; Fri, 11 Dec 2015 14:40:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7D7A320532 for ; Fri, 11 Dec 2015 14:40:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753595AbbLKOkQ (ORCPT ); Fri, 11 Dec 2015 09:40:16 -0500 Received: from mailout4.w1.samsung.com ([210.118.77.14]:45768 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751227AbbLKOkN (ORCPT ); Fri, 11 Dec 2015 09:40:13 -0500 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NZ70094K7EYGB70@mailout4.w1.samsung.com>; Fri, 11 Dec 2015 14:40:10 +0000 (GMT) X-AuditID: cbfec7f4-f79026d00000418a-50-566ae04ae794 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id C6.B1.16778.A40EA665; Fri, 11 Dec 2015 14:40:10 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NZ7008RG7EQ1130@eusync3.samsung.com>; Fri, 11 Dec 2015 14:40:10 +0000 (GMT) From: Marek Szyprowski To: linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Cc: Marek Szyprowski , Sylwester Nawrocki , Tomasz Figa , Mike Turquette , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Viresh Kumar , Thomas Abraham , Ben Gamari , Lukasz Majewski , Chanwoo Choi , Kevin Hilman , stable@vger.kernel.org Subject: [PATCH] clk: exynos: use irqsave version of spin_lock to avoid deadlock with irqs Date: Fri, 11 Dec 2015 15:38:40 +0100 Message-id: <1449844798-27384-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrFLMWRmVeSWpSXmKPExsVy+t/xq7peD7LCDA7/VLLYOGM9q8Ws+XdZ LK5/ec5q8fqFocXXwysYLd483MxocXnXHDaLz71HGC1mnN/HZLH2yF12i4unXC0Ov2lntViw 8RGjRccyRotVu/4wWmz86uEg4PH+Riu7x85Zd9k97lzbw+bRt2UVo8eZ384enzfJBbBFcdmk pOZklqUW6dslcGUcX3OPreCxScWetQ0sDYyvdLsYOTkkBEwkTizsYISwxSQu3FvP1sXIxSEk sJRR4tmPl+wQThOTxJmTi1lBqtgEDCW63naxgdgiAvES9/snMoEUMQssYJE4+fUdWJGwQIzE trvnwMayCKhKbGm9DmbzCnhI/Lx1kBVinZzE/5crmCYwci9gZFjFKJpamlxQnJSea6hXnJhb XJqXrpecn7uJERKCX3YwLj5mdYhRgINRiYd3IUdWmBBrYllxZe4hRgkOZiUR3l8bgEK8KYmV ValF+fFFpTmpxYcYpTlYlMR55+56HyIkkJ5YkpqdmlqQWgSTZeLglGpglPddbfp/X9HtI2Wl R3sU/FwE5S9arFB64DKbwfllSE3vnDvTxOJ29xk3mqluOyZueUKQ9+RfCxfzGW9ba/bdC7xZ amF59u+18/WHfLJYJsVJir07eez4sh0mc5gLHippP7iQ7uuSUqig+IlJ6OumqEthEwIrD/a/ LXPRX+DDvfptRfb1vM2eSizFGYmGWsxFxYkAEjLzhj0CAAA= Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP It is allowed to enable/disable clocks from interrupts, so common Exynos ARM clock management code for CPUfreq should use 'irqsave' version of spin_lock calls to avoid potential deadlock caused by spin_lock recursion. The same spin_lock is used by gate/mux clocks during enable/disable calls. This deadlock, can be reproduced by enabling CPUfreq (ondemand or userspace) and decoding video with s5p-mfc driver. Relevant stack trace: [ 5928.061534] BUG: spinlock recursion on CPU#0, bash/1252 [ 5928.061609] lock: 0xee80454c, .magic: dead4ead, .owner: bash/1252, .owner_cpu: 0 [ 5928.068586] CPU: 0 PID: 1252 Comm: bash Tainted: G W 4.4.0-rc4-00001-g447a7fd #678 [ 5928.077260] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [ 5928.083359] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 5928.091072] [] (show_stack) from [] (dump_stack+0x68/0xb8) [ 5928.098275] [] (dump_stack) from [] (do_raw_spin_lock+0x184/0x1ac) [ 5928.106177] [] (do_raw_spin_lock) from [] (_raw_spin_lock_irqsave+0x20/0x28) [ 5928.114943] [] (_raw_spin_lock_irqsave) from [] (clk_gate_endisable+0x24/0x98) [ 5928.123882] [] (clk_gate_endisable) from [] (clk_core_disable+0x60/0x84) [ 5928.132299] [] (clk_core_disable) from [] (clk_disable+0x24/0x30) [ 5928.140117] [] (clk_disable) from [] (s5p_mfc_handle_frame+0x254/0x860) [ 5928.148445] [] (s5p_mfc_handle_frame) from [] (s5p_mfc_irq+0x890/0xa24) [ 5928.156778] [] (s5p_mfc_irq) from [] (handle_irq_event_percpu+0x50/0x14c) [ 5928.165283] [] (handle_irq_event_percpu) from [] (handle_irq_event+0x38/0x5c) [ 5928.174143] [] (handle_irq_event) from [] (handle_fasteoi_irq+0xdc/0x1a4) [ 5928.182645] [] (handle_fasteoi_irq) from [] (generic_handle_irq+0x18/0x28) [ 5928.191236] [] (generic_handle_irq) from [] (__handle_domain_irq+0x6c/0xdc) [ 5928.199917] [] (__handle_domain_irq) from [] (gic_handle_irq+0x4c/0x98) [ 5928.208249] [] (gic_handle_irq) from [] (__irq_svc+0x54/0x90) [ 5928.215709] Exception stack(0xeddb5cb8 to 0xeddb5d00) [ 5928.220745] 5ca0: ee80454c faddfadc [ 5928.228906] 5cc0: 00000000 01000001 ee831ce0 f8114200 ee807c00 01130520 00000403 eddb5d84 [ 5928.237063] 5ce0: ee807c48 2faf0800 ee807c0c eddb5d08 c046b618 c046b634 20000053 ffffffff [ 5928.245225] [] (__irq_svc) from [] (exynos_cpuclk_notifier_cb+0x170/0x270) [ 5928.253823] [] (exynos_cpuclk_notifier_cb) from [] (notifier_call_chain+0x44/0x84) [ 5928.263106] [] (notifier_call_chain) from [] (__srcu_notifier_call_chain+0x6c/0x9c) [ 5928.272480] [] (__srcu_notifier_call_chain) from [] (srcu_notifier_call_chain+0x18/0x20) [ 5928.282288] [] (srcu_notifier_call_chain) from [] (__clk_notify+0x6c/0x74) [ 5928.290881] [] (__clk_notify) from [] (clk_propagate_rate_change+0xa0/0xac) [ 5928.299561] [] (clk_propagate_rate_change) from [] (clk_propagate_rate_change+0x90/0xac) [ 5928.309370] [] (clk_propagate_rate_change) from [] (clk_core_set_rate_nolock+0x64/0xa8) [ 5928.319091] [] (clk_core_set_rate_nolock) from [] (clk_set_rate+0x20/0x30) [ 5928.327686] [] (clk_set_rate) from [] (set_target+0xe8/0x23c) [ 5928.335152] [] (set_target) from [] (__cpufreq_driver_target+0x184/0x29c) [ 5928.343655] [] (__cpufreq_driver_target) from [] (cpufreq_set+0x44/0x64) [ 5928.352074] [] (cpufreq_set) from [] (store_scaling_setspeed+0x5c/0x74) [ 5928.360407] [] (store_scaling_setspeed) from [] (store+0x7c/0x98) [ 5928.368221] [] (store) from [] (sysfs_kf_write+0x44/0x48) [ 5928.375338] [] (sysfs_kf_write) from [] (kernfs_fop_write+0xb8/0x1bc) [ 5928.383496] [] (kernfs_fop_write) from [] (__vfs_write+0x2c/0xd4) [ 5928.391308] [] (__vfs_write) from [] (vfs_write+0xa0/0x144) [ 5928.398598] [] (vfs_write) from [] (SyS_write+0x44/0x84) [ 5928.405631] [] (SyS_write) from [] (ret_fast_syscall+0x0/0x3c) Signed-off-by: Marek Szyprowski CC: stable@vger.kernel.org # v4.2+ Acked-by: Tomasz Figa Acked-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-cpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 2fe37f708dc7..813003d6ce09 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -148,6 +148,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent); unsigned long alt_div = 0, alt_div_mask = DIV_MASK; unsigned long div0, div1 = 0, mux_reg; + unsigned long flags; /* find out the divider values to use for clock data */ while ((cfg_data->prate * 1000) != ndata->new_rate) { @@ -156,7 +157,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, cfg_data++; } - spin_lock(cpuclk->lock); + spin_lock_irqsave(cpuclk->lock, flags); /* * For the selected PLL clock frequency, get the pre-defined divider @@ -212,7 +213,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, DIV_MASK_ALL); } - spin_unlock(cpuclk->lock); + spin_unlock_irqrestore(cpuclk->lock, flags); return 0; } @@ -223,6 +224,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata, const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg; unsigned long div = 0, div_mask = DIV_MASK; unsigned long mux_reg; + unsigned long flags; /* find out the divider values to use for clock data */ if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) { @@ -233,7 +235,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata, } } - spin_lock(cpuclk->lock); + spin_lock_irqsave(cpuclk->lock, flags); /* select mout_apll as the alternate parent */ mux_reg = readl(base + E4210_SRC_CPU); @@ -246,7 +248,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata, } exynos_set_safe_div(base, div, div_mask); - spin_unlock(cpuclk->lock); + spin_unlock_irqrestore(cpuclk->lock, flags); return 0; }