From d3b8415948de8c9ffe2f2fa66340dd7e71a894e6 Mon Sep 17 00:00:00 2001 From: Deepak Goyal Date: Mon, 16 Jul 2018 11:10:23 +0530 Subject: gpu: nvgpu: tpc powergating through sysfs - adds static tpc-powergating through sysfs. - active tpc count will remain till the GPU/systems is not booted again. - tpc_pg_mask can be written only after GPU probe finishes and GPU boot is triggered. Note: To be able to use this feature, we need to change boot/init scripts of the OS(used with nvgpu driver) to write to sysfs nodes before posting discover image size query to FECS. Bug 200406784 Change-Id: Id749c7a617422c625f77d0c1a9aada2eb960c4d0 Signed-off-by: Deepak Goyal Reviewed-on: https://git-master.nvidia.com/r/1742422 Reviewed-by: svc-misra-checker GVS: Gerrit_Virtual_Submit Reviewed-by: Vijayakumar Subbu Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/os/linux/sysfs.c | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers/gpu/nvgpu/os/linux/sysfs.c') diff --git a/drivers/gpu/nvgpu/os/linux/sysfs.c b/drivers/gpu/nvgpu/os/linux/sysfs.c index 1b84e2e2..b607768a 100644 --- a/drivers/gpu/nvgpu/os/linux/sysfs.c +++ b/drivers/gpu/nvgpu/os/linux/sysfs.c @@ -31,6 +31,8 @@ #define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) +#define TPC_MASK_FOR_ALL_ACTIVE_TPCs (u32) 0x0 + static ssize_t elcg_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -843,6 +845,61 @@ static ssize_t force_idle_read(struct device *dev, static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store); #endif +static ssize_t tpc_pg_mask_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gk20a *g = get_gk20a(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", g->tpc_pg_mask); +} + +static ssize_t tpc_pg_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct gk20a *g = get_gk20a(dev); + struct gr_gk20a *gr = &g->gr; + unsigned long val = 0; + + nvgpu_mutex_acquire(&g->tpc_pg_lock); + + if (!g->can_tpc_powergate) { + nvgpu_info(g, "TPC-PG not enabled for the platform"); + goto exit; + } + + if (kstrtoul(buf, 10, &val) < 0) { + nvgpu_err(g, "invalid value"); + nvgpu_mutex_release(&g->tpc_pg_lock); + return -EINVAL; + } + + if (val == g->tpc_pg_mask) { + nvgpu_info(g, "no value change, same mask already set"); + goto exit; + } + + if (gr->ctx_vars.golden_image_size) { + nvgpu_err(g, "golden image size already initialized"); + nvgpu_mutex_release(&g->tpc_pg_lock); + return -ENODEV; + } + + if (val == TPC_MASK_FOR_ALL_ACTIVE_TPCs || val == g->valid_tpc_mask) { + g->tpc_pg_mask = val; + } else { + + nvgpu_err(g, "TPC-PG mask is invalid"); + nvgpu_mutex_release(&g->tpc_pg_lock); + return -EINVAL; + } +exit: + nvgpu_mutex_release(&g->tpc_pg_lock); + + return count; +} + +static DEVICE_ATTR(tpc_pg_mask, ROOTRW, tpc_pg_mask_read, tpc_pg_mask_store); + static ssize_t tpc_fs_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1130,6 +1187,7 @@ void nvgpu_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_aelpg_enable); device_remove_file(dev, &dev_attr_allow_all); device_remove_file(dev, &dev_attr_tpc_fs_mask); + device_remove_file(dev, &dev_attr_tpc_pg_mask); device_remove_file(dev, &dev_attr_min_timeslice_us); device_remove_file(dev, &dev_attr_max_timeslice_us); @@ -1181,6 +1239,7 @@ int nvgpu_create_sysfs(struct device *dev) error |= device_create_file(dev, &dev_attr_aelpg_enable); error |= device_create_file(dev, &dev_attr_allow_all); error |= device_create_file(dev, &dev_attr_tpc_fs_mask); + error |= device_create_file(dev, &dev_attr_tpc_pg_mask); error |= device_create_file(dev, &dev_attr_min_timeslice_us); error |= device_create_file(dev, &dev_attr_max_timeslice_us); -- cgit v1.2.2