diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 12 | ||||
-rw-r--r-- | drivers/char/istallion.c | 8 | ||||
-rw-r--r-- | drivers/char/mem.c | 28 | ||||
-rw-r--r-- | drivers/char/mxser.c | 8 | ||||
-rw-r--r-- | drivers/char/ppdev.c | 3 | ||||
-rw-r--r-- | drivers/char/riscom8.c | 8 | ||||
-rw-r--r-- | drivers/char/sysrq.c | 250 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 1 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 4 | ||||
-rw-r--r-- | drivers/char/watchdog/Kconfig | 10 | ||||
-rw-r--r-- | drivers/char/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/watchdog/ep93xx_wdt.c | 257 |
12 files changed, 420 insertions, 170 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d745004281d0..abd4c5118a1b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -736,7 +736,8 @@ int ipmi_create_user(unsigned int if_num, | |||
736 | intf = ipmi_interfaces[if_num]; | 736 | intf = ipmi_interfaces[if_num]; |
737 | if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { | 737 | if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { |
738 | spin_unlock_irqrestore(&interfaces_lock, flags); | 738 | spin_unlock_irqrestore(&interfaces_lock, flags); |
739 | return -EINVAL; | 739 | rv = -EINVAL; |
740 | goto out_kfree; | ||
740 | } | 741 | } |
741 | 742 | ||
742 | /* Note that each existing user holds a refcount to the interface. */ | 743 | /* Note that each existing user holds a refcount to the interface. */ |
@@ -751,14 +752,14 @@ int ipmi_create_user(unsigned int if_num, | |||
751 | 752 | ||
752 | if (!try_module_get(intf->handlers->owner)) { | 753 | if (!try_module_get(intf->handlers->owner)) { |
753 | rv = -ENODEV; | 754 | rv = -ENODEV; |
754 | goto out_err; | 755 | goto out_kref; |
755 | } | 756 | } |
756 | 757 | ||
757 | if (intf->handlers->inc_usecount) { | 758 | if (intf->handlers->inc_usecount) { |
758 | rv = intf->handlers->inc_usecount(intf->send_info); | 759 | rv = intf->handlers->inc_usecount(intf->send_info); |
759 | if (rv) { | 760 | if (rv) { |
760 | module_put(intf->handlers->owner); | 761 | module_put(intf->handlers->owner); |
761 | goto out_err; | 762 | goto out_kref; |
762 | } | 763 | } |
763 | } | 764 | } |
764 | 765 | ||
@@ -769,9 +770,10 @@ int ipmi_create_user(unsigned int if_num, | |||
769 | *user = new_user; | 770 | *user = new_user; |
770 | return 0; | 771 | return 0; |
771 | 772 | ||
772 | out_err: | 773 | out_kref: |
773 | kfree(new_user); | ||
774 | kref_put(&intf->refcount, intf_free); | 774 | kref_put(&intf->refcount, intf_free); |
775 | out_kfree: | ||
776 | kfree(new_user); | ||
775 | return rv; | 777 | return rv; |
776 | } | 778 | } |
777 | 779 | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index ede128356af2..e5247f85a446 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -378,13 +378,13 @@ MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver"); | |||
378 | MODULE_LICENSE("GPL"); | 378 | MODULE_LICENSE("GPL"); |
379 | 379 | ||
380 | 380 | ||
381 | MODULE_PARM(board0, "1-3s"); | 381 | module_param_array(board0, charp, NULL, 0); |
382 | MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); | 382 | MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); |
383 | MODULE_PARM(board1, "1-3s"); | 383 | module_param_array(board1, charp, NULL, 0); |
384 | MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); | 384 | MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); |
385 | MODULE_PARM(board2, "1-3s"); | 385 | module_param_array(board2, charp, NULL, 0); |
386 | MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); | 386 | MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); |
387 | MODULE_PARM(board3, "1-3s"); | 387 | module_param_array(board3, charp, NULL, 0); |
388 | MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); | 388 | MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); |
389 | 389 | ||
390 | #endif | 390 | #endif |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 29c41f4418c0..26d0116b48d4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -216,11 +216,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
216 | 216 | ||
217 | copied = copy_from_user(ptr, buf, sz); | 217 | copied = copy_from_user(ptr, buf, sz); |
218 | if (copied) { | 218 | if (copied) { |
219 | ssize_t ret; | 219 | written += sz - copied; |
220 | 220 | if (written) | |
221 | ret = written + (sz - copied); | 221 | break; |
222 | if (ret) | ||
223 | return ret; | ||
224 | return -EFAULT; | 222 | return -EFAULT; |
225 | } | 223 | } |
226 | buf += sz; | 224 | buf += sz; |
@@ -456,11 +454,9 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, | |||
456 | 454 | ||
457 | copied = copy_from_user(ptr, buf, sz); | 455 | copied = copy_from_user(ptr, buf, sz); |
458 | if (copied) { | 456 | if (copied) { |
459 | ssize_t ret; | 457 | written += sz - copied; |
460 | 458 | if (written) | |
461 | ret = written + (sz - copied); | 459 | break; |
462 | if (ret) | ||
463 | return ret; | ||
464 | return -EFAULT; | 460 | return -EFAULT; |
465 | } | 461 | } |
466 | buf += sz; | 462 | buf += sz; |
@@ -514,11 +510,10 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
514 | if (len) { | 510 | if (len) { |
515 | written = copy_from_user(kbuf, buf, len); | 511 | written = copy_from_user(kbuf, buf, len); |
516 | if (written) { | 512 | if (written) { |
517 | ssize_t ret; | 513 | if (wrote + virtr) |
518 | 514 | break; | |
519 | free_page((unsigned long)kbuf); | 515 | free_page((unsigned long)kbuf); |
520 | ret = wrote + virtr + (len - written); | 516 | return -EFAULT; |
521 | return ret ? ret : -EFAULT; | ||
522 | } | 517 | } |
523 | } | 518 | } |
524 | len = vwrite(kbuf, (char *)p, len); | 519 | len = vwrite(kbuf, (char *)p, len); |
@@ -563,8 +558,11 @@ static ssize_t write_port(struct file * file, const char __user * buf, | |||
563 | return -EFAULT; | 558 | return -EFAULT; |
564 | while (count-- > 0 && i < 65536) { | 559 | while (count-- > 0 && i < 65536) { |
565 | char c; | 560 | char c; |
566 | if (__get_user(c, tmp)) | 561 | if (__get_user(c, tmp)) { |
562 | if (tmp > buf) | ||
563 | break; | ||
567 | return -EFAULT; | 564 | return -EFAULT; |
565 | } | ||
568 | outb(c,i); | 566 | outb(c,i); |
569 | i++; | 567 | i++; |
570 | tmp++; | 568 | tmp++; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index ea725a9964e2..0fb2fb9fb024 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -243,10 +243,10 @@ static int verbose = 0; | |||
243 | 243 | ||
244 | MODULE_AUTHOR("Casper Yang"); | 244 | MODULE_AUTHOR("Casper Yang"); |
245 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | 245 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); |
246 | MODULE_PARM(ioaddr, "1-4i"); | 246 | module_param_array(ioaddr, int, NULL, 0); |
247 | MODULE_PARM(ttymajor, "i"); | 247 | module_param(ttymajor, int, 0); |
248 | MODULE_PARM(calloutmajor, "i"); | 248 | module_param(calloutmajor, int, 0); |
249 | MODULE_PARM(verbose, "i"); | 249 | module_param(verbose, bool, 0); |
250 | MODULE_LICENSE("GPL"); | 250 | MODULE_LICENSE("GPL"); |
251 | 251 | ||
252 | struct mxser_log { | 252 | struct mxser_log { |
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 306ee0f091a4..bee6c47b45bd 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -65,10 +65,11 @@ | |||
65 | #include <linux/parport.h> | 65 | #include <linux/parport.h> |
66 | #include <linux/ctype.h> | 66 | #include <linux/ctype.h> |
67 | #include <linux/poll.h> | 67 | #include <linux/poll.h> |
68 | #include <asm/uaccess.h> | 68 | #include <linux/major.h> |
69 | #include <linux/ppdev.h> | 69 | #include <linux/ppdev.h> |
70 | #include <linux/smp_lock.h> | 70 | #include <linux/smp_lock.h> |
71 | #include <linux/device.h> | 71 | #include <linux/device.h> |
72 | #include <asm/uaccess.h> | ||
72 | 73 | ||
73 | #define PP_VERSION "ppdev: user-space parallel port driver" | 74 | #define PP_VERSION "ppdev: user-space parallel port driver" |
74 | #define CHRDEV "ppdev" | 75 | #define CHRDEV "ppdev" |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 119e629656b7..657c0d88f48c 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -1743,10 +1743,10 @@ static int iobase; | |||
1743 | static int iobase1; | 1743 | static int iobase1; |
1744 | static int iobase2; | 1744 | static int iobase2; |
1745 | static int iobase3; | 1745 | static int iobase3; |
1746 | MODULE_PARM(iobase, "i"); | 1746 | module_param(iobase, int, 0); |
1747 | MODULE_PARM(iobase1, "i"); | 1747 | module_param(iobase1, int, 0); |
1748 | MODULE_PARM(iobase2, "i"); | 1748 | module_param(iobase2, int, 0); |
1749 | MODULE_PARM(iobase3, "i"); | 1749 | module_param(iobase3, int, 0); |
1750 | 1750 | ||
1751 | MODULE_LICENSE("GPL"); | 1751 | MODULE_LICENSE("GPL"); |
1752 | #endif /* MODULE */ | 1752 | #endif /* MODULE */ |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index d58f82318853..35082dc12eae 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -42,16 +42,15 @@ | |||
42 | /* Whether we react on sysrq keys or just ignore them */ | 42 | /* Whether we react on sysrq keys or just ignore them */ |
43 | int sysrq_enabled = 1; | 43 | int sysrq_enabled = 1; |
44 | 44 | ||
45 | /* Loglevel sysrq handler */ | ||
46 | static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, | 45 | static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, |
47 | struct tty_struct *tty) | 46 | struct tty_struct *tty) |
48 | { | 47 | { |
49 | int i; | 48 | int i; |
50 | i = key - '0'; | 49 | i = key - '0'; |
51 | console_loglevel = 7; | 50 | console_loglevel = 7; |
52 | printk("Loglevel set to %d\n", i); | 51 | printk("Loglevel set to %d\n", i); |
53 | console_loglevel = i; | 52 | console_loglevel = i; |
54 | } | 53 | } |
55 | static struct sysrq_key_op sysrq_loglevel_op = { | 54 | static struct sysrq_key_op sysrq_loglevel_op = { |
56 | .handler = sysrq_handle_loglevel, | 55 | .handler = sysrq_handle_loglevel, |
57 | .help_msg = "loglevel0-8", | 56 | .help_msg = "loglevel0-8", |
@@ -59,11 +58,9 @@ static struct sysrq_key_op sysrq_loglevel_op = { | |||
59 | .enable_mask = SYSRQ_ENABLE_LOG, | 58 | .enable_mask = SYSRQ_ENABLE_LOG, |
60 | }; | 59 | }; |
61 | 60 | ||
62 | |||
63 | /* SAK sysrq handler */ | ||
64 | #ifdef CONFIG_VT | 61 | #ifdef CONFIG_VT |
65 | static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, | 62 | static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, |
66 | struct tty_struct *tty) | 63 | struct tty_struct *tty) |
67 | { | 64 | { |
68 | if (tty) | 65 | if (tty) |
69 | do_SAK(tty); | 66 | do_SAK(tty); |
@@ -75,12 +72,13 @@ static struct sysrq_key_op sysrq_SAK_op = { | |||
75 | .action_msg = "SAK", | 72 | .action_msg = "SAK", |
76 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, | 73 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
77 | }; | 74 | }; |
75 | #else | ||
76 | #define sysrq_SAK_op (*(struct sysrq_key_op *)0) | ||
78 | #endif | 77 | #endif |
79 | 78 | ||
80 | #ifdef CONFIG_VT | 79 | #ifdef CONFIG_VT |
81 | /* unraw sysrq handler */ | ||
82 | static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, | 80 | static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, |
83 | struct tty_struct *tty) | 81 | struct tty_struct *tty) |
84 | { | 82 | { |
85 | struct kbd_struct *kbd = &kbd_table[fg_console]; | 83 | struct kbd_struct *kbd = &kbd_table[fg_console]; |
86 | 84 | ||
@@ -93,10 +91,11 @@ static struct sysrq_key_op sysrq_unraw_op = { | |||
93 | .action_msg = "Keyboard mode set to XLATE", | 91 | .action_msg = "Keyboard mode set to XLATE", |
94 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, | 92 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
95 | }; | 93 | }; |
94 | #else | ||
95 | #define sysrq_unraw_op (*(struct sysrq_key_op *)0) | ||
96 | #endif /* CONFIG_VT */ | 96 | #endif /* CONFIG_VT */ |
97 | 97 | ||
98 | #ifdef CONFIG_KEXEC | 98 | #ifdef CONFIG_KEXEC |
99 | /* crashdump sysrq handler */ | ||
100 | static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, | 99 | static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, |
101 | struct tty_struct *tty) | 100 | struct tty_struct *tty) |
102 | { | 101 | { |
@@ -108,16 +107,16 @@ static struct sysrq_key_op sysrq_crashdump_op = { | |||
108 | .action_msg = "Trigger a crashdump", | 107 | .action_msg = "Trigger a crashdump", |
109 | .enable_mask = SYSRQ_ENABLE_DUMP, | 108 | .enable_mask = SYSRQ_ENABLE_DUMP, |
110 | }; | 109 | }; |
110 | #else | ||
111 | #define sysrq_crashdump_op (*(struct sysrq_key_op *)0) | ||
111 | #endif | 112 | #endif |
112 | 113 | ||
113 | /* reboot sysrq handler */ | ||
114 | static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, | 114 | static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, |
115 | struct tty_struct *tty) | 115 | struct tty_struct *tty) |
116 | { | 116 | { |
117 | local_irq_enable(); | 117 | local_irq_enable(); |
118 | emergency_restart(); | 118 | emergency_restart(); |
119 | } | 119 | } |
120 | |||
121 | static struct sysrq_key_op sysrq_reboot_op = { | 120 | static struct sysrq_key_op sysrq_reboot_op = { |
122 | .handler = sysrq_handle_reboot, | 121 | .handler = sysrq_handle_reboot, |
123 | .help_msg = "reBoot", | 122 | .help_msg = "reBoot", |
@@ -126,11 +125,10 @@ static struct sysrq_key_op sysrq_reboot_op = { | |||
126 | }; | 125 | }; |
127 | 126 | ||
128 | static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, | 127 | static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, |
129 | struct tty_struct *tty) | 128 | struct tty_struct *tty) |
130 | { | 129 | { |
131 | emergency_sync(); | 130 | emergency_sync(); |
132 | } | 131 | } |
133 | |||
134 | static struct sysrq_key_op sysrq_sync_op = { | 132 | static struct sysrq_key_op sysrq_sync_op = { |
135 | .handler = sysrq_handle_sync, | 133 | .handler = sysrq_handle_sync, |
136 | .help_msg = "Sync", | 134 | .help_msg = "Sync", |
@@ -139,11 +137,10 @@ static struct sysrq_key_op sysrq_sync_op = { | |||
139 | }; | 137 | }; |
140 | 138 | ||
141 | static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, | 139 | static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, |
142 | struct tty_struct *tty) | 140 | struct tty_struct *tty) |
143 | { | 141 | { |
144 | emergency_remount(); | 142 | emergency_remount(); |
145 | } | 143 | } |
146 | |||
147 | static struct sysrq_key_op sysrq_mountro_op = { | 144 | static struct sysrq_key_op sysrq_mountro_op = { |
148 | .handler = sysrq_handle_mountro, | 145 | .handler = sysrq_handle_mountro, |
149 | .help_msg = "Unmount", | 146 | .help_msg = "Unmount", |
@@ -151,28 +148,23 @@ static struct sysrq_key_op sysrq_mountro_op = { | |||
151 | .enable_mask = SYSRQ_ENABLE_REMOUNT, | 148 | .enable_mask = SYSRQ_ENABLE_REMOUNT, |
152 | }; | 149 | }; |
153 | 150 | ||
154 | /* END SYNC SYSRQ HANDLERS BLOCK */ | ||
155 | |||
156 | #ifdef CONFIG_DEBUG_MUTEXES | 151 | #ifdef CONFIG_DEBUG_MUTEXES |
157 | 152 | static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, | |
158 | static void | 153 | struct tty_struct *tty) |
159 | sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty) | ||
160 | { | 154 | { |
161 | mutex_debug_show_all_locks(); | 155 | mutex_debug_show_all_locks(); |
162 | } | 156 | } |
163 | |||
164 | static struct sysrq_key_op sysrq_showlocks_op = { | 157 | static struct sysrq_key_op sysrq_showlocks_op = { |
165 | .handler = sysrq_handle_showlocks, | 158 | .handler = sysrq_handle_showlocks, |
166 | .help_msg = "show-all-locks(D)", | 159 | .help_msg = "show-all-locks(D)", |
167 | .action_msg = "Show Locks Held", | 160 | .action_msg = "Show Locks Held", |
168 | }; | 161 | }; |
169 | 162 | #else | |
163 | #define sysrq_showlocks_op (*(struct sysrq_key_op *)0) | ||
170 | #endif | 164 | #endif |
171 | 165 | ||
172 | /* SHOW SYSRQ HANDLERS BLOCK */ | ||
173 | |||
174 | static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, | 166 | static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, |
175 | struct tty_struct *tty) | 167 | struct tty_struct *tty) |
176 | { | 168 | { |
177 | if (pt_regs) | 169 | if (pt_regs) |
178 | show_regs(pt_regs); | 170 | show_regs(pt_regs); |
@@ -184,9 +176,8 @@ static struct sysrq_key_op sysrq_showregs_op = { | |||
184 | .enable_mask = SYSRQ_ENABLE_DUMP, | 176 | .enable_mask = SYSRQ_ENABLE_DUMP, |
185 | }; | 177 | }; |
186 | 178 | ||
187 | |||
188 | static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, | 179 | static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, |
189 | struct tty_struct *tty) | 180 | struct tty_struct *tty) |
190 | { | 181 | { |
191 | show_state(); | 182 | show_state(); |
192 | } | 183 | } |
@@ -197,9 +188,8 @@ static struct sysrq_key_op sysrq_showstate_op = { | |||
197 | .enable_mask = SYSRQ_ENABLE_DUMP, | 188 | .enable_mask = SYSRQ_ENABLE_DUMP, |
198 | }; | 189 | }; |
199 | 190 | ||
200 | |||
201 | static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, | 191 | static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, |
202 | struct tty_struct *tty) | 192 | struct tty_struct *tty) |
203 | { | 193 | { |
204 | show_mem(); | 194 | show_mem(); |
205 | } | 195 | } |
@@ -210,13 +200,9 @@ static struct sysrq_key_op sysrq_showmem_op = { | |||
210 | .enable_mask = SYSRQ_ENABLE_DUMP, | 200 | .enable_mask = SYSRQ_ENABLE_DUMP, |
211 | }; | 201 | }; |
212 | 202 | ||
213 | /* SHOW SYSRQ HANDLERS BLOCK */ | 203 | /* |
214 | 204 | * Signal sysrq helper function. Sends a signal to all user processes. | |
215 | 205 | */ | |
216 | /* SIGNAL SYSRQ HANDLERS BLOCK */ | ||
217 | |||
218 | /* signal sysrq helper function | ||
219 | * Sends a signal to all user processes */ | ||
220 | static void send_sig_all(int sig) | 206 | static void send_sig_all(int sig) |
221 | { | 207 | { |
222 | struct task_struct *p; | 208 | struct task_struct *p; |
@@ -229,7 +215,7 @@ static void send_sig_all(int sig) | |||
229 | } | 215 | } |
230 | 216 | ||
231 | static void sysrq_handle_term(int key, struct pt_regs *pt_regs, | 217 | static void sysrq_handle_term(int key, struct pt_regs *pt_regs, |
232 | struct tty_struct *tty) | 218 | struct tty_struct *tty) |
233 | { | 219 | { |
234 | send_sig_all(SIGTERM); | 220 | send_sig_all(SIGTERM); |
235 | console_loglevel = 8; | 221 | console_loglevel = 8; |
@@ -243,7 +229,8 @@ static struct sysrq_key_op sysrq_term_op = { | |||
243 | 229 | ||
244 | static void moom_callback(void *ignored) | 230 | static void moom_callback(void *ignored) |
245 | { | 231 | { |
246 | out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); | 232 | out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], |
233 | GFP_KERNEL, 0); | ||
247 | } | 234 | } |
248 | 235 | ||
249 | static DECLARE_WORK(moom_work, moom_callback, NULL); | 236 | static DECLARE_WORK(moom_work, moom_callback, NULL); |
@@ -260,7 +247,7 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
260 | }; | 247 | }; |
261 | 248 | ||
262 | static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, | 249 | static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, |
263 | struct tty_struct *tty) | 250 | struct tty_struct *tty) |
264 | { | 251 | { |
265 | send_sig_all(SIGKILL); | 252 | send_sig_all(SIGKILL); |
266 | console_loglevel = 8; | 253 | console_loglevel = 8; |
@@ -272,8 +259,6 @@ static struct sysrq_key_op sysrq_kill_op = { | |||
272 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | 259 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
273 | }; | 260 | }; |
274 | 261 | ||
275 | /* END SIGNAL SYSRQ HANDLERS BLOCK */ | ||
276 | |||
277 | static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, | 262 | static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, |
278 | struct tty_struct *tty) | 263 | struct tty_struct *tty) |
279 | { | 264 | { |
@@ -288,110 +273,99 @@ static struct sysrq_key_op sysrq_unrt_op = { | |||
288 | 273 | ||
289 | /* Key Operations table and lock */ | 274 | /* Key Operations table and lock */ |
290 | static DEFINE_SPINLOCK(sysrq_key_table_lock); | 275 | static DEFINE_SPINLOCK(sysrq_key_table_lock); |
291 | #define SYSRQ_KEY_TABLE_LENGTH 36 | 276 | |
292 | static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { | 277 | static struct sysrq_key_op *sysrq_key_table[36] = { |
293 | /* 0 */ &sysrq_loglevel_op, | 278 | &sysrq_loglevel_op, /* 0 */ |
294 | /* 1 */ &sysrq_loglevel_op, | 279 | &sysrq_loglevel_op, /* 1 */ |
295 | /* 2 */ &sysrq_loglevel_op, | 280 | &sysrq_loglevel_op, /* 2 */ |
296 | /* 3 */ &sysrq_loglevel_op, | 281 | &sysrq_loglevel_op, /* 3 */ |
297 | /* 4 */ &sysrq_loglevel_op, | 282 | &sysrq_loglevel_op, /* 4 */ |
298 | /* 5 */ &sysrq_loglevel_op, | 283 | &sysrq_loglevel_op, /* 5 */ |
299 | /* 6 */ &sysrq_loglevel_op, | 284 | &sysrq_loglevel_op, /* 6 */ |
300 | /* 7 */ &sysrq_loglevel_op, | 285 | &sysrq_loglevel_op, /* 7 */ |
301 | /* 8 */ &sysrq_loglevel_op, | 286 | &sysrq_loglevel_op, /* 8 */ |
302 | /* 9 */ &sysrq_loglevel_op, | 287 | &sysrq_loglevel_op, /* 9 */ |
303 | /* a */ NULL, /* Don't use for system provided sysrqs, | 288 | |
304 | it is handled specially on the sparc | 289 | /* |
305 | and will never arrive */ | 290 | * Don't use for system provided sysrqs, it is handled specially on |
306 | /* b */ &sysrq_reboot_op, | 291 | * sparc and will never arrive |
307 | #ifdef CONFIG_KEXEC | 292 | */ |
308 | /* c */ &sysrq_crashdump_op, | 293 | NULL, /* a */ |
309 | #else | 294 | &sysrq_reboot_op, /* b */ |
310 | /* c */ NULL, | 295 | &sysrq_crashdump_op, /* c */ |
311 | #endif | 296 | &sysrq_showlocks_op, /* d */ |
312 | #ifdef CONFIG_DEBUG_MUTEXES | 297 | &sysrq_term_op, /* e */ |
313 | /* d */ &sysrq_showlocks_op, | 298 | &sysrq_moom_op, /* f */ |
314 | #else | 299 | NULL, /* g */ |
315 | /* d */ NULL, | 300 | NULL, /* h */ |
316 | #endif | 301 | &sysrq_kill_op, /* i */ |
317 | /* e */ &sysrq_term_op, | 302 | NULL, /* j */ |
318 | /* f */ &sysrq_moom_op, | 303 | &sysrq_SAK_op, /* k */ |
319 | /* g */ NULL, | 304 | NULL, /* l */ |
320 | /* h */ NULL, | 305 | &sysrq_showmem_op, /* m */ |
321 | /* i */ &sysrq_kill_op, | 306 | &sysrq_unrt_op, /* n */ |
322 | /* j */ NULL, | 307 | /* This will often be registered as 'Off' at init time */ |
323 | #ifdef CONFIG_VT | 308 | NULL, /* o */ |
324 | /* k */ &sysrq_SAK_op, | 309 | &sysrq_showregs_op, /* p */ |
325 | #else | 310 | NULL, /* q */ |
326 | /* k */ NULL, | 311 | &sysrq_unraw_op, /* r */ |
327 | #endif | 312 | &sysrq_sync_op, /* s */ |
328 | /* l */ NULL, | 313 | &sysrq_showstate_op, /* t */ |
329 | /* m */ &sysrq_showmem_op, | 314 | &sysrq_mountro_op, /* u */ |
330 | /* n */ &sysrq_unrt_op, | 315 | /* May be assigned at init time by SMP VOYAGER */ |
331 | /* o */ NULL, /* This will often be registered | 316 | NULL, /* v */ |
332 | as 'Off' at init time */ | 317 | NULL, /* w */ |
333 | /* p */ &sysrq_showregs_op, | 318 | NULL, /* x */ |
334 | /* q */ NULL, | 319 | NULL, /* y */ |
335 | #ifdef CONFIG_VT | 320 | NULL /* z */ |
336 | /* r */ &sysrq_unraw_op, | ||
337 | #else | ||
338 | /* r */ NULL, | ||
339 | #endif | ||
340 | /* s */ &sysrq_sync_op, | ||
341 | /* t */ &sysrq_showstate_op, | ||
342 | /* u */ &sysrq_mountro_op, | ||
343 | /* v */ NULL, /* May be assigned at init time by SMP VOYAGER */ | ||
344 | /* w */ NULL, | ||
345 | /* x */ NULL, | ||
346 | /* y */ NULL, | ||
347 | /* z */ NULL | ||
348 | }; | 321 | }; |
349 | 322 | ||
350 | /* key2index calculation, -1 on invalid index */ | 323 | /* key2index calculation, -1 on invalid index */ |
351 | static int sysrq_key_table_key2index(int key) { | 324 | static int sysrq_key_table_key2index(int key) |
325 | { | ||
352 | int retval; | 326 | int retval; |
353 | if ((key >= '0') && (key <= '9')) { | 327 | |
328 | if ((key >= '0') && (key <= '9')) | ||
354 | retval = key - '0'; | 329 | retval = key - '0'; |
355 | } else if ((key >= 'a') && (key <= 'z')) { | 330 | else if ((key >= 'a') && (key <= 'z')) |
356 | retval = key + 10 - 'a'; | 331 | retval = key + 10 - 'a'; |
357 | } else { | 332 | else |
358 | retval = -1; | 333 | retval = -1; |
359 | } | ||
360 | return retval; | 334 | return retval; |
361 | } | 335 | } |
362 | 336 | ||
363 | /* | 337 | /* |
364 | * get and put functions for the table, exposed to modules. | 338 | * get and put functions for the table, exposed to modules. |
365 | */ | 339 | */ |
366 | 340 | struct sysrq_key_op *__sysrq_get_key_op(int key) | |
367 | struct sysrq_key_op *__sysrq_get_key_op (int key) { | 341 | { |
368 | struct sysrq_key_op *op_p; | 342 | struct sysrq_key_op *op_p = NULL; |
369 | int i; | 343 | int i; |
370 | 344 | ||
371 | i = sysrq_key_table_key2index(key); | 345 | i = sysrq_key_table_key2index(key); |
372 | op_p = (i == -1) ? NULL : sysrq_key_table[i]; | 346 | if (i != -1) |
347 | op_p = sysrq_key_table[i]; | ||
373 | return op_p; | 348 | return op_p; |
374 | } | 349 | } |
375 | 350 | ||
376 | static void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { | 351 | static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) |
377 | int i; | 352 | { |
353 | int i = sysrq_key_table_key2index(key); | ||
378 | 354 | ||
379 | i = sysrq_key_table_key2index(key); | ||
380 | if (i != -1) | 355 | if (i != -1) |
381 | sysrq_key_table[i] = op_p; | 356 | sysrq_key_table[i] = op_p; |
382 | } | 357 | } |
383 | 358 | ||
384 | /* | 359 | /* |
385 | * This is the non-locking version of handle_sysrq | 360 | * This is the non-locking version of handle_sysrq. It must/can only be called |
386 | * It must/can only be called by sysrq key handlers, | 361 | * by sysrq key handlers, as they are inside of the lock |
387 | * as they are inside of the lock | ||
388 | */ | 362 | */ |
389 | 363 | void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, | |
390 | void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) | 364 | int check_mask) |
391 | { | 365 | { |
392 | struct sysrq_key_op *op_p; | 366 | struct sysrq_key_op *op_p; |
393 | int orig_log_level; | 367 | int orig_log_level; |
394 | int i, j; | 368 | int i; |
395 | unsigned long flags; | 369 | unsigned long flags; |
396 | 370 | ||
397 | spin_lock_irqsave(&sysrq_key_table_lock, flags); | 371 | spin_lock_irqsave(&sysrq_key_table_lock, flags); |
@@ -401,26 +375,34 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in | |||
401 | 375 | ||
402 | op_p = __sysrq_get_key_op(key); | 376 | op_p = __sysrq_get_key_op(key); |
403 | if (op_p) { | 377 | if (op_p) { |
404 | /* Should we check for enabled operations (/proc/sysrq-trigger should not) | 378 | /* |
405 | * and is the invoked operation enabled? */ | 379 | * Should we check for enabled operations (/proc/sysrq-trigger |
380 | * should not) and is the invoked operation enabled? | ||
381 | */ | ||
406 | if (!check_mask || sysrq_enabled == 1 || | 382 | if (!check_mask || sysrq_enabled == 1 || |
407 | (sysrq_enabled & op_p->enable_mask)) { | 383 | (sysrq_enabled & op_p->enable_mask)) { |
408 | printk ("%s\n", op_p->action_msg); | 384 | printk("%s\n", op_p->action_msg); |
409 | console_loglevel = orig_log_level; | 385 | console_loglevel = orig_log_level; |
410 | op_p->handler(key, pt_regs, tty); | 386 | op_p->handler(key, pt_regs, tty); |
411 | } | 387 | } else { |
412 | else | ||
413 | printk("This sysrq operation is disabled.\n"); | 388 | printk("This sysrq operation is disabled.\n"); |
389 | } | ||
414 | } else { | 390 | } else { |
415 | printk("HELP : "); | 391 | printk("HELP : "); |
416 | /* Only print the help msg once per handler */ | 392 | /* Only print the help msg once per handler */ |
417 | for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) | 393 | for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { |
418 | if (sysrq_key_table[i]) { | 394 | if (sysrq_key_table[i]) { |
419 | for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++); | 395 | int j; |
420 | if (j == i) | 396 | |
421 | printk ("%s ", sysrq_key_table[i]->help_msg); | 397 | for (j = 0; sysrq_key_table[i] != |
398 | sysrq_key_table[j]; j++) | ||
399 | ; | ||
400 | if (j != i) | ||
401 | continue; | ||
402 | printk("%s ", sysrq_key_table[i]->help_msg); | ||
403 | } | ||
422 | } | 404 | } |
423 | printk ("\n"); | 405 | printk("\n"); |
424 | console_loglevel = orig_log_level; | 406 | console_loglevel = orig_log_level; |
425 | } | 407 | } |
426 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); | 408 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); |
@@ -430,16 +412,17 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in | |||
430 | * This function is called by the keyboard handler when SysRq is pressed | 412 | * This function is called by the keyboard handler when SysRq is pressed |
431 | * and any other keycode arrives. | 413 | * and any other keycode arrives. |
432 | */ | 414 | */ |
433 | |||
434 | void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) | 415 | void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) |
435 | { | 416 | { |
436 | if (!sysrq_enabled) | 417 | if (!sysrq_enabled) |
437 | return; | 418 | return; |
438 | __handle_sysrq(key, pt_regs, tty, 1); | 419 | __handle_sysrq(key, pt_regs, tty, 1); |
439 | } | 420 | } |
421 | EXPORT_SYMBOL(handle_sysrq); | ||
440 | 422 | ||
441 | static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, | 423 | static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, |
442 | struct sysrq_key_op *remove_op_p) { | 424 | struct sysrq_key_op *remove_op_p) |
425 | { | ||
443 | 426 | ||
444 | int retval; | 427 | int retval; |
445 | unsigned long flags; | 428 | unsigned long flags; |
@@ -452,7 +435,6 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, | |||
452 | retval = -1; | 435 | retval = -1; |
453 | } | 436 | } |
454 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); | 437 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); |
455 | |||
456 | return retval; | 438 | return retval; |
457 | } | 439 | } |
458 | 440 | ||
@@ -460,12 +442,10 @@ int register_sysrq_key(int key, struct sysrq_key_op *op_p) | |||
460 | { | 442 | { |
461 | return __sysrq_swap_key_ops(key, op_p, NULL); | 443 | return __sysrq_swap_key_ops(key, op_p, NULL); |
462 | } | 444 | } |
445 | EXPORT_SYMBOL(register_sysrq_key); | ||
463 | 446 | ||
464 | int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) | 447 | int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) |
465 | { | 448 | { |
466 | return __sysrq_swap_key_ops(key, NULL, op_p); | 449 | return __sysrq_swap_key_ops(key, NULL, op_p); |
467 | } | 450 | } |
468 | |||
469 | EXPORT_SYMBOL(handle_sysrq); | ||
470 | EXPORT_SYMBOL(register_sysrq_key); | ||
471 | EXPORT_SYMBOL(unregister_sysrq_key); | 451 | EXPORT_SYMBOL(unregister_sysrq_key); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index fd3a4beaa53d..dec0224b4478 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/miscdevice.h> | 25 | #include <linux/miscdevice.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/io.h> | ||
27 | 28 | ||
28 | enum tpm_timeout { | 29 | enum tpm_timeout { |
29 | TPM_TIMEOUT = 5, /* msecs */ | 30 | TPM_TIMEOUT = 5, /* msecs */ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 76592ee1fb38..48d795bb8c4b 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -354,7 +354,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
354 | 354 | ||
355 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 355 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
356 | 356 | ||
357 | int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size) | 357 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) |
358 | { | 358 | { |
359 | int copied = 0; | 359 | int copied = 0; |
360 | do { | 360 | do { |
@@ -378,7 +378,7 @@ int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t | |||
378 | 378 | ||
379 | EXPORT_SYMBOL_GPL(tty_insert_flip_string); | 379 | EXPORT_SYMBOL_GPL(tty_insert_flip_string); |
380 | 380 | ||
381 | int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size) | 381 | int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) |
382 | { | 382 | { |
383 | int copied = 0; | 383 | int copied = 0; |
384 | do { | 384 | do { |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index c0dfcf273f0a..16e99db2e12d 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -148,6 +148,16 @@ config MPCORE_WATCHDOG | |||
148 | To compile this driver as a module, choose M here: the | 148 | To compile this driver as a module, choose M here: the |
149 | module will be called mpcore_wdt. | 149 | module will be called mpcore_wdt. |
150 | 150 | ||
151 | config EP93XX_WATCHDOG | ||
152 | tristate "EP93xx Watchdog" | ||
153 | depends on WATCHDOG && ARCH_EP93XX | ||
154 | help | ||
155 | Say Y here if to include support for the watchdog timer | ||
156 | embedded in the Cirrus Logic EP93xx family of devices. | ||
157 | |||
158 | To compile this driver as a module, choose M here: the | ||
159 | module will be called ep93xx_wdt. | ||
160 | |||
151 | # X86 (i386 + ia64 + x86_64) Architecture | 161 | # X86 (i386 + ia64 + x86_64) Architecture |
152 | 162 | ||
153 | config ACQUIRE_WDT | 163 | config ACQUIRE_WDT |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 36c0b282b8ba..d6f27fde9905 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -30,6 +30,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | |||
30 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o | 30 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o |
31 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | 31 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o |
32 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o | 32 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o |
33 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | ||
33 | 34 | ||
34 | # X86 (i386 + ia64 + x86_64) Architecture | 35 | # X86 (i386 + ia64 + x86_64) Architecture |
35 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o | 36 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o |
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c new file mode 100644 index 000000000000..9021dbb78299 --- /dev/null +++ b/drivers/char/watchdog/ep93xx_wdt.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Watchdog driver for Cirrus Logic EP93xx family of devices. | ||
3 | * | ||
4 | * Copyright (c) 2004 Ray Lehtiniemi | ||
5 | * Copyright (c) 2006 Tower Technologies | ||
6 | * Based on ep93xx driver, bits from alim7101_wdt.c | ||
7 | * | ||
8 | * Authors: Ray Lehtiniemi <rayl@mail.com>, | ||
9 | * Alessandro Zummo <a.zummo@towertech.it> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | * | ||
15 | * This watchdog fires after 250msec, which is a too short interval | ||
16 | * for us to rely on the user space daemon alone. So we ping the | ||
17 | * wdt each ~200msec and eventually stop doing it if the user space | ||
18 | * daemon dies. | ||
19 | * | ||
20 | * TODO: | ||
21 | * | ||
22 | * - Test last reset from watchdog status | ||
23 | * - Add a few missing ioctls | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/watchdog.h> | ||
30 | #include <linux/timer.h> | ||
31 | |||
32 | #include <asm/hardware.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | |||
35 | #define WDT_VERSION "0.3" | ||
36 | #define PFX "ep93xx_wdt: " | ||
37 | |||
38 | /* default timeout (secs) */ | ||
39 | #define WDT_TIMEOUT 30 | ||
40 | |||
41 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
42 | static int timeout = WDT_TIMEOUT; | ||
43 | |||
44 | static struct timer_list timer; | ||
45 | static unsigned long next_heartbeat; | ||
46 | static unsigned long wdt_status; | ||
47 | static unsigned long boot_status; | ||
48 | |||
49 | #define WDT_IN_USE 0 | ||
50 | #define WDT_OK_TO_CLOSE 1 | ||
51 | |||
52 | #define EP93XX_WDT_REG(x) (EP93XX_WATCHDOG_BASE + (x)) | ||
53 | #define EP93XX_WDT_WATCHDOG EP93XX_WDT_REG(0x00) | ||
54 | #define EP93XX_WDT_WDSTATUS EP93XX_WDT_REG(0x04) | ||
55 | |||
56 | /* reset the wdt every ~200ms */ | ||
57 | #define WDT_INTERVAL (HZ/5) | ||
58 | |||
59 | static void wdt_enable(void) | ||
60 | { | ||
61 | __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG); | ||
62 | } | ||
63 | |||
64 | static void wdt_disable(void) | ||
65 | { | ||
66 | __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG); | ||
67 | } | ||
68 | |||
69 | static inline void wdt_ping(void) | ||
70 | { | ||
71 | __raw_writew(0x5555, EP93XX_WDT_WATCHDOG); | ||
72 | } | ||
73 | |||
74 | static void wdt_startup(void) | ||
75 | { | ||
76 | next_heartbeat = jiffies + (timeout * HZ); | ||
77 | |||
78 | wdt_enable(); | ||
79 | mod_timer(&timer, jiffies + WDT_INTERVAL); | ||
80 | } | ||
81 | |||
82 | static void wdt_shutdown(void) | ||
83 | { | ||
84 | del_timer_sync(&timer); | ||
85 | wdt_disable(); | ||
86 | } | ||
87 | |||
88 | static void wdt_keepalive(void) | ||
89 | { | ||
90 | /* user land ping */ | ||
91 | next_heartbeat = jiffies + (timeout * HZ); | ||
92 | } | ||
93 | |||
94 | static int ep93xx_wdt_open(struct inode *inode, struct file *file) | ||
95 | { | ||
96 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
97 | return -EBUSY; | ||
98 | |||
99 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
100 | |||
101 | wdt_startup(); | ||
102 | |||
103 | return nonseekable_open(inode, file); | ||
104 | } | ||
105 | |||
106 | static ssize_t | ||
107 | ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, | ||
108 | loff_t *ppos) | ||
109 | { | ||
110 | /* Can't seek (pwrite) on this device */ | ||
111 | if (*ppos != file->f_pos) | ||
112 | return -ESPIPE; | ||
113 | |||
114 | if (len) { | ||
115 | if (!nowayout) { | ||
116 | size_t i; | ||
117 | |||
118 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
119 | |||
120 | for (i = 0; i != len; i++) { | ||
121 | char c; | ||
122 | |||
123 | if (get_user(c, data + i)) | ||
124 | return -EFAULT; | ||
125 | |||
126 | if (c == 'V') | ||
127 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
128 | else | ||
129 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
130 | } | ||
131 | } | ||
132 | wdt_keepalive(); | ||
133 | } | ||
134 | |||
135 | return len; | ||
136 | } | ||
137 | |||
138 | static struct watchdog_info ident = { | ||
139 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, | ||
140 | .identity = "EP93xx Watchdog", | ||
141 | }; | ||
142 | |||
143 | static int | ||
144 | ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
145 | unsigned long arg) | ||
146 | { | ||
147 | int ret = -ENOIOCTLCMD; | ||
148 | |||
149 | switch (cmd) { | ||
150 | case WDIOC_GETSUPPORT: | ||
151 | ret = copy_to_user((struct watchdog_info __user *)arg, &ident, | ||
152 | sizeof(ident)) ? -EFAULT : 0; | ||
153 | break; | ||
154 | |||
155 | case WDIOC_GETSTATUS: | ||
156 | ret = put_user(0, (int __user *)arg); | ||
157 | break; | ||
158 | |||
159 | case WDIOC_GETBOOTSTATUS: | ||
160 | ret = put_user(boot_status, (int __user *)arg); | ||
161 | break; | ||
162 | |||
163 | case WDIOC_GETTIMEOUT: | ||
164 | /* actually, it is 0.250 seconds.... */ | ||
165 | ret = put_user(1, (int __user *)arg); | ||
166 | break; | ||
167 | |||
168 | case WDIOC_KEEPALIVE: | ||
169 | wdt_keepalive(); | ||
170 | ret = 0; | ||
171 | break; | ||
172 | } | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static int ep93xx_wdt_release(struct inode *inode, struct file *file) | ||
177 | { | ||
178 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
179 | wdt_shutdown(); | ||
180 | else | ||
181 | printk(KERN_CRIT PFX "Device closed unexpectedly - " | ||
182 | "timer will not stop\n"); | ||
183 | |||
184 | clear_bit(WDT_IN_USE, &wdt_status); | ||
185 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static struct file_operations ep93xx_wdt_fops = { | ||
191 | .owner = THIS_MODULE, | ||
192 | .write = ep93xx_wdt_write, | ||
193 | .ioctl = ep93xx_wdt_ioctl, | ||
194 | .open = ep93xx_wdt_open, | ||
195 | .release = ep93xx_wdt_release, | ||
196 | }; | ||
197 | |||
198 | static struct miscdevice ep93xx_wdt_miscdev = { | ||
199 | .minor = WATCHDOG_MINOR, | ||
200 | .name = "watchdog", | ||
201 | .fops = &ep93xx_wdt_fops, | ||
202 | }; | ||
203 | |||
204 | static void ep93xx_timer_ping(unsigned long data) | ||
205 | { | ||
206 | if (time_before(jiffies, next_heartbeat)) | ||
207 | wdt_ping(); | ||
208 | |||
209 | /* Re-set the timer interval */ | ||
210 | mod_timer(&timer, jiffies + WDT_INTERVAL); | ||
211 | } | ||
212 | |||
213 | static int __init ep93xx_wdt_init(void) | ||
214 | { | ||
215 | int err; | ||
216 | |||
217 | err = misc_register(&ep93xx_wdt_miscdev); | ||
218 | |||
219 | boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0; | ||
220 | |||
221 | printk(KERN_INFO PFX "EP93XX watchdog, driver version " | ||
222 | WDT_VERSION "%s\n", | ||
223 | (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08) | ||
224 | ? " (nCS1 disable detected)" : ""); | ||
225 | |||
226 | if (timeout < 1 || timeout > 3600) { | ||
227 | timeout = WDT_TIMEOUT; | ||
228 | printk(KERN_INFO PFX | ||
229 | "timeout value must be 1<=x<=3600, using %d\n", | ||
230 | timeout); | ||
231 | } | ||
232 | |||
233 | setup_timer(&timer, ep93xx_timer_ping, 1); | ||
234 | return err; | ||
235 | } | ||
236 | |||
237 | static void __exit ep93xx_wdt_exit(void) | ||
238 | { | ||
239 | wdt_shutdown(); | ||
240 | misc_deregister(&ep93xx_wdt_miscdev); | ||
241 | } | ||
242 | |||
243 | module_init(ep93xx_wdt_init); | ||
244 | module_exit(ep93xx_wdt_exit); | ||
245 | |||
246 | module_param(nowayout, int, 0); | ||
247 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
248 | |||
249 | module_param(timeout, int, 0); | ||
250 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
251 | |||
252 | MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>," | ||
253 | "Alessandro Zummo <a.zummo@towertech.it>"); | ||
254 | MODULE_DESCRIPTION("EP93xx Watchdog"); | ||
255 | MODULE_LICENSE("GPL"); | ||
256 | MODULE_VERSION(WDT_VERSION); | ||
257 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||