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

Commit ac6c7ff9 authored by Ankit Gupta's avatar Ankit Gupta Committed by Gerrit - the friendly Code Review server
Browse files

i2c-msm-v2: fix potential spinning forever in ISR



IRQ is disabled before doing reset state in
post transfer on timeout to avoid entering ISR that can cause
this issue. If ISR is entered due to transfer error,
waiting for the qup core to get in a valid state may cause watch
dog bite if HW generates NoC error while reading status.
Avoid that by not polling in ISR.

Change-Id: I2e92e43cb37d501a378a717c996b9e98f6cf9fe8
Signed-off-by: default avatarAnkit Gupta <ankgupta@codeaurora.org>
Signed-off-by: default avatarKiran Gunda <kgunda@codeaurora.org>
parent a5eb2c93
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -1781,10 +1781,10 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)

		/* HW workaround: when interrupt is level triggerd, more
		 * than one interrupt may fire in error cases. Thus we
		 * resetting the QUP core state immediately in the ISR
		 * to ward off the next interrupt.
		 * change the QUP core state to Reset immediately in the
		 * ISR to ward off the next interrupt.
		 */
		i2c_msm_qup_state_set(ctrl, QUP_STATE_RESET);
		writel_relaxed(QUP_STATE_RESET, ctrl->rsrcs.base + QUP_STATE);

		signal_complete = true;
		log_event       = true;
@@ -1975,6 +1975,13 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err)
		}
	}

	/*
	 * Disable the IRQ before change to reset state to avoid
	 * spurious interrupts.
	 *
	 */
	disable_irq(ctrl->rsrcs.irq);

	/* flush dma data and reset the qup core in timeout error.
	 * for other error case, its handled by the ISR
	 */
@@ -1983,8 +1990,9 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err)
		if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_DMA)
			writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base
								+ QUP_STATE);
		/* reset the sw core */
		i2c_msm_qup_sw_reset(ctrl);

		/* reset the qup core */
		i2c_msm_qup_state_set(ctrl, QUP_STATE_RESET);
		err = -ETIMEDOUT;
	} else if (ctrl->xfer.err == I2C_MSM_ERR_NACK) {
		err = -ENOTCONN;
@@ -2214,7 +2222,6 @@ static int i2c_msm_pm_xfer_start(struct i2c_msm_ctrl *ctrl)

static void i2c_msm_pm_xfer_end(struct i2c_msm_ctrl *ctrl)
{
	disable_irq(ctrl->rsrcs.irq);

	atomic_set(&ctrl->xfer.is_active, 0);