From 75c09b96b409dfbd495081100e5fa82605651947 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Wed, 21 Oct 2015 13:14:09 -0700 Subject: gpu: nvgpu: Protect sync by an own lock Protect creation and deletion of sync by an own mutex. This prevents deadlock in channel abort when abort is called from submit path. Bug 200147887 Change-Id: I5d6308b773c1d1a6a89d4590e2e74c74d691f79d Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/821127 --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 14 ++++++++++++-- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 34b62ac4..c09586c5 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -312,10 +312,13 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a) * resource at this point * if not, then it will be destroyed at channel_free() */ + mutex_lock(&ch_gk20a->sync_lock); if (ch_gk20a->sync && ch_gk20a->sync->aggressive_destroy) { + ch_gk20a->sync->destroy(ch_gk20a->sync); ch_gk20a->sync = NULL; } + mutex_unlock(&ch_gk20a->sync_lock); } int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch) @@ -375,10 +378,10 @@ void gk20a_channel_abort(struct channel_gk20a *ch) ch->g->ops.fifo.disable_channel(ch); /* ensure no fences are pending */ - mutex_lock(&ch->submit_lock); + mutex_lock(&ch->sync_lock); if (ch->sync) ch->sync->set_min_eq_max(ch->sync); - mutex_unlock(&ch->submit_lock); + mutex_unlock(&ch->sync_lock); /* release all job semaphores (applies only to jobs that use semaphore synchronization) */ @@ -812,10 +815,12 @@ static void gk20a_free_channel(struct channel_gk20a *ch) channel_gk20a_free_priv_cmdbuf(ch); /* sync must be destroyed before releasing channel vm */ + mutex_lock(&ch->sync_lock); if (ch->sync) { ch->sync->destroy(ch->sync); ch->sync = NULL; } + mutex_unlock(&ch->sync_lock); /* release channel binding to the as_share */ if (ch_vm->as_share) @@ -1772,11 +1777,13 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) * the sync resource */ if (list_empty(&c->jobs)) { + mutex_lock(&c->sync_lock); if (c->sync && c->sync->aggressive_destroy && gk20a_fence_is_expired(c->last_submit.post_fence)) { c->sync->destroy(c->sync); c->sync = NULL; } + mutex_unlock(&c->sync_lock); } mutex_unlock(&c->jobs_lock); mutex_unlock(&c->submit_lock); @@ -1889,6 +1896,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, mutex_lock(&c->submit_lock); + mutex_lock(&c->sync_lock); if (!c->sync) { c->sync = gk20a_channel_sync_create(c); if (!c->sync) { @@ -1901,6 +1909,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, if (err) return err; } + mutex_unlock(&c->sync_lock); /* * optionally insert syncpt wait in the beginning of gpfifo submission @@ -2053,6 +2062,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) mutex_init(&c->jobs_lock); mutex_init(&c->submit_lock); mutex_init(&c->timeout.lock); + mutex_init(&c->sync_lock); INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); INIT_LIST_HEAD(&c->jobs); #if defined(CONFIG_GK20A_CYCLE_STATS) diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 3e18e053..794d8228 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -166,6 +166,7 @@ struct channel_gk20a { struct nvgpu_notification *error_notifier; void *error_notifier_va; + struct mutex sync_lock; struct gk20a_channel_sync *sync; #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION -- cgit v1.2.2