diff options
author | Peter Rosin <peda@axentia.se> | 2016-12-17 15:29:11 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2016-12-18 02:54:38 -0500 |
commit | 649ac63a9ae5e08b7123f2fa98c2bf42f033bdb9 (patch) | |
tree | 6e571792c6101cbe1d59f52db24e4f6562b21826 | |
parent | 8e598769c55dd6c442a1c6cbd21e7abda2a52215 (diff) |
i2c: mux: mlxcpld: fix i2c mux selection caching
smbus functions return -ve on error, 0 on success. However,
__i2c_transfer() have a different return signature - -ve on error, or
number of buffers transferred (which may be zero or greater).
The upshot of this is that the sense of the test is reversed when using
the mux on a bus supporting the master_xfer method: we cache the value
and never retry if we fail to transfer any buffers, but if we succeed,
we clear the cached value.
Fix this by making mlxcpld_mux_reg_write() return a -ve error code for
all failure cases, just as was done in commit 7f638c1cb0a1 ("i2c: mux:
pca954x: fix i2c mux selection caching").
This also aligns the implementations of these two muxes in this area.
Signed-off-by: Peter Rosin <peda@axentia.se>
Acked-by: Vadim Pasternak <vadimp@mellanox.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-mlxcpld.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c index 3ab654bbfab5..b7ca249ec9c3 100644 --- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c | |||
@@ -95,6 +95,7 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, | |||
95 | struct i2c_client *client, u8 val) | 95 | struct i2c_client *client, u8 val) |
96 | { | 96 | { |
97 | struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); | 97 | struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); |
98 | int ret = -ENODEV; | ||
98 | 99 | ||
99 | if (adap->algo->master_xfer) { | 100 | if (adap->algo->master_xfer) { |
100 | struct i2c_msg msg; | 101 | struct i2c_msg msg; |
@@ -104,17 +105,21 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, | |||
104 | msg.flags = 0; | 105 | msg.flags = 0; |
105 | msg.len = 2; | 106 | msg.len = 2; |
106 | msg.buf = msgbuf; | 107 | msg.buf = msgbuf; |
107 | return __i2c_transfer(adap, &msg, 1); | 108 | ret = __i2c_transfer(adap, &msg, 1); |
109 | |||
110 | if (ret >= 0 && ret != 1) | ||
111 | ret = -EREMOTEIO; | ||
108 | } else if (adap->algo->smbus_xfer) { | 112 | } else if (adap->algo->smbus_xfer) { |
109 | union i2c_smbus_data data; | 113 | union i2c_smbus_data data; |
110 | 114 | ||
111 | data.byte = val; | 115 | data.byte = val; |
112 | return adap->algo->smbus_xfer(adap, client->addr, | 116 | ret = adap->algo->smbus_xfer(adap, client->addr, |
113 | client->flags, I2C_SMBUS_WRITE, | 117 | client->flags, I2C_SMBUS_WRITE, |
114 | pdata->sel_reg_addr, | 118 | pdata->sel_reg_addr, |
115 | I2C_SMBUS_BYTE_DATA, &data); | 119 | I2C_SMBUS_BYTE_DATA, &data); |
116 | } else | 120 | } |
117 | return -ENODEV; | 121 | |
122 | return ret; | ||
118 | } | 123 | } |
119 | 124 | ||
120 | static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) | 125 | static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) |
@@ -127,10 +132,7 @@ static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) | |||
127 | /* Only select the channel if its different from the last channel */ | 132 | /* Only select the channel if its different from the last channel */ |
128 | if (data->last_chan != regval) { | 133 | if (data->last_chan != regval) { |
129 | err = mlxcpld_mux_reg_write(muxc->parent, client, regval); | 134 | err = mlxcpld_mux_reg_write(muxc->parent, client, regval); |
130 | if (err) | 135 | data->last_chan = err < 0 ? 0 : regval; |
131 | data->last_chan = 0; | ||
132 | else | ||
133 | data->last_chan = regval; | ||
134 | } | 136 | } |
135 | 137 | ||
136 | return err; | 138 | return err; |