]> Pileus Git - ~andy/linux/blobdiff - drivers/input/evdev.c
Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[~andy/linux] / drivers / input / evdev.c
index be3dbc1ae67d154bd879c7a7c5bf87f2a0425add..f1c3d6cebd585a5392c96e0ed1a25e9cf275a73a 100644 (file)
@@ -30,6 +30,7 @@ struct evdev {
        wait_queue_head_t wait;
        struct evdev_client *grab;
        struct list_head client_list;
+       struct device dev;
 };
 
 struct evdev_client {
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
        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 @@ static int evdev_release(struct inode *inode, struct file *file)
        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 @@ static int evdev_open(struct inode *inode, struct file *file)
        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
@@ -177,7 +186,7 @@ struct input_event_compat {
 #elif defined(CONFIG_S390)
 #  define COMPAT_TEST test_thread_flag(TIF_31BIT)
 #elif defined(CONFIG_MIPS)
-#  define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
+#  define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
 #else
 #  define COMPAT_TEST test_thread_flag(TIF_32BIT)
 #endif
@@ -336,7 +345,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
 
        if (compat) {
                len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
-               if (len < maxlen)
+               if (len > maxlen)
                        len = maxlen;
 
                for (i = 0; i < len / sizeof(compat_long_t); i++)
@@ -511,7 +520,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
 
-                                       long *bits;
+                                       unsigned long *bits;
                                        int len;
 
                                        switch (_IOC_NR(cmd) & EV_MAX) {
@@ -556,7 +565,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
-                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       t = _IOC_NR(cmd) & ABS_MAX;
 
                                        abs.value = dev->abs[t];
                                        abs.minimum = dev->absmin[t];
@@ -576,7 +585,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 
                                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
-                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       t = _IOC_NR(cmd) & ABS_MAX;
 
                                        if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
                                                return -EFAULT;
@@ -625,8 +634,6 @@ 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;
 
@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        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);
 
-       evdev_table[minor] = evdev;
-
-       devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + 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);
 
-       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;
-       }
+       evdev_table[minor] = 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,20 +691,19 @@ static void evdev_disconnect(struct input_handle *handle)
        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) {
                input_flush_device(handle, NULL);
                input_close_device(handle);
-               wake_up_interruptible(&evdev->wait);
                list_for_each_entry(client, &evdev->client_list, node)
                        kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-       } else
-               evdev_free(evdev);
+               wake_up_interruptible(&evdev->wait);
+       }
+
+       put_device(&evdev->dev);
 }
 
 static const struct input_device_id evdev_ids[] = {