i2c-fixes for v7.2-rc4

imx: fix empty SMBus block reads in atomic and IRQ paths
 spacemit: return IRQ_NONE for empty interrupt status
 mlxbf: fix a use-after-free issue
 mediatek: restore WRRD support without automatic restart
 CREDITS: add Wolfram Sang
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQScDfrjQa34uOld1VLaeAVmJtMtbgUCaltX3AAKCRDaeAVmJtMt
 bqqgAPsFCe+3Y/71UNBWzOEI99zUlyFu7OH7Rt/015HVXsmelgEAjkQ0X5RX2Njg
 AswoeT+OGvxxVxlNeNMMrxAM4s6caQU=
 =yKh8
 -----END PGP SIGNATURE-----

Merge tag 'i2c-fixes-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux

Pull i2c fixes from Andi Shyti:
 "A handful of small fixes for host controller drivers.

  One patch also adds Wolfram Sang to CREDITS after more than a decade
  of work on I2C"

* tag 'i2c-fixes-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux:
  i2c: mediatek: fix WRRD for SoCs without auto_restart option
  i2c: mlxbf: Fix use-after-free in mlxbf_i2c_init_resource()
  i2c: spacemit: fix spurious IRQ handling returning IRQ_HANDLED
  i2c: imx: fix locked bus on SMBus block-read of 0 (IRQ)
  i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)
  CREDITS: Add Wolfram Sang
This commit is contained in:
Linus Torvalds 2026-07-18 09:16:35 -07:00
commit ba6bd0df9a
5 changed files with 45 additions and 6 deletions

View File

@ -3626,6 +3626,13 @@ S: 69 rue Dunois
S: 75013 Paris
S: France
N: Wolfram Sang
E: wsa@kernel.org
W: sang-engineering.com
P: rsa4096/140DE4CC14A029B6 3991 B1EA B9E2 6751 A4F7 645D 140D E4CC 14A0 29B6
D: I2C Maintainer 2012 - 2026
S: Berlin, Germany
N: Aleksa Sarai
E: cyphar@cyphar.com
W: https://www.cyphar.com/

View File

@ -1061,11 +1061,28 @@ static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct
static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)
{
u8 len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
unsigned int temp;
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
/*
* SMBus 3.1 6.5.7: support count byte of 0.
* I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
* So NACK it (TXAK) to not hold the bus.
*/
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_TXAK;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
if (len == 0) {
i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = 0;
i2c_imx->msg->len = 2;
return;
}
i2c_imx->isr_result = -EPROTO;
i2c_imx->state = IMX_I2C_STATE_FAILED;
wake_up(&i2c_imx->queue);
return;
}
i2c_imx->msg->len += len;
i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len;
@ -1415,6 +1432,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
int block_err = 0;
result = i2c_imx_prepare_read(i2c_imx, msgs, false);
if (result)
@ -1436,8 +1454,20 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
*/
if ((!i) && block_data) {
len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
return -EPROTO;
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
/*
* SMBus 3.1 6.5.7: support count byte of 0.
* I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
*/
if (len > I2C_SMBUS_BLOCK_MAX)
block_err = -EPROTO;
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_TXAK;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
msgs->buf[0] = 0;
msgs->len = 2;
continue;
}
dev_dbg(&i2c_imx->adapter.dev,
"<%s> read length: 0x%X\n",
__func__, len);
@ -1485,7 +1515,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
"<%s> read byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
}
return 0;
return block_err;
}
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,

View File

@ -596,7 +596,7 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
status = readl(i2c->base + SPACEMIT_ISR);
if (!status)
return IRQ_HANDLED;
return IRQ_NONE;
i2c->status = status;

View File

@ -1051,8 +1051,10 @@ static int mlxbf_i2c_init_resource(struct platform_device *pdev,
tmp_res->io = devm_platform_get_and_ioremap_resource(pdev, type, &tmp_res->params);
if (IS_ERR(tmp_res->io)) {
int ret = PTR_ERR(tmp_res->io);
devm_kfree(dev, tmp_res);
return PTR_ERR(tmp_res->io);
return ret;
}
tmp_res->type = type;

View File

@ -1258,7 +1258,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
i2c->auto_restart = i2c->dev_comp->auto_restart;
/* checking if we can skip restart and optimize using WRRD mode */
if (i2c->auto_restart && num == 2) {
if (num == 2) {
if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&
msgs[0].addr == msgs[1].addr) {
i2c->auto_restart = 0;