watchdog: Add Locking support

This patch fixes some potential multithreading issues, despite only
allowing one process to open the /dev/watchdog device, we can still get
called multiple times at the same time, since a program could be using thread,
or could share the fd after a fork.

This causes 2 potential problems:
1) watchdog_start / open do an unlocked test_n_set / test_n_clear,
   if these 2 race, the watchdog could be stopped while the active
   bit indicates it is running or visa versa.

2) Most watchdog_dev drivers probably assume that only one
   watchdog-op will get called at a time, this is not necessary
   true atm.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 76d2572..4d295d2 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -63,6 +63,8 @@
 {
 	int err = 0;
 
+	mutex_lock(&wddev->lock);
+
 	if (!watchdog_active(wddev))
 		goto out_ping;
 
@@ -72,6 +74,7 @@
 		err = wddev->ops->start(wddev); /* restart watchdog */
 
 out_ping:
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -88,6 +91,8 @@
 {
 	int err = 0;
 
+	mutex_lock(&wddev->lock);
+
 	if (watchdog_active(wddev))
 		goto out_start;
 
@@ -96,6 +101,7 @@
 		set_bit(WDOG_ACTIVE, &wddev->status);
 
 out_start:
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -113,6 +119,8 @@
 {
 	int err = 0;
 
+	mutex_lock(&wddev->lock);
+
 	if (!watchdog_active(wddev))
 		goto out_stop;
 
@@ -127,6 +135,7 @@
 		clear_bit(WDOG_ACTIVE, &wddev->status);
 
 out_stop:
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -147,8 +156,11 @@
 	if (!wddev->ops->status)
 		return -EOPNOTSUPP;
 
+	mutex_lock(&wddev->lock);
+
 	*status = wddev->ops->status(wddev);
 
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -171,8 +183,11 @@
 	    (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
 		return -EINVAL;
 
+	mutex_lock(&wddev->lock);
+
 	err = wddev->ops->set_timeout(wddev, timeout);
 
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -193,8 +208,11 @@
 	if (!wddev->ops->get_timeleft)
 		return -EOPNOTSUPP;
 
+	mutex_lock(&wddev->lock);
+
 	*timeleft = wddev->ops->get_timeleft(wddev);
 
+	mutex_unlock(&wddev->lock);
 	return err;
 }
 
@@ -213,8 +231,11 @@
 	if (!wddev->ops->ioctl)
 		return -ENOIOCTLCMD;
 
+	mutex_lock(&wddev->lock);
+
 	err = wddev->ops->ioctl(wddev, cmd, arg);
 
+	mutex_unlock(&wddev->lock);
 	return err;
 }