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