From 8bdce5337ee5f4d1e1f6d4c7b2dc0abe4a532893 Mon Sep 17 00:00:00 2001 From: Konsta Holtta Date: Mon, 6 Nov 2017 14:25:47 +0200 Subject: 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 Reviewed-on: https://git-master.nvidia.com/r/1554563 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/channel.c | 11 +++ drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c | 115 ++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 5 +- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 2 + drivers/gpu/nvgpu/gk20a/gk20a.c | 2 + drivers/gpu/nvgpu/include/nvgpu/enabled.h | 3 + 6 files changed, 137 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/common/linux/channel.c b/drivers/gpu/nvgpu/common/linux/channel.c index 716c5820..c295336f 100644 --- a/drivers/gpu/nvgpu/common/linux/channel.c +++ b/drivers/gpu/nvgpu/common/linux/channel.c @@ -537,6 +537,17 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, if (c->deterministic) nvgpu_rwsem_down_read(&g->deterministic_busy); + if (c->deterministic && c->deterministic_railgate_allowed) { + /* + * Nope - this channel has dropped its own power ref. As + * deterministic submits don't hold power on per each submitted + * job like normal ones do, the GPU might railgate any time now + * and thus submit is disallowed. + */ + err = -EINVAL; + goto clean_up; + } + trace_gk20a_channel_submit_gpfifo(g->name, c->chid, num_entries, diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c index 73911717..08a831b9 100644 --- a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c @@ -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; diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 805902eb..6c607ae2 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -578,7 +578,10 @@ unbind: if (ch->deterministic) { nvgpu_rwsem_down_read(&g->deterministic_busy); ch->deterministic = false; - gk20a_idle(g); + if (!ch->deterministic_railgate_allowed) + gk20a_idle(g); + ch->deterministic_railgate_allowed = false; + nvgpu_rwsem_up_read(&g->deterministic_busy); } diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 762daea9..0cb60200 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -208,6 +208,8 @@ struct channel_gk20a { bool first_init; bool vpr; bool deterministic; + /* deterministic, but explicitly idle and submits disallowed */ + bool deterministic_railgate_allowed; bool cde; pid_t pid; pid_t tgid; diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index e8db9d2c..756db415 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -439,6 +439,8 @@ int gk20a_init_gpu_characteristics(struct gk20a *g) NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_FULL, true); + __nvgpu_set_enabled(g, NVGPU_SUPPORT_DETERMINISTIC_OPTS, true); + __nvgpu_set_enabled(g, NVGPU_SUPPORT_USERSPACE_MANAGED_AS, true); __nvgpu_set_enabled(g, NVGPU_SUPPORT_TSG, true); diff --git a/drivers/gpu/nvgpu/include/nvgpu/enabled.h b/drivers/gpu/nvgpu/include/nvgpu/enabled.h index 14595497..82f9e6d2 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/enabled.h +++ b/drivers/gpu/nvgpu/include/nvgpu/enabled.h @@ -91,6 +91,9 @@ struct gk20a; /* FECS context switch tracing is available */ #define NVGPU_SUPPORT_FECS_CTXSW_TRACE 38 +/* NVGPU_GPU_IOCTL_SET_DETERMINISTIC_OPTS is available */ +#define NVGPU_SUPPORT_DETERMINISTIC_OPTS 39 + /* * Security flags */ -- cgit v1.2.2