From fdba1eef100ef8bb9e1c5a3b443250658ab93db6 Mon Sep 17 00:00:00 2001 From: Sagar Kadamati Date: Thu, 12 May 2022 01:59:54 +0530 Subject: [PATCH] gpu: nvgpu: add FLCG support for PERFMON Add FLCG register programming for PERFMON Jira NVGPU-7228 Change-Id: Ia1b3b2976c65c44f718789bcfbef4cad7e0718b3 Signed-off-by: Sagar Kadamati Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2712095 Tested-by: Rajesh Devaraj Reviewed-by: Antony Clince Alex Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra Reviewed-by: svc-mobile-cert Reviewed-by: Ankur Kishore GVS: Gerrit_Virtual_Submit --- .../gpu/nvgpu/common/power_features/cg/cg.c | 46 +++++++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/enabled.h | 2 + drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 2 + drivers/gpu/nvgpu/include/nvgpu/gops/cg.h | 1 + .../nvgpu/include/nvgpu/power_features/cg.h | 3 ++ drivers/gpu/nvgpu/os/linux/driver_common.c | 4 ++ drivers/gpu/nvgpu/os/linux/platform_gk20a.h | 8 +++- drivers/gpu/nvgpu/os/linux/sysfs.c | 41 +++++++++++++++++ 8 files changed, 106 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nvgpu/common/power_features/cg/cg.c b/drivers/gpu/nvgpu/common/power_features/cg/cg.c index ff376c834..fba7ca2db 100644 --- a/drivers/gpu/nvgpu/common/power_features/cg/cg.c +++ b/drivers/gpu/nvgpu/common/power_features/cg/cg.c @@ -375,6 +375,13 @@ done: nvgpu_mutex_release(&g->cg_pg_lock); } +static void cg_init_gr_flcg_load_gating_prod(struct gk20a *g) +{ + if (g->ops.cg.flcg_perf_load_gating_prod != NULL) { + g->ops.cg.flcg_perf_load_gating_prod(g, true); + } +} + static void cg_init_gr_slcg_load_gating_prod(struct gk20a *g) { if (g->ops.cg.slcg_bus_load_gating_prod != NULL) { @@ -419,6 +426,13 @@ void nvgpu_cg_init_gr_load_gating_prod(struct gk20a *g) nvgpu_mutex_acquire(&g->cg_pg_lock); + if (!g->flcg_enabled) { + goto check_can_slcg; + } + + cg_init_gr_flcg_load_gating_prod(g); + +check_can_slcg: if (!g->slcg_enabled) { goto check_can_blcg; } @@ -699,6 +713,38 @@ done: nvgpu_mutex_release(&g->cg_pg_lock); } +void nvgpu_cg_flcg_set_flcg_enabled(struct gk20a *g, bool enable) +{ + bool load = false; + + nvgpu_log_fn(g, " "); + + g->ops.gr.init.wait_initialized(g); + + nvgpu_mutex_acquire(&g->cg_pg_lock); + if (enable) { + if (!g->flcg_enabled) { + load = true; + g->flcg_enabled = true; + } + } else { + if (g->flcg_enabled) { + load = true; + g->flcg_enabled = false; + } + } + if (!load) { + goto done; + } + + if (g->ops.cg.flcg_perf_load_gating_prod != NULL) { + g->ops.cg.flcg_perf_load_gating_prod(g, enable); + } + +done: + nvgpu_mutex_release(&g->cg_pg_lock); +} + void nvgpu_cg_elcg_ce_load_enable(struct gk20a *g) { nvgpu_log_fn(g, " "); diff --git a/drivers/gpu/nvgpu/include/nvgpu/enabled.h b/drivers/gpu/nvgpu/include/nvgpu/enabled.h index 14e4e8d7a..9334e516d 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/enabled.h +++ b/drivers/gpu/nvgpu/include/nvgpu/enabled.h @@ -128,6 +128,8 @@ struct gk20a; DEFINE_FLAG(NVGPU_PMU_ZBC_SAVE, "Save ZBC reglist"), \ DEFINE_FLAG(NVGPU_GPU_CAN_BLCG, \ "Supports Block Level Clock Gating"), \ + DEFINE_FLAG(NVGPU_GPU_CAN_FLCG, \ + "Supports First Level Clock Gating"), \ DEFINE_FLAG(NVGPU_GPU_CAN_SLCG, \ "Supports Second Level Clock Gating"), \ DEFINE_FLAG(NVGPU_GPU_CAN_ELCG, \ diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 302c5c8df..e696e61b5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -584,6 +584,8 @@ struct gk20a { /** Lock serializing CG an PG programming for various units */ struct nvgpu_mutex cg_pg_lock; + /** FLCG setting read from the platform data */ + bool flcg_enabled; /** SLCG setting read from the platform data */ bool slcg_enabled; /** BLCG setting read from the platform data */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/cg.h b/drivers/gpu/nvgpu/include/nvgpu/gops/cg.h index 60c9001ed..28c5fc63e 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/cg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/cg.h @@ -63,6 +63,7 @@ struct gops_cg { void (*blcg_hshub_load_gating_prod)(struct gk20a *g, bool prod); void (*slcg_runlist_load_gating_prod)(struct gk20a *g, bool prod); void (*blcg_runlist_load_gating_prod)(struct gk20a *g, bool prod); + void (*flcg_perf_load_gating_prod)(struct gk20a *g, bool prod); /* Ring station slcg prod gops */ void (*slcg_rs_ctrl_fbp_load_gating_prod)(struct gk20a *g, bool prod); diff --git a/drivers/gpu/nvgpu/include/nvgpu/power_features/cg.h b/drivers/gpu/nvgpu/include/nvgpu/power_features/cg.h index f8a7f750c..d4f129d3b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/power_features/cg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/power_features/cg.h @@ -571,6 +571,9 @@ void nvgpu_cg_slcg_timer_load_enable(struct gk20a *g); #endif #ifdef CONFIG_NVGPU_PROFILER +void nvgpu_cg_flcg_perf_load_enable(struct gk20a *g, bool enable); void nvgpu_cg_slcg_perf_load_enable(struct gk20a *g, bool enable); #endif + +void nvgpu_cg_flcg_set_flcg_enabled(struct gk20a *g, bool enable); #endif /*NVGPU_POWER_FEATURES_CG_H*/ diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index b403d9b24..47eb19a58 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -188,6 +188,8 @@ static void nvgpu_init_pm_vars(struct gk20a *g) * Set up initial power settings. For non-slicon platforms, disable * power features and for silicon platforms, read from platform data */ + g->flcg_enabled = + nvgpu_platform_is_silicon(g) ? platform->enable_flcg : false; g->slcg_enabled = nvgpu_platform_is_silicon(g) ? platform->enable_slcg : false; g->blcg_enabled = @@ -203,6 +205,8 @@ static void nvgpu_init_pm_vars(struct gk20a *g) nvgpu_set_enabled(g, NVGPU_GPU_CAN_ELCG, nvgpu_platform_is_silicon(g) ? platform->can_elcg : false); + nvgpu_set_enabled(g, NVGPU_GPU_CAN_FLCG, + nvgpu_platform_is_silicon(g) ? platform->can_flcg : false); nvgpu_set_enabled(g, NVGPU_GPU_CAN_SLCG, nvgpu_platform_is_silicon(g) ? platform->can_slcg : false); nvgpu_set_enabled(g, NVGPU_GPU_CAN_BLCG, diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h index e6c663507..e827c8c48 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h @@ -1,7 +1,7 @@ /* * GK20A Platform (SoC) Interface * - * Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2022, 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, @@ -133,6 +133,9 @@ struct gk20a_platform { /* init value for slowdown factor */ u8 ldiv_slowdown_factor_init; + /* First Level Clock Gating: true = enable false = disable */ + bool enable_flcg; + /* Second Level Clock Gating: true = enable false = disable */ bool enable_slcg; @@ -142,6 +145,9 @@ struct gk20a_platform { /* Engine Level Clock Gating: true = enable flase = disable */ bool enable_elcg; + /* Should be populated at probe. */ + bool can_flcg; + /* Should be populated at probe. */ bool can_slcg; diff --git a/drivers/gpu/nvgpu/os/linux/sysfs.c b/drivers/gpu/nvgpu/os/linux/sysfs.c index c5b24f4ac..bb521cac6 100644 --- a/drivers/gpu/nvgpu/os/linux/sysfs.c +++ b/drivers/gpu/nvgpu/os/linux/sysfs.c @@ -182,6 +182,45 @@ static ssize_t slcg_enable_read(struct device *dev, static DEVICE_ATTR(slcg_enable, ROOTRW, slcg_enable_read, slcg_enable_store); +static ssize_t flcg_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct gk20a *g = get_gk20a(dev); + unsigned long val = 0; + int err; + + if (kstrtoul(buf, 10, &val) < 0) + return -EINVAL; + + err = gk20a_busy(g); + if (err) { + return err; + } + + if (val) { + nvgpu_cg_flcg_set_flcg_enabled(g, true); + } else { + nvgpu_cg_flcg_set_flcg_enabled(g, false); + } + + gk20a_idle(g); + + nvgpu_info(g, "FLCG is %s.", val ? "enabled" : + "disabled"); + + return count; +} + +static ssize_t flcg_enable_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gk20a *g = get_gk20a(dev); + + return snprintf(buf, NVGPU_CPU_PAGE_SIZE, "%d\n", g->flcg_enabled ? 1 : 0); +} + +static DEVICE_ATTR(flcg_enable, ROOTRW, flcg_enable_read, flcg_enable_store); + static ssize_t ptimer_scale_factor_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1447,6 +1486,7 @@ void nvgpu_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_elcg_enable); device_remove_file(dev, &dev_attr_blcg_enable); device_remove_file(dev, &dev_attr_slcg_enable); + device_remove_file(dev, &dev_attr_flcg_enable); device_remove_file(dev, &dev_attr_ptimer_scale_factor); device_remove_file(dev, &dev_attr_ptimer_ref_freq); device_remove_file(dev, &dev_attr_ptimer_src_freq); @@ -1515,6 +1555,7 @@ int nvgpu_create_sysfs(struct device *dev) error |= device_create_file(dev, &dev_attr_elcg_enable); error |= device_create_file(dev, &dev_attr_blcg_enable); error |= device_create_file(dev, &dev_attr_slcg_enable); + error |= device_create_file(dev, &dev_attr_flcg_enable); error |= device_create_file(dev, &dev_attr_ptimer_scale_factor); error |= device_create_file(dev, &dev_attr_ptimer_ref_freq); error |= device_create_file(dev, &dev_attr_ptimer_src_freq);