Skip to content

Commit decfa49

Browse files
marsyang1206OpenEmbedded
authored andcommitted
Use mutex_trylock for i2c adapter or MUX lock.
Problem: There're multiple requests and the first request acquires the kernel mutex lock and the 2nd request will be blocked by this mutex. mctp-demux-daemon will be blocked, too and can't process any further requests and responses. This is a deadlock problem. mctp-demux-daemon will be unblocked until kernel timeout handler happened. Changes: Use mutex_trylock and return EIO if the lock is acquired. Tested: check if MCTP requests or responses of NVNe/BF3 are handled successfully. check RF storage APIs. Fixes jira https://jirasw.nvidia.com/browse/DGXOPENBMC-13845 Signed-off-by: MarsYang <[email protected]>
1 parent c504d19 commit decfa49

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

drivers/i2c/i2c-core-base.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,10 +1503,16 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
15031503
}
15041504
EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
15051505

1506-
static void i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout)
1506+
static int i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout)
15071507
{
1508-
mutex_lock(&adapter->hold_lock);
1508+
int ret;
1509+
ret = mutex_trylock(&adapter->hold_lock);
1510+
if (ret == 0) {
1511+
return 0;
1512+
}
1513+
15091514
schedule_delayed_work(&adapter->unhold_work, timeout);
1515+
return 1;
15101516
}
15111517

15121518
static void i2c_adapter_unhold(struct i2c_adapter *adapter)
@@ -1521,6 +1527,7 @@ static void i2c_adapter_unhold_work(struct work_struct *work)
15211527
struct i2c_adapter *adapter = container_of(dwork, struct i2c_adapter,
15221528
unhold_work);
15231529

1530+
printk("[%d]i2c adapter lock timeout", adapter->nr);
15241531
mutex_unlock(&adapter->hold_lock);
15251532
}
15261533

@@ -2271,15 +2278,19 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
22712278
(u16 *)msgs[num - 1].buf);
22722279
if (hold_msg == I2C_HOLD_MSG_SET) {
22732280
timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
2274-
i2c_adapter_hold(adap, timeout);
2281+
if (i2c_adapter_hold(adap, timeout) == 0) {
2282+
return -EIO;
2283+
}
22752284

22762285
if (--num == 0)
22772286
return 0;
22782287
} else if (hold_msg == I2C_HOLD_MSG_RESET) {
22792288
i2c_adapter_unhold(adap);
22802289
return 0;
22812290
} else if (hold_msg == I2C_HOLD_MSG_NONE) {
2282-
mutex_lock(&adap->hold_lock);
2291+
if (mutex_trylock(&adap->hold_lock) == 0) {
2292+
return -EIO;
2293+
}
22832294
}
22842295
}
22852296

drivers/i2c/i2c-mux.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ struct i2c_mux_priv {
3636
u32 chan_id;
3737
};
3838

39-
static void i2c_mux_hold(struct i2c_mux_core *muxc, u32 chan_id,
39+
static int i2c_mux_hold(struct i2c_mux_core *muxc, u32 chan_id,
4040
unsigned long timeout)
4141
{
42-
mutex_lock(&muxc->hold_lock);
42+
int ret;
43+
ret = mutex_trylock(&muxc->hold_lock);
44+
if(!ret)
45+
return 0;
46+
4347
muxc->holder_chan_id = chan_id;
4448
schedule_delayed_work(&muxc->unhold_work, timeout);
49+
return 1;
4550
}
4651

4752
static void i2c_mux_unhold(struct i2c_mux_core *muxc)
@@ -56,6 +61,8 @@ static void i2c_mux_unhold_work(struct work_struct *work)
5661
struct i2c_mux_core *muxc = container_of(dwork, struct i2c_mux_core,
5762
unhold_work);
5863

64+
printk("[%d]i2c mux timeout - chnl:%d",
65+
muxc->parent->nr,muxc->holder_chan_id);
5966
if (muxc->deselect)
6067
muxc->deselect(muxc, muxc->holder_chan_id);
6168

@@ -77,11 +84,16 @@ static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
7784
hold_msg = i2c_check_hold_msg(msgs[num - 1].flags,
7885
msgs[num - 1].len,
7986
(u16 *)msgs[num - 1].buf);
87+
8088
if (hold_msg == I2C_HOLD_MSG_SET) {
8189
timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
82-
i2c_mux_hold(muxc, priv->chan_id, timeout);
90+
if(i2c_mux_hold(muxc, priv->chan_id, timeout) == 0) {
91+
return -EIO;
92+
}
8393
} else if (hold_msg == I2C_HOLD_MSG_NONE) {
84-
mutex_lock(&muxc->hold_lock);
94+
if (mutex_trylock(&muxc->hold_lock) == 0) {
95+
return -EIO;
96+
}
8597
}
8698
ret = muxc->select(muxc, priv->chan_id);
8799
if (ret >= 0)
@@ -115,11 +127,16 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
115127
hold_msg = i2c_check_hold_msg(msgs[num - 1].flags,
116128
msgs[num - 1].len,
117129
(u16 *)msgs[num - 1].buf);
130+
118131
if (hold_msg == I2C_HOLD_MSG_SET) {
119132
timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
120-
i2c_mux_hold(muxc, priv->chan_id, timeout);
133+
if (i2c_mux_hold(muxc, priv->chan_id, timeout) == 0) {
134+
return -EIO;
135+
}
121136
} else if (hold_msg == I2C_HOLD_MSG_NONE) {
122-
mutex_lock(&muxc->hold_lock);
137+
if (mutex_trylock(&muxc->hold_lock) == 0) {
138+
return -EIO;
139+
}
123140
}
124141
ret = muxc->select(muxc, priv->chan_id);
125142
if (ret >= 0)
@@ -153,11 +170,16 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
153170
hold_msg = i2c_check_hold_msg(flags,
154171
size == I2C_SMBUS_WORD_DATA ? 2 : 0,
155172
&data->word);
173+
156174
if (hold_msg == I2C_HOLD_MSG_SET) {
157175
timeout = msecs_to_jiffies(data->word);
158-
i2c_mux_hold(muxc, priv->chan_id, timeout);
176+
if (i2c_mux_hold(muxc, priv->chan_id, timeout) == 0) {
177+
return -EIO;
178+
}
159179
} else if (hold_msg == I2C_HOLD_MSG_NONE) {
160-
mutex_lock(&muxc->hold_lock);
180+
if (mutex_trylock(&muxc->hold_lock) == 0) {
181+
return -EIO;
182+
}
161183
}
162184
ret = muxc->select(muxc, priv->chan_id);
163185
if (ret >= 0)
@@ -194,9 +216,13 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
194216
&data->word);
195217
if (hold_msg == I2C_HOLD_MSG_SET) {
196218
timeout = msecs_to_jiffies(data->word);
197-
i2c_mux_hold(muxc, priv->chan_id, timeout);
219+
if (i2c_mux_hold(muxc, priv->chan_id, timeout) == 0) {
220+
return -EAGAIN;
221+
}
198222
} else if (hold_msg == I2C_HOLD_MSG_NONE) {
199-
mutex_lock(&muxc->hold_lock);
223+
if (mutex_trylock(&muxc->hold_lock) == 0) {
224+
return -EAGAIN;
225+
}
200226
}
201227
ret = muxc->select(muxc, priv->chan_id);
202228
if (ret >= 0)

0 commit comments

Comments
 (0)