diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
index 88a011c9f985c090def78c8a7cd29f0b734d5582..d537c48cc6d02d0541b44271698f6997e90332e4 100644
--- a/Documentation/input/joystick-parport.txt
+++ b/Documentation/input/joystick-parport.txt
@@ -36,12 +36,12 @@ with them.
 
   All NES and SNES use the same synchronous serial protocol, clocked from
 the computer's side (and thus timing insensitive). To allow up to 5 NES
-and/or SNES gamepads connected to the parallel port at once, the output
-lines of the parallel port are shared, while one of 5 available input lines
-is assigned to each gamepad.
+and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
+the output lines of the parallel port are shared, while one of 5 available
+input lines is assigned to each gamepad.
 
   This protocol is handled by the gamecon.c driver, so that's the one
-you'll use for NES and SNES gamepads.
+you'll use for NES, SNES gamepads and SNES mice.
 
   The main problem with PC parallel ports is that they don't have +5V power
 source on any of their pins. So, if you want a reliable source of power
@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is
 either a NES or NES clone and will work with this connection. SNES gamepads
 also use 5 wires, but have more buttons. They will work as well, of course.
 
-Pinout for NES gamepads                 Pinout for SNES gamepads
+Pinout for NES gamepads                 Pinout for SNES gamepads and mice
 
 	   +----> Power                   +-----------------------\
 	   |                            7 | o  o  o  o |  x  x  o  | 1
@@ -454,6 +454,7 @@ uses the following kernel/module command line:
 	  6  | N64 pad
 	  7  | Sony PSX controller
 	  8  | Sony PSX DDR controller
+	  9  | SNES mouse
 
   The exact type of the PSX controller type is autoprobed when used so
 hot swapping should work (but is not recomended).
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index dd87696705969ce1e07ef095285c3370bb170f93..a15e18a00258ee69d65329945c174e0ec0e3f66c 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
+#include <linux/platform_device.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
 #include <linux/seq_file.h>
@@ -1478,3 +1479,20 @@ alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
 #endif
         return NOTIFY_DONE;
 }
+
+static __init int add_pcspkr(void)
+{
+	struct platform_device *pd;
+	int ret;
+
+	pd = platform_device_alloc("pcspkr", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+device_initcall(add_pcspkr);
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 8c08660b4e5dd6c2411fb79fa62cbc557f751a70..eacc3f0a2ea4de5b334f8172cce979570eddc133 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -34,6 +34,7 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
+#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/mca.h>
 #include <linux/root_dev.h>
@@ -1547,6 +1548,23 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+static __init int add_pcspkr(void)
+{
+	struct platform_device *pd;
+	int ret;
+
+	pd = platform_device_alloc("pcspkr", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+device_initcall(add_pcspkr);
+
 #include "setup_arch_post.h"
 /*
  * Local Variables:
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5080ea1799a43807c31f718b439b21b441d487aa..e15709ce886626158aba18c05851cb5bc04065c6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -233,6 +233,7 @@ config MACH_JAZZ
 	select ARC32
 	select ARCH_MAY_HAVE_PC_FDC
 	select GENERIC_ISA_DMA
+	select I8253
 	select I8259
 	select ISA
 	select SYS_HAS_CPU_R4X00
@@ -530,6 +531,7 @@ config QEMU
 	select DMA_COHERENT
 	select GENERIC_ISA_DMA
 	select HAVE_STD_PC_SERIAL_PORT
+	select I8253
 	select I8259
 	select ISA
 	select SWAP_IO_SPACE
@@ -714,6 +716,7 @@ config SNI_RM200_PCI
 	select HAVE_STD_PC_SERIAL_PORT
 	select HW_HAS_EISA
 	select HW_HAS_PCI
+	select I8253
 	select I8259
 	select ISA
 	select SYS_HAS_CPU_R4X00
@@ -1721,6 +1724,9 @@ config MMU
 	bool
 	default y
 
+config I8253
+	bool
+
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index f36c4f20ee8af09bbeca3658cf96ba15a410d8b2..309d54cceda3c66eb93d4c48eb655aaa6238d72c 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -59,6 +59,8 @@ obj-$(CONFIG_PROC_FS)		+= proc.o
 
 obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
 
+obj-$(CONFIG_I8253)		+= i8253.o
+
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
new file mode 100644
index 0000000000000000000000000000000000000000..475df6904219b20923ceaf0c60d6c727bcea13dd
--- /dev/null
+++ b/arch/mips/kernel/i8253.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * Implements device information for i8253 timer chip
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation
+ */
+
+#include <linux/platform_device.h>
+
+static __init int add_pcspkr(void)
+{
+	struct platform_device *pd;
+	int ret;
+
+	pd = platform_device_alloc("pcspkr", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+device_initcall(add_pcspkr);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index c607f3b9ca17494ce7a1f93ddac8d811ce66b997..1d93e73a700345ab65c3243786edabb8422587d8 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -21,6 +21,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/initrd.h>
+#include <linux/platform_device.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/ioport.h>
@@ -462,6 +463,29 @@ static int __init early_xmon(char *p)
 early_param("xmon", early_xmon);
 #endif
 
+static __init int add_pcspkr(void)
+{
+	struct device_node *np;
+	struct platform_device *pd;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL, "pnpPNP,100");
+	of_node_put(np);
+	if (!np)
+		return -ENODEV;
+
+	pd = platform_device_alloc("pcspkr", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+device_initcall(add_pcspkr);
+
 void probe_machine(void)
 {
 	extern struct machdep_calls __machine_desc_start;
diff --git a/drivers/Makefile b/drivers/Makefile
index d6e8ffbd8132d8b29fc51f699e63e8a8b9e4b1dc..55205c8d23184bb0cdea144083c16fa769b67dcb 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR)		+= connector/
 obj-$(CONFIG_FB_I810)           += video/i810/
 obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
-# we also need input/serio early so serio bus is initialized by the time
-# serial drivers start registering their serio ports
-obj-$(CONFIG_SERIO)		+= input/serio/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ mfd/ net/ media/
@@ -53,6 +50,7 @@ obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
+obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_I2O)		+= message/
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 8b603b2d1c4211ebedb7a4e575db84278b75c276..935670a3cd987a2ea13e4412873b9ed8ca41e17d 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -74,7 +74,7 @@ void compute_shiftstate(void);
 	k_self,		k_fn,		k_spec,		k_pad,\
 	k_dead,		k_cons,		k_cur,		k_shift,\
 	k_meta,		k_ascii,	k_lock,		k_lowercase,\
-	k_slock,	k_dead2,	k_ignore,	k_ignore
+	k_slock,	k_dead2,	k_brl,		k_ignore
 
 typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
 			    char up_flag, struct pt_regs *regs);
@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
 const int max_vals[] = {
 	255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
 	NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
-	255, NR_LOCK - 1, 255
+	255, NR_LOCK - 1, 255, NR_BRL - 1
 };
 
 const int NR_TYPES = ARRAY_SIZE(max_vals);
@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)];		/* keyboard key bitmap */
 static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
 static int dead_key_next;
 static int npadch = -1;					/* -1 or number assembled on pad */
-static unsigned char diacr;
+static unsigned int diacr;
 static char rep;					/* flag telling character repeat */
 
 static unsigned char ledstate = 0xff;			/* undefined */
@@ -394,22 +394,30 @@ void compute_shiftstate(void)
  * Otherwise, conclude that DIACR was not combining after all,
  * queue it and return CH.
  */
-static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
+static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
 {
-	int d = diacr;
+	unsigned int d = diacr;
 	unsigned int i;
 
 	diacr = 0;
 
-	for (i = 0; i < accent_table_size; i++) {
-		if (accent_table[i].diacr == d && accent_table[i].base == ch)
-			return accent_table[i].result;
+	if ((d & ~0xff) == BRL_UC_ROW) {
+		if ((ch & ~0xff) == BRL_UC_ROW)
+			return d | ch;
+	} else {
+		for (i = 0; i < accent_table_size; i++)
+			if (accent_table[i].diacr == d && accent_table[i].base == ch)
+				return accent_table[i].result;
 	}
 
-	if (ch == ' ' || ch == d)
+	if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
 		return d;
 
-	put_queue(vc, d);
+	if (kbd->kbdmode == VC_UNICODE)
+		to_utf8(vc, d);
+	else if (d < 0x100)
+		put_queue(vc, d);
+
 	return ch;
 }
 
@@ -419,7 +427,10 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
 static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
 {
 	if (diacr) {
-		put_queue(vc, diacr);
+		if (kbd->kbdmode == VC_UNICODE)
+			to_utf8(vc, diacr);
+		else if (diacr < 0x100)
+			put_queue(vc, diacr);
 		diacr = 0;
 	}
 	put_queue(vc, 13);
@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s
 	printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
 }
 
-static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
 {
 	if (up_flag)
 		return;		/* no action, if this is a key release */
@@ -628,7 +639,10 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
 		diacr = value;
 		return;
 	}
-	put_queue(vc, value);
+	if (kbd->kbdmode == VC_UNICODE)
+		to_utf8(vc, value);
+	else if (value < 0x100)
+		put_queue(vc, value);
 }
 
 /*
@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
  * dead keys modifying the same character. Very useful
  * for Vietnamese.
  */
-static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
 {
 	if (up_flag)
 		return;
 	diacr = (diacr ? handle_diacr(vc, value) : value);
 }
 
+static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+	k_unicode(vc, value, up_flag, regs);
+}
+
+static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+	k_deadunicode(vc, value, up_flag, regs);
+}
+
 /*
  * Obsolete - for backwards compatibility only
  */
@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct
 {
 	static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
 	value = ret_diacr[value];
-	k_dead2(vc, value, up_flag, regs);
+	k_deadunicode(vc, value, up_flag, regs);
 }
 
 static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
@@ -835,6 +859,62 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc
 	}
 }
 
+/* by default, 300ms interval for combination release */
+static long brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
+module_param(brl_timeout, long, 0644);
+static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+	static unsigned pressed,committing;
+	static unsigned long releasestart;
+
+	if (kbd->kbdmode != VC_UNICODE) {
+		if (!up_flag)
+			printk("keyboard mode must be unicode for braille patterns\n");
+		return;
+	}
+
+	if (!value) {
+		k_unicode(vc, BRL_UC_ROW, up_flag, regs);
+		return;
+	}
+
+	if (value > 8)
+		return;
+
+	if (brl_timeout < 0) {
+		k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs);
+		return;
+	}
+
+	if (up_flag) {
+		if (brl_timeout) {
+			if (!committing ||
+			    jiffies - releasestart > (brl_timeout * HZ) / 1000) {
+				committing = pressed;
+				releasestart = jiffies;
+			}
+			pressed &= ~(1 << (value - 1));
+			if (!pressed) {
+				if (committing) {
+					k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+					committing = 0;
+				}
+			}
+		} else {
+			if (committing) {
+				k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+				committing = 0;
+			}
+			pressed &= ~(1 << (value - 1));
+		}
+	} else {
+		pressed |= 1 << (value - 1);
+		if (!brl_timeout)
+			committing = pressed;
+	}
+}
+
 /*
  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
  * or (ii) whatever pattern of lights people want to show using KDSETLED,
@@ -1125,9 +1205,13 @@ static void kbd_keycode(unsigned int keycode, int down,
 	}
 
 	if (keycode > NR_KEYS)
-		return;
+		if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
+			keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
+		else
+			return;
+	else
+		keysym = key_map[keycode];
 
-	keysym = key_map[keycode];
 	type = KTYP(keysym);
 
 	if (type < 0xf0) {
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index d7828936fd8f5edf49145e68bde6272628cfcac9..07358fb51b82aacf8e7cb1b9fbe9f2cc943eb455 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct
 {
 	struct input_handle *handle;
 
-	if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
 		return NULL;
-	memset(handle, 0, sizeof(struct input_handle));
 
 	handle->dev = dev;
 	handle->handler = handler;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 745979f33dc2e2cf3e3a9bbc1909b50897cb6c04..a34e3d91d9ed987d387bf77f1eab888e63029552 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file)
 	if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
 		return accept_err;
 
-	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(list, 0, sizeof(struct evdev_list));
 
 	list->evdev = evdev_table[i];
 	list_add_tail(&list->node, &evdev_table[i]->list);
@@ -609,9 +608,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
 		return NULL;
 	}
 
-	if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
+	if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
 		return NULL;
-	memset(evdev, 0, sizeof(struct evdev));
 
 	INIT_LIST_HEAD(&evdev->list);
 	init_waitqueue_head(&evdev->wait);
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index b765a155c0088db9c29cad78ca8fd3f9810ac838..36644bff379d5126a90d209fc71f8605ab4b74e9 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>	/* HZ */
+#include <linux/mutex.h>
 
 /*#include <asm/io.h>*/
 
@@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling);
 EXPORT_SYMBOL(gameport_stop_polling);
 
 /*
- * gameport_sem protects entire gameport subsystem and is taken
+ * gameport_mutex protects entire gameport subsystem and is taken
  * every time gameport port or driver registrered or unregistered.
  */
-static DECLARE_MUTEX(gameport_sem);
+static DEFINE_MUTEX(gameport_mutex);
 
 static LIST_HEAD(gameport_list);
 
@@ -265,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner,
 	if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
 		if (!try_module_get(owner)) {
 			printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+			kfree(event);
 			goto out;
 		}
 
@@ -342,7 +344,7 @@ static void gameport_handle_event(void)
 	struct gameport_event *event;
 	struct gameport_driver *gameport_drv;
 
-	down(&gameport_sem);
+	mutex_lock(&gameport_mutex);
 
 	/*
 	 * Note that we handle only one event here to give swsusp
@@ -379,7 +381,7 @@ static void gameport_handle_event(void)
 		gameport_free_event(event);
 	}
 
-	up(&gameport_sem);
+	mutex_unlock(&gameport_mutex);
 }
 
 /*
@@ -464,7 +466,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
 	struct device_driver *drv;
 	int retval;
 
-	retval = down_interruptible(&gameport_sem);
+	retval = mutex_lock_interruptible(&gameport_mutex);
 	if (retval)
 		return retval;
 
@@ -484,7 +486,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
 		retval = -EINVAL;
 	}
 
-	up(&gameport_sem);
+	mutex_unlock(&gameport_mutex);
 
 	return retval;
 }
@@ -521,7 +523,7 @@ static void gameport_init_port(struct gameport *gameport)
 
 	__module_get(THIS_MODULE);
 
-	init_MUTEX(&gameport->drv_sem);
+	mutex_init(&gameport->drv_mutex);
 	device_initialize(&gameport->dev);
 	snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
 		 "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
@@ -661,10 +663,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
  */
 void gameport_unregister_port(struct gameport *gameport)
 {
-	down(&gameport_sem);
+	mutex_lock(&gameport_mutex);
 	gameport_disconnect_port(gameport);
 	gameport_destroy_port(gameport);
-	up(&gameport_sem);
+	mutex_unlock(&gameport_mutex);
 }
 
 
@@ -717,7 +719,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
 {
 	struct gameport *gameport;
 
-	down(&gameport_sem);
+	mutex_lock(&gameport_mutex);
 	drv->ignore = 1;	/* so gameport_find_driver ignores it */
 
 start_over:
@@ -731,7 +733,7 @@ start_over:
 	}
 
 	driver_unregister(&drv->driver);
-	up(&gameport_sem);
+	mutex_unlock(&gameport_mutex);
 }
 
 static int gameport_bus_match(struct device *dev, struct device_driver *drv)
@@ -743,9 +745,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
 
 static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
 {
-	down(&gameport->drv_sem);
+	mutex_lock(&gameport->drv_mutex);
 	gameport->drv = drv;
-	up(&gameport->drv_sem);
+	mutex_unlock(&gameport->drv_mutex);
 }
 
 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
@@ -796,5 +798,5 @@ static void __exit gameport_exit(void)
 	kthread_stop(gameport_task);
 }
 
-module_init(gameport_init);
+subsys_initcall(gameport_init);
 module_exit(gameport_exit);
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index d2e55dc956bafd3477ebd4e7ea448263b6375fcd..3e2d28f263e9ad56c7b2cb7f3c4d697b28e849db 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver;
 
 #endif
 
-static int pnp_registered = 0;
-
 static int __init ns558_init(void)
 {
 	int i = 0;
+	int error;
 
-	if (pnp_register_driver(&ns558_pnp_driver) >= 0)
-		pnp_registered = 1;
+	error = pnp_register_driver(&ns558_pnp_driver);
+	if (error && error != -ENODEV)	/* should be ENOSYS really */
+		return error;
 
 /*
  * Probe ISA ports after PnP, so that PnP ports that are already
@@ -270,7 +270,7 @@ static int __init ns558_init(void)
 	while (ns558_isa_portlist[i])
 		ns558_isa_probe(ns558_isa_portlist[i++]);
 
-	return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
+	return list_empty(&ns558_list) && error ? -ENODEV : 0;
 }
 
 static void __exit ns558_exit(void)
@@ -283,8 +283,7 @@ static void __exit ns558_exit(void)
 		kfree(ns558);
 	}
 
-	if (pnp_registered)
-		pnp_unregister_driver(&ns558_pnp_driver);
+	pnp_unregister_driver(&ns558_pnp_driver);
 }
 
 module_init(ns558_init);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index f8af0945964ecf85147a54712e08b73f237101e1..a935abeffffc4618bb7f99f429b09e81f1ce4609 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -18,9 +18,11 @@
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -224,7 +226,7 @@ int input_open_device(struct input_handle *handle)
 	struct input_dev *dev = handle->dev;
 	int err;
 
-	err = down_interruptible(&dev->sem);
+	err = mutex_lock_interruptible(&dev->mutex);
 	if (err)
 		return err;
 
@@ -236,7 +238,7 @@ int input_open_device(struct input_handle *handle)
 	if (err)
 		handle->open--;
 
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 
 	return err;
 }
@@ -255,13 +257,13 @@ void input_close_device(struct input_handle *handle)
 
 	input_release_device(handle);
 
-	down(&dev->sem);
+	mutex_lock(&dev->mutex);
 
 	if (!--dev->users && dev->close)
 		dev->close(dev);
 	handle->open--;
 
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 }
 
 static void input_link_handle(struct input_handle *handle)
@@ -315,21 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
 	return NULL;
 }
 
-static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
-{
-	int i;
-	int len = 0;
-
-	for (i = NBITS(max) - 1; i > 0; i--)
-		if (bitmap[i])
-			break;
-
-	for (; i >= 0; i--)
-		len += snprintf(buf + len, max(buf_size - len, 0),
-				"%lx%s", bitmap[i], i > 0 ? " " : "");
-	return len;
-}
-
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -342,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void)
 	wake_up(&input_devices_poll_wait);
 }
 
-static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
 {
 	int state = input_devices_state;
 	poll_wait(file, &input_devices_poll_wait, wait);
@@ -351,115 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
 	return 0;
 }
 
-#define SPRINTF_BIT(ev, bm)						\
-	do {								\
-		len += sprintf(buf + len, "B: %s=", #ev);		\
-		len += input_print_bitmap(buf + len, INT_MAX,		\
-					dev->bm##bit, ev##_MAX);	\
-		len += sprintf(buf + len, "\n");			\
-	} while (0)
+static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
+{
+	struct list_head *node;
+	loff_t i = 0;
 
-#define TEST_AND_SPRINTF_BIT(ev, bm)					\
-	do {								\
-		if (test_bit(EV_##ev, dev->evbit))			\
-			SPRINTF_BIT(ev, bm);				\
-	} while (0)
+	list_for_each(node, list)
+		if (i++ == *pos)
+			return node;
+
+	return NULL;
+}
 
-static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
 {
-	struct input_dev *dev;
-	struct input_handle *handle;
-	const char *path;
+	if (element->next == list)
+		return NULL;
+
+	++(*pos);
+	return element->next;
+}
+
+static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	/* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+
+	return list_get_nth_element(&input_dev_list, pos);
+}
 
-	off_t at = 0;
-	int len, cnt = 0;
+static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	return list_get_next_element(&input_dev_list, v, pos);
+}
 
-	list_for_each_entry(dev, &input_dev_list, node) {
+static void input_devices_seq_stop(struct seq_file *seq, void *v)
+{
+	/* release lock here */
+}
 
-		path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
+				   unsigned long *bitmap, int max)
+{
+	int i;
 
-		len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
-			dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
+	for (i = NBITS(max) - 1; i > 0; i--)
+		if (bitmap[i])
+			break;
 
-		len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
-		len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
-		len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
-		len += sprintf(buf + len, "H: Handlers=");
+	seq_printf(seq, "B: %s=", name);
+	for (; i >= 0; i--)
+		seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+	seq_putc(seq, '\n');
+}
 
-		list_for_each_entry(handle, &dev->h_list, d_node)
-			len += sprintf(buf + len, "%s ", handle->name);
-
-		len += sprintf(buf + len, "\n");
-
-		SPRINTF_BIT(EV, ev);
-		TEST_AND_SPRINTF_BIT(KEY, key);
-		TEST_AND_SPRINTF_BIT(REL, rel);
-		TEST_AND_SPRINTF_BIT(ABS, abs);
-		TEST_AND_SPRINTF_BIT(MSC, msc);
-		TEST_AND_SPRINTF_BIT(LED, led);
-		TEST_AND_SPRINTF_BIT(SND, snd);
-		TEST_AND_SPRINTF_BIT(FF, ff);
-		TEST_AND_SPRINTF_BIT(SW, sw);
-
-		len += sprintf(buf + len, "\n");
-
-		at += len;
-
-		if (at >= pos) {
-			if (!*start) {
-				*start = buf + (pos - (at - len));
-				cnt = at - pos;
-			} else  cnt += len;
-			buf += len;
-			if (cnt >= count)
-				break;
-		}
+static int input_devices_seq_show(struct seq_file *seq, void *v)
+{
+	struct input_dev *dev = container_of(v, struct input_dev, node);
+	const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	struct input_handle *handle;
 
-		kfree(path);
-	}
+	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+		   dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
 
-	if (&dev->node == &input_dev_list)
-		*eof = 1;
+	seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+	seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+	seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+	seq_printf(seq, "H: Handlers=");
 
-	return (count > cnt) ? cnt : count;
+	list_for_each_entry(handle, &dev->h_list, d_node)
+		seq_printf(seq, "%s ", handle->name);
+	seq_putc(seq, '\n');
+
+	input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
+	if (test_bit(EV_KEY, dev->evbit))
+		input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
+	if (test_bit(EV_REL, dev->evbit))
+		input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
+	if (test_bit(EV_ABS, dev->evbit))
+		input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
+	if (test_bit(EV_MSC, dev->evbit))
+		input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
+	if (test_bit(EV_LED, dev->evbit))
+		input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
+	if (test_bit(EV_SND, dev->evbit))
+		input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
+	if (test_bit(EV_FF, dev->evbit))
+		input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
+	if (test_bit(EV_SW, dev->evbit))
+		input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+
+	seq_putc(seq, '\n');
+
+	kfree(path);
+	return 0;
 }
 
-static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+static struct seq_operations input_devices_seq_ops = {
+	.start	= input_devices_seq_start,
+	.next	= input_devices_seq_next,
+	.stop	= input_devices_seq_stop,
+	.show	= input_devices_seq_show,
+};
+
+static int input_proc_devices_open(struct inode *inode, struct file *file)
 {
-	struct input_handler *handler;
+	return seq_open(file, &input_devices_seq_ops);
+}
 
-	off_t at = 0;
-	int len = 0, cnt = 0;
-	int i = 0;
+static struct file_operations input_devices_fileops = {
+	.owner		= THIS_MODULE,
+	.open		= input_proc_devices_open,
+	.poll		= input_proc_devices_poll,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
-	list_for_each_entry(handler, &input_handler_list, node) {
+static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	/* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+	seq->private = (void *)(unsigned long)*pos;
+	return list_get_nth_element(&input_handler_list, pos);
+}
+
+static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	seq->private = (void *)(unsigned long)(*pos + 1);
+	return list_get_next_element(&input_handler_list, v, pos);
+}
 
-		if (handler->fops)
-			len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
-				i++, handler->name, handler->minor);
-		else
-			len = sprintf(buf, "N: Number=%d Name=%s\n",
-				i++, handler->name);
+static void input_handlers_seq_stop(struct seq_file *seq, void *v)
+{
+	/* release lock here */
+}
 
-		at += len;
+static int input_handlers_seq_show(struct seq_file *seq, void *v)
+{
+	struct input_handler *handler = container_of(v, struct input_handler, node);
 
-		if (at >= pos) {
-			if (!*start) {
-				*start = buf + (pos - (at - len));
-				cnt = at - pos;
-			} else  cnt += len;
-			buf += len;
-			if (cnt >= count)
-				break;
-		}
-	}
-	if (&handler->node == &input_handler_list)
-		*eof = 1;
+	seq_printf(seq, "N: Number=%ld Name=%s",
+		   (unsigned long)seq->private, handler->name);
+	if (handler->fops)
+		seq_printf(seq, " Minor=%d", handler->minor);
+	seq_putc(seq, '\n');
 
-	return (count > cnt) ? cnt : count;
+	return 0;
 }
+static struct seq_operations input_handlers_seq_ops = {
+	.start	= input_handlers_seq_start,
+	.next	= input_handlers_seq_next,
+	.stop	= input_handlers_seq_stop,
+	.show	= input_handlers_seq_show,
+};
 
-static struct file_operations input_fileops;
+static int input_proc_handlers_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &input_handlers_seq_ops);
+}
+
+static struct file_operations input_handlers_fileops = {
+	.owner		= THIS_MODULE,
+	.open		= input_proc_handlers_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 static int __init input_proc_init(void)
 {
@@ -471,20 +514,19 @@ static int __init input_proc_init(void)
 
 	proc_bus_input_dir->owner = THIS_MODULE;
 
-	entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+	entry = create_proc_entry("devices", 0, proc_bus_input_dir);
 	if (!entry)
 		goto fail1;
 
 	entry->owner = THIS_MODULE;
-	input_fileops = *entry->proc_fops;
-	input_fileops.poll = input_devices_poll;
-	entry->proc_fops = &input_fileops;
+	entry->proc_fops = &input_devices_fileops;
 
-	entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+	entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
 	if (!entry)
 		goto fail2;
 
 	entry->owner = THIS_MODULE;
+	entry->proc_fops = &input_handlers_fileops;
 
 	return 0;
 
@@ -512,13 +554,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
 	struct input_dev *input_dev = to_input_dev(dev);			\
 	int retval;								\
 										\
-	retval = down_interruptible(&input_dev->sem);				\
+	retval = mutex_lock_interruptible(&input_dev->mutex);			\
 	if (retval)								\
 		return retval;							\
 										\
-	retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : "");	\
+	retval = scnprintf(buf, PAGE_SIZE,					\
+			   "%s\n", input_dev->name ? input_dev->name : "");	\
 										\
-	up(&input_dev->sem);							\
+	mutex_unlock(&input_dev->mutex);					\
 										\
 	return retval;								\
 }										\
@@ -528,46 +571,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
 INPUT_DEV_STRING_ATTR_SHOW(uniq);
 
-static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
-			       unsigned int min, unsigned int max)
+static int input_print_modalias_bits(char *buf, int size,
+				     char name, unsigned long *bm,
+				     unsigned int min_bit, unsigned int max_bit)
 {
-	int len, i;
+	int len = 0, i;
 
-	len = snprintf(buf, size, "%c", prefix);
-	for (i = min; i < max; i++)
-		if (arr[LONG(i)] & BIT(i))
-			len += snprintf(buf + len, size - len, "%X,", i);
+	len += snprintf(buf, max(size, 0), "%c", name);
+	for (i = min_bit; i < max_bit; i++)
+		if (bm[LONG(i)] & BIT(i))
+			len += snprintf(buf + len, max(size - len, 0), "%X,", i);
 	return len;
 }
 
-static int print_modalias(char *buf, int size, struct input_dev *id)
+static int input_print_modalias(char *buf, int size, struct input_dev *id,
+				int add_cr)
 {
 	int len;
 
-	len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
-		       id->id.bustype,
-		       id->id.vendor,
-		       id->id.product,
-		       id->id.version);
-
-	len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
-				   0, EV_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
-				   KEY_MIN_INTERESTING, KEY_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
-				   0, REL_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
-				   0, ABS_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
-				   0, MSC_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
-				   0, LED_MAX);
-	len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
-				   0, SND_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
-				   0, FF_MAX);
-	len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
-				   0, SW_MAX);
+	len = snprintf(buf, max(size, 0),
+		       "input:b%04Xv%04Xp%04Xe%04X-",
+		       id->id.bustype, id->id.vendor,
+		       id->id.product, id->id.version);
+
+	len += input_print_modalias_bits(buf + len, size - len,
+				'e', id->evbit, 0, EV_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'r', id->relbit, 0, REL_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'a', id->absbit, 0, ABS_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'm', id->mscbit, 0, MSC_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'l', id->ledbit, 0, LED_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				's', id->sndbit, 0, SND_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'f', id->ffbit, 0, FF_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'w', id->swbit, 0, SW_MAX);
+
+	if (add_cr)
+		len += snprintf(buf + len, max(size - len, 0), "\n");
+
 	return len;
 }
 
@@ -576,9 +624,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
 	struct input_dev *id = to_input_dev(dev);
 	ssize_t len;
 
-	len = print_modalias(buf, PAGE_SIZE, id);
-	len += snprintf(buf + len, PAGE_SIZE-len, "\n");
-	return len;
+	len = input_print_modalias(buf, PAGE_SIZE, id, 1);
+
+	return max_t(int, len, PAGE_SIZE);
 }
 static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
@@ -598,7 +646,7 @@ static struct attribute_group input_dev_attr_group = {
 static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
 {										\
 	struct input_dev *input_dev = to_input_dev(dev);			\
-	return sprintf(buf, "%04x\n", input_dev->id.name);			\
+	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);		\
 }										\
 static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
 
@@ -620,11 +668,33 @@ static struct attribute_group input_dev_id_attr_group = {
 	.attrs	= input_dev_id_attrs,
 };
 
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+			      int max, int add_cr)
+{
+	int i;
+	int len = 0;
+
+	for (i = NBITS(max) - 1; i > 0; i--)
+		if (bitmap[i])
+			break;
+
+	for (; i >= 0; i--)
+		len += snprintf(buf + len, max(buf_size - len, 0),
+				"%lx%s", bitmap[i], i > 0 ? " " : "");
+
+	if (add_cr)
+		len += snprintf(buf + len, max(buf_size - len, 0), "\n");
+
+	return len;
+}
+
 #define INPUT_DEV_CAP_ATTR(ev, bm)						\
 static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
 {										\
 	struct input_dev *input_dev = to_input_dev(dev);			\
-	return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+	int len = input_print_bitmap(buf, PAGE_SIZE,				\
+				     input_dev->bm##bit, ev##_MAX, 1);		\
+	return min_t(int, len, PAGE_SIZE);					\
 }										\
 static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
 
@@ -669,8 +739,8 @@ static void input_dev_release(struct class_device *class_dev)
  * device bitfields.
  */
 static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
-				    char *buffer, int buffer_size, int *cur_len,
-				    const char *name, unsigned long *bitmap, int max)
+				   char *buffer, int buffer_size, int *cur_len,
+				   const char *name, unsigned long *bitmap, int max)
 {
 	if (*cur_index >= num_envp - 1)
 		return -ENOMEM;
@@ -678,12 +748,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
 	envp[*cur_index] = buffer + *cur_len;
 
 	*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
-	if (*cur_len > buffer_size)
+	if (*cur_len >= buffer_size)
 		return -ENOMEM;
 
 	*cur_len += input_print_bitmap(buffer + *cur_len,
 					max(buffer_size - *cur_len, 0),
-					bitmap, max) + 1;
+					bitmap, max, 0) + 1;
+	if (*cur_len > buffer_size)
+		return -ENOMEM;
+
+	(*cur_index)++;
+	return 0;
+}
+
+static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
+					 char *buffer, int buffer_size, int *cur_len,
+					 struct input_dev *dev)
+{
+	if (*cur_index >= num_envp - 1)
+		return -ENOMEM;
+
+	envp[*cur_index] = buffer + *cur_len;
+
+	*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
+			     "MODALIAS=");
+	if (*cur_len >= buffer_size)
+		return -ENOMEM;
+
+	*cur_len += input_print_modalias(buffer + *cur_len,
+					 max(buffer_size - *cur_len, 0),
+					 dev, 0) + 1;
 	if (*cur_len > buffer_size)
 		return -ENOMEM;
 
@@ -693,7 +787,7 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
 
 #define INPUT_ADD_HOTPLUG_VAR(fmt, val...)				\
 	do {								\
-		int err = add_uevent_var(envp, num_envp, &i,	\
+		int err = add_uevent_var(envp, num_envp, &i,		\
 					buffer, buffer_size, &len,	\
 					fmt, val);			\
 		if (err)						\
@@ -709,6 +803,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
 			return err;					\
 	} while (0)
 
+#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev)				\
+	do {								\
+		int err = input_add_uevent_modalias_var(envp,		\
+					num_envp, &i,			\
+					buffer, buffer_size, &len,	\
+					dev);				\
+		if (err)						\
+			return err;					\
+	} while (0)
+
 static int input_dev_uevent(struct class_device *cdev, char **envp,
 			    int num_envp, char *buffer, int buffer_size)
 {
@@ -744,9 +848,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
 	if (test_bit(EV_SW, dev->evbit))
 		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
 
-	envp[i++] = buffer + len;
-	len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
-	len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
+	INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
 
 	envp[i] = NULL;
 	return 0;
@@ -790,7 +892,7 @@ int input_register_device(struct input_dev *dev)
 		return -EINVAL;
 	}
 
-	init_MUTEX(&dev->sem);
+	mutex_init(&dev->mutex);
 	set_bit(EV_SYN, dev->evbit);
 
 	/*
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 20e2972b9204f25fd5e60d9c051271f0a32acfb8..949bdcef8c2be7f7f9365a1fa96719c986b767f7 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file)
 	if (i >= JOYDEV_MINORS || !joydev_table[i])
 		return -ENODEV;
 
-	if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+	if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(list, 0, sizeof(struct joydev_list));
 
 	list->joydev = joydev_table[i];
 	list_add_tail(&list->node, &joydev_table[i]->list);
@@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
 		return NULL;
 	}
 
-	if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
+	if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
 		return NULL;
-	memset(joydev, 0, sizeof(struct joydev));
 
 	INIT_LIST_HEAD(&joydev->list);
 	init_waitqueue_head(&joydev->wait);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index ec55a29fc861047dcd5ff11100a8fb797faaec8e..7249d324297b8d441a64113ffb2debd2131cb45c 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -36,6 +36,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/mutex.h>
 
 #include <asm/system.h>
 #include <asm/amigahw.h>
@@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
 __obsolete_setup("amijoy=");
 
 static int amijoy_used;
-static DECLARE_MUTEX(amijoy_sem);
+static DEFINE_MUTEX(amijoy_mutex);
 static struct input_dev *amijoy_dev[2];
 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
 
@@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev)
 {
 	int err;
 
-	err = down_interruptible(&amijoy_sem);
+	err = mutex_lock_interruptible(&amijoy_mutex);
 	if (err)
 		return err;
 
@@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev)
 
 	amijoy_used++;
 out:
-	up(&amijoy_sem);
+	mutex_unlock(&amijoy_mutex);
 	return err;
 }
 
 static void amijoy_close(struct input_dev *dev)
 {
-	down(&amijoy_sem);
+	mutex_lock(&amijoy_mutex);
 	if (!--amijoy_used)
 		free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
-	up(&amijoy_sem);
+	mutex_unlock(&amijoy_mutex);
 }
 
 static int __init amijoy_init(void)
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index dcffc34f30c3c130b7a61d5e8b30cf3c453874a8..e61894685cb1b29f3ef884a9e8ce9d5e780d9c56 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/parport.h>
 #include <linux/input.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
@@ -111,7 +112,7 @@ struct db9 {
 	struct pardevice *pd;
 	int mode;
 	int used;
-	struct semaphore sem;
+	struct mutex mutex;
 	char phys[DB9_MAX_DEVICES][32];
 };
 
@@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev)
 	struct parport *port = db9->pd->port;
 	int err;
 
-	err = down_interruptible(&db9->sem);
+	err = mutex_lock_interruptible(&db9->mutex);
 	if (err)
 		return err;
 
@@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev)
 		mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
 	}
 
-	up(&db9->sem);
+	mutex_unlock(&db9->mutex);
 	return 0;
 }
 
@@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev)
 	struct db9 *db9 = dev->private;
 	struct parport *port = db9->pd->port;
 
-	down(&db9->sem);
+	mutex_lock(&db9->mutex);
 	if (!--db9->used) {
 		del_timer_sync(&db9->timer);
 		parport_write_control(port, 0x00);
 		parport_data_forward(port);
 		parport_release(db9->pd);
 	}
-	up(&db9->sem);
+	mutex_unlock(&db9->mutex);
 }
 
 static struct db9 __init *db9_probe(int parport, int mode)
@@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
 		goto err_unreg_pardev;
 	}
 
-	init_MUTEX(&db9->sem);
+	mutex_init(&db9->mutex);
 	db9->pd = pd;
 	db9->mode = mode;
 	init_timer(&db9->timer);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 900587acdb47c16d1c983f9c36c27a067fb375d0..ecbdb6b9bbd6dd64323a929a98a5b95d6d97dc52 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -7,6 +7,7 @@
  *  Based on the work of:
  *	Andree Borrmann		John Dahlstrom
  *	David Kuder		Nathan Hand
+ *	Raphael Assenat
  */
 
 /*
@@ -36,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/parport.h>
 #include <linux/input.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
@@ -72,8 +74,9 @@ __obsolete_setup("gc_3=");
 #define GC_N64		6
 #define GC_PSX		7
 #define GC_DDR		8
+#define GC_SNESMOUSE	9
 
-#define GC_MAX		8
+#define GC_MAX		9
 
 #define GC_REFRESH_TIME	HZ/100
 
@@ -83,7 +86,7 @@ struct gc {
 	struct timer_list timer;
 	unsigned char pads[GC_MAX + 1];
 	int used;
-	struct semaphore sem;
+	struct mutex mutex;
 	char phys[GC_MAX_DEVICES][32];
 };
 
@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
 				"Multisystem 2-button joystick", "N64 controller", "PSX controller",
-				"PSX DDR controller" };
+				"PSX DDR controller", "SNES mouse" };
 /*
  * N64 support.
  */
@@ -205,9 +208,12 @@ static void gc_n64_process_packet(struct gc *gc)
  * NES/SNES support.
  */
 
-#define GC_NES_DELAY	6	/* Delay between bits - 6us */
-#define GC_NES_LENGTH	8	/* The NES pads use 8 bits of data */
-#define GC_SNES_LENGTH	12	/* The SNES true length is 16, but the last 4 bits are unused */
+#define GC_NES_DELAY		6	/* Delay between bits - 6us */
+#define GC_NES_LENGTH		8	/* The NES pads use 8 bits of data */
+#define GC_SNES_LENGTH		12	/* The SNES true length is 16, but the
+					   last 4 bits are unused */
+#define GC_SNESMOUSE_LENGTH	32	/* The SNES mouse uses 32 bits, the first
+					   16 bits are equivalent to a gamepad */
 
 #define GC_NES_POWER	0xfc
 #define GC_NES_CLOCK	0x01
@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
 
 static void gc_nes_process_packet(struct gc *gc)
 {
-	unsigned char data[GC_SNES_LENGTH];
+	unsigned char data[GC_SNESMOUSE_LENGTH];
 	struct input_dev *dev;
-	int i, j, s;
+	int i, j, s, len;
+	char x_rel, y_rel;
+
+	len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
+			(gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
 
-	gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+	gc_nes_read_packet(gc, len, data);
 
 	for (i = 0; i < GC_MAX_DEVICES; i++) {
 
@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc)
 			for (j = 0; j < 8; j++)
 				input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
 
+		if (s & gc->pads[GC_SNESMOUSE]) {
+			/*
+			 * The 4 unused bits from SNES controllers appear to be ID bits
+			 * so use them to make sure iwe are dealing with a mouse.
+			 * gamepad is connected. This is important since
+			 * my SNES gamepad sends 1's for bits 16-31, which
+			 * cause the mouse pointer to quickly move to the
+			 * upper left corner of the screen.
+			 */
+			if (!(s & data[12]) && !(s & data[13]) &&
+			    !(s & data[14]) && (s & data[15])) {
+				input_report_key(dev, BTN_LEFT, s & data[9]);
+				input_report_key(dev, BTN_RIGHT, s & data[8]);
+
+				x_rel = y_rel = 0;
+				for (j = 0; j < 7; j++) {
+					x_rel <<= 1;
+					if (data[25 + j] & s)
+						x_rel |= 1;
+
+					y_rel <<= 1;
+					if (data[17 + j] & s)
+						y_rel |= 1;
+				}
+
+				if (x_rel) {
+					if (data[24] & s)
+						x_rel = -x_rel;
+					input_report_rel(dev, REL_X, x_rel);
+				}
+
+				if (y_rel) {
+					if (data[16] & s)
+						y_rel = -y_rel;
+					input_report_rel(dev, REL_Y, y_rel);
+				}
+			}
+		}
 		input_sync(dev);
 	}
 }
@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private)
 		gc_n64_process_packet(gc);
 
 /*
- * NES and SNES pads
+ * NES and SNES pads or mouse
  */
 
-	if (gc->pads[GC_NES] || gc->pads[GC_SNES])
+	if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
 		gc_nes_process_packet(gc);
 
 /*
@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev)
 	struct gc *gc = dev->private;
 	int err;
 
-	err = down_interruptible(&gc->sem);
+	err = mutex_lock_interruptible(&gc->mutex);
 	if (err)
 		return err;
 
@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev)
 		mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
 	}
 
-	up(&gc->sem);
+	mutex_unlock(&gc->mutex);
 	return 0;
 }
 
@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev)
 {
 	struct gc *gc = dev->private;
 
-	down(&gc->sem);
+	mutex_lock(&gc->mutex);
 	if (!--gc->used) {
 		del_timer_sync(&gc->timer);
 		parport_write_control(gc->pd->port, 0x00);
 		parport_release(gc->pd);
 	}
-	up(&gc->sem);
+	mutex_unlock(&gc->mutex);
 }
 
 static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
 	input_dev->open = gc_open;
 	input_dev->close = gc_close;
 
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	if (pad_type != GC_SNESMOUSE) {
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-	for (i = 0; i < 2; i++)
-		input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+		for (i = 0; i < 2; i++)
+			input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+	} else
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 
 	gc->pads[0] |= gc_status_bit[idx];
 	gc->pads[pad_type] |= gc_status_bit[idx];
@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
 
 			break;
 
+		case GC_SNESMOUSE:
+			set_bit(BTN_LEFT, input_dev->keybit);
+			set_bit(BTN_RIGHT, input_dev->keybit);
+			set_bit(REL_X, input_dev->relbit);
+			set_bit(REL_Y, input_dev->relbit);
+			break;
+
 		case GC_SNES:
 			for (i = 4; i < 8; i++)
 				set_bit(gc_snes_btn[i], input_dev->keybit);
@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
 		goto err_unreg_pardev;
 	}
 
-	init_MUTEX(&gc->sem);
+	mutex_init(&gc->mutex);
 	gc->pd = pd;
 	init_timer(&gc->timer);
 	gc->timer.data = (long) gc;
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 4678b6dab43bf663040ad084dbff07c66dc3c9bb..2b8e8456c9fae62349da5813eae01e2f789fbab4 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce,
 	unsigned char data[3];
 
 	if (!no_alloc) {
-		down(&iforce->mem_mutex);
+		mutex_lock(&iforce->mem_mutex);
 		if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
-			up(&iforce->mem_mutex);
+			mutex_unlock(&iforce->mem_mutex);
 			return -ENOMEM;
 		}
-		up(&iforce->mem_mutex);
+		mutex_unlock(&iforce->mem_mutex);
 	}
 
 	data[0] = LO(mod_chunk->start);
@@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce,
 	period = TIME_SCALE(period);
 
 	if (!no_alloc) {
-		down(&iforce->mem_mutex);
+		mutex_lock(&iforce->mem_mutex);
 		if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
-			up(&iforce->mem_mutex);
+			mutex_unlock(&iforce->mem_mutex);
 			return -ENOMEM;
 		}
-		up(&iforce->mem_mutex);
+		mutex_unlock(&iforce->mem_mutex);
 	}
 
 	data[0] = LO(mod_chunk->start);
@@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce,
 	fade_duration = TIME_SCALE(fade_duration);
 
 	if (!no_alloc) {
-		down(&iforce->mem_mutex);
+		mutex_lock(&iforce->mem_mutex);
 		if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
-			up(&iforce->mem_mutex);
+			mutex_unlock(&iforce->mem_mutex);
 			return -ENOMEM;
 		}
-		up(&iforce->mem_mutex);
+		mutex_unlock(&iforce->mem_mutex);
 	}
 
 	data[0] = LO(mod_chunk->start);
@@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce,
 	unsigned char data[10];
 
 	if (!no_alloc) {
-		down(&iforce->mem_mutex);
+		mutex_lock(&iforce->mem_mutex);
 		if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
-			up(&iforce->mem_mutex);
+			mutex_unlock(&iforce->mem_mutex);
 			return -ENOMEM;
 		}
-		up(&iforce->mem_mutex);
+		mutex_unlock(&iforce->mem_mutex);
 	}
 
 	data[0] = LO(mod_chunk->start);
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index b6bc049980471892998d705b5068219c6412bede..ab0a26b924cacc728594819049c774a52fabb676 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce)
 
 	init_waitqueue_head(&iforce->wait);
 	spin_lock_init(&iforce->xmit_lock);
-	init_MUTEX(&iforce->mem_mutex);
+	mutex_init(&iforce->mem_mutex);
 	iforce->xmit.buf = iforce->xmit_data;
 	iforce->dev = input_dev;
 
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 146f406b8f8a4dc25dbc248f4a8dce0dc5447f71..668f24535ba0778e23d34c8800f5ffea77d9b6f1 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -37,7 +37,7 @@
 #include <linux/serio.h>
 #include <linux/config.h>
 #include <linux/circ_buf.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 /* This module provides arbitrary resource management routines.
  * I use it to manage the device's memory.
@@ -45,6 +45,7 @@
  */
 #include <linux/ioport.h>
 
+
 #define IFORCE_MAX_LENGTH	16
 
 /* iforce::bus */
@@ -146,7 +147,7 @@ struct iforce {
 	wait_queue_head_t wait;
 	struct resource device_memory;
 	struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
-	struct semaphore mem_mutex;
+	struct mutex mem_mutex;
 };
 
 /* Get hi and low bytes of a 16-bits int */
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index b154938e88a4f0a1c287e69f30f37dc9edef1299..5570fd5487c730bc973b29736033942c00c1c560 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
@@ -86,7 +87,7 @@ static struct tgfx {
 	char phys[TGFX_MAX_DEVICES][32];
 	int sticks;
 	int used;
-	struct semaphore sem;
+	struct mutex sem;
 } *tgfx_base[TGFX_MAX_PORTS];
 
 /*
@@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev)
 	struct tgfx *tgfx = dev->private;
 	int err;
 
-	err = down_interruptible(&tgfx->sem);
+	err = mutex_lock_interruptible(&tgfx->sem);
 	if (err)
 		return err;
 
@@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev)
 		mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
 	}
 
-	up(&tgfx->sem);
+	mutex_unlock(&tgfx->sem);
 	return 0;
 }
 
@@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev)
 {
 	struct tgfx *tgfx = dev->private;
 
-	down(&tgfx->sem);
+	mutex_lock(&tgfx->sem);
 	if (!--tgfx->used) {
 		del_timer_sync(&tgfx->timer);
 		parport_write_control(tgfx->pd->port, 0x00);
 		parport_release(tgfx->pd);
 	}
-	up(&tgfx->sem);
+	mutex_unlock(&tgfx->sem);
 }
 
 
@@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
 		goto err_unreg_pardev;
 	}
 
-	init_MUTEX(&tgfx->sem);
+	mutex_init(&tgfx->sem);
 	tgfx->pd = pd;
 	init_timer(&tgfx->timer);
 	tgfx->timer.data = (long) tgfx;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 3b0ac3b43c541f04ede9fb7503964c5f6b32ee61..a9dda56f62c412a8af7b4be41edb94abe847b361 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD
 if INPUT_KEYBOARD
 
 config KEYBOARD_ATKBD
-	tristate "AT keyboard" if !X86_PC
+	tristate "AT keyboard" if EMBEDDED || !X86_PC
 	default y
 	select SERIO
 	select SERIO_LIBPS2
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ffacf6eca5f536c9107d6e6d0ac8be31f22327ed..fad04b66d268f4188a5ff7af3fa28792a40cd5d2 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -27,6 +27,7 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 #include <linux/libps2.h>
+#include <linux/mutex.h>
 
 #define DRIVER_DESC	"AT and PS/2 keyboard driver"
 
@@ -216,7 +217,7 @@ struct atkbd {
 	unsigned long time;
 
 	struct work_struct event_work;
-	struct semaphore event_sem;
+	struct mutex event_mutex;
 	unsigned long event_mask;
 };
 
@@ -302,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 	if (atkbd->translated) {
 
 		if (atkbd->emul ||
-		    !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
-		      code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
-		     (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
-	             (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
+		    (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 &&
+		     code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA &&
+		     (code != ATKBD_RET_ERR || atkbd->err_xl) &&
+	             (code != ATKBD_RET_BAT || atkbd->bat_xl))) {
 			atkbd->release = code >> 7;
 			code &= 0x7f;
 		}
 
 		if (!atkbd->emul) {
 		     if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
-			atkbd->bat_xl = !atkbd->release;
+			atkbd->bat_xl = !(data >> 7);
 		     if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
-			atkbd->err_xl = !atkbd->release;
+			atkbd->err_xl = !(data >> 7);
 		}
 	}
 
@@ -449,7 +450,7 @@ static void atkbd_event_work(void *data)
 	unsigned char param[2];
 	int i, j;
 
-	down(&atkbd->event_sem);
+	mutex_lock(&atkbd->event_mutex);
 
 	if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
 		param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
@@ -480,7 +481,7 @@ static void atkbd_event_work(void *data)
 		ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
 	}
 
-	up(&atkbd->event_sem);
+	mutex_unlock(&atkbd->event_mutex);
 }
 
 /*
@@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 	atkbd->dev = dev;
 	ps2_init(&atkbd->ps2dev, serio);
 	INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
-	init_MUTEX(&atkbd->event_sem);
+	mutex_init(&atkbd->event_mutex);
 
 	switch (serio->id.type) {
 
@@ -862,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 	atkbd->softrepeat = atkbd_softrepeat;
 	atkbd->scroll = atkbd_scroll;
 
-	if (!atkbd->write)
-		atkbd->softrepeat = 1;
-
 	if (atkbd->softrepeat)
 		atkbd->softraw = 1;
 
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index e301ee4ca264e6a5b1315a81a88fdda6880da112..96c6bf77248ae7a67dc134ccfffb7f8465ffd974 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -29,11 +29,11 @@
 #define KB_COLS				12
 #define KB_ROWMASK(r)		(1 << (r))
 #define SCANCODE(r,c)		( ((r)<<4) + (c) + 1 )
-/* zero code, 124 scancodes + 3 hinge combinations */
-#define	NR_SCANCODES		( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
-#define SCAN_INTERVAL		(HZ/10)
+/* zero code, 124 scancodes */
+#define	NR_SCANCODES		( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 )
 
-#define HINGE_SCAN_INTERVAL		(HZ/4)
+#define SCAN_INTERVAL		(50) /* ms */
+#define HINGE_SCAN_INTERVAL	(250) /* ms */
 
 #define CORGI_KEY_CALENDER	KEY_F1
 #define CORGI_KEY_ADDRESS	KEY_F2
@@ -49,9 +49,6 @@
 #define CORGI_KEY_MAIL		KEY_F10
 #define CORGI_KEY_OK		KEY_F11
 #define CORGI_KEY_MENU		KEY_F12
-#define CORGI_HINGE_0		KEY_KP0
-#define CORGI_HINGE_1		KEY_KP1
-#define CORGI_HINGE_2		KEY_KP2
 
 static unsigned char corgikbd_keycode[NR_SCANCODES] = {
 	0,                                                                                                                /* 0 */
@@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
 	CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0,            /* 81-96 */
 	KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0,  /* 97-112 */
 	CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0,   /* 113-124 */
-	CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2	  /* 125-127 */
 };
 
 
@@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
 
 	/* if any keys are pressed, enable the timer */
 	if (num_pressed)
-		mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
+		mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
 
 	spin_unlock_irqrestore(&corgikbd_data->lock, flags);
 }
@@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data)
  *          0x0c - Keyboard and Screen Closed
  */
 
+#define READ_GPIO_BIT(x)    (GPLR(x) & GPIO_bit(x))
 #define HINGE_STABLE_COUNT 2
 static int sharpsl_hinge_state;
 static int hinge_count;
@@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data)
 	unsigned long flags;
 
 	gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+	gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0);
 	if (gprr != sharpsl_hinge_state) {
 		hinge_count = 0;
 		sharpsl_hinge_state = gprr;
@@ -249,27 +247,38 @@ static void corgikbd_hinge_timer(unsigned long data)
 
 			input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
 			input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+			input_report_switch(corgikbd_data->input, SW_2, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
 			input_sync(corgikbd_data->input);
 
 			spin_unlock_irqrestore(&corgikbd_data->lock, flags);
 		}
 	}
-	mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
+	mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 }
 
 #ifdef CONFIG_PM
 static int corgikbd_suspend(struct platform_device *dev, pm_message_t state)
 {
+	int i;
 	struct corgikbd *corgikbd = platform_get_drvdata(dev);
+
 	corgikbd->suspended = 1;
+	/* strobe 0 is the power key so this can't be made an input for
+	   powersaving therefore i = 1 */
+	for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN);
 
 	return 0;
 }
 
 static int corgikbd_resume(struct platform_device *dev)
 {
+	int i;
 	struct corgikbd *corgikbd = platform_get_drvdata(dev);
 
+	for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
 	/* Upon resume, ignore the suspend key for a short while */
 	corgikbd->suspend_jiffies=jiffies;
 	corgikbd->suspended = 0;
@@ -333,10 +342,11 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 	clear_bit(0, input_dev->keybit);
 	set_bit(SW_0, input_dev->swbit);
 	set_bit(SW_1, input_dev->swbit);
+	set_bit(SW_2, input_dev->swbit);
 
 	input_register_device(corgikbd->input);
 
-	mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
+	mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
 	/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
 	for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
@@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 	for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
 		pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
 
+	/* Setup the headphone jack as an input */
+	pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
+
 	return 0;
 }
 
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 63f387e4b783d4d23d85b76554552b33975c8920..1dca3cf42a54c50209f80bb96e91bd4941244aa7 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -250,16 +250,19 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
 	struct hil_kbd	*kbd;
 	uint8_t		did, *idd;
 	int		i;
-	
+
 	kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
 	if (!kbd)
 		return -ENOMEM;
 
 	kbd->dev = input_allocate_device();
-	if (!kbd->dev) goto bail1;
+	if (!kbd->dev)
+		goto bail0;
+
 	kbd->dev->private = kbd;
 
-	if (serio_open(serio, drv)) goto bail0;
+	if (serio_open(serio, drv))
+		goto bail1;
 
 	serio_set_drvdata(serio, kbd);
 	kbd->serio = serio;
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 83999d5831225e20ffa0bc000c326673596089f2..bc61cf8cfc65391f718e0b28beceacb20ae473c1 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -30,6 +30,7 @@
 #define SCANCODE(r,c)		(((r)<<4) + (c) + 1)
 #define	NR_SCANCODES		((KB_ROWS<<4) + 1)
 
+#define SCAN_INTERVAL		(50) /* ms */
 #define HINGE_SCAN_INTERVAL	(150) /* ms */
 
 #define SPITZ_KEY_CALENDER	KEY_F1
@@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
 
 	/* if any keys are pressed, enable the timer */
 	if (num_pressed)
-		mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+		mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
 
 	spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
 }
@@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
 	unsigned long flags;
 
 	state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+	state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
 	if (state != sharpsl_hinge_state) {
 		hinge_count = 0;
 		sharpsl_hinge_state = state;
@@ -299,6 +301,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
 
 		input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
 		input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+		input_report_switch(spitzkbd_data->input, SW_2, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
 		input_sync(spitzkbd_data->input);
 
 		spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
@@ -397,6 +400,7 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 	clear_bit(0, input_dev->keybit);
 	set_bit(SW_0, input_dev->swbit);
 	set_bit(SW_1, input_dev->swbit);
+	set_bit(SW_2, input_dev->swbit);
 
 	input_register_device(input_dev);
 
@@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 	request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
 		    SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
 		    "Spitzkbd SWB", spitzkbd);
+ 	request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+		    SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+		    "Spitzkbd HP", spitzkbd);
 
 	printk(KERN_INFO "input: Spitz Keyboard Registered\n");
 
@@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev)
 	free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
 	free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
 	free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+	free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
 
 	del_timer_sync(&spitzkbd->htimer);
 	del_timer_sync(&spitzkbd->timer);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 1ef477f4469c1a1e359bd4cbacc7917680c95524..afd322185bbff65e20e055f7310bc64228d7f61f 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-static struct platform_device *pcspkr_platform_device;
 static DEFINE_SPINLOCK(i8253_beep_lock);
 
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = {
 
 static int __init pcspkr_init(void)
 {
-	int err;
-
-	err = platform_driver_register(&pcspkr_platform_driver);
-	if (err)
-		return err;
-
-	pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
-	if (!pcspkr_platform_device) {
-		err = -ENOMEM;
-		goto err_unregister_driver;
-	}
-
-	err = platform_device_add(pcspkr_platform_device);
-	if (err)
-		goto err_free_device;
-
-	return 0;
-
- err_free_device:
-	platform_device_put(pcspkr_platform_device);
- err_unregister_driver:
-	platform_driver_unregister(&pcspkr_platform_driver);
-
-	return err;
+	return platform_driver_register(&pcspkr_platform_driver);
 }
 
 static void __exit pcspkr_exit(void)
 {
-	platform_device_unregister(pcspkr_platform_device);
 	platform_driver_unregister(&pcspkr_platform_driver);
 }
 
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 546ed9b4901df211ae125e5395fc5e0675fc7458..d723e9ad7c41a103ce092db1b45068b98b8acd9b 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file)
 	if (!newdev)
 		return -ENOMEM;
 
-	init_MUTEX(&newdev->sem);
+	mutex_init(&newdev->mutex);
 	spin_lock_init(&newdev->requests_lock);
 	init_waitqueue_head(&newdev->requests_waitq);
 	init_waitqueue_head(&newdev->waitq);
@@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
 	struct uinput_device *udev = file->private_data;
 	int retval;
 
-	retval = down_interruptible(&udev->sem);
+	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
 		return retval;
 
@@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
 			uinput_inject_event(udev, buffer, count) :
 			uinput_setup_device(udev, buffer, count);
 
-	up(&udev->sem);
+	mutex_unlock(&udev->mutex);
 
 	return retval;
 }
@@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
 	if (retval)
 		return retval;
 
-	retval = down_interruptible(&udev->sem);
+	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
 		return retval;
 
@@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
 	}
 
  out:
-	up(&udev->sem);
+	mutex_unlock(&udev->mutex);
 
 	return retval;
 }
@@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	udev = file->private_data;
 
-	retval = down_interruptible(&udev->sem);
+	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
 		return retval;
 
@@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	}
 
  out:
-	up(&udev->sem);
+	mutex_unlock(&udev->mutex);
 	return retval;
 }
 
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bfb564fd8fe2ed0a4db4d42c60b57ccd21c68705..69f02178c528c87178a3ae188181ea3c2ae581d9 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -249,10 +249,13 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 		return -ENOMEM;
 
 	ptr->dev = input_allocate_device();
-	if (!ptr->dev) goto bail0;
+	if (!ptr->dev)
+		goto bail0;
+
 	ptr->dev->private = ptr;
 
-	if (serio_open(serio, driver)) goto bail1;
+	if (serio_open(serio, driver))
+		goto bail1;
 
 	serio_set_drvdata(serio, ptr);
 	ptr->serio = serio;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index ad62174676761e095ba26e232db99e6df843e52d..32d70ed8f41dd7087f4fcc32f6522aec29ac3c3d 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -20,6 +20,8 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 #include <linux/libps2.h>
+#include <linux/mutex.h>
+
 #include "psmouse.h"
 #include "synaptics.h"
 #include "logips2pp.h"
@@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter=");
 __obsolete_setup("psmouse_rate=");
 
 /*
- * psmouse_sem protects all operations changing state of mouse
+ * psmouse_mutex protects all operations changing state of mouse
  * (connecting, disconnecting, changing rate or resolution via
  * sysfs). We could use a per-device semaphore but since there
  * rarely more than one PS/2 mouse connected and since semaphore
  * is taken in "slow" paths it is not worth it.
  */
-static DECLARE_MUTEX(psmouse_sem);
+static DEFINE_MUTEX(psmouse_mutex);
 
 static struct workqueue_struct *kpsmoused_wq;
 
@@ -868,7 +870,7 @@ static void psmouse_resync(void *p)
 	int failed = 0, enabled = 0;
 	int i;
 
-	down(&psmouse_sem);
+	mutex_lock(&psmouse_mutex);
 
 	if (psmouse->state != PSMOUSE_RESYNCING)
 		goto out;
@@ -948,7 +950,7 @@ static void psmouse_resync(void *p)
 	if (parent)
 		psmouse_activate(parent);
  out:
-	up(&psmouse_sem);
+	mutex_unlock(&psmouse_mutex);
 }
 
 /*
@@ -974,14 +976,14 @@ static void psmouse_disconnect(struct serio *serio)
 
 	sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
 
-	down(&psmouse_sem);
+	mutex_lock(&psmouse_mutex);
 
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
 	/* make sure we don't have a resync in progress */
-	up(&psmouse_sem);
+	mutex_unlock(&psmouse_mutex);
 	flush_workqueue(kpsmoused_wq);
-	down(&psmouse_sem);
+	mutex_lock(&psmouse_mutex);
 
 	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
 		parent = serio_get_drvdata(serio->parent);
@@ -1004,7 +1006,7 @@ static void psmouse_disconnect(struct serio *serio)
 	if (parent)
 		psmouse_activate(parent);
 
-	up(&psmouse_sem);
+	mutex_unlock(&psmouse_mutex);
 }
 
 static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
@@ -1076,7 +1078,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int retval = -ENOMEM;
 
-	down(&psmouse_sem);
+	mutex_lock(&psmouse_mutex);
 
 	/*
 	 * If this is a pass-through port deactivate parent so the device
@@ -1144,7 +1146,7 @@ out:
 	if (parent)
 		psmouse_activate(parent);
 
-	up(&psmouse_sem);
+	mutex_unlock(&psmouse_mutex);
 	return retval;
 }
 
@@ -1161,7 +1163,7 @@ static int psmouse_reconnect(struct serio *serio)
 		return -1;
 	}
 
-	down(&psmouse_sem);
+	mutex_lock(&psmouse_mutex);
 
 	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
 		parent = serio_get_drvdata(serio->parent);
@@ -1195,7 +1197,7 @@ out:
 	if (parent)
 		psmouse_activate(parent);
 
-	up(&psmouse_sem);
+	mutex_unlock(&psmouse_mutex);
 	return rc;
 }
 
@@ -1273,7 +1275,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 		goto out_unpin;
 	}
 
-	retval = down_interruptible(&psmouse_sem);
+	retval = mutex_lock_interruptible(&psmouse_mutex);
 	if (retval)
 		goto out_unpin;
 
@@ -1281,7 +1283,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 
 	if (psmouse->state == PSMOUSE_IGNORE) {
 		retval = -ENODEV;
-		goto out_up;
+		goto out_unlock;
 	}
 
 	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1299,8 +1301,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 	if (parent)
 		psmouse_activate(parent);
 
- out_up:
-	up(&psmouse_sem);
+ out_unlock:
+	mutex_unlock(&psmouse_mutex);
  out_unpin:
 	serio_unpin_driver(serio);
 	return retval;
@@ -1357,11 +1359,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
 			return -EIO;
 		}
 
-		up(&psmouse_sem);
+		mutex_unlock(&psmouse_mutex);
 		serio_unpin_driver(serio);
 		serio_unregister_child_port(serio);
 		serio_pin_driver_uninterruptible(serio);
-		down(&psmouse_sem);
+		mutex_lock(&psmouse_mutex);
 
 		if (serio->drv != &psmouse_drv) {
 			input_free_device(new_dev);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 2051bec2c394b896700612590749ac7b31da9de2..ad5d0a85e960157b335915e693a87872e4a9bf96 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse)
 {
 	struct serio *serio;
 
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!serio) {
 		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
 		return;
 	}
 
-	memset(serio, 0, sizeof(struct serio));
-
 	serio->id.type = SERIO_PS_PSTHRU;
 	strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
 	strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
@@ -605,14 +603,21 @@ static struct dmi_system_id toshiba_dmi_table[] = {
 		.ident = "Toshiba Satellite",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
 		},
 	},
 	{
 		.ident = "Toshiba Dynabook",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME , "dynabook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
+		},
+	},
+	{
+		.ident = "Toshiba Portege M300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
 		},
 	},
 	{ }
@@ -623,10 +628,9 @@ int synaptics_init(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv;
 
-	psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
+	psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 	if (!priv)
 		return -1;
-	memset(priv, 0, sizeof(struct synaptics_data));
 
 	if (synaptics_query_hardware(psmouse)) {
 		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 9abed18d2ecf79493b3d4be737b0db25ee60dd22..b685a507955d2c81aa5d6ad239d92d6a04c228a0 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
 	if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
 		return -ENODEV;
 
-	if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+	if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(list, 0, sizeof(struct mousedev_list));
 
 	spin_lock_init(&list->packet_lock);
 	list->pos_x = xres / 2;
@@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
 		return NULL;
 	}
 
-	if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
+	if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
 		return NULL;
-	memset(mousedev, 0, sizeof(struct mousedev));
 
 	INIT_LIST_HEAD(&mousedev->list);
 	init_waitqueue_head(&mousedev->wait);
diff --git a/drivers/input/power.c b/drivers/input/power.c
index bfc5c63ebffe2a018ffeae99ebe23fc2669983bf..526e6070600c8a02a29df0283d55fcae79217b0f 100644
--- a/drivers/input/power.c
+++ b/drivers/input/power.c
@@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler,
 {
 	struct input_handle *handle;
 
-	if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
 		return NULL;
-	memset(handle, 0, sizeof(struct input_handle));
 
 	handle->dev = dev;
 	handle->handler = handler;
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index ea499783fb12f76ccc8d5723a2ffdef4a2487b5e..bbbe15e219044fb6f9aadbcc60795f90ddc74d17 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) {
 	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
 		struct serio *mlc_serio;
 		hil_mlc_copy_di_scratch(mlc, i);
-		mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+		mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
 		mlc->serio[i] = mlc_serio;
-		memset(mlc_serio, 0, sizeof(*mlc_serio));
 		mlc_serio->id			= hil_mlc_serio_id;
 		mlc_serio->write		= hil_mlc_serio_write;
 		mlc_serio->open			= hil_mlc_serio_open;
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index a4c6f352272390af0d2d8b740d53a1bb8cd2668d..f606e96bc2f4b5e4f5e04f22f0440c94c3453607 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
 #include <linux/pnp.h>
 
 static int i8042_pnp_kbd_registered;
+static unsigned int i8042_pnp_kbd_devices;
 static int i8042_pnp_aux_registered;
+static unsigned int i8042_pnp_aux_devices;
 
 static int i8042_pnp_command_reg;
 static int i8042_pnp_data_reg;
@@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
 		strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
 	}
 
+	i8042_pnp_kbd_devices++;
 	return 0;
 }
 
@@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
 		strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
 	}
 
+	i8042_pnp_aux_devices++;
 	return 0;
 }
 
@@ -287,21 +291,23 @@ static void i8042_pnp_exit(void)
 
 static int __init i8042_pnp_init(void)
 {
-	int result_kbd = 0, result_aux = 0;
 	char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
+	int err;
 
 	if (i8042_nopnp) {
 		printk(KERN_INFO "i8042: PNP detection disabled\n");
 		return 0;
 	}
 
-	if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+	err = pnp_register_driver(&i8042_pnp_kbd_driver);
+	if (!err)
 		i8042_pnp_kbd_registered = 1;
 
-	if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+	err = pnp_register_driver(&i8042_pnp_aux_driver);
+	if (!err)
 		i8042_pnp_aux_registered = 1;
 
-	if (result_kbd <= 0 && result_aux <= 0) {
+	if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) {
 		i8042_pnp_exit();
 #if defined(__ia64__)
 		return -ENODEV;
@@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void)
 #endif
 	}
 
-	if (result_kbd > 0)
+	if (i8042_pnp_kbd_devices)
 		snprintf(kbd_irq_str, sizeof(kbd_irq_str),
 			"%d", i8042_pnp_kbd_irq);
-	if (result_aux > 0)
+	if (i8042_pnp_aux_devices)
 		snprintf(aux_irq_str, sizeof(aux_irq_str),
 			"%d", i8042_pnp_aux_irq);
 
 	printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
-		i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
+		i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
 		i8042_pnp_aux_name,
 		i8042_pnp_data_reg, i8042_pnp_command_reg,
-		kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+		kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
 		aux_irq_str);
 
 #if defined(__ia64__)
-	if (result_kbd <= 0)
+	if (!i8042_pnp_kbd_devices)
 		i8042_nokbd = 1;
-	if (result_aux <= 0)
+	if (!i8042_pnp_aux_devices)
 		i8042_noaux = 1;
 #endif
 
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index d4c990f7c85e9a1f64c2f03340ad01e625eaf29c..79c97f94bcbd5e9bcc31168020c3b7f1f0c32106 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
 		maxbytes = sizeof(ps2dev->cmdbuf);
 	}
 
-	down(&ps2dev->cmd_sem);
+	mutex_lock(&ps2dev->cmd_mutex);
 
 	serio_pause_rx(ps2dev->serio);
 	ps2dev->flags = PS2_FLAG_CMD;
@@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
 	wait_event_timeout(ps2dev->wait,
 			   !(ps2dev->flags & PS2_FLAG_CMD),
 			   msecs_to_jiffies(timeout));
-	up(&ps2dev->cmd_sem);
+	mutex_unlock(&ps2dev->cmd_mutex);
 }
 
 /*
@@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
 		return -1;
 	}
 
-	down(&ps2dev->cmd_sem);
+	mutex_lock(&ps2dev->cmd_mutex);
 
 	serio_pause_rx(ps2dev->serio);
 	ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
@@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
 	ps2dev->flags = 0;
 	serio_continue_rx(ps2dev->serio);
 
-	up(&ps2dev->cmd_sem);
+	mutex_unlock(&ps2dev->cmd_mutex);
 	return rc;
 }
 
@@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
 
 void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
 {
-	init_MUTEX(&ps2dev->cmd_sem);
+	mutex_init(&ps2dev->cmd_mutex);
 	init_waitqueue_head(&ps2dev->wait);
 	ps2dev->serio = serio;
 }
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 1d15c2819818dcd03d0d22056a12944f4bf5a8b1..a5c1fb3a4a51961749f5a0f9aa8998e729dc0864 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void)
 {
 	struct serio *serio;
 
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
-		memset(serio, 0, sizeof(struct serio));
 		serio->id.type = parkbd_mode;
 		serio->write = parkbd_write,
 		strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index a3bd11589bc3a0371f421b621432a277c78fd43a..513d37fc1acfc2380a1b6732ec780c4987c1eab6 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
 {
 	struct serio *serio;
 
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!serio)
 		return -ENOMEM;
 
-	memset(serio, 0, sizeof(struct serio));
 	serio->id.type		= SERIO_8042;
 	serio->write		= rpckbd_write;
 	serio->open		= rpckbd_open;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 2f76813c3a645c7d3d6a9e797df4525f19c6ac3d..6521034bc93328289819d92894fd2388401cecbb 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
 /*
- * serio_sem protects entire serio subsystem and is taken every time
+ * serio_mutex protects entire serio subsystem and is taken every time
  * serio port or driver registrered or unregistered.
  */
-static DECLARE_MUTEX(serio_sem);
+static DEFINE_MUTEX(serio_mutex);
 
 static LIST_HEAD(serio_list);
 
@@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
 {
 	int retval;
 
-	down(&serio->drv_sem);
+	mutex_lock(&serio->drv_mutex);
 	retval = drv->connect(serio, drv);
-	up(&serio->drv_sem);
+	mutex_unlock(&serio->drv_mutex);
 
 	return retval;
 }
@@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio)
 {
 	int retval = -1;
 
-	down(&serio->drv_sem);
+	mutex_lock(&serio->drv_mutex);
 	if (serio->drv && serio->drv->reconnect)
 		retval = serio->drv->reconnect(serio);
-	up(&serio->drv_sem);
+	mutex_unlock(&serio->drv_mutex);
 
 	return retval;
 }
 
 static void serio_disconnect_driver(struct serio *serio)
 {
-	down(&serio->drv_sem);
+	mutex_lock(&serio->drv_mutex);
 	if (serio->drv)
 		serio->drv->disconnect(serio);
-	up(&serio->drv_sem);
+	mutex_unlock(&serio->drv_mutex);
 }
 
 static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
@@ -195,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner,
 	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
 		if (!try_module_get(owner)) {
 			printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
+			kfree(event);
 			goto out;
 		}
 
@@ -272,7 +274,7 @@ static void serio_handle_event(void)
 	struct serio_event *event;
 	struct serio_driver *serio_drv;
 
-	down(&serio_sem);
+	mutex_lock(&serio_mutex);
 
 	/*
 	 * Note that we handle only one event here to give swsusp
@@ -314,7 +316,7 @@ static void serio_handle_event(void)
 		serio_free_event(event);
 	}
 
-	up(&serio_sem);
+	mutex_unlock(&serio_mutex);
 }
 
 /*
@@ -449,7 +451,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
 	struct device_driver *drv;
 	int retval;
 
-	retval = down_interruptible(&serio_sem);
+	retval = mutex_lock_interruptible(&serio_mutex);
 	if (retval)
 		return retval;
 
@@ -469,7 +471,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
 		retval = -EINVAL;
 	}
 
-	up(&serio_sem);
+	mutex_unlock(&serio_mutex);
 
 	return retval;
 }
@@ -524,7 +526,7 @@ static void serio_init_port(struct serio *serio)
 	__module_get(THIS_MODULE);
 
 	spin_lock_init(&serio->lock);
-	init_MUTEX(&serio->drv_sem);
+	mutex_init(&serio->drv_mutex);
 	device_initialize(&serio->dev);
 	snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
 		 "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
@@ -661,10 +663,10 @@ void __serio_register_port(struct serio *serio, struct module *owner)
  */
 void serio_unregister_port(struct serio *serio)
 {
-	down(&serio_sem);
+	mutex_lock(&serio_mutex);
 	serio_disconnect_port(serio);
 	serio_destroy_port(serio);
-	up(&serio_sem);
+	mutex_unlock(&serio_mutex);
 }
 
 /*
@@ -672,17 +674,17 @@ void serio_unregister_port(struct serio *serio)
  */
 void serio_unregister_child_port(struct serio *serio)
 {
-	down(&serio_sem);
+	mutex_lock(&serio_mutex);
 	if (serio->child) {
 		serio_disconnect_port(serio->child);
 		serio_destroy_port(serio->child);
 	}
-	up(&serio_sem);
+	mutex_unlock(&serio_mutex);
 }
 
 /*
  * Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_sem is
+ * Can be used when it is not obvious whether the serio_mutex is
  * taken or not and when delayed execution is feasible.
  */
 void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
@@ -765,7 +767,7 @@ void serio_unregister_driver(struct serio_driver *drv)
 {
 	struct serio *serio;
 
-	down(&serio_sem);
+	mutex_lock(&serio_mutex);
 	drv->manual_bind = 1;	/* so serio_find_driver ignores it */
 
 start_over:
@@ -779,7 +781,7 @@ start_over:
 	}
 
 	driver_unregister(&drv->driver);
-	up(&serio_sem);
+	mutex_unlock(&serio_mutex);
 }
 
 static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
@@ -858,7 +860,7 @@ static int serio_resume(struct device *dev)
 	return 0;
 }
 
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
 int serio_open(struct serio *serio, struct serio_driver *drv)
 {
 	serio_set_drv(serio, drv);
@@ -870,7 +872,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
 	return 0;
 }
 
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
 void serio_close(struct serio *serio)
 {
 	if (serio->close)
@@ -923,5 +925,5 @@ static void __exit serio_exit(void)
 	kthread_stop(serio_task);
 }
 
-module_init(serio_init);
+subsys_initcall(serio_init);
 module_exit(serio_exit);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 47e08de18d07adab295db158fa237b2cc5f83383..5a2703b536dc0948bcb8c1b530c6cbff80eb4482 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -19,6 +19,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/miscdevice.h>
 #include <linux/wait.h>
+#include <linux/mutex.h>
 
 #define DRIVER_DESC	"Raw serio driver"
 
@@ -46,7 +47,7 @@ struct serio_raw_list {
 	struct list_head node;
 };
 
-static DECLARE_MUTEX(serio_raw_sem);
+static DEFINE_MUTEX(serio_raw_mutex);
 static LIST_HEAD(serio_raw_list);
 static unsigned int serio_raw_no;
 
@@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
 	struct serio_raw_list *list;
 	int retval = 0;
 
-	retval = down_interruptible(&serio_raw_sem);
+	retval = mutex_lock_interruptible(&serio_raw_mutex);
 	if (retval)
 		return retval;
 
@@ -95,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file)
 		goto out;
 	}
 
-	if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
+	if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
 		retval = -ENOMEM;
 		goto out;
 	}
 
-	memset(list, 0, sizeof(struct serio_raw_list));
 	list->serio_raw = serio_raw;
 	file->private_data = list;
 
@@ -108,7 +108,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
 	list_add_tail(&list->node, &serio_raw->list);
 
 out:
-	up(&serio_raw_sem);
+	mutex_unlock(&serio_raw_mutex);
 	return retval;
 }
 
@@ -130,12 +130,12 @@ static int serio_raw_release(struct inode *inode, struct file *file)
 	struct serio_raw_list *list = file->private_data;
 	struct serio_raw *serio_raw = list->serio_raw;
 
-	down(&serio_raw_sem);
+	mutex_lock(&serio_raw_mutex);
 
 	serio_raw_fasync(-1, file, 0);
 	serio_raw_cleanup(serio_raw);
 
-	up(&serio_raw_sem);
+	mutex_unlock(&serio_raw_mutex);
 	return 0;
 }
 
@@ -194,7 +194,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
 	int retval;
 	unsigned char c;
 
-	retval = down_interruptible(&serio_raw_sem);
+	retval = mutex_lock_interruptible(&serio_raw_mutex);
 	if (retval)
 		return retval;
 
@@ -219,7 +219,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
 	};
 
 out:
-	up(&serio_raw_sem);
+	mutex_unlock(&serio_raw_mutex);
 	return written;
 }
 
@@ -275,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
 	struct serio_raw *serio_raw;
 	int err;
 
-	if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
+	if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
 		printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
 		return -ENOMEM;
 	}
 
-	down(&serio_raw_sem);
+	mutex_lock(&serio_raw_mutex);
 
-	memset(serio_raw, 0, sizeof(struct serio_raw));
 	snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
 	serio_raw->refcnt = 1;
 	serio_raw->serio = serio;
@@ -325,7 +324,7 @@ out_free:
 	serio_set_drvdata(serio, NULL);
 	kfree(serio_raw);
 out:
-	up(&serio_raw_sem);
+	mutex_unlock(&serio_raw_mutex);
 	return err;
 }
 
@@ -350,7 +349,7 @@ static void serio_raw_disconnect(struct serio *serio)
 {
 	struct serio_raw *serio_raw;
 
-	down(&serio_raw_sem);
+	mutex_lock(&serio_raw_mutex);
 
 	serio_raw = serio_get_drvdata(serio);
 
@@ -361,7 +360,7 @@ static void serio_raw_disconnect(struct serio *serio)
 	if (!serio_raw_cleanup(serio_raw))
 		wake_up_interruptible(&serio_raw->wait);
 
-	up(&serio_raw_sem);
+	mutex_unlock(&serio_raw_mutex);
 }
 
 static struct serio_device_id serio_raw_serio_ids[] = {
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index ca1547929d62e0aabf55bb60c813e9a11ce3189c..d678d144bbf8652b629d23417eda0a58f94518bf 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file)
 	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
 		return -ENODEV;
 
-	if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+	if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(list, 0, sizeof(struct tsdev_list));
 
 	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
 
@@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
 		return NULL;
 	}
 
-	if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL)))
+	if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
 		return NULL;
-	memset(tsdev, 0, sizeof(struct tsdev));
 
 	INIT_LIST_HEAD(&tsdev->list);
 	init_waitqueue_head(&tsdev->wait);
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index cb0d80f492520eeb42e5592cccd203ac81032a6a..25bc85f8ce39ba7368fe90a8fa1c1359df19aaba 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 				case 0x025: map_key_clear(KEY_TV);		break;
 				case 0x026: map_key_clear(KEY_MENU);		break;
 				case 0x031: map_key_clear(KEY_AUDIO);		break;
-				case 0x032: map_key_clear(KEY_SUBTITLE);	break;
+				case 0x032: map_key_clear(KEY_TEXT);		break;
 				case 0x033: map_key_clear(KEY_LAST);		break;
 				case 0x047: map_key_clear(KEY_MP3);		break;
 				case 0x048: map_key_clear(KEY_DVD);		break;
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 9c8e6da2393bbd29f48dc2a13c2cbb2238dc9ee5..71e7b2847cb30e3842b8a3ce9eb61bbf6b53e8d6 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/timer.h>
 
@@ -40,7 +41,7 @@ struct gameport {
 	struct gameport *parent, *child;
 
 	struct gameport_driver *drv;
-	struct semaphore drv_sem;	/* protects serio->drv so attributes can pin driver */
+	struct mutex drv_mutex;		/* protects serio->drv so attributes can pin driver */
 
 	struct device dev;
 	unsigned int registered;	/* port has been fully registered with driver core */
@@ -137,12 +138,12 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
  */
 static inline int gameport_pin_driver(struct gameport *gameport)
 {
-	return down_interruptible(&gameport->drv_sem);
+	return mutex_lock_interruptible(&gameport->drv_mutex);
 }
 
 static inline void gameport_unpin_driver(struct gameport *gameport)
 {
-	up(&gameport->drv_sem);
+	mutex_unlock(&gameport->drv_mutex);
 }
 
 void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
diff --git a/include/linux/input.h b/include/linux/input.h
index 1d4e341b72e62c23bcd0847bdaa44b5f2971ff9a..b0e612dda0cf2887e364f95010f136d87be2fdcd 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -421,7 +421,7 @@ struct input_absinfo {
 #define BTN_GEAR_UP		0x151
 
 #define KEY_OK			0x160
-#define KEY_SELECT 		0x161
+#define KEY_SELECT		0x161
 #define KEY_GOTO		0x162
 #define KEY_CLEAR		0x163
 #define KEY_POWER2		0x164
@@ -512,6 +512,15 @@ struct input_absinfo {
 #define KEY_FN_S		0x1e3
 #define KEY_FN_B		0x1e4
 
+#define KEY_BRL_DOT1		0x1f1
+#define KEY_BRL_DOT2		0x1f2
+#define KEY_BRL_DOT3		0x1f3
+#define KEY_BRL_DOT4		0x1f4
+#define KEY_BRL_DOT5		0x1f5
+#define KEY_BRL_DOT6		0x1f6
+#define KEY_BRL_DOT7		0x1f7
+#define KEY_BRL_DOT8		0x1f8
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x1ff
@@ -929,7 +938,7 @@ struct input_dev {
 
 	struct input_handle *grab;
 
-	struct semaphore sem;	/* serializes open and close operations */
+	struct mutex mutex;	/* serializes open and close operations */
 	unsigned int users;
 
 	struct class_device cdev;
@@ -995,11 +1004,6 @@ static inline void init_input_dev(struct input_dev *dev)
 
 struct input_dev *input_allocate_device(void);
 
-static inline void input_free_device(struct input_dev *dev)
-{
-	kfree(dev);
-}
-
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
 	return to_input_dev(class_device_get(&dev->cdev));
@@ -1010,6 +1014,11 @@ static inline void input_put_device(struct input_dev *dev)
 	class_device_put(&dev->cdev);
 }
 
+static inline void input_free_device(struct input_dev *dev)
+{
+	input_put_device(dev);
+}
+
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index e87c32a5c86a022dde6ccdfdf03a794ebc327627..4eb851ece080d0682f4ada0b9fe24aad22c3cd19 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
 
 #define U(x) ((x) ^ 0xf000)
 
+#define BRL_UC_ROW 0x2800
+
 /* keyboard.c */
 
 struct console;
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 08488042d74a7979e55c6ba9dedf9f2e75913e78..de76843bbe8a8839a18d4687f60d9187e5aff238 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS];
 #define KT_ASCII	9
 #define KT_LOCK		10
 #define KT_SLOCK	12
+#define KT_BRL		14
 
 #define K(t,v)		(((t)<<8)|(v))
 #define KTYP(x)		((x) >> 8)
@@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS];
 
 #define NR_LOCK		8
 
+#define K_BRL_BLANK     K(KT_BRL, 0)
+#define K_BRL_DOT1      K(KT_BRL, 1)
+#define K_BRL_DOT2      K(KT_BRL, 2)
+#define K_BRL_DOT3      K(KT_BRL, 3)
+#define K_BRL_DOT4      K(KT_BRL, 4)
+#define K_BRL_DOT5      K(KT_BRL, 5)
+#define K_BRL_DOT6      K(KT_BRL, 6)
+#define K_BRL_DOT7      K(KT_BRL, 7)
+#define K_BRL_DOT8      K(KT_BRL, 8)
+
+#define NR_BRL		9
+
 #define MAX_DIACR	256
 #endif
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index a710bddda4ebaade343bd925bf7f9c7fb9fc20a5..08a450a9dbf7dc77bd6788824e82a38f8d09e6e2 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -28,7 +28,7 @@ struct ps2dev {
 	struct serio *serio;
 
 	/* Ensures that only one command is executing at a time */
-	struct semaphore cmd_sem;
+	struct mutex cmd_mutex;
 
 	/* Used to signal completion from interrupt handler */
 	wait_queue_head_t wait;
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 690aabca8ed07ea0d1bcd3781703f66655007a91..6348e8330897c3393a88e937ef7ae167c767faca 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
@@ -42,7 +43,7 @@ struct serio {
 	struct serio *parent, *child;
 
 	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock and serio->sem */
-	struct semaphore drv_sem;	/* protects serio->drv so attributes can pin driver */
+	struct mutex drv_mutex;		/* protects serio->drv so attributes can pin driver */
 
 	struct device dev;
 	unsigned int registered;	/* port has been fully registered with driver core */
@@ -151,17 +152,17 @@ static inline void serio_continue_rx(struct serio *serio)
  */
 static inline int serio_pin_driver(struct serio *serio)
 {
-	return down_interruptible(&serio->drv_sem);
+	return mutex_lock_interruptible(&serio->drv_mutex);
 }
 
 static inline void serio_pin_driver_uninterruptible(struct serio *serio)
 {
-	down(&serio->drv_sem);
+	mutex_lock(&serio->drv_mutex);
 }
 
 static inline void serio_unpin_driver(struct serio *serio)
 {
-	up(&serio->drv_sem);
+	mutex_unlock(&serio->drv_mutex);
 }
 
 
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 0ff7ca68e5c53412e22c063eda26edc84381718b..7168302f98441ea9da3c42c931ea40a23bfec5b1 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
- * 
+ *
  * Changes/Revisions:
  *	0.2	16/10/2004 (Micah Dowty <micah@navi.cx>)
  *		- added force feedback support
@@ -51,7 +51,7 @@ struct uinput_request {
 
 struct uinput_device {
 	struct input_dev	*dev;
-	struct semaphore	sem;
+	struct mutex		mutex;
 	enum uinput_state	state;
 	wait_queue_head_t	waitq;
 	unsigned char		ready;