On Sat, Jan 11, 2020 at 12:46:17PM +0100, Mark Kettenis wrote:
> > Date: Fri, 10 Jan 2020 12:07:51 +0100
> > From: Claudio Jeker <cje...@diehard.n-r-g.com>
> > 
> > On Sun, Dec 22, 2019 at 04:55:59PM +0100, Mark Kettenis wrote:
> > > The diff below contains a couple of improvements to dwiic(4).  They're
> > > mostly for making ipmi(4) on the Ampere/Lenovo arm64 boxes work
> > > better.  But they need testing on x86 machines with
> > > keyboards.touchpads/touchscreens connected over i2c.
> > > 
> > > Most of the diff is there to properly implement SMBus block write/read
> > > transactions.  Defines for these are taken from NetBSD (even though
> > > NetBSD doesn't actually implement these).  Nothing special needs to
> > > been done for block writes, but for block reads the slave device sends
> > > us byte count before sending us the data bytes.  So the code is
> > > changed such that we read the byte count first and then adjust the
> > > length of the transaction accordingly.
> > > 
> > > The diff then uses this support for block reads in the ipmi(4) SSIF
> > > interface code and adds support for multi-part read transactions on
> > > top of that.  That makes ipmi(4) fully functional on the arm64 machine
> > > mentioned above.
> > > 
> > > Well, almost.  I found that dwiic(4) still craps out every now and
> > > then on this machine.  Limiting the number of commands we send to the
> > > controller to the size of the Tx FIFO minus one seems to help.
> > > 
> > > Will probably split up the diff before committing.
> > > 
> > > ok?
> > > 
> > > 
> > > Index: dev/ic/dwiic.c
> > > ===================================================================
> > > RCS file: /cvs/src/sys/dev/ic/dwiic.c,v
> > > retrieving revision 1.8
> > > diff -u -p -r1.8 dwiic.c
> > > --- dev/ic/dwiic.c        18 Aug 2019 15:52:45 -0000      1.8
> > > +++ dev/ic/dwiic.c        22 Dec 2019 15:40:28 -0000
> > > @@ -338,6 +338,13 @@ dwiic_i2c_exec(void *cookie, i2c_op_t op
> > >  
> > >           dwiic_write(sc, DW_IC_DATA_CMD, cmd);
> > >  
> > > +         /*
> > > +          * For a block read, get the byte count before
> > > +          * continuing to read the data bytes.
> > > +          */
> > > +         if (I2C_OP_READ_P(op) && I2C_OP_BLKMODE_P(op) && readpos == 0)
> > > +                 tx_limit = 1;
> > > +
> > >           tx_limit--;
> > >           x++;
> > >  
> > > @@ -345,7 +352,7 @@ dwiic_i2c_exec(void *cookie, i2c_op_t op
> > >            * As TXFLR fills up, we need to clear it out by reading all
> > >            * available data.
> > >            */
> > > -         while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) {
> > > +         while (I2C_OP_READ_P(op) && (tx_limit <= 1 || x == len)) {
> > >                   DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n",
> > >                       sc->sc_dev.dv_xname, __func__, tx_limit, x));
> > >  
> > 
> > I'm a bit confused with the previous two hunks. Why change the tx_limit
> > check? Also you set tx_limit to 1 and then immediatly a tx_limit-- follows
> > so that the limit is actually 0 which is what you want but then the change
> > of the check in the while loop seems wrong.
> 
> Ok, let's separate things out a bit more.  Here is the diff that just
> implements block mode.  There the limit is initially set to 1 to make
> sure we have a chance to look at the first byte to determine the total
> length of the transfer.
> 
> ok?
> 

Sure, that is OK claudio@

> 
> Index: dev/ic/dwiic.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/dwiic.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 dwiic.c
> --- dev/ic/dwiic.c    18 Aug 2019 15:52:45 -0000      1.8
> +++ dev/ic/dwiic.c    11 Jan 2020 11:37:53 -0000
> @@ -338,6 +338,13 @@ dwiic_i2c_exec(void *cookie, i2c_op_t op
>  
>               dwiic_write(sc, DW_IC_DATA_CMD, cmd);
>  
> +             /*
> +              * For a block read, get the byte count before
> +              * continuing to read the data bytes.
> +              */
> +             if (I2C_OP_READ_P(op) && I2C_OP_BLKMODE_P(op) && readpos == 0)
> +                     tx_limit = 1;
> +
>               tx_limit--;
>               x++;
>  
> @@ -374,8 +381,7 @@ dwiic_i2c_exec(void *cookie, i2c_op_t op
>  
>                       if (rx_avail == 0) {
>                               printf("%s: timed out reading remaining %d\n",
> -                                 sc->sc_dev.dv_xname,
> -                                 (int)(len - 1 - readpos));
> +                                 sc->sc_dev.dv_xname, (int)(len - readpos));
>                               sc->sc_i2c_xfer.error = 1;
>                               sc->sc_busy = 0;
>  
> @@ -394,6 +400,13 @@ dwiic_i2c_exec(void *cookie, i2c_op_t op
>                               }
>                               rx_avail--;
>                       }
> +
> +                     /*
> +                      * Update the transfer length when doing a
> +                      * block read.
> +                      */
> +                     if (I2C_OP_BLKMODE_P(op) && readpos > 0 && len > b[0])
> +                             len = b[0] + 1;
>  
>                       if (readpos >= len)
>                               break;

-- 
:wq Claudio

Reply via email to