From 90b2f780d414d993571dceccafbc01b371068782 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Sat, 5 May 2018 08:10:48 -0700 Subject: gpu: nvgpu: support TSG IOCTL to unbind channel We so far do not support unbinding a channel from TSG explicitly through IOCTL Channel is unbound from TSG when channel fd is closed But this could create issue in case process is forked and fd is duplicated In worst case it is possible that duplicate fd is closed sometime later when TSG is active and that could lead to corruption of TSG state Fix this by implementing NVGPU_TSG_IOCTL_UNBIND_CHANNEL API This API will simply call gk20a_tsg_unbind_channel() API to unbind the channel Note that we also mark the channel has_timedout since unbound channel does not have any context of its own and it cannot serve any job Remove call to gk20a_disable_channel() while closing the channel. We do not support bare channels without TSG, and if channel is not part of TSG then it means channel is already unbound from TSG with call to NVGPU_TSG_IOCTL_UNBIND_CHANNEL, and there is nothing to do while closing the channel Bug 200327095 Jira NVGPU-229 Change-Id: Ib7f6710f0dc8125caafabe7bee737622c3dd9fa3 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/1708902 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/ioctl_tsg.c | 46 ++++++++++++++++++++++++++++-- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 6 +++- 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_tsg.c b/drivers/gpu/nvgpu/common/linux/ioctl_tsg.c index d0bfd55a..4ef99ded 100644 --- a/drivers/gpu/nvgpu/common/linux/ioctl_tsg.c +++ b/drivers/gpu/nvgpu/common/linux/ioctl_tsg.c @@ -120,6 +120,33 @@ mutex_release: return err; } +static int gk20a_tsg_unbind_channel_fd(struct tsg_gk20a *tsg, int ch_fd) +{ + struct channel_gk20a *ch; + int err = 0; + + ch = gk20a_get_channel_from_file(ch_fd); + if (!ch) + return -EINVAL; + + if (ch->tsgid != tsg->tsgid) { + err = -EINVAL; + goto out; + } + + err = gk20a_tsg_unbind_channel(ch); + + /* + * Mark the channel timedout since channel unbound from TSG + * has no context of its own so it can't serve any job + */ + ch->has_timedout = true; + +out: + gk20a_channel_put(ch); + return err; +} + static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg, unsigned int event_id, struct gk20a_event_id_data **event_id_data) @@ -552,10 +579,23 @@ long nvgpu_ioctl_tsg_dev_ioctl(struct file *filp, unsigned int cmd, } case NVGPU_TSG_IOCTL_UNBIND_CHANNEL: - /* We do not support explicitly unbinding channel from TSG. - * Channel will be unbounded from TSG when it is closed. - */ + { + int ch_fd = *(int *)buf; + + if (ch_fd < 0) { + err = -EINVAL; + break; + } + err = gk20a_busy(g); + if (err) { + nvgpu_err(g, + "failed to host gk20a for ioctl cmd: 0x%x", cmd); + break; + } + err = gk20a_tsg_unbind_channel_fd(tsg, ch_fd); + gk20a_idle(g); break; + } case NVGPU_IOCTL_TSG_ENABLE: { diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 21abdf9a..0c199146 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -314,7 +314,11 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force) "failed to unbind channel %d from TSG", ch->chid); } else { - gk20a_disable_channel(ch); + /* + * Channel is already unbound from TSG by User with + * explicit call + * Nothing to do here in that case + */ } } /* wait until there's only our ref to the channel */ -- cgit v1.2.2