Re: [PATCH v2 1/2] i2c: xiic: Wait for TX empty to avoid missed TX NAKs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2024-09-11 at 14:40 +0200, Andi Shyti wrote:
> Hi Robert,
> 
> For some reason this patch and the next was set in patchwork as
> "Changes requested" and did not appear in the list of things to
> review.
> 
> On Tue, Nov 21, 2023 at 06:11:16PM GMT, Robert Hancock wrote:
> > Frequently an I2C write will be followed by a read, such as a
> > register
> > address write followed by a read of the register value. In this
> > driver,
> > when the TX FIFO half empty interrupt was raised and it was
> > determined
> > that there was enough space in the TX FIFO to send the following
> > read
> > command, it would do so without waiting for the TX FIFO to actually
> > empty.
> > 
> > Unfortunately it appears that in some cases this can result in a
> > NAK
> > that was raised by the target device on the write, such as due to
> > an
> > unsupported register address, being ignored and the subsequent read
> > being done anyway. This can potentially put the I2C bus into an
> > invalid state and/or result in invalid read data being processed.
> > 
> > To avoid this, once a message has been fully written to the TX
> > FIFO,
> > wait for the TX FIFO empty interrupt before moving on to the next
> > message, to ensure NAKs are handled properly.
> > 
> > Fixes: e1d5b6598cdc ("i2c: Add support for Xilinx XPS IIC Bus
> > Interface")
> > Signed-off-by: Robert Hancock <robert.hancock@xxxxxxxxxx>
> > ---
> >  drivers/i2c/busses/i2c-xiic.c | 19 +++++++++----------
> >  1 file changed, 9 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-xiic.c
> > b/drivers/i2c/busses/i2c-xiic.c
> > index 71391b590ada..fd623e8ad08a 100644
> > --- a/drivers/i2c/busses/i2c-xiic.c
> > +++ b/drivers/i2c/busses/i2c-xiic.c
> > @@ -772,14 +772,17 @@ static irqreturn_t xiic_process(int irq, void
> > *dev_id)
> >                       goto out;
> >               }
> > 
> > -             xiic_fill_tx_fifo(i2c);
> > -
> > -             /* current message sent and there is space in the
> > fifo */
> > -             if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >=
> > 2) {
> > +             if (xiic_tx_space(i2c)) {
> > +                     xiic_fill_tx_fifo(i2c);
> > +             } else {
> > +                     /* current message fully written */
> >                       dev_dbg(i2c->adap.dev.parent,
> >                               "%s end of message sent, nmsgs:
> > %d\n",
> >                               __func__, i2c->nmsgs);
> > -                     if (i2c->nmsgs > 1) {
> > +                     /* Don't move onto the next message until the
> > TX FIFO empties,
> > +                      * to ensure that a NAK is not missed.
> > +                      */
> > +                     if (i2c->nmsgs > 1 && (pend &
> > XIIC_INTR_TX_EMPTY_MASK)) {
> 
> can "pend" be both XIIC_INTR_TX_EMPTY_MASK and
> XIIC_INTR_TX_HALF_MASK?
> 

It's been a while since I looked at this, but I believe it potentially
could be. However, it seems like the behavior should still be correct -
if the TX FIFO is empty then it is also half empty, but really the fact
it is empty is what we care about in that situation...

> Andi
> 
> >                               i2c->nmsgs--;
> >                               i2c->tx_msg++;
> >                               xfer_more = 1;
> > @@ -790,11 +793,7 @@ static irqreturn_t xiic_process(int irq, void
> > *dev_id)
> >                                       "%s Got TX IRQ but no more to
> > do...\n",
> >                                       __func__);
> >                       }
> > -             } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1))
> > -                     /* current frame is sent and is last,
> > -                      * make sure to disable tx half
> > -                      */
> > -                     xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
> > +             }
> >       }
> > 
> >       if (pend & XIIC_INTR_BNB_MASK) {
> > --
> > 2.42.0
> > 





[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux