From d4030081a867865be95cd3ede1407f0d35d5c761 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Sun, 20 Apr 2014 15:28:20 +0530 Subject: gpu: nvgpu: gk20a: add submit_lock Add submit mutex lock to avoid race conditions between submitting a job, removing a job and submitting WFI With this lock make below operations atomic : during submit_gpfifo() - 1. getting new syncpt 2. inserting syncpt increment 3. submitting gpfifo 4. setting job completion interrupt during submit_wfi() - 1. getting new syncpt 2. inserting syncpt increment when idle during channel_update() - 1. checking the submit job completion 2. freeing the job if it is completed Bug 1305024 Change-Id: I0e3c0b8906d83fd59642344626ffdf24fad2aaab Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/397670 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 64 ++++++++++++++++++++++----------- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 1 + 2 files changed, 44 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 1570e12c..b7bd55ea 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -1268,12 +1268,6 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c) if (c->has_timedout) return -ETIMEDOUT; - if (!c->sync) { - c->sync = gk20a_channel_sync_create(c); - if (!c->sync) - return -ENOMEM; - } - update_gp_get(g, c); free_count = gp_free_count(c); if (unlikely(!free_count)) { @@ -1282,9 +1276,21 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c) return -EAGAIN; } + mutex_lock(&c->submit_lock); + + if (!c->sync) { + c->sync = gk20a_channel_sync_create(c); + if (!c->sync) { + mutex_unlock(&c->submit_lock); + return -ENOMEM; + } + } + err = c->sync->incr_wfi(c->sync, &cmd, &c->last_submit_fence); - if (unlikely(err)) + if (unlikely(err)) { + mutex_unlock(&c->submit_lock); return err; + } WARN_ON(!c->last_submit_fence.wfi); @@ -1301,6 +1307,8 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c) c->userd_gpu_va + 4 * ram_userd_gp_put_w(), c->gpfifo.put); + mutex_unlock(&c->submit_lock); + gk20a_dbg_info("post-submit put %d, get %d, size %d", c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num); @@ -1393,6 +1401,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) wake_up(&c->submit_wq); + mutex_lock(&c->submit_lock); mutex_lock(&c->jobs_lock); list_for_each_entry_safe(job, n, &c->jobs, list) { bool completed = WARN_ON(!c->sync) || @@ -1411,6 +1420,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) gk20a_idle(g->dev); } mutex_unlock(&c->jobs_lock); + mutex_unlock(&c->submit_lock); for (i = 0; i < nr_completed; i++) gk20a_idle(c->g->dev); @@ -1452,12 +1462,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, !fence) return -EINVAL; - if (!c->sync) { - c->sync = gk20a_channel_sync_create(c); - if (!c->sync) - return -ENOMEM; - } - #ifdef CONFIG_DEBUG_FS /* update debug settings */ if (g->ops.ltc.sync_debugfs) @@ -1510,6 +1514,17 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, goto clean_up; } + mutex_lock(&c->submit_lock); + + if (!c->sync) { + c->sync = gk20a_channel_sync_create(c); + if (!c->sync) { + err = -ENOMEM; + mutex_unlock(&c->submit_lock); + goto clean_up; + } + } + /* * optionally insert syncpt wait in the beginning of gpfifo submission * when user requested and the wait hasn't expired. @@ -1525,8 +1540,10 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, err = c->sync->wait_syncpt(c->sync, fence->syncpt_id, fence->value, &wait_cmd); } - if (err) + if (err) { + mutex_unlock(&c->submit_lock); goto clean_up; + } /* always insert syncpt increment at end of gpfifo submission @@ -1544,8 +1561,10 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, else err = c->sync->incr(c->sync, &incr_cmd, &c->last_submit_fence); - if (err) + if (err) { + mutex_unlock(&c->submit_lock); goto clean_up; + } if (wait_cmd) { c->gpfifo.cpu_va[c->gpfifo.put].entry0 = @@ -1587,12 +1606,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, incr_cmd->gp_put = c->gpfifo.put; } - trace_gk20a_channel_submitted_gpfifo(c->g->dev->name, - c->hw_chid, - num_entries, - flags, - fence->syncpt_id, fence->value); - /* TODO! Check for errors... */ gk20a_channel_add_job(c, &c->last_submit_fence); @@ -1601,6 +1614,14 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, c->userd_gpu_va + 4 * ram_userd_gp_put_w(), c->gpfifo.put); + mutex_unlock(&c->submit_lock); + + trace_gk20a_channel_submitted_gpfifo(c->g->dev->name, + c->hw_chid, + num_entries, + flags, + fence->syncpt_id, fence->value); + gk20a_dbg_info("post-submit put %d, get %d, size %d", c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num); @@ -1629,6 +1650,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) c->bound = false; c->remove_support = gk20a_remove_channel_support; mutex_init(&c->jobs_lock); + mutex_init(&c->submit_lock); INIT_LIST_HEAD(&c->jobs); #if defined(CONFIG_GK20A_CYCLE_STATS) mutex_init(&c->cyclestate.cyclestate_buffer_mutex); diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 47fc714c..e37511cb 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -84,6 +84,7 @@ struct channel_gk20a { struct list_head jobs; struct mutex jobs_lock; + struct mutex submit_lock; struct vm_gk20a *vm; -- cgit v1.2.2