The message handler and si are already using /proc/ipmi/<intf_num>. The
patch code simply reuse it. By the way, shouldn't we be using sysfs?

As for separating from power_off, it just seem so simple to integrate
the power cycle command into the power_off code. It could definitely be
a separate module.

Thanks,
-Chris Poblete


-----Original Message-----
From: Corey Minyard [mailto:[EMAIL PROTECTED] 
Sent: Friday, April 08, 2005 10:35 AM
To: Poblete, Chris
Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]
Subject: Re: [PATCH 2.6.11.6] Add power cycle to ipmi_poweroff module

[EMAIL PROTECTED] wrote:

>Below is a patch to add "power cycle" functionality to the IPMI power 
>off module ipmi_poweroff.
>
>A new module param is added to support this:
>parmtype:       do_power_cycle:int
>parm:           do_power_cycle: Set to 1 to enable power cycle instead
>of power down. Power cycle is contingent on hardware support, otherwise

>it defaults back to power down.
>
>This parameter can also be dynamically modified through the proc
>filesystem:
>/proc/ipmi/<interface_num>/poweroff
>  
>
This should probably be /proc/sys/dev/ipmi/power_cycle_on_halt.  Most
things to control a system go there.  The /proc/sys/dev/ipmi directory
should probably be created by the base IPMI file, too.

Thinking about it a little more, this should really be an option for
reset, not for power off (thus making the name power_cycle_on_reset).  
I'm not sure how easy that will be to tie into.  It doesn't look easy;
there's not something like pm_power_off for reset.

All the proc fs stuff should be ifdef-ed appropriately so it will
compile with procfs turned off.

-Corey

>The power cycle action is considered an optional chassis control in the

>IPMI specification.  However, it is definitely useful when the hardware

>supports it.  A power cycle is usually required in order to reset a 
>firmware in a bad state.  This action is critical to allow remote 
>management of servers.
>
>The implementation adds power cycle as optional to the ipmi_poweroff 
>module. It can be modified dynamically through the proc entry mentioned

>above. During a power down and enabled, the power cycle command is sent

>to the BMC firmware. If it fails either due to non-support or some 
>error, it will retry to send the command as power off.
>
>Signed-off-by: Christopher A. Poblete <[EMAIL PROTECTED]>
>
>--
>Chris Poblete
>Software Engineer
>Dell OpenManage Instrumentation
>
>
>===== drivers/char/ipmi/ipmi_poweroff.c linux-2.6.11.6 vi edited =====
>--- linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c.orig
>2005-03-25 21:28:22.000000000 -0600
>+++ linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c   2005-04-07
>18:36:10.656537656 -0500
>@@ -34,6 +34,8 @@
> #include <asm/semaphore.h>
> #include <linux/kdev_t.h>
> #include <linux/module.h>
>+#include <linux/moduleparam.h>
>+#include <linux/proc_fs.h>
> #include <linux/string.h>
> #include <linux/ipmi.h>
> #include <linux/ipmi_smi.h>
>@@ -41,6 +43,13 @@
> #define PFX "IPMI poweroff: "
> #define IPMI_POWEROFF_VERSION "v33"
> 
>+/* container to flag power cycle instead of power down */ static int 
>+do_power_cycle = 0;
>+
>+/* parameter definition to allow user to flag power cycle */ 
>+module_param(do_power_cycle, int, 0); MODULE_PARM_DESC(do_power_cycle,

>+" Set to 1 to enable power cycle
>instead of power down. Power cycle is contingent on hardware support, 
>otherwise it defaults back to power down.");
>+
> /* Where to we insert our poweroff function? */ extern void 
> (*pm_power_off)(void);
> 
>@@ -349,23 +358,37 @@ static void ipmi_poweroff_chassis (ipmi_
>         smi_addr.channel = IPMI_BMC_CHANNEL;
>         smi_addr.lun = 0;
> 
>-      printk(KERN_INFO PFX "Powering down via IPMI chassis control
>command\n");
>+ powercyclefailed:
>+      printk(KERN_INFO PFX "Powering %s via IPMI chassis control
>command\n",
>+              ((do_power_cycle != 1) ? "down" : "cycle"));
> 
>       /*
>        * Power down
>        */
>       send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
>       send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
>-      data[0] = 0; /* Power down */
>+      if (do_power_cycle != 1) {
>+              data[0] = 0; /* Power down */
>+      } else {
>+              data[0] = 2; /* Power cycle */
>+      }
>       send_msg.data = data;
>       send_msg.data_len = sizeof(data);
>       rv = ipmi_request_in_rc_mode(user,
>                                    (struct ipmi_addr *) &smi_addr,
>                                    &send_msg);
>       if (rv) {
>-              printk(KERN_ERR PFX "Unable to send chassis powerdown
>message,"
>-                     " IPMI error 0x%x\n", rv);
>-              goto out;
>+              if (do_power_cycle != 1) {
>+                      printk(KERN_ERR PFX "Unable to send chassis
>power " \
>+                              "down message, IPMI error 0x%x\n", rv);
>+                      goto out;
>+                } else {
>+                      /* power cycle failed, default to power down */
>+                      printk(KERN_ERR PFX "Unable to send chassis
>power " \
>+                              "cycle message, IPMI error 0x%x\n", rv);
>+                      do_power_cycle = 0;
>+                      goto powercyclefailed;
>+                }
>       }
> 
>  out:
>@@ -418,6 +441,110 @@ static void ipmi_poweroff_function (void
>       ipmi_user_set_run_to_completion(ipmi_user, 0);  }
> 
>+/* procfs global memory */
>+static struct proc_dir_entry *proc_ipo_root = NULL; static struct 
>+proc_dir_entry *proc_ipo_dir = NULL; static char ipo_dirname[4];
>+
>+/* displays properties to proc */
>+static int proc_read_do_power_cycle(char *page, char **start,
>+                      off_t off, int count,
>+                      int *eof, void *data)
>+{
>+      /* sanity check */
>+      if (data != NULL) {
>+              return sprintf(page, "do_power_cycle = '%s'\n",
>+                      (*((int *)data) != 0 ? "enabled" : "disabled"));
>+      }
>+
>+      return -EINVAL;
>+}
>+
>+/* process property writes from proc */ static int 
>+proc_write_do_power_cycle(struct file *file,
>+                      const char *buffer,
>+                      unsigned long count,
>+                      void *data)
>+{
>+      int rv = count;
>+      int newval = 0;
>+
>+      /* sanity check */
>+      if ((buffer != NULL) && (data != NULL)) {
>+              sscanf(buffer, "%d", &newval);
>+              if (newval != 0) {
>+                      *((int *)data) = 1;
>+                      printk(KERN_INFO PFX "power cycle is now
>enabled\n");
>+              } else {
>+                      *((int *)data) = 0;
>+                      printk(KERN_INFO PFX "power cycle is now
>disabled\n");
>+              }
>+      }
>+
>+      return rv;
>+}
>+
>+/* removes proc entries */
>+static void ipmi_po_remove_proc_entries(void) {
>+      remove_proc_entry("poweroff", proc_ipo_dir);
>+      if (ipo_dirname[0] != '\0') {
>+              remove_proc_entry(ipo_dirname, proc_ipo_root);
>+              ipo_dirname[0] = '\0';
>+      }
>+      remove_proc_entry("ipmi", NULL);
>+}
>+
>+/* creates proc entries */
>+static int ipmi_po_add_proc_entries(int if_num) {
>+      struct proc_dir_entry *proc_ipo_pc = NULL;
>+      int rv = -ENOMEM;
>+
>+      /* check for unreasonable value, besides buffer has room for
>only 3 */
>+      if ((if_num < 0) || (if_num > 255)) {
>+              printk(KERN_ERR PFX "invalid interface num: %d\n",
>if_num);
>+              goto error1;
>+      }
>+      proc_ipo_root = proc_mkdir("ipmi", NULL);
>+      if (!proc_ipo_root) {
>+              printk(KERN_ERR PFX "failed to create ipmi proc dir\n");
>+              goto error1;
>+      }
>+      proc_ipo_root->owner = THIS_MODULE;
>+      ipo_dirname[0] = '\0';
>+      sprintf(ipo_dirname, "%d", if_num);
>+      if (ipo_dirname[0] == '\0') {
>+              goto error2;
>+      }
>+      proc_ipo_dir = proc_mkdir(ipo_dirname, proc_ipo_root);
>+      if (!proc_ipo_dir) {
>+              printk(KERN_ERR PFX "failed to create ipmi/%d proc
>dir\n", if_num);
>+              goto error2;
>+      }
>+      proc_ipo_dir->owner = THIS_MODULE;
>+      proc_ipo_pc = create_proc_entry("poweroff", 0, proc_ipo_dir);
>+      if (!proc_ipo_pc) {
>+              printk(KERN_ERR PFX "failed to create poweroff proc
>entry\n");
>+              goto error3;
>+      }
>+      proc_ipo_pc->owner = THIS_MODULE;
>+      proc_ipo_pc->data = &do_power_cycle;
>+      proc_ipo_pc->read_proc = proc_read_do_power_cycle;
>+      proc_ipo_pc->write_proc = proc_write_do_power_cycle;
>+
>+      /* success only at this point */
>+      return 0;
>+
>+ error3:
>+      remove_proc_entry(ipo_dirname, proc_ipo_root);
>+ error2:
>+      ipo_dirname[0] = '\0';
>+      remove_proc_entry("ipmi", NULL);
>+ error1:
>+      return rv;
>+}
>+
> /* Wait for an IPMI interface to be installed, the first one installed
>    will be grabbed by this code and used to perform the powerdown. */

>static void ipmi_po_new_smi(int if_num) @@ -430,6 +557,13 @@ static 
>void ipmi_po_new_smi(int if_num)
>       if (ready)
>               return;
> 
>+      /* add procfs entries for setting properties */
>+      rv = ipmi_po_add_proc_entries(if_num);
>+      if (rv) {
>+              printk(KERN_ERR PFX "failed to create procfs
>entries\n");
>+              return;
>+      }
>+
>       rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, 
>&ipmi_user);
>       if (rv) {
>               printk(KERN_ERR PFX "could not create IPMI user, error
%d\n", @@ 
>-520,6 +654,10 @@ static int ipmi_poweroff_init (void)
>               " IPMI Powerdown via sys_reboot version "
>               IPMI_POWEROFF_VERSION ".\n");
> 
>+      if (do_power_cycle == 1) {
>+              printk (KERN_INFO PFX "Power cycle is enabled.\n");
>+      }
>+
>       rv = ipmi_smi_watcher_register(&smi_watcher);
>       if (rv)
>               printk(KERN_ERR PFX "Unable to register SMI watcher:
>%d\n", rv);
>@@ -532,6 +670,7 @@ static __exit void ipmi_poweroff_cleanup  {
>       int rv;
> 
>+      ipmi_po_remove_proc_entries();
>       ipmi_smi_watcher_unregister(&smi_watcher);
> 
>       if (ready) {
>  
>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to