浏览代码

Merge "msm: camera: isp: Change error irq subscription for SFE top" into camera-kernel.lnx.5.0

Savita Patted 4 年之前
父节点
当前提交
2d20272f38

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

@@ -11082,6 +11082,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,
@@ -11102,6 +11132,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

@@ -1986,6 +1986,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;
@@ -2018,13 +2019,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;