Hi Cosmo, On Mon, Nov 20, 2023 at 05:17:46PM +0800, Cosmo Chou wrote: > commit 2be6b47211e1 ("i2c: aspeed: Acknowledge most interrupts early > in interrupt handler") moved most interrupt acknowledgments to the > start of the interrupt handler to avoid race conditions. However, > slave Tx ack status shouldn't be cleared before SLAVE_READ_PROCESSED > is handled. > > Acknowledge Tx ack status after handling SLAVE_READ_PROCESSED to fix > the problem that the next byte is not sent correctly. > > Fixes: 2be6b47211e1 ("i2c: aspeed: Acknowledge most interrupts early in interrupt handler") > Signed-off-by: Cosmo Chou <chou.cosmo@xxxxxxxxx> > --- > drivers/i2c/busses/i2c-aspeed.c | 17 ++++++++++++++--- > 1 file changed, 14 insertions(+), 3 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c > index 28e2a5fc4528..c2d74e4b7e50 100644 > --- a/drivers/i2c/busses/i2c-aspeed.c > +++ b/drivers/i2c/busses/i2c-aspeed.c > @@ -337,6 +337,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) > break; > } > > + /* Ack Tx ack */ > + if (irq_handled & ASPEED_I2CD_INTR_TX_ACK) { > + writel(ASPEED_I2CD_INTR_TX_ACK, bus->base + ASPEED_I2C_INTR_STS_REG); > + readl(bus->base + ASPEED_I2C_INTR_STS_REG); > + } > + > return irq_handled; > } > #endif /* CONFIG_I2C_SLAVE */ > @@ -602,13 +608,18 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) > static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) > { > struct aspeed_i2c_bus *bus = dev_id; > - u32 irq_received, irq_remaining, irq_handled; > + u32 irq_received, irq_remaining, irq_handled, irq_acked; > > spin_lock(&bus->lock); > irq_received = readl(bus->base + ASPEED_I2C_INTR_STS_REG); > /* Ack all interrupts except for Rx done */ > - writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE, > - bus->base + ASPEED_I2C_INTR_STS_REG); > + irq_acked = irq_received & ~ASPEED_I2CD_INTR_RX_DONE; > +#if IS_ENABLED(CONFIG_I2C_SLAVE) > + /* shouldn't ack Slave Tx Ack before it's handled */ > + if (bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) > + irq_acked &= ~ASPEED_I2CD_INTR_TX_ACK; > +#endif > + writel(irq_acked, bus->base + ASPEED_I2C_INTR_STS_REG); which branch are you? You don't look like being in the latest. Please update your branch. Andi > readl(bus->base + ASPEED_I2C_INTR_STS_REG); > irq_received &= ASPEED_I2CD_INTR_RECV_MASK; > irq_remaining = irq_received; > -- > 2.34.1 >