Browse Source

msm: camera: isp: Change error irq subscription for SFE top

Subscribe to error IRQs once in SFE top as opposed to per path
since the error IRQs are common to all paths. The change also
adds handling of SFE violation in HW mgr.

CRs-Fixed: 2841729
Change-Id: Id805b7365f81254cdacad618bffdfd5f4028dcfc
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 4 years ago
parent
commit
84bbf0b9af

+ 36 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -11235,6 +11235,36 @@ static int cam_ife_hw_mgr_handle_hw_dump_info(
 	return rc;
 }
 
+static int cam_ife_hw_mgr_handle_sfe_event(
+	uint32_t                         evt_id,
+	struct cam_ife_hw_mgr_ctx       *ctx,
+	struct cam_isp_hw_event_info    *event_info)
+{
+	struct cam_isp_hw_error_event_data      error_event_data = {0};
+	struct cam_ife_hw_event_recovery_data   recovery_data = {0};
+
+	/* Currently only error events supported from SFE */
+	if (evt_id != CAM_ISP_HW_EVENT_ERROR) {
+		CAM_DBG(CAM_ISP, "SFE %u event not supported", evt_id);
+		return 0;
+	}
+
+	CAM_DBG(CAM_ISP, "SFE[%u] error [%u] on res_type %u",
+		event_info->hw_idx, event_info->err_type,
+		event_info->res_type);
+
+	/* Only report error to userspace */
+	if (event_info->err_type & CAM_SFE_IRQ_STATUS_VIOLATION) {
+		error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION;
+		error_event_data.error_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
+		CAM_DBG(CAM_ISP, "Notify context for SFE error");
+		cam_ife_hw_mgr_find_affected_ctx(&error_event_data,
+			event_info->hw_idx, &recovery_data);
+	}
+
+	return 0;
+}
+
 static int cam_ife_hw_mgr_handle_hw_err(
 	uint32_t                             evt_id,
 	void                                *ctx,
@@ -11255,6 +11285,12 @@ static int cam_ife_hw_mgr_handle_hw_err(
 		goto end;
 	}
 
+	if (event_info->hw_type == CAM_ISP_HW_TYPE_SFE) {
+		rc = cam_ife_hw_mgr_handle_sfe_event(evt_id, ctx,
+			event_info);
+		goto end;
+	}
+
 	if (ctx) {
 		ife_hw_mgr_ctx =
 			(struct cam_ife_hw_mgr_ctx *)ctx;

+ 22 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c

@@ -1985,6 +1985,7 @@ static void cam_sfe_bus_wr_print_violation_info(
 static int cam_sfe_bus_wr_irq_bottom_half(
 	void *handler_priv, void *evt_payload_priv)
 {
+	int i;
 	uint32_t status = 0;
 	struct cam_sfe_bus_wr_priv            *bus_priv = handler_priv;
 	struct cam_sfe_bus_wr_common_data     *common_data;
@@ -2017,13 +2018,31 @@ static int cam_sfe_bus_wr_irq_bottom_half(
 	cam_sfe_bus_wr_put_evt_payload(common_data, &evt_payload);
 
 	evt_info.hw_idx = common_data->core_index;
+	evt_info.hw_type = CAM_ISP_HW_TYPE_SFE;
 	evt_info.res_type = CAM_ISP_RESOURCE_SFE_OUT;
 	evt_info.res_id = CAM_SFE_BUS_SFE_OUT_MAX;
 	evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
 
-	if (common_data->event_cb)
-		common_data->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR,
-			(void *)&evt_info);
+	if (common_data->event_cb) {
+		struct cam_isp_resource_node      *out_rsrc_node = NULL;
+		struct cam_sfe_bus_wr_out_data    *out_rsrc_data = NULL;
+
+		for (i = 0; i < bus_priv->num_out; i++) {
+			out_rsrc_node = &bus_priv->sfe_out[i];
+
+			if (!out_rsrc_node || !out_rsrc_node->res_priv)
+				continue;
+
+			if (out_rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)
+				continue;
+
+			out_rsrc_data = out_rsrc_node->res_priv;
+			common_data->event_cb(out_rsrc_data->priv,
+				CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
+			break;
+		}
+	}
+
 	return 0;
 }
 

+ 76 - 48
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c

@@ -25,6 +25,7 @@ struct cam_sfe_top_common_data {
 	struct cam_hw_soc_info                  *soc_info;
 	struct cam_hw_intf                      *hw_intf;
 	struct cam_sfe_top_common_reg_offset    *common_reg;
+	struct cam_sfe_top_common_reg_data      *common_reg_data;
 	struct cam_irq_controller               *sfe_irq_controller;
 	struct cam_sfe_top_irq_evt_payload       evt_payload[CAM_SFE_EVT_MAX];
 	struct list_head                         free_payload_list;
@@ -47,6 +48,7 @@ struct cam_sfe_top_priv {
 	struct cam_sfe_core_cfg         core_cfg;
 	uint32_t                        sfe_debug_cfg;
 	uint32_t                        sensor_sel_diag_cfg;
+	int                             error_irq_handle;
 	spinlock_t                      spin_lock;
 	struct cam_sfe_top_module_desc *module_desc;
 	struct cam_sfe_wr_client_desc  *wr_client_desc;
@@ -63,7 +65,6 @@ struct cam_sfe_path_data {
 	struct cam_sfe_path_common_reg_data      *path_reg_data;
 	struct cam_hw_soc_info                   *soc_info;
 	uint32_t                                  min_hblank_cnt;
-	int                                       error_irq_handle;
 	int                                       sof_eof_handle;
 	cam_hw_mgr_event_cb_func                  event_cb;
 };
@@ -1108,7 +1109,7 @@ int cam_sfe_top_release(void *device_priv,
 }
 
 static int cam_sfe_top_get_evt_payload(
-	struct cam_sfe_top_priv            *top_priv,
+	struct cam_sfe_top_priv                *top_priv,
 	struct cam_sfe_top_irq_evt_payload    **evt_payload)
 {
 	int rc = 0;
@@ -1165,26 +1166,18 @@ static int cam_sfe_top_handle_err_irq_top_half(
 	uint32_t irq_status = 0;
 	void __iomem *base = NULL;
 	struct cam_sfe_top_priv            *top_priv;
-	struct cam_isp_resource_node       *res;
-	struct cam_sfe_path_data           *path_data;
 	struct cam_sfe_top_irq_evt_payload *evt_payload;
 
-	res = th_payload->handler_priv;
-	path_data = res->res_priv;
-	top_priv = path_data->priv;
-
-	CAM_DBG(CAM_SFE, "Top error IRQ Received");
-
+	top_priv = th_payload->handler_priv;
 	irq_status = th_payload->evt_status_arr[0];
 
-	base = path_data->mem_base;
-	if (irq_status & path_data->common_reg_data->error_irq_mask) {
-		CAM_ERR(CAM_SFE,
-			"SFE Violation Detected irq_status: 0x%x",
-			irq_status);
+	CAM_DBG(CAM_SFE, "Top error IRQ Received: 0x%x", irq_status);
+
+	base = top_priv->common_data.soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base;
+	if (irq_status & top_priv->common_data.common_reg_data->error_irq_mask) {
 		cam_irq_controller_disable_irq(
 			top_priv->common_data.sfe_irq_controller,
-			path_data->error_irq_handle);
+			top_priv->error_irq_handle);
 		cam_irq_controller_clear_and_mask(evt_id,
 			top_priv->common_data.sfe_irq_controller);
 	}
@@ -1199,7 +1192,7 @@ static int cam_sfe_top_handle_err_irq_top_half(
 
 	cam_isp_hw_get_timestamp(&evt_payload->ts);
 	evt_payload->violation_status =
-	cam_io_r(base +
+		cam_io_r(base +
 		top_priv->common_data.common_reg->violation_status);
 
 	th_payload->evt_payload_priv = evt_payload;
@@ -1296,29 +1289,28 @@ void cam_sfe_top_sel_frame_counter(
 	}
 }
 
-static int cam_sfe_top_handle_irq_bottom_half(
+
+static int cam_sfe_top_handle_err_irq_bottom_half(
 	void *handler_priv, void *evt_payload_priv)
 {
 	int i;
-	uint32_t val0, val1, frame_cnt, offset0, offset1, viol_sts;
+	uint32_t viol_sts;
 	uint32_t irq_status[CAM_SFE_IRQ_REGISTERS_MAX] = {0};
 	enum cam_sfe_hw_irq_status          ret = CAM_SFE_IRQ_STATUS_MAX;
 	struct cam_isp_hw_event_info        evt_info;
-	struct cam_isp_resource_node       *res = handler_priv;
-	struct cam_sfe_path_data           *path_data = res->res_priv;
-	struct cam_sfe_top_priv            *top_priv = path_data->top_priv;
+	struct cam_sfe_top_priv            *top_priv = handler_priv;
 	struct cam_sfe_top_irq_evt_payload *payload = evt_payload_priv;
 
 	for (i = 0; i < CAM_SFE_IRQ_REGISTERS_MAX; i++)
 		irq_status[i] = payload->irq_reg_val[i];
 
-	evt_info.hw_idx = res->hw_intf->hw_idx;
-	evt_info.res_id = res->res_id;
-	evt_info.res_type = res->res_type;
+	evt_info.hw_idx = top_priv->common_data.soc_info->index;
+	evt_info.hw_type = CAM_ISP_HW_TYPE_SFE;
+	evt_info.res_type = CAM_ISP_RESOURCE_SFE_IN;
 	evt_info.reg_val = 0;
 
 	if (irq_status[0] &
-		path_data->common_reg_data->error_irq_mask) {
+		top_priv->common_data.common_reg_data->error_irq_mask) {
 		if (irq_status[0] & 0x4000)
 			CAM_ERR(CAM_SFE, "PP VIOLATION");
 
@@ -1339,17 +1331,48 @@ static int cam_sfe_top_handle_irq_bottom_half(
 
 		evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
 		cam_sfe_top_print_debug_reg_info(top_priv);
-		if (path_data->event_cb)
-			path_data->event_cb(NULL,
-				CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
+		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;
+				}
+			}
+		}
 
 		ret = CAM_SFE_IRQ_STATUS_VIOLATION;
 	}
 
+	cam_sfe_top_put_evt_payload(top_priv, &payload);
+
+	return ret;
+}
+
+static int cam_sfe_top_handle_irq_bottom_half(
+	void *handler_priv, void *evt_payload_priv)
+{
+	int i;
+	uint32_t val0, val1, frame_cnt, offset0, offset1;
+	uint32_t irq_status[CAM_SFE_IRQ_REGISTERS_MAX] = {0};
+	enum cam_sfe_hw_irq_status          ret = CAM_SFE_IRQ_STATUS_MAX;
+	struct cam_isp_resource_node       *res = handler_priv;
+	struct cam_sfe_path_data           *path_data = res->res_priv;
+	struct cam_sfe_top_priv            *top_priv = path_data->top_priv;
+	struct cam_sfe_top_irq_evt_payload *payload = evt_payload_priv;
+
+	for (i = 0; i < CAM_SFE_IRQ_REGISTERS_MAX; i++)
+		irq_status[i] = payload->irq_reg_val[i];
+
 	if (irq_status[0] & path_data->path_reg_data->subscribe_irq_mask) {
 		if (irq_status[0] & path_data->path_reg_data->sof_irq_mask) {
 			CAM_DBG(CAM_SFE, "SFE:%d Received %s SOF",
-				evt_info.hw_idx,
+				res->hw_intf->hw_idx,
 				res->res_name);
 			offset0 = path_data->common_reg->diag_sensor_status_0;
 			offset1 = path_data->common_reg->diag_sensor_status_1;
@@ -1362,7 +1385,7 @@ static int cam_sfe_top_handle_irq_bottom_half(
 					offset1);
 				CAM_INFO(CAM_SFE,
 					"SFE:%d HBI: 0x%x VBI: 0x%x NEQ_HBI: %s HBI_MIN_ERR: %s",
-					evt_info.hw_idx, (val0 & 0x3FFF), val1,
+					res->hw_intf->hw_idx, (val0 & 0x3FFF), val1,
 					(val0 & (0x4000) ? "TRUE" : "FALSE"),
 					(val0 & (0x8000) ? "TRUE" : "FALSE"));
 			}
@@ -1377,7 +1400,7 @@ static int cam_sfe_top_handle_irq_bottom_half(
 		if (irq_status[0] &
 			path_data->path_reg_data->eof_irq_mask) {
 			CAM_DBG(CAM_SFE, "SFE:%d Received %s EOF",
-				evt_info.hw_idx,
+				res->hw_intf->hw_idx,
 				res->res_name);
 		}
 		ret = CAM_SFE_IRQ_STATUS_SUCCESS;
@@ -1479,21 +1502,21 @@ int cam_sfe_top_start(
 	}
 
 	error_mask[0] = path_data->common_reg_data->error_irq_mask;
-	/* Enable error IRQ by default */
-	if (!path_data->error_irq_handle) {
-		path_data->error_irq_handle = cam_irq_controller_subscribe_irq(
+	/* Enable error IRQ by default once */
+	if (!top_priv->error_irq_handle) {
+		top_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
 			top_priv->common_data.sfe_irq_controller,
 			CAM_IRQ_PRIORITY_0,
 			error_mask,
-			sfe_res,
+			top_priv,
 			cam_sfe_top_handle_err_irq_top_half,
-			cam_sfe_top_handle_irq_bottom_half,
+			cam_sfe_top_handle_err_irq_bottom_half,
 			sfe_res->tasklet_info,
 			&tasklet_bh_api);
 
-		if (path_data->error_irq_handle < 1) {
+		if (top_priv->error_irq_handle < 1) {
 			CAM_ERR(CAM_SFE, "Failed to subscribe Top IRQ");
-			path_data->error_irq_handle = 0;
+			top_priv->error_irq_handle = 0;
 			return -EFAULT;
 		}
 	}
@@ -1567,13 +1590,6 @@ int cam_sfe_top_stop(
 		}
 	}
 
-	if (path_data->error_irq_handle > 0) {
-		cam_irq_controller_unsubscribe_irq(
-			top_priv->common_data.sfe_irq_controller,
-			path_data->error_irq_handle);
-		path_data->error_irq_handle = 0;
-	}
-
 	if (path_data->sof_eof_handle > 0) {
 		cam_irq_controller_unsubscribe_irq(
 			top_priv->common_data.sfe_irq_controller,
@@ -1608,9 +1624,19 @@ int cam_sfe_top_stop(
 			path_data->common_reg->diag_config);
 	}
 
-	/* Reset clk rate when all resources are streamed off */
-	if (!start_stop_cnt)
+	/*
+	 * Reset clk rate & unsubscribe error irq
+	 * when all resources are streamed off
+	 */
+	if (!start_stop_cnt) {
 		top_priv->hw_clk_rate = 0;
+		if (top_priv->error_irq_handle > 0) {
+			cam_irq_controller_unsubscribe_irq(
+				top_priv->common_data.sfe_irq_controller,
+				top_priv->error_irq_handle);
+			top_priv->error_irq_handle = 0;
+		}
+	}
 
 	return 0;
 }
@@ -1742,6 +1768,8 @@ int cam_sfe_top_init(
 	top_priv->common_data.hw_intf = hw_intf;
 	top_priv->common_data.common_reg =
 		sfe_top_hw_info->common_reg;
+	top_priv->common_data.common_reg_data =
+		sfe_top_hw_info->common_reg_data;
 	top_priv->module_desc = sfe_top_hw_info->module_desc;
 	top_priv->wr_client_desc = sfe_top_hw_info->wr_client_desc;
 	top_priv->sfe_debug_cfg = 0;