diff options
Diffstat (limited to 'drivers/char/watchdog/sa1100_wdt.c')
-rw-r--r-- | drivers/char/watchdog/sa1100_wdt.c | 53 |
1 files changed, 10 insertions, 43 deletions
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 34e8f7b15e30..fb88b4041dca 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c | |||
@@ -36,17 +36,10 @@ | |||
36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
37 | 37 | ||
38 | #define OSCR_FREQ CLOCK_TICK_RATE | 38 | #define OSCR_FREQ CLOCK_TICK_RATE |
39 | #define SA1100_CLOSE_MAGIC (0x5afc4453) | ||
40 | 39 | ||
41 | static unsigned long sa1100wdt_users; | 40 | static unsigned long sa1100wdt_users; |
42 | static int expect_close; | ||
43 | static int pre_margin; | 41 | static int pre_margin; |
44 | static int boot_status; | 42 | static int boot_status; |
45 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
46 | static int nowayout = 1; | ||
47 | #else | ||
48 | static int nowayout = 0; | ||
49 | #endif | ||
50 | 43 | ||
51 | /* | 44 | /* |
52 | * Allow only one person to hold it open | 45 | * Allow only one person to hold it open |
@@ -66,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) | |||
66 | } | 59 | } |
67 | 60 | ||
68 | /* | 61 | /* |
69 | * Shut off the timer. | 62 | * The watchdog cannot be disabled. |
70 | * Lock it in if it's a module and we defined ...NOWAYOUT | 63 | * |
71 | * Oddly, the watchdog can only be enabled, but we can turn off | 64 | * Previous comments suggested that turning off the interrupt by |
72 | * the interrupt, which appears to prevent the watchdog timing out. | 65 | * clearing OIER[E3] would prevent the watchdog timing out but this |
66 | * does not appear to be true (at least on the PXA255). | ||
73 | */ | 67 | */ |
74 | static int sa1100dog_release(struct inode *inode, struct file *file) | 68 | static int sa1100dog_release(struct inode *inode, struct file *file) |
75 | { | 69 | { |
76 | OSMR3 = OSCR + pre_margin; | 70 | printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); |
77 | |||
78 | if (expect_close == SA1100_CLOSE_MAGIC) { | ||
79 | OIER &= ~OIER_E3; | ||
80 | } else { | ||
81 | printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); | ||
82 | } | ||
83 | 71 | ||
84 | clear_bit(1, &sa1100wdt_users); | 72 | clear_bit(1, &sa1100wdt_users); |
85 | expect_close = 0; | ||
86 | 73 | ||
87 | return 0; | 74 | return 0; |
88 | } | 75 | } |
89 | 76 | ||
90 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 77 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) |
91 | { | 78 | { |
92 | if (len) { | 79 | if (len) |
93 | if (!nowayout) { | ||
94 | size_t i; | ||
95 | |||
96 | expect_close = 0; | ||
97 | |||
98 | for (i = 0; i != len; i++) { | ||
99 | char c; | ||
100 | |||
101 | if (get_user(c, data + i)) | ||
102 | return -EFAULT; | ||
103 | if (c == 'V') | ||
104 | expect_close = SA1100_CLOSE_MAGIC; | ||
105 | } | ||
106 | } | ||
107 | /* Refresh OSMR3 timer. */ | 80 | /* Refresh OSMR3 timer. */ |
108 | OSMR3 = OSCR + pre_margin; | 81 | OSMR3 = OSCR + pre_margin; |
109 | } | ||
110 | 82 | ||
111 | return len; | 83 | return len; |
112 | } | 84 | } |
113 | 85 | ||
114 | static struct watchdog_info ident = { | 86 | static struct watchdog_info ident = { |
115 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | | 87 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
116 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 88 | .identity = "SA1100/PXA255 Watchdog", |
117 | .identity = "SA1100 Watchdog", | ||
118 | }; | 89 | }; |
119 | 90 | ||
120 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, | 91 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, |
@@ -176,7 +147,7 @@ static struct file_operations sa1100dog_fops = | |||
176 | static struct miscdevice sa1100dog_miscdev = | 147 | static struct miscdevice sa1100dog_miscdev = |
177 | { | 148 | { |
178 | .minor = WATCHDOG_MINOR, | 149 | .minor = WATCHDOG_MINOR, |
179 | .name = "SA1100/PXA2xx watchdog", | 150 | .name = "watchdog", |
180 | .fops = &sa1100dog_fops, | 151 | .fops = &sa1100dog_fops, |
181 | }; | 152 | }; |
182 | 153 | ||
@@ -198,7 +169,6 @@ static int __init sa1100dog_init(void) | |||
198 | if (ret == 0) | 169 | if (ret == 0) |
199 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", | 170 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", |
200 | margin); | 171 | margin); |
201 | |||
202 | return ret; | 172 | return ret; |
203 | } | 173 | } |
204 | 174 | ||
@@ -216,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); | |||
216 | module_param(margin, int, 0); | 186 | module_param(margin, int, 0); |
217 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); | 187 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
218 | 188 | ||
219 | module_param(nowayout, int, 0); | ||
220 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
221 | |||
222 | MODULE_LICENSE("GPL"); | 189 | MODULE_LICENSE("GPL"); |
223 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 190 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |