mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 02:52:51 +03:00
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:
committed by
Terje Bergstrom
parent
2ca20e14ba
commit
8b665ac6b2
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user