]> Pileus Git - ~andy/linux/blobdiff - drivers/input/joydev.c
mlx4: change TX coalescing defaults
[~andy/linux] / drivers / input / joydev.c
index 78f323ea1e4bff2821dcd8cd73bedf90ede73cbc..b62b5891f3999573893c732297ecd0467a094147 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/cdev.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Joystick device interfaces");
@@ -39,13 +40,13 @@ MODULE_LICENSE("GPL");
 
 struct joydev {
        int open;
-       int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
        struct list_head client_list;
        spinlock_t client_lock; /* protects client_list */
        struct mutex mutex;
        struct device dev;
+       struct cdev cdev;
        bool exist;
 
        struct js_corr corr[ABS_CNT];
@@ -70,9 +71,6 @@ struct joydev_client {
        struct list_head node;
 };
 
-static struct joydev *joydev_table[JOYDEV_MINORS];
-static DEFINE_MUTEX(joydev_table_mutex);
-
 static int joydev_correct(int value, struct js_corr *corr)
 {
        switch (corr->type) {
@@ -252,30 +250,14 @@ static int joydev_release(struct inode *inode, struct file *file)
 
 static int joydev_open(struct inode *inode, struct file *file)
 {
+       struct joydev *joydev =
+                       container_of(inode->i_cdev, struct joydev, cdev);
        struct joydev_client *client;
-       struct joydev *joydev;
-       int i = iminor(inode) - JOYDEV_MINOR_BASE;
        int error;
 
-       if (i >= JOYDEV_MINORS)
-               return -ENODEV;
-
-       error = mutex_lock_interruptible(&joydev_table_mutex);
-       if (error)
-               return error;
-       joydev = joydev_table[i];
-       if (joydev)
-               get_device(&joydev->dev);
-       mutex_unlock(&joydev_table_mutex);
-
-       if (!joydev)
-               return -ENODEV;
-
        client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
-       if (!client) {
-               error = -ENOMEM;
-               goto err_put_joydev;
-       }
+       if (!client)
+               return -ENOMEM;
 
        spin_lock_init(&client->buffer_lock);
        client->joydev = joydev;
@@ -288,13 +270,12 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
+       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
        joydev_detach_client(joydev, client);
        kfree(client);
- err_put_joydev:
-       put_device(&joydev->dev);
        return error;
 }
 
@@ -742,19 +723,6 @@ static const struct file_operations joydev_fops = {
        .llseek         = no_llseek,
 };
 
-static int joydev_install_chrdev(struct joydev *joydev)
-{
-       joydev_table[joydev->minor] = joydev;
-       return 0;
-}
-
-static void joydev_remove_chrdev(struct joydev *joydev)
-{
-       mutex_lock(&joydev_table_mutex);
-       joydev_table[joydev->minor] = NULL;
-       mutex_unlock(&joydev_table_mutex);
-}
-
 /*
  * Mark device non-existent. This disables writes, ioctls and
  * prevents new users from opening the device. Already posted
@@ -773,7 +741,8 @@ static void joydev_cleanup(struct joydev *joydev)
 
        joydev_mark_dead(joydev);
        joydev_hangup(joydev);
-       joydev_remove_chrdev(joydev);
+
+       cdev_del(&joydev->cdev);
 
        /* joydev is marked dead so no one else accesses joydev->open */
        if (joydev->open)
@@ -798,30 +767,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                          const struct input_device_id *id)
 {
        struct joydev *joydev;
-       int i, j, t, minor;
+       int i, j, t, minor, dev_no;
        int error;
 
-       for (minor = 0; minor < JOYDEV_MINORS; minor++)
-               if (!joydev_table[minor])
-                       break;
-
-       if (minor == JOYDEV_MINORS) {
-               pr_err("no more free joydev devices\n");
-               return -ENFILE;
+       minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
+       if (minor < 0) {
+               error = minor;
+               pr_err("failed to reserve new minor: %d\n", error);
+               return error;
        }
 
        joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
-       if (!joydev)
-               return -ENOMEM;
+       if (!joydev) {
+               error = -ENOMEM;
+               goto err_free_minor;
+       }
 
        INIT_LIST_HEAD(&joydev->client_list);
        spin_lock_init(&joydev->client_lock);
        mutex_init(&joydev->mutex);
        init_waitqueue_head(&joydev->wait);
-
-       dev_set_name(&joydev->dev, "js%d", minor);
        joydev->exist = true;
-       joydev->minor = minor;
+
+       dev_no = minor;
+       /* Normalize device number if it falls into legacy range */
+       if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS)
+               dev_no -= JOYDEV_MINOR_BASE;
+       dev_set_name(&joydev->dev, "js%d", dev_no);
 
        joydev->handle.dev = input_get_device(dev);
        joydev->handle.name = dev_name(&joydev->dev);
@@ -875,7 +847,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                }
        }
 
-       joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+       joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
        joydev->dev.class = &input_class;
        joydev->dev.parent = &dev->dev;
        joydev->dev.release = joydev_free;
@@ -885,7 +857,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        if (error)
                goto err_free_joydev;
 
-       error = joydev_install_chrdev(joydev);
+       cdev_init(&joydev->cdev, &joydev_fops);
+       error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
 
@@ -901,6 +874,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        input_unregister_handle(&joydev->handle);
  err_free_joydev:
        put_device(&joydev->dev);
+ err_free_minor:
+       input_free_minor(minor);
        return error;
 }
 
@@ -910,6 +885,7 @@ static void joydev_disconnect(struct input_handle *handle)
 
        device_del(&joydev->dev);
        joydev_cleanup(joydev);
+       input_free_minor(MINOR(joydev->dev.devt));
        input_unregister_handle(handle);
        put_device(&joydev->dev);
 }
@@ -961,7 +937,7 @@ static struct input_handler joydev_handler = {
        .match          = joydev_match,
        .connect        = joydev_connect,
        .disconnect     = joydev_disconnect,
-       .fops           = &joydev_fops,
+       .legacy_minors  = true,
        .minor          = JOYDEV_MINOR_BASE,
        .name           = "joydev",
        .id_table       = joydev_ids,