From cd9f8553ad1e6e03e8a3a70cb8d08edd3513fb66 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Tue, 27 May 2014 19:19:45 +0530 Subject: gpu: nvgpu: sysfs to put gpu into idle - Add a sysfs "force_idle" to forcibly idle the GPU - read on this sysfs will return the current status 0 : not in idle (running) 1 : in forced idle state "echo 1 > force_idle" will force the gpu into idle "echo 0 > force_idle" will cause the gpu to resume Bug 1376916 Bug 1487804 Change-Id: I48dfd52e0d14561220bc4baea0776d1bdfaa7ea5 Signed-off-by: Deepak Nibade --- drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 115cd7f4..6d3c8225 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -248,6 +248,7 @@ struct gk20a { bool elcg_enabled; bool elpg_enabled; bool aelpg_enabled; + bool forced_idle; #ifdef CONFIG_DEBUG_FS spinlock_t debugfs_lock; diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index 9ebc5bab..a9e7274e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -331,6 +332,55 @@ static ssize_t elpg_enable_read(struct device *device, static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); +static ssize_t force_idle_store(struct device *device, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + unsigned long val = 0; + int err = 0; + + if (kstrtoul(buf, 10, &val) < 0) + return -EINVAL; + + if (val) { + if (g->forced_idle) + return count; /* do nothing */ + else { + err = gk20a_do_idle(); + if (!err) { + g->forced_idle = 1; + dev_info(device, "gpu is idle : %d\n", + g->forced_idle); + } + } + } else { + if (!g->forced_idle) + return count; /* do nothing */ + else { + err = gk20a_do_unidle(); + if (!err) { + g->forced_idle = 0; + dev_info(device, "gpu is idle : %d\n", + g->forced_idle); + } + } + } + + return count; +} + +static ssize_t force_idle_read(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + + return sprintf(buf, "%d\n", g->forced_idle ? 1 : 0); +} + +static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store); + void gk20a_remove_sysfs(struct device *dev) { struct gk20a *g = get_gk20a(to_platform_device(dev)); @@ -345,6 +395,7 @@ void gk20a_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_load); device_remove_file(dev, &dev_attr_railgate_delay); device_remove_file(dev, &dev_attr_clockgate_delay); + device_remove_file(dev, &dev_attr_force_idle); if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) sysfs_remove_link(&dev->kobj, dev_name(dev)); @@ -365,6 +416,7 @@ void gk20a_create_sysfs(struct platform_device *dev) error |= device_create_file(&dev->dev, &dev_attr_load); error |= device_create_file(&dev->dev, &dev_attr_railgate_delay); error |= device_create_file(&dev->dev, &dev_attr_clockgate_delay); + error |= device_create_file(&dev->dev, &dev_attr_force_idle); if (g->host1x_dev && (dev->dev.parent != &g->host1x_dev->dev)) error |= sysfs_create_link(&g->host1x_dev->dev.kobj, -- cgit v1.2.2