diff options
author | Corey Minyard <minyard@acm.org> | 2006-12-06 23:41:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:47 -0500 |
commit | b2c03941b50944a268ee4d5823872f220809a3ba (patch) | |
tree | 9ade96c649031f1eaf20587a2fdf855fe0118f4c /drivers/char/ipmi/ipmi_poweroff.c | |
parent | 759643b874907e76ae81e34df62f41ab6683f5c2 (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.c | 60 |
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 | ||
46 | static void ipmi_po_smi_gone(int if_num); | ||
47 | static 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 */ |
52 | static int poweroff_powercycle; | 55 | static int poweroff_powercycle; |
53 | 56 | ||
57 | /* Which interface to use, -1 means the first we see. */ | ||
58 | static int ifnum_to_use = -1; | ||
59 | |||
60 | /* Our local state. */ | ||
61 | static int ready = 0; | ||
62 | static ipmi_user_t ipmi_user; | ||
63 | static int ipmi_ifnum; | ||
64 | static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; | ||
65 | |||
66 | /* Holds the old poweroff function so we can restore it on removal. */ | ||
67 | static void (*old_poweroff_func)(void); | ||
68 | |||
69 | static 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 | |||
82 | module_param_call(ifnum_to_use, set_param_ifnum, param_get_int, | ||
83 | &ifnum_to_use, 0644); | ||
84 | MODULE_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 */ |
55 | module_param(poweroff_powercycle, int, 0644); | 89 | module_param(poweroff_powercycle, int, 0644); |
56 | MODULE_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."); | 90 | MODULE_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. */ | ||
444 | static int ready = 0; | ||
445 | static ipmi_user_t ipmi_user; | ||
446 | static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; | ||
447 | |||
448 | /* Holds the old poweroff function so we can restore it on removal. */ | ||
449 | static void (*old_poweroff_func)(void); | ||
450 | |||
451 | |||
452 | /* Called on a powerdown request. */ | 477 | /* Called on a powerdown request. */ |
453 | static void ipmi_poweroff_function (void) | 478 | static 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 | ||
542 | static void ipmi_po_smi_gone(int if_num) | 572 | static 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 | ||
549 | static struct ipmi_smi_watcher smi_watcher = | 585 | static struct ipmi_smi_watcher smi_watcher = |