diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-10-21 16:14:09 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-10-22 14:41:24 -0400 |
commit | 75c09b96b409dfbd495081100e5fa82605651947 (patch) | |
tree | 3aab3b2e170926b0a3fe0e9e70b9bd8ed7caef3a /drivers/gpu/nvgpu | |
parent | 790173dcfd505d03bd5fb1a92e28bb53c94b0876 (diff) |
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 <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/821127
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 14 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 1 |
2 files changed, 13 insertions, 2 deletions
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) | |||
312 | * resource at this point | 312 | * resource at this point |
313 | * if not, then it will be destroyed at channel_free() | 313 | * if not, then it will be destroyed at channel_free() |
314 | */ | 314 | */ |
315 | mutex_lock(&ch_gk20a->sync_lock); | ||
315 | if (ch_gk20a->sync && ch_gk20a->sync->aggressive_destroy) { | 316 | if (ch_gk20a->sync && ch_gk20a->sync->aggressive_destroy) { |
317 | |||
316 | ch_gk20a->sync->destroy(ch_gk20a->sync); | 318 | ch_gk20a->sync->destroy(ch_gk20a->sync); |
317 | ch_gk20a->sync = NULL; | 319 | ch_gk20a->sync = NULL; |
318 | } | 320 | } |
321 | mutex_unlock(&ch_gk20a->sync_lock); | ||
319 | } | 322 | } |
320 | 323 | ||
321 | int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch) | 324 | int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch) |
@@ -375,10 +378,10 @@ void gk20a_channel_abort(struct channel_gk20a *ch) | |||
375 | ch->g->ops.fifo.disable_channel(ch); | 378 | ch->g->ops.fifo.disable_channel(ch); |
376 | 379 | ||
377 | /* ensure no fences are pending */ | 380 | /* ensure no fences are pending */ |
378 | mutex_lock(&ch->submit_lock); | 381 | mutex_lock(&ch->sync_lock); |
379 | if (ch->sync) | 382 | if (ch->sync) |
380 | ch->sync->set_min_eq_max(ch->sync); | 383 | ch->sync->set_min_eq_max(ch->sync); |
381 | mutex_unlock(&ch->submit_lock); | 384 | mutex_unlock(&ch->sync_lock); |
382 | 385 | ||
383 | /* release all job semaphores (applies only to jobs that use | 386 | /* release all job semaphores (applies only to jobs that use |
384 | semaphore synchronization) */ | 387 | semaphore synchronization) */ |
@@ -812,10 +815,12 @@ static void gk20a_free_channel(struct channel_gk20a *ch) | |||
812 | channel_gk20a_free_priv_cmdbuf(ch); | 815 | channel_gk20a_free_priv_cmdbuf(ch); |
813 | 816 | ||
814 | /* sync must be destroyed before releasing channel vm */ | 817 | /* sync must be destroyed before releasing channel vm */ |
818 | mutex_lock(&ch->sync_lock); | ||
815 | if (ch->sync) { | 819 | if (ch->sync) { |
816 | ch->sync->destroy(ch->sync); | 820 | ch->sync->destroy(ch->sync); |
817 | ch->sync = NULL; | 821 | ch->sync = NULL; |
818 | } | 822 | } |
823 | mutex_unlock(&ch->sync_lock); | ||
819 | 824 | ||
820 | /* release channel binding to the as_share */ | 825 | /* release channel binding to the as_share */ |
821 | if (ch_vm->as_share) | 826 | if (ch_vm->as_share) |
@@ -1772,11 +1777,13 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | |||
1772 | * the sync resource | 1777 | * the sync resource |
1773 | */ | 1778 | */ |
1774 | if (list_empty(&c->jobs)) { | 1779 | if (list_empty(&c->jobs)) { |
1780 | mutex_lock(&c->sync_lock); | ||
1775 | if (c->sync && c->sync->aggressive_destroy && | 1781 | if (c->sync && c->sync->aggressive_destroy && |
1776 | gk20a_fence_is_expired(c->last_submit.post_fence)) { | 1782 | gk20a_fence_is_expired(c->last_submit.post_fence)) { |
1777 | c->sync->destroy(c->sync); | 1783 | c->sync->destroy(c->sync); |
1778 | c->sync = NULL; | 1784 | c->sync = NULL; |
1779 | } | 1785 | } |
1786 | mutex_unlock(&c->sync_lock); | ||
1780 | } | 1787 | } |
1781 | mutex_unlock(&c->jobs_lock); | 1788 | mutex_unlock(&c->jobs_lock); |
1782 | mutex_unlock(&c->submit_lock); | 1789 | mutex_unlock(&c->submit_lock); |
@@ -1889,6 +1896,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1889 | 1896 | ||
1890 | mutex_lock(&c->submit_lock); | 1897 | mutex_lock(&c->submit_lock); |
1891 | 1898 | ||
1899 | mutex_lock(&c->sync_lock); | ||
1892 | if (!c->sync) { | 1900 | if (!c->sync) { |
1893 | c->sync = gk20a_channel_sync_create(c); | 1901 | c->sync = gk20a_channel_sync_create(c); |
1894 | if (!c->sync) { | 1902 | if (!c->sync) { |
@@ -1901,6 +1909,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1901 | if (err) | 1909 | if (err) |
1902 | return err; | 1910 | return err; |
1903 | } | 1911 | } |
1912 | mutex_unlock(&c->sync_lock); | ||
1904 | 1913 | ||
1905 | /* | 1914 | /* |
1906 | * optionally insert syncpt wait in the beginning of gpfifo submission | 1915 | * optionally insert syncpt wait in the beginning of gpfifo submission |
@@ -2053,6 +2062,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) | |||
2053 | mutex_init(&c->jobs_lock); | 2062 | mutex_init(&c->jobs_lock); |
2054 | mutex_init(&c->submit_lock); | 2063 | mutex_init(&c->submit_lock); |
2055 | mutex_init(&c->timeout.lock); | 2064 | mutex_init(&c->timeout.lock); |
2065 | mutex_init(&c->sync_lock); | ||
2056 | INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); | 2066 | INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); |
2057 | INIT_LIST_HEAD(&c->jobs); | 2067 | INIT_LIST_HEAD(&c->jobs); |
2058 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 2068 | #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 { | |||
166 | struct nvgpu_notification *error_notifier; | 166 | struct nvgpu_notification *error_notifier; |
167 | void *error_notifier_va; | 167 | void *error_notifier_va; |
168 | 168 | ||
169 | struct mutex sync_lock; | ||
169 | struct gk20a_channel_sync *sync; | 170 | struct gk20a_channel_sync *sync; |
170 | 171 | ||
171 | #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION | 172 | #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION |