Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 : : /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
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 : : * Name: vchi_msg_peek
25 : : *
26 : : * Arguments: const VCHI_SERVICE_HANDLE_T handle,
27 : : * void **data,
28 : : * uint32_t *msg_size,
29 : :
30 : : * VCHI_FLAGS_T flags
31 : : *
32 : : * Description: Routine to return a pointer to the current message (to allow in
33 : : * place processing). The message can be removed using
34 : : * vchi_msg_remove when you're finished
35 : : *
36 : : * Returns: int32_t - success == 0
37 : : *
38 : : ***********************************************************/
39 : 2 : 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 : 2 : WARN_ON((flags != VCHI_FLAGS_NONE) &&
48 : : (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
49 : :
50 : 2 : if (flags == VCHI_FLAGS_NONE)
51 : 2 : if (vchiu_queue_is_empty(&service->queue))
52 : : return -1;
53 : :
54 : 2 : header = vchiu_queue_peek(&service->queue);
55 : :
56 : 2 : *data = header->data;
57 : 2 : *msg_size = header->size;
58 : :
59 : 2 : return 0;
60 : : }
61 : : EXPORT_SYMBOL(vchi_msg_peek);
62 : :
63 : : /***********************************************************
64 : : * Name: vchi_msg_remove
65 : : *
66 : : * Arguments: const VCHI_SERVICE_HANDLE_T handle,
67 : : *
68 : : * Description: Routine to remove a message (after it has been read with
69 : : * vchi_msg_peek)
70 : : *
71 : : * Returns: int32_t - success == 0
72 : : *
73 : : ***********************************************************/
74 : 2 : 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 : 2 : header = vchiu_queue_pop(&service->queue);
80 : :
81 : 2 : vchiq_release_message(service->handle, header);
82 : :
83 : 2 : return 0;
84 : : }
85 : : EXPORT_SYMBOL(vchi_msg_remove);
86 : :
87 : : /***********************************************************
88 : : * Name: vchi_msg_queue
89 : : *
90 : : * Arguments: VCHI_SERVICE_HANDLE_T handle,
91 : : * ssize_t (*copy_callback)(void *context, void *dest,
92 : : * size_t offset, size_t maxsize),
93 : : * void *context,
94 : : * uint32_t data_size
95 : : *
96 : : * Description: Thin wrapper to queue a message onto a connection
97 : : *
98 : : * Returns: int32_t - success == 0
99 : : *
100 : : ***********************************************************/
101 : : static
102 : 2 : 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 : 2 : status = vchiq_queue_message(service->handle,
113 : : copy_callback,
114 : : context,
115 : : data_size);
116 : :
117 : : /*
118 : : * vchiq_queue_message() may return VCHIQ_RETRY, so we need to
119 : : * implement a retry mechanism since this function is supposed
120 : : * to block until queued
121 : : */
122 : 2 : if (status != VCHIQ_RETRY)
123 : : break;
124 : :
125 : 0 : msleep(1);
126 : 0 : }
127 : :
128 : 2 : return vchiq_status_to_vchi(status);
129 : : }
130 : :
131 : : static ssize_t
132 : 2 : vchi_queue_kernel_message_callback(void *context,
133 : : void *dest,
134 : : size_t offset,
135 : : size_t maxsize)
136 : : {
137 : 2 : memcpy(dest, context + offset, maxsize);
138 : 2 : return maxsize;
139 : : }
140 : :
141 : : int
142 : 2 : vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
143 : : void *data,
144 : : unsigned int size)
145 : : {
146 : 2 : 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 : 0 : 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 : 0 : if (copy_from_user(dest, copycontext->data + offset, maxsize))
166 : : return -EFAULT;
167 : :
168 : 0 : return maxsize;
169 : : }
170 : :
171 : : int
172 : 0 : vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
173 : : void __user *data,
174 : : unsigned int size)
175 : : {
176 : 0 : struct vchi_queue_user_message_context copycontext = {
177 : : .data = data
178 : : };
179 : :
180 : 0 : 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 : : * Name: vchi_bulk_queue_receive
189 : : *
190 : : * Arguments: VCHI_BULK_HANDLE_T handle,
191 : : * void *data_dst,
192 : : * const uint32_t data_size,
193 : : * VCHI_FLAGS_T flags
194 : : * void *bulk_handle
195 : : *
196 : : * Description: Routine to setup a rcv buffer
197 : : *
198 : : * Returns: int32_t - success == 0
199 : : *
200 : : ***********************************************************/
201 : 0 : 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 : 0 : switch ((int)flags) {
212 : : case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
213 : : | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
214 : 0 : 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 : 0 : break;
224 : : default:
225 : 0 : WARN(1, "unsupported message\n");
226 : 0 : return vchiq_status_to_vchi(VCHIQ_ERROR);
227 : : }
228 : :
229 : : while (1) {
230 : 0 : status = vchiq_bulk_receive(service->handle, data_dst,
231 : : data_size, bulk_handle, mode);
232 : : /*
233 : : * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
234 : : * implement a retry mechanism since this function is supposed
235 : : * to block until queued
236 : : */
237 : 0 : if (status != VCHIQ_RETRY)
238 : : break;
239 : :
240 : 0 : msleep(1);
241 : 0 : }
242 : :
243 : 0 : return vchiq_status_to_vchi(status);
244 : : }
245 : : EXPORT_SYMBOL(vchi_bulk_queue_receive);
246 : :
247 : : /***********************************************************
248 : : * Name: vchi_bulk_queue_transmit
249 : : *
250 : : * Arguments: VCHI_BULK_HANDLE_T handle,
251 : : * const void *data_src,
252 : : * uint32_t data_size,
253 : : * VCHI_FLAGS_T flags,
254 : : * void *bulk_handle
255 : : *
256 : : * Description: Routine to transmit some data
257 : : *
258 : : * Returns: int32_t - success == 0
259 : : *
260 : : ***********************************************************/
261 : 0 : 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 : 0 : switch ((int)flags) {
272 : : case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
273 : : | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
274 : 0 : 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 : 0 : break;
285 : : default:
286 : 0 : WARN(1, "unsupported message\n");
287 : 0 : return vchiq_status_to_vchi(VCHIQ_ERROR);
288 : : }
289 : :
290 : : while (1) {
291 : 0 : status = vchiq_bulk_transmit(service->handle, data_src,
292 : : data_size, bulk_handle, mode);
293 : :
294 : : /*
295 : : * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
296 : : * implement a retry mechanism since this function is supposed
297 : : * to block until queued
298 : : */
299 : 0 : if (status != VCHIQ_RETRY)
300 : : break;
301 : :
302 : 0 : msleep(1);
303 : 0 : }
304 : :
305 : 0 : return vchiq_status_to_vchi(status);
306 : : }
307 : : EXPORT_SYMBOL(vchi_bulk_queue_transmit);
308 : :
309 : : /***********************************************************
310 : : * Name: vchi_msg_dequeue
311 : : *
312 : : * Arguments: VCHI_SERVICE_HANDLE_T handle,
313 : : * void *data,
314 : : * uint32_t max_data_size_to_read,
315 : : * uint32_t *actual_msg_size
316 : : * VCHI_FLAGS_T flags
317 : : *
318 : : * Description: Routine to dequeue a message into the supplied buffer
319 : : *
320 : : * Returns: int32_t - success == 0
321 : : *
322 : : ***********************************************************/
323 : 0 : 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 : 0 : WARN_ON((flags != VCHI_FLAGS_NONE) &&
333 : : (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
334 : :
335 : 0 : if (flags == VCHI_FLAGS_NONE)
336 : 0 : if (vchiu_queue_is_empty(&service->queue))
337 : : return -1;
338 : :
339 : 0 : header = vchiu_queue_pop(&service->queue);
340 : :
341 : 0 : memcpy(data, header->data, header->size < max_data_size_to_read ?
342 : 0 : header->size : max_data_size_to_read);
343 : :
344 : 0 : *actual_msg_size = header->size;
345 : :
346 : 0 : vchiq_release_message(service->handle, header);
347 : :
348 : 0 : return 0;
349 : : }
350 : : EXPORT_SYMBOL(vchi_msg_dequeue);
351 : :
352 : : /***********************************************************
353 : : * Name: vchi_held_msg_release
354 : : *
355 : : * Arguments: struct vchi_held_msg *message
356 : : *
357 : : * Description: Routine to release a held message (after it has been read with
358 : : * vchi_msg_hold)
359 : : *
360 : : * Returns: int32_t - success == 0
361 : : *
362 : : ***********************************************************/
363 : 2 : int32_t vchi_held_msg_release(struct vchi_held_msg *message)
364 : : {
365 : : /*
366 : : * Convert the service field pointer back to an
367 : : * VCHIQ_SERVICE_HANDLE_T which is an int.
368 : : * This pointer is opaque to everything except
369 : : * vchi_msg_hold which simply upcasted the int
370 : : * to a pointer.
371 : : */
372 : :
373 : 2 : vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service,
374 : 2 : (struct vchiq_header *)message->message);
375 : :
376 : 2 : return 0;
377 : : }
378 : : EXPORT_SYMBOL(vchi_held_msg_release);
379 : :
380 : : /***********************************************************
381 : : * Name: vchi_msg_hold
382 : : *
383 : : * Arguments: VCHI_SERVICE_HANDLE_T handle,
384 : : * void **data,
385 : : * uint32_t *msg_size,
386 : : * VCHI_FLAGS_T flags,
387 : : * struct vchi_held_msg *message_handle
388 : : *
389 : : * Description: Routine to return a pointer to the current message (to allow
390 : : * in place processing). The message is dequeued - don't forget
391 : : * to release the message using vchi_held_msg_release when you're
392 : : * finished.
393 : : *
394 : : * Returns: int32_t - success == 0
395 : : *
396 : : ***********************************************************/
397 : 2 : 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 : 2 : WARN_ON((flags != VCHI_FLAGS_NONE) &&
407 : : (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
408 : :
409 : 2 : if (flags == VCHI_FLAGS_NONE)
410 : 2 : if (vchiu_queue_is_empty(&service->queue))
411 : : return -1;
412 : :
413 : 2 : header = vchiu_queue_pop(&service->queue);
414 : :
415 : 2 : *data = header->data;
416 : 2 : *msg_size = header->size;
417 : :
418 : : /*
419 : : * upcast the VCHIQ_SERVICE_HANDLE_T which is an int
420 : : * to a pointer and stuff it in the held message.
421 : : * This pointer is opaque to everything except
422 : : * vchi_held_msg_release which simply downcasts it back
423 : : * to an int.
424 : : */
425 : :
426 : 2 : message_handle->service =
427 : 2 : (struct opaque_vchi_service_t *)(long)service->handle;
428 : 2 : message_handle->message = header;
429 : :
430 : 2 : return 0;
431 : : }
432 : : EXPORT_SYMBOL(vchi_msg_hold);
433 : :
434 : : /***********************************************************
435 : : * Name: vchi_initialise
436 : : *
437 : : * Arguments: VCHI_INSTANCE_T *instance_handle
438 : : *
439 : : * Description: Initialises the hardware but does not transmit anything
440 : : * When run as a Host App this will be called twice hence the need
441 : : * to malloc the state information
442 : : *
443 : : * Returns: 0 if successful, failure otherwise
444 : : *
445 : : ***********************************************************/
446 : :
447 : 2 : int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
448 : : {
449 : : VCHIQ_INSTANCE_T instance;
450 : : VCHIQ_STATUS_T status;
451 : :
452 : 2 : status = vchiq_initialise(&instance);
453 : :
454 : 2 : *instance_handle = (VCHI_INSTANCE_T)instance;
455 : :
456 : 2 : return vchiq_status_to_vchi(status);
457 : : }
458 : : EXPORT_SYMBOL(vchi_initialise);
459 : :
460 : : /***********************************************************
461 : : * Name: vchi_connect
462 : : *
463 : : * Arguments: VCHI_INSTANCE_T instance_handle
464 : : *
465 : : * Description: Starts the command service on each connection,
466 : : * causing INIT messages to be pinged back and forth
467 : : *
468 : : * Returns: 0 if successful, failure otherwise
469 : : *
470 : : ***********************************************************/
471 : 2 : int32_t vchi_connect(VCHI_INSTANCE_T instance_handle)
472 : : {
473 : : VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
474 : :
475 : 2 : return vchiq_connect(instance);
476 : : }
477 : : EXPORT_SYMBOL(vchi_connect);
478 : :
479 : : /***********************************************************
480 : : * Name: vchi_disconnect
481 : : *
482 : : * Arguments: VCHI_INSTANCE_T instance_handle
483 : : *
484 : : * Description: Stops the command service on each connection,
485 : : * causing DE-INIT messages to be pinged back and forth
486 : : *
487 : : * Returns: 0 if successful, failure otherwise
488 : : *
489 : : ***********************************************************/
490 : 0 : int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
491 : : {
492 : : VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
493 : :
494 : 0 : return vchiq_status_to_vchi(vchiq_shutdown(instance));
495 : : }
496 : : EXPORT_SYMBOL(vchi_disconnect);
497 : :
498 : : /***********************************************************
499 : : * Name: vchi_service_open
500 : : * Name: vchi_service_create
501 : : *
502 : : * Arguments: VCHI_INSTANCE_T *instance_handle
503 : : * struct service_creation *setup,
504 : : * VCHI_SERVICE_HANDLE_T *handle
505 : : *
506 : : * Description: Routine to open a service
507 : : *
508 : : * Returns: int32_t - success == 0
509 : : *
510 : : ***********************************************************/
511 : :
512 : 2 : 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 : 2 : struct shim_service *service =
518 : : (struct shim_service *)VCHIQ_GET_SERVICE_USERDATA(handle);
519 : :
520 : 2 : if (!service->callback)
521 : : goto release;
522 : :
523 : 2 : switch (reason) {
524 : : case VCHIQ_MESSAGE_AVAILABLE:
525 : 2 : vchiu_queue_push(&service->queue, header);
526 : :
527 : 2 : service->callback(service->callback_param,
528 : : VCHI_CALLBACK_MSG_AVAILABLE, NULL);
529 : :
530 : 2 : goto done;
531 : :
532 : : case VCHIQ_BULK_TRANSMIT_DONE:
533 : 0 : service->callback(service->callback_param,
534 : : VCHI_CALLBACK_BULK_SENT, bulk_user);
535 : 0 : break;
536 : :
537 : : case VCHIQ_BULK_RECEIVE_DONE:
538 : 0 : service->callback(service->callback_param,
539 : : VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
540 : 0 : break;
541 : :
542 : : case VCHIQ_SERVICE_CLOSED:
543 : 2 : service->callback(service->callback_param,
544 : : VCHI_CALLBACK_SERVICE_CLOSED, NULL);
545 : 2 : break;
546 : :
547 : : case VCHIQ_SERVICE_OPENED:
548 : : /* No equivalent VCHI reason */
549 : : break;
550 : :
551 : : case VCHIQ_BULK_TRANSMIT_ABORTED:
552 : 0 : service->callback(service->callback_param,
553 : : VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
554 : : bulk_user);
555 : 0 : break;
556 : :
557 : : case VCHIQ_BULK_RECEIVE_ABORTED:
558 : 0 : service->callback(service->callback_param,
559 : : VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
560 : : bulk_user);
561 : 0 : break;
562 : :
563 : : default:
564 : 0 : WARN(1, "not supported\n");
565 : 0 : break;
566 : : }
567 : :
568 : : release:
569 : 2 : vchiq_release_message(service->handle, header);
570 : : done:
571 : 2 : return VCHIQ_SUCCESS;
572 : : }
573 : :
574 : 2 : static struct shim_service *service_alloc(VCHIQ_INSTANCE_T instance,
575 : : struct service_creation *setup)
576 : : {
577 : 2 : struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL);
578 : :
579 : : (void)instance;
580 : :
581 : 2 : if (service) {
582 : 2 : if (vchiu_queue_init(&service->queue, 64)) {
583 : 2 : service->callback = setup->callback;
584 : 2 : service->callback_param = setup->callback_param;
585 : : } else {
586 : 0 : kfree(service);
587 : : service = NULL;
588 : : }
589 : : }
590 : :
591 : 2 : return service;
592 : : }
593 : :
594 : 2 : static void service_free(struct shim_service *service)
595 : : {
596 : 2 : if (service) {
597 : 2 : vchiu_queue_delete(&service->queue);
598 : 2 : kfree(service);
599 : : }
600 : 2 : }
601 : :
602 : 2 : 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 : 2 : struct shim_service *service = service_alloc(instance, setup);
608 : :
609 : 2 : *handle = (VCHI_SERVICE_HANDLE_T)service;
610 : :
611 : 2 : if (service) {
612 : : struct vchiq_service_params params;
613 : : VCHIQ_STATUS_T status;
614 : :
615 : 2 : memset(¶ms, 0, sizeof(params));
616 : 2 : params.fourcc = setup->service_id;
617 : 2 : params.callback = shim_callback;
618 : 2 : params.userdata = service;
619 : 2 : params.version = setup->version.version;
620 : 2 : params.version_min = setup->version.version_min;
621 : :
622 : 2 : status = vchiq_open_service(instance, ¶ms,
623 : : &service->handle);
624 : 2 : if (status != VCHIQ_SUCCESS) {
625 : 0 : service_free(service);
626 : : service = NULL;
627 : 0 : *handle = NULL;
628 : : }
629 : : }
630 : :
631 : 2 : return (service != NULL) ? 0 : -1;
632 : : }
633 : : EXPORT_SYMBOL(vchi_service_open);
634 : :
635 : 2 : 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 : 2 : if (service) {
641 : 2 : VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
642 : 2 : if (status == VCHIQ_SUCCESS)
643 : 2 : service_free(service);
644 : :
645 : : ret = vchiq_status_to_vchi(status);
646 : : }
647 : 2 : return ret;
648 : : }
649 : : EXPORT_SYMBOL(vchi_service_close);
650 : :
651 : 0 : 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 : 0 : if (service) {
657 : 0 : VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
658 : :
659 : 0 : if (status == VCHIQ_SUCCESS) {
660 : 0 : service_free(service);
661 : : service = NULL;
662 : : }
663 : :
664 : : ret = vchiq_status_to_vchi(status);
665 : : }
666 : 0 : return ret;
667 : : }
668 : : EXPORT_SYMBOL(vchi_service_destroy);
669 : :
670 : 0 : 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 : 0 : 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 : 0 : break;
685 : : default:
686 : : service = NULL;
687 : 0 : break;
688 : : }
689 : 0 : if (service) {
690 : 0 : VCHIQ_STATUS_T status =
691 : 0 : vchiq_set_service_option(service->handle,
692 : : vchiq_option,
693 : : value);
694 : :
695 : : ret = vchiq_status_to_vchi(status);
696 : : }
697 : 0 : return ret;
698 : : }
699 : : EXPORT_SYMBOL(vchi_service_set_option);
700 : :
701 : 0 : 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 : 0 : if (service) {
707 : : VCHIQ_STATUS_T status;
708 : :
709 : 0 : status = vchiq_get_peer_version(service->handle, peer_version);
710 : : ret = vchiq_status_to_vchi(status);
711 : : }
712 : 0 : return ret;
713 : : }
714 : : EXPORT_SYMBOL(vchi_get_peer_version);
715 : :
716 : : /***********************************************************
717 : : * Name: vchi_service_use
718 : : *
719 : : * Arguments: const VCHI_SERVICE_HANDLE_T handle
720 : : *
721 : : * Description: Routine to increment refcount on a service
722 : : *
723 : : * Returns: void
724 : : *
725 : : ***********************************************************/
726 : 2 : 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 : 2 : if (service)
732 : 2 : ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
733 : 2 : return ret;
734 : : }
735 : : EXPORT_SYMBOL(vchi_service_use);
736 : :
737 : : /***********************************************************
738 : : * Name: vchi_service_release
739 : : *
740 : : * Arguments: const VCHI_SERVICE_HANDLE_T handle
741 : : *
742 : : * Description: Routine to decrement refcount on a service
743 : : *
744 : : * Returns: void
745 : : *
746 : : ***********************************************************/
747 : 2 : 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 : 2 : if (service)
753 : 2 : ret = vchiq_status_to_vchi(
754 : : vchiq_release_service(service->handle));
755 : 2 : return ret;
756 : : }
757 : : EXPORT_SYMBOL(vchi_service_release);
|