RE: [PATCH 2.6.11.6] Add power cycle to ipmi_poweroff module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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: [email protected]; [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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux