diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-05-10 02:15:08 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-05-10 02:15:08 -0400 |
commit | f9fb360cb3440fb7d22ad7061de4e99235a97e1c (patch) | |
tree | 16c24b4c9b69c4c125e8182be6b01d4cb72519a9 /drivers/watchdog/shwdt.c | |
parent | 1950f499df4eacb5d89cf0151f5edda139b800f4 (diff) |
watchdog: shwdt: Migrate to per-device locking.
Presently we've been using global locking for everything. Push the
locking down to the per-device level in preparation for per-CPU
watchdogs.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/watchdog/shwdt.c')
-rw-r--r-- | drivers/watchdog/shwdt.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 0beabf238d4f..0d734a38d29f 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/spinlock.h> | ||
28 | #include <linux/miscdevice.h> | 29 | #include <linux/miscdevice.h> |
29 | #include <linux/watchdog.h> | 30 | #include <linux/watchdog.h> |
30 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
@@ -65,8 +66,6 @@ | |||
65 | static int clock_division_ratio = WTCSR_CKS_4096; | 66 | static int clock_division_ratio = WTCSR_CKS_4096; |
66 | #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) | 67 | #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) |
67 | 68 | ||
68 | static DEFINE_SPINLOCK(shwdt_lock); | ||
69 | |||
70 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 69 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
71 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 70 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
72 | static bool nowayout = WATCHDOG_NOWAYOUT; | 71 | static bool nowayout = WATCHDOG_NOWAYOUT; |
@@ -75,6 +74,7 @@ static unsigned long next_heartbeat; | |||
75 | struct sh_wdt { | 74 | struct sh_wdt { |
76 | void __iomem *base; | 75 | void __iomem *base; |
77 | struct device *dev; | 76 | struct device *dev; |
77 | spinlock_t lock; | ||
78 | 78 | ||
79 | struct timer_list timer; | 79 | struct timer_list timer; |
80 | 80 | ||
@@ -88,7 +88,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev) | |||
88 | unsigned long flags; | 88 | unsigned long flags; |
89 | u8 csr; | 89 | u8 csr; |
90 | 90 | ||
91 | spin_lock_irqsave(&shwdt_lock, flags); | 91 | spin_lock_irqsave(&wdt->lock, flags); |
92 | 92 | ||
93 | next_heartbeat = jiffies + (heartbeat * HZ); | 93 | next_heartbeat = jiffies + (heartbeat * HZ); |
94 | mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); | 94 | mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); |
@@ -117,7 +117,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev) | |||
117 | csr &= ~RSTCSR_RSTS; | 117 | csr &= ~RSTCSR_RSTS; |
118 | sh_wdt_write_rstcsr(csr); | 118 | sh_wdt_write_rstcsr(csr); |
119 | #endif | 119 | #endif |
120 | spin_unlock_irqrestore(&shwdt_lock, flags); | 120 | spin_unlock_irqrestore(&wdt->lock, flags); |
121 | 121 | ||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
@@ -128,7 +128,7 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev) | |||
128 | unsigned long flags; | 128 | unsigned long flags; |
129 | u8 csr; | 129 | u8 csr; |
130 | 130 | ||
131 | spin_lock_irqsave(&shwdt_lock, flags); | 131 | spin_lock_irqsave(&wdt->lock, flags); |
132 | 132 | ||
133 | del_timer(&wdt->timer); | 133 | del_timer(&wdt->timer); |
134 | 134 | ||
@@ -136,33 +136,35 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev) | |||
136 | csr &= ~WTCSR_TME; | 136 | csr &= ~WTCSR_TME; |
137 | sh_wdt_write_csr(csr); | 137 | sh_wdt_write_csr(csr); |
138 | 138 | ||
139 | spin_unlock_irqrestore(&shwdt_lock, flags); | 139 | spin_unlock_irqrestore(&wdt->lock, flags); |
140 | 140 | ||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int sh_wdt_keepalive(struct watchdog_device *wdt_dev) | 144 | static int sh_wdt_keepalive(struct watchdog_device *wdt_dev) |
145 | { | 145 | { |
146 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
146 | unsigned long flags; | 147 | unsigned long flags; |
147 | 148 | ||
148 | spin_lock_irqsave(&shwdt_lock, flags); | 149 | spin_lock_irqsave(&wdt->lock, flags); |
149 | next_heartbeat = jiffies + (heartbeat * HZ); | 150 | next_heartbeat = jiffies + (heartbeat * HZ); |
150 | spin_unlock_irqrestore(&shwdt_lock, flags); | 151 | spin_unlock_irqrestore(&wdt->lock, flags); |
151 | 152 | ||
152 | return 0; | 153 | return 0; |
153 | } | 154 | } |
154 | 155 | ||
155 | static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t) | 156 | static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t) |
156 | { | 157 | { |
158 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
157 | unsigned long flags; | 159 | unsigned long flags; |
158 | 160 | ||
159 | if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ | 161 | if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ |
160 | return -EINVAL; | 162 | return -EINVAL; |
161 | 163 | ||
162 | spin_lock_irqsave(&shwdt_lock, flags); | 164 | spin_lock_irqsave(&wdt->lock, flags); |
163 | heartbeat = t; | 165 | heartbeat = t; |
164 | wdt_dev->timeout = t; | 166 | wdt_dev->timeout = t; |
165 | spin_unlock_irqrestore(&shwdt_lock, flags); | 167 | spin_unlock_irqrestore(&wdt->lock, flags); |
166 | 168 | ||
167 | return 0; | 169 | return 0; |
168 | } | 170 | } |
@@ -172,7 +174,7 @@ static void sh_wdt_ping(unsigned long data) | |||
172 | struct sh_wdt *wdt = (struct sh_wdt *)data; | 174 | struct sh_wdt *wdt = (struct sh_wdt *)data; |
173 | unsigned long flags; | 175 | unsigned long flags; |
174 | 176 | ||
175 | spin_lock_irqsave(&shwdt_lock, flags); | 177 | spin_lock_irqsave(&wdt->lock, flags); |
176 | if (time_before(jiffies, next_heartbeat)) { | 178 | if (time_before(jiffies, next_heartbeat)) { |
177 | u8 csr; | 179 | u8 csr; |
178 | 180 | ||
@@ -186,7 +188,7 @@ static void sh_wdt_ping(unsigned long data) | |||
186 | } else | 188 | } else |
187 | dev_warn(wdt->dev, "Heartbeat lost! Will not ping " | 189 | dev_warn(wdt->dev, "Heartbeat lost! Will not ping " |
188 | "the watchdog\n"); | 190 | "the watchdog\n"); |
189 | spin_unlock_irqrestore(&shwdt_lock, flags); | 191 | spin_unlock_irqrestore(&wdt->lock, flags); |
190 | } | 192 | } |
191 | 193 | ||
192 | static const struct watchdog_info sh_wdt_info = { | 194 | static const struct watchdog_info sh_wdt_info = { |
@@ -238,12 +240,17 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev) | |||
238 | 240 | ||
239 | wdt->dev = &pdev->dev; | 241 | wdt->dev = &pdev->dev; |
240 | 242 | ||
243 | watchdog_set_nowayout(&sh_wdt_dev, nowayout); | ||
244 | watchdog_set_drvdata(&sh_wdt_dev, wdt); | ||
245 | |||
241 | wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | 246 | wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
242 | if (unlikely(!wdt->base)) { | 247 | if (unlikely(!wdt->base)) { |
243 | rc = -ENXIO; | 248 | rc = -ENXIO; |
244 | goto out_err; | 249 | goto out_err; |
245 | } | 250 | } |
246 | 251 | ||
252 | spin_lock_init(&wdt->lock); | ||
253 | |||
247 | rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); | 254 | rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); |
248 | if (unlikely(rc)) { | 255 | if (unlikely(rc)) { |
249 | /* Default timeout if invalid */ | 256 | /* Default timeout if invalid */ |
@@ -257,9 +264,6 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev) | |||
257 | dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n", | 264 | dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n", |
258 | sh_wdt_dev.timeout, nowayout); | 265 | sh_wdt_dev.timeout, nowayout); |
259 | 266 | ||
260 | watchdog_set_nowayout(&sh_wdt_dev, nowayout); | ||
261 | watchdog_set_drvdata(&sh_wdt_dev, wdt); | ||
262 | |||
263 | rc = watchdog_register_device(&sh_wdt_dev); | 267 | rc = watchdog_register_device(&sh_wdt_dev); |
264 | if (unlikely(rc)) { | 268 | if (unlikely(rc)) { |
265 | dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); | 269 | dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); |