Skip to content

Commit dbb43fb

Browse files
sudeep-hollagregkh
authored andcommitted
cpufreq: check if policy is inactive early in __cpufreq_get()
[ Upstream commit 2f66196 ] cpuinfo_cur_freq gets current CPU frequency as detected by hardware while scaling_cur_freq last known CPU frequency. Some platforms may not allow checking the CPU frequency of an offline CPU or the associated resources may have been released via cpufreq_exit when the CPU gets offlined, in which case the policy would have been invalidated already. If we attempt to get current frequency from the hardware, it may result in hang or crash. For example on Juno, I see: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000188 [0000000000000188] pgd=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: CPU: 5 PID: 4202 Comm: cat Not tainted 4.20.0-08251-ga0f2c0318a15-dirty #87 Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform pstate: 40000005 (nZcv daif -PAN -UAO) pc : scmi_cpufreq_get_rate+0x34/0xb0 lr : scmi_cpufreq_get_rate+0x34/0xb0 Call trace: scmi_cpufreq_get_rate+0x34/0xb0 __cpufreq_get+0x34/0xc0 show_cpuinfo_cur_freq+0x24/0x78 show+0x40/0x60 sysfs_kf_seq_show+0xc0/0x148 kernfs_seq_show+0x44/0x50 seq_read+0xd4/0x480 kernfs_fop_read+0x15c/0x208 __vfs_read+0x60/0x188 vfs_read+0x94/0x150 ksys_read+0x6c/0xd8 __arm64_sys_read+0x24/0x30 el0_svc_common+0x78/0x100 el0_svc_handler+0x38/0x78 el0_svc+0x8/0xc ---[ end trace 3d1024e58f77f6b2 ]--- So fix the issue by checking if the policy is invalid early in __cpufreq_get before attempting to get the current frequency. Signed-off-by: Sudeep Holla <[email protected]> Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 3555798 commit dbb43fb

File tree

1 file changed

+3
-4
lines changed

1 file changed

+3
-4
lines changed

drivers/cpufreq/cpufreq.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,17 +1496,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
14961496
{
14971497
unsigned int ret_freq = 0;
14981498

1499-
if (!cpufreq_driver->get)
1499+
if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
15001500
return ret_freq;
15011501

15021502
ret_freq = cpufreq_driver->get(policy->cpu);
15031503

15041504
/*
1505-
* Updating inactive policies is invalid, so avoid doing that. Also
1506-
* if fast frequency switching is used with the given policy, the check
1505+
* If fast frequency switching is used with the given policy, the check
15071506
* against policy->cur is pointless, so skip it in that case too.
15081507
*/
1509-
if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
1508+
if (policy->fast_switch_enabled)
15101509
return ret_freq;
15111510

15121511
if (ret_freq && policy->cur &&

0 commit comments

Comments
 (0)