gpu: nvgpu: Add sysfs nodes for timeslice min/max

The timeslice values that can be selected for a particular channel/tsg
are bounded by a static min/max. This change introduces two sysfs
nodes that allow these bounds to be configured from userspace.

min_timeslice_us
max_timeslice_us

Bug 200251974
Bug 1854791

Change-Id: I5d5a14225eee4090e418c7e43629324114f60768
Signed-off-by: Peter Boonstoppel <pboonstoppel@nvidia.com>
Reviewed-on: http://git-master/r/1280372
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Peter Boonstoppel
2016-11-28 17:33:30 -08:00
committed by mobile promotions
parent 09dba979a8
commit f15a86f265
5 changed files with 75 additions and 13 deletions

View File

@@ -44,9 +44,6 @@
#define NVMAP_HANDLE_PARAM_SIZE 1
#define NVGPU_CHANNEL_MIN_TIMESLICE_US 1000
#define NVGPU_CHANNEL_MAX_TIMESLICE_US 50000
/*
* Although channels do have pointers back to the gk20a struct that they were
* created under in cases where the driver is killed that pointer can be bad.
@@ -3345,14 +3342,16 @@ int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority)
int gk20a_channel_set_timeslice(struct channel_gk20a *ch, u32 timeslice)
{
struct gk20a *g = ch->g;
if (gk20a_is_channel_marked_as_tsg(ch)) {
gk20a_err(dev_from_gk20a(ch->g),
"invalid operation for TSG!\n");
return -EINVAL;
}
if (timeslice < NVGPU_CHANNEL_MIN_TIMESLICE_US ||
timeslice > NVGPU_CHANNEL_MAX_TIMESLICE_US)
if (timeslice < g->min_timeslice_us ||
timeslice > g->max_timeslice_us)
return -EINVAL;
ch->timeslice_us = timeslice;

View File

@@ -840,6 +840,8 @@ struct gk20a {
u32 timeslice_low_priority_us;
u32 timeslice_medium_priority_us;
u32 timeslice_high_priority_us;
u32 min_timeslice_us;
u32 max_timeslice_us;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
u32 runlist_interleave;
#else

View File

@@ -3,7 +3,7 @@
*
* GK20A Graphics
*
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2011-2017, 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,
@@ -756,6 +756,63 @@ static ssize_t tpc_fs_mask_read(struct device *dev,
static DEVICE_ATTR(tpc_fs_mask, ROOTRW, tpc_fs_mask_read, tpc_fs_mask_store);
static ssize_t min_timeslice_us_read(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gk20a *g = get_gk20a(dev);
return snprintf(buf, PAGE_SIZE, "%u\n", g->min_timeslice_us);
}
static ssize_t min_timeslice_us_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct gk20a *g = get_gk20a(dev);
unsigned long val;
if (kstrtoul(buf, 10, &val) < 0)
return -EINVAL;
if (val > g->max_timeslice_us)
return -EINVAL;
g->min_timeslice_us = val;
return count;
}
static DEVICE_ATTR(min_timeslice_us, ROOTRW, min_timeslice_us_read,
min_timeslice_us_store);
static ssize_t max_timeslice_us_read(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gk20a *g = get_gk20a(dev);
return snprintf(buf, PAGE_SIZE, "%u\n", g->max_timeslice_us);
}
static ssize_t max_timeslice_us_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct gk20a *g = get_gk20a(dev);
unsigned long val;
if (kstrtoul(buf, 10, &val) < 0)
return -EINVAL;
if (val < g->min_timeslice_us)
return -EINVAL;
g->max_timeslice_us = val;
return count;
}
static DEVICE_ATTR(max_timeslice_us, ROOTRW, max_timeslice_us_read,
max_timeslice_us_store);
void gk20a_remove_sysfs(struct device *dev)
{
struct gk20a *g = get_gk20a(dev);
@@ -782,6 +839,8 @@ void gk20a_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_min_timeslice_us);
device_remove_file(dev, &dev_attr_max_timeslice_us);
if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) {
sysfs_remove_link(&g->host1x_dev->dev.kobj, dev_name(dev));
@@ -822,6 +881,8 @@ void gk20a_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_min_timeslice_us);
error |= device_create_file(dev, &dev_attr_max_timeslice_us);
if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) {
error |= sysfs_create_link(&g->host1x_dev->dev.kobj,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2014-2017, 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,
@@ -26,9 +26,6 @@
#include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h>
#define NVGPU_TSG_MIN_TIMESLICE_US 1000
#define NVGPU_TSG_MAX_TIMESLICE_US 50000
struct tsg_private {
struct gk20a *g;
struct tsg_gk20a *tsg;
@@ -367,8 +364,8 @@ int gk20a_tsg_set_timeslice(struct tsg_gk20a *tsg, u32 timeslice)
{
struct gk20a *g = tsg->g;
if (timeslice < NVGPU_TSG_MIN_TIMESLICE_US ||
timeslice > NVGPU_TSG_MAX_TIMESLICE_US)
if (timeslice < g->min_timeslice_us ||
timeslice > g->max_timeslice_us)
return -EINVAL;
gk20a_channel_get_timescale_from_timeslice(g, timeslice,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2016-2017, 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,
@@ -69,6 +69,9 @@ static void nvgpu_init_timeslice(struct gk20a *g)
g->timeslice_low_priority_us = 1300;
g->timeslice_medium_priority_us = 2600;
g->timeslice_high_priority_us = 5200;
g->min_timeslice_us = 1000;
g->max_timeslice_us = 50000;
}
static void nvgpu_init_pm_vars(struct gk20a *g)