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