staging: comedi: remove comedi_clear_subdevice_minor()
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / comedi_fops.c
index c57f853d3c467986ac1c4ef13f688d0d9cdb65d6..64721f7f089be06ded2f352d940a802b41fe9c1f 100644 (file)
@@ -85,7 +85,6 @@ struct comedi_file_info {
        struct comedi_device *device;
        struct comedi_subdevice *read_subdevice;
        struct comedi_subdevice *write_subdevice;
-       struct device *hardware_device;
 };
 
 static DEFINE_MUTEX(comedi_board_minor_table_lock);
@@ -138,26 +137,6 @@ static struct comedi_file_info *comedi_clear_board_minor(unsigned minor)
        return info;
 }
 
-static struct comedi_file_info *comedi_clear_subdevice_minor(unsigned minor)
-{
-       struct comedi_file_info *info;
-       unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
-
-       mutex_lock(&comedi_subdevice_minor_table_lock);
-       info = comedi_subdevice_minor_table[i];
-       comedi_subdevice_minor_table[i] = NULL;
-       mutex_unlock(&comedi_subdevice_minor_table_lock);
-       return info;
-}
-
-static struct comedi_file_info *comedi_clear_minor(unsigned minor)
-{
-       if (minor < COMEDI_NUM_BOARD_MINORS)
-               return comedi_clear_board_minor(minor);
-       else
-               return comedi_clear_subdevice_minor(minor);
-}
-
 static void comedi_free_board_file_info(struct comedi_file_info *info)
 {
        if (info) {
@@ -199,44 +178,65 @@ static struct comedi_file_info
        return info;
 }
 
-static struct comedi_file_info *comedi_file_info_from_minor(unsigned minor)
-{
-       if (minor < COMEDI_NUM_BOARD_MINORS)
-               return comedi_file_info_from_board_minor(minor);
-       else
-               return comedi_file_info_from_subdevice_minor(minor);
-}
-
 static struct comedi_device *
 comedi_dev_from_file_info(struct comedi_file_info *info)
 {
        return info ? info->device : NULL;
 }
 
+static struct comedi_device *comedi_dev_from_board_minor(unsigned minor)
+{
+       struct comedi_file_info *info;
+
+       info = comedi_file_info_from_board_minor(minor);
+       return comedi_dev_from_file_info(info);
+}
+
+static struct comedi_device *comedi_dev_from_subdevice_minor(unsigned minor)
+{
+       struct comedi_file_info *info;
+
+       info = comedi_file_info_from_subdevice_minor(minor);
+       return comedi_dev_from_file_info(info);
+}
+
 struct comedi_device *comedi_dev_from_minor(unsigned minor)
 {
-       return comedi_dev_from_file_info(comedi_file_info_from_minor(minor));
+       if (minor < COMEDI_NUM_BOARD_MINORS)
+               return comedi_dev_from_board_minor(minor);
+       else
+               return comedi_dev_from_subdevice_minor(minor);
 }
 EXPORT_SYMBOL_GPL(comedi_dev_from_minor);
 
 static struct comedi_subdevice *
-comedi_read_subdevice(const struct comedi_file_info *info)
+comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
 {
-       if (info->read_subdevice)
-               return info->read_subdevice;
-       if (info->device)
-               return info->device->read_subdev;
-       return NULL;
+       struct comedi_file_info *info;
+
+       if (minor >= COMEDI_NUM_BOARD_MINORS) {
+               info = comedi_file_info_from_subdevice_minor(minor);
+               if (!info || info->device != dev)
+                       return NULL;
+               if (info->read_subdevice)
+                       return info->read_subdevice;
+       }
+       return dev->read_subdev;
 }
 
 static struct comedi_subdevice *
-comedi_write_subdevice(const struct comedi_file_info *info)
+comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
 {
-       if (info->write_subdevice)
-               return info->write_subdevice;
-       if (info->device)
-               return info->device->write_subdev;
-       return NULL;
+       struct comedi_file_info *info;
+
+       if (minor >= COMEDI_NUM_BOARD_MINORS) {
+               info = comedi_file_info_from_subdevice_minor(minor);
+               if (!info || info->device != dev)
+                       return NULL;
+               if (info->write_subdevice)
+                       return info->write_subdevice;
+       }
+       return dev->write_subdev;
 }
 
 static int resize_async_buffer(struct comedi_device *dev,
@@ -281,27 +281,34 @@ static int resize_async_buffer(struct comedi_device *dev,
 
 /* sysfs attribute files */
 
-static ssize_t show_max_read_buffer_kb(struct device *dev,
+static ssize_t show_max_read_buffer_kb(struct device *csdev,
                                       struct device_attribute *attr, char *buf)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_read_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size = 0;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_read_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
                size = s->async->max_bufsize / 1024;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_read_buffer_kb(struct device *dev,
+static ssize_t store_max_read_buffer_kb(struct device *csdev,
                                        struct device_attribute *attr,
                                        const char *buf, size_t count)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_read_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size;
        int err;
 
@@ -312,37 +319,49 @@ static ssize_t store_max_read_buffer_kb(struct device *dev,
                return -EINVAL;
        size *= 1024;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_read_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
                s->async->max_bufsize = size;
        else
                err = -EINVAL;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return err ? err : count;
 }
 
-static ssize_t show_read_buffer_kb(struct device *dev,
+static ssize_t show_read_buffer_kb(struct device *csdev,
                                   struct device_attribute *attr, char *buf)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_read_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size = 0;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_read_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
                size = s->async->prealloc_bufsz / 1024;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_read_buffer_kb(struct device *dev,
+static ssize_t store_read_buffer_kb(struct device *csdev,
                                    struct device_attribute *attr,
                                    const char *buf, size_t count)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_read_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size;
        int err;
 
@@ -353,38 +372,50 @@ static ssize_t store_read_buffer_kb(struct device *dev,
                return -EINVAL;
        size *= 1024;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_read_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
-               err = resize_async_buffer(info->device, s, s->async, size);
+               err = resize_async_buffer(dev, s, s->async, size);
        else
                err = -EINVAL;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return err ? err : count;
 }
 
-static ssize_t show_max_write_buffer_kb(struct device *dev,
+static ssize_t show_max_write_buffer_kb(struct device *csdev,
                                        struct device_attribute *attr,
                                        char *buf)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_write_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size = 0;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_write_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
                size = s->async->max_bufsize / 1024;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_write_buffer_kb(struct device *dev,
+static ssize_t store_max_write_buffer_kb(struct device *csdev,
                                         struct device_attribute *attr,
                                         const char *buf, size_t count)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_write_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size;
        int err;
 
@@ -395,37 +426,49 @@ static ssize_t store_max_write_buffer_kb(struct device *dev,
                return -EINVAL;
        size *= 1024;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_write_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
                s->async->max_bufsize = size;
        else
                err = -EINVAL;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return err ? err : count;
 }
 
-static ssize_t show_write_buffer_kb(struct device *dev,
+static ssize_t show_write_buffer_kb(struct device *csdev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_write_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size = 0;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_write_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
                size = s->async->prealloc_bufsz / 1024;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_write_buffer_kb(struct device *dev,
+static ssize_t store_write_buffer_kb(struct device *csdev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t count)
 {
-       struct comedi_file_info *info = dev_get_drvdata(dev);
-       struct comedi_subdevice *s = comedi_write_subdevice(info);
+       unsigned int minor = MINOR(csdev->devt);
+       struct comedi_device *dev;
+       struct comedi_subdevice *s;
        unsigned int size;
        int err;
 
@@ -436,12 +479,17 @@ static ssize_t store_write_buffer_kb(struct device *dev,
                return -EINVAL;
        size *= 1024;
 
-       mutex_lock(&info->device->mutex);
+       dev = comedi_dev_from_minor(minor);
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
+       s = comedi_write_subdevice(dev, minor);
        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
-               err = resize_async_buffer(info->device, s, s->async, size);
+               err = resize_async_buffer(dev, s, s->async, size);
        else
                err = -EINVAL;
-       mutex_unlock(&info->device->mutex);
+       mutex_unlock(&dev->mutex);
 
        return err ? err : count;
 }
@@ -686,7 +734,6 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
                            struct file *file)
 {
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
        struct comedi_subdevice *s;
        struct comedi_devinfo devinfo;
 
@@ -698,13 +745,13 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
        strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
        strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
 
-       s = comedi_read_subdevice(info);
+       s = comedi_read_subdevice(dev, minor);
        if (s)
                devinfo.read_subdevice = s->index;
        else
                devinfo.read_subdevice = -1;
 
-       s = comedi_write_subdevice(info);
+       s = comedi_write_subdevice(dev, minor);
        if (s)
                devinfo.write_subdevice = s->index;
        else
@@ -1721,8 +1768,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
                                  unsigned long arg)
 {
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
-       struct comedi_device *dev = comedi_dev_from_file_info(info);
+       struct comedi_device *dev = comedi_dev_from_minor(minor);
        int rc;
 
        if (!dev)
@@ -1745,7 +1791,8 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
                            dev->minor >= comedi_num_legacy_minors) {
                                /* Successfully unconfigured a dynamically
                                 * allocated device.  Try and remove it. */
-                               info = comedi_clear_minor(dev->minor);
+                               struct comedi_file_info *info;
+                               info = comedi_clear_board_minor(dev->minor);
                                if (info) {
                                        mutex_unlock(&dev->mutex);
                                        comedi_free_board_file_info(info);
@@ -1859,8 +1906,7 @@ static struct vm_operations_struct comedi_vm_ops = {
 static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
 {
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
-       struct comedi_device *dev = comedi_dev_from_file_info(info);
+       struct comedi_device *dev = comedi_dev_from_minor(minor);
        struct comedi_subdevice *s;
        struct comedi_async *async;
        unsigned long start = vma->vm_start;
@@ -1881,9 +1927,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
        }
 
        if (vma->vm_flags & VM_WRITE)
-               s = comedi_write_subdevice(info);
+               s = comedi_write_subdevice(dev, minor);
        else
-               s = comedi_read_subdevice(info);
+               s = comedi_read_subdevice(dev, minor);
        if (!s) {
                retval = -EINVAL;
                goto done;
@@ -1939,8 +1985,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
 {
        unsigned int mask = 0;
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
-       struct comedi_device *dev = comedi_dev_from_file_info(info);
+       struct comedi_device *dev = comedi_dev_from_minor(minor);
        struct comedi_subdevice *s;
 
        if (!dev)
@@ -1953,7 +1998,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
                goto done;
        }
 
-       s = comedi_read_subdevice(info);
+       s = comedi_read_subdevice(dev, minor);
        if (s && s->async) {
                poll_wait(file, &s->async->wait_head, wait);
                if (!s->busy || !comedi_is_subdevice_running(s) ||
@@ -1961,7 +2006,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
                        mask |= POLLIN | POLLRDNORM;
        }
 
-       s = comedi_write_subdevice(info);
+       s = comedi_write_subdevice(dev, minor);
        if (s && s->async) {
                unsigned int bps = bytes_per_sample(s->async->subdevice);
 
@@ -1985,8 +2030,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
        int n, m, count = 0, retval = 0;
        DECLARE_WAITQUEUE(wait, current);
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
-       struct comedi_device *dev = comedi_dev_from_file_info(info);
+       struct comedi_device *dev = comedi_dev_from_minor(minor);
 
        if (!dev)
                return -ENODEV;
@@ -1996,7 +2040,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
                return -ENODEV;
        }
 
-       s = comedi_write_subdevice(info);
+       s = comedi_write_subdevice(dev, minor);
        if (!s || !s->async)
                return -EIO;
 
@@ -2080,8 +2124,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
        int n, m, count = 0, retval = 0;
        DECLARE_WAITQUEUE(wait, current);
        const unsigned minor = iminor(file_inode(file));
-       struct comedi_file_info *info = comedi_file_info_from_minor(minor);
-       struct comedi_device *dev = comedi_dev_from_file_info(info);
+       struct comedi_device *dev = comedi_dev_from_minor(minor);
 
        if (!dev)
                return -ENODEV;
@@ -2091,7 +2134,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
                return -ENODEV;
        }
 
-       s = comedi_read_subdevice(info);
+       s = comedi_read_subdevice(dev, minor);
        if (!s || !s->async)
                return -EIO;
 
@@ -2376,7 +2419,6 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
                return ERR_PTR(-ENOMEM);
        }
        info->device = dev;
-       info->hardware_device = hardware_device;
        comedi_device_init(dev);
        comedi_set_hw_dev(dev, hardware_device);
        mutex_lock(&dev->mutex);
@@ -2402,7 +2444,6 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
                              MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
        if (!IS_ERR(csdev))
                dev->class_dev = csdev;
-       dev_set_drvdata(csdev, info);
 
        /* Note: dev->mutex needs to be unlocked by the caller. */
        return dev;
@@ -2411,7 +2452,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
 static void comedi_free_board_minor(unsigned minor)
 {
        BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
-       comedi_free_board_file_info(comedi_clear_minor(minor));
+       comedi_free_board_file_info(comedi_clear_board_minor(minor));
 }
 
 void comedi_release_hardware_device(struct device *hardware_device)
@@ -2423,7 +2464,7 @@ void comedi_release_hardware_device(struct device *hardware_device)
             minor++) {
                mutex_lock(&comedi_board_minor_table_lock);
                info = comedi_board_minor_table[minor];
-               if (info && info->hardware_device == hardware_device) {
+               if (info && info->device->hw_dev == hardware_device) {
                        comedi_board_minor_table[minor] = NULL;
                        mutex_unlock(&comedi_board_minor_table_lock);
                        comedi_free_board_file_info(info);
@@ -2468,7 +2509,6 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
                              dev->minor, s->index);
        if (!IS_ERR(csdev))
                s->class_dev = csdev;
-       dev_set_drvdata(csdev, info);
 
        return 0;
 }
@@ -2476,6 +2516,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
 void comedi_free_subdevice_minor(struct comedi_subdevice *s)
 {
        struct comedi_file_info *info;
+       unsigned int i;
 
        if (s == NULL)
                return;
@@ -2485,7 +2526,11 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
        BUG_ON(s->minor >= COMEDI_NUM_MINORS);
        BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS);
 
-       info = comedi_clear_minor(s->minor);
+       i = s->minor - COMEDI_NUM_BOARD_MINORS;
+       mutex_lock(&comedi_subdevice_minor_table_lock);
+       info = comedi_subdevice_minor_table[i];
+       comedi_subdevice_minor_table[i] = NULL;
+       mutex_unlock(&comedi_subdevice_minor_table_lock);
        if (s->class_dev) {
                device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
                s->class_dev = NULL;