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