gpu: nvgpu: remove unnecessary devfreq limit checks

gk20a_scale_target is called through the target member of a
devfreq_profile. It is only called from devfreqs update_devfreq
function or through governor_passive. governor_passive is not used for
nvgpu.

Since update_devfreq already enforce the devfreq limits,
gka20_scale_target can be simplified by only checking pm_qos
limits and also only if GK20A_PM_QOS is enabled.

This also resolves a race between creating devfreq sysfs
files and setting 'l->devfreq' in gk20a_scale_init that can
lead to accessing a NULL pointer by writing to the sysfs files.

Example:
Unable to handle kernel NULL pointer dereference at virtual address 00000430
<snip>
Call trace:
[<000000006aa50d89>] gk20a_scale_target+0x5c/0x120 [nvgpu]
[<00000000e5a63f7c>] update_devfreq+0xec/0x22c
[<0000000014a13c8a>] max_freq_store+0xa8/0xfc
[<0000000072139393>] dev_attr_store+0x48/0x60
[<000000008ec280df>] sysfs_kf_write+0x60/0x70
[<0000000038427ed5>] kernfs_fop_write+0xc4/0x1e0
[<00000000c0b74aa9>] __vfs_write+0x60/0x14c
[<0000000078fcebb4>] vfs_write+0xb0/0x1b4
[<000000007720da30>] SyS_write+0x74/0xf0
[<0000000067443e2c>] __sys_trace_return+0x0/0x4

Bug 3910155

Change-Id: I7193cc5ea85454acf0890b3ca8d1c3526ca8517e
Signed-off-by: Ken Chang <kenc@nvidia.com>
Signed-off-by: Sagar Kamble <skamble@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2828219
Reviewed-by: Rajesh Devaraj <rdevaraj@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
This commit is contained in:
Sagar Kamble
2022-12-19 20:15:31 +05:30
committed by mobile promotions
parent b432b5f41a
commit 49a6676ef6

View File

@@ -1,7 +1,7 @@
/*
* gk20a clock scaling profile
*
* Copyright (c) 2013-2020, NVIDIA Corporation. All rights reserved.
* Copyright (c) 2013-2023, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -148,32 +148,24 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq,
{
struct gk20a_platform *platform = dev_get_drvdata(dev);
struct gk20a *g = platform->g;
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
struct gk20a_scale_profile *profile = g->scale_profile;
struct devfreq *devfreq = l->devfreq;
unsigned long local_freq = *freq;
unsigned long rounded_rate;
#ifdef CONFIG_GK20A_PM_QOS
unsigned long min_freq = 0, max_freq = 0;
#endif
if (nvgpu_clk_arb_has_active_req(g))
return 0;
#ifdef CONFIG_GK20A_PM_QOS
/*
* Calculate floor and cap frequency values
*
* Policy :
* We have two APIs to clip the frequency
* 1. devfreq
* 2. pm_qos
*
* To calculate floor (min) freq, we select MAX of floor frequencies
* requested from both APIs
* To get cap (max) freq, we select MIN of max frequencies
*
* In case we have conflict (min_freq > max_freq) after above
* steps, we ensure that max_freq wins over min_freq
* devfreq takes care of min/max freq clipping in update_devfreq() then
* invoked devfreq->profile->target(), thus we only need to do freq
* clipping based on pm_qos constraint
*/
min_freq = max_t(u32, devfreq->min_freq, profile->qos_min_freq);
max_freq = min_t(u32, devfreq->max_freq, profile->qos_max_freq);
min_freq = profile->qos_min_freq;
max_freq = profile->qos_max_freq;
if (min_freq > max_freq)
min_freq = max_freq;
@@ -184,6 +176,7 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq,
if (local_freq > max_freq)
local_freq = max_freq;
#endif
/* set the final frequency */
rounded_rate = platform->clk_round_rate(dev, local_freq);