128 lines
3.8 KiB
Diff
128 lines
3.8 KiB
Diff
Index: linux-2.6.38-rc6/drivers/cbus/retu-wdt.c
|
|
===================================================================
|
|
--- linux-2.6.38-rc6.orig/drivers/cbus/retu-wdt.c 2011-03-02 16:08:59.022211654 +0100
|
|
+++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-02 16:29:43.215284501 +0100
|
|
@@ -58,13 +58,11 @@ struct retu_wdt_dev {
|
|
struct device *dev;
|
|
int users;
|
|
struct miscdevice retu_wdt_miscdev;
|
|
- struct timer_list ping_timer;
|
|
+ struct delayed_work ping_work;
|
|
};
|
|
|
|
static struct retu_wdt_dev *retu_wdt;
|
|
|
|
-static void retu_wdt_set_ping_timer(unsigned long enable);
|
|
-
|
|
static int _retu_modify_counter(unsigned int new)
|
|
{
|
|
if (retu_wdt)
|
|
@@ -86,6 +84,31 @@ static int retu_modify_counter(unsigned
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Since retu watchdog cannot be disabled in hardware, we must kick it
|
|
+ * with a timer until userspace watchdog software takes over. Do this
|
|
+ * unless /dev/watchdog is open or CONFIG_WATCHDOG_NOWAYOUT is set.
|
|
+ */
|
|
+static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
|
|
+{
|
|
+ _retu_modify_counter(RETU_WDT_MAX_TIMER);
|
|
+ schedule_delayed_work(&wdev->ping_work,
|
|
+ round_jiffies_relative(RETU_WDT_DEFAULT_TIMER * HZ));
|
|
+}
|
|
+
|
|
+static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
|
|
+{
|
|
+ _retu_modify_counter(RETU_WDT_MAX_TIMER);
|
|
+ cancel_delayed_work_sync(&wdev->ping_work);
|
|
+}
|
|
+
|
|
+static void retu_wdt_ping_work(struct work_struct *work)
|
|
+{
|
|
+ struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
|
|
+ struct retu_wdt_dev, ping_work);
|
|
+ retu_wdt_ping_enable(wdev);
|
|
+}
|
|
+
|
|
static ssize_t retu_wdt_period_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
@@ -105,7 +128,7 @@ static ssize_t retu_wdt_period_store(str
|
|
int ret;
|
|
|
|
#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
|
- retu_wdt_set_ping_timer(0);
|
|
+ retu_wdt_ping_disable(retu_wdt);
|
|
#endif
|
|
|
|
if (sscanf(buf, "%u", &new_period) != 1) {
|
|
@@ -136,30 +159,13 @@ static DEVICE_ATTR(period, S_IRUGO | S_I
|
|
retu_wdt_period_store);
|
|
static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL);
|
|
|
|
-/*----------------------------------------------------------------------------*/
|
|
-
|
|
-/*
|
|
- * Since retu watchdog cannot be disabled in hardware, we must kick it
|
|
- * with a timer until userspace watchdog software takes over. Do this
|
|
- * unless /dev/watchdog is open or CONFIG_WATCHDOG_NOWAYOUT is set.
|
|
- */
|
|
-static void retu_wdt_set_ping_timer(unsigned long enable)
|
|
-{
|
|
- _retu_modify_counter(RETU_WDT_MAX_TIMER);
|
|
- if (enable)
|
|
- mod_timer(&retu_wdt->ping_timer,
|
|
- jiffies + RETU_WDT_DEFAULT_TIMER * HZ);
|
|
- else
|
|
- del_timer_sync(&retu_wdt->ping_timer);
|
|
-}
|
|
-
|
|
static int retu_wdt_open(struct inode *inode, struct file *file)
|
|
{
|
|
if (test_and_set_bit(1, (unsigned long *)&(retu_wdt->users)))
|
|
return -EBUSY;
|
|
|
|
file->private_data = (void *)retu_wdt;
|
|
- retu_wdt_set_ping_timer(0);
|
|
+ retu_wdt_ping_disable(retu_wdt);
|
|
|
|
return nonseekable_open(inode, file);
|
|
}
|
|
@@ -169,7 +175,7 @@ static int retu_wdt_release(struct inode
|
|
struct retu_wdt_dev *wdev = file->private_data;
|
|
|
|
#ifndef CONFIG_WATCHDOG_NOWAYOUT
|
|
- retu_wdt_set_ping_timer(1);
|
|
+ retu_wdt_ping_enable(retu_wdt);
|
|
#endif
|
|
wdev->users = 0;
|
|
|
|
@@ -232,7 +238,7 @@ static int __devinit retu_wdt_ping(void)
|
|
#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
|
retu_modify_counter(RETU_WDT_MAX_TIMER);
|
|
#else
|
|
- retu_wdt_set_ping_timer(1);
|
|
+ retu_wdt_ping_enable(retu_wdt);
|
|
#endif
|
|
|
|
return 0;
|
|
@@ -283,7 +289,7 @@ static int __init retu_wdt_probe(struct
|
|
if (ret)
|
|
goto free3;
|
|
|
|
- setup_timer(&wdev->ping_timer, retu_wdt_set_ping_timer, 1);
|
|
+ INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);
|
|
|
|
/* passed as module parameter? */
|
|
ret = retu_modify_counter(counter_param);
|
|
@@ -326,6 +332,7 @@ static int __devexit retu_wdt_remove(str
|
|
misc_deregister(&wdev->retu_wdt_miscdev);
|
|
device_remove_file(&pdev->dev, &dev_attr_period);
|
|
device_remove_file(&pdev->dev, &dev_attr_counter);
|
|
+ cancel_delayed_work_sync(&wdev->ping_work);
|
|
kfree(wdev);
|
|
|
|
return 0;
|