From 8b665ac6b2984e07a290d5ecbcec2c93ec973c65 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Tue, 12 Jan 2016 18:51:37 +0530 Subject: gpu: nvgpu: move clean up of jobs to separate worker We currently clean up the jobs in gk20a_channel_update() which is called from nvhost worker thread Instead of doing this, schedule another delayed worker thread clean_up_work to clean up the jobs (with delay of 1 jiffies) Keep update_gp_get() in channel_update() and not in delayed worker since this will help in better book keeping of gp_get Also, this scheduling will help delay job clean-up so that more number of jobs are batched for clean up and hence less time is consumed by worker Bug 1718092 Change-Id: If3b94b6aab93c92da4cf0d1c74aaba756f4cd838 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/931701 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 67 ++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 6 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 5e5bbcb0..1f63bbd8 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -64,6 +64,8 @@ static void gk20a_free_error_notifiers(struct channel_gk20a *ch); static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch); +static void gk20a_channel_clean_up_jobs(struct work_struct *work); + /* allocate GPU channel */ static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) { @@ -1144,6 +1146,7 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) ch->wdt_enabled = true; ch->obj_class = 0; ch->interleave = false; + ch->clean_up.scheduled = false; gk20a_fifo_set_channel_priority( ch->g, 0, ch->hw_chid, ch->interleave); @@ -1771,6 +1774,32 @@ static int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, return 0; } +static void gk20a_channel_schedule_job_clean_up(struct channel_gk20a *c) +{ + mutex_lock(&c->clean_up.lock); + + if (c->clean_up.scheduled) { + mutex_unlock(&c->clean_up.lock); + return; + } + + c->clean_up.scheduled = true; + schedule_delayed_work(&c->clean_up.wq, 1); + + mutex_unlock(&c->clean_up.lock); +} + +static void gk20a_channel_cancel_job_clean_up(struct channel_gk20a *c, + bool wait_for_completion) +{ + if (wait_for_completion) + cancel_delayed_work_sync(&c->clean_up.wq); + + mutex_lock(&c->clean_up.lock); + c->clean_up.scheduled = false; + mutex_unlock(&c->clean_up.lock); +} + static int gk20a_channel_add_job(struct channel_gk20a *c, struct gk20a_fence *pre_fence, struct gk20a_fence *post_fence, @@ -1832,22 +1861,28 @@ err_put_vm: return err; } -void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) +static void gk20a_channel_clean_up_jobs(struct work_struct *work) { - struct vm_gk20a *vm = c->vm; + 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 gk20a_platform *platform = gk20a_get_platform(c->g->dev); + struct gk20a_platform *platform; - trace_gk20a_channel_update(c->hw_chid); + c = gk20a_channel_get(c); + if (!c) + return; - update_gp_get(c->g, c); - wake_up(&c->submit_wq); + vm = c->vm; + platform = gk20a_get_platform(c->g->dev); mutex_lock(&c->submit_lock); /* gp_put check needs to be done inside submit lock */ check_gp_put(c->g, c); + 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; @@ -1908,6 +1943,23 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) if (c->update_fn) schedule_work(&c->update_fn_work); + + gk20a_channel_put(c); +} + +void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) +{ + c = gk20a_channel_get(c); + if (!c) + return; + + update_gp_get(c->g, c); + wake_up(&c->submit_wq); + + trace_gk20a_channel_update(c->hw_chid); + gk20a_channel_schedule_job_clean_up(c); + + gk20a_channel_put(c); } int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, @@ -2249,6 +2301,8 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) mutex_init(&c->timeout.lock); mutex_init(&c->sync_lock); INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); + INIT_DELAYED_WORK(&c->clean_up.wq, gk20a_channel_clean_up_jobs); + mutex_init(&c->clean_up.lock); INIT_LIST_HEAD(&c->jobs); #if defined(CONFIG_GK20A_CYCLE_STATS) mutex_init(&c->cyclestate.cyclestate_buffer_mutex); @@ -2612,6 +2666,7 @@ int gk20a_channel_suspend(struct gk20a *g) if (ch->update_fn && work_pending(&ch->update_fn_work)) flush_work(&ch->update_fn_work); + gk20a_channel_cancel_job_clean_up(ch, true); channels_in_use = true; -- cgit v1.2.2