Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc6311b1 authored by Vara Reddy's avatar Vara Reddy Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/dsi: fix dsi command dma async race condition



Change will be removing checking and clearing dsi cmd done
interrupt in commit thread and in workqueue context, which
can race with dsi isr, when it tries to clear the interrupt.

Change-Id: I96e7f8dffed1af3cec0c7668ab1729337d4b260e
Signed-off-by: default avatarVara Reddy <varar@codeaurora.org>
parent 10465152
Loading
Loading
Loading
Loading
+1 −31
Original line number Diff line number Diff line
@@ -265,10 +265,6 @@ dsi_ctrl_get_aspace(struct dsi_ctrl *dsi_ctrl,

static void dsi_ctrl_flush_cmd_dma_queue(struct dsi_ctrl *dsi_ctrl)
{
	u32 status;
	u32 mask = DSI_CMD_MODE_DMA_DONE;
	struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;

	/*
	 * If a command is triggered right after another command,
	 * check if the previous command transfer is completed. If
@@ -277,21 +273,8 @@ static void dsi_ctrl_flush_cmd_dma_queue(struct dsi_ctrl *dsi_ctrl)
	 * completed before triggering the next command by
	 * flushing the workqueue.
	 */
	status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
	if (atomic_read(&dsi_ctrl->dma_irq_trig)) {
		cancel_work_sync(&dsi_ctrl->dma_cmd_wait);
	} else if (status & mask) {
		atomic_set(&dsi_ctrl->dma_irq_trig, 1);
		status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);
		dsi_hw_ops.clear_interrupt_status(
						&dsi_ctrl->hw,
						status);
		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
				DSI_SINT_CMD_MODE_DMA_DONE);
		complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
		cancel_work_sync(&dsi_ctrl->dma_cmd_wait);
		DSI_CTRL_DEBUG(dsi_ctrl,
				"dma_tx done but irq not yet triggered\n");
	} else {
		flush_workqueue(dsi_ctrl->dma_cmd_workq);
	}
@@ -315,24 +298,11 @@ static void dsi_ctrl_dma_cmd_wait_for_done(struct work_struct *work)
	 */
	if (atomic_read(&dsi_ctrl->dma_irq_trig))
		goto done;
	/*
	 * If IRQ wasn't triggered check interrupt status register for
	 * transfer done before waiting.
	 */
	status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
	if (status & mask) {
		status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);
		dsi_hw_ops.clear_interrupt_status(&dsi_ctrl->hw,
				status);
		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
				DSI_SINT_CMD_MODE_DMA_DONE);
		goto done;
	}

	ret = wait_for_completion_timeout(
			&dsi_ctrl->irq_info.cmd_dma_done,
			msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
	if (ret == 0) {
	if (ret == 0 && !atomic_read(&dsi_ctrl->dma_irq_trig)) {
		status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
		if (status & mask) {
			status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);