diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-03 16:09:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-03 16:09:43 -0400 |
commit | 194d0710e1a7fe92dcf860ddd31fded8c3103b7a (patch) | |
tree | da03b56fa4dee221c53af5770492d391f0d09459 /drivers | |
parent | a68d2ebc1581a3aec57bd032651e013fa609f530 (diff) | |
parent | 9bbd03758945858c9303f3258b418b94c4ffd735 (diff) |
Merge master.kernel.org:/home/rmk/linux-2.6-arm
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/watchdog/sa1100_wdt.c | 49 |
1 files changed, 10 insertions, 39 deletions
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 1b2132617dc3..fb88b4041dca 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c | |||
@@ -36,13 +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 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
46 | 43 | ||
47 | /* | 44 | /* |
48 | * Allow only one person to hold it open | 45 | * Allow only one person to hold it open |
@@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) | |||
62 | } | 59 | } |
63 | 60 | ||
64 | /* | 61 | /* |
65 | * Shut off the timer. | 62 | * The watchdog cannot be disabled. |
66 | * Lock it in if it's a module and we defined ...NOWAYOUT | 63 | * |
67 | * Oddly, the watchdog can only be enabled, but we can turn off | 64 | * Previous comments suggested that turning off the interrupt by |
68 | * 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). | ||
69 | */ | 67 | */ |
70 | static int sa1100dog_release(struct inode *inode, struct file *file) | 68 | static int sa1100dog_release(struct inode *inode, struct file *file) |
71 | { | 69 | { |
72 | OSMR3 = OSCR + pre_margin; | 70 | printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); |
73 | |||
74 | if (expect_close == SA1100_CLOSE_MAGIC) { | ||
75 | OIER &= ~OIER_E3; | ||
76 | } else { | ||
77 | printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); | ||
78 | } | ||
79 | 71 | ||
80 | clear_bit(1, &sa1100wdt_users); | 72 | clear_bit(1, &sa1100wdt_users); |
81 | expect_close = 0; | ||
82 | 73 | ||
83 | return 0; | 74 | return 0; |
84 | } | 75 | } |
85 | 76 | ||
86 | 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) |
87 | { | 78 | { |
88 | if (len) { | 79 | if (len) |
89 | if (!nowayout) { | ||
90 | size_t i; | ||
91 | |||
92 | expect_close = 0; | ||
93 | |||
94 | for (i = 0; i != len; i++) { | ||
95 | char c; | ||
96 | |||
97 | if (get_user(c, data + i)) | ||
98 | return -EFAULT; | ||
99 | if (c == 'V') | ||
100 | expect_close = SA1100_CLOSE_MAGIC; | ||
101 | } | ||
102 | } | ||
103 | /* Refresh OSMR3 timer. */ | 80 | /* Refresh OSMR3 timer. */ |
104 | OSMR3 = OSCR + pre_margin; | 81 | OSMR3 = OSCR + pre_margin; |
105 | } | ||
106 | 82 | ||
107 | return len; | 83 | return len; |
108 | } | 84 | } |
109 | 85 | ||
110 | static struct watchdog_info ident = { | 86 | static struct watchdog_info ident = { |
111 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | | 87 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
112 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 88 | .identity = "SA1100/PXA255 Watchdog", |
113 | .identity = "SA1100 Watchdog", | ||
114 | }; | 89 | }; |
115 | 90 | ||
116 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, | 91 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, |
@@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops = | |||
172 | static struct miscdevice sa1100dog_miscdev = | 147 | static struct miscdevice sa1100dog_miscdev = |
173 | { | 148 | { |
174 | .minor = WATCHDOG_MINOR, | 149 | .minor = WATCHDOG_MINOR, |
175 | .name = "SA1100/PXA2xx watchdog", | 150 | .name = "watchdog", |
176 | .fops = &sa1100dog_fops, | 151 | .fops = &sa1100dog_fops, |
177 | }; | 152 | }; |
178 | 153 | ||
@@ -194,7 +169,6 @@ static int __init sa1100dog_init(void) | |||
194 | if (ret == 0) | 169 | if (ret == 0) |
195 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", | 170 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", |
196 | margin); | 171 | margin); |
197 | |||
198 | return ret; | 172 | return ret; |
199 | } | 173 | } |
200 | 174 | ||
@@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); | |||
212 | module_param(margin, int, 0); | 186 | module_param(margin, int, 0); |
213 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); | 187 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
214 | 188 | ||
215 | module_param(nowayout, int, 0); | ||
216 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
217 | |||
218 | MODULE_LICENSE("GPL"); | 189 | MODULE_LICENSE("GPL"); |
219 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 190 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |