diff options
-rw-r--r-- | Documentation/IPMI.txt | 13 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_poweroff.c | 132 | ||||
-rw-r--r-- | include/linux/sysctl.h | 6 |
3 files changed, 71 insertions, 80 deletions
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index 84d3d4d10c17..bf1cf98d2a27 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt | |||
@@ -605,12 +605,13 @@ is in the ipmi_poweroff module. When the system requests a powerdown, | |||
605 | it will send the proper IPMI commands to do this. This is supported on | 605 | it will send the proper IPMI commands to do this. This is supported on |
606 | several platforms. | 606 | several platforms. |
607 | 607 | ||
608 | There is a module parameter named "poweroff_control" that may either be zero | 608 | There is a module parameter named "poweroff_powercycle" that may |
609 | (do a power down) or 2 (do a power cycle, power the system off, then power | 609 | either be zero (do a power down) or non-zero (do a power cycle, power |
610 | it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do | 610 | the system off, then power it on in a few seconds). Setting |
611 | the same thing on the kernel command line. The parameter is also available | 611 | ipmi_poweroff.poweroff_control=x will do the same thing on the kernel |
612 | via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the | 612 | command line. The parameter is also available via the proc filesystem |
613 | system does not support power cycling, it will always to the power off. | 613 | in /proc/sys/dev/ipmi/poweroff_powercycle. Note that if the system |
614 | does not support power cycling, it will always do the power off. | ||
614 | 615 | ||
615 | Note that if you have ACPI enabled, the system will prefer using ACPI to | 616 | Note that if you have ACPI enabled, the system will prefer using ACPI to |
616 | power off. | 617 | power off. |
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 */ |
55 | static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 55 | static 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 */ |
58 | module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); | 58 | module_param(poweroff_powercycle, int, 0); |
59 | MODULE_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."); | 59 | MODULE_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. */ |
62 | static unsigned int mfg_id; | 62 | static 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> |
565 | static int proc_read_chassctrl(char *page, char **start, off_t off, int count, | 562 | |
566 | int *eof, void *data) | 563 | static 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 */ | 573 | static ctl_table ipmi_dir_table[] = { |
573 | static 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; | 581 | static 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 | |||
589 | static 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 | */ |
602 | static int ipmi_poweroff_init (void) | 595 | static 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); |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index e82be96d4906..532a6c5c24e9 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -711,6 +711,7 @@ enum { | |||
711 | DEV_RAID=4, | 711 | DEV_RAID=4, |
712 | DEV_MAC_HID=5, | 712 | DEV_MAC_HID=5, |
713 | DEV_SCSI=6, | 713 | DEV_SCSI=6, |
714 | DEV_IPMI=7, | ||
714 | }; | 715 | }; |
715 | 716 | ||
716 | /* /proc/sys/dev/cdrom */ | 717 | /* /proc/sys/dev/cdrom */ |
@@ -776,6 +777,11 @@ enum { | |||
776 | DEV_SCSI_LOGGING_LEVEL=1, | 777 | DEV_SCSI_LOGGING_LEVEL=1, |
777 | }; | 778 | }; |
778 | 779 | ||
780 | /* /proc/sys/dev/ipmi */ | ||
781 | enum { | ||
782 | DEV_IPMI_POWEROFF_POWERCYCLE=1, | ||
783 | }; | ||
784 | |||
779 | /* /proc/sys/abi */ | 785 | /* /proc/sys/abi */ |
780 | enum | 786 | enum |
781 | { | 787 | { |