gpu: nvgpu: Simplify ref-counting on VMs

Simplify ref-counting on VMs: take a ref when a VM is bound to a
channel and drop a ref when a channel is freed.

Previously ref-counts were scattered over the driver. Also the CE
and CDE code would bind channels with custom rolled code. This was
because the gk20a_vm_bind_channel() function took an as_share as
the VM argument (the VM was then inferred from that as_share).
However, it is trivial to abtract that bit out and allow a central
bind channel function that just takes a VM and a channel.

Bug 1846718

Change-Id: I156aab259f6c7a2fa338408c6c4a3a464cd44a0c
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: http://git-master/r/1261886
Reviewed-by: Richard Zhao <rizhao@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Alex Waterman
2016-11-29 16:01:41 -08:00
committed by mobile promotions
parent 07f0798173
commit 7e403974d3
6 changed files with 23 additions and 30 deletions

View File

@@ -1203,9 +1203,7 @@ static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx)
}
/* bind the channel to the vm */
gk20a_vm_get(&g->mm.cde.vm);
ch->vm = &g->mm.cde.vm;
err = channel_gk20a_commit_va(ch);
err = __gk20a_vm_bind_channel(&g->mm.cde.vm, ch);
if (err) {
gk20a_warn(cde_ctx->dev, "cde: could not bind vm");
goto err_commit_va;

View File

@@ -453,9 +453,7 @@ u32 gk20a_ce_create_context_with_cb(struct device *dev,
}
/* bind the channel to the vm */
gk20a_vm_get(&g->mm.ce.vm);
ce_ctx->vm = ce_ctx->ch->vm = &g->mm.ce.vm;
err = channel_gk20a_commit_va(ce_ctx->ch);
err = __gk20a_vm_bind_channel(&g->mm.ce.vm, ce_ctx->ch);
if (err) {
gk20a_err(ce_ctx->dev, "ce: could not bind vm");
goto end;

View File

@@ -1008,11 +1008,10 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
if (ch->hw_sema)
gk20a_semaphore_free_hw_sema(ch);
/* release channel binding to the as_share */
if (ch_vm->as_share)
gk20a_as_release_share(ch_vm->as_share);
else
gk20a_vm_put(ch_vm);
/*
* When releasing the channel we unbind the VM - so release the ref.
*/
gk20a_vm_put(ch_vm);
spin_lock(&ch->update_fn_lock);
ch->update_fn = NULL;
@@ -2252,14 +2251,11 @@ static int gk20a_channel_add_job(struct channel_gk20a *c,
int err = 0, num_mapped_buffers = 0;
bool pre_alloc_enabled = channel_gk20a_is_prealloc_enabled(c);
/* job needs reference to this vm (released in channel_update) */
gk20a_vm_get(vm);
if (!skip_buffer_refcounting) {
err = gk20a_vm_get_buffers(vm, &mapped_buffers,
&num_mapped_buffers);
if (err)
goto err_put_vm;
return err;
}
/* put() is done in gk20a_channel_update() when the job is done */
@@ -2293,8 +2289,6 @@ static int gk20a_channel_add_job(struct channel_gk20a *c,
err_put_buffers:
gk20a_vm_put_buffers(vm, mapped_buffers, num_mapped_buffers);
err_put_vm:
gk20a_vm_put(vm);
return err;
}
@@ -2385,8 +2379,6 @@ static void gk20a_channel_clean_up_jobs(struct channel_gk20a *c,
gk20a_free_priv_cmdbuf(c, job->wait_cmd);
gk20a_free_priv_cmdbuf(c, job->incr_cmd);
/* job is done. release its vm reference (taken in add_job) */
gk20a_vm_put(vm);
/* another bookkeeping taken in add_job. caller must hold a ref
* so this wouldn't get freed here. */
gk20a_channel_put(c);

View File

@@ -4199,10 +4199,8 @@ static int gk20a_init_sema_pool(struct vm_gk20a *vm)
return -ENOMEM;
vm->sema_pool = gk20a_semaphore_pool_alloc(sema_sea);
if (!vm->sema_pool) {
gk20a_vm_put(vm);
if (!vm->sema_pool)
return -ENOMEM;
}
/*
* Allocate a chunk of GPU VA space for mapping the semaphores. We will
@@ -4227,7 +4225,7 @@ static int gk20a_init_sema_pool(struct vm_gk20a *vm)
gk20a_semaphore_pool_unmap(vm->sema_pool, vm);
nvgpu_free(vm->vma[gmmu_page_size_small],
vm->sema_pool->gpu_va);
gk20a_vm_put(vm);
return err;
}
return 0;
@@ -4632,12 +4630,10 @@ int gk20a_vm_release_share(struct gk20a_as_share *as_share)
gk20a_dbg_fn("");
vm->as_share = NULL;
/* put as reference to vm */
gk20a_vm_put(vm);
as_share->vm = NULL;
gk20a_vm_put(vm);
return 0;
}
@@ -4792,14 +4788,13 @@ int gk20a_vm_free_space(struct gk20a_as_share *as_share,
return err;
}
int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
struct channel_gk20a *ch)
int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch)
{
int err = 0;
struct vm_gk20a *vm = as_share->vm;
gk20a_dbg_fn("");
gk20a_vm_get(vm);
ch->vm = vm;
err = channel_gk20a_commit_va(ch);
if (err)
@@ -4808,6 +4803,12 @@ int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
return err;
}
int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
struct channel_gk20a *ch)
{
return __gk20a_vm_bind_channel(as_share->vm, ch);
}
int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev)
{
struct gk20a_dmabuf_priv *priv;

View File

@@ -707,6 +707,7 @@ int gk20a_vm_free_space(struct gk20a_as_share *as_share,
struct nvgpu_as_free_space_args *args);
int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
struct channel_gk20a *ch);
int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch);
/* batching eliminates redundant cache flushes and invalidates */
void gk20a_vm_mapping_batch_start(struct vm_gk20a_mapping_batch *batch);

View File

@@ -446,6 +446,9 @@ static int vgpu_vm_bind_channel(struct gk20a_as_share *as_share,
err = -ENOMEM;
}
if (ch->vm)
gk20a_vm_get(ch->vm);
return err;
}