diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/tsg_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 23 |
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 | ||
28 | static void gk20a_tsg_release(struct kref *ref); | 28 | static void gk20a_tsg_release(struct kref *ref); |
29 | 29 | ||
30 | static void gk20a_tsg_release(struct kref *ref); | ||
31 | |||
32 | bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch) | 30 | bool 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 | ||
35 | static 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); |