From b81e9a2431e9a045e586ff028e0262e99202b3f0 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Thu, 4 Sep 2014 19:09:26 +0530 Subject: 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 Reviewed-on: http://git-master/r/495667 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/tsg_gk20a.c') 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 @@ #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; } -- cgit v1.2.2