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>
This commit is contained in:
Deepak Nibade
2014-09-04 19:09:26 +05:30
committed by Dan Willemsen
parent 949c47cbbb
commit b81e9a2431
2 changed files with 17 additions and 11 deletions

View File

@@ -24,6 +24,8 @@
#include "gk20a.h"
static void gk20a_tsg_release(struct kref *ref);
bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch)
{
return !(ch->tsgid == NVGPU_INVALID_TSG_ID);
@@ -51,6 +53,8 @@ static int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, int ch_fd)
list_add_tail(&ch->ch_entry, &tsg->ch_list);
mutex_unlock(&tsg->ch_list_lock);
kref_get(&tsg->refcount);
gk20a_dbg(gpu_dbg_fn, "BIND tsg:%d channel:%d\n",
tsg->tsgid, ch->hw_chid);
@@ -68,6 +72,8 @@ int gk20a_tsg_unbind_channel(struct channel_gk20a *ch)
list_del_init(&ch->ch_entry);
mutex_unlock(&tsg->ch_list_lock);
kref_put(&tsg->refcount, gk20a_tsg_release);
ch->tsgid = NVGPU_INVALID_TSG_ID;
return 0;
@@ -134,6 +140,7 @@ int gk20a_tsg_dev_open(struct inode *inode, struct file *filp)
tsg->g = g;
tsg->num_active_channels = 0;
kref_init(&tsg->refcount);
tsg->tsg_gr_ctx = NULL;
tsg->vm = NULL;
@@ -145,18 +152,10 @@ int gk20a_tsg_dev_open(struct inode *inode, struct file *filp)
return 0;
}
int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
static void gk20a_tsg_release(struct kref *ref)
{
struct tsg_gk20a *tsg = filp->private_data;
struct gk20a *g = container_of(inode->i_cdev,
struct gk20a, tsg.cdev);
if (tsg->num_active_channels) {
gk20a_err(dev_from_gk20a(g),
"Trying to free TSG %d with active channels %d\n",
tsg->tsgid, tsg->num_active_channels);
return -EBUSY;
}
struct tsg_gk20a *tsg = container_of(ref, struct tsg_gk20a, refcount);
struct gk20a *g = tsg->g;
if (tsg->tsg_gr_ctx) {
gr_gk20a_free_tsg_gr_ctx(tsg);
@@ -168,7 +167,12 @@ int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
release_used_tsg(&g->fifo, tsg);
gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid);
}
int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
{
struct tsg_gk20a *tsg = filp->private_data;
kref_put(&tsg->refcount, gk20a_tsg_release);
return 0;
}

View File

@@ -35,6 +35,8 @@ struct tsg_gk20a {
bool in_use;
int tsgid;
struct kref refcount;
struct list_head ch_list;
int num_active_channels;
struct mutex ch_list_lock;