diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-09-04 09:39:26 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:11:10 -0400 |
commit | b81e9a2431e9a045e586ff028e0262e99202b3f0 (patch) | |
tree | 133891ddf59562794bc5913e0c0c688e245ed3ad /drivers/gpu/nvgpu | |
parent | 949c47cbbb1f7560945b515c23a35b76475e16bf (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')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 26 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | 2 |
2 files changed, 17 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 | ||
27 | static void gk20a_tsg_release(struct kref *ref); | ||
28 | |||
27 | bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch) | 29 | bool 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 | ||
148 | int gk20a_tsg_dev_release(struct inode *inode, struct file *filp) | 155 | static 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 | ||
172 | int 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 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h index dd8679be..4ad02996 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | |||
@@ -35,6 +35,8 @@ struct tsg_gk20a { | |||
35 | bool in_use; | 35 | bool in_use; |
36 | int tsgid; | 36 | int tsgid; |
37 | 37 | ||
38 | struct kref refcount; | ||
39 | |||
38 | struct list_head ch_list; | 40 | struct list_head ch_list; |
39 | int num_active_channels; | 41 | int num_active_channels; |
40 | struct mutex ch_list_lock; | 42 | struct mutex ch_list_lock; |