This source file includes following definitions.
- vchi_msg_peek
- vchi_msg_remove
- vchi_msg_queue
- vchi_queue_kernel_message_callback
- vchi_queue_kernel_message
- vchi_queue_user_message_callback
- vchi_queue_user_message
- vchi_bulk_queue_receive
- vchi_bulk_queue_transmit
- vchi_msg_dequeue
- vchi_held_msg_release
- vchi_msg_hold
- vchi_initialise
- vchi_connect
- vchi_disconnect
- shim_callback
- service_alloc
- service_free
- vchi_service_open
- vchi_service_close
- vchi_service_destroy
- vchi_service_set_option
- vchi_get_peer_version
- vchi_service_use
- vchi_service_release
1
2
3 #include <linux/module.h>
4 #include <linux/types.h>
5
6 #include "interface/vchi/vchi.h"
7 #include "vchiq.h"
8 #include "vchiq_core.h"
9
10 #include "vchiq_util.h"
11
12 #define vchiq_status_to_vchi(status) ((int32_t)status)
13
14 struct shim_service {
15 VCHIQ_SERVICE_HANDLE_T handle;
16
17 struct vchiu_queue queue;
18
19 VCHI_CALLBACK_T callback;
20 void *callback_param;
21 };
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
40 void **data,
41 uint32_t *msg_size,
42 VCHI_FLAGS_T flags)
43 {
44 struct shim_service *service = (struct shim_service *)handle;
45 struct vchiq_header *header;
46
47 WARN_ON((flags != VCHI_FLAGS_NONE) &&
48 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
49
50 if (flags == VCHI_FLAGS_NONE)
51 if (vchiu_queue_is_empty(&service->queue))
52 return -1;
53
54 header = vchiu_queue_peek(&service->queue);
55
56 *data = header->data;
57 *msg_size = header->size;
58
59 return 0;
60 }
61 EXPORT_SYMBOL(vchi_msg_peek);
62
63
64
65
66
67
68
69
70
71
72
73
74 int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
75 {
76 struct shim_service *service = (struct shim_service *)handle;
77 struct vchiq_header *header;
78
79 header = vchiu_queue_pop(&service->queue);
80
81 vchiq_release_message(service->handle, header);
82
83 return 0;
84 }
85 EXPORT_SYMBOL(vchi_msg_remove);
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 static
102 int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
103 ssize_t (*copy_callback)(void *context, void *dest,
104 size_t offset, size_t maxsize),
105 void *context,
106 uint32_t data_size)
107 {
108 struct shim_service *service = (struct shim_service *)handle;
109 VCHIQ_STATUS_T status;
110
111 while (1) {
112 status = vchiq_queue_message(service->handle,
113 copy_callback,
114 context,
115 data_size);
116
117
118
119
120
121
122 if (status != VCHIQ_RETRY)
123 break;
124
125 msleep(1);
126 }
127
128 return vchiq_status_to_vchi(status);
129 }
130
131 static ssize_t
132 vchi_queue_kernel_message_callback(void *context,
133 void *dest,
134 size_t offset,
135 size_t maxsize)
136 {
137 memcpy(dest, context + offset, maxsize);
138 return maxsize;
139 }
140
141 int
142 vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
143 void *data,
144 unsigned int size)
145 {
146 return vchi_msg_queue(handle,
147 vchi_queue_kernel_message_callback,
148 data,
149 size);
150 }
151 EXPORT_SYMBOL(vchi_queue_kernel_message);
152
153 struct vchi_queue_user_message_context {
154 void __user *data;
155 };
156
157 static ssize_t
158 vchi_queue_user_message_callback(void *context,
159 void *dest,
160 size_t offset,
161 size_t maxsize)
162 {
163 struct vchi_queue_user_message_context *copycontext = context;
164
165 if (copy_from_user(dest, copycontext->data + offset, maxsize))
166 return -EFAULT;
167
168 return maxsize;
169 }
170
171 int
172 vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
173 void __user *data,
174 unsigned int size)
175 {
176 struct vchi_queue_user_message_context copycontext = {
177 .data = data
178 };
179
180 return vchi_msg_queue(handle,
181 vchi_queue_user_message_callback,
182 ©context,
183 size);
184 }
185 EXPORT_SYMBOL(vchi_queue_user_message);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,
202 void *data_dst,
203 uint32_t data_size,
204 VCHI_FLAGS_T flags,
205 void *bulk_handle)
206 {
207 struct shim_service *service = (struct shim_service *)handle;
208 VCHIQ_BULK_MODE_T mode;
209 VCHIQ_STATUS_T status;
210
211 switch ((int)flags) {
212 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
213 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
214 WARN_ON(!service->callback);
215 mode = VCHIQ_BULK_MODE_CALLBACK;
216 break;
217 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
218 mode = VCHIQ_BULK_MODE_BLOCKING;
219 break;
220 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
221 case VCHI_FLAGS_NONE:
222 mode = VCHIQ_BULK_MODE_NOCALLBACK;
223 break;
224 default:
225 WARN(1, "unsupported message\n");
226 return vchiq_status_to_vchi(VCHIQ_ERROR);
227 }
228
229 while (1) {
230 status = vchiq_bulk_receive(service->handle, data_dst,
231 data_size, bulk_handle, mode);
232
233
234
235
236
237 if (status != VCHIQ_RETRY)
238 break;
239
240 msleep(1);
241 }
242
243 return vchiq_status_to_vchi(status);
244 }
245 EXPORT_SYMBOL(vchi_bulk_queue_receive);
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261 int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,
262 const void *data_src,
263 uint32_t data_size,
264 VCHI_FLAGS_T flags,
265 void *bulk_handle)
266 {
267 struct shim_service *service = (struct shim_service *)handle;
268 VCHIQ_BULK_MODE_T mode;
269 VCHIQ_STATUS_T status;
270
271 switch ((int)flags) {
272 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
273 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
274 WARN_ON(!service->callback);
275 mode = VCHIQ_BULK_MODE_CALLBACK;
276 break;
277 case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
278 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
279 mode = VCHIQ_BULK_MODE_BLOCKING;
280 break;
281 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
282 case VCHI_FLAGS_NONE:
283 mode = VCHIQ_BULK_MODE_NOCALLBACK;
284 break;
285 default:
286 WARN(1, "unsupported message\n");
287 return vchiq_status_to_vchi(VCHIQ_ERROR);
288 }
289
290 while (1) {
291 status = vchiq_bulk_transmit(service->handle, data_src,
292 data_size, bulk_handle, mode);
293
294
295
296
297
298
299 if (status != VCHIQ_RETRY)
300 break;
301
302 msleep(1);
303 }
304
305 return vchiq_status_to_vchi(status);
306 }
307 EXPORT_SYMBOL(vchi_bulk_queue_transmit);
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
324 void *data,
325 uint32_t max_data_size_to_read,
326 uint32_t *actual_msg_size,
327 VCHI_FLAGS_T flags)
328 {
329 struct shim_service *service = (struct shim_service *)handle;
330 struct vchiq_header *header;
331
332 WARN_ON((flags != VCHI_FLAGS_NONE) &&
333 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
334
335 if (flags == VCHI_FLAGS_NONE)
336 if (vchiu_queue_is_empty(&service->queue))
337 return -1;
338
339 header = vchiu_queue_pop(&service->queue);
340
341 memcpy(data, header->data, header->size < max_data_size_to_read ?
342 header->size : max_data_size_to_read);
343
344 *actual_msg_size = header->size;
345
346 vchiq_release_message(service->handle, header);
347
348 return 0;
349 }
350 EXPORT_SYMBOL(vchi_msg_dequeue);
351
352
353
354
355
356
357
358
359
360
361
362
363 int32_t vchi_held_msg_release(struct vchi_held_msg *message)
364 {
365
366
367
368
369
370
371
372
373 vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service,
374 (struct vchiq_header *)message->message);
375
376 return 0;
377 }
378 EXPORT_SYMBOL(vchi_held_msg_release);
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
398 void **data,
399 uint32_t *msg_size,
400 VCHI_FLAGS_T flags,
401 struct vchi_held_msg *message_handle)
402 {
403 struct shim_service *service = (struct shim_service *)handle;
404 struct vchiq_header *header;
405
406 WARN_ON((flags != VCHI_FLAGS_NONE) &&
407 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
408
409 if (flags == VCHI_FLAGS_NONE)
410 if (vchiu_queue_is_empty(&service->queue))
411 return -1;
412
413 header = vchiu_queue_pop(&service->queue);
414
415 *data = header->data;
416 *msg_size = header->size;
417
418
419
420
421
422
423
424
425
426 message_handle->service =
427 (struct opaque_vchi_service_t *)(long)service->handle;
428 message_handle->message = header;
429
430 return 0;
431 }
432 EXPORT_SYMBOL(vchi_msg_hold);
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447 int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
448 {
449 VCHIQ_INSTANCE_T instance;
450 VCHIQ_STATUS_T status;
451
452 status = vchiq_initialise(&instance);
453
454 *instance_handle = (VCHI_INSTANCE_T)instance;
455
456 return vchiq_status_to_vchi(status);
457 }
458 EXPORT_SYMBOL(vchi_initialise);
459
460
461
462
463
464
465
466
467
468
469
470
471 int32_t vchi_connect(VCHI_INSTANCE_T instance_handle)
472 {
473 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
474
475 return vchiq_connect(instance);
476 }
477 EXPORT_SYMBOL(vchi_connect);
478
479
480
481
482
483
484
485
486
487
488
489
490 int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
491 {
492 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
493
494 return vchiq_status_to_vchi(vchiq_shutdown(instance));
495 }
496 EXPORT_SYMBOL(vchi_disconnect);
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512 static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
513 struct vchiq_header *header,
514 VCHIQ_SERVICE_HANDLE_T handle,
515 void *bulk_user)
516 {
517 struct shim_service *service =
518 (struct shim_service *)VCHIQ_GET_SERVICE_USERDATA(handle);
519
520 if (!service->callback)
521 goto release;
522
523 switch (reason) {
524 case VCHIQ_MESSAGE_AVAILABLE:
525 vchiu_queue_push(&service->queue, header);
526
527 service->callback(service->callback_param,
528 VCHI_CALLBACK_MSG_AVAILABLE, NULL);
529
530 goto done;
531
532 case VCHIQ_BULK_TRANSMIT_DONE:
533 service->callback(service->callback_param,
534 VCHI_CALLBACK_BULK_SENT, bulk_user);
535 break;
536
537 case VCHIQ_BULK_RECEIVE_DONE:
538 service->callback(service->callback_param,
539 VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
540 break;
541
542 case VCHIQ_SERVICE_CLOSED:
543 service->callback(service->callback_param,
544 VCHI_CALLBACK_SERVICE_CLOSED, NULL);
545 break;
546
547 case VCHIQ_SERVICE_OPENED:
548
549 break;
550
551 case VCHIQ_BULK_TRANSMIT_ABORTED:
552 service->callback(service->callback_param,
553 VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
554 bulk_user);
555 break;
556
557 case VCHIQ_BULK_RECEIVE_ABORTED:
558 service->callback(service->callback_param,
559 VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
560 bulk_user);
561 break;
562
563 default:
564 WARN(1, "not supported\n");
565 break;
566 }
567
568 release:
569 vchiq_release_message(service->handle, header);
570 done:
571 return VCHIQ_SUCCESS;
572 }
573
574 static struct shim_service *service_alloc(VCHIQ_INSTANCE_T instance,
575 struct service_creation *setup)
576 {
577 struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL);
578
579 (void)instance;
580
581 if (service) {
582 if (vchiu_queue_init(&service->queue, 64)) {
583 service->callback = setup->callback;
584 service->callback_param = setup->callback_param;
585 } else {
586 kfree(service);
587 service = NULL;
588 }
589 }
590
591 return service;
592 }
593
594 static void service_free(struct shim_service *service)
595 {
596 if (service) {
597 vchiu_queue_delete(&service->queue);
598 kfree(service);
599 }
600 }
601
602 int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
603 struct service_creation *setup,
604 VCHI_SERVICE_HANDLE_T *handle)
605 {
606 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
607 struct shim_service *service = service_alloc(instance, setup);
608
609 *handle = (VCHI_SERVICE_HANDLE_T)service;
610
611 if (service) {
612 struct vchiq_service_params params;
613 VCHIQ_STATUS_T status;
614
615 memset(¶ms, 0, sizeof(params));
616 params.fourcc = setup->service_id;
617 params.callback = shim_callback;
618 params.userdata = service;
619 params.version = setup->version.version;
620 params.version_min = setup->version.version_min;
621
622 status = vchiq_open_service(instance, ¶ms,
623 &service->handle);
624 if (status != VCHIQ_SUCCESS) {
625 service_free(service);
626 service = NULL;
627 *handle = NULL;
628 }
629 }
630
631 return (service != NULL) ? 0 : -1;
632 }
633 EXPORT_SYMBOL(vchi_service_open);
634
635 int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
636 {
637 int32_t ret = -1;
638 struct shim_service *service = (struct shim_service *)handle;
639
640 if (service) {
641 VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
642 if (status == VCHIQ_SUCCESS)
643 service_free(service);
644
645 ret = vchiq_status_to_vchi(status);
646 }
647 return ret;
648 }
649 EXPORT_SYMBOL(vchi_service_close);
650
651 int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
652 {
653 int32_t ret = -1;
654 struct shim_service *service = (struct shim_service *)handle;
655
656 if (service) {
657 VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
658
659 if (status == VCHIQ_SUCCESS) {
660 service_free(service);
661 service = NULL;
662 }
663
664 ret = vchiq_status_to_vchi(status);
665 }
666 return ret;
667 }
668 EXPORT_SYMBOL(vchi_service_destroy);
669
670 int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
671 VCHI_SERVICE_OPTION_T option,
672 int value)
673 {
674 int32_t ret = -1;
675 struct shim_service *service = (struct shim_service *)handle;
676 VCHIQ_SERVICE_OPTION_T vchiq_option;
677
678 switch (option) {
679 case VCHI_SERVICE_OPTION_TRACE:
680 vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
681 break;
682 case VCHI_SERVICE_OPTION_SYNCHRONOUS:
683 vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS;
684 break;
685 default:
686 service = NULL;
687 break;
688 }
689 if (service) {
690 VCHIQ_STATUS_T status =
691 vchiq_set_service_option(service->handle,
692 vchiq_option,
693 value);
694
695 ret = vchiq_status_to_vchi(status);
696 }
697 return ret;
698 }
699 EXPORT_SYMBOL(vchi_service_set_option);
700
701 int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, short *peer_version)
702 {
703 int32_t ret = -1;
704 struct shim_service *service = (struct shim_service *)handle;
705
706 if (service) {
707 VCHIQ_STATUS_T status;
708
709 status = vchiq_get_peer_version(service->handle, peer_version);
710 ret = vchiq_status_to_vchi(status);
711 }
712 return ret;
713 }
714 EXPORT_SYMBOL(vchi_get_peer_version);
715
716
717
718
719
720
721
722
723
724
725
726 int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
727 {
728 int32_t ret = -1;
729
730 struct shim_service *service = (struct shim_service *)handle;
731 if (service)
732 ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
733 return ret;
734 }
735 EXPORT_SYMBOL(vchi_service_use);
736
737
738
739
740
741
742
743
744
745
746
747 int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
748 {
749 int32_t ret = -1;
750
751 struct shim_service *service = (struct shim_service *)handle;
752 if (service)
753 ret = vchiq_status_to_vchi(
754 vchiq_release_service(service->handle));
755 return ret;
756 }
757 EXPORT_SYMBOL(vchi_service_release);