From 5d740f98b07831b5380ec3079747e69b25d03ae2 Mon Sep 17 00:00:00 2001 From: Aaron Tian Date: Tue, 18 Aug 2020 17:48:35 +0800 Subject: [PATCH] gpu: nvgpu: enable CONFIG_GK20A_DEVFREQ for k5.9 Enable CONFIG_GK20A_DEVFREQ and apply corresponding changes for kernel-5.9 - Remove frequency clipping of devfreq min/max frequency constraint due to devfreq already takes care of it. - Register available GPU frequencies to OPP framework due to devfreq access available device frequencies through OPP frameworks during device frequency transition. Bug 200639056 Change-Id: I72e4a7825ae9ca814791dc283138d17a5cfbe8e2 Signed-off-by: Aaron Tian Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2400107 Reviewed-by: automaticguardword Reviewed-by: Terje Bergstrom Reviewed-by: Alex Waterman Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.linux.configs | 1 - drivers/gpu/nvgpu/os/linux/scale.c | 59 +++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/nvgpu/Makefile.linux.configs b/drivers/gpu/nvgpu/Makefile.linux.configs index c38b3784e..964b05dbf 100644 --- a/drivers/gpu/nvgpu/Makefile.linux.configs +++ b/drivers/gpu/nvgpu/Makefile.linux.configs @@ -148,7 +148,6 @@ ifneq ($(findstring stable,$(NV_BUILD_KERNEL_OPTIONS)),) CONFIG_GK20A_DEVFREQ := n CONFIG_GK20A_PM_QOS := n else ifneq ($(findstring 5.9,$(NV_BUILD_KERNEL_OPTIONS)),) -CONFIG_GK20A_DEVFREQ := n CONFIG_GK20A_PM_QOS := n endif diff --git a/drivers/gpu/nvgpu/os/linux/scale.c b/drivers/gpu/nvgpu/os/linux/scale.c index e802d89de..54a3a23da 100644 --- a/drivers/gpu/nvgpu/os/linux/scale.c +++ b/drivers/gpu/nvgpu/os/linux/scale.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -149,9 +150,11 @@ 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; +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) + struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct devfreq *devfreq = l->devfreq; +#endif unsigned long local_freq = *freq; unsigned long rounded_rate; unsigned long min_freq = 0, max_freq = 0; @@ -173,8 +176,18 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq, * In case we have conflict (min_freq > max_freq) after above * steps, we ensure that max_freq wins over min_freq */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) min_freq = max_t(u32, devfreq->min_freq, profile->qos_min_freq); max_freq = min_t(u32, devfreq->max_freq, profile->qos_max_freq); +#else + /* + * 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 = profile->qos_min_freq; + max_freq = profile->qos_max_freq; +#endif if (min_freq > max_freq) min_freq = max_freq; @@ -320,6 +333,46 @@ static int get_cur_freq(struct device *dev, unsigned long *freq) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) +static int register_gpu_opp(struct device *dev) +{ + return 0; +} + +static void unregister_gpu_opp(struct device *dev) +{ +} +#else +static void unregister_gpu_opp(struct device *dev) +{ + dev_pm_opp_remove_all_dynamic(dev); +} + +static int register_gpu_opp(struct device *dev) +{ + struct gk20a_platform *platform = dev_get_drvdata(dev); + struct gk20a *g = platform->g; + struct gk20a_scale_profile *profile = g->scale_profile; + unsigned long *freq_table = profile->devfreq_profile.freq_table; + int max_states = profile->devfreq_profile.max_state; + int i; + int err = 0; + + for (i = 0; i < max_states; ++i) { + err = dev_pm_opp_add(dev, freq_table[i], 0); + if (err) { + nvgpu_err(g, + "Failed to add OPP %lu: %d\n", + freq_table[i], + err); + unregister_gpu_opp(dev); + break; + } + } + + return err; +} +#endif /* * gk20a_scale_init(dev) @@ -362,6 +415,8 @@ void gk20a_scale_init(struct device *dev) struct devfreq *devfreq; int error = 0; + register_gpu_opp(dev); + profile->devfreq_profile.initial_freq = profile->devfreq_profile.freq_table[0]; profile->devfreq_profile.target = gk20a_scale_target; @@ -432,6 +487,8 @@ void gk20a_scale_exit(struct device *dev) err = devfreq_remove_device(l->devfreq); l->devfreq = NULL; + + unregister_gpu_opp(dev); } nvgpu_kfree(g, g->scale_profile);