Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6

Conflicts:

	drivers/usb/input/Makefile
	drivers/usb/input/gtco.c
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt
index 180e0689..d9d5230 100644
--- a/Documentation/input/input-programming.txt
+++ b/Documentation/input/input-programming.txt
@@ -1,5 +1,3 @@
-$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
-
 Programming input drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -20,28 +18,51 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
+static struct input_dev *button_dev;
+
 static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
-	input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
-	input_sync(&button_dev);
+	input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
+	input_sync(button_dev);
 }
 
 static int __init button_init(void)
 {
+	int error;
+
 	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                 return -EBUSY;
         }
-	
-	button_dev.evbit[0] = BIT(EV_KEY);
-	button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
-	
-	input_register_device(&button_dev);
+
+	button_dev = input_allocate_device();
+	if (!button_dev) {
+		printk(KERN_ERR "button.c: Not enough memory\n");
+		error = -ENOMEM;
+		goto err_free_irq;
+	}
+
+	button_dev->evbit[0] = BIT(EV_KEY);
+	button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+	error = input_register_device(button_dev);
+	if (error) {
+		printk(KERN_ERR "button.c: Failed to register device\n");
+		goto err_free_dev;
+	}
+
+	return 0;
+
+ err_free_dev:
+	input_free_device(button_dev);
+ err_free_irq:
+	free_irq(BUTTON_IRQ, button_interrupt);
+	return error;
 }
 
 static void __exit button_exit(void)
 {
-        input_unregister_device(&button_dev);
+        input_unregister_device(button_dev);
 	free_irq(BUTTON_IRQ, button_interrupt);
 }
 
@@ -58,17 +79,18 @@
 booting the kernel, it grabs the required resources (it should also check
 for the presence of the device).
 
-Then it sets the input bitfields. This way the device driver tells the other
+Then it allocates a new input device structure with input_aloocate_device()
+and sets up input bitfields. This way the device driver tells the other
 parts of the input systems what it is - what events can be generated or
-accepted by this input device. Our example device can only generate EV_KEY type
-events, and from those only BTN_0 event code. Thus we only set these two
-bits. We could have used
+accepted by this input device. Our example device can only generate EV_KEY
+type events, and from those only BTN_0 event code. Thus we only set these
+two bits. We could have used
 
 	set_bit(EV_KEY, button_dev.evbit);
 	set_bit(BTN_0, button_dev.keybit);
 
 as well, but with more than single bits the first approach tends to be
-shorter. 
+shorter.
 
 Then the example driver registers the input device structure by calling
 
@@ -76,16 +98,15 @@
 
 This adds the button_dev structure to linked lists of the input driver and
 calls device handler modules _connect functions to tell them a new input
-device has appeared. Because the _connect functions may call kmalloc(,
-GFP_KERNEL), which can sleep, input_register_device() must not be called
-from an interrupt or with a spinlock held.
+device has appeared. input_register_device() may sleep and therefore must
+not be called from an interrupt or with a spinlock held.
 
 While in use, the only used function of the driver is
 
 	button_interrupt()
 
 which upon every interrupt from the button checks its state and reports it
-via the 
+via the
 
 	input_report_key()
 
@@ -113,16 +134,10 @@
 release the interrupt and when it must resume polling or grab the interrupt
 again. To do that, we would add this to our example driver:
 
-int button_used = 0;
-
 static int button_open(struct input_dev *dev)
 {
-        if (button_used++)
-                return 0;
-
 	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
-                button_used--;
                 return -EBUSY;
         }
 
@@ -131,20 +146,21 @@
 
 static void button_close(struct input_dev *dev)
 {
-        if (!--button_used)
-                free_irq(IRQ_AMIGA_VERTB, button_interrupt);
+        free_irq(IRQ_AMIGA_VERTB, button_interrupt);
 }
 
 static int __init button_init(void)
 {
 	...
-	button_dev.open = button_open;
-	button_dev.close = button_close;
+	button_dev->open = button_open;
+	button_dev->close = button_close;
 	...
 }
 
-Note the button_used variable - we have to track how many times the open
-function was called to know when exactly our device stops being used.
+Note that input core keeps track of number of users for the device and
+makes sure that dev->open() is called only when the first user connects
+to the device and that dev->close() is called when the very last user
+disconnects. Calls to both callbacks are serialized.
 
 The open() callback should return a 0 in case of success or any nonzero value
 in case of failure. The close() callback (which is void) must always succeed.
@@ -175,7 +191,7 @@
 
 	input_report_rel(struct input_dev *dev, int code, int value)
 
-function. Events are generated only for nonzero value. 
+function. Events are generated only for nonzero value.
 
 However EV_ABS requires a little special care. Before calling
 input_register_device, you have to fill additional fields in the input_dev
@@ -187,6 +203,10 @@
 	button_dev.absfuzz[ABS_X] = 4;
 	button_dev.absflat[ABS_X] = 8;
 
+Or, you can just say:
+
+	input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
+
 This setting would be appropriate for a joystick X axis, with the minimum of
 0, maximum of 255 (which the joystick *must* be able to reach, no problem if
 it sometimes reports more, but it must be able to always reach the min and
@@ -197,14 +217,7 @@
 that the thing is precise and always returns to exactly the center position
 (if it has any).
 
-1.4 The void *private field
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This field in the input structure can be used to point to any private data
-structures in the input device driver, in case the driver handles more than
-one device. You'll need it in the open and close callbacks.
-
-1.5 NBITS(), LONG(), BIT()
+1.4 NBITS(), LONG(), BIT()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 These three macros from input.h help some bitfield computations:
@@ -213,13 +226,9 @@
 	LONG(x)  - returns the index in the array in longs for bit x
 	BIT(x)   - returns the index in a long for bit x
 
-1.6 The number, id* and name fields
+1.5 The id* and name fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The dev->number is assigned by the input system to the input device when it
-is registered. It has no use except for identifying the device to the user
-in system messages.
-
 The dev->name should be set before registering the input device by the input
 device driver. It's a string like 'Generic button device' containing a
 user friendly name of the device.
@@ -234,15 +243,25 @@
 
 The id and name fields can be passed to userland via the evdev interface.
 
-1.7 The keycode, keycodemax, keycodesize fields
+1.6 The keycode, keycodemax, keycodesize fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-These two fields will be used for any input devices that report their data
-as scancodes. If not all scancodes can be known by autodetection, they may
-need to be set by userland utilities. The keycode array then is an array
-used to map from scancodes to input system keycodes. The keycode max will
-contain the size of the array and keycodesize the size of each entry in it
-(in bytes).
+These three fields should be used by input devices that have dense keymaps.
+The keycode is an array used to map from scancodes to input system keycodes.
+The keycode max should contain the size of the array and keycodesize the
+size of each entry in it (in bytes).
+
+Userspace can query and alter current scancode to keycode mappings using
+EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.
+When a device has all 3 aforementioned fields filled in, the driver may
+rely on kernel's default implementation of setting and querying keycode
+mappings.
+
+1.7 dev->getkeycode() and dev->setkeycode()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+getkeycode() and setkeycode() callbacks allow drivers to override default
+keycode/keycodesize/keycodemax mapping mechanism provided by input core
+and implement sparse keycode maps.
 
 1.8 Key autorepeat
 ~~~~~~~~~~~~~~~~~~
@@ -266,7 +285,7 @@
 driver can handle these events, it has to set the respective bits in evbit,
 *and* also the callback routine:
 
-	button_dev.event = button_event;
+	button_dev->event = button_event;
 
 int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 {
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index de017c1..9565b21 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o reset.o setup.o
+obj-y	 := irq.o reset.o setup.o buttons.o
 
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c
new file mode 100644
index 0000000..9e14398
--- /dev/null
+++ b/arch/mips/cobalt/buttons.c
@@ -0,0 +1,54 @@
+/*
+ *  Cobalt buttons platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static struct resource cobalt_buttons_resource __initdata = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static __init int cobalt_add_buttons(void)
+{
+	struct platform_device *pd;
+	int error;
+
+	pd = platform_device_alloc("Cobalt buttons", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	error = platform_device_add_resources(pd, &cobalt_buttons_resource, 1);
+	if (error)
+		goto err_free_device;
+
+	error = platform_device_add(pd);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(pd);
+	return error;
+}
+device_initcall(cobalt_add_buttons);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index cb8d691..c06e86a 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -41,7 +41,6 @@
 #include <linux/input.h>
 #include <linux/reboot.h>
 
-static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
 
 /*
@@ -159,65 +158,41 @@
 static int sysrq_alt;
 
 /*
- * Translation of scancodes to keycodes. We set them on only the first attached
- * keyboard - for per-keyboard setting, /dev/input/event is more useful.
+ * Translation of scancodes to keycodes. We set them on only the first
+ * keyboard in the list that accepts the scancode and keycode.
+ * Explanation for not choosing the first attached keyboard anymore:
+ *  USB keyboards for example have two event devices: one for all "normal"
+ *  keys and one for extra function keys (like "volume up", "make coffee",
+ *  etc.). So this means that scancodes for the extra function keys won't
+ *  be valid for the first event device, but will be for the second.
  */
 int getkeycode(unsigned int scancode)
 {
-	struct list_head *node;
-	struct input_dev *dev = NULL;
+	struct input_handle *handle;
+	int keycode;
+	int error = -ENODEV;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
-		if (handle->dev->keycodesize) {
-			dev = handle->dev;
-			break;
-		}
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+		error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
+		if (!error)
+			return keycode;
 	}
 
-	if (!dev)
-		return -ENODEV;
-
-	if (scancode >= dev->keycodemax)
-		return -EINVAL;
-
-	return INPUT_KEYCODE(dev, scancode);
+	return error;
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-	struct list_head *node;
-	struct input_dev *dev = NULL;
-	unsigned int i, oldkey;
+	struct input_handle *handle;
+	int error = -ENODEV;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
-		if (handle->dev->keycodesize) {
-			dev = handle->dev;
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+		error = handle->dev->setkeycode(handle->dev, scancode, keycode);
+		if (!error)
 			break;
-		}
 	}
 
-	if (!dev)
-		return -ENODEV;
-
-	if (scancode >= dev->keycodemax)
-		return -EINVAL;
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
-		return -EINVAL;
-
-	oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
-
-	clear_bit(oldkey, dev->keybit);
-	set_bit(keycode, dev->keybit);
-
-	for (i = 0; i < dev->keycodemax; i++)
-		if (INPUT_KEYCODE(dev,i) == oldkey)
-			set_bit(oldkey, dev->keybit);
-
-	return 0;
+	return error;
 }
 
 /*
@@ -225,10 +200,9 @@
  */
 static void kd_nosound(unsigned long ignored)
 {
-	struct list_head *node;
+	struct input_handle *handle;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
 		if (test_bit(EV_SND, handle->dev->evbit)) {
 			if (test_bit(SND_TONE, handle->dev->sndbit))
 				input_inject_event(handle, EV_SND, SND_TONE, 0);
@@ -1161,7 +1135,7 @@
 
 	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
 		if (emulate_raw(vc, keycode, !down << 7))
-			if (keycode < BTN_MISC)
+			if (keycode < BTN_MISC && printk_ratelimit())
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
 #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
@@ -1285,11 +1259,11 @@
  * likes it, it can open it and get events from it. In this (kbd_connect)
  * function, we should decide which VT to bind that keyboard to initially.
  */
-static struct input_handle *kbd_connect(struct input_handler *handler,
-					struct input_dev *dev,
-					const struct input_device_id *id)
+static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
+			const struct input_device_id *id)
 {
 	struct input_handle *handle;
+	int error;
 	int i;
 
 	for (i = KEY_RESERVED; i < BTN_MISC; i++)
@@ -1297,24 +1271,37 @@
 			break;
 
 	if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
-		return NULL;
+		return -ENODEV;
 
 	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
 	if (!handle)
-		return NULL;
+		return -ENOMEM;
 
 	handle->dev = dev;
 	handle->handler = handler;
 	handle->name = "kbd";
 
-	input_open_device(handle);
+	error = input_register_handle(handle);
+	if (error)
+		goto err_free_handle;
 
-	return handle;
+	error = input_open_device(handle);
+	if (error)
+		goto err_unregister_handle;
+
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(handle);
+ err_free_handle:
+	kfree(handle);
+	return error;
 }
 
 static void kbd_disconnect(struct input_handle *handle)
 {
 	input_close_device(handle);
+	input_unregister_handle(handle);
 	kfree(handle);
 }
 
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index da575de..b4cd106 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -13,7 +13,6 @@
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
 obj-$(CONFIG_INPUT_EVDEV)	+= evdev.o
 obj-$(CONFIG_INPUT_TSDEV)	+= tsdev.o
-obj-$(CONFIG_INPUT_POWER)	+= power.o
 obj-$(CONFIG_INPUT_EVBUG)	+= evbug.o
 
 obj-$(CONFIG_INPUT_KEYBOARD)	+= keyboard/
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index 5a9653c..c21f2f1 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -38,31 +38,43 @@
 MODULE_DESCRIPTION("Input driver event debug module");
 MODULE_LICENSE("GPL");
 
-static char evbug_name[] = "evbug";
-
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
 		handle->dev->phys, type, code, value);
 }
 
-static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev,
-					  const struct input_device_id *id)
+static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct input_handle *handle;
+	int error;
 
-	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-		return NULL;
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
 
 	handle->dev = dev;
 	handle->handler = handler;
-	handle->name = evbug_name;
+	handle->name = "evbug";
 
-	input_open_device(handle);
+	error = input_register_handle(handle);
+	if (error)
+		goto err_free_handle;
+
+	error = input_open_device(handle);
+	if (error)
+		goto err_unregister_handle;
 
 	printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
 
-	return handle;
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(handle);
+ err_free_handle:
+	kfree(handle);
+	return error;
 }
 
 static void evbug_disconnect(struct input_handle *handle)
@@ -70,7 +82,7 @@
 	printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
 
 	input_close_device(handle);
-
+	input_unregister_handle(handle);
 	kfree(handle);
 }
 
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6439f37..6cff809 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -29,11 +29,11 @@
 	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct evdev_list *grab;
-	struct list_head list;
+	struct evdev_client *grab;
+	struct list_head client_list;
 };
 
-struct evdev_list {
+struct evdev_client {
 	struct input_event buffer[EVDEV_BUFFER_SIZE];
 	int head;
 	int tail;
@@ -47,28 +47,28 @@
 static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct evdev *evdev = handle->private;
-	struct evdev_list *list;
+	struct evdev_client *client;
 
 	if (evdev->grab) {
-		list = evdev->grab;
+		client = evdev->grab;
 
-		do_gettimeofday(&list->buffer[list->head].time);
-		list->buffer[list->head].type = type;
-		list->buffer[list->head].code = code;
-		list->buffer[list->head].value = value;
-		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+		do_gettimeofday(&client->buffer[client->head].time);
+		client->buffer[client->head].type = type;
+		client->buffer[client->head].code = code;
+		client->buffer[client->head].value = value;
+		client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	} else
-		list_for_each_entry(list, &evdev->list, node) {
+		list_for_each_entry(client, &evdev->client_list, node) {
 
-			do_gettimeofday(&list->buffer[list->head].time);
-			list->buffer[list->head].type = type;
-			list->buffer[list->head].code = code;
-			list->buffer[list->head].value = value;
-			list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+			do_gettimeofday(&client->buffer[client->head].time);
+			client->buffer[client->head].type = type;
+			client->buffer[client->head].code = code;
+			client->buffer[client->head].value = value;
+			client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 		}
 
 	wake_up_interruptible(&evdev->wait);
@@ -76,22 +76,23 @@
 
 static int evdev_fasync(int fd, struct file *file, int on)
 {
+	struct evdev_client *client = file->private_data;
 	int retval;
-	struct evdev_list *list = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
 
 static int evdev_flush(struct file *file, fl_owner_t id)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
-	return input_flush_device(&list->evdev->handle, file);
+	return input_flush_device(&evdev->handle, file);
 }
 
 static void evdev_free(struct evdev *evdev)
@@ -100,48 +101,62 @@
 	kfree(evdev);
 }
 
-static int evdev_release(struct inode * inode, struct file * file)
+static int evdev_release(struct inode *inode, struct file *file)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	if (list->evdev->grab == list) {
-		input_release_device(&list->evdev->handle);
-		list->evdev->grab = NULL;
+	if (evdev->grab == client) {
+		input_release_device(&evdev->handle);
+		evdev->grab = NULL;
 	}
 
 	evdev_fasync(-1, file, 0);
-	list_del(&list->node);
+	list_del(&client->node);
+	kfree(client);
 
-	if (!--list->evdev->open) {
-		if (list->evdev->exist)
-			input_close_device(&list->evdev->handle);
+	if (!--evdev->open) {
+		if (evdev->exist)
+			input_close_device(&evdev->handle);
 		else
-			evdev_free(list->evdev);
+			evdev_free(evdev);
 	}
 
-	kfree(list);
 	return 0;
 }
 
-static int evdev_open(struct inode * inode, struct file * file)
+static int evdev_open(struct inode *inode, struct file *file)
 {
-	struct evdev_list *list;
+	struct evdev_client *client;
+	struct evdev *evdev;
 	int i = iminor(inode) - EVDEV_MINOR_BASE;
+	int error;
 
-	if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
+	if (i >= EVDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+	evdev = evdev_table[i];
+
+	if (!evdev || !evdev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->evdev = evdev_table[i];
-	list_add_tail(&list->node, &evdev_table[i]->list);
-	file->private_data = list;
+	client->evdev = evdev;
+	list_add_tail(&client->node, &evdev->client_list);
 
-	if (!list->evdev->open++)
-		if (list->evdev->exist)
-			input_open_device(&list->evdev->handle);
+	if (!evdev->open++ && evdev->exist) {
+		error = input_open_device(&evdev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
+	file->private_data = client;
 	return 0;
 }
 
@@ -243,54 +258,55 @@
 
 #endif /* CONFIG_COMPAT */
 
-static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	struct input_event event;
 	int retval = 0;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
 	while (retval < count) {
 
 		if (evdev_event_from_user(buffer + retval, &event))
 			return -EFAULT;
-		input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
+		input_inject_event(&evdev->handle, event.type, event.code, event.value);
 		retval += evdev_event_size();
 	}
 
 	return retval;
 }
 
-static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	int retval;
 
 	if (count < evdev_event_size())
 		return -EINVAL;
 
-	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
+	if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->evdev->wait,
-		list->head != list->tail || (!list->evdev->exist));
-
+	retval = wait_event_interruptible(evdev->wait,
+		client->head != client->tail || !evdev->exist);
 	if (retval)
 		return retval;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + evdev_event_size() <= count) {
+	while (client->head != client->tail && retval + evdev_event_size() <= count) {
 
-		struct input_event *event = (struct input_event *) list->buffer + list->tail;
+		struct input_event *event = (struct input_event *) client->buffer + client->tail;
 
 		if (evdev_event_to_user(buffer + retval, event))
 			return -EFAULT;
 
-		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
 		retval += evdev_event_size();
 	}
 
@@ -300,11 +316,12 @@
 /* No kernel lock - fine */
 static unsigned int evdev_poll(struct file *file, poll_table *wait)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	poll_wait(file, &list->evdev->wait, wait);
-	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &evdev->wait, wait);
+	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 #ifdef CONFIG_COMPAT
@@ -387,8 +404,8 @@
 static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 				void __user *p, int compat_mode)
 {
-	struct evdev_list *list = file->private_data;
-	struct evdev *evdev = list->evdev;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
 	struct ff_effect effect;
@@ -434,32 +451,21 @@
 		case EVIOCGKEYCODE:
 			if (get_user(t, ip))
 				return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-				return -EINVAL;
-			if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+
+			error = dev->getkeycode(dev, t, &v);
+			if (error)
+				return error;
+
+			if (put_user(v, ip + 1))
 				return -EFAULT;
+
 			return 0;
 
 		case EVIOCSKEYCODE:
-			if (get_user(t, ip))
+			if (get_user(t, ip) || get_user(v, ip + 1))
 				return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-				return -EINVAL;
-			if (get_user(v, ip + 1))
-				return -EFAULT;
-			if (v < 0 || v > KEY_MAX)
-				return -EINVAL;
-			if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
-				return -EINVAL;
 
-			u = SET_INPUT_KEYCODE(dev, t, v);
-			clear_bit(u, dev->keybit);
-			set_bit(v, dev->keybit);
-			for (i = 0; i < dev->keycodemax; i++)
-				if (INPUT_KEYCODE(dev, i) == u)
-					set_bit(u, dev->keybit);
-
-			return 0;
+			return dev->setkeycode(dev, t, v);
 
 		case EVIOCSFF:
 			if (copy_from_user(&effect, p, sizeof(effect)))
@@ -487,10 +493,10 @@
 					return -EBUSY;
 				if (input_grab_device(&evdev->handle))
 					return -EBUSY;
-				evdev->grab = list;
+				evdev->grab = client;
 				return 0;
 			} else {
-				if (evdev->grab != list)
+				if (evdev->grab != client)
 					return -EINVAL;
 				input_release_device(&evdev->handle);
 				evdev->grab = NULL;
@@ -616,23 +622,26 @@
 	.flush =	evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev,
-					  const struct input_device_id *id)
+static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
 	struct class_device *cdev;
+	dev_t devt;
 	int minor;
+	int error;
 
 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
 	if (minor == EVDEV_MINORS) {
 		printk(KERN_ERR "evdev: no more free evdev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
-		return NULL;
+	evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
+	if (!evdev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&evdev->list);
+	INIT_LIST_HEAD(&evdev->client_list);
 	init_waitqueue_head(&evdev->wait);
 
 	evdev->exist = 1;
@@ -645,21 +654,43 @@
 
 	evdev_table[minor] = evdev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			dev->cdev.dev, evdev->name);
+	devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, evdev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_evdev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  evdev->name);
+	error = sysfs_create_link(&input_class.subsys.kset.kobj,
+				  &cdev->kobj, evdev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &evdev->handle;
+	error = input_register_handle(&evdev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_evdev:
+	kfree(evdev);
+	evdev_table[minor] = NULL;
+	return error;
 }
 
 static void evdev_disconnect(struct input_handle *handle)
 {
 	struct evdev *evdev = handle->private;
-	struct evdev_list *list;
+	struct evdev_client *client;
+
+	input_unregister_handle(handle);
 
 	sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
 	class_device_destroy(&input_class,
@@ -670,8 +701,8 @@
 		input_flush_device(handle, NULL);
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
-		list_for_each_entry(list, &evdev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &evdev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		evdev_free(evdev);
 }
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a9a706f..915e9ab 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -299,12 +299,87 @@
 }
 EXPORT_SYMBOL(input_close_device);
 
-static void input_link_handle(struct input_handle *handle)
+static int input_fetch_keycode(struct input_dev *dev, int scancode)
 {
-	list_add_tail(&handle->d_node, &handle->dev->h_list);
-	list_add_tail(&handle->h_node, &handle->handler->h_list);
+	switch (dev->keycodesize) {
+		case 1:
+			return ((u8 *)dev->keycode)[scancode];
+
+		case 2:
+			return ((u16 *)dev->keycode)[scancode];
+
+		default:
+			return ((u32 *)dev->keycode)[scancode];
+	}
 }
 
+static int input_default_getkeycode(struct input_dev *dev,
+				    int scancode, int *keycode)
+{
+	if (!dev->keycodesize)
+		return -EINVAL;
+
+	if (scancode < 0 || scancode >= dev->keycodemax)
+		return -EINVAL;
+
+	*keycode = input_fetch_keycode(dev, scancode);
+
+	return 0;
+}
+
+static int input_default_setkeycode(struct input_dev *dev,
+				    int scancode, int keycode)
+{
+	int old_keycode;
+	int i;
+
+	if (scancode < 0 || scancode >= dev->keycodemax)
+		return -EINVAL;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	if (!dev->keycodesize)
+		return -EINVAL;
+
+	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+		return -EINVAL;
+
+	switch (dev->keycodesize) {
+		case 1: {
+			u8 *k = (u8 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+		case 2: {
+			u16 *k = (u16 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+		default: {
+			u32 *k = (u32 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+	}
+
+	clear_bit(old_keycode, dev->keybit);
+	set_bit(keycode, dev->keybit);
+
+	for (i = 0; i < dev->keycodemax; i++) {
+		if (input_fetch_keycode(dev, i) == old_keycode) {
+			set_bit(old_keycode, dev->keybit);
+			break; /* Setting the bit twice is useless, so break */
+		}
+	}
+
+	return 0;
+}
+
+
 #define MATCH_BIT(bit, max) \
 		for (i = 0; i < NBITS(max); i++) \
 			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
@@ -351,6 +426,29 @@
 	return NULL;
 }
 
+static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
+{
+	const struct input_device_id *id;
+	int error;
+
+	if (handler->blacklist && input_match_device(handler->blacklist, dev))
+		return -ENODEV;
+
+	id = input_match_device(handler->id_table, dev);
+	if (!id)
+		return -ENODEV;
+
+	error = handler->connect(handler, dev, id);
+	if (error && error != -ENODEV)
+		printk(KERN_ERR
+			"input: failed to attach handler %s to device %s, "
+			"error: %d\n",
+			handler->name, kobject_name(&dev->cdev.kobj), error);
+
+	return error;
+}
+
+
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -439,6 +537,7 @@
 	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, "U: Uniq=%s\n", dev->uniq ? dev->uniq : "");
 	seq_printf(seq, "H: Handlers=");
 
 	list_for_each_entry(handle, &dev->h_list, d_node)
@@ -753,6 +852,13 @@
 	.attrs	= input_dev_caps_attrs,
 };
 
+static struct attribute_group *input_dev_attr_groups[] = {
+	&input_dev_attr_group,
+	&input_dev_id_attr_group,
+	&input_dev_caps_attr_group,
+	NULL
+};
+
 static void input_dev_release(struct class_device *class_dev)
 {
 	struct input_dev *dev = to_input_dev(class_dev);
@@ -906,6 +1012,7 @@
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (dev) {
 		dev->cdev.class = &input_class;
+		dev->cdev.groups = input_dev_attr_groups;
 		class_device_initialize(&dev->cdev);
 		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
@@ -934,23 +1041,71 @@
  */
 void input_free_device(struct input_dev *dev)
 {
-	if (dev) {
-
-		mutex_lock(&dev->mutex);
-		dev->name = dev->phys = dev->uniq = NULL;
-		mutex_unlock(&dev->mutex);
-
+	if (dev)
 		input_put_device(dev);
-	}
 }
 EXPORT_SYMBOL(input_free_device);
 
+/**
+ * input_set_capability - mark device as capable of a certain event
+ * @dev: device that is capable of emitting or accepting event
+ * @type: type of the event (EV_KEY, EV_REL, etc...)
+ * @code: event code
+ *
+ * In addition to setting up corresponding bit in appropriate capability
+ * bitmap the function also adjusts dev->evbit.
+ */
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
+{
+	switch (type) {
+	case EV_KEY:
+		__set_bit(code, dev->keybit);
+		break;
+
+	case EV_REL:
+		__set_bit(code, dev->relbit);
+		break;
+
+	case EV_ABS:
+		__set_bit(code, dev->absbit);
+		break;
+
+	case EV_MSC:
+		__set_bit(code, dev->mscbit);
+		break;
+
+	case EV_SW:
+		__set_bit(code, dev->swbit);
+		break;
+
+	case EV_LED:
+		__set_bit(code, dev->ledbit);
+		break;
+
+	case EV_SND:
+		__set_bit(code, dev->sndbit);
+		break;
+
+	case EV_FF:
+		__set_bit(code, dev->ffbit);
+		break;
+
+	default:
+		printk(KERN_ERR
+			"input_set_capability: unknown type %u (code %u)\n",
+			type, code);
+		dump_stack();
+		return;
+	}
+
+	__set_bit(type, dev->evbit);
+}
+EXPORT_SYMBOL(input_set_capability);
+
 int input_register_device(struct input_dev *dev)
 {
 	static atomic_t input_no = ATOMIC_INIT(0);
-	struct input_handle *handle;
 	struct input_handler *handler;
-	const struct input_device_id *id;
 	const char *path;
 	int error;
 
@@ -969,55 +1124,41 @@
 		dev->rep[REP_PERIOD] = 33;
 	}
 
+	if (!dev->getkeycode)
+		dev->getkeycode = input_default_getkeycode;
+
+	if (!dev->setkeycode)
+		dev->setkeycode = input_default_setkeycode;
+
 	list_add_tail(&dev->node, &input_dev_list);
 
 	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
 		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
+	if (!dev->cdev.dev)
+		dev->cdev.dev = dev->dev.parent;
+
 	error = class_device_add(&dev->cdev);
 	if (error)
 		return error;
 
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group);
-	if (error)
-		goto fail1;
-
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-	if (error)
-		goto fail2;
-
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-	if (error)
-		goto fail3;
-
 	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
 	printk(KERN_INFO "input: %s as %s\n",
 		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
 	kfree(path);
 
 	list_for_each_entry(handler, &input_handler_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 
 	return 0;
-
- fail3:	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- fail2:	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
- fail1:	class_device_del(&dev->cdev);
-	return error;
 }
 EXPORT_SYMBOL(input_register_device);
 
 void input_unregister_device(struct input_dev *dev)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 	int code;
 
 	for (code = 0; code <= KEY_MAX; code++)
@@ -1027,19 +1168,12 @@
 
 	del_timer_sync(&dev->timer);
 
-	list_for_each_safe(node, next, &dev->h_list) {
-		struct input_handle * handle = to_handle(node);
-		list_del_init(&handle->d_node);
-		list_del_init(&handle->h_node);
+	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
 		handle->handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&dev->h_list));
 
 	list_del_init(&dev->node);
 
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
-
 	class_device_unregister(&dev->cdev);
 
 	input_wakeup_procfs_readers();
@@ -1049,8 +1183,6 @@
 int input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev;
-	struct input_handle *handle;
-	const struct input_device_id *id;
 
 	INIT_LIST_HEAD(&handler->h_list);
 
@@ -1064,13 +1196,7 @@
 	list_add_tail(&handler->node, &input_handler_list);
 
 	list_for_each_entry(dev, &input_dev_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 	return 0;
@@ -1079,14 +1205,11 @@
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 
-	list_for_each_safe(node, next, &handler->h_list) {
-		struct input_handle * handle = to_handle_h(node);
-		list_del_init(&handle->h_node);
-		list_del_init(&handle->d_node);
+	list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
 		handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&handler->h_list));
 
 	list_del_init(&handler->node);
 
@@ -1097,6 +1220,27 @@
 }
 EXPORT_SYMBOL(input_unregister_handler);
 
+int input_register_handle(struct input_handle *handle)
+{
+	struct input_handler *handler = handle->handler;
+
+	list_add_tail(&handle->d_node, &handle->dev->h_list);
+	list_add_tail(&handle->h_node, &handler->h_list);
+
+	if (handler->start)
+		handler->start(handle);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_register_handle);
+
+void input_unregister_handle(struct input_handle *handle)
+{
+	list_del_init(&handle->h_node);
+	list_del_init(&handle->d_node);
+}
+EXPORT_SYMBOL(input_unregister_handle);
+
 static int input_open_file(struct inode *inode, struct file *file)
 {
 	struct input_handler *handler = input_table[iminor(inode) >> 5];
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 9f3529a..4f37224 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,7 +43,7 @@
 	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
@@ -55,7 +55,7 @@
 	__s16 abs[ABS_MAX + 1];
 };
 
-struct joydev_list {
+struct joydev_client {
 	struct js_event buffer[JOYDEV_BUFFER_SIZE];
 	int head;
 	int tail;
@@ -87,7 +87,7 @@
 static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct joydev *joydev = handle->private;
-	struct joydev_list *list;
+	struct joydev_client *client;
 	struct js_event event;
 
 	switch (type) {
@@ -115,15 +115,15 @@
 
 	event.time = jiffies_to_msecs(jiffies);
 
-	list_for_each_entry(list, &joydev->list, node) {
+	list_for_each_entry(client, &joydev->client_list, node) {
 
-		memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
+		memcpy(client->buffer + client->head, &event, sizeof(struct js_event));
 
-		if (list->startup == joydev->nabs + joydev->nkey)
-			if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
-				list->startup = 0;
+		if (client->startup == joydev->nabs + joydev->nkey)
+			if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
+				client->startup = 0;
 
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
 
 	wake_up_interruptible(&joydev->wait);
@@ -132,9 +132,9 @@
 static int joydev_fasync(int fd, struct file *file, int on)
 {
 	int retval;
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
@@ -145,60 +145,73 @@
 	kfree(joydev);
 }
 
-static int joydev_release(struct inode * inode, struct file * file)
+static int joydev_release(struct inode *inode, struct file *file)
 {
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 
 	joydev_fasync(-1, file, 0);
 
-	list_del(&list->node);
+	list_del(&client->node);
+	kfree(client);
 
-	if (!--list->joydev->open) {
-		if (list->joydev->exist)
-			input_close_device(&list->joydev->handle);
+	if (!--joydev->open) {
+		if (joydev->exist)
+			input_close_device(&joydev->handle);
 		else
-			joydev_free(list->joydev);
+			joydev_free(joydev);
 	}
 
-	kfree(list);
 	return 0;
 }
 
 static int joydev_open(struct inode *inode, struct file *file)
 {
-	struct joydev_list *list;
+	struct joydev_client *client;
+	struct joydev *joydev;
 	int i = iminor(inode) - JOYDEV_MINOR_BASE;
+	int error;
 
-	if (i >= JOYDEV_MINORS || !joydev_table[i])
+	if (i >= JOYDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+	joydev = joydev_table[i];
+	if (!joydev || !joydev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->joydev = joydev_table[i];
-	list_add_tail(&list->node, &joydev_table[i]->list);
-	file->private_data = list;
+	client->joydev = joydev;
+	list_add_tail(&client->node, &joydev->client_list);
 
-	if (!list->joydev->open++)
-		if (list->joydev->exist)
-			input_open_device(&list->joydev->handle);
+	if (!joydev->open++ && joydev->exist) {
+		error = input_open_device(&joydev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
+	file->private_data = client;
 	return 0;
 }
 
-static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	return -EINVAL;
 }
 
 static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	struct input_dev *input = joydev->handle.dev;
 	int retval = 0;
 
-	if (!list->joydev->exist)
+	if (!joydev->exist)
 		return -ENODEV;
 
 	if (count < sizeof(struct js_event))
@@ -217,56 +230,55 @@
 		if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
 			return -EFAULT;
 
-		list->startup = 0;
-		list->tail = list->head;
+		client->startup = 0;
+		client->tail = client->head;
 
 		return sizeof(struct JS_DATA_TYPE);
 	}
 
-	if (list->startup == joydev->nabs + joydev->nkey &&
-	    list->head == list->tail && (file->f_flags & O_NONBLOCK))
+	if (client->startup == joydev->nabs + joydev->nkey &&
+	    client->head == client->tail && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->joydev->wait,
-					  !list->joydev->exist ||
-					  list->startup < joydev->nabs + joydev->nkey ||
-					  list->head != list->tail);
-
+	retval = wait_event_interruptible(joydev->wait,
+					  !joydev->exist ||
+					  client->startup < joydev->nabs + joydev->nkey ||
+					  client->head != client->tail);
 	if (retval)
 		return retval;
 
-	if (!list->joydev->exist)
+	if (!joydev->exist)
 		return -ENODEV;
 
-	while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
+	while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
 
 		struct js_event event;
 
 		event.time = jiffies_to_msecs(jiffies);
 
-		if (list->startup < joydev->nkey) {
+		if (client->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
-			event.number = list->startup;
+			event.number = client->startup;
 			event.value = !!test_bit(joydev->keypam[event.number], input->key);
 		} else {
 			event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
-			event.number = list->startup - joydev->nkey;
+			event.number = client->startup - joydev->nkey;
 			event.value = joydev->abs[event.number];
 		}
 
 		if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
 			return -EFAULT;
 
-		list->startup++;
+		client->startup++;
 		retval += sizeof(struct js_event);
 	}
 
-	while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
+	while (client->head != client->tail && retval + sizeof(struct js_event) <= count) {
 
-		if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
+		if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event)))
 			return -EFAULT;
 
-		list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
 		retval += sizeof(struct js_event);
 	}
 
@@ -276,11 +288,12 @@
 /* No kernel lock - fine */
 static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 
-	poll_wait(file, &list->joydev->wait, wait);
-	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
-		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &joydev->wait, wait);
+	return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ?
+		(POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
@@ -374,8 +387,8 @@
 #ifdef CONFIG_COMPAT
 static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	void __user *argp = (void __user *)arg;
 	s32 tmp32;
 	struct JS_DATA_SAVE_TYPE_32 ds32;
@@ -428,8 +441,8 @@
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	void __user *argp = (void __user *)arg;
 
 	if (!joydev->exist)
@@ -465,23 +478,26 @@
 	.fasync =	joydev_fasync,
 };
 
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev,
-					   const struct input_device_id *id)
+static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
+			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
 	struct class_device *cdev;
+	dev_t devt;
 	int i, j, t, minor;
+	int error;
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
 	if (minor == JOYDEV_MINORS) {
 		printk(KERN_ERR "joydev: no more free joydev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
-		return NULL;
+	joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
+	if (!joydev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&joydev->list);
+	INIT_LIST_HEAD(&joydev->client_list);
 	init_waitqueue_head(&joydev->wait);
 
 	joydev->minor = minor;
@@ -534,21 +550,44 @@
 
 	joydev_table[minor] = joydev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			dev->cdev.dev, joydev->name);
+	devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, joydev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_joydev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  joydev->name);
+	error = sysfs_create_link(&input_class.subsys.kset.kobj,
+				  &cdev->kobj, joydev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &joydev->handle;
+	error = input_register_handle(&joydev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_joydev:
+	joydev_table[minor] = NULL;
+	kfree(joydev);
+	return error;
 }
 
+
 static void joydev_disconnect(struct input_handle *handle)
 {
 	struct joydev *joydev = handle->private;
-	struct joydev_list *list;
+	struct joydev_client *client;
+
+	input_unregister_handle(handle);
 
 	sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
 	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
@@ -557,8 +596,8 @@
 	if (joydev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&joydev->wait);
-		list_for_each_entry(list, &joydev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &joydev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		joydev_free(joydev);
 }
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index b11a4bb..ff701ab 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -241,7 +241,7 @@
 
 static int a3d_open(struct input_dev *dev)
 {
-	struct a3d *a3d = dev->private;
+	struct a3d *a3d = input_get_drvdata(dev);
 
 	gameport_start_polling(a3d->gameport);
 	return 0;
@@ -253,7 +253,7 @@
 
 static void a3d_close(struct input_dev *dev)
 {
-	struct a3d *a3d = dev->private;
+	struct a3d *a3d = input_get_drvdata(dev);
 
 	gameport_stop_polling(a3d->gameport);
 }
@@ -314,11 +314,12 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
 	input_dev->id.product = a3d->mode;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = a3d;
+	input_dev->dev.parent = &gameport->dev;
 	input_dev->open = a3d_open;
 	input_dev->close = a3d_close;
 
+	input_set_drvdata(input_dev, a3d);
+
 	if (a3d->mode == A3D_MODE_PXL) {
 
 		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 6279ced..28140c4 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -290,7 +290,7 @@
 
 static int adi_open(struct input_dev *dev)
 {
-	struct adi_port *port = dev->private;
+	struct adi_port *port = input_get_drvdata(dev);
 
 	gameport_start_polling(port->gameport);
 	return 0;
@@ -302,7 +302,7 @@
 
 static void adi_close(struct input_dev *dev)
 {
-	struct adi_port *port = dev->private;
+	struct adi_port *port = input_get_drvdata(dev);
 
 	gameport_stop_polling(port->gameport);
 }
@@ -424,8 +424,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
 	input_dev->id.product = adi->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &port->gameport->dev;
-	input_dev->private = port;
+	input_dev->dev.parent = &port->gameport->dev;
+
+	input_set_drvdata(input_dev, port);
 
 	input_dev->open = adi_open;
 	input_dev->close = adi_close;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 51f1e4b..1c1afb5 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -343,7 +343,7 @@
 
 static int analog_open(struct input_dev *dev)
 {
-	struct analog_port *port = dev->private;
+	struct analog_port *port = input_get_drvdata(dev);
 
 	gameport_start_polling(port->gameport);
 	return 0;
@@ -355,7 +355,7 @@
 
 static void analog_close(struct input_dev *dev)
 {
-	struct analog_port *port = dev->private;
+	struct analog_port *port = input_get_drvdata(dev);
 
 	gameport_stop_polling(port->gameport);
 }
@@ -449,10 +449,13 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
 	input_dev->id.product = analog->mask >> 4;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &port->gameport->dev;
+
+	input_set_drvdata(input_dev, port);
 
 	input_dev->open = analog_open;
 	input_dev->close = analog_close;
-	input_dev->private = port;
+
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = j = 0; i < 4; i++)
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 034ec39..d3352a8 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -142,7 +142,7 @@
 
 static int cobra_open(struct input_dev *dev)
 {
-	struct cobra *cobra = dev->private;
+	struct cobra *cobra = input_get_drvdata(dev);
 
 	gameport_start_polling(cobra->gameport);
 	return 0;
@@ -150,7 +150,7 @@
 
 static void cobra_close(struct input_dev *dev)
 {
-	struct cobra *cobra = dev->private;
+	struct cobra *cobra = input_get_drvdata(dev);
 
 	gameport_stop_polling(cobra->gameport);
 }
@@ -211,8 +211,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
 		input_dev->id.product = 0x0008;
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = cobra;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, cobra);
 
 		input_dev->open = cobra_open;
 		input_dev->close = cobra_close;
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index b41bd2e..c27593b 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -518,7 +518,7 @@
 
 static int db9_open(struct input_dev *dev)
 {
-	struct db9 *db9 = dev->private;
+	struct db9 *db9 = input_get_drvdata(dev);
 	struct parport *port = db9->pd->port;
 	int err;
 
@@ -542,7 +542,7 @@
 
 static void db9_close(struct input_dev *dev)
 {
-	struct db9 *db9 = dev->private;
+	struct db9 *db9 = input_get_drvdata(dev);
 	struct parport *port = db9->pd->port;
 
 	mutex_lock(&db9->mutex);
@@ -625,7 +625,8 @@
 		input_dev->id.vendor = 0x0002;
 		input_dev->id.product = mode;
 		input_dev->id.version = 0x0100;
-		input_dev->private = db9;
+
+		input_set_drvdata(input_dev, db9);
 
 		input_dev->open = db9_open;
 		input_dev->close = db9_close;
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 711e4b3..c71b58f 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -591,7 +591,7 @@
 
 static int gc_open(struct input_dev *dev)
 {
-	struct gc *gc = dev->private;
+	struct gc *gc = input_get_drvdata(dev);
 	int err;
 
 	err = mutex_lock_interruptible(&gc->mutex);
@@ -610,7 +610,7 @@
 
 static void gc_close(struct input_dev *dev)
 {
-	struct gc *gc = dev->private;
+	struct gc *gc = input_get_drvdata(dev);
 
 	mutex_lock(&gc->mutex);
 	if (!--gc->used) {
@@ -646,7 +646,8 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = pad_type;
 	input_dev->id.version = 0x0100;
-	input_dev->private = gc;
+
+	input_set_drvdata(input_dev, gc);
 
 	input_dev->open = gc_open;
 	input_dev->close = gc_close;
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index bacbab5..d514aeb 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -220,7 +220,7 @@
 
 static int gf2k_open(struct input_dev *dev)
 {
-	struct gf2k *gf2k = dev->private;
+	struct gf2k *gf2k = input_get_drvdata(dev);
 
 	gameport_start_polling(gf2k->gameport);
 	return 0;
@@ -228,7 +228,7 @@
 
 static void gf2k_close(struct input_dev *dev)
 {
-	struct gf2k *gf2k = dev->private;
+	struct gf2k *gf2k = input_get_drvdata(dev);
 
 	gameport_stop_polling(gf2k->gameport);
 }
@@ -308,11 +308,13 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
 	input_dev->id.product = gf2k->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = gf2k;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, gf2k);
 
 	input_dev->open = gf2k_open;
 	input_dev->close = gf2k_close;
+
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; i < gf2k_axes[gf2k->id]; i++)
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 17a90c4..73eb5ab 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -285,7 +285,7 @@
 
 static int grip_open(struct input_dev *dev)
 {
-	struct grip *grip = dev->private;
+	struct grip *grip = input_get_drvdata(dev);
 
 	gameport_start_polling(grip->gameport);
 	return 0;
@@ -293,7 +293,7 @@
 
 static void grip_close(struct input_dev *dev)
 {
-	struct grip *grip = dev->private;
+	struct grip *grip = input_get_drvdata(dev);
 
 	gameport_stop_polling(grip->gameport);
 }
@@ -363,8 +363,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
 		input_dev->id.product = grip->mode[i];
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = grip;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, grip);
 
 		input_dev->open = grip_open;
 		input_dev->close = grip_close;
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 8120a9c..555319e 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -562,7 +562,7 @@
 
 static int grip_open(struct input_dev *dev)
 {
-	struct grip_mp *grip = dev->private;
+	struct grip_mp *grip = input_get_drvdata(dev);
 
 	gameport_start_polling(grip->gameport);
 	return 0;
@@ -574,9 +574,9 @@
 
 static void grip_close(struct input_dev *dev)
 {
-	struct grip_mp *grip = dev->private;
+	struct grip_mp *grip = input_get_drvdata(dev);
 
-	gameport_start_polling(grip->gameport);
+	gameport_stop_polling(grip->gameport);
 }
 
 /*
@@ -599,8 +599,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
 	input_dev->id.product = 0x0100 + port->mode;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &grip->gameport->dev;
-	input_dev->private = grip;
+	input_dev->dev.parent = &grip->gameport->dev;
+
+	input_set_drvdata(input_dev, grip);
 
 	input_dev->open = grip_open;
 	input_dev->close = grip_close;
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index dbc5d92..d4e8073 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -156,7 +156,7 @@
 
 static int guillemot_open(struct input_dev *dev)
 {
-	struct guillemot *guillemot = dev->private;
+	struct guillemot *guillemot = input_get_drvdata(dev);
 
 	gameport_start_polling(guillemot->gameport);
 	return 0;
@@ -168,7 +168,7 @@
 
 static void guillemot_close(struct input_dev *dev)
 {
-	struct guillemot *guillemot = dev->private;
+	struct guillemot *guillemot = input_get_drvdata(dev);
 
 	gameport_stop_polling(guillemot->gameport);
 }
@@ -231,8 +231,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
 	input_dev->id.product = guillemot_type[i].id;
 	input_dev->id.version = (int)data[14] << 8 | data[15];
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = guillemot;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, guillemot);
 
 	input_dev->open = guillemot_open;
 	input_dev->close = guillemot_close;
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 8fb0c19..f2a4381 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -2,7 +2,7 @@
  * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -205,7 +205,7 @@
 	int i;
 
 	if (new->type != FF_SPRING && new->type != FF_FRICTION) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n");
+		warn("bad effect type in need_condition_modifier");
 		return 0;
 	}
 
@@ -227,7 +227,7 @@
 static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect)
 {
 	if (effect->type != FF_CONSTANT) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+		warn("bad effect type in need_envelope_modifier");
 		return 0;
 	}
 
@@ -258,7 +258,7 @@
 		break;
 
 	default:
-		printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+		warn("bad effect type in need_envelope_modifier");
 	}
 
 	return 0;
@@ -271,7 +271,7 @@
 static int need_period_modifier(struct ff_effect *old, struct ff_effect *new)
 {
 	if (new->type != FF_PERIODIC) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n");
+		warn("bad effect type in need_period_modifier");
 		return 0;
 	}
 	return (old->u.periodic.period != new->u.periodic.period
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 3393a37..fb129c4 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -2,7 +2,7 @@
  * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -29,7 +29,7 @@
 
 #include "iforce.h"
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
 MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
 MODULE_LICENSE("GPL");
 
@@ -220,7 +220,7 @@
 		/* Check: no effects should be present in memory */
 		for (i = 0; i < dev->ff->max_effects; i++) {
 			if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) {
-				printk(KERN_WARNING "iforce_release: Device still owns effects\n");
+				warn("iforce_release: Device still owns effects");
 				break;
 			}
 		}
@@ -232,7 +232,7 @@
 	switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
 		case IFORCE_USB:
-			usb_unlink_urb(iforce->irq);
+			usb_kill_urb(iforce->irq);
 
 			/* The device was unplugged before the file
 			 * was released */
@@ -287,13 +287,13 @@
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
 	case IFORCE_USB:
 		input_dev->id.bustype = BUS_USB;
-		input_dev->cdev.dev = &iforce->usbdev->dev;
+		input_dev->dev.parent = &iforce->usbdev->dev;
 		break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
 	case IFORCE_232:
 		input_dev->id.bustype = BUS_RS232;
-		input_dev->cdev.dev = &iforce->serio->dev;
+		input_dev->dev.parent = &iforce->serio->dev;
 		break;
 #endif
 	}
@@ -324,7 +324,7 @@
 			break;
 
 	if (i == 20) { /* 5 seconds */
-		printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
+		err("Timeout waiting for response from device.");
 		error = -ENODEV;
 		goto fail;
 	}
@@ -336,26 +336,26 @@
 	if (!iforce_get_id_packet(iforce, "M"))
 		input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
+		warn("Device does not respond to id packet M");
 
 	if (!iforce_get_id_packet(iforce, "P"))
 		input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
+		warn("Device does not respond to id packet P");
 
 	if (!iforce_get_id_packet(iforce, "B"))
 		iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
+		warn("Device does not respond to id packet B");
 
 	if (!iforce_get_id_packet(iforce, "N"))
 		ff_effects = iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
+		warn("Device does not respond to id packet N");
 
 	/* Check if the device can store more effects than the driver can really handle */
 	if (ff_effects > IFORCE_EFFECTS_MAX) {
-		printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n",
+		warn("Limiting number of effects to %d (device reports %d)",
 		       IFORCE_EFFECTS_MAX, ff_effects);
 		ff_effects = IFORCE_EFFECTS_MAX;
 	}
@@ -457,8 +457,6 @@
 	if (error)
 		goto fail;
 
-	printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
-
 	return 0;
 
  fail:	input_free_device(input_dev);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 808f059..21c4e13 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -2,7 +2,7 @@
  * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -39,10 +39,10 @@
 {
 	int i;
 
-	printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
+	printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd);
 	for (i = 0; i < LO(cmd); i++)
 		printk("%02x ", data[i]);
-	printk(")\n");
+	printk("\n");
 }
 
 /*
@@ -65,8 +65,9 @@
 	head = iforce->xmit.head;
 	tail = iforce->xmit.tail;
 
+
 	if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
-		printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
+		warn("not enough space in xmit buffer to send new packet");
 		spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 		return -1;
 	}
@@ -126,8 +127,6 @@
 {
 	unsigned char data[3];
 
-printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
-
 	data[0] = LO(id);
 	data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
 	data[2] = LO(value);
@@ -151,7 +150,7 @@
 			return 0;
 		}
 	}
-	printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr);
+	warn("unused effect %04x updated !!!", addr);
 	return -1;
 }
 
@@ -162,7 +161,7 @@
 	static int being_used = 0;
 
 	if (being_used)
-		printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used);
+		warn("re-entrant call to iforce_process %d", being_used);
 	being_used++;
 
 #ifdef CONFIG_JOYSTICK_IFORCE_232
@@ -266,7 +265,7 @@
 			return -1;
 		}
 #else
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n");
+		err("iforce_get_id_packet: iforce->bus = USB!");
 #endif
 		break;
 
@@ -284,13 +283,12 @@
 			return -1;
 		}
 #else
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n");
+		err("iforce_get_id_packet: iforce->bus = SERIO!");
 #endif
 		break;
 
 	default:
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n",
-		       iforce->bus);
+		err("iforce_get_id_packet: iforce->bus = %d", iforce->bus);
 		break;
 	}
 
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index ec4be53..7b4bc19 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -2,7 +2,7 @@
  * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 80cdebc..750099d 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -2,7 +2,7 @@
  * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -65,7 +65,7 @@
 	XMIT_INC(iforce->xmit.tail, n);
 
 	if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
-		printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
+		warn("usb_submit_urb failed %d\n", n);
 	}
 
 	/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -110,7 +110,7 @@
 	struct iforce *iforce = urb->context;
 
 	if (urb->status) {
-		printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status);
+		dbg("urb->status %d, exiting", urb->status);
 		return;
 	}
 
@@ -190,10 +190,9 @@
 /* Called by iforce_delete() */
 void iforce_usb_delete(struct iforce* iforce)
 {
-	usb_unlink_urb(iforce->irq);
-/* Is it ok to unlink those ? */
-	usb_unlink_urb(iforce->out);
-	usb_unlink_urb(iforce->ctrl);
+	usb_kill_urb(iforce->irq);
+	usb_kill_urb(iforce->out);
+	usb_kill_urb(iforce->ctrl);
 
 	usb_free_urb(iforce->irq);
 	usb_free_urb(iforce->out);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index ffaeaef..dadcf4f 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -2,7 +2,7 @@
  * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index fec8b3d..1aec1e9 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -185,7 +185,7 @@
 
 static int interact_open(struct input_dev *dev)
 {
-	struct interact *interact = dev->private;
+	struct interact *interact = input_get_drvdata(dev);
 
 	gameport_start_polling(interact->gameport);
 	return 0;
@@ -197,7 +197,7 @@
 
 static void interact_close(struct input_dev *dev)
 {
-	struct interact *interact = dev->private;
+	struct interact *interact = input_get_drvdata(dev);
 
 	gameport_stop_polling(interact->gameport);
 }
@@ -262,7 +262,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
 	input_dev->id.product = interact_type[i].id;
 	input_dev->id.version = 0x0100;
-	input_dev->private = interact;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, interact);
 
 	input_dev->open = interact_open;
 	input_dev->close = interact_close;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 4112789..b35604e 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -168,8 +168,7 @@
 	input_dev->id.vendor = SERIO_MAGELLAN;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = magellan;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index e58b22c..2adf73f 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -509,7 +509,7 @@
 
 static int sw_open(struct input_dev *dev)
 {
-	struct sw *sw = dev->private;
+	struct sw *sw = input_get_drvdata(dev);
 
 	gameport_start_polling(sw->gameport);
 	return 0;
@@ -517,7 +517,7 @@
 
 static void sw_close(struct input_dev *dev)
 {
-	struct sw *sw = dev->private;
+	struct sw *sw = input_get_drvdata(dev);
 
 	gameport_stop_polling(sw->gameport);
 }
@@ -751,8 +751,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
 		input_dev->id.product = sw->type;
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = sw;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, sw);
 
 		input_dev->open = sw_open;
 		input_dev->close = sw_close;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 08bf113..abb7c4c 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -226,8 +226,7 @@
 	input_dev->id.vendor = SERIO_SPACEBALL;
 	input_dev->id.product = id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = spaceball;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c9c7921..c4937f1 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -183,8 +183,7 @@
 	input_dev->id.vendor = SERIO_SPACEORB;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = spaceorb;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index ecb0916..8581ee9 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -154,8 +154,7 @@
 	input_dev->id.vendor = SERIO_STINGER;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = stinger;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index bb23ed2..3b36ee0 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -265,7 +265,7 @@
 
 static int tmdc_open(struct input_dev *dev)
 {
-	struct tmdc *tmdc = dev->private;
+	struct tmdc *tmdc = input_get_drvdata(dev);
 
 	gameport_start_polling(tmdc->gameport);
 	return 0;
@@ -273,7 +273,7 @@
 
 static void tmdc_close(struct input_dev *dev)
 {
-	struct tmdc *tmdc = dev->private;
+	struct tmdc *tmdc = input_get_drvdata(dev);
 
 	gameport_stop_polling(tmdc->gameport);
 }
@@ -326,8 +326,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
 	input_dev->id.product = model->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &tmdc->gameport->dev;
-	input_dev->private = tmdc;
+	input_dev->dev.parent = &tmdc->gameport->dev;
+
+	input_set_drvdata(input_dev, tmdc);
 
 	input_dev->open = tmdc_open;
 	input_dev->close = tmdc_close;
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 037d348..0f2c608 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -122,7 +122,7 @@
 
 static int tgfx_open(struct input_dev *dev)
 {
-	struct tgfx *tgfx = dev->private;
+	struct tgfx *tgfx = input_get_drvdata(dev);
 	int err;
 
 	err = mutex_lock_interruptible(&tgfx->sem);
@@ -141,7 +141,7 @@
 
 static void tgfx_close(struct input_dev *dev)
 {
-	struct tgfx *tgfx = dev->private;
+	struct tgfx *tgfx = input_get_drvdata(dev);
 
 	mutex_lock(&tgfx->sem);
 	if (!--tgfx->used) {
@@ -224,7 +224,8 @@
 		input_dev->id.product = n_buttons[i];
 		input_dev->id.version = 0x0100;
 
-		input_dev->private = tgfx;
+		input_set_drvdata(input_dev, tgfx);
+
 		input_dev->open = tgfx_open;
 		input_dev->close = tgfx_close;
 
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 9cf17d6..c91504e 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -205,11 +205,9 @@
 	input_dev->id.vendor = SERIO_TWIDJOY;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = twidjoy;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
 	input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
 	input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
 
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 29d339a..4e85f72 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -160,8 +160,7 @@
 	input_dev->id.vendor = SERIO_WARRIOR;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = warrior;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f17e9c7..e285172 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -203,6 +203,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called omap-keypad.
 
+config KEYBOARD_PXA27x
+	tristate "PXA27x keyboard support"
+	depends on PXA27x
+	help
+	  Enable support for PXA27x matrix keyboard controller
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pxa27x_keyboard.
+
 config KEYBOARD_AAED2000
 	tristate "AAED-2000 keyboard"
 	depends on MACH_AAED2000
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 586a0fe..fc1d1f2 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
 obj-$(CONFIG_KEYBOARD_OMAP)		+= omap-keypad.o
+obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keyboard.o
 obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
index 65fcb6a..3a37505 100644
--- a/drivers/input/keyboard/aaed2000_kbd.c
+++ b/drivers/input/keyboard/aaed2000_kbd.c
@@ -97,7 +97,7 @@
 
 static int aaedkbd_open(struct input_dev *indev)
 {
-	struct aaedkbd *aaedkbd = indev->private;
+	struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
 	schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
 
@@ -106,7 +106,7 @@
 
 static void aaedkbd_close(struct input_dev *indev)
 {
-	struct aaedkbd *aaedkbd = indev->private;
+	struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
 	cancel_delayed_work(&aaedkbd->workq);
 	flush_scheduled_work();
@@ -141,8 +141,9 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = aaedkbd;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_set_drvdata(input_dev, aaedkbd);
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = aaedkbd->keycode;
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 6638770..be1fe46 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -586,7 +586,7 @@
 
 static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct atkbd *atkbd = dev->private;
+	struct atkbd *atkbd = input_get_drvdata(dev);
 
 	if (!atkbd->write)
 		return -1;
@@ -883,8 +883,9 @@
 	input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
 	input_dev->id.version = atkbd->id;
 	input_dev->event = atkbd_event;
-	input_dev->private = atkbd;
-	input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
+	input_dev->dev.parent = &atkbd->ps2dev.serio->dev;
+
+	input_set_drvdata(input_dev, atkbd);
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
 
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 1016c94..6578bff 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -323,8 +323,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = corgikbd;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
 	input_dev->keycode = corgikbd->keycode;
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ccf6df3..0d2796c 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -63,8 +63,7 @@
 
 	input->name = pdev->name;
 	input->phys = "gpio-keys/input0";
-	input->cdev.dev = &pdev->dev;
-	input->private = pdata;
+	input->dev.parent = &pdev->dev;
 
 	input->id.bustype = BUS_HOST;
 	input->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 7cc9728..cdd254f 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -51,7 +51,7 @@
 
 #define HIL_KBD_SET1_UPBIT 0x01
 #define HIL_KBD_SET1_SHIFT 1
-static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = 
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET1 };
 
 #define HIL_KBD_SET2_UPBIT 0x01
@@ -60,10 +60,10 @@
 
 #define HIL_KBD_SET3_UPBIT 0x80
 #define HIL_KBD_SET3_SHIFT 0
-static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET3 };
 
-static char hil_language[][16] = { HIL_LOCALE_MAP };
+static const char hil_language[][16] = { HIL_LOCALE_MAP };
 
 struct hil_kbd {
 	struct input_dev *dev;
@@ -94,10 +94,12 @@
 	idx = kbd->idx4/4;
 	p = data[idx - 1];
 
-	if ((p & ~HIL_CMDCT_POL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-	if ((p & ~HIL_CMDCT_RPL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+	if ((p & ~HIL_CMDCT_POL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+		goto report;
+	if ((p & ~HIL_CMDCT_RPL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+		goto report;
 
 	/* Not a poll response.  See if we are loading config records. */
 	switch (p & HIL_PKT_DATA_MASK) {
@@ -107,27 +109,32 @@
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->idd[i] = 0;
 		break;
+
 	case HIL_CMD_RSC:
 		for (i = 0; i < idx; i++)
 			kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->rsc[i] = 0;
 		break;
+
 	case HIL_CMD_EXD:
 		for (i = 0; i < idx; i++)
 			kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->exd[i] = 0;
 		break;
+
 	case HIL_CMD_RNM:
 		for (i = 0; i < idx; i++)
 			kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
 			kbd->rnm[i] = '\0';
 		break;
+
 	default:
 		/* These occur when device isn't present */
-		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+			break;
 		/* Anything else we'd like to know about. */
 		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
 		break;
@@ -139,16 +146,19 @@
 	switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
 	case HIL_POL_CHARTYPE_NONE:
 		break;
+
 	case HIL_POL_CHARTYPE_ASCII:
 		while (cnt < idx - 1)
 			input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
 		break;
+
 	case HIL_POL_CHARTYPE_RSVD1:
 	case HIL_POL_CHARTYPE_RSVD2:
 	case HIL_POL_CHARTYPE_BINARY:
 		while (cnt < idx - 1)
 			input_report_key(dev, kbd->data[cnt++], 1);
 		break;
+
 	case HIL_POL_CHARTYPE_SET1:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -161,6 +171,7 @@
 				input_report_key(dev, key, !up);
 		}
 		break;
+
 	case HIL_POL_CHARTYPE_SET2:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -173,6 +184,7 @@
 				input_report_key(dev, key, !up);
 		}
 		break;
+
 	case HIL_POL_CHARTYPE_SET3:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -191,42 +203,43 @@
 	up(&kbd->sem);
 }
 
-static void hil_kbd_process_err(struct hil_kbd *kbd) {
+static void hil_kbd_process_err(struct hil_kbd *kbd)
+{
 	printk(KERN_WARNING PREFIX "errored HIL packet\n");
 	kbd->idx4 = 0;
 	up(&kbd->sem);
 }
 
-static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
-	      unsigned char data, unsigned int flags)
+static irqreturn_t hil_kbd_interrupt(struct serio *serio,
+				unsigned char data, unsigned int flags)
 {
 	struct hil_kbd *kbd;
 	hil_packet packet;
 	int idx;
 
 	kbd = serio_get_drvdata(serio);
-	if (kbd == NULL) {
-		BUG();
-		return IRQ_HANDLED;
-	}
+	BUG_ON(kbd == NULL);
 
 	if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
 		hil_kbd_process_err(kbd);
 		return IRQ_HANDLED;
 	}
 	idx = kbd->idx4/4;
-	if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+	if (!(kbd->idx4 % 4))
+		kbd->data[idx] = 0;
 	packet = kbd->data[idx];
 	packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
 	kbd->data[idx] = packet;
 
 	/* Records of N 4-byte hil_packets must terminate with a command. */
-	if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+	if ((++(kbd->idx4)) % 4)
+		return IRQ_HANDLED;
 	if ((packet & 0xffff0000) != HIL_ERR_INT) {
 		hil_kbd_process_err(kbd);
 		return IRQ_HANDLED;
 	}
-	if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+	if (packet & HIL_PKT_CMD)
+		hil_kbd_process_record(kbd);
 	return IRQ_HANDLED;
 }
 
@@ -235,10 +248,7 @@
 	struct hil_kbd *kbd;
 
 	kbd = serio_get_drvdata(serio);
-	if (kbd == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(kbd == NULL);
 
 	serio_close(serio);
 	input_unregister_device(kbd->dev);
@@ -259,42 +269,40 @@
 	if (!kbd->dev)
 		goto bail0;
 
-	kbd->dev->private = kbd;
-
 	if (serio_open(serio, drv))
 		goto bail1;
 
 	serio_set_drvdata(serio, kbd);
 	kbd->serio = serio;
 
-	init_MUTEX_LOCKED(&(kbd->sem));
+	init_MUTEX_LOCKED(&kbd->sem);
 
 	/* Get device info.  MLC driver supplies devid/status/etc. */
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_IDD);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RSC);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RNM);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EXD);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
-	up(&(kbd->sem));
+	up(&kbd->sem);
 
 	did = kbd->idd[0];
 	idd = kbd->idd + 1;
@@ -310,12 +318,11 @@
 		goto bail2;
 	}
 
-	if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+	if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
 		printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
 		goto bail2;
 	}
 
-
 	kbd->dev->evbit[0]	= BIT(EV_KEY) | BIT(EV_REP);
 	kbd->dev->ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
 	kbd->dev->keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
@@ -328,7 +335,7 @@
 	kbd->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	kbd->dev->id.product	= 0x0001; /* TODO: get from kbd->rsc */
 	kbd->dev->id.version	= 0x0100; /* TODO: get from kbd->rsc */
-	kbd->dev->cdev.dev	= &serio->dev;
+	kbd->dev->dev.parent	= &serio->dev;
 
 	for (i = 0; i < 128; i++) {
 		set_bit(hil_kbd_set1[i], kbd->dev->keybit);
@@ -344,8 +351,8 @@
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
-	down(&(kbd->sem));
-	up(&(kbd->sem));
+	down(&kbd->sem);
+	up(&kbd->sem);
 
 	return 0;
  bail2:
@@ -368,26 +375,26 @@
 	{ 0 }
 };
 
-struct serio_driver hil_kbd_serio_drv = {
+static struct serio_driver hil_kbd_serio_drv = {
 	.driver		= {
 		.name	= "hil_kbd",
 	},
 	.description	= "HP HIL keyboard driver",
 	.id_table	= hil_kbd_ids,
-	.connect 	= hil_kbd_connect,
-	.disconnect 	= hil_kbd_disconnect,
-	.interrupt 	= hil_kbd_interrupt
+	.connect	= hil_kbd_connect,
+	.disconnect	= hil_kbd_disconnect,
+	.interrupt	= hil_kbd_interrupt
 };
 
 static int __init hil_kbd_init(void)
 {
 	return serio_register_driver(&hil_kbd_serio_drv);
 }
-                
+
 static void __exit hil_kbd_exit(void)
 {
 	serio_unregister_driver(&hil_kbd_serio_drv);
 }
-                        
+
 module_init(hil_kbd_init);
 module_exit(hil_kbd_exit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 4de4dc2..73b85cb 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
  *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
- *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
+ *  Copyright (C) 1999-2007 Helge Deller <deller@gmx.de>
  *
  *  Very basic HP Human Interface Loop (HIL) driver.
  *  This driver handles the keyboard on HP300 (m68k) and on some
@@ -89,7 +89,7 @@
 #define	HIL_READKBDSADR		0xF9
 #define	HIL_WRITEKBDSADR	0xE9
 
-static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET1 };
 
 /* HIL structure */
@@ -211,10 +211,10 @@
 		return -ENODEV; /* already initialized */
 	}
 
+	spin_lock_init(&hil_dev.lock);
 	hil_dev.dev = input_allocate_device();
 	if (!hil_dev.dev)
 		return -ENOMEM;
-	hil_dev.dev->private = &hil_dev;
 
 #if defined(CONFIG_HP300)
 	if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 3d4d0a0..1b08f4e 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -515,7 +515,7 @@
 lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
 		int value)
 {
-	struct lkkbd *lk = dev->private;
+	struct lkkbd *lk = input_get_drvdata (dev);
 	unsigned char leds_on = 0;
 	unsigned char leds_off = 0;
 
@@ -666,9 +666,10 @@
 	input_dev->id.vendor = SERIO_LKKBD;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->event = lkkbd_event;
-	input_dev->private = lk;
+
+	input_set_drvdata (input_dev, lk);
 
 	set_bit (EV_KEY, input_dev->evbit);
 	set_bit (EV_LED, input_dev->evbit);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 2ade518..7a41b27 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -231,7 +231,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->private = locomokbd;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = locomokbd->keycode;
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index aa29b50..b97a41e 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -104,8 +104,7 @@
 	input_dev->id.vendor = SERIO_NEWTON;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = nkbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = nkbd->keycode;
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 5680a6d..3a22863 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -370,8 +370,7 @@
 		set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
 	input_dev->name = "omap-keypad";
 	input_dev->phys = "omap-keypad/input0";
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = omap_kp;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
new file mode 100644
index 0000000..06eaf76
--- /dev/null
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -0,0 +1,258 @@
+/*
+ * linux/drivers/input/keyboard/pxa27x_keyboard.c
+ *
+ * Driver for the pxa27x matrix keyboard controller.
+ *
+ * Created:	Feb 22, 2007
+ * Author:	Rodolfo Giometti <giometti@linux.it>
+ *
+ * Based on a previous implementations by Kevin O'Connor
+ * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
+ * on some suggestions by Nicolas Pitre <nico@cam.org>.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/pxa27x_keyboard.h>
+
+#define DRIVER_NAME		"pxa27x-keyboard"
+
+#define KPASMKP(col)		(col/2 == 0 ? KPASMKP0 : \
+				 col/2 == 1 ? KPASMKP1 : \
+				 col/2 == 2 ? KPASMKP2 : KPASMKP3)
+#define KPASMKPx_MKC(row, col)	(1 << (row + 16 * (col % 2)))
+
+static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+	unsigned long kpc = KPC;
+	int p, row, col, rel;
+
+	if (kpc & KPC_DI) {
+		unsigned long kpdk = KPDK;
+
+		if (!(kpdk & KPDK_DKP)) {
+			/* better luck next time */
+		} else if (kpc & KPC_REE0) {
+			unsigned long kprec = KPREC;
+			KPREC = 0x7f;
+
+			if (kprec & KPREC_OF0)
+				rel = (kprec & 0xff) + 0x7f;
+			else if (kprec & KPREC_UF0)
+				rel = (kprec & 0xff) - 0x7f - 0xff;
+			else
+				rel = (kprec & 0xff) - 0x7f;
+
+			if (rel) {
+				input_report_rel(input_dev, REL_WHEEL, rel);
+				input_sync(input_dev);
+			}
+		}
+	}
+
+	if (kpc & KPC_MI) {
+		/* report the status of every button */
+		for (row = 0; row < pdata->nr_rows; row++) {
+			for (col = 0; col < pdata->nr_cols; col++) {
+				p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+					1 : 0;
+				pr_debug("keycode %x - pressed %x\n",
+						pdata->keycodes[row][col], p);
+				input_report_key(input_dev,
+						pdata->keycodes[row][col], p);
+			}
+		}
+		input_sync(input_dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int pxakbd_open(struct input_dev *dev)
+{
+	/* Set keypad control register */
+	KPC |= (KPC_ASACT |
+		KPC_MS_ALL |
+		(2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+		KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+
+	KPC &= ~KPC_AS;         /* disable automatic scan */
+	KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
+
+	/* Set rotary count to mid-point value */
+	KPREC = 0x7F;
+
+	/* Enable unit clock */
+	pxa_set_cken(CKEN19_KEYPAD, 1);
+
+	return 0;
+}
+
+static void pxakbd_close(struct input_dev *dev)
+{
+	/* Disable clock unit */
+	pxa_set_cken(CKEN19_KEYPAD, 0);
+}
+
+#ifdef CONFIG_PM
+static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+
+	/* Save controller status */
+	pdata->reg_kpc = KPC;
+	pdata->reg_kprec = KPREC;
+
+	return 0;
+}
+
+static int pxakbd_resume(struct platform_device *pdev)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users) {
+		/* Restore controller status */
+		KPC = pdata->reg_kpc;
+		KPREC = pdata->reg_kprec;
+
+		/* Enable unit clock */
+		pxa_set_cken(CKEN19_KEYPAD, 1);
+	}
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+#else
+#define pxakbd_suspend	NULL
+#define pxakbd_resume	NULL
+#endif
+
+static int __devinit pxakbd_probe(struct platform_device *pdev)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev;
+	int i, row, col, error;
+
+	/* Create and register the input driver. */
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		printk(KERN_ERR "Cannot request keypad device\n");
+		return -ENOMEM;
+	}
+
+	input_dev->name = DRIVER_NAME;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->open = pxakbd_open;
+	input_dev->close = pxakbd_close;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+	input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+	for (row = 0; row < pdata->nr_rows; row++) {
+		for (col = 0; col < pdata->nr_cols; col++) {
+			int code = pdata->keycodes[row][col];
+			if (code > 0)
+				set_bit(code, input_dev->keybit);
+		}
+	}
+
+	error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+			    DRIVER_NAME, pdev);
+	if (error) {
+		printk(KERN_ERR "Cannot request keypad IRQ\n");
+		pxa_set_cken(CKEN19_KEYPAD, 0);
+		goto err_free_dev;
+	}
+
+	platform_set_drvdata(pdev, input_dev);
+
+	/* Register the input device */
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_irq;
+
+	/* Setup GPIOs. */
+	for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+		pxa_gpio_mode(pdata->gpio_modes[i]);
+
+	/*
+	 * Store rows/cols info into keyboard registers.
+	 */
+
+	KPC |= (pdata->nr_rows - 1) << 26;
+	KPC |= (pdata->nr_cols - 1) << 23;
+
+	for (col = 0; col < pdata->nr_cols; col++)
+		KPC |= KPC_MS0 << col;
+
+	return 0;
+
+ err_free_irq:
+	platform_set_drvdata(pdev, NULL);
+	free_irq(IRQ_KEYPAD, pdev);
+ err_free_dev:
+	input_free_device(input_dev);
+	return error;
+}
+
+static int __devexit pxakbd_remove(struct platform_device *pdev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+	input_unregister_device(input_dev);
+	free_irq(IRQ_KEYPAD, pdev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver pxakbd_driver = {
+	.probe		= pxakbd_probe,
+	.remove		= __devexit_p(pxakbd_remove),
+	.suspend	= pxakbd_suspend,
+	.resume		= pxakbd_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init pxakbd_init(void)
+{
+	return platform_driver_register(&pxakbd_driver);
+}
+
+static void __exit pxakbd_exit(void)
+{
+	platform_driver_unregister(&pxakbd_driver);
+}
+
+module_init(pxakbd_init);
+module_exit(pxakbd_exit);
+
+MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 8a2166c..41b8038 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -372,10 +372,9 @@
 
 	spitzkbd->input = input_dev;
 
-	input_dev->private = spitzkbd;
 	input_dev->name = "Spitz Keyboard";
 	input_dev->phys = spitzkbd->phys;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index f7b5c5b..b44b068 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -108,8 +108,7 @@
 	input_dev->id.vendor = SERIO_STOWAWAY;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = skbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = skbd->keycode;
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index cc02383..1d4e396 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -146,7 +146,7 @@
 
 static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sunkbd *sunkbd = dev->private;
+	struct sunkbd *sunkbd = input_get_drvdata(dev);
 
 	switch (type) {
 
@@ -271,8 +271,10 @@
 	input_dev->id.vendor  = SERIO_SUNKBD;
 	input_dev->id.product = sunkbd->type;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = sunkbd;
+	input_dev->dev.parent = &serio->dev;
+
+	input_set_drvdata(input_dev, sunkbd);
+
 	input_dev->event = sunkbd_event;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index a820934..f3a56eb 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -108,8 +108,7 @@
 	input_dev->id.vendor  = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = xtkbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = xtkbd->keycode;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 41b4258..1d0d3e7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -40,6 +40,16 @@
 	tristate "M68k Beeper support"
 	depends on M68K
 
+config INPUT_COBALT_BTNS
+	tristate "Cobalt button interface"
+	depends on MIPS_COBALT
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you want to support MIPS Cobalt button interface.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cobalt_btns.
+
 config INPUT_WISTRON_BTNS
 	tristate "x86 Wistron laptop button interface"
 	depends on X86 && !X86_64
@@ -81,8 +91,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
+config INPUT_POLLDEV
+	tristate "Polled input device skeleton"
+	help
+	  Say Y here if you are using a driver for an input
+	  device that periodically polls hardware state. This
+	  option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called input-polldev.
+
 config HP_SDC_RTC
-	tristate "HP SDC Real Time Clock"       
+	tristate "HP SDC Real Time Clock"
 	depends on GSC || HP300
 	select HP_SDC
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index e0a8d58..21e3cca 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,10 +4,12 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_INPUT_POLLDEV)		+= input-polldev.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
 obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
new file mode 100644
index 0000000..064b079
--- /dev/null
+++ b/drivers/input/misc/cobalt_btns.c
@@ -0,0 +1,172 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define BUTTONS_POLL_INTERVAL	30	/* msec */
+#define BUTTONS_COUNT_THRESHOLD	3
+#define BUTTONS_STATUS_MASK	0xfe000000
+
+struct buttons_dev {
+	struct input_polled_dev *poll_dev;
+	void __iomem *reg;
+};
+
+struct buttons_map {
+	uint32_t mask;
+	int keycode;
+	int count;
+};
+
+static struct buttons_map buttons_map[] = {
+	{ 0x02000000, KEY_RESTART, },
+	{ 0x04000000, KEY_LEFT, },
+	{ 0x08000000, KEY_UP, },
+	{ 0x10000000, KEY_DOWN, },
+	{ 0x20000000, KEY_RIGHT, },
+	{ 0x40000000, KEY_ENTER, },
+	{ 0x80000000, KEY_SELECT, },
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+	struct buttons_map *button = buttons_map;
+	struct buttons_dev *bdev = dev->private;
+	struct input_dev *input = dev->input;
+	uint32_t status;
+	int i;
+
+	status = readl(bdev->reg);
+	status = ~status & BUTTONS_STATUS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		if (status & button->mask) {
+			button->count++;
+		} else {
+			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+				input_report_key(input, button->keycode, 0);
+				input_sync(input);
+			}
+			button->count = 0;
+		}
+
+		if (button->count == BUTTONS_COUNT_THRESHOLD) {
+			input_report_key(input, button->keycode, 1);
+			input_sync(input);
+		}
+
+		button++;
+	}
+}
+
+static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	struct resource *res;
+	int error, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	poll_dev = input_allocate_polled_device();
+	if (!bdev || !poll_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	poll_dev->private = bdev;
+	poll_dev->poll = handle_buttons;
+	poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+	input = poll_dev->input;
+	input->name = "Cobalt buttons";
+	input->phys = "cobalt/input0";
+	input->id.bustype = BUS_HOST;
+	input->cdev.dev = &pdev->dev;
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		set_bit(buttons_map[i].keycode, input->keybit);
+		buttons_map[i].count = 0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		error = -EBUSY;
+		goto err_free_mem;
+	}
+
+	bdev->poll_dev = poll_dev;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	error = input_register_polled_device(poll_dev);
+	if (error)
+		goto err_iounmap;
+
+	return 0;
+
+ err_iounmap:
+	iounmap(bdev->reg);
+ err_free_mem:
+	input_free_polled_device(poll_dev);
+	kfree(bdev);
+	dev_set_drvdata(&pdev->dev, NULL);
+	return error;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	input_unregister_polled_device(bdev->poll_dev);
+	input_free_polled_device(bdev->poll_dev);
+	iounmap(bdev->reg);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+	.probe	= cobalt_buttons_probe,
+	.remove	= __devexit_p(cobalt_buttons_remove),
+	.driver	= {
+		.name	= "Cobalt buttons",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init cobalt_buttons_init(void)
+{
+	return platform_driver_register(&cobalt_buttons_driver);
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);
diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/misc/input-polldev.c
new file mode 100644
index 0000000..1b2b9c9
--- /dev/null
+++ b/drivers/input/misc/input-polldev.c
@@ -0,0 +1,171 @@
+/*
+ * Generic implementation of a polled input device
+
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * 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/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+
+static DEFINE_MUTEX(polldev_mutex);
+static int polldev_users;
+static struct workqueue_struct *polldev_wq;
+
+static int input_polldev_start_workqueue(void)
+{
+	int retval;
+
+	retval = mutex_lock_interruptible(&polldev_mutex);
+	if (retval)
+		return retval;
+
+	if (!polldev_users) {
+		polldev_wq = create_singlethread_workqueue("ipolldevd");
+		if (!polldev_wq) {
+			printk(KERN_ERR "input-polldev: failed to create "
+				"ipolldevd workqueue\n");
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	polldev_users++;
+
+ out:
+	mutex_unlock(&polldev_mutex);
+	return retval;
+}
+
+static void input_polldev_stop_workqueue(void)
+{
+	mutex_lock(&polldev_mutex);
+
+	if (!--polldev_users)
+		destroy_workqueue(polldev_wq);
+
+	mutex_unlock(&polldev_mutex);
+}
+
+static void input_polled_device_work(struct work_struct *work)
+{
+	struct input_polled_dev *dev =
+		container_of(work, struct input_polled_dev, work.work);
+
+	dev->poll(dev);
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+}
+
+static int input_open_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+	int error;
+
+	error = input_polldev_start_workqueue();
+	if (error)
+		return error;
+
+	if (dev->flush)
+		dev->flush(dev);
+
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+
+	return 0;
+}
+
+static void input_close_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+
+	cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
+	input_polldev_stop_workqueue();
+}
+
+/**
+ * input_allocate_polled_device - allocated memory polled device
+ *
+ * The function allocates memory for a polled device and also
+ * for an input device associated with this polled device.
+ */
+struct input_polled_dev *input_allocate_polled_device(void)
+{
+	struct input_polled_dev *dev;
+
+	dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->input = input_allocate_device();
+	if (!dev->input) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+EXPORT_SYMBOL(input_allocate_polled_device);
+
+/**
+ * input_free_polled_device - free memory allocated for polled device
+ * @dev: device to free
+ *
+ * The function frees memory allocated for polling device and drops
+ * reference to the associated input device (if present).
+ */
+void input_free_polled_device(struct input_polled_dev *dev)
+{
+	if (dev) {
+		input_free_device(dev->input);
+		kfree(dev);
+	}
+}
+EXPORT_SYMBOL(input_free_polled_device);
+
+/**
+ * input_register_polled_device - register polled device
+ * @dev: device to register
+ *
+ * The function registers previously initialized polled input device
+ * with input layer. The device should be allocated with call to
+ * input_allocate_polled_device(). Callers should also set up poll()
+ * method and set up capabilities (id, name, phys, bits) of the
+ * corresponing input_dev structure.
+ */
+int input_register_polled_device(struct input_polled_dev *dev)
+{
+	struct input_dev *input = dev->input;
+
+	INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+	if (!dev->poll_interval)
+		dev->poll_interval = 500;
+	input->private = dev;
+	input->open = input_open_polled_device;
+	input->close = input_close_polled_device;
+
+	return input_register_device(input);
+}
+EXPORT_SYMBOL(input_register_polled_device);
+
+/**
+ * input_unregister_polled_device - unregister polled device
+ * @dev: device to unregister
+ *
+ * The function unregisters previously registered polled input
+ * device from input layer. Polling is stopped and device is
+ * ready to be freed with call to input_free_polled_device().
+ * Callers should not attempt to access dev->input pointer
+ * after calling this function.
+ */
+void input_unregister_polled_device(struct input_polled_dev *dev)
+{
+	input_unregister_device(dev->input);
+	dev->input = NULL;
+}
+EXPORT_SYMBOL(input_unregister_polled_device);
+
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 105c6fc..3d4b619 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -51,7 +51,7 @@
 
 static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	unsigned int pin = (unsigned int) dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 	unsigned int count = 0;
 
 	if (type != EV_SND)
@@ -99,14 +99,15 @@
 	if (!input_dev)
 		return -ENOMEM;
 
-	input_dev->private = (void *) dev->id;
+	input_set_drvdata(input_dev, (void *) dev->id);
+
 	input_dev->name = "ixp4xx beeper",
 	input_dev->phys = "ixp4xx/gpio";
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor  = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
@@ -136,7 +137,7 @@
 static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
-	unsigned int pin = (unsigned int) input_dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
 	input_unregister_device(input_dev);
 	platform_set_drvdata(dev, NULL);
@@ -153,7 +154,7 @@
 static void ixp4xx_spkr_shutdown(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
-	unsigned int pin = (unsigned int) input_dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
 	/* turn off the speaker */
 	disable_irq(IRQ_IXP4XX_TIMER2);
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 8d6c383..e9f26e7 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -63,7 +63,7 @@
 	input_dev->id.vendor  = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index afd3221..31989dc 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -78,7 +78,7 @@
 	pcspkr_dev->id.vendor = 0x001f;
 	pcspkr_dev->id.product = 0x0001;
 	pcspkr_dev->id.version = 0x0100;
-	pcspkr_dev->cdev.dev = &dev->dev;
+	pcspkr_dev->dev.parent = &dev->dev;
 
 	pcspkr_dev->evbit[0] = BIT(EV_SND);
 	pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 106c94f..e36ec1d 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -28,7 +28,7 @@
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -61,7 +61,7 @@
 
 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -113,7 +113,7 @@
 	input_dev->id.vendor = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = dev;
+	input_dev->dev.parent = dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 4255623..031467e 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -41,9 +41,7 @@
 
 static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct uinput_device	*udev;
-
-	udev = dev->private;
+	struct uinput_device	*udev = input_get_drvdata(dev);
 
 	udev->buff[udev->head].type = type;
 	udev->buff[udev->head].code = code;
@@ -136,7 +134,7 @@
 	request.u.upload.effect = effect;
 	request.u.upload.old = old;
 
-	retval = uinput_request_reserve_slot(dev->private, &request);
+	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
 	if (!retval)
 		retval = uinput_request_submit(dev, &request);
 
@@ -156,7 +154,7 @@
 	request.code = UI_FF_ERASE;
 	request.u.effect_id = effect_id;
 
-	retval = uinput_request_reserve_slot(dev->private, &request);
+	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
 	if (!retval)
 		retval = uinput_request_submit(dev, &request);
 
@@ -274,7 +272,7 @@
 		return -ENOMEM;
 
 	udev->dev->event = uinput_dev_event;
-	udev->dev->private = udev;
+	input_set_drvdata(udev->dev, udev);
 
 	return 0;
 }
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index e1183ae..961aad7 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -50,7 +50,7 @@
 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
 MODULE_DESCRIPTION("Wistron laptop button driver");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
+MODULE_VERSION("0.2");
 
 static int force; /* = 0; */
 module_param(force, bool, 0);
@@ -58,7 +58,7 @@
 
 static char *keymap_name; /* = NULL; */
 module_param_named(keymap, keymap_name, charp, 0);
-MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected");
+MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
 
 static struct platform_device *wistron_device;
 
@@ -233,10 +233,20 @@
 struct key_entry {
 	char type;		/* See KE_* below */
 	u8 code;
-	unsigned keycode;	/* For KE_KEY */
+	union {
+		u16 keycode;		/* For KE_KEY */
+		struct {		/* For KE_SW */
+			u8 code;
+			u8 value;
+		} sw;
+	};
 };
 
-enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
+enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
+
+#define FE_MAIL_LED 0x01
+#define FE_WIFI_LED 0x02
+#define FE_UNTESTED 0x80
 
 static const struct key_entry *keymap; /* = NULL; Current key map */
 static int have_wifi;
@@ -256,93 +266,341 @@
 	return 1;
 }
 
-static struct key_entry keymap_empty[] = {
+static struct key_entry keymap_empty[] __initdata = {
 	{ KE_END, 0 }
 };
 
-static struct key_entry keymap_fs_amilo_pro_v2000[] = {
-	{ KE_KEY,  0x01, KEY_HELP },
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
+	{ KE_KEY,  0x01, {KEY_HELP} },
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 }
 };
 
-static struct key_entry keymap_fujitsu_n3510[] = {
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x71, KEY_STOPCD },
-	{ KE_KEY, 0x72, KEY_PLAYPAUSE },
-	{ KE_KEY, 0x74, KEY_REWIND },
-	{ KE_KEY, 0x78, KEY_FORWARD },
+static struct key_entry keymap_fujitsu_n3510[] __initdata = {
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x71, {KEY_STOPCD} },
+	{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x74, {KEY_REWIND} },
+	{ KE_KEY, 0x78, {KEY_FORWARD} },
 	{ KE_END, 0 }
 };
 
-static struct key_entry keymap_wistron_ms2111[] = {
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_KEY,  0x13, KEY_PROG3 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_wistron_ms2111[] __initdata = {
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_KEY,  0x13, {KEY_PROG3} },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
+	{ KE_END, FE_MAIL_LED }
+};
+
+static struct key_entry keymap_wistron_md40100[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_ms2141[] __initdata = {
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x22, {KEY_REWIND} },
+	{ KE_KEY,  0x23, {KEY_FORWARD} },
+	{ KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY,  0x25, {KEY_STOPCD} },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 }
 };
 
-static struct key_entry keymap_wistron_ms2141[] = {
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x22, KEY_REWIND },
-	{ KE_KEY,  0x23, KEY_FORWARD },
-	{ KE_KEY,  0x24, KEY_PLAYPAUSE },
-	{ KE_KEY,  0x25, KEY_STOPCD },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
-	{ KE_END,  0 }
+static struct key_entry keymap_acer_aspire_1500[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_UNTESTED }
 };
 
-static struct key_entry keymap_acer_aspire_1500[] = {
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_BLUETOOTH, 0x44, 0 },
-	{ KE_END, 0 }
+static struct key_entry keymap_acer_aspire_1600[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_acer_travelmate_240[] = {
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_BLUETOOTH, 0x44, 0 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_END, 0 }
+/* 3020 has been tested */
+static struct key_entry keymap_acer_aspire_5020[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_aopen_1559as[] = {
-	{ KE_KEY,  0x01, KEY_HELP },
-	{ KE_KEY,  0x06, KEY_PROG3 },
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x6d, {KEY_POWER} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_110[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+	{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_300[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_380[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+/* unusual map */
+static struct key_entry keymap_acer_travelmate_220[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_MAIL} },
+	{ KE_KEY, 0x12, {KEY_WWW} },
+	{ KE_KEY, 0x13, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_PROG1} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_230[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_240[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_350[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_MAIL} },
+	{ KE_KEY, 0x14, {KEY_PROG3} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_360[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_MAIL} },
+	{ KE_KEY, 0x14, {KEY_PROG3} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
+};
+
+/* Wifi subsystem only activates the led. Therefore we need to pass
+ * wifi event as a normal key, then userspace can really change the wifi state.
+ * TODO we need to export led state to userspace (wifi and mail) */
+static struct key_entry keymap_acer_travelmate_610[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x14, {KEY_MAIL} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED }
+};
+
+static struct key_entry keymap_acer_travelmate_630[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_aopen_1559as[] __initdata = {
+	{ KE_KEY,  0x01, {KEY_HELP} },
+	{ KE_KEY,  0x06, {KEY_PROG3} },
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 },
 };
 
-static struct key_entry keymap_fs_amilo_d88x0[] = {
-	{ KE_KEY, 0x01, KEY_HELP },
-	{ KE_KEY, 0x08, KEY_MUTE },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_KEY, 0x13, KEY_PROG3 },
+static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md2900[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md96500[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x22, {KEY_REWIND} },
+	{ KE_KEY, 0x23, {KEY_FORWARD} },
+	{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x25, {KEY_STOPCD} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_generic[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x14, {KEY_MAIL} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x22, {KEY_REWIND} },
+	{ KE_KEY, 0x23, {KEY_FORWARD} },
+	{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x25, {KEY_STOPCD} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+	{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_KEY, 0x6d, {KEY_POWER} },
+	{ KE_KEY, 0x71, {KEY_STOPCD} },
+	{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x74, {KEY_REWIND} },
+	{ KE_KEY, 0x78, {KEY_FORWARD} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
 	{ KE_END, 0 }
 };
 
@@ -390,6 +648,133 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer Aspire 1600",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
+		},
+		.driver_data = keymap_acer_aspire_1600
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 3020",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 5020",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 2100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 2410",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
+		},
+		.driver_data = keymap_acer_travelmate_2410
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
+		},
+		.driver_data = keymap_acer_travelmate_300
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
+		},
+		.driver_data = keymap_acer_travelmate_300
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C110",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
+		},
+		.driver_data = keymap_acer_travelmate_110
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 380",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
+		},
+		.driver_data = keymap_acer_travelmate_380
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 370",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
+		},
+		.driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 220",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
+		},
+		.driver_data = keymap_acer_travelmate_220
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 260",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
+		},
+		.driver_data = keymap_acer_travelmate_220
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 230",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
+			/* acerhk looks for "TravelMate F4..." ?! */
+		},
+		.driver_data = keymap_acer_travelmate_230
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 280",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
+		},
+		.driver_data = keymap_acer_travelmate_230
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Acer TravelMate 240",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -399,6 +784,15 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer TravelMate 250",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
+		},
+		.driver_data = keymap_acer_travelmate_240
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Acer TravelMate 2424NWXCi",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -408,6 +802,51 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer TravelMate 350",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
+		},
+		.driver_data = keymap_acer_travelmate_350
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+		},
+		.driver_data = keymap_acer_travelmate_360
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 610",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
+		},
+		.driver_data = keymap_acer_travelmate_610
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 620",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
+		},
+		.driver_data = keymap_acer_travelmate_630
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 630",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
+		},
+		.driver_data = keymap_acer_travelmate_630
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "AOpen 1559AS",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
@@ -426,6 +865,51 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Medion MD 40100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
+		},
+		.driver_data = keymap_wistron_md40100
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 2900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
+		},
+		.driver_data = keymap_wistron_md2900
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 96500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
+		},
+		.driver_data = keymap_wistron_md96500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 95400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
+		},
+		.driver_data = keymap_wistron_md96500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Fujitsu Siemens Amilo D7820",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
+			DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
+		},
+		.driver_data = keymap_fs_amilo_d88x0
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Fujitsu Siemens Amilo D88x0",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -436,17 +920,39 @@
 	{ NULL, }
 };
 
+/* Copy the good keymap, as the original ones are free'd */
+static int __init copy_keymap(void)
+{
+	const struct key_entry *key;
+	struct key_entry *new_keymap;
+	unsigned int length = 1;
+
+	for (key = keymap; key->type != KE_END; key++)
+		length++;
+
+	new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL);
+	if (!new_keymap)
+		return -ENOMEM;
+
+	memcpy(new_keymap, keymap, length * sizeof(struct key_entry));
+	keymap = new_keymap;
+
+	return 0;
+}
+
 static int __init select_keymap(void)
 {
+	dmi_check_system(dmi_ids);
 	if (keymap_name != NULL) {
 		if (strcmp (keymap_name, "1557/MS2141") == 0)
 			keymap = keymap_wistron_ms2141;
+		else if (strcmp (keymap_name, "generic") == 0)
+			keymap = keymap_wistron_generic;
 		else {
 			printk(KERN_ERR "wistron_btns: Keymap unknown\n");
 			return -EINVAL;
 		}
 	}
-	dmi_check_system(dmi_ids);
 	if (keymap == NULL) {
 		if (!force) {
 			printk(KERN_ERR "wistron_btns: System unknown\n");
@@ -454,7 +960,8 @@
 		}
 		keymap = keymap_empty;
 	}
-	return 0;
+
+	return copy_keymap();
 }
 
  /* Input layer interface */
@@ -476,12 +983,28 @@
 	input_dev->cdev.dev = &wistron_device->dev;
 
 	for (key = keymap; key->type != KE_END; key++) {
-		if (key->type == KE_KEY) {
-			input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
-			set_bit(key->keycode, input_dev->keybit);
+		switch (key->type) {
+			case KE_KEY:
+				set_bit(EV_KEY, input_dev->evbit);
+				set_bit(key->keycode, input_dev->keybit);
+				break;
+
+			case KE_SW:
+				set_bit(EV_SW, input_dev->evbit);
+				set_bit(key->sw.code, input_dev->swbit);
+				break;
+
+			default:
+				;
 		}
 	}
 
+	/* reads information flags on KE_END */
+	if (key->code & FE_UNTESTED)
+		printk(KERN_WARNING "Untested laptop multimedia keys, "
+			"please report success or failure to eric.piel"
+			"@tremplin-utc.net\n");
+
 	error = input_register_device(input_dev);
 	if (error) {
 		input_free_device(input_dev);
@@ -499,6 +1022,12 @@
 	input_sync(input_dev);
 }
 
+static void report_switch(unsigned code, int value)
+{
+	input_report_switch(input_dev, code, value);
+	input_sync(input_dev);
+}
+
  /* Driver core */
 
 static int wifi_enabled;
@@ -519,6 +1048,10 @@
 				report_key(key->keycode);
 				break;
 
+			case KE_SW:
+				report_switch(key->sw.code, key->sw.value);
+				break;
+
 			case KE_WIFI:
 				if (have_wifi) {
 					wifi_enabled = !wifi_enabled;
@@ -534,6 +1067,7 @@
 				break;
 
 			case KE_END:
+				break;
 			default:
 				BUG();
 			}
@@ -690,6 +1224,7 @@
 	platform_device_unregister(wistron_device);
 	platform_driver_unregister(&wistron_driver);
 	unmap_bios();
+	kfree(keymap);
 }
 
 module_init(wb_module_init);
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 35d998c..d0d0744 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -37,6 +37,65 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called psmouse.
 
+config MOUSE_PS2_ALPS
+	bool "ALPS PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an ALPS PS/2 touchpad connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_LOGIPS2PP
+	bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Logictech PS/2++ mouse connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_SYNAPTICS
+	bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Synaptics PS/2 TouchPad connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_LIFEBOOK
+	bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Fujitsu B-series Lifebook PS/2
+	  TouchScreen connected to your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_TRACKPOINT
+	bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an IBM Trackpoint PS/2 mouse connected
+	  to your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_TOUCHKIT
+	bool "eGalax TouchKit PS/2 protocol extension"
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an eGalax TouchKit PS/2 touchscreen
+	  connected to your system.
+
+	  If unsure, say N.
+
 config MOUSE_SERIAL
 	tristate "Serial mouse"
 	select SERIO
@@ -118,7 +177,7 @@
 	  digitizer (VSXXX-AB) DEC produced.
 
 config MOUSE_HIL
-	tristate "HIL pointers (mice etc)."     
+	tristate "HIL pointers (mice etc)."
 	depends on GSC || HP300
 	select HP_SDC
 	select HIL_MLC
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 21a1de6..83477d5 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -14,4 +14,10 @@
 obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
 
-psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
+psmouse-objs := psmouse-base.o synaptics.o
+
+psmouse-$(CONFIG_MOUSE_PS2_ALPS)	+= alps.o
+psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP)	+= logips2pp.o
+psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK)	+= lifebook.o
+psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)	+= trackpoint.o
+psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)	+= touchkit_ps2.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4e71a66..cf3e466 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -424,14 +424,15 @@
 	struct input_dev *dev1 = psmouse->dev, *dev2;
 	int version;
 
-	psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+	priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
 	dev2 = input_allocate_device();
 	if (!priv || !dev2)
 		goto init_fail;
 
 	priv->dev2 = dev2;
 
-	if (!(priv->i = alps_get_model(psmouse, &version)))
+	priv->i = alps_get_model(psmouse, &version);
+	if (!priv->i)
 		goto init_fail;
 
 	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
@@ -480,7 +481,8 @@
 	dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
 	dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-	input_register_device(priv->dev2);
+	if (input_register_device(priv->dev2))
+		goto init_fail;
 
 	psmouse->protocol_handler = alps_process_byte;
 	psmouse->poll = alps_poll;
@@ -491,9 +493,11 @@
 	/* We are having trouble resyncing ALPS touchpads so disable it for now */
 	psmouse->resync_time = 0;
 
+	psmouse->private = priv;
 	return 0;
 
 init_fail:
+	psmouse_reset(psmouse);
 	input_free_device(dev2);
 	kfree(priv);
 	return -1;
@@ -504,7 +508,8 @@
 	int version;
 	const struct alps_model_info *model;
 
-	if (!(model = alps_get_model(psmouse, &version)))
+	model = alps_get_model(psmouse, &version);
+	if (!model)
 		return -1;
 
 	if (set_properties) {
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 69db732..4bbddc9 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,9 +12,6 @@
 #ifndef _ALPS_H
 #define _ALPS_H
 
-int alps_detect(struct psmouse *psmouse, int set_properties);
-int alps_init(struct psmouse *psmouse);
-
 struct alps_model_info {
         unsigned char signature[3];
         unsigned char byte0, mask0;
@@ -23,10 +20,23 @@
 
 struct alps_data {
 	struct input_dev *dev2;		/* Relative device */
-	char name[32];			/* Name */
 	char phys[32];			/* Phys */
 	const struct alps_model_info *i;/* Info */
 	int prev_fin;			/* Finger bit from previous packet */
 };
 
+#ifdef CONFIG_MOUSE_PS2_ALPS
+int alps_detect(struct psmouse *psmouse, int set_properties);
+int alps_init(struct psmouse *psmouse);
+#else
+inline int alps_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+inline int alps_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_ALPS */
+
 #endif
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bfb174f..449bf4d 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -88,10 +88,12 @@
 	idx = ptr->idx4/4;
 	p = data[idx - 1];
 
-	if ((p & ~HIL_CMDCT_POL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-	if ((p & ~HIL_CMDCT_RPL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+	if ((p & ~HIL_CMDCT_POL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+		goto report;
+	if ((p & ~HIL_CMDCT_RPL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+		goto report;
 
 	/* Not a poll response.  See if we are loading config records. */
 	switch (p & HIL_PKT_DATA_MASK) {
@@ -101,27 +103,32 @@
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->idd[i] = 0;
 		break;
+
 	case HIL_CMD_RSC:
 		for (i = 0; i < idx; i++)
 			ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->rsc[i] = 0;
 		break;
+
 	case HIL_CMD_EXD:
 		for (i = 0; i < idx; i++)
 			ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->exd[i] = 0;
 		break;
+
 	case HIL_CMD_RNM:
 		for (i = 0; i < idx; i++)
 			ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
-			ptr->rnm[i] = '\0';
+			ptr->rnm[i] = 0;
 		break;
+
 	default:
 		/* These occur when device isn't present */
-		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+			break;
 		/* Anything else we'd like to know about. */
 		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
 		break;
@@ -130,7 +137,8 @@
 
  report:
 	if ((p & HIL_CMDCT_POL) != idx - 1) {
-		printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+		printk(KERN_WARNING PREFIX
+			"Malformed poll packet %x (idx = %i)\n", p, idx);
 		goto out;
 	}
 
@@ -139,7 +147,7 @@
 	laxis += i;
 
 	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
-	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
+	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
 
 	for (cnt = 1; i < laxis; i++) {
 		unsigned int lo,hi,val;
@@ -157,7 +165,8 @@
 			input_report_abs(dev, ABS_X + i, val);
 		} else {
 			val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
-			if (i%3) val *= -1;
+			if (i%3)
+				val *= -1;
 			input_report_rel(dev, REL_X + i, val);
 		}
 	}
@@ -168,10 +177,11 @@
 		btn = ptr->data[cnt++];
 		up = btn & 1;
 		btn &= 0xfe;
-		if (btn == 0x8e) {
+		if (btn == 0x8e)
 			continue; /* TODO: proximity == touch? */
-		}
-		else if ((btn > 0x8c) || (btn < 0x80)) continue;
+		else
+			if ((btn > 0x8c) || (btn < 0x80))
+				continue;
 		btn = (btn - 0x80) >> 1;
 		btn = ptr->btnmap[btn];
 		input_report_key(dev, btn, !up);
@@ -182,14 +192,14 @@
 	up(&ptr->sem);
 }
 
-static void hil_ptr_process_err(struct hil_ptr *ptr) {
+static void hil_ptr_process_err(struct hil_ptr *ptr)
+{
 	printk(KERN_WARNING PREFIX "errored HIL packet\n");
 	ptr->idx4 = 0;
 	up(&ptr->sem);
-	return;
 }
 
-static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
+static irqreturn_t hil_ptr_interrupt(struct serio *serio,
         unsigned char data, unsigned int flags)
 {
 	struct hil_ptr *ptr;
@@ -197,29 +207,29 @@
 	int idx;
 
 	ptr = serio_get_drvdata(serio);
-	if (ptr == NULL) {
-		BUG();
-		return IRQ_HANDLED;
-	}
+	BUG_ON(ptr == NULL);
 
 	if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
 		hil_ptr_process_err(ptr);
 		return IRQ_HANDLED;
 	}
 	idx = ptr->idx4/4;
-	if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+	if (!(ptr->idx4 % 4))
+		ptr->data[idx] = 0;
 	packet = ptr->data[idx];
 	packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
 	ptr->data[idx] = packet;
 
 	/* Records of N 4-byte hil_packets must terminate with a command. */
-	if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+	if ((++(ptr->idx4)) % 4)
+		return IRQ_HANDLED;
 	if ((packet & 0xffff0000) != HIL_ERR_INT) {
 		hil_ptr_process_err(ptr);
 		return IRQ_HANDLED;
 	}
-	if (packet & HIL_PKT_CMD) 
+	if (packet & HIL_PKT_CMD)
 		hil_ptr_process_record(ptr);
+
 	return IRQ_HANDLED;
 }
 
@@ -228,10 +238,7 @@
 	struct hil_ptr *ptr;
 
 	ptr = serio_get_drvdata(serio);
-	if (ptr == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(ptr == NULL);
 
 	serio_close(serio);
 	input_unregister_device(ptr->dev);
@@ -241,7 +248,7 @@
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
 	struct hil_ptr	 *ptr;
-	char		 *txt;
+	const char	 *txt;
 	unsigned int	 i, naxsets, btntype;
 	uint8_t		 did, *idd;
 
@@ -252,42 +259,40 @@
 	if (!ptr->dev)
 		goto bail0;
 
-	ptr->dev->private = ptr;
-
 	if (serio_open(serio, driver))
 		goto bail1;
 
 	serio_set_drvdata(serio, ptr);
 	ptr->serio = serio;
 
-	init_MUTEX_LOCKED(&(ptr->sem));
+	init_MUTEX_LOCKED(&ptr->sem);
 
 	/* Get device info.  MLC driver supplies devid/status/etc. */
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_IDD);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RSC);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RNM);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EXD);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
-	up(&(ptr->sem));
+	up(&ptr->sem);
 
 	did = ptr->idd[0];
 	idd = ptr->idd + 1;
@@ -301,12 +306,12 @@
 		ptr->dev->evbit[0] = BIT(EV_ABS);
 		txt = "absolute";
 	}
-	if (!ptr->dev->evbit[0]) {
+	if (!ptr->dev->evbit[0])
 		goto bail2;
-	}
 
 	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
-	if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
+	if (ptr->nbtn)
+		ptr->dev->evbit[0] |= BIT(EV_KEY);
 
 	naxsets = HIL_IDD_NUM_AXSETS(*idd);
 	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -315,7 +320,7 @@
 			did, txt);
 	printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
 			ptr->nbtn, naxsets, ptr->naxes);
-	
+
 	btntype = BTN_MISC;
 	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
 #ifdef TABLET_SIMULATES_MOUSE
@@ -325,7 +330,7 @@
 #endif
 	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
 		btntype = BTN_TOUCH;
-		
+
 	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
 		btntype = BTN_MOUSE;
 
@@ -341,12 +346,10 @@
 	}
 
 	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
-		for (i = 0; i < ptr->naxes; i++) {
+		for (i = 0; i < ptr->naxes; i++)
 			set_bit(REL_X + i, ptr->dev->relbit);
-		}
-		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++)
 			set_bit(REL_X + i, ptr->dev->relbit);
-		}
 	} else {
 		for (i = 0; i < ptr->naxes; i++) {
 			set_bit(ABS_X + i, ptr->dev->absbit);
@@ -375,7 +378,7 @@
 	ptr->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	ptr->dev->id.product	= 0x0001; /* TODO: get from ptr->rsc */
 	ptr->dev->id.version	= 0x0100; /* TODO: get from ptr->rsc */
-	ptr->dev->cdev.dev	= &serio->dev;
+	ptr->dev->dev.parent	= &serio->dev;
 
 	input_register_device(ptr->dev);
 	printk(KERN_INFO "input: %s (%s), ID: %d\n",
@@ -419,11 +422,11 @@
 {
 	return serio_register_driver(&hil_ptr_serio_driver);
 }
-                
+
 static void __exit hil_ptr_exit(void)
 {
 	serio_unregister_driver(&hil_ptr_serio_driver);
 }
-                        
+
 module_init(hil_ptr_init);
 module_exit(hil_ptr_exit);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 29542f0..1740cad 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -20,6 +20,27 @@
 #include "psmouse.h"
 #include "lifebook.h"
 
+struct lifebook_data {
+	struct input_dev *dev2;		/* Relative device */
+	char phys[32];
+};
+
+static const char *desired_serio_phys;
+
+static int lifebook_set_serio_phys(struct dmi_system_id *d)
+{
+	desired_serio_phys = d->driver_data;
+	return 0;
+}
+
+static unsigned char lifebook_use_6byte_proto;
+
+static int lifebook_set_6byte_proto(struct dmi_system_id *d)
+{
+	lifebook_use_6byte_proto = 1;
+	return 0;
+}
+
 static struct dmi_system_id lifebook_dmi_table[] = {
 	{
 		.ident = "FLORA-ie 55mi",
@@ -56,6 +77,24 @@
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
 		},
+		.callback = lifebook_set_serio_phys,
+		.driver_data = "isa0060/serio3",
+	},
+	{
+		.ident = "Panasonic CF-28",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
+		},
+		.callback = lifebook_set_6byte_proto,
+	},
+	{
+		.ident = "Panasonic CF-29",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+		},
+		.callback = lifebook_set_6byte_proto,
 	},
 	{
 		.ident = "Lifebook B142",
@@ -68,30 +107,70 @@
 
 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
 {
+	struct lifebook_data *priv = psmouse->private;
+	struct input_dev *dev1 = psmouse->dev;
+	struct input_dev *dev2 = priv->dev2;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
+	int relative_packet = packet[0] & 0x08;
 
-	if (psmouse->pktcnt != 3)
-		return PSMOUSE_GOOD_DATA;
-
-	/* calculate X and Y */
-	if ((packet[0] & 0x08) == 0x00) {
-		input_report_abs(dev, ABS_X,
-				 (packet[1] | ((packet[0] & 0x30) << 4)));
-		input_report_abs(dev, ABS_Y,
-				 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+	if (relative_packet || !lifebook_use_6byte_proto) {
+		if (psmouse->pktcnt != 3)
+			return PSMOUSE_GOOD_DATA;
 	} else {
-		input_report_rel(dev, REL_X,
-				((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
-		input_report_rel(dev, REL_Y,
-				 -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
+		switch (psmouse->pktcnt) {
+		case 1:
+			return (packet[0] & 0xf8) == 0x00 ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 2:
+			return PSMOUSE_GOOD_DATA;
+		case 3:
+			return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 4:
+			return (packet[3] & 0xf8) == 0xc0 ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 5:
+			return (packet[4] & 0xc0) == (packet[2] & 0xc0) ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 6:
+			if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0))
+				return PSMOUSE_BAD_DATA;
+			if ((packet[5] & 0xc0) != (packet[1] & 0xc0))
+				return PSMOUSE_BAD_DATA;
+			break; /* report data */
+		}
 	}
 
-	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
-	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
-	input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
+	if (relative_packet) {
+		if (!dev2)
+			printk(KERN_WARNING "lifebook.c: got relative packet "
+				"but no relative device set up\n");
+	} else if (lifebook_use_6byte_proto) {
+		input_report_abs(dev1, ABS_X,
+				 ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
+		input_report_abs(dev1, ABS_Y,
+				 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
+	} else {
+		input_report_abs(dev1, ABS_X,
+				 (packet[1] | ((packet[0] & 0x30) << 4)));
+		input_report_abs(dev1, ABS_Y,
+				 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+	}
 
-	input_sync(dev);
+	input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+	input_sync(dev1);
+
+	if (dev2) {
+		if (relative_packet) {
+			input_report_rel(dev2, REL_X,
+				((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
+			input_report_rel(dev2, REL_Y,
+				 -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
+		}
+		input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
+		input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
+		input_sync(dev2);
+	}
 
 	return PSMOUSE_FULL_PACKET;
 }
@@ -109,12 +188,20 @@
 	   you leave this call out the touchsreen will never send
 	   absolute coordinates
 	*/
-	param = 0x07;
+	param = lifebook_use_6byte_proto ? 0x08 : 0x07;
 	ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
 
 	return 0;
 }
 
+static void lifebook_relative_mode(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param = 0x06;
+
+	ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
+}
+
 static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
 {
 	static const unsigned char params[] = { 0, 1, 2, 2, 3 };
@@ -131,6 +218,8 @@
 static void lifebook_disconnect(struct psmouse *psmouse)
 {
 	psmouse_reset(psmouse);
+	kfree(psmouse->private);
+	psmouse->private = NULL;
 }
 
 int lifebook_detect(struct psmouse *psmouse, int set_properties)
@@ -138,6 +227,10 @@
         if (!dmi_check_system(lifebook_dmi_table))
                 return -1;
 
+	if (desired_serio_phys &&
+	    strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys))
+		return -1;
+
 	if (set_properties) {
 		psmouse->vendor = "Fujitsu";
 		psmouse->name = "Lifebook TouchScreen";
@@ -146,24 +239,78 @@
         return 0;
 }
 
+static int lifebook_create_relative_device(struct psmouse *psmouse)
+{
+	struct input_dev *dev2;
+	struct lifebook_data *priv;
+	int error = -ENOMEM;
+
+	priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL);
+	dev2 = input_allocate_device();
+	if (!priv || !dev2)
+		goto err_out;
+
+	priv->dev2 = dev2;
+	snprintf(priv->phys, sizeof(priv->phys),
+		 "%s/input1", psmouse->ps2dev.serio->phys);
+
+	dev2->phys = priv->phys;
+	dev2->name = "PS/2 Touchpad";
+	dev2->id.bustype = BUS_I8042;
+	dev2->id.vendor  = 0x0002;
+	dev2->id.product = PSMOUSE_LIFEBOOK;
+	dev2->id.version = 0x0000;
+	dev2->dev.parent = &psmouse->ps2dev.serio->dev;
+
+	dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y);
+	dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+
+	error = input_register_device(priv->dev2);
+	if (error)
+		goto err_out;
+
+	psmouse->private = priv;
+	return 0;
+
+ err_out:
+	input_free_device(dev2);
+	kfree(priv);
+	return error;
+}
+
 int lifebook_init(struct psmouse *psmouse)
 {
-	struct input_dev *input_dev = psmouse->dev;
+	struct input_dev *dev1 = psmouse->dev;
+	int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
 
 	if (lifebook_absolute_mode(psmouse))
 		return -1;
 
-	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-	input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
+	dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	dev1->relbit[0] = 0;
+	dev1->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
+	input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
+
+	if (!desired_serio_phys) {
+		if (lifebook_create_relative_device(psmouse)) {
+			lifebook_relative_mode(psmouse);
+			return -1;
+		}
+	}
 
 	psmouse->protocol_handler = lifebook_process_byte;
 	psmouse->set_resolution = lifebook_set_resolution;
 	psmouse->disconnect = lifebook_disconnect;
 	psmouse->reconnect  = lifebook_absolute_mode;
+
+	psmouse->model = lifebook_use_6byte_proto ? 6 : 3;
+
+	/*
+	 * Use packet size = 3 even when using 6-byte protocol because
+	 * that's what POLL will return on Lifebooks (according to spec).
+	 */
 	psmouse->pktsize = 3;
 
 	return 0;
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h
index be1c094..c1647cf 100644
--- a/drivers/input/mouse/lifebook.h
+++ b/drivers/input/mouse/lifebook.h
@@ -11,7 +11,18 @@
 #ifndef _LIFEBOOK_H
 #define _LIFEBOOK_H
 
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
 int lifebook_detect(struct psmouse *psmouse, int set_properties);
 int lifebook_init(struct psmouse *psmouse);
+#else
+inline int lifebook_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+inline int lifebook_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+#endif
 
 #endif
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index d3ddea2..9df74b7 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -200,6 +200,7 @@
 static const struct ps2pp_info *get_model_info(unsigned char model)
 {
 	static const struct ps2pp_info ps2pp_list[] = {
+		{  1,	0,			0 },	/* Simple 2-button mouse */
 		{ 12,	0,			PS2PP_SIDE_BTN},
 		{ 13,	0,			0 },
 		{ 15,	PS2PP_KIND_MX,					/* MX1000 */
@@ -338,12 +339,12 @@
 	param[1] = 0;
 	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
 
-	if (!param[1])
-		return -1;
-
 	model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
 	buttons = param[1];
 
+	if (!model || !buttons)
+		return -1;
+
 	if ((model_info = get_model_info(model)) != NULL) {
 
 /*
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h
index 64a8ec5..6e57125 100644
--- a/drivers/input/mouse/logips2pp.h
+++ b/drivers/input/mouse/logips2pp.h
@@ -11,6 +11,13 @@
 #ifndef _LOGIPS2PP_H
 #define _LOGIPS2PP_H
 
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
 int ps2pp_init(struct psmouse *psmouse, int set_properties);
+#else
+inline int ps2pp_init(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */
 
 #endif
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 0fe5869..f15f695 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -28,6 +28,7 @@
 #include "alps.h"
 #include "lifebook.h"
 #include "trackpoint.h"
+#include "touchkit_ps2.h"
 
 #define DRIVER_DESC	"PS/2 mouse driver"
 
@@ -569,7 +570,9 @@
 		return PSMOUSE_THINKPS;
 
 /*
- * Try Synaptics TouchPad
+ * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol
+ * support is disabled in config - we need to know if it is synaptics so we
+ * can reset it properly after probing for intellimouse.
  */
 	if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
 		synaptics_hardware = 1;
@@ -605,14 +608,20 @@
 		}
 	}
 
-	if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
-		return PSMOUSE_GENPS;
+	if (max_proto > PSMOUSE_IMEX) {
 
-	if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
-		return PSMOUSE_PS2PP;
+		if (genius_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_GENPS;
 
-	if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
-		return PSMOUSE_TRACKPOINT;
+		if (ps2pp_init(psmouse, set_properties) == 0)
+			return PSMOUSE_PS2PP;
+
+		if (trackpoint_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_TRACKPOINT;
+
+		if (touchkit_ps2_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_TOUCHKIT_PS2;
+	}
 
 /*
  * Reset to defaults in case the device got confused by extended
@@ -654,12 +663,14 @@
 		.maxproto	= 1,
 		.detect		= ps2bare_detect,
 	},
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
 	{
 		.type		= PSMOUSE_PS2PP,
 		.name		= "PS2++",
 		.alias		= "logitech",
 		.detect		= ps2pp_init,
 	},
+#endif
 	{
 		.type		= PSMOUSE_THINKPS,
 		.name		= "ThinkPS/2",
@@ -686,6 +697,7 @@
 		.maxproto	= 1,
 		.detect		= im_explorer_detect,
 	},
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
 	{
 		.type		= PSMOUSE_SYNAPTICS,
 		.name		= "SynPS/2",
@@ -693,6 +705,8 @@
 		.detect		= synaptics_detect,
 		.init		= synaptics_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_ALPS
 	{
 		.type		= PSMOUSE_ALPS,
 		.name		= "AlpsPS/2",
@@ -700,18 +714,31 @@
 		.detect		= alps_detect,
 		.init		= alps_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
 	{
 		.type		= PSMOUSE_LIFEBOOK,
 		.name		= "LBPS/2",
 		.alias		= "lifebook",
 		.init		= lifebook_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
 	{
 		.type		= PSMOUSE_TRACKPOINT,
 		.name		= "TPPS/2",
 		.alias		= "trackpoint",
 		.detect		= trackpoint_detect,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+	{
+		.type		= PSMOUSE_TOUCHKIT_PS2,
+		.name		= "touchkitPS/2",
+		.alias		= "touchkit",
+		.detect		= touchkit_ps2_detect,
+	},
+#endif
 	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
@@ -823,12 +850,6 @@
 static void psmouse_initialize(struct psmouse *psmouse)
 {
 /*
- * We set the mouse into streaming mode.
- */
-
-	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM);
-
-/*
  * We set the mouse report rate, resolution and scaling.
  */
 
@@ -1062,8 +1083,7 @@
 {
 	struct input_dev *input_dev = psmouse->dev;
 
-	input_dev->private = psmouse;
-	input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
+	input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index cf1de95..3964e8a 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -87,6 +87,7 @@
 	PSMOUSE_ALPS,
 	PSMOUSE_LIFEBOOK,
 	PSMOUSE_TRACKPOINT,
+	PSMOUSE_TOUCHKIT_PS2,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index a85d747..77b8ee2 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -69,7 +69,8 @@
 	switch (sermouse->count) {
 
 		case 0:
-			if ((data & 0xf8) != 0x80) return;
+			if ((data & 0xf8) != 0x80)
+				return;
 			input_report_key(dev, BTN_LEFT,   !(data & 4));
 			input_report_key(dev, BTN_RIGHT,  !(data & 1));
 			input_report_key(dev, BTN_MIDDLE, !(data & 2));
@@ -107,7 +108,10 @@
 	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
-	if (data & 0x40) sermouse->count = 0;
+	if (data & 0x40)
+		sermouse->count = 0;
+	else if (sermouse->count == 0)
+		return;
 
 	switch (sermouse->count) {
 
@@ -169,7 +173,8 @@
 
 		case 5:
 		case 7: /* Ignore anything besides MZ++ */
-			if (sermouse->type != SERIO_MZPP) break;
+			if (sermouse->type != SERIO_MZPP)
+				break;
 
 			switch (buf[1]) {
 
@@ -206,13 +211,16 @@
 {
 	struct sermouse *sermouse = serio_get_drvdata(serio);
 
-	if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
+	if (time_after(jiffies, sermouse->last + HZ/10))
+		sermouse->count = 0;
+
 	sermouse->last = jiffies;
 
 	if (sermouse->type > SERIO_SUN)
 		sermouse_process_ms(sermouse, data);
 	else
 		sermouse_process_msc(sermouse, data);
+
 	return IRQ_HANDLED;
 }
 
@@ -258,12 +266,11 @@
 	input_dev->id.vendor  = sermouse->type;
 	input_dev->id.product = c;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
 	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_dev->private = sermouse;
 
 	if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
 	if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index f0f9413..c77788b 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -40,21 +40,10 @@
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
-/*****************************************************************************
- *	Synaptics communications functions
- ****************************************************************************/
 
-/*
- * Send a command to the synpatics touchpad by special commands
- */
-static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
-{
-	if (psmouse_sliced_command(psmouse, c))
-		return -1;
-	if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
-		return -1;
-	return 0;
-}
+/*****************************************************************************
+ *	Stuff we need even when we do not want native Synaptics support
+ ****************************************************************************/
 
 /*
  * Set the synaptics touchpad mode byte by special commands
@@ -71,6 +60,54 @@
 	return 0;
 }
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[4];
+
+	param[0] = 0;
+
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+
+	if (param[1] != 0x47)
+		return -ENODEV;
+
+	if (set_properties) {
+		psmouse->vendor = "Synaptics";
+		psmouse->name = "TouchPad";
+	}
+
+	return 0;
+}
+
+void synaptics_reset(struct psmouse *psmouse)
+{
+	/* reset touchpad back to relative mode, gestures enabled */
+	synaptics_mode_cmd(psmouse, 0);
+}
+
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+
+/*****************************************************************************
+ *	Synaptics communications functions
+ ****************************************************************************/
+
+/*
+ * Send a command to the synpatics touchpad by special commands
+ */
+static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
+{
+	if (psmouse_sliced_command(psmouse, c))
+		return -1;
+	if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
+		return -1;
+	return 0;
+}
+
 /*
  * Read the model-id bytes from the touchpad
  * see also SYN_MODEL_* macros
@@ -529,12 +566,6 @@
 	clear_bit(REL_Y, dev->relbit);
 }
 
-void synaptics_reset(struct psmouse *psmouse)
-{
-	/* reset touchpad back to relative mode, gestures enabled */
-	synaptics_mode_cmd(psmouse, 0);
-}
-
 static void synaptics_disconnect(struct psmouse *psmouse)
 {
 	synaptics_reset(psmouse);
@@ -569,30 +600,6 @@
 	return 0;
 }
 
-int synaptics_detect(struct psmouse *psmouse, int set_properties)
-{
-	struct ps2dev *ps2dev = &psmouse->ps2dev;
-	unsigned char param[4];
-
-	param[0] = 0;
-
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
-
-	if (param[1] != 0x47)
-		return -1;
-
-	if (set_properties) {
-		psmouse->vendor = "Synaptics";
-		psmouse->name = "TouchPad";
-	}
-
-	return 0;
-}
-
 #if defined(__i386__)
 #include <linux/dmi.h>
 static struct dmi_system_id toshiba_dmi_table[] = {
@@ -648,6 +655,16 @@
 
 	set_input_params(psmouse->dev, priv);
 
+	/*
+	 * Encode touchpad model so that it can be used to set
+	 * input device->id.version and be visible to userspace.
+	 * Because version is __u16 we have to drop something.
+	 * Hardware info bits seem to be good candidates as they
+	 * are documented to be for Synaptics corp. internal use.
+	 */
+	psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
+			  (priv->model_id & 0x000000ff);
+
 	psmouse->protocol_handler = synaptics_process_byte;
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->disconnect = synaptics_disconnect;
@@ -680,4 +697,12 @@
 	return -1;
 }
 
+#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
+
+int synaptics_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
 
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 68fff1d..02aa4cf 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -9,10 +9,6 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-extern int synaptics_detect(struct psmouse *psmouse, int set_properties);
-extern int synaptics_init(struct psmouse *psmouse);
-extern void synaptics_reset(struct psmouse *psmouse);
-
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY		0x00
 #define SYN_QUE_MODES			0x01
@@ -62,9 +58,9 @@
 #define SYN_MODE_WMODE(m)		((m) & (1 << 0))
 
 /* synaptics identify query bits */
-#define SYN_ID_MODEL(i) 		(((i) >> 4) & 0x0f)
-#define SYN_ID_MAJOR(i) 		((i) & 0x0f)
-#define SYN_ID_MINOR(i) 		(((i) >> 16) & 0xff)
+#define SYN_ID_MODEL(i)			(((i) >> 4) & 0x0f)
+#define SYN_ID_MAJOR(i)			((i) & 0x0f)
+#define SYN_ID_MINOR(i)			(((i) >> 16) & 0xff)
 #define SYN_ID_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)
 
 /* synaptics special commands */
@@ -98,8 +94,8 @@
 struct synaptics_data {
 	/* Data read from the touchpad */
 	unsigned long int model_id;		/* Model-ID */
-	unsigned long int capabilities; 	/* Capabilities */
-	unsigned long int ext_cap; 		/* Extended Capabilities */
+	unsigned long int capabilities;		/* Capabilities */
+	unsigned long int ext_cap;		/* Extended Capabilities */
 	unsigned long int identity;		/* Identification */
 
 	unsigned char pkt_type;			/* packet type - old, new, etc */
@@ -107,4 +103,8 @@
 	int scroll;
 };
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties);
+int synaptics_init(struct psmouse *psmouse);
+void synaptics_reset(struct psmouse *psmouse);
+
 #endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
new file mode 100644
index 0000000..7b977fd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.c
@@ -0,0 +1,100 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.c  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) by Todd E. Johnson (mtouchusb.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based upon touchkitusb.c
+ *
+ * Vendor documentation is available in support section of:
+ * http://www.egalax.com.tw/
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+
+#include "psmouse.h"
+#include "touchkit_ps2.h"
+
+#define TOUCHKIT_MAX_XC			0x07ff
+#define TOUCHKIT_MAX_YC			0x07ff
+
+#define TOUCHKIT_CMD			0x0a
+#define TOUCHKIT_CMD_LENGTH		1
+
+#define TOUCHKIT_CMD_ACTIVE		'A'
+#define TOUCHKIT_CMD_FIRMWARE_VERSION	'D'
+#define TOUCHKIT_CMD_CONTROLLER_TYPE	'E'
+
+#define TOUCHKIT_SEND_PARMS(s, r, c)	((s) << 12 | (r) << 8 | (c))
+
+#define TOUCHKIT_GET_TOUCHED(packet)	(((packet)[0]) & 0x01)
+#define TOUCHKIT_GET_X(packet)		(((packet)[1] << 7) | (packet)[2])
+#define TOUCHKIT_GET_Y(packet)		(((packet)[3] << 7) | (packet)[4])
+
+static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+	struct input_dev *dev = psmouse->dev;
+
+	if (psmouse->pktcnt != 5)
+		return PSMOUSE_GOOD_DATA;
+
+	input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
+	input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
+	input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));
+	input_sync(dev);
+
+	return PSMOUSE_FULL_PACKET;
+}
+
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char param[3];
+	int command;
+
+	param[0] = TOUCHKIT_CMD_LENGTH;
+	param[1] = TOUCHKIT_CMD_ACTIVE;
+	command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD);
+
+	if (ps2_command(&psmouse->ps2dev, param, command))
+		return -ENODEV;
+
+	if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 ||
+	    param[2] != TOUCHKIT_CMD_ACTIVE)
+		return -ENODEV;
+
+	if (set_properties) {
+		dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		set_bit(BTN_TOUCH, dev->keybit);
+		input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0);
+		input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0);
+
+		psmouse->vendor = "eGalax";
+		psmouse->name = "Touchscreen";
+		psmouse->protocol_handler = touchkit_ps2_process_byte;
+		psmouse->pktsize = 5;
+	}
+
+	return 0;
+}
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h
new file mode 100644
index 0000000..61e9dfd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.h
@@ -0,0 +1,24 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.h  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (c) 2005 Vojtech Pavlik
+ *
+ * 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.
+ */
+
+#ifndef _TOUCHKIT_PS2_H
+#define _TOUCHKIT_PS2_H
+
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */
+
+#endif
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 050298b..c10a6e7 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -142,6 +142,13 @@
 	unsigned char ext_dev;
 };
 
-extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
+int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */
 
 #endif /* _TRACKPOINT_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index c3d64fc..4a32157 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -508,8 +508,7 @@
 	input_dev->name = mouse->name;
 	input_dev->phys = mouse->phys;
 	input_dev->id.bustype = BUS_RS232;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = mouse;
+	input_dev->dev.parent = &serio->dev;
 
 	set_bit (EV_KEY, input_dev->evbit);		/* We have buttons */
 	set_bit (EV_REL, input_dev->evbit);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 664bcc8..3b8011c 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -63,9 +63,12 @@
 	int minor;
 	char name[16];
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct input_handle handle;
 
+	struct list_head mixdev_node;
+	int mixdev_open;
+
 	struct mousedev_hw_data packet;
 	unsigned int pkt_count;
 	int old_x[4], old_y[4];
@@ -85,7 +88,7 @@
 };
 
 #define PACKET_QUEUE_LEN	16
-struct mousedev_list {
+struct mousedev_client {
 	struct fasync_struct *fasync;
 	struct mousedev *mousedev;
 	struct list_head node;
@@ -111,6 +114,7 @@
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
 static struct mousedev mousedev_mix;
+static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -120,32 +124,33 @@
 	int size, tmp;
 	enum { FRACTION_DENOM = 128 };
 
-	if (mousedev->touch) {
-		size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-		if (size == 0)
-			size = 256 * 2;
+	switch (code) {
+		case ABS_X:
+			fx(0) = value;
+			if (mousedev->touch && mousedev->pkt_count >= 2) {
+				size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+				if (size == 0)
+					size = 256 * 2;
+				tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
+				tmp += mousedev->frac_dx;
+				mousedev->packet.dx = tmp / FRACTION_DENOM;
+				mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
+			}
+			break;
 
-		switch (code) {
-			case ABS_X:
-				fx(0) = value;
-				if (mousedev->pkt_count >= 2) {
-					tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
-					tmp += mousedev->frac_dx;
-					mousedev->packet.dx = tmp / FRACTION_DENOM;
-					mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
-				}
-				break;
-
-			case ABS_Y:
-				fy(0) = value;
-				if (mousedev->pkt_count >= 2) {
-					tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
-					tmp += mousedev->frac_dy;
-					mousedev->packet.dy = tmp / FRACTION_DENOM;
-					mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
-				}
-				break;
-		}
+		case ABS_Y:
+			fy(0) = value;
+			if (mousedev->touch && mousedev->pkt_count >= 2) {
+				/* use X size to keep the same scale */
+				size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+				if (size == 0)
+					size = 256 * 2;
+				tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
+				tmp += mousedev->frac_dy;
+				mousedev->packet.dy = tmp / FRACTION_DENOM;
+				mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
+			}
+			break;
 	}
 }
 
@@ -223,47 +228,47 @@
 
 static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
 {
-	struct mousedev_list *list;
+	struct mousedev_client *client;
 	struct mousedev_motion *p;
 	unsigned long flags;
 	int wake_readers = 0;
 
-	list_for_each_entry(list, &mousedev->list, node) {
-		spin_lock_irqsave(&list->packet_lock, flags);
+	list_for_each_entry(client, &mousedev->client_list, node) {
+		spin_lock_irqsave(&client->packet_lock, flags);
 
-		p = &list->packets[list->head];
-		if (list->ready && p->buttons != mousedev->packet.buttons) {
-			unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
-			if (new_head != list->tail) {
-				p = &list->packets[list->head = new_head];
+		p = &client->packets[client->head];
+		if (client->ready && p->buttons != mousedev->packet.buttons) {
+			unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN;
+			if (new_head != client->tail) {
+				p = &client->packets[client->head = new_head];
 				memset(p, 0, sizeof(struct mousedev_motion));
 			}
 		}
 
 		if (packet->abs_event) {
-			p->dx += packet->x - list->pos_x;
-			p->dy += packet->y - list->pos_y;
-			list->pos_x = packet->x;
-			list->pos_y = packet->y;
+			p->dx += packet->x - client->pos_x;
+			p->dy += packet->y - client->pos_y;
+			client->pos_x = packet->x;
+			client->pos_y = packet->y;
 		}
 
-		list->pos_x += packet->dx;
-		list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
-		list->pos_y += packet->dy;
-		list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
+		client->pos_x += packet->dx;
+		client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x);
+		client->pos_y += packet->dy;
+		client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y);
 
 		p->dx += packet->dx;
 		p->dy += packet->dy;
 		p->dz += packet->dz;
 		p->buttons = mousedev->packet.buttons;
 
-		if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons)
-			list->ready = 1;
+		if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons)
+			client->ready = 1;
 
-		spin_unlock_irqrestore(&list->packet_lock, flags);
+		spin_unlock_irqrestore(&client->packet_lock, flags);
 
-		if (list->ready) {
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		if (client->ready) {
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 			wake_readers = 1;
 		}
 	}
@@ -351,9 +356,9 @@
 static int mousedev_fasync(int fd, struct file *file, int on)
 {
 	int retval;
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
@@ -364,50 +369,95 @@
 	kfree(mousedev);
 }
 
-static void mixdev_release(void)
+static int mixdev_add_device(struct mousedev *mousedev)
 {
-	struct input_handle *handle;
+	int error;
 
-	list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-		struct mousedev *mousedev = handle->private;
+	if (mousedev_mix.open) {
+		error = input_open_device(&mousedev->handle);
+		if (error)
+			return error;
 
-		if (!mousedev->open) {
-			if (mousedev->exist)
-				input_close_device(&mousedev->handle);
-			else
-				mousedev_free(mousedev);
-		}
-	}
-}
-
-static int mousedev_release(struct inode * inode, struct file * file)
-{
-	struct mousedev_list *list = file->private_data;
-
-	mousedev_fasync(-1, file, 0);
-
-	list_del(&list->node);
-
-	if (!--list->mousedev->open) {
-		if (list->mousedev->minor == MOUSEDEV_MIX)
-			mixdev_release();
-		else if (!mousedev_mix.open) {
-			if (list->mousedev->exist)
-				input_close_device(&list->mousedev->handle);
-			else
-				mousedev_free(list->mousedev);
-		}
+		mousedev->open++;
+		mousedev->mixdev_open++;
 	}
 
-	kfree(list);
+	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
+
 	return 0;
 }
 
-static int mousedev_open(struct inode * inode, struct file * file)
+static void mixdev_remove_device(struct mousedev *mousedev)
 {
-	struct mousedev_list *list;
-	struct input_handle *handle;
+	if (mousedev->mixdev_open) {
+		mousedev->mixdev_open = 0;
+		if (!--mousedev->open && mousedev->exist)
+			input_close_device(&mousedev->handle);
+	}
+
+	list_del_init(&mousedev->mixdev_node);
+}
+
+static void mixdev_open_devices(void)
+{
 	struct mousedev *mousedev;
+
+	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+		if (mousedev->exist && !mousedev->open) {
+			if (input_open_device(&mousedev->handle))
+				continue;
+
+			mousedev->open++;
+			mousedev->mixdev_open++;
+		}
+	}
+}
+
+static void mixdev_close_devices(void)
+{
+	struct mousedev *mousedev, *next;
+
+	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+		if (mousedev->mixdev_open) {
+			mousedev->mixdev_open = 0;
+			if (!--mousedev->open) {
+				if (mousedev->exist)
+					input_close_device(&mousedev->handle);
+				else
+					mousedev_free(mousedev);
+			}
+		}
+	}
+}
+
+static int mousedev_release(struct inode *inode, struct file *file)
+{
+	struct mousedev_client *client = file->private_data;
+	struct mousedev *mousedev = client->mousedev;
+
+	mousedev_fasync(-1, file, 0);
+
+	list_del(&client->node);
+	kfree(client);
+
+	if (!--mousedev->open) {
+		if (mousedev->minor == MOUSEDEV_MIX)
+			mixdev_close_devices();
+		else if (mousedev->exist)
+			input_close_device(&mousedev->handle);
+		else
+			mousedev_free(mousedev);
+	}
+
+	return 0;
+}
+
+
+static int mousedev_open(struct inode *inode, struct file *file)
+{
+	struct mousedev_client *client;
+	struct mousedev *mousedev;
+	int error;
 	int i;
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -417,31 +467,37 @@
 #endif
 		i = iminor(inode) - MOUSEDEV_MINOR_BASE;
 
-	if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
+	if (i >= MOUSEDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+	mousedev = mousedev_table[i];
+	if (!mousedev)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	spin_lock_init(&list->packet_lock);
-	list->pos_x = xres / 2;
-	list->pos_y = yres / 2;
-	list->mousedev = mousedev_table[i];
-	list_add_tail(&list->node, &mousedev_table[i]->list);
-	file->private_data = list;
+	spin_lock_init(&client->packet_lock);
+	client->pos_x = xres / 2;
+	client->pos_y = yres / 2;
+	client->mousedev = mousedev;
+	list_add_tail(&client->node, &mousedev->client_list);
 
-	if (!list->mousedev->open++) {
-		if (list->mousedev->minor == MOUSEDEV_MIX) {
-			list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-				mousedev = handle->private;
-				if (!mousedev->open && mousedev->exist)
-					input_open_device(handle);
+	if (!mousedev->open++) {
+		if (mousedev->minor == MOUSEDEV_MIX)
+			mixdev_open_devices();
+		else if (mousedev->exist) {
+			error = input_open_device(&mousedev->handle);
+			if (error) {
+				list_del(&client->node);
+				kfree(client);
+				return error;
 			}
-		} else
-			if (!mousedev_mix.open && list->mousedev->exist)
-				input_open_device(&list->mousedev->handle);
+		}
 	}
 
+	file->private_data = client;
 	return 0;
 }
 
@@ -450,13 +506,13 @@
 	return delta > limit ? limit : (delta < -limit ? -limit : delta);
 }
 
-static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
+static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data)
 {
 	struct mousedev_motion *p;
 	unsigned long flags;
 
-	spin_lock_irqsave(&list->packet_lock, flags);
-	p = &list->packets[list->tail];
+	spin_lock_irqsave(&client->packet_lock, flags);
+	p = &client->packets[client->tail];
 
 	ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
 	ps2_data[1] = mousedev_limit_delta(p->dx, 127);
@@ -464,44 +520,44 @@
 	p->dx -= ps2_data[1];
 	p->dy -= ps2_data[2];
 
-	switch (list->mode) {
+	switch (client->mode) {
 		case MOUSEDEV_EMUL_EXPS:
 			ps2_data[3] = mousedev_limit_delta(p->dz, 7);
 			p->dz -= ps2_data[3];
 			ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
-			list->bufsiz = 4;
+			client->bufsiz = 4;
 			break;
 
 		case MOUSEDEV_EMUL_IMPS:
 			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
 			p->dz -= ps2_data[3];
-			list->bufsiz = 4;
+			client->bufsiz = 4;
 			break;
 
 		case MOUSEDEV_EMUL_PS2:
 		default:
 			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 			p->dz = 0;
-			list->bufsiz = 3;
+			client->bufsiz = 3;
 			break;
 	}
 
 	if (!p->dx && !p->dy && !p->dz) {
-		if (list->tail == list->head) {
-			list->ready = 0;
-			list->last_buttons = p->buttons;
+		if (client->tail == client->head) {
+			client->ready = 0;
+			client->last_buttons = p->buttons;
 		} else
-			list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
+			client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
 	}
 
-	spin_unlock_irqrestore(&list->packet_lock, flags);
+	spin_unlock_irqrestore(&client->packet_lock, flags);
 }
 
 
-static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 	unsigned char c;
 	unsigned int i;
 
@@ -510,95 +566,95 @@
 		if (get_user(c, buffer + i))
 			return -EFAULT;
 
-		if (c == mousedev_imex_seq[list->imexseq]) {
-			if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
-				list->imexseq = 0;
-				list->mode = MOUSEDEV_EMUL_EXPS;
+		if (c == mousedev_imex_seq[client->imexseq]) {
+			if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
+				client->imexseq = 0;
+				client->mode = MOUSEDEV_EMUL_EXPS;
 			}
 		} else
-			list->imexseq = 0;
+			client->imexseq = 0;
 
-		if (c == mousedev_imps_seq[list->impsseq]) {
-			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
-				list->impsseq = 0;
-				list->mode = MOUSEDEV_EMUL_IMPS;
+		if (c == mousedev_imps_seq[client->impsseq]) {
+			if (++client->impsseq == MOUSEDEV_SEQ_LEN) {
+				client->impsseq = 0;
+				client->mode = MOUSEDEV_EMUL_IMPS;
 			}
 		} else
-			list->impsseq = 0;
+			client->impsseq = 0;
 
-		list->ps2[0] = 0xfa;
+		client->ps2[0] = 0xfa;
 
 		switch (c) {
 
 			case 0xeb: /* Poll */
-				mousedev_packet(list, &list->ps2[1]);
-				list->bufsiz++; /* account for leading ACK */
+				mousedev_packet(client, &client->ps2[1]);
+				client->bufsiz++; /* account for leading ACK */
 				break;
 
 			case 0xf2: /* Get ID */
-				switch (list->mode) {
-					case MOUSEDEV_EMUL_PS2:  list->ps2[1] = 0; break;
-					case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
-					case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
+				switch (client->mode) {
+					case MOUSEDEV_EMUL_PS2:  client->ps2[1] = 0; break;
+					case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break;
+					case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break;
 				}
-				list->bufsiz = 2;
+				client->bufsiz = 2;
 				break;
 
 			case 0xe9: /* Get info */
-				list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
-				list->bufsiz = 4;
+				client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
+				client->bufsiz = 4;
 				break;
 
 			case 0xff: /* Reset */
-				list->impsseq = list->imexseq = 0;
-				list->mode = MOUSEDEV_EMUL_PS2;
-				list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
-				list->bufsiz = 3;
+				client->impsseq = client->imexseq = 0;
+				client->mode = MOUSEDEV_EMUL_PS2;
+				client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
+				client->bufsiz = 3;
 				break;
 
 			default:
-				list->bufsiz = 1;
+				client->bufsiz = 1;
 				break;
 		}
 
-		list->buffer = list->bufsiz;
+		client->buffer = client->bufsiz;
 	}
 
-	kill_fasync(&list->fasync, SIGIO, POLL_IN);
+	kill_fasync(&client->fasync, SIGIO, POLL_IN);
 
-	wake_up_interruptible(&list->mousedev->wait);
+	wake_up_interruptible(&client->mousedev->wait);
 
 	return count;
 }
 
-static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 	int retval = 0;
 
-	if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
+	if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->mousedev->wait,
-					  !list->mousedev->exist || list->ready || list->buffer);
+	retval = wait_event_interruptible(client->mousedev->wait,
+					  !client->mousedev->exist || client->ready || client->buffer);
 
 	if (retval)
 		return retval;
 
-	if (!list->mousedev->exist)
+	if (!client->mousedev->exist)
 		return -ENODEV;
 
-	if (!list->buffer && list->ready) {
-		mousedev_packet(list, list->ps2);
-		list->buffer = list->bufsiz;
+	if (!client->buffer && client->ready) {
+		mousedev_packet(client, client->ps2);
+		client->buffer = client->bufsiz;
 	}
 
-	if (count > list->buffer)
-		count = list->buffer;
+	if (count > client->buffer)
+		count = client->buffer;
 
-	list->buffer -= count;
+	client->buffer -= count;
 
-	if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count))
+	if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count))
 		return -EFAULT;
 
 	return count;
@@ -607,11 +663,12 @@
 /* No kernel lock - fine */
 static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
+	struct mousedev *mousedev = client->mousedev;
 
-	poll_wait(file, &list->mousedev->wait, wait);
-	return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
-		(list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &mousedev->wait, wait);
+	return ((client->ready || client->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+		(mousedev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static const struct file_operations mousedev_fops = {
@@ -624,23 +681,27 @@
 	.fasync =	mousedev_fasync,
 };
 
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev,
-					     const struct input_device_id *id)
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+			    const struct input_device_id *id)
 {
 	struct mousedev *mousedev;
 	struct class_device *cdev;
-	int minor = 0;
+	dev_t devt;
+	int minor;
+	int error;
 
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
 	if (minor == MOUSEDEV_MINORS) {
 		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
-		return NULL;
+	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+	if (!mousedev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&mousedev->list);
+	INIT_LIST_HEAD(&mousedev->client_list);
+	INIT_LIST_HEAD(&mousedev->mixdev_node);
 	init_waitqueue_head(&mousedev->wait);
 
 	mousedev->minor = minor;
@@ -651,42 +712,66 @@
 	mousedev->handle.private = mousedev;
 	sprintf(mousedev->name, "mouse%d", minor);
 
-	if (mousedev_mix.open)
-		input_open_device(&mousedev->handle);
-
 	mousedev_table[minor] = mousedev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			dev->cdev.dev, mousedev->name);
+	devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, mousedev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_mousedev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  mousedev->name);
+	error = sysfs_create_link(&input_class.subsys.kset.kobj,
+				  &cdev->kobj, mousedev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &mousedev->handle;
+	error = input_register_handle(&mousedev->handle);
+	if (error)
+		goto err_remove_link;
+
+	error = mixdev_add_device(mousedev);
+	if (error)
+		goto err_unregister_handle;
+
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(&mousedev->handle);
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_mousedev:
+	mousedev_table[minor] = NULL;
+	kfree(mousedev);
+	return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
-	struct mousedev_list *list;
+	struct mousedev_client *client;
+
+	input_unregister_handle(handle);
 
 	sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
 	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	mousedev->exist = 0;
 
+	mixdev_remove_device(mousedev);
+
 	if (mousedev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&mousedev->wait);
-		list_for_each_entry(list, &mousedev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
-	} else {
-		if (mousedev_mix.open)
-			input_close_device(handle);
+		list_for_each_entry(client, &mousedev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+	} else
 		mousedev_free(mousedev);
-	}
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -714,7 +799,7 @@
 		.absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
 	},	/* A touchpad */
 
-	{ }, 	/* Terminating entry */
+	{ },	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(input, mousedev_ids);
@@ -746,7 +831,7 @@
 		return error;
 
 	memset(&mousedev_mix, 0, sizeof(struct mousedev));
-	INIT_LIST_HEAD(&mousedev_mix.list);
+	INIT_LIST_HEAD(&mousedev_mix.client_list);
 	init_waitqueue_head(&mousedev_mix.wait);
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
 	mousedev_mix.exist = 1;
diff --git a/drivers/input/power.c b/drivers/input/power.c
deleted file mode 100644
index ee82464..0000000
--- a/drivers/input/power.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
- *
- *  Copyright (c) 2001 "Crazy" James Simmons
- *
- *  Input driver Power Management.
- *
- *  Sponsored by Transvirtual Technology.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
- */
-
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-
-static struct input_handler power_handler;
-
-/*
- * Power management can't be done in a interrupt context. So we have to
- * use keventd.
- */
-static int suspend_button_pushed = 0;
-static void suspend_button_task_handler(void *data)
-{
-        udelay(200); /* debounce */
-        suspend_button_pushed = 0;
-}
-
-static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL);
-
-static void power_event(struct input_handle *handle, unsigned int type,
-		        unsigned int code, int down)
-{
-	struct input_dev *dev = handle->dev;
-
-	printk("Entering power_event\n");
-
-	if (type == EV_PWR) {
-		switch (code) {
-			case KEY_SUSPEND:
-				printk("Powering down entire device\n");
-
-				if (!suspend_button_pushed) {
-                			suspend_button_pushed = 1;
-                        		schedule_work(&suspend_button_task);
-                		}
-				break;
-			case KEY_POWER:
-				/* Hum power down the machine. */
-				break;
-			default:
-				return;
-		}
-	}
-
-	if (type == EV_KEY) {
-		switch (code) {
-			case KEY_SUSPEND:
-				printk("Powering down input device\n");
-				/* This is risky. See pm.h for details. */
-				if (dev->state != PM_RESUME)
-					dev->state = PM_RESUME;
-				else
-					dev->state = PM_SUSPEND;
-				pm_send(dev->pm_dev, dev->state, dev);
-				break;
-			case KEY_POWER:
-				/* Turn the input device off completely ? */
-				break;
-			default:
-				return;
-		}
-	}
-	return;
-}
-
-static struct input_handle *power_connect(struct input_handler *handler,
-					  struct input_dev *dev,
-					  const struct input_device_id *id)
-{
-	struct input_handle *handle;
-
-	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-		return NULL;
-
-	handle->dev = dev;
-	handle->handler = handler;
-
-	input_open_device(handle);
-
-	printk(KERN_INFO "power.c: Adding power management to input layer\n");
-	return handle;
-}
-
-static void power_disconnect(struct input_handle *handle)
-{
-	input_close_device(handle);
-	kfree(handle);
-}
-
-static const struct input_device_id power_ids[] = {
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT(EV_KEY) },
-		.keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
-	},
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT(EV_KEY) },
-		.keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
-	},
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
-		.evbit = { BIT(EV_PWR) },
-	},
-	{ }, 	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(input, power_ids);
-
-static struct input_handler power_handler = {
-	.event =	power_event,
-	.connect =	power_connect,
-	.disconnect =	power_disconnect,
-	.name =		"power",
-	.id_table =	power_ids,
-};
-
-static int __init power_init(void)
-{
-	return input_register_handler(&power_handler);
-}
-
-static void __exit power_exit(void)
-{
-	input_unregister_handler(&power_handler);
-}
-
-module_init(power_init);
-module_exit(power_exit);
-
-MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("Input Power Management driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 4fa93ff..93a1a6b 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -32,11 +32,11 @@
  *
  *	Driver theory of operation:
  *
- *	Some access methods and an ISR is defined by the sub-driver 
- *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a 
- *	few bits of logic in addition to raw access to the HIL MLC, 
- *	specifically, the ISR, which is entirely registered by the 
- *	sub-driver and invoked directly, must check for record 
+ *	Some access methods and an ISR is defined by the sub-driver
+ *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a
+ *	few bits of logic in addition to raw access to the HIL MLC,
+ *	specifically, the ISR, which is entirely registered by the
+ *	sub-driver and invoked directly, must check for record
  *	termination or packet match, at which point a semaphore must
  *	be cleared and then the hil_mlcs_tasklet must be scheduled.
  *
@@ -47,7 +47,7 @@
  *	itself if output is pending.  (This rescheduling should be replaced
  *	at some point with a sub-driver-specific mechanism.)
  *
- *	A timer task prods the tasklet once per second to prevent 
+ *	A timer task prods the tasklet once per second to prevent
  *	hangups when attached devices do not return expected data
  *	and to initiate probes of the loop for new devices.
  */
@@ -83,69 +83,85 @@
 
 /********************** Device info/instance management **********************/
 
-static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+static void hil_mlc_clear_di_map(hil_mlc *mlc, int val)
+{
 	int j;
-	for (j = val; j < 7 ; j++) {
+
+	for (j = val; j < 7 ; j++)
 		mlc->di_map[j] = -1;
-	}
 }
 
-static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
-	memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+static void hil_mlc_clear_di_scratch(hil_mlc *mlc)
+{
+	memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch));
 }
 
-static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
-	memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx)
+{
+	memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch));
 }
 
-static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+static int hil_mlc_match_di_scratch(hil_mlc *mlc)
+{
 	int idx;
 
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
+		int j, found = 0;
 
 		/* In-use slots are not eligible. */
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (found) continue;
-		if (!memcmp(mlc->di + idx, 
-			    &(mlc->di_scratch), 
-			    sizeof(mlc->di_scratch))) break;
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (found)
+			continue;
+
+		if (!memcmp(mlc->di + idx, &mlc->di_scratch,
+				sizeof(mlc->di_scratch)))
+			break;
 	}
-	return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+	return idx >= HIL_MLC_DEVMEM ? -1 : idx;
 }
 
-static int hil_mlc_find_free_di(hil_mlc *mlc) {
+static int hil_mlc_find_free_di(hil_mlc *mlc)
+{
 	int idx;
-	/* TODO: Pick all-zero slots first, failing that, 
-	 * randomize the slot picked among those eligible. 
+
+	/* TODO: Pick all-zero slots first, failing that,
+	 * randomize the slot picked among those eligible.
 	 */
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (!found) break;
+		int j, found = 0;
+
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (!found)
+			break;
 	}
-	return(idx); /* Note: It is guaranteed at least one above will match */
+
+	return idx; /* Note: It is guaranteed at least one above will match */
 }
 
-static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc)
+{
 	int idx;
+
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (!found) mlc->serio_map[idx].di_revmap = -1;
+		int j, found = 0;
+
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (!found)
+			mlc->serio_map[idx].di_revmap = -1;
 	}
 }
 
-static void hil_mlc_send_polls(hil_mlc *mlc) {
+static void hil_mlc_send_polls(hil_mlc *mlc)
+{
 	int did, i, cnt;
 	struct serio *serio;
 	struct serio_driver *drv;
@@ -157,26 +173,31 @@
 
 	while (mlc->icount < 15 - i) {
 		hil_packet p;
+
 		p = mlc->ipacket[i];
 		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
-			if (drv == NULL || drv->interrupt == NULL) goto skip;
+			if (drv && drv->interrupt) {
+				drv->interrupt(serio, 0, 0);
+				drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+				drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
+				drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
+			}
 
-			drv->interrupt(serio, 0, 0);
-			drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
-			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
-			drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
-		skip:
 			did = (p & HIL_PKT_ADDR_MASK) >> 8;
 			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
 			drv = (serio != NULL) ? serio->drv : NULL;
 			cnt = 0;
 		}
-		cnt++; i++;
-		if (drv == NULL || drv->interrupt == NULL) continue;
-		drv->interrupt(serio, (p >> 24), 0);
-		drv->interrupt(serio, (p >> 16) & 0xff, 0);
-		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
-		drv->interrupt(serio, p & 0xff, 0);
+
+		cnt++;
+		i++;
+
+		if (drv && drv->interrupt) {
+			drv->interrupt(serio, (p >> 24), 0);
+			drv->interrupt(serio, (p >> 16) & 0xff, 0);
+			drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
+			drv->interrupt(serio, p & 0xff, 0);
+		}
 	}
 }
 
@@ -215,12 +236,16 @@
 #define HILSEN_DOZE	(HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
 #define HILSEN_SLEEP	(HILSEN_SAME | HILSEN_BREAK)
 
-static int hilse_match(hil_mlc *mlc, int unused) {
+static int hilse_match(hil_mlc *mlc, int unused)
+{
 	int rc;
+
 	rc = hil_mlc_match_di_scratch(mlc);
 	if (rc == -1) {
 		rc = hil_mlc_find_free_di(mlc);
-		if (rc == -1) goto err;
+		if (rc == -1)
+			goto err;
+
 #ifdef HIL_MLC_DEBUG
 		printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
 #endif
@@ -231,6 +256,7 @@
 		serio_rescan(mlc->serio[rc]);
 		return -1;
 	}
+
 	mlc->di_map[mlc->ddi] = rc;
 #ifdef HIL_MLC_DEBUG
 	printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
@@ -238,152 +264,177 @@
 	mlc->serio_map[rc].di_revmap = mlc->ddi;
 	hil_mlc_clean_serio_map(mlc);
 	return 0;
+
  err:
 	printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
 	return 1;
 }
 
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
-static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+static int hilse_init_lcv(hil_mlc *mlc, int unused)
+{
 	struct timeval tv;
 
 	do_gettimeofday(&tv);
 
-	if(mlc->lcv == 0) goto restart;  /* First init, no need to dally */
-	if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
- restart:
+	if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+		return -1;
+
 	mlc->lcv_tv = tv;
 	mlc->lcv = 0;
+
 	return 0;
 }
 
-static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
-	if (mlc->lcv++ >= lim) return -1;
-	return 0;
+static int hilse_inc_lcv(hil_mlc *mlc, int lim)
+{
+	return mlc->lcv++ >= lim ? -1 : 0;
 }
 
 #if 0
-static int hilse_set_lcv(hil_mlc *mlc, int val) {
+static int hilse_set_lcv(hil_mlc *mlc, int val)
+{
 	mlc->lcv = val;
+
 	return 0;
 }
 #endif
 
 /* Management of the discovered device index (zero based, -1 means no devs) */
-static int hilse_set_ddi(hil_mlc *mlc, int val) {
+static int hilse_set_ddi(hil_mlc *mlc, int val)
+{
 	mlc->ddi = val;
 	hil_mlc_clear_di_map(mlc, val + 1);
+
 	return 0;
 }
 
-static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+static int hilse_dec_ddi(hil_mlc *mlc, int unused)
+{
 	mlc->ddi--;
-	if (mlc->ddi <= -1) { 
+	if (mlc->ddi <= -1) {
 		mlc->ddi = -1;
 		hil_mlc_clear_di_map(mlc, 0);
 		return -1;
 	}
 	hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+
 	return 0;
 }
 
-static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
-	if (mlc->ddi >= 6) {
-		BUG();
-		return -1;
-	}
+static int hilse_inc_ddi(hil_mlc *mlc, int unused)
+{
+	BUG_ON(mlc->ddi >= 6);
 	mlc->ddi++;
+
 	return 0;
 }
 
-static int hilse_take_idd(hil_mlc *mlc, int unused) {
+static int hilse_take_idd(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	/* Help the state engine: 
-	 * Is this a real IDD response or just an echo? 
+	/* Help the state engine:
+	 * Is this a real IDD response or just an echo?
 	 *
-	 * Real IDD response does not start with a command. 
+	 * Real IDD response does not start with a command.
 	 */
-	if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+	if (mlc->ipacket[0] & HIL_PKT_CMD)
+		goto bail;
+
 	/* Should have the command echoed further down. */
 	for (i = 1; i < 16; i++) {
-		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == 
+		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
 		     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
-		    (mlc->ipacket[i] & HIL_PKT_CMD) && 
+		    (mlc->ipacket[i] & HIL_PKT_CMD) &&
 		    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
 			break;
 	}
-	if (i > 15) goto bail;
+	if (i > 15)
+		goto bail;
+
 	/* And the rest of the packets should still be clear. */
-	while (++i < 16) {
-		if (mlc->ipacket[i]) break;
-	}
-	if (i < 16) goto bail;
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.idd[i] = 
+	while (++i < 16)
+		if (mlc->ipacket[i])
+			break;
+
+	if (i < 16)
+		goto bail;
+
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.idd[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if RSC supported */
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) 
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
 		return HILSEN_NEXT;
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
 		return HILSEN_DOWN | 4;
+
 	return 0;
+
  bail:
 	mlc->ddi--;
+
 	return -1; /* This should send us off to ACF */
 }
 
-static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+static int hilse_take_rsc(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.rsc[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.rsc[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if EXD supported (IDD has already been read) */
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
 		return HILSEN_NEXT;
+
 	return 0;
 }
 
-static int hilse_take_exd(hil_mlc *mlc, int unused) {
+static int hilse_take_exd(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.exd[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.exd[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if RNM supported. */
-	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) 
+	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
 		return HILSEN_NEXT;
+
 	return 0;
 }
 
-static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+static int hilse_take_rnm(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.rnm[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.rnm[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
-	do {
-	  char nam[17];
-	  snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
-	  nam[16] = '\0';
-	  printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
-	} while (0);
+
+	printk(KERN_INFO PREFIX "Device name gotten: %16s\n",
+			mlc->di_scratch.rnm);
+
 	return 0;
 }
 
-static int hilse_operate(hil_mlc *mlc, int repoll) { 
+static int hilse_operate(hil_mlc *mlc, int repoll)
+{
 
-	if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+	if (mlc->opercnt == 0)
+		hil_mlcs_probe = 0;
 	mlc->opercnt = 1;
 
 	hil_mlc_send_polls(mlc);
 
-	if (!hil_mlcs_probe) return 0;
+	if (!hil_mlcs_probe)
+		return 0;
 	hil_mlcs_probe = 0;
 	mlc->opercnt = 0;
 	return 1;
@@ -408,7 +459,7 @@
 #define OUT_LAST(pack) \
 { HILSE_OUT_LAST,	{ .packet = pack }, 0, 0, 0, 0 },
 
-struct hilse_node hil_mlc_se[HILSEN_END] = {
+const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
 	/* 0  HILSEN_START */
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
@@ -428,7 +479,7 @@
 	EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
 	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
 	OUT(HIL_CTRL_ONLY | 0)			/* Disable test mode */
-	
+
 	/* 9  HILSEN_DHR */
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
 
@@ -439,7 +490,7 @@
 	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
 
 	/* 14 HILSEN_IFC */
-  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
 	       20000,		HILSEN_DISC,	HILSEN_DHR2,	HILSEN_NEXT )
 
@@ -455,7 +506,7 @@
 
 	/* 18 HILSEN_HEAL */
 	OUT_LAST(HIL_CMD_ELB)
-	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 
+	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
 		    20000,	HILSEN_REPOLL,	HILSEN_DSR,	HILSEN_NEXT)
 	FUNC(hilse_dec_ddi, 0,	HILSEN_HEAL,	HILSEN_NEXT,	0)
 
@@ -503,7 +554,7 @@
 
 	/* 44 HILSEN_PROBE */
 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
-	IN(10000, 		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
 	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
 	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
 	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
@@ -514,7 +565,7 @@
 	/* 52 HILSEN_DSR */
 	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
 	OUT(HIL_PKT_CMD | HIL_CMD_DSR)
-	IN(20000, 		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
+	IN(20000,		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
 
 	/* 55 HILSEN_REPOLL */
 	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
@@ -523,14 +574,15 @@
 	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
 
 	/* 58 HILSEN_IFCACF */
-  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
 	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)
 
 	/* 60 HILSEN_END */
 };
 
-static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node)
+{
 
 	switch (node->act) {
 	case HILSE_EXPECT_DISC:
@@ -555,29 +607,27 @@
 	do_gettimeofday(&(mlc->instart));
 	mlc->icount = 15;
 	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
-	BUG_ON(down_trylock(&(mlc->isem)));
-
-	return;
+	BUG_ON(down_trylock(&mlc->isem));
 }
 
 #ifdef HIL_MLC_DEBUG
-static int doze = 0;
+static int doze;
 static int seidx; /* For debug */
-static int kick = 1;
 #endif
 
-static int hilse_donode (hil_mlc *mlc) {
-	struct hilse_node *node;
+static int hilse_donode(hil_mlc *mlc)
+{
+	const struct hilse_node *node;
 	int nextidx = 0;
 	int sched_long = 0;
 	unsigned long flags;
 
 #ifdef HIL_MLC_DEBUG
-	if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
-	  printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+	if (mlc->seidx && mlc->seidx != seidx &&
+	    mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+		printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx);
 		doze = 0;
 	}
-	kick = 0;
 
 	seidx = mlc->seidx;
 #endif
@@ -588,52 +638,61 @@
 		hil_packet pack;
 
 	case HILSE_FUNC:
-		if (node->object.func == NULL) break;
+		BUG_ON(node->object.func == NULL);
 		rc = node->object.func(mlc, node->arg);
-		nextidx = (rc > 0) ? node->ugly : 
+		nextidx = (rc > 0) ? node->ugly :
 			((rc < 0) ? node->bad : node->good);
-		if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+		if (nextidx == HILSEN_FOLLOW)
+			nextidx = rc;
 		break;
+
 	case HILSE_EXPECT_LAST:
 	case HILSE_EXPECT_DISC:
 	case HILSE_EXPECT:
 	case HILSE_IN:
 		/* Already set up from previous HILSE_OUT_* */
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		rc = mlc->in(mlc, node->arg);
 		if (rc == 2)  {
 			nextidx = HILSEN_DOZE;
 			sched_long = 1;
-			write_unlock_irqrestore(&(mlc->lock), flags);
+			write_unlock_irqrestore(&mlc->lock, flags);
 			break;
 		}
-		if (rc == 1)		nextidx = node->ugly;
-		else if (rc == 0)	nextidx = node->good;
-		else			nextidx = node->bad;
+		if (rc == 1)
+			nextidx = node->ugly;
+		else if (rc == 0)
+			nextidx = node->good;
+		else
+			nextidx = node->bad;
 		mlc->istarted = 0;
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 		break;
+
 	case HILSE_OUT_LAST:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
 		goto out;
+
 	case HILSE_OUT_DISC:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
 		goto out;
+
 	case HILSE_OUT:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 	out:
-		if (mlc->istarted) goto out2;
+		if (mlc->istarted)
+			goto out2;
 		/* Prepare to receive input */
 		if ((node + 1)->act & HILSE_IN)
 			hilse_setup_input(mlc, node + 1);
 
 	out2:
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 
 		if (down_trylock(&mlc->osem)) {
 			nextidx = HILSEN_DOZE;
@@ -641,60 +700,71 @@
 		}
 		up(&mlc->osem);
 
-		write_lock_irqsave(&(mlc->lock), flags);
-		if (!(mlc->ostarted)) {
+		write_lock_irqsave(&mlc->lock, flags);
+		if (!mlc->ostarted) {
 			mlc->ostarted = 1;
 			mlc->opacket = pack;
 			mlc->out(mlc);
 			nextidx = HILSEN_DOZE;
-			write_unlock_irqrestore(&(mlc->lock), flags);
+			write_unlock_irqrestore(&mlc->lock, flags);
 			break;
 		}
 		mlc->ostarted = 0;
 		do_gettimeofday(&(mlc->instart));
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 		nextidx = HILSEN_NEXT;
 		break;
+
 	case HILSE_CTS:
+		write_lock_irqsave(&mlc->lock, flags);
 		nextidx = mlc->cts(mlc) ? node->bad : node->good;
+		write_unlock_irqrestore(&mlc->lock, flags);
 		break;
+
 	default:
 		BUG();
-		nextidx = 0;
-		break;
 	}
 
 #ifdef HIL_MLC_DEBUG
-	if (nextidx == HILSEN_DOZE) doze++;
+	if (nextidx == HILSEN_DOZE)
+		doze++;
 #endif
 
 	while (nextidx & HILSEN_SCHED) {
 		struct timeval tv;
 
-		if (!sched_long) goto sched;
+		if (!sched_long)
+			goto sched;
 
 		do_gettimeofday(&tv);
-		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
 		tv.tv_usec -= mlc->instart.tv_usec;
 		if (tv.tv_usec >= mlc->intimeout) goto sched;
-		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
 		if (!tv.tv_usec) goto sched;
 		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
 		break;
 	sched:
 		tasklet_schedule(&hil_mlcs_tasklet);
 		break;
-	} 
-	if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
-	else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
-	else mlc->seidx = nextidx & HILSEN_MASK;
+	}
 
-	if (nextidx & HILSEN_BREAK)	return 1;
+	if (nextidx & HILSEN_DOWN)
+		mlc->seidx += nextidx & HILSEN_MASK;
+	else if (nextidx & HILSEN_UP)
+		mlc->seidx -= nextidx & HILSEN_MASK;
+	else
+		mlc->seidx = nextidx & HILSEN_MASK;
+
+	if (nextidx & HILSEN_BREAK)
+		return 1;
+
 	return 0;
 }
 
 /******************** tasklet context functions **************************/
-static void hil_mlcs_process(unsigned long unused) {
+static void hil_mlcs_process(unsigned long unused)
+{
 	struct list_head *tmp;
 
 	read_lock(&hil_mlcs_lock);
@@ -702,19 +772,20 @@
 		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
 		while (hilse_donode(mlc) == 0) {
 #ifdef HIL_MLC_DEBUG
-		  if (mlc->seidx != 41 && 
-		      mlc->seidx != 42 && 
-		      mlc->seidx != 43) 
-		    printk(KERN_DEBUG PREFIX " + ");
+			if (mlc->seidx != 41 &&
+			    mlc->seidx != 42 &&
+			    mlc->seidx != 43)
+				printk(KERN_DEBUG PREFIX " + ");
 #endif
-		};
+		}
 	}
 	read_unlock(&hil_mlcs_lock);
 }
 
 /************************* Keepalive timer task *********************/
 
-void hil_mlcs_timer (unsigned long data) {
+void hil_mlcs_timer(unsigned long data)
+{
 	hil_mlcs_probe = 1;
 	tasklet_schedule(&hil_mlcs_tasklet);
 	/* Re-insert the periodic task. */
@@ -724,28 +795,25 @@
 
 /******************** user/kernel context functions **********************/
 
-static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 	struct serio_driver *drv;
 	uint8_t *idx, *last;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return -EIO;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return -EIO;
-	}
-	mlc->serio_opacket[map->didx] |= 
+	BUG_ON(mlc == NULL);
+
+	mlc->serio_opacket[map->didx] |=
 		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
 
 	if (mlc->serio_oidx[map->didx] >= 3) {
 		/* for now only commands */
-		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 
+		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
 			return -EIO;
 		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
 		case HIL_CMD_IDD:
@@ -771,12 +839,11 @@
 	return -EIO;
  emu:
 	drv = serio->drv;
-	if (drv == NULL) {
-		BUG();
-		return -EIO;
-	}
+	BUG_ON(drv == NULL);
+
 	last = idx + 15;
-	while ((last != idx) && (*last == 0)) last--;
+	while ((last != idx) && (*last == 0))
+		last--;
 
 	while (idx != last) {
 		drv->interrupt(serio, 0, 0);
@@ -789,14 +856,15 @@
 	drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
 	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0);
 	drv->interrupt(serio, *idx, 0);
-	
+
 	mlc->serio_oidx[map->didx] = 0;
 	mlc->serio_opacket[map->didx] = 0;
 
 	return 0;
 }
 
-static int hil_mlc_serio_open(struct serio *serio) {
+static int hil_mlc_serio_open(struct serio *serio)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 
@@ -804,67 +872,57 @@
 		return -EBUSY;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return -ENODEV;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return -ENODEV;
-	}
+	BUG_ON(mlc == NULL);
 
 	return 0;
 }
 
-static void hil_mlc_serio_close(struct serio *serio) {
+static void hil_mlc_serio_close(struct serio *serio)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(mlc == NULL);
 
 	serio_set_drvdata(serio, NULL);
 	serio->drv = NULL;
 	/* TODO wake up interruptable */
 }
 
-static struct serio_device_id hil_mlc_serio_id = {
+static const struct serio_device_id hil_mlc_serio_id = {
 	.type = SERIO_HIL_MLC,
 	.proto = SERIO_HIL,
 	.extra = SERIO_ANY,
 	.id = SERIO_ANY,
 };
 
-int hil_mlc_register(hil_mlc *mlc) {
+int hil_mlc_register(hil_mlc *mlc)
+{
 	int i;
-        unsigned long flags;
+	unsigned long flags;
 
-	if (mlc == NULL) {
-		return -EINVAL;
-	}
+	BUG_ON(mlc == NULL);
 
 	mlc->istarted = 0;
-        mlc->ostarted = 0;
+	mlc->ostarted = 0;
 
-        rwlock_init(&mlc->lock);
-        init_MUTEX(&(mlc->osem));
+	rwlock_init(&mlc->lock);
+	init_MUTEX(&mlc->osem);
 
-        init_MUTEX(&(mlc->isem));
-        mlc->icount = -1;
-        mlc->imatch = 0;
+	init_MUTEX(&mlc->isem);
+	mlc->icount = -1;
+	mlc->imatch = 0;
 
 	mlc->opercnt = 0;
 
-        init_MUTEX_LOCKED(&(mlc->csem));
+	init_MUTEX_LOCKED(&(mlc->csem));
 
 	hil_mlc_clear_di_scratch(mlc);
 	hil_mlc_clear_di_map(mlc, 0);
@@ -873,6 +931,8 @@
 		hil_mlc_copy_di_scratch(mlc, i);
 		mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
 		mlc->serio[i] = mlc_serio;
+		snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
+		snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
 		mlc_serio->id			= hil_mlc_serio_id;
 		mlc_serio->write		= hil_mlc_serio_write;
 		mlc_serio->open			= hil_mlc_serio_open;
@@ -897,19 +957,18 @@
 	return 0;
 }
 
-int hil_mlc_unregister(hil_mlc *mlc) {
+int hil_mlc_unregister(hil_mlc *mlc)
+{
 	struct list_head *tmp;
-        unsigned long flags;
+	unsigned long flags;
 	int i;
 
-	if (mlc == NULL)
-		return -EINVAL;
+	BUG_ON(mlc == NULL);
 
 	write_lock_irqsave(&hil_mlcs_lock, flags);
-	list_for_each(tmp, &hil_mlcs) {
+	list_for_each(tmp, &hil_mlcs)
 		if (list_entry(tmp, hil_mlc, list) == mlc)
 			goto found;
-	}
 
 	/* not found in list */
 	write_unlock_irqrestore(&hil_mlcs_lock, flags);
@@ -918,7 +977,7 @@
 
  found:
 	list_del(tmp);
-        write_unlock_irqrestore(&hil_mlcs_lock, flags);
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
 
 	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
 		serio_unregister_port(mlc->serio[i]);
@@ -942,7 +1001,7 @@
 
 	return 0;
 }
-                
+
 static void __exit hil_mlc_exit(void)
 {
 	del_timer(&hil_mlcs_kicker);
@@ -950,6 +1009,6 @@
 	tasklet_disable(&hil_mlcs_tasklet);
 	tasklet_kill(&hil_mlcs_tasklet);
 }
-                        
+
 module_init(hil_mlc_init);
 module_exit(hil_mlc_exit);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index b57370d..6af1998 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -34,27 +34,27 @@
  *
  * Driver theory of operation:
  *
- * hp_sdc_put does all writing to the SDC.  ISR can run on a different 
- * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 
+ * hp_sdc_put does all writing to the SDC.  ISR can run on a different
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
  * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
  *
- * All data coming back from the SDC is sent via interrupt and can be read 
- * fully in the ISR, so there are no latency/throughput problems there.  
- * The problem is with output, due to the slow clock speed of the SDC 
- * compared to the CPU.  This should not be too horrible most of the time, 
- * but if used with HIL devices that support the multibyte transfer command, 
- * keeping outbound throughput flowing at the 6500KBps that the HIL is 
+ * All data coming back from the SDC is sent via interrupt and can be read
+ * fully in the ISR, so there are no latency/throughput problems there.
+ * The problem is with output, due to the slow clock speed of the SDC
+ * compared to the CPU.  This should not be too horrible most of the time,
+ * but if used with HIL devices that support the multibyte transfer command,
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is
  * capable of is more than can be done at HZ=100.
  *
- * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf 
- * is set to 0 when the IBF flag in the status register has cleared.  ISR 
- * may do this, and may also access the parts of queued transactions related 
- * to reading data back from the SDC, but otherwise will not touch the 
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf
+ * is set to 0 when the IBF flag in the status register has cleared.  ISR
+ * may do this, and may also access the parts of queued transactions related
+ * to reading data back from the SDC, but otherwise will not touch the
  * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
  *
  * The i8042 write index and the values in the 4-byte input buffer
  * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
- * to minimize the amount of IO needed to the SDC.  However these values 
+ * to minimize the amount of IO needed to the SDC.  However these values
  * do not need to be locked since they are only ever accessed by hp_sdc_put.
  *
  * A timer task schedules the tasklet once per second just to make
@@ -100,39 +100,46 @@
 EXPORT_SYMBOL(hp_sdc_release_hil_irq);
 EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
 
+EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 
 static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
 
 /*************** primitives for use in any context *********************/
-static inline uint8_t hp_sdc_status_in8 (void) {
+static inline uint8_t hp_sdc_status_in8(void)
+{
 	uint8_t status;
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 	status = sdc_readb(hp_sdc.status_io);
-	if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+	if (!(status & HP_SDC_STATUS_IBF))
+		hp_sdc.ibf = 0;
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 
 	return status;
 }
 
-static inline uint8_t hp_sdc_data_in8 (void) {
-	return sdc_readb(hp_sdc.data_io); 
+static inline uint8_t hp_sdc_data_in8(void)
+{
+	return sdc_readb(hp_sdc.data_io);
 }
 
-static inline void hp_sdc_status_out8 (uint8_t val) {
+static inline void hp_sdc_status_out8(uint8_t val)
+{
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 	hp_sdc.ibf = 1;
-	if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+	if ((val & 0xf0) == 0xe0)
+		hp_sdc.wi = 0xff;
 	sdc_writeb(val, hp_sdc.status_io);
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-static inline void hp_sdc_data_out8 (uint8_t val) {
+static inline void hp_sdc_data_out8(uint8_t val)
+{
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
@@ -141,11 +148,12 @@
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-/*	Care must be taken to only invoke hp_sdc_spin_ibf when 
- *	absolutely needed, or in rarely invoked subroutines.  
- *	Not only does it waste CPU cycles, it also wastes bus cycles. 
+/*	Care must be taken to only invoke hp_sdc_spin_ibf when
+ *	absolutely needed, or in rarely invoked subroutines.
+ *	Not only does it waste CPU cycles, it also wastes bus cycles.
  */
-static inline void hp_sdc_spin_ibf(void) {
+static inline void hp_sdc_spin_ibf(void)
+{
 	unsigned long flags;
 	rwlock_t *lock;
 
@@ -158,19 +166,21 @@
 	}
 	read_unlock(lock);
 	write_lock(lock);
-	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
+		{ }
 	hp_sdc.ibf = 0;
 	write_unlock_irqrestore(lock, flags);
 }
 
 
 /************************ Interrupt context functions ************************/
-static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
+{
 	hp_sdc_transaction *curr;
 
 	read_lock(&hp_sdc.rtq_lock);
 	if (hp_sdc.rcurr < 0) {
-	  	read_unlock(&hp_sdc.rtq_lock);
+		read_unlock(&hp_sdc.rtq_lock);
 		return;
 	}
 	curr = hp_sdc.tq[hp_sdc.rcurr];
@@ -183,25 +193,27 @@
 
 	if (hp_sdc.rqty <= 0) {
 		/* All data has been gathered. */
-		if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
-			if (curr->act.semaphore) up(curr->act.semaphore);
-		}
-		if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+		if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
+			if (curr->act.semaphore)
+				up(curr->act.semaphore);
+
+		if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
 			if (curr->act.irqhook)
 				curr->act.irqhook(irq, dev_id, status, data);
-		}
+
 		curr->actidx = curr->idx;
 		curr->idx++;
 		/* Return control of this transaction */
 		write_lock(&hp_sdc.rtq_lock);
-		hp_sdc.rcurr = -1; 
+		hp_sdc.rcurr = -1;
 		hp_sdc.rqty = 0;
 		write_unlock(&hp_sdc.rtq_lock);
 		tasklet_schedule(&hp_sdc.task);
 	}
 }
 
-static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
+{
 	uint8_t status, data;
 
 	status = hp_sdc_status_in8();
@@ -209,67 +221,74 @@
 	data =   hp_sdc_data_in8();
 
 	/* For now we are ignoring these until we get the SDC to behave. */
-	if (((status & 0xf1) == 0x51) && data == 0x82) {
-	  return IRQ_HANDLED;
-	}
+	if (((status & 0xf1) == 0x51) && data == 0x82)
+		return IRQ_HANDLED;
 
-	switch(status & HP_SDC_STATUS_IRQMASK) {
-	      case 0: /* This case is not documented. */
+	switch (status & HP_SDC_STATUS_IRQMASK) {
+	case 0: /* This case is not documented. */
 		break;
-	      case HP_SDC_STATUS_USERTIMER:
-	      case HP_SDC_STATUS_PERIODIC:
-	      case HP_SDC_STATUS_TIMER:
+
+	case HP_SDC_STATUS_USERTIMER:
+	case HP_SDC_STATUS_PERIODIC:
+	case HP_SDC_STATUS_TIMER:
 		read_lock(&hp_sdc.hook_lock);
-	      	if (hp_sdc.timer != NULL)
+		if (hp_sdc.timer != NULL)
 			hp_sdc.timer(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      case HP_SDC_STATUS_REG:
+
+	case HP_SDC_STATUS_REG:
 		hp_sdc_take(irq, dev_id, status, data);
 		break;
-	      case HP_SDC_STATUS_HILCMD:
-	      case HP_SDC_STATUS_HILDATA:
+
+	case HP_SDC_STATUS_HILCMD:
+	case HP_SDC_STATUS_HILDATA:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.hil != NULL)
 			hp_sdc.hil(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      case HP_SDC_STATUS_PUP:
+
+	case HP_SDC_STATUS_PUP:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.pup != NULL)
 			hp_sdc.pup(irq, dev_id, status, data);
-		else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+		else
+			printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      default:
+
+	default:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.cooked != NULL)
 			hp_sdc.cooked(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
 	}
+
 	return IRQ_HANDLED;
 }
 
 
-static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
+{
 	int status;
-	
+
 	status = hp_sdc_status_in8();
 	printk(KERN_WARNING PREFIX "NMI !\n");
 
-#if 0	
+#if 0
 	if (status & HP_SDC_NMISTATUS_FHS) {
 		read_lock(&hp_sdc.hook_lock);
-	      	if (hp_sdc.timer != NULL)
+		if (hp_sdc.timer != NULL)
 			hp_sdc.timer(irq, dev_id, status, 0);
 		read_unlock(&hp_sdc.hook_lock);
-	}
-	else {
+	} else {
 		/* TODO: pass this on to the HIL handler, or do SAK here? */
 		printk(KERN_WARNING PREFIX "HIL NMI\n");
 	}
 #endif
+
 	return IRQ_HANDLED;
 }
 
@@ -278,13 +297,17 @@
 
 unsigned long hp_sdc_put(void);
 
-static void hp_sdc_tasklet(unsigned long foo) {
-
+static void hp_sdc_tasklet(unsigned long foo)
+{
 	write_lock_irq(&hp_sdc.rtq_lock);
+
 	if (hp_sdc.rcurr >= 0) {
 		struct timeval tv;
+
 		do_gettimeofday(&tv);
-		if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+		if (tv.tv_sec > hp_sdc.rtv.tv_sec)
+			tv.tv_usec += USEC_PER_SEC;
+
 		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
 			hp_sdc_transaction *curr;
 			uint8_t tmp;
@@ -300,27 +323,29 @@
 			hp_sdc.rqty = 0;
 			tmp = curr->seq[curr->actidx];
 			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
-			if(tmp & HP_SDC_ACT_SEMAPHORE) {
-				if (curr->act.semaphore) 
+			if (tmp & HP_SDC_ACT_SEMAPHORE)
+				if (curr->act.semaphore)
 					up(curr->act.semaphore);
-			}
-			if(tmp & HP_SDC_ACT_CALLBACK) {
+
+			if (tmp & HP_SDC_ACT_CALLBACK) {
 				/* Note this means that irqhooks may be called
 				 * in tasklet/bh context.
 				 */
-				if (curr->act.irqhook) 
+				if (curr->act.irqhook)
 					curr->act.irqhook(0, NULL, 0, 0);
 			}
+
 			curr->actidx = curr->idx;
 			curr->idx++;
-			hp_sdc.rcurr = -1; 
+			hp_sdc.rcurr = -1;
 		}
 	}
 	write_unlock_irq(&hp_sdc.rtq_lock);
 	hp_sdc_put();
 }
 
-unsigned long hp_sdc_put(void) {
+unsigned long hp_sdc_put(void)
+{
 	hp_sdc_transaction *curr;
 	uint8_t act;
 	int idx, curridx;
@@ -333,19 +358,24 @@
 	   requires output, so we skip to the administrativa. */
 	if (hp_sdc.ibf) {
 		hp_sdc_status_in8();
-		if (hp_sdc.ibf) goto finish;
+		if (hp_sdc.ibf)
+			goto finish;
 	}
 
  anew:
 	/* See if we are in the middle of a sequence. */
-	if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr < 0)
+		hp_sdc.wcurr = 0;
 	read_lock_irq(&hp_sdc.rtq_lock);
-	if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+	if (hp_sdc.rcurr == hp_sdc.wcurr)
+		hp_sdc.wcurr++;
 	read_unlock_irq(&hp_sdc.rtq_lock);
-	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+		hp_sdc.wcurr = 0;
 	curridx = hp_sdc.wcurr;
 
-	if (hp_sdc.tq[curridx] != NULL) goto start;
+	if (hp_sdc.tq[curridx] != NULL)
+		goto start;
 
 	while (++curridx != hp_sdc.wcurr) {
 		if (curridx >= HP_SDC_QUEUE_LEN) {
@@ -358,7 +388,8 @@
 			continue;
 		}
 		read_unlock_irq(&hp_sdc.rtq_lock);
-		if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+		if (hp_sdc.tq[curridx] != NULL)
+			break; /* Found one. */
 	}
 	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
 		curridx = -1;
@@ -374,7 +405,8 @@
 		goto finish;
 	}
 
-	if (hp_sdc.wcurr == -1) goto done;
+	if (hp_sdc.wcurr == -1)
+		goto done;
 
 	curr = hp_sdc.tq[curridx];
 	idx = curr->actidx;
@@ -383,20 +415,23 @@
 		hp_sdc.tq[curridx] = NULL;
 		/* Interleave outbound data between the transactions. */
 		hp_sdc.wcurr++;
-		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-		goto finish;	
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+			hp_sdc.wcurr = 0;
+		goto finish;
 	}
 
 	act = curr->seq[idx];
 	idx++;
 
 	if (curr->idx >= curr->endidx) {
-		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		if (act & HP_SDC_ACT_DEALLOC)
+			kfree(curr);
 		hp_sdc.tq[curridx] = NULL;
 		/* Interleave outbound data between the transactions. */
 		hp_sdc.wcurr++;
-		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-		goto finish;	
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+			hp_sdc.wcurr = 0;
+		goto finish;
 	}
 
 	while (act & HP_SDC_ACT_PRECMD) {
@@ -409,9 +444,10 @@
 		curr->idx++;
 		/* act finished? */
 		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
-		  goto actdone;
+			goto actdone;
 		/* skip quantity field if data-out sequence follows. */
-		if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+		if (act & HP_SDC_ACT_DATAOUT)
+			curr->idx++;
 		goto finish;
 	}
 	if (act & HP_SDC_ACT_DATAOUT) {
@@ -423,15 +459,15 @@
 			hp_sdc_data_out8(curr->seq[curr->idx]);
 			curr->idx++;
 			/* act finished? */
-			if ((curr->idx - idx >= qty) && 
-			    ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+			if (curr->idx - idx >= qty &&
+			    (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
 				goto actdone;
 			goto finish;
 		}
 		idx += qty;
 		act &= ~HP_SDC_ACT_DATAOUT;
-	}
-	else while (act & HP_SDC_ACT_DATAREG) {
+	} else
+	    while (act & HP_SDC_ACT_DATAREG) {
 		int mask;
 		uint8_t w7[4];
 
@@ -445,26 +481,30 @@
 			act &= ~HP_SDC_ACT_DATAREG;
 			break;
 		}
-		
+
 		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
 		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
 		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
 		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
-		
+
 		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
-		        w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+		    w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
 			int i = 0;
 
-			/* Need to point the write index register */	
-			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			/* Need to point the write index register */
+			while (i < 4 && w7[i] == hp_sdc.r7[i])
+				i++;
+
 			if (i < 4) {
 				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
 				hp_sdc.wi = 0x70 + i;
 				goto finish;
 			}
+
 			idx++;
 			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
 				goto actdone;
+
 			curr->idx = idx;
 			act &= ~HP_SDC_ACT_DATAREG;
 			break;
@@ -476,12 +516,13 @@
 		{
 			int i = 0;
 
-			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			while ((i < 4) && w7[i] == hp_sdc.r7[i])
+				i++;
 			if (i >= 4) {
 				curr->idx = idx + 1;
-				if ((act & HP_SDC_ACT_DURING) == 
+				if ((act & HP_SDC_ACT_DURING) ==
 				    HP_SDC_ACT_DATAREG)
-				        goto actdone;
+					goto actdone;
 			}
 		}
 		goto finish;
@@ -497,7 +538,7 @@
 
 
 	if (act & HP_SDC_ACT_POSTCMD) {
-	  	uint8_t postcmd;
+		uint8_t postcmd;
 
 		/* curr->idx should == idx at this point. */
 		postcmd = curr->seq[idx];
@@ -505,12 +546,12 @@
 		if (act & HP_SDC_ACT_DATAIN) {
 
 			/* Start a new read */
-	  		hp_sdc.rqty = curr->seq[curr->idx];
+			hp_sdc.rqty = curr->seq[curr->idx];
 			do_gettimeofday(&hp_sdc.rtv);
 			curr->idx++;
 			/* Still need to lock here in case of spurious irq. */
 			write_lock_irq(&hp_sdc.rtq_lock);
-			hp_sdc.rcurr = curridx; 
+			hp_sdc.rcurr = curridx;
 			write_unlock_irq(&hp_sdc.rtq_lock);
 			hp_sdc_status_out8(postcmd);
 			goto finish;
@@ -519,75 +560,86 @@
 		goto actdone;
 	}
 
-actdone:
-	if (act & HP_SDC_ACT_SEMAPHORE) {
+ actdone:
+	if (act & HP_SDC_ACT_SEMAPHORE)
 		up(curr->act.semaphore);
-	}
-	else if (act & HP_SDC_ACT_CALLBACK) {
+	else if (act & HP_SDC_ACT_CALLBACK)
 		curr->act.irqhook(0,NULL,0,0);
-	}
+
 	if (curr->idx >= curr->endidx) { /* This transaction is over. */
-		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		if (act & HP_SDC_ACT_DEALLOC)
+			kfree(curr);
 		hp_sdc.tq[curridx] = NULL;
-	}
-	else {
+	} else {
 		curr->actidx = idx + 1;
 		curr->idx = idx + 2;
 	}
 	/* Interleave outbound data between the transactions. */
 	hp_sdc.wcurr++;
-	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+		hp_sdc.wcurr = 0;
 
  finish:
-	/* If by some quirk IBF has cleared and our ISR has run to 
+	/* If by some quirk IBF has cleared and our ISR has run to
 	   see that that has happened, do it all again. */
-	if (!hp_sdc.ibf && limit++ < 20) goto anew;
+	if (!hp_sdc.ibf && limit++ < 20)
+		goto anew;
 
  done:
-	if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+	if (hp_sdc.wcurr >= 0)
+		tasklet_schedule(&hp_sdc.task);
 	write_unlock(&hp_sdc.lock);
+
 	return 0;
 }
 
 /******* Functions called in either user or kernel context ****/
-int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
-	unsigned long flags;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
+{
 	int i;
 
 	if (this == NULL) {
-		tasklet_schedule(&hp_sdc.task);
+		BUG();
 		return -EINVAL;
-	};
-
-	write_lock_irqsave(&hp_sdc.lock, flags);
+	}
 
 	/* Can't have same transaction on queue twice */
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-		if (hp_sdc.tq[i] == this) goto fail;
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this)
+			goto fail;
 
 	this->actidx = 0;
 	this->idx = 1;
 
 	/* Search for empty slot */
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
 		if (hp_sdc.tq[i] == NULL) {
 			hp_sdc.tq[i] = this;
-			write_unlock_irqrestore(&hp_sdc.lock, flags);
 			tasklet_schedule(&hp_sdc.task);
 			return 0;
 		}
-	}
-	write_unlock_irqrestore(&hp_sdc.lock, flags);
+
 	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
 	return -EBUSY;
 
  fail:
-	write_unlock_irqrestore(&hp_sdc.lock,flags);
 	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
 	return -EINVAL;
 }
 
-int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int ret;
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+	ret = __hp_sdc_enqueue_transaction(this);
+	write_unlock_irqrestore(&hp_sdc.lock,flags);
+
+	return ret;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
+{
 	unsigned long flags;
 	int i;
 
@@ -595,8 +647,9 @@
 
 	/* TODO: don't remove it if it's not done. */
 
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-		if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this)
+			hp_sdc.tq[i] = NULL;
 
 	write_unlock_irqrestore(&hp_sdc.lock, flags);
 	return 0;
@@ -605,11 +658,11 @@
 
 
 /********************** User context functions **************************/
-int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.timer != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -629,11 +682,11 @@
 	return 0;
 }
 
-int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.hil != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -650,11 +703,11 @@
 	return 0;
 }
 
-int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.cooked != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -672,9 +725,8 @@
 	return 0;
 }
 
-int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
-
-
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.timer) ||
 	    (hp_sdc.timer == NULL)) {
@@ -694,8 +746,8 @@
 	return 0;
 }
 
-int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.hil) ||
 	    (hp_sdc.hil == NULL)) {
@@ -715,8 +767,8 @@
 	return 0;
 }
 
-int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.cooked) ||
 	    (hp_sdc.cooked == NULL)) {
@@ -738,7 +790,8 @@
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data) {
+void hp_sdc_kicker (unsigned long data)
+{
 	tasklet_schedule(&hp_sdc.task);
 	/* Re-insert the periodic task. */
 	mod_timer(&hp_sdc.kicker, jiffies + HZ);
@@ -748,12 +801,12 @@
 
 #if defined(__hppa__)
 
-static struct parisc_device_id hp_sdc_tbl[] = {
+static const struct parisc_device_id hp_sdc_tbl[] = {
 	{
-		.hw_type =	HPHW_FIO, 
+		.hw_type =	HPHW_FIO,
 		.hversion_rev =	HVERSION_REV_ANY_ID,
 		.hversion =	HVERSION_ANY_ID,
-		.sversion =	0x73, 
+		.sversion =	0x73,
 	 },
 	{ 0, }
 };
@@ -772,16 +825,15 @@
 
 static int __init hp_sdc_init(void)
 {
-	int i;
 	char *errstr;
 	hp_sdc_transaction t_sync;
 	uint8_t ts_sync[6];
 	struct semaphore s_sync;
 
-  	rwlock_init(&hp_sdc.lock);
-  	rwlock_init(&hp_sdc.ibf_lock);
-  	rwlock_init(&hp_sdc.rtq_lock);
-  	rwlock_init(&hp_sdc.hook_lock);
+	rwlock_init(&hp_sdc.lock);
+	rwlock_init(&hp_sdc.ibf_lock);
+	rwlock_init(&hp_sdc.rtq_lock);
+	rwlock_init(&hp_sdc.hook_lock);
 
 	hp_sdc.timer		= NULL;
 	hp_sdc.hil		= NULL;
@@ -796,7 +848,8 @@
 	hp_sdc.r7[3]		= 0xff;
 	hp_sdc.ibf		= 1;
 
-	for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+	memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
+
 	hp_sdc.wcurr		= -1;
         hp_sdc.rcurr		= -1;
 	hp_sdc.rqty		= 0;
@@ -804,27 +857,32 @@
 	hp_sdc.dev_err = -ENODEV;
 
 	errstr = "IO not found for";
-	if (!hp_sdc.base_io) goto err0;
+	if (!hp_sdc.base_io)
+		goto err0;
 
 	errstr = "IRQ not found for";
-	if (!hp_sdc.irq) goto err0;
+	if (!hp_sdc.irq)
+		goto err0;
 
 	hp_sdc.dev_err = -EBUSY;
 
 #if defined(__hppa__)
 	errstr = "IO not available for";
-        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
-#endif	
+        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
+		goto err0;
+#endif
 
 	errstr = "IRQ not available for";
-        if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
-		       (void *) hp_sdc.base_io)) goto err1;
+	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
+			"HP SDC", &hp_sdc))
+		goto err1;
 
 	errstr = "NMI not available for";
-	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 
-			(void *) hp_sdc.base_io)) goto err2;
+	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
+			"HP SDC NMI", &hp_sdc))
+		goto err2;
 
-	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 
+	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
 	       (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 
 	hp_sdc_status_in8();
@@ -854,13 +912,14 @@
 	hp_sdc.dev_err = 0;
 	return 0;
  err2:
-	free_irq(hp_sdc.irq, NULL);
+	free_irq(hp_sdc.irq, &hp_sdc);
  err1:
 	release_region(hp_sdc.data_io, 2);
  err0:
-	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 
+	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
 		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 	hp_sdc.dev = NULL;
+
 	return hp_sdc.dev_err;
 }
 
@@ -868,8 +927,10 @@
 
 static int __init hp_sdc_init_hppa(struct parisc_device *d)
 {
-	if (!d) return 1;
-	if (hp_sdc.dev != NULL) return 1;	/* We only expect one SDC */
+	if (!d)
+		return 1;
+	if (hp_sdc.dev != NULL)
+		return 1;	/* We only expect one SDC */
 
 	hp_sdc.dev		= d;
 	hp_sdc.irq		= d->irq;
@@ -898,18 +959,16 @@
 	/* Wait until we know this has been processed by the i8042 */
 	hp_sdc_spin_ibf();
 
-	free_irq(hp_sdc.nmi, NULL);
-	free_irq(hp_sdc.irq, NULL);
+	free_irq(hp_sdc.nmi, &hp_sdc);
+	free_irq(hp_sdc.irq, &hp_sdc);
 	write_unlock_irq(&hp_sdc.lock);
 
 	del_timer(&hp_sdc.kicker);
 
 	tasklet_kill(&hp_sdc.task);
 
-/*        release_region(hp_sdc.data_io, 2); */
-
 #if defined(__hppa__)
-	if (unregister_parisc_driver(&hp_sdc_driver)) 
+	if (unregister_parisc_driver(&hp_sdc_driver))
 		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
 #endif
 }
@@ -923,7 +982,7 @@
 	mm_segment_t fs;
 	unsigned char i;
 #endif
-	
+
 	hp_sdc.dev = NULL;
 	hp_sdc.dev_err = 0;
 #if defined(__hppa__)
@@ -960,8 +1019,8 @@
 	tq_init.seq		= tq_init_seq;
 	tq_init.act.semaphore	= &tq_init_sem;
 
-	tq_init_seq[0] = 
-	  HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	tq_init_seq[0] =
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
 	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
 	tq_init_seq[2] = 1;
 	tq_init_seq[3] = 0;
@@ -979,13 +1038,13 @@
 	}
 	hp_sdc.r11 = tq_init_seq[4];
 	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
-		char *str;
+		const char *str;
 		printk(KERN_INFO PREFIX "New style SDC\n");
 		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
 		tq_init.actidx		= 0;
 		tq_init.idx		= 1;
 		down(&tq_init_sem);
-		hp_sdc_enqueue_transaction(&tq_init);		
+		hp_sdc_enqueue_transaction(&tq_init);
 		down(&tq_init_sem);
 		up(&tq_init_sem);
 		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
@@ -995,15 +1054,13 @@
 		hp_sdc.r7e = tq_init_seq[4];
 		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
 		printk(KERN_INFO PREFIX "Revision: %s\n", str);
-		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
 			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
-		}
-		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
 			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
-		}
 		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
 		       "on next firmware reset.\n");
-		tq_init_seq[0] = HP_SDC_ACT_PRECMD | 
+		tq_init_seq[0] = HP_SDC_ACT_PRECMD |
 			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
 		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
 		tq_init_seq[2] = 1;
@@ -1012,14 +1069,12 @@
 		tq_init.idx		= 1;
 		tq_init.endidx		= 4;
 		down(&tq_init_sem);
-		hp_sdc_enqueue_transaction(&tq_init);		
+		hp_sdc_enqueue_transaction(&tq_init);
 		down(&tq_init_sem);
 		up(&tq_init_sem);
-	}
-	else {
-		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 
+	} else
+		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
 		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
-	}
 
         return 0;
 }
@@ -1027,13 +1082,13 @@
 module_init(hp_sdc_register);
 module_exit(hp_sdc_exit);
 
-/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64) 
+/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
  *                                              cycles cycles-adj    time
  * between two consecutive mfctl(16)'s:              4        n/a    63ns
  * hp_sdc_spin_ibf when idle:                      119        115   1.7us
  * gsc_writeb status register:                      83         79   1.2us
  * IBF to clear after sending SET_IM:             6204       6006    93us
- * IBF to clear after sending LOAD_RT:            4467       4352    68us  
+ * IBF to clear after sending LOAD_RT:            4467       4352    68us
  * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
  * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
  * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index aa4a8a4..c45ea74 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -58,12 +58,13 @@
 } hp_sdc_mlc_priv;
 
 /************************* Interrupt context ******************************/
-static void hp_sdc_mlc_isr (int irq, void *dev_id, 
-			    uint8_t status, uint8_t data) {
-  	int idx;
+static void hp_sdc_mlc_isr (int irq, void *dev_id,
+			    uint8_t status, uint8_t data)
+{
+	int idx;
 	hil_mlc *mlc = &hp_sdc_mlc;
 
-	write_lock(&(mlc->lock));
+	write_lock(&mlc->lock);
 	if (mlc->icount < 0) {
 		printk(KERN_WARNING PREFIX "HIL Overflow!\n");
 		up(&mlc->isem);
@@ -73,239 +74,232 @@
 	if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
 		mlc->ipacket[idx] |= data | HIL_ERR_INT;
 		mlc->icount--;
-		if (hp_sdc_mlc_priv.got5x) goto check;
-		if (!idx) goto check;
-		if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+		if (hp_sdc_mlc_priv.got5x || !idx)
+			goto check;
+		if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) !=
 		    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
 			mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
-			mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 
-						    & HIL_PKT_ADDR_MASK);
+			mlc->ipacket[idx] |= (mlc->ipacket[idx - 1]
+						& HIL_PKT_ADDR_MASK);
 		}
 		goto check;
 	}
 	/* We know status is 5X */
-	if (data & HP_SDC_HIL_ISERR) goto err;
-	mlc->ipacket[idx] = 
+	if (data & HP_SDC_HIL_ISERR)
+		goto err;
+	mlc->ipacket[idx] =
 		(data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
 	hp_sdc_mlc_priv.got5x = 1;
 	goto out;
 
  check:
 	hp_sdc_mlc_priv.got5x = 0;
-	if (mlc->imatch == 0) goto done;
-	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 
-	    && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
-	if (mlc->ipacket[idx] == mlc->imatch) goto done;
+	if (mlc->imatch == 0)
+		goto done;
+	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+	    && (mlc->ipacket[idx] == (mlc->imatch | idx)))
+		goto done;
+	if (mlc->ipacket[idx] == mlc->imatch)
+		goto done;
 	goto out;
 
- err:				
+ err:
 	printk(KERN_DEBUG PREFIX "err code %x\n", data);
+
 	switch (data) {
 	case HP_SDC_HIL_RC_DONE:
 		printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
 		break;
+
 	case HP_SDC_HIL_ERR:
-		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 
-		  HIL_ERR_FERR | HIL_ERR_FOF;
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
+					HIL_ERR_FERR | HIL_ERR_FOF;
 		break;
+
 	case HP_SDC_HIL_TO:
 		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
 		break;
+
 	case HP_SDC_HIL_RC:
 		printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
 		break;
+
 	default:
 		printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
 		break;
 	}
+
 	/* No more data will be coming due to an error. */
  done:
 	tasklet_schedule(mlc->tasklet);
-	up(&(mlc->isem));
+	up(&mlc->isem);
  out:
-	write_unlock(&(mlc->lock));
+	write_unlock(&mlc->lock);
 }
 
 
 /******************** Tasklet or userspace context functions ****************/
 
-static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
-	unsigned long flags;
+static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
+{
 	struct hp_sdc_mlc_priv_s *priv;
 	int rc = 2;
 
 	priv = mlc->priv;
 
-	write_lock_irqsave(&(mlc->lock), flags);
-
 	/* Try to down the semaphore */
-	if (down_trylock(&(mlc->isem))) {
+	if (down_trylock(&mlc->isem)) {
 		struct timeval tv;
 		if (priv->emtestmode) {
-			mlc->ipacket[0] = 
-				HIL_ERR_INT | (mlc->opacket & 
-					       (HIL_PKT_CMD | 
-						HIL_PKT_ADDR_MASK | 
+			mlc->ipacket[0] =
+				HIL_ERR_INT | (mlc->opacket &
+					       (HIL_PKT_CMD |
+						HIL_PKT_ADDR_MASK |
 						HIL_PKT_DATA_MASK));
 			mlc->icount = 14;
 			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
 			goto wasup;
 		}
 		do_gettimeofday(&tv);
-		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
 		if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
-		  /*		  printk("!%i %i", 
-				  tv.tv_usec - mlc->instart.tv_usec, 
-				  mlc->intimeout);
-		  */
+			/*	printk("!%i %i",
+				tv.tv_usec - mlc->instart.tv_usec,
+				mlc->intimeout);
+			 */
 			rc = 1;
-			up(&(mlc->isem));
+			up(&mlc->isem);
 		}
 		goto done;
 	}
  wasup:
-	up(&(mlc->isem));
+	up(&mlc->isem);
 	rc = 0;
-	goto done;
  done:
-	write_unlock_irqrestore(&(mlc->lock), flags);
 	return rc;
 }
 
-static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+static int hp_sdc_mlc_cts(hil_mlc *mlc)
+{
 	struct hp_sdc_mlc_priv_s *priv;
-	unsigned long flags;
 
-	priv = mlc->priv;	
-
-	write_lock_irqsave(&(mlc->lock), flags);
+	priv = mlc->priv;
 
 	/* Try to down the semaphores -- they should be up. */
-	if (down_trylock(&(mlc->isem))) {
-		BUG();
-		goto busy;
-	}
-	if (down_trylock(&(mlc->osem))) {
-	 	BUG();
-		up(&(mlc->isem));
-		goto busy;
-	}
-	up(&(mlc->isem));
-	up(&(mlc->osem));
+	BUG_ON(down_trylock(&mlc->isem));
+	BUG_ON(down_trylock(&mlc->osem));
 
-	if (down_trylock(&(mlc->csem))) {
-		if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
-		goto busy;
+	up(&mlc->isem);
+	up(&mlc->osem);
+
+	if (down_trylock(&mlc->csem)) {
+		if (priv->trans.act.semaphore != &mlc->csem)
+			goto poll;
+		else
+			goto busy;
 	}
-	if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+	if (!(priv->tseq[4] & HP_SDC_USE_LOOP))
+		goto done;
 
  poll:
-	priv->trans.act.semaphore = &(mlc->csem);
+	priv->trans.act.semaphore = &mlc->csem;
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
 	priv->trans.endidx = 5;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = HP_SDC_CMD_READ_USE;
 	priv->tseq[2] = 1;
 	priv->tseq[3] = 0;
 	priv->tseq[4] = 0;
-	hp_sdc_enqueue_transaction(&(priv->trans));
+	__hp_sdc_enqueue_transaction(&priv->trans);
  busy:
-	write_unlock_irqrestore(&(mlc->lock), flags);
 	return 1;
  done:
-	priv->trans.act.semaphore = &(mlc->osem);
-	up(&(mlc->csem));
-	write_unlock_irqrestore(&(mlc->lock), flags);
+	priv->trans.act.semaphore = &mlc->osem;
+	up(&mlc->csem);
 	return 0;
 }
 
-static void hp_sdc_mlc_out (hil_mlc *mlc) {
+static void hp_sdc_mlc_out(hil_mlc *mlc)
+{
 	struct hp_sdc_mlc_priv_s *priv;
-	unsigned long flags;
 
 	priv = mlc->priv;
 
-	write_lock_irqsave(&(mlc->lock), flags);
-	
 	/* Try to down the semaphore -- it should be up. */
-	if (down_trylock(&(mlc->osem))) {
-	 	BUG();
-		goto done;
-	}
+	BUG_ON(down_trylock(&mlc->osem));
 
-	if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+	if (mlc->opacket & HIL_DO_ALTER_CTRL)
+		goto do_control;
 
  do_data:
 	if (priv->emtestmode) {
-		up(&(mlc->osem));
-		goto done;
+		up(&mlc->osem);
+		return;
 	}
 	/* Shouldn't be sending commands when loop may be busy */
-	if (down_trylock(&(mlc->csem))) {
-	 	BUG();
-		goto done;
-	}
-	up(&(mlc->csem));
+	BUG_ON(down_trylock(&mlc->csem));
+	up(&mlc->csem);
 
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
-	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.act.semaphore = &mlc->osem;
 	priv->trans.endidx = 6;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 		HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = 0x7;
-	priv->tseq[2] = 
-		(mlc->opacket & 
+	priv->tseq[2] =
+		(mlc->opacket &
 		 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
 		   >> HIL_PKT_ADDR_SHIFT;
-	priv->tseq[3] = 
-		(mlc->opacket & HIL_PKT_DATA_MASK) 
+	priv->tseq[3] =
+		(mlc->opacket & HIL_PKT_DATA_MASK)
 		  >> HIL_PKT_DATA_SHIFT;
 	priv->tseq[4] = 0;  /* No timeout */
-	if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+	if (priv->tseq[3] == HIL_CMD_DHR)
+		priv->tseq[4] = 1;
 	priv->tseq[5] = HP_SDC_CMD_DO_HIL;
 	goto enqueue;
 
  do_control:
 	priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
-	
+
 	/* we cannot emulate this, it should not be used. */
 	BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
-	
-	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
-	if (mlc->opacket & HIL_CTRL_APE) { 
-		BUG(); /* Should not send command/data after engaging APE */
-		goto done;
-	}
-	/* Disengaging APE this way would not be valid either since 
+
+	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY)
+		goto control_only;
+
+	/* Should not send command/data after engaging APE */
+	BUG_ON(mlc->opacket & HIL_CTRL_APE);
+
+	/* Disengaging APE this way would not be valid either since
 	 * the loop must be allowed to idle.
 	 *
-	 * So, it works out that we really never actually send control 
-	 * and data when using SDC, we just send the data. 
+	 * So, it works out that we really never actually send control
+	 * and data when using SDC, we just send the data.
 	 */
 	goto do_data;
 
  control_only:
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
-	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.act.semaphore = &mlc->osem;
 	priv->trans.endidx = 4;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 	  HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = HP_SDC_CMD_SET_LPC;
 	priv->tseq[2] = 1;
-	//	priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+	/* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */
 	priv->tseq[3] = 0;
 	if (mlc->opacket & HIL_CTRL_APE) {
 		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
-		down_trylock(&(mlc->csem));
-	} 
+		down_trylock(&mlc->csem);
+	}
  enqueue:
-	hp_sdc_enqueue_transaction(&(priv->trans));
- done:
-	write_unlock_irqrestore(&(mlc->lock), flags);
+	hp_sdc_enqueue_transaction(&priv->trans);
 }
 
 static int __init hp_sdc_mlc_init(void)
@@ -316,18 +310,18 @@
 
 	hp_sdc_mlc_priv.emtestmode = 0;
 	hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
-	hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+	hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem;
 	hp_sdc_mlc_priv.got5x = 0;
 
-	mlc->cts		= &hp_sdc_mlc_cts;
-	mlc->in			= &hp_sdc_mlc_in;
-	mlc->out		= &hp_sdc_mlc_out;
+	mlc->cts = &hp_sdc_mlc_cts;
+	mlc->in	= &hp_sdc_mlc_in;
+	mlc->out = &hp_sdc_mlc_out;
+	mlc->priv = &hp_sdc_mlc_priv;
 
 	if (hil_mlc_register(mlc)) {
 		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
 		goto err0;
 	}
-	mlc->priv		= &hp_sdc_mlc_priv;
 
 	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
 		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
@@ -335,10 +329,9 @@
 	}
 	return 0;
  err1:
-	if (hil_mlc_unregister(mlc)) {
+	if (hil_mlc_unregister(mlc))
 		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
  err0:
 	return -EBUSY;
 }
@@ -346,14 +339,14 @@
 static void __exit hp_sdc_mlc_exit(void)
 {
 	hil_mlc *mlc = &hp_sdc_mlc;
-	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+
+	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr))
 		printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
-	if (hil_mlc_unregister(mlc)) {
+
+	if (hil_mlc_unregister(mlc))
 		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
 }
 
 module_init(hp_sdc_mlc_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index d36bd54..6858bc5 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -160,6 +160,28 @@
 		},
 	},
 	{
+		/*
+		 * No data is coming from the touchscreen unless KBC
+		 * is in legacy mode.
+		 */
+		.ident = "Panasonic CF-29",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+		},
+	},
+	{
+		/*
+		 * Errors on MUX ports are reported without raising AUXDATA
+		 * causing "spurious NAK" messages.
+		 */
+		.ident = "HP Pavilion DV4017EA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+		},
+	},
+	{
 		.ident = "Toshiba P10",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -280,6 +302,8 @@
 };
 
 static struct pnp_device_id pnp_aux_devids[] = {
+	{ .id = "FJC6000", .driver_data = 0 },
+	{ .id = "FJC6001", .driver_data = 0 },
 	{ .id = "PNP0f03", .driver_data = 0 },
 	{ .id = "PNP0f0b", .driver_data = 0 },
 	{ .id = "PNP0f0e", .driver_data = 0 },
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index db9cca3..7c17377 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -768,6 +768,13 @@
 	i8042_flush();
 
 /*
+ * Disable both KBD and AUX interfaces so they don't get in the way
+ */
+
+	i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
+	i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
+
+/*
  * Disable MUX mode if present.
  */
 
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 0a26e06..693e3b2 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -39,7 +39,8 @@
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
- * Support for ads7843 and ads7845 has only been stubbed in.
+ * Support for ads7843 tested on Atmel at91sam926x-EK.
+ * Support for ads7845 has only been stubbed in.
  *
  * IRQ handling needs a workaround because of a shortcoming in handling
  * edge triggered IRQs on some platforms like the OMAP1/2. These
@@ -246,18 +247,16 @@
 
 	/* REVISIT:  take a few more samples, and compare ... */
 
-	/* maybe off internal vREF */
-	if (use_internal) {
-		req->ref_off = REF_OFF;
-		req->xfer[4].tx_buf = &req->ref_off;
-		req->xfer[4].len = 1;
-		spi_message_add_tail(&req->xfer[4], &req->msg);
+	/* converter in low power mode & enable PENIRQ */
+	req->ref_off = PWRDOWN;
+	req->xfer[4].tx_buf = &req->ref_off;
+	req->xfer[4].len = 1;
+	spi_message_add_tail(&req->xfer[4], &req->msg);
 
-		req->xfer[5].rx_buf = &req->scratch;
-		req->xfer[5].len = 2;
-		CS_CHANGE(req->xfer[5]);
-		spi_message_add_tail(&req->xfer[5], &req->msg);
-	}
+	req->xfer[5].rx_buf = &req->scratch;
+	req->xfer[5].len = 2;
+	CS_CHANGE(req->xfer[5]);
+	spi_message_add_tail(&req->xfer[5], &req->msg);
 
 	ts->irq_disabled = 1;
 	disable_irq(spi->irq);
@@ -536,6 +535,9 @@
 	} else
 		Rt = 0;
 
+	if (ts->model == 7843)
+		Rt = ts->pressure_max / 2;
+
 	/* Sample found inconsistent by debouncing or pressure is beyond
 	 * the maximum. Don't report it to user space, repeat at least
 	 * once more the measurement
@@ -897,7 +899,7 @@
 
 	input_dev->name = "ADS784x Touchscreen";
 	input_dev->phys = ts->phys;
-	input_dev->cdev.dev = &spi->dev;
+	input_dev->dev.parent = &spi->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index e294558..e6a31d1 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -300,8 +300,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0002;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = corgi_ts;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 9d61cd1..557d781 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -312,14 +312,13 @@
 	init_completion(&elo->cmd_done);
 	snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
 
-	input_dev->private = elo;
 	input_dev->name = "Elo Serial TouchScreen";
 	input_dev->phys = elo->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_ELO;
 	input_dev->id.product = elo->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 9157eb1..39d6026 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -130,13 +130,13 @@
 	gunze->dev = input_dev;
 	snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
 
-	input_dev->private = gunze;
 	input_dev->name = "Gunze AHL-51S TouchScreen";
 	input_dev->phys = gunze->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_GUNZE;
 	input_dev->id.product = 0x0051;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index c4116d4..09ed780 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -147,7 +147,7 @@
 unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
 {
 	unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness;
-	struct h3600_dev *ts = dev->private;
+	struct h3600_dev *ts = input_get_drvdata(dev);
 
 	/* Must be in this order */
 	ts->serio->write(ts->serio, 1);
@@ -260,7 +260,7 @@
 			 unsigned int code, int value)
 {
 #if 0
-	struct h3600_dev *ts = dev->private;
+	struct h3600_dev *ts = input_get_drvdata(dev);
 
 	switch (type) {
 		case EV_LED: {
@@ -367,8 +367,9 @@
 	input_dev->id.vendor = SERIO_H3600;
 	input_dev->id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = ts;
+	input_dev->dev.parent = &serio->dev;
+
+	input_set_drvdata(input_dev, ts);
 
 	input_dev->event = h3600ts_event;
 
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index c3c2d73..4ec3b1f 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -144,13 +144,13 @@
 	mtouch->dev = input_dev;
 	snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
 
-	input_dev->private = mtouch;
 	input_dev->name = "MicroTouch Serial TouchScreen";
 	input_dev->phys = mtouch->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_MICROTOUCH;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index bd27679..f2c0d3c 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -105,14 +105,13 @@
 	pm->dev = input_dev;
 	snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
 
-	input_dev->private = pm;
 	input_dev->name = "Penmount Serial TouchScreen";
 	input_dev->phys = pm->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_PENMOUNT;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
         input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 35ba46c..3def7bb 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -118,13 +118,13 @@
 	tr->dev = input_dev;
 	snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
 
-	input_dev->private = tr;
 	input_dev->name = "Touchright Serial TouchScreen";
 	input_dev->phys = tr->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_TOUCHRIGHT;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index 4dc073d..ac4bdcf 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -125,13 +125,13 @@
 	tw->dev = input_dev;
 	snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
 
-	input_dev->private = tw;
 	input_dev->name = "Touchwindow Serial TouchScreen";
 	input_dev->phys = tw->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_TOUCHWIN;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index e8606c4..6582816 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -97,6 +97,8 @@
 };
 
 static int adcsync;
+static int ts_delay = 55; /* us */
+static int ts_delay_pressure;	/* us */
 
 static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
 {
@@ -159,6 +161,7 @@
 			UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
 			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
 			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	udelay(ts_delay_pressure);
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
 
@@ -180,7 +183,7 @@
 			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-	udelay(55);
+	udelay(ts_delay);
 
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
@@ -203,7 +206,7 @@
 			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-	udelay(55);
+	udelay(ts_delay);
 
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
 }
@@ -369,7 +372,7 @@
 
 static int ucb1400_ts_open(struct input_dev *idev)
 {
-	struct ucb1400 *ucb = idev->private;
+	struct ucb1400 *ucb = input_get_drvdata(idev);
 	int ret = 0;
 
 	BUG_ON(ucb->ts_task);
@@ -385,7 +388,7 @@
 
 static void ucb1400_ts_close(struct input_dev *idev)
 {
-	struct ucb1400 *ucb = idev->private;
+	struct ucb1400 *ucb = input_get_drvdata(idev);
 
 	if (ucb->ts_task)
 		kthread_stop(ucb->ts_task);
@@ -507,8 +510,9 @@
 	}
 	printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
 
-	idev->private		= ucb;
-	idev->cdev.dev		= dev;
+	input_set_drvdata(idev, ucb);
+
+	idev->dev.parent	= dev;
 	idev->name		= "UCB1400 touchscreen interface";
 	idev->id.vendor		= ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
 	idev->id.product	= id;
@@ -571,7 +575,15 @@
 	driver_unregister(&ucb1400_ts_driver);
 }
 
-module_param(adcsync, int, 0444);
+module_param(adcsync, bool, 0444);
+MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
+
+module_param(ts_delay, int, 0444);
+MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us.");
+
+module_param(ts_delay_pressure, int, 0444);
+MODULE_PARM_DESC(ts_delay_pressure,
+		  "delay between panel setup and pressure read.  Default = 0us.");
 
 module_init(ucb1400_ts_init);
 module_exit(ucb1400_ts_exit);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 0300dca..8e2d2c9 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -111,13 +111,13 @@
 	int minor;
 	char name[8];
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct input_handle handle;
 	int x, y, pressure;
 	struct ts_calibration cal;
 };
 
-struct tsdev_list {
+struct tsdev_client {
 	struct fasync_struct *fasync;
 	struct list_head node;
 	struct tsdev *tsdev;
@@ -139,38 +139,49 @@
 
 static int tsdev_fasync(int fd, struct file *file, int on)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
 	int retval;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 	return retval < 0 ? retval : 0;
 }
 
 static int tsdev_open(struct inode *inode, struct file *file)
 {
 	int i = iminor(inode) - TSDEV_MINOR_BASE;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
+	struct tsdev *tsdev;
+	int error;
 
 	printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
 		"for removal.\nSee Documentation/feature-removal-schedule.txt "
 		"for details.\n");
 
-	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
+	if (i >= TSDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+	tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
+	if (!tsdev || !tsdev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+	client->tsdev = tsdev;
+	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
+	list_add_tail(&client->node, &tsdev->client_list);
 
-	i &= TSDEV_MINOR_MASK;
-	list->tsdev = tsdev_table[i];
-	list_add_tail(&list->node, &tsdev_table[i]->list);
-	file->private_data = list;
+	if (!tsdev->open++ && tsdev->exist) {
+		error = input_open_device(&tsdev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
-	if (!list->tsdev->open++)
-		if (list->tsdev->exist)
-			input_open_device(&list->tsdev->handle);
+	file->private_data = client;
 	return 0;
 }
 
@@ -182,45 +193,48 @@
 
 static int tsdev_release(struct inode *inode, struct file *file)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 
 	tsdev_fasync(-1, file, 0);
-	list_del(&list->node);
 
-	if (!--list->tsdev->open) {
-		if (list->tsdev->exist)
-			input_close_device(&list->tsdev->handle);
+	list_del(&client->node);
+	kfree(client);
+
+	if (!--tsdev->open) {
+		if (tsdev->exist)
+			input_close_device(&tsdev->handle);
 		else
-			tsdev_free(list->tsdev);
+			tsdev_free(tsdev);
 	}
-	kfree(list);
+
 	return 0;
 }
 
 static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
-			  loff_t * ppos)
+			  loff_t *ppos)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 	int retval = 0;
 
-	if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
+	if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->tsdev->wait,
-			list->head != list->tail || !list->tsdev->exist);
-
+	retval = wait_event_interruptible(tsdev->wait,
+			client->head != client->tail || !tsdev->exist);
 	if (retval)
 		return retval;
 
-	if (!list->tsdev->exist)
+	if (!tsdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail &&
+	while (client->head != client->tail &&
 	       retval + sizeof (struct ts_event) <= count) {
-		if (copy_to_user (buffer + retval, list->event + list->tail,
+		if (copy_to_user (buffer + retval, client->event + client->tail,
 				  sizeof (struct ts_event)))
 			return -EFAULT;
-		list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
 		retval += sizeof (struct ts_event);
 	}
 
@@ -228,32 +242,33 @@
 }
 
 /* No kernel lock - fine */
-static unsigned int tsdev_poll(struct file *file, poll_table * wait)
+static unsigned int tsdev_poll(struct file *file, poll_table *wait)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 
-	poll_wait(file, &list->tsdev->wait, wait);
-	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &tsdev->wait, wait);
+	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(tsdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int tsdev_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
-	struct tsdev_list *list = file->private_data;
-	struct tsdev *tsdev = list->tsdev;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 	int retval = 0;
 
 	switch (cmd) {
 	case TS_GET_CAL:
-		if (copy_to_user ((void __user *)arg, &tsdev->cal,
-				  sizeof (struct ts_calibration)))
+		if (copy_to_user((void __user *)arg, &tsdev->cal,
+				 sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
 
 	case TS_SET_CAL:
-		if (copy_from_user (&tsdev->cal, (void __user *)arg,
-				    sizeof (struct ts_calibration)))
+		if (copy_from_user(&tsdev->cal, (void __user *)arg,
+				   sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
 
@@ -279,7 +294,7 @@
 			unsigned int code, int value)
 {
 	struct tsdev *tsdev = handle->private;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
 	struct timeval time;
 
 	switch (type) {
@@ -343,18 +358,18 @@
 	if (type != EV_SYN || code != SYN_REPORT)
 		return;
 
-	list_for_each_entry(list, &tsdev->list, node) {
+	list_for_each_entry(client, &tsdev->client_list, node) {
 		int x, y, tmp;
 
 		do_gettimeofday(&time);
-		list->event[list->head].millisecs = time.tv_usec / 100;
-		list->event[list->head].pressure = tsdev->pressure;
+		client->event[client->head].millisecs = time.tv_usec / 100;
+		client->event[client->head].pressure = tsdev->pressure;
 
 		x = tsdev->x;
 		y = tsdev->y;
 
 		/* Calibration */
-		if (!list->raw) {
+		if (!client->raw) {
 			x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
 			y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
 			if (tsdev->cal.xyswap) {
@@ -362,33 +377,35 @@
 			}
 		}
 
-		list->event[list->head].x = x;
-		list->event[list->head].y = y;
-		list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		client->event[client->head].x = x;
+		client->event[client->head].y = y;
+		client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
 	wake_up_interruptible(&tsdev->wait);
 }
 
-static struct input_handle *tsdev_connect(struct input_handler *handler,
-					  struct input_dev *dev,
-					  const struct input_device_id *id)
+static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct tsdev *tsdev;
 	struct class_device *cdev;
+	dev_t devt;
 	int minor, delta;
+	int error;
 
 	for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
 	if (minor >= TSDEV_MINORS / 2) {
 		printk(KERN_ERR
 		       "tsdev: You have way too many touchscreens\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
-		return NULL;
+	tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
+	if (!tsdev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&tsdev->list);
+	INIT_LIST_HEAD(&tsdev->client_list);
 	init_waitqueue_head(&tsdev->wait);
 
 	sprintf(tsdev->name, "ts%d", minor);
@@ -415,21 +432,43 @@
 
 	tsdev_table[minor] = tsdev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			dev->cdev.dev, tsdev->name);
+	devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, tsdev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_tsdev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  tsdev->name);
+	error = sysfs_create_link(&input_class.subsys.kset.kobj,
+				  &cdev->kobj, tsdev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &tsdev->handle;
+	error = input_register_handle(&tsdev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_tsdev:
+	tsdev_table[minor] = NULL;
+	kfree(tsdev);
+	return error;
 }
 
 static void tsdev_disconnect(struct input_handle *handle)
 {
 	struct tsdev *tsdev = handle->private;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
+
+	input_unregister_handle(handle);
 
 	sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
 	class_device_destroy(&input_class,
@@ -439,8 +478,8 @@
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
-		list_for_each_entry(list, &tsdev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &tsdev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		tsdev_free(tsdev);
 }
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 9bf420e..284a073 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -10,9 +10,6 @@
 obj-$(CONFIG_USB_ATI_REMOTE2)	+= ati_remote2.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
 obj-$(CONFIG_USB_KEYSPAN_REMOTE)	+= keyspan_remote.o
-obj-$(CONFIG_USB_MTOUCH)	+= mtouchusb.o
-obj-$(CONFIG_USB_ITMTOUCH)	+= itmtouch.o
-obj-$(CONFIG_USB_EGALAX)	+= touchkitusb.o
 obj-$(CONFIG_USB_TOUCHSCREEN)	+= usbtouchscreen.o
 obj-$(CONFIG_USB_POWERMATE)	+= powermate.o
 obj-$(CONFIG_USB_WACOM)		+= wacom.o
@@ -20,7 +17,7 @@
 obj-$(CONFIG_USB_YEALINK)	+= yealink.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)	+= appletouch.o
-obj-$(CONFIG_USB_GTCO)         += gtco.o
+obj-$(CONFIG_USB_GTCO)		+= gtco.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 909138e..be8e924 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -111,7 +111,7 @@
 
 static int usb_acecad_open(struct input_dev *dev)
 {
-	struct usb_acecad *acecad = dev->private;
+	struct usb_acecad *acecad = input_get_drvdata(dev);
 
 	acecad->irq->dev = acecad->usbdev;
 	if (usb_submit_urb(acecad->irq, GFP_KERNEL))
@@ -122,7 +122,7 @@
 
 static void usb_acecad_close(struct input_dev *dev)
 {
-	struct usb_acecad *acecad = dev->private;
+	struct usb_acecad *acecad = input_get_drvdata(dev);
 
 	usb_kill_urb(acecad->irq);
 }
@@ -135,6 +135,7 @@
 	struct usb_acecad *acecad;
 	struct input_dev *input_dev;
 	int pipe, maxp;
+	int err = -ENOMEM;
 
 	if (interface->desc.bNumEndpoints != 1)
 		return -ENODEV;
@@ -149,16 +150,22 @@
 
 	acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
 	input_dev = input_allocate_device();
-	if (!acecad || !input_dev)
+	if (!acecad || !input_dev) {
+		err = -ENOMEM;
 		goto fail1;
+	}
 
 	acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
-	if (!acecad->data)
+	if (!acecad->data) {
+		err= -ENOMEM;
 		goto fail1;
+	}
 
 	acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!acecad->irq)
+	if (!acecad->irq) {
+		err = -ENOMEM;
 		goto fail2;
+	}
 
 	acecad->usbdev = dev;
 	acecad->input = input_dev;
@@ -178,8 +185,9 @@
 	input_dev->name = acecad->name;
 	input_dev->phys = acecad->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = acecad;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, acecad);
 
 	input_dev->open = usb_acecad_open;
 	input_dev->close = usb_acecad_close;
@@ -221,7 +229,9 @@
 	acecad->irq->transfer_dma = acecad->data_dma;
 	acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(acecad->input);
+	err = input_register_device(acecad->input);
+	if (err)
+		goto fail2;
 
 	usb_set_intfdata(intf, acecad);
 
@@ -230,7 +240,7 @@
  fail2:	usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
  fail1: input_free_device(input_dev);
 	kfree(acecad);
-	return -ENOMEM;
+	return err;
 }
 
 static void usb_acecad_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index f857935..cc0a498 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -798,7 +798,7 @@
  */
 static int aiptek_open(struct input_dev *inputdev)
 {
-	struct aiptek *aiptek = inputdev->private;
+	struct aiptek *aiptek = input_get_drvdata(inputdev);
 
 	aiptek->urb->dev = aiptek->usbdev;
 	if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
@@ -812,7 +812,7 @@
  */
 static void aiptek_close(struct input_dev *inputdev)
 {
-	struct aiptek *aiptek = inputdev->private;
+	struct aiptek *aiptek = input_get_drvdata(inputdev);
 
 	usb_kill_urb(aiptek->urb);
 }
@@ -1972,6 +1972,7 @@
 		AIPTEK_PROGRAMMABLE_DELAY_200,
 		AIPTEK_PROGRAMMABLE_DELAY_300
 	};
+	int err = -ENOMEM;
 
 	/* programmableDelay is where the command-line specified
 	 * delay is kept. We make it the first element of speeds[],
@@ -2043,8 +2044,10 @@
 	inputdev->name = "Aiptek";
 	inputdev->phys = aiptek->features.usbPath;
 	usb_to_input_id(usbdev, &inputdev->id);
-	inputdev->cdev.dev = &intf->dev;
-	inputdev->private = aiptek;
+	inputdev->dev.parent = &intf->dev;
+
+	input_set_drvdata(inputdev, aiptek);
+
 	inputdev->open = aiptek_open;
 	inputdev->close = aiptek_close;
 
@@ -2133,7 +2136,9 @@
 
 	/* Register the tablet as an Input Device
 	 */
-	input_register_device(aiptek->inputdev);
+	err = input_register_device(aiptek->inputdev);
+	if (err)
+		goto fail2;
 
 	/* We now will look for the evdev device which is mapped to
 	 * the tablet. The partial name is kept in the link list of
@@ -2165,23 +2170,13 @@
 
 	return 0;
 
-fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+ fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
 			aiptek->data_dma);
-fail1:	input_free_device(inputdev);
+ fail1:	input_free_device(inputdev);
 	kfree(aiptek);
-	return -ENOMEM;
+	return err;
 }
 
-/* Forward declaration */
-static void aiptek_disconnect(struct usb_interface *intf);
-
-static struct usb_driver aiptek_driver = {
-	.name = "aiptek",
-	.probe = aiptek_probe,
-	.disconnect = aiptek_disconnect,
-	.id_table = aiptek_ids,
-};
-
 /***********************************************************************
  * Deal with tablet disconnecting from the system.
  */
@@ -2206,6 +2201,13 @@
 	}
 }
 
+static struct usb_driver aiptek_driver = {
+	.name = "aiptek",
+	.probe = aiptek_probe,
+	.disconnect = aiptek_disconnect,
+	.id_table = aiptek_ids,
+};
+
 static int __init aiptek_init(void)
 {
 	int result = usb_register(&aiptek_driver);
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index c77291d..e321526 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -466,7 +466,7 @@
 
 static int atp_open(struct input_dev *input)
 {
-	struct atp *dev = input->private;
+	struct atp *dev = input_get_drvdata(input);
 
 	if (usb_submit_urb(dev->urb, GFP_ATOMIC))
 		return -EIO;
@@ -477,7 +477,7 @@
 
 static void atp_close(struct input_dev *input)
 {
-	struct atp *dev = input->private;
+	struct atp *dev = input_get_drvdata(input);
 
 	usb_kill_urb(dev->urb);
 	dev->open = 0;
@@ -491,8 +491,7 @@
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	int int_in_endpointAddr = 0;
-	int i, retval = -ENOMEM;
-
+	int i, error = -ENOMEM;
 
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
@@ -567,17 +566,13 @@
 	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->urb) {
-		retval = -ENOMEM;
+	if (!dev->urb)
 		goto err_free_devs;
-	}
 
 	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
-	if (!dev->data) {
-		retval = -ENOMEM;
+	if (!dev->data)
 		goto err_free_urb;
-	}
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
@@ -589,9 +584,10 @@
 	input_dev->name = "appletouch";
 	input_dev->phys = dev->phys;
 	usb_to_input_id(dev->udev, &input_dev->id);
-	input_dev->cdev.dev = &iface->dev;
+	input_dev->dev.parent = &iface->dev;
 
-	input_dev->private = dev;
+	input_set_drvdata(input_dev, dev);
+
 	input_dev->open = atp_open;
 	input_dev->close = atp_close;
 
@@ -633,20 +629,25 @@
 	set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 	set_bit(BTN_LEFT, input_dev->keybit);
 
-	input_register_device(dev->input);
+	error = input_register_device(dev->input);
+	if (error)
+		goto err_free_buffer;
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(iface, dev);
 
 	return 0;
 
+ err_free_buffer:
+	usb_buffer_free(dev->udev, dev->datalen,
+			dev->data, dev->urb->transfer_dma);
  err_free_urb:
 	usb_free_urb(dev->urb);
  err_free_devs:
 	usb_set_intfdata(iface, NULL);
 	kfree(dev);
 	input_free_device(input_dev);
-	return retval;
+	return error;
 }
 
 static void atp_disconnect(struct usb_interface *iface)
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index b724e36..471aab2 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -120,6 +120,7 @@
  * behaviour.
  */
 #define FILTER_TIME	60 /* msec */
+#define REPEAT_DELAY	500 /* msec */
 
 static unsigned long channel_mask;
 module_param(channel_mask, ulong, 0644);
@@ -133,6 +134,10 @@
 module_param(repeat_filter, int, 0644);
 MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
 
+static int repeat_delay = REPEAT_DELAY;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
 #undef err
 #define err(format, arg...) printk(KERN_ERR format , ## arg)
@@ -174,6 +179,8 @@
 	unsigned char old_data[2];  /* Detect duplicate events */
 	unsigned long old_jiffies;
 	unsigned long acc_jiffies;  /* handle acceleration */
+	unsigned long first_jiffies;
+
 	unsigned int repeat_count;
 
 	char name[NAME_BUFSIZE];
@@ -318,7 +325,7 @@
  */
 static int ati_remote_open(struct input_dev *inputdev)
 {
-	struct ati_remote *ati_remote = inputdev->private;
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
 	/* On first open, submit the read urb which was set up previously. */
 	ati_remote->irq_urb->dev = ati_remote->udev;
@@ -336,7 +343,7 @@
  */
 static void ati_remote_close(struct input_dev *inputdev)
 {
-	struct ati_remote *ati_remote = inputdev->private;
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
 	usb_kill_urb(ati_remote->irq_urb);
 }
@@ -501,21 +508,31 @@
 	}
 
 	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
+		unsigned long now = jiffies;
+
 		/* Filter duplicate events which happen "too close" together. */
 		if (ati_remote->old_data[0] == data[1] &&
 		    ati_remote->old_data[1] == data[2] &&
-		    time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) {
+		    time_before(now, ati_remote->old_jiffies +
+				     msecs_to_jiffies(repeat_filter))) {
 			ati_remote->repeat_count++;
 		} else {
 			ati_remote->repeat_count = 0;
+			ati_remote->first_jiffies = now;
 		}
 
 		ati_remote->old_data[0] = data[1];
 		ati_remote->old_data[1] = data[2];
-		ati_remote->old_jiffies = jiffies;
+		ati_remote->old_jiffies = now;
 
+		/* Ensure we skip at least the 4 first duplicate events (generated
+		 * by a single keypress), and continue skipping until repeat_delay
+		 * msecs have passed
+		 */
 		if (ati_remote->repeat_count > 0 &&
-		    ati_remote->repeat_count < 5)
+		    (ati_remote->repeat_count < 5 ||
+		     time_before(now, ati_remote->first_jiffies +
+				      msecs_to_jiffies(repeat_delay))))
 			return;
 
 
@@ -653,7 +670,8 @@
 		if (ati_remote_tbl[i].type == EV_KEY)
 			set_bit(ati_remote_tbl[i].code, idev->keybit);
 
-	idev->private = ati_remote;
+	input_set_drvdata(idev, ati_remote);
+
 	idev->open = ati_remote_open;
 	idev->close = ati_remote_close;
 
@@ -661,7 +679,7 @@
 	idev->phys = ati_remote->phys;
 
 	usb_to_input_id(ati_remote->udev, &idev->id);
-	idev->cdev.dev = &ati_remote->udev->dev;
+	idev->dev.parent = &ati_remote->udev->dev;
 }
 
 static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -772,15 +790,17 @@
 		goto fail3;
 
 	/* Set up and register input device */
-	input_register_device(ati_remote->idev);
+	err = input_register_device(ati_remote->idev);
+	if (err)
+		goto fail3;
 
 	usb_set_intfdata(interface, ati_remote);
 	return 0;
 
-fail3:	usb_kill_urb(ati_remote->irq_urb);
+ fail3:	usb_kill_urb(ati_remote->irq_urb);
 	usb_kill_urb(ati_remote->out_urb);
-fail2:	ati_remote_free_buffers(ati_remote);
-fail1:	input_free_device(input_dev);
+ fail2:	ati_remote_free_buffers(ati_remote);
+ fail1:	input_free_device(input_dev);
 	kfree(ati_remote);
 	return err;
 }
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index 6459be9..a9032aa 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -131,7 +131,7 @@
 
 static int ati_remote2_open(struct input_dev *idev)
 {
-	struct ati_remote2 *ar2 = idev->private;
+	struct ati_remote2 *ar2 = input_get_drvdata(idev);
 	int r;
 
 	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
@@ -153,7 +153,7 @@
 
 static void ati_remote2_close(struct input_dev *idev)
 {
-	struct ati_remote2 *ar2 = idev->private;
+	struct ati_remote2 *ar2 = input_get_drvdata(idev);
 
 	usb_kill_urb(ar2->urb[0]);
 	usb_kill_urb(ar2->urb[1]);
@@ -337,14 +337,14 @@
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
 {
 	struct input_dev *idev;
-	int i;
+	int i, retval;
 
 	idev = input_allocate_device();
 	if (!idev)
 		return -ENOMEM;
 
 	ar2->idev = idev;
-	idev->private = ar2;
+	input_set_drvdata(idev, ar2);
 
 	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
 	idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
@@ -362,13 +362,13 @@
 	idev->phys = ar2->phys;
 
 	usb_to_input_id(ar2->udev, &idev->id);
-	idev->cdev.dev = &ar2->udev->dev;
+	idev->dev.parent = &ar2->udev->dev;
 
-	i = input_register_device(idev);
-	if (i)
+	retval = input_register_device(idev);
+	if (retval)
 		input_free_device(idev);
 
-	return i;
+	return retval;
 }
 
 static int ati_remote2_urb_init(struct ati_remote2 *ar2)
diff --git a/drivers/usb/input/gtco.c b/drivers/usb/input/gtco.c
index ae756e0..b2ca10f2f 100644
--- a/drivers/usb/input/gtco.c
+++ b/drivers/usb/input/gtco.c
@@ -187,7 +187,6 @@
 
 
 /*
- *
  *   This is an abbreviated parser for the HID Report Descriptor.  We
  *   know what devices we are talking to, so this is by no means meant
  *   to be generic.  We can make some safe assumptions:
@@ -204,7 +203,7 @@
 static void parse_hid_report_descriptor(struct gtco *device, char * report,
 					int length)
 {
-	int   x,i=0;
+	int   x, i = 0;
 
 	/* Tag primitive vars */
 	__u8   prefix;
@@ -215,7 +214,6 @@
 	__u16  data16 = 0;
 	__u32  data32 = 0;
 
-
 	/* For parsing logic */
 	int   inputnum = 0;
 	__u32 usage = 0;
@@ -225,46 +223,46 @@
 	__u32 oldval[TAG_GLOB_MAX];
 
 	/* Debug stuff */
-	char  maintype='x';
+	char  maintype = 'x';
 	char  globtype[12];
-	int   indent=0;
-	char  indentstr[10]="";
-
+	int   indent = 0;
+	char  indentstr[10] = "";
 
 
 	dbg("======>>>>>>PARSE<<<<<<======");
 
 	/* Walk  this report and pull out the info we need */
-	while (i<length){
-		prefix=report[i];
+	while (i < length) {
+		prefix = report[i];
 
 		/* Skip over prefix */
 		i++;
 
 		/* Determine data size and save the data in the proper variable */
 		size = PREF_SIZE(prefix);
-		switch(size){
+		switch (size) {
 		case 1:
 			data = report[i];
 			break;
 		case 2:
-			data16 = le16_to_cpu(get_unaligned((__le16*)(&(report[i]))));
+			data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
 			break;
 		case 3:
 			size = 4;
-			data32 = le32_to_cpu(get_unaligned((__le32*)(&(report[i]))));
+			data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
+			break;
 		}
 
 		/* Skip size of data */
-		i+=size;
+		i += size;
 
 		/* What we do depends on the tag type */
 		tag  = PREF_TAG(prefix);
 		type = PREF_TYPE(prefix);
-		switch(type){
+		switch (type) {
 		case TYPE_MAIN:
-			strcpy(globtype,"");
-			switch(tag){
+			strcpy(globtype, "");
+			switch (tag) {
 
 			case TAG_MAIN_INPUT:
 				/*
@@ -274,19 +272,17 @@
 				 * min/max values
 				 */
 
-				maintype='I';
-				if (data==2){
-					strcpy(globtype,"Variable");
-				}
-				if (data==3){
-					strcpy(globtype,"Var|Const");
-				}
+				maintype = 'I';
+				if (data == 2)
+					strcpy(globtype, "Variable");
+				else if (data == 3)
+					strcpy(globtype, "Var|Const");
 
 				dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
-				    globalval[TAG_GLOB_REPORT_ID],inputnum,
-				    globalval[TAG_GLOB_LOG_MAX],globalval[TAG_GLOB_LOG_MAX],
-				    globalval[TAG_GLOB_LOG_MIN],globalval[TAG_GLOB_LOG_MIN],
-				    (globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]));
+				    globalval[TAG_GLOB_REPORT_ID], inputnum,
+				    globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
+				    globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
+				    globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
 
 
 				/*
@@ -295,43 +291,43 @@
 				  that, we look for everything else by
 				  local usage value
 				 */
-				switch (inputnum){
+				switch (inputnum) {
 				case 0:  /* X coord */
-					dbg("GER: X Usage: 0x%x",usage);
-					if (device->max_X == 0){
+					dbg("GER: X Usage: 0x%x", usage);
+					if (device->max_X == 0) {
 						device->max_X = globalval[TAG_GLOB_LOG_MAX];
 						device->min_X = globalval[TAG_GLOB_LOG_MIN];
 					}
-
 					break;
+
 				case 1:  /* Y coord */
-					dbg("GER: Y Usage: 0x%x",usage);
-					if (device->max_Y == 0){
+					dbg("GER: Y Usage: 0x%x", usage);
+					if (device->max_Y == 0) {
 						device->max_Y = globalval[TAG_GLOB_LOG_MAX];
 						device->min_Y = globalval[TAG_GLOB_LOG_MIN];
 					}
 					break;
+
 				default:
 					/* Tilt X */
-					if (usage == DIGITIZER_USAGE_TILT_X){
-						if (device->maxtilt_X == 0){
+					if (usage == DIGITIZER_USAGE_TILT_X) {
+						if (device->maxtilt_X == 0) {
 							device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX];
 							device->mintilt_X = globalval[TAG_GLOB_LOG_MIN];
 						}
 					}
 
 					/* Tilt Y */
-					if (usage == DIGITIZER_USAGE_TILT_Y){
-						if (device->maxtilt_Y == 0){
+					if (usage == DIGITIZER_USAGE_TILT_Y) {
+						if (device->maxtilt_Y == 0) {
 							device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX];
 							device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN];
 						}
 					}
 
-
 					/* Pressure */
-					if (usage == DIGITIZER_USAGE_TIP_PRESSURE){
-						if (device->maxpressure == 0){
+					if (usage == DIGITIZER_USAGE_TIP_PRESSURE) {
+						if (device->maxpressure == 0) {
 							device->maxpressure = globalval[TAG_GLOB_LOG_MAX];
 							device->minpressure = globalval[TAG_GLOB_LOG_MIN];
 						}
@@ -341,214 +337,226 @@
 				}
 
 				inputnum++;
-
-
 				break;
+
 			case TAG_MAIN_OUTPUT:
-				maintype='O';
+				maintype = 'O';
 				break;
-			case TAG_MAIN_FEATURE:
-				maintype='F';
-				break;
-			case TAG_MAIN_COL_START:
-				maintype='S';
 
-				if (data==0){
+			case TAG_MAIN_FEATURE:
+				maintype = 'F';
+				break;
+
+			case TAG_MAIN_COL_START:
+				maintype = 'S';
+
+				if (data == 0) {
 					dbg("======>>>>>> Physical");
-					strcpy(globtype,"Physical");
-				}else{
+					strcpy(globtype, "Physical");
+				} else
 					dbg("======>>>>>>");
-				}
 
 				/* Indent the debug output */
 				indent++;
-				for (x=0;x<indent;x++){
-					indentstr[x]='-';
-				}
-				indentstr[x]=0;
+				for (x = 0; x < indent; x++)
+					indentstr[x] = '-';
+				indentstr[x] = 0;
 
 				/* Save global tags */
-				for (x=0;x<TAG_GLOB_MAX;x++){
+				for (x = 0; x < TAG_GLOB_MAX; x++)
 					oldval[x] = globalval[x];
-				}
 
 				break;
+
 			case TAG_MAIN_COL_END:
 				dbg("<<<<<<======");
-				maintype='E';
+				maintype = 'E';
 				indent--;
-				for (x=0;x<indent;x++){
-					indentstr[x]='-';
-				}
-				indentstr[x]=0;
+				for (x = 0; x < indent; x++)
+					indentstr[x] = '-';
+				indentstr[x] = 0;
 
 				/* Copy global tags back */
-				for (x=0;x<TAG_GLOB_MAX;x++){
+				for (x = 0; x < TAG_GLOB_MAX; x++)
 					globalval[x] = oldval[x];
-				}
 
 				break;
 			}
 
-			switch (size){
+			switch (size) {
 			case 1:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype,data);
+				    indentstr, tag, maintype, size, globtype, data);
 				break;
+
 			case 2:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype, data16);
+				    indentstr, tag, maintype, size, globtype, data16);
 				break;
+
 			case 4:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype,data32);
+				    indentstr, tag, maintype, size, globtype, data32);
 				break;
 			}
 			break;
+
 		case TYPE_GLOBAL:
-			switch(tag){
+			switch (tag) {
 			case TAG_GLOB_USAGE:
 				/*
 				 * First time we hit the global usage tag,
 				 * it should tell us the type of device
 				 */
-				if (device->usage == 0){
+				if (device->usage == 0)
 					device->usage = data;
-				}
-				strcpy(globtype,"USAGE");
+
+				strcpy(globtype, "USAGE");
 				break;
-			case TAG_GLOB_LOG_MIN   :
-				strcpy(globtype,"LOG_MIN");
+
+			case TAG_GLOB_LOG_MIN:
+				strcpy(globtype, "LOG_MIN");
 				break;
-			case TAG_GLOB_LOG_MAX   :
-				strcpy(globtype,"LOG_MAX");
+
+			case TAG_GLOB_LOG_MAX:
+				strcpy(globtype, "LOG_MAX");
 				break;
-			case TAG_GLOB_PHYS_MIN  :
-				strcpy(globtype,"PHYS_MIN");
+
+			case TAG_GLOB_PHYS_MIN:
+				strcpy(globtype, "PHYS_MIN");
 				break;
-			case TAG_GLOB_PHYS_MAX  :
-				strcpy(globtype,"PHYS_MAX");
+
+			case TAG_GLOB_PHYS_MAX:
+				strcpy(globtype, "PHYS_MAX");
 				break;
-			case TAG_GLOB_UNIT_EXP  :
-				strcpy(globtype,"EXP");
+
+			case TAG_GLOB_UNIT_EXP:
+				strcpy(globtype, "EXP");
 				break;
-			case TAG_GLOB_UNIT      :
-				strcpy(globtype,"UNIT");
+
+			case TAG_GLOB_UNIT:
+				strcpy(globtype, "UNIT");
 				break;
-			case TAG_GLOB_REPORT_SZ :
-				strcpy(globtype,"REPORT_SZ");
+
+			case TAG_GLOB_REPORT_SZ:
+				strcpy(globtype, "REPORT_SZ");
 				break;
-			case TAG_GLOB_REPORT_ID :
-				strcpy(globtype,"REPORT_ID");
+
+			case TAG_GLOB_REPORT_ID:
+				strcpy(globtype, "REPORT_ID");
 				/* New report, restart numbering */
-				inputnum=0;
+				inputnum = 0;
 				break;
+
 			case TAG_GLOB_REPORT_CNT:
-				strcpy(globtype,"REPORT_CNT");
+				strcpy(globtype, "REPORT_CNT");
 				break;
-			case TAG_GLOB_PUSH :
-				strcpy(globtype,"PUSH");
+
+			case TAG_GLOB_PUSH:
+				strcpy(globtype, "PUSH");
 				break;
+
 			case TAG_GLOB_POP:
-				strcpy(globtype,"POP");
+				strcpy(globtype, "POP");
 				break;
 			}
 
-
 			/* Check to make sure we have a good tag number
 			   so we don't overflow array */
-			if (tag < TAG_GLOB_MAX){
-				switch (size){
+			if (tag < TAG_GLOB_MAX) {
+				switch (size) {
 				case 1:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data);
-					globalval[tag]=data;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data);
+					globalval[tag] = data;
 					break;
+
 				case 2:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16);
-					globalval[tag]=data16;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data16);
+					globalval[tag] = data16;
 					break;
+
 				case 4:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32);
-					globalval[tag]=data32;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data32);
+					globalval[tag] = data32;
 					break;
 				}
-			}else{
+			} else {
 				dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
-				    indentstr,tag,size);
+				    indentstr, tag, size);
 			}
-
-
 			break;
 
 		case TYPE_LOCAL:
-			switch(tag){
+			switch (tag) {
 			case TAG_GLOB_USAGE:
-				strcpy(globtype,"USAGE");
+				strcpy(globtype, "USAGE");
 				/* Always 1 byte */
 				usage = data;
 				break;
-			case TAG_GLOB_LOG_MIN   :
-				strcpy(globtype,"MIN");
+
+			case TAG_GLOB_LOG_MIN:
+				strcpy(globtype, "MIN");
 				break;
-			case TAG_GLOB_LOG_MAX   :
-				strcpy(globtype,"MAX");
+
+			case TAG_GLOB_LOG_MAX:
+				strcpy(globtype, "MAX");
 				break;
+
 			default:
-				strcpy(globtype,"UNKNOWN");
+				strcpy(globtype, "UNKNOWN");
+				break;
 			}
 
-			switch (size){
+			switch (size) {
 			case 1:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data);
+				    indentstr, tag, globtype, size, data);
 				break;
+
 			case 2:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data16);
+				    indentstr, tag, globtype, size, data16);
 				break;
+
 			case 4:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data32);
+				    indentstr, tag, globtype, size, data32);
 				break;
 			}
 
 			break;
 		}
-
 	}
-
 }
 
-
-
 /*   INPUT DRIVER Routines                               */
 
-
 /*
- *    Called when opening the input device.  This will submit the URB to
- *    the usb system so we start getting reports
+ * Called when opening the input device.  This will submit the URB to
+ * the usb system so we start getting reports
  */
 static int gtco_input_open(struct input_dev *inputdev)
 {
-	struct gtco *device;
-	device = inputdev->private;
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	device->urbinfo->dev = device->usbdev;
-	if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) {
+	if (usb_submit_urb(device->urbinfo, GFP_KERNEL))
 		return -EIO;
-	}
+
 	return 0;
 }
 
-/**
-    Called when closing the input device.  This will unlink the URB
-*/
+/*
+ * Called when closing the input device.  This will unlink the URB
+ */
 static void gtco_input_close(struct input_dev *inputdev)
 {
-	struct gtco *device = inputdev->private;
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	usb_kill_urb(device->urbinfo);
-
 }
 
 
@@ -560,19 +568,16 @@
  *  placed in the struct gtco structure
  *
  */
-static void  gtco_setup_caps(struct input_dev  *inputdev)
+static void gtco_setup_caps(struct input_dev *inputdev)
 {
-	struct gtco *device = inputdev->private;
-
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	/* Which events */
 	inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
 
-
 	/* Misc event menu block */
 	inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ;
 
-
 	/* Absolute values based on HID report info */
 	input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
 			     0, 0);
@@ -590,17 +595,12 @@
 	input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure,
 			     device->maxpressure, 0, 0);
 
-
 	/* Transducer */
-	input_set_abs_params(inputdev, ABS_MISC, 0,0xFF, 0, 0);
-
+	input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0);
 }
 
-
-
 /*   USB Routines  */
 
-
 /*
  * URB callback routine.  Called when we get IRQ reports from the
  *  digitizer.
@@ -610,9 +610,7 @@
  */
 static void gtco_urb_callback(struct urb *urbinfo)
 {
-
-
-	struct gtco     *device = urbinfo->context;
+	struct gtco *device = urbinfo->context;
 	struct input_dev  *inputdev;
 	int               rc;
 	u32               val = 0;
@@ -621,19 +619,20 @@
 
 	inputdev = device->inputdevice;
 
-
 	/* Was callback OK? */
-	if ((urbinfo->status == -ECONNRESET ) ||
-	    (urbinfo->status == -ENOENT ) ||
-	    (urbinfo->status == -ESHUTDOWN )){
+	if (urbinfo->status == -ECONNRESET ||
+	    urbinfo->status == -ENOENT ||
+	    urbinfo->status == -ESHUTDOWN) {
 
 		/* Shutdown is occurring. Return and don't queue up any more */
 		return;
 	}
 
-	if (urbinfo->status != 0 ) {
-		/* Some unknown error.  Hopefully temporary.  Just go and */
-		/* requeue an URB */
+	if (urbinfo->status != 0) {
+		/*
+		 * Some unknown error.  Hopefully temporary. Just go and
+		 * requeue an URB
+		 */
 		goto resubmit;
 	}
 
@@ -642,10 +641,9 @@
 	 */
 
 	/* PID dependent when we interpret the report */
-	if ((inputdev->id.product == PID_1000 )||
-	    (inputdev->id.product == PID_1001 )||
-	    (inputdev->id.product == PID_1002 ))
-	{
+	if (inputdev->id.product == PID_1000 ||
+	    inputdev->id.product == PID_1001 ||
+	    inputdev->id.product == PID_1002) {
 
 		/*
 		 * Switch on the report ID
@@ -653,10 +651,10 @@
 		 * the report number.  We can just fall through the case
 		 * statements if we start with the highest number report
 		 */
-		switch(device->buffer[0]){
+		switch (device->buffer[0]) {
 		case 5:
 			/* Pressure is 9 bits */
-			val =  ((u16)(device->buffer[8]) << 1);
+			val = ((u16)(device->buffer[8]) << 1);
 			val |= (u16)(device->buffer[7] >> 7);
 			input_report_abs(inputdev, ABS_PRESSURE,
 					 device->buffer[8]);
@@ -664,7 +662,6 @@
 			/* Mask out the Y tilt value used for pressure */
 			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);
 
-
 			/* Fall thru */
 		case 4:
 			/* Tilt */
@@ -684,11 +681,10 @@
 			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);
 
 			/* Fall thru */
-
 		case 2:
 		case 3:
 			/* Convert buttons, only 5 bits possible */
-			val = (device->buffer[5])&MASK_BUTTON;
+			val = (device->buffer[5]) & MASK_BUTTON;
 
 			/* We don't apply any meaning to the bitmask,
 			   just report */
@@ -696,132 +692,109 @@
 
 			/*  Fall thru */
 		case 1:
-
 			/* All reports have X and Y coords in the same place */
-			val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[1])));
+			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
 			input_report_abs(inputdev, ABS_X, val);
 
-			val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[3])));
+			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
 			input_report_abs(inputdev, ABS_Y, val);
 
-
 			/* Ditto for proximity bit */
-			if (device->buffer[5]& MASK_INRANGE){
-				val = 1;
-			}else{
-				val=0;
-			}
+			val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
 			input_report_abs(inputdev, ABS_DISTANCE, val);
 
-
 			/* Report 1 is an exception to how we handle buttons */
 			/* Buttons are an index, not a bitmask */
-			if (device->buffer[0] == 1){
+			if (device->buffer[0] == 1) {
 
-				/* Convert buttons, 5 bit index */
-				/* Report value of index set as one,
-				   the rest as 0 */
-				val = device->buffer[5]& MASK_BUTTON;
+				/*
+				 * Convert buttons, 5 bit index
+				 * Report value of index set as one,
+				 * the rest as 0
+				 */
+				val = device->buffer[5] & MASK_BUTTON;
 				dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
-				    val,val);
+				    val, val);
 
 				/*
 				 * We don't apply any meaning to the button
 				 * index, just report it
 				 */
 				input_event(inputdev, EV_MSC, MSC_SERIAL, val);
-
-
 			}
-
 			break;
+
 		case 7:
 			/* Menu blocks */
 			input_event(inputdev, EV_MSC, MSC_SCAN,
 				    device->buffer[1]);
-
-
 			break;
-
 		}
-
-
 	}
+
 	/* Other pid class */
-	if ((inputdev->id.product == PID_400 )||
-	    (inputdev->id.product == PID_401 ))
-	{
+	if (inputdev->id.product == PID_400 ||
+	    inputdev->id.product == PID_401) {
 
 		/* Report 2 */
-		if (device->buffer[0] == 2){
+		if (device->buffer[0] == 2) {
 			/* Menu blocks */
-			input_event(inputdev, EV_MSC, MSC_SCAN,
-				    device->buffer[1]);
+			input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
 		}
 
 		/*  Report 1 */
-		if (device->buffer[0] == 1){
+		if (device->buffer[0] == 1) {
 			char buttonbyte;
 
-
 			/*  IF X max > 64K, we still a bit from the y report */
-			if (device->max_X > 0x10000){
+			if (device->max_X > 0x10000) {
 
-				val = (u16)(((u16)(device->buffer[2]<<8))|((u8)(device->buffer[1])));
-				val |= (u32)(((u8)device->buffer[3]&0x1)<< 16);
+				val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
+				val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);
 
 				input_report_abs(inputdev, ABS_X, val);
 
-				le_buffer[0]  = (u8)((u8)(device->buffer[3])>>1);
-				le_buffer[0] |= (u8)((device->buffer[3]&0x1)<<7);
+				le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);
+				le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);
 
-				le_buffer[1]  = (u8)(device->buffer[4]>>1);
-				le_buffer[1] |= (u8)((device->buffer[5]&0x1)<<7);
+				le_buffer[1]  = (u8)(device->buffer[4] >> 1);
+				le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
 
-				val = le16_to_cpu(get_unaligned((__le16 *)(le_buffer)));
-
+				val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));
 				input_report_abs(inputdev, ABS_Y, val);
 
-
 				/*
 				 * Shift the button byte right by one to
 				 * make it look like the standard report
 				 */
-				buttonbyte = (device->buffer[5])>>1;
-			}else{
+				buttonbyte = device->buffer[5] >> 1;
+			} else {
 
-				val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1]))));
+				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
 				input_report_abs(inputdev, ABS_X, val);
 
-				val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[3]))));
+				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
 				input_report_abs(inputdev, ABS_Y, val);
 
 				buttonbyte = device->buffer[5];
-
 			}
 
-
 			/* BUTTONS and PROXIMITY */
-			if (buttonbyte& MASK_INRANGE){
-				val = 1;
-			}else{
-				val=0;
-			}
+			val = buttonbyte & MASK_INRANGE ? 1 : 0;
 			input_report_abs(inputdev, ABS_DISTANCE, val);
 
 			/* Convert buttons, only 4 bits possible */
-			val = buttonbyte&0x0F;
+			val = buttonbyte & 0x0F;
 #ifdef USE_BUTTONS
-			for ( i=0;i<5;i++){
-				input_report_key(inputdev, BTN_DIGI+i,val&(1<<i));
-			}
+			for (i = 0; i < 5; i++)
+				input_report_key(inputdev, BTN_DIGI + i, val & (1 << i));
 #else
 			/* We don't apply any meaning to the bitmask, just report */
 			input_event(inputdev, EV_MSC, MSC_SERIAL, val);
 #endif
+
 			/* TRANSDUCER */
 			input_report_abs(inputdev, ABS_MISC, device->buffer[6]);
-
 		}
 	}
 
@@ -833,10 +806,8 @@
 
  resubmit:
 	rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
-	if (rc != 0) {
-		err("usb_submit_urb failed rc=0x%x",rc);
-	}
-
+	if (rc != 0)
+		err("usb_submit_urb failed rc=0x%x", rc);
 }
 
 /*
@@ -854,58 +825,46 @@
 		      const struct usb_device_id *id)
 {
 
-	struct gtco             *device = NULL;
-	char                    path[PATHLENGTH];
-	struct input_dev        *inputdev;
+	struct gtco             *gtco;
+	struct input_dev        *input_dev;
 	struct hid_descriptor   *hid_desc;
-	char                    *report;
-	int                     result=0, retry;
+	char                    *report = NULL;
+	int                     result = 0, retry;
+	int			error;
 	struct usb_endpoint_descriptor *endpoint;
 
 	/* Allocate memory for device structure */
-	device = kzalloc(sizeof(struct gtco), GFP_KERNEL);
-	if (device == NULL) {
+	gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!gtco || !input_dev) {
 		err("No more memory");
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_free_devs;
 	}
 
-
-	device->inputdevice = input_allocate_device();
-	if (!device->inputdevice){
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
-	}
-
-	/* Get pointer to the input device */
-	inputdev = device->inputdevice;
+	/* Set pointer to the input device */
+	gtco->inputdevice = input_dev;
 
 	/* Save interface information */
-	device->usbdev     = usb_get_dev(interface_to_usbdev(usbinterface));
-
+	gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
 
 	/* Allocate some data for incoming reports */
-	device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE,
-					   GFP_KERNEL, &(device->buf_dma));
-	if (!device->buffer){
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
+	gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,
+					GFP_KERNEL, &gtco->buf_dma);
+	if (!gtco->buffer) {
+		err("No more memory for us buffers");
+		error = -ENOMEM;
+		goto err_free_devs;
 	}
 
 	/* Allocate URB for reports */
-	device->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
-	if (!device->urbinfo) {
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
+	gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
+	if (!gtco->urbinfo) {
+		err("Failed to allocate URB");
 		return -ENOMEM;
+		goto err_free_buf;
 	}
 
-
 	/*
 	 * The endpoint is always altsetting 0, we know this since we know
 	 * this device only has one interrupt endpoint
@@ -913,51 +872,43 @@
 	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
 	/* Some debug */
-	dbg("gtco # interfaces: %d",usbinterface->num_altsetting);
-	dbg("num endpoints:     %d",usbinterface->cur_altsetting->desc.bNumEndpoints);
-	dbg("interface class:   %d",usbinterface->cur_altsetting->desc.bInterfaceClass);
-	dbg("endpoint: attribute:0x%x type:0x%x",endpoint->bmAttributes,endpoint->bDescriptorType);
+	dbg("gtco # interfaces: %d", usbinterface->num_altsetting);
+	dbg("num endpoints:     %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
+	dbg("interface class:   %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
+	dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
 		dbg("endpoint: we have interrupt endpoint\n");
 
-	dbg("endpoint extra len:%d ",usbinterface->altsetting[0].extralen);
-
-
+	dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
 
 	/*
 	 * Find the HID descriptor so we can find out the size of the
 	 * HID report descriptor
 	 */
 	if (usb_get_extra_descriptor(usbinterface->cur_altsetting,
-				     HID_DEVICE_TYPE,&hid_desc) != 0){
+				     HID_DEVICE_TYPE, &hid_desc) != 0){
 		err("Can't retrieve exta USB descriptor to get hid report descriptor length");
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
-		return -EIO;
+		error = -EIO;
+		goto err_free_urb;
 	}
 
 	dbg("Extra descriptor success: type:%d  len:%d",
 	    hid_desc->bDescriptorType,  hid_desc->wDescriptorLength);
 
-	if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) {
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
+	report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+	if (!report) {
+		err("No more memory for report");
+		error = -ENOMEM;
+		goto err_free_urb;
 	}
 
 	/* Couple of tries to get reply */
-	for (retry=0;retry<3;retry++) {
-		result = usb_control_msg(device->usbdev,
-					 usb_rcvctrlpipe(device->usbdev, 0),
+	for (retry = 0; retry < 3; retry++) {
+		result = usb_control_msg(gtco->usbdev,
+					 usb_rcvctrlpipe(gtco->usbdev, 0),
 					 USB_REQ_GET_DESCRIPTOR,
 					 USB_RECIP_INTERFACE | USB_DIR_IN,
-					 (REPORT_DEVICE_TYPE << 8),
+					 REPORT_DEVICE_TYPE << 8,
 					 0, /* interface */
 					 report,
 					 hid_desc->wDescriptorLength,
@@ -969,72 +920,76 @@
 
 	/* If we didn't get the report, fail */
 	dbg("usb_control_msg result: :%d", result);
-	if (result != hid_desc->wDescriptorLength){
-		kfree(report);
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
+	if (result != hid_desc->wDescriptorLength) {
 		err("Failed to get HID Report Descriptor of size: %d",
 		    hid_desc->wDescriptorLength);
-		return -EIO;
+		error = -EIO;
+		goto err_free_urb;
 	}
 
-
 	/* Now we parse the report */
-	parse_hid_report_descriptor(device,report,result);
+	parse_hid_report_descriptor(gtco, report, result);
 
 	/* Now we delete it */
 	kfree(report);
 
 	/* Create a device file node */
-	usb_make_path(device->usbdev, path, PATHLENGTH);
-	sprintf(device->usbpath, "%s/input0", path);
-
+	usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
+	strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));
 
 	/* Set Input device functions */
-	inputdev->open     = gtco_input_open;
-	inputdev->close    = gtco_input_close;
+	input_dev->open = gtco_input_open;
+	input_dev->close = gtco_input_close;
 
 	/* Set input device information */
-	inputdev->name     = "GTCO_CalComp";
-	inputdev->phys     = device->usbpath;
-	inputdev->private  = device;
+	input_dev->name = "GTCO_CalComp";
+	input_dev->phys = gtco->usbpath;
 
+	input_set_drvdata(input_dev, gtco);
 
 	/* Now set up all the input device capabilities */
-	gtco_setup_caps(inputdev);
+	gtco_setup_caps(input_dev);
 
 	/* Set input device required ID information */
-	usb_to_input_id(device->usbdev, &device->inputdevice->id);
-	inputdev->cdev.dev = &usbinterface->dev;
+	usb_to_input_id(gtco->usbdev, &input_dev->id);
+	input_dev->dev.parent = &usbinterface->dev;
 
 	/* Setup the URB, it will be posted later on open of input device */
 	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
-	usb_fill_int_urb(device->urbinfo,
-			 device->usbdev,
-			 usb_rcvintpipe(device->usbdev,
+	usb_fill_int_urb(gtco->urbinfo,
+			 gtco->usbdev,
+			 usb_rcvintpipe(gtco->usbdev,
 					endpoint->bEndpointAddress),
-			 device->buffer,
+			 gtco->buffer,
 			 REPORT_MAX_SIZE,
 			 gtco_urb_callback,
-			 device,
+			 gtco,
 			 endpoint->bInterval);
 
-	device->urbinfo->transfer_dma = device->buf_dma;
-	device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	gtco->urbinfo->transfer_dma = gtco->buf_dma;
+	gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-
-	/* Save device pointer in USB interface device */
-	usb_set_intfdata(usbinterface, device);
+	/* Save gtco pointer in USB interface gtco */
+	usb_set_intfdata(usbinterface, gtco);
 
 	/* All done, now register the input device */
-	input_register_device(inputdev);
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_urb;
 
-	info( "gtco driver created usb:  %s\n",  path);
 	return 0;
 
+ err_free_urb:
+	usb_free_urb(gtco->urbinfo);
+ err_free_buf:
+	usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+			gtco->buffer, gtco->buf_dma);
+ err_free_devs:
+	kfree(report);
+	input_free_device(input_dev);
+	kfree(gtco);
+	return error;
 }
 
 /*
@@ -1044,47 +999,46 @@
  */
 static void gtco_disconnect(struct usb_interface *interface)
 {
-
 	/* Grab private device ptr */
-	struct gtco    *device = usb_get_intfdata (interface);
+	struct gtco *gtco = usb_get_intfdata(interface);
 
 	/* Now reverse all the registration stuff */
-	if (device) {
-		input_unregister_device(device->inputdevice);
-		usb_kill_urb(device->urbinfo);
-		usb_free_urb(device->urbinfo);
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		kfree(device);
+	if (gtco) {
+		input_unregister_device(gtco->inputdevice);
+		usb_kill_urb(gtco->urbinfo);
+		usb_free_urb(gtco->urbinfo);
+		usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+				gtco->buffer, gtco->buf_dma);
+		kfree(gtco);
 	}
 
 	info("gtco driver disconnected");
 }
 
-
 /*   STANDARD MODULE LOAD ROUTINES  */
 
 static struct usb_driver gtco_driverinfo_table = {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
-	.owner      = THIS_MODULE,
-#endif
-	.name       = "gtco",
-	.id_table   = gtco_usbid_table,
-	.probe      = gtco_probe,
-	.disconnect = gtco_disconnect,
+	.name		= "gtco",
+	.id_table	= gtco_usbid_table,
+	.probe		= gtco_probe,
+	.disconnect	= gtco_disconnect,
 };
+
 /*
  *  Register this module with the USB subsystem
  */
 static int __init gtco_init(void)
 {
-	int rc;
-	rc = usb_register(&gtco_driverinfo_table);
-	if (rc) {
-		err("usb_register() failed rc=0x%x", rc);
+	int error;
+
+	error = usb_register(&gtco_driverinfo_table);
+	if (error) {
+		err("usb_register() failed rc=0x%x", error);
+		return error;
 	}
-	printk("GTCO usb driver version: %s",GTCO_VERSION);
-	return rc;
+
+	printk("GTCO usb driver version: %s", GTCO_VERSION);
+	return 0;
 }
 
 /*
@@ -1095,7 +1049,7 @@
 	usb_deregister(&gtco_driverinfo_table);
 }
 
-module_init (gtco_init);
-module_exit (gtco_exit);
+module_init(gtco_init);
+module_exit(gtco_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
deleted file mode 100644
index aac968a..0000000
--- a/drivers/usb/input/itmtouch.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/******************************************************************************
- * itmtouch.c  --  Driver for ITM touchscreen panel
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>.
- *
- * Kudos to ITM for providing me with the datasheet for the panel,
- * even though it was a day later than I had finished writing this
- * driver.
- *
- * It has meant that I've been able to correct my interpretation of the
- * protocol packets however.
- *
- * CC -- 2003/9/29
- *
- * History
- * 1.0 & 1.1  2003 (CC) vojtech@suse.cz
- *   Original version for 2.4.x kernels
- *
- * 1.2  02/03/2005 (HCE) hc@mivu.no
- *   Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints.
- *   Unfortunately no calibration support at this time.
- *
- * 1.2.1  09/03/2005 (HCE) hc@mivu.no
- *   Code cleanup and adjusting syntax to start matching kernel standards
- * 
- * 1.2.2  10/05/2006 (MJA) massad@gmail.com
- *   Flag for detecting if the screen was being touch was incorrectly 
- *   inverted, so no touch events were being detected. 	
- *   
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-/* only an 8 byte buffer necessary for a single packet */
-#define ITM_BUFSIZE			8
-#define PATH_SIZE			64
-
-#define USB_VENDOR_ID_ITMINC		0x0403
-#define USB_PRODUCT_ID_TOUCHPANEL	0xf9e9
-
-#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>"
-#define DRIVER_VERSION "v1.2.2"
-#define DRIVER_DESC "USB ITM Inc Touch Panel Driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( DRIVER_LICENSE );
-
-struct itmtouch_dev {
-	struct usb_device	*usbdev; /* usb device */
-	struct input_dev	*inputdev; /* input device */
-	struct urb		*readurb; /* urb */
-	char			rbuf[ITM_BUFSIZE]; /* data */
-	int			users;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id itmtouch_ids [] = {
-	{ USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) },
-	{ }
-};
-
-static void itmtouch_irq(struct urb *urb)
-{
-	struct itmtouch_dev *itmtouch = urb->context;
-	unsigned char *data = urb->transfer_buffer;
-	struct input_dev *dev = itmtouch->inputdev;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	/* if pressure has been released, then don't report X/Y */
-	if (!(data[7] & 0x20)) {
-		input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F));
-		input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F));
-	}
-
-	input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F));
-	input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20);
-	input_sync(dev);
-
-exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		printk(KERN_ERR "%s - usb_submit_urb failed with result: %d",
-				__FUNCTION__, retval);
-}
-
-static int itmtouch_open(struct input_dev *input)
-{
-	struct itmtouch_dev *itmtouch = input->private;
-
-	itmtouch->readurb->dev = itmtouch->usbdev;
-
-	if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void itmtouch_close(struct input_dev *input)
-{
-	struct itmtouch_dev *itmtouch = input->private;
-
-	usb_kill_urb(itmtouch->readurb);
-}
-
-static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct itmtouch_dev *itmtouch;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	unsigned int pipe;
-	unsigned int maxp;
-
-	interface = intf->cur_altsetting;
-	endpoint = &interface->endpoint[0].desc;
-
-	itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!itmtouch || !input_dev) {
-		err("%s - Out of memory.", __FUNCTION__);
-		goto fail;
-	}
-
-	itmtouch->usbdev = udev;
-	itmtouch->inputdev = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
-		strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
-	}
-
-	if (!strlen(itmtouch->name))
-		sprintf(itmtouch->name, "USB ITM touchscreen");
-
-	usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
-	strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
-
-	input_dev->name = itmtouch->name;
-	input_dev->phys = itmtouch->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = itmtouch;
-
-	input_dev->open = itmtouch_open;
-	input_dev->close = itmtouch_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	/* device limits */
-	/* as specified by the ITM datasheet, X and Y are 12bit,
-	 * Z (pressure) is 8 bit. However, the fields are defined up
-	 * to 14 bits for future possible expansion.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
-
-	/* initialise the URB so we can read from the transport stream */
-	pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-
-	if (maxp > ITM_BUFSIZE)
-		maxp = ITM_BUFSIZE;
-
-	itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!itmtouch->readurb) {
-		dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
-		goto fail;
-	}
-
-	usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
-			 maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
-
-	input_register_device(itmtouch->inputdev);
-
-	usb_set_intfdata(intf, itmtouch);
-
-	return 0;
-
- fail:	input_free_device(input_dev);
-	kfree(itmtouch);
-	return -ENOMEM;
-}
-
-static void itmtouch_disconnect(struct usb_interface *intf)
-{
-	struct itmtouch_dev *itmtouch = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	if (itmtouch) {
-		input_unregister_device(itmtouch->inputdev);
-		usb_kill_urb(itmtouch->readurb);
-		usb_free_urb(itmtouch->readurb);
-		kfree(itmtouch);
-	}
-}
-
-MODULE_DEVICE_TABLE(usb, itmtouch_ids);
-
-static struct usb_driver itmtouch_driver = {
-	.name =         "itmtouch",
-	.probe =        itmtouch_probe,
-	.disconnect =   itmtouch_disconnect,
-	.id_table =     itmtouch_ids,
-};
-
-static int __init itmtouch_init(void)
-{
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	info(DRIVER_AUTHOR);
-	return usb_register(&itmtouch_driver);
-}
-
-static void __exit itmtouch_exit(void)
-{
-	usb_deregister(&itmtouch_driver);
-}
-
-module_init(itmtouch_init);
-module_exit(itmtouch_exit);
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index fedbcb1..c4781b9 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -100,7 +100,7 @@
 
 static int kbtab_open(struct input_dev *dev)
 {
-	struct kbtab *kbtab = dev->private;
+	struct kbtab *kbtab = input_get_drvdata(dev);
 
 	kbtab->irq->dev = kbtab->usbdev;
 	if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
@@ -111,7 +111,7 @@
 
 static void kbtab_close(struct input_dev *dev)
 {
-	struct kbtab *kbtab = dev->private;
+	struct kbtab *kbtab = input_get_drvdata(dev);
 
 	usb_kill_urb(kbtab->irq);
 }
@@ -122,6 +122,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct kbtab *kbtab;
 	struct input_dev *input_dev;
+	int error = -ENOMEM;
 
 	kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -145,8 +146,9 @@
 	input_dev->name = "KB Gear Tablet";
 	input_dev->phys = kbtab->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = kbtab;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, kbtab);
 
 	input_dev->open = kbtab_open;
 	input_dev->close = kbtab_close;
@@ -168,15 +170,19 @@
 	kbtab->irq->transfer_dma = kbtab->data_dma;
 	kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(kbtab->dev);
+	error = input_register_device(kbtab->dev);
+	if (error)
+		goto fail3;
 
 	usb_set_intfdata(intf, kbtab);
+
 	return 0;
 
-fail2:	usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(kbtab->irq);
+ fail2:	usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(kbtab);
-	return -ENOMEM;
+	return error;
 }
 
 static void kbtab_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 98bd323..1bffc9f 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -394,7 +394,7 @@
 
 static int keyspan_open(struct input_dev *dev)
 {
-	struct usb_keyspan *remote = dev->private;
+	struct usb_keyspan *remote = input_get_drvdata(dev);
 
 	remote->irq_urb->dev = remote->udev;
 	if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
@@ -405,7 +405,7 @@
 
 static void keyspan_close(struct input_dev *dev)
 {
-	struct usb_keyspan *remote = dev->private;
+	struct usb_keyspan *remote = input_get_drvdata(dev);
 
 	usb_kill_urb(remote->irq_urb);
 }
@@ -437,7 +437,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_keyspan *remote;
 	struct input_dev *input_dev;
-	int i, retval;
+	int i, error;
 
 	endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
 	if (!endpoint)
@@ -446,7 +446,7 @@
 	remote = kzalloc(sizeof(*remote), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!remote || !input_dev) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail1;
 	}
 
@@ -458,19 +458,19 @@
 
 	remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
 	if (!remote->in_buffer) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail1;
 	}
 
 	remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!remote->irq_urb) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail2;
 	}
 
-	retval = keyspan_setup(udev);
-	if (retval) {
-		retval = -ENODEV;
+	error = keyspan_setup(udev);
+	if (error) {
+		error = -ENODEV;
 		goto fail3;
 	}
 
@@ -495,14 +495,15 @@
 	input_dev->name = remote->name;
 	input_dev->phys = remote->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &interface->dev;
+	input_dev->dev.parent = &interface->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY);		/* We will only report KEY events. */
 	for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
 		if (keyspan_key_table[i] != KEY_RESERVED)
 			set_bit(keyspan_key_table[i], input_dev->keybit);
 
-	input_dev->private = remote;
+	input_set_drvdata(input_dev, remote);
+
 	input_dev->open = keyspan_open;
 	input_dev->close = keyspan_close;
 
@@ -517,7 +518,9 @@
 	remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* we can register the device now, as it is ready */
-	input_register_device(remote->input);
+	error = input_register_device(remote->input);
+	if (error)
+		goto fail3;
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, remote);
@@ -529,7 +532,7 @@
  fail1:	kfree(remote);
 	input_free_device(input_dev);
 
-	return retval;
+	return error;
 }
 
 /*
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
deleted file mode 100644
index 92c4e07..0000000
--- a/drivers/usb/input/mtouchusb.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/******************************************************************************
- * mtouchusb.c  --  Driver for Microtouch (Now 3M) USB Touchscreens
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl)
- *  (http://freshmeat.net/projects/3mtouchscreendriver)
- *
- * History
- *
- *  0.3 & 0.4  2002 (TEJ) tejohnson@yahoo.com
- *    Updated to 2.4.18, then 2.4.19
- *    Old version still relied on stealing a minor
- *
- *  0.5  02/26/2004 (TEJ) tejohnson@yahoo.com
- *    Complete rewrite using Linux Input in 2.6.3
- *    Unfortunately no calibration support at this time
- *
- *  1.4 04/25/2004 (TEJ) tejohnson@yahoo.com
- *    Changed reset from standard USB dev reset to vendor reset
- *    Changed data sent to host from compensated to raw coordinates
- *    Eliminated vendor/product module params
- *    Performed multiple successful tests with an EXII-5010UC
- *
- *  1.5 02/27/2005 ddstreet@ieee.org
- *    Added module parameter to select raw or hw-calibrated coordinate reporting
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define MTOUCHUSB_MIN_XC                0x0
-#define MTOUCHUSB_MAX_RAW_XC            0x4000
-#define MTOUCHUSB_MAX_CALIB_XC          0xffff
-#define MTOUCHUSB_XC_FUZZ               0x0
-#define MTOUCHUSB_XC_FLAT               0x0
-#define MTOUCHUSB_MIN_YC                0x0
-#define MTOUCHUSB_MAX_RAW_YC            0x4000
-#define MTOUCHUSB_MAX_CALIB_YC          0xffff
-#define MTOUCHUSB_YC_FUZZ               0x0
-#define MTOUCHUSB_YC_FLAT               0x0
-
-#define MTOUCHUSB_ASYNC_REPORT          1
-#define MTOUCHUSB_RESET                 7
-#define MTOUCHUSB_REPORT_DATA_SIZE      11
-#define MTOUCHUSB_REQ_CTRLLR_ID         10
-
-#define MTOUCHUSB_GET_RAW_XC(data)      (data[8]<<8 | data[7])
-#define MTOUCHUSB_GET_CALIB_XC(data)    (data[4]<<8 | data[3])
-#define MTOUCHUSB_GET_RAW_YC(data)      (data[10]<<8 | data[9])
-#define MTOUCHUSB_GET_CALIB_YC(data)    (data[6]<<8 | data[5])
-#define MTOUCHUSB_GET_XC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_XC(data) : \
-                                         MTOUCHUSB_GET_CALIB_XC(data))
-#define MTOUCHUSB_GET_YC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_YC(data) : \
-                                         MTOUCHUSB_GET_CALIB_YC(data))
-#define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
-
-#define DRIVER_VERSION "v1.5"
-#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
-#define DRIVER_DESC "3M USB Touchscreen Driver"
-#define DRIVER_LICENSE "GPL"
-
-static int raw_coordinates = 1;
-
-module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)");
-
-struct mtouch_usb {
-	unsigned char *data;
-	dma_addr_t data_dma;
-	struct urb *irq;
-	struct usb_device *udev;
-	struct input_dev *input;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id mtouchusb_devices[] = {
-	{ USB_DEVICE(0x0596, 0x0001) },
-	{ }
-};
-
-static void mtouchusb_irq(struct urb *urb)
-{
-	struct mtouch_usb *mtouch = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	input_report_key(mtouch->input, BTN_TOUCH,
-			 MTOUCHUSB_GET_TOUCHED(mtouch->data));
-	input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
-	input_report_abs(mtouch->input, ABS_Y,
-			 (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
-			 - MTOUCHUSB_GET_YC(mtouch->data));
-	input_sync(mtouch->input);
-
-exit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		err("%s - usb_submit_urb failed with result: %d",
-		    __FUNCTION__, retval);
-}
-
-static int mtouchusb_open(struct input_dev *input)
-{
-	struct mtouch_usb *mtouch = input->private;
-
-	mtouch->irq->dev = mtouch->udev;
-
-	if (usb_submit_urb(mtouch->irq, GFP_ATOMIC))
-		return -EIO;
-
-	return 0;
-}
-
-static void mtouchusb_close(struct input_dev *input)
-{
-	struct mtouch_usb *mtouch = input->private;
-
-	usb_kill_urb(mtouch->irq);
-}
-
-static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-	dbg("%s - called", __FUNCTION__);
-
-	mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-					GFP_ATOMIC, &mtouch->data_dma);
-
-	if (!mtouch->data)
-		return -1;
-
-	return 0;
-}
-
-static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-	dbg("%s - called", __FUNCTION__);
-
-	if (mtouch->data)
-		usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-				mtouch->data, mtouch->data_dma);
-}
-
-static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct mtouch_usb *mtouch;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	int nRet;
-
-	dbg("%s - called", __FUNCTION__);
-
-	dbg("%s - setting interface", __FUNCTION__);
-	interface = intf->cur_altsetting;
-
-	dbg("%s - setting endpoint", __FUNCTION__);
-	endpoint = &interface->endpoint[0].desc;
-
-	mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!mtouch || !input_dev) {
-		err("%s - Out of memory.", __FUNCTION__);
-		goto fail1;
-	}
-
-	dbg("%s - allocating buffers", __FUNCTION__);
-	if (mtouchusb_alloc_buffers(udev, mtouch))
-		goto fail2;
-
-	mtouch->udev = udev;
-	mtouch->input = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(mtouch->name, " ", sizeof(mtouch->name));
-		strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
-	}
-
-	if (!strlen(mtouch->name))
-		snprintf(mtouch->name, sizeof(mtouch->name),
-			"USB Touchscreen %04x:%04x",
-			le16_to_cpu(udev->descriptor.idVendor),
-			le16_to_cpu(udev->descriptor.idProduct));
-
-	usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
-	strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
-
-	input_dev->name = mtouch->name;
-	input_dev->phys = mtouch->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = mtouch;
-
-	input_dev->open = mtouchusb_open;
-	input_dev->close = mtouchusb_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
-		raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
-				MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
-	input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
-		raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
-		MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
-
-	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-			       MTOUCHUSB_RESET,
-			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
-	    __FUNCTION__, nRet);
-
-	dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__);
-	mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mtouch->irq) {
-		dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
-		goto fail2;
-	}
-
-	dbg("%s - usb_fill_int_urb", __FUNCTION__);
-	usb_fill_int_urb(mtouch->irq, mtouch->udev,
-			 usb_rcvintpipe(mtouch->udev, 0x81),
-			 mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE,
-			 mtouchusb_irq, mtouch, endpoint->bInterval);
-
-	dbg("%s - input_register_device", __FUNCTION__);
-	input_register_device(mtouch->input);
-
-	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-			       MTOUCHUSB_ASYNC_REPORT,
-			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-	    __FUNCTION__, nRet);
-
-	usb_set_intfdata(intf, mtouch);
-	return 0;
-
-fail2:	mtouchusb_free_buffers(udev, mtouch);
-fail1:	input_free_device(input_dev);
-	kfree(mtouch);
-	return -ENOMEM;
-}
-
-static void mtouchusb_disconnect(struct usb_interface *intf)
-{
-	struct mtouch_usb *mtouch = usb_get_intfdata(intf);
-
-	dbg("%s - called", __FUNCTION__);
-	usb_set_intfdata(intf, NULL);
-	if (mtouch) {
-		dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
-		usb_kill_urb(mtouch->irq);
-		input_unregister_device(mtouch->input);
-		usb_free_urb(mtouch->irq);
-		mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
-		kfree(mtouch);
-	}
-}
-
-MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
-
-static struct usb_driver mtouchusb_driver = {
-	.name		= "mtouchusb",
-	.probe		= mtouchusb_probe,
-	.disconnect	= mtouchusb_disconnect,
-	.id_table	= mtouchusb_devices,
-};
-
-static int __init mtouchusb_init(void)
-{
-	dbg("%s - called", __FUNCTION__);
-	return usb_register(&mtouchusb_driver);
-}
-
-static void __exit mtouchusb_cleanup(void)
-{
-	dbg("%s - called", __FUNCTION__);
-	usb_deregister(&mtouchusb_driver);
-}
-
-module_init(mtouchusb_init);
-module_exit(mtouchusb_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index fea97e5..4f93a76 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -252,7 +252,7 @@
 static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value)
 {
 	unsigned int command = (unsigned int)_value;
-	struct powermate_device *pm = dev->private;
+	struct powermate_device *pm = input_get_drvdata(dev);
 
 	if (type == EV_MSC && code == MSC_PULSELED){
 		/*
@@ -308,7 +308,7 @@
 	struct powermate_device *pm;
 	struct input_dev *input_dev;
 	int pipe, maxp;
-	int err = -ENOMEM;
+	int error = -ENOMEM;
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
@@ -359,8 +359,9 @@
 
 	input_dev->phys = pm->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = pm;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, pm);
 
 	input_dev->event = powermate_input_event;
 
@@ -387,11 +388,14 @@
 
 	/* register our interrupt URB with the USB system */
 	if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
-		err = -EIO;
+		error = -EIO;
 		goto fail4;
 	}
 
-	input_register_device(pm->input);
+	error = input_register_device(pm->input);
+	if (error)
+		goto fail5;
+
 
 	/* force an update of everything */
 	pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -400,12 +404,13 @@
 	usb_set_intfdata(intf, pm);
 	return 0;
 
-fail4:	usb_free_urb(pm->config);
-fail3:	usb_free_urb(pm->irq);
-fail2:	powermate_free_buffers(udev, pm);
-fail1:	input_free_device(input_dev);
+ fail5:	usb_kill_urb(pm->irq);
+ fail4:	usb_free_urb(pm->config);
+ fail3:	usb_free_urb(pm->irq);
+ fail2:	powermate_free_buffers(udev, pm);
+ fail1:	input_free_device(input_dev);
 	kfree(pm);
-	return err;
+	return error;
 }
 
 /* Called when a USB device we've accepted ownership of is removed */
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
deleted file mode 100644
index 2a314b0..0000000
--- a/drivers/usb/input/touchkitusb.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/******************************************************************************
- * touchkitusb.c  --  Driver for eGalax TouchKit USB Touchscreens
- *
- * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
- * Copyright (C) by Todd E. Johnson (mtouchusb.c)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon mtouchusb.c
- *
- *****************************************************************************/
-
-//#define DEBUG
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define TOUCHKIT_MIN_XC			0x0
-#define TOUCHKIT_MAX_XC			0x07ff
-#define TOUCHKIT_XC_FUZZ		0x0
-#define TOUCHKIT_XC_FLAT		0x0
-#define TOUCHKIT_MIN_YC			0x0
-#define TOUCHKIT_MAX_YC			0x07ff
-#define TOUCHKIT_YC_FUZZ		0x0
-#define TOUCHKIT_YC_FLAT		0x0
-#define TOUCHKIT_REPORT_DATA_SIZE	16
-
-#define TOUCHKIT_DOWN			0x01
-
-#define TOUCHKIT_PKT_TYPE_MASK		0xFE
-#define TOUCHKIT_PKT_TYPE_REPT		0x80
-#define TOUCHKIT_PKT_TYPE_DIAG		0x0A
-
-#define DRIVER_VERSION			"v0.1"
-#define DRIVER_AUTHOR			"Daniel Ritz <daniel.ritz@gmx.ch>"
-#define DRIVER_DESC			"eGalax TouchKit USB HID Touchscreen Driver"
-
-static int swap_xy;
-module_param(swap_xy, bool, 0644);
-MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
-
-struct touchkit_usb {
-	unsigned char *data;
-	dma_addr_t data_dma;
-	char buffer[TOUCHKIT_REPORT_DATA_SIZE];
-	int buf_len;
-	struct urb *irq;
-	struct usb_device *udev;
-	struct input_dev *input;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id touchkit_devices[] = {
-	{USB_DEVICE(0x3823, 0x0001)},
-	{USB_DEVICE(0x0123, 0x0001)},
-	{USB_DEVICE(0x0eef, 0x0001)},
-	{USB_DEVICE(0x0eef, 0x0002)},
-	{}
-};
-
-/* helpers to read the data */
-static inline int touchkit_get_touched(char *data)
-{
-	return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
-}
-
-static inline int touchkit_get_x(char *data)
-{
-	return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
-}
-
-static inline int touchkit_get_y(char *data)
-{
-	return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
-}
-
-
-/* processes one input packet. */
-static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt)
-{
-	int x, y;
-
-	/* only process report packets */
-	if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
-		return;
-
-	if (swap_xy) {
-		y = touchkit_get_x(pkt);
-		x = touchkit_get_y(pkt);
-	} else {
-		x = touchkit_get_x(pkt);
-		y = touchkit_get_y(pkt);
-	}
-
-	input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
-	input_report_abs(touchkit->input, ABS_X, x);
-	input_report_abs(touchkit->input, ABS_Y, y);
-	input_sync(touchkit->input);
-}
-
-
-static int touchkit_get_pkt_len(char *buf)
-{
-	switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
-	case TOUCHKIT_PKT_TYPE_REPT:
-		return 5;
-
-	case TOUCHKIT_PKT_TYPE_DIAG:
-		return buf[1] + 2;
-	}
-
-	return 0;
-}
-
-static void touchkit_process(struct touchkit_usb *touchkit, int len)
-{
-	char *buffer;
-	int pkt_len, buf_len, pos;
-
-	/* if the buffer contains data, append */
-	if (unlikely(touchkit->buf_len)) {
-		int tmp;
-
-		/* if only 1 byte in buffer, add another one to get length */
-		if (touchkit->buf_len == 1)
-			touchkit->buffer[1] = touchkit->data[0];
-
-		pkt_len = touchkit_get_pkt_len(touchkit->buffer);
-
-		/* unknown packet: drop everything */
-		if (!pkt_len)
-			return;
-
-		/* append, process */
-		tmp = pkt_len - touchkit->buf_len;
-		memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
-		touchkit_process_pkt(touchkit, touchkit->buffer);
-
-		buffer = touchkit->data + tmp;
-		buf_len = len - tmp;
-	} else {
-		buffer = touchkit->data;
-		buf_len = len;
-	}
-
-	/* only one byte left in buffer */
-	if (unlikely(buf_len == 1)) {
-		touchkit->buffer[0] = buffer[0];
-		touchkit->buf_len = 1;
-		return;
-	}
-
-	/* loop over the buffer */
-	pos = 0;
-	while (pos < buf_len) {
-		/* get packet len */
-		pkt_len = touchkit_get_pkt_len(buffer + pos);
-
-		/* unknown packet: drop everything */
-		if (unlikely(!pkt_len))
-			return;
-
-		/* full packet: process */
-		if (likely(pkt_len <= buf_len)) {
-			touchkit_process_pkt(touchkit, buffer + pos);
-		} else {
-			/* incomplete packet: save in buffer */
-			memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
-			touchkit->buf_len = buf_len - pos;
-		}
-		pos += pkt_len;
-	}
-}
-
-
-static void touchkit_irq(struct urb *urb)
-{
-	struct touchkit_usb *touchkit = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	touchkit_process(touchkit, urb->actual_length);
-
-exit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		err("%s - usb_submit_urb failed with result: %d",
-		    __FUNCTION__, retval);
-}
-
-static int touchkit_open(struct input_dev *input)
-{
-	struct touchkit_usb *touchkit = input->private;
-
-	touchkit->irq->dev = touchkit->udev;
-
-	if (usb_submit_urb(touchkit->irq, GFP_ATOMIC))
-		return -EIO;
-
-	return 0;
-}
-
-static void touchkit_close(struct input_dev *input)
-{
-	struct touchkit_usb *touchkit = input->private;
-
-	usb_kill_urb(touchkit->irq);
-}
-
-static int touchkit_alloc_buffers(struct usb_device *udev,
-				  struct touchkit_usb *touchkit)
-{
-	touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE,
-	                                  GFP_ATOMIC, &touchkit->data_dma);
-
-	if (!touchkit->data)
-		return -1;
-
-	return 0;
-}
-
-static void touchkit_free_buffers(struct usb_device *udev,
-				  struct touchkit_usb *touchkit)
-{
-	if (touchkit->data)
-		usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE,
-		                touchkit->data, touchkit->data_dma);
-}
-
-static int touchkit_probe(struct usb_interface *intf,
-			  const struct usb_device_id *id)
-{
-	struct touchkit_usb *touchkit;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	interface = intf->cur_altsetting;
-	endpoint = &interface->endpoint[0].desc;
-
-	touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!touchkit || !input_dev)
-		goto out_free;
-
-	if (touchkit_alloc_buffers(udev, touchkit))
-		goto out_free;
-
-	touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!touchkit->irq) {
-		dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
-		goto out_free_buffers;
-	}
-
-	touchkit->udev = udev;
-	touchkit->input = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(touchkit->name, " ", sizeof(touchkit->name));
-		strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
-	}
-
-	if (!strlen(touchkit->name))
-		snprintf(touchkit->name, sizeof(touchkit->name),
-			"USB Touchscreen %04x:%04x",
-			 le16_to_cpu(udev->descriptor.idVendor),
-			 le16_to_cpu(udev->descriptor.idProduct));
-
-	usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
-	strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
-
-	input_dev->name = touchkit->name;
-	input_dev->phys = touchkit->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = touchkit;
-	input_dev->open = touchkit_open;
-	input_dev->close = touchkit_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
-				TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
-	input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
-				TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
-
-	usb_fill_int_urb(touchkit->irq, touchkit->udev,
-			 usb_rcvintpipe(touchkit->udev, 0x81),
-			 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
-			 touchkit_irq, touchkit, endpoint->bInterval);
-
-	touchkit->irq->transfer_dma = touchkit->data_dma;
-	touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	input_register_device(touchkit->input);
-
-	usb_set_intfdata(intf, touchkit);
-	return 0;
-
-out_free_buffers:
-	touchkit_free_buffers(udev, touchkit);
-out_free:
-	input_free_device(input_dev);
-	kfree(touchkit);
-	return -ENOMEM;
-}
-
-static void touchkit_disconnect(struct usb_interface *intf)
-{
-	struct touchkit_usb *touchkit = usb_get_intfdata(intf);
-
-	dbg("%s - called", __FUNCTION__);
-
-	if (!touchkit)
-		return;
-
-	dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
-	usb_set_intfdata(intf, NULL);
-	usb_kill_urb(touchkit->irq);
-	input_unregister_device(touchkit->input);
-	usb_free_urb(touchkit->irq);
-	touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
-	kfree(touchkit);
-}
-
-MODULE_DEVICE_TABLE(usb, touchkit_devices);
-
-static struct usb_driver touchkit_driver = {
-	.name		= "touchkitusb",
-	.probe		= touchkit_probe,
-	.disconnect	= touchkit_disconnect,
-	.id_table	= touchkit_devices,
-};
-
-static int __init touchkit_init(void)
-{
-	return usb_register(&touchkit_driver);
-}
-
-static void __exit touchkit_cleanup(void)
-{
-	usb_deregister(&touchkit_driver);
-}
-
-module_init(touchkit_init);
-module_exit(touchkit_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 86e37a2..e082941 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -647,7 +647,7 @@
 
 static int usbtouch_open(struct input_dev *input)
 {
-	struct usbtouch_usb *usbtouch = input->private;
+	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
 	usbtouch->irq->dev = usbtouch->udev;
 
@@ -659,7 +659,7 @@
 
 static void usbtouch_close(struct input_dev *input)
 {
-	struct usbtouch_usb *usbtouch = input->private;
+	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
 	usb_kill_urb(usbtouch->irq);
 }
@@ -740,8 +740,10 @@
 	input_dev->name = usbtouch->name;
 	input_dev->phys = usbtouch->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = usbtouch;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, usbtouch);
+
 	input_dev->open = usbtouch_open;
 	input_dev->close = usbtouch_close;
 
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 12b4274..1fe4820 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -122,7 +122,7 @@
 
 static int wacom_open(struct input_dev *dev)
 {
-	struct wacom *wacom = dev->private;
+	struct wacom *wacom = input_get_drvdata(dev);
 
 	wacom->irq->dev = wacom->usbdev;
 	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
@@ -133,7 +133,7 @@
 
 static void wacom_close(struct input_dev *dev)
 {
-	struct wacom *wacom = dev->private;
+	struct wacom *wacom = input_get_drvdata(dev);
 
 	usb_kill_urb(wacom->irq);
 }
@@ -201,6 +201,7 @@
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct input_dev *input_dev;
+	int error = -ENOMEM;
 	char rep_data[2], limit = 0;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -229,8 +230,10 @@
 	wacom->wacom_wac = wacom_wac;
 	usb_to_input_id(dev, &input_dev->id);
 
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = wacom;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, wacom);
+
 	input_dev->open = wacom_open;
 	input_dev->close = wacom_close;
 
@@ -252,7 +255,9 @@
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(wacom->dev);
+	error = input_register_device(wacom->dev);
+	if (error)
+		goto fail3;
 
 	/* Ask the tablet to report tablet data. Repeat until it succeeds */
 	do {
@@ -265,11 +270,12 @@
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
-fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(wacom->irq);
+ fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(wacom);
 	kfree(wacom_wac);
-	return -ENOMEM;
+	return error;
 }
 
 static void wacom_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index e4bc76e..7357239 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -267,7 +267,7 @@
 
 static int xpad_open (struct input_dev *dev)
 {
-	struct usb_xpad *xpad = dev->private;
+	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	xpad->irq_in->dev = xpad->udev;
 	if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
@@ -278,7 +278,7 @@
 
 static void xpad_close (struct input_dev *dev)
 {
-	struct usb_xpad *xpad = dev->private;
+	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	usb_kill_urb(xpad->irq_in);
 }
@@ -312,6 +312,7 @@
 	struct input_dev *input_dev;
 	struct usb_endpoint_descriptor *ep_irq_in;
 	int i;
+	int error = -ENOMEM;
 
 	for (i = 0; xpad_device[i].idVendor; i++) {
 		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
@@ -344,8 +345,10 @@
 	input_dev->name = xpad_device[i].name;
 	input_dev->phys = xpad->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = xpad;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, xpad);
+
 	input_dev->open = xpad_open;
 	input_dev->close = xpad_close;
 
@@ -373,15 +376,18 @@
 	xpad->irq_in->transfer_dma = xpad->idata_dma;
 	xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(xpad->dev);
+	error = input_register_device(xpad->dev);
+	if (error)
+		goto fail3;
 
 	usb_set_intfdata(intf, xpad);
 	return 0;
 
-fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(xpad->irq_in);
+ fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(xpad);
-	return -ENOMEM;
+	return error;
 
 }
 
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index caff8e6..c54f1a5 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -502,7 +502,7 @@
 
 static int input_open(struct input_dev *dev)
 {
-	struct yealink_dev *yld = dev->private;
+	struct yealink_dev *yld = input_get_drvdata(dev);
 	int i, ret;
 
 	dbg("%s", __FUNCTION__);
@@ -529,7 +529,7 @@
 
 static void input_close(struct input_dev *dev)
 {
-	struct yealink_dev *yld = dev->private;
+	struct yealink_dev *yld = input_get_drvdata(dev);
 
 	usb_kill_urb(yld->urb_ctl);
 	usb_kill_urb(yld->urb_irq);
@@ -937,9 +937,10 @@
 	input_dev->name = nfo->name;
 	input_dev->phys = yld->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
+	input_dev->dev.parent = &intf->dev;
 
-	input_dev->private = yld;
+	input_set_drvdata(input_dev, yld);
+
 	input_dev->open = input_open;
 	input_dev->close = input_close;
 	/* input_dev->event = input_ev;	TODO */
@@ -955,7 +956,9 @@
 		}
 	}
 
-	input_register_device(yld->idev);
+	ret = input_register_device(yld->idev);
+	if (ret)
+		return usb_cleanup(yld, ret);
 
 	usb_set_intfdata(intf, yld);
 
diff --git a/include/asm-arm/arch-pxa/pxa27x_keyboard.h b/include/asm-arm/arch-pxa/pxa27x_keyboard.h
new file mode 100644
index 0000000..3aaff92
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa27x_keyboard.h
@@ -0,0 +1,13 @@
+#define PXAKBD_MAXROW		8
+#define PXAKBD_MAXCOL		8
+
+struct pxa27x_keyboard_platform_data {
+	int nr_rows, nr_cols;
+	int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL];
+	int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL];
+
+#ifdef CONFIG_PM
+	u32 reg_kpc;
+	u32 reg_kprec;
+#endif
+};
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index debd715..9db3d45 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -71,6 +71,7 @@
 	  struct semaphore *semaphore;	/* Semaphore to sleep on. */
 	} act;
 } hp_sdc_transaction;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this);
 
diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h
new file mode 100644
index 0000000..597a007
--- /dev/null
+++ b/include/linux/input-polldev.h
@@ -0,0 +1,46 @@
+#ifndef _INPUT_POLLDEV_H
+#define _INPUT_POLLDEV_H
+
+/*
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * 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/input.h>
+#include <linux/workqueue.h>
+
+/**
+ * struct input_polled_dev - simple polled input device
+ * @private: private driver data
+ * @flush: driver-supplied method that flushes device's state upon
+ *	opening (optional)
+ * @poll: driver-supplied method that polls the device and posts
+ *	input events (mandatory).
+ * @poll_interval: specifies how often the poll() method shoudl be called.
+ * @input: input device structire associated with the polled device.
+ *	Must be properly initialized by the driver (id, name, phys, bits).
+ *
+ * Polled input device provides a skeleton for supporting simple input
+ * devices that do not raise interrupts but have to be periodically
+ * scanned or polled to detect changes in their state.
+ */
+struct input_polled_dev {
+	void *private;
+
+	void (*flush)(struct input_polled_dev *dev);
+	void (*poll)(struct input_polled_dev *dev);
+	unsigned int poll_interval; /* msec */
+
+	struct input_dev *input;
+	struct delayed_work work;
+};
+
+struct input_polled_dev *input_allocate_polled_device(void);
+void input_free_polled_device(struct input_polled_dev *dev);
+int input_register_polled_device(struct input_polled_dev *dev);
+void input_unregister_polled_device(struct input_polled_dev *dev);
+
+#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index bde65c8..1789ee9 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -506,6 +506,7 @@
 #define KEY_VOICEMAIL		0x1ac
 #define KEY_ADDRESSBOOK		0x1ad
 #define KEY_MESSENGER		0x1ae
+#define KEY_DISPLAYTOGGLE	0x1af	/* Turn display (LCD) on and off */
 
 #define KEY_DEL_EOL		0x1c0
 #define KEY_DEL_EOS		0x1c1
@@ -913,33 +914,6 @@
 #define BIT(x)	(1UL<<((x)%BITS_PER_LONG))
 #define LONG(x) ((x)/BITS_PER_LONG)
 
-#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
-	((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
-
-#define SET_INPUT_KEYCODE(dev, scancode, val)			\
-		({	unsigned __old;				\
-		switch (dev->keycodesize) {			\
-			case 1: {				\
-				u8 *k = (u8 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-			case 2: {				\
-				u16 *k = (u16 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-			default: {				\
-				u32 *k = (u32 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-		}						\
-		__old; })
-
 struct input_dev {
 
 	void *private;
@@ -962,6 +936,8 @@
 	unsigned int keycodemax;
 	unsigned int keycodesize;
 	void *keycode;
+	int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
+	int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
 
 	struct ff_device *ff;
 
@@ -996,6 +972,9 @@
 	unsigned int users;
 
 	struct class_device cdev;
+	union {			/* temporarily so while we switching to struct device */
+		struct device *parent;
+	} dev;
 
 	struct list_head	h_list;
 	struct list_head	node;
@@ -1074,7 +1053,7 @@
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
+	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
 	void (*start)(struct input_handle *handle);
 
@@ -1104,7 +1083,7 @@
 };
 
 #define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node);
+#define to_handler(n) container_of(n,struct input_handler,node)
 #define to_handle(n) container_of(n,struct input_handle,d_node)
 #define to_handle_h(n) container_of(n,struct input_handle,h_node)
 
@@ -1121,12 +1100,25 @@
 	class_device_put(&dev->cdev);
 }
 
+static inline void *input_get_drvdata(struct input_dev *dev)
+{
+	return dev->private;
+}
+
+static inline void input_set_drvdata(struct input_dev *dev, void *data)
+{
+	dev->private = data;
+}
+
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
 int input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+int input_register_handle(struct input_handle *);
+void input_unregister_handle(struct input_handle *);
+
 int input_grab_device(struct input_handle *);
 void input_release_device(struct input_handle *);
 
@@ -1168,6 +1160,8 @@
 	input_event(dev, EV_SYN, SYN_REPORT, 0);
 }
 
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
+
 static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
 {
 	dev->absmin[axis] = min;