PM / devfreq: rockchip_dmc: Fix locking when rounding rate
authorFinley Xiao <finley.xiao@rock-chips.com>
Wed, 9 Aug 2017 04:36:21 +0000 (12:36 +0800)
committerFinley Xiao <finley.xiao@rock-chips.com>
Wed, 9 Aug 2017 04:48:20 +0000 (12:48 +0800)
There's no need to take the rcu read lock when rounding rate.

This patch fixes the following BUG:
BUG: sleeping function called from invalid context at kernel/locking/mutex.c:620
in_atomic(): 0, irqs_disabled(): 0, pid: 153, name: kworker/u16:2
5 locks held by kworker/u16:2/153:
 #0:  ("%s"("devfreq_wq")){......}, at: [<ffffff80080b8cf4>] process_one_work+0x1c4/0x58c
 #1:  ((&(&devfreq->work)->work)){......}, at: [<ffffff80080b8cf4>] process_one_work+0x1c4/0x58c
 #2:  (&devfreq->lock){......}, at: [<ffffff80089534c8>] devfreq_monitor+0x28/0x8c
 #3:  (&vop->vop_lock){......}, at: [<ffffff80084c826c>] dmc_notifier_call+0x14/0x34
 #4:  (rcu_read_lock){......}, at: [<ffffff80089557f0>] rockchip_dmcfreq_target+0x0/0x2e0
CPU: 3 PID: 153 Comm: kworker/u16:2 Not tainted 4.4.77 #2573
Hardware name: Rockchip Sheep board (DT)
Workqueue: devfreq_wq devfreq_monitor
Call trace:
[<ffffff8008089930>] dump_backtrace+0x0/0x1c8
[<ffffff8008089b0c>] show_stack+0x14/0x1c
[<ffffff800839718c>] dump_stack+0x8c/0xac
[<ffffff80080c8d5c>] ___might_sleep+0x11c/0x128
[<ffffff80080c8ddc>] __might_sleep+0x74/0x84
[<ffffff8008c371a4>] mutex_lock_nested+0x4c/0x39c
[<ffffff80089458d8>] clk_prepare_lock+0x58/0xc8
[<ffffff8008946ec8>] clk_round_rate+0x34/0x94
[<ffffff800895589c>] rockchip_dmcfreq_target+0xac/0x2e0
[<ffffff80089533f4>] update_devfreq+0x100/0x1ac
[<ffffff80089534d0>] devfreq_monitor+0x30/0x8c
[<ffffff80080b8e1c>] process_one_work+0x2ec/0x58c
[<ffffff80080ba16c>] worker_thread+0x300/0x428
[<ffffff80080bf3e0>] kthread+0x104/0x10c
[<ffffff8008082840>] ret_from_fork+0x10/0x50

Change-Id: I31f75a55da72cab597796edd5c339222094fff97
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
drivers/devfreq/rockchip_dmc.c

index fa00e367b35388eab30fc2b7410496b171d6ef85..13a0a5bf2cf2e24ce3d7422cebc3734b9ab1e2c0 100644 (file)
@@ -249,20 +249,21 @@ static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq,
        int err;
 
        rcu_read_lock();
+
        opp = devfreq_recommended_opp(dev, freq, flags);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                return PTR_ERR(opp);
        }
-
        temp_rate = dev_pm_opp_get_freq(opp);
-       target_rate = clk_round_rate(dmcfreq->dmc_clk, temp_rate);
-       if ((long)target_rate <= 0)
-               target_rate = temp_rate;
        target_volt = dev_pm_opp_get_voltage(opp);
 
        rcu_read_unlock();
 
+       target_rate = clk_round_rate(dmcfreq->dmc_clk, temp_rate);
+       if ((long)target_rate <= 0)
+               target_rate = temp_rate;
+
        if (dmcfreq->rate == target_rate) {
                if (dmcfreq->volt == target_volt)
                        return 0;