summaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_poweroff.c
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2008-04-29 10:01:02 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 17:06:14 +0200
commitbda4c30aa6f7dc1483f39ea1dfe37bcab8a96207 (patch)
tree760c538139c5b41ef54a27d62e5a8a1b01cf1c60 /drivers/char/ipmi/ipmi_poweroff.c
parentipmi: hold ATTN until upper layer ready (diff)
downloadlinux-bda4c30aa6f7dc1483f39ea1dfe37bcab8a96207.tar.xz
linux-bda4c30aa6f7dc1483f39ea1dfe37bcab8a96207.zip
ipmi: run to completion fixes
The "run_to_completion" mode was somewhat broken. Locks need to be avoided in run_to_completion mode, and it shouldn't be used by normal users, just internally for panic situations. This patch removes locks in run_to_completion mode and removes the user call for setting the mode. The only user was the poweroff code, but it was easily converted to use the polling interface. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Corey Minyard <cminyard@mvista.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_poweroff.c')
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index b86186de7f07..b065a53d1ca8 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -99,11 +99,14 @@ static unsigned char ipmi_version;
allocate them, since we may be in a panic situation. The whole
thing is single-threaded, anyway, so multiple messages are not
required. */
+static atomic_t dummy_count = ATOMIC_INIT(0);
static void dummy_smi_free(struct ipmi_smi_msg *msg)
{
+ atomic_dec(&dummy_count);
}
static void dummy_recv_free(struct ipmi_recv_msg *msg)
{
+ atomic_dec(&dummy_count);
}
static struct ipmi_smi_msg halt_smi_msg =
{
@@ -152,17 +155,28 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
return halt_recv_msg.msg.data[0];
}
-/* We are in run-to-completion mode, no completion is desired. */
+/* Wait for message to complete, spinning. */
static int ipmi_request_in_rc_mode(ipmi_user_t user,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *send_msg)
{
int rv;
+ atomic_set(&dummy_count, 2);
rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
&halt_smi_msg, &halt_recv_msg, 0);
- if (rv)
+ if (rv) {
+ atomic_set(&dummy_count, 0);
return rv;
+ }
+
+ /*
+ * Spin until our message is done.
+ */
+ while (atomic_read(&dummy_count) > 0) {
+ ipmi_poll_interface(user);
+ cpu_relax();
+ }
return halt_recv_msg.msg.data[0];
}
@@ -531,9 +545,7 @@ static void ipmi_poweroff_function (void)
return;
/* Use run-to-completion mode, since interrupts may be off. */
- ipmi_user_set_run_to_completion(ipmi_user, 1);
specific_poweroff_func(ipmi_user);
- ipmi_user_set_run_to_completion(ipmi_user, 0);
}
/* Wait for an IPMI interface to be installed, the first one installed