omap24xx: Fix n810 boot
[openwrt.git] / target / linux / omap24xx / patches-2.6.38 / 530-cbus-retu-wdt-preemptible.patch
1 --- a/drivers/cbus/retu-wdt.c
2 +++ b/drivers/cbus/retu-wdt.c
3 @@ -58,13 +58,11 @@ struct retu_wdt_dev {
4         struct device           *dev;
5         int                     users;
6         struct miscdevice       retu_wdt_miscdev;
7 -       struct timer_list       ping_timer;
8 +       struct delayed_work     ping_work;
9  };
10  
11  static struct retu_wdt_dev *retu_wdt;
12  
13 -static void retu_wdt_set_ping_timer(unsigned long enable);
14 -
15  static int _retu_modify_counter(unsigned int new)
16  {
17         if (retu_wdt)
18 @@ -86,6 +84,31 @@ static int retu_modify_counter(unsigned
19         return 0;
20  }
21  
22 +/*
23 + * Since retu watchdog cannot be disabled in hardware, we must kick it
24 + * with a timer until userspace watchdog software takes over. Do this
25 + * unless /dev/watchdog is open or CONFIG_WATCHDOG_NOWAYOUT is set.
26 + */
27 +static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
28 +{
29 +       _retu_modify_counter(RETU_WDT_MAX_TIMER);
30 +       schedule_delayed_work(&wdev->ping_work,
31 +                             round_jiffies_relative(RETU_WDT_DEFAULT_TIMER * HZ));
32 +}
33 +
34 +static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
35 +{
36 +       _retu_modify_counter(RETU_WDT_MAX_TIMER);
37 +       cancel_delayed_work_sync(&wdev->ping_work);
38 +}
39 +
40 +static void retu_wdt_ping_work(struct work_struct *work)
41 +{
42 +       struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
43 +                                       struct retu_wdt_dev, ping_work);
44 +       retu_wdt_ping_enable(wdev);
45 +}
46 +
47  static ssize_t retu_wdt_period_show(struct device *dev,
48                                 struct device_attribute *attr, char *buf)
49  {
50 @@ -105,7 +128,7 @@ static ssize_t retu_wdt_period_store(str
51         int ret;
52  
53  #ifdef CONFIG_WATCHDOG_NOWAYOUT
54 -       retu_wdt_set_ping_timer(0);
55 +       retu_wdt_ping_disable(retu_wdt);
56  #endif
57  
58         if (sscanf(buf, "%u", &new_period) != 1) {
59 @@ -136,30 +159,13 @@ static DEVICE_ATTR(period, S_IRUGO | S_I
60                         retu_wdt_period_store);
61  static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL);
62  
63 -/*----------------------------------------------------------------------------*/
64 -
65 -/*
66 - * Since retu watchdog cannot be disabled in hardware, we must kick it
67 - * with a timer until userspace watchdog software takes over. Do this
68 - * unless /dev/watchdog is open or CONFIG_WATCHDOG_NOWAYOUT is set.
69 - */
70 -static void retu_wdt_set_ping_timer(unsigned long enable)
71 -{
72 -       _retu_modify_counter(RETU_WDT_MAX_TIMER);
73 -       if (enable)
74 -               mod_timer(&retu_wdt->ping_timer,
75 -                               jiffies + RETU_WDT_DEFAULT_TIMER * HZ);
76 -       else
77 -               del_timer_sync(&retu_wdt->ping_timer);
78 -}
79 -
80  static int retu_wdt_open(struct inode *inode, struct file *file)
81  {
82         if (test_and_set_bit(1, (unsigned long *)&(retu_wdt->users)))
83                 return -EBUSY;
84  
85         file->private_data = (void *)retu_wdt;
86 -       retu_wdt_set_ping_timer(0);
87 +       retu_wdt_ping_disable(retu_wdt);
88  
89         return nonseekable_open(inode, file);
90  }
91 @@ -169,7 +175,7 @@ static int retu_wdt_release(struct inode
92         struct retu_wdt_dev *wdev = file->private_data;
93  
94  #ifndef CONFIG_WATCHDOG_NOWAYOUT
95 -       retu_wdt_set_ping_timer(1);
96 +       retu_wdt_ping_enable(retu_wdt);
97  #endif
98         wdev->users = 0;
99  
100 @@ -232,7 +238,7 @@ static int __devinit retu_wdt_ping(void)
101  #ifdef CONFIG_WATCHDOG_NOWAYOUT
102         retu_modify_counter(RETU_WDT_MAX_TIMER);
103  #else
104 -       retu_wdt_set_ping_timer(1);
105 +       retu_wdt_ping_enable(retu_wdt);
106  #endif
107  
108         return 0;
109 @@ -283,7 +289,7 @@ static int __init retu_wdt_probe(struct
110         if (ret)
111                 goto free3;
112  
113 -       setup_timer(&wdev->ping_timer, retu_wdt_set_ping_timer, 1);
114 +       INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);
115  
116         /* passed as module parameter? */
117         ret = retu_modify_counter(counter_param);
118 @@ -326,6 +332,7 @@ static int __devexit retu_wdt_remove(str
119         misc_deregister(&wdev->retu_wdt_miscdev);
120         device_remove_file(&pdev->dev, &dev_attr_period);
121         device_remove_file(&pdev->dev, &dev_attr_counter);
122 +       cancel_delayed_work_sync(&wdev->ping_work);
123         kfree(wdev);
124  
125         return 0;