summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-09-04 09:39:26 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:11:10 -0400
commitb81e9a2431e9a045e586ff028e0262e99202b3f0 (patch)
tree133891ddf59562794bc5913e0c0c688e245ed3ad /drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
parent949c47cbbb1f7560945b515c23a35b76475e16bf (diff)
gpu: nvgpu: add refcounting for TSG
Add refcounting for TSGs and manage the refcounts as below : - initialize ref when TSG is opened - get ref when channel is bound to TSG - drop the ref when channel is unbound (i.e. during channel close) - drop the ref when TSG is closed - when refcount drops to zero, we free the TSG This refcounting makes it possible to close channels or TSG in any order Bug 1470692 Change-Id: Ia4b39164a4582c8169da62a91b9131094c67f5f8 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/495667 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/tsg_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/tsg_gk20a.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
index 42d92f43..e7b70894 100644
--- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
@@ -24,6 +24,8 @@
24 24
25#include "gk20a.h" 25#include "gk20a.h"
26 26
27static void gk20a_tsg_release(struct kref *ref);
28
27bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch) 29bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch)
28{ 30{
29 return !(ch->tsgid == NVGPU_INVALID_TSG_ID); 31 return !(ch->tsgid == NVGPU_INVALID_TSG_ID);
@@ -51,6 +53,8 @@ static int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, int ch_fd)
51 list_add_tail(&ch->ch_entry, &tsg->ch_list); 53 list_add_tail(&ch->ch_entry, &tsg->ch_list);
52 mutex_unlock(&tsg->ch_list_lock); 54 mutex_unlock(&tsg->ch_list_lock);
53 55
56 kref_get(&tsg->refcount);
57
54 gk20a_dbg(gpu_dbg_fn, "BIND tsg:%d channel:%d\n", 58 gk20a_dbg(gpu_dbg_fn, "BIND tsg:%d channel:%d\n",
55 tsg->tsgid, ch->hw_chid); 59 tsg->tsgid, ch->hw_chid);
56 60
@@ -68,6 +72,8 @@ int gk20a_tsg_unbind_channel(struct channel_gk20a *ch)
68 list_del_init(&ch->ch_entry); 72 list_del_init(&ch->ch_entry);
69 mutex_unlock(&tsg->ch_list_lock); 73 mutex_unlock(&tsg->ch_list_lock);
70 74
75 kref_put(&tsg->refcount, gk20a_tsg_release);
76
71 ch->tsgid = NVGPU_INVALID_TSG_ID; 77 ch->tsgid = NVGPU_INVALID_TSG_ID;
72 78
73 return 0; 79 return 0;
@@ -134,6 +140,7 @@ int gk20a_tsg_dev_open(struct inode *inode, struct file *filp)
134 140
135 tsg->g = g; 141 tsg->g = g;
136 tsg->num_active_channels = 0; 142 tsg->num_active_channels = 0;
143 kref_init(&tsg->refcount);
137 144
138 tsg->tsg_gr_ctx = NULL; 145 tsg->tsg_gr_ctx = NULL;
139 tsg->vm = NULL; 146 tsg->vm = NULL;
@@ -145,18 +152,10 @@ int gk20a_tsg_dev_open(struct inode *inode, struct file *filp)
145 return 0; 152 return 0;
146} 153}
147 154
148int gk20a_tsg_dev_release(struct inode *inode, struct file *filp) 155static void gk20a_tsg_release(struct kref *ref)
149{ 156{
150 struct tsg_gk20a *tsg = filp->private_data; 157 struct tsg_gk20a *tsg = container_of(ref, struct tsg_gk20a, refcount);
151 struct gk20a *g = container_of(inode->i_cdev, 158 struct gk20a *g = tsg->g;
152 struct gk20a, tsg.cdev);
153
154 if (tsg->num_active_channels) {
155 gk20a_err(dev_from_gk20a(g),
156 "Trying to free TSG %d with active channels %d\n",
157 tsg->tsgid, tsg->num_active_channels);
158 return -EBUSY;
159 }
160 159
161 if (tsg->tsg_gr_ctx) { 160 if (tsg->tsg_gr_ctx) {
162 gr_gk20a_free_tsg_gr_ctx(tsg); 161 gr_gk20a_free_tsg_gr_ctx(tsg);
@@ -168,7 +167,12 @@ int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
168 release_used_tsg(&g->fifo, tsg); 167 release_used_tsg(&g->fifo, tsg);
169 168
170 gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid); 169 gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid);
170}
171 171
172int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
173{
174 struct tsg_gk20a *tsg = filp->private_data;
175 kref_put(&tsg->refcount, gk20a_tsg_release);
172 return 0; 176 return 0;
173} 177}
174 178