On Tue, Jun 2, 2009 at 5:12 PM, Grant Likely <grant.likely@xxxxxxxxxxxx> wrote: > Hi Esben and Ben, > > Sorry for the lateness in reviewing this. FWIW, here are my comments. > > g. > > On Mon, May 18, 2009 at 11:22 PM, Esben Haabendal > <eha@xxxxxxxxxxxxxxxxxx> wrote: >> This fixes MAL (arbitration lost) bug caused by illegal use of >> RSTA (repeated START) after STOP condition generated after last byte >> of reads. With this patch, it is possible to do an i2c_transfer() with >> additional i2c_msg's following the I2C_M_RD messages. >> >> It still needs to be resolved if it is possible to fix this issue >> by removing the STOP condition after reads in a robust way. >> >> Signed-off-by: Esben Haabendal <eha@xxxxxxxxxxxxxxxxxx> >> --- >> drivers/i2c/busses/i2c-mpc.c | 9 +++++++-- >> 1 files changed, 7 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c >> index 4af5c09..0199f9a 100644 >> --- a/drivers/i2c/busses/i2c-mpc.c >> +++ b/drivers/i2c/busses/i2c-mpc.c >> @@ -456,17 +456,22 @@ static int mpc_xfer(struct i2c_adapter *adap, struct >> i2c_msg *msgs, int num) >> } >> >> for (i = 0; ret >= 0 && i < num; i++) { >> + int restart = i; >> pmsg = &msgs[i]; >> dev_dbg(i2c->dev, >> "Doing %s %d bytes to 0x%02x - %d of %d messages\n", >> pmsg->flags & I2C_M_RD ? "read" : "write", >> pmsg->len, pmsg->addr, i + 1, num); >> + if (i > 0 && ((pmsg - 1)->flags & I2C_M_RD)) >> + restart = 0; >> if (pmsg->flags & I2C_M_RD) >> ret = >> - mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, >> i); >> + mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, >> + restart); >> else >> ret = >> - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, >> i); >> + mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, >> + restart); >> } > > Hmmm, seems to be a rather convoluted code path. Surely this could be > handled in a clearer way. The whole (pmsg - 1) bit raises my eyebrows > (I'd rather see msgs[i-1]). At the very least this deserves an > comment describing what it is doing. The following might be better > for the next person who has to read this code: > > + int restart = 0; > for (i = 0; ret >= 0 && i < num; i++) { > pmsg = &msgs[i]; > dev_dbg(i2c->dev, > "Doing %s %d bytes to 0x%02x - %d of %d messages\n", > pmsg->flags & I2C_M_RD ? "read" : "write", > pmsg->len, pmsg->addr, i + 1, num); > if (pmsg->flags & I2C_M_RD) > ret = > - mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, > i); > + mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, > + restart); > else > ret = > - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, > i); > + mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, > + restart); > + /* Only set the restart flag if this was not an > I2C_M_RD transaction > + * because it causes an illegal use of > + * RSTA (repeated START) after STOP condition > generated after last byte > + * of reads */ > + restart = (pmsg->flags & I2C_M_RD == 0); > } BTW, since you're touching these lines anyway, please clean up the whitespace usage. Since you have to break the line anyway, it no longer makes sense for the "ret = " to be on a separate line anymore. g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html