Преглед на файлове

msm: camera: cdm: Improve error handling during cdm hang

Reduce logging as part of error handling to avoid
flooding kernel log with excessive log. Apart from
that send feedback to client irrespective of cdm
reset status.

CRs-Fixed: 2826285
Change-Id: I9b0d8c6f64ced4972bb20e26774508573c815e4f
Signed-off-by: Alok Chauhan <[email protected]>
Alok Chauhan преди 4 години
родител
ревизия
63bca8c33d
променени са 4 файла, в които са добавени 76 реда и са изтрити 66 реда
  1. 1 0
      drivers/cam_cdm/cam_cdm.h
  2. 62 59
      drivers/cam_cdm/cam_cdm_hw_core.c
  3. 1 3
      drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c
  4. 12 4
      drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c

+ 1 - 0
drivers/cam_cdm/cam_cdm.h

@@ -83,6 +83,7 @@
 #define CAM_CDM_RESET_HW_STATUS 0x4
 #define CAM_CDM_ERROR_HW_STATUS 0x5
 #define CAM_CDM_FLUSH_HW_STATUS 0x6
+#define CAM_CDM_RESET_ERR_STATUS 0x7
 
 /* Curent BL command masks and shifts */
 #define CAM_CDM_CURRENT_BL_LEN   0xFFFFF

+ 62 - 59
drivers/cam_cdm/cam_cdm_hw_core.c

@@ -297,15 +297,15 @@ static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
 void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
 	bool pause_core)
 {
-	uint32_t dump_reg, core_dbg = 0x100;
+	uint32_t dump_reg[4], core_dbg = 0x100;
 	int i;
 	bool is_core_paused_already;
 	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
 	const struct cam_cdm_icl_regs *inv_cmd_log =
 		core->offsets->cmn_reg->icl_reg;
 
-	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW core status=0x%x", dump_reg);
+	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en,
+		&dump_reg[0]);
 
 	if (pause_core) {
 		cam_hw_cdm_pause_core(cdm_hw, true);
@@ -314,23 +314,24 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
 	cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg);
 
 	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data,
-		&dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg);
+		&dump_reg[1]);
 
 	cam_cdm_read_hw_reg(cdm_hw,
 		core->offsets->cmn_reg->debug_status,
-		&dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW Debug status reg=0x%x", dump_reg);
+		&dump_reg[2]);
+
+	CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x",
+			dump_reg[0], dump_reg[1], dump_reg[2]);
 
 	if (core_dbg & 0x100) {
 		cam_cdm_read_hw_reg(cdm_hw,
 			core->offsets->cmn_reg->last_ahb_addr,
-			&dump_reg);
-		CAM_INFO(CAM_CDM, "AHB dump reglastaddr=0x%x", dump_reg);
+			&dump_reg[0]);
 		cam_cdm_read_hw_reg(cdm_hw,
 			core->offsets->cmn_reg->last_ahb_data,
-			&dump_reg);
-		CAM_INFO(CAM_CDM, "AHB dump reglastdata=0x%x", dump_reg);
+			&dump_reg[1]);
+		CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x",
+			dump_reg[0], dump_reg[1]);
 	} else {
 		CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable");
 	}
@@ -339,46 +340,41 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
 		if (inv_cmd_log->misc_regs) {
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->misc_regs->icl_status,
-				&dump_reg);
-			CAM_INFO(CAM_CDM,
-				"Last Inv Cmd Log(ICL)Status: 0x%x",
-				dump_reg);
+				&dump_reg[0]);
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->misc_regs->icl_inv_bl_addr,
-				&dump_reg);
+				&dump_reg[1]);
 			CAM_INFO(CAM_CDM,
-				"Last Inv bl_addr: 0x%x",
-				dump_reg);
+				"Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x",
+				dump_reg[0], dump_reg[1]);
 		}
 		if (inv_cmd_log->data_regs) {
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->data_regs->icl_inv_data,
-				&dump_reg);
+				&dump_reg[0]);
 			CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x",
-				dump_reg);
+				dump_reg[0]);
 
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->data_regs->icl_last_data_0,
-				&dump_reg);
-			CAM_INFO(CAM_CDM, "First word of Last Good cmd: 0x%x",
-				dump_reg);
+				&dump_reg[0]);
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->data_regs->icl_last_data_1,
-				&dump_reg);
-			CAM_INFO(CAM_CDM, "Second word of Last Good cmd: 0x%x",
-				dump_reg);
+				&dump_reg[1]);
 			cam_cdm_read_hw_reg(cdm_hw,
 				inv_cmd_log->data_regs->icl_last_data_2,
-				&dump_reg);
-			CAM_INFO(CAM_CDM, "Third word of Last Good cmd: 0x%x",
-				dump_reg);
+				&dump_reg[2]);
+
+
+			CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x",
+					dump_reg[0], dump_reg[1], dump_reg[2]);
 		}
 	}
 
 	if (core_dbg & 0x10000) {
 		cam_cdm_read_hw_reg(cdm_hw,
-			core->offsets->cmn_reg->core_en, &dump_reg);
-		is_core_paused_already = (bool)(dump_reg & 0x20);
+			core->offsets->cmn_reg->core_en, &dump_reg[0]);
+		is_core_paused_already = (bool)(dump_reg[0] & 0x20);
 		if (!is_core_paused_already) {
 			cam_hw_cdm_pause_core(cdm_hw, true);
 			usleep_range(1000, 1010);
@@ -390,49 +386,44 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
 			cam_hw_cdm_pause_core(cdm_hw, false);
 	}
 
-	CAM_INFO(CAM_CDM, "CDM HW default dump");
 	cam_cdm_read_hw_reg(cdm_hw,
-		core->offsets->cmn_reg->core_cfg, &dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg);
+		core->offsets->cmn_reg->core_cfg, &dump_reg[0]);
+	CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]);
 
 	for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) {
 		cam_cdm_read_hw_reg(cdm_hw,
-			core->offsets->irq_reg[i]->irq_status, &dump_reg);
-		CAM_INFO(CAM_CDM, "CDM HW irq status%d=0x%x", i, dump_reg);
-
+			core->offsets->irq_reg[i]->irq_status, &dump_reg[0]);
 		cam_cdm_read_hw_reg(cdm_hw,
-			core->offsets->irq_reg[i]->irq_set, &dump_reg);
-		CAM_INFO(CAM_CDM, "CDM HW irq set%d=0x%x", i, dump_reg);
-
+			core->offsets->irq_reg[i]->irq_set, &dump_reg[1]);
 		cam_cdm_read_hw_reg(cdm_hw,
-			core->offsets->irq_reg[i]->irq_mask, &dump_reg);
-		CAM_INFO(CAM_CDM, "CDM HW irq mask%d=0x%x", i, dump_reg);
-
+			core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]);
 		cam_cdm_read_hw_reg(cdm_hw,
-			core->offsets->irq_reg[i]->irq_clear, &dump_reg);
-		CAM_INFO(CAM_CDM, "CDM HW irq clear%d=0x%x", i, dump_reg);
+			core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]);
+
+		CAM_INFO(CAM_CDM,
+			"cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x",
+			i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]);
 	}
 
 	cam_cdm_read_hw_reg(cdm_hw,
-		core->offsets->cmn_reg->current_bl_base, &dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW current BL base=0x%x", dump_reg);
+		core->offsets->cmn_reg->current_bl_base, &dump_reg[0]);
+	cam_cdm_read_hw_reg(cdm_hw,
+		core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]);
+	CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x",
+		dump_reg[0], dump_reg[1]);
 
 	cam_cdm_read_hw_reg(cdm_hw,
-		core->offsets->cmn_reg->current_bl_len, &dump_reg);
+		core->offsets->cmn_reg->current_bl_len, &dump_reg[0]);
 	CAM_INFO(CAM_CDM,
 		"CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ",
-		(dump_reg & CAM_CDM_CURRENT_BL_LEN),
-		(dump_reg & CAM_CDM_CURRENT_BL_ARB) >>
+		(dump_reg[0] & CAM_CDM_CURRENT_BL_LEN),
+		(dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >>
 			CAM_CDM_CURRENT_BL_ARB_SHIFT,
-		(dump_reg & CAM_CDM_CURRENT_BL_FIFO) >>
+		(dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >>
 			CAM_CDM_CURRENT_BL_FIFO_SHIFT,
-		(dump_reg & CAM_CDM_CURRENT_BL_TAG) >>
+		(dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >>
 			CAM_CDM_CURRENT_BL_TAG_SHIFT);
 
-	cam_cdm_read_hw_reg(cdm_hw,
-		core->offsets->cmn_reg->current_used_ahb_base, &dump_reg);
-	CAM_INFO(CAM_CDM, "CDM HW current AHB base=0x%x", dump_reg);
-
 	cam_hw_cdm_disable_core_dbg(cdm_hw);
 	if (pause_core)
 		cam_hw_cdm_pause_core(cdm_hw, false);
@@ -1128,11 +1119,15 @@ static void cam_hw_cdm_reset_cleanup(
 	int i;
 	struct cam_cdm_bl_cb_request_entry *node, *tnode;
 	bool flush_hw = false;
+	bool reset_err = false;
 
 	if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) ||
 		test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status))
 		flush_hw = true;
 
+	if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status))
+		reset_err = true;
+
 	for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
 		list_for_each_entry_safe(node, tnode,
 			&core->bl_fifo[i].bl_request_list, entry) {
@@ -1141,12 +1136,19 @@ static void cam_hw_cdm_reset_cleanup(
 				CAM_DBG(CAM_CDM,
 					"Notifying client %d for tag %d",
 					node->client_hdl, node->bl_tag);
-				if (flush_hw)
+				if (flush_hw) {
+					enum cam_cdm_cb_status status;
+
+					status = reset_err ?
+						CAM_CDM_CB_STATUS_HW_ERROR :
+						CAM_CDM_CB_STATUS_HW_RESUBMIT;
+
 					cam_cdm_notify_clients(cdm_hw,
 						(node->client_hdl == handle) ?
 						CAM_CDM_CB_STATUS_HW_FLUSH :
-						CAM_CDM_CB_STATUS_HW_RESUBMIT,
+						status,
 						(void *)node);
+				}
 				else
 					cam_cdm_notify_clients(cdm_hw,
 						CAM_CDM_CB_STATUS_HW_RESET_DONE,
@@ -1695,7 +1697,7 @@ int cam_hw_cdm_handle_error_info(
 	if (time_left <= 0) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc);
-		goto end;
+		set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
 	}
 
 	rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw);
@@ -1734,6 +1736,7 @@ int cam_hw_cdm_handle_error_info(
 end:
 	clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status);
 	clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status);
+	clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
 	for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++)
 		mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock);
 

+ 1 - 3
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

@@ -686,9 +686,7 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data)
 		}
 
 		CAM_ERR(CAM_OPE,
-			"pending requests means, issue is with HW for ctx %d",
-			ctx_data->ctx_id);
-		CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu",
+			"pending req at HW, ctx %d lrt %llu lct %llu",
 			ctx_data->ctx_id, ctx_data->last_req_time,
 			ope_hw_mgr->last_callback_time);
 		hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd(

+ 12 - 4
drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c

@@ -31,14 +31,22 @@ static struct ope_top ope_top_info;
 
 static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info)
 {
-	uint32_t i, val;
+	uint32_t i, val[3];
 	struct cam_ope_top_reg *top_reg;
 
 	top_reg = ope_hw_info->top_reg;
-	for (i = 0; i < top_reg->num_debug_registers; i++) {
-		val = cam_io_r_mb(top_reg->base +
+	for (i = 0; i < top_reg->num_debug_registers; i = i+3) {
+		val[0] = cam_io_r_mb(top_reg->base +
 			top_reg->debug_regs[i].offset);
-		CAM_INFO(CAM_OPE, "Debug_status_%d val: 0x%x", i, val);
+		val[1] = ((i+1) < top_reg->num_debug_registers) ?
+			cam_io_r_mb(top_reg->base +
+			top_reg->debug_regs[i+1].offset) : 0;
+		val[2] = ((i+2) < top_reg->num_debug_registers) ?
+			cam_io_r_mb(top_reg->base +
+			top_reg->debug_regs[i+2].offset) : 0;
+
+		CAM_INFO(CAM_OPE, "status[%d-%d] : 0x%x 0x%x 0x%x",
+			i, i+2, val[0], val[1], val[2]);
 	}
 	return 0;
 }