summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJae Hyun Yoo <jae.hyun.yoo@intel.com>2021-07-26 21:13:09 +0300
committerJae Hyun Yoo <jae.hyun.yoo@intel.com>2021-07-26 21:22:43 +0300
commit986843a87f9f2c2e2eaf99f3d8432e00d8751dc7 (patch)
tree6b34b83f7376affdd95a5a17b5e66eab565de017
parent12438d7847e57486a52105f25239fa424275ced5 (diff)
downloadlinux-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.c8
-rw-r--r--drivers/i2c/i2c-mux.c2
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;