From 7a65a3e636e91bc3a22436378ddcec6ad24327cc Mon Sep 17 00:00:00 2001 From: shaochunk Date: Tue, 12 Sep 2023 15:23:35 +0800 Subject: [PATCH] gpu: nvgpu: support module parameters for devfreq For POR like safety GPU, we may specify devfreq timer and governor to keep GPU running with high performance. This change supports module parameters for specifying devfreq governor and devfreq timer. safety nvgpu module parameter example: devfreq_timer="delayed" devfreq_gov="performance" Regarding devfreq timers, a delayed timer can ensure that the devfreq monitor polls on time. However, a deferrable timer might potentially cause a delay in polling time. Regarding devfreq governors, the default governor of nvgpu is nvhost_podgov, which scales the gpu frequency based on GPU load reported by PMU. Using the performance governor will keep the GPU operating at a higher GPU frequency, providing better performance. Bug 4084478 Change-Id: I9dfef11648203c6af281e980d3a5790b36742414 Signed-off-by: shaochunk Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2978810 Reviewed-by: Divya Singhatwaria Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/os/linux/driver_common.c | 65 +++++++++++++++------- drivers/gpu/nvgpu/os/linux/driver_common.h | 4 +- drivers/gpu/nvgpu/os/linux/module.c | 10 ++++ drivers/gpu/nvgpu/os/linux/scale.c | 2 +- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 2608c1797..b0ae8c868 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -83,34 +83,59 @@ void nvgpu_read_support_gpu_tools(struct gk20a *g) } } -void nvgpu_read_devfreq_timer(struct gk20a *g) +void nvgpu_devfreq_init(struct gk20a *g) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) - struct device_node *np; - int ret = 0; - const char *timer; + struct device *dev = dev_from_gk20a(g); + struct gk20a_platform *platform = dev_get_drvdata(dev); - np = nvgpu_get_node(g); - ret = of_property_read_string(np, "devfreq-timer", &timer); - if (ret != 0) { - nvgpu_log_info(g, "GPU devfreq monitor uses default timer"); - } else { - if (strncmp(timer, "deferrable", - sizeof("deferrable") - 1) == 0) { - g->scale_profile->devfreq_profile.timer = +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) + /* specify devfreq timer with module parameter */ + + if (strlen(nvgpu_devfreq_timer) == 0) { + nvgpu_log_info(g, "GPU devfreq uses default timer"); + } else if (strncmp(nvgpu_devfreq_timer, "deferrable", + strlen("deferrable")) == 0) { + g->scale_profile->devfreq_profile.timer = DEVFREQ_TIMER_DEFERRABLE; - } else if (strncmp(timer, "delayed", - sizeof("delayed") - 1) == 0) { - g->scale_profile->devfreq_profile.timer = + nvgpu_log_info(g, "use deferrable devfreq timer"); + } else if (strncmp(nvgpu_devfreq_timer, "delayed", + strlen("delayed")) == 0) { + g->scale_profile->devfreq_profile.timer = DEVFREQ_TIMER_DELAYED; - } else { - nvgpu_err(g, "dt specified " - "invalid devfreq timer for GPU: %s", timer); - } + nvgpu_log_info(g, "use delayed devfreq timer"); + } else { + nvgpu_err(g, "specified invalid devfreq timer: %s", + nvgpu_devfreq_timer); } #else nvgpu_log_info(g, "GPU devfreq monitor uses default timer"); #endif + + /* specify devfreq governor from module parameter */ +#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND + if (strncmp(nvgpu_devfreq_gov, "simple_ondemand", + strlen("simple_ondemand")) == 0) + platform->devfreq_governor = DEVFREQ_GOV_SIMPLE_ONDEMAND; +#endif +#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE + if (strncmp(nvgpu_devfreq_gov, "performance", + strlen("performance")) == 0) + platform->devfreq_governor = DEVFREQ_GOV_PERFORMANCE; +#endif +#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE + if (strncmp(nvgpu_devfreq_gov, "powersave", strlen("powersave")) == 0) + platform->devfreq_governor = DEVFREQ_GOV_POWERSAVE; +#endif +#ifdef CONFIG_DEVFREQ_GOV_USERSPACE + if (strncmp(nvgpu_devfreq_gov, "userspace", strlen("userspace")) == 0) + platform->devfreq_governor = DEVFREQ_GOV_USERSPACE; +#endif +#ifdef CONFIG_DEVFREQ_GOV_PASSIVE + if (strncmp(nvgpu_devfreq_gov, "passive", strlen("passive")) == 0) + platform->devfreq_governor = DEVFREQ_GOV_PASSIVE; +#endif + nvgpu_log_info(g, "GPU devfreq governor: %s", + platform->devfreq_governor); } static void nvgpu_init_vars(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.h b/drivers/gpu/nvgpu/os/linux/driver_common.h index c84b53305..ff7ca82c8 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.h +++ b/drivers/gpu/nvgpu/os/linux/driver_common.h @@ -18,6 +18,8 @@ #define NVGPU_LINUX_DRIVER_COMMON extern int nvgpu_lpwr_enable; +extern char *nvgpu_devfreq_timer; +extern char *nvgpu_devfreq_gov; struct gk20a; @@ -26,6 +28,6 @@ int nvgpu_probe(struct gk20a *g, void nvgpu_init_gk20a(struct gk20a *g); void nvgpu_read_support_gpu_tools(struct gk20a *g); -void nvgpu_read_devfreq_timer(struct gk20a *g); +void nvgpu_devfreq_init(struct gk20a *g); #endif diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index c5c110fa1..de555ecda 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -115,6 +115,16 @@ #define CREATE_TRACE_POINTS #include +char *nvgpu_devfreq_timer = ""; +module_param_named(devfreq_timer, nvgpu_devfreq_timer, charp, 0400); +MODULE_PARM_DESC(devfreq_timer, + "Specify gpu devfreq governor with module parameter."); + +char *nvgpu_devfreq_gov = ""; +module_param_named(devfreq_gov, nvgpu_devfreq_gov, charp, 0400); +MODULE_PARM_DESC(devfreq_gov, + "Specify gpu devfreq governor with module parameter."); + int nvgpu_lpwr_enable; module_param_named(lpwr_enable, nvgpu_lpwr_enable, int, 0400); MODULE_PARM_DESC(lpwr_enable, diff --git a/drivers/gpu/nvgpu/os/linux/scale.c b/drivers/gpu/nvgpu/os/linux/scale.c index 5ccd1e7a9..0cb9bd297 100644 --- a/drivers/gpu/nvgpu/os/linux/scale.c +++ b/drivers/gpu/nvgpu/os/linux/scale.c @@ -521,7 +521,7 @@ void gk20a_scale_init(struct device *dev) int error = 0; register_gpu_opp(dev); - nvgpu_read_devfreq_timer(g); + nvgpu_devfreq_init(g); profile->devfreq_profile.initial_freq = profile->devfreq_profile.freq_table[0];