diff options
Diffstat (limited to 'drivers/watchdog/ixp4xx_wdt.c')
-rw-r--r-- | drivers/watchdog/ixp4xx_wdt.c | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 5864bb865cfe..24e624c847ae 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c | |||
@@ -30,40 +30,40 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
30 | static int heartbeat = 60; /* (secs) Default is 1 minute */ | 30 | static int heartbeat = 60; /* (secs) Default is 1 minute */ |
31 | static unsigned long wdt_status; | 31 | static unsigned long wdt_status; |
32 | static unsigned long boot_status; | 32 | static unsigned long boot_status; |
33 | static spin_lock_t wdt_lock; | ||
33 | 34 | ||
34 | #define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL) | 35 | #define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL) |
35 | 36 | ||
36 | #define WDT_IN_USE 0 | 37 | #define WDT_IN_USE 0 |
37 | #define WDT_OK_TO_CLOSE 1 | 38 | #define WDT_OK_TO_CLOSE 1 |
38 | 39 | ||
39 | static void | 40 | static void wdt_enable(void) |
40 | wdt_enable(void) | ||
41 | { | 41 | { |
42 | spin_lock(&wdt_lock); | ||
42 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; | 43 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; |
43 | *IXP4XX_OSWE = 0; | 44 | *IXP4XX_OSWE = 0; |
44 | *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat; | 45 | *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat; |
45 | *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE; | 46 | *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE; |
46 | *IXP4XX_OSWK = 0; | 47 | *IXP4XX_OSWK = 0; |
48 | spin_unlock(&wdt_lock); | ||
47 | } | 49 | } |
48 | 50 | ||
49 | static void | 51 | static void wdt_disable(void) |
50 | wdt_disable(void) | ||
51 | { | 52 | { |
53 | spin_lock(&wdt_lock); | ||
52 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; | 54 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; |
53 | *IXP4XX_OSWE = 0; | 55 | *IXP4XX_OSWE = 0; |
54 | *IXP4XX_OSWK = 0; | 56 | *IXP4XX_OSWK = 0; |
57 | spin_unlock(&wdt_lock); | ||
55 | } | 58 | } |
56 | 59 | ||
57 | static int | 60 | static int ixp4xx_wdt_open(struct inode *inode, struct file *file) |
58 | ixp4xx_wdt_open(struct inode *inode, struct file *file) | ||
59 | { | 61 | { |
60 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 62 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
61 | return -EBUSY; | 63 | return -EBUSY; |
62 | 64 | ||
63 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 65 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
64 | |||
65 | wdt_enable(); | 66 | wdt_enable(); |
66 | |||
67 | return nonseekable_open(inode, file); | 67 | return nonseekable_open(inode, file); |
68 | } | 68 | } |
69 | 69 | ||
@@ -87,7 +87,6 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | |||
87 | } | 87 | } |
88 | wdt_enable(); | 88 | wdt_enable(); |
89 | } | 89 | } |
90 | |||
91 | return len; | 90 | return len; |
92 | } | 91 | } |
93 | 92 | ||
@@ -98,9 +97,8 @@ static struct watchdog_info ident = { | |||
98 | }; | 97 | }; |
99 | 98 | ||
100 | 99 | ||
101 | static int | 100 | static long ixp4xx_wdt_ioctl(struct file *file, unsigned int cmd, |
102 | ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 101 | unsigned long arg) |
103 | unsigned long arg) | ||
104 | { | 102 | { |
105 | int ret = -ENOTTY; | 103 | int ret = -ENOTTY; |
106 | int time; | 104 | int time; |
@@ -145,16 +143,13 @@ ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
145 | return ret; | 143 | return ret; |
146 | } | 144 | } |
147 | 145 | ||
148 | static int | 146 | static int ixp4xx_wdt_release(struct inode *inode, struct file *file) |
149 | ixp4xx_wdt_release(struct inode *inode, struct file *file) | ||
150 | { | 147 | { |
151 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { | 148 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
152 | wdt_disable(); | 149 | wdt_disable(); |
153 | } else { | 150 | else |
154 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 151 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
155 | "timer will not stop\n"); | 152 | "timer will not stop\n"); |
156 | } | ||
157 | |||
158 | clear_bit(WDT_IN_USE, &wdt_status); | 153 | clear_bit(WDT_IN_USE, &wdt_status); |
159 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 154 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
160 | 155 | ||
@@ -167,7 +162,7 @@ static const struct file_operations ixp4xx_wdt_fops = | |||
167 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
168 | .llseek = no_llseek, | 163 | .llseek = no_llseek, |
169 | .write = ixp4xx_wdt_write, | 164 | .write = ixp4xx_wdt_write, |
170 | .ioctl = ixp4xx_wdt_ioctl, | 165 | .unlocked_ioctl = ixp4xx_wdt_ioctl, |
171 | .open = ixp4xx_wdt_open, | 166 | .open = ixp4xx_wdt_open, |
172 | .release = ixp4xx_wdt_release, | 167 | .release = ixp4xx_wdt_release, |
173 | }; | 168 | }; |
@@ -191,14 +186,12 @@ static int __init ixp4xx_wdt_init(void) | |||
191 | 186 | ||
192 | return -ENODEV; | 187 | return -ENODEV; |
193 | } | 188 | } |
194 | 189 | spin_lock_init(&wdt_lock); | |
190 | boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? | ||
191 | WDIOF_CARDRESET : 0; | ||
195 | ret = misc_register(&ixp4xx_wdt_miscdev); | 192 | ret = misc_register(&ixp4xx_wdt_miscdev); |
196 | if (ret == 0) | 193 | if (ret == 0) |
197 | printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat); | 194 | printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat); |
198 | |||
199 | boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? | ||
200 | WDIOF_CARDRESET : 0; | ||
201 | |||
202 | return ret; | 195 | return ret; |
203 | } | 196 | } |
204 | 197 | ||