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