gpu: nvgpu: support tuning per-ch deterministic opts

Add a new ioctl NVGPU_GPU_IOCTL_SET_DETERMINISTIC_OPTS to adjust
deterministic options on a per-channel basis. Currently, the only
supported option is to relax the no-railgating requirement on open
deterministic channels. This also disallows submits on such channels,
until the railgate option is reset.

Bug 200327089

Change-Id: If4f0f51fd1d40ad7407d13638150d7402479aff0
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1554563
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Konsta Holtta
2017-11-06 14:25:47 +02:00
committed by mobile promotions
parent 1480afeb01
commit 8bdce5337e
7 changed files with 179 additions and 3 deletions

View File

@@ -161,6 +161,8 @@ static struct nvgpu_flags_mapping flags_mapping[] = {
NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_NO_JOBTRACKING},
{NVGPU_GPU_FLAGS_SUPPORT_DETERMINISTIC_SUBMIT_FULL,
NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_FULL},
{NVGPU_GPU_FLAGS_SUPPORT_DETERMINISTIC_OPTS,
NVGPU_SUPPORT_DETERMINISTIC_OPTS},
{NVGPU_GPU_FLAGS_SUPPORT_IO_COHERENCE,
NVGPU_SUPPORT_IO_COHERENCE},
{NVGPU_GPU_FLAGS_SUPPORT_RESCHEDULE_RUNLIST,
@@ -1319,6 +1321,114 @@ static int nvgpu_gpu_set_therm_alert_limit(struct gk20a *g,
return err;
}
static int nvgpu_gpu_set_deterministic_ch_railgate(struct channel_gk20a *ch,
u32 flags)
{
int err = 0;
bool allow;
bool disallow;
allow = flags &
NVGPU_GPU_SET_DETERMINISTIC_OPTS_FLAGS_ALLOW_RAILGATING;
disallow = flags &
NVGPU_GPU_SET_DETERMINISTIC_OPTS_FLAGS_DISALLOW_RAILGATING;
/* Can't be both at the same time */
if (allow && disallow)
return -EINVAL;
/* Nothing to do */
if (!allow && !disallow)
return 0;
/*
* Moving into explicit idle or back from it? A call that doesn't
* change the status is a no-op.
*/
if (!ch->deterministic_railgate_allowed &&
allow) {
gk20a_idle(ch->g);
} else if (ch->deterministic_railgate_allowed &&
!allow) {
err = gk20a_busy(ch->g);
if (err) {
nvgpu_warn(ch->g,
"cannot busy to restore deterministic ch");
return err;
}
}
ch->deterministic_railgate_allowed = allow;
return err;
}
static int nvgpu_gpu_set_deterministic_ch(struct channel_gk20a *ch, u32 flags)
{
if (!ch->deterministic)
return -EINVAL;
return nvgpu_gpu_set_deterministic_ch_railgate(ch, flags);
}
static int nvgpu_gpu_set_deterministic_opts(struct gk20a *g,
struct nvgpu_gpu_set_deterministic_opts_args *args)
{
int __user *user_channels;
u32 i = 0;
int err = 0;
gk20a_dbg_fn("");
user_channels = (int __user *)(uintptr_t)args->channels;
/* Upper limit; prevent holding deterministic_busy for long */
if (args->num_channels > g->fifo.num_channels) {
err = -EINVAL;
goto out;
}
/* Trivial sanity check first */
if (!access_ok(VERIFY_READ, user_channels,
args->num_channels * sizeof(int))) {
err = -EFAULT;
goto out;
}
nvgpu_rwsem_down_read(&g->deterministic_busy);
/* note: we exit at the first failure */
for (; i < args->num_channels; i++) {
int ch_fd = 0;
struct channel_gk20a *ch;
if (copy_from_user(&ch_fd, &user_channels[i], sizeof(int))) {
/* User raced with above access_ok */
err = -EFAULT;
break;
}
ch = gk20a_get_channel_from_file(ch_fd);
if (!ch) {
err = -EINVAL;
break;
}
err = nvgpu_gpu_set_deterministic_ch(ch, args->flags);
gk20a_channel_put(ch);
if (err)
break;
}
nvgpu_rwsem_up_read(&g->deterministic_busy);
out:
args->num_channels = i;
return err;
}
long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct gk20a_ctrl_priv *priv = filp->private_data;
@@ -1633,6 +1743,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg
(struct nvgpu_gpu_set_therm_alert_limit_args *)buf);
break;
case NVGPU_GPU_IOCTL_SET_DETERMINISTIC_OPTS:
err = nvgpu_gpu_set_deterministic_opts(g,
(struct nvgpu_gpu_set_deterministic_opts_args *)buf);
break;
default:
gk20a_dbg_info("unrecognized gpu ioctl cmd: 0x%x", cmd);
err = -ENOTTY;