diff mbox series

[1/4] watchdog device drivers:pc87413_wdt:Rewriting of pc87413_wdt driver to utilize common watchdog interface

Message ID 20190730021540.66579-1-mbalant3@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series [1/4] watchdog device drivers:pc87413_wdt:Rewriting of pc87413_wdt driver to utilize common watchdog interface | expand

Commit Message

Mark Balantzyan July 30, 2019, 2:15 a.m. UTC
There is a potential for the variable swc_base_addr in the call chain of the
driver initialization function (init) to be used before initialization. This
brought up the need for, by rewriting the driver to use the common watchdog
interface, ensuring to have all resources in place. This patch addresses this
need by rewriting into common watchdog interface utilization for the driver.

Signed-off-by: Mark Balantzyan <mbalant3@gmail.com>
---
 drivers/media/pci/tw686x/Kconfig |  1 +
 drivers/watchdog/pc87413_wdt.c   | 92 +++++++++++++++-----------------
 2 files changed, 45 insertions(+), 48 deletions(-)

Comments

Guenter Roeck July 30, 2019, 2:33 a.m. UTC | #1
On 7/29/19 7:15 PM, Mark Balantzyan wrote:
> There is a potential for the variable swc_base_addr in the call chain of the
> driver initialization function (init) to be used before initialization. This
> brought up the need for, by rewriting the driver to use the common watchdog
> interface, ensuring to have all resources in place. This patch addresses this
> need by rewriting into common watchdog interface utilization for the driver.
> 

First, those four patches should be just one. Splitting them into four just makes
review more difficult.

Second, the potential race is not the key change, even though it may have
triggered it. Just describe the change, ie the rework to the watchdog API.

Then add that this also resolves a race condition.

Also see inline.

Thanks,
Guenter


> Signed-off-by: Mark Balantzyan <mbalant3@gmail.com>
> ---
>   drivers/media/pci/tw686x/Kconfig |  1 +
>   drivers/watchdog/pc87413_wdt.c   | 92 +++++++++++++++-----------------
>   2 files changed, 45 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig
> index da8bfee7..079d7464 100644
> --- a/drivers/media/pci/tw686x/Kconfig
> +++ b/drivers/media/pci/tw686x/Kconfig
> @@ -5,6 +5,7 @@ config VIDEO_TW686X
>   	select VIDEOBUF2_DMA_CONTIG
>   	select VIDEOBUF2_DMA_SG
>   	select SND_PCM
> +	select WATCHDOG_CORE
>   	help
>   	  Support for Intersil/Techwell TW686x-based frame grabber cards.
>   
> diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
> index 06a892e3..4c330ee5 100644
> --- a/drivers/watchdog/pc87413_wdt.c
> +++ b/drivers/watchdog/pc87413_wdt.c
> @@ -22,12 +22,10 @@
>   
>   #include <linux/module.h>
>   #include <linux/types.h>
> -#include <linux/miscdevice.h>
>   #include <linux/watchdog.h>
>   #include <linux/ioport.h>
>   #include <linux/delay.h>
>   #include <linux/notifier.h>
> -#include <linux/fs.h>
>   #include <linux/reboot.h>
>   #include <linux/init.h>
>   #include <linux/spinlock.h>
> @@ -65,7 +63,6 @@ static char expect_close;		/* is the close expected? */
>   
>   static DEFINE_SPINLOCK(io_lock);	/* to guard us from io races */
>   
> -static bool nowayout = WATCHDOG_NOWAYOUT;
>   
>   /* -- Low level function ----------------------------------------*/
>   
> @@ -216,9 +213,9 @@ static inline void pc87413_disable_sw_wd_trg(void)
>   
>   /* -- Higher level functions ------------------------------------*/
>   
> -/* Enable the watchdog */
> +/* Enable/start the watchdog */
>   
> -static void pc87413_enable(void)
> +static void pc87413_start(void)
>   {
>   	spin_lock(&io_lock);
>   
> @@ -231,9 +228,9 @@ static void pc87413_enable(void)
>   	spin_unlock(&io_lock);
>   }
>   
> -/* Disable the watchdog */
> +/* Disable/stop the watchdog */
>   
> -static void pc87413_disable(void)
> +static void pc87413_stop(void)
>   {
>   	spin_lock(&io_lock);
>   
> @@ -245,9 +242,9 @@ static void pc87413_disable(void)
>   	spin_unlock(&io_lock);
>   }
>   
> -/* Refresh the watchdog */
> +/* Refresh/keepalive the watchdog */
>   
> -static void pc87413_refresh(void)
> +static void pc87413_keepalive(struct watchdog_device *wdd)
>   {
>   	spin_lock(&io_lock);
>   
> @@ -260,6 +257,8 @@ static void pc87413_refresh(void)
>   	pc87413_enable_sw_wd_trg();
>   
>   	spin_unlock(&io_lock);
> +
> +	return 0;
>   }
>   
>   /* -- File operations -------------------------------------------*/
> @@ -278,9 +277,6 @@ static int pc87413_open(struct inode *inode, struct file *file)
>   	if (test_and_set_bit(0, &timer_enabled))
>   		return -EBUSY;
>   
> -	if (nowayout)
> -		__module_get(THIS_MODULE);
> -
>   	/* Reload and activate timer */
>   	pc87413_refresh();
>   
> @@ -331,7 +327,6 @@ static int pc87413_status(void)
>   
>   /**
>    *	pc87413_write:
> - *	@file: file handle to the watchdog
>    *	@data: data buffer to write
>    *	@len: length in bytes
>    *	@ppos: pointer to the position to write. No seeks allowed
> @@ -345,26 +340,25 @@ static ssize_t pc87413_write(struct file *file, const char __user *data,
>   {
>   	/* See if we got the magic character 'V' and reload the timer */
>   	if (len) {
> -		if (!nowayout) {
> -			size_t i;
> -
> -			/* reset expect flag */
> -			expect_close = 0;
> -
> -			/* scan to see whether or not we got the
> -			   magic character */
> -			for (i = 0; i != len; i++) {
> -				char c;
> -				if (get_user(c, data + i))
> -					return -EFAULT;
> -				if (c == 'V')
> -					expect_close = 42;
> -			}
> +		size_t i;
> +
> +		/* reset expect flag */
> +		expect_close = 0;
> +
> +		/* scan to see whether or not we got the
> +		   magic character */
> +		for (i = 0; i != len; i++) {
> +			char c;
> +			if (get_user(c, data + i))
> +				return -EFAULT;
> +			if (c == 'V')
> +				expect_close = 42;
>   		}
> +	}
>   
>   		/* someone wrote to us, we should reload the timer */
> -		pc87413_refresh();
> -	}
> +	pc87413_refresh();
> +	
>   	return len;
>   }
>   
> @@ -417,7 +411,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
>   			retval = 0;
>   		}
>   		if (options & WDIOS_ENABLECARD) {
> -			pc87413_enable();
> +			pc87413_start();

This is where things get confusing. This function is removed in the next patch.
Plus, it should be removed here, as you remove pc87413_fops below.

Why bother changing it only to remove it later ?

>   			retval = 0;
>   		}
>   		return retval;
> @@ -466,31 +460,32 @@ static int pc87413_notify_sys(struct notifier_block *this,
>   {
>   	if (code == SYS_DOWN || code == SYS_HALT)
>   		/* Turn the card off */
> -		pc87413_disable();
> +		pc87413_stop();

This can be accomplished by calling watchdog_stop_on_reboot() in the probe
function.

>   	return NOTIFY_DONE;
>   }
>   
>   /* -- Module's structures ---------------------------------------*/
>   
> -static const struct file_operations pc87413_fops = {
> -	.owner		= THIS_MODULE,
> -	.llseek		= no_llseek,
> -	.write		= pc87413_write,
> -	.unlocked_ioctl	= pc87413_ioctl,
> -	.open		= pc87413_open,
> -	.release	= pc87413_release,
> -};
>   
> -static struct notifier_block pc87413_notifier = {
> +static struct notifier_block pc87413wdt_notifier = {
>   	.notifier_call  = pc87413_notify_sys,
>   };
>   
> -static struct miscdevice pc87413_miscdev = {
> -	.minor          = WATCHDOG_MINOR,
> -	.name           = "watchdog",
> -	.fops           = &pc87413_fops,
> +static struct watchdog_ops pc87413wdt_ops = {
> +       .owner = THIS_MODULE,
> +       .start = pc87413wdt_start,
> +       .stop = pc87413wdt_stop,
> +       .ping = pc87413wdt_keepalive,
> +       .set_timeout = pc87413wdt_set_heartbeat,
> +};
> +
> +static struct watchdog_device pc87413wdt_wdd = {
> +       	.info = &pc87413wdt_ident,
> +       	.ops = &pc87413wdt_ops,
> +	.status = WATCHDOG_NOWAYOUT_INIT_STATUS
>   };
>   
> +
>   /* -- Module init functions -------------------------------------*/
>   
>   /**
> @@ -515,7 +510,7 @@ static int __init pc87413_init(void)
>   	if (ret != 0)
>   		pr_err("cannot register reboot notifier (err=%d)\n", ret);
>   
> -	ret = misc_register(&pc87413_miscdev);
> +	ret = watchdog_register_device(&pc87413wdt_wdd);
>   	if (ret != 0) {
>   		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
>   		       WATCHDOG_MINOR, ret);
> @@ -533,13 +528,14 @@ static int __init pc87413_init(void)
>   		goto misc_unreg;
>   	}
>   
> -	pc87413_enable();
> +	pc87413_start();

You should drop this; it doesn't make sense to start the watchdog here.

>   
>   	release_region(io, 2);
> +	pc87413_keepalive(&pc87413wdt_wdd);
>   	return 0;
>   
>   misc_unreg:
> -	misc_deregister(&pc87413_miscdev);
> +	watchdog_unregister_device(&pc87413wdt_wdd)
>   reboot_unreg:
>   	unregister_reboot_notifier(&pc87413_notifier);
>   	release_region(io, 2);
>
Guenter Roeck July 30, 2019, 2:38 a.m. UTC | #2
On 7/29/19 7:15 PM, Mark Balantzyan wrote:
> There is a potential for the variable swc_base_addr in the call chain of the
> driver initialization function (init) to be used before initialization. This
> brought up the need for, by rewriting the driver to use the common watchdog
> interface, ensuring to have all resources in place. This patch addresses this
> need by rewriting into common watchdog interface utilization for the driver.
> 
> Signed-off-by: Mark Balantzyan <mbalant3@gmail.com>
> ---
>   drivers/media/pci/tw686x/Kconfig |  1 +
>   drivers/watchdog/pc87413_wdt.c   | 92 +++++++++++++++-----------------
>   2 files changed, 45 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig
> index da8bfee7..079d7464 100644
> --- a/drivers/media/pci/tw686x/Kconfig
> +++ b/drivers/media/pci/tw686x/Kconfig
> @@ -5,6 +5,7 @@ config VIDEO_TW686X
>   	select VIDEOBUF2_DMA_CONTIG
>   	select VIDEOBUF2_DMA_SG
>   	select SND_PCM
> +	select WATCHDOG_CORE
>   	help
>   	  Support for Intersil/Techwell TW686x-based frame grabber cards.
>   
> diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
> index 06a892e3..4c330ee5 100644
> --- a/drivers/watchdog/pc87413_wdt.c
> +++ b/drivers/watchdog/pc87413_wdt.c
> @@ -22,12 +22,10 @@
>   
>   #include <linux/module.h>
>   #include <linux/types.h>
> -#include <linux/miscdevice.h>
>   #include <linux/watchdog.h>
>   #include <linux/ioport.h>
>   #include <linux/delay.h>
>   #include <linux/notifier.h>
> -#include <linux/fs.h>
>   #include <linux/reboot.h>
>   #include <linux/init.h>
>   #include <linux/spinlock.h>
> @@ -65,7 +63,6 @@ static char expect_close;		/* is the close expected? */
>   
>   static DEFINE_SPINLOCK(io_lock);	/* to guard us from io races */
>   
> -static bool nowayout = WATCHDOG_NOWAYOUT;
>   
>   /* -- Low level function ----------------------------------------*/
>   
> @@ -216,9 +213,9 @@ static inline void pc87413_disable_sw_wd_trg(void)
>   
>   /* -- Higher level functions ------------------------------------*/
>   
> -/* Enable the watchdog */
> +/* Enable/start the watchdog */
>   
> -static void pc87413_enable(void)
> +static void pc87413_start(void)

I really don't think that this code compiles without warning.

Guenter

>   {
>   	spin_lock(&io_lock);
>   
> @@ -231,9 +228,9 @@ static void pc87413_enable(void)
>   	spin_unlock(&io_lock);
>   }
>   
> -/* Disable the watchdog */
> +/* Disable/stop the watchdog */
>   
> -static void pc87413_disable(void)
> +static void pc87413_stop(void)
>   {
>   	spin_lock(&io_lock);
>   
> @@ -245,9 +242,9 @@ static void pc87413_disable(void)
>   	spin_unlock(&io_lock);
>   }
>   
> -/* Refresh the watchdog */
> +/* Refresh/keepalive the watchdog */
>   
> -static void pc87413_refresh(void)
> +static void pc87413_keepalive(struct watchdog_device *wdd)
>   {
>   	spin_lock(&io_lock);
>   
> @@ -260,6 +257,8 @@ static void pc87413_refresh(void)
>   	pc87413_enable_sw_wd_trg();
>   
>   	spin_unlock(&io_lock);
> +
> +	return 0;
>   }
>   
>   /* -- File operations -------------------------------------------*/
> @@ -278,9 +277,6 @@ static int pc87413_open(struct inode *inode, struct file *file)
>   	if (test_and_set_bit(0, &timer_enabled))
>   		return -EBUSY;
>   
> -	if (nowayout)
> -		__module_get(THIS_MODULE);
> -
>   	/* Reload and activate timer */
>   	pc87413_refresh();
>   
> @@ -331,7 +327,6 @@ static int pc87413_status(void)
>   
>   /**
>    *	pc87413_write:
> - *	@file: file handle to the watchdog
>    *	@data: data buffer to write
>    *	@len: length in bytes
>    *	@ppos: pointer to the position to write. No seeks allowed
> @@ -345,26 +340,25 @@ static ssize_t pc87413_write(struct file *file, const char __user *data,
>   {
>   	/* See if we got the magic character 'V' and reload the timer */
>   	if (len) {
> -		if (!nowayout) {
> -			size_t i;
> -
> -			/* reset expect flag */
> -			expect_close = 0;
> -
> -			/* scan to see whether or not we got the
> -			   magic character */
> -			for (i = 0; i != len; i++) {
> -				char c;
> -				if (get_user(c, data + i))
> -					return -EFAULT;
> -				if (c == 'V')
> -					expect_close = 42;
> -			}
> +		size_t i;
> +
> +		/* reset expect flag */
> +		expect_close = 0;
> +
> +		/* scan to see whether or not we got the
> +		   magic character */
> +		for (i = 0; i != len; i++) {
> +			char c;
> +			if (get_user(c, data + i))
> +				return -EFAULT;
> +			if (c == 'V')
> +				expect_close = 42;
>   		}
> +	}
>   
>   		/* someone wrote to us, we should reload the timer */
> -		pc87413_refresh();
> -	}
> +	pc87413_refresh();
> +	
>   	return len;
>   }
>   
> @@ -417,7 +411,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
>   			retval = 0;
>   		}
>   		if (options & WDIOS_ENABLECARD) {
> -			pc87413_enable();
> +			pc87413_start();
>   			retval = 0;
>   		}
>   		return retval;
> @@ -466,31 +460,32 @@ static int pc87413_notify_sys(struct notifier_block *this,
>   {
>   	if (code == SYS_DOWN || code == SYS_HALT)
>   		/* Turn the card off */
> -		pc87413_disable();
> +		pc87413_stop();
>   	return NOTIFY_DONE;
>   }
>   
>   /* -- Module's structures ---------------------------------------*/
>   
> -static const struct file_operations pc87413_fops = {
> -	.owner		= THIS_MODULE,
> -	.llseek		= no_llseek,
> -	.write		= pc87413_write,
> -	.unlocked_ioctl	= pc87413_ioctl,
> -	.open		= pc87413_open,
> -	.release	= pc87413_release,
> -};
>   
> -static struct notifier_block pc87413_notifier = {
> +static struct notifier_block pc87413wdt_notifier = {
>   	.notifier_call  = pc87413_notify_sys,
>   };
>   
> -static struct miscdevice pc87413_miscdev = {
> -	.minor          = WATCHDOG_MINOR,
> -	.name           = "watchdog",
> -	.fops           = &pc87413_fops,
> +static struct watchdog_ops pc87413wdt_ops = {
> +       .owner = THIS_MODULE,
> +       .start = pc87413wdt_start,
> +       .stop = pc87413wdt_stop,
> +       .ping = pc87413wdt_keepalive,
> +       .set_timeout = pc87413wdt_set_heartbeat,
> +};
> +
> +static struct watchdog_device pc87413wdt_wdd = {
> +       	.info = &pc87413wdt_ident,
> +       	.ops = &pc87413wdt_ops,
> +	.status = WATCHDOG_NOWAYOUT_INIT_STATUS
>   };
>   
> +
>   /* -- Module init functions -------------------------------------*/
>   
>   /**
> @@ -515,7 +510,7 @@ static int __init pc87413_init(void)
>   	if (ret != 0)
>   		pr_err("cannot register reboot notifier (err=%d)\n", ret);
>   
> -	ret = misc_register(&pc87413_miscdev);
> +	ret = watchdog_register_device(&pc87413wdt_wdd);
>   	if (ret != 0) {
>   		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
>   		       WATCHDOG_MINOR, ret);
> @@ -533,13 +528,14 @@ static int __init pc87413_init(void)
>   		goto misc_unreg;
>   	}
>   
> -	pc87413_enable();
> +	pc87413_start();
>   
>   	release_region(io, 2);
> +	pc87413_keepalive(&pc87413wdt_wdd);
>   	return 0;
>   
>   misc_unreg:
> -	misc_deregister(&pc87413_miscdev);
> +	watchdog_unregister_device(&pc87413wdt_wdd)
>   reboot_unreg:
>   	unregister_reboot_notifier(&pc87413_notifier);
>   	release_region(io, 2);
>
Mark Balantzyan July 30, 2019, 2:47 a.m. UTC | #3
Yes, each time I go through an edit I discover something I missed,
apologies. Will be working on it for a bit, currently getting compile time
errors. Just letting you know and it’s good we’re checking :-)

Thank you,
Mark
diff mbox series

Patch

diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig
index da8bfee7..079d7464 100644
--- a/drivers/media/pci/tw686x/Kconfig
+++ b/drivers/media/pci/tw686x/Kconfig
@@ -5,6 +5,7 @@  config VIDEO_TW686X
 	select VIDEOBUF2_DMA_CONTIG
 	select VIDEOBUF2_DMA_SG
 	select SND_PCM
+	select WATCHDOG_CORE
 	help
 	  Support for Intersil/Techwell TW686x-based frame grabber cards.
 
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 06a892e3..4c330ee5 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -22,12 +22,10 @@ 
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
-#include <linux/fs.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
@@ -65,7 +63,6 @@  static char expect_close;		/* is the close expected? */
 
 static DEFINE_SPINLOCK(io_lock);	/* to guard us from io races */
 
-static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* -- Low level function ----------------------------------------*/
 
@@ -216,9 +213,9 @@  static inline void pc87413_disable_sw_wd_trg(void)
 
 /* -- Higher level functions ------------------------------------*/
 
-/* Enable the watchdog */
+/* Enable/start the watchdog */
 
-static void pc87413_enable(void)
+static void pc87413_start(void)
 {
 	spin_lock(&io_lock);
 
@@ -231,9 +228,9 @@  static void pc87413_enable(void)
 	spin_unlock(&io_lock);
 }
 
-/* Disable the watchdog */
+/* Disable/stop the watchdog */
 
-static void pc87413_disable(void)
+static void pc87413_stop(void)
 {
 	spin_lock(&io_lock);
 
@@ -245,9 +242,9 @@  static void pc87413_disable(void)
 	spin_unlock(&io_lock);
 }
 
-/* Refresh the watchdog */
+/* Refresh/keepalive the watchdog */
 
-static void pc87413_refresh(void)
+static void pc87413_keepalive(struct watchdog_device *wdd)
 {
 	spin_lock(&io_lock);
 
@@ -260,6 +257,8 @@  static void pc87413_refresh(void)
 	pc87413_enable_sw_wd_trg();
 
 	spin_unlock(&io_lock);
+
+	return 0;
 }
 
 /* -- File operations -------------------------------------------*/
@@ -278,9 +277,6 @@  static int pc87413_open(struct inode *inode, struct file *file)
 	if (test_and_set_bit(0, &timer_enabled))
 		return -EBUSY;
 
-	if (nowayout)
-		__module_get(THIS_MODULE);
-
 	/* Reload and activate timer */
 	pc87413_refresh();
 
@@ -331,7 +327,6 @@  static int pc87413_status(void)
 
 /**
  *	pc87413_write:
- *	@file: file handle to the watchdog
  *	@data: data buffer to write
  *	@len: length in bytes
  *	@ppos: pointer to the position to write. No seeks allowed
@@ -345,26 +340,25 @@  static ssize_t pc87413_write(struct file *file, const char __user *data,
 {
 	/* See if we got the magic character 'V' and reload the timer */
 	if (len) {
-		if (!nowayout) {
-			size_t i;
-
-			/* reset expect flag */
-			expect_close = 0;
-
-			/* scan to see whether or not we got the
-			   magic character */
-			for (i = 0; i != len; i++) {
-				char c;
-				if (get_user(c, data + i))
-					return -EFAULT;
-				if (c == 'V')
-					expect_close = 42;
-			}
+		size_t i;
+
+		/* reset expect flag */
+		expect_close = 0;
+
+		/* scan to see whether or not we got the
+		   magic character */
+		for (i = 0; i != len; i++) {
+			char c;
+			if (get_user(c, data + i))
+				return -EFAULT;
+			if (c == 'V')
+				expect_close = 42;
 		}
+	}
 
 		/* someone wrote to us, we should reload the timer */
-		pc87413_refresh();
-	}
+	pc87413_refresh();
+	
 	return len;
 }
 
@@ -417,7 +411,7 @@  static long pc87413_ioctl(struct file *file, unsigned int cmd,
 			retval = 0;
 		}
 		if (options & WDIOS_ENABLECARD) {
-			pc87413_enable();
+			pc87413_start();
 			retval = 0;
 		}
 		return retval;
@@ -466,31 +460,32 @@  static int pc87413_notify_sys(struct notifier_block *this,
 {
 	if (code == SYS_DOWN || code == SYS_HALT)
 		/* Turn the card off */
-		pc87413_disable();
+		pc87413_stop();
 	return NOTIFY_DONE;
 }
 
 /* -- Module's structures ---------------------------------------*/
 
-static const struct file_operations pc87413_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.write		= pc87413_write,
-	.unlocked_ioctl	= pc87413_ioctl,
-	.open		= pc87413_open,
-	.release	= pc87413_release,
-};
 
-static struct notifier_block pc87413_notifier = {
+static struct notifier_block pc87413wdt_notifier = {
 	.notifier_call  = pc87413_notify_sys,
 };
 
-static struct miscdevice pc87413_miscdev = {
-	.minor          = WATCHDOG_MINOR,
-	.name           = "watchdog",
-	.fops           = &pc87413_fops,
+static struct watchdog_ops pc87413wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = pc87413wdt_start,
+       .stop = pc87413wdt_stop,
+       .ping = pc87413wdt_keepalive,
+       .set_timeout = pc87413wdt_set_heartbeat,
+};
+
+static struct watchdog_device pc87413wdt_wdd = {
+       	.info = &pc87413wdt_ident,
+       	.ops = &pc87413wdt_ops,
+	.status = WATCHDOG_NOWAYOUT_INIT_STATUS
 };
 
+
 /* -- Module init functions -------------------------------------*/
 
 /**
@@ -515,7 +510,7 @@  static int __init pc87413_init(void)
 	if (ret != 0)
 		pr_err("cannot register reboot notifier (err=%d)\n", ret);
 
-	ret = misc_register(&pc87413_miscdev);
+	ret = watchdog_register_device(&pc87413wdt_wdd);
 	if (ret != 0) {
 		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
 		       WATCHDOG_MINOR, ret);
@@ -533,13 +528,14 @@  static int __init pc87413_init(void)
 		goto misc_unreg;
 	}
 
-	pc87413_enable();
+	pc87413_start();
 
 	release_region(io, 2);
+	pc87413_keepalive(&pc87413wdt_wdd);
 	return 0;
 
 misc_unreg:
-	misc_deregister(&pc87413_miscdev);
+	watchdog_unregister_device(&pc87413wdt_wdd)
 reboot_unreg:
 	unregister_reboot_notifier(&pc87413_notifier);
 	release_region(io, 2);