summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-04-18 06:16:10 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-04-19 11:16:13 -0400
commite0c9da1fe9d8862fc89773208aa170b7c73d093b (patch)
treef9f0f9edbe7ae1c2f44285b0ce89385d18dc826a /drivers/gpu/nvgpu/gk20a/channel_gk20a.c
parent1c96bc6942cdae7f4e90563687da7d068aea90bc (diff)
gpu: nvgpu: implement sync refcounting
We currently free sync when we find job list empty If aggressive_sync is set to true, we try to free sync during channel unbind() call But we rarely free sync from channel_unbind() call since freeing it when job list is empty is aggressive enough Hence remove sync free code from channel_unbind() Implement refcounting for sync: - get a refcount while submitting a job (and allocate sync if it is not allocated already) - put a refcount while freeing the job - if refcount==0 and if aggressive_sync_destroy is set, free the sync - if aggressive_sync_destroy is not set, we will free the sync during channel close time Bug 200187553 Change-Id: I74e24adb15dc26a375ebca1fdd017b3ad6d57b61 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1120410 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c45
1 files changed, 13 insertions, 32 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index aeb115ef..b282db89 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -370,7 +370,6 @@ static void channel_gk20a_bind(struct channel_gk20a *c)
370void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a) 370void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a)
371{ 371{
372 struct gk20a *g = ch_gk20a->g; 372 struct gk20a *g = ch_gk20a->g;
373 struct gk20a_platform *platform = gk20a_get_platform(g->dev);
374 373
375 gk20a_dbg_fn(""); 374 gk20a_dbg_fn("");
376 375
@@ -380,18 +379,6 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a)
380 ccsr_channel_inst_bind_false_f()); 379 ccsr_channel_inst_bind_false_f());
381 380
382 ch_gk20a->bound = false; 381 ch_gk20a->bound = false;
383
384 /*
385 * if we are agrressive then we can destroy the syncpt
386 * resource at this point
387 * if not, then it will be destroyed at channel_free()
388 */
389 mutex_lock(&ch_gk20a->sync_lock);
390 if (ch_gk20a->sync && platform->aggressive_sync_destroy) {
391 ch_gk20a->sync->destroy(ch_gk20a->sync);
392 ch_gk20a->sync = NULL;
393 }
394 mutex_unlock(&ch_gk20a->sync_lock);
395} 382}
396 383
397int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch) 384int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch)
@@ -954,7 +941,7 @@ static void gk20a_free_channel(struct channel_gk20a *ch)
954 /* sync must be destroyed before releasing channel vm */ 941 /* sync must be destroyed before releasing channel vm */
955 mutex_lock(&ch->sync_lock); 942 mutex_lock(&ch->sync_lock);
956 if (ch->sync) { 943 if (ch->sync) {
957 ch->sync->destroy(ch->sync); 944 gk20a_channel_sync_destroy(ch->sync);
958 ch->sync = NULL; 945 ch->sync = NULL;
959 } 946 }
960 mutex_unlock(&ch->sync_lock); 947 mutex_unlock(&ch->sync_lock);
@@ -1922,8 +1909,18 @@ static void gk20a_channel_clean_up_jobs(struct work_struct *work)
1922 1909
1923 gk20a_channel_timeout_stop(c); 1910 gk20a_channel_timeout_stop(c);
1924 1911
1925 if (c->sync) 1912 mutex_lock(&c->sync_lock);
1913 if (c->sync) {
1926 c->sync->signal_timeline(c->sync); 1914 c->sync->signal_timeline(c->sync);
1915 if (atomic_dec_and_test(&c->sync->refcount) &&
1916 platform->aggressive_sync_destroy) {
1917 gk20a_channel_sync_destroy(c->sync);
1918 c->sync = NULL;
1919 }
1920 } else {
1921 WARN_ON(1);
1922 }
1923 mutex_unlock(&c->sync_lock);
1927 1924
1928 if (job->num_mapped_buffers) 1925 if (job->num_mapped_buffers)
1929 gk20a_vm_put_buffers(vm, job->mapped_buffers, 1926 gk20a_vm_put_buffers(vm, job->mapped_buffers,
@@ -1950,23 +1947,6 @@ static void gk20a_channel_clean_up_jobs(struct work_struct *work)
1950 gk20a_idle(g->dev); 1947 gk20a_idle(g->dev);
1951 } 1948 }
1952 1949
1953 /*
1954 * If job list is empty then channel is idle and we can free
1955 * the syncpt here (given aggressive_destroy flag is set)
1956 * Note: check if last submit is complete before destroying
1957 * the sync resource
1958 */
1959 if (list_empty(&c->jobs)) {
1960 mutex_lock(&c->sync_lock);
1961 mutex_lock(&c->last_submit.fence_lock);
1962 if (c->sync && platform->aggressive_sync_destroy &&
1963 gk20a_fence_is_expired(c->last_submit.post_fence)) {
1964 c->sync->destroy(c->sync);
1965 c->sync = NULL;
1966 }
1967 mutex_unlock(&c->last_submit.fence_lock);
1968 mutex_unlock(&c->sync_lock);
1969 }
1970 mutex_unlock(&c->jobs_lock); 1950 mutex_unlock(&c->jobs_lock);
1971 mutex_unlock(&c->submit_lock); 1951 mutex_unlock(&c->submit_lock);
1972 1952
@@ -2121,6 +2101,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2121 } 2101 }
2122 new_sync_created = true; 2102 new_sync_created = true;
2123 } 2103 }
2104 atomic_inc(&c->sync->refcount);
2124 mutex_unlock(&c->sync_lock); 2105 mutex_unlock(&c->sync_lock);
2125 2106
2126 if (g->ops.fifo.resetup_ramfc && new_sync_created) { 2107 if (g->ops.fifo.resetup_ramfc && new_sync_created) {