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