From 2ac8c9729a5b7ca0b0bdc053e72d2b4658f8bed7 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Fri, 1 Apr 2016 16:25:52 +0530 Subject: gpu: nvgpu: make jobs_lock more fine grained While processing all the jobs in gk20a_channel_clean_up_jobs(), We currently acquire jobs_lock, traverse the list, clean up the jobs, and then release the lock But in this case we might hold the lock for too long blocking the submit path Hence make jobs_lock more fine grained by restricting it for list accesses only Bug 200187553 Change-Id: If82af8ff386f7bc29061cfd57fdda7df62f11c17 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/1120412 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 1b9047c0..e6ecac14 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -1862,23 +1862,33 @@ static void gk20a_channel_clean_up_jobs(struct work_struct *work) struct channel_gk20a *c = container_of(to_delayed_work(work), struct channel_gk20a, clean_up.wq); struct vm_gk20a *vm; - struct channel_gk20a_job *job, *n; + struct channel_gk20a_job *job; struct gk20a_platform *platform; + struct gk20a *g; c = gk20a_channel_get(c); if (!c) return; vm = c->vm; - platform = gk20a_get_platform(c->g->dev); + g = c->g; + platform = gk20a_get_platform(g->dev); gk20a_channel_cancel_job_clean_up(c, false); - mutex_lock(&c->jobs_lock); - list_for_each_entry_safe(job, n, &c->jobs, list) { - struct gk20a *g = c->g; + while (1) { + bool completed; - bool completed = gk20a_fence_is_expired(job->post_fence); + mutex_lock(&c->jobs_lock); + if (list_empty(&c->jobs)) { + mutex_unlock(&c->jobs_lock); + break; + } + job = list_first_entry(&c->jobs, + struct channel_gk20a_job, list); + mutex_unlock(&c->jobs_lock); + + completed = gk20a_fence_is_expired(job->post_fence); if (!completed) { gk20a_channel_timeout_start(c, job); break; @@ -1919,13 +1929,15 @@ static void gk20a_channel_clean_up_jobs(struct work_struct *work) * so this wouldn't get freed here. */ gk20a_channel_put(c); + mutex_lock(&c->jobs_lock); list_del_init(&job->list); + mutex_unlock(&c->jobs_lock); + kfree(job); + gk20a_idle(g->dev); } - mutex_unlock(&c->jobs_lock); - if (c->update_fn) schedule_work(&c->update_fn_work); -- cgit v1.2.2