diff options
Diffstat (limited to 'drivers/xen/manage.c')
-rw-r--r-- | drivers/xen/manage.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index e12bd3635f83..26e5e8507f03 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -168,7 +168,9 @@ out: | |||
168 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ | 168 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
169 | 169 | ||
170 | struct shutdown_handler { | 170 | struct shutdown_handler { |
171 | const char *command; | 171 | #define SHUTDOWN_CMD_SIZE 11 |
172 | const char command[SHUTDOWN_CMD_SIZE]; | ||
173 | bool flag; | ||
172 | void (*cb)(void); | 174 | void (*cb)(void); |
173 | }; | 175 | }; |
174 | 176 | ||
@@ -206,22 +208,22 @@ static void do_reboot(void) | |||
206 | ctrl_alt_del(); | 208 | ctrl_alt_del(); |
207 | } | 209 | } |
208 | 210 | ||
211 | static struct shutdown_handler shutdown_handlers[] = { | ||
212 | { "poweroff", true, do_poweroff }, | ||
213 | { "halt", false, do_poweroff }, | ||
214 | { "reboot", true, do_reboot }, | ||
215 | #ifdef CONFIG_HIBERNATE_CALLBACKS | ||
216 | { "suspend", true, do_suspend }, | ||
217 | #endif | ||
218 | }; | ||
219 | |||
209 | static void shutdown_handler(struct xenbus_watch *watch, | 220 | static void shutdown_handler(struct xenbus_watch *watch, |
210 | const char **vec, unsigned int len) | 221 | const char **vec, unsigned int len) |
211 | { | 222 | { |
212 | char *str; | 223 | char *str; |
213 | struct xenbus_transaction xbt; | 224 | struct xenbus_transaction xbt; |
214 | int err; | 225 | int err; |
215 | static struct shutdown_handler handlers[] = { | 226 | int idx; |
216 | { "poweroff", do_poweroff }, | ||
217 | { "halt", do_poweroff }, | ||
218 | { "reboot", do_reboot }, | ||
219 | #ifdef CONFIG_HIBERNATE_CALLBACKS | ||
220 | { "suspend", do_suspend }, | ||
221 | #endif | ||
222 | {NULL, NULL}, | ||
223 | }; | ||
224 | static struct shutdown_handler *handler; | ||
225 | 227 | ||
226 | if (shutting_down != SHUTDOWN_INVALID) | 228 | if (shutting_down != SHUTDOWN_INVALID) |
227 | return; | 229 | return; |
@@ -238,13 +240,13 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
238 | return; | 240 | return; |
239 | } | 241 | } |
240 | 242 | ||
241 | for (handler = &handlers[0]; handler->command; handler++) { | 243 | for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) { |
242 | if (strcmp(str, handler->command) == 0) | 244 | if (strcmp(str, shutdown_handlers[idx].command) == 0) |
243 | break; | 245 | break; |
244 | } | 246 | } |
245 | 247 | ||
246 | /* Only acknowledge commands which we are prepared to handle. */ | 248 | /* Only acknowledge commands which we are prepared to handle. */ |
247 | if (handler->cb) | 249 | if (idx < ARRAY_SIZE(shutdown_handlers)) |
248 | xenbus_write(xbt, "control", "shutdown", ""); | 250 | xenbus_write(xbt, "control", "shutdown", ""); |
249 | 251 | ||
250 | err = xenbus_transaction_end(xbt, 0); | 252 | err = xenbus_transaction_end(xbt, 0); |
@@ -253,8 +255,8 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
253 | goto again; | 255 | goto again; |
254 | } | 256 | } |
255 | 257 | ||
256 | if (handler->cb) { | 258 | if (idx < ARRAY_SIZE(shutdown_handlers)) { |
257 | handler->cb(); | 259 | shutdown_handlers[idx].cb(); |
258 | } else { | 260 | } else { |
259 | pr_info("Ignoring shutdown request: %s\n", str); | 261 | pr_info("Ignoring shutdown request: %s\n", str); |
260 | shutting_down = SHUTDOWN_INVALID; | 262 | shutting_down = SHUTDOWN_INVALID; |
@@ -310,6 +312,9 @@ static struct notifier_block xen_reboot_nb = { | |||
310 | static int setup_shutdown_watcher(void) | 312 | static int setup_shutdown_watcher(void) |
311 | { | 313 | { |
312 | int err; | 314 | int err; |
315 | int idx; | ||
316 | #define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-")) | ||
317 | char node[FEATURE_PATH_SIZE]; | ||
313 | 318 | ||
314 | err = register_xenbus_watch(&shutdown_watch); | 319 | err = register_xenbus_watch(&shutdown_watch); |
315 | if (err) { | 320 | if (err) { |
@@ -326,6 +331,14 @@ static int setup_shutdown_watcher(void) | |||
326 | } | 331 | } |
327 | #endif | 332 | #endif |
328 | 333 | ||
334 | for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) { | ||
335 | if (!shutdown_handlers[idx].flag) | ||
336 | continue; | ||
337 | snprintf(node, FEATURE_PATH_SIZE, "feature-%s", | ||
338 | shutdown_handlers[idx].command); | ||
339 | xenbus_printf(XBT_NIL, "control", node, "%u", 1); | ||
340 | } | ||
341 | |||
329 | return 0; | 342 | return 0; |
330 | } | 343 | } |
331 | 344 | ||