From: Wim Van Sebroeck <wim@iguana.be>
To: Marc Vertes <marc.vertes@sigfox.com>
Cc: broonie@opensource.wolfsonmicro.com, w.sang@pengutronix.de,
linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org,
HaraldWelte@viatech.com
Subject: Re: [PATCH RFC] watchdog: add a new driver for VIA chipsets
Date: Wed, 23 Nov 2011 22:43:38 +0100 [thread overview]
Message-ID: <20111123214338.GP23376@infomag.iguana.be> (raw)
In-Reply-To: <4ecd075d.2YyTTCA13zxwZmwT%marc.vertes@sigfox.com>
Hi Marc,
> > Coming back to now: if the driver incorporates the timer (like all other
> > devices that can be started but not stopped once started do), then the start
> > and stop functions are not empty.
> > The timer (with the example that I prepared as part of the generic code) is
> > not so difficult and will be a good solution for the time being. (Unless
> > Dmitry Artamonow's comment about the fact that the watchdog could perhaps
> > be started and stopped is correct... This should be investigated first imho).
> >
> The watchdog can not be started and stopped from the driver. This is
> what I investigated first and found impossible (and explains why this
> driver is still missing).
>
> I do not fully understand yet what has to be done with the timer.
Below the example driver that should get included in the Documentation.
Kind regards,
Wim.
--------------------------------------------------------------------------------
/*
* Watchdog timer driver example with timer.
*
* Copyright (C) 2009-2011 Wim Van Sebroeck <wim@iguana.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/*
* Some watchdog device can't stop once started. To support
* the magic_close feature we therefor need to use an internal
* timer to keep the watchdog being pinged when /dev/watchdog has
* been closed correctly.
*
* This is an example driver for these kind of watchdog devices.
*/
#define DRV_NAME KBUILD_MODNAME
#define pr_fmt(fmt) DRV_NAME ": " fmt
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/watchdog.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/platform_device.h>
/* Hardware heartbeat in seconds */
#define WDT_HW_HEARTBEAT 2
/* Timer heartbeat (500ms) */
#define WDT_HEARTBEAT (HZ/2) /* should be <= ((WDT_HW_HEARTBEAT*HZ)/2) */
/* User land timeout */
#define WDT_TIMEOUT 15
static int timeout = WDT_TIMEOUT;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. "
"(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started. "
"(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static struct watchdog_device wdt_dev;
static void wdt_timer_tick(unsigned long data);
static DEFINE_TIMER(timer, wdt_timer_tick, 0, 0);
/* The timer that pings the watchdog */
static unsigned long next_heartbeat; /* the next_heartbeat for the timer */
static unsigned long running; /* is watchdog running for userspace? */
static struct platform_device *wdt_platform_device;
/*
* Reset the watchdog timer. (ie, pat the watchdog)
*/
static inline void wdt_reset(void)
{
/* Reset the watchdog timer hardware here */
}
/*
* Timer tick: the timer will make sure that the watchdog timer hardware
* is being reset in time. The conditions to do this are:
* 1) the watchog timer has been started and /dev/watchdog is open
* and there is still time left before userspace should send the
* next heartbeat/ping. (note: the internal heartbeat is much smaller
* then the external/userspace heartbeat).
* 2) the watchdog timer has been stopped by userspace.
*/
static void wdt_timer_tick(unsigned long data)
{
if (time_before(jiffies, next_heartbeat) ||
(!test_bit(WDOG_ACTIVE, &wdt_dev.status))) {
wdt_reset();
mod_timer(&timer, jiffies + WDT_HEARTBEAT);
} else
pr_crit("I will reboot your machine !\n");
}
/*
* The watchdog operations
*/
static int wdt_ping(struct watchdog_device *wdd)
{
/* calculate when the next userspace timeout will be */
next_heartbeat = jiffies + timeout * HZ;
return 0;
}
static int wdt_start(struct watchdog_device *wdd)
{
/* calculate the next userspace timeout and modify the timer */
wdt_ping(wdd);
mod_timer(&timer, jiffies + WDT_HEARTBEAT);
/* Start the watchdog timer hardware here */
pr_info("wdt_start\n");
running = 1;
return 0;
}
static int wdt_stop(struct watchdog_device *wdd)
{
/* The watchdog timer hardware can not be stopped... */
pr_info("wdt_stop\n");
running = 0;
return 0;
}
static unsigned int wdt_status(struct watchdog_device *wdd)
{
return WDIOF_FANFAULT;
}
static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout)
{
if (new_timeout < 1)
return -EINVAL;
return 0;
}
/*
* The watchdog kernel structures
*/
static const struct watchdog_info wdt_info = {
.identity = DRV_NAME,
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
};
static const struct watchdog_ops wdt_ops = {
.owner = THIS_MODULE,
.start = wdt_start,
.stop = wdt_stop,
.ping = wdt_ping,
.status = wdt_status,
.set_timeout = wdt_set_timeout,
};
static struct watchdog_device wdt_dev = {
.info = &wdt_info,
.ops = &wdt_ops,
};
/*
* The watchdog timer drivers init and exit routines
*/
static int __devinit wdt_probe(struct platform_device *pdev)
{
int res;
/* Register other stuff */
/* Set watchdog_device parameters */
wdt_dev.timeout = timeout;
/* wdt_dev.dev.parent = &pdev->dev;*/
if (nowayout)
set_bit(WDOG_NO_WAY_OUT, &wdt_dev.status);
/* Register the watchdog timer device */
res = watchdog_register_device(&wdt_dev);
if (res) {
pr_err("watchdog_register_device returned %d\n", res);
return res;
}
pr_info("enabled (timeout=%d sec)\n", timeout);
return 0;
}
static int __devexit wdt_remove(struct platform_device *pdev)
{
/* Unregister the watchdog timer device */
watchdog_unregister_device(&wdt_dev);
/* stop and delete the timer */
pr_warn("I quit now, hardware will probably reboot!\n");
del_timer(&timer);
/* Unregister other stuff */
return 0;
}
static struct platform_driver wdt_driver = {
.probe = wdt_probe,
.remove = __devexit_p(wdt_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init wdt_init(void)
{
int err;
pr_info("WDT driver initialising.\n");
err = platform_driver_register(&wdt_driver);
if (err)
return err;
wdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(wdt_platform_device)) {
err = PTR_ERR(wdt_platform_device);
goto unreg_platform_driver;
}
return 0;
unreg_platform_driver:
platform_driver_unregister(&wdt_driver);
return err;
}
static void __exit wdt_exit(void)
{
platform_device_unregister(wdt_platform_device);
platform_driver_unregister(&wdt_driver);
pr_info("Watchdog Module Unloaded.\n");
}
module_init(wdt_init);
module_exit(wdt_exit);
MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
MODULE_DESCRIPTION("WatchDog Timer Driver example with timer");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
next prev parent reply other threads:[~2011-11-23 21:46 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-22 11:17 Marc Vertes
2011-11-22 11:22 ` Wolfram Sang
2011-11-22 12:56 ` Rahul Bedarkar
2011-11-22 17:05 ` Marc Vertes
2011-11-22 17:30 ` Wolfram Sang
2011-11-22 18:09 ` Marc Vertes
2011-11-22 18:55 ` Marc Vertes
2011-11-23 12:10 ` Dmitry Artamonow
2011-11-23 14:12 ` Marc Vertes
2011-11-23 14:37 ` Mark Brown
2011-11-23 19:25 ` Dmitry Artamonow
2011-11-23 21:43 ` Wolfram Sang
2011-11-23 18:22 ` Harald Welte
2011-11-23 21:41 ` Wim Van Sebroeck
2011-11-24 19:22 ` Marc Vertes
2011-11-24 19:34 ` Wim Van Sebroeck
2011-11-25 20:02 ` Marc Vertes
2011-11-22 17:32 ` Mark Brown
2011-11-22 18:40 ` Wolfram Sang
2011-11-23 9:59 ` Marc Vertes
2011-11-23 10:49 ` Wolfram Sang
2011-11-23 11:43 ` Marc Vertes
2011-11-23 12:13 ` Wim Van Sebroeck
2011-11-23 12:20 ` Mark Brown
2011-11-23 12:40 ` Wim Van Sebroeck
2011-11-23 14:46 ` Marc Vertes
2011-11-23 21:43 ` Wim Van Sebroeck [this message]
2011-11-23 21:52 ` Wolfram Sang
2011-11-24 8:29 ` Wim Van Sebroeck
2011-11-23 21:46 ` Wim Van Sebroeck
2011-11-24 10:57 ` Marc Vertes
2011-11-24 13:42 ` Wim Van Sebroeck
2011-11-24 14:42 ` Marc Vertes
2011-11-24 15:48 ` Wim Van Sebroeck
2011-11-24 16:47 ` Marc Vertes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111123214338.GP23376@infomag.iguana.be \
--to=wim@iguana.be \
--cc=HaraldWelte@viatech.com \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=marc.vertes@sigfox.com \
--cc=w.sang@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®