cbus-retu-wdt: Some fixes
SVN-Revision: 25832
This commit is contained in:
parent
3c801b3dc0
commit
d5d6811ac4
3 changed files with 360 additions and 0 deletions
|
@ -0,0 +1,127 @@
|
|||
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;
|
|
@ -0,0 +1,39 @@
|
|||
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:46:24.574676092 +0100
|
||||
+++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-02 16:48:17.469807413 +0100
|
||||
@@ -56,7 +56,7 @@ static int counter_param = RETU_WDT_MAX_
|
||||
|
||||
struct retu_wdt_dev {
|
||||
struct device *dev;
|
||||
- int users;
|
||||
+ unsigned long users;
|
||||
struct miscdevice retu_wdt_miscdev;
|
||||
struct delayed_work ping_work;
|
||||
};
|
||||
@@ -161,7 +161,7 @@ static DEVICE_ATTR(counter, S_IRUGO, ret
|
||||
|
||||
static int retu_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- if (test_and_set_bit(1, (unsigned long *)&(retu_wdt->users)))
|
||||
+ if (test_and_set_bit(0, &retu_wdt->users))
|
||||
return -EBUSY;
|
||||
|
||||
file->private_data = (void *)retu_wdt;
|
||||
@@ -177,7 +177,7 @@ static int retu_wdt_release(struct inode
|
||||
#ifndef CONFIG_WATCHDOG_NOWAYOUT
|
||||
retu_wdt_ping_enable(retu_wdt);
|
||||
#endif
|
||||
- wdev->users = 0;
|
||||
+ clear_bit(0, &retu_wdt->users);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -264,7 +264,6 @@ static int __init retu_wdt_probe(struct
|
||||
return -ENOMEM;
|
||||
|
||||
wdev->dev = &pdev->dev;
|
||||
- wdev->users = 0;
|
||||
|
||||
ret = device_create_file(&pdev->dev, &dev_attr_period);
|
||||
if (ret) {
|
|
@ -0,0 +1,194 @@
|
|||
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:49:51.231863891 +0100
|
||||
+++ linux-2.6.38-rc6/drivers/cbus/retu-wdt.c 2011-03-02 16:53:47.189454637 +0100
|
||||
@@ -52,7 +52,6 @@ static DEFINE_MUTEX(retu_wdt_mutex);
|
||||
|
||||
/* Current period of watchdog */
|
||||
static unsigned int period_val = RETU_WDT_DEFAULT_TIMER;
|
||||
-static int counter_param = RETU_WDT_MAX_TIMER;
|
||||
|
||||
struct retu_wdt_dev {
|
||||
struct device *dev;
|
||||
@@ -109,56 +108,6 @@ static void retu_wdt_ping_work(struct wo
|
||||
retu_wdt_ping_enable(wdev);
|
||||
}
|
||||
|
||||
-static ssize_t retu_wdt_period_show(struct device *dev,
|
||||
- struct device_attribute *attr, char *buf)
|
||||
-{
|
||||
- /* Show current max counter */
|
||||
- return sprintf(buf, "%u\n", (u16)period_val);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Note: This inteface is non-standard and likely to disappear!
|
||||
- * Use /dev/watchdog instead, that's the standard.
|
||||
- */
|
||||
-static ssize_t retu_wdt_period_store(struct device *dev,
|
||||
- struct device_attribute *attr,
|
||||
- const char *buf, size_t count)
|
||||
-{
|
||||
- unsigned int new_period;
|
||||
- int ret;
|
||||
-
|
||||
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
||||
- retu_wdt_ping_disable(retu_wdt);
|
||||
-#endif
|
||||
-
|
||||
- if (sscanf(buf, "%u", &new_period) != 1) {
|
||||
- printk(KERN_ALERT "retu_wdt_period_store: Invalid input\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- ret = retu_modify_counter(new_period);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- return strnlen(buf, count);
|
||||
-}
|
||||
-
|
||||
-static ssize_t retu_wdt_counter_show(struct device *dev,
|
||||
- struct device_attribute *attr, char *buf)
|
||||
-{
|
||||
- u16 counter;
|
||||
-
|
||||
- /* Show current value in watchdog counter */
|
||||
- counter = retu_read_reg(dev, RETU_REG_WATCHDOG);
|
||||
-
|
||||
- /* Only the 5 LSB are important */
|
||||
- return snprintf(buf, PAGE_SIZE, "%u\n", (counter & 0x3F));
|
||||
-}
|
||||
-
|
||||
-static DEVICE_ATTR(period, S_IRUGO | S_IWUSR, retu_wdt_period_show, \
|
||||
- retu_wdt_period_store);
|
||||
-static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL);
|
||||
-
|
||||
static int retu_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(0, &retu_wdt->users))
|
||||
@@ -175,9 +124,9 @@ static int retu_wdt_release(struct inode
|
||||
struct retu_wdt_dev *wdev = file->private_data;
|
||||
|
||||
#ifndef CONFIG_WATCHDOG_NOWAYOUT
|
||||
- retu_wdt_ping_enable(retu_wdt);
|
||||
+ retu_wdt_ping_enable(wdev);
|
||||
#endif
|
||||
- clear_bit(0, &retu_wdt->users);
|
||||
+ clear_bit(0, &wdev->users);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -232,18 +181,6 @@ static long retu_wdt_ioctl(struct file *
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Start kicking retu watchdog until user space starts doing the kicking */
|
||||
-static int __devinit retu_wdt_ping(void)
|
||||
-{
|
||||
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
||||
- retu_modify_counter(RETU_WDT_MAX_TIMER);
|
||||
-#else
|
||||
- retu_wdt_ping_enable(retu_wdt);
|
||||
-#endif
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static const struct file_operations retu_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = retu_wdt_write,
|
||||
@@ -252,8 +189,6 @@ static const struct file_operations retu
|
||||
.release = retu_wdt_release,
|
||||
};
|
||||
|
||||
-/*----------------------------------------------------------------------------*/
|
||||
-
|
||||
static int __init retu_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct retu_wdt_dev *wdev;
|
||||
@@ -265,18 +200,6 @@ static int __init retu_wdt_probe(struct
|
||||
|
||||
wdev->dev = &pdev->dev;
|
||||
|
||||
- ret = device_create_file(&pdev->dev, &dev_attr_period);
|
||||
- if (ret) {
|
||||
- dev_err(&pdev->dev, "Error creating sysfs period\n");
|
||||
- goto free1;
|
||||
- }
|
||||
-
|
||||
- ret = device_create_file(&pdev->dev, &dev_attr_counter);
|
||||
- if (ret) {
|
||||
- dev_err(&pdev->dev, "Error creating sysfs counter\n");
|
||||
- goto free2;
|
||||
- }
|
||||
-
|
||||
platform_set_drvdata(pdev, wdev);
|
||||
retu_wdt = wdev;
|
||||
wdev->retu_wdt_miscdev.parent = &pdev->dev;
|
||||
@@ -286,38 +209,21 @@ static int __init retu_wdt_probe(struct
|
||||
|
||||
ret = misc_register(&(wdev->retu_wdt_miscdev));
|
||||
if (ret)
|
||||
- goto free3;
|
||||
+ goto err_free_wdev;
|
||||
|
||||
INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);
|
||||
|
||||
- /* passed as module parameter? */
|
||||
- ret = retu_modify_counter(counter_param);
|
||||
- if (ret == -EINVAL) {
|
||||
- ret = retu_modify_counter(RETU_WDT_DEFAULT_TIMER);
|
||||
- dev_dbg(&pdev->dev, "Initializing to default value\n");
|
||||
- }
|
||||
-
|
||||
- /* Kick the watchdog for kernel booting to finish */
|
||||
+ /* Kick the watchdog for kernel booting to finish.
|
||||
+ * If nowayout is not set, we start the ping work. */
|
||||
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
||||
retu_modify_counter(RETU_WDT_MAX_TIMER);
|
||||
-
|
||||
- ret = retu_wdt_ping();
|
||||
- if (ret < 0) {
|
||||
- dev_err(&pdev->dev, "Failed to ping\n");
|
||||
- goto free4;
|
||||
- }
|
||||
+#else
|
||||
+ retu_wdt_ping_enable(retu_wdt);
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
|
||||
-free4:
|
||||
- misc_deregister(&wdev->retu_wdt_miscdev);
|
||||
-
|
||||
-free3:
|
||||
- device_remove_file(&pdev->dev, &dev_attr_counter);
|
||||
-
|
||||
-free2:
|
||||
- device_remove_file(&pdev->dev, &dev_attr_period);
|
||||
-
|
||||
-free1:
|
||||
+err_free_wdev:
|
||||
kfree(wdev);
|
||||
|
||||
return ret;
|
||||
@@ -329,8 +235,6 @@ static int __devexit retu_wdt_remove(str
|
||||
|
||||
wdev = platform_get_drvdata(pdev);
|
||||
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);
|
||||
|
||||
@@ -356,9 +260,7 @@ static void __exit retu_wdt_exit(void)
|
||||
|
||||
module_init(retu_wdt_init);
|
||||
module_exit(retu_wdt_exit);
|
||||
-module_param(counter_param, int, 0);
|
||||
|
||||
MODULE_DESCRIPTION("Retu WatchDog");
|
||||
MODULE_AUTHOR("Amit Kucheria");
|
||||
MODULE_LICENSE("GPL");
|
||||
-
|
Loading…
Reference in a new issue