With an i2c device behind a PCA9540 mux having CONFIG_I2C_DEBUG_BUS enabled connection timeouts caused by a busy i2c bus can be observed: i2c i2c-3: master_xfer[0] W, addr=0x57, len=2 i2c i2c-3: master_xfer[1] R, addr=0x57, len=128 i2c i2c-2: <i2c_imx_xfer> i2c i2c-2: <i2c_imx_start> i2c i2c-2: <i2c_imx_bus_busy> i2c i2c-2: <i2c_imx_bus_busy> I2C bus is busy i2c i2c-2: <i2c_imx_xfer> exit with: error: -110 This happens due to the locking problem described in 6ef91fcca8a8 ("i2c: mux: relax locking of the top i2c adapter during mux-locked muxing"): The cause of the problem is that the mux is a i2c client on the same i2c bus that it muxes. Transfers to the mux clients will lock the whole i2c bus prior to attempting to switch the mux to the correct i2c segment. The mentioned commit introduced a new locking concept as "mux-locked" muxes so that these muxes lock only the muxes on the parent adapter instead of the whole i2c bus when there is a transfer to the slave side of the mux. Make use of this new locking concept: use the introduced flag I2C_MUX_LOCKED along with lock-aware i2c_transfer() instead of __i2c_transfer(). Signed-off-by: Bastian Stender <bst@xxxxxxxxxxxxxx> --- drivers/i2c/muxes/i2c-mux-pca954x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 09bafd3e68fa..0ea970eaa324 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -230,7 +230,7 @@ static int pca954x_reg_write(struct i2c_adapter *adap, msg.len = 1; buf[0] = val; msg.buf = buf; - ret = __i2c_transfer(adap, &msg, 1); + ret = i2c_transfer(adap, &msg, 1); if (ret >= 0 && ret != 1) ret = -EREMOTEIO; @@ -380,8 +380,9 @@ static int pca954x_probe(struct i2c_client *client, return -ENODEV; muxc = i2c_mux_alloc(adap, &client->dev, - PCA954X_MAX_NCHANS, sizeof(*data), 0, - pca954x_select_chan, pca954x_deselect_mux); + PCA954X_MAX_NCHANS, sizeof(*data), + I2C_MUX_LOCKED, pca954x_select_chan, + pca954x_deselect_mux); if (!muxc) return -ENOMEM; data = i2c_mux_priv(muxc); -- 2.17.0