diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 6015ab5ea..8db885e33 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -42,6 +42,8 @@ #define NVMAP_HANDLE_PARAM_SIZE 1 +#define NVGPU_BEGIN_AGGRESSIVE_SYNC_DESTROY_LIMIT 64 /* channels */ + static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f); static void free_channel(struct fifo_gk20a *f, struct channel_gk20a *c); @@ -64,6 +66,7 @@ static void gk20a_free_error_notifiers(struct channel_gk20a *ch); static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) { struct channel_gk20a *ch = NULL; + struct gk20a_platform *platform = gk20a_get_platform(f->g->dev); mutex_lock(&f->free_chs_mutex); if (!list_empty(&f->free_chs)) { @@ -72,21 +75,31 @@ static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) list_del(&ch->free_chs); WARN_ON(atomic_read(&ch->ref_count)); WARN_ON(ch->referenceable); + f->used_channels++; } mutex_unlock(&f->free_chs_mutex); + if (f->used_channels > NVGPU_BEGIN_AGGRESSIVE_SYNC_DESTROY_LIMIT) + platform->aggressive_sync_destroy = true; + return ch; } static void free_channel(struct fifo_gk20a *f, struct channel_gk20a *ch) { + struct gk20a_platform *platform = gk20a_get_platform(f->g->dev); + trace_gk20a_release_used_channel(ch->hw_chid); /* refcount is zero here and channel is in a freed/dead state */ mutex_lock(&f->free_chs_mutex); /* add to head to increase visibility of timing-related bugs */ list_add(&ch->free_chs, &f->free_chs); + f->used_channels--; mutex_unlock(&f->free_chs_mutex); + + if (f->used_channels < NVGPU_BEGIN_AGGRESSIVE_SYNC_DESTROY_LIMIT) + platform->aggressive_sync_destroy = false; } int channel_gk20a_commit_va(struct channel_gk20a *c) @@ -311,6 +324,7 @@ static void channel_gk20a_bind(struct channel_gk20a *ch_gk20a) void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a) { struct gk20a *g = ch_gk20a->g; + struct gk20a_platform *platform = gk20a_get_platform(g->dev); gk20a_dbg_fn(""); @@ -327,8 +341,7 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a) * if not, then it will be destroyed at channel_free() */ mutex_lock(&ch_gk20a->sync_lock); - if (ch_gk20a->sync && ch_gk20a->sync->aggressive_destroy) { - + if (ch_gk20a->sync && platform->aggressive_sync_destroy) { ch_gk20a->sync->destroy(ch_gk20a->sync); ch_gk20a->sync = NULL; } @@ -1715,6 +1728,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) { struct vm_gk20a *vm = c->vm; struct channel_gk20a_job *job, *n; + struct gk20a_platform *platform = gk20a_get_platform(c->g->dev); trace_gk20a_channel_update(c->hw_chid); @@ -1769,7 +1783,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) */ if (list_empty(&c->jobs)) { mutex_lock(&c->sync_lock); - if (c->sync && c->sync->aggressive_destroy && + if (c->sync && platform->aggressive_sync_destroy && gk20a_fence_is_expired(c->last_submit.post_fence)) { c->sync->destroy(c->sync); c->sync = NULL; diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index 7f70d3472..95647774c 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c @@ -345,8 +345,6 @@ gk20a_channel_syncpt_create(struct channel_gk20a *c) sp->ops.syncpt_id = gk20a_channel_syncpt_id; sp->ops.destroy = gk20a_channel_syncpt_destroy; - sp->ops.aggressive_destroy = true; - return &sp->ops; } #endif /* CONFIG_TEGRA_GK20A */ @@ -690,10 +688,6 @@ gk20a_channel_semaphore_create(struct channel_gk20a *c) sema->ops.syncpt_id = gk20a_channel_semaphore_syncpt_id; sema->ops.destroy = gk20a_channel_semaphore_destroy; - /* Aggressively destroying the semaphore sync would cause overhead - * since the pool needs to be mapped to GMMU. */ - sema->ops.aggressive_destroy = false; - return &sema->ops; clean_up: gk20a_channel_semaphore_destroy(&sema->ops); diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index 3f9fac548..1b47677b1 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h @@ -105,6 +105,7 @@ struct fifo_gk20a { struct mem_desc userd; u32 userd_entry_size; + int used_channels; struct channel_gk20a *channel; /* zero-kref'd channels here */ struct list_head free_chs; diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index b7a28ea57..84b3fcafc 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h @@ -47,6 +47,9 @@ struct gk20a_platform { /* Should be populated at probe. */ bool has_syncpoints; + /* flag to set sync destroy aggressiveness */ + bool aggressive_sync_destroy; + /* Should be populated by probe. */ struct dentry *debugfs; struct dentry *debugfs_alias; diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c index 664f8c5bc..dd6630a77 100644 --- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c @@ -63,7 +63,7 @@ static void vgpu_channel_unbind(struct channel_gk20a *ch) * resource at this point * if not, then it will be destroyed at channel_free() */ - if (ch->sync && ch->sync->aggressive_destroy) { + if (ch->sync && platform->aggressive_sync_destroy) { ch->sync->destroy(ch->sync); ch->sync = NULL; }