summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-12-17 12:10:56 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-19 20:18:05 +0100
commit26eae206b78669ec4994d047a4b9418b1c588e35 (patch)
tree75200eb54e7f7f5914eec154a499a216d8f71334 /drivers/i2c
parent396b25173370fc1afa3bc91a315d5597c2b10734 (diff)
i2c: mux: pca954x: fix i2c mux selection caching
commit 7f638c1cb0a1112dbe0b682a42db30521646686b upstream. 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 pca954x_reg_write() return a negative error code for all failure cases. Fixes: 463e8f845cbf ("i2c: mux: pca954x: retry updating the mux selection on failure") Acked-by: Peter Rosin <peda@axentia.se> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 8bc3d36d2837..9c4ac26c014e 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -151,6 +151,9 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
buf[0] = val;
msg.buf = buf;
ret = __i2c_transfer(adap, &msg, 1);
+
+ if (ret >= 0 && ret != 1)
+ ret = -EREMOTEIO;
} else {
union i2c_smbus_data data;
ret = adap->algo->smbus_xfer(adap, client->addr,
@@ -179,7 +182,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
/* Only select the channel if its different from the last channel */
if (data->last_chan != regval) {
ret = pca954x_reg_write(muxc->parent, client, regval);
- data->last_chan = ret ? 0 : regval;
+ data->last_chan = ret < 0 ? 0 : regval;
}
return ret;