|
@@ -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)
|