[linux-yocto] [PATCH 06/17] i2c: axxia: Fix broken smbus block read
From: Anders Berg Changed the initial transfer size on block reads from 1 to I2C_SMBUS_BLOCK_MAX. The size is adjusted when the first byte (block length) is received. Having the initial size set to 1 could cause the controller to stop the transfer after the block length byte, if the transfer length register wasn't updated in time. Signed-off-by: Anders Berg --- drivers/i2c/busses/i2c-axxia.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index e965793..15d5f0d 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -271,15 +271,18 @@ axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev) while (0 < bytes_to_transfer--) { int c = readl(&idev->regs->mst_data); if (idev->msg_xfrd == 0 && i2c_m_recv_len(msg)) { - if (c == 0 || c > I2C_SMBUS_BLOCK_MAX) { + /* +* Check length byte for SMBus block read +*/ + if (c <= 0) { idev->msg_err = -EPROTO; i2c_int_disable(idev, ~0); - dev_err(idev->dev, - "invalid SMBus block size (%d)\n", c); complete(&idev->msg_complete); break; + } else if (c > I2C_SMBUS_BLOCK_MAX) { + c = I2C_SMBUS_BLOCK_MAX; } - msg->len += c; + msg->len = 1 + c; writel(msg->len, &idev->regs->mst_rx_xfer); } msg->buf[idev->msg_xfrd++] = c; @@ -402,7 +405,10 @@ axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) /* TX 0 bytes */ writel(0, &idev->regs->mst_tx_xfer); /* RX # bytes */ - writel(msg->len, &idev->regs->mst_rx_xfer); + if (i2c_m_recv_len(msg)) + writel(I2C_SMBUS_BLOCK_MAX, &idev->regs->mst_rx_xfer); + else + writel(msg->len, &idev->regs->mst_rx_xfer); } else { /* TX # bytes */ writel(msg->len, &idev->regs->mst_tx_xfer); -- 1.7.9.5 -- ___ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto
[linux-yocto] [PATCH 06/17] i2c: axxia: Fix broken smbus block read
From: Anders Berg Changed the initial transfer size on block reads from 1 to I2C_SMBUS_BLOCK_MAX. The size is adjusted when the first byte (block length) is received. Having the initial size set to 1 could cause the controller to stop the transfer after the block length byte, if the transfer length register wasn't updated in time. Signed-off-by: Anders Berg --- drivers/i2c/busses/i2c-axxia.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index e965793..15d5f0d 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -271,15 +271,18 @@ axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev) while (0 < bytes_to_transfer--) { int c = readl(&idev->regs->mst_data); if (idev->msg_xfrd == 0 && i2c_m_recv_len(msg)) { - if (c == 0 || c > I2C_SMBUS_BLOCK_MAX) { + /* +* Check length byte for SMBus block read +*/ + if (c <= 0) { idev->msg_err = -EPROTO; i2c_int_disable(idev, ~0); - dev_err(idev->dev, - "invalid SMBus block size (%d)\n", c); complete(&idev->msg_complete); break; + } else if (c > I2C_SMBUS_BLOCK_MAX) { + c = I2C_SMBUS_BLOCK_MAX; } - msg->len += c; + msg->len = 1 + c; writel(msg->len, &idev->regs->mst_rx_xfer); } msg->buf[idev->msg_xfrd++] = c; @@ -402,7 +405,10 @@ axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) /* TX 0 bytes */ writel(0, &idev->regs->mst_tx_xfer); /* RX # bytes */ - writel(msg->len, &idev->regs->mst_rx_xfer); + if (i2c_m_recv_len(msg)) + writel(I2C_SMBUS_BLOCK_MAX, &idev->regs->mst_rx_xfer); + else + writel(msg->len, &idev->regs->mst_rx_xfer); } else { /* TX # bytes */ writel(msg->len, &idev->regs->mst_tx_xfer); -- 1.7.9.5 -- ___ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto