2 * Copyright (c) 2010-2012 Broadcom. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions, and the following disclaimer,
9 * without modification.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The names of the above-listed copyright holders may not be used
14 * to endorse or promote products derived from this software without
15 * specific prior written permission.
17 * ALTERNATIVELY, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2, as published by the Free
19 * Software Foundation.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <linux/module.h>
34 #include <linux/types.h>
36 #include "interface/vchi/vchi.h"
38 #include "vchiq_core.h"
40 #include "vchiq_util.h"
44 #define vchiq_status_to_vchi(status) ((int32_t)status)
47 VCHIQ_SERVICE_HANDLE_T handle;
51 VCHI_CALLBACK_T callback;
55 /* ----------------------------------------------------------------------
56 * return pointer to the mphi message driver function table
57 * -------------------------------------------------------------------- */
58 const VCHI_MESSAGE_DRIVER_T *
59 vchi_mphi_message_driver_func_table(void)
64 /* ----------------------------------------------------------------------
65 * return a pointer to the 'single' connection driver fops
66 * -------------------------------------------------------------------- */
67 const VCHI_CONNECTION_API_T *
68 single_get_func_table(void)
73 VCHI_CONNECTION_T *vchi_create_connection(
74 const VCHI_CONNECTION_API_T *function_table,
75 const VCHI_MESSAGE_DRIVER_T *low_level)
82 /***********************************************************
85 * Arguments: const VCHI_SERVICE_HANDLE_T handle,
92 * Description: Routine to return a pointer to the current message (to allow in
93 * place processing). The message can be removed using
94 * vchi_msg_remove when you're finished
96 * Returns: int32_t - success == 0
98 ***********************************************************/
99 int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
104 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
105 VCHIQ_HEADER_T *header;
107 WARN_ON((flags != VCHI_FLAGS_NONE) &&
108 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
110 if (flags == VCHI_FLAGS_NONE)
111 if (vchiu_queue_is_empty(&service->queue))
114 header = vchiu_queue_peek(&service->queue);
116 *data = header->data;
117 *msg_size = header->size;
121 EXPORT_SYMBOL(vchi_msg_peek);
123 /***********************************************************
124 * Name: vchi_msg_remove
126 * Arguments: const VCHI_SERVICE_HANDLE_T handle,
128 * Description: Routine to remove a message (after it has been read with
131 * Returns: int32_t - success == 0
133 ***********************************************************/
134 int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
136 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
137 VCHIQ_HEADER_T *header;
139 header = vchiu_queue_pop(&service->queue);
141 vchiq_release_message(service->handle, header);
145 EXPORT_SYMBOL(vchi_msg_remove);
147 /***********************************************************
148 * Name: vchi_msg_queue
150 * Arguments: VCHI_SERVICE_HANDLE_T handle,
151 * ssize_t (*copy_callback)(void *context, void *dest,
152 * size_t offset, size_t maxsize),
156 * Description: Thin wrapper to queue a message onto a connection
158 * Returns: int32_t - success == 0
160 ***********************************************************/
162 int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
163 ssize_t (*copy_callback)(void *context, void *dest,
164 size_t offset, size_t maxsize),
168 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
169 VCHIQ_STATUS_T status;
172 status = vchiq_queue_message(service->handle,
178 * vchiq_queue_message() may return VCHIQ_RETRY, so we need to
179 * implement a retry mechanism since this function is supposed
180 * to block until queued
182 if (status != VCHIQ_RETRY)
188 return vchiq_status_to_vchi(status);
192 vchi_queue_kernel_message_callback(void *context,
197 memcpy(dest, context + offset, maxsize);
202 vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
206 return vchi_msg_queue(handle,
207 vchi_queue_kernel_message_callback,
211 EXPORT_SYMBOL(vchi_queue_kernel_message);
213 struct vchi_queue_user_message_context {
218 vchi_queue_user_message_callback(void *context,
223 struct vchi_queue_user_message_context *copycontext = context;
225 if (copy_from_user(dest, copycontext->data + offset, maxsize))
232 vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
236 struct vchi_queue_user_message_context copycontext = {
240 return vchi_msg_queue(handle,
241 vchi_queue_user_message_callback,
245 EXPORT_SYMBOL(vchi_queue_user_message);
247 /***********************************************************
248 * Name: vchi_bulk_queue_receive
250 * Arguments: VCHI_BULK_HANDLE_T handle,
252 * const uint32_t data_size,
256 * Description: Routine to setup a rcv buffer
258 * Returns: int32_t - success == 0
260 ***********************************************************/
261 int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,
267 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
268 VCHIQ_BULK_MODE_T mode;
269 VCHIQ_STATUS_T status;
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;
277 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
278 mode = VCHIQ_BULK_MODE_BLOCKING;
280 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
281 case VCHI_FLAGS_NONE:
282 mode = VCHIQ_BULK_MODE_NOCALLBACK;
285 WARN(1, "unsupported message\n");
286 return vchiq_status_to_vchi(VCHIQ_ERROR);
290 status = vchiq_bulk_receive(service->handle, data_dst,
291 data_size, bulk_handle, mode);
293 * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
294 * implement a retry mechanism since this function is supposed
295 * to block until queued
297 if (status != VCHIQ_RETRY)
303 return vchiq_status_to_vchi(status);
305 EXPORT_SYMBOL(vchi_bulk_queue_receive);
307 /***********************************************************
308 * Name: vchi_bulk_queue_transmit
310 * Arguments: VCHI_BULK_HANDLE_T handle,
311 * const void *data_src,
312 * uint32_t data_size,
313 * VCHI_FLAGS_T flags,
316 * Description: Routine to transmit some data
318 * Returns: int32_t - success == 0
320 ***********************************************************/
321 int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,
322 const void *data_src,
327 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
328 VCHIQ_BULK_MODE_T mode;
329 VCHIQ_STATUS_T status;
331 switch ((int)flags) {
332 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
333 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
334 WARN_ON(!service->callback);
335 mode = VCHIQ_BULK_MODE_CALLBACK;
337 case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
338 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
339 mode = VCHIQ_BULK_MODE_BLOCKING;
341 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
342 case VCHI_FLAGS_NONE:
343 mode = VCHIQ_BULK_MODE_NOCALLBACK;
346 WARN(1, "unsupported message\n");
347 return vchiq_status_to_vchi(VCHIQ_ERROR);
351 status = vchiq_bulk_transmit(service->handle, data_src,
352 data_size, bulk_handle, mode);
355 * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
356 * implement a retry mechanism since this function is supposed
357 * to block until queued
359 if (status != VCHIQ_RETRY)
365 return vchiq_status_to_vchi(status);
367 EXPORT_SYMBOL(vchi_bulk_queue_transmit);
369 /***********************************************************
370 * Name: vchi_msg_dequeue
372 * Arguments: VCHI_SERVICE_HANDLE_T handle,
374 * uint32_t max_data_size_to_read,
375 * uint32_t *actual_msg_size
378 * Description: Routine to dequeue a message into the supplied buffer
380 * Returns: int32_t - success == 0
382 ***********************************************************/
383 int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
385 uint32_t max_data_size_to_read,
386 uint32_t *actual_msg_size,
389 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
390 VCHIQ_HEADER_T *header;
392 WARN_ON((flags != VCHI_FLAGS_NONE) &&
393 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
395 if (flags == VCHI_FLAGS_NONE)
396 if (vchiu_queue_is_empty(&service->queue))
399 header = vchiu_queue_pop(&service->queue);
401 memcpy(data, header->data, header->size < max_data_size_to_read ?
402 header->size : max_data_size_to_read);
404 *actual_msg_size = header->size;
406 vchiq_release_message(service->handle, header);
410 EXPORT_SYMBOL(vchi_msg_dequeue);
412 /***********************************************************
413 * Name: vchi_held_msg_release
415 * Arguments: VCHI_HELD_MSG_T *message
417 * Description: Routine to release a held message (after it has been read with
420 * Returns: int32_t - success == 0
422 ***********************************************************/
423 int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)
426 * Convert the service field pointer back to an
427 * VCHIQ_SERVICE_HANDLE_T which is an int.
428 * This pointer is opaque to everything except
429 * vchi_msg_hold which simply upcasted the int
433 vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service,
434 (VCHIQ_HEADER_T *)message->message);
438 EXPORT_SYMBOL(vchi_held_msg_release);
440 /***********************************************************
441 * Name: vchi_msg_hold
443 * Arguments: VCHI_SERVICE_HANDLE_T handle,
445 * uint32_t *msg_size,
446 * VCHI_FLAGS_T flags,
447 * VCHI_HELD_MSG_T *message_handle
449 * Description: Routine to return a pointer to the current message (to allow
450 * in place processing). The message is dequeued - don't forget
451 * to release the message using vchi_held_msg_release when you're
454 * Returns: int32_t - success == 0
456 ***********************************************************/
457 int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
461 VCHI_HELD_MSG_T *message_handle)
463 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
464 VCHIQ_HEADER_T *header;
466 WARN_ON((flags != VCHI_FLAGS_NONE) &&
467 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
469 if (flags == VCHI_FLAGS_NONE)
470 if (vchiu_queue_is_empty(&service->queue))
473 header = vchiu_queue_pop(&service->queue);
475 *data = header->data;
476 *msg_size = header->size;
479 * upcast the VCHIQ_SERVICE_HANDLE_T which is an int
480 * to a pointer and stuff it in the held message.
481 * This pointer is opaque to everything except
482 * vchi_held_msg_release which simply downcasts it back
486 message_handle->service =
487 (struct opaque_vchi_service_t *)(long)service->handle;
488 message_handle->message = header;
492 EXPORT_SYMBOL(vchi_msg_hold);
494 /***********************************************************
495 * Name: vchi_initialise
497 * Arguments: VCHI_INSTANCE_T *instance_handle
499 * Description: Initialises the hardware but does not transmit anything
500 * When run as a Host App this will be called twice hence the need
501 * to malloc the state information
503 * Returns: 0 if successful, failure otherwise
505 ***********************************************************/
507 int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
509 VCHIQ_INSTANCE_T instance;
510 VCHIQ_STATUS_T status;
512 status = vchiq_initialise(&instance);
514 *instance_handle = (VCHI_INSTANCE_T)instance;
516 return vchiq_status_to_vchi(status);
518 EXPORT_SYMBOL(vchi_initialise);
520 /***********************************************************
523 * Arguments: VCHI_CONNECTION_T **connections
524 * const uint32_t num_connections
525 * VCHI_INSTANCE_T instance_handle)
527 * Description: Starts the command service on each connection,
528 * causing INIT messages to be pinged back and forth
530 * Returns: 0 if successful, failure otherwise
532 ***********************************************************/
533 int32_t vchi_connect(VCHI_CONNECTION_T **connections,
534 const uint32_t num_connections,
535 VCHI_INSTANCE_T instance_handle)
537 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
540 (void)num_connections;
542 return vchiq_connect(instance);
544 EXPORT_SYMBOL(vchi_connect);
547 /***********************************************************
548 * Name: vchi_disconnect
550 * Arguments: VCHI_INSTANCE_T instance_handle
552 * Description: Stops the command service on each connection,
553 * causing DE-INIT messages to be pinged back and forth
555 * Returns: 0 if successful, failure otherwise
557 ***********************************************************/
558 int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
560 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
561 return vchiq_status_to_vchi(vchiq_shutdown(instance));
563 EXPORT_SYMBOL(vchi_disconnect);
566 /***********************************************************
567 * Name: vchi_service_open
568 * Name: vchi_service_create
570 * Arguments: VCHI_INSTANCE_T *instance_handle
571 * SERVICE_CREATION_T *setup,
572 * VCHI_SERVICE_HANDLE_T *handle
574 * Description: Routine to open a service
576 * Returns: int32_t - success == 0
578 ***********************************************************/
580 static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
581 VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)
583 SHIM_SERVICE_T *service =
584 (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);
586 if (!service->callback)
590 case VCHIQ_MESSAGE_AVAILABLE:
591 vchiu_queue_push(&service->queue, header);
593 service->callback(service->callback_param,
594 VCHI_CALLBACK_MSG_AVAILABLE, NULL);
599 case VCHIQ_BULK_TRANSMIT_DONE:
600 service->callback(service->callback_param,
601 VCHI_CALLBACK_BULK_SENT, bulk_user);
604 case VCHIQ_BULK_RECEIVE_DONE:
605 service->callback(service->callback_param,
606 VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
609 case VCHIQ_SERVICE_CLOSED:
610 service->callback(service->callback_param,
611 VCHI_CALLBACK_SERVICE_CLOSED, NULL);
614 case VCHIQ_SERVICE_OPENED:
615 /* No equivalent VCHI reason */
618 case VCHIQ_BULK_TRANSMIT_ABORTED:
619 service->callback(service->callback_param,
620 VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
624 case VCHIQ_BULK_RECEIVE_ABORTED:
625 service->callback(service->callback_param,
626 VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
631 WARN(1, "not supported\n");
636 vchiq_release_message(service->handle, header);
638 return VCHIQ_SUCCESS;
641 static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
642 SERVICE_CREATION_T *setup)
644 SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);
649 if (vchiu_queue_init(&service->queue, 64)) {
650 service->callback = setup->callback;
651 service->callback_param = setup->callback_param;
661 static void service_free(SHIM_SERVICE_T *service)
664 vchiu_queue_delete(&service->queue);
669 int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
670 SERVICE_CREATION_T *setup,
671 VCHI_SERVICE_HANDLE_T *handle)
673 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
674 SHIM_SERVICE_T *service = service_alloc(instance, setup);
676 *handle = (VCHI_SERVICE_HANDLE_T)service;
679 VCHIQ_SERVICE_PARAMS_T params;
680 VCHIQ_STATUS_T status;
682 memset(¶ms, 0, sizeof(params));
683 params.fourcc = setup->service_id;
684 params.callback = shim_callback;
685 params.userdata = service;
686 params.version = setup->version.version;
687 params.version_min = setup->version.version_min;
689 status = vchiq_open_service(instance, ¶ms,
691 if (status != VCHIQ_SUCCESS) {
692 service_free(service);
698 return (service != NULL) ? 0 : -1;
700 EXPORT_SYMBOL(vchi_service_open);
702 int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,
703 SERVICE_CREATION_T *setup,
704 VCHI_SERVICE_HANDLE_T *handle)
706 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
707 SHIM_SERVICE_T *service = service_alloc(instance, setup);
709 *handle = (VCHI_SERVICE_HANDLE_T)service;
712 VCHIQ_SERVICE_PARAMS_T params;
713 VCHIQ_STATUS_T status;
715 memset(¶ms, 0, sizeof(params));
716 params.fourcc = setup->service_id;
717 params.callback = shim_callback;
718 params.userdata = service;
719 params.version = setup->version.version;
720 params.version_min = setup->version.version_min;
721 status = vchiq_add_service(instance, ¶ms, &service->handle);
723 if (status != VCHIQ_SUCCESS) {
724 service_free(service);
730 return (service != NULL) ? 0 : -1;
732 EXPORT_SYMBOL(vchi_service_create);
734 int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
737 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
739 VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
740 if (status == VCHIQ_SUCCESS) {
741 service_free(service);
745 ret = vchiq_status_to_vchi(status);
749 EXPORT_SYMBOL(vchi_service_close);
751 int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
754 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
756 VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
757 if (status == VCHIQ_SUCCESS) {
758 service_free(service);
762 ret = vchiq_status_to_vchi(status);
766 EXPORT_SYMBOL(vchi_service_destroy);
768 int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
769 VCHI_SERVICE_OPTION_T option,
773 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
774 VCHIQ_SERVICE_OPTION_T vchiq_option;
776 case VCHI_SERVICE_OPTION_TRACE:
777 vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
779 case VCHI_SERVICE_OPTION_SYNCHRONOUS:
780 vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS;
787 VCHIQ_STATUS_T status =
788 vchiq_set_service_option(service->handle,
792 ret = vchiq_status_to_vchi(status);
796 EXPORT_SYMBOL(vchi_service_set_option);
798 int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, short *peer_version)
801 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
804 VCHIQ_STATUS_T status;
806 status = vchiq_get_peer_version(service->handle, peer_version);
807 ret = vchiq_status_to_vchi(status);
811 EXPORT_SYMBOL(vchi_get_peer_version);
813 /* ----------------------------------------------------------------------
814 * read a uint32_t from buffer.
815 * network format is defined to be little endian
816 * -------------------------------------------------------------------- */
818 vchi_readbuf_uint32(const void *_ptr)
820 const unsigned char *ptr = _ptr;
821 return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
824 /* ----------------------------------------------------------------------
825 * write a uint32_t to buffer.
826 * network format is defined to be little endian
827 * -------------------------------------------------------------------- */
829 vchi_writebuf_uint32(void *_ptr, uint32_t value)
831 unsigned char *ptr = _ptr;
832 ptr[0] = (unsigned char)((value >> 0) & 0xFF);
833 ptr[1] = (unsigned char)((value >> 8) & 0xFF);
834 ptr[2] = (unsigned char)((value >> 16) & 0xFF);
835 ptr[3] = (unsigned char)((value >> 24) & 0xFF);
838 /* ----------------------------------------------------------------------
839 * read a uint16_t from buffer.
840 * network format is defined to be little endian
841 * -------------------------------------------------------------------- */
843 vchi_readbuf_uint16(const void *_ptr)
845 const unsigned char *ptr = _ptr;
846 return ptr[0] | (ptr[1] << 8);
849 /* ----------------------------------------------------------------------
850 * write a uint16_t into the buffer.
851 * network format is defined to be little endian
852 * -------------------------------------------------------------------- */
854 vchi_writebuf_uint16(void *_ptr, uint16_t value)
856 unsigned char *ptr = _ptr;
857 ptr[0] = (value >> 0) & 0xFF;
858 ptr[1] = (value >> 8) & 0xFF;
861 /***********************************************************
862 * Name: vchi_service_use
864 * Arguments: const VCHI_SERVICE_HANDLE_T handle
866 * Description: Routine to increment refcount on a service
870 ***********************************************************/
871 int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
874 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
876 ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
879 EXPORT_SYMBOL(vchi_service_use);
881 /***********************************************************
882 * Name: vchi_service_release
884 * Arguments: const VCHI_SERVICE_HANDLE_T handle
886 * Description: Routine to decrement refcount on a service
890 ***********************************************************/
891 int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
894 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
896 ret = vchiq_status_to_vchi(
897 vchiq_release_service(service->handle));
900 EXPORT_SYMBOL(vchi_service_release);