From 18362fe03e11cd578a16a2e2b92a2b6ae55bf2f5 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 27 Jun 2018 09:41:19 +0800 Subject: [PATCH] soc: rockchip: opp_select: Fix sleeping inside atomic context This patch fixes the following warning: [ 2.226264] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:620 [ 2.226341] in_atomic(): 0, irqs_disabled(): 0, pid: 1, name: swapper/0 [ 2.226366] 4 locks held by swapper/0/1: [ 2.226385] #0: (&dev->mutex){......}, at: [] __device_attach+0x3c/0x134 [ 2.226515] #1: (cpu_hotplug.lock){......}, at: [] get_online_cpus+0x38/0x9c [ 2.226594] #2: (subsys mutex#7){......}, at: [] subsys_interface_register+0x54/0xfc [ 2.226684] #3: (rcu_read_lock){......}, at: [] rockchip_adjust_power_scale+0x88/0x450 [ 2.226771] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.4.132 #600 [ 2.226790] Hardware name: Rockchip PX30 evb ddr3 board (DT) [ 2.226809] Call trace: [ 2.226840] [] dump_backtrace+0x0/0x1ec [ 2.226889] [] show_stack+0x14/0x1c [ 2.226918] [] dump_stack+0x94/0xbc [ 2.226946] [] ___might_sleep+0x108/0x118 [ 2.226972] [] __might_sleep+0x70/0x80 [ 2.227001] [] mutex_lock_nested+0x54/0x38c [ 2.227031] [] __of_clk_get_from_provider+0x44/0xec [ 2.227061] [] __of_clk_get_by_name+0xd4/0x14c [ 2.227112] [] of_clk_get_by_name+0x18/0x28 [ 2.227140] [] rockchip_adjust_power_scale+0x2a4/0x450 [ 2.227171] [] cpufreq_init+0x154/0x394 [ 2.227199] [] cpufreq_online+0x1b0/0x68c [ 2.227225] [] cpufreq_add_dev+0x3c/0x94 [ 2.227253] [] subsys_interface_register+0xd8/0xfc [ 2.227281] [] cpufreq_register_driver+0x10c/0x1a8 [ 2.227332] [] dt_cpufreq_probe+0xcc/0xe8 [ 2.227360] [] platform_drv_probe+0x54/0xa8 [ 2.227385] [] driver_probe_device+0x194/0x278 [ 2.227411] [] __device_attach_driver+0x60/0x9c [ 2.227439] [] bus_for_each_drv+0x9c/0xbc [ 2.227464] [] __device_attach+0xc8/0x134 [ 2.227488] [] device_initial_probe+0x10/0x18 [ 2.227514] [] bus_probe_device+0x2c/0x90 [ 2.227541] [] device_add+0x44c/0x510 [ 2.227570] [] platform_device_add+0xa0/0x1e4 [ 2.227597] [] platform_device_register_full+0xa4/0xe4 [ 2.227627] [] rockchip_cpufreq_driver_init+0xd4/0x31c [ 2.227654] [] do_one_initcall+0x84/0x1a4 [ 2.227682] [] kernel_init_freeable+0x260/0x264 [ 2.227708] [] kernel_init+0x10/0xf8 [ 2.227734] [] ret_from_fork+0x10/0x30 Fixes: 197a2d322ade ("soc: rockchip: opp_select: add missing rcu lock") Change-Id: Ib52b6f7bc77bb207a1c8c6880f7a5e916fa3d2ee Signed-off-by: Finley Xiao --- drivers/soc/rockchip/rockchip_opp_select.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 4e45f817401fe..231f24839922c 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -590,7 +590,7 @@ static int rockchip_adjust_opp_by_irdrop(struct device *dev, count = dev_pm_opp_get_opp_count(dev); if (count <= 0) { ret = count ? count : -ENODATA; - goto out; + goto unlock; } for (i = 0, rate = 0; i < count; i++, rate++) { @@ -598,7 +598,7 @@ static int rockchip_adjust_opp_by_irdrop(struct device *dev, opp = dev_pm_opp_find_freq_ceil(dev, &rate); if (IS_ERR(opp)) { ret = PTR_ERR(opp); - goto out; + goto unlock; } board_irdrop = rockchip_of_get_irdrop(np, opp->rate); if (IS_ERR_VALUE(board_irdrop)) @@ -621,9 +621,18 @@ static int rockchip_adjust_opp_by_irdrop(struct device *dev, } } +unlock: +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + rcu_read_unlock(); +#endif + if (ret) + goto out; + clk = of_clk_get_by_name(np, NULL); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); goto out; + } if (safe_opp && safe_opp != opp && irdrop_scale) { *irdrop_scale = rockchip_pll_clk_rate_to_scale(clk, safe_opp->rate); @@ -634,9 +643,6 @@ static int rockchip_adjust_opp_by_irdrop(struct device *dev, clk_put(clk); out: -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - rcu_read_unlock(); -#endif return ret; }