diff --git a/drivers/watchdog/ipmi_watchdog.c b/drivers/watchdog/ipmi_watchdog.c
index 218c01707c0b..77dbd3851fdc 100644
--- a/drivers/watchdog/ipmi_watchdog.c
+++ b/drivers/watchdog/ipmi_watchdog.c
@@ -80,12 +80,6 @@
 #define WDOG_PRETIMEOUT_NMI		2
 #define WDOG_PRETIMEOUT_MSG_INT		3
 
-/* Operations that can be performed on a pretimout. */
-#define WDOG_PREOP_NONE		0
-#define WDOG_PREOP_PANIC	1
-/* Cause data to be available to read.  Doesn't work in NMI mode. */
-#define WDOG_PREOP_GIVE_DATA	2
-
 /* Actions to perform on a full timeout. */
 #define WDOG_SET_TIMEOUT_ACT(byte, use) \
 	byte = ((byte) & 0xf8) | ((use) & 0x7)
@@ -144,6 +138,7 @@ struct ipmi_wdt {
 	struct ipmi_recv_msg recv_msg;
 
 	int state; /* One of WDOG_TIMEOUT_xxx, NONE if disabled. */
+	int prestate;  /* One of WDOG_PRETIMEOUT_xxx. */
 
 	bool nmi_works;
 
@@ -164,6 +159,8 @@ static int ipmi_set_timeout(struct ipmi_wdt *iwd, int timeout,
 			    int do_heartbeat);
 static int ipmi_set_pretimeout(struct ipmi_wdt *iwd, int timeout,
 			       int do_heartbeat);
+static int ipmi_set_action(struct ipmi_wdt *iwd, unsigned int action);
+static int ipmi_set_preaction(struct ipmi_wdt *iwd, unsigned int action);
 static void ipmi_register_watchdog(int ipmi_intf, struct device *dev);
 static void _ipmi_unregister_watchdog(struct ipmi_wdt *iwd);
 static void ipmi_unregister_watchdog(int ipmi_intf);
@@ -189,18 +186,14 @@ static int timeout = 10; /* Default timeout. */
 static int pretimeout; /* Default pretimeout. */
 static int panic_wdt_timeout = 255; /* Default timeout to set on panic */
 
-/* Default action is to reset the board on a timeout. */
-static unsigned char action_val = WDOG_TIMEOUT_RESET;
-
-static char action[16] = "reset";
-
-static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
-
-static char preaction[16] = "pre_none";
-
-static unsigned char preop_val = WDOG_PREOP_NONE;
+#define WDOG_PREOP_NONE		0
+#define WDOG_PREOP_PANIC	1
+#define WDOG_PREOP_GIVE_DATA	2
 
-static char preop[16] = "preop_none";
+/* Default action is to reset the board on a timeout. */
+static unsigned char def_action_val = WDIOA_RESET;
+static unsigned char def_preaction_val = WDIOP_NONE;
+static unsigned char def_preop_val = WDOG_PREOP_NONE;
 
 /*
  * If true, the driver will start running as soon as it is configured
@@ -211,33 +204,41 @@ static int start_now;
 static int action_op(const char *inval, char *outval)
 {
 	int rv = 0;
+	unsigned int new_val;
 
 	mutex_lock(&ipmi_wdt_data_mutex);
-	if (outval)
-		strcpy(outval, action);
+	if (outval) {
+		switch (def_action_val) {
+		case WDIOA_RESET:
+			strcpy(outval, "reset");
+			break;
+		case WDIOA_POWER_OFF:
+			strcpy(outval, "power_off");
+			break;
+		case WDIOA_POWER_CYCLE:
+			strcpy(outval, "power_cycle");
+			break;
+		default:
+			strcpy(outval, "?");
+			break;
+		}
+	}
 
 	if (!inval)
 		goto out_unlock;
 
 	if (strcmp(inval, "reset") == 0)
-		action_val = WDOG_TIMEOUT_RESET;
-	else if (strcmp(inval, "none") == 0)
-		action_val = WDOG_TIMEOUT_NONE;
+		new_val = WDIOA_RESET;
 	else if (strcmp(inval, "power_cycle") == 0)
-		action_val = WDOG_TIMEOUT_POWER_CYCLE;
+		new_val = WDIOA_POWER_CYCLE;
 	else if (strcmp(inval, "power_off") == 0)
-		action_val = WDOG_TIMEOUT_POWER_DOWN;
+		new_val = WDIOA_POWER_OFF;
 	else
 		rv = -EINVAL;
-	if (!rv) {
-		strcpy(action, inval);
-		if (ipmi_wdt && ipmi_wdt->state != WDOG_TIMEOUT_NONE) {
-			ipmi_wdt->state = action_val;
-			rv = _ipmi_update_timeout(ipmi_wdt,
-					IPMI_SET_TIMEOUT_HB_IF_NECESSARY,
-					false);
-		}
-	}
+	if (!rv && ipmi_wdt)
+		rv = ipmi_set_action(ipmi_wdt, new_val);
+	if (!rv)
+		def_action_val = new_val;
 out_unlock:
 	mutex_unlock(&ipmi_wdt_data_mutex);
 
@@ -247,84 +248,115 @@ static int action_op(const char *inval, char *outval)
 static int preaction_op(const char *inval, char *outval)
 {
 	int rv = 0;
+	unsigned int new_val;
 
 	mutex_lock(&ipmi_wdt_data_mutex);
-	if (outval)
-		strcpy(outval, preaction);
+	if (outval) {
+		switch (def_preaction_val) {
+		case WDIOP_NONE:
+			strcpy(outval, "pre_none");
+			break;
+		case WDIOP_NMI:
+			strcpy(outval, "pre_nmi");
+			break;
+		case WDIOP_SMI:
+			strcpy(outval, "pre_smi");
+			break;
+		case WDIOP_INTERRUPT:
+			strcpy(outval, "pre_int");
+			break;
+		default:
+			strcpy(outval, "?");
+			break;
+		}
+	}
 
 	if (!inval)
 		goto out_unlock;
 
-	if (strcmp(inval, "pre_none") == 0)
-		preaction_val = WDOG_PRETIMEOUT_NONE;
-	else if (strcmp(inval, "pre_smi") == 0)
-		preaction_val = WDOG_PRETIMEOUT_SMI;
+	if (strcmp(inval, "pre_none") == 0) {
+		new_val = WDIOP_NONE;
+	} else if (strcmp(inval, "pre_smi") == 0) {
+		new_val = WDIOP_SMI;
 #ifdef HAVE_DIE_NMI
-	else if (strcmp(inval, "pre_nmi") == 0) {
-		if (preop_val == WDOG_PREOP_GIVE_DATA)
-			rv = -EINVAL;
-		else if (ipmi_wdt && !ipmi_wdt->nmi_works)
-			rv = -EINVAL;
-		else
-			preaction_val = WDOG_PRETIMEOUT_NMI;
-	}
+	} else if (strcmp(inval, "pre_nmi") == 0) {
+		new_val = WDIOP_NMI;
 #endif
-	else if (strcmp(inval, "pre_int") == 0)
-		preaction_val = WDOG_PRETIMEOUT_MSG_INT;
-	else
+	} else if (strcmp(inval, "pre_int") == 0) {
+		new_val = WDIOP_INTERRUPT;
+	} else {
 		rv = -EINVAL;
-	if (!rv) {
-		strcpy(preaction, inval);
-		if (ipmi_wdt && ipmi_wdt->state != WDOG_TIMEOUT_NONE &&
-		    ipmi_wdt->wdd.pretimeout) {
-			rv = _ipmi_update_timeout(ipmi_wdt,
-					IPMI_SET_TIMEOUT_HB_IF_NECESSARY,
-					false);
-		}
 	}
+	if (!rv && ipmi_wdt)
+		rv = ipmi_set_preaction(ipmi_wdt, new_val);
+	if (!rv)
+		def_preaction_val = new_val;
 out_unlock:
 	mutex_unlock(&ipmi_wdt_data_mutex);
 
 	return rv;
 }
 
+static const char *preop_to_governor(unsigned int preop)
+{
+	switch (preop) {
+	case WDOG_PREOP_NONE:
+		return "noop";
+	case WDOG_PREOP_PANIC:
+		return "panic";
+	case WDOG_PREOP_GIVE_DATA:
+		return "read_data";
+	default:
+		return NULL;
+	}
+}
 static int preop_op(const char *inval, char *outval)
 {
 	int rv = 0;
 	const char *gov = NULL;
-	unsigned int orig_val;
+	unsigned int new_val;
 
 	mutex_lock(&ipmi_wdt_data_mutex);
-	if (outval)
-		strcpy(outval, preop);
+	if (outval) {
+		switch (def_preop_val) {
+		case WDOG_PREOP_NONE:
+			strcpy(outval, "preop_none");
+			break;
+		case WDOG_PREOP_PANIC:
+			strcpy(outval, "preop_panic");
+			break;
+		case WDOG_PREOP_GIVE_DATA:
+			strcpy(outval, "preop_give_data");
+			break;
+		default:
+			strcpy(outval, "?");
+			break;
+		}
+	}
 
 	if (!inval)
 		goto out_unlock;
 
-	orig_val = preop_val;
 	if (strcmp(inval, "preop_none") == 0) {
-		preop_val = WDOG_PREOP_NONE;
-		gov = "noop";
+		new_val = WDOG_PREOP_NONE;
 	} else if (strcmp(inval, "preop_panic") == 0) {
-		preop_val = WDOG_PREOP_PANIC;
-		gov = "panic";
+		new_val = WDOG_PREOP_PANIC;
 	} else if (strcmp(inval, "preop_give_data") == 0) {
-		if (preaction_val == WDOG_PRETIMEOUT_NMI)
-			rv = -EINVAL;
-		else {
-			preop_val = WDOG_PREOP_GIVE_DATA;
-			gov = "read_data";
-		}
+		new_val = WDOG_PREOP_GIVE_DATA;
 	} else {
 		rv = -EINVAL;
 	}
-	if (!rv) {
-		rv = watchdog_pretimeout_governor_set(&ipmi_wdt->wdd, gov);
-		if (rv)
-			preaction_val = orig_val;
-		else
-			strcpy(preop, inval);
+	if (!rv && ipmi_wdt) {
+		gov = preop_to_governor(new_val);
+		if (!gov)
+			rv = -EINVAL;
+		if (!rv) {
+			rv = watchdog_pretimeout_governor_set(&ipmi_wdt->wdd,
+							      gov);
+		}
 	}
+	if (!rv)
+		def_preop_val = new_val;
 out_unlock:
 	mutex_unlock(&ipmi_wdt_data_mutex);
 
@@ -551,7 +583,7 @@ static int __ipmi_update_timeout(struct ipmi_wdt *iwd, int *send_heartbeat_now)
 	WDOG_SET_TIMEOUT_ACT(data[1], iwd->state);
 	if ((iwd->wdd.pretimeout > 0) &&
 	    (iwd->state != WDOG_TIMEOUT_NONE)) {
-		WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
+		WDOG_SET_PRETIMEOUT_ACT(data[1], iwd->prestate);
 		data[2] = iwd->wdd.pretimeout;
 	} else {
 		WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE);
@@ -863,19 +895,36 @@ static void ipmi_wdog_panic_handler(void *user_data)
 	}
 }
 
-static int ipmi_wdt_start(struct watchdog_device *wdd)
+static int _ipmi_wdt_start(struct ipmi_wdt *iwd)
 {
-	struct ipmi_wdt *iwd = wdd_to_ipmi_wdt(wdd);
-	int rv;
+	int rv = 0;
 
-	mutex_lock(&iwd->lock);
-	iwd->state = action_val;
-	rv = _ipmi_update_timeout(iwd, IPMI_SET_TIMEOUT_FORCE_HB, false);
-	mutex_unlock(&iwd->lock);
+	switch (iwd->wdd.action) {
+	case WDIOA_RESET:
+		iwd->state = WDOG_TIMEOUT_RESET;
+		break;
+	case WDIOA_POWER_OFF:
+		iwd->state = WDOG_TIMEOUT_RESET;
+		break;
+	case WDIOA_POWER_CYCLE:
+		iwd->state = WDOG_TIMEOUT_RESET;
+		break;
+	default:
+		rv = -EINVAL;
+		break;
+	}
+	if (!rv)
+		rv = _ipmi_update_timeout(iwd, IPMI_SET_TIMEOUT_FORCE_HB,
+					  false);
 
 	return rv;
 }
 
+static int ipmi_wdt_start(struct watchdog_device *wdd)
+{
+	return _ipmi_wdt_start(wdd_to_ipmi_wdt(wdd));
+}
+
 static int ipmi_wdt_stop(struct watchdog_device *wdd)
 {
 	struct ipmi_wdt *iwd = wdd_to_ipmi_wdt(wdd);
@@ -903,25 +952,101 @@ static int ipmi_wdt_ping(struct watchdog_device *wdd)
 
 static int ipmi_wdt_set_timeout(struct watchdog_device *wdd, unsigned int val)
 {
-	struct ipmi_wdt *iwd = wdd_to_ipmi_wdt(wdd);
-
-	return ipmi_set_timeout(iwd, val, IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+	return ipmi_set_timeout(wdd_to_ipmi_wdt(wdd), val,
+				IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
 }
 
 static int ipmi_wdt_set_pretimeout(struct watchdog_device *wdd,
 				   unsigned int val)
 {
 	struct ipmi_wdt *iwd = wdd_to_ipmi_wdt(wdd);
-	int rv;
+
+	return ipmi_set_pretimeout(iwd, val, IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+}
+
+static int ipmi_set_action(struct ipmi_wdt *iwd, unsigned int val)
+{
+	int rv = 0;
 
 	mutex_lock(&iwd->lock);
-	iwd->wdd.pretimeout = val;
-	rv = _ipmi_update_timeout(iwd, IPMI_SET_TIMEOUT_NO_HB, false);
+	if (val == iwd->wdd.action)
+		goto out_unlock;
+	switch (val) {
+	case WDIOA_RESET:
+	case WDIOA_POWER_OFF:
+	case WDIOA_POWER_CYCLE:
+		iwd->wdd.action = val;
+		break;
+	default:
+		rv = -EINVAL;
+	}
+	if (!rv)
+		rv = _ipmi_wdt_start(iwd);
+out_unlock:
 	mutex_unlock(&iwd->lock);
 
 	return rv;
 }
 
+static int ipmi_wdt_set_action(struct watchdog_device *wdd,
+			       unsigned int val)
+{
+	return ipmi_set_action(wdd_to_ipmi_wdt(wdd), val);
+}
+
+static int ipmi_set_preaction(struct ipmi_wdt *iwd, unsigned int val)
+{
+	int rv = 0;
+	int new_state = 0;
+
+	mutex_lock(&iwd->lock);
+	if (val == iwd->wdd.preaction)
+		goto out_unlock;
+	switch (val) {
+	case WDIOP_NONE:
+		new_state = WDOG_PRETIMEOUT_NONE;
+		break;
+	case WDIOP_SMI:
+		new_state = WDOG_PRETIMEOUT_SMI;
+		break;
+	case WDIOP_INTERRUPT:
+		new_state = WDOG_PRETIMEOUT_MSG_INT;
+		break;
+#ifdef HAVE_DIE_NMI
+	case WDIOP_NMI:
+		if (!iwd->nmi_works)
+			rv = -EINVAL;
+		else
+			new_state = WDOG_PRETIMEOUT_NMI;
+		break;
+#endif
+	default:
+		rv = -EINVAL;
+	}
+	if (!rv) {
+		int old_preaction = iwd->wdd.preaction;
+		int old_prestate = iwd->prestate;
+
+		iwd->wdd.preaction = val;
+		iwd->prestate = new_state;
+		rv = _ipmi_wdt_start(iwd);
+		if (rv) {
+			iwd->wdd.preaction = old_preaction;
+			iwd->prestate = old_prestate;
+		}
+	}
+out_unlock:
+	mutex_unlock(&iwd->lock);
+
+	return rv;
+}
+
+static int ipmi_wdt_set_preaction(struct watchdog_device *wdd,
+				  unsigned int val)
+{
+	return ipmi_set_preaction(wdd_to_ipmi_wdt(wdd), val);
+}
+
 static const struct watchdog_info ipmi_wdt_ident = {
 	.options	= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
 			  WDIOF_PRETIMEOUT | WDIOF_MAGICCLOSE,
@@ -936,7 +1061,9 @@ static const struct watchdog_ops ipmi_wdt_ops = {
 	.ping		= ipmi_wdt_ping,
 	.set_timeout	= ipmi_wdt_set_timeout,
 	.set_pretimeout = ipmi_wdt_set_pretimeout,
-	.get_timeleft   = ipmi_wdt_get_timeleft,
+	.get_timeleft	= ipmi_wdt_get_timeleft,
+	.set_action	= ipmi_wdt_set_action,
+	.set_preaction	= ipmi_wdt_set_preaction,
 };
 
 static const struct ipmi_user_hndl ipmi_hndlrs = {
@@ -976,14 +1103,14 @@ ipmi_nmi(unsigned int val, struct pt_regs *regs)
 	if (iwd->state == WDOG_TIMEOUT_NONE)
 		return NMI_DONE;
 
-	if (preaction_val != WDOG_PRETIMEOUT_NMI)
+	if (iwd->wdd.preaction != WDIOP_NMI)
 		return NMI_DONE;
 
 	/*
 	 * If no one else handled the NMI, we assume it was the IPMI
 	 * watchdog.
 	 */
-	if (preop_val == WDOG_PREOP_PANIC) {
+	if (iwd->wdd.gov && strcmp(iwd->wdd.gov->name, "panic") == 0) {
 		/*
 		 * On some machines, the heartbeat will give an error
 		 * and not work unless we re-enable the timer.  So
@@ -1000,6 +1127,7 @@ ipmi_nmi(unsigned int val, struct pt_regs *regs)
 static void nmi_check(struct ipmi_wdt *iwd)
 {
 	int old_state = iwd->state;
+	int old_prestate = iwd->prestate;
 	int old_pretimeout = iwd->wdd.pretimeout;
 	int old_timeout = iwd->wdd.timeout;
 	int rv;
@@ -1026,6 +1154,7 @@ static void nmi_check(struct ipmi_wdt *iwd)
 	 * ourselves 99 seconds to stop the timer.
 	 */
 	iwd->state = WDOG_TIMEOUT_RESET;
+	iwd->prestate = WDOG_PRETIMEOUT_NMI;
 	iwd->wdd.pretimeout = 99;
 	iwd->wdd.timeout = 100;
 
@@ -1063,6 +1192,7 @@ static void nmi_check(struct ipmi_wdt *iwd)
 	mutex_unlock(&ipmi_nmi_test_mutex);
 	iwd->wdd.pretimeout = old_pretimeout;
 	iwd->wdd.timeout = old_timeout;
+	iwd->prestate = old_prestate;
 	iwd->state = old_state;
 	rv = _ipmi_update_timeout(iwd, IPMI_SET_TIMEOUT_FORCE_HB, false);
 	if (rv)
@@ -1079,6 +1209,7 @@ static void ipmi_register_watchdog(int ipmi_intf, struct device *dev)
 {
 	struct ipmi_wdt *iwd = NULL;
 	int rv = -EBUSY;
+	const char *gov;
 
 	mutex_lock(&ipmi_wdt_data_mutex);
 	if ((ifnum_to_use != -1) && (ifnum_to_use != ipmi_intf))
@@ -1126,6 +1257,8 @@ static void ipmi_register_watchdog(int ipmi_intf, struct device *dev)
 	watchdog_init_timeout(&iwd->wdd, timeout, NULL);
 	iwd->wdd.pretimeout = pretimeout;
 	iwd->wdd.parent = dev;
+	iwd->wdd.action = def_action_val;
+	iwd->wdd.preaction = def_preaction_val;
 
 	rv = watchdog_register_device(&iwd->wdd);
 	if (rv) {
@@ -1136,24 +1269,34 @@ static void ipmi_register_watchdog(int ipmi_intf, struct device *dev)
 
 	nmi_check(iwd);
 
-	if (preaction_val == WDOG_PRETIMEOUT_NMI && !iwd->nmi_works) {
+	if (iwd->wdd.preaction == WDIOP_NMI && !iwd->nmi_works) {
 		pr_warn("NMI pretimeout test failed, disabling pretimeout.\n");
-		preaction_val = WDOG_PRETIMEOUT_NONE;
+		iwd->wdd.preaction = WDIOP_NONE;
+	}
+
+	gov = preop_to_governor(def_preop_val);
+	if (!gov) {
+		pr_warn("Invalid preop value: %d\n", def_preop_val);
+	} else {
+		rv = watchdog_pretimeout_governor_set(&iwd->wdd, gov);
+		if (rv)
+			pr_warn("Setting governor to %s failed: %d\n",
+				gov, rv);
 	}
 
 	ipmi_wdt = iwd;
+	rv = 0;
 
  out:
 	mutex_unlock(&ipmi_wdt_data_mutex);
 	if (start_now && rv == 0) {
 		/* Run from startup, so start the timer now. */
 		start_now = 0; /* Disable this function after first startup. */
-		iwd->state = action_val;
-		mutex_lock(&iwd->lock);
-		_ipmi_update_timeout(iwd, IPMI_SET_TIMEOUT_FORCE_HB, false);
-		mutex_unlock(&iwd->lock);
-		pr_info("Starting now!\n");
-	} else if (iwd && rv != 0) {
+		if (_ipmi_wdt_start(iwd))
+			pr_warn("Starting now failed!\n");
+		else
+			pr_info("Starting now!\n");
+	} else if (iwd && rv) {
 		kfree(iwd);
 	}
 }
@@ -1236,22 +1379,6 @@ static int __init ipmi_wdog_init(void)
 {
 	int rv;
 
-	if (action_op(action, NULL)) {
-		pr_info("Unknown action '%s', defaulting to reset\n", action);
-		action_op("reset", NULL);
-	}
-
-	if (preaction_op(preaction, NULL)) {
-		pr_info("Unknown preaction '%s', defaulting to none\n",
-			preaction);
-		preaction_op("pre_none", NULL);
-	}
-
-	if (preop_op(preop, NULL)) {
-		pr_info("Unknown preop '%s', defaulting to none\n", preop);
-		preop_op("preop_none", NULL);
-	}
-
 	register_reboot_notifier(&wdog_reboot_notifier);
 
 	rv = ipmi_smi_watcher_register(&smi_watcher);
