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