mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: take power refcount in gk20a_cde_convert()
We have a gk20a_busy() call in gk20a_buffer_convert_gpu_to_cde() and we again call gk20a_busy() in gk20a_submit_channel_gpfifo() If gk20a_do_idle() is triggered in between these two calls, then this leads to a deadlock and results in idle failure Hence to avoid this take power refcount in a more fine-grained way i.e. in gk20a_cde_convert() instead of taking in gk20a_buffer_convert_gpu_to_cde() Keep gk20a_cde_execute_buffer() out of the gk20a_busy()/ gk20a_idle() pair since we take power refcount in submit path anyways Add correct error handling path in gk20a_cde_convert() Bug 200287073 Change-Id: Iffea2d4c03f42b47dbf05e7fe8fe2994f9c6b37c Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1324329 GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
3c8eef0d0e
commit
ce057d784d
@@ -947,12 +947,16 @@ __releases(&cde_app->mutex)
|
||||
scatterbuffer_byte_offset < compbits_byte_offset)
|
||||
return -EINVAL;
|
||||
|
||||
err = gk20a_busy(g->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nvgpu_mutex_acquire(&g->cde_app.mutex);
|
||||
cde_ctx = gk20a_cde_get_context(g);
|
||||
nvgpu_mutex_release(&g->cde_app.mutex);
|
||||
if (IS_ERR(cde_ctx)) {
|
||||
err = PTR_ERR(cde_ctx);
|
||||
goto exit_unlock;
|
||||
goto exit_idle;
|
||||
}
|
||||
|
||||
/* First, map the buffer to local va */
|
||||
@@ -960,7 +964,7 @@ __releases(&cde_app->mutex)
|
||||
/* ensure that the compbits buffer has drvdata */
|
||||
err = gk20a_dmabuf_alloc_drvdata(compbits_scatter_buf, g->dev);
|
||||
if (err)
|
||||
goto exit_unlock;
|
||||
goto exit_idle;
|
||||
|
||||
/* compbits don't start at page aligned offset, so we need to align
|
||||
the region to be mapped */
|
||||
@@ -1003,7 +1007,7 @@ __releases(&cde_app->mutex)
|
||||
if (!map_vaddr) {
|
||||
dma_buf_put(compbits_scatter_buf);
|
||||
err = -EINVAL;
|
||||
goto exit_unlock;
|
||||
goto exit_idle;
|
||||
}
|
||||
|
||||
if (scatterbuffer_byte_offset &&
|
||||
@@ -1017,7 +1021,7 @@ __releases(&cde_app->mutex)
|
||||
gk20a_warn(g->dev,
|
||||
"dma_buf_vmap failed");
|
||||
err = -EINVAL;
|
||||
goto exit_unlock;
|
||||
goto exit_unmap_vaddr;
|
||||
}
|
||||
|
||||
scatter_buffer = surface + scatterbuffer_byte_offset;
|
||||
@@ -1029,7 +1033,7 @@ __releases(&cde_app->mutex)
|
||||
gk20a_warn(g->dev,
|
||||
"mm_pin failed");
|
||||
err = -EINVAL;
|
||||
goto exit_unlock;
|
||||
goto exit_unmap_surface;
|
||||
} else {
|
||||
err = g->ops.cde.populate_scatter_buffer(g, sgt,
|
||||
compbits_byte_offset, scatter_buffer,
|
||||
@@ -1039,7 +1043,7 @@ __releases(&cde_app->mutex)
|
||||
gk20a_mm_unpin(g->dev, compbits_scatter_buf,
|
||||
sgt);
|
||||
if (err)
|
||||
goto exit_unlock;
|
||||
goto exit_unmap_surface;
|
||||
}
|
||||
|
||||
__cpuc_flush_dcache_area(scatter_buffer, scatterbuffer_size);
|
||||
@@ -1076,7 +1080,7 @@ __releases(&cde_app->mutex)
|
||||
if (id < 0 || id >= MAX_CDE_USER_PARAMS) {
|
||||
gk20a_warn(cde_ctx->dev, "cde: unknown user parameter");
|
||||
err = -EINVAL;
|
||||
goto exit_unlock;
|
||||
goto exit_unmap_surface;
|
||||
}
|
||||
cde_ctx->user_param_values[id] = param->value;
|
||||
}
|
||||
@@ -1085,7 +1089,7 @@ __releases(&cde_app->mutex)
|
||||
err = gk20a_cde_patch_params(cde_ctx);
|
||||
if (err) {
|
||||
gk20a_warn(cde_ctx->dev, "cde: failed to patch parameters");
|
||||
goto exit_unlock;
|
||||
goto exit_unmap_surface;
|
||||
}
|
||||
|
||||
gk20a_dbg(gpu_dbg_cde, "cde: buffer=cbc, size=%zu, gpuva=%llx\n",
|
||||
@@ -1095,11 +1099,13 @@ __releases(&cde_app->mutex)
|
||||
gk20a_dbg(gpu_dbg_cde, "cde: buffer=scatterbuffer, size=%llu, gpuva=%llx\n",
|
||||
cde_ctx->scatterbuffer_size, cde_ctx->scatterbuffer_vaddr);
|
||||
|
||||
|
||||
/* take always the postfence as it is needed for protecting the
|
||||
* cde context */
|
||||
flags = __flags | NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET;
|
||||
|
||||
/* gk20a_cde_execute_buffer() will grab a power reference of it's own */
|
||||
gk20a_idle(g->dev);
|
||||
|
||||
/* execute the conversion buffer, combined with init first if it's the
|
||||
* first time */
|
||||
err = gk20a_cde_execute_buffer(cde_ctx,
|
||||
@@ -1110,16 +1116,21 @@ __releases(&cde_app->mutex)
|
||||
|
||||
cde_ctx->init_cmd_executed = true;
|
||||
|
||||
exit_unlock:
|
||||
|
||||
/* unmap the buffers - channel holds references to them now */
|
||||
if (map_vaddr)
|
||||
gk20a_vm_unmap(cde_ctx->vm, map_vaddr);
|
||||
|
||||
if (surface)
|
||||
dma_buf_vunmap(compbits_scatter_buf, surface);
|
||||
gk20a_vm_unmap(cde_ctx->vm, map_vaddr);
|
||||
|
||||
return err;
|
||||
|
||||
exit_unmap_surface:
|
||||
if (surface)
|
||||
dma_buf_vunmap(compbits_scatter_buf, surface);
|
||||
exit_unmap_vaddr:
|
||||
gk20a_vm_unmap(cde_ctx->vm, map_vaddr);
|
||||
exit_idle:
|
||||
gk20a_idle(g->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void gk20a_cde_finished_ctx_cb(struct channel_gk20a *ch, void *data)
|
||||
@@ -1511,10 +1522,6 @@ static int gk20a_buffer_convert_gpu_to_cde(
|
||||
if (!g->cde_app.initialised)
|
||||
return -ENOSYS;
|
||||
|
||||
err = gk20a_busy(g->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
gk20a_dbg(gpu_dbg_cde, "firmware version = %d\n",
|
||||
g->cde_app.firmware_version);
|
||||
|
||||
@@ -1530,7 +1537,6 @@ static int gk20a_buffer_convert_gpu_to_cde(
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
gk20a_idle(g->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user