Input: convert from class devices to standard devices

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index be6b93c..ab4b2d9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@
 	wait_queue_head_t wait;
 	struct evdev_client *grab;
 	struct list_head client_list;
+	struct device dev;
 };
 
 struct evdev_client {
@@ -94,8 +95,10 @@
 	return input_flush_device(&evdev->handle, file);
 }
 
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
 {
+	struct evdev *evdev = container_of(dev, struct evdev, dev);
+
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -114,12 +117,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--evdev->open) {
-		if (evdev->exist)
-			input_close_device(&evdev->handle);
-		else
-			evdev_free(evdev);
-	}
+	if (!--evdev->open && evdev->exist)
+		input_close_device(&evdev->handle);
+
+	put_device(&evdev->dev);
 
 	return 0;
 }
@@ -139,24 +140,32 @@
 	if (!evdev || !evdev->exist)
 		return -ENODEV;
 
+	get_device(&evdev->dev);
+
 	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_evdev;
+	}
 
 	client->evdev = evdev;
 	list_add_tail(&client->node, &evdev->client_list);
 
 	if (!evdev->open++ && evdev->exist) {
 		error = input_open_device(&evdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_evdev:
+	put_device(&evdev->dev);
+	return error;
 }
 
 #ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@
 			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -649,38 +656,32 @@
 	evdev->handle.name = evdev->name;
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
-	sprintf(evdev->name, "event%d", minor);
+	snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+
+	snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+		 "event%d", minor);
+	evdev->dev.class = &input_class;
+	evdev->dev.parent = &dev->dev;
+	evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+	evdev->dev.release = evdev_free;
+	device_initialize(&evdev->dev);
 
 	evdev_table[minor] = evdev;
 
-	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 */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, evdev->name);
+	error = device_add(&evdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_evdev;
 
 	error = input_register_handle(&evdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_evdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+	device_del(&evdev->dev);
  err_free_evdev:
-	kfree(evdev);
-	evdev_table[minor] = NULL;
+	put_device(&evdev->dev);
 	return error;
 }
 
@@ -690,10 +691,8 @@
 	struct evdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&evdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
 
 	if (evdev->open) {
@@ -702,8 +701,9 @@
 		list_for_each_entry(client, &evdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&evdev->wait);
-	} else
-		evdev_free(evdev);
+	}
+
+	put_device(&evdev->dev);
 }
 
 static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8aba..75b4d2a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@
 		printk(KERN_ERR
 			"input: failed to attach handler %s to device %s, "
 			"error: %d\n",
-			handler->name, kobject_name(&dev->cdev.kobj), error);
+			handler->name, kobject_name(&dev->dev.kobj), error);
 
 	return error;
 }
@@ -527,7 +527,7 @@
 static int input_devices_seq_show(struct seq_file *seq, void *v)
 {
 	struct input_dev *dev = container_of(v, struct input_dev, node);
-	const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	struct input_handle *handle;
 
 	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@
 static inline void input_proc_exit(void) { }
 #endif
 
-#define INPUT_DEV_STRING_ATTR_SHOW(name)					\
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-										\
-	return scnprintf(buf, PAGE_SIZE, "%s\n",				\
-			 input_dev->name ? input_dev->name : "");		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name)				\
+static ssize_t input_dev_show_##name(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     char *buf)				\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+									\
+	return scnprintf(buf, PAGE_SIZE, "%s\n",			\
+			 input_dev->name ? input_dev->name : "");	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
 
 INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@
 	return len;
 }
 
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
 {
 	struct input_dev *id = to_input_dev(dev);
 	ssize_t len;
@@ -753,13 +757,13 @@
 
 	return min_t(int, len, PAGE_SIZE);
 }
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
 static struct attribute *input_dev_attrs[] = {
-	&class_device_attr_name.attr,
-	&class_device_attr_phys.attr,
-	&class_device_attr_uniq.attr,
-	&class_device_attr_modalias.attr,
+	&dev_attr_name.attr,
+	&dev_attr_phys.attr,
+	&dev_attr_uniq.attr,
+	&dev_attr_modalias.attr,
 	NULL
 };
 
@@ -767,13 +771,15 @@
 	.attrs	= input_dev_attrs,
 };
 
-#define INPUT_DEV_ID_ATTR(name)							\
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name)						\
+static ssize_t input_dev_show_id_##name(struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
 
 INPUT_DEV_ID_ATTR(bustype);
 INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@
 INPUT_DEV_ID_ATTR(version);
 
 static struct attribute *input_dev_id_attrs[] = {
-	&class_device_attr_bustype.attr,
-	&class_device_attr_vendor.attr,
-	&class_device_attr_product.attr,
-	&class_device_attr_version.attr,
+	&dev_attr_bustype.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_product.attr,
+	&dev_attr_version.attr,
 	NULL
 };
 
@@ -813,15 +819,17 @@
 	return len;
 }
 
-#define INPUT_DEV_CAP_ATTR(ev, bm)						\
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	int len = input_print_bitmap(buf, PAGE_SIZE,				\
-				     input_dev->bm##bit, ev##_MAX, 1);		\
-	return min_t(int, len, PAGE_SIZE);					\
-}										\
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm)					\
+static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
+				       struct device_attribute *attr,	\
+				       char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	int len = input_print_bitmap(buf, PAGE_SIZE,			\
+				     input_dev->bm##bit, ev##_MAX, 1);	\
+	return min_t(int, len, PAGE_SIZE);				\
+}									\
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
 
 INPUT_DEV_CAP_ATTR(EV, ev);
 INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@
 INPUT_DEV_CAP_ATTR(SW, sw);
 
 static struct attribute *input_dev_caps_attrs[] = {
-	&class_device_attr_ev.attr,
-	&class_device_attr_key.attr,
-	&class_device_attr_rel.attr,
-	&class_device_attr_abs.attr,
-	&class_device_attr_msc.attr,
-	&class_device_attr_led.attr,
-	&class_device_attr_snd.attr,
-	&class_device_attr_ff.attr,
-	&class_device_attr_sw.attr,
+	&dev_attr_ev.attr,
+	&dev_attr_key.attr,
+	&dev_attr_rel.attr,
+	&dev_attr_abs.attr,
+	&dev_attr_msc.attr,
+	&dev_attr_led.attr,
+	&dev_attr_snd.attr,
+	&dev_attr_ff.attr,
+	&dev_attr_sw.attr,
 	NULL
 };
 
@@ -858,9 +866,9 @@
 	NULL
 };
 
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
 {
-	struct input_dev *dev = to_input_dev(class_dev);
+	struct input_dev *dev = to_input_dev(device);
 
 	input_ff_destroy(dev);
 	kfree(dev);
@@ -947,10 +955,10 @@
 			return err;					\
 	} while (0)
 
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
 			    int num_envp, char *buffer, int buffer_size)
 {
-	struct input_dev *dev = to_input_dev(cdev);
+	struct input_dev *dev = to_input_dev(device);
 	int i = 0;
 	int len = 0;
 
@@ -988,10 +996,14 @@
 	return 0;
 }
 
+static struct device_type input_dev_type = {
+	.groups		= input_dev_attr_groups,
+	.release	= input_dev_release,
+	.uevent		= input_dev_uevent,
+};
+
 struct class input_class = {
-	.name			= "input",
-	.release		= input_dev_release,
-	.uevent			= input_dev_uevent,
+	.name		= "input",
 };
 EXPORT_SYMBOL_GPL(input_class);
 
@@ -1010,9 +1022,9 @@
 
 	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);
+		dev->dev.type = &input_dev_type;
+		dev->dev.class = &input_class;
+		device_initialize(&dev->dev);
 		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@
 
 	list_add_tail(&dev->node, &input_dev_list);
 
-	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
 		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
-	if (!dev->cdev.dev)
-		dev->cdev.dev = dev->dev.parent;
+	if (dev->cdev.dev)
+		dev->dev.parent = dev->cdev.dev;
 
-	error = class_device_add(&dev->cdev);
+	error = device_add(&dev->dev);
 	if (error)
 		return error;
 
-	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	printk(KERN_INFO "input: %s as %s\n",
 		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
 	kfree(path);
@@ -1173,7 +1185,7 @@
 
 	list_del_init(&dev->node);
 
-	class_device_unregister(&dev->cdev);
+	device_unregister(&dev->dev);
 
 	input_wakeup_procfs_readers();
 }
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 10e3b7b..a9a0180 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
+	struct device dev;
+
 	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
@@ -138,8 +140,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
 {
+	struct joydev *joydev = container_of(dev, struct joydev, dev);
+
 	joydev_table[joydev->minor] = NULL;
 	kfree(joydev);
 }
@@ -154,12 +158,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--joydev->open) {
-		if (joydev->exist)
-			input_close_device(&joydev->handle);
-		else
-			joydev_free(joydev);
-	}
+	if (!--joydev->open && joydev->exist)
+		input_close_device(&joydev->handle);
+
+	put_device(&joydev->dev);
 
 	return 0;
 }
@@ -178,24 +180,32 @@
 	if (!joydev || !joydev->exist)
 		return -ENODEV;
 
+	get_device(&joydev->dev);
+
 	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_joydev;
+	}
 
 	client->joydev = joydev;
 	list_add_tail(&client->node, &joydev->client_list);
 
 	if (!joydev->open++ && joydev->exist) {
 		error = input_open_device(&joydev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_joydev:
+	put_device(&joydev->dev);
+	return error;
 }
 
 static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@
 			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
-	struct class_device *cdev;
-	dev_t devt;
 	int i, j, t, minor;
 	int error;
 
@@ -505,7 +513,7 @@
 	joydev->handle.name = joydev->name;
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
-	sprintf(joydev->name, "js%d", minor);
+	snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
 
 	for (i = 0; i < ABS_MAX + 1; i++)
 		if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
+	snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+		 "js%d", minor);
+	joydev->dev.class = &input_class;
+	joydev->dev.parent = &dev->dev;
+	joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+	joydev->dev.release = joydev_free;
+	device_initialize(&joydev->dev);
+
 	joydev_table[minor] = joydev;
 
-	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 */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, joydev->name);
+	error = device_add(&joydev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_joydev;
 
 	error = input_register_handle(&joydev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_joydev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+	device_del(&joydev->dev);
  err_free_joydev:
-	joydev_table[minor] = NULL;
-	kfree(joydev);
+	put_device(&joydev->dev);
 	return error;
 }
 
@@ -587,9 +589,8 @@
 	struct joydev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&joydev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
-	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
@@ -597,8 +598,9 @@
 		list_for_each_entry(client, &joydev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&joydev->wait);
-	} else
-		joydev_free(joydev);
+	}
+
+	put_device(&joydev->dev);
 }
 
 static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 3f4866d..9173916 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@
 	wait_queue_head_t wait;
 	struct list_head client_list;
 	struct input_handle handle;
+	struct device dev;
 
 	struct list_head mixdev_node;
 	int mixdev_open;
@@ -112,7 +113,7 @@
 static struct input_handler mousedev_handler;
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
 static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@
 
 	if (value) {
 		set_bit(index, &mousedev->packet.buttons);
-		set_bit(index, &mousedev_mix.packet.buttons);
+		set_bit(index, &mousedev_mix->packet.buttons);
 	} else {
 		clear_bit(index, &mousedev->packet.buttons);
-		clear_bit(index, &mousedev_mix.packet.buttons);
+		clear_bit(index, &mousedev_mix->packet.buttons);
 	}
 }
 
@@ -287,11 +288,11 @@
 			 * motion packet so we won't mess current position.
 			 */
 			set_bit(0, &mousedev->packet.buttons);
-			set_bit(0, &mousedev_mix.packet.buttons);
-			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
-			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+			set_bit(0, &mousedev_mix->packet.buttons);
+			mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+			mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
 			clear_bit(0, &mousedev->packet.buttons);
-			clear_bit(0, &mousedev_mix.packet.buttons);
+			clear_bit(0, &mousedev_mix->packet.buttons);
 		}
 		mousedev->touch = mousedev->pkt_count = 0;
 		mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@
 				}
 
 				mousedev_notify_readers(mousedev, &mousedev->packet);
-				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+				mousedev_notify_readers(mousedev_mix, &mousedev->packet);
 
 				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
 				mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
 {
+	struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
 	mousedev_table[mousedev->minor] = NULL;
 	kfree(mousedev);
 }
@@ -372,15 +375,16 @@
 {
 	int error;
 
-	if (mousedev_mix.open) {
+	if (mousedev_mix->open) {
 		error = input_open_device(&mousedev->handle);
 		if (error)
 			return error;
 
 		mousedev->open++;
-		mousedev->mixdev_open++;
+		mousedev->mixdev_open = 1;
 	}
 
+	get_device(&mousedev->dev);
 	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
 
 	return 0;
@@ -395,36 +399,40 @@
 	}
 
 	list_del_init(&mousedev->mixdev_node);
+	put_device(&mousedev->dev);
 }
 
 static void mixdev_open_devices(void)
 {
 	struct mousedev *mousedev;
 
+	if (mousedev_mix->open++)
+		return;
+
 	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-		if (mousedev->exist && !mousedev->open) {
-			if (input_open_device(&mousedev->handle))
-				continue;
+		if (!mousedev->mixdev_open) {
+			if (!mousedev->open && mousedev->exist)
+				if (input_open_device(&mousedev->handle))
+					continue;
 
 			mousedev->open++;
-			mousedev->mixdev_open++;
+			mousedev->mixdev_open = 1;
 		}
 	}
 }
 
 static void mixdev_close_devices(void)
 {
-	struct mousedev *mousedev, *next;
+	struct mousedev *mousedev;
 
-	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+	if (--mousedev_mix->open)
+		return;
+
+	list_for_each_entry(mousedev, &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);
-			}
+			if (!--mousedev->open && mousedev->exist)
+				input_close_device(&mousedev->handle);
 		}
 	}
 }
@@ -439,14 +447,12 @@
 	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);
-	}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_close_devices();
+	else if (!--mousedev->open && mousedev->exist)
+		input_close_device(&mousedev->handle);
+
+	put_device(&mousedev->dev);
 
 	return 0;
 }
@@ -473,9 +479,13 @@
 	if (!mousedev)
 		return -ENODEV;
 
+	get_device(&mousedev->dev);
+
 	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_mousedev;
+	}
 
 	spin_lock_init(&client->packet_lock);
 	client->pos_x = xres / 2;
@@ -483,21 +493,23 @@
 	client->mousedev = mousedev;
 	list_add_tail(&client->node, &mousedev->client_list);
 
-	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;
-			}
-		}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_open_devices();
+	else if (!mousedev->open++ && mousedev->exist) {
+		error = input_open_device(&mousedev->handle);
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_mousedev:
+	put_device(&mousedev->dev);
+	return error;
 }
 
 static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,12 +692,80 @@
 	.fasync =	mousedev_fasync,
 };
 
+static struct mousedev *mousedev_create(struct input_dev *dev,
+					struct input_handler *handler,
+					int minor)
+{
+	struct mousedev *mousedev;
+	int error;
+
+	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+	if (!mousedev) {
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	INIT_LIST_HEAD(&mousedev->client_list);
+	INIT_LIST_HEAD(&mousedev->mixdev_node);
+	init_waitqueue_head(&mousedev->wait);
+
+	if (minor == MOUSEDEV_MIX)
+		strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+	else
+		snprintf(mousedev->name, sizeof(mousedev->name),
+			 "mouse%d", minor);
+
+	mousedev->minor = minor;
+	mousedev->exist = 1;
+	mousedev->handle.dev = dev;
+	mousedev->handle.name = mousedev->name;
+	mousedev->handle.handler = handler;
+	mousedev->handle.private = mousedev;
+
+	strlcpy(mousedev->dev.bus_id, mousedev->name,
+		sizeof(mousedev->dev.bus_id));
+	mousedev->dev.class = &input_class;
+	if (dev)
+		mousedev->dev.parent = &dev->dev;
+	mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+	mousedev->dev.release = mousedev_free;
+	device_initialize(&mousedev->dev);
+
+	mousedev_table[minor] = mousedev;
+
+	error = device_add(&mousedev->dev);
+	if (error)
+		goto err_free_mousedev;
+
+	return mousedev;
+
+ err_free_mousedev:
+	put_device(&mousedev->dev);
+ err_out:
+	return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+	struct mousedev_client *client;
+
+	device_del(&mousedev->dev);
+	mousedev->exist = 0;
+
+	if (mousedev->open) {
+		input_close_device(&mousedev->handle);
+		list_for_each_entry(client, &mousedev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+		wake_up_interruptible(&mousedev->wait);
+	}
+
+	put_device(&mousedev->dev);
+}
+
 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;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -695,42 +775,13 @@
 		return -ENFILE;
 	}
 
-	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
-	if (!mousedev)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&mousedev->client_list);
-	INIT_LIST_HEAD(&mousedev->mixdev_node);
-	init_waitqueue_head(&mousedev->wait);
-
-	mousedev->minor = minor;
-	mousedev->exist = 1;
-	mousedev->handle.dev = dev;
-	mousedev->handle.name = mousedev->name;
-	mousedev->handle.handler = handler;
-	mousedev->handle.private = mousedev;
-	sprintf(mousedev->name, "mouse%d", minor);
-
-	mousedev_table[minor] = mousedev;
-
-	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 */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, mousedev->name);
-	if (error)
-		goto err_cdev_destroy;
+	mousedev = mousedev_create(dev, handler, minor);
+	if (IS_ERR(mousedev))
+		return PTR_ERR(mousedev);
 
 	error = input_register_handle(&mousedev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_mousedev;
 
 	error = mixdev_add_device(mousedev);
 	if (error)
@@ -740,37 +791,18 @@
 
  err_unregister_handle:
 	input_unregister_handle(&mousedev->handle);
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
- err_free_mousedev:
-	mousedev_table[minor] = NULL;
-	kfree(mousedev);
+ err_delete_mousedev:
+	device_unregister(&mousedev->dev);
 	return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
-	struct mousedev_client *client;
-
-	input_unregister_handle(handle);
-
-	sysfs_remove_link(&input_class.subsys.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);
-		list_for_each_entry(client, &mousedev->client_list, node)
-			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-		wake_up_interruptible(&mousedev->wait);
-	} else
-		mousedev_free(mousedev);
+	input_unregister_handle(handle);
+	mousedev_destroy(mousedev);
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@
 
 static int __init mousedev_init(void)
 {
-	struct class_device *cdev;
 	int error;
 
+	mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+	if (IS_ERR(mousedev_mix))
+		return PTR_ERR(mousedev_mix);
+
 	error = input_register_handler(&mousedev_handler);
-	if (error)
+	if (error) {
+		mousedev_destroy(mousedev_mix);
 		return error;
-
-	memset(&mousedev_mix, 0, sizeof(struct mousedev));
-	INIT_LIST_HEAD(&mousedev_mix.client_list);
-	init_waitqueue_head(&mousedev_mix.wait);
-	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
-	mousedev_mix.exist = 1;
-	mousedev_mix.minor = MOUSEDEV_MIX;
-
-	cdev = class_device_create(&input_class, NULL,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
-	if (IS_ERR(cdev)) {
-		input_unregister_handler(&mousedev_handler);
-		return PTR_ERR(cdev);
 	}
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
+	mousedev_destroy(mousedev_mix);
 }
 
 module_init(mousedev_init);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 2db3648..4cd5bbc 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@
 	int open;
 	int minor;
 	char name[8];
+	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
-	struct input_handle handle;
+	struct device dev;
+
 	int x, y, pressure;
 	struct ts_calibration cal;
 };
@@ -163,9 +165,13 @@
 	if (!tsdev || !tsdev->exist)
 		return -ENODEV;
 
+	get_device(&tsdev->dev);
+
 	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_tsdev;
+	}
 
 	client->tsdev = tsdev;
 	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@
 
 	if (!tsdev->open++ && tsdev->exist) {
 		error = input_open_device(&tsdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_tsdev:
+	put_device(&tsdev->dev);
+	return error;
 }
 
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
 {
+	struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
 	tsdev_table[tsdev->minor] = NULL;
 	kfree(tsdev);
 }
@@ -200,12 +212,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--tsdev->open) {
-		if (tsdev->exist)
-			input_close_device(&tsdev->handle);
-		else
-			tsdev_free(tsdev);
-	}
+	if (!--tsdev->open && tsdev->exist)
+		input_close_device(&tsdev->handle);
+
+	put_device(&tsdev->dev);
 
 	return 0;
 }
@@ -388,8 +398,6 @@
 			 const struct input_device_id *id)
 {
 	struct tsdev *tsdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor, delta;
 	int error;
 
@@ -407,14 +415,13 @@
 	INIT_LIST_HEAD(&tsdev->client_list);
 	init_waitqueue_head(&tsdev->wait);
 
-	sprintf(tsdev->name, "ts%d", minor);
-
 	tsdev->exist = 1;
 	tsdev->minor = minor;
 	tsdev->handle.dev = dev;
 	tsdev->handle.name = tsdev->name;
 	tsdev->handle.handler = handler;
 	tsdev->handle.private = tsdev;
+	snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
 
 	/* Precompute the rough calibration matrix */
 	delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@
 	tsdev->cal.yscale = (yres << 8) / delta;
 	tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
 
+	snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+		 "ts%d", minor);
+	tsdev->dev.class = &input_class;
+	tsdev->dev.parent = &dev->dev;
+	tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+	tsdev->dev.release = tsdev_free;
+	device_initialize(&tsdev->dev);
+
 	tsdev_table[minor] = tsdev;
 
-	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 */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, tsdev->name);
+	error = device_add(&tsdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_tsdev;
 
 	error = input_register_handle(&tsdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_tsdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+	device_del(&tsdev->dev);
  err_free_tsdev:
-	tsdev_table[minor] = NULL;
-	kfree(tsdev);
+	put_device(&tsdev->dev);
 	return error;
 }
 
@@ -468,10 +469,8 @@
 	struct tsdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&tsdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
 
 	if (tsdev->open) {
@@ -479,8 +478,9 @@
 		list_for_each_entry(client, &tsdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&tsdev->wait);
-	} else
-		tsdev_free(tsdev);
+	}
+
+	put_device(&tsdev->dev);
 }
 
 static const struct input_device_id tsdev_ids[] = {