From 32eade687afb54c1ea0c79c8f607b88bb0689dfc Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 20 Jan 2020 14:37:51 -0800 Subject: [PATCH] msm: camera: isp: Config hardware in work queue Currently requests for offline IFE are applied from tasklet context or from an ioctl thread within a critical section protected by a spinlock. In both of these cases, preemtion is disabled but CDM requires mutex locks during this operation. Therefore a work queue is added in this change to handle apply request for offline IFE. CRs-Fixed: 2606911 Change-Id: Ie893a626bc274d026fb878f1f19830e990be6dc6 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 68 +++++++++++++++++---- drivers/cam_isp/cam_isp_context.h | 4 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 29 ++++++--- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9e28d2eeb6..5843b6be10 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1047,13 +1047,21 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( } static int __cam_isp_ctx_apply_req_offline( - struct cam_context *ctx, uint32_t next_state, - struct cam_isp_context *ctx_isp) + void *priv, void *data) { int rc = 0; - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_hw_config_args cfg; + struct cam_context *ctx = NULL; + struct cam_isp_context *ctx_isp = priv; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_hw_config_args cfg; + + if (!ctx_isp) { + CAM_ERR(CAM_ISP, "Invalid ctx_isp:%pK", ctx); + rc = -EINVAL; + goto end; + } + ctx = ctx_isp->base; if (list_empty(&ctx->pending_req_list)) { CAM_DBG(CAM_ISP, "No pending requests to apply"); @@ -1067,8 +1075,10 @@ static int __cam_isp_ctx_apply_req_offline( if (ctx_isp->active_req_cnt >= 2) goto end; + spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); + spin_unlock_bh(&ctx->lock); CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u", req->request_id, ctx_isp->substate_activated, ctx->ctx_id); @@ -1087,13 +1097,21 @@ static int __cam_isp_ctx_apply_req_offline( if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { + spin_lock_bh(&ctx->lock); + atomic_set(&ctx_isp->rxd_epoch, 0); - ctx_isp->substate_activated = next_state; + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_APPLIED; ctx_isp->last_applied_req_id = req->request_id; + list_del_init(&req->list); list_add_tail(&req->list, &ctx->wait_req_list); + + spin_unlock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld", - next_state, ctx_isp->last_applied_req_id); + CAM_ISP_CTX_ACTIVATED_APPLIED, + ctx_isp->last_applied_req_id); __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, @@ -1103,6 +1121,26 @@ end: return rc; } +static int __cam_isp_ctx_schedule_apply_req_offline( + struct cam_isp_context *ctx_isp) +{ + int rc = 0; + struct crm_workq_task *task; + + task = cam_req_mgr_workq_get_task(ctx_isp->workq); + if (!task) { + CAM_ERR(CAM_ISP, "No task for worker"); + return -ENOMEM; + } + + task->process_cb = __cam_isp_ctx_apply_req_offline; + rc = cam_req_mgr_workq_enqueue_task(task, ctx_isp, CRM_TASK_PRIORITY_0); + if (rc) + CAM_ERR(CAM_ISP, "Failed to schedule task rc:%d", rc); + + return rc; +} + static int __cam_isp_ctx_offline_epoch_in_activated_state( struct cam_isp_context *ctx_isp, void *evt_data) { @@ -1123,8 +1161,7 @@ static int __cam_isp_ctx_offline_epoch_in_activated_state( } } - __cam_isp_ctx_apply_req_offline(ctx, CAM_ISP_CTX_ACTIVATED_APPLIED, - ctx_isp); + __cam_isp_ctx_schedule_apply_req_offline(ctx_isp); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); @@ -3887,10 +3924,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req->request_id, ctx->ctx_id); if (ctx_isp->offline_context && atomic_read(&ctx_isp->rxd_epoch)) { - spin_lock_bh(&ctx->lock); - __cam_isp_ctx_apply_req_offline(ctx, - CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp); - spin_unlock_bh(&ctx->lock); + __cam_isp_ctx_schedule_apply_req_offline(ctx_isp); } return rc; @@ -4336,6 +4370,13 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, cam_isp_ctx_offline_state_machine_irq; ctx_isp->substate_machine = NULL; ctx_isp->offline_context = true; + + rc = cam_req_mgr_workq_create("offline_ife", 20, + &ctx_isp->workq, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) + CAM_ERR(CAM_ISP, + "Failed to create workq for offline IFE rc:%d", + rc); } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = @@ -5252,6 +5293,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, atomic64_set(&ctx->event_record_head[i], -1); cam_isp_context_debug_register(); + err: return rc; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index beec13e3ff..ba49f534e0 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -14,7 +14,7 @@ #include "cam_context.h" #include "cam_isp_hw_mgr_intf.h" - +#include "cam_req_mgr_workq.h" #define CAM_IFE_QTIMER_MUL_FACTOR 10000 #define CAM_IFE_QTIMER_DIV_FACTOR 192 @@ -257,6 +257,7 @@ struct cam_isp_context_event_record { * @isp_device_type: ISP device type * @rxd_epoch: Indicate whether epoch has been received. Used to * decide whether to apply request in offline ctx + * @workq: Worker thread for offline ife * */ struct cam_isp_context { @@ -298,6 +299,7 @@ struct cam_isp_context { unsigned int init_timestamp; uint32_t isp_device_type; atomic_t rxd_epoch; + struct cam_req_mgr_core_workq *workq; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6434a4abe9..1e5154fb5c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -648,6 +648,11 @@ static void cam_ife_hw_mgr_print_acquire_info( hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_csid, struct cam_isp_hw_mgr_res, list); + + if (hw_mgr_ctx->is_offline) + hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_src, + struct cam_isp_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { hw_res = hw_mgr_res->hw_res[i]; if (hw_res && hw_res->hw_intf) @@ -2173,7 +2178,7 @@ static int cam_ife_hw_mgr_preprocess_port( return 0; } -static int cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd( +static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port) { @@ -2385,7 +2390,7 @@ end: return rc; } -static int cam_ife_mgr_acquire_hw_for_fe_ctx( +static int cam_ife_mgr_acquire_hw_for_offline_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, uint32_t *num_pix_port, @@ -2417,7 +2422,7 @@ static int cam_ife_mgr_acquire_hw_for_fe_ctx( return -EINVAL; } - rc = cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(ife_ctx, in_port); + rc = cam_ife_hw_mgr_acquire_res_ife_bus_rd(ife_ctx, in_port); if (rc) { CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed"); @@ -2486,17 +2491,21 @@ static int cam_ife_mgr_acquire_hw_for_ctx( cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); - if (ife_rd_count) { - CAM_ERR(CAM_ISP, "Invalid BUS RD port for non-FE ctx"); - return -EINVAL; - } - if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) { CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or LCR resource"); return -EINVAL; } + if (ife_rd_count) { + rc = cam_ife_hw_mgr_acquire_res_ife_bus_rd(ife_ctx, in_port); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed"); + goto err; + } + } + if (ipp_count || lcr_count) { /* get ife csid IPP resource */ rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, @@ -2937,8 +2946,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto free_mem; } - if (ife_ctx->is_fe_enabled) - rc = cam_ife_mgr_acquire_hw_for_fe_ctx( + if (ife_ctx->is_offline) + rc = cam_ife_mgr_acquire_hw_for_offline_ctx( ife_ctx, in_port, &num_pix_port_per_in, &acquire_args->acquired_hw_id[i],