From 3873d83d2a6bd0cfb8ed7076d3cbea545888205f Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Tue, 6 Mar 2018 17:05:49 +0530 Subject: [PATCH] msm: camera: Deregister sync callbacks at context flush When the request is flushed, any input fences are now unused. Cancel any pending input sync callbacks. Change-Id: I30740fa18009b38330d4e1da583821cf2f502f69 Signed-off-by: Lynus Vaz --- .../msm/camera/cam_core/cam_context.h | 2 +- .../msm/camera/cam_core/cam_context_utils.c | 59 +++++++++++++++++-- .../platform/msm/camera/cam_sync/cam_sync.c | 4 +- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h index 8324e78d9e0e..ffceea22ae0f 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h @@ -70,7 +70,7 @@ struct cam_ctx_request { uint32_t num_in_map_entries; struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX]; uint32_t num_out_map_entries; - uint32_t num_in_acked; + atomic_t num_in_acked; uint32_t num_out_acked; int flushed; struct cam_context *ctx; diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c index b4f83f7e473b..f167ef7ca5ff 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c @@ -189,8 +189,7 @@ static void cam_context_sync_callback(int32_t sync_obj, int status, void *data) return; } - req->num_in_acked++; - if (req->num_in_acked == req->num_in_map_entries) { + if (atomic_inc_return(&req->num_in_acked) == req->num_in_map_entries) { apply.request_id = req->request_id; /* * take mutex to ensure that another thread does @@ -342,6 +341,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, req->num_hw_update_entries = cfg.num_hw_update_entries; req->num_out_map_entries = cfg.num_out_map_entries; req->num_in_map_entries = cfg.num_in_map_entries; + atomic_set(&req->num_in_acked, 0); req->request_id = packet->header.request_id; req->status = 1; req->req_priv = cfg.priv; @@ -492,6 +492,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) struct cam_ctx_request *req; uint32_t i; int rc = 0; + bool free_req; CAM_DBG(CAM_CTXT, "[%s] E: NRT flush ctx", ctx->dev_name); @@ -528,6 +529,21 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) flush_args.flush_req_pending[flush_args.num_req_pending++] = req->req_priv; + + free_req = false; + for (i = 0; i < req->num_in_map_entries; i++) { + rc = cam_sync_deregister_callback( + cam_context_sync_callback, + (void *)req, + req->in_map_entries[i].sync_id); + if (!rc) { + cam_context_putref(ctx); + if (atomic_inc_return(&req->num_in_acked) == + req->num_in_map_entries) + free_req = true; + } + } + for (i = 0; i < req->num_out_map_entries; i++) { if (req->out_map_entries[i].sync_id != -1) { rc = cam_sync_signal( @@ -543,6 +559,17 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } } + /* + * If we have deregistered the last sync callback, req will + * not be put on the free list. So put it on the free list here + */ + if (free_req) { + req->ctx = NULL; + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + } + if (cam_debug_ctx_req_list & ctx->dev_id) CAM_INFO(CAM_CTXT, "[%s][%d] : Deleting req[%llu] from temp_list", @@ -630,6 +657,7 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, uint32_t i; int32_t sync_id = 0; int rc = 0; + bool free_req = false; CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name); @@ -682,6 +710,22 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, } if (req) { + if (flush_args.num_req_pending) { + for (i = 0; i < req->num_in_map_entries; i++) { + rc = cam_sync_deregister_callback( + cam_context_sync_callback, + (void *)req, + req->in_map_entries[i].sync_id); + if (rc) + continue; + + cam_context_putref(ctx); + if (atomic_inc_return(&req->num_in_acked) == + req->num_in_map_entries) + free_req = true; + } + } + if (flush_args.num_req_pending || flush_args.num_req_active) { for (i = 0; i < req->num_out_map_entries; i++) { sync_id = @@ -697,17 +741,20 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, } } } - if (flush_args.num_req_active) { + if (flush_args.num_req_active || free_req) { + req->ctx = NULL; spin_lock(&ctx->lock); list_add_tail(&req->list, &ctx->free_req_list); spin_unlock(&ctx->lock); - req->ctx = NULL; if (cam_debug_ctx_req_list & ctx->dev_id) CAM_INFO(CAM_CTXT, - "[%s][%d] : Moving req[%llu] from active_list to free_list", + "[%s][%d] : Moving req[%llu] from %s to free_list", ctx->dev_name, ctx->ctx_id, - req->request_id); + req->request_id, + flush_args.num_req_active ? + "active_list" : + "pending_list"); } } } diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c index d625a20d6ad5..517b7dfe8128 100644 --- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c +++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c @@ -123,6 +123,7 @@ int cam_sync_deregister_callback(sync_callback cb_func, { struct sync_table_row *row = NULL; struct sync_callback_info *sync_cb, *temp; + bool found = false; if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) return -EINVAL; @@ -145,11 +146,12 @@ int cam_sync_deregister_callback(sync_callback cb_func, sync_cb->cb_data == userdata) { list_del_init(&sync_cb->list); kfree(sync_cb); + found = true; } } spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); - return 0; + return found ? 0 : -ENOENT; } int cam_sync_signal(int32_t sync_obj, uint32_t status)