From d5d6811ac49b533e7fb996b513c406d8fe75a85e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20B=C3=BCsch?= <mb@bu3sch.de>
Date: Wed, 2 Mar 2011 16:20:58 +0000
Subject: [PATCH] cbus-retu-wdt: Some fixes

SVN-Revision: 25832
---
 .../530-cbus-retu-wdt-preemptible.patch       | 127 ++++++++++++
 .../531-cbus-retu-wdt-fix-bitfield.patch      |  39 ++++
 .../535-cbus-retu-wdt-cleanup.patch           | 194 ++++++++++++++++++
 3 files changed, 360 insertions(+)
 create mode 100644 target/linux/omap24xx/patches-2.6.38/530-cbus-retu-wdt-preemptible.patch
 create mode 100644 target/linux/omap24xx/patches-2.6.38/531-cbus-retu-wdt-fix-bitfield.patch
 create mode 100644 target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch

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
index 0000000000..fecbd09a76
--- /dev/null
+++ b/target/linux/omap24xx/patches-2.6.38/530-cbus-retu-wdt-preemptible.patch
@@ -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
index 0000000000..6de2c79f1a
--- /dev/null
+++ b/target/linux/omap24xx/patches-2.6.38/531-cbus-retu-wdt-fix-bitfield.patch
@@ -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
index 0000000000..4b650686fd
--- /dev/null
+++ b/target/linux/omap24xx/patches-2.6.38/535-cbus-retu-wdt-cleanup.patch
@@ -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");
+-
-- 
GitLab