Ver código fonte

disp: msm: dsi: remove early return from dma_cmd_wait_for_done

In ASYNC wait mode, next command kickoff can happen before previous command ISR execution is
completed in below sequence:

ASYNC command A -> triggered

dsi_ctrl_isr for command A -> fired and executed atomic_set(&dsi_ctrl->dma_irq_trig, 1);

wait_for_done for command A -> returns early as dsi_ctrl->dma_irq_trig is 1

ASYNC Command B -> triggered

wait_for_done for command B -> waiting for cmd_dma_done

dsi_ctrl_isr for command A -> executes complete_all(&dsi_ctrl->irq_info.cmd_dma_done);

wait_for_done for command B -> returns success incorrectly based on complete_all of previous
	command isr and disable_status_interrupt() is not called.

This leads to refcount of dma_done going wrong and dsi_ctrl_isr is not enabled on suspend resume.

To fix this issue, mark command transfer successful only based on complete_all(cmd_dma_done). This
way disable_status_interrupt() will be always called either from dsi_ctrl_isr or wait_for_done().

Change-Id: I0379ea7ff82a1e077b95f6996d11d1722de00936
Signed-off-by: Ritesh Kumar <[email protected]>
Ritesh Kumar 3 anos atrás
pai
commit
f2499b50d8
1 arquivos alterados com 1 adições e 7 exclusões
  1. 1 7
      msm/dsi/dsi_ctrl.c

+ 1 - 7
msm/dsi/dsi_ctrl.c

@@ -370,13 +370,6 @@ static void dsi_ctrl_dma_cmd_wait_for_done(struct dsi_ctrl *dsi_ctrl)
 	dsi_hw_ops = dsi_ctrl->hw.ops;
 	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY);
 
-	/*
-	 * This atomic state will be set if ISR has been triggered,
-	 * so the wait is not needed.
-	 */
-	if (atomic_read(&dsi_ctrl->dma_irq_trig))
-		return;
-
 	ret = wait_for_completion_timeout(
 			&dsi_ctrl->irq_info.cmd_dma_done,
 			msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
@@ -397,6 +390,7 @@ static void dsi_ctrl_dma_cmd_wait_for_done(struct dsi_ctrl *dsi_ctrl)
 		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
 					DSI_SINT_CMD_MODE_DMA_DONE);
 	}
+	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_EXIT);
 
 }