mirror of https://gitee.com/openkylin/linux.git
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fix from Wolfram Sang: "A single driver bugfix for I2C. The bug was found by systematically stress testing the driver, so I am confident to merge it that late in the cycle although it is probably unusually large" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: xlp9xx: Fix case where SSIF read transaction completes early
This commit is contained in:
commit
f313b43be4
|
@ -191,28 +191,43 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
|
|||
if (priv->len_recv) {
|
||||
/* read length byte */
|
||||
rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
|
||||
|
||||
/*
|
||||
* We expect at least 2 interrupts for I2C_M_RECV_LEN
|
||||
* transactions. The length is updated during the first
|
||||
* interrupt, and the buffer contents are only copied
|
||||
* during subsequent interrupts. If in case the interrupts
|
||||
* get merged we would complete the transaction without
|
||||
* copying out the bytes from RX fifo. To avoid this now we
|
||||
* drain the fifo as and when data is available.
|
||||
* We drained the rlen byte already, decrement total length
|
||||
* by one.
|
||||
*/
|
||||
|
||||
len--;
|
||||
if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) {
|
||||
rlen = 0; /*abort transfer */
|
||||
priv->msg_buf_remaining = 0;
|
||||
priv->msg_len = 0;
|
||||
} else {
|
||||
*buf++ = rlen;
|
||||
if (priv->client_pec)
|
||||
++rlen; /* account for error check byte */
|
||||
/* update remaining bytes and message length */
|
||||
priv->msg_buf_remaining = rlen;
|
||||
priv->msg_len = rlen + 1;
|
||||
xlp9xx_i2c_update_rlen(priv);
|
||||
return;
|
||||
}
|
||||
|
||||
*buf++ = rlen;
|
||||
if (priv->client_pec)
|
||||
++rlen; /* account for error check byte */
|
||||
/* update remaining bytes and message length */
|
||||
priv->msg_buf_remaining = rlen;
|
||||
priv->msg_len = rlen + 1;
|
||||
xlp9xx_i2c_update_rlen(priv);
|
||||
priv->len_recv = false;
|
||||
} else {
|
||||
len = min(priv->msg_buf_remaining, len);
|
||||
for (i = 0; i < len; i++, buf++)
|
||||
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
|
||||
|
||||
priv->msg_buf_remaining -= len;
|
||||
}
|
||||
|
||||
len = min(priv->msg_buf_remaining, len);
|
||||
for (i = 0; i < len; i++, buf++)
|
||||
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
|
||||
|
||||
priv->msg_buf_remaining -= len;
|
||||
priv->msg_buf = buf;
|
||||
|
||||
if (priv->msg_buf_remaining)
|
||||
|
|
Loading…
Reference in New Issue