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 <shaochunk@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2978810
Reviewed-by: Divya Singhatwaria <dsinghatwari@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
shaochunk
2023-09-12 15:23:35 +08:00
committed by mobile promotions
parent d28dda7149
commit 7a65a3e636
4 changed files with 59 additions and 22 deletions

View File

@@ -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) {
#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) {
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;
nvgpu_log_info(g, "use delayed devfreq timer");
} else {
nvgpu_err(g, "dt specified "
"invalid devfreq timer for GPU: %s", timer);
}
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)

View File

@@ -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

View File

@@ -115,6 +115,16 @@
#define CREATE_TRACE_POINTS
#include <nvgpu/trace.h>
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,

View File

@@ -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];