linux/drivers/staging/comedi/comedi_fops.c
<<
>>
Prefs
   1/*
   2 * comedi/comedi_fops.c
   3 * comedi kernel module
   4 *
   5 * COMEDI - Linux Control and Measurement Device Interface
   6 * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 */
  18
  19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  20
  21#include "comedi_compat32.h"
  22
  23#include <linux/module.h>
  24#include <linux/errno.h>
  25#include <linux/kernel.h>
  26#include <linux/sched.h>
  27#include <linux/fcntl.h>
  28#include <linux/delay.h>
  29#include <linux/mm.h>
  30#include <linux/slab.h>
  31#include <linux/kmod.h>
  32#include <linux/poll.h>
  33#include <linux/init.h>
  34#include <linux/device.h>
  35#include <linux/vmalloc.h>
  36#include <linux/fs.h>
  37#include "comedidev.h"
  38#include <linux/cdev.h>
  39#include <linux/stat.h>
  40
  41#include <linux/io.h>
  42#include <linux/uaccess.h>
  43
  44#include "comedi_internal.h"
  45
  46/*
  47 * comedi_subdevice "runflags"
  48 * COMEDI_SRF_RT:               DEPRECATED: command is running real-time
  49 * COMEDI_SRF_ERROR:            indicates an COMEDI_CB_ERROR event has occurred
  50 *                              since the last command was started
  51 * COMEDI_SRF_RUNNING:          command is running
  52 * COMEDI_SRF_FREE_SPRIV:       free s->private on detach
  53 *
  54 * COMEDI_SRF_BUSY_MASK:        runflags that indicate the subdevice is "busy"
  55 */
  56#define COMEDI_SRF_RT           BIT(1)
  57#define COMEDI_SRF_ERROR        BIT(2)
  58#define COMEDI_SRF_RUNNING      BIT(27)
  59#define COMEDI_SRF_FREE_SPRIV   BIT(31)
  60
  61#define COMEDI_SRF_BUSY_MASK    (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING)
  62
  63/**
  64 * struct comedi_file - Per-file private data for COMEDI device
  65 * @dev: COMEDI device.
  66 * @read_subdev: Current "read" subdevice.
  67 * @write_subdev: Current "write" subdevice.
  68 * @last_detach_count: Last known detach count.
  69 * @last_attached: Last known attached/detached state.
  70 */
  71struct comedi_file {
  72        struct comedi_device *dev;
  73        struct comedi_subdevice *read_subdev;
  74        struct comedi_subdevice *write_subdev;
  75        unsigned int last_detach_count;
  76        bool last_attached:1;
  77};
  78
  79#define COMEDI_NUM_MINORS 0x100
  80#define COMEDI_NUM_SUBDEVICE_MINORS     \
  81        (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
  82
  83static int comedi_num_legacy_minors;
  84module_param(comedi_num_legacy_minors, int, S_IRUGO);
  85MODULE_PARM_DESC(comedi_num_legacy_minors,
  86                 "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
  87                );
  88
  89unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
  90module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR);
  91MODULE_PARM_DESC(comedi_default_buf_size_kb,
  92                 "default asynchronous buffer size in KiB (default "
  93                 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
  94
  95unsigned int comedi_default_buf_maxsize_kb
  96        = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
  97module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR);
  98MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
  99                 "default maximum size of asynchronous buffer in KiB (default "
 100                 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
 101
 102static DEFINE_MUTEX(comedi_board_minor_table_lock);
 103static struct comedi_device
 104*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS];
 105
 106static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
 107/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */
 108static struct comedi_subdevice
 109*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
 110
 111static struct class *comedi_class;
 112static struct cdev comedi_cdev;
 113
 114static void comedi_device_init(struct comedi_device *dev)
 115{
 116        kref_init(&dev->refcount);
 117        spin_lock_init(&dev->spinlock);
 118        mutex_init(&dev->mutex);
 119        init_rwsem(&dev->attach_lock);
 120        dev->minor = -1;
 121}
 122
 123static void comedi_dev_kref_release(struct kref *kref)
 124{
 125        struct comedi_device *dev =
 126                container_of(kref, struct comedi_device, refcount);
 127
 128        mutex_destroy(&dev->mutex);
 129        put_device(dev->class_dev);
 130        kfree(dev);
 131}
 132
 133/**
 134 * comedi_dev_put() - Release a use of a COMEDI device
 135 * @dev: COMEDI device.
 136 *
 137 * Must be called when a user of a COMEDI device is finished with it.
 138 * When the last user of the COMEDI device calls this function, the
 139 * COMEDI device is destroyed.
 140 *
 141 * Return: 1 if the COMEDI device is destroyed by this call or @dev is
 142 * NULL, otherwise return 0.  Callers must not assume the COMEDI
 143 * device is still valid if this function returns 0.
 144 */
 145int comedi_dev_put(struct comedi_device *dev)
 146{
 147        if (dev)
 148                return kref_put(&dev->refcount, comedi_dev_kref_release);
 149        return 1;
 150}
 151EXPORT_SYMBOL_GPL(comedi_dev_put);
 152
 153static struct comedi_device *comedi_dev_get(struct comedi_device *dev)
 154{
 155        if (dev)
 156                kref_get(&dev->refcount);
 157        return dev;
 158}
 159
 160static void comedi_device_cleanup(struct comedi_device *dev)
 161{
 162        struct module *driver_module = NULL;
 163
 164        if (!dev)
 165                return;
 166        mutex_lock(&dev->mutex);
 167        if (dev->attached)
 168                driver_module = dev->driver->module;
 169        comedi_device_detach(dev);
 170        if (driver_module && dev->use_count)
 171                module_put(driver_module);
 172        mutex_unlock(&dev->mutex);
 173}
 174
 175static bool comedi_clear_board_dev(struct comedi_device *dev)
 176{
 177        unsigned int i = dev->minor;
 178        bool cleared = false;
 179
 180        mutex_lock(&comedi_board_minor_table_lock);
 181        if (dev == comedi_board_minor_table[i]) {
 182                comedi_board_minor_table[i] = NULL;
 183                cleared = true;
 184        }
 185        mutex_unlock(&comedi_board_minor_table_lock);
 186        return cleared;
 187}
 188
 189static struct comedi_device *comedi_clear_board_minor(unsigned minor)
 190{
 191        struct comedi_device *dev;
 192
 193        mutex_lock(&comedi_board_minor_table_lock);
 194        dev = comedi_board_minor_table[minor];
 195        comedi_board_minor_table[minor] = NULL;
 196        mutex_unlock(&comedi_board_minor_table_lock);
 197        return dev;
 198}
 199
 200static void comedi_free_board_dev(struct comedi_device *dev)
 201{
 202        if (dev) {
 203                comedi_device_cleanup(dev);
 204                if (dev->class_dev) {
 205                        device_destroy(comedi_class,
 206                                       MKDEV(COMEDI_MAJOR, dev->minor));
 207                }
 208                comedi_dev_put(dev);
 209        }
 210}
 211
 212static struct comedi_subdevice
 213*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned minor)
 214{
 215        struct comedi_subdevice *s;
 216        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 217
 218        mutex_lock(&comedi_subdevice_minor_table_lock);
 219        s = comedi_subdevice_minor_table[i];
 220        if (s && s->device != dev)
 221                s = NULL;
 222        mutex_unlock(&comedi_subdevice_minor_table_lock);
 223        return s;
 224}
 225
 226static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor)
 227{
 228        struct comedi_device *dev;
 229
 230        mutex_lock(&comedi_board_minor_table_lock);
 231        dev = comedi_dev_get(comedi_board_minor_table[minor]);
 232        mutex_unlock(&comedi_board_minor_table_lock);
 233        return dev;
 234}
 235
 236static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor)
 237{
 238        struct comedi_device *dev;
 239        struct comedi_subdevice *s;
 240        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 241
 242        mutex_lock(&comedi_subdevice_minor_table_lock);
 243        s = comedi_subdevice_minor_table[i];
 244        dev = comedi_dev_get(s ? s->device : NULL);
 245        mutex_unlock(&comedi_subdevice_minor_table_lock);
 246        return dev;
 247}
 248
 249/**
 250 * comedi_dev_get_from_minor() - Get COMEDI device by minor device number
 251 * @minor: Minor device number.
 252 *
 253 * Finds the COMEDI device associated with the minor device number, if any,
 254 * and increments its reference count.  The COMEDI device is prevented from
 255 * being freed until a matching call is made to comedi_dev_put().
 256 *
 257 * Return: A pointer to the COMEDI device if it exists, with its usage
 258 * reference incremented.  Return NULL if no COMEDI device exists with the
 259 * specified minor device number.
 260 */
 261struct comedi_device *comedi_dev_get_from_minor(unsigned minor)
 262{
 263        if (minor < COMEDI_NUM_BOARD_MINORS)
 264                return comedi_dev_get_from_board_minor(minor);
 265
 266        return comedi_dev_get_from_subdevice_minor(minor);
 267}
 268EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor);
 269
 270static struct comedi_subdevice *
 271comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
 272{
 273        struct comedi_subdevice *s;
 274
 275        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 276                s = comedi_subdevice_from_minor(dev, minor);
 277                if (!s || (s->subdev_flags & SDF_CMD_READ))
 278                        return s;
 279        }
 280        return dev->read_subdev;
 281}
 282
 283static struct comedi_subdevice *
 284comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
 285{
 286        struct comedi_subdevice *s;
 287
 288        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 289                s = comedi_subdevice_from_minor(dev, minor);
 290                if (!s || (s->subdev_flags & SDF_CMD_WRITE))
 291                        return s;
 292        }
 293        return dev->write_subdev;
 294}
 295
 296static void comedi_file_reset(struct file *file)
 297{
 298        struct comedi_file *cfp = file->private_data;
 299        struct comedi_device *dev = cfp->dev;
 300        struct comedi_subdevice *s, *read_s, *write_s;
 301        unsigned int minor = iminor(file_inode(file));
 302
 303        read_s = dev->read_subdev;
 304        write_s = dev->write_subdev;
 305        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 306                s = comedi_subdevice_from_minor(dev, minor);
 307                if (!s || s->subdev_flags & SDF_CMD_READ)
 308                        read_s = s;
 309                if (!s || s->subdev_flags & SDF_CMD_WRITE)
 310                        write_s = s;
 311        }
 312        cfp->last_attached = dev->attached;
 313        cfp->last_detach_count = dev->detach_count;
 314        ACCESS_ONCE(cfp->read_subdev) = read_s;
 315        ACCESS_ONCE(cfp->write_subdev) = write_s;
 316}
 317
 318static void comedi_file_check(struct file *file)
 319{
 320        struct comedi_file *cfp = file->private_data;
 321        struct comedi_device *dev = cfp->dev;
 322
 323        if (cfp->last_attached != dev->attached ||
 324            cfp->last_detach_count != dev->detach_count)
 325                comedi_file_reset(file);
 326}
 327
 328static struct comedi_subdevice *comedi_file_read_subdevice(struct file *file)
 329{
 330        struct comedi_file *cfp = file->private_data;
 331
 332        comedi_file_check(file);
 333        return ACCESS_ONCE(cfp->read_subdev);
 334}
 335
 336static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file)
 337{
 338        struct comedi_file *cfp = file->private_data;
 339
 340        comedi_file_check(file);
 341        return ACCESS_ONCE(cfp->write_subdev);
 342}
 343
 344static int resize_async_buffer(struct comedi_device *dev,
 345                               struct comedi_subdevice *s, unsigned new_size)
 346{
 347        struct comedi_async *async = s->async;
 348        int retval;
 349
 350        if (new_size > async->max_bufsize)
 351                return -EPERM;
 352
 353        if (s->busy) {
 354                dev_dbg(dev->class_dev,
 355                        "subdevice is busy, cannot resize buffer\n");
 356                return -EBUSY;
 357        }
 358        if (comedi_buf_is_mmapped(s)) {
 359                dev_dbg(dev->class_dev,
 360                        "subdevice is mmapped, cannot resize buffer\n");
 361                return -EBUSY;
 362        }
 363
 364        /* make sure buffer is an integral number of pages (we round up) */
 365        new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
 366
 367        retval = comedi_buf_alloc(dev, s, new_size);
 368        if (retval < 0)
 369                return retval;
 370
 371        if (s->buf_change) {
 372                retval = s->buf_change(dev, s);
 373                if (retval < 0)
 374                        return retval;
 375        }
 376
 377        dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n",
 378                s->index, async->prealloc_bufsz);
 379        return 0;
 380}
 381
 382/* sysfs attribute files */
 383
 384static ssize_t max_read_buffer_kb_show(struct device *csdev,
 385                                       struct device_attribute *attr, char *buf)
 386{
 387        unsigned int minor = MINOR(csdev->devt);
 388        struct comedi_device *dev;
 389        struct comedi_subdevice *s;
 390        unsigned int size = 0;
 391
 392        dev = comedi_dev_get_from_minor(minor);
 393        if (!dev)
 394                return -ENODEV;
 395
 396        mutex_lock(&dev->mutex);
 397        s = comedi_read_subdevice(dev, minor);
 398        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 399                size = s->async->max_bufsize / 1024;
 400        mutex_unlock(&dev->mutex);
 401
 402        comedi_dev_put(dev);
 403        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 404}
 405
 406static ssize_t max_read_buffer_kb_store(struct device *csdev,
 407                                        struct device_attribute *attr,
 408                                        const char *buf, size_t count)
 409{
 410        unsigned int minor = MINOR(csdev->devt);
 411        struct comedi_device *dev;
 412        struct comedi_subdevice *s;
 413        unsigned int size;
 414        int err;
 415
 416        err = kstrtouint(buf, 10, &size);
 417        if (err)
 418                return err;
 419        if (size > (UINT_MAX / 1024))
 420                return -EINVAL;
 421        size *= 1024;
 422
 423        dev = comedi_dev_get_from_minor(minor);
 424        if (!dev)
 425                return -ENODEV;
 426
 427        mutex_lock(&dev->mutex);
 428        s = comedi_read_subdevice(dev, minor);
 429        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 430                s->async->max_bufsize = size;
 431        else
 432                err = -EINVAL;
 433        mutex_unlock(&dev->mutex);
 434
 435        comedi_dev_put(dev);
 436        return err ? err : count;
 437}
 438static DEVICE_ATTR_RW(max_read_buffer_kb);
 439
 440static ssize_t read_buffer_kb_show(struct device *csdev,
 441                                   struct device_attribute *attr, char *buf)
 442{
 443        unsigned int minor = MINOR(csdev->devt);
 444        struct comedi_device *dev;
 445        struct comedi_subdevice *s;
 446        unsigned int size = 0;
 447
 448        dev = comedi_dev_get_from_minor(minor);
 449        if (!dev)
 450                return -ENODEV;
 451
 452        mutex_lock(&dev->mutex);
 453        s = comedi_read_subdevice(dev, minor);
 454        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 455                size = s->async->prealloc_bufsz / 1024;
 456        mutex_unlock(&dev->mutex);
 457
 458        comedi_dev_put(dev);
 459        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 460}
 461
 462static ssize_t read_buffer_kb_store(struct device *csdev,
 463                                    struct device_attribute *attr,
 464                                    const char *buf, size_t count)
 465{
 466        unsigned int minor = MINOR(csdev->devt);
 467        struct comedi_device *dev;
 468        struct comedi_subdevice *s;
 469        unsigned int size;
 470        int err;
 471
 472        err = kstrtouint(buf, 10, &size);
 473        if (err)
 474                return err;
 475        if (size > (UINT_MAX / 1024))
 476                return -EINVAL;
 477        size *= 1024;
 478
 479        dev = comedi_dev_get_from_minor(minor);
 480        if (!dev)
 481                return -ENODEV;
 482
 483        mutex_lock(&dev->mutex);
 484        s = comedi_read_subdevice(dev, minor);
 485        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 486                err = resize_async_buffer(dev, s, size);
 487        else
 488                err = -EINVAL;
 489        mutex_unlock(&dev->mutex);
 490
 491        comedi_dev_put(dev);
 492        return err ? err : count;
 493}
 494static DEVICE_ATTR_RW(read_buffer_kb);
 495
 496static ssize_t max_write_buffer_kb_show(struct device *csdev,
 497                                        struct device_attribute *attr,
 498                                        char *buf)
 499{
 500        unsigned int minor = MINOR(csdev->devt);
 501        struct comedi_device *dev;
 502        struct comedi_subdevice *s;
 503        unsigned int size = 0;
 504
 505        dev = comedi_dev_get_from_minor(minor);
 506        if (!dev)
 507                return -ENODEV;
 508
 509        mutex_lock(&dev->mutex);
 510        s = comedi_write_subdevice(dev, minor);
 511        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 512                size = s->async->max_bufsize / 1024;
 513        mutex_unlock(&dev->mutex);
 514
 515        comedi_dev_put(dev);
 516        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 517}
 518
 519static ssize_t max_write_buffer_kb_store(struct device *csdev,
 520                                         struct device_attribute *attr,
 521                                         const char *buf, size_t count)
 522{
 523        unsigned int minor = MINOR(csdev->devt);
 524        struct comedi_device *dev;
 525        struct comedi_subdevice *s;
 526        unsigned int size;
 527        int err;
 528
 529        err = kstrtouint(buf, 10, &size);
 530        if (err)
 531                return err;
 532        if (size > (UINT_MAX / 1024))
 533                return -EINVAL;
 534        size *= 1024;
 535
 536        dev = comedi_dev_get_from_minor(minor);
 537        if (!dev)
 538                return -ENODEV;
 539
 540        mutex_lock(&dev->mutex);
 541        s = comedi_write_subdevice(dev, minor);
 542        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 543                s->async->max_bufsize = size;
 544        else
 545                err = -EINVAL;
 546        mutex_unlock(&dev->mutex);
 547
 548        comedi_dev_put(dev);
 549        return err ? err : count;
 550}
 551static DEVICE_ATTR_RW(max_write_buffer_kb);
 552
 553static ssize_t write_buffer_kb_show(struct device *csdev,
 554                                    struct device_attribute *attr, char *buf)
 555{
 556        unsigned int minor = MINOR(csdev->devt);
 557        struct comedi_device *dev;
 558        struct comedi_subdevice *s;
 559        unsigned int size = 0;
 560
 561        dev = comedi_dev_get_from_minor(minor);
 562        if (!dev)
 563                return -ENODEV;
 564
 565        mutex_lock(&dev->mutex);
 566        s = comedi_write_subdevice(dev, minor);
 567        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 568                size = s->async->prealloc_bufsz / 1024;
 569        mutex_unlock(&dev->mutex);
 570
 571        comedi_dev_put(dev);
 572        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 573}
 574
 575static ssize_t write_buffer_kb_store(struct device *csdev,
 576                                     struct device_attribute *attr,
 577                                     const char *buf, size_t count)
 578{
 579        unsigned int minor = MINOR(csdev->devt);
 580        struct comedi_device *dev;
 581        struct comedi_subdevice *s;
 582        unsigned int size;
 583        int err;
 584
 585        err = kstrtouint(buf, 10, &size);
 586        if (err)
 587                return err;
 588        if (size > (UINT_MAX / 1024))
 589                return -EINVAL;
 590        size *= 1024;
 591
 592        dev = comedi_dev_get_from_minor(minor);
 593        if (!dev)
 594                return -ENODEV;
 595
 596        mutex_lock(&dev->mutex);
 597        s = comedi_write_subdevice(dev, minor);
 598        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 599                err = resize_async_buffer(dev, s, size);
 600        else
 601                err = -EINVAL;
 602        mutex_unlock(&dev->mutex);
 603
 604        comedi_dev_put(dev);
 605        return err ? err : count;
 606}
 607static DEVICE_ATTR_RW(write_buffer_kb);
 608
 609static struct attribute *comedi_dev_attrs[] = {
 610        &dev_attr_max_read_buffer_kb.attr,
 611        &dev_attr_read_buffer_kb.attr,
 612        &dev_attr_max_write_buffer_kb.attr,
 613        &dev_attr_write_buffer_kb.attr,
 614        NULL,
 615};
 616ATTRIBUTE_GROUPS(comedi_dev);
 617
 618static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
 619                                              unsigned bits)
 620{
 621        s->runflags &= ~bits;
 622}
 623
 624static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s,
 625                                            unsigned bits)
 626{
 627        s->runflags |= bits;
 628}
 629
 630static void comedi_update_subdevice_runflags(struct comedi_subdevice *s,
 631                                             unsigned mask, unsigned bits)
 632{
 633        unsigned long flags;
 634
 635        spin_lock_irqsave(&s->spin_lock, flags);
 636        __comedi_clear_subdevice_runflags(s, mask);
 637        __comedi_set_subdevice_runflags(s, bits & mask);
 638        spin_unlock_irqrestore(&s->spin_lock, flags);
 639}
 640
 641static unsigned __comedi_get_subdevice_runflags(struct comedi_subdevice *s)
 642{
 643        return s->runflags;
 644}
 645
 646static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
 647{
 648        unsigned long flags;
 649        unsigned runflags;
 650
 651        spin_lock_irqsave(&s->spin_lock, flags);
 652        runflags = __comedi_get_subdevice_runflags(s);
 653        spin_unlock_irqrestore(&s->spin_lock, flags);
 654        return runflags;
 655}
 656
 657static bool comedi_is_runflags_running(unsigned runflags)
 658{
 659        return runflags & COMEDI_SRF_RUNNING;
 660}
 661
 662static bool comedi_is_runflags_in_error(unsigned runflags)
 663{
 664        return runflags & COMEDI_SRF_ERROR;
 665}
 666
 667/**
 668 * comedi_is_subdevice_running() - Check if async command running on subdevice
 669 * @s: COMEDI subdevice.
 670 *
 671 * Return: %true if an asynchronous COMEDI command is active on the
 672 * subdevice, else %false.
 673 */
 674bool comedi_is_subdevice_running(struct comedi_subdevice *s)
 675{
 676        unsigned runflags = comedi_get_subdevice_runflags(s);
 677
 678        return comedi_is_runflags_running(runflags);
 679}
 680EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
 681
 682static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
 683{
 684        unsigned runflags = __comedi_get_subdevice_runflags(s);
 685
 686        return comedi_is_runflags_running(runflags);
 687}
 688
 689bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
 690{
 691        unsigned runflags = __comedi_get_subdevice_runflags(s);
 692
 693        return runflags & COMEDI_SRF_FREE_SPRIV;
 694}
 695
 696/**
 697 * comedi_set_spriv_auto_free() - Mark subdevice private data as freeable
 698 * @s: COMEDI subdevice.
 699 *
 700 * Mark the subdevice as having a pointer to private data that can be
 701 * automatically freed when the COMEDI device is detached from the low-level
 702 * driver.
 703 */
 704void comedi_set_spriv_auto_free(struct comedi_subdevice *s)
 705{
 706        __comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV);
 707}
 708EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free);
 709
 710/**
 711 * comedi_alloc_spriv - Allocate memory for the subdevice private data
 712 * @s: COMEDI subdevice.
 713 * @size: Size of the memory to allocate.
 714 *
 715 * Allocate memory for the subdevice private data and point @s->private
 716 * to it.  The memory will be freed automatically when the COMEDI device
 717 * is detached from the low-level driver.
 718 *
 719 * Return: A pointer to the allocated memory @s->private on success.
 720 * Return NULL on failure.
 721 */
 722void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size)
 723{
 724        s->private = kzalloc(size, GFP_KERNEL);
 725        if (s->private)
 726                comedi_set_spriv_auto_free(s);
 727        return s->private;
 728}
 729EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
 730
 731/*
 732 * This function restores a subdevice to an idle state.
 733 */
 734static void do_become_nonbusy(struct comedi_device *dev,
 735                              struct comedi_subdevice *s)
 736{
 737        struct comedi_async *async = s->async;
 738
 739        comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
 740        if (async) {
 741                comedi_buf_reset(s);
 742                async->inttrig = NULL;
 743                kfree(async->cmd.chanlist);
 744                async->cmd.chanlist = NULL;
 745                s->busy = NULL;
 746                wake_up_interruptible_all(&async->wait_head);
 747        } else {
 748                dev_err(dev->class_dev,
 749                        "BUG: (?) do_become_nonbusy called with async=NULL\n");
 750                s->busy = NULL;
 751        }
 752}
 753
 754static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 755{
 756        int ret = 0;
 757
 758        if (comedi_is_subdevice_running(s) && s->cancel)
 759                ret = s->cancel(dev, s);
 760
 761        do_become_nonbusy(dev, s);
 762
 763        return ret;
 764}
 765
 766void comedi_device_cancel_all(struct comedi_device *dev)
 767{
 768        struct comedi_subdevice *s;
 769        int i;
 770
 771        if (!dev->attached)
 772                return;
 773
 774        for (i = 0; i < dev->n_subdevices; i++) {
 775                s = &dev->subdevices[i];
 776                if (s->async)
 777                        do_cancel(dev, s);
 778        }
 779}
 780
 781static int is_device_busy(struct comedi_device *dev)
 782{
 783        struct comedi_subdevice *s;
 784        int i;
 785
 786        if (!dev->attached)
 787                return 0;
 788
 789        for (i = 0; i < dev->n_subdevices; i++) {
 790                s = &dev->subdevices[i];
 791                if (s->busy)
 792                        return 1;
 793                if (s->async && comedi_buf_is_mmapped(s))
 794                        return 1;
 795        }
 796
 797        return 0;
 798}
 799
 800/*
 801 * COMEDI_DEVCONFIG ioctl
 802 * attaches (and configures) or detaches a legacy device
 803 *
 804 * arg:
 805 *      pointer to comedi_devconfig structure (NULL if detaching)
 806 *
 807 * reads:
 808 *      comedi_devconfig structure (if attaching)
 809 *
 810 * writes:
 811 *      nothing
 812 */
 813static int do_devconfig_ioctl(struct comedi_device *dev,
 814                              struct comedi_devconfig __user *arg)
 815{
 816        struct comedi_devconfig it;
 817
 818        if (!capable(CAP_SYS_ADMIN))
 819                return -EPERM;
 820
 821        if (!arg) {
 822                if (is_device_busy(dev))
 823                        return -EBUSY;
 824                if (dev->attached) {
 825                        struct module *driver_module = dev->driver->module;
 826
 827                        comedi_device_detach(dev);
 828                        module_put(driver_module);
 829                }
 830                return 0;
 831        }
 832
 833        if (copy_from_user(&it, arg, sizeof(it)))
 834                return -EFAULT;
 835
 836        it.board_name[COMEDI_NAMELEN - 1] = 0;
 837
 838        if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
 839                dev_warn(dev->class_dev,
 840                         "comedi_config --init_data is deprecated\n");
 841                return -EINVAL;
 842        }
 843
 844        if (dev->minor >= comedi_num_legacy_minors)
 845                /* don't re-use dynamically allocated comedi devices */
 846                return -EBUSY;
 847
 848        /* This increments the driver module count on success. */
 849        return comedi_device_attach(dev, &it);
 850}
 851
 852/*
 853 * COMEDI_BUFCONFIG ioctl
 854 * buffer configuration
 855 *
 856 * arg:
 857 *      pointer to comedi_bufconfig structure
 858 *
 859 * reads:
 860 *      comedi_bufconfig structure
 861 *
 862 * writes:
 863 *      modified comedi_bufconfig structure
 864 */
 865static int do_bufconfig_ioctl(struct comedi_device *dev,
 866                              struct comedi_bufconfig __user *arg)
 867{
 868        struct comedi_bufconfig bc;
 869        struct comedi_async *async;
 870        struct comedi_subdevice *s;
 871        int retval = 0;
 872
 873        if (copy_from_user(&bc, arg, sizeof(bc)))
 874                return -EFAULT;
 875
 876        if (bc.subdevice >= dev->n_subdevices)
 877                return -EINVAL;
 878
 879        s = &dev->subdevices[bc.subdevice];
 880        async = s->async;
 881
 882        if (!async) {
 883                dev_dbg(dev->class_dev,
 884                        "subdevice does not have async capability\n");
 885                bc.size = 0;
 886                bc.maximum_size = 0;
 887                goto copyback;
 888        }
 889
 890        if (bc.maximum_size) {
 891                if (!capable(CAP_SYS_ADMIN))
 892                        return -EPERM;
 893
 894                async->max_bufsize = bc.maximum_size;
 895        }
 896
 897        if (bc.size) {
 898                retval = resize_async_buffer(dev, s, bc.size);
 899                if (retval < 0)
 900                        return retval;
 901        }
 902
 903        bc.size = async->prealloc_bufsz;
 904        bc.maximum_size = async->max_bufsize;
 905
 906copyback:
 907        if (copy_to_user(arg, &bc, sizeof(bc)))
 908                return -EFAULT;
 909
 910        return 0;
 911}
 912
 913/*
 914 * COMEDI_DEVINFO ioctl
 915 * device info
 916 *
 917 * arg:
 918 *      pointer to comedi_devinfo structure
 919 *
 920 * reads:
 921 *      nothing
 922 *
 923 * writes:
 924 *      comedi_devinfo structure
 925 */
 926static int do_devinfo_ioctl(struct comedi_device *dev,
 927                            struct comedi_devinfo __user *arg,
 928                            struct file *file)
 929{
 930        struct comedi_subdevice *s;
 931        struct comedi_devinfo devinfo;
 932
 933        memset(&devinfo, 0, sizeof(devinfo));
 934
 935        /* fill devinfo structure */
 936        devinfo.version_code = COMEDI_VERSION_CODE;
 937        devinfo.n_subdevs = dev->n_subdevices;
 938        strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
 939        strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
 940
 941        s = comedi_file_read_subdevice(file);
 942        if (s)
 943                devinfo.read_subdevice = s->index;
 944        else
 945                devinfo.read_subdevice = -1;
 946
 947        s = comedi_file_write_subdevice(file);
 948        if (s)
 949                devinfo.write_subdevice = s->index;
 950        else
 951                devinfo.write_subdevice = -1;
 952
 953        if (copy_to_user(arg, &devinfo, sizeof(devinfo)))
 954                return -EFAULT;
 955
 956        return 0;
 957}
 958
 959/*
 960 * COMEDI_SUBDINFO ioctl
 961 * subdevices info
 962 *
 963 * arg:
 964 *      pointer to array of comedi_subdinfo structures
 965 *
 966 * reads:
 967 *      nothing
 968 *
 969 * writes:
 970 *      array of comedi_subdinfo structures
 971 */
 972static int do_subdinfo_ioctl(struct comedi_device *dev,
 973                             struct comedi_subdinfo __user *arg, void *file)
 974{
 975        int ret, i;
 976        struct comedi_subdinfo *tmp, *us;
 977        struct comedi_subdevice *s;
 978
 979        tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL);
 980        if (!tmp)
 981                return -ENOMEM;
 982
 983        /* fill subdinfo structs */
 984        for (i = 0; i < dev->n_subdevices; i++) {
 985                s = &dev->subdevices[i];
 986                us = tmp + i;
 987
 988                us->type = s->type;
 989                us->n_chan = s->n_chan;
 990                us->subd_flags = s->subdev_flags;
 991                if (comedi_is_subdevice_running(s))
 992                        us->subd_flags |= SDF_RUNNING;
 993#define TIMER_nanosec 5         /* backwards compatibility */
 994                us->timer_type = TIMER_nanosec;
 995                us->len_chanlist = s->len_chanlist;
 996                us->maxdata = s->maxdata;
 997                if (s->range_table) {
 998                        us->range_type =
 999                            (i << 24) | (0 << 16) | (s->range_table->length);
1000                } else {
1001                        us->range_type = 0;     /* XXX */
1002                }
1003
1004                if (s->busy)
1005                        us->subd_flags |= SDF_BUSY;
1006                if (s->busy == file)
1007                        us->subd_flags |= SDF_BUSY_OWNER;
1008                if (s->lock)
1009                        us->subd_flags |= SDF_LOCKED;
1010                if (s->lock == file)
1011                        us->subd_flags |= SDF_LOCK_OWNER;
1012                if (!s->maxdata && s->maxdata_list)
1013                        us->subd_flags |= SDF_MAXDATA;
1014                if (s->range_table_list)
1015                        us->subd_flags |= SDF_RANGETYPE;
1016                if (s->do_cmd)
1017                        us->subd_flags |= SDF_CMD;
1018
1019                if (s->insn_bits != &insn_inval)
1020                        us->insn_bits_support = COMEDI_SUPPORTED;
1021                else
1022                        us->insn_bits_support = COMEDI_UNSUPPORTED;
1023        }
1024
1025        ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
1026
1027        kfree(tmp);
1028
1029        return ret ? -EFAULT : 0;
1030}
1031
1032/*
1033 * COMEDI_CHANINFO ioctl
1034 * subdevice channel info
1035 *
1036 * arg:
1037 *      pointer to comedi_chaninfo structure
1038 *
1039 * reads:
1040 *      comedi_chaninfo structure
1041 *
1042 * writes:
1043 *      array of maxdata values to chaninfo->maxdata_list if requested
1044 *      array of range table lengths to chaninfo->range_table_list if requested
1045 */
1046static int do_chaninfo_ioctl(struct comedi_device *dev,
1047                             struct comedi_chaninfo __user *arg)
1048{
1049        struct comedi_subdevice *s;
1050        struct comedi_chaninfo it;
1051
1052        if (copy_from_user(&it, arg, sizeof(it)))
1053                return -EFAULT;
1054
1055        if (it.subdev >= dev->n_subdevices)
1056                return -EINVAL;
1057        s = &dev->subdevices[it.subdev];
1058
1059        if (it.maxdata_list) {
1060                if (s->maxdata || !s->maxdata_list)
1061                        return -EINVAL;
1062                if (copy_to_user(it.maxdata_list, s->maxdata_list,
1063                                 s->n_chan * sizeof(unsigned int)))
1064                        return -EFAULT;
1065        }
1066
1067        if (it.flaglist)
1068                return -EINVAL; /* flaglist not supported */
1069
1070        if (it.rangelist) {
1071                int i;
1072
1073                if (!s->range_table_list)
1074                        return -EINVAL;
1075                for (i = 0; i < s->n_chan; i++) {
1076                        int x;
1077
1078                        x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
1079                            (s->range_table_list[i]->length);
1080                        if (put_user(x, it.rangelist + i))
1081                                return -EFAULT;
1082                }
1083        }
1084
1085        return 0;
1086}
1087
1088/*
1089 * COMEDI_BUFINFO ioctl
1090 * buffer information
1091 *
1092 * arg:
1093 *      pointer to comedi_bufinfo structure
1094 *
1095 * reads:
1096 *      comedi_bufinfo structure
1097 *
1098 * writes:
1099 *      modified comedi_bufinfo structure
1100 */
1101static int do_bufinfo_ioctl(struct comedi_device *dev,
1102                            struct comedi_bufinfo __user *arg, void *file)
1103{
1104        struct comedi_bufinfo bi;
1105        struct comedi_subdevice *s;
1106        struct comedi_async *async;
1107        unsigned int runflags;
1108        int retval = 0;
1109        bool become_nonbusy = false;
1110
1111        if (copy_from_user(&bi, arg, sizeof(bi)))
1112                return -EFAULT;
1113
1114        if (bi.subdevice >= dev->n_subdevices)
1115                return -EINVAL;
1116
1117        s = &dev->subdevices[bi.subdevice];
1118
1119        async = s->async;
1120
1121        if (!async || s->busy != file)
1122                return -EINVAL;
1123
1124        runflags = comedi_get_subdevice_runflags(s);
1125        if (!(async->cmd.flags & CMDF_WRITE)) {
1126                /* command was set up in "read" direction */
1127                if (bi.bytes_read) {
1128                        comedi_buf_read_alloc(s, bi.bytes_read);
1129                        bi.bytes_read = comedi_buf_read_free(s, bi.bytes_read);
1130                }
1131                /*
1132                 * If nothing left to read, and command has stopped, and
1133                 * {"read" position not updated or command stopped normally},
1134                 * then become non-busy.
1135                 */
1136                if (comedi_buf_read_n_available(s) == 0 &&
1137                    !comedi_is_runflags_running(runflags) &&
1138                    (bi.bytes_read == 0 ||
1139                     !comedi_is_runflags_in_error(runflags))) {
1140                        become_nonbusy = true;
1141                        if (comedi_is_runflags_in_error(runflags))
1142                                retval = -EPIPE;
1143                }
1144                bi.bytes_written = 0;
1145        } else {
1146                /* command was set up in "write" direction */
1147                if (!comedi_is_runflags_running(runflags)) {
1148                        bi.bytes_written = 0;
1149                        become_nonbusy = true;
1150                        if (comedi_is_runflags_in_error(runflags))
1151                                retval = -EPIPE;
1152                } else if (bi.bytes_written) {
1153                        comedi_buf_write_alloc(s, bi.bytes_written);
1154                        bi.bytes_written =
1155                            comedi_buf_write_free(s, bi.bytes_written);
1156                }
1157                bi.bytes_read = 0;
1158        }
1159
1160        bi.buf_write_count = async->buf_write_count;
1161        bi.buf_write_ptr = async->buf_write_ptr;
1162        bi.buf_read_count = async->buf_read_count;
1163        bi.buf_read_ptr = async->buf_read_ptr;
1164
1165        if (become_nonbusy)
1166                do_become_nonbusy(dev, s);
1167
1168        if (retval)
1169                return retval;
1170
1171        if (copy_to_user(arg, &bi, sizeof(bi)))
1172                return -EFAULT;
1173
1174        return 0;
1175}
1176
1177static int check_insn_config_length(struct comedi_insn *insn,
1178                                    unsigned int *data)
1179{
1180        if (insn->n < 1)
1181                return -EINVAL;
1182
1183        switch (data[0]) {
1184        case INSN_CONFIG_DIO_OUTPUT:
1185        case INSN_CONFIG_DIO_INPUT:
1186        case INSN_CONFIG_DISARM:
1187        case INSN_CONFIG_RESET:
1188                if (insn->n == 1)
1189                        return 0;
1190                break;
1191        case INSN_CONFIG_ARM:
1192        case INSN_CONFIG_DIO_QUERY:
1193        case INSN_CONFIG_BLOCK_SIZE:
1194        case INSN_CONFIG_FILTER:
1195        case INSN_CONFIG_SERIAL_CLOCK:
1196        case INSN_CONFIG_BIDIRECTIONAL_DATA:
1197        case INSN_CONFIG_ALT_SOURCE:
1198        case INSN_CONFIG_SET_COUNTER_MODE:
1199        case INSN_CONFIG_8254_READ_STATUS:
1200        case INSN_CONFIG_SET_ROUTING:
1201        case INSN_CONFIG_GET_ROUTING:
1202        case INSN_CONFIG_GET_PWM_STATUS:
1203        case INSN_CONFIG_PWM_SET_PERIOD:
1204        case INSN_CONFIG_PWM_GET_PERIOD:
1205                if (insn->n == 2)
1206                        return 0;
1207                break;
1208        case INSN_CONFIG_SET_GATE_SRC:
1209        case INSN_CONFIG_GET_GATE_SRC:
1210        case INSN_CONFIG_SET_CLOCK_SRC:
1211        case INSN_CONFIG_GET_CLOCK_SRC:
1212        case INSN_CONFIG_SET_OTHER_SRC:
1213        case INSN_CONFIG_GET_COUNTER_STATUS:
1214        case INSN_CONFIG_PWM_SET_H_BRIDGE:
1215        case INSN_CONFIG_PWM_GET_H_BRIDGE:
1216        case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
1217                if (insn->n == 3)
1218                        return 0;
1219                break;
1220        case INSN_CONFIG_PWM_OUTPUT:
1221        case INSN_CONFIG_ANALOG_TRIG:
1222                if (insn->n == 5)
1223                        return 0;
1224                break;
1225        case INSN_CONFIG_DIGITAL_TRIG:
1226                if (insn->n == 6)
1227                        return 0;
1228                break;
1229                /*
1230                 * by default we allow the insn since we don't have checks for
1231                 * all possible cases yet
1232                 */
1233        default:
1234                pr_warn("No check for data length of config insn id %i is implemented\n",
1235                        data[0]);
1236                pr_warn("Add a check to %s in %s\n", __func__, __FILE__);
1237                pr_warn("Assuming n=%i is correct\n", insn->n);
1238                return 0;
1239        }
1240        return -EINVAL;
1241}
1242
1243static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
1244                      unsigned int *data, void *file)
1245{
1246        struct comedi_subdevice *s;
1247        int ret = 0;
1248        int i;
1249
1250        if (insn->insn & INSN_MASK_SPECIAL) {
1251                /* a non-subdevice instruction */
1252
1253                switch (insn->insn) {
1254                case INSN_GTOD:
1255                        {
1256                                struct timeval tv;
1257
1258                                if (insn->n != 2) {
1259                                        ret = -EINVAL;
1260                                        break;
1261                                }
1262
1263                                do_gettimeofday(&tv);
1264                                data[0] = tv.tv_sec;
1265                                data[1] = tv.tv_usec;
1266                                ret = 2;
1267
1268                                break;
1269                        }
1270                case INSN_WAIT:
1271                        if (insn->n != 1 || data[0] >= 100000) {
1272                                ret = -EINVAL;
1273                                break;
1274                        }
1275                        udelay(data[0] / 1000);
1276                        ret = 1;
1277                        break;
1278                case INSN_INTTRIG:
1279                        if (insn->n != 1) {
1280                                ret = -EINVAL;
1281                                break;
1282                        }
1283                        if (insn->subdev >= dev->n_subdevices) {
1284                                dev_dbg(dev->class_dev,
1285                                        "%d not usable subdevice\n",
1286                                        insn->subdev);
1287                                ret = -EINVAL;
1288                                break;
1289                        }
1290                        s = &dev->subdevices[insn->subdev];
1291                        if (!s->async) {
1292                                dev_dbg(dev->class_dev, "no async\n");
1293                                ret = -EINVAL;
1294                                break;
1295                        }
1296                        if (!s->async->inttrig) {
1297                                dev_dbg(dev->class_dev, "no inttrig\n");
1298                                ret = -EAGAIN;
1299                                break;
1300                        }
1301                        ret = s->async->inttrig(dev, s, data[0]);
1302                        if (ret >= 0)
1303                                ret = 1;
1304                        break;
1305                default:
1306                        dev_dbg(dev->class_dev, "invalid insn\n");
1307                        ret = -EINVAL;
1308                        break;
1309                }
1310        } else {
1311                /* a subdevice instruction */
1312                unsigned int maxdata;
1313
1314                if (insn->subdev >= dev->n_subdevices) {
1315                        dev_dbg(dev->class_dev, "subdevice %d out of range\n",
1316                                insn->subdev);
1317                        ret = -EINVAL;
1318                        goto out;
1319                }
1320                s = &dev->subdevices[insn->subdev];
1321
1322                if (s->type == COMEDI_SUBD_UNUSED) {
1323                        dev_dbg(dev->class_dev, "%d not usable subdevice\n",
1324                                insn->subdev);
1325                        ret = -EIO;
1326                        goto out;
1327                }
1328
1329                /* are we locked? (ioctl lock) */
1330                if (s->lock && s->lock != file) {
1331                        dev_dbg(dev->class_dev, "device locked\n");
1332                        ret = -EACCES;
1333                        goto out;
1334                }
1335
1336                ret = comedi_check_chanlist(s, 1, &insn->chanspec);
1337                if (ret < 0) {
1338                        ret = -EINVAL;
1339                        dev_dbg(dev->class_dev, "bad chanspec\n");
1340                        goto out;
1341                }
1342
1343                if (s->busy) {
1344                        ret = -EBUSY;
1345                        goto out;
1346                }
1347                /* This looks arbitrary.  It is. */
1348                s->busy = parse_insn;
1349                switch (insn->insn) {
1350                case INSN_READ:
1351                        ret = s->insn_read(dev, s, insn, data);
1352                        if (ret == -ETIMEDOUT) {
1353                                dev_dbg(dev->class_dev,
1354                                        "subdevice %d read instruction timed out\n",
1355                                        s->index);
1356                        }
1357                        break;
1358                case INSN_WRITE:
1359                        maxdata = s->maxdata_list
1360                            ? s->maxdata_list[CR_CHAN(insn->chanspec)]
1361                            : s->maxdata;
1362                        for (i = 0; i < insn->n; ++i) {
1363                                if (data[i] > maxdata) {
1364                                        ret = -EINVAL;
1365                                        dev_dbg(dev->class_dev,
1366                                                "bad data value(s)\n");
1367                                        break;
1368                                }
1369                        }
1370                        if (ret == 0) {
1371                                ret = s->insn_write(dev, s, insn, data);
1372                                if (ret == -ETIMEDOUT) {
1373                                        dev_dbg(dev->class_dev,
1374                                                "subdevice %d write instruction timed out\n",
1375                                                s->index);
1376                                }
1377                        }
1378                        break;
1379                case INSN_BITS:
1380                        if (insn->n != 2) {
1381                                ret = -EINVAL;
1382                        } else {
1383                                /*
1384                                 * Most drivers ignore the base channel in
1385                                 * insn->chanspec.  Fix this here if
1386                                 * the subdevice has <= 32 channels.
1387                                 */
1388                                unsigned int orig_mask = data[0];
1389                                unsigned int shift = 0;
1390
1391                                if (s->n_chan <= 32) {
1392                                        shift = CR_CHAN(insn->chanspec);
1393                                        if (shift > 0) {
1394                                                insn->chanspec = 0;
1395                                                data[0] <<= shift;
1396                                                data[1] <<= shift;
1397                                        }
1398                                }
1399                                ret = s->insn_bits(dev, s, insn, data);
1400                                data[0] = orig_mask;
1401                                if (shift > 0)
1402                                        data[1] >>= shift;
1403                        }
1404                        break;
1405                case INSN_CONFIG:
1406                        ret = check_insn_config_length(insn, data);
1407                        if (ret)
1408                                break;
1409                        ret = s->insn_config(dev, s, insn, data);
1410                        break;
1411                default:
1412                        ret = -EINVAL;
1413                        break;
1414                }
1415
1416                s->busy = NULL;
1417        }
1418
1419out:
1420        return ret;
1421}
1422
1423/*
1424 * COMEDI_INSNLIST ioctl
1425 * synchronous instruction list
1426 *
1427 * arg:
1428 *      pointer to comedi_insnlist structure
1429 *
1430 * reads:
1431 *      comedi_insnlist structure
1432 *      array of comedi_insn structures from insnlist->insns pointer
1433 *      data (for writes) from insns[].data pointers
1434 *
1435 * writes:
1436 *      data (for reads) to insns[].data pointers
1437 */
1438/* arbitrary limits */
1439#define MAX_SAMPLES 256
1440static int do_insnlist_ioctl(struct comedi_device *dev,
1441                             struct comedi_insnlist __user *arg, void *file)
1442{
1443        struct comedi_insnlist insnlist;
1444        struct comedi_insn *insns = NULL;
1445        unsigned int *data = NULL;
1446        int i = 0;
1447        int ret = 0;
1448
1449        if (copy_from_user(&insnlist, arg, sizeof(insnlist)))
1450                return -EFAULT;
1451
1452        data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
1453        if (!data) {
1454                ret = -ENOMEM;
1455                goto error;
1456        }
1457
1458        insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
1459        if (!insns) {
1460                ret = -ENOMEM;
1461                goto error;
1462        }
1463
1464        if (copy_from_user(insns, insnlist.insns,
1465                           sizeof(*insns) * insnlist.n_insns)) {
1466                dev_dbg(dev->class_dev, "copy_from_user failed\n");
1467                ret = -EFAULT;
1468                goto error;
1469        }
1470
1471        for (i = 0; i < insnlist.n_insns; i++) {
1472                if (insns[i].n > MAX_SAMPLES) {
1473                        dev_dbg(dev->class_dev,
1474                                "number of samples too large\n");
1475                        ret = -EINVAL;
1476                        goto error;
1477                }
1478                if (insns[i].insn & INSN_MASK_WRITE) {
1479                        if (copy_from_user(data, insns[i].data,
1480                                           insns[i].n * sizeof(unsigned int))) {
1481                                dev_dbg(dev->class_dev,
1482                                        "copy_from_user failed\n");
1483                                ret = -EFAULT;
1484                                goto error;
1485                        }
1486                }
1487                ret = parse_insn(dev, insns + i, data, file);
1488                if (ret < 0)
1489                        goto error;
1490                if (insns[i].insn & INSN_MASK_READ) {
1491                        if (copy_to_user(insns[i].data, data,
1492                                         insns[i].n * sizeof(unsigned int))) {
1493                                dev_dbg(dev->class_dev,
1494                                        "copy_to_user failed\n");
1495                                ret = -EFAULT;
1496                                goto error;
1497                        }
1498                }
1499                if (need_resched())
1500                        schedule();
1501        }
1502
1503error:
1504        kfree(insns);
1505        kfree(data);
1506
1507        if (ret < 0)
1508                return ret;
1509        return i;
1510}
1511
1512/*
1513 * COMEDI_INSN ioctl
1514 * synchronous instruction
1515 *
1516 * arg:
1517 *      pointer to comedi_insn structure
1518 *
1519 * reads:
1520 *      comedi_insn structure
1521 *      data (for writes) from insn->data pointer
1522 *
1523 * writes:
1524 *      data (for reads) to insn->data pointer
1525 */
1526static int do_insn_ioctl(struct comedi_device *dev,
1527                         struct comedi_insn __user *arg, void *file)
1528{
1529        struct comedi_insn insn;
1530        unsigned int *data = NULL;
1531        int ret = 0;
1532
1533        data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
1534        if (!data) {
1535                ret = -ENOMEM;
1536                goto error;
1537        }
1538
1539        if (copy_from_user(&insn, arg, sizeof(insn))) {
1540                ret = -EFAULT;
1541                goto error;
1542        }
1543
1544        /* This is where the behavior of insn and insnlist deviate. */
1545        if (insn.n > MAX_SAMPLES)
1546                insn.n = MAX_SAMPLES;
1547        if (insn.insn & INSN_MASK_WRITE) {
1548                if (copy_from_user(data,
1549                                   insn.data,
1550                                   insn.n * sizeof(unsigned int))) {
1551                        ret = -EFAULT;
1552                        goto error;
1553                }
1554        }
1555        ret = parse_insn(dev, &insn, data, file);
1556        if (ret < 0)
1557                goto error;
1558        if (insn.insn & INSN_MASK_READ) {
1559                if (copy_to_user(insn.data,
1560                                 data,
1561                                 insn.n * sizeof(unsigned int))) {
1562                        ret = -EFAULT;
1563                        goto error;
1564                }
1565        }
1566        ret = insn.n;
1567
1568error:
1569        kfree(data);
1570
1571        return ret;
1572}
1573
1574static int __comedi_get_user_cmd(struct comedi_device *dev,
1575                                 struct comedi_cmd __user *arg,
1576                                 struct comedi_cmd *cmd)
1577{
1578        struct comedi_subdevice *s;
1579
1580        if (copy_from_user(cmd, arg, sizeof(*cmd))) {
1581                dev_dbg(dev->class_dev, "bad cmd address\n");
1582                return -EFAULT;
1583        }
1584
1585        if (cmd->subdev >= dev->n_subdevices) {
1586                dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd->subdev);
1587                return -ENODEV;
1588        }
1589
1590        s = &dev->subdevices[cmd->subdev];
1591
1592        if (s->type == COMEDI_SUBD_UNUSED) {
1593                dev_dbg(dev->class_dev, "%d not valid subdevice\n",
1594                        cmd->subdev);
1595                return -EIO;
1596        }
1597
1598        if (!s->do_cmd || !s->do_cmdtest || !s->async) {
1599                dev_dbg(dev->class_dev,
1600                        "subdevice %d does not support commands\n",
1601                        cmd->subdev);
1602                return -EIO;
1603        }
1604
1605        /* make sure channel/gain list isn't too long */
1606        if (cmd->chanlist_len > s->len_chanlist) {
1607                dev_dbg(dev->class_dev, "channel/gain list too long %d > %d\n",
1608                        cmd->chanlist_len, s->len_chanlist);
1609                return -EINVAL;
1610        }
1611
1612        /*
1613         * Set the CMDF_WRITE flag to the correct state if the subdevice
1614         * supports only "read" commands or only "write" commands.
1615         */
1616        switch (s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) {
1617        case SDF_CMD_READ:
1618                cmd->flags &= ~CMDF_WRITE;
1619                break;
1620        case SDF_CMD_WRITE:
1621                cmd->flags |= CMDF_WRITE;
1622                break;
1623        default:
1624                break;
1625        }
1626
1627        return 0;
1628}
1629
1630static int __comedi_get_user_chanlist(struct comedi_device *dev,
1631                                      struct comedi_subdevice *s,
1632                                      unsigned int __user *user_chanlist,
1633                                      struct comedi_cmd *cmd)
1634{
1635        unsigned int *chanlist;
1636        int ret;
1637
1638        cmd->chanlist = NULL;
1639        chanlist = memdup_user(user_chanlist,
1640                               cmd->chanlist_len * sizeof(unsigned int));
1641        if (IS_ERR(chanlist))
1642                return PTR_ERR(chanlist);
1643
1644        /* make sure each element in channel/gain list is valid */
1645        ret = comedi_check_chanlist(s, cmd->chanlist_len, chanlist);
1646        if (ret < 0) {
1647                kfree(chanlist);
1648                return ret;
1649        }
1650
1651        cmd->chanlist = chanlist;
1652
1653        return 0;
1654}
1655
1656/*
1657 * COMEDI_CMD ioctl
1658 * asynchronous acquisition command set-up
1659 *
1660 * arg:
1661 *      pointer to comedi_cmd structure
1662 *
1663 * reads:
1664 *      comedi_cmd structure
1665 *      channel/range list from cmd->chanlist pointer
1666 *
1667 * writes:
1668 *      possibly modified comedi_cmd structure (when -EAGAIN returned)
1669 */
1670static int do_cmd_ioctl(struct comedi_device *dev,
1671                        struct comedi_cmd __user *arg, void *file)
1672{
1673        struct comedi_cmd cmd;
1674        struct comedi_subdevice *s;
1675        struct comedi_async *async;
1676        unsigned int __user *user_chanlist;
1677        int ret;
1678
1679        /* get the user's cmd and do some simple validation */
1680        ret = __comedi_get_user_cmd(dev, arg, &cmd);
1681        if (ret)
1682                return ret;
1683
1684        /* save user's chanlist pointer so it can be restored later */
1685        user_chanlist = (unsigned int __user *)cmd.chanlist;
1686
1687        s = &dev->subdevices[cmd.subdev];
1688        async = s->async;
1689
1690        /* are we locked? (ioctl lock) */
1691        if (s->lock && s->lock != file) {
1692                dev_dbg(dev->class_dev, "subdevice locked\n");
1693                return -EACCES;
1694        }
1695
1696        /* are we busy? */
1697        if (s->busy) {
1698                dev_dbg(dev->class_dev, "subdevice busy\n");
1699                return -EBUSY;
1700        }
1701
1702        /* make sure channel/gain list isn't too short */
1703        if (cmd.chanlist_len < 1) {
1704                dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n",
1705                        cmd.chanlist_len);
1706                return -EINVAL;
1707        }
1708
1709        async->cmd = cmd;
1710        async->cmd.data = NULL;
1711
1712        /* load channel/gain list */
1713        ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &async->cmd);
1714        if (ret)
1715                goto cleanup;
1716
1717        ret = s->do_cmdtest(dev, s, &async->cmd);
1718
1719        if (async->cmd.flags & CMDF_BOGUS || ret) {
1720                dev_dbg(dev->class_dev, "test returned %d\n", ret);
1721                cmd = async->cmd;
1722                /* restore chanlist pointer before copying back */
1723                cmd.chanlist = (unsigned int __force *)user_chanlist;
1724                cmd.data = NULL;
1725                if (copy_to_user(arg, &cmd, sizeof(cmd))) {
1726                        dev_dbg(dev->class_dev, "fault writing cmd\n");
1727                        ret = -EFAULT;
1728                        goto cleanup;
1729                }
1730                ret = -EAGAIN;
1731                goto cleanup;
1732        }
1733
1734        if (!async->prealloc_bufsz) {
1735                ret = -ENOMEM;
1736                dev_dbg(dev->class_dev, "no buffer (?)\n");
1737                goto cleanup;
1738        }
1739
1740        comedi_buf_reset(s);
1741
1742        async->cb_mask = COMEDI_CB_BLOCK | COMEDI_CB_CANCEL_MASK;
1743        if (async->cmd.flags & CMDF_WAKE_EOS)
1744                async->cb_mask |= COMEDI_CB_EOS;
1745
1746        comedi_update_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
1747                                         COMEDI_SRF_RUNNING);
1748
1749        /*
1750         * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid
1751         * race with comedi_read() or comedi_write().
1752         */
1753        s->busy = file;
1754        ret = s->do_cmd(dev, s);
1755        if (ret == 0)
1756                return 0;
1757
1758cleanup:
1759        do_become_nonbusy(dev, s);
1760
1761        return ret;
1762}
1763
1764/*
1765 * COMEDI_CMDTEST ioctl
1766 * asynchronous acquisition command testing
1767 *
1768 * arg:
1769 *      pointer to comedi_cmd structure
1770 *
1771 * reads:
1772 *      comedi_cmd structure
1773 *      channel/range list from cmd->chanlist pointer
1774 *
1775 * writes:
1776 *      possibly modified comedi_cmd structure
1777 */
1778static int do_cmdtest_ioctl(struct comedi_device *dev,
1779                            struct comedi_cmd __user *arg, void *file)
1780{
1781        struct comedi_cmd cmd;
1782        struct comedi_subdevice *s;
1783        unsigned int __user *user_chanlist;
1784        int ret;
1785
1786        /* get the user's cmd and do some simple validation */
1787        ret = __comedi_get_user_cmd(dev, arg, &cmd);
1788        if (ret)
1789                return ret;
1790
1791        /* save user's chanlist pointer so it can be restored later */
1792        user_chanlist = (unsigned int __user *)cmd.chanlist;
1793
1794        s = &dev->subdevices[cmd.subdev];
1795
1796        /* user_chanlist can be NULL for COMEDI_CMDTEST ioctl */
1797        if (user_chanlist) {
1798                /* load channel/gain list */
1799                ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &cmd);
1800                if (ret)
1801                        return ret;
1802        }
1803
1804        ret = s->do_cmdtest(dev, s, &cmd);
1805
1806        kfree(cmd.chanlist);    /* free kernel copy of user chanlist */
1807
1808        /* restore chanlist pointer before copying back */
1809        cmd.chanlist = (unsigned int __force *)user_chanlist;
1810
1811        if (copy_to_user(arg, &cmd, sizeof(cmd))) {
1812                dev_dbg(dev->class_dev, "bad cmd address\n");
1813                ret = -EFAULT;
1814        }
1815
1816        return ret;
1817}
1818
1819/*
1820 * COMEDI_LOCK ioctl
1821 * lock subdevice
1822 *
1823 * arg:
1824 *      subdevice number
1825 *
1826 * reads:
1827 *      nothing
1828 *
1829 * writes:
1830 *      nothing
1831 */
1832static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg,
1833                         void *file)
1834{
1835        int ret = 0;
1836        unsigned long flags;
1837        struct comedi_subdevice *s;
1838
1839        if (arg >= dev->n_subdevices)
1840                return -EINVAL;
1841        s = &dev->subdevices[arg];
1842
1843        spin_lock_irqsave(&s->spin_lock, flags);
1844        if (s->busy || s->lock)
1845                ret = -EBUSY;
1846        else
1847                s->lock = file;
1848        spin_unlock_irqrestore(&s->spin_lock, flags);
1849
1850        return ret;
1851}
1852
1853/*
1854 * COMEDI_UNLOCK ioctl
1855 * unlock subdevice
1856 *
1857 * arg:
1858 *      subdevice number
1859 *
1860 * reads:
1861 *      nothing
1862 *
1863 * writes:
1864 *      nothing
1865 */
1866static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg,
1867                           void *file)
1868{
1869        struct comedi_subdevice *s;
1870
1871        if (arg >= dev->n_subdevices)
1872                return -EINVAL;
1873        s = &dev->subdevices[arg];
1874
1875        if (s->busy)
1876                return -EBUSY;
1877
1878        if (s->lock && s->lock != file)
1879                return -EACCES;
1880
1881        if (s->lock == file)
1882                s->lock = NULL;
1883
1884        return 0;
1885}
1886
1887/*
1888 * COMEDI_CANCEL ioctl
1889 * cancel asynchronous acquisition
1890 *
1891 * arg:
1892 *      subdevice number
1893 *
1894 * reads:
1895 *      nothing
1896 *
1897 * writes:
1898 *      nothing
1899 */
1900static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
1901                           void *file)
1902{
1903        struct comedi_subdevice *s;
1904
1905        if (arg >= dev->n_subdevices)
1906                return -EINVAL;
1907        s = &dev->subdevices[arg];
1908        if (!s->async)
1909                return -EINVAL;
1910
1911        if (!s->busy)
1912                return 0;
1913
1914        if (s->busy != file)
1915                return -EBUSY;
1916
1917        return do_cancel(dev, s);
1918}
1919
1920/*
1921 * COMEDI_POLL ioctl
1922 * instructs driver to synchronize buffers
1923 *
1924 * arg:
1925 *      subdevice number
1926 *
1927 * reads:
1928 *      nothing
1929 *
1930 * writes:
1931 *      nothing
1932 */
1933static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg,
1934                         void *file)
1935{
1936        struct comedi_subdevice *s;
1937
1938        if (arg >= dev->n_subdevices)
1939                return -EINVAL;
1940        s = &dev->subdevices[arg];
1941
1942        if (!s->busy)
1943                return 0;
1944
1945        if (s->busy != file)
1946                return -EBUSY;
1947
1948        if (s->poll)
1949                return s->poll(dev, s);
1950
1951        return -EINVAL;
1952}
1953
1954/*
1955 * COMEDI_SETRSUBD ioctl
1956 * sets the current "read" subdevice on a per-file basis
1957 *
1958 * arg:
1959 *      subdevice number
1960 *
1961 * reads:
1962 *      nothing
1963 *
1964 * writes:
1965 *      nothing
1966 */
1967static int do_setrsubd_ioctl(struct comedi_device *dev, unsigned long arg,
1968                             struct file *file)
1969{
1970        struct comedi_file *cfp = file->private_data;
1971        struct comedi_subdevice *s_old, *s_new;
1972
1973        if (arg >= dev->n_subdevices)
1974                return -EINVAL;
1975
1976        s_new = &dev->subdevices[arg];
1977        s_old = comedi_file_read_subdevice(file);
1978        if (s_old == s_new)
1979                return 0;       /* no change */
1980
1981        if (!(s_new->subdev_flags & SDF_CMD_READ))
1982                return -EINVAL;
1983
1984        /*
1985         * Check the file isn't still busy handling a "read" command on the
1986         * old subdevice (if any).
1987         */
1988        if (s_old && s_old->busy == file && s_old->async &&
1989            !(s_old->async->cmd.flags & CMDF_WRITE))
1990                return -EBUSY;
1991
1992        ACCESS_ONCE(cfp->read_subdev) = s_new;
1993        return 0;
1994}
1995
1996/*
1997 * COMEDI_SETWSUBD ioctl
1998 * sets the current "write" subdevice on a per-file basis
1999 *
2000 * arg:
2001 *      subdevice number
2002 *
2003 * reads:
2004 *      nothing
2005 *
2006 * writes:
2007 *      nothing
2008 */
2009static int do_setwsubd_ioctl(struct comedi_device *dev, unsigned long arg,
2010                             struct file *file)
2011{
2012        struct comedi_file *cfp = file->private_data;
2013        struct comedi_subdevice *s_old, *s_new;
2014
2015        if (arg >= dev->n_subdevices)
2016                return -EINVAL;
2017
2018        s_new = &dev->subdevices[arg];
2019        s_old = comedi_file_write_subdevice(file);
2020        if (s_old == s_new)
2021                return 0;       /* no change */
2022
2023        if (!(s_new->subdev_flags & SDF_CMD_WRITE))
2024                return -EINVAL;
2025
2026        /*
2027         * Check the file isn't still busy handling a "write" command on the
2028         * old subdevice (if any).
2029         */
2030        if (s_old && s_old->busy == file && s_old->async &&
2031            (s_old->async->cmd.flags & CMDF_WRITE))
2032                return -EBUSY;
2033
2034        ACCESS_ONCE(cfp->write_subdev) = s_new;
2035        return 0;
2036}
2037
2038static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
2039                                  unsigned long arg)
2040{
2041        unsigned minor = iminor(file_inode(file));
2042        struct comedi_file *cfp = file->private_data;
2043        struct comedi_device *dev = cfp->dev;
2044        int rc;
2045
2046        mutex_lock(&dev->mutex);
2047
2048        /*
2049         * Device config is special, because it must work on
2050         * an unconfigured device.
2051         */
2052        if (cmd == COMEDI_DEVCONFIG) {
2053                if (minor >= COMEDI_NUM_BOARD_MINORS) {
2054                        /* Device config not appropriate on non-board minors. */
2055                        rc = -ENOTTY;
2056                        goto done;
2057                }
2058                rc = do_devconfig_ioctl(dev,
2059                                        (struct comedi_devconfig __user *)arg);
2060                if (rc == 0) {
2061                        if (arg == 0 &&
2062                            dev->minor >= comedi_num_legacy_minors) {
2063                                /*
2064                                 * Successfully unconfigured a dynamically
2065                                 * allocated device.  Try and remove it.
2066                                 */
2067                                if (comedi_clear_board_dev(dev)) {
2068                                        mutex_unlock(&dev->mutex);
2069                                        comedi_free_board_dev(dev);
2070                                        return rc;
2071                                }
2072                        }
2073                }
2074                goto done;
2075        }
2076
2077        if (!dev->attached) {
2078                dev_dbg(dev->class_dev, "no driver attached\n");
2079                rc = -ENODEV;
2080                goto done;
2081        }
2082
2083        switch (cmd) {
2084        case COMEDI_BUFCONFIG:
2085                rc = do_bufconfig_ioctl(dev,
2086                                        (struct comedi_bufconfig __user *)arg);
2087                break;
2088        case COMEDI_DEVINFO:
2089                rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg,
2090                                      file);
2091                break;
2092        case COMEDI_SUBDINFO:
2093                rc = do_subdinfo_ioctl(dev,
2094                                       (struct comedi_subdinfo __user *)arg,
2095                                       file);
2096                break;
2097        case COMEDI_CHANINFO:
2098                rc = do_chaninfo_ioctl(dev, (void __user *)arg);
2099                break;
2100        case COMEDI_RANGEINFO:
2101                rc = do_rangeinfo_ioctl(dev, (void __user *)arg);
2102                break;
2103        case COMEDI_BUFINFO:
2104                rc = do_bufinfo_ioctl(dev,
2105                                      (struct comedi_bufinfo __user *)arg,
2106                                      file);
2107                break;
2108        case COMEDI_LOCK:
2109                rc = do_lock_ioctl(dev, arg, file);
2110                break;
2111        case COMEDI_UNLOCK:
2112                rc = do_unlock_ioctl(dev, arg, file);
2113                break;
2114        case COMEDI_CANCEL:
2115                rc = do_cancel_ioctl(dev, arg, file);
2116                break;
2117        case COMEDI_CMD:
2118                rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file);
2119                break;
2120        case COMEDI_CMDTEST:
2121                rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg,
2122                                      file);
2123                break;
2124        case COMEDI_INSNLIST:
2125                rc = do_insnlist_ioctl(dev,
2126                                       (struct comedi_insnlist __user *)arg,
2127                                       file);
2128                break;
2129        case COMEDI_INSN:
2130                rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg,
2131                                   file);
2132                break;
2133        case COMEDI_POLL:
2134                rc = do_poll_ioctl(dev, arg, file);
2135                break;
2136        case COMEDI_SETRSUBD:
2137                rc = do_setrsubd_ioctl(dev, arg, file);
2138                break;
2139        case COMEDI_SETWSUBD:
2140                rc = do_setwsubd_ioctl(dev, arg, file);
2141                break;
2142        default:
2143                rc = -ENOTTY;
2144                break;
2145        }
2146
2147done:
2148        mutex_unlock(&dev->mutex);
2149        return rc;
2150}
2151
2152static void comedi_vm_open(struct vm_area_struct *area)
2153{
2154        struct comedi_buf_map *bm;
2155
2156        bm = area->vm_private_data;
2157        comedi_buf_map_get(bm);
2158}
2159
2160static void comedi_vm_close(struct vm_area_struct *area)
2161{
2162        struct comedi_buf_map *bm;
2163
2164        bm = area->vm_private_data;
2165        comedi_buf_map_put(bm);
2166}
2167
2168static const struct vm_operations_struct comedi_vm_ops = {
2169        .open = comedi_vm_open,
2170        .close = comedi_vm_close,
2171};
2172
2173static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
2174{
2175        struct comedi_file *cfp = file->private_data;
2176        struct comedi_device *dev = cfp->dev;
2177        struct comedi_subdevice *s;
2178        struct comedi_async *async;
2179        struct comedi_buf_map *bm = NULL;
2180        unsigned long start = vma->vm_start;
2181        unsigned long size;
2182        int n_pages;
2183        int i;
2184        int retval;
2185
2186        /*
2187         * 'trylock' avoids circular dependency with current->mm->mmap_sem
2188         * and down-reading &dev->attach_lock should normally succeed without
2189         * contention unless the device is in the process of being attached
2190         * or detached.
2191         */
2192        if (!down_read_trylock(&dev->attach_lock))
2193                return -EAGAIN;
2194
2195        if (!dev->attached) {
2196                dev_dbg(dev->class_dev, "no driver attached\n");
2197                retval = -ENODEV;
2198                goto done;
2199        }
2200
2201        if (vma->vm_flags & VM_WRITE)
2202                s = comedi_file_write_subdevice(file);
2203        else
2204                s = comedi_file_read_subdevice(file);
2205        if (!s) {
2206                retval = -EINVAL;
2207                goto done;
2208        }
2209
2210        async = s->async;
2211        if (!async) {
2212                retval = -EINVAL;
2213                goto done;
2214        }
2215
2216        if (vma->vm_pgoff != 0) {
2217                dev_dbg(dev->class_dev, "mmap() offset must be 0.\n");
2218                retval = -EINVAL;
2219                goto done;
2220        }
2221
2222        size = vma->vm_end - vma->vm_start;
2223        if (size > async->prealloc_bufsz) {
2224                retval = -EFAULT;
2225                goto done;
2226        }
2227        if (offset_in_page(size)) {
2228                retval = -EFAULT;
2229                goto done;
2230        }
2231
2232        n_pages = size >> PAGE_SHIFT;
2233
2234        /* get reference to current buf map (if any) */
2235        bm = comedi_buf_map_from_subdev_get(s);
2236        if (!bm || n_pages > bm->n_pages) {
2237                retval = -EINVAL;
2238                goto done;
2239        }
2240        for (i = 0; i < n_pages; ++i) {
2241                struct comedi_buf_page *buf = &bm->page_list[i];
2242
2243                if (remap_pfn_range(vma, start,
2244                                    page_to_pfn(virt_to_page(buf->virt_addr)),
2245                                    PAGE_SIZE, PAGE_SHARED)) {
2246                        retval = -EAGAIN;
2247                        goto done;
2248                }
2249                start += PAGE_SIZE;
2250        }
2251
2252        vma->vm_ops = &comedi_vm_ops;
2253        vma->vm_private_data = bm;
2254
2255        vma->vm_ops->open(vma);
2256
2257        retval = 0;
2258done:
2259        up_read(&dev->attach_lock);
2260        comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */
2261        return retval;
2262}
2263
2264static unsigned int comedi_poll(struct file *file, poll_table *wait)
2265{
2266        unsigned int mask = 0;
2267        struct comedi_file *cfp = file->private_data;
2268        struct comedi_device *dev = cfp->dev;
2269        struct comedi_subdevice *s, *s_read;
2270
2271        down_read(&dev->attach_lock);
2272
2273        if (!dev->attached) {
2274                dev_dbg(dev->class_dev, "no driver attached\n");
2275                goto done;
2276        }
2277
2278        s = comedi_file_read_subdevice(file);
2279        s_read = s;
2280        if (s && s->async) {
2281                poll_wait(file, &s->async->wait_head, wait);
2282                if (s->busy != file || !comedi_is_subdevice_running(s) ||
2283                    (s->async->cmd.flags & CMDF_WRITE) ||
2284                    comedi_buf_read_n_available(s) > 0)
2285                        mask |= POLLIN | POLLRDNORM;
2286        }
2287
2288        s = comedi_file_write_subdevice(file);
2289        if (s && s->async) {
2290                unsigned int bps = comedi_bytes_per_sample(s);
2291
2292                if (s != s_read)
2293                        poll_wait(file, &s->async->wait_head, wait);
2294                if (s->busy != file || !comedi_is_subdevice_running(s) ||
2295                    !(s->async->cmd.flags & CMDF_WRITE) ||
2296                    comedi_buf_write_n_available(s) >= bps)
2297                        mask |= POLLOUT | POLLWRNORM;
2298        }
2299
2300done:
2301        up_read(&dev->attach_lock);
2302        return mask;
2303}
2304
2305static ssize_t comedi_write(struct file *file, const char __user *buf,
2306                            size_t nbytes, loff_t *offset)
2307{
2308        struct comedi_subdevice *s;
2309        struct comedi_async *async;
2310        unsigned int n, m;
2311        ssize_t count = 0;
2312        int retval = 0;
2313        DECLARE_WAITQUEUE(wait, current);
2314        struct comedi_file *cfp = file->private_data;
2315        struct comedi_device *dev = cfp->dev;
2316        bool become_nonbusy = false;
2317        bool attach_locked;
2318        unsigned int old_detach_count;
2319
2320        /* Protect against device detachment during operation. */
2321        down_read(&dev->attach_lock);
2322        attach_locked = true;
2323        old_detach_count = dev->detach_count;
2324
2325        if (!dev->attached) {
2326                dev_dbg(dev->class_dev, "no driver attached\n");
2327                retval = -ENODEV;
2328                goto out;
2329        }
2330
2331        s = comedi_file_write_subdevice(file);
2332        if (!s || !s->async) {
2333                retval = -EIO;
2334                goto out;
2335        }
2336
2337        async = s->async;
2338        if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) {
2339                retval = -EINVAL;
2340                goto out;
2341        }
2342
2343        add_wait_queue(&async->wait_head, &wait);
2344        while (count == 0 && !retval) {
2345                unsigned runflags;
2346                unsigned int wp, n1, n2;
2347
2348                set_current_state(TASK_INTERRUPTIBLE);
2349
2350                runflags = comedi_get_subdevice_runflags(s);
2351                if (!comedi_is_runflags_running(runflags)) {
2352                        if (comedi_is_runflags_in_error(runflags))
2353                                retval = -EPIPE;
2354                        if (retval || nbytes)
2355                                become_nonbusy = true;
2356                        break;
2357                }
2358                if (nbytes == 0)
2359                        break;
2360
2361                /* Allocate all free buffer space. */
2362                comedi_buf_write_alloc(s, async->prealloc_bufsz);
2363                m = comedi_buf_write_n_allocated(s);
2364                n = min_t(size_t, m, nbytes);
2365
2366                if (n == 0) {
2367                        if (file->f_flags & O_NONBLOCK) {
2368                                retval = -EAGAIN;
2369                                break;
2370                        }
2371                        schedule();
2372                        if (signal_pending(current)) {
2373                                retval = -ERESTARTSYS;
2374                                break;
2375                        }
2376                        if (s->busy != file ||
2377                            !(async->cmd.flags & CMDF_WRITE)) {
2378                                retval = -EINVAL;
2379                                break;
2380                        }
2381                        continue;
2382                }
2383
2384                wp = async->buf_write_ptr;
2385                n1 = min(n, async->prealloc_bufsz - wp);
2386                n2 = n - n1;
2387                m = copy_from_user(async->prealloc_buf + wp, buf, n1);
2388                if (m)
2389                        m += n2;
2390                else if (n2)
2391                        m = copy_from_user(async->prealloc_buf, buf + n1, n2);
2392                if (m) {
2393                        n -= m;
2394                        retval = -EFAULT;
2395                }
2396                comedi_buf_write_free(s, n);
2397
2398                count += n;
2399                nbytes -= n;
2400
2401                buf += n;
2402        }
2403        remove_wait_queue(&async->wait_head, &wait);
2404        set_current_state(TASK_RUNNING);
2405        if (become_nonbusy && count == 0) {
2406                struct comedi_subdevice *new_s;
2407
2408                /*
2409                 * To avoid deadlock, cannot acquire dev->mutex
2410                 * while dev->attach_lock is held.
2411                 */
2412                up_read(&dev->attach_lock);
2413                attach_locked = false;
2414                mutex_lock(&dev->mutex);
2415                /*
2416                 * Check device hasn't become detached behind our back.
2417                 * Checking dev->detach_count is unchanged ought to be
2418                 * sufficient (unless there have been 2**32 detaches in the
2419                 * meantime!), but check the subdevice pointer as well just in
2420                 * case.
2421                 *
2422                 * Also check the subdevice is still in a suitable state to
2423                 * become non-busy in case it changed behind our back.
2424                 */
2425                new_s = comedi_file_write_subdevice(file);
2426                if (dev->attached && old_detach_count == dev->detach_count &&
2427                    s == new_s && new_s->async == async && s->busy == file &&
2428                    (async->cmd.flags & CMDF_WRITE) &&
2429                    !comedi_is_subdevice_running(s))
2430                        do_become_nonbusy(dev, s);
2431                mutex_unlock(&dev->mutex);
2432        }
2433out:
2434        if (attach_locked)
2435                up_read(&dev->attach_lock);
2436
2437        return count ? count : retval;
2438}
2439
2440static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
2441                           loff_t *offset)
2442{
2443        struct comedi_subdevice *s;
2444        struct comedi_async *async;
2445        unsigned int n, m;
2446        ssize_t count = 0;
2447        int retval = 0;
2448        DECLARE_WAITQUEUE(wait, current);
2449        struct comedi_file *cfp = file->private_data;
2450        struct comedi_device *dev = cfp->dev;
2451        unsigned int old_detach_count;
2452        bool become_nonbusy = false;
2453        bool attach_locked;
2454
2455        /* Protect against device detachment during operation. */
2456        down_read(&dev->attach_lock);
2457        attach_locked = true;
2458        old_detach_count = dev->detach_count;
2459
2460        if (!dev->attached) {
2461                dev_dbg(dev->class_dev, "no driver attached\n");
2462                retval = -ENODEV;
2463                goto out;
2464        }
2465
2466        s = comedi_file_read_subdevice(file);
2467        if (!s || !s->async) {
2468                retval = -EIO;
2469                goto out;
2470        }
2471
2472        async = s->async;
2473        if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) {
2474                retval = -EINVAL;
2475                goto out;
2476        }
2477
2478        add_wait_queue(&async->wait_head, &wait);
2479        while (count == 0 && !retval) {
2480                unsigned int rp, n1, n2;
2481
2482                set_current_state(TASK_INTERRUPTIBLE);
2483
2484                m = comedi_buf_read_n_available(s);
2485                n = min_t(size_t, m, nbytes);
2486
2487                if (n == 0) {
2488                        unsigned runflags = comedi_get_subdevice_runflags(s);
2489
2490                        if (!comedi_is_runflags_running(runflags)) {
2491                                if (comedi_is_runflags_in_error(runflags))
2492                                        retval = -EPIPE;
2493                                if (retval || nbytes)
2494                                        become_nonbusy = true;
2495                                break;
2496                        }
2497                        if (nbytes == 0)
2498                                break;
2499                        if (file->f_flags & O_NONBLOCK) {
2500                                retval = -EAGAIN;
2501                                break;
2502                        }
2503                        schedule();
2504                        if (signal_pending(current)) {
2505                                retval = -ERESTARTSYS;
2506                                break;
2507                        }
2508                        if (s->busy != file ||
2509                            (async->cmd.flags & CMDF_WRITE)) {
2510                                retval = -EINVAL;
2511                                break;
2512                        }
2513                        continue;
2514                }
2515                rp = async->buf_read_ptr;
2516                n1 = min(n, async->prealloc_bufsz - rp);
2517                n2 = n - n1;
2518                m = copy_to_user(buf, async->prealloc_buf + rp, n1);
2519                if (m)
2520                        m += n2;
2521                else if (n2)
2522                        m = copy_to_user(buf + n1, async->prealloc_buf, n2);
2523                if (m) {
2524                        n -= m;
2525                        retval = -EFAULT;
2526                }
2527
2528                comedi_buf_read_alloc(s, n);
2529                comedi_buf_read_free(s, n);
2530
2531                count += n;
2532                nbytes -= n;
2533
2534                buf += n;
2535        }
2536        remove_wait_queue(&async->wait_head, &wait);
2537        set_current_state(TASK_RUNNING);
2538        if (become_nonbusy && count == 0) {
2539                struct comedi_subdevice *new_s;
2540
2541                /*
2542                 * To avoid deadlock, cannot acquire dev->mutex
2543                 * while dev->attach_lock is held.
2544                 */
2545                up_read(&dev->attach_lock);
2546                attach_locked = false;
2547                mutex_lock(&dev->mutex);
2548                /*
2549                 * Check device hasn't become detached behind our back.
2550                 * Checking dev->detach_count is unchanged ought to be
2551                 * sufficient (unless there have been 2**32 detaches in the
2552                 * meantime!), but check the subdevice pointer as well just in
2553                 * case.
2554                 *
2555                 * Also check the subdevice is still in a suitable state to
2556                 * become non-busy in case it changed behind our back.
2557                 */
2558                new_s = comedi_file_read_subdevice(file);
2559                if (dev->attached && old_detach_count == dev->detach_count &&
2560                    s == new_s && new_s->async == async && s->busy == file &&
2561                    !(async->cmd.flags & CMDF_WRITE) &&
2562                    !comedi_is_subdevice_running(s) &&
2563                    comedi_buf_read_n_available(s) == 0)
2564                        do_become_nonbusy(dev, s);
2565                mutex_unlock(&dev->mutex);
2566        }
2567out:
2568        if (attach_locked)
2569                up_read(&dev->attach_lock);
2570
2571        return count ? count : retval;
2572}
2573
2574static int comedi_open(struct inode *inode, struct file *file)
2575{
2576        const unsigned minor = iminor(inode);
2577        struct comedi_file *cfp;
2578        struct comedi_device *dev = comedi_dev_get_from_minor(minor);
2579        int rc;
2580
2581        if (!dev) {
2582                pr_debug("invalid minor number\n");
2583                return -ENODEV;
2584        }
2585
2586        cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
2587        if (!cfp)
2588                return -ENOMEM;
2589
2590        cfp->dev = dev;
2591
2592        mutex_lock(&dev->mutex);
2593        if (!dev->attached && !capable(CAP_SYS_ADMIN)) {
2594                dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n");
2595                rc = -ENODEV;
2596                goto out;
2597        }
2598        if (dev->attached && dev->use_count == 0) {
2599                if (!try_module_get(dev->driver->module)) {
2600                        rc = -ENXIO;
2601                        goto out;
2602                }
2603                if (dev->open) {
2604                        rc = dev->open(dev);
2605                        if (rc < 0) {
2606                                module_put(dev->driver->module);
2607                                goto out;
2608                        }
2609                }
2610        }
2611
2612        dev->use_count++;
2613        file->private_data = cfp;
2614        comedi_file_reset(file);
2615        rc = 0;
2616
2617out:
2618        mutex_unlock(&dev->mutex);
2619        if (rc) {
2620                comedi_dev_put(dev);
2621                kfree(cfp);
2622        }
2623        return rc;
2624}
2625
2626static int comedi_fasync(int fd, struct file *file, int on)
2627{
2628        struct comedi_file *cfp = file->private_data;
2629        struct comedi_device *dev = cfp->dev;
2630
2631        return fasync_helper(fd, file, on, &dev->async_queue);
2632}
2633
2634static int comedi_close(struct inode *inode, struct file *file)
2635{
2636        struct comedi_file *cfp = file->private_data;
2637        struct comedi_device *dev = cfp->dev;
2638        struct comedi_subdevice *s = NULL;
2639        int i;
2640
2641        mutex_lock(&dev->mutex);
2642
2643        if (dev->subdevices) {
2644                for (i = 0; i < dev->n_subdevices; i++) {
2645                        s = &dev->subdevices[i];
2646
2647                        if (s->busy == file)
2648                                do_cancel(dev, s);
2649                        if (s->lock == file)
2650                                s->lock = NULL;
2651                }
2652        }
2653        if (dev->attached && dev->use_count == 1) {
2654                if (dev->close)
2655                        dev->close(dev);
2656                module_put(dev->driver->module);
2657        }
2658
2659        dev->use_count--;
2660
2661        mutex_unlock(&dev->mutex);
2662        comedi_dev_put(dev);
2663        kfree(cfp);
2664
2665        return 0;
2666}
2667
2668static const struct file_operations comedi_fops = {
2669        .owner = THIS_MODULE,
2670        .unlocked_ioctl = comedi_unlocked_ioctl,
2671        .compat_ioctl = comedi_compat_ioctl,
2672        .open = comedi_open,
2673        .release = comedi_close,
2674        .read = comedi_read,
2675        .write = comedi_write,
2676        .mmap = comedi_mmap,
2677        .poll = comedi_poll,
2678        .fasync = comedi_fasync,
2679        .llseek = noop_llseek,
2680};
2681
2682/**
2683 * comedi_event() - Handle events for asynchronous COMEDI command
2684 * @dev: COMEDI device.
2685 * @s: COMEDI subdevice.
2686 * Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
2687 *
2688 * If an asynchronous COMEDI command is active on the subdevice, process
2689 * any %COMEDI_CB_... event flags that have been set, usually by an
2690 * interrupt handler.  These may change the run state of the asynchronous
2691 * command, wake a task, and/or send a %SIGIO signal.
2692 */
2693void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
2694{
2695        struct comedi_async *async = s->async;
2696        unsigned int events;
2697        int si_code = 0;
2698        unsigned long flags;
2699
2700        spin_lock_irqsave(&s->spin_lock, flags);
2701
2702        events = async->events;
2703        async->events = 0;
2704        if (!__comedi_is_subdevice_running(s)) {
2705                spin_unlock_irqrestore(&s->spin_lock, flags);
2706                return;
2707        }
2708
2709        if (events & COMEDI_CB_CANCEL_MASK)
2710                __comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING);
2711
2712        /*
2713         * Remember if an error event has occurred, so an error can be
2714         * returned the next time the user does a read() or write().
2715         */
2716        if (events & COMEDI_CB_ERROR_MASK)
2717                __comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR);
2718
2719        if (async->cb_mask & events) {
2720                wake_up_interruptible(&async->wait_head);
2721                si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN;
2722        }
2723
2724        spin_unlock_irqrestore(&s->spin_lock, flags);
2725
2726        if (si_code)
2727                kill_fasync(&dev->async_queue, SIGIO, si_code);
2728}
2729EXPORT_SYMBOL_GPL(comedi_event);
2730
2731/* Note: the ->mutex is pre-locked on successful return */
2732struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
2733{
2734        struct comedi_device *dev;
2735        struct device *csdev;
2736        unsigned i;
2737
2738        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2739        if (!dev)
2740                return ERR_PTR(-ENOMEM);
2741        comedi_device_init(dev);
2742        comedi_set_hw_dev(dev, hardware_device);
2743        mutex_lock(&dev->mutex);
2744        mutex_lock(&comedi_board_minor_table_lock);
2745        for (i = hardware_device ? comedi_num_legacy_minors : 0;
2746             i < COMEDI_NUM_BOARD_MINORS; ++i) {
2747                if (!comedi_board_minor_table[i]) {
2748                        comedi_board_minor_table[i] = dev;
2749                        break;
2750                }
2751        }
2752        mutex_unlock(&comedi_board_minor_table_lock);
2753        if (i == COMEDI_NUM_BOARD_MINORS) {
2754                mutex_unlock(&dev->mutex);
2755                comedi_device_cleanup(dev);
2756                comedi_dev_put(dev);
2757                dev_err(hardware_device,
2758                        "ran out of minor numbers for board device files\n");
2759                return ERR_PTR(-EBUSY);
2760        }
2761        dev->minor = i;
2762        csdev = device_create(comedi_class, hardware_device,
2763                              MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
2764        if (!IS_ERR(csdev))
2765                dev->class_dev = get_device(csdev);
2766
2767        /* Note: dev->mutex needs to be unlocked by the caller. */
2768        return dev;
2769}
2770
2771void comedi_release_hardware_device(struct device *hardware_device)
2772{
2773        int minor;
2774        struct comedi_device *dev;
2775
2776        for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS;
2777             minor++) {
2778                mutex_lock(&comedi_board_minor_table_lock);
2779                dev = comedi_board_minor_table[minor];
2780                if (dev && dev->hw_dev == hardware_device) {
2781                        comedi_board_minor_table[minor] = NULL;
2782                        mutex_unlock(&comedi_board_minor_table_lock);
2783                        comedi_free_board_dev(dev);
2784                        break;
2785                }
2786                mutex_unlock(&comedi_board_minor_table_lock);
2787        }
2788}
2789
2790int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
2791{
2792        struct comedi_device *dev = s->device;
2793        struct device *csdev;
2794        unsigned i;
2795
2796        mutex_lock(&comedi_subdevice_minor_table_lock);
2797        for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) {
2798                if (!comedi_subdevice_minor_table[i]) {
2799                        comedi_subdevice_minor_table[i] = s;
2800                        break;
2801                }
2802        }
2803        mutex_unlock(&comedi_subdevice_minor_table_lock);
2804        if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
2805                dev_err(dev->class_dev,
2806                        "ran out of minor numbers for subdevice files\n");
2807                return -EBUSY;
2808        }
2809        i += COMEDI_NUM_BOARD_MINORS;
2810        s->minor = i;
2811        csdev = device_create(comedi_class, dev->class_dev,
2812                              MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
2813                              dev->minor, s->index);
2814        if (!IS_ERR(csdev))
2815                s->class_dev = csdev;
2816
2817        return 0;
2818}
2819
2820void comedi_free_subdevice_minor(struct comedi_subdevice *s)
2821{
2822        unsigned int i;
2823
2824        if (!s)
2825                return;
2826        if (s->minor < COMEDI_NUM_BOARD_MINORS ||
2827            s->minor >= COMEDI_NUM_MINORS)
2828                return;
2829
2830        i = s->minor - COMEDI_NUM_BOARD_MINORS;
2831        mutex_lock(&comedi_subdevice_minor_table_lock);
2832        if (s == comedi_subdevice_minor_table[i])
2833                comedi_subdevice_minor_table[i] = NULL;
2834        mutex_unlock(&comedi_subdevice_minor_table_lock);
2835        if (s->class_dev) {
2836                device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
2837                s->class_dev = NULL;
2838        }
2839}
2840
2841static void comedi_cleanup_board_minors(void)
2842{
2843        struct comedi_device *dev;
2844        unsigned i;
2845
2846        for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
2847                dev = comedi_clear_board_minor(i);
2848                comedi_free_board_dev(dev);
2849        }
2850}
2851
2852static int __init comedi_init(void)
2853{
2854        int i;
2855        int retval;
2856
2857        pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n");
2858
2859        if (comedi_num_legacy_minors < 0 ||
2860            comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
2861                pr_err("invalid value for module parameter \"comedi_num_legacy_minors\".  Valid values are 0 through %i.\n",
2862                       COMEDI_NUM_BOARD_MINORS);
2863                return -EINVAL;
2864        }
2865
2866        retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2867                                        COMEDI_NUM_MINORS, "comedi");
2868        if (retval)
2869                return -EIO;
2870        cdev_init(&comedi_cdev, &comedi_fops);
2871        comedi_cdev.owner = THIS_MODULE;
2872
2873        retval = kobject_set_name(&comedi_cdev.kobj, "comedi");
2874        if (retval) {
2875                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2876                                         COMEDI_NUM_MINORS);
2877                return retval;
2878        }
2879
2880        if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
2881                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2882                                         COMEDI_NUM_MINORS);
2883                return -EIO;
2884        }
2885        comedi_class = class_create(THIS_MODULE, "comedi");
2886        if (IS_ERR(comedi_class)) {
2887                pr_err("failed to create class\n");
2888                cdev_del(&comedi_cdev);
2889                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2890                                         COMEDI_NUM_MINORS);
2891                return PTR_ERR(comedi_class);
2892        }
2893
2894        comedi_class->dev_groups = comedi_dev_groups;
2895
2896        /* XXX requires /proc interface */
2897        comedi_proc_init();
2898
2899        /* create devices files for legacy/manual use */
2900        for (i = 0; i < comedi_num_legacy_minors; i++) {
2901                struct comedi_device *dev;
2902
2903                dev = comedi_alloc_board_minor(NULL);
2904                if (IS_ERR(dev)) {
2905                        comedi_cleanup_board_minors();
2906                        cdev_del(&comedi_cdev);
2907                        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2908                                                 COMEDI_NUM_MINORS);
2909                        return PTR_ERR(dev);
2910                }
2911                /* comedi_alloc_board_minor() locked the mutex */
2912                mutex_unlock(&dev->mutex);
2913        }
2914
2915        return 0;
2916}
2917module_init(comedi_init);
2918
2919static void __exit comedi_cleanup(void)
2920{
2921        comedi_cleanup_board_minors();
2922        class_destroy(comedi_class);
2923        cdev_del(&comedi_cdev);
2924        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
2925
2926        comedi_proc_cleanup();
2927}
2928module_exit(comedi_cleanup);
2929
2930MODULE_AUTHOR("http://www.comedi.org");
2931MODULE_DESCRIPTION("Comedi core module");
2932MODULE_LICENSE("GPL");
2933