Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+28 -13
+28 -13
drivers/i2c/busses/i2c-xlp9xx.c
··· 191 191 if (priv->len_recv) { 192 192 /* read length byte */ 193 193 rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); 194 + 195 + /* 196 + * We expect at least 2 interrupts for I2C_M_RECV_LEN 197 + * transactions. The length is updated during the first 198 + * interrupt, and the buffer contents are only copied 199 + * during subsequent interrupts. If in case the interrupts 200 + * get merged we would complete the transaction without 201 + * copying out the bytes from RX fifo. To avoid this now we 202 + * drain the fifo as and when data is available. 203 + * We drained the rlen byte already, decrement total length 204 + * by one. 205 + */ 206 + 207 + len--; 194 208 if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) { 195 209 rlen = 0; /*abort transfer */ 196 210 priv->msg_buf_remaining = 0; 197 211 priv->msg_len = 0; 198 - } else { 199 - *buf++ = rlen; 200 - if (priv->client_pec) 201 - ++rlen; /* account for error check byte */ 202 - /* update remaining bytes and message length */ 203 - priv->msg_buf_remaining = rlen; 204 - priv->msg_len = rlen + 1; 212 + xlp9xx_i2c_update_rlen(priv); 213 + return; 205 214 } 215 + 216 + *buf++ = rlen; 217 + if (priv->client_pec) 218 + ++rlen; /* account for error check byte */ 219 + /* update remaining bytes and message length */ 220 + priv->msg_buf_remaining = rlen; 221 + priv->msg_len = rlen + 1; 206 222 xlp9xx_i2c_update_rlen(priv); 207 223 priv->len_recv = false; 208 - } else { 209 - len = min(priv->msg_buf_remaining, len); 210 - for (i = 0; i < len; i++, buf++) 211 - *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); 212 - 213 - priv->msg_buf_remaining -= len; 214 224 } 215 225 226 + len = min(priv->msg_buf_remaining, len); 227 + for (i = 0; i < len; i++, buf++) 228 + *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); 229 + 230 + priv->msg_buf_remaining -= len; 216 231 priv->msg_buf = buf; 217 232 218 233 if (priv->msg_buf_remaining)