Procházet zdrojové kódy

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 <[email protected]>
Venkat Chinta před 5 roky
rodič
revize
32eade687a

+ 55 - 13
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;
 }

+ 3 - 1
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;
 };
 
 /**

+ 19 - 10
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],