summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2018-05-05 11:10:48 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-05-10 05:13:58 -0400
commit90b2f780d414d993571dceccafbc01b371068782 (patch)
tree22eacf1ab70196ab9373ebe903e881bc05d22352
parent6ad9862657469e7dac343d7857f907967f6d4c76 (diff)
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 <dnibade@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1708902 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl_tsg.c46
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c6
2 files changed, 48 insertions, 4 deletions
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:
120 return err; 120 return err;
121} 121}
122 122
123static int gk20a_tsg_unbind_channel_fd(struct tsg_gk20a *tsg, int ch_fd)
124{
125 struct channel_gk20a *ch;
126 int err = 0;
127
128 ch = gk20a_get_channel_from_file(ch_fd);
129 if (!ch)
130 return -EINVAL;
131
132 if (ch->tsgid != tsg->tsgid) {
133 err = -EINVAL;
134 goto out;
135 }
136
137 err = gk20a_tsg_unbind_channel(ch);
138
139 /*
140 * Mark the channel timedout since channel unbound from TSG
141 * has no context of its own so it can't serve any job
142 */
143 ch->has_timedout = true;
144
145out:
146 gk20a_channel_put(ch);
147 return err;
148}
149
123static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg, 150static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg,
124 unsigned int event_id, 151 unsigned int event_id,
125 struct gk20a_event_id_data **event_id_data) 152 struct gk20a_event_id_data **event_id_data)
@@ -552,10 +579,23 @@ long nvgpu_ioctl_tsg_dev_ioctl(struct file *filp, unsigned int cmd,
552 } 579 }
553 580
554 case NVGPU_TSG_IOCTL_UNBIND_CHANNEL: 581 case NVGPU_TSG_IOCTL_UNBIND_CHANNEL:
555 /* We do not support explicitly unbinding channel from TSG. 582 {
556 * Channel will be unbounded from TSG when it is closed. 583 int ch_fd = *(int *)buf;
557 */ 584
585 if (ch_fd < 0) {
586 err = -EINVAL;
587 break;
588 }
589 err = gk20a_busy(g);
590 if (err) {
591 nvgpu_err(g,
592 "failed to host gk20a for ioctl cmd: 0x%x", cmd);
593 break;
594 }
595 err = gk20a_tsg_unbind_channel_fd(tsg, ch_fd);
596 gk20a_idle(g);
558 break; 597 break;
598 }
559 599
560 case NVGPU_IOCTL_TSG_ENABLE: 600 case NVGPU_IOCTL_TSG_ENABLE:
561 { 601 {
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)
314 "failed to unbind channel %d from TSG", 314 "failed to unbind channel %d from TSG",
315 ch->chid); 315 ch->chid);
316 } else { 316 } else {
317 gk20a_disable_channel(ch); 317 /*
318 * Channel is already unbound from TSG by User with
319 * explicit call
320 * Nothing to do here in that case
321 */
318 } 322 }
319 } 323 }
320 /* wait until there's only our ref to the channel */ 324 /* wait until there's only our ref to the channel */