cbus-retu-wdt: Some fixes
authorMichael Büsch <mb@bu3sch.de>
Wed, 2 Mar 2011 16:20:58 +0000 (16:20 +0000)
committerMichael Büsch <mb@bu3sch.de>
Wed, 2 Mar 2011 16:20:58 +0000 (16:20 +0000)
SVN-Revision: 25832

target/linux/omap24xx/patches-2.6.38/530-cbus-retu-wdt-preemptible.patch [new file with mode: 0644]
target/linux/omap24xx/patches-2.6.38/531-cbus-retu-wdt-fix-bitfield.patch [new file with mode: 0644]
target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch [new file with mode: 0644]

diff --git a/target/linux/omap24xx/patches-2.6.38/530-cbus-retu-wdt-preemptible.patch b/target/linux/omap24xx/patches-2.6.38/530-cbus-retu-wdt-preemptible.patch
new file mode 100644 (file)
index 0000000..fecbd09
--- /dev/null
@@ -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;
diff --git a/target/linux/omap24xx/patches-2.6.38/531-cbus-retu-wdt-fix-bitfield.patch b/target/linux/omap24xx/patches-2.6.38/531-cbus-retu-wdt-fix-bitfield.patch
new file mode 100644 (file)
index 0000000..6de2c79
--- /dev/null
@@ -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) {
diff --git a/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch b/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch
new file mode 100644 (file)
index 0000000..4b65068
--- /dev/null
@@ -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");
+-