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

Commit eeebf75a authored by Shrey Vijay's avatar Shrey Vijay Committed by Gerrit - the friendly Code Review server
Browse files

i2c-msm-v2: Print error logs in process context



Move error logs from interrupt context to process context to
avoid blocking other interrupts and reduce latencies in
ISR handling.
Also keep error check for BAM rx completion.

Change-Id: Ibf355561495b35702118eaf9a0f38c0fdc9310b3
Signed-off-by: default avatarShrey Vijay <shreyv@codeaurora.org>
parent bfd96c27
Loading
Loading
Loading
Loading
+26 −23
Original line number Diff line number Diff line
@@ -1310,7 +1310,8 @@ static int i2c_msm_dma_xfer_process(struct i2c_msm_ctrl *ctrl)

	ret = i2c_msm_xfer_wait_for_completion(ctrl, &ctrl->xfer.complete);
	if (!ret && ctrl->xfer.rx_cnt)
		i2c_msm_xfer_wait_for_completion(ctrl, &ctrl->xfer.rx_complete);
		ret = i2c_msm_xfer_wait_for_completion(ctrl,
						&ctrl->xfer.rx_complete);

dma_xfer_end:
	/* free scatter-gather lists */
@@ -1716,9 +1717,7 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
	void __iomem        *base = ctrl->rsrcs.base;
	struct i2c_msm_xfer *xfer = &ctrl->xfer;
	struct i2c_msm_xfer_mode_blk *blk = &ctrl->xfer.blk;
	u32  i2c_status = 0;
	u32  err_flags  = 0;
	u32  qup_op     = 0;
	u32  clr_flds   = 0;
	bool log_event       = false;
	bool signal_complete = false;
@@ -1731,24 +1730,24 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
		return IRQ_HANDLED;
	}

	i2c_status  = readl_relaxed(base + QUP_I2C_STATUS);
	ctrl->i2c_sts_reg  = readl_relaxed(base + QUP_I2C_STATUS);
	err_flags	   = readl_relaxed(base + QUP_ERROR_FLAGS);
	qup_op      = readl_relaxed(base + QUP_OPERATIONAL);
	ctrl->qup_op_reg   = readl_relaxed(base + QUP_OPERATIONAL);

	if (i2c_status & QUP_MSTR_STTS_ERR_MASK) {
	if (ctrl->i2c_sts_reg & QUP_MSTR_STTS_ERR_MASK) {
		signal_complete = true;
		log_event       = true;
		/*
		 * If there is more than 1 error here, last one sticks.
		 * The order of the error set here matters.
		 */
		if (i2c_status & QUP_ARB_LOST)
		if (ctrl->i2c_sts_reg & QUP_ARB_LOST)
			ctrl->xfer.err = I2C_MSM_ERR_ARB_LOST;

		if (i2c_status & QUP_BUS_ERROR)
		if (ctrl->i2c_sts_reg & QUP_BUS_ERROR)
			ctrl->xfer.err = I2C_MSM_ERR_BUS_ERR;

		if (i2c_status & QUP_PACKET_NACKED)
		if (ctrl->i2c_sts_reg & QUP_PACKET_NACKED)
			ctrl->xfer.err = I2C_MSM_ERR_NACK;
	}

@@ -1761,7 +1760,7 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
		i2c_msm_dbg_qup_reg_dump(ctrl);

	/* clear interrupts fields */
	clr_flds = i2c_status & QUP_MSTR_STTS_ERR_MASK;
	clr_flds = ctrl->i2c_sts_reg & QUP_MSTR_STTS_ERR_MASK;
	if (clr_flds) {
		writel_relaxed(clr_flds, base + QUP_I2C_STATUS);
		need_wmb = true;
@@ -1773,7 +1772,9 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
		need_wmb = true;
	}

	clr_flds = qup_op & (QUP_OUTPUT_SERVICE_FLAG | QUP_INPUT_SERVICE_FLAG);
	clr_flds = ctrl->qup_op_reg &
			(QUP_OUTPUT_SERVICE_FLAG |
			QUP_INPUT_SERVICE_FLAG);
	if (clr_flds) {
		writel_relaxed(clr_flds, base + QUP_OPERATIONAL);
		need_wmb = true;
@@ -1814,25 +1815,25 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
	/* handle data completion */
	if (xfer->mode_id == I2C_MSM_XFER_MODE_BLOCK) {
		/* block ready for writing */
		if (qup_op & QUP_OUTPUT_SERVICE_FLAG) {
		if (ctrl->qup_op_reg & QUP_OUTPUT_SERVICE_FLAG) {
			log_event = true;
			if (qup_op & QUP_OUT_BLOCK_WRITE_REQ)
			if (ctrl->qup_op_reg & QUP_OUT_BLOCK_WRITE_REQ)
				complete(&blk->wait_tx_blk);

			if ((qup_op & blk->complete_mask)
			if ((ctrl->qup_op_reg & blk->complete_mask)
					== blk->complete_mask) {
				log_event       = true;
				signal_complete = true;
			}
		}
		/* block ready for reading */
		if (qup_op & QUP_INPUT_SERVICE_FLAG) {
		if (ctrl->qup_op_reg & QUP_INPUT_SERVICE_FLAG) {
			log_event = true;
			complete(&blk->wait_rx_blk);
		}
	} else {
		/* for FIFO/DMA Mode*/
		if (qup_op & QUP_MAX_INPUT_DONE_FLAG) {
		if (ctrl->qup_op_reg & QUP_MAX_INPUT_DONE_FLAG) {
			log_event = true;
			/*
			 * If last transaction is an input then the entire
@@ -1850,7 +1851,7 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
		 * here QUP_OUTPUT_SERVICE_FLAG and assumes that
		 * QUP_MAX_OUTPUT_DONE_FLAG.
		 */
		if (qup_op & (QUP_OUTPUT_SERVICE_FLAG |
		if (ctrl->qup_op_reg & (QUP_OUTPUT_SERVICE_FLAG |
						QUP_MAX_OUTPUT_DONE_FLAG)) {
			log_event = true;
			/*
@@ -1863,13 +1864,11 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid)
	}

isr_end:
	if (ctrl->xfer.err || (ctrl->dbgfs.dbg_lvl >= MSM_DBG))
		i2c_msm_dbg_dump_diag(ctrl, true, i2c_status, qup_op);

	if (log_event || (ctrl->dbgfs.dbg_lvl >= MSM_DBG))
		i2c_msm_prof_evnt_add(ctrl, MSM_PROF,
					I2C_MSM_IRQ_END,
					i2c_status, qup_op, err_flags);
					ctrl->i2c_sts_reg, ctrl->qup_op_reg,
					err_flags);

	if (signal_complete)
		complete(&ctrl->xfer.complete);
@@ -2078,8 +2077,12 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl,
					xfer->timeout, time_left, 0);
	} else {
		/* return an error if one detected by ISR */
		if (xfer->err)
		if (ctrl->xfer.err ||
				(ctrl->dbgfs.dbg_lvl >= MSM_DBG)) {
			i2c_msm_dbg_dump_diag(ctrl, true,
					ctrl->i2c_sts_reg, ctrl->qup_op_reg);
			ret = -(xfer->err);
		}
		i2c_msm_prof_evnt_add(ctrl, MSM_DBG, I2C_MSM_COMPLT_OK,
					xfer->timeout, time_left, 0);
	}
+4 −0
Original line number Diff line number Diff line
@@ -581,6 +581,8 @@ struct i2c_msm_xfer {
 * @rsrcs    resources from platform data including clocks, gpios, irqs, and
 *           memory regions.
 * @mstr_clk_ctl cached value for programming to mstr_clk_ctl register
 * @i2c_sts_reg	 status of QUP_I2C_MASTER_STATUS register.
 * @qup_op_reg	 status of QUP_OPERATIONAL register.
 */
struct i2c_msm_ctrl {
	struct device             *dev;
@@ -589,6 +591,8 @@ struct i2c_msm_ctrl {
	struct i2c_msm_dbgfs       dbgfs;
	struct i2c_msm_resources   rsrcs;
	u32                        mstr_clk_ctl;
	u32			   i2c_sts_reg;
	u32			   qup_op_reg;
	enum i2c_msm_power_state   pwr_state;
};