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