diff options
author | Jae Hyun Yoo <jae.hyun.yoo@intel.com> | 2021-07-26 21:13:09 +0300 |
---|---|---|
committer | Jae Hyun Yoo <jae.hyun.yoo@intel.com> | 2021-07-26 21:22:43 +0300 |
commit | 986843a87f9f2c2e2eaf99f3d8432e00d8751dc7 (patch) | |
tree | 6b34b83f7376affdd95a5a17b5e66eab565de017 | |
parent | 12438d7847e57486a52105f25239fa424275ced5 (diff) | |
download | linux-986843a87f9f2c2e2eaf99f3d8432e00d8751dc7.tar.xz |
fixup! i2c: Add mux hold/unhold msg types
Fixup an unexpected bus holding case caused by a message sending
failure on packet which has a holding message. In case of an error
on sending a message, a bus holding should be immediately released
by itself to prevent a race condition because user space doesn't
send an unhold message when a packet which has hold message fails.
This case was obversed in PLDM stress test which can make intensive
AIC resets so driver was in a severe condition that has lots of
arbitration losses and abnormal stops.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Change-Id: Ibd169c791d0c24f41932ea676d4e187ddbd3e140
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 8 | ||||
-rw-r--r-- | drivers/i2c/i2c-mux.c | 2 |
2 files changed, 8 insertions, 2 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index a46ca6259019..faf2f4fee1e3 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -2118,8 +2118,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) trace_i2c_result(adap, num, ret); } - if (!i2c_parent_is_i2c_adapter(adap) && hold_msg == I2C_HOLD_MSG_NONE) - mutex_unlock(&adap->hold_lock); + if (!i2c_parent_is_i2c_adapter(adap)) { + if (hold_msg == I2C_HOLD_MSG_SET && ret) + i2c_adapter_unhold(adap); + else if (hold_msg == I2C_HOLD_MSG_NONE) + mutex_unlock(&adap->hold_lock); + } return ret; } diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index dc95c40dfc30..554522a6b6e7 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -88,6 +88,8 @@ static int __i2c_mux_master_xfer(struct i2c_adapter *adap, i2c_mux_unhold(muxc); else mutex_unlock(&muxc->hold_lock); + } else if (hold_msg == I2C_HOLD_MSG_SET && ret) { + i2c_mux_unhold(muxc); } return ret; |