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