diff options
Diffstat (limited to 'target/linux/rdc/patches-2.6.32/110-rdc321x_watchdog_fix.patch')
-rw-r--r-- | target/linux/rdc/patches-2.6.32/110-rdc321x_watchdog_fix.patch | 313 |
1 files changed, 0 insertions, 313 deletions
diff --git a/target/linux/rdc/patches-2.6.32/110-rdc321x_watchdog_fix.patch b/target/linux/rdc/patches-2.6.32/110-rdc321x_watchdog_fix.patch deleted file mode 100644 index fe7969e..0000000 --- a/target/linux/rdc/patches-2.6.32/110-rdc321x_watchdog_fix.patch +++ /dev/null @@ -1,313 +0,0 @@ ---- a/drivers/watchdog/rdc321x_wdt.c -+++ b/drivers/watchdog/rdc321x_wdt.c -@@ -36,111 +36,99 @@ - #include <linux/watchdog.h> - #include <linux/io.h> - #include <linux/uaccess.h> -+#include <linux/pci.h> -+#include <linux/delay.h> - #include <linux/mfd/rdc321x.h> - --#define RDC_WDT_MASK 0x80000000 /* Mask */ -+#define RDC321X_WDT_REG 0x00000044 -+ - #define RDC_WDT_EN 0x00800000 /* Enable bit */ --#define RDC_WDT_WTI 0x00200000 /* Generate CPU reset/NMI/WDT on timeout */ --#define RDC_WDT_RST 0x00100000 /* Reset bit */ --#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */ --#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */ --#define RDC_WDT_CNT 0x00000001 /* WDT count */ -+#define RDC_WDT_WDTIRQ 0x00400000 /* Create WDT IRQ before CPU reset */ -+#define RDC_WDT_NMIIRQ 0x00200000 /* Create NMI IRQ before CPU reset */ -+#define RDC_WDT_RST 0x00100000 /* Reset wdt */ -+#define RDC_WDT_NIF 0x00080000 /* NMI interrupt occured */ -+#define RDC_WDT_WIF 0x00040000 /* WDT interrupt occured */ -+#define RDC_WDT_IRT 0x00000700 /* IRQ Routing table */ -+#define RDC_WDT_CNT 0x0000007F /* WDT count */ - --#define RDC_CLS_TMR 0x80003844 /* Clear timer */ -+/* default counter value (2.34 s) */ -+#define RDC_WDT_DFLT_CNT 0x00000040 - --#define RDC_WDT_INTERVAL (HZ/10+1) -+#define RDC_WDT_SETUP (RDC_WDT_EN | RDC_WDT_NMIIRQ | RDC_WDT_RST | RDC_WDT_DFLT_CNT) - - static int ticks = 1000; - - /* some device data */ - - static struct { -- struct completion stop; -- int running; - struct timer_list timer; -- int queue; -- int default_ticks; -- unsigned long inuse; -- spinlock_t lock; -+ int seconds_left; -+ int total_seconds; -+ bool inuse; -+ bool running; -+ bool close_expected; -+ - struct pci_dev *sb_pdev; - int base_reg; - } rdc321x_wdt_device; - --/* generic helper functions */ -+static struct watchdog_info ident = { -+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, -+ .identity = "RDC321x WDT", -+}; - --static void rdc321x_wdt_trigger(unsigned long unused) -+ -+/* generic helper functions */ -+static void rdc321x_wdt_timer(unsigned long unused) - { -- unsigned long flags; -- u32 val; -+ if (!rdc321x_wdt_device.running) { -+ pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -+ rdc321x_wdt_device.base_reg, 0); -+ return; -+ } - -- if (rdc321x_wdt_device.running) -- ticks--; -+ rdc321x_wdt_device.seconds_left--; - -- /* keep watchdog alive */ -- spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); -- pci_read_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, &val); -- val |= RDC_WDT_EN; -- pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, val); -- spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); -+ if (rdc321x_wdt_device.seconds_left < 1) -+ return; - -- /* requeue?? */ -- if (rdc321x_wdt_device.queue && ticks) -- mod_timer(&rdc321x_wdt_device.timer, -- jiffies + RDC_WDT_INTERVAL); -- else { -- /* ticks doesn't matter anyway */ -- complete(&rdc321x_wdt_device.stop); -- } -+ pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -+ rdc321x_wdt_device.base_reg, RDC_WDT_SETUP); - -+ mod_timer(&rdc321x_wdt_device.timer, HZ * 2 + jiffies); - } - - static void rdc321x_wdt_reset(void) - { -- ticks = rdc321x_wdt_device.default_ticks; -+ rdc321x_wdt_device.seconds_left = rdc321x_wdt_device.total_seconds; - } - - static void rdc321x_wdt_start(void) - { -- unsigned long flags; -- -- if (!rdc321x_wdt_device.queue) { -- rdc321x_wdt_device.queue = 1; -- -- /* Clear the timer */ -- spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); -- pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, RDC_CLS_TMR); -- -- /* Enable watchdog and set the timeout to 81.92 us */ -- pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, -- RDC_WDT_EN | RDC_WDT_CNT); -- spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); -+ if (rdc321x_wdt_device.running) -+ return; - -- mod_timer(&rdc321x_wdt_device.timer, -- jiffies + RDC_WDT_INTERVAL); -- } -+ rdc321x_wdt_device.seconds_left = rdc321x_wdt_device.total_seconds; -+ rdc321x_wdt_device.running = true; -+ rdc321x_wdt_timer(0); - -- /* if process dies, counter is not decremented */ -- rdc321x_wdt_device.running++; -+ return; - } - - static int rdc321x_wdt_stop(void) - { -- if (rdc321x_wdt_device.running) -- rdc321x_wdt_device.running = 0; -+ if (WATCHDOG_NOWAYOUT) -+ return -ENOSYS; - -- ticks = rdc321x_wdt_device.default_ticks; -+ rdc321x_wdt_device.running = false; - -- return -EIO; -+ return 0; - } - - /* filesystem operations */ - static int rdc321x_wdt_open(struct inode *inode, struct file *file) - { -- if (test_and_set_bit(0, &rdc321x_wdt_device.inuse)) -+ if (xchg(&rdc321x_wdt_device.inuse, true)) - return -EBUSY; - - return nonseekable_open(inode, file); -@@ -148,7 +136,16 @@ static int rdc321x_wdt_open(struct inode - - static int rdc321x_wdt_release(struct inode *inode, struct file *file) - { -- clear_bit(0, &rdc321x_wdt_device.inuse); -+ int ret; -+ -+ if (rdc321x_wdt_device.close_expected) { -+ ret = rdc321x_wdt_stop(); -+ if (ret) -+ return ret; -+ } -+ -+ rdc321x_wdt_device.inuse = false; -+ - return 0; - } - -@@ -156,30 +153,29 @@ static long rdc321x_wdt_ioctl(struct fil - unsigned long arg) - { - void __user *argp = (void __user *)arg; -- u32 value; -- static struct watchdog_info ident = { -- .options = WDIOF_CARDRESET, -- .identity = "RDC321x WDT", -- }; -- unsigned long flags; -+ int value; - - switch (cmd) { - case WDIOC_KEEPALIVE: - rdc321x_wdt_reset(); - break; -- case WDIOC_GETSTATUS: -- /* Read the value from the DATA register */ -- spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); -- pci_read_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, &value); -- spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); -- if (copy_to_user(argp, &value, sizeof(u32))) -- return -EFAULT; -- break; - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &ident, sizeof(ident))) - return -EFAULT; - break; -+ case WDIOC_SETTIMEOUT: -+ if (copy_from_user(&rdc321x_wdt_device.total_seconds, argp, sizeof(int))) -+ return -EFAULT; -+ rdc321x_wdt_device.seconds_left = rdc321x_wdt_device.total_seconds; -+ break; -+ case WDIOC_GETTIMEOUT: -+ if (copy_to_user(argp, &rdc321x_wdt_device.total_seconds, sizeof(int))) -+ return -EFAULT; -+ break; -+ case WDIOC_GETTIMELEFT: -+ if (copy_to_user(argp, &rdc321x_wdt_device.seconds_left, sizeof(int))) -+ return -EFAULT; -+ break; - case WDIOC_SETOPTIONS: - if (copy_from_user(&value, argp, sizeof(int))) - return -EFAULT; -@@ -194,17 +190,34 @@ static long rdc321x_wdt_ioctl(struct fil - } - break; - default: -- return -ENOTTY; -+ return -EINVAL; - } -+ - return 0; - } - - static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) - { -+ size_t i; -+ - if (!count) - return -EIO; - -+ rdc321x_wdt_device.close_expected = false; -+ -+ for (i = 0; i != count; i++) { -+ char c; -+ -+ if (get_user(c, buf + i)) -+ return -EFAULT; -+ -+ if (c == 'V') { -+ rdc321x_wdt_device.close_expected = true; -+ break; -+ } -+ } -+ - rdc321x_wdt_reset(); - - return count; -@@ -246,27 +259,18 @@ static int __devinit rdc321x_wdt_probe(s - rdc321x_wdt_device.sb_pdev = pdata->sb_pdev; - rdc321x_wdt_device.base_reg = r->start; - -+ rdc321x_wdt_device.running = false; -+ rdc321x_wdt_device.close_expected = false; -+ rdc321x_wdt_device.inuse = 0; -+ setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_timer, 0); -+ rdc321x_wdt_device.total_seconds = 100; -+ - err = misc_register(&rdc321x_wdt_misc); - if (err < 0) { - dev_err(&pdev->dev, "misc_register failed\n"); - return err; - } - -- spin_lock_init(&rdc321x_wdt_device.lock); -- -- /* Reset the watchdog */ -- pci_write_config_dword(rdc321x_wdt_device.sb_pdev, -- rdc321x_wdt_device.base_reg, RDC_WDT_RST); -- -- init_completion(&rdc321x_wdt_device.stop); -- rdc321x_wdt_device.queue = 0; -- -- clear_bit(0, &rdc321x_wdt_device.inuse); -- -- setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0); -- -- rdc321x_wdt_device.default_ticks = ticks; -- - dev_info(&pdev->dev, "watchdog init success\n"); - - return 0; -@@ -274,10 +278,11 @@ static int __devinit rdc321x_wdt_probe(s - - static int __devexit rdc321x_wdt_remove(struct platform_device *pdev) - { -- if (rdc321x_wdt_device.queue) { -- rdc321x_wdt_device.queue = 0; -- wait_for_completion(&rdc321x_wdt_device.stop); -- } -+ if (rdc321x_wdt_device.inuse) -+ rdc321x_wdt_device.inuse = 0; -+ -+ while (timer_pending(&rdc321x_wdt_device.timer)) -+ msleep(100); - - misc_deregister(&rdc321x_wdt_misc); - |