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