mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
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:
committed by
Dan Willemsen
parent
949c47cbbb
commit
b81e9a2431
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user