+static int set_param_int(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ int l;
+ int rv = 0;
+
+ if (!val)
+ return -EINVAL;
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val)
+ return -EINVAL;
+
+ down_read(®ister_sem);
+ *((int *)kp->arg) = l;
+ if (watchdog_user)
+ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+ up_read(®ister_sem);
+
+ return rv;
+}
+
+static int get_param_int(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, "%i", *((int *)kp->arg));
+}
+
+typedef int (*action_fn)(const char *intval, char *outval);
+
+static int action_op(const char *inval, char *outval);
+static int preaction_op(const char *inval, char *outval);
+static int preop_op(const char *inval, char *outval);
+static void check_parms(void);
+
+static int set_param_str(const char *val, struct kernel_param *kp)
+{
+ action_fn fn = (action_fn) kp->arg;
+ int rv = 0;
+ const char *end;
+ char valcp[16];
+ int len;
+
+ /* Truncate leading and trailing spaces. */
+ while (isspace(*val))
+ val++;
+ end = val + strlen(val) - 1;
+ while ((end >= val) && isspace(*end))
+ end--;
+ len = end - val + 1;
+ if (len > sizeof(valcp) - 1)
+ return -EINVAL;
+ memcpy(valcp, val, len);
+ valcp[len] = '\0';
+
+ down_read(®ister_sem);
+ rv = fn(valcp, NULL);
+ if (rv)
+ goto out_unlock;
+
+ check_parms();
+ if (watchdog_user)
+ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+
+ out_unlock:
+ up_read(®ister_sem);
+ return rv;
+}
+
+static int get_param_str(char *buffer, struct kernel_param *kp)
+{
+ action_fn fn = (action_fn) kp->arg;
+ int rv;
+
+ rv = fn(NULL, buffer);
+ if (rv)
+ return rv;
+ return strlen(buffer);
+}
+
+module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644);