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