aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_watchdog.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ipmi/ipmi_watchdog.c')
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c259
1 files changed, 205 insertions, 54 deletions
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 2da64bf7469c..1f3159eb1ede 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -47,6 +47,9 @@
47#include <linux/reboot.h> 47#include <linux/reboot.h>
48#include <linux/wait.h> 48#include <linux/wait.h>
49#include <linux/poll.h> 49#include <linux/poll.h>
50#include <linux/string.h>
51#include <linux/ctype.h>
52#include <asm/atomic.h>
50#ifdef CONFIG_X86_LOCAL_APIC 53#ifdef CONFIG_X86_LOCAL_APIC
51#include <asm/apic.h> 54#include <asm/apic.h>
52#endif 55#endif
@@ -158,27 +161,120 @@ static struct fasync_struct *fasync_q = NULL;
158static char pretimeout_since_last_heartbeat = 0; 161static char pretimeout_since_last_heartbeat = 0;
159static char expect_close; 162static char expect_close;
160 163
164static DECLARE_RWSEM(register_sem);
165
166/* Parameters to ipmi_set_timeout */
167#define IPMI_SET_TIMEOUT_NO_HB 0
168#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
169#define IPMI_SET_TIMEOUT_FORCE_HB 2
170
171static int ipmi_set_timeout(int do_heartbeat);
172
161/* If true, the driver will start running as soon as it is configured 173/* If true, the driver will start running as soon as it is configured
162 and ready. */ 174 and ready. */
163static int start_now = 0; 175static int start_now = 0;
164 176
165module_param(timeout, int, 0); 177static int set_param_int(const char *val, struct kernel_param *kp)
178{
179 char *endp;
180 int l;
181 int rv = 0;
182
183 if (!val)
184 return -EINVAL;
185 l = simple_strtoul(val, &endp, 0);
186 if (endp == val)
187 return -EINVAL;
188
189 down_read(&register_sem);
190 *((int *)kp->arg) = l;
191 if (watchdog_user)
192 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
193 up_read(&register_sem);
194
195 return rv;
196}
197
198static int get_param_int(char *buffer, struct kernel_param *kp)
199{
200 return sprintf(buffer, "%i", *((int *)kp->arg));
201}
202
203typedef int (*action_fn)(const char *intval, char *outval);
204
205static int action_op(const char *inval, char *outval);
206static int preaction_op(const char *inval, char *outval);
207static int preop_op(const char *inval, char *outval);
208static void check_parms(void);
209
210static int set_param_str(const char *val, struct kernel_param *kp)
211{
212 action_fn fn = (action_fn) kp->arg;
213 int rv = 0;
214 const char *end;
215 char valcp[16];
216 int len;
217
218 /* Truncate leading and trailing spaces. */
219 while (isspace(*val))
220 val++;
221 end = val + strlen(val) - 1;
222 while ((end >= val) && isspace(*end))
223 end--;
224 len = end - val + 1;
225 if (len > sizeof(valcp) - 1)
226 return -EINVAL;
227 memcpy(valcp, val, len);
228 valcp[len] = '\0';
229
230 down_read(&register_sem);
231 rv = fn(valcp, NULL);
232 if (rv)
233 goto out_unlock;
234
235 check_parms();
236 if (watchdog_user)
237 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
238
239 out_unlock:
240 up_read(&register_sem);
241 return rv;
242}
243
244static int get_param_str(char *buffer, struct kernel_param *kp)
245{
246 action_fn fn = (action_fn) kp->arg;
247 int rv;
248
249 rv = fn(NULL, buffer);
250 if (rv)
251 return rv;
252 return strlen(buffer);
253}
254
255module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644);
166MODULE_PARM_DESC(timeout, "Timeout value in seconds."); 256MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
167module_param(pretimeout, int, 0); 257
258module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644);
168MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); 259MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
169module_param_string(action, action, sizeof(action), 0); 260
261module_param_call(action, set_param_str, get_param_str, action_op, 0644);
170MODULE_PARM_DESC(action, "Timeout action. One of: " 262MODULE_PARM_DESC(action, "Timeout action. One of: "
171 "reset, none, power_cycle, power_off."); 263 "reset, none, power_cycle, power_off.");
172module_param_string(preaction, preaction, sizeof(preaction), 0); 264
265module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644);
173MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " 266MODULE_PARM_DESC(preaction, "Pretimeout action. One of: "
174 "pre_none, pre_smi, pre_nmi, pre_int."); 267 "pre_none, pre_smi, pre_nmi, pre_int.");
175module_param_string(preop, preop, sizeof(preop), 0); 268
269module_param_call(preop, set_param_str, get_param_str, preop_op, 0644);
176MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " 270MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: "
177 "preop_none, preop_panic, preop_give_data."); 271 "preop_none, preop_panic, preop_give_data.");
272
178module_param(start_now, int, 0); 273module_param(start_now, int, 0);
179MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" 274MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
180 "soon as the driver is loaded."); 275 "soon as the driver is loaded.");
181module_param(nowayout, int, 0); 276
277module_param(nowayout, int, 0644);
182MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 278MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
183 279
184/* Default state of the timer. */ 280/* Default state of the timer. */
@@ -200,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0;
200static unsigned char ipmi_version_major; 296static unsigned char ipmi_version_major;
201static unsigned char ipmi_version_minor; 297static unsigned char ipmi_version_minor;
202 298
299/* If a pretimeout occurs, this is used to allow only one panic to happen. */
300static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
203 301
204static int ipmi_heartbeat(void); 302static int ipmi_heartbeat(void);
205static void panic_halt_ipmi_heartbeat(void); 303static void panic_halt_ipmi_heartbeat(void);
@@ -294,11 +392,6 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
294 return rv; 392 return rv;
295} 393}
296 394
297/* Parameters to ipmi_set_timeout */
298#define IPMI_SET_TIMEOUT_NO_HB 0
299#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
300#define IPMI_SET_TIMEOUT_FORCE_HB 2
301
302static int ipmi_set_timeout(int do_heartbeat) 395static int ipmi_set_timeout(int do_heartbeat)
303{ 396{
304 int send_heartbeat_now; 397 int send_heartbeat_now;
@@ -732,8 +825,6 @@ static struct miscdevice ipmi_wdog_miscdev = {
732 .fops = &ipmi_wdog_fops 825 .fops = &ipmi_wdog_fops
733}; 826};
734 827
735static DECLARE_RWSEM(register_sem);
736
737static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, 828static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
738 void *handler_data) 829 void *handler_data)
739{ 830{
@@ -749,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
749static void ipmi_wdog_pretimeout_handler(void *handler_data) 840static void ipmi_wdog_pretimeout_handler(void *handler_data)
750{ 841{
751 if (preaction_val != WDOG_PRETIMEOUT_NONE) { 842 if (preaction_val != WDOG_PRETIMEOUT_NONE) {
752 if (preop_val == WDOG_PREOP_PANIC) 843 if (preop_val == WDOG_PREOP_PANIC) {
753 panic("Watchdog pre-timeout"); 844 if (atomic_inc_and_test(&preop_panic_excl))
754 else if (preop_val == WDOG_PREOP_GIVE_DATA) { 845 panic("Watchdog pre-timeout");
846 } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
755 spin_lock(&ipmi_read_lock); 847 spin_lock(&ipmi_read_lock);
756 data_to_read = 1; 848 data_to_read = 1;
757 wake_up_interruptible(&read_q); 849 wake_up_interruptible(&read_q);
@@ -825,7 +917,8 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
825 an error and not work unless we re-enable 917 an error and not work unless we re-enable
826 the timer. So do so. */ 918 the timer. So do so. */
827 pretimeout_since_last_heartbeat = 1; 919 pretimeout_since_last_heartbeat = 1;
828 panic(PFX "pre-timeout"); 920 if (atomic_inc_and_test(&preop_panic_excl))
921 panic(PFX "pre-timeout");
829 } 922 }
830 923
831 return NOTIFY_DONE; 924 return NOTIFY_DONE;
@@ -839,6 +932,7 @@ static struct nmi_handler ipmi_nmi_handler =
839 .handler = ipmi_nmi, 932 .handler = ipmi_nmi,
840 .priority = 0, /* Call us last. */ 933 .priority = 0, /* Call us last. */
841}; 934};
935int nmi_handler_registered;
842#endif 936#endif
843 937
844static int wdog_reboot_handler(struct notifier_block *this, 938static int wdog_reboot_handler(struct notifier_block *this,
@@ -921,59 +1015,86 @@ static struct ipmi_smi_watcher smi_watcher =
921 .smi_gone = ipmi_smi_gone 1015 .smi_gone = ipmi_smi_gone
922}; 1016};
923 1017
924static int __init ipmi_wdog_init(void) 1018static int action_op(const char *inval, char *outval)
925{ 1019{
926 int rv; 1020 if (outval)
1021 strcpy(outval, action);
1022
1023 if (!inval)
1024 return 0;
927 1025
928 if (strcmp(action, "reset") == 0) { 1026 if (strcmp(inval, "reset") == 0)
929 action_val = WDOG_TIMEOUT_RESET; 1027 action_val = WDOG_TIMEOUT_RESET;
930 } else if (strcmp(action, "none") == 0) { 1028 else if (strcmp(inval, "none") == 0)
931 action_val = WDOG_TIMEOUT_NONE; 1029 action_val = WDOG_TIMEOUT_NONE;
932 } else if (strcmp(action, "power_cycle") == 0) { 1030 else if (strcmp(inval, "power_cycle") == 0)
933 action_val = WDOG_TIMEOUT_POWER_CYCLE; 1031 action_val = WDOG_TIMEOUT_POWER_CYCLE;
934 } else if (strcmp(action, "power_off") == 0) { 1032 else if (strcmp(inval, "power_off") == 0)
935 action_val = WDOG_TIMEOUT_POWER_DOWN; 1033 action_val = WDOG_TIMEOUT_POWER_DOWN;
936 } else { 1034 else
937 action_val = WDOG_TIMEOUT_RESET; 1035 return -EINVAL;
938 printk(KERN_INFO PFX "Unknown action '%s', defaulting to" 1036 strcpy(action, inval);
939 " reset\n", action); 1037 return 0;
940 } 1038}
1039
1040static int preaction_op(const char *inval, char *outval)
1041{
1042 if (outval)
1043 strcpy(outval, preaction);
941 1044
942 if (strcmp(preaction, "pre_none") == 0) { 1045 if (!inval)
1046 return 0;
1047
1048 if (strcmp(inval, "pre_none") == 0)
943 preaction_val = WDOG_PRETIMEOUT_NONE; 1049 preaction_val = WDOG_PRETIMEOUT_NONE;
944 } else if (strcmp(preaction, "pre_smi") == 0) { 1050 else if (strcmp(inval, "pre_smi") == 0)
945 preaction_val = WDOG_PRETIMEOUT_SMI; 1051 preaction_val = WDOG_PRETIMEOUT_SMI;
946#ifdef HAVE_NMI_HANDLER 1052#ifdef HAVE_NMI_HANDLER
947 } else if (strcmp(preaction, "pre_nmi") == 0) { 1053 else if (strcmp(inval, "pre_nmi") == 0)
948 preaction_val = WDOG_PRETIMEOUT_NMI; 1054 preaction_val = WDOG_PRETIMEOUT_NMI;
949#endif 1055#endif
950 } else if (strcmp(preaction, "pre_int") == 0) { 1056 else if (strcmp(inval, "pre_int") == 0)
951 preaction_val = WDOG_PRETIMEOUT_MSG_INT; 1057 preaction_val = WDOG_PRETIMEOUT_MSG_INT;
952 } else { 1058 else
953 preaction_val = WDOG_PRETIMEOUT_NONE; 1059 return -EINVAL;
954 printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to" 1060 strcpy(preaction, inval);
955 " none\n", preaction); 1061 return 0;
956 } 1062}
1063
1064static int preop_op(const char *inval, char *outval)
1065{
1066 if (outval)
1067 strcpy(outval, preop);
957 1068
958 if (strcmp(preop, "preop_none") == 0) { 1069 if (!inval)
1070 return 0;
1071
1072 if (strcmp(inval, "preop_none") == 0)
959 preop_val = WDOG_PREOP_NONE; 1073 preop_val = WDOG_PREOP_NONE;
960 } else if (strcmp(preop, "preop_panic") == 0) { 1074 else if (strcmp(inval, "preop_panic") == 0)
961 preop_val = WDOG_PREOP_PANIC; 1075 preop_val = WDOG_PREOP_PANIC;
962 } else if (strcmp(preop, "preop_give_data") == 0) { 1076 else if (strcmp(inval, "preop_give_data") == 0)
963 preop_val = WDOG_PREOP_GIVE_DATA; 1077 preop_val = WDOG_PREOP_GIVE_DATA;
964 } else { 1078 else
965 preop_val = WDOG_PREOP_NONE; 1079 return -EINVAL;
966 printk(KERN_INFO PFX "Unknown preop '%s', defaulting to" 1080 strcpy(preop, inval);
967 " none\n", preop); 1081 return 0;
968 } 1082}
969 1083
1084static void check_parms(void)
1085{
970#ifdef HAVE_NMI_HANDLER 1086#ifdef HAVE_NMI_HANDLER
1087 int do_nmi = 0;
1088 int rv;
1089
971 if (preaction_val == WDOG_PRETIMEOUT_NMI) { 1090 if (preaction_val == WDOG_PRETIMEOUT_NMI) {
1091 do_nmi = 1;
972 if (preop_val == WDOG_PREOP_GIVE_DATA) { 1092 if (preop_val == WDOG_PREOP_GIVE_DATA) {
973 printk(KERN_WARNING PFX "Pretimeout op is to give data" 1093 printk(KERN_WARNING PFX "Pretimeout op is to give data"
974 " but NMI pretimeout is enabled, setting" 1094 " but NMI pretimeout is enabled, setting"
975 " pretimeout op to none\n"); 1095 " pretimeout op to none\n");
976 preop_val = WDOG_PREOP_NONE; 1096 preop_op("preop_none", NULL);
1097 do_nmi = 0;
977 } 1098 }
978#ifdef CONFIG_X86_LOCAL_APIC 1099#ifdef CONFIG_X86_LOCAL_APIC
979 if (nmi_watchdog == NMI_IO_APIC) { 1100 if (nmi_watchdog == NMI_IO_APIC) {
@@ -983,18 +1104,48 @@ static int __init ipmi_wdog_init(void)
983 " Disabling IPMI nmi pretimeout.\n", 1104 " Disabling IPMI nmi pretimeout.\n",
984 nmi_watchdog); 1105 nmi_watchdog);
985 preaction_val = WDOG_PRETIMEOUT_NONE; 1106 preaction_val = WDOG_PRETIMEOUT_NONE;
986 } else { 1107 do_nmi = 0;
1108 }
987#endif 1109#endif
1110 }
1111 if (do_nmi && !nmi_handler_registered) {
988 rv = request_nmi(&ipmi_nmi_handler); 1112 rv = request_nmi(&ipmi_nmi_handler);
989 if (rv) { 1113 if (rv) {
990 printk(KERN_WARNING PFX "Can't register nmi handler\n"); 1114 printk(KERN_WARNING PFX
991 return rv; 1115 "Can't register nmi handler\n");
992 } 1116 return;
993#ifdef CONFIG_X86_LOCAL_APIC 1117 } else
994 } 1118 nmi_handler_registered = 1;
995#endif 1119 } else if (!do_nmi && nmi_handler_registered) {
1120 release_nmi(&ipmi_nmi_handler);
1121 nmi_handler_registered = 0;
996 } 1122 }
997#endif 1123#endif
1124}
1125
1126static int __init ipmi_wdog_init(void)
1127{
1128 int rv;
1129
1130 if (action_op(action, NULL)) {
1131 action_op("reset", NULL);
1132 printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
1133 " reset\n", action);
1134 }
1135
1136 if (preaction_op(preaction, NULL)) {
1137 preaction_op("pre_none", NULL);
1138 printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
1139 " none\n", preaction);
1140 }
1141
1142 if (preop_op(preop, NULL)) {
1143 preop_op("preop_none", NULL);
1144 printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
1145 " none\n", preop);
1146 }
1147
1148 check_parms();
998 1149
999 rv = ipmi_smi_watcher_register(&smi_watcher); 1150 rv = ipmi_smi_watcher_register(&smi_watcher);
1000 if (rv) { 1151 if (rv) {
@@ -1021,7 +1172,7 @@ static __exit void ipmi_unregister_watchdog(void)
1021 down_write(&register_sem); 1172 down_write(&register_sem);
1022 1173
1023#ifdef HAVE_NMI_HANDLER 1174#ifdef HAVE_NMI_HANDLER
1024 if (preaction_val == WDOG_PRETIMEOUT_NMI) 1175 if (nmi_handler_registered)
1025 release_nmi(&ipmi_nmi_handler); 1176 release_nmi(&ipmi_nmi_handler);
1026#endif 1177#endif
1027 1178