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