diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_poweroff.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_poweroff.c | 20 |
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; | |||
99 | allocate them, since we may be in a panic situation. The whole | 99 | allocate them, since we may be in a panic situation. The whole |
100 | thing is single-threaded, anyway, so multiple messages are not | 100 | thing is single-threaded, anyway, so multiple messages are not |
101 | required. */ | 101 | required. */ |
102 | static atomic_t dummy_count = ATOMIC_INIT(0); | ||
102 | static void dummy_smi_free(struct ipmi_smi_msg *msg) | 103 | static void dummy_smi_free(struct ipmi_smi_msg *msg) |
103 | { | 104 | { |
105 | atomic_dec(&dummy_count); | ||
104 | } | 106 | } |
105 | static void dummy_recv_free(struct ipmi_recv_msg *msg) | 107 | static void dummy_recv_free(struct ipmi_recv_msg *msg) |
106 | { | 108 | { |
109 | atomic_dec(&dummy_count); | ||
107 | } | 110 | } |
108 | static struct ipmi_smi_msg halt_smi_msg = | 111 | static struct ipmi_smi_msg halt_smi_msg = |
109 | { | 112 | { |
@@ -152,17 +155,28 @@ static int ipmi_request_wait_for_response(ipmi_user_t user, | |||
152 | return halt_recv_msg.msg.data[0]; | 155 | return halt_recv_msg.msg.data[0]; |
153 | } | 156 | } |
154 | 157 | ||
155 | /* We are in run-to-completion mode, no completion is desired. */ | 158 | /* Wait for message to complete, spinning. */ |
156 | static int ipmi_request_in_rc_mode(ipmi_user_t user, | 159 | static int ipmi_request_in_rc_mode(ipmi_user_t user, |
157 | struct ipmi_addr *addr, | 160 | struct ipmi_addr *addr, |
158 | struct kernel_ipmi_msg *send_msg) | 161 | struct kernel_ipmi_msg *send_msg) |
159 | { | 162 | { |
160 | int rv; | 163 | int rv; |
161 | 164 | ||
165 | atomic_set(&dummy_count, 2); | ||
162 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, | 166 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, |
163 | &halt_smi_msg, &halt_recv_msg, 0); | 167 | &halt_smi_msg, &halt_recv_msg, 0); |
164 | if (rv) | 168 | if (rv) { |
169 | atomic_set(&dummy_count, 0); | ||
165 | return rv; | 170 | return rv; |
171 | } | ||
172 | |||
173 | /* | ||
174 | * Spin until our message is done. | ||
175 | */ | ||
176 | while (atomic_read(&dummy_count) > 0) { | ||
177 | ipmi_poll_interface(user); | ||
178 | cpu_relax(); | ||
179 | } | ||
166 | 180 | ||
167 | return halt_recv_msg.msg.data[0]; | 181 | return halt_recv_msg.msg.data[0]; |
168 | } | 182 | } |
@@ -531,9 +545,7 @@ static void ipmi_poweroff_function (void) | |||
531 | return; | 545 | return; |
532 | 546 | ||
533 | /* Use run-to-completion mode, since interrupts may be off. */ | 547 | /* Use run-to-completion mode, since interrupts may be off. */ |
534 | ipmi_user_set_run_to_completion(ipmi_user, 1); | ||
535 | specific_poweroff_func(ipmi_user); | 548 | specific_poweroff_func(ipmi_user); |
536 | ipmi_user_set_run_to_completion(ipmi_user, 0); | ||
537 | } | 549 | } |
538 | 550 | ||
539 | /* Wait for an IPMI interface to be installed, the first one installed | 551 | /* Wait for an IPMI interface to be installed, the first one installed |