summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/tsg_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/tsg_gk20a.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
index c84e8d0b..98e1ae2c 100644
--- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
@@ -27,13 +27,26 @@
27 27
28static void gk20a_tsg_release(struct kref *ref); 28static void gk20a_tsg_release(struct kref *ref);
29 29
30static void gk20a_tsg_release(struct kref *ref);
31
32bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch) 30bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch)
33{ 31{
34 return !(ch->tsgid == NVGPU_INVALID_TSG_ID); 32 return !(ch->tsgid == NVGPU_INVALID_TSG_ID);
35} 33}
36 34
35static bool gk20a_is_channel_active(struct gk20a *g, struct channel_gk20a *ch)
36{
37 struct fifo_gk20a *f = &g->fifo;
38 struct fifo_runlist_info_gk20a *runlist;
39 int i;
40
41 for (i = 0; i < f->max_runlists; ++i) {
42 runlist = &f->runlist_info[i];
43 if (test_bit(ch->hw_chid, runlist->active_channels))
44 return true;
45 }
46
47 return false;
48}
49
37/* 50/*
38 * API to mark channel as part of TSG 51 * API to mark channel as part of TSG
39 * 52 *
@@ -50,6 +63,12 @@ static int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, int ch_fd)
50 return -EINVAL; 63 return -EINVAL;
51 } 64 }
52 65
66 /* channel cannot be bound to TSG if it is already active */
67 if (gk20a_is_channel_active(tsg->g, ch)) {
68 fput(f);
69 return -EINVAL;
70 }
71
53 ch->tsgid = tsg->tsgid; 72 ch->tsgid = tsg->tsgid;
54 73
55 mutex_lock(&tsg->ch_list_lock); 74 mutex_lock(&tsg->ch_list_lock);