Explorar o código

disp: msm: dsi: send panel dead for overflow/underflow interrupt

In case of underflow/overflow IRQ storm, send panel dead event from
scheduled underflow and overflow workqueue handler.

Change-Id: Ic6cd6cbae097ea970a392fa99e30b3b620633d40
Signed-off-by: Anand Tarakh <[email protected]>
Anand Tarakh hai 1 ano
pai
achega
79073c4b29
Modificáronse 3 ficheiros con 22 adicións e 6 borrados
  1. 10 6
      msm/dsi/dsi_ctrl.c
  2. 10 0
      msm/dsi/dsi_display.c
  3. 2 0
      msm/dsi/dsi_display.h

+ 10 - 6
msm/dsi/dsi_ctrl.c

@@ -2715,6 +2715,7 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
 	struct dsi_event_cb_info cb_info;
 	struct dsi_display *display;
 	bool skip_irq_enable = false;
+	bool is_spurious_interrupt = false;
 
 	cb_info = dsi_ctrl->irq_info.irq_err_cb;
 
@@ -2727,6 +2728,10 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
 		dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
 					error);
 
+	/* check for spurious interrupts */
+	if (dsi_ctrl_check_for_spurious_error_interrupts(dsi_ctrl))
+		is_spurious_interrupt = true;
+
 	/* DTLN PHY error */
 	if (error & 0x3000E00)
 		pr_err_ratelimited("[%s] dsi PHY contention error: 0x%lx\n",
@@ -2760,12 +2765,12 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
 		/* no need to report FIFO overflow if already masked */
 		if (cb_info.event_cb && !(mask & 0xf0000)) {
 			cb_info.event_idx = DSI_FIFO_OVERFLOW;
+			display = cb_info.event_usr_ptr;
+			display->is_spurious_interrupt = is_spurious_interrupt;
 			(void)cb_info.event_cb(cb_info.event_usr_ptr,
 						cb_info.event_idx,
 						dsi_ctrl->cell_index,
 						0, 0, 0, 0);
-			display = cb_info.event_usr_ptr;
-			dsi_display_report_dead(display);
 			skip_irq_enable = true;
 		}
 	}
@@ -2774,12 +2779,12 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
 	if (error & 0xF00000) {
 		if (cb_info.event_cb) {
 			cb_info.event_idx = DSI_FIFO_UNDERFLOW;
+			display = cb_info.event_usr_ptr;
+			display->is_spurious_interrupt = is_spurious_interrupt;
 			(void)cb_info.event_cb(cb_info.event_usr_ptr,
 						cb_info.event_idx,
 						dsi_ctrl->cell_index,
 						0, 0, 0, 0);
-			display = cb_info.event_usr_ptr;
-			dsi_display_report_dead(display);
 			skip_irq_enable = true;
 		}
 	}
@@ -2799,8 +2804,7 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
 	 * case and prevent us from re enabling interrupts until a full ESD
 	 * recovery is completed.
 	 */
-	if (dsi_ctrl_check_for_spurious_error_interrupts(dsi_ctrl) &&
-				dsi_ctrl->esd_check_underway) {
+	if (is_spurious_interrupt && dsi_ctrl->esd_check_underway) {
 		dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
 		return;
 	}

+ 10 - 0
msm/dsi/dsi_display.c

@@ -8043,6 +8043,11 @@ static void dsi_display_handle_fifo_underflow(struct work_struct *work)
 	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
 
 	mutex_unlock(&display->display_lock);
+
+	if (display->is_spurious_interrupt) {
+		dsi_display_report_dead(display);
+		display->is_spurious_interrupt = false;
+	}
 }
 
 static void dsi_display_handle_fifo_overflow(struct work_struct *work)
@@ -8124,6 +8129,11 @@ end:
 	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
 
 	mutex_unlock(&display->display_lock);
+
+	if (display->is_spurious_interrupt) {
+		dsi_display_report_dead(display);
+		display->is_spurious_interrupt = false;
+	}
 }
 
 static void dsi_display_handle_lp_rx_timeout(struct work_struct *work)

+ 2 - 0
msm/dsi/dsi_display.h

@@ -149,6 +149,7 @@ struct dsi_display_ext_bridge {
  * @sw_te_using_wd:   Is software te enabled
  * @display_lock:     Mutex for dsi_display interface.
  * @disp_te_gpio:     GPIO for panel TE interrupt.
+ * @is_spurious_interrupt: bool to specify spurious interrupt.
  * @is_te_irq_enabled:bool to specify whether TE interrupt is enabled.
  * @esd_te_gate:      completion gate to signal TE interrupt.
  * @ctrl_count:       Number of DSI interfaces required by panel.
@@ -215,6 +216,7 @@ struct dsi_display {
 	int disp_te_gpio;
 	bool is_te_irq_enabled;
 	struct completion esd_te_gate;
+	bool is_spurious_interrupt;
 
 	u32 ctrl_count;
 	struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY];