aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_poweroff.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ipmi/ipmi_poweroff.c')
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c132
1 files changed, 58 insertions, 74 deletions
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 42ea9843b394..e82a96ba396b 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -52,11 +52,11 @@ extern void (*pm_power_off)(void);
52#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ 52#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
53 53
54/* the IPMI data command */ 54/* the IPMI data command */
55static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; 55static int poweroff_powercycle;
56 56
57/* parameter definition to allow user to flag power cycle */ 57/* parameter definition to allow user to flag power cycle */
58module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); 58module_param(poweroff_powercycle, int, 0);
59MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); 59MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
60 60
61/* Stuff from the get device id command. */ 61/* Stuff from the get device id command. */
62static unsigned int mfg_id; 62static unsigned int mfg_id;
@@ -385,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
385 385
386 powercyclefailed: 386 powercyclefailed:
387 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", 387 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
388 ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); 388 (poweroff_powercycle ? "cycle" : "down"));
389 389
390 /* 390 /*
391 * Power down 391 * Power down
392 */ 392 */
393 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 393 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
394 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 394 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
395 data[0] = poweroff_control; 395 if (poweroff_powercycle)
396 data[0] = IPMI_CHASSIS_POWER_CYCLE;
397 else
398 data[0] = IPMI_CHASSIS_POWER_DOWN;
396 send_msg.data = data; 399 send_msg.data = data;
397 send_msg.data_len = sizeof(data); 400 send_msg.data_len = sizeof(data);
398 rv = ipmi_request_in_rc_mode(user, 401 rv = ipmi_request_in_rc_mode(user,
399 (struct ipmi_addr *) &smi_addr, 402 (struct ipmi_addr *) &smi_addr,
400 &send_msg); 403 &send_msg);
401 if (rv) { 404 if (rv) {
402 switch (poweroff_control) { 405 if (poweroff_powercycle) {
403 case IPMI_CHASSIS_POWER_CYCLE: 406 /* power cycle failed, default to power down */
404 /* power cycle failed, default to power down */ 407 printk(KERN_ERR PFX "Unable to send chassis power " \
405 printk(KERN_ERR PFX "Unable to send chassis power " \ 408 "cycle message, IPMI error 0x%x\n", rv);
406 "cycle message, IPMI error 0x%x\n", rv); 409 poweroff_powercycle = 0;
407 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 410 goto powercyclefailed;
408 goto powercyclefailed;
409
410 case IPMI_CHASSIS_POWER_DOWN:
411 default:
412 printk(KERN_ERR PFX "Unable to send chassis power " \
413 "down message, IPMI error 0x%x\n", rv);
414 break;
415 } 411 }
416 }
417 412
418 return; 413 printk(KERN_ERR PFX "Unable to send chassis power " \
414 "down message, IPMI error 0x%x\n", rv);
415 }
419} 416}
420 417
421 418
@@ -561,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher =
561 558
562 559
563#ifdef CONFIG_PROC_FS 560#ifdef CONFIG_PROC_FS
564/* displays properties to proc */ 561#include <linux/sysctl.h>
565static int proc_read_chassctrl(char *page, char **start, off_t off, int count, 562
566 int *eof, void *data) 563static ctl_table ipmi_table[] = {
567{ 564 { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE,
568 return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", 565 .procname = "poweroff_powercycle",
569 poweroff_control); 566 .data = &poweroff_powercycle,
570} 567 .maxlen = sizeof(poweroff_powercycle),
568 .mode = 0644,
569 .proc_handler = &proc_dointvec },
570 { }
571};
571 572
572/* process property writes from proc */ 573static ctl_table ipmi_dir_table[] = {
573static int proc_write_chassctrl(struct file *file, const char *buffer, 574 { .ctl_name = DEV_IPMI,
574 unsigned long count, void *data) 575 .procname = "ipmi",
575{ 576 .mode = 0555,
576 int rv = count; 577 .child = ipmi_table },
577 unsigned int newval = 0; 578 { }
578 579};
579 sscanf(buffer, "%d", &newval);
580 switch (newval) {
581 case IPMI_CHASSIS_POWER_CYCLE:
582 printk(KERN_INFO PFX "power cycle is now enabled\n");
583 poweroff_control = newval;
584 break;
585
586 case IPMI_CHASSIS_POWER_DOWN:
587 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
588 break;
589
590 default:
591 rv = -EINVAL;
592 break;
593 }
594 580
595 return rv; 581static ctl_table ipmi_root_table[] = {
596} 582 { .ctl_name = CTL_DEV,
583 .procname = "dev",
584 .mode = 0555,
585 .child = ipmi_dir_table },
586 { }
587};
588
589static struct ctl_table_header *ipmi_table_header;
597#endif /* CONFIG_PROC_FS */ 590#endif /* CONFIG_PROC_FS */
598 591
599/* 592/*
@@ -601,41 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer,
601 */ 594 */
602static int ipmi_poweroff_init (void) 595static int ipmi_poweroff_init (void)
603{ 596{
604 int rv; 597 int rv;
605 struct proc_dir_entry *file;
606 598
607 printk ("Copyright (C) 2004 MontaVista Software -" 599 printk ("Copyright (C) 2004 MontaVista Software -"
608 " IPMI Powerdown via sys_reboot.\n"); 600 " IPMI Powerdown via sys_reboot.\n");
609 601
610 switch (poweroff_control) { 602 if (poweroff_powercycle)
611 case IPMI_CHASSIS_POWER_CYCLE: 603 printk(KERN_INFO PFX "Power cycle is enabled.\n");
612 printk(KERN_INFO PFX "Power cycle is enabled.\n");
613 break;
614 604
615 case IPMI_CHASSIS_POWER_DOWN: 605#ifdef CONFIG_PROC_FS
616 default: 606 ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
617 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 607 if (!ipmi_table_header) {
618 break; 608 printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
609 rv = -ENOMEM;
610 goto out_err;
619 } 611 }
612#endif
620 613
614#ifdef CONFIG_PROC_FS
621 rv = ipmi_smi_watcher_register(&smi_watcher); 615 rv = ipmi_smi_watcher_register(&smi_watcher);
616#endif
622 if (rv) { 617 if (rv) {
618 unregister_sysctl_table(ipmi_table_header);
623 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); 619 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
624 goto out_err; 620 goto out_err;
625 } 621 }
626 622
627#ifdef CONFIG_PROC_FS
628 file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
629 if (!file) {
630 printk(KERN_ERR PFX "Unable to create proc power control\n");
631 } else {
632 file->nlink = 1;
633 file->read_proc = proc_read_chassctrl;
634 file->write_proc = proc_write_chassctrl;
635 file->owner = THIS_MODULE;
636 }
637#endif
638
639 out_err: 623 out_err:
640 return rv; 624 return rv;
641} 625}
@@ -646,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void)
646 int rv; 630 int rv;
647 631
648#ifdef CONFIG_PROC_FS 632#ifdef CONFIG_PROC_FS
649 remove_proc_entry("poweroff_control", proc_ipmi_root); 633 unregister_sysctl_table(ipmi_table_header);
650#endif 634#endif
651 635
652 ipmi_smi_watcher_unregister(&smi_watcher); 636 ipmi_smi_watcher_unregister(&smi_watcher);