Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 2af8997

Browse files
Lv Zhenggregkh
Lv Zheng
authored andcommitted
ACPI / IPMI: Fix atomic context requirement of ipmi_msg_handler()
commit 06a8566 upstream. This patch fixes the issues indicated by the test results that ipmi_msg_handler() is invoked in atomic context. BUG: scheduling while atomic: kipmi0/18933/0x10000100 Modules linked in: ipmi_si acpi_ipmi ... CPU: 3 PID: 18933 Comm: kipmi0 Tainted: G AW 3.10.0-rc7+ #2 Hardware name: QCI QSSC-S4R/QSSC-S4R, BIOS QSSC-S4R.QCI.01.00.0027.070120100606 07/01/2010 ffff8838245eea00 ffff88103fc63c98 ffffffff814c4a1e ffff88103fc63ca8 ffffffff814bfbab ffff88103fc63d28 ffffffff814c73e0 ffff88103933cbd4 0000000000000096 ffff88103fc63ce8 ffff88102f618000 ffff881035c01fd8 Call Trace: <IRQ> [<ffffffff814c4a1e>] dump_stack+0x19/0x1b [<ffffffff814bfbab>] __schedule_bug+0x46/0x54 [<ffffffff814c73e0>] __schedule+0x83/0x59c [<ffffffff81058853>] __cond_resched+0x22/0x2d [<ffffffff814c794b>] _cond_resched+0x14/0x1d [<ffffffff814c6d82>] mutex_lock+0x11/0x32 [<ffffffff8101e1e9>] ? __default_send_IPI_dest_field.constprop.0+0x53/0x58 [<ffffffffa09e3f9c>] ipmi_msg_handler+0x23/0x166 [ipmi_si] [<ffffffff812bf6e4>] deliver_response+0x55/0x5a [<ffffffff812c0fd4>] handle_new_recv_msgs+0xb67/0xc65 [<ffffffff81007ad1>] ? read_tsc+0x9/0x19 [<ffffffff814c8620>] ? _raw_spin_lock_irq+0xa/0xc [<ffffffffa09e1128>] ipmi_thread+0x5c/0x146 [ipmi_si] ... Also Tony Camuso says: We were getting occasional "Scheduling while atomic" call traces during boot on some systems. Problem was first seen on a Cisco C210 but we were able to reproduce it on a Cisco c220m3. Setting CONFIG_LOCKDEP and LOCKDEP_SUPPORT to 'y' exposed a lockdep around tx_msg_lock in acpi_ipmi.c struct acpi_ipmi_device. ================================= [ INFO: inconsistent lock state ] 2.6.32-415.el6.x86_64-debug-splck #1 --------------------------------- inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. ksoftirqd/3/17 [HC0[0]:SC1[1]:HE1:SE0] takes: (&ipmi_device->tx_msg_lock){+.?...}, at: [<ffffffff81337a27>] ipmi_msg_handler+0x71/0x126 {SOFTIRQ-ON-W} state was registered at: [<ffffffff810ba11c>] __lock_acquire+0x63c/0x1570 [<ffffffff810bb0f4>] lock_acquire+0xa4/0x120 [<ffffffff815581cc>] __mutex_lock_common+0x4c/0x400 [<ffffffff815586ea>] mutex_lock_nested+0x4a/0x60 [<ffffffff8133789d>] acpi_ipmi_space_handler+0x11b/0x234 [<ffffffff81321c62>] acpi_ev_address_space_dispatch+0x170/0x1be The fix implemented by this change has been tested by Tony: Tested the patch in a boot loop with lockdep debug enabled and never saw the problem in over 400 reboots. Reported-and-tested-by: Tony Camuso <[email protected]> Signed-off-by: Lv Zheng <[email protected]> Reviewed-by: Huang Ying <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]> Cc: Jonghwan Choi <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 414224f commit 2af8997

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

Diff for: drivers/acpi/acpi_ipmi.c

+14-10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <linux/ipmi.h>
4040
#include <linux/device.h>
4141
#include <linux/pnp.h>
42+
#include <linux/spinlock.h>
4243

4344
MODULE_AUTHOR("Zhao Yakui");
4445
MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
@@ -57,7 +58,7 @@ struct acpi_ipmi_device {
5758
struct list_head head;
5859
/* the IPMI request message list */
5960
struct list_head tx_msg_list;
60-
struct mutex tx_msg_lock;
61+
spinlock_t tx_msg_lock;
6162
acpi_handle handle;
6263
struct pnp_dev *pnp_dev;
6364
ipmi_user_t user_interface;
@@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
147148
struct kernel_ipmi_msg *msg;
148149
struct acpi_ipmi_buffer *buffer;
149150
struct acpi_ipmi_device *device;
151+
unsigned long flags;
150152

151153
msg = &tx_msg->tx_message;
152154
/*
@@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
177179

178180
/* Get the msgid */
179181
device = tx_msg->device;
180-
mutex_lock(&device->tx_msg_lock);
182+
spin_lock_irqsave(&device->tx_msg_lock, flags);
181183
device->curr_msgid++;
182184
tx_msg->tx_msgid = device->curr_msgid;
183-
mutex_unlock(&device->tx_msg_lock);
185+
spin_unlock_irqrestore(&device->tx_msg_lock, flags);
184186
}
185187

186188
static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
@@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
242244
int msg_found = 0;
243245
struct acpi_ipmi_msg *tx_msg;
244246
struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
247+
unsigned long flags;
245248

246249
if (msg->user != ipmi_device->user_interface) {
247250
dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
@@ -250,15 +253,15 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
250253
ipmi_free_recv_msg(msg);
251254
return;
252255
}
253-
mutex_lock(&ipmi_device->tx_msg_lock);
256+
spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
254257
list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
255258
if (msg->msgid == tx_msg->tx_msgid) {
256259
msg_found = 1;
257260
break;
258261
}
259262
}
260263

261-
mutex_unlock(&ipmi_device->tx_msg_lock);
264+
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
262265
if (!msg_found) {
263266
dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
264267
"returned.\n", msg->msgid);
@@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
378381
struct acpi_ipmi_device *ipmi_device = handler_context;
379382
int err, rem_time;
380383
acpi_status status;
384+
unsigned long flags;
381385
/*
382386
* IPMI opregion message.
383387
* IPMI message is firstly written to the BMC and system software
@@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
395399
return AE_NO_MEMORY;
396400

397401
acpi_format_ipmi_msg(tx_msg, address, value);
398-
mutex_lock(&ipmi_device->tx_msg_lock);
402+
spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
399403
list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
400-
mutex_unlock(&ipmi_device->tx_msg_lock);
404+
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
401405
err = ipmi_request_settime(ipmi_device->user_interface,
402406
&tx_msg->addr,
403407
tx_msg->tx_msgid,
@@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
413417
status = AE_OK;
414418

415419
end_label:
416-
mutex_lock(&ipmi_device->tx_msg_lock);
420+
spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
417421
list_del(&tx_msg->head);
418-
mutex_unlock(&ipmi_device->tx_msg_lock);
422+
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
419423
kfree(tx_msg);
420424
return status;
421425
}
@@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
457461

458462
INIT_LIST_HEAD(&ipmi_device->head);
459463

460-
mutex_init(&ipmi_device->tx_msg_lock);
464+
spin_lock_init(&ipmi_device->tx_msg_lock);
461465
INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
462466
ipmi_install_space_handler(ipmi_device);
463467

0 commit comments

Comments
 (0)