aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_poweroff.c
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2006-12-06 23:41:00 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:47 -0500
commitb2c03941b50944a268ee4d5823872f220809a3ba (patch)
tree9ade96c649031f1eaf20587a2fdf855fe0118f4c /drivers/char/ipmi/ipmi_poweroff.c
parent759643b874907e76ae81e34df62f41ab6683f5c2 (diff)
[PATCH] IPMI: Allow hot system interface remove
This modifies the IPMI driver so that a lower-level interface can be dynamically removed while in use so it can support hot-removal of hardware. It also adds the ability to specify and dynamically change the IPMI interface the watchdog timer and the poweroff code use. Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_poweroff.c')
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 8d941db83457..85f8071be1b5 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -43,6 +43,9 @@
43 43
44#define PFX "IPMI poweroff: " 44#define PFX "IPMI poweroff: "
45 45
46static void ipmi_po_smi_gone(int if_num);
47static void ipmi_po_new_smi(int if_num, struct device *device);
48
46/* Definitions for controlling power off (if the system supports it). It 49/* Definitions for controlling power off (if the system supports it). It
47 * conveniently matches the IPMI chassis control values. */ 50 * conveniently matches the IPMI chassis control values. */
48#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ 51#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */
@@ -51,6 +54,37 @@
51/* the IPMI data command */ 54/* the IPMI data command */
52static int poweroff_powercycle; 55static int poweroff_powercycle;
53 56
57/* Which interface to use, -1 means the first we see. */
58static int ifnum_to_use = -1;
59
60/* Our local state. */
61static int ready = 0;
62static ipmi_user_t ipmi_user;
63static int ipmi_ifnum;
64static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
65
66/* Holds the old poweroff function so we can restore it on removal. */
67static void (*old_poweroff_func)(void);
68
69static int set_param_ifnum(const char *val, struct kernel_param *kp)
70{
71 int rv = param_set_int(val, kp);
72 if (rv)
73 return rv;
74 if ((ifnum_to_use < 0) || (ifnum_to_use == ipmi_ifnum))
75 return 0;
76
77 ipmi_po_smi_gone(ipmi_ifnum);
78 ipmi_po_new_smi(ifnum_to_use, NULL);
79 return 0;
80}
81
82module_param_call(ifnum_to_use, set_param_ifnum, param_get_int,
83 &ifnum_to_use, 0644);
84MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
85 "timer. Setting to -1 defaults to the first registered "
86 "interface");
87
54/* parameter definition to allow user to flag power cycle */ 88/* parameter definition to allow user to flag power cycle */
55module_param(poweroff_powercycle, int, 0644); 89module_param(poweroff_powercycle, int, 0644);
56MODULE_PARM_DESC(poweroff_powercycle, " 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."); 90MODULE_PARM_DESC(poweroff_powercycle, " 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.");
@@ -440,15 +474,6 @@ static struct poweroff_function poweroff_functions[] = {
440 / sizeof(struct poweroff_function)) 474 / sizeof(struct poweroff_function))
441 475
442 476
443/* Our local state. */
444static int ready = 0;
445static ipmi_user_t ipmi_user;
446static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
447
448/* Holds the old poweroff function so we can restore it on removal. */
449static void (*old_poweroff_func)(void);
450
451
452/* Called on a powerdown request. */ 477/* Called on a powerdown request. */
453static void ipmi_poweroff_function (void) 478static void ipmi_poweroff_function (void)
454{ 479{
@@ -473,6 +498,9 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
473 if (ready) 498 if (ready)
474 return; 499 return;
475 500
501 if ((ifnum_to_use >= 0) && (ifnum_to_use != if_num))
502 return;
503
476 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, 504 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
477 &ipmi_user); 505 &ipmi_user);
478 if (rv) { 506 if (rv) {
@@ -481,6 +509,8 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
481 return; 509 return;
482 } 510 }
483 511
512 ipmi_ifnum = if_num;
513
484 /* 514 /*
485 * Do a get device ide and store some results, since this is 515 * Do a get device ide and store some results, since this is
486 * used by several functions. 516 * used by several functions.
@@ -541,9 +571,15 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
541 571
542static void ipmi_po_smi_gone(int if_num) 572static void ipmi_po_smi_gone(int if_num)
543{ 573{
544 /* This can never be called, because once poweroff driver is 574 if (!ready)
545 registered, the interface can't go away until the power 575 return;
546 driver is unregistered. */ 576
577 if (ipmi_ifnum != if_num)
578 return;
579
580 ready = 0;
581 ipmi_destroy_user(ipmi_user);
582 pm_power_off = old_poweroff_func;
547} 583}
548 584
549static struct ipmi_smi_watcher smi_watcher = 585static struct ipmi_smi_watcher smi_watcher =