summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c12
-rw-r--r--drivers/char/istallion.c8
-rw-r--r--drivers/char/mem.c28
-rw-r--r--drivers/char/mxser.c8
-rw-r--r--drivers/char/ppdev.c3
-rw-r--r--drivers/char/riscom8.c8
-rw-r--r--drivers/char/sysrq.c250
-rw-r--r--drivers/char/tpm/tpm.h1
-rw-r--r--drivers/char/tty_io.c4
-rw-r--r--drivers/char/watchdog/Kconfig10
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/ep93xx_wdt.c257
12 files changed, 420 insertions, 170 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d745004281d..abd4c5118a1 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,
intf = ipmi_interfaces[if_num];
if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) {
spin_unlock_irqrestore(&interfaces_lock, flags);
- return -EINVAL;
+ rv = -EINVAL;
+ goto out_kfree;
}
/* Note that each existing user holds a refcount to the interface. */
@@ -751,14 +752,14 @@ int ipmi_create_user(unsigned int if_num,
if (!try_module_get(intf->handlers->owner)) {
rv = -ENODEV;
- goto out_err;
+ goto out_kref;
}
if (intf->handlers->inc_usecount) {
rv = intf->handlers->inc_usecount(intf->send_info);
if (rv) {
module_put(intf->handlers->owner);
- goto out_err;
+ goto out_kref;
}
}
@@ -769,9 +770,10 @@ int ipmi_create_user(unsigned int if_num,
*user = new_user;
return 0;
- out_err:
- kfree(new_user);
+out_kref:
kref_put(&intf->refcount, intf_free);
+out_kfree:
+ kfree(new_user);
return rv;
}
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ede128356af..e5247f85a44 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -378,13 +378,13 @@ MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(board0, "1-3s");
+module_param_array(board0, charp, NULL, 0);
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board1, "1-3s");
+module_param_array(board1, charp, NULL, 0);
MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board2, "1-3s");
+module_param_array(board2, charp, NULL, 0);
MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board3, "1-3s");
+module_param_array(board3, charp, NULL, 0);
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
#endif
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 29c41f4418c..26d0116b48d 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,
copied = copy_from_user(ptr, buf, sz);
if (copied) {
- ssize_t ret;
-
- ret = written + (sz - copied);
- if (ret)
- return ret;
+ written += sz - copied;
+ if (written)
+ break;
return -EFAULT;
}
buf += sz;
@@ -456,11 +454,9 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf,
copied = copy_from_user(ptr, buf, sz);
if (copied) {
- ssize_t ret;
-
- ret = written + (sz - copied);
- if (ret)
- return ret;
+ written += sz - copied;
+ if (written)
+ break;
return -EFAULT;
}
buf += sz;
@@ -514,11 +510,10 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
if (len) {
written = copy_from_user(kbuf, buf, len);
if (written) {
- ssize_t ret;
-
+ if (wrote + virtr)
+ break;
free_page((unsigned long)kbuf);
- ret = wrote + virtr + (len - written);
- return ret ? ret : -EFAULT;
+ return -EFAULT;
}
}
len = vwrite(kbuf, (char *)p, len);
@@ -563,8 +558,11 @@ static ssize_t write_port(struct file * file, const char __user * buf,
return -EFAULT;
while (count-- > 0 && i < 65536) {
char c;
- if (__get_user(c, tmp))
+ if (__get_user(c, tmp)) {
+ if (tmp > buf)
+ break;
return -EFAULT;
+ }
outb(c,i);
i++;
tmp++;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index ea725a9964e..0fb2fb9fb02 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -243,10 +243,10 @@ static int verbose = 0;
MODULE_AUTHOR("Casper Yang");
MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-MODULE_PARM(ioaddr, "1-4i");
-MODULE_PARM(ttymajor, "i");
-MODULE_PARM(calloutmajor, "i");
-MODULE_PARM(verbose, "i");
+module_param_array(ioaddr, int, NULL, 0);
+module_param(ttymajor, int, 0);
+module_param(calloutmajor, int, 0);
+module_param(verbose, bool, 0);
MODULE_LICENSE("GPL");
struct mxser_log {
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 306ee0f091a..bee6c47b45b 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -65,10 +65,11 @@
#include <linux/parport.h>
#include <linux/ctype.h>
#include <linux/poll.h>
-#include <asm/uaccess.h>
+#include <linux/major.h>
#include <linux/ppdev.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
+#include <asm/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
#define CHRDEV "ppdev"
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 119e629656b..657c0d88f48 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1743,10 +1743,10 @@ static int iobase;
static int iobase1;
static int iobase2;
static int iobase3;
-MODULE_PARM(iobase, "i");
-MODULE_PARM(iobase1, "i");
-MODULE_PARM(iobase2, "i");
-MODULE_PARM(iobase3, "i");
+module_param(iobase, int, 0);
+module_param(iobase1, int, 0);
+module_param(iobase2, int, 0);
+module_param(iobase3, int, 0);
MODULE_LICENSE("GPL");
#endif /* MODULE */
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index d58f8231885..35082dc12ea 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -42,16 +42,15 @@
/* Whether we react on sysrq keys or just ignore them */
int sysrq_enabled = 1;
-/* Loglevel sysrq handler */
static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
int i;
i = key - '0';
console_loglevel = 7;
printk("Loglevel set to %d\n", i);
console_loglevel = i;
-}
+}
static struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
.help_msg = "loglevel0-8",
@@ -59,11 +58,9 @@ static struct sysrq_key_op sysrq_loglevel_op = {
.enable_mask = SYSRQ_ENABLE_LOG,
};
-
-/* SAK sysrq handler */
#ifdef CONFIG_VT
static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
if (tty)
do_SAK(tty);
@@ -75,12 +72,13 @@ static struct sysrq_key_op sysrq_SAK_op = {
.action_msg = "SAK",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
+#else
+#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
#endif
#ifdef CONFIG_VT
-/* unraw sysrq handler */
static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
struct kbd_struct *kbd = &kbd_table[fg_console];
@@ -93,10 +91,11 @@ static struct sysrq_key_op sysrq_unraw_op = {
.action_msg = "Keyboard mode set to XLATE",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
+#else
+#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
#endif /* CONFIG_VT */
#ifdef CONFIG_KEXEC
-/* crashdump sysrq handler */
static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -108,16 +107,16 @@ static struct sysrq_key_op sysrq_crashdump_op = {
.action_msg = "Trigger a crashdump",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
+#else
+#define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
#endif
-/* reboot sysrq handler */
static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
local_irq_enable();
emergency_restart();
}
-
static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
@@ -126,11 +125,10 @@ static struct sysrq_key_op sysrq_reboot_op = {
};
static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
emergency_sync();
}
-
static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
@@ -139,11 +137,10 @@ static struct sysrq_key_op sysrq_sync_op = {
};
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
emergency_remount();
}
-
static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
@@ -151,28 +148,23 @@ static struct sysrq_key_op sysrq_mountro_op = {
.enable_mask = SYSRQ_ENABLE_REMOUNT,
};
-/* END SYNC SYSRQ HANDLERS BLOCK */
-
#ifdef CONFIG_DEBUG_MUTEXES
-
-static void
-sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
{
mutex_debug_show_all_locks();
}
-
static struct sysrq_key_op sysrq_showlocks_op = {
.handler = sysrq_handle_showlocks,
.help_msg = "show-all-locks(D)",
.action_msg = "Show Locks Held",
};
-
+#else
+#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
#endif
-/* SHOW SYSRQ HANDLERS BLOCK */
-
static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
if (pt_regs)
show_regs(pt_regs);
@@ -184,9 +176,8 @@ static struct sysrq_key_op sysrq_showregs_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-
static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
show_state();
}
@@ -197,9 +188,8 @@ static struct sysrq_key_op sysrq_showstate_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-
static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
show_mem();
}
@@ -210,13 +200,9 @@ static struct sysrq_key_op sysrq_showmem_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-/* SHOW SYSRQ HANDLERS BLOCK */
-
-
-/* SIGNAL SYSRQ HANDLERS BLOCK */
-
-/* signal sysrq helper function
- * Sends a signal to all user processes */
+/*
+ * Signal sysrq helper function. Sends a signal to all user processes.
+ */
static void send_sig_all(int sig)
{
struct task_struct *p;
@@ -229,7 +215,7 @@ static void send_sig_all(int sig)
}
static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
send_sig_all(SIGTERM);
console_loglevel = 8;
@@ -243,7 +229,8 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
+ GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
@@ -260,7 +247,7 @@ static struct sysrq_key_op sysrq_moom_op = {
};
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
send_sig_all(SIGKILL);
console_loglevel = 8;
@@ -272,8 +259,6 @@ static struct sysrq_key_op sysrq_kill_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
-/* END SIGNAL SYSRQ HANDLERS BLOCK */
-
static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -288,110 +273,99 @@ static struct sysrq_key_op sysrq_unrt_op = {
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
-#define SYSRQ_KEY_TABLE_LENGTH 36
-static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
-/* 0 */ &sysrq_loglevel_op,
-/* 1 */ &sysrq_loglevel_op,
-/* 2 */ &sysrq_loglevel_op,
-/* 3 */ &sysrq_loglevel_op,
-/* 4 */ &sysrq_loglevel_op,
-/* 5 */ &sysrq_loglevel_op,
-/* 6 */ &sysrq_loglevel_op,
-/* 7 */ &sysrq_loglevel_op,
-/* 8 */ &sysrq_loglevel_op,
-/* 9 */ &sysrq_loglevel_op,
-/* a */ NULL, /* Don't use for system provided sysrqs,
- it is handled specially on the sparc
- and will never arrive */
-/* b */ &sysrq_reboot_op,
-#ifdef CONFIG_KEXEC
-/* c */ &sysrq_crashdump_op,
-#else
-/* c */ NULL,
-#endif
-#ifdef CONFIG_DEBUG_MUTEXES
-/* d */ &sysrq_showlocks_op,
-#else
-/* d */ NULL,
-#endif
-/* e */ &sysrq_term_op,
-/* f */ &sysrq_moom_op,
-/* g */ NULL,
-/* h */ NULL,
-/* i */ &sysrq_kill_op,
-/* j */ NULL,
-#ifdef CONFIG_VT
-/* k */ &sysrq_SAK_op,
-#else
-/* k */ NULL,
-#endif
-/* l */ NULL,
-/* m */ &sysrq_showmem_op,
-/* n */ &sysrq_unrt_op,
-/* o */ NULL, /* This will often be registered
- as 'Off' at init time */
-/* p */ &sysrq_showregs_op,
-/* q */ NULL,
-#ifdef CONFIG_VT
-/* r */ &sysrq_unraw_op,
-#else
-/* r */ NULL,
-#endif
-/* s */ &sysrq_sync_op,
-/* t */ &sysrq_showstate_op,
-/* u */ &sysrq_mountro_op,
-/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
-/* w */ NULL,
-/* x */ NULL,
-/* y */ NULL,
-/* z */ NULL
+
+static struct sysrq_key_op *sysrq_key_table[36] = {
+ &sysrq_loglevel_op, /* 0 */
+ &sysrq_loglevel_op, /* 1 */
+ &sysrq_loglevel_op, /* 2 */
+ &sysrq_loglevel_op, /* 3 */
+ &sysrq_loglevel_op, /* 4 */
+ &sysrq_loglevel_op, /* 5 */
+ &sysrq_loglevel_op, /* 6 */
+ &sysrq_loglevel_op, /* 7 */
+ &sysrq_loglevel_op, /* 8 */
+ &sysrq_loglevel_op, /* 9 */
+
+ /*
+ * Don't use for system provided sysrqs, it is handled specially on
+ * sparc and will never arrive
+ */
+ NULL, /* a */
+ &sysrq_reboot_op, /* b */
+ &sysrq_crashdump_op, /* c */
+ &sysrq_showlocks_op, /* d */
+ &sysrq_term_op, /* e */
+ &sysrq_moom_op, /* f */
+ NULL, /* g */
+ NULL, /* h */
+ &sysrq_kill_op, /* i */
+ NULL, /* j */
+ &sysrq_SAK_op, /* k */
+ NULL, /* l */
+ &sysrq_showmem_op, /* m */
+ &sysrq_unrt_op, /* n */
+ /* This will often be registered as 'Off' at init time */
+ NULL, /* o */
+ &sysrq_showregs_op, /* p */
+ NULL, /* q */
+ &sysrq_unraw_op, /* r */
+ &sysrq_sync_op, /* s */
+ &sysrq_showstate_op, /* t */
+ &sysrq_mountro_op, /* u */
+ /* May be assigned at init time by SMP VOYAGER */
+ NULL, /* v */
+ NULL, /* w */
+ NULL, /* x */
+ NULL, /* y */
+ NULL /* z */
};
/* key2index calculation, -1 on invalid index */
-static int sysrq_key_table_key2index(int key) {
+static int sysrq_key_table_key2index(int key)
+{
int retval;
- if ((key >= '0') && (key <= '9')) {
+
+ if ((key >= '0') && (key <= '9'))
retval = key - '0';
- } else if ((key >= 'a') && (key <= 'z')) {
+ else if ((key >= 'a') && (key <= 'z'))
retval = key + 10 - 'a';
- } else {
+ else
retval = -1;
- }
return retval;
}
/*
* get and put functions for the table, exposed to modules.
*/
-
-struct sysrq_key_op *__sysrq_get_key_op (int key) {
- struct sysrq_key_op *op_p;
+struct sysrq_key_op *__sysrq_get_key_op(int key)
+{
+ struct sysrq_key_op *op_p = NULL;
int i;
-
+
i = sysrq_key_table_key2index(key);
- op_p = (i == -1) ? NULL : sysrq_key_table[i];
+ if (i != -1)
+ op_p = sysrq_key_table[i];
return op_p;
}
-static void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
- int i;
+static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
+{
+ int i = sysrq_key_table_key2index(key);
- i = sysrq_key_table_key2index(key);
if (i != -1)
sysrq_key_table[i] = op_p;
}
/*
- * This is the non-locking version of handle_sysrq
- * It must/can only be called by sysrq key handlers,
- * as they are inside of the lock
+ * This is the non-locking version of handle_sysrq. It must/can only be called
+ * by sysrq key handlers, as they are inside of the lock
*/
-
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty,
+ int check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
- int i, j;
+ int i;
unsigned long flags;
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
op_p = __sysrq_get_key_op(key);
if (op_p) {
- /* Should we check for enabled operations (/proc/sysrq-trigger should not)
- * and is the invoked operation enabled? */
+ /*
+ * Should we check for enabled operations (/proc/sysrq-trigger
+ * should not) and is the invoked operation enabled?
+ */
if (!check_mask || sysrq_enabled == 1 ||
(sysrq_enabled & op_p->enable_mask)) {
- printk ("%s\n", op_p->action_msg);
+ printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key, pt_regs, tty);
- }
- else
+ } else {
printk("This sysrq operation is disabled.\n");
+ }
} else {
printk("HELP : ");
/* Only print the help msg once per handler */
- for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++)
- if (sysrq_key_table[i]) {
- for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
- if (j == i)
- printk ("%s ", sysrq_key_table[i]->help_msg);
+ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
+ if (sysrq_key_table[i]) {
+ int j;
+
+ for (j = 0; sysrq_key_table[i] !=
+ sysrq_key_table[j]; j++)
+ ;
+ if (j != i)
+ continue;
+ printk("%s ", sysrq_key_table[i]->help_msg);
+ }
}
- printk ("\n");
+ printk("\n");
console_loglevel = orig_log_level;
}
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
* This function is called by the keyboard handler when SysRq is pressed
* and any other keycode arrives.
*/
-
void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
{
if (!sysrq_enabled)
return;
__handle_sysrq(key, pt_regs, tty, 1);
}
+EXPORT_SYMBOL(handle_sysrq);
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
- struct sysrq_key_op *remove_op_p) {
+ struct sysrq_key_op *remove_op_p)
+{
int retval;
unsigned long flags;
@@ -452,7 +435,6 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
retval = -1;
}
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
-
return retval;
}
@@ -460,12 +442,10 @@ int register_sysrq_key(int key, struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, op_p, NULL);
}
+EXPORT_SYMBOL(register_sysrq_key);
int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, NULL, op_p);
}
-
-EXPORT_SYMBOL(handle_sysrq);
-EXPORT_SYMBOL(register_sysrq_key);
EXPORT_SYMBOL(unregister_sysrq_key);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index fd3a4beaa53..dec0224b447 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -24,6 +24,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
+#include <linux/io.h>
enum tpm_timeout {
TPM_TIMEOUT = 5, /* msecs */
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 76592ee1fb3..48d795bb8c4 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)
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
{
int copied = 0;
do {
@@ -378,7 +378,7 @@ int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t
EXPORT_SYMBOL_GPL(tty_insert_flip_string);
-int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
+int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
{
int copied = 0;
do {
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index c0dfcf273f0..16e99db2e12 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -148,6 +148,16 @@ config MPCORE_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called mpcore_wdt.
+config EP93XX_WATCHDOG
+ tristate "EP93xx Watchdog"
+ depends on WATCHDOG && ARCH_EP93XX
+ help
+ Say Y here if to include support for the watchdog timer
+ embedded in the Cirrus Logic EP93xx family of devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ep93xx_wdt.
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 36c0b282b8b..d6f27fde990 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
# X86 (i386 + ia64 + x86_64) Architecture
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 00000000000..9021dbb7829
--- /dev/null
+++ b/drivers/char/watchdog/ep93xx_wdt.c
@@ -0,0 +1,257 @@
+/*
+ * Watchdog driver for Cirrus Logic EP93xx family of devices.
+ *
+ * Copyright (c) 2004 Ray Lehtiniemi
+ * Copyright (c) 2006 Tower Technologies
+ * Based on ep93xx driver, bits from alim7101_wdt.c
+ *
+ * Authors: Ray Lehtiniemi <rayl@mail.com>,
+ * Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This watchdog fires after 250msec, which is a too short interval
+ * for us to rely on the user space daemon alone. So we ping the
+ * wdt each ~200msec and eventually stop doing it if the user space
+ * daemon dies.
+ *
+ * TODO:
+ *
+ * - Test last reset from watchdog status
+ * - Add a few missing ioctls
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+
+#define WDT_VERSION "0.3"
+#define PFX "ep93xx_wdt: "
+
+/* default timeout (secs) */
+#define WDT_TIMEOUT 30
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int timeout = WDT_TIMEOUT;
+
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define WDT_IN_USE 0
+#define WDT_OK_TO_CLOSE 1
+
+#define EP93XX_WDT_REG(x) (EP93XX_WATCHDOG_BASE + (x))
+#define EP93XX_WDT_WATCHDOG EP93XX_WDT_REG(0x00)
+#define EP93XX_WDT_WDSTATUS EP93XX_WDT_REG(0x04)
+
+/* reset the wdt every ~200ms */
+#define WDT_INTERVAL (HZ/5)
+
+static void wdt_enable(void)
+{
+ __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_disable(void)
+{
+ __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG);
+}
+
+static inline void wdt_ping(void)
+{
+ __raw_writew(0x5555, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_startup(void)
+{
+ next_heartbeat = jiffies + (timeout * HZ);
+
+ wdt_enable();
+ mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static void wdt_shutdown(void)
+{
+ del_timer_sync(&timer);
+ wdt_disable();
+}
+
+static void wdt_keepalive(void)
+{
+ /* user land ping */
+ next_heartbeat = jiffies + (timeout * HZ);
+}
+
+static int ep93xx_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ wdt_startup();
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t
+ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
+ loff_t *ppos)
+{
+ /* Can't seek (pwrite) on this device */
+ if (*ppos != file->f_pos)
+ return -ESPIPE;
+
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ else
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ }
+ }
+ wdt_keepalive();
+ }
+
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
+ .identity = "EP93xx Watchdog",
+};
+
+static int
+ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(boot_status, (int __user *)arg);
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ /* actually, it is 0.250 seconds.... */
+ ret = put_user(1, (int __user *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int ep93xx_wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+ wdt_shutdown();
+ else
+ printk(KERN_CRIT PFX "Device closed unexpectedly - "
+ "timer will not stop\n");
+
+ clear_bit(WDT_IN_USE, &wdt_status);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return 0;
+}
+
+static struct file_operations ep93xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .write = ep93xx_wdt_write,
+ .ioctl = ep93xx_wdt_ioctl,
+ .open = ep93xx_wdt_open,
+ .release = ep93xx_wdt_release,
+};
+
+static struct miscdevice ep93xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ep93xx_wdt_fops,
+};
+
+static void ep93xx_timer_ping(unsigned long data)
+{
+ if (time_before(jiffies, next_heartbeat))
+ wdt_ping();
+
+ /* Re-set the timer interval */
+ mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static int __init ep93xx_wdt_init(void)
+{
+ int err;
+
+ err = misc_register(&ep93xx_wdt_miscdev);
+
+ boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0;
+
+ printk(KERN_INFO PFX "EP93XX watchdog, driver version "
+ WDT_VERSION "%s\n",
+ (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08)
+ ? " (nCS1 disable detected)" : "");
+
+ if (timeout < 1 || timeout > 3600) {
+ timeout = WDT_TIMEOUT;
+ printk(KERN_INFO PFX
+ "timeout value must be 1<=x<=3600, using %d\n",
+ timeout);
+ }
+
+ setup_timer(&timer, ep93xx_timer_ping, 1);
+ return err;
+}
+
+static void __exit ep93xx_wdt_exit(void)
+{
+ wdt_shutdown();
+ misc_deregister(&ep93xx_wdt_miscdev);
+}
+
+module_init(ep93xx_wdt_init);
+module_exit(ep93xx_wdt_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("EP93xx Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(WDT_VERSION);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);