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