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 <dnibade@nvidia.com>
This commit is contained in:
Deepak Nibade
2014-05-27 19:19:45 +05:30
committed by Dan Willemsen
parent 3f7be93dab
commit cd9f8553ad
2 changed files with 53 additions and 0 deletions

View File

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

View File

@@ -22,6 +22,7 @@
#include <linux/pm_runtime.h>
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/gk20a.h>
#include <mach/clk.h>
@@ -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,