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