Lines Matching +full:bm +full:- +full:work

1 // SPDX-License-Identifier: GPL-2.0+
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
37 * COMEDI_SRF_RT: DEPRECATED: command is running real-time
41 * COMEDI_SRF_FREE_SPRIV: free s->private on detach
53 * struct comedi_file - Per-file private data for COMEDI device
70 (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
75 "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
96 /* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */
104 kref_init(&dev->refcount); in comedi_device_init()
105 spin_lock_init(&dev->spinlock); in comedi_device_init()
106 mutex_init(&dev->mutex); in comedi_device_init()
107 init_rwsem(&dev->attach_lock); in comedi_device_init()
108 dev->minor = -1; in comedi_device_init()
116 mutex_destroy(&dev->mutex); in comedi_dev_kref_release()
117 put_device(dev->class_dev); in comedi_dev_kref_release()
122 * comedi_dev_put() - Release a use of a COMEDI device
136 return kref_put(&dev->refcount, comedi_dev_kref_release); in comedi_dev_put()
144 kref_get(&dev->refcount); in comedi_dev_get()
154 mutex_lock(&dev->mutex); in comedi_device_cleanup()
155 if (dev->attached) in comedi_device_cleanup()
156 driver_module = dev->driver->module; in comedi_device_cleanup()
158 if (driver_module && dev->use_count) in comedi_device_cleanup()
160 mutex_unlock(&dev->mutex); in comedi_device_cleanup()
165 unsigned int i = dev->minor; in comedi_clear_board_dev()
168 lockdep_assert_held(&dev->mutex); in comedi_clear_board_dev()
193 unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; in comedi_subdevice_from_minor()
197 if (s && s->device != dev) in comedi_subdevice_from_minor()
218 unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; in comedi_dev_get_from_subdevice_minor()
222 dev = comedi_dev_get(s ? s->device : NULL); in comedi_dev_get_from_subdevice_minor()
228 * comedi_dev_get_from_minor() - Get COMEDI device by minor device number
253 lockdep_assert_held(&dev->mutex); in comedi_read_subdevice()
256 if (!s || (s->subdev_flags & SDF_CMD_READ)) in comedi_read_subdevice()
259 return dev->read_subdev; in comedi_read_subdevice()
267 lockdep_assert_held(&dev->mutex); in comedi_write_subdevice()
270 if (!s || (s->subdev_flags & SDF_CMD_WRITE)) in comedi_write_subdevice()
273 return dev->write_subdev; in comedi_write_subdevice()
278 struct comedi_file *cfp = file->private_data; in comedi_file_reset()
279 struct comedi_device *dev = cfp->dev; in comedi_file_reset()
283 read_s = dev->read_subdev; in comedi_file_reset()
284 write_s = dev->write_subdev; in comedi_file_reset()
287 if (!s || s->subdev_flags & SDF_CMD_READ) in comedi_file_reset()
289 if (!s || s->subdev_flags & SDF_CMD_WRITE) in comedi_file_reset()
292 cfp->last_attached = dev->attached; in comedi_file_reset()
293 cfp->last_detach_count = dev->detach_count; in comedi_file_reset()
294 WRITE_ONCE(cfp->read_subdev, read_s); in comedi_file_reset()
295 WRITE_ONCE(cfp->write_subdev, write_s); in comedi_file_reset()
300 struct comedi_file *cfp = file->private_data; in comedi_file_check()
301 struct comedi_device *dev = cfp->dev; in comedi_file_check()
303 if (cfp->last_attached != dev->attached || in comedi_file_check()
304 cfp->last_detach_count != dev->detach_count) in comedi_file_check()
310 struct comedi_file *cfp = file->private_data; in comedi_file_read_subdevice()
313 return READ_ONCE(cfp->read_subdev); in comedi_file_read_subdevice()
318 struct comedi_file *cfp = file->private_data; in comedi_file_write_subdevice()
321 return READ_ONCE(cfp->write_subdev); in comedi_file_write_subdevice()
328 struct comedi_async *async = s->async; in resize_async_buffer()
331 lockdep_assert_held(&dev->mutex); in resize_async_buffer()
333 if (new_size > async->max_bufsize) in resize_async_buffer()
334 return -EPERM; in resize_async_buffer()
336 if (s->busy) { in resize_async_buffer()
337 dev_dbg(dev->class_dev, in resize_async_buffer()
339 return -EBUSY; in resize_async_buffer()
342 dev_dbg(dev->class_dev, in resize_async_buffer()
344 return -EBUSY; in resize_async_buffer()
348 new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; in resize_async_buffer()
354 if (s->buf_change) { in resize_async_buffer()
355 retval = s->buf_change(dev, s); in resize_async_buffer()
360 dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n", in resize_async_buffer()
361 s->index, async->prealloc_bufsz); in resize_async_buffer()
370 unsigned int minor = MINOR(csdev->devt); in max_read_buffer_kb_show()
377 return -ENODEV; in max_read_buffer_kb_show()
379 mutex_lock(&dev->mutex); in max_read_buffer_kb_show()
381 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) in max_read_buffer_kb_show()
382 size = s->async->max_bufsize / 1024; in max_read_buffer_kb_show()
383 mutex_unlock(&dev->mutex); in max_read_buffer_kb_show()
393 unsigned int minor = MINOR(csdev->devt); in max_read_buffer_kb_store()
403 return -EINVAL; in max_read_buffer_kb_store()
408 return -ENODEV; in max_read_buffer_kb_store()
410 mutex_lock(&dev->mutex); in max_read_buffer_kb_store()
412 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) in max_read_buffer_kb_store()
413 s->async->max_bufsize = size; in max_read_buffer_kb_store()
415 err = -EINVAL; in max_read_buffer_kb_store()
416 mutex_unlock(&dev->mutex); in max_read_buffer_kb_store()
426 unsigned int minor = MINOR(csdev->devt); in read_buffer_kb_show()
433 return -ENODEV; in read_buffer_kb_show()
435 mutex_lock(&dev->mutex); in read_buffer_kb_show()
437 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) in read_buffer_kb_show()
438 size = s->async->prealloc_bufsz / 1024; in read_buffer_kb_show()
439 mutex_unlock(&dev->mutex); in read_buffer_kb_show()
449 unsigned int minor = MINOR(csdev->devt); in read_buffer_kb_store()
459 return -EINVAL; in read_buffer_kb_store()
464 return -ENODEV; in read_buffer_kb_store()
466 mutex_lock(&dev->mutex); in read_buffer_kb_store()
468 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) in read_buffer_kb_store()
471 err = -EINVAL; in read_buffer_kb_store()
472 mutex_unlock(&dev->mutex); in read_buffer_kb_store()
483 unsigned int minor = MINOR(csdev->devt); in max_write_buffer_kb_show()
490 return -ENODEV; in max_write_buffer_kb_show()
492 mutex_lock(&dev->mutex); in max_write_buffer_kb_show()
494 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) in max_write_buffer_kb_show()
495 size = s->async->max_bufsize / 1024; in max_write_buffer_kb_show()
496 mutex_unlock(&dev->mutex); in max_write_buffer_kb_show()
506 unsigned int minor = MINOR(csdev->devt); in max_write_buffer_kb_store()
516 return -EINVAL; in max_write_buffer_kb_store()
521 return -ENODEV; in max_write_buffer_kb_store()
523 mutex_lock(&dev->mutex); in max_write_buffer_kb_store()
525 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) in max_write_buffer_kb_store()
526 s->async->max_bufsize = size; in max_write_buffer_kb_store()
528 err = -EINVAL; in max_write_buffer_kb_store()
529 mutex_unlock(&dev->mutex); in max_write_buffer_kb_store()
539 unsigned int minor = MINOR(csdev->devt); in write_buffer_kb_show()
546 return -ENODEV; in write_buffer_kb_show()
548 mutex_lock(&dev->mutex); in write_buffer_kb_show()
550 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) in write_buffer_kb_show()
551 size = s->async->prealloc_bufsz / 1024; in write_buffer_kb_show()
552 mutex_unlock(&dev->mutex); in write_buffer_kb_show()
562 unsigned int minor = MINOR(csdev->devt); in write_buffer_kb_store()
572 return -EINVAL; in write_buffer_kb_store()
577 return -ENODEV; in write_buffer_kb_store()
579 mutex_lock(&dev->mutex); in write_buffer_kb_store()
581 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) in write_buffer_kb_store()
584 err = -EINVAL; in write_buffer_kb_store()
585 mutex_unlock(&dev->mutex); in write_buffer_kb_store()
610 if (dev->class_dev) { in comedi_free_board_dev()
612 MKDEV(COMEDI_MAJOR, dev->minor)); in comedi_free_board_dev()
621 s->runflags &= ~bits; in __comedi_clear_subdevice_runflags()
627 s->runflags |= bits; in __comedi_set_subdevice_runflags()
636 spin_lock_irqsave(&s->spin_lock, flags); in comedi_update_subdevice_runflags()
639 spin_unlock_irqrestore(&s->spin_lock, flags); in comedi_update_subdevice_runflags()
644 return s->runflags; in __comedi_get_subdevice_runflags()
652 spin_lock_irqsave(&s->spin_lock, flags); in comedi_get_subdevice_runflags()
654 spin_unlock_irqrestore(&s->spin_lock, flags); in comedi_get_subdevice_runflags()
669 * comedi_is_subdevice_running() - Check if async command running on subdevice
698 * comedi_set_spriv_auto_free() - Mark subdevice private data as freeable
702 * automatically freed when the COMEDI device is detached from the low-level
712 * comedi_alloc_spriv - Allocate memory for the subdevice private data
716 * Allocate memory for the subdevice private data and point @s->private
718 * is detached from the low-level driver.
720 * Return: A pointer to the allocated memory @s->private on success.
725 s->private = kzalloc(size, GFP_KERNEL); in comedi_alloc_spriv()
726 if (s->private) in comedi_alloc_spriv()
728 return s->private; in comedi_alloc_spriv()
738 struct comedi_async *async = s->async; in do_become_nonbusy()
740 lockdep_assert_held(&dev->mutex); in do_become_nonbusy()
744 async->inttrig = NULL; in do_become_nonbusy()
745 kfree(async->cmd.chanlist); in do_become_nonbusy()
746 async->cmd.chanlist = NULL; in do_become_nonbusy()
747 s->busy = NULL; in do_become_nonbusy()
748 wake_up_interruptible_all(&async->wait_head); in do_become_nonbusy()
750 dev_err(dev->class_dev, in do_become_nonbusy()
752 s->busy = NULL; in do_become_nonbusy()
760 lockdep_assert_held(&dev->mutex); in do_cancel()
761 if (comedi_is_subdevice_running(s) && s->cancel) in do_cancel()
762 ret = s->cancel(dev, s); in do_cancel()
774 lockdep_assert_held(&dev->mutex); in comedi_device_cancel_all()
775 if (!dev->attached) in comedi_device_cancel_all()
778 for (i = 0; i < dev->n_subdevices; i++) { in comedi_device_cancel_all()
779 s = &dev->subdevices[i]; in comedi_device_cancel_all()
780 if (s->async) in comedi_device_cancel_all()
790 lockdep_assert_held(&dev->mutex); in is_device_busy()
791 if (!dev->attached) in is_device_busy()
794 for (i = 0; i < dev->n_subdevices; i++) { in is_device_busy()
795 s = &dev->subdevices[i]; in is_device_busy()
796 if (s->busy) in is_device_busy()
798 if (s->async && comedi_buf_is_mmapped(s)) in is_device_busy()
823 lockdep_assert_held(&dev->mutex); in do_devconfig_ioctl()
825 return -EPERM; in do_devconfig_ioctl()
829 return -EBUSY; in do_devconfig_ioctl()
830 if (dev->attached) { in do_devconfig_ioctl()
831 struct module *driver_module = dev->driver->module; in do_devconfig_ioctl()
840 return -EFAULT; in do_devconfig_ioctl()
842 it.board_name[COMEDI_NAMELEN - 1] = 0; in do_devconfig_ioctl()
845 dev_warn(dev->class_dev, in do_devconfig_ioctl()
846 "comedi_config --init_data is deprecated\n"); in do_devconfig_ioctl()
847 return -EINVAL; in do_devconfig_ioctl()
850 if (dev->minor >= comedi_num_legacy_minors) in do_devconfig_ioctl()
851 /* don't re-use dynamically allocated comedi devices */ in do_devconfig_ioctl()
852 return -EBUSY; in do_devconfig_ioctl()
879 lockdep_assert_held(&dev->mutex); in do_bufconfig_ioctl()
881 return -EFAULT; in do_bufconfig_ioctl()
883 if (bc.subdevice >= dev->n_subdevices) in do_bufconfig_ioctl()
884 return -EINVAL; in do_bufconfig_ioctl()
886 s = &dev->subdevices[bc.subdevice]; in do_bufconfig_ioctl()
887 async = s->async; in do_bufconfig_ioctl()
890 dev_dbg(dev->class_dev, in do_bufconfig_ioctl()
899 return -EPERM; in do_bufconfig_ioctl()
901 async->max_bufsize = bc.maximum_size; in do_bufconfig_ioctl()
910 bc.size = async->prealloc_bufsz; in do_bufconfig_ioctl()
911 bc.maximum_size = async->max_bufsize; in do_bufconfig_ioctl()
915 return -EFAULT; in do_bufconfig_ioctl()
940 lockdep_assert_held(&dev->mutex); in do_devinfo_ioctl()
945 devinfo.n_subdevs = dev->n_subdevices; in do_devinfo_ioctl()
946 strscpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); in do_devinfo_ioctl()
947 strscpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); in do_devinfo_ioctl()
951 devinfo.read_subdevice = s->index; in do_devinfo_ioctl()
953 devinfo.read_subdevice = -1; in do_devinfo_ioctl()
957 devinfo.write_subdevice = s->index; in do_devinfo_ioctl()
959 devinfo.write_subdevice = -1; in do_devinfo_ioctl()
962 return -EFAULT; in do_devinfo_ioctl()
987 lockdep_assert_held(&dev->mutex); in do_subdinfo_ioctl()
988 tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL); in do_subdinfo_ioctl()
990 return -ENOMEM; in do_subdinfo_ioctl()
993 for (i = 0; i < dev->n_subdevices; i++) { in do_subdinfo_ioctl()
994 s = &dev->subdevices[i]; in do_subdinfo_ioctl()
997 us->type = s->type; in do_subdinfo_ioctl()
998 us->n_chan = s->n_chan; in do_subdinfo_ioctl()
999 us->subd_flags = s->subdev_flags; in do_subdinfo_ioctl()
1001 us->subd_flags |= SDF_RUNNING; in do_subdinfo_ioctl()
1003 us->timer_type = TIMER_nanosec; in do_subdinfo_ioctl()
1004 us->len_chanlist = s->len_chanlist; in do_subdinfo_ioctl()
1005 us->maxdata = s->maxdata; in do_subdinfo_ioctl()
1006 if (s->range_table) { in do_subdinfo_ioctl()
1007 us->range_type = in do_subdinfo_ioctl()
1008 (i << 24) | (0 << 16) | (s->range_table->length); in do_subdinfo_ioctl()
1010 us->range_type = 0; /* XXX */ in do_subdinfo_ioctl()
1013 if (s->busy) in do_subdinfo_ioctl()
1014 us->subd_flags |= SDF_BUSY; in do_subdinfo_ioctl()
1015 if (s->busy == file) in do_subdinfo_ioctl()
1016 us->subd_flags |= SDF_BUSY_OWNER; in do_subdinfo_ioctl()
1017 if (s->lock) in do_subdinfo_ioctl()
1018 us->subd_flags |= SDF_LOCKED; in do_subdinfo_ioctl()
1019 if (s->lock == file) in do_subdinfo_ioctl()
1020 us->subd_flags |= SDF_LOCK_OWNER; in do_subdinfo_ioctl()
1021 if (!s->maxdata && s->maxdata_list) in do_subdinfo_ioctl()
1022 us->subd_flags |= SDF_MAXDATA; in do_subdinfo_ioctl()
1023 if (s->range_table_list) in do_subdinfo_ioctl()
1024 us->subd_flags |= SDF_RANGETYPE; in do_subdinfo_ioctl()
1025 if (s->do_cmd) in do_subdinfo_ioctl()
1026 us->subd_flags |= SDF_CMD; in do_subdinfo_ioctl()
1028 if (s->insn_bits != &insn_inval) in do_subdinfo_ioctl()
1029 us->insn_bits_support = COMEDI_SUPPORTED; in do_subdinfo_ioctl()
1031 us->insn_bits_support = COMEDI_UNSUPPORTED; in do_subdinfo_ioctl()
1034 ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp)); in do_subdinfo_ioctl()
1038 return ret ? -EFAULT : 0; in do_subdinfo_ioctl()
1052 * array of maxdata values to chaninfo->maxdata_list if requested
1053 * array of range table lengths to chaninfo->range_table_list if requested
1060 lockdep_assert_held(&dev->mutex); in do_chaninfo_ioctl()
1062 if (it->subdev >= dev->n_subdevices) in do_chaninfo_ioctl()
1063 return -EINVAL; in do_chaninfo_ioctl()
1064 s = &dev->subdevices[it->subdev]; in do_chaninfo_ioctl()
1066 if (it->maxdata_list) { in do_chaninfo_ioctl()
1067 if (s->maxdata || !s->maxdata_list) in do_chaninfo_ioctl()
1068 return -EINVAL; in do_chaninfo_ioctl()
1069 if (copy_to_user(it->maxdata_list, s->maxdata_list, in do_chaninfo_ioctl()
1070 s->n_chan * sizeof(unsigned int))) in do_chaninfo_ioctl()
1071 return -EFAULT; in do_chaninfo_ioctl()
1074 if (it->flaglist) in do_chaninfo_ioctl()
1075 return -EINVAL; /* flaglist not supported */ in do_chaninfo_ioctl()
1077 if (it->rangelist) { in do_chaninfo_ioctl()
1080 if (!s->range_table_list) in do_chaninfo_ioctl()
1081 return -EINVAL; in do_chaninfo_ioctl()
1082 for (i = 0; i < s->n_chan; i++) { in do_chaninfo_ioctl()
1085 x = (dev->minor << 28) | (it->subdev << 24) | (i << 16) | in do_chaninfo_ioctl()
1086 (s->range_table_list[i]->length); in do_chaninfo_ioctl()
1087 if (put_user(x, it->rangelist + i)) in do_chaninfo_ioctl()
1088 return -EFAULT; in do_chaninfo_ioctl()
1118 lockdep_assert_held(&dev->mutex); in do_bufinfo_ioctl()
1120 return -EFAULT; in do_bufinfo_ioctl()
1122 if (bi.subdevice >= dev->n_subdevices) in do_bufinfo_ioctl()
1123 return -EINVAL; in do_bufinfo_ioctl()
1125 s = &dev->subdevices[bi.subdevice]; in do_bufinfo_ioctl()
1127 async = s->async; in do_bufinfo_ioctl()
1129 if (!async || s->busy != file) in do_bufinfo_ioctl()
1130 return -EINVAL; in do_bufinfo_ioctl()
1133 if (!(async->cmd.flags & CMDF_WRITE)) { in do_bufinfo_ioctl()
1142 * then become non-busy. in do_bufinfo_ioctl()
1150 retval = -EPIPE; in do_bufinfo_ioctl()
1159 retval = -EPIPE; in do_bufinfo_ioctl()
1168 bi.buf_write_count = async->buf_write_count; in do_bufinfo_ioctl()
1169 bi.buf_write_ptr = async->buf_write_ptr; in do_bufinfo_ioctl()
1170 bi.buf_read_count = async->buf_read_count; in do_bufinfo_ioctl()
1171 bi.buf_read_ptr = async->buf_read_ptr; in do_bufinfo_ioctl()
1180 return -EFAULT; in do_bufinfo_ioctl()
1188 if (insn->n < 1) in check_insn_config_length()
1189 return -EINVAL; in check_insn_config_length()
1196 if (insn->n == 1) in check_insn_config_length()
1213 if (insn->n == 2) in check_insn_config_length()
1226 if (insn->n == 3) in check_insn_config_length()
1232 if (insn->n == 5) in check_insn_config_length()
1236 if (insn->n == 6) in check_insn_config_length()
1240 if (insn->n >= 4) in check_insn_config_length()
1251 pr_warn("Assuming n=%i is correct\n", insn->n); in check_insn_config_length()
1254 return -EINVAL; in check_insn_config_length()
1260 if (insn->n < 1) in check_insn_device_config_length()
1261 return -EINVAL; in check_insn_device_config_length()
1267 if (insn->n == 3) in check_insn_device_config_length()
1276 if (insn->n >= 2) in check_insn_device_config_length()
1280 return -EINVAL; in check_insn_device_config_length()
1284 * get_valid_routes() - Calls low-level driver get_valid_routes function to
1299 * Return: -EINVAL if low-level driver does not allocate and return routes as
1304 lockdep_assert_held(&dev->mutex); in get_valid_routes()
1305 data[1] = dev->get_valid_routes(dev, data[1], data + 2); in get_valid_routes()
1316 lockdep_assert_held(&dev->mutex); in parse_insn()
1317 if (insn->insn & INSN_MASK_SPECIAL) { in parse_insn()
1318 /* a non-subdevice instruction */ in parse_insn()
1320 switch (insn->insn) { in parse_insn()
1325 if (insn->n != 2) { in parse_insn()
1326 ret = -EINVAL; in parse_insn()
1339 if (insn->n != 1 || data[0] >= 100000) { in parse_insn()
1340 ret = -EINVAL; in parse_insn()
1347 if (insn->n != 1) { in parse_insn()
1348 ret = -EINVAL; in parse_insn()
1351 if (insn->subdev >= dev->n_subdevices) { in parse_insn()
1352 dev_dbg(dev->class_dev, in parse_insn()
1354 insn->subdev); in parse_insn()
1355 ret = -EINVAL; in parse_insn()
1358 s = &dev->subdevices[insn->subdev]; in parse_insn()
1359 if (!s->async) { in parse_insn()
1360 dev_dbg(dev->class_dev, "no async\n"); in parse_insn()
1361 ret = -EINVAL; in parse_insn()
1364 if (!s->async->inttrig) { in parse_insn()
1365 dev_dbg(dev->class_dev, "no inttrig\n"); in parse_insn()
1366 ret = -EAGAIN; in parse_insn()
1369 ret = s->async->inttrig(dev, s, data[0]); in parse_insn()
1383 data[1] = (insn->n - 2) / 2; in parse_insn()
1389 ret = dev->insn_device_config(dev, insn, data); in parse_insn()
1392 dev_dbg(dev->class_dev, "invalid insn\n"); in parse_insn()
1393 ret = -EINVAL; in parse_insn()
1400 if (insn->subdev >= dev->n_subdevices) { in parse_insn()
1401 dev_dbg(dev->class_dev, "subdevice %d out of range\n", in parse_insn()
1402 insn->subdev); in parse_insn()
1403 ret = -EINVAL; in parse_insn()
1406 s = &dev->subdevices[insn->subdev]; in parse_insn()
1408 if (s->type == COMEDI_SUBD_UNUSED) { in parse_insn()
1409 dev_dbg(dev->class_dev, "%d not usable subdevice\n", in parse_insn()
1410 insn->subdev); in parse_insn()
1411 ret = -EIO; in parse_insn()
1416 if (s->lock && s->lock != file) { in parse_insn()
1417 dev_dbg(dev->class_dev, "device locked\n"); in parse_insn()
1418 ret = -EACCES; in parse_insn()
1422 ret = comedi_check_chanlist(s, 1, &insn->chanspec); in parse_insn()
1424 ret = -EINVAL; in parse_insn()
1425 dev_dbg(dev->class_dev, "bad chanspec\n"); in parse_insn()
1429 if (s->busy) { in parse_insn()
1430 ret = -EBUSY; in parse_insn()
1434 s->busy = parse_insn; in parse_insn()
1435 switch (insn->insn) { in parse_insn()
1437 ret = s->insn_read(dev, s, insn, data); in parse_insn()
1438 if (ret == -ETIMEDOUT) { in parse_insn()
1439 dev_dbg(dev->class_dev, in parse_insn()
1441 s->index); in parse_insn()
1445 maxdata = s->maxdata_list in parse_insn()
1446 ? s->maxdata_list[CR_CHAN(insn->chanspec)] in parse_insn()
1447 : s->maxdata; in parse_insn()
1448 for (i = 0; i < insn->n; ++i) { in parse_insn()
1450 ret = -EINVAL; in parse_insn()
1451 dev_dbg(dev->class_dev, in parse_insn()
1457 ret = s->insn_write(dev, s, insn, data); in parse_insn()
1458 if (ret == -ETIMEDOUT) { in parse_insn()
1459 dev_dbg(dev->class_dev, in parse_insn()
1461 s->index); in parse_insn()
1466 if (insn->n != 2) { in parse_insn()
1467 ret = -EINVAL; in parse_insn()
1471 * insn->chanspec. Fix this here if in parse_insn()
1477 if (s->n_chan <= 32) { in parse_insn()
1478 shift = CR_CHAN(insn->chanspec); in parse_insn()
1480 insn->chanspec = 0; in parse_insn()
1485 ret = s->insn_bits(dev, s, insn, data); in parse_insn()
1495 ret = s->insn_config(dev, s, insn, data); in parse_insn()
1498 ret = -EINVAL; in parse_insn()
1502 s->busy = NULL; in parse_insn()
1518 * array of comedi_insn structures from insnlist->insns pointer
1537 lockdep_assert_held(&dev->mutex); in do_insnlist_ioctl()
1542 dev_dbg(dev->class_dev, in do_insnlist_ioctl()
1544 ret = -EINVAL; in do_insnlist_ioctl()
1554 ret = -ENOMEM; in do_insnlist_ioctl()
1562 dev_dbg(dev->class_dev, in do_insnlist_ioctl()
1564 ret = -EFAULT; in do_insnlist_ioctl()
1574 dev_dbg(dev->class_dev, in do_insnlist_ioctl()
1576 ret = -EFAULT; in do_insnlist_ioctl()
1601 * data (for writes) from insn->data pointer
1604 * data (for reads) to insn->data pointer
1613 lockdep_assert_held(&dev->mutex); in do_insn_ioctl()
1615 n_data = max(n_data, insn->n); in do_insn_ioctl()
1618 if (insn->n > MAX_SAMPLES) { in do_insn_ioctl()
1619 insn->n = MAX_SAMPLES; in do_insn_ioctl()
1625 ret = -ENOMEM; in do_insn_ioctl()
1629 if (insn->insn & INSN_MASK_WRITE) { in do_insn_ioctl()
1631 insn->data, in do_insn_ioctl()
1632 insn->n * sizeof(unsigned int))) { in do_insn_ioctl()
1633 ret = -EFAULT; in do_insn_ioctl()
1640 if (insn->insn & INSN_MASK_READ) { in do_insn_ioctl()
1641 if (copy_to_user(insn->data, in do_insn_ioctl()
1643 insn->n * sizeof(unsigned int))) { in do_insn_ioctl()
1644 ret = -EFAULT; in do_insn_ioctl()
1648 ret = insn->n; in do_insn_ioctl()
1661 lockdep_assert_held(&dev->mutex); in __comedi_get_user_cmd()
1662 if (cmd->subdev >= dev->n_subdevices) { in __comedi_get_user_cmd()
1663 dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd->subdev); in __comedi_get_user_cmd()
1664 return -ENODEV; in __comedi_get_user_cmd()
1667 s = &dev->subdevices[cmd->subdev]; in __comedi_get_user_cmd()
1669 if (s->type == COMEDI_SUBD_UNUSED) { in __comedi_get_user_cmd()
1670 dev_dbg(dev->class_dev, "%d not valid subdevice\n", in __comedi_get_user_cmd()
1671 cmd->subdev); in __comedi_get_user_cmd()
1672 return -EIO; in __comedi_get_user_cmd()
1675 if (!s->do_cmd || !s->do_cmdtest || !s->async) { in __comedi_get_user_cmd()
1676 dev_dbg(dev->class_dev, in __comedi_get_user_cmd()
1678 cmd->subdev); in __comedi_get_user_cmd()
1679 return -EIO; in __comedi_get_user_cmd()
1683 if (cmd->chanlist_len > s->len_chanlist) { in __comedi_get_user_cmd()
1684 dev_dbg(dev->class_dev, "channel/gain list too long %d > %d\n", in __comedi_get_user_cmd()
1685 cmd->chanlist_len, s->len_chanlist); in __comedi_get_user_cmd()
1686 return -EINVAL; in __comedi_get_user_cmd()
1693 switch (s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) { in __comedi_get_user_cmd()
1695 cmd->flags &= ~CMDF_WRITE; in __comedi_get_user_cmd()
1698 cmd->flags |= CMDF_WRITE; in __comedi_get_user_cmd()
1715 lockdep_assert_held(&dev->mutex); in __comedi_get_user_chanlist()
1716 cmd->chanlist = NULL; in __comedi_get_user_chanlist()
1718 cmd->chanlist_len * sizeof(unsigned int)); in __comedi_get_user_chanlist()
1723 ret = comedi_check_chanlist(s, cmd->chanlist_len, chanlist); in __comedi_get_user_chanlist()
1729 cmd->chanlist = chanlist; in __comedi_get_user_chanlist()
1736 * asynchronous acquisition command set-up
1743 * channel/range list from cmd->chanlist pointer
1746 * possibly modified comedi_cmd structure (when -EAGAIN returned)
1756 lockdep_assert_held(&dev->mutex); in do_cmd_ioctl()
1764 user_chanlist = (unsigned int __user *)cmd->chanlist; in do_cmd_ioctl()
1766 s = &dev->subdevices[cmd->subdev]; in do_cmd_ioctl()
1767 async = s->async; in do_cmd_ioctl()
1770 if (s->lock && s->lock != file) { in do_cmd_ioctl()
1771 dev_dbg(dev->class_dev, "subdevice locked\n"); in do_cmd_ioctl()
1772 return -EACCES; in do_cmd_ioctl()
1776 if (s->busy) { in do_cmd_ioctl()
1777 dev_dbg(dev->class_dev, "subdevice busy\n"); in do_cmd_ioctl()
1778 return -EBUSY; in do_cmd_ioctl()
1782 if (cmd->chanlist_len < 1) { in do_cmd_ioctl()
1783 dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n", in do_cmd_ioctl()
1784 cmd->chanlist_len); in do_cmd_ioctl()
1785 return -EINVAL; in do_cmd_ioctl()
1788 async->cmd = *cmd; in do_cmd_ioctl()
1789 async->cmd.data = NULL; in do_cmd_ioctl()
1792 ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &async->cmd); in do_cmd_ioctl()
1796 ret = s->do_cmdtest(dev, s, &async->cmd); in do_cmd_ioctl()
1798 if (async->cmd.flags & CMDF_BOGUS || ret) { in do_cmd_ioctl()
1799 dev_dbg(dev->class_dev, "test returned %d\n", ret); in do_cmd_ioctl()
1800 *cmd = async->cmd; in do_cmd_ioctl()
1802 cmd->chanlist = (unsigned int __force *)user_chanlist; in do_cmd_ioctl()
1803 cmd->data = NULL; in do_cmd_ioctl()
1805 ret = -EAGAIN; in do_cmd_ioctl()
1809 if (!async->prealloc_bufsz) { in do_cmd_ioctl()
1810 ret = -ENOMEM; in do_cmd_ioctl()
1811 dev_dbg(dev->class_dev, "no buffer (?)\n"); in do_cmd_ioctl()
1817 async->cb_mask = COMEDI_CB_BLOCK | COMEDI_CB_CANCEL_MASK; in do_cmd_ioctl()
1818 if (async->cmd.flags & CMDF_WAKE_EOS) in do_cmd_ioctl()
1819 async->cb_mask |= COMEDI_CB_EOS; in do_cmd_ioctl()
1825 * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid in do_cmd_ioctl()
1828 s->busy = file; in do_cmd_ioctl()
1829 ret = s->do_cmd(dev, s); in do_cmd_ioctl()
1848 * channel/range list from cmd->chanlist pointer
1860 lockdep_assert_held(&dev->mutex); in do_cmdtest_ioctl()
1868 user_chanlist = (unsigned int __user *)cmd->chanlist; in do_cmdtest_ioctl()
1870 s = &dev->subdevices[cmd->subdev]; in do_cmdtest_ioctl()
1880 ret = s->do_cmdtest(dev, s, cmd); in do_cmdtest_ioctl()
1882 kfree(cmd->chanlist); /* free kernel copy of user chanlist */ in do_cmdtest_ioctl()
1885 cmd->chanlist = (unsigned int __force *)user_chanlist; in do_cmdtest_ioctl()
1911 lockdep_assert_held(&dev->mutex); in do_lock_ioctl()
1912 if (arg >= dev->n_subdevices) in do_lock_ioctl()
1913 return -EINVAL; in do_lock_ioctl()
1914 s = &dev->subdevices[arg]; in do_lock_ioctl()
1916 spin_lock_irqsave(&s->spin_lock, flags); in do_lock_ioctl()
1917 if (s->busy || s->lock) in do_lock_ioctl()
1918 ret = -EBUSY; in do_lock_ioctl()
1920 s->lock = file; in do_lock_ioctl()
1921 spin_unlock_irqrestore(&s->spin_lock, flags); in do_lock_ioctl()
1944 lockdep_assert_held(&dev->mutex); in do_unlock_ioctl()
1945 if (arg >= dev->n_subdevices) in do_unlock_ioctl()
1946 return -EINVAL; in do_unlock_ioctl()
1947 s = &dev->subdevices[arg]; in do_unlock_ioctl()
1949 if (s->busy) in do_unlock_ioctl()
1950 return -EBUSY; in do_unlock_ioctl()
1952 if (s->lock && s->lock != file) in do_unlock_ioctl()
1953 return -EACCES; in do_unlock_ioctl()
1955 if (s->lock == file) in do_unlock_ioctl()
1956 s->lock = NULL; in do_unlock_ioctl()
1979 lockdep_assert_held(&dev->mutex); in do_cancel_ioctl()
1980 if (arg >= dev->n_subdevices) in do_cancel_ioctl()
1981 return -EINVAL; in do_cancel_ioctl()
1982 s = &dev->subdevices[arg]; in do_cancel_ioctl()
1983 if (!s->async) in do_cancel_ioctl()
1984 return -EINVAL; in do_cancel_ioctl()
1986 if (!s->busy) in do_cancel_ioctl()
1989 if (s->busy != file) in do_cancel_ioctl()
1990 return -EBUSY; in do_cancel_ioctl()
2013 lockdep_assert_held(&dev->mutex); in do_poll_ioctl()
2014 if (arg >= dev->n_subdevices) in do_poll_ioctl()
2015 return -EINVAL; in do_poll_ioctl()
2016 s = &dev->subdevices[arg]; in do_poll_ioctl()
2018 if (!s->busy) in do_poll_ioctl()
2021 if (s->busy != file) in do_poll_ioctl()
2022 return -EBUSY; in do_poll_ioctl()
2024 if (s->poll) in do_poll_ioctl()
2025 return s->poll(dev, s); in do_poll_ioctl()
2027 return -EINVAL; in do_poll_ioctl()
2032 * sets the current "read" subdevice on a per-file basis
2046 struct comedi_file *cfp = file->private_data; in do_setrsubd_ioctl()
2049 lockdep_assert_held(&dev->mutex); in do_setrsubd_ioctl()
2050 if (arg >= dev->n_subdevices) in do_setrsubd_ioctl()
2051 return -EINVAL; in do_setrsubd_ioctl()
2053 s_new = &dev->subdevices[arg]; in do_setrsubd_ioctl()
2058 if (!(s_new->subdev_flags & SDF_CMD_READ)) in do_setrsubd_ioctl()
2059 return -EINVAL; in do_setrsubd_ioctl()
2065 if (s_old && s_old->busy == file && s_old->async && in do_setrsubd_ioctl()
2066 !(s_old->async->cmd.flags & CMDF_WRITE)) in do_setrsubd_ioctl()
2067 return -EBUSY; in do_setrsubd_ioctl()
2069 WRITE_ONCE(cfp->read_subdev, s_new); in do_setrsubd_ioctl()
2075 * sets the current "write" subdevice on a per-file basis
2089 struct comedi_file *cfp = file->private_data; in do_setwsubd_ioctl()
2092 lockdep_assert_held(&dev->mutex); in do_setwsubd_ioctl()
2093 if (arg >= dev->n_subdevices) in do_setwsubd_ioctl()
2094 return -EINVAL; in do_setwsubd_ioctl()
2096 s_new = &dev->subdevices[arg]; in do_setwsubd_ioctl()
2101 if (!(s_new->subdev_flags & SDF_CMD_WRITE)) in do_setwsubd_ioctl()
2102 return -EINVAL; in do_setwsubd_ioctl()
2108 if (s_old && s_old->busy == file && s_old->async && in do_setwsubd_ioctl()
2109 (s_old->async->cmd.flags & CMDF_WRITE)) in do_setwsubd_ioctl()
2110 return -EBUSY; in do_setwsubd_ioctl()
2112 WRITE_ONCE(cfp->write_subdev, s_new); in do_setwsubd_ioctl()
2120 struct comedi_file *cfp = file->private_data; in comedi_unlocked_ioctl()
2121 struct comedi_device *dev = cfp->dev; in comedi_unlocked_ioctl()
2124 mutex_lock(&dev->mutex); in comedi_unlocked_ioctl()
2127 * Device config is special, because it must work on in comedi_unlocked_ioctl()
2132 /* Device config not appropriate on non-board minors. */ in comedi_unlocked_ioctl()
2133 rc = -ENOTTY; in comedi_unlocked_ioctl()
2140 dev->minor >= comedi_num_legacy_minors) { in comedi_unlocked_ioctl()
2146 mutex_unlock(&dev->mutex); in comedi_unlocked_ioctl()
2155 if (!dev->attached) { in comedi_unlocked_ioctl()
2156 dev_dbg(dev->class_dev, "no driver attached\n"); in comedi_unlocked_ioctl()
2157 rc = -ENODEV; in comedi_unlocked_ioctl()
2179 rc = -EFAULT; in comedi_unlocked_ioctl()
2188 rc = -EFAULT; in comedi_unlocked_ioctl()
2212 rc = -EFAULT; in comedi_unlocked_ioctl()
2217 rc = -EFAULT; in comedi_unlocked_ioctl()
2225 rc = -EFAULT; in comedi_unlocked_ioctl()
2230 rc = -EFAULT; in comedi_unlocked_ioctl()
2239 rc = -EFAULT; in comedi_unlocked_ioctl()
2244 rc = -ENOMEM; in comedi_unlocked_ioctl()
2249 rc = -EFAULT; in comedi_unlocked_ioctl()
2261 rc = -EFAULT; in comedi_unlocked_ioctl()
2276 rc = -ENOTTY; in comedi_unlocked_ioctl()
2281 mutex_unlock(&dev->mutex); in comedi_unlocked_ioctl()
2287 struct comedi_buf_map *bm; in comedi_vm_open() local
2289 bm = area->vm_private_data; in comedi_vm_open()
2290 comedi_buf_map_get(bm); in comedi_vm_open()
2295 struct comedi_buf_map *bm; in comedi_vm_close() local
2297 bm = area->vm_private_data; in comedi_vm_close()
2298 comedi_buf_map_put(bm); in comedi_vm_close()
2304 struct comedi_buf_map *bm = vma->vm_private_data; in comedi_vm_access() local
2306 addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT); in comedi_vm_access()
2309 return -EINVAL; in comedi_vm_access()
2310 if (len > vma->vm_end - addr) in comedi_vm_access()
2311 len = vma->vm_end - addr; in comedi_vm_access()
2312 return comedi_buf_map_access(bm, offset, buf, len, write); in comedi_vm_access()
2323 struct comedi_file *cfp = file->private_data; in comedi_mmap()
2324 struct comedi_device *dev = cfp->dev; in comedi_mmap()
2327 struct comedi_buf_map *bm = NULL; in comedi_mmap() local
2329 unsigned long start = vma->vm_start; in comedi_mmap()
2336 * 'trylock' avoids circular dependency with current->mm->mmap_lock in comedi_mmap()
2337 * and down-reading &dev->attach_lock should normally succeed without in comedi_mmap()
2341 if (!down_read_trylock(&dev->attach_lock)) in comedi_mmap()
2342 return -EAGAIN; in comedi_mmap()
2344 if (!dev->attached) { in comedi_mmap()
2345 dev_dbg(dev->class_dev, "no driver attached\n"); in comedi_mmap()
2346 retval = -ENODEV; in comedi_mmap()
2350 if (vma->vm_flags & VM_WRITE) in comedi_mmap()
2355 retval = -EINVAL; in comedi_mmap()
2359 async = s->async; in comedi_mmap()
2361 retval = -EINVAL; in comedi_mmap()
2365 if (vma->vm_pgoff != 0) { in comedi_mmap()
2366 dev_dbg(dev->class_dev, "mmap() offset must be 0.\n"); in comedi_mmap()
2367 retval = -EINVAL; in comedi_mmap()
2371 size = vma->vm_end - vma->vm_start; in comedi_mmap()
2372 if (size > async->prealloc_bufsz) { in comedi_mmap()
2373 retval = -EFAULT; in comedi_mmap()
2377 retval = -EFAULT; in comedi_mmap()
2384 bm = comedi_buf_map_from_subdev_get(s); in comedi_mmap()
2385 if (!bm || n_pages > bm->n_pages) { in comedi_mmap()
2386 retval = -EINVAL; in comedi_mmap()
2389 if (bm->dma_dir != DMA_NONE) { in comedi_mmap()
2394 buf = &bm->page_list[0]; in comedi_mmap()
2395 retval = dma_mmap_coherent(bm->dma_hw_dev, vma, buf->virt_addr, in comedi_mmap()
2396 buf->dma_addr, n_pages * PAGE_SIZE); in comedi_mmap()
2401 buf = &bm->page_list[i]; in comedi_mmap()
2402 pfn = page_to_pfn(virt_to_page(buf->virt_addr)); in comedi_mmap()
2420 zap_vma_ptes(vma, vma->vm_start, size); in comedi_mmap()
2425 vma->vm_ops = &comedi_vm_ops; in comedi_mmap()
2426 vma->vm_private_data = bm; in comedi_mmap()
2428 vma->vm_ops->open(vma); in comedi_mmap()
2432 up_read(&dev->attach_lock); in comedi_mmap()
2433 comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */ in comedi_mmap()
2440 struct comedi_file *cfp = file->private_data; in comedi_poll()
2441 struct comedi_device *dev = cfp->dev; in comedi_poll()
2444 down_read(&dev->attach_lock); in comedi_poll()
2446 if (!dev->attached) { in comedi_poll()
2447 dev_dbg(dev->class_dev, "no driver attached\n"); in comedi_poll()
2453 if (s && s->async) { in comedi_poll()
2454 poll_wait(file, &s->async->wait_head, wait); in comedi_poll()
2455 if (s->busy != file || !comedi_is_subdevice_running(s) || in comedi_poll()
2456 (s->async->cmd.flags & CMDF_WRITE) || in comedi_poll()
2462 if (s && s->async) { in comedi_poll()
2466 poll_wait(file, &s->async->wait_head, wait); in comedi_poll()
2467 if (s->busy != file || !comedi_is_subdevice_running(s) || in comedi_poll()
2468 !(s->async->cmd.flags & CMDF_WRITE) || in comedi_poll()
2474 up_read(&dev->attach_lock); in comedi_poll()
2487 struct comedi_file *cfp = file->private_data; in comedi_write()
2488 struct comedi_device *dev = cfp->dev; in comedi_write()
2494 down_read(&dev->attach_lock); in comedi_write()
2496 old_detach_count = dev->detach_count; in comedi_write()
2498 if (!dev->attached) { in comedi_write()
2499 dev_dbg(dev->class_dev, "no driver attached\n"); in comedi_write()
2500 retval = -ENODEV; in comedi_write()
2505 if (!s || !s->async) { in comedi_write()
2506 retval = -EIO; in comedi_write()
2510 async = s->async; in comedi_write()
2511 if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) { in comedi_write()
2512 retval = -EINVAL; in comedi_write()
2516 add_wait_queue(&async->wait_head, &wait); in comedi_write()
2526 retval = -EPIPE; in comedi_write()
2535 comedi_buf_write_alloc(s, async->prealloc_bufsz); in comedi_write()
2540 if (file->f_flags & O_NONBLOCK) { in comedi_write()
2541 retval = -EAGAIN; in comedi_write()
2546 retval = -ERESTARTSYS; in comedi_write()
2549 if (s->busy != file || in comedi_write()
2550 !(async->cmd.flags & CMDF_WRITE)) { in comedi_write()
2551 retval = -EINVAL; in comedi_write()
2558 wp = async->buf_write_ptr; in comedi_write()
2559 n1 = min(n, async->prealloc_bufsz - wp); in comedi_write()
2560 n2 = n - n1; in comedi_write()
2561 m = copy_from_user(async->prealloc_buf + wp, buf, n1); in comedi_write()
2565 m = copy_from_user(async->prealloc_buf, buf + n1, n2); in comedi_write()
2567 n -= m; in comedi_write()
2568 retval = -EFAULT; in comedi_write()
2573 nbytes -= n; in comedi_write()
2577 remove_wait_queue(&async->wait_head, &wait); in comedi_write()
2583 * To avoid deadlock, cannot acquire dev->mutex in comedi_write()
2584 * while dev->attach_lock is held. in comedi_write()
2586 up_read(&dev->attach_lock); in comedi_write()
2588 mutex_lock(&dev->mutex); in comedi_write()
2591 * Checking dev->detach_count is unchanged ought to be in comedi_write()
2597 * become non-busy in case it changed behind our back. in comedi_write()
2600 if (dev->attached && old_detach_count == dev->detach_count && in comedi_write()
2601 s == new_s && new_s->async == async && s->busy == file && in comedi_write()
2602 (async->cmd.flags & CMDF_WRITE) && in comedi_write()
2605 mutex_unlock(&dev->mutex); in comedi_write()
2609 up_read(&dev->attach_lock); in comedi_write()
2623 struct comedi_file *cfp = file->private_data; in comedi_read()
2624 struct comedi_device *dev = cfp->dev; in comedi_read()
2630 down_read(&dev->attach_lock); in comedi_read()
2632 old_detach_count = dev->detach_count; in comedi_read()
2634 if (!dev->attached) { in comedi_read()
2635 dev_dbg(dev->class_dev, "no driver attached\n"); in comedi_read()
2636 retval = -ENODEV; in comedi_read()
2641 if (!s || !s->async) { in comedi_read()
2642 retval = -EIO; in comedi_read()
2646 async = s->async; in comedi_read()
2647 if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) { in comedi_read()
2648 retval = -EINVAL; in comedi_read()
2652 add_wait_queue(&async->wait_head, &wait); in comedi_read()
2667 retval = -EPIPE; in comedi_read()
2674 if (file->f_flags & O_NONBLOCK) { in comedi_read()
2675 retval = -EAGAIN; in comedi_read()
2680 retval = -ERESTARTSYS; in comedi_read()
2683 if (s->busy != file || in comedi_read()
2684 (async->cmd.flags & CMDF_WRITE)) { in comedi_read()
2685 retval = -EINVAL; in comedi_read()
2692 rp = async->buf_read_ptr; in comedi_read()
2693 n1 = min(n, async->prealloc_bufsz - rp); in comedi_read()
2694 n2 = n - n1; in comedi_read()
2695 m = copy_to_user(buf, async->prealloc_buf + rp, n1); in comedi_read()
2699 m = copy_to_user(buf + n1, async->prealloc_buf, n2); in comedi_read()
2701 n -= m; in comedi_read()
2702 retval = -EFAULT; in comedi_read()
2709 nbytes -= n; in comedi_read()
2713 remove_wait_queue(&async->wait_head, &wait); in comedi_read()
2719 * To avoid deadlock, cannot acquire dev->mutex in comedi_read()
2720 * while dev->attach_lock is held. in comedi_read()
2722 up_read(&dev->attach_lock); in comedi_read()
2724 mutex_lock(&dev->mutex); in comedi_read()
2727 * Checking dev->detach_count is unchanged ought to be in comedi_read()
2733 * become non-busy in case it changed behind our back. in comedi_read()
2736 if (dev->attached && old_detach_count == dev->detach_count && in comedi_read()
2737 s == new_s && new_s->async == async && s->busy == file && in comedi_read()
2738 !(async->cmd.flags & CMDF_WRITE) && in comedi_read()
2742 mutex_unlock(&dev->mutex); in comedi_read()
2746 up_read(&dev->attach_lock); in comedi_read()
2760 return -ENODEV; in comedi_open()
2766 return -ENOMEM; in comedi_open()
2769 cfp->dev = dev; in comedi_open()
2771 mutex_lock(&dev->mutex); in comedi_open()
2772 if (!dev->attached && !capable(CAP_SYS_ADMIN)) { in comedi_open()
2773 dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n"); in comedi_open()
2774 rc = -ENODEV; in comedi_open()
2777 if (dev->attached && dev->use_count == 0) { in comedi_open()
2778 if (!try_module_get(dev->driver->module)) { in comedi_open()
2779 rc = -ENXIO; in comedi_open()
2782 if (dev->open) { in comedi_open()
2783 rc = dev->open(dev); in comedi_open()
2785 module_put(dev->driver->module); in comedi_open()
2791 dev->use_count++; in comedi_open()
2792 file->private_data = cfp; in comedi_open()
2797 mutex_unlock(&dev->mutex); in comedi_open()
2807 struct comedi_file *cfp = file->private_data; in comedi_fasync()
2808 struct comedi_device *dev = cfp->dev; in comedi_fasync()
2810 return fasync_helper(fd, file, on, &dev->async_queue); in comedi_fasync()
2815 struct comedi_file *cfp = file->private_data; in comedi_close()
2816 struct comedi_device *dev = cfp->dev; in comedi_close()
2820 mutex_lock(&dev->mutex); in comedi_close()
2822 if (dev->subdevices) { in comedi_close()
2823 for (i = 0; i < dev->n_subdevices; i++) { in comedi_close()
2824 s = &dev->subdevices[i]; in comedi_close()
2826 if (s->busy == file) in comedi_close()
2828 if (s->lock == file) in comedi_close()
2829 s->lock = NULL; in comedi_close()
2832 if (dev->attached && dev->use_count == 1) { in comedi_close()
2833 if (dev->close) in comedi_close()
2834 dev->close(dev); in comedi_close()
2835 module_put(dev->driver->module); in comedi_close()
2838 dev->use_count--; in comedi_close()
2840 mutex_unlock(&dev->mutex); in comedi_close()
2866 compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */
2867 compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */
2868 compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
2874 compat_uptr_t range_ptr; /* 32-bit 'void *' */
2890 compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
2892 compat_uptr_t data; /* 32-bit 'short *' */
2899 compat_uptr_t data; /* 32-bit 'unsigned int *' */
2907 compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */
2910 /* Handle 32-bit COMEDI_CHANINFO ioctl. */
2913 struct comedi_file *cfp = file->private_data; in compat_chaninfo()
2914 struct comedi_device *dev = cfp->dev; in compat_chaninfo()
2920 return -EFAULT; in compat_chaninfo()
2928 mutex_lock(&dev->mutex); in compat_chaninfo()
2930 mutex_unlock(&dev->mutex); in compat_chaninfo()
2934 /* Handle 32-bit COMEDI_RANGEINFO ioctl. */
2937 struct comedi_file *cfp = file->private_data; in compat_rangeinfo()
2938 struct comedi_device *dev = cfp->dev; in compat_rangeinfo()
2944 return -EFAULT; in compat_rangeinfo()
2949 mutex_lock(&dev->mutex); in compat_rangeinfo()
2951 mutex_unlock(&dev->mutex); in compat_rangeinfo()
2955 /* Copy 32-bit cmd structure to native cmd structure. */
2962 return -EFAULT; in get_compat_cmd()
2964 cmd->subdev = v32.subdev; in get_compat_cmd()
2965 cmd->flags = v32.flags; in get_compat_cmd()
2966 cmd->start_src = v32.start_src; in get_compat_cmd()
2967 cmd->start_arg = v32.start_arg; in get_compat_cmd()
2968 cmd->scan_begin_src = v32.scan_begin_src; in get_compat_cmd()
2969 cmd->scan_begin_arg = v32.scan_begin_arg; in get_compat_cmd()
2970 cmd->convert_src = v32.convert_src; in get_compat_cmd()
2971 cmd->convert_arg = v32.convert_arg; in get_compat_cmd()
2972 cmd->scan_end_src = v32.scan_end_src; in get_compat_cmd()
2973 cmd->scan_end_arg = v32.scan_end_arg; in get_compat_cmd()
2974 cmd->stop_src = v32.stop_src; in get_compat_cmd()
2975 cmd->stop_arg = v32.stop_arg; in get_compat_cmd()
2976 cmd->chanlist = (unsigned int __force *)compat_ptr(v32.chanlist); in get_compat_cmd()
2977 cmd->chanlist_len = v32.chanlist_len; in get_compat_cmd()
2978 cmd->data = compat_ptr(v32.data); in get_compat_cmd()
2979 cmd->data_len = v32.data_len; in get_compat_cmd()
2983 /* Copy native cmd structure to 32-bit cmd structure. */
2990 v32.subdev = cmd->subdev; in put_compat_cmd()
2991 v32.flags = cmd->flags; in put_compat_cmd()
2992 v32.start_src = cmd->start_src; in put_compat_cmd()
2993 v32.start_arg = cmd->start_arg; in put_compat_cmd()
2994 v32.scan_begin_src = cmd->scan_begin_src; in put_compat_cmd()
2995 v32.scan_begin_arg = cmd->scan_begin_arg; in put_compat_cmd()
2996 v32.convert_src = cmd->convert_src; in put_compat_cmd()
2997 v32.convert_arg = cmd->convert_arg; in put_compat_cmd()
2998 v32.scan_end_src = cmd->scan_end_src; in put_compat_cmd()
2999 v32.scan_end_arg = cmd->scan_end_arg; in put_compat_cmd()
3000 v32.stop_src = cmd->stop_src; in put_compat_cmd()
3001 v32.stop_arg = cmd->stop_arg; in put_compat_cmd()
3003 v32.chanlist = ptr_to_compat((unsigned int __user *)cmd->chanlist); in put_compat_cmd()
3004 v32.chanlist_len = cmd->chanlist_len; in put_compat_cmd()
3005 v32.data = ptr_to_compat(cmd->data); in put_compat_cmd()
3006 v32.data_len = cmd->data_len; in put_compat_cmd()
3008 return -EFAULT; in put_compat_cmd()
3012 /* Handle 32-bit COMEDI_CMD ioctl. */
3015 struct comedi_file *cfp = file->private_data; in compat_cmd()
3016 struct comedi_device *dev = cfp->dev; in compat_cmd()
3025 mutex_lock(&dev->mutex); in compat_cmd()
3027 mutex_unlock(&dev->mutex); in compat_cmd()
3037 /* Handle 32-bit COMEDI_CMDTEST ioctl. */
3040 struct comedi_file *cfp = file->private_data; in compat_cmdtest()
3041 struct comedi_device *dev = cfp->dev; in compat_cmdtest()
3050 mutex_lock(&dev->mutex); in compat_cmdtest()
3052 mutex_unlock(&dev->mutex); in compat_cmdtest()
3061 /* Copy 32-bit insn structure to native insn structure. */
3069 return -EFAULT; in get_compat_insn()
3071 insn->insn = v32.insn; in get_compat_insn()
3072 insn->n = v32.n; in get_compat_insn()
3073 insn->data = compat_ptr(v32.data); in get_compat_insn()
3074 insn->subdev = v32.subdev; in get_compat_insn()
3075 insn->chanspec = v32.chanspec; in get_compat_insn()
3079 /* Handle 32-bit COMEDI_INSNLIST ioctl. */
3082 struct comedi_file *cfp = file->private_data; in compat_insnlist()
3083 struct comedi_device *dev = cfp->dev; in compat_insnlist()
3091 return -EFAULT; in compat_insnlist()
3095 return -ENOMEM; in compat_insnlist()
3107 mutex_lock(&dev->mutex); in compat_insnlist()
3109 mutex_unlock(&dev->mutex); in compat_insnlist()
3114 /* Handle 32-bit COMEDI_INSN ioctl. */
3117 struct comedi_file *cfp = file->private_data; in compat_insn()
3118 struct comedi_device *dev = cfp->dev; in compat_insn()
3126 mutex_lock(&dev->mutex); in compat_insn()
3128 mutex_unlock(&dev->mutex); in compat_insn()
3135 * Returns -ENOIOCTLCMD for unrecognised ioctl codes.
3179 rc = -ENOIOCTLCMD; in comedi_compat_ioctl()
3203 * comedi_event() - Handle events for asynchronous COMEDI command
3206 * Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
3215 struct comedi_async *async = s->async; in comedi_event()
3220 spin_lock_irqsave(&s->spin_lock, flags); in comedi_event()
3222 events = async->events; in comedi_event()
3223 async->events = 0; in comedi_event()
3225 spin_unlock_irqrestore(&s->spin_lock, flags); in comedi_event()
3239 if (async->cb_mask & events) { in comedi_event()
3240 wake_up_interruptible(&async->wait_head); in comedi_event()
3241 si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN; in comedi_event()
3244 spin_unlock_irqrestore(&s->spin_lock, flags); in comedi_event()
3247 kill_fasync(&dev->async_queue, SIGIO, si_code); in comedi_event()
3251 /* Note: the ->mutex is pre-locked on successful return */
3260 return ERR_PTR(-ENOMEM); in comedi_alloc_board_minor()
3263 mutex_lock(&dev->mutex); in comedi_alloc_board_minor()
3274 mutex_unlock(&dev->mutex); in comedi_alloc_board_minor()
3279 return ERR_PTR(-EBUSY); in comedi_alloc_board_minor()
3281 dev->minor = i; in comedi_alloc_board_minor()
3285 dev->class_dev = get_device(csdev); in comedi_alloc_board_minor()
3287 /* Note: dev->mutex needs to be unlocked by the caller. */ in comedi_alloc_board_minor()
3300 if (dev && dev->hw_dev == hardware_device) { in comedi_release_hardware_device()
3312 struct comedi_device *dev = s->device; in comedi_alloc_subdevice_minor()
3325 dev_err(dev->class_dev, in comedi_alloc_subdevice_minor()
3327 return -EBUSY; in comedi_alloc_subdevice_minor()
3330 s->minor = i; in comedi_alloc_subdevice_minor()
3331 csdev = device_create(&comedi_class, dev->class_dev, in comedi_alloc_subdevice_minor()
3333 dev->minor, s->index); in comedi_alloc_subdevice_minor()
3335 s->class_dev = csdev; in comedi_alloc_subdevice_minor()
3346 if (s->minor < COMEDI_NUM_BOARD_MINORS || in comedi_free_subdevice_minor()
3347 s->minor >= COMEDI_NUM_MINORS) in comedi_free_subdevice_minor()
3350 i = s->minor - COMEDI_NUM_BOARD_MINORS; in comedi_free_subdevice_minor()
3355 if (s->class_dev) { in comedi_free_subdevice_minor()
3356 device_destroy(&comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); in comedi_free_subdevice_minor()
3357 s->class_dev = NULL; in comedi_free_subdevice_minor()
3377 pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n"); in comedi_init()
3382 return -EINVAL; in comedi_init()
3418 lockdep_assert_held(&dev->mutex); in comedi_init()
3419 mutex_unlock(&dev->mutex); in comedi_init()