Bläddra i källkod

Merge "msm: camera: isp: Add safety checks for SFE handling" into camera-kernel.lnx.5.0

Camera Software Integration 4 år sedan
förälder
incheckning
823a276cb2

+ 55 - 12
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -467,7 +467,8 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv,
 	return rc;
 }
 
-static int cam_ife_hw_mgr_is_sfe_rdi_for_fetch(uint32_t res_id)
+static inline int cam_ife_hw_mgr_is_sfe_rdi_for_fetch(
+	uint32_t res_id)
 {
 	int rc = 0;
 
@@ -484,6 +485,13 @@ static int cam_ife_hw_mgr_is_sfe_rdi_for_fetch(uint32_t res_id)
 	return rc;
 }
 
+static inline int cam_ife_hw_mgr_is_shdr_fs_rdi_res(
+	uint32_t res_id, bool is_sfe_shdr, bool is_sfe_fs)
+{
+	return (cam_ife_hw_mgr_is_sfe_rdi_for_fetch(res_id) &&
+		(is_sfe_shdr || is_sfe_fs));
+}
+
 static int cam_ife_hw_mgr_is_sfe_rdi_res(uint32_t res_id)
 {
 	int rc = 0;
@@ -3390,9 +3398,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 		csid_acquire.tasklet = ife_ctx->common.tasklet_info;
 		csid_acquire.cb_priv = ife_ctx;
 		csid_acquire.cdm_ops = ife_ctx->cdm_ops;
-		if (cam_ife_hw_mgr_is_sfe_rdi_for_fetch(
-			out_port->res_type)) {
-			CAM_DBG(CAM_ISP, "setting inline shdr mode");
+		if (cam_ife_hw_mgr_is_shdr_fs_rdi_res(
+			out_port->res_type,
+			ife_ctx->flags.is_sfe_shdr, ife_ctx->flags.is_sfe_fs)) {
+			CAM_DBG(CAM_ISP, "setting inline shdr mode for res: 0x%x",
+				out_port->res_type);
 			csid_acquire.sfe_inline_shdr = true;
 		}
 
@@ -7150,7 +7160,7 @@ static inline int __cam_isp_sfe_send_cache_config(
 		sizeof(struct cam_isp_sfe_bus_sys_cache_config));
 	if (rc) {
 		CAM_ERR(CAM_ISP,
-			"Failed in sending cache config for:%d",
+			"Failed in sending cache config for: %u",
 			hw_res->res_id);
 	}
 
@@ -7163,6 +7173,7 @@ static int cam_isp_blob_sfe_exp_order_update(
 	struct cam_hw_prepare_update_args   *prepare)
 {
 	int rc = 0, i, j;
+	bool send_config;
 	uint32_t exp_order_max = 0;
 	uint32_t res_id_out, res_id_in;
 	struct cam_ife_hw_mgr_ctx               *ctx;
@@ -7193,8 +7204,14 @@ static int cam_isp_blob_sfe_exp_order_update(
 			order_cfg->res_type);
 		if (!rc) {
 			CAM_ERR(CAM_ISP,
-				"Not a SFE fetch RDI: 0x%x",
-				order_cfg->res_type);
+				"Not a SFE fetch RDI: 0x%x", order_cfg->res_type);
+			return -EINVAL;
+		}
+
+		if ((order_cfg->res_type - CAM_ISP_SFE_OUT_RES_RDI_0) >=
+			ctx->sfe_info.num_fetches) {
+			CAM_ERR(CAM_ISP, "resource 0x%x active fetches: %u mismatch",
+				order_cfg->res_type, ctx->sfe_info.num_fetches);
 			return -EINVAL;
 		}
 
@@ -7204,6 +7221,7 @@ static int cam_isp_blob_sfe_exp_order_update(
 		wm_rm_cache_cfg.use_cache =
 			(exp_order_max == i) ? true : false;
 		wm_rm_cache_cfg.scid = 0;
+		send_config = false;
 
 		/* Currently using cache for short only */
 		if (wm_rm_cache_cfg.use_cache) {
@@ -7238,10 +7256,18 @@ static int cam_isp_blob_sfe_exp_order_update(
 			rc = __cam_isp_sfe_send_cache_config(
 				CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG,
 				&wm_rm_cache_cfg);
-			if (rc)
-				return rc;
+			send_config = true;
+			break;
+		}
+
+		if (rc || !send_config) {
+			CAM_ERR(CAM_ISP,
+				"Failed to send cache config for WR res: 0x%x base_idx: %u send_config: %d rc: %d",
+				order_cfg->res_type, base_idx, send_config, rc);
+			return -EINVAL;
 		}
 
+		send_config = false;
 		/* RDI WMs have been validated find corresponding RM */
 		if (order_cfg->res_type == CAM_ISP_SFE_OUT_RES_RDI_0)
 			res_id_in = CAM_ISP_HW_SFE_IN_RD0;
@@ -7266,11 +7292,18 @@ static int cam_isp_blob_sfe_exp_order_update(
 				rc = __cam_isp_sfe_send_cache_config(
 					CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG,
 					&wm_rm_cache_cfg);
-				if (rc)
-					return rc;
+				send_config = true;
+				break;
 			}
 		}
 
+		if (rc || !send_config) {
+			CAM_ERR(CAM_ISP,
+				"Failed to send cache config for RD res: 0x%x base_idx: %u send_config: %d rc: %d",
+				res_id_in, base_idx, send_config, rc);
+			return -EINVAL;
+		}
+
 		if (!wm_rm_cache_cfg.rd_enabled && !wm_rm_cache_cfg.wr_enabled) {
 			wm_rm_cache_cfg.use_cache = false;
 			if (base_idx == CAM_SFE_CORE_0)
@@ -9183,6 +9216,14 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_SCRATCH_BUF_CFG: {
 		struct cam_isp_sfe_init_scratch_buf_config *scratch_config;
 
+		if (!(ife_mgr_ctx->flags.is_sfe_fs ||
+			ife_mgr_ctx->flags.is_sfe_shdr)) {
+			CAM_ERR(CAM_ISP,
+				"Not SFE sHDR/FS context: %u scratch buf blob not supported",
+				ife_mgr_ctx->ctx_index);
+			return -EINVAL;
+		}
+
 		if (blob_size <
 			sizeof(struct cam_isp_sfe_init_scratch_buf_config)) {
 			CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
@@ -11726,7 +11767,9 @@ static int cam_ife_hw_mgr_handle_hw_buf_done(
 		((event_info->hw_type == CAM_ISP_HW_TYPE_SFE) ? "SFE" : "IFE"),
 		event_info->hw_idx, event_info->res_id[i], event_info->last_consumed_addr[i]);
 
-		if (cam_ife_hw_mgr_is_sfe_rdi_for_fetch(event_info->res_id[i])) {
+		if (cam_ife_hw_mgr_is_shdr_fs_rdi_res(event_info->res_id[i],
+			ife_hw_mgr_ctx->flags.is_sfe_shdr,
+			ife_hw_mgr_ctx->flags.is_sfe_fs)) {
 			rc = cam_ife_hw_mgr_check_rdi_scratch_buf_done(
 				ife_hw_mgr_ctx->ctx_index,
 				ife_hw_mgr_ctx->sfe_info.scratch_config,

+ 41 - 26
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c

@@ -51,14 +51,17 @@ struct cam_sfe_top_priv {
 	uint32_t                        sfe_debug_cfg;
 	uint32_t                        sensor_sel_diag_cfg;
 	int                             error_irq_handle;
+	uint16_t                        reserve_cnt;
+	uint16_t                        start_stop_cnt;
+	void                           *priv_per_stream;
 	spinlock_t                      spin_lock;
+	cam_hw_mgr_event_cb_func        event_cb;
 	struct cam_sfe_top_module_desc *module_desc;
 	struct cam_sfe_wr_client_desc  *wr_client_desc;
 };
 
 struct cam_sfe_path_data {
 	void __iomem                             *mem_base;
-	void                                     *priv;
 	struct cam_hw_intf                       *hw_intf;
 	struct cam_sfe_top_priv                  *top_priv;
 	struct cam_sfe_top_common_reg_offset     *common_reg;
@@ -68,11 +71,8 @@ struct cam_sfe_path_data {
 	struct cam_hw_soc_info                   *soc_info;
 	uint32_t                                  min_hblank_cnt;
 	int                                       sof_eof_handle;
-	cam_hw_mgr_event_cb_func                  event_cb;
 };
 
-static int start_stop_cnt;
-
 struct cam_sfe_top_debug_info {
 	uint32_t  shift;
 	char     *clc_name;
@@ -1318,6 +1318,15 @@ int cam_sfe_top_reserve(void *device_priv,
 	args = (struct cam_sfe_acquire_args *)reserve_args;
 	acquire_args = &args->sfe_in;
 
+	if (top_priv->reserve_cnt) {
+		if (top_priv->priv_per_stream != args->priv) {
+			CAM_ERR(CAM_SFE,
+				"Acquiring same SFE[%u] HW res: %u for different streams");
+			rc = -EINVAL;
+			return rc;
+		}
+	}
+
 	for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) {
 		CAM_DBG(CAM_SFE, "i: %d res_id: %d state: %d", i,
 			acquire_args->res_id, top_priv->in_rsrc[i].res_state);
@@ -1327,9 +1336,6 @@ int cam_sfe_top_reserve(void *device_priv,
 			CAM_ISP_RESOURCE_STATE_AVAILABLE)) {
 			path_data = (struct cam_sfe_path_data *)
 				top_priv->in_rsrc[i].res_priv;
-			path_data->event_cb = args->event_cb;
-			path_data->priv = args->priv;
-			path_data->top_priv = top_priv;
 			CAM_DBG(CAM_SFE,
 				"SFE [%u] for rsrc: %u acquired",
 				top_priv->in_rsrc[i].hw_intf->hw_idx,
@@ -1346,6 +1352,12 @@ int cam_sfe_top_reserve(void *device_priv,
 		}
 	}
 
+	if (!rc) {
+		top_priv->reserve_cnt++;
+		top_priv->priv_per_stream = args->priv;
+		top_priv->event_cb = args->event_cb;
+	}
+
 	return rc;
 }
 
@@ -1376,6 +1388,13 @@ int cam_sfe_top_release(void *device_priv,
 	in_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 	in_res->cdm_ops = NULL;
 	in_res->tasklet_info = NULL;
+	if (top_priv->reserve_cnt)
+		top_priv->reserve_cnt--;
+
+	if (!top_priv->reserve_cnt) {
+		top_priv->priv_per_stream = NULL;
+		top_priv->event_cb = NULL;
+	}
 
 	return 0;
 }
@@ -1603,20 +1622,9 @@ static int cam_sfe_top_handle_err_irq_bottom_half(
 
 		evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
 		cam_sfe_top_print_debug_reg_info(top_priv);
-		for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) {
-			if (top_priv->in_rsrc[i].res_state ==
-				CAM_ISP_RESOURCE_STATE_STREAMING) {
-				struct cam_sfe_path_data *path_data;
-
-				path_data = (struct cam_sfe_path_data *)
-					top_priv->in_rsrc[i].res_priv;
-				if (path_data->event_cb) {
-					path_data->event_cb(path_data->priv,
-						CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
-					break;
-				}
-			}
-		}
+		if (top_priv->event_cb)
+			top_priv->event_cb(top_priv->priv_per_stream,
+				CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
 
 		ret = CAM_SFE_IRQ_STATUS_VIOLATION;
 	}
@@ -1824,7 +1832,7 @@ int cam_sfe_top_start(
 	}
 
 	sfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
-	start_stop_cnt++;
+	top_priv->start_stop_cnt++;
 	return 0;
 }
 
@@ -1877,10 +1885,10 @@ int cam_sfe_top_stop(
 		debug_cfg_disable = true;
 	}
 
-	if (start_stop_cnt)
-		start_stop_cnt--;
+	if (top_priv->start_stop_cnt)
+		top_priv->start_stop_cnt--;
 
-	if (!start_stop_cnt &&
+	if (!top_priv->start_stop_cnt &&
 		((top_priv->sfe_debug_cfg &
 		SFE_DEBUG_ENABLE_FRAME_COUNTER) ||
 		(top_priv->sfe_debug_cfg &
@@ -1902,8 +1910,9 @@ int cam_sfe_top_stop(
 	 * Reset clk rate & unsubscribe error irq
 	 * when all resources are streamed off
 	 */
-	if (!start_stop_cnt) {
+	if (!top_priv->start_stop_cnt) {
 		top_priv->applied_clk_rate = 0;
+
 		if (top_priv->error_irq_handle > 0) {
 			cam_irq_controller_unsubscribe_irq(
 				top_priv->common_data.sfe_irq_controller,
@@ -1956,6 +1965,10 @@ int cam_sfe_top_init(
 	}
 
 	top_priv->applied_clk_rate = 0;
+	top_priv->reserve_cnt = 0;
+	top_priv->start_stop_cnt = 0;
+	top_priv->priv_per_stream = NULL;
+	top_priv->event_cb = NULL;
 	top_priv->num_in_ports = sfe_top_hw_info->num_inputs;
 	memset(&top_priv->core_cfg, 0x0,
 		sizeof(struct cam_sfe_core_cfg));
@@ -1995,6 +2008,7 @@ int cam_sfe_top_init(
 				sfe_top_hw_info->common_reg_data;
 			path_data->modules_reg =
 				sfe_top_hw_info->modules_hw_info;
+			path_data->top_priv = top_priv;
 			path_data->hw_intf = hw_intf;
 			path_data->soc_info = soc_info;
 			scnprintf(top_priv->in_rsrc[i].res_name,
@@ -2028,6 +2042,7 @@ int cam_sfe_top_init(
 			path_data->modules_reg =
 				sfe_top_hw_info->modules_hw_info;
 			path_data->soc_info = soc_info;
+			path_data->top_priv = top_priv;
 			path_data->path_reg_data =
 				sfe_top_hw_info->rdi_reg_data[j++];
 		} else {