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 <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/931701
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Deepak Nibade
2016-01-12 18:51:37 +05:30
committed by Terje Bergstrom
parent 2ca20e14ba
commit 8b665ac6b2
2 changed files with 68 additions and 6 deletions

View File

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

View File

@@ -80,6 +80,12 @@ struct channel_gk20a_poll_events {
int num_pending_events;
};
struct channel_gk20a_clean_up {
struct mutex lock;
bool scheduled;
struct delayed_work wq;
};
/* this is the priv element of struct nvhost_channel */
struct channel_gk20a {
struct gk20a *g; /* set only when channel is active */
@@ -133,6 +139,7 @@ struct channel_gk20a {
u32 timeout_gpfifo_get;
struct channel_gk20a_timeout timeout;
struct channel_gk20a_clean_up clean_up;
bool cmds_pending;
struct {