Skip to content

Commit 8fd8ea2

Browse files
committed
ipmi:msghandler:Change seq_lock to a mutex
Dan Carpenter got a Smatch warning: drivers/char/ipmi/ipmi_msghandler.c:5265 ipmi_free_recv_msg() warn: sleeping in atomic context due to the recent rework of the IPMI driver's locking. I didn't realize vfree could block. But there is an easy solution to this, now that almost everything in the message handler runs in thread context. I wanted to spend the time earlier to see if seq_lock could be converted from a spinlock to a mutex, but I wanted the previous changes to go in and soak before I did that. So I went ahead and did the analysis and converting should work. And solve this problem. Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/r/202503240244.LR7pOwyr-lkp@intel.com/ Fixes: 3be997d ("ipmi:msghandler: Remove srcu from the ipmi user structure") Cc: <stable@vger.kernel.org> # 6.16 Signed-off-by: Corey Minyard <corey@minyard.net>
1 parent 6e64f45 commit 8fd8ea2

1 file changed

Lines changed: 26 additions & 37 deletions

File tree

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ struct ipmi_smi {
464464
* interface to match them up with their responses. A routine
465465
* is called periodically to time the items in this list.
466466
*/
467-
spinlock_t seq_lock;
467+
struct mutex seq_lock;
468468
struct seq_table seq_table[IPMI_IPMB_NUM_SEQ];
469469
int curr_seq;
470470

@@ -1116,12 +1116,11 @@ static int intf_find_seq(struct ipmi_smi *intf,
11161116
struct ipmi_recv_msg **recv_msg)
11171117
{
11181118
int rv = -ENODEV;
1119-
unsigned long flags;
11201119

11211120
if (seq >= IPMI_IPMB_NUM_SEQ)
11221121
return -EINVAL;
11231122

1124-
spin_lock_irqsave(&intf->seq_lock, flags);
1123+
mutex_lock(&intf->seq_lock);
11251124
if (intf->seq_table[seq].inuse) {
11261125
struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
11271126

@@ -1134,7 +1133,7 @@ static int intf_find_seq(struct ipmi_smi *intf,
11341133
rv = 0;
11351134
}
11361135
}
1137-
spin_unlock_irqrestore(&intf->seq_lock, flags);
1136+
mutex_unlock(&intf->seq_lock);
11381137

11391138
return rv;
11401139
}
@@ -1145,14 +1144,13 @@ static int intf_start_seq_timer(struct ipmi_smi *intf,
11451144
long msgid)
11461145
{
11471146
int rv = -ENODEV;
1148-
unsigned long flags;
11491147
unsigned char seq;
11501148
unsigned long seqid;
11511149

11521150

11531151
GET_SEQ_FROM_MSGID(msgid, seq, seqid);
11541152

1155-
spin_lock_irqsave(&intf->seq_lock, flags);
1153+
mutex_lock(&intf->seq_lock);
11561154
/*
11571155
* We do this verification because the user can be deleted
11581156
* while a message is outstanding.
@@ -1163,7 +1161,7 @@ static int intf_start_seq_timer(struct ipmi_smi *intf,
11631161
ent->timeout = ent->orig_timeout;
11641162
rv = 0;
11651163
}
1166-
spin_unlock_irqrestore(&intf->seq_lock, flags);
1164+
mutex_unlock(&intf->seq_lock);
11671165

11681166
return rv;
11691167
}
@@ -1174,15 +1172,14 @@ static int intf_err_seq(struct ipmi_smi *intf,
11741172
unsigned int err)
11751173
{
11761174
int rv = -ENODEV;
1177-
unsigned long flags;
11781175
unsigned char seq;
11791176
unsigned long seqid;
11801177
struct ipmi_recv_msg *msg = NULL;
11811178

11821179

11831180
GET_SEQ_FROM_MSGID(msgid, seq, seqid);
11841181

1185-
spin_lock_irqsave(&intf->seq_lock, flags);
1182+
mutex_lock(&intf->seq_lock);
11861183
/*
11871184
* We do this verification because the user can be deleted
11881185
* while a message is outstanding.
@@ -1196,7 +1193,7 @@ static int intf_err_seq(struct ipmi_smi *intf,
11961193
msg = ent->recv_msg;
11971194
rv = 0;
11981195
}
1199-
spin_unlock_irqrestore(&intf->seq_lock, flags);
1196+
mutex_unlock(&intf->seq_lock);
12001197

12011198
if (msg)
12021199
deliver_err_response(intf, msg, err);
@@ -1209,7 +1206,6 @@ int ipmi_create_user(unsigned int if_num,
12091206
void *handler_data,
12101207
struct ipmi_user **user)
12111208
{
1212-
unsigned long flags;
12131209
struct ipmi_user *new_user = NULL;
12141210
int rv = 0;
12151211
struct ipmi_smi *intf;
@@ -1277,9 +1273,9 @@ int ipmi_create_user(unsigned int if_num,
12771273
new_user->gets_events = false;
12781274

12791275
mutex_lock(&intf->users_mutex);
1280-
spin_lock_irqsave(&intf->seq_lock, flags);
1276+
mutex_lock(&intf->seq_lock);
12811277
list_add(&new_user->link, &intf->users);
1282-
spin_unlock_irqrestore(&intf->seq_lock, flags);
1278+
mutex_unlock(&intf->seq_lock);
12831279
mutex_unlock(&intf->users_mutex);
12841280

12851281
if (handler->ipmi_watchdog_pretimeout)
@@ -1325,7 +1321,6 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13251321
{
13261322
struct ipmi_smi *intf = user->intf;
13271323
int i;
1328-
unsigned long flags;
13291324
struct cmd_rcvr *rcvr;
13301325
struct cmd_rcvr *rcvrs = NULL;
13311326
struct ipmi_recv_msg *msg, *msg2;
@@ -1346,7 +1341,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13461341
list_del(&user->link);
13471342
atomic_dec(&intf->nr_users);
13481343

1349-
spin_lock_irqsave(&intf->seq_lock, flags);
1344+
mutex_lock(&intf->seq_lock);
13501345
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
13511346
if (intf->seq_table[i].inuse
13521347
&& (intf->seq_table[i].recv_msg->user == user)) {
@@ -1355,7 +1350,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13551350
ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
13561351
}
13571352
}
1358-
spin_unlock_irqrestore(&intf->seq_lock, flags);
1353+
mutex_unlock(&intf->seq_lock);
13591354

13601355
/*
13611356
* Remove the user from the command receiver's table. First
@@ -2026,10 +2021,7 @@ static int i_ipmi_req_ipmb(struct ipmi_smi *intf,
20262021
*/
20272022
smi_msg->user_data = recv_msg;
20282023
} else {
2029-
/* It's a command, so get a sequence for it. */
2030-
unsigned long flags;
2031-
2032-
spin_lock_irqsave(&intf->seq_lock, flags);
2024+
mutex_lock(&intf->seq_lock);
20332025

20342026
if (is_maintenance_mode_cmd(msg))
20352027
intf->ipmb_maintenance_mode_timeout =
@@ -2087,7 +2079,7 @@ static int i_ipmi_req_ipmb(struct ipmi_smi *intf,
20872079
* to be correct.
20882080
*/
20892081
out_err:
2090-
spin_unlock_irqrestore(&intf->seq_lock, flags);
2082+
mutex_unlock(&intf->seq_lock);
20912083
}
20922084

20932085
return rv;
@@ -2205,10 +2197,7 @@ static int i_ipmi_req_lan(struct ipmi_smi *intf,
22052197
*/
22062198
smi_msg->user_data = recv_msg;
22072199
} else {
2208-
/* It's a command, so get a sequence for it. */
2209-
unsigned long flags;
2210-
2211-
spin_lock_irqsave(&intf->seq_lock, flags);
2200+
mutex_lock(&intf->seq_lock);
22122201

22132202
/*
22142203
* Create a sequence number with a 1 second
@@ -2257,7 +2246,7 @@ static int i_ipmi_req_lan(struct ipmi_smi *intf,
22572246
* to be correct.
22582247
*/
22592248
out_err:
2260-
spin_unlock_irqrestore(&intf->seq_lock, flags);
2249+
mutex_unlock(&intf->seq_lock);
22612250
}
22622251

22632252
return rv;
@@ -3575,7 +3564,7 @@ int ipmi_add_smi(struct module *owner,
35753564
atomic_set(&intf->nr_users, 0);
35763565
intf->handlers = handlers;
35773566
intf->send_info = send_info;
3578-
spin_lock_init(&intf->seq_lock);
3567+
mutex_init(&intf->seq_lock);
35793568
for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
35803569
intf->seq_table[j].inuse = 0;
35813570
intf->seq_table[j].seqid = 0;
@@ -4529,9 +4518,10 @@ static int handle_one_recv_msg(struct ipmi_smi *intf,
45294518

45304519
if (msg->rsp_size < 2) {
45314520
/* Message is too small to be correct. */
4532-
dev_warn(intf->si_dev,
4533-
"BMC returned too small a message for netfn %x cmd %x, got %d bytes\n",
4534-
(msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size);
4521+
dev_warn_ratelimited(intf->si_dev,
4522+
"BMC returned too small a message for netfn %x cmd %x, got %d bytes\n",
4523+
(msg->data[0] >> 2) | 1,
4524+
msg->data[1], msg->rsp_size);
45354525

45364526
return_unspecified:
45374527
/* Generate an error response for the message. */
@@ -4951,8 +4941,7 @@ smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg,
49514941
static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
49524942
struct list_head *timeouts,
49534943
unsigned long timeout_period,
4954-
int slot, unsigned long *flags,
4955-
bool *need_timer)
4944+
int slot, bool *need_timer)
49564945
{
49574946
struct ipmi_recv_msg *msg;
49584947

@@ -5004,7 +4993,7 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
50044993
return;
50054994
}
50064995

5007-
spin_unlock_irqrestore(&intf->seq_lock, *flags);
4996+
mutex_unlock(&intf->seq_lock);
50084997

50094998
/*
50104999
* Send the new message. We send with a zero
@@ -5025,7 +5014,7 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
50255014
} else
50265015
ipmi_free_smi_msg(smi_msg);
50275016

5028-
spin_lock_irqsave(&intf->seq_lock, *flags);
5017+
mutex_lock(&intf->seq_lock);
50295018
}
50305019
}
50315020

@@ -5052,7 +5041,7 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf,
50525041
* list.
50535042
*/
50545043
INIT_LIST_HEAD(&timeouts);
5055-
spin_lock_irqsave(&intf->seq_lock, flags);
5044+
mutex_lock(&intf->seq_lock);
50565045
if (intf->ipmb_maintenance_mode_timeout) {
50575046
if (intf->ipmb_maintenance_mode_timeout <= timeout_period)
50585047
intf->ipmb_maintenance_mode_timeout = 0;
@@ -5062,8 +5051,8 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf,
50625051
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
50635052
check_msg_timeout(intf, &intf->seq_table[i],
50645053
&timeouts, timeout_period, i,
5065-
&flags, &need_timer);
5066-
spin_unlock_irqrestore(&intf->seq_lock, flags);
5054+
&need_timer);
5055+
mutex_unlock(&intf->seq_lock);
50675056

50685057
list_for_each_entry_safe(msg, msg2, &timeouts, link)
50695058
deliver_err_response(intf, msg, IPMI_TIMEOUT_COMPLETION_CODE);

0 commit comments

Comments
 (0)