Tested-by: Raviteja Narayanam <raviteja.narayanam@xxxxxxxxxx> Thanks Raviteja N > -----Original Message----- > From: linux-i2c-owner@xxxxxxxxxxxxxxx <linux-i2c-owner@xxxxxxxxxxxxxxx> On > Behalf Of Raviteja Narayanam > Sent: Friday, June 26, 2020 5:44 PM > To: Marek Vasut <marex@xxxxxxx>; linux-i2c@xxxxxxxxxxxxxxx > Cc: Michal Simek <michals@xxxxxxxxxx>; Shubhrajyoti Datta > <shubhraj@xxxxxxxxxx>; Wolfram Sang <wsa@xxxxxxxxxx> > Subject: RE: [PATCH 3/5] i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in > xiic_process() > > > > > -----Original Message----- > > From: linux-i2c-owner@xxxxxxxxxxxxxxx > > <linux-i2c-owner@xxxxxxxxxxxxxxx> On Behalf Of Marek Vasut > > Sent: Saturday, June 13, 2020 8:38 PM > > To: linux-i2c@xxxxxxxxxxxxxxx > > Cc: Marek Vasut <marex@xxxxxxx>; Michal Simek <michals@xxxxxxxxxx>; > > Shubhrajyoti Datta <shubhraj@xxxxxxxxxx>; Wolfram Sang > > <wsa@xxxxxxxxxx> > > Subject: [PATCH 3/5] i2c: xiic: Defer xiic_wakeup() and > > __xiic_start_xfer() in > > xiic_process() > > > > The __xiic_start_xfer() manipulates the interrupt flags, xiic_wakeup() > > may result in return from xiic_xfer() early. Defer both to the end of > > the > > xiic_process() interrupt thread, so that they are executed after all > > the other interrupt bits handling completed and once it completely > > safe to perform changes to the interrupt bits in the hardware. > > > > Signed-off-by: Marek Vasut <marex@xxxxxxx> > > Cc: Michal Simek <michal.simek@xxxxxxxxxx> > > Cc: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx> > > Cc: Wolfram Sang <wsa@xxxxxxxxxx> > > --- > > drivers/i2c/busses/i2c-xiic.c | 37 > > ++++++++++++++++++++++++----------- > > 1 file changed, 26 insertions(+), 11 deletions(-) > > > > diff --git a/drivers/i2c/busses/i2c-xiic.c > > b/drivers/i2c/busses/i2c-xiic.c index > > 6db71c0fb6583..87eca9d46afd9 100644 > > --- a/drivers/i2c/busses/i2c-xiic.c > > +++ b/drivers/i2c/busses/i2c-xiic.c > > @@ -373,6 +373,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) > > struct xiic_i2c *i2c = dev_id; > > u32 pend, isr, ier; > > u32 clr = 0; > > + int xfer_more = 0; > > + int wakeup_req = 0; > > + int wakeup_code = 0; > > > > /* Get the interrupt Status from the IPIF. There is no clearing of > > * interrupts in the IPIF. Interrupts must be cleared at the source. > > @@ -409,10 +412,14 @@ static irqreturn_t xiic_process(int irq, void > *dev_id) > > */ > > xiic_reinit(i2c); > > > > - if (i2c->rx_msg) > > - xiic_wakeup(i2c, STATE_ERROR); > > - if (i2c->tx_msg) > > - xiic_wakeup(i2c, STATE_ERROR); > > + if (i2c->rx_msg) { > > + wakeup_req = 1; > > + wakeup_code = STATE_ERROR; > > + } > > + if (i2c->tx_msg) { > > + wakeup_req = 1; > > + wakeup_code = STATE_ERROR; > > + } > > } > > if (pend & XIIC_INTR_RX_FULL_MASK) { > > /* Receive register/FIFO is full */ @@ -446,8 +453,7 @@ static > > irqreturn_t xiic_process(int irq, void *dev_id) > > i2c->tx_msg++; > > dev_dbg(i2c->adap.dev.parent, > > "%s will start next...\n", __func__); > > - > > - __xiic_start_xfer(i2c); > > + xfer_more = 1; > > } > > } > > } > > @@ -461,11 +467,13 @@ static irqreturn_t xiic_process(int irq, void > *dev_id) > > if (!i2c->tx_msg) > > goto out; > > > > - if ((i2c->nmsgs == 1) && !i2c->rx_msg && > > - xiic_tx_space(i2c) == 0) > > - xiic_wakeup(i2c, STATE_DONE); > > + wakeup_req = 1; > > + > > + if (i2c->nmsgs == 1 && !i2c->rx_msg && > > + xiic_tx_space(i2c) == 0) > > + wakeup_code = STATE_DONE; > > else > > - xiic_wakeup(i2c, STATE_ERROR); > > + wakeup_code = STATE_ERROR; > > } > > if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) > { > > /* Transmit register/FIFO is empty or ½ empty */ @@ -489,7 > > +497,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) > > if (i2c->nmsgs > 1) { > > i2c->nmsgs--; > > i2c->tx_msg++; > > - __xiic_start_xfer(i2c); > > + xfer_more = 1; > > } else { > > xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); > > > > @@ -507,6 +515,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) > > dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); > > > > xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); > > + if (xfer_more) > > + __xiic_start_xfer(i2c); > > + if (wakeup_req) > > + xiic_wakeup(i2c, wakeup_code); > > + > > + WARN_ON(xfer_more && wakeup_req); > > + > > mutex_unlock(&i2c->lock); > > return IRQ_HANDLED; > > } > > This is tested and working fine. > > Raviteja N