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