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 <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/397670
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Deepak Nibade
2014-04-20 15:28:20 +05:30
committed by Dan Willemsen
parent 9984dff233
commit d4030081a8
2 changed files with 44 additions and 21 deletions

View File

@@ -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);

View File

@@ -84,6 +84,7 @@ struct channel_gk20a {
struct list_head jobs;
struct mutex jobs_lock;
struct mutex submit_lock;
struct vm_gk20a *vm;