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/signal.h>
  27#include <linux/fcntl.h>
  28#include <linux/delay.h>
  29#include <linux/mm.h>
  30#include <linux/slab.h>
  31#include <linux/poll.h>
  32#include <linux/device.h>
  33#include <linux/fs.h>
  34#include "comedidev.h"
  35#include <linux/cdev.h>
  36
  37#include <linux/io.h>
  38#include <linux/uaccess.h>
  39
  40#include "comedi_internal.h"
  41
  42/*
  43 * comedi_subdevice "runflags"
  44 * COMEDI_SRF_RT:               DEPRECATED: command is running real-time
  45 * COMEDI_SRF_ERROR:            indicates an COMEDI_CB_ERROR event has occurred
  46 *                              since the last command was started
  47 * COMEDI_SRF_RUNNING:          command is running
  48 * COMEDI_SRF_FREE_SPRIV:       free s->private on detach
  49 *
  50 * COMEDI_SRF_BUSY_MASK:        runflags that indicate the subdevice is "busy"
  51 */
  52#define COMEDI_SRF_RT           BIT(1)
  53#define COMEDI_SRF_ERROR        BIT(2)
  54#define COMEDI_SRF_RUNNING      BIT(27)
  55#define COMEDI_SRF_FREE_SPRIV   BIT(31)
  56
  57#define COMEDI_SRF_BUSY_MASK    (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING)
  58
  59/**
  60 * struct comedi_file - Per-file private data for COMEDI device
  61 * @dev: COMEDI device.
  62 * @read_subdev: Current "read" subdevice.
  63 * @write_subdev: Current "write" subdevice.
  64 * @last_detach_count: Last known detach count.
  65 * @last_attached: Last known attached/detached state.
  66 */
  67struct comedi_file {
  68        struct comedi_device *dev;
  69        struct comedi_subdevice *read_subdev;
  70        struct comedi_subdevice *write_subdev;
  71        unsigned int last_detach_count;
  72        bool last_attached:1;
  73};
  74
  75#define COMEDI_NUM_MINORS 0x100
  76#define COMEDI_NUM_SUBDEVICE_MINORS     \
  77        (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
  78
  79static int comedi_num_legacy_minors;
  80module_param(comedi_num_legacy_minors, int, 0444);
  81MODULE_PARM_DESC(comedi_num_legacy_minors,
  82                 "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
  83                );
  84
  85unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
  86module_param(comedi_default_buf_size_kb, uint, 0644);
  87MODULE_PARM_DESC(comedi_default_buf_size_kb,
  88                 "default asynchronous buffer size in KiB (default "
  89                 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
  90
  91unsigned int comedi_default_buf_maxsize_kb
  92        = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
  93module_param(comedi_default_buf_maxsize_kb, uint, 0644);
  94MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
  95                 "default maximum size of asynchronous buffer in KiB (default "
  96                 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
  97
  98static DEFINE_MUTEX(comedi_board_minor_table_lock);
  99static struct comedi_device
 100*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS];
 101
 102static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
 103/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */
 104static struct comedi_subdevice
 105*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
 106
 107static struct class *comedi_class;
 108static struct cdev comedi_cdev;
 109
 110static void comedi_device_init(struct comedi_device *dev)
 111{
 112        kref_init(&dev->refcount);
 113        spin_lock_init(&dev->spinlock);
 114        mutex_init(&dev->mutex);
 115        init_rwsem(&dev->attach_lock);
 116        dev->minor = -1;
 117}
 118
 119static void comedi_dev_kref_release(struct kref *kref)
 120{
 121        struct comedi_device *dev =
 122                container_of(kref, struct comedi_device, refcount);
 123
 124        mutex_destroy(&dev->mutex);
 125        put_device(dev->class_dev);
 126        kfree(dev);
 127}
 128
 129/**
 130 * comedi_dev_put() - Release a use of a COMEDI device
 131 * @dev: COMEDI device.
 132 *
 133 * Must be called when a user of a COMEDI device is finished with it.
 134 * When the last user of the COMEDI device calls this function, the
 135 * COMEDI device is destroyed.
 136 *
 137 * Return: 1 if the COMEDI device is destroyed by this call or @dev is
 138 * NULL, otherwise return 0.  Callers must not assume the COMEDI
 139 * device is still valid if this function returns 0.
 140 */
 141int comedi_dev_put(struct comedi_device *dev)
 142{
 143        if (dev)
 144                return kref_put(&dev->refcount, comedi_dev_kref_release);
 145        return 1;
 146}
 147EXPORT_SYMBOL_GPL(comedi_dev_put);
 148
 149static struct comedi_device *comedi_dev_get(struct comedi_device *dev)
 150{
 151        if (dev)
 152                kref_get(&dev->refcount);
 153        return dev;
 154}
 155
 156static void comedi_device_cleanup(struct comedi_device *dev)
 157{
 158        struct module *driver_module = NULL;
 159
 160        if (!dev)
 161                return;
 162        mutex_lock(&dev->mutex);
 163        if (dev->attached)
 164                driver_module = dev->driver->module;
 165        comedi_device_detach(dev);
 166        if (driver_module && dev->use_count)
 167                module_put(driver_module);
 168        mutex_unlock(&dev->mutex);
 169}
 170
 171static bool comedi_clear_board_dev(struct comedi_device *dev)
 172{
 173        unsigned int i = dev->minor;
 174        bool cleared = false;
 175
 176        mutex_lock(&comedi_board_minor_table_lock);
 177        if (dev == comedi_board_minor_table[i]) {
 178                comedi_board_minor_table[i] = NULL;
 179                cleared = true;
 180        }
 181        mutex_unlock(&comedi_board_minor_table_lock);
 182        return cleared;
 183}
 184
 185static struct comedi_device *comedi_clear_board_minor(unsigned int minor)
 186{
 187        struct comedi_device *dev;
 188
 189        mutex_lock(&comedi_board_minor_table_lock);
 190        dev = comedi_board_minor_table[minor];
 191        comedi_board_minor_table[minor] = NULL;
 192        mutex_unlock(&comedi_board_minor_table_lock);
 193        return dev;
 194}
 195
 196static void comedi_free_board_dev(struct comedi_device *dev)
 197{
 198        if (dev) {
 199                comedi_device_cleanup(dev);
 200                if (dev->class_dev) {
 201                        device_destroy(comedi_class,
 202                                       MKDEV(COMEDI_MAJOR, dev->minor));
 203                }
 204                comedi_dev_put(dev);
 205        }
 206}
 207
 208static struct comedi_subdevice *
 209comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor)
 210{
 211        struct comedi_subdevice *s;
 212        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 213
 214        mutex_lock(&comedi_subdevice_minor_table_lock);
 215        s = comedi_subdevice_minor_table[i];
 216        if (s && s->device != dev)
 217                s = NULL;
 218        mutex_unlock(&comedi_subdevice_minor_table_lock);
 219        return s;
 220}
 221
 222static struct comedi_device *comedi_dev_get_from_board_minor(unsigned int minor)
 223{
 224        struct comedi_device *dev;
 225
 226        mutex_lock(&comedi_board_minor_table_lock);
 227        dev = comedi_dev_get(comedi_board_minor_table[minor]);
 228        mutex_unlock(&comedi_board_minor_table_lock);
 229        return dev;
 230}
 231
 232static struct comedi_device *
 233comedi_dev_get_from_subdevice_minor(unsigned int minor)
 234{
 235        struct comedi_device *dev;
 236        struct comedi_subdevice *s;
 237        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 238
 239        mutex_lock(&comedi_subdevice_minor_table_lock);
 240        s = comedi_subdevice_minor_table[i];
 241        dev = comedi_dev_get(s ? s->device : NULL);
 242        mutex_unlock(&comedi_subdevice_minor_table_lock);
 243        return dev;
 244}
 245
 246/**
 247 * comedi_dev_get_from_minor() - Get COMEDI device by minor device number
 248 * @minor: Minor device number.
 249 *
 250 * Finds the COMEDI device associated with the minor device number, if any,
 251 * and increments its reference count.  The COMEDI device is prevented from
 252 * being freed until a matching call is made to comedi_dev_put().
 253 *
 254 * Return: A pointer to the COMEDI device if it exists, with its usage
 255 * reference incremented.  Return NULL if no COMEDI device exists with the
 256 * specified minor device number.
 257 */
 258struct comedi_device *comedi_dev_get_from_minor(unsigned int minor)
 259{
 260        if (minor < COMEDI_NUM_BOARD_MINORS)
 261                return comedi_dev_get_from_board_minor(minor);
 262
 263        return comedi_dev_get_from_subdevice_minor(minor);
 264}
 265EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor);
 266
 267static struct comedi_subdevice *
 268comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
 269{
 270        struct comedi_subdevice *s;
 271
 272        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 273                s = comedi_subdevice_from_minor(dev, minor);
 274                if (!s || (s->subdev_flags & SDF_CMD_READ))
 275                        return s;
 276        }
 277        return dev->read_subdev;
 278}
 279
 280static struct comedi_subdevice *
 281comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
 282{
 283        struct comedi_subdevice *s;
 284
 285        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 286                s = comedi_subdevice_from_minor(dev, minor);
 287                if (!s || (s->subdev_flags & SDF_CMD_WRITE))
 288                        return s;
 289        }
 290        return dev->write_subdev;
 291}
 292
 293static void comedi_file_reset(struct file *file)
 294{
 295        struct comedi_file *cfp = file->private_data;
 296        struct comedi_device *dev = cfp->dev;
 297        struct comedi_subdevice *s, *read_s, *write_s;
 298        unsigned int minor = iminor(file_inode(file));
 299
 300        read_s = dev->read_subdev;
 301        write_s = dev->write_subdev;
 302        if (minor >= COMEDI_NUM_BOARD_MINORS) {
 303                s = comedi_subdevice_from_minor(dev, minor);
 304                if (!s || s->subdev_flags & SDF_CMD_READ)
 305                        read_s = s;
 306                if (!s || s->subdev_flags & SDF_CMD_WRITE)
 307                        write_s = s;
 308        }
 309        cfp->last_attached = dev->attached;
 310        cfp->last_detach_count = dev->detach_count;
 311        WRITE_ONCE(cfp->read_subdev, read_s);
 312        WRITE_ONCE(cfp->write_subdev, write_s);
 313}
 314
 315static void comedi_file_check(struct file *file)
 316{
 317        struct comedi_file *cfp = file->private_data;
 318        struct comedi_device *dev = cfp->dev;
 319
 320        if (cfp->last_attached != dev->attached ||
 321            cfp->last_detach_count != dev->detach_count)
 322                comedi_file_reset(file);
 323}
 324
 325static struct comedi_subdevice *comedi_file_read_subdevice(struct file *file)
 326{
 327        struct comedi_file *cfp = file->private_data;
 328
 329        comedi_file_check(file);
 330        return READ_ONCE(cfp->read_subdev);
 331}
 332
 333static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file)
 334{
 335        struct comedi_file *cfp = file->private_data;
 336
 337        comedi_file_check(file);
 338        return READ_ONCE(cfp->write_subdev);
 339}
 340
 341static int resize_async_buffer(struct comedi_device *dev,
 342                               struct comedi_subdevice *s,
 343                               unsigned int new_size)
 344{
 345        struct comedi_async *async = s->async;
 346        int retval;
 347
 348        if (new_size > async->max_bufsize)
 349                return -EPERM;
 350
 351        if (s->busy) {
 352                dev_dbg(dev->class_dev,
 353                        "subdevice is busy, cannot resize buffer\n");
 354                return -EBUSY;
 355        }
 356        if (comedi_buf_is_mmapped(s)) {
 357                dev_dbg(dev->class_dev,
 358                        "subdevice is mmapped, cannot resize buffer\n");
 359                return -EBUSY;
 360        }
 361
 362        /* make sure buffer is an integral number of pages (we round up) */
 363        new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
 364
 365        retval = comedi_buf_alloc(dev, s, new_size);
 366        if (retval < 0)
 367                return retval;
 368
 369        if (s->buf_change) {
 370                retval = s->buf_change(dev, s);
 371                if (retval < 0)
 372                        return retval;
 373        }
 374
 375        dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n",
 376                s->index, async->prealloc_bufsz);
 377        return 0;
 378}
 379
 380/* sysfs attribute files */
 381
 382static ssize_t max_read_buffer_kb_show(struct device *csdev,
 383                                       struct device_attribute *attr, char *buf)
 384{
 385        unsigned int minor = MINOR(csdev->devt);
 386        struct comedi_device *dev;
 387        struct comedi_subdevice *s;
 388        unsigned int size = 0;
 389
 390        dev = comedi_dev_get_from_minor(minor);
 391        if (!dev)
 392                return -ENODEV;
 393
 394        mutex_lock(&dev->mutex);
 395        s = comedi_read_subdevice(dev, minor);
 396        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 397                size = s->async->max_bufsize / 1024;
 398        mutex_unlock(&dev->mutex);
 399
 400        comedi_dev_put(dev);
 401        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 402}
 403
 404static ssize_t max_read_buffer_kb_store(struct device *csdev,
 405                                        struct device_attribute *attr,
 406                                        const char *buf, size_t count)
 407{
 408        unsigned int minor = MINOR(csdev->devt);
 409        struct comedi_device *dev;
 410        struct comedi_subdevice *s;
 411        unsigned int size;
 412        int err;
 413
 414        err = kstrtouint(buf, 10, &size);
 415        if (err)
 416                return err;
 417        if (size > (UINT_MAX / 1024))
 418                return -EINVAL;
 419        size *= 1024;
 420
 421        dev = comedi_dev_get_from_minor(minor);
 422        if (!dev)
 423                return -ENODEV;
 424
 425        mutex_lock(&dev->mutex);
 426        s = comedi_read_subdevice(dev, minor);
 427        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 428                s->async->max_bufsize = size;
 429        else
 430                err = -EINVAL;
 431        mutex_unlock(&dev->mutex);
 432
 433        comedi_dev_put(dev);
 434        return err ? err : count;
 435}
 436static DEVICE_ATTR_RW(max_read_buffer_kb);
 437
 438static ssize_t read_buffer_kb_show(struct device *csdev,
 439                                   struct device_attribute *attr, char *buf)
 440{
 441        unsigned int minor = MINOR(csdev->devt);
 442        struct comedi_device *dev;
 443        struct comedi_subdevice *s;
 444        unsigned int size = 0;
 445
 446        dev = comedi_dev_get_from_minor(minor);
 447        if (!dev)
 448                return -ENODEV;
 449
 450        mutex_lock(&dev->mutex);
 451        s = comedi_read_subdevice(dev, minor);
 452        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 453                size = s->async->prealloc_bufsz / 1024;
 454        mutex_unlock(&dev->mutex);
 455
 456        comedi_dev_put(dev);
 457        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 458}
 459
 460static ssize_t read_buffer_kb_store(struct device *csdev,
 461                                    struct device_attribute *attr,
 462                                    const char *buf, size_t count)
 463{
 464        unsigned int minor = MINOR(csdev->devt);
 465        struct comedi_device *dev;
 466        struct comedi_subdevice *s;
 467        unsigned int size;
 468        int err;
 469
 470        err = kstrtouint(buf, 10, &size);
 471        if (err)
 472                return err;
 473        if (size > (UINT_MAX / 1024))
 474                return -EINVAL;
 475        size *= 1024;
 476
 477        dev = comedi_dev_get_from_minor(minor);
 478        if (!dev)
 479                return -ENODEV;
 480
 481        mutex_lock(&dev->mutex);
 482        s = comedi_read_subdevice(dev, minor);
 483        if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
 484                err = resize_async_buffer(dev, s, size);
 485        else
 486                err = -EINVAL;
 487        mutex_unlock(&dev->mutex);
 488
 489        comedi_dev_put(dev);
 490        return err ? err : count;
 491}
 492static DEVICE_ATTR_RW(read_buffer_kb);
 493
 494static ssize_t max_write_buffer_kb_show(struct device *csdev,
 495                                        struct device_attribute *attr,
 496                                        char *buf)
 497{
 498        unsigned int minor = MINOR(csdev->devt);
 499        struct comedi_device *dev;
 500        struct comedi_subdevice *s;
 501        unsigned int size = 0;
 502
 503        dev = comedi_dev_get_from_minor(minor);
 504        if (!dev)
 505                return -ENODEV;
 506
 507        mutex_lock(&dev->mutex);
 508        s = comedi_write_subdevice(dev, minor);
 509        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 510                size = s->async->max_bufsize / 1024;
 511        mutex_unlock(&dev->mutex);
 512
 513        comedi_dev_put(dev);
 514        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 515}
 516
 517static ssize_t max_write_buffer_kb_store(struct device *csdev,
 518                                         struct device_attribute *attr,
 519                                         const char *buf, size_t count)
 520{
 521        unsigned int minor = MINOR(csdev->devt);
 522        struct comedi_device *dev;
 523        struct comedi_subdevice *s;
 524        unsigned int size;
 525        int err;
 526
 527        err = kstrtouint(buf, 10, &size);
 528        if (err)
 529                return err;
 530        if (size > (UINT_MAX / 1024))
 531                return -EINVAL;
 532        size *= 1024;
 533
 534        dev = comedi_dev_get_from_minor(minor);
 535        if (!dev)
 536                return -ENODEV;
 537
 538        mutex_lock(&dev->mutex);
 539        s = comedi_write_subdevice(dev, minor);
 540        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 541                s->async->max_bufsize = size;
 542        else
 543                err = -EINVAL;
 544        mutex_unlock(&dev->mutex);
 545
 546        comedi_dev_put(dev);
 547        return err ? err : count;
 548}
 549static DEVICE_ATTR_RW(max_write_buffer_kb);
 550
 551static ssize_t write_buffer_kb_show(struct device *csdev,
 552                                    struct device_attribute *attr, char *buf)
 553{
 554        unsigned int minor = MINOR(csdev->devt);
 555        struct comedi_device *dev;
 556        struct comedi_subdevice *s;
 557        unsigned int size = 0;
 558
 559        dev = comedi_dev_get_from_minor(minor);
 560        if (!dev)
 561                return -ENODEV;
 562
 563        mutex_lock(&dev->mutex);
 564        s = comedi_write_subdevice(dev, minor);
 565        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 566                size = s->async->prealloc_bufsz / 1024;
 567        mutex_unlock(&dev->mutex);
 568
 569        comedi_dev_put(dev);
 570        return snprintf(buf, PAGE_SIZE, "%u\n", size);
 571}
 572
 573static ssize_t write_buffer_kb_store(struct device *csdev,
 574                                     struct device_attribute *attr,
 575                                     const char *buf, size_t count)
 576{
 577        unsigned int minor = MINOR(csdev->devt);
 578        struct comedi_device *dev;
 579        struct comedi_subdevice *s;
 580        unsigned int size;
 581        int err;
 582
 583        err = kstrtouint(buf, 10, &size);
 584        if (err)
 585                return err;
 586        if (size > (UINT_MAX / 1024))
 587                return -EINVAL;
 588        size *= 1024;
 589
 590        dev = comedi_dev_get_from_minor(minor);
 591        if (!dev)
 592                return -ENODEV;
 593
 594        mutex_lock(&dev->mutex);
 595        s = comedi_write_subdevice(dev, minor);
 596        if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
 597                err = resize_async_buffer(dev, s, size);
 598        else
 599                err = -EINVAL;
 600        mutex_unlock(&dev->mutex);
 601
 602        comedi_dev_put(dev);
 603        return err ? err : count;
 604}
 605static DEVICE_ATTR_RW(write_buffer_kb);
 606
 607static struct attribute *comedi_dev_attrs[] = {
 608        &dev_attr_max_read_buffer_kb.attr,
 609        &dev_attr_read_buffer_kb.attr,
 610        &dev_attr_max_write_buffer_kb.attr,
 611        &dev_attr_write_buffer_kb.attr,
 612        NULL,
 613};
 614ATTRIBUTE_GROUPS(comedi_dev);
 615
 616static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
 617                                              unsigned int bits)
 618{
 619        s->runflags &= ~bits;
 620}
 621
 622static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s,
 623                                            unsigned int bits)
 624{
 625        s->runflags |= bits;
 626}
 627
 628static void comedi_update_subdevice_runflags(struct comedi_subdevice *s,
 629                                             unsigned int mask,
 630                                             unsigned int bits)
 631{
 632        unsigned long flags;
 633
 634        spin_lock_irqsave(&s->spin_lock, flags);
 635        __comedi_clear_subdevice_runflags(s, mask);
 636        __comedi_set_subdevice_runflags(s, bits & mask);
 637        spin_unlock_irqrestore(&s->spin_lock, flags);
 638}
 639
 640static unsigned int __comedi_get_subdevice_runflags(struct comedi_subdevice *s)
 641{
 642        return s->runflags;
 643}
 644
 645static unsigned int comedi_get_subdevice_runflags(struct comedi_subdevice *s)
 646{
 647        unsigned long flags;
 648        unsigned int runflags;
 649
 650        spin_lock_irqsave(&s->spin_lock, flags);
 651        runflags = __comedi_get_subdevice_runflags(s);
 652        spin_unlock_irqrestore(&s->spin_lock, flags);
 653        return runflags;
 654}
 655
 656static bool comedi_is_runflags_running(unsigned int runflags)
 657{
 658        return runflags & COMEDI_SRF_RUNNING;
 659}
 660
 661static bool comedi_is_runflags_in_error(unsigned int runflags)
 662{
 663        return runflags & COMEDI_SRF_ERROR;
 664}
 665
 666/**
 667 * comedi_is_subdevice_running() - Check if async command running on subdevice
 668 * @s: COMEDI subdevice.
 669 *
 670 * Return: %true if an asynchronous COMEDI command is active on the
 671 * subdevice, else %false.
 672 */
 673bool comedi_is_subdevice_running(struct comedi_subdevice *s)
 674{
 675        unsigned int runflags = comedi_get_subdevice_runflags(s);
 676
 677        return comedi_is_runflags_running(runflags);
 678}
 679EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
 680
 681static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
 682{
 683        unsigned int runflags = __comedi_get_subdevice_runflags(s);
 684
 685        return comedi_is_runflags_running(runflags);
 686}
 687
 688bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
 689{
 690        unsigned int runflags = __comedi_get_subdevice_runflags(s);
 691
 692        return runflags & COMEDI_SRF_FREE_SPRIV;
 693}
 694
 695/**
 696 * comedi_set_spriv_auto_free() - Mark subdevice private data as freeable
 697 * @s: COMEDI subdevice.
 698 *
 699 * Mark the subdevice as having a pointer to private data that can be
 700 * automatically freed when the COMEDI device is detached from the low-level
 701 * driver.
 702 */
 703void comedi_set_spriv_auto_free(struct comedi_subdevice *s)
 704{
 705        __comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV);
 706}
 707EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free);
 708
 709/**
 710 * comedi_alloc_spriv - Allocate memory for the subdevice private data
 711 * @s: COMEDI subdevice.
 712 * @size: Size of the memory to allocate.
 713 *
 714 * Allocate memory for the subdevice private data and point @s->private
 715 * to it.  The memory will be freed automatically when the COMEDI device
 716 * is detached from the low-level driver.
 717 *
 718 * Return: A pointer to the allocated memory @s->private on success.
 719 * Return NULL on failure.
 720 */
 721void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size)
 722{
 723        s->private = kzalloc(size, GFP_KERNEL);
 724        if (s->private)
 725                comedi_set_spriv_auto_free(s);
 726        return s->private;
 727}
 728EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
 729
 730/*
 731 * This function restores a subdevice to an idle state.
 732 */
 733static void do_become_nonbusy(struct comedi_device *dev,
 734                              struct comedi_subdevice *s)
 735{
 736        struct comedi_async *async = s->async;
 737
 738        comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
 739        if (async) {
 740                comedi_buf_reset(s);
 741                async->inttrig = NULL;
 742                kfree(async->cmd.chanlist);
 743                async->cmd.chanlist = NULL;
 744                s->busy = NULL;
 745                wake_up_interruptible_all(&async->wait_head);
 746        } else {
 747                dev_err(dev->class_dev,
 748                        "BUG: (?) do_become_nonbusy called with async=NULL\n");
 749                s->busy = NULL;
 750        }
 751}
 752
 753static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 754{
 755        int ret = 0;
 756
 757        if (comedi_is_subdevice_running(s) && s->cancel)
 758                ret = s->cancel(dev, s);
 759
 760        do_become_nonbusy(dev, s);
 761
 762        return ret;
 763}
 764
 765void comedi_device_cancel_all(struct comedi_device *dev)
 766{
 767        struct comedi_subdevice *s;
 768        int i;
 769
 770        if (!dev->attached)
 771                return;
 772
 773        for (i = 0; i < dev->n_subdevices; i++) {
 774                s = &dev->subdevices[i];
 775                if (s->async)
 776                        do_cancel(dev, s);
 777        }
 778}
 779
 780static int is_device_busy(struct comedi_device *dev)
 781{
 782        struct comedi_subdevice *s;
 783        int i;
 784
 785        if (!dev->attached)
 786                return 0;
 787
 788        for (i = 0; i < dev->n_subdevices; i++) {
 789                s = &dev->subdevices[i];
 790                if (s->busy)
 791                        return 1;
 792                if (s->async && comedi_buf_is_mmapped(s))
 793                        return 1;
 794        }
 795
 796        return 0;
 797}
 798
 799/*
 800 * COMEDI_DEVCONFIG ioctl
 801 * attaches (and configures) or detaches a legacy device
 802 *
 803 * arg:
 804 *      pointer to comedi_devconfig structure (NULL if detaching)
 805 *
 806 * reads:
 807 *      comedi_devconfig structure (if attaching)
 808 *
 809 * writes:
 810 *      nothing
 811 */
 812static int do_devconfig_ioctl(struct comedi_device *dev,
 813                              struct comedi_devconfig __user *arg)
 814{
 815        struct comedi_devconfig it;
 816
 817        if (!capable(CAP_SYS_ADMIN))
 818                return -EPERM;
 819
 820        if (!arg) {
 821                if (is_device_busy(dev))
 822                        return -EBUSY;
 823                if (dev->attached) {
 824                        struct module *driver_module = dev->driver->module;
 825
 826                        comedi_device_detach(dev);
 827                        module_put(driver_module);
 828                }
 829                return 0;
 830        }
 831
 832        if (copy_from_user(&it, arg, sizeof(it)))
 833                return -EFAULT;
 834
 835        it.board_name[COMEDI_NAMELEN - 1] = 0;
 836
 837        if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
 838                dev_warn(dev->class_dev,
 839                         "comedi_config --init_data is deprecated\n");
 840                return -EINVAL;
 841        }
 842
 843        if (dev->minor >= comedi_num_legacy_minors)
 844                /* don't re-use dynamically allocated comedi devices */
 845                return -EBUSY;
 846
 847        /* This increments the driver module count on success. */
 848        return comedi_device_attach(dev, &it);
 849}
 850
 851/*
 852 * COMEDI_BUFCONFIG ioctl
 853 * buffer configuration
 854 *
 855 * arg:
 856 *      pointer to comedi_bufconfig structure
 857 *
 858 * reads:
 859 *      comedi_bufconfig structure
 860 *
 861 * writes:
 862 *      modified comedi_bufconfig structure
 863 */
 864static int do_bufconfig_ioctl(struct comedi_device *dev,
 865                              struct comedi_bufconfig __user *arg)
 866{
 867        struct comedi_bufconfig bc;
 868        struct comedi_async *async;
 869        struct comedi_subdevice *s;
 870        int retval = 0;
 871
 872        if (copy_from_user(&bc, arg, sizeof(bc)))
 873                return -EFAULT;
 874
 875        if (bc.subdevice >= dev->n_subdevices)
 876                return -EINVAL;
 877
 878        s = &dev->subdevices[bc.subdevice];
 879        async = s->async;
 880
 881        if (!async) {
 882                dev_dbg(dev->class_dev,
 883                        "subdevice does not have async capability\n");
 884                bc.size = 0;
 885                bc.maximum_size = 0;
 886                goto copyback;
 887        }
 888
 889        if (bc.maximum_size) {
 890                if (!capable(CAP_SYS_ADMIN))
 891                        return -EPERM;
 892
 893                async->max_bufsize = bc.maximum_size;
 894        }
 895
 896        if (bc.size) {
 897                retval = resize_async_buffer(dev, s, bc.size);
 898                if (retval < 0)
 899                        return retval;
 900        }
 901
 902        bc.size = async->prealloc_bufsz;
 903        bc.maximum_size = async->max_bufsize;
 904
 905copyback:
 906        if (copy_to_user(arg, &bc, sizeof(bc)))
 907                return -EFAULT;
 908
 909        return 0;
 910}
 911
 912/*
 913 * COMEDI_DEVINFO ioctl
 914 * device info
 915 *
 916 * arg:
 917 *      pointer to comedi_devinfo structure
 918 *
 919 * reads:
 920 *      nothing
 921 *
 922 * writes:
 923 *      comedi_devinfo structure
 924 */
 925static int do_devinfo_ioctl(struct comedi_device *dev,
 926                            struct comedi_devinfo __user *arg,
 927                            struct file *file)
 928{
 929        struct comedi_subdevice *s;
 930        struct comedi_devinfo devinfo;
 931
 932        memset(&devinfo, 0, sizeof(devinfo));
 933
 934        /* fill devinfo structure */
 935        devinfo.version_code = COMEDI_VERSION_CODE;
 936        devinfo.n_subdevs = dev->n_subdevices;
 937        strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
 938        strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
 939
 940        s = comedi_file_read_subdevice(file);
 941        if (s)
 942                devinfo.read_subdevice = s->index;
 943        else
 944                devinfo.read_subdevice = -1;
 945
 946        s = comedi_file_write_subdevice(file);
 947        if (s)
 948                devinfo.write_subdevice = s->index;
 949        else
 950                devinfo.write_subdevice = -1;
 951
 952        if (copy_to_user(arg, &devinfo, sizeof(devinfo)))
 953                return -EFAULT;
 954
 955        return 0;
 956}
 957
 958/*
 959 * COMEDI_SUBDINFO ioctl
 960 * subdevices info
 961 *
 962 * arg:
 963 *      pointer to array of comedi_subdinfo structures
 964 *
 965 * reads:
 966 *      nothing
 967 *
 968 * writes:
 969 *      array of comedi_subdinfo structures
 970 */
 971static int do_subdinfo_ioctl(struct comedi_device *dev,
 972                             struct comedi_subdinfo __user *arg, void *file)
 973{
 974        int ret, i;
 975        struct comedi_subdinfo *tmp, *us;
 976        struct comedi_subdevice *s;
 977
 978        tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL);
 979        if (!tmp)
 980                return -ENOMEM;
 981
 982        /* fill subdinfo structs */
 983        for (i = 0; i < dev->n_subdevices; i++) {
 984                s = &dev->subdevices[i];
 985                us = tmp + i;
 986
 987                us->type = s->type;
 988                us->n_chan = s->n_chan;
 989                us->subd_flags = s->subdev_flags;
 990                if (comedi_is_subdevice_running(s))
 991                        us->subd_flags |= SDF_RUNNING;
 992#define TIMER_nanosec 5         /* backwards compatibility */
 993                us->timer_type = TIMER_nanosec;
 994                us->len_chanlist = s->len_chanlist;
 995                us->maxdata = s->maxdata;
 996                if (s->range_table) {
 997                        us->range_type =
 998                            (i << 24) | (0 << 16) | (s->range_table->length);
 999                } else {
1000                        us->range_type = 0;     /* XXX */
1001                }
1002
1003                if (s->busy)
1004                        us->subd_flags |= SDF_BUSY;
1005                if (s->busy == file)
1006                        us->subd_flags |= SDF_BUSY_OWNER;
1007                if (s->lock)
1008                        us->subd_flags |= SDF_LOCKED;
1009                if (s->lock == file)
1010                        us->subd_flags |= SDF_LOCK_OWNER;
1011                if (!s->maxdata && s->maxdata_list)
1012                        us->subd_flags |= SDF_MAXDATA;
1013                if (s->range_table_list)
1014                        us->subd_flags |= SDF_RANGETYPE;
1015                if (s->do_cmd)
1016                        us->subd_flags |= SDF_CMD;
1017
1018                if (s->insn_bits != &insn_inval)
1019                        us->insn_bits_support = COMEDI_SUPPORTED;
1020                else
1021                        us->insn_bits_support = COMEDI_UNSUPPORTED;
1022        }
1023
1024        ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
1025
1026        kfree(tmp);
1027
1028        return ret ? -EFAULT : 0;
1029}
1030
1031/*
1032 * COMEDI_CHANINFO ioctl
1033 * subdevice channel info
1034 *
1035 * arg:
1036 *      pointer to comedi_chaninfo structure
1037 *
1038 * reads:
1039 *      comedi_chaninfo structure
1040 *
1041 * writes:
1042 *      array of maxdata values to chaninfo->maxdata_list if requested
1043 *      array of range table lengths to chaninfo->range_table_list if requested
1044 */
1045static int do_chaninfo_ioctl(struct comedi_device *dev,
1046                             struct comedi_chaninfo __user *arg)
1047{
1048        struct comedi_subdevice *s;
1049        struct comedi_chaninfo it;
1050
1051        if (copy_from_user(&it, arg, sizeof(it)))
1052                return -EFAULT;
1053
1054        if (it.subdev >= dev->n_subdevices)
1055                return -EINVAL;
1056        s = &dev->subdevices[it.subdev];
1057
1058        if (it.maxdata_list) {
1059                if (s->maxdata || !s->maxdata_list)
1060                        return -EINVAL;
1061                if (copy_to_user(it.maxdata_list, s->maxdata_list,
1062                                 s->n_chan * sizeof(unsigned int)))
1063                        return -EFAULT;
1064        }
1065
1066        if (it.flaglist)
1067                return -EINVAL; /* flaglist not supported */
1068
1069        if (it.rangelist) {
1070                int i;
1071
1072                if (!s->range_table_list)
1073                        return -EINVAL;
1074                for (i = 0; i < s->n_chan; i++) {
1075                        int x;
1076
1077                        x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
1078                            (s->range_table_list[i]->length);
1079                        if (put_user(x, it.rangelist + i))
1080                                return -EFAULT;
1081                }
1082        }
1083
1084        return 0;
1085}
1086
1087/*
1088 * COMEDI_BUFINFO ioctl
1089 * buffer information
1090 *
1091 * arg:
1092 *      pointer to comedi_bufinfo structure
1093 *
1094 * reads:
1095 *      comedi_bufinfo structure
1096 *
1097 * writes:
1098 *      modified comedi_bufinfo structure
1099 */
1100static int do_bufinfo_ioctl(struct comedi_device *dev,
1101                            struct comedi_bufinfo __user *arg, void *file)
1102{
1103        struct comedi_bufinfo bi;
1104        struct comedi_subdevice *s;
1105        struct comedi_async *async;
1106        unsigned int runflags;
1107        int retval = 0;
1108        bool become_nonbusy = false;
1109
1110        if (copy_from_user(&bi, arg, sizeof(bi)))
1111                return -EFAULT;
1112
1113        if (bi.subdevice >= dev->n_subdevices)
1114                return -EINVAL;
1115
1116        s = &dev->subdevices[bi.subdevice];
1117
1118        async = s->async;
1119
1120        if (!async || s->busy != file)
1121                return -EINVAL;
1122
1123        runflags = comedi_get_subdevice_runflags(s);
1124        if (!(async->cmd.flags & CMDF_WRITE)) {
1125                /* command was set up in "read" direction */
1126                if (bi.bytes_read) {
1127                        comedi_buf_read_alloc(s, bi.bytes_read);
1128                        bi.bytes_read = comedi_buf_read_free(s, bi.bytes_read);
1129                }
1130                /*
1131                 * If nothing left to read, and command has stopped, and
1132                 * {"read" position not updated or command stopped normally},
1133                 * then become non-busy.
1134                 */
1135                if (comedi_buf_read_n_available(s) == 0 &&
1136                    !comedi_is_runflags_running(runflags) &&
1137                    (bi.bytes_read == 0 ||
1138                     !comedi_is_runflags_in_error(runflags))) {
1139                        become_nonbusy = true;
1140                        if (comedi_is_runflags_in_error(runflags))
1141                                retval = -EPIPE;
1142                }
1143                bi.bytes_written = 0;
1144        } else {
1145                /* command was set up in "write" direction */
1146                if (!comedi_is_runflags_running(runflags)) {
1147                        bi.bytes_written = 0;
1148                        become_nonbusy = true;
1149                        if (comedi_is_runflags_in_error(runflags))
1150                                retval = -EPIPE;
1151                } else if (bi.bytes_written) {
1152                        comedi_buf_write_alloc(s, bi.bytes_written);
1153                        bi.bytes_written =
1154                            comedi_buf_write_free(s, bi.bytes_written);
1155                }
1156                bi.bytes_read = 0;
1157        }
1158
1159        bi.buf_write_count = async->buf_write_count;
1160        bi.buf_write_ptr = async->buf_write_ptr;
1161        bi.buf_read_count = async->buf_read_count;
1162        bi.buf_read_ptr = async->buf_read_ptr;
1163
1164        if (become_nonbusy)
1165                do_become_nonbusy(dev, s);
1166
1167        if (retval)
1168                return retval;
1169
1170        if (copy_to_user(arg, &bi, sizeof(bi)))
1171                return -EFAULT;
1172
1173        return 0;
1174}
1175
1176static int check_insn_config_length(struct comedi_insn *insn,
1177                                    unsigned int *data)
1178{
1179        if (insn->n < 1)
1180                return -EINVAL;
1181
1182        switch (data[0]) {
1183        case INSN_CONFIG_DIO_OUTPUT:
1184        case INSN_CONFIG_DIO_INPUT:
1185        case INSN_CONFIG_DISARM:
1186        case INSN_CONFIG_RESET:
1187                if (insn->n == 1)
1188                        return 0;
1189                break;
1190        case INSN_CONFIG_ARM:
1191        case INSN_CONFIG_DIO_QUERY:
1192        case INSN_CONFIG_BLOCK_SIZE:
1193        case INSN_CONFIG_FILTER:
1194        case INSN_CONFIG_SERIAL_CLOCK:
1195        case INSN_CONFIG_BIDIRECTIONAL_DATA:
1196        case INSN_CONFIG_ALT_SOURCE:
1197        case INSN_CONFIG_SET_COUNTER_MODE:
1198        case INSN_CONFIG_8254_READ_STATUS:
1199        case INSN_CONFIG_SET_ROUTING:
1200        case INSN_CONFIG_GET_ROUTING:
1201        case INSN_CONFIG_GET_PWM_STATUS:
1202        case INSN_CONFIG_PWM_SET_PERIOD:
1203        case INSN_CONFIG_PWM_GET_PERIOD:
1204                if (insn->n == 2)
1205                        return 0;
1206                break;
1207        case INSN_CONFIG_SET_GATE_SRC:
1208        case INSN_CONFIG_GET_GATE_SRC:
1209        case INSN_CONFIG_SET_CLOCK_SRC:
1210        case INSN_CONFIG_GET_CLOCK_SRC:
1211        case INSN_CONFIG_SET_OTHER_SRC:
1212        case INSN_CONFIG_GET_COUNTER_STATUS:
1213        case INSN_CONFIG_PWM_SET_H_BRIDGE:
1214        case INSN_CONFIG_PWM_GET_H_BRIDGE:
1215        case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
1216                if (insn->n == 3)
1217                        return 0;
1218                break;
1219        case INSN_CONFIG_PWM_OUTPUT:
1220        case INSN_CONFIG_ANALOG_TRIG:
1221                if (insn->n == 5)
1222                        return 0;
1223                break;
1224        case INSN_CONFIG_DIGITAL_TRIG:
1225                if (insn->n == 6)
1226                        return 0;
1227                break;
1228                /*
1229                 * by default we allow the insn since we don't have checks for
1230                 * all possible cases yet
1231                 */
1232        default:
1233                pr_warn("No check for data length of config insn id %i is implemented\n",
1234                        data[0]);
1235                pr_warn("Add a check to %s in %s\n", __func__, __FILE__);
1236                pr_warn("Assuming n=%i is correct\n", insn->n);
1237                return 0;
1238        }
1239        return -EINVAL;
1240}
1241
1242static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
1243                      unsigned int *data, void *file)
1244{
1245        struct comedi_subdevice *s;
1246        int ret = 0;
1247        int i;
1248
1249        if (insn->insn & INSN_MASK_SPECIAL) {
1250                /* a non-subdevice instruction */
1251
1252                switch (insn->insn) {
1253                case INSN_GTOD:
1254                        {
1255                                struct timespec64 tv;
1256
1257                                if (insn->n != 2) {
1258                                        ret = -EINVAL;
1259                                        break;
1260                                }
1261
1262                                ktime_get_real_ts64(&tv);
1263                                /* unsigned data safe until 2106 */
1264                                data[0] = (unsigned int)tv.tv_sec;
1265                                data[1] = tv.tv_nsec / NSEC_PER_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        WRITE_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        WRITE_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 int 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 = vma_pages(vma);
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 int 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 int runflags =
2489                                     comedi_get_subdevice_runflags(s);
2490
2491                        if (!comedi_is_runflags_running(runflags)) {
2492                                if (comedi_is_runflags_in_error(runflags))
2493                                        retval = -EPIPE;
2494                                if (retval || nbytes)
2495                                        become_nonbusy = true;
2496                                break;
2497                        }
2498                        if (nbytes == 0)
2499                                break;
2500                        if (file->f_flags & O_NONBLOCK) {
2501                                retval = -EAGAIN;
2502                                break;
2503                        }
2504                        schedule();
2505                        if (signal_pending(current)) {
2506                                retval = -ERESTARTSYS;
2507                                break;
2508                        }
2509                        if (s->busy != file ||
2510                            (async->cmd.flags & CMDF_WRITE)) {
2511                                retval = -EINVAL;
2512                                break;
2513                        }
2514                        continue;
2515                }
2516                rp = async->buf_read_ptr;
2517                n1 = min(n, async->prealloc_bufsz - rp);
2518                n2 = n - n1;
2519                m = copy_to_user(buf, async->prealloc_buf + rp, n1);
2520                if (m)
2521                        m += n2;
2522                else if (n2)
2523                        m = copy_to_user(buf + n1, async->prealloc_buf, n2);
2524                if (m) {
2525                        n -= m;
2526                        retval = -EFAULT;
2527                }
2528
2529                comedi_buf_read_alloc(s, n);
2530                comedi_buf_read_free(s, n);
2531
2532                count += n;
2533                nbytes -= n;
2534
2535                buf += n;
2536        }
2537        remove_wait_queue(&async->wait_head, &wait);
2538        set_current_state(TASK_RUNNING);
2539        if (become_nonbusy && count == 0) {
2540                struct comedi_subdevice *new_s;
2541
2542                /*
2543                 * To avoid deadlock, cannot acquire dev->mutex
2544                 * while dev->attach_lock is held.
2545                 */
2546                up_read(&dev->attach_lock);
2547                attach_locked = false;
2548                mutex_lock(&dev->mutex);
2549                /*
2550                 * Check device hasn't become detached behind our back.
2551                 * Checking dev->detach_count is unchanged ought to be
2552                 * sufficient (unless there have been 2**32 detaches in the
2553                 * meantime!), but check the subdevice pointer as well just in
2554                 * case.
2555                 *
2556                 * Also check the subdevice is still in a suitable state to
2557                 * become non-busy in case it changed behind our back.
2558                 */
2559                new_s = comedi_file_read_subdevice(file);
2560                if (dev->attached && old_detach_count == dev->detach_count &&
2561                    s == new_s && new_s->async == async && s->busy == file &&
2562                    !(async->cmd.flags & CMDF_WRITE) &&
2563                    !comedi_is_subdevice_running(s) &&
2564                    comedi_buf_read_n_available(s) == 0)
2565                        do_become_nonbusy(dev, s);
2566                mutex_unlock(&dev->mutex);
2567        }
2568out:
2569        if (attach_locked)
2570                up_read(&dev->attach_lock);
2571
2572        return count ? count : retval;
2573}
2574
2575static int comedi_open(struct inode *inode, struct file *file)
2576{
2577        const unsigned int minor = iminor(inode);
2578        struct comedi_file *cfp;
2579        struct comedi_device *dev = comedi_dev_get_from_minor(minor);
2580        int rc;
2581
2582        if (!dev) {
2583                pr_debug("invalid minor number\n");
2584                return -ENODEV;
2585        }
2586
2587        cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
2588        if (!cfp)
2589                return -ENOMEM;
2590
2591        cfp->dev = dev;
2592
2593        mutex_lock(&dev->mutex);
2594        if (!dev->attached && !capable(CAP_SYS_ADMIN)) {
2595                dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n");
2596                rc = -ENODEV;
2597                goto out;
2598        }
2599        if (dev->attached && dev->use_count == 0) {
2600                if (!try_module_get(dev->driver->module)) {
2601                        rc = -ENXIO;
2602                        goto out;
2603                }
2604                if (dev->open) {
2605                        rc = dev->open(dev);
2606                        if (rc < 0) {
2607                                module_put(dev->driver->module);
2608                                goto out;
2609                        }
2610                }
2611        }
2612
2613        dev->use_count++;
2614        file->private_data = cfp;
2615        comedi_file_reset(file);
2616        rc = 0;
2617
2618out:
2619        mutex_unlock(&dev->mutex);
2620        if (rc) {
2621                comedi_dev_put(dev);
2622                kfree(cfp);
2623        }
2624        return rc;
2625}
2626
2627static int comedi_fasync(int fd, struct file *file, int on)
2628{
2629        struct comedi_file *cfp = file->private_data;
2630        struct comedi_device *dev = cfp->dev;
2631
2632        return fasync_helper(fd, file, on, &dev->async_queue);
2633}
2634
2635static int comedi_close(struct inode *inode, struct file *file)
2636{
2637        struct comedi_file *cfp = file->private_data;
2638        struct comedi_device *dev = cfp->dev;
2639        struct comedi_subdevice *s = NULL;
2640        int i;
2641
2642        mutex_lock(&dev->mutex);
2643
2644        if (dev->subdevices) {
2645                for (i = 0; i < dev->n_subdevices; i++) {
2646                        s = &dev->subdevices[i];
2647
2648                        if (s->busy == file)
2649                                do_cancel(dev, s);
2650                        if (s->lock == file)
2651                                s->lock = NULL;
2652                }
2653        }
2654        if (dev->attached && dev->use_count == 1) {
2655                if (dev->close)
2656                        dev->close(dev);
2657                module_put(dev->driver->module);
2658        }
2659
2660        dev->use_count--;
2661
2662        mutex_unlock(&dev->mutex);
2663        comedi_dev_put(dev);
2664        kfree(cfp);
2665
2666        return 0;
2667}
2668
2669static const struct file_operations comedi_fops = {
2670        .owner = THIS_MODULE,
2671        .unlocked_ioctl = comedi_unlocked_ioctl,
2672        .compat_ioctl = comedi_compat_ioctl,
2673        .open = comedi_open,
2674        .release = comedi_close,
2675        .read = comedi_read,
2676        .write = comedi_write,
2677        .mmap = comedi_mmap,
2678        .poll = comedi_poll,
2679        .fasync = comedi_fasync,
2680        .llseek = noop_llseek,
2681};
2682
2683/**
2684 * comedi_event() - Handle events for asynchronous COMEDI command
2685 * @dev: COMEDI device.
2686 * @s: COMEDI subdevice.
2687 * Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
2688 *
2689 * If an asynchronous COMEDI command is active on the subdevice, process
2690 * any %COMEDI_CB_... event flags that have been set, usually by an
2691 * interrupt handler.  These may change the run state of the asynchronous
2692 * command, wake a task, and/or send a %SIGIO signal.
2693 */
2694void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
2695{
2696        struct comedi_async *async = s->async;
2697        unsigned int events;
2698        int si_code = 0;
2699        unsigned long flags;
2700
2701        spin_lock_irqsave(&s->spin_lock, flags);
2702
2703        events = async->events;
2704        async->events = 0;
2705        if (!__comedi_is_subdevice_running(s)) {
2706                spin_unlock_irqrestore(&s->spin_lock, flags);
2707                return;
2708        }
2709
2710        if (events & COMEDI_CB_CANCEL_MASK)
2711                __comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING);
2712
2713        /*
2714         * Remember if an error event has occurred, so an error can be
2715         * returned the next time the user does a read() or write().
2716         */
2717        if (events & COMEDI_CB_ERROR_MASK)
2718                __comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR);
2719
2720        if (async->cb_mask & events) {
2721                wake_up_interruptible(&async->wait_head);
2722                si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN;
2723        }
2724
2725        spin_unlock_irqrestore(&s->spin_lock, flags);
2726
2727        if (si_code)
2728                kill_fasync(&dev->async_queue, SIGIO, si_code);
2729}
2730EXPORT_SYMBOL_GPL(comedi_event);
2731
2732/* Note: the ->mutex is pre-locked on successful return */
2733struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
2734{
2735        struct comedi_device *dev;
2736        struct device *csdev;
2737        unsigned int i;
2738
2739        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2740        if (!dev)
2741                return ERR_PTR(-ENOMEM);
2742        comedi_device_init(dev);
2743        comedi_set_hw_dev(dev, hardware_device);
2744        mutex_lock(&dev->mutex);
2745        mutex_lock(&comedi_board_minor_table_lock);
2746        for (i = hardware_device ? comedi_num_legacy_minors : 0;
2747             i < COMEDI_NUM_BOARD_MINORS; ++i) {
2748                if (!comedi_board_minor_table[i]) {
2749                        comedi_board_minor_table[i] = dev;
2750                        break;
2751                }
2752        }
2753        mutex_unlock(&comedi_board_minor_table_lock);
2754        if (i == COMEDI_NUM_BOARD_MINORS) {
2755                mutex_unlock(&dev->mutex);
2756                comedi_device_cleanup(dev);
2757                comedi_dev_put(dev);
2758                dev_err(hardware_device,
2759                        "ran out of minor numbers for board device files\n");
2760                return ERR_PTR(-EBUSY);
2761        }
2762        dev->minor = i;
2763        csdev = device_create(comedi_class, hardware_device,
2764                              MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
2765        if (!IS_ERR(csdev))
2766                dev->class_dev = get_device(csdev);
2767
2768        /* Note: dev->mutex needs to be unlocked by the caller. */
2769        return dev;
2770}
2771
2772void comedi_release_hardware_device(struct device *hardware_device)
2773{
2774        int minor;
2775        struct comedi_device *dev;
2776
2777        for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS;
2778             minor++) {
2779                mutex_lock(&comedi_board_minor_table_lock);
2780                dev = comedi_board_minor_table[minor];
2781                if (dev && dev->hw_dev == hardware_device) {
2782                        comedi_board_minor_table[minor] = NULL;
2783                        mutex_unlock(&comedi_board_minor_table_lock);
2784                        comedi_free_board_dev(dev);
2785                        break;
2786                }
2787                mutex_unlock(&comedi_board_minor_table_lock);
2788        }
2789}
2790
2791int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
2792{
2793        struct comedi_device *dev = s->device;
2794        struct device *csdev;
2795        unsigned int i;
2796
2797        mutex_lock(&comedi_subdevice_minor_table_lock);
2798        for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) {
2799                if (!comedi_subdevice_minor_table[i]) {
2800                        comedi_subdevice_minor_table[i] = s;
2801                        break;
2802                }
2803        }
2804        mutex_unlock(&comedi_subdevice_minor_table_lock);
2805        if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
2806                dev_err(dev->class_dev,
2807                        "ran out of minor numbers for subdevice files\n");
2808                return -EBUSY;
2809        }
2810        i += COMEDI_NUM_BOARD_MINORS;
2811        s->minor = i;
2812        csdev = device_create(comedi_class, dev->class_dev,
2813                              MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
2814                              dev->minor, s->index);
2815        if (!IS_ERR(csdev))
2816                s->class_dev = csdev;
2817
2818        return 0;
2819}
2820
2821void comedi_free_subdevice_minor(struct comedi_subdevice *s)
2822{
2823        unsigned int i;
2824
2825        if (!s)
2826                return;
2827        if (s->minor < COMEDI_NUM_BOARD_MINORS ||
2828            s->minor >= COMEDI_NUM_MINORS)
2829                return;
2830
2831        i = s->minor - COMEDI_NUM_BOARD_MINORS;
2832        mutex_lock(&comedi_subdevice_minor_table_lock);
2833        if (s == comedi_subdevice_minor_table[i])
2834                comedi_subdevice_minor_table[i] = NULL;
2835        mutex_unlock(&comedi_subdevice_minor_table_lock);
2836        if (s->class_dev) {
2837                device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
2838                s->class_dev = NULL;
2839        }
2840}
2841
2842static void comedi_cleanup_board_minors(void)
2843{
2844        struct comedi_device *dev;
2845        unsigned int i;
2846
2847        for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
2848                dev = comedi_clear_board_minor(i);
2849                comedi_free_board_dev(dev);
2850        }
2851}
2852
2853static int __init comedi_init(void)
2854{
2855        int i;
2856        int retval;
2857
2858        pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n");
2859
2860        if (comedi_num_legacy_minors < 0 ||
2861            comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
2862                pr_err("invalid value for module parameter \"comedi_num_legacy_minors\".  Valid values are 0 through %i.\n",
2863                       COMEDI_NUM_BOARD_MINORS);
2864                return -EINVAL;
2865        }
2866
2867        retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2868                                        COMEDI_NUM_MINORS, "comedi");
2869        if (retval)
2870                return -EIO;
2871        cdev_init(&comedi_cdev, &comedi_fops);
2872        comedi_cdev.owner = THIS_MODULE;
2873
2874        retval = kobject_set_name(&comedi_cdev.kobj, "comedi");
2875        if (retval) {
2876                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2877                                         COMEDI_NUM_MINORS);
2878                return retval;
2879        }
2880
2881        if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
2882                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2883                                         COMEDI_NUM_MINORS);
2884                return -EIO;
2885        }
2886        comedi_class = class_create(THIS_MODULE, "comedi");
2887        if (IS_ERR(comedi_class)) {
2888                pr_err("failed to create class\n");
2889                cdev_del(&comedi_cdev);
2890                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2891                                         COMEDI_NUM_MINORS);
2892                return PTR_ERR(comedi_class);
2893        }
2894
2895        comedi_class->dev_groups = comedi_dev_groups;
2896
2897        /* create devices files for legacy/manual use */
2898        for (i = 0; i < comedi_num_legacy_minors; i++) {
2899                struct comedi_device *dev;
2900
2901                dev = comedi_alloc_board_minor(NULL);
2902                if (IS_ERR(dev)) {
2903                        comedi_cleanup_board_minors();
2904                        cdev_del(&comedi_cdev);
2905                        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2906                                                 COMEDI_NUM_MINORS);
2907                        return PTR_ERR(dev);
2908                }
2909                /* comedi_alloc_board_minor() locked the mutex */
2910                mutex_unlock(&dev->mutex);
2911        }
2912
2913        /* XXX requires /proc interface */
2914        comedi_proc_init();
2915
2916        return 0;
2917}
2918module_init(comedi_init);
2919
2920static void __exit comedi_cleanup(void)
2921{
2922        comedi_cleanup_board_minors();
2923        class_destroy(comedi_class);
2924        cdev_del(&comedi_cdev);
2925        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
2926
2927        comedi_proc_cleanup();
2928}
2929module_exit(comedi_cleanup);
2930
2931MODULE_AUTHOR("http://www.comedi.org");
2932MODULE_DESCRIPTION("Comedi core module");
2933MODULE_LICENSE("GPL");
2934