From 49a6676ef63cabd16f4aadefa6bbce5dd22977df Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Mon, 19 Dec 2022 20:15:31 +0530 Subject: [PATCH] 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 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 Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2828219 Reviewed-by: Rajesh Devaraj Reviewed-by: Vijayakumar Subbu --- drivers/gpu/nvgpu/os/linux/scale.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/scale.c b/drivers/gpu/nvgpu/os/linux/scale.c index 388e168da..f8f0ef940 100644 --- a/drivers/gpu/nvgpu/os/linux/scale.c +++ b/drivers/gpu/nvgpu/os/linux/scale.c @@ -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);