From 7505a759542c2d95e5abb42d44b8fb6afda74a87 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Tue, 14 Mar 2017 14:13:35 +0530 Subject: 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 Reviewed-on: http://git-master/r/1324329 (cherry picked from commit ce057d784d40a6ce57e892d58e211ed2fd9826f8) Reviewed-on: http://git-master/r/1320408 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/cde_gk20a.c | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c index 8f9d7831..df15cf51 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c @@ -949,12 +949,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 */ @@ -962,7 +966,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 */ @@ -1005,7 +1009,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 && @@ -1019,7 +1023,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; @@ -1031,7 +1035,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, @@ -1041,7 +1045,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); @@ -1078,7 +1082,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; } @@ -1087,7 +1091,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", @@ -1097,11 +1101,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, @@ -1112,16 +1118,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) @@ -1520,10 +1531,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); @@ -1539,7 +1546,6 @@ static int gk20a_buffer_convert_gpu_to_cde( err = -EINVAL; } - gk20a_idle(g->dev); return err; } -- cgit v1.2.2