Skip to content

Commit

Permalink
PM / devfreq: rockchip_dmc: Fix locking when rounding rate
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
finley1226 committed Aug 9, 2017
1 parent f52f739 commit a54bcc8
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions drivers/devfreq/rockchip_dmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit a54bcc8

Please sign in to comment.