1
2
3
4
5
6
7#include <linux/cdev.h>
8#include <linux/fs.h>
9#include <linux/device.h>
10#include <linux/slab.h>
11#include <linux/compat.h>
12
13#include "vchiq_core.h"
14#include "vchiq_ioctl.h"
15#include "vchiq_arm.h"
16#include "vchiq_debugfs.h"
17
18#define DEVICE_NAME "vchiq"
19
20static struct cdev vchiq_cdev;
21static dev_t vchiq_devid;
22static struct class *vchiq_class;
23
24static const char *const ioctl_names[] = {
25 "CONNECT",
26 "SHUTDOWN",
27 "CREATE_SERVICE",
28 "REMOVE_SERVICE",
29 "QUEUE_MESSAGE",
30 "QUEUE_BULK_TRANSMIT",
31 "QUEUE_BULK_RECEIVE",
32 "AWAIT_COMPLETION",
33 "DEQUEUE_MESSAGE",
34 "GET_CLIENT_ID",
35 "GET_CONFIG",
36 "CLOSE_SERVICE",
37 "USE_SERVICE",
38 "RELEASE_SERVICE",
39 "SET_SERVICE_OPTION",
40 "DUMP_PHYS_MEM",
41 "LIB_VERSION",
42 "CLOSE_DELIVERED"
43};
44
45static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1));
46
47static void
48user_service_free(void *userdata)
49{
50 kfree(userdata);
51}
52
53static void close_delivered(struct user_service *user_service)
54{
55 vchiq_log_info(vchiq_arm_log_level,
56 "%s(handle=%x)",
57 __func__, user_service->service->handle);
58
59 if (user_service->close_pending) {
60
61 vchiq_service_put(user_service->service);
62
63
64 complete(&user_service->close_event);
65
66 user_service->close_pending = 0;
67 }
68}
69
70struct vchiq_io_copy_callback_context {
71 struct vchiq_element *element;
72 size_t element_offset;
73 unsigned long elements_to_go;
74};
75
76static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest,
77 size_t offset, size_t maxsize)
78{
79 struct vchiq_io_copy_callback_context *cc = context;
80 size_t total_bytes_copied = 0;
81 size_t bytes_this_round;
82
83 while (total_bytes_copied < maxsize) {
84 if (!cc->elements_to_go)
85 return total_bytes_copied;
86
87 if (!cc->element->size) {
88 cc->elements_to_go--;
89 cc->element++;
90 cc->element_offset = 0;
91 continue;
92 }
93
94 bytes_this_round = min(cc->element->size - cc->element_offset,
95 maxsize - total_bytes_copied);
96
97 if (copy_from_user(dest + total_bytes_copied,
98 cc->element->data + cc->element_offset,
99 bytes_this_round))
100 return -EFAULT;
101
102 cc->element_offset += bytes_this_round;
103 total_bytes_copied += bytes_this_round;
104
105 if (cc->element_offset == cc->element->size) {
106 cc->elements_to_go--;
107 cc->element++;
108 cc->element_offset = 0;
109 }
110 }
111
112 return maxsize;
113}
114
115static int
116vchiq_ioc_queue_message(unsigned int handle, struct vchiq_element *elements,
117 unsigned long count)
118{
119 struct vchiq_io_copy_callback_context context;
120 enum vchiq_status status = VCHIQ_SUCCESS;
121 unsigned long i;
122 size_t total_size = 0;
123
124 context.element = elements;
125 context.element_offset = 0;
126 context.elements_to_go = count;
127
128 for (i = 0; i < count; i++) {
129 if (!elements[i].data && elements[i].size != 0)
130 return -EFAULT;
131
132 total_size += elements[i].size;
133 }
134
135 status = vchiq_queue_message(handle, vchiq_ioc_copy_element_data,
136 &context, total_size);
137
138 if (status == VCHIQ_ERROR)
139 return -EIO;
140 else if (status == VCHIQ_RETRY)
141 return -EINTR;
142 return 0;
143}
144
145static int vchiq_ioc_create_service(struct vchiq_instance *instance,
146 struct vchiq_create_service *args)
147{
148 struct user_service *user_service = NULL;
149 struct vchiq_service *service;
150 enum vchiq_status status = VCHIQ_SUCCESS;
151 struct vchiq_service_params_kernel params;
152 int srvstate;
153
154 user_service = kmalloc(sizeof(*user_service), GFP_KERNEL);
155 if (!user_service)
156 return -ENOMEM;
157
158 if (args->is_open) {
159 if (!instance->connected) {
160 kfree(user_service);
161 return -ENOTCONN;
162 }
163 srvstate = VCHIQ_SRVSTATE_OPENING;
164 } else {
165 srvstate = instance->connected ?
166 VCHIQ_SRVSTATE_LISTENING : VCHIQ_SRVSTATE_HIDDEN;
167 }
168
169 params = (struct vchiq_service_params_kernel) {
170 .fourcc = args->params.fourcc,
171 .callback = service_callback,
172 .userdata = user_service,
173 .version = args->params.version,
174 .version_min = args->params.version_min,
175 };
176 service = vchiq_add_service_internal(instance->state, ¶ms,
177 srvstate, instance,
178 user_service_free);
179 if (!service) {
180 kfree(user_service);
181 return -EEXIST;
182 }
183
184 user_service->service = service;
185 user_service->userdata = args->params.userdata;
186 user_service->instance = instance;
187 user_service->is_vchi = (args->is_vchi != 0);
188 user_service->dequeue_pending = 0;
189 user_service->close_pending = 0;
190 user_service->message_available_pos = instance->completion_remove - 1;
191 user_service->msg_insert = 0;
192 user_service->msg_remove = 0;
193 init_completion(&user_service->insert_event);
194 init_completion(&user_service->remove_event);
195 init_completion(&user_service->close_event);
196
197 if (args->is_open) {
198 status = vchiq_open_service_internal(service, instance->pid);
199 if (status != VCHIQ_SUCCESS) {
200 vchiq_remove_service(service->handle);
201 return (status == VCHIQ_RETRY) ?
202 -EINTR : -EIO;
203 }
204 }
205 args->handle = service->handle;
206
207 return 0;
208}
209
210static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
211 struct vchiq_dequeue_message *args)
212{
213 struct user_service *user_service;
214 struct vchiq_service *service;
215 struct vchiq_header *header;
216 int ret;
217
218 DEBUG_INITIALISE(g_state.local)
219 DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
220 service = find_service_for_instance(instance, args->handle);
221 if (!service)
222 return -EINVAL;
223
224 user_service = (struct user_service *)service->base.userdata;
225 if (user_service->is_vchi == 0) {
226 ret = -EINVAL;
227 goto out;
228 }
229
230 spin_lock(&msg_queue_spinlock);
231 if (user_service->msg_remove == user_service->msg_insert) {
232 if (!args->blocking) {
233 spin_unlock(&msg_queue_spinlock);
234 DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
235 ret = -EWOULDBLOCK;
236 goto out;
237 }
238 user_service->dequeue_pending = 1;
239 ret = 0;
240 do {
241 spin_unlock(&msg_queue_spinlock);
242 DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
243 if (wait_for_completion_interruptible(
244 &user_service->insert_event)) {
245 vchiq_log_info(vchiq_arm_log_level,
246 "DEQUEUE_MESSAGE interrupted");
247 ret = -EINTR;
248 break;
249 }
250 spin_lock(&msg_queue_spinlock);
251 } while (user_service->msg_remove == user_service->msg_insert);
252
253 if (ret)
254 goto out;
255 }
256
257 if (WARN_ON_ONCE((int)(user_service->msg_insert -
258 user_service->msg_remove) < 0)) {
259 spin_unlock(&msg_queue_spinlock);
260 ret = -EINVAL;
261 goto out;
262 }
263
264 header = user_service->msg_queue[user_service->msg_remove &
265 (MSG_QUEUE_SIZE - 1)];
266 user_service->msg_remove++;
267 spin_unlock(&msg_queue_spinlock);
268
269 complete(&user_service->remove_event);
270 if (!header) {
271 ret = -ENOTCONN;
272 } else if (header->size <= args->bufsize) {
273
274 if (!args->buf || (copy_to_user(args->buf,
275 header->data, header->size) == 0)) {
276 ret = header->size;
277 vchiq_release_message(service->handle, header);
278 } else {
279 ret = -EFAULT;
280 }
281 } else {
282 vchiq_log_error(vchiq_arm_log_level,
283 "header %pK: bufsize %x < size %x",
284 header, args->bufsize, header->size);
285 WARN(1, "invalid size\n");
286 ret = -EMSGSIZE;
287 }
288 DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
289out:
290 vchiq_service_put(service);
291 return ret;
292}
293
294static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
295 struct vchiq_queue_bulk_transfer *args,
296 enum vchiq_bulk_dir dir,
297 enum vchiq_bulk_mode __user *mode)
298{
299 struct vchiq_service *service;
300 struct bulk_waiter_node *waiter = NULL;
301 bool found = false;
302 void *userdata;
303 int status = 0;
304 int ret;
305
306 service = find_service_for_instance(instance, args->handle);
307 if (!service)
308 return -EINVAL;
309
310 if (args->mode == VCHIQ_BULK_MODE_BLOCKING) {
311 waiter = kzalloc(sizeof(*waiter), GFP_KERNEL);
312 if (!waiter) {
313 ret = -ENOMEM;
314 goto out;
315 }
316
317 userdata = &waiter->bulk_waiter;
318 } else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
319 mutex_lock(&instance->bulk_waiter_list_mutex);
320 list_for_each_entry(waiter, &instance->bulk_waiter_list,
321 list) {
322 if (waiter->pid == current->pid) {
323 list_del(&waiter->list);
324 found = true;
325 break;
326 }
327 }
328 mutex_unlock(&instance->bulk_waiter_list_mutex);
329 if (!found) {
330 vchiq_log_error(vchiq_arm_log_level,
331 "no bulk_waiter found for pid %d",
332 current->pid);
333 ret = -ESRCH;
334 goto out;
335 }
336 vchiq_log_info(vchiq_arm_log_level,
337 "found bulk_waiter %pK for pid %d", waiter,
338 current->pid);
339 userdata = &waiter->bulk_waiter;
340 } else {
341 userdata = args->userdata;
342 }
343
344 status = vchiq_bulk_transfer(args->handle, NULL, args->data, args->size,
345 userdata, args->mode, dir);
346
347 if (!waiter) {
348 ret = 0;
349 goto out;
350 }
351
352 if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
353 !waiter->bulk_waiter.bulk) {
354 if (waiter->bulk_waiter.bulk) {
355
356 spin_lock(&bulk_waiter_spinlock);
357 waiter->bulk_waiter.bulk->userdata = NULL;
358 spin_unlock(&bulk_waiter_spinlock);
359 }
360 kfree(waiter);
361 ret = 0;
362 } else {
363 const enum vchiq_bulk_mode mode_waiting =
364 VCHIQ_BULK_MODE_WAITING;
365 waiter->pid = current->pid;
366 mutex_lock(&instance->bulk_waiter_list_mutex);
367 list_add(&waiter->list, &instance->bulk_waiter_list);
368 mutex_unlock(&instance->bulk_waiter_list_mutex);
369 vchiq_log_info(vchiq_arm_log_level,
370 "saved bulk_waiter %pK for pid %d",
371 waiter, current->pid);
372
373 ret = put_user(mode_waiting, mode);
374 }
375out:
376 vchiq_service_put(service);
377 if (ret)
378 return ret;
379 else if (status == VCHIQ_ERROR)
380 return -EIO;
381 else if (status == VCHIQ_RETRY)
382 return -EINTR;
383 return 0;
384}
385
386
387static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int index)
388{
389 int ret;
390
391 if (in_compat_syscall()) {
392 compat_uptr_t ptr32;
393 compat_uptr_t __user *uptr = ubuf;
394
395 ret = get_user(ptr32, uptr + index);
396 if (ret)
397 return ret;
398
399 *buf = compat_ptr(ptr32);
400 } else {
401 uintptr_t ptr, __user *uptr = ubuf;
402
403 ret = get_user(ptr, uptr + index);
404
405 if (ret)
406 return ret;
407
408 *buf = (void __user *)ptr;
409 }
410
411 return 0;
412}
413
414struct vchiq_completion_data32 {
415 enum vchiq_reason reason;
416 compat_uptr_t header;
417 compat_uptr_t service_userdata;
418 compat_uptr_t bulk_userdata;
419};
420
421static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
422 struct vchiq_completion_data *completion,
423 int index)
424{
425 struct vchiq_completion_data32 __user *buf32 = (void __user *)buf;
426
427 if (in_compat_syscall()) {
428 struct vchiq_completion_data32 tmp = {
429 .reason = completion->reason,
430 .header = ptr_to_compat(completion->header),
431 .service_userdata = ptr_to_compat(completion->service_userdata),
432 .bulk_userdata = ptr_to_compat(completion->bulk_userdata),
433 };
434 if (copy_to_user(&buf32[index], &tmp, sizeof(tmp)))
435 return -EFAULT;
436 } else {
437 if (copy_to_user(&buf[index], completion, sizeof(*completion)))
438 return -EFAULT;
439 }
440
441 return 0;
442}
443
444static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
445 struct vchiq_await_completion *args,
446 int __user *msgbufcountp)
447{
448 int msgbufcount;
449 int remove;
450 int ret;
451
452 DEBUG_INITIALISE(g_state.local)
453
454 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
455 if (!instance->connected) {
456 return -ENOTCONN;
457 }
458
459 mutex_lock(&instance->completion_mutex);
460
461 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
462 while ((instance->completion_remove == instance->completion_insert)
463 && !instance->closing) {
464 int rc;
465
466 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
467 mutex_unlock(&instance->completion_mutex);
468 rc = wait_for_completion_interruptible(
469 &instance->insert_event);
470 mutex_lock(&instance->completion_mutex);
471 if (rc) {
472 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
473 vchiq_log_info(vchiq_arm_log_level,
474 "AWAIT_COMPLETION interrupted");
475 ret = -EINTR;
476 goto out;
477 }
478 }
479 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
480
481 msgbufcount = args->msgbufcount;
482 remove = instance->completion_remove;
483
484 for (ret = 0; ret < args->count; ret++) {
485 struct vchiq_completion_data_kernel *completion;
486 struct vchiq_completion_data user_completion;
487 struct vchiq_service *service;
488 struct user_service *user_service;
489 struct vchiq_header *header;
490
491 if (remove == instance->completion_insert)
492 break;
493
494 completion = &instance->completions[
495 remove & (MAX_COMPLETIONS - 1)];
496
497
498
499
500
501 rmb();
502
503 service = completion->service_userdata;
504 user_service = service->base.userdata;
505
506 memset(&user_completion, 0, sizeof(user_completion));
507 user_completion = (struct vchiq_completion_data) {
508 .reason = completion->reason,
509 .service_userdata = user_service->userdata,
510 };
511
512 header = completion->header;
513 if (header) {
514 void __user *msgbuf;
515 int msglen;
516
517 msglen = header->size + sizeof(struct vchiq_header);
518
519 if (args->msgbufsize < msglen) {
520 vchiq_log_error(vchiq_arm_log_level,
521 "header %pK: msgbufsize %x < msglen %x",
522 header, args->msgbufsize, msglen);
523 WARN(1, "invalid message size\n");
524 if (ret == 0)
525 ret = -EMSGSIZE;
526 break;
527 }
528 if (msgbufcount <= 0)
529
530 break;
531
532 msgbufcount--;
533 if (vchiq_get_user_ptr(&msgbuf, args->msgbufs,
534 msgbufcount)) {
535 if (ret == 0)
536 ret = -EFAULT;
537 break;
538 }
539
540
541 if (copy_to_user(msgbuf, header, msglen)) {
542 if (ret == 0)
543 ret = -EFAULT;
544 break;
545 }
546
547
548 vchiq_release_message(service->handle, header);
549
550
551 user_completion.header = msgbuf;
552 }
553
554 if ((completion->reason == VCHIQ_SERVICE_CLOSED) &&
555 !instance->use_close_delivered)
556 vchiq_service_put(service);
557
558
559
560
561
562 user_completion.bulk_userdata = completion->bulk_userdata;
563
564 if (vchiq_put_completion(args->buf, &user_completion, ret)) {
565 if (ret == 0)
566 ret = -EFAULT;
567 break;
568 }
569
570
571
572
573
574 mb();
575 remove++;
576 instance->completion_remove = remove;
577 }
578
579 if (msgbufcount != args->msgbufcount) {
580 if (put_user(msgbufcount, msgbufcountp))
581 ret = -EFAULT;
582 }
583out:
584 if (ret)
585 complete(&instance->remove_event);
586 mutex_unlock(&instance->completion_mutex);
587 DEBUG_TRACE(AWAIT_COMPLETION_LINE);
588
589 return ret;
590}
591
592static long
593vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
594{
595 struct vchiq_instance *instance = file->private_data;
596 enum vchiq_status status = VCHIQ_SUCCESS;
597 struct vchiq_service *service = NULL;
598 long ret = 0;
599 int i, rc;
600
601 vchiq_log_trace(vchiq_arm_log_level,
602 "%s - instance %pK, cmd %s, arg %lx",
603 __func__, instance,
604 ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) &&
605 (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
606 ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
607
608 switch (cmd) {
609 case VCHIQ_IOC_SHUTDOWN:
610 if (!instance->connected)
611 break;
612
613
614 i = 0;
615 while ((service = next_service_by_instance(instance->state,
616 instance, &i))) {
617 status = vchiq_remove_service(service->handle);
618 vchiq_service_put(service);
619 if (status != VCHIQ_SUCCESS)
620 break;
621 }
622 service = NULL;
623
624 if (status == VCHIQ_SUCCESS) {
625
626 instance->closing = 1;
627 complete(&instance->insert_event);
628 }
629
630 break;
631
632 case VCHIQ_IOC_CONNECT:
633 if (instance->connected) {
634 ret = -EINVAL;
635 break;
636 }
637 rc = mutex_lock_killable(&instance->state->mutex);
638 if (rc) {
639 vchiq_log_error(vchiq_arm_log_level,
640 "vchiq: connect: could not lock mutex for state %d: %d",
641 instance->state->id, rc);
642 ret = -EINTR;
643 break;
644 }
645 status = vchiq_connect_internal(instance->state, instance);
646 mutex_unlock(&instance->state->mutex);
647
648 if (status == VCHIQ_SUCCESS)
649 instance->connected = 1;
650 else
651 vchiq_log_error(vchiq_arm_log_level,
652 "vchiq: could not connect: %d", status);
653 break;
654
655 case VCHIQ_IOC_CREATE_SERVICE: {
656 struct vchiq_create_service __user *argp;
657 struct vchiq_create_service args;
658
659 argp = (void __user *)arg;
660 if (copy_from_user(&args, argp, sizeof(args))) {
661 ret = -EFAULT;
662 break;
663 }
664
665 ret = vchiq_ioc_create_service(instance, &args);
666 if (ret < 0)
667 break;
668
669 if (put_user(args.handle, &argp->handle)) {
670 vchiq_remove_service(args.handle);
671 ret = -EFAULT;
672 }
673 } break;
674
675 case VCHIQ_IOC_CLOSE_SERVICE:
676 case VCHIQ_IOC_REMOVE_SERVICE: {
677 unsigned int handle = (unsigned int)arg;
678 struct user_service *user_service;
679
680 service = find_service_for_instance(instance, handle);
681 if (!service) {
682 ret = -EINVAL;
683 break;
684 }
685
686 user_service = service->base.userdata;
687
688
689
690
691
692 if (!user_service->close_pending) {
693 status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ?
694 vchiq_close_service(service->handle) :
695 vchiq_remove_service(service->handle);
696 if (status != VCHIQ_SUCCESS)
697 break;
698 }
699
700
701
702
703
704
705 if (user_service->close_pending &&
706 wait_for_completion_interruptible(
707 &user_service->close_event))
708 status = VCHIQ_RETRY;
709 break;
710 }
711
712 case VCHIQ_IOC_USE_SERVICE:
713 case VCHIQ_IOC_RELEASE_SERVICE: {
714 unsigned int handle = (unsigned int)arg;
715
716 service = find_service_for_instance(instance, handle);
717 if (service) {
718 ret = (cmd == VCHIQ_IOC_USE_SERVICE) ?
719 vchiq_use_service_internal(service) :
720 vchiq_release_service_internal(service);
721 if (ret) {
722 vchiq_log_error(vchiq_susp_log_level,
723 "%s: cmd %s returned error %ld for service %c%c%c%c:%03d",
724 __func__,
725 (cmd == VCHIQ_IOC_USE_SERVICE) ?
726 "VCHIQ_IOC_USE_SERVICE" :
727 "VCHIQ_IOC_RELEASE_SERVICE",
728 ret,
729 VCHIQ_FOURCC_AS_4CHARS(
730 service->base.fourcc),
731 service->client_id);
732 }
733 } else {
734 ret = -EINVAL;
735 }
736 } break;
737
738 case VCHIQ_IOC_QUEUE_MESSAGE: {
739 struct vchiq_queue_message args;
740
741 if (copy_from_user(&args, (const void __user *)arg,
742 sizeof(args))) {
743 ret = -EFAULT;
744 break;
745 }
746
747 service = find_service_for_instance(instance, args.handle);
748
749 if (service && (args.count <= MAX_ELEMENTS)) {
750
751 struct vchiq_element elements[MAX_ELEMENTS];
752
753 if (copy_from_user(elements, args.elements,
754 args.count * sizeof(struct vchiq_element)) == 0)
755 ret = vchiq_ioc_queue_message(args.handle, elements,
756 args.count);
757 else
758 ret = -EFAULT;
759 } else {
760 ret = -EINVAL;
761 }
762 } break;
763
764 case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
765 case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
766 struct vchiq_queue_bulk_transfer args;
767 struct vchiq_queue_bulk_transfer __user *argp;
768
769 enum vchiq_bulk_dir dir =
770 (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
771 VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
772
773 argp = (void __user *)arg;
774 if (copy_from_user(&args, argp, sizeof(args))) {
775 ret = -EFAULT;
776 break;
777 }
778
779 ret = vchiq_irq_queue_bulk_tx_rx(instance, &args,
780 dir, &argp->mode);
781 } break;
782
783 case VCHIQ_IOC_AWAIT_COMPLETION: {
784 struct vchiq_await_completion args;
785 struct vchiq_await_completion __user *argp;
786
787 argp = (void __user *)arg;
788 if (copy_from_user(&args, argp, sizeof(args))) {
789 ret = -EFAULT;
790 break;
791 }
792
793 ret = vchiq_ioc_await_completion(instance, &args,
794 &argp->msgbufcount);
795 } break;
796
797 case VCHIQ_IOC_DEQUEUE_MESSAGE: {
798 struct vchiq_dequeue_message args;
799
800 if (copy_from_user(&args, (const void __user *)arg,
801 sizeof(args))) {
802 ret = -EFAULT;
803 break;
804 }
805
806 ret = vchiq_ioc_dequeue_message(instance, &args);
807 } break;
808
809 case VCHIQ_IOC_GET_CLIENT_ID: {
810 unsigned int handle = (unsigned int)arg;
811
812 ret = vchiq_get_client_id(handle);
813 } break;
814
815 case VCHIQ_IOC_GET_CONFIG: {
816 struct vchiq_get_config args;
817 struct vchiq_config config;
818
819 if (copy_from_user(&args, (const void __user *)arg,
820 sizeof(args))) {
821 ret = -EFAULT;
822 break;
823 }
824 if (args.config_size > sizeof(config)) {
825 ret = -EINVAL;
826 break;
827 }
828
829 vchiq_get_config(&config);
830 if (copy_to_user(args.pconfig, &config, args.config_size)) {
831 ret = -EFAULT;
832 break;
833 }
834 } break;
835
836 case VCHIQ_IOC_SET_SERVICE_OPTION: {
837 struct vchiq_set_service_option args;
838
839 if (copy_from_user(&args, (const void __user *)arg,
840 sizeof(args))) {
841 ret = -EFAULT;
842 break;
843 }
844
845 service = find_service_for_instance(instance, args.handle);
846 if (!service) {
847 ret = -EINVAL;
848 break;
849 }
850
851 ret = vchiq_set_service_option(args.handle, args.option,
852 args.value);
853 } break;
854
855 case VCHIQ_IOC_LIB_VERSION: {
856 unsigned int lib_version = (unsigned int)arg;
857
858 if (lib_version < VCHIQ_VERSION_MIN)
859 ret = -EINVAL;
860 else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED)
861 instance->use_close_delivered = 1;
862 } break;
863
864 case VCHIQ_IOC_CLOSE_DELIVERED: {
865 unsigned int handle = (unsigned int)arg;
866
867 service = find_closed_service_for_instance(instance, handle);
868 if (service) {
869 struct user_service *user_service =
870 (struct user_service *)service->base.userdata;
871 close_delivered(user_service);
872 } else {
873 ret = -EINVAL;
874 }
875 } break;
876
877 default:
878 ret = -ENOTTY;
879 break;
880 }
881
882 if (service)
883 vchiq_service_put(service);
884
885 if (ret == 0) {
886 if (status == VCHIQ_ERROR)
887 ret = -EIO;
888 else if (status == VCHIQ_RETRY)
889 ret = -EINTR;
890 }
891
892 if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) &&
893 (ret != -EWOULDBLOCK))
894 vchiq_log_info(vchiq_arm_log_level,
895 " ioctl instance %pK, cmd %s -> status %d, %ld",
896 instance,
897 (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
898 ioctl_names[_IOC_NR(cmd)] :
899 "<invalid>",
900 status, ret);
901 else
902 vchiq_log_trace(vchiq_arm_log_level,
903 " ioctl instance %pK, cmd %s -> status %d, %ld",
904 instance,
905 (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
906 ioctl_names[_IOC_NR(cmd)] :
907 "<invalid>",
908 status, ret);
909
910 return ret;
911}
912
913#if defined(CONFIG_COMPAT)
914
915struct vchiq_service_params32 {
916 int fourcc;
917 compat_uptr_t callback;
918 compat_uptr_t userdata;
919 short version;
920 short version_min;
921};
922
923struct vchiq_create_service32 {
924 struct vchiq_service_params32 params;
925 int is_open;
926 int is_vchi;
927 unsigned int handle;
928};
929
930#define VCHIQ_IOC_CREATE_SERVICE32 \
931 _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service32)
932
933static long
934vchiq_compat_ioctl_create_service(struct file *file, unsigned int cmd,
935 struct vchiq_create_service32 __user *ptrargs32)
936{
937 struct vchiq_create_service args;
938 struct vchiq_create_service32 args32;
939 long ret;
940
941 if (copy_from_user(&args32, ptrargs32, sizeof(args32)))
942 return -EFAULT;
943
944 args = (struct vchiq_create_service) {
945 .params = {
946 .fourcc = args32.params.fourcc,
947 .callback = compat_ptr(args32.params.callback),
948 .userdata = compat_ptr(args32.params.userdata),
949 .version = args32.params.version,
950 .version_min = args32.params.version_min,
951 },
952 .is_open = args32.is_open,
953 .is_vchi = args32.is_vchi,
954 .handle = args32.handle,
955 };
956
957 ret = vchiq_ioc_create_service(file->private_data, &args);
958 if (ret < 0)
959 return ret;
960
961 if (put_user(args.handle, &ptrargs32->handle)) {
962 vchiq_remove_service(args.handle);
963 return -EFAULT;
964 }
965
966 return 0;
967}
968
969struct vchiq_element32 {
970 compat_uptr_t data;
971 unsigned int size;
972};
973
974struct vchiq_queue_message32 {
975 unsigned int handle;
976 unsigned int count;
977 compat_uptr_t elements;
978};
979
980#define VCHIQ_IOC_QUEUE_MESSAGE32 \
981 _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message32)
982
983static long
984vchiq_compat_ioctl_queue_message(struct file *file,
985 unsigned int cmd,
986 struct vchiq_queue_message32 __user *arg)
987{
988 struct vchiq_queue_message args;
989 struct vchiq_queue_message32 args32;
990 struct vchiq_service *service;
991 int ret;
992
993 if (copy_from_user(&args32, arg, sizeof(args32)))
994 return -EFAULT;
995
996 args = (struct vchiq_queue_message) {
997 .handle = args32.handle,
998 .count = args32.count,
999 .elements = compat_ptr(args32.elements),
1000 };
1001
1002 if (args32.count > MAX_ELEMENTS)
1003 return -EINVAL;
1004
1005 service = find_service_for_instance(file->private_data, args.handle);
1006 if (!service)
1007 return -EINVAL;
1008
1009 if (args32.elements && args32.count) {
1010 struct vchiq_element32 element32[MAX_ELEMENTS];
1011 struct vchiq_element elements[MAX_ELEMENTS];
1012 unsigned int count;
1013
1014 if (copy_from_user(&element32, args.elements,
1015 sizeof(element32))) {
1016 vchiq_service_put(service);
1017 return -EFAULT;
1018 }
1019
1020 for (count = 0; count < args32.count; count++) {
1021 elements[count].data =
1022 compat_ptr(element32[count].data);
1023 elements[count].size = element32[count].size;
1024 }
1025 ret = vchiq_ioc_queue_message(args.handle, elements,
1026 args.count);
1027 } else {
1028 ret = -EINVAL;
1029 }
1030 vchiq_service_put(service);
1031
1032 return ret;
1033}
1034
1035struct vchiq_queue_bulk_transfer32 {
1036 unsigned int handle;
1037 compat_uptr_t data;
1038 unsigned int size;
1039 compat_uptr_t userdata;
1040 enum vchiq_bulk_mode mode;
1041};
1042
1043#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
1044 _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer32)
1045#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \
1046 _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer32)
1047
1048static long
1049vchiq_compat_ioctl_queue_bulk(struct file *file,
1050 unsigned int cmd,
1051 struct vchiq_queue_bulk_transfer32 __user *argp)
1052{
1053 struct vchiq_queue_bulk_transfer32 args32;
1054 struct vchiq_queue_bulk_transfer args;
1055 enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ?
1056 VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
1057
1058 if (copy_from_user(&args32, argp, sizeof(args32)))
1059 return -EFAULT;
1060
1061 args = (struct vchiq_queue_bulk_transfer) {
1062 .handle = args32.handle,
1063 .data = compat_ptr(args32.data),
1064 .size = args32.size,
1065 .userdata = compat_ptr(args32.userdata),
1066 .mode = args32.mode,
1067 };
1068
1069 return vchiq_irq_queue_bulk_tx_rx(file->private_data, &args,
1070 dir, &argp->mode);
1071}
1072
1073struct vchiq_await_completion32 {
1074 unsigned int count;
1075 compat_uptr_t buf;
1076 unsigned int msgbufsize;
1077 unsigned int msgbufcount;
1078 compat_uptr_t msgbufs;
1079};
1080
1081#define VCHIQ_IOC_AWAIT_COMPLETION32 \
1082 _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion32)
1083
1084static long
1085vchiq_compat_ioctl_await_completion(struct file *file,
1086 unsigned int cmd,
1087 struct vchiq_await_completion32 __user *argp)
1088{
1089 struct vchiq_await_completion args;
1090 struct vchiq_await_completion32 args32;
1091
1092 if (copy_from_user(&args32, argp, sizeof(args32)))
1093 return -EFAULT;
1094
1095 args = (struct vchiq_await_completion) {
1096 .count = args32.count,
1097 .buf = compat_ptr(args32.buf),
1098 .msgbufsize = args32.msgbufsize,
1099 .msgbufcount = args32.msgbufcount,
1100 .msgbufs = compat_ptr(args32.msgbufs),
1101 };
1102
1103 return vchiq_ioc_await_completion(file->private_data, &args,
1104 &argp->msgbufcount);
1105}
1106
1107struct vchiq_dequeue_message32 {
1108 unsigned int handle;
1109 int blocking;
1110 unsigned int bufsize;
1111 compat_uptr_t buf;
1112};
1113
1114#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \
1115 _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message32)
1116
1117static long
1118vchiq_compat_ioctl_dequeue_message(struct file *file,
1119 unsigned int cmd,
1120 struct vchiq_dequeue_message32 __user *arg)
1121{
1122 struct vchiq_dequeue_message32 args32;
1123 struct vchiq_dequeue_message args;
1124
1125 if (copy_from_user(&args32, arg, sizeof(args32)))
1126 return -EFAULT;
1127
1128 args = (struct vchiq_dequeue_message) {
1129 .handle = args32.handle,
1130 .blocking = args32.blocking,
1131 .bufsize = args32.bufsize,
1132 .buf = compat_ptr(args32.buf),
1133 };
1134
1135 return vchiq_ioc_dequeue_message(file->private_data, &args);
1136}
1137
1138struct vchiq_get_config32 {
1139 unsigned int config_size;
1140 compat_uptr_t pconfig;
1141};
1142
1143#define VCHIQ_IOC_GET_CONFIG32 \
1144 _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config32)
1145
1146static long
1147vchiq_compat_ioctl_get_config(struct file *file,
1148 unsigned int cmd,
1149 struct vchiq_get_config32 __user *arg)
1150{
1151 struct vchiq_get_config32 args32;
1152 struct vchiq_config config;
1153 void __user *ptr;
1154
1155 if (copy_from_user(&args32, arg, sizeof(args32)))
1156 return -EFAULT;
1157 if (args32.config_size > sizeof(config))
1158 return -EINVAL;
1159
1160 vchiq_get_config(&config);
1161 ptr = compat_ptr(args32.pconfig);
1162 if (copy_to_user(ptr, &config, args32.config_size))
1163 return -EFAULT;
1164
1165 return 0;
1166}
1167
1168static long
1169vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1170{
1171 void __user *argp = compat_ptr(arg);
1172
1173 switch (cmd) {
1174 case VCHIQ_IOC_CREATE_SERVICE32:
1175 return vchiq_compat_ioctl_create_service(file, cmd, argp);
1176 case VCHIQ_IOC_QUEUE_MESSAGE32:
1177 return vchiq_compat_ioctl_queue_message(file, cmd, argp);
1178 case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32:
1179 case VCHIQ_IOC_QUEUE_BULK_RECEIVE32:
1180 return vchiq_compat_ioctl_queue_bulk(file, cmd, argp);
1181 case VCHIQ_IOC_AWAIT_COMPLETION32:
1182 return vchiq_compat_ioctl_await_completion(file, cmd, argp);
1183 case VCHIQ_IOC_DEQUEUE_MESSAGE32:
1184 return vchiq_compat_ioctl_dequeue_message(file, cmd, argp);
1185 case VCHIQ_IOC_GET_CONFIG32:
1186 return vchiq_compat_ioctl_get_config(file, cmd, argp);
1187 default:
1188 return vchiq_ioctl(file, cmd, (unsigned long)argp);
1189 }
1190}
1191
1192#endif
1193
1194static int vchiq_open(struct inode *inode, struct file *file)
1195{
1196 struct vchiq_state *state = vchiq_get_state();
1197 struct vchiq_instance *instance;
1198
1199 vchiq_log_info(vchiq_arm_log_level, "vchiq_open");
1200
1201 if (!state) {
1202 vchiq_log_error(vchiq_arm_log_level,
1203 "vchiq has no connection to VideoCore");
1204 return -ENOTCONN;
1205 }
1206
1207 instance = kzalloc(sizeof(*instance), GFP_KERNEL);
1208 if (!instance)
1209 return -ENOMEM;
1210
1211 instance->state = state;
1212 instance->pid = current->tgid;
1213
1214 vchiq_debugfs_add_instance(instance);
1215
1216 init_completion(&instance->insert_event);
1217 init_completion(&instance->remove_event);
1218 mutex_init(&instance->completion_mutex);
1219 mutex_init(&instance->bulk_waiter_list_mutex);
1220 INIT_LIST_HEAD(&instance->bulk_waiter_list);
1221
1222 file->private_data = instance;
1223
1224 return 0;
1225}
1226
1227static int vchiq_release(struct inode *inode, struct file *file)
1228{
1229 struct vchiq_instance *instance = file->private_data;
1230 struct vchiq_state *state = vchiq_get_state();
1231 struct vchiq_service *service;
1232 int ret = 0;
1233 int i;
1234
1235 vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__,
1236 (unsigned long)instance);
1237
1238 if (!state) {
1239 ret = -EPERM;
1240 goto out;
1241 }
1242
1243
1244 vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ);
1245
1246 mutex_lock(&instance->completion_mutex);
1247
1248
1249 instance->closing = 1;
1250 complete(&instance->insert_event);
1251
1252 mutex_unlock(&instance->completion_mutex);
1253
1254
1255 complete(&instance->remove_event);
1256
1257
1258 i = 0;
1259 while ((service = next_service_by_instance(state, instance, &i))) {
1260 struct user_service *user_service = service->base.userdata;
1261
1262
1263 complete(&user_service->remove_event);
1264
1265 vchiq_terminate_service_internal(service);
1266 vchiq_service_put(service);
1267 }
1268
1269
1270 i = 0;
1271 while ((service = next_service_by_instance(state, instance, &i))) {
1272 struct user_service *user_service = service->base.userdata;
1273
1274 wait_for_completion(&service->remove_event);
1275
1276 if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) {
1277 vchiq_service_put(service);
1278 break;
1279 }
1280
1281 spin_lock(&msg_queue_spinlock);
1282
1283 while (user_service->msg_remove != user_service->msg_insert) {
1284 struct vchiq_header *header;
1285 int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1);
1286
1287 header = user_service->msg_queue[m];
1288 user_service->msg_remove++;
1289 spin_unlock(&msg_queue_spinlock);
1290
1291 if (header)
1292 vchiq_release_message(service->handle, header);
1293 spin_lock(&msg_queue_spinlock);
1294 }
1295
1296 spin_unlock(&msg_queue_spinlock);
1297
1298 vchiq_service_put(service);
1299 }
1300
1301
1302 while (instance->completion_remove != instance->completion_insert) {
1303 struct vchiq_completion_data_kernel *completion;
1304 struct vchiq_service *service;
1305
1306 completion = &instance->completions[
1307 instance->completion_remove & (MAX_COMPLETIONS - 1)];
1308 service = completion->service_userdata;
1309 if (completion->reason == VCHIQ_SERVICE_CLOSED) {
1310 struct user_service *user_service =
1311 service->base.userdata;
1312
1313
1314 if (instance->use_close_delivered)
1315 complete(&user_service->close_event);
1316 vchiq_service_put(service);
1317 }
1318 instance->completion_remove++;
1319 }
1320
1321
1322 vchiq_release_internal(instance->state, NULL);
1323
1324 free_bulk_waiter(instance);
1325
1326 vchiq_debugfs_remove_instance(instance);
1327
1328 kfree(instance);
1329 file->private_data = NULL;
1330
1331out:
1332 return ret;
1333}
1334
1335static ssize_t
1336vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
1337{
1338 struct dump_context context;
1339 int err;
1340
1341 context.buf = buf;
1342 context.actual = 0;
1343 context.space = count;
1344 context.offset = *ppos;
1345
1346 err = vchiq_dump_state(&context, &g_state);
1347 if (err)
1348 return err;
1349
1350 *ppos += context.actual;
1351
1352 return context.actual;
1353}
1354
1355static const struct file_operations
1356vchiq_fops = {
1357 .owner = THIS_MODULE,
1358 .unlocked_ioctl = vchiq_ioctl,
1359#if defined(CONFIG_COMPAT)
1360 .compat_ioctl = vchiq_compat_ioctl,
1361#endif
1362 .open = vchiq_open,
1363 .release = vchiq_release,
1364 .read = vchiq_read
1365};
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375int vchiq_register_chrdev(struct device *parent)
1376{
1377 struct device *vchiq_dev;
1378 int ret;
1379
1380 vchiq_class = class_create(THIS_MODULE, DEVICE_NAME);
1381 if (IS_ERR(vchiq_class)) {
1382 pr_err("Failed to create vchiq class\n");
1383 ret = PTR_ERR(vchiq_class);
1384 goto error_exit;
1385 }
1386
1387 ret = alloc_chrdev_region(&vchiq_devid, 0, 1, DEVICE_NAME);
1388 if (ret) {
1389 pr_err("vchiq: Failed to allocate vchiq's chrdev region\n");
1390 goto alloc_region_error;
1391 }
1392
1393 cdev_init(&vchiq_cdev, &vchiq_fops);
1394 vchiq_cdev.owner = THIS_MODULE;
1395 ret = cdev_add(&vchiq_cdev, vchiq_devid, 1);
1396 if (ret) {
1397 vchiq_log_error(vchiq_arm_log_level,
1398 "Unable to register vchiq char device");
1399 goto cdev_add_error;
1400 }
1401
1402 vchiq_dev = device_create(vchiq_class, parent, vchiq_devid, NULL,
1403 DEVICE_NAME);
1404 if (IS_ERR(vchiq_dev)) {
1405 vchiq_log_error(vchiq_arm_log_level,
1406 "Failed to create vchiq char device node");
1407 ret = PTR_ERR(vchiq_dev);
1408 goto device_create_error;
1409 }
1410
1411 vchiq_log_info(vchiq_arm_log_level,
1412 "vchiq char dev initialised successfully - device %d.%d",
1413 MAJOR(vchiq_devid), MINOR(vchiq_devid));
1414
1415 return 0;
1416
1417device_create_error:
1418 cdev_del(&vchiq_cdev);
1419
1420cdev_add_error:
1421 unregister_chrdev_region(vchiq_devid, 1);
1422
1423alloc_region_error:
1424 class_destroy(vchiq_class);
1425
1426error_exit:
1427 return ret;
1428}
1429
1430
1431
1432
1433
1434void vchiq_deregister_chrdev(void)
1435{
1436 device_destroy(vchiq_class, vchiq_devid);
1437 cdev_del(&vchiq_cdev);
1438 unregister_chrdev_region(vchiq_devid, 1);
1439 class_destroy(vchiq_class);
1440}
1441