1 1.1 jmcneill /** 2 1.1 jmcneill * Copyright (c) 2010-2012 Broadcom. All rights reserved. 3 1.1 jmcneill * 4 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 5 1.1 jmcneill * modification, are permitted provided that the following conditions 6 1.1 jmcneill * are met: 7 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 8 1.1 jmcneill * notice, this list of conditions, and the following disclaimer, 9 1.1 jmcneill * without modification. 10 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 12 1.1 jmcneill * documentation and/or other materials provided with the distribution. 13 1.1 jmcneill * 3. The names of the above-listed copyright holders may not be used 14 1.1 jmcneill * to endorse or promote products derived from this software without 15 1.1 jmcneill * specific prior written permission. 16 1.1 jmcneill * 17 1.1 jmcneill * ALTERNATIVELY, this software may be distributed under the terms of the 18 1.1 jmcneill * GNU General Public License ("GPL") version 2, as published by the Free 19 1.1 jmcneill * Software Foundation. 20 1.1 jmcneill * 21 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 1.1 jmcneill * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 1.1 jmcneill * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 1.1 jmcneill * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 1.1 jmcneill * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 jmcneill * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 1.1 jmcneill * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 1.1 jmcneill * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 1.1 jmcneill * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 1.1 jmcneill * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 jmcneill */ 33 1.1 jmcneill 34 1.1 jmcneill #include <interface/compat/vchi_bsd.h> 35 1.1 jmcneill 36 1.1 jmcneill #include "interface/vchi/vchi.h" 37 1.1 jmcneill #include "vchiq.h" 38 1.1 jmcneill #include "vchiq_core.h" 39 1.1 jmcneill 40 1.1 jmcneill #include "vchiq_util.h" 41 1.1 jmcneill 42 1.1 jmcneill #define vchiq_status_to_vchi(status) ((int32_t)status) 43 1.1 jmcneill 44 1.1 jmcneill typedef struct { 45 1.1 jmcneill VCHIQ_SERVICE_HANDLE_T handle; 46 1.1 jmcneill 47 1.1 jmcneill VCHIU_QUEUE_T queue; 48 1.1 jmcneill 49 1.1 jmcneill VCHI_CALLBACK_T callback; 50 1.1 jmcneill void *callback_param; 51 1.1 jmcneill } SHIM_SERVICE_T; 52 1.1 jmcneill 53 1.1 jmcneill /* ---------------------------------------------------------------------- 54 1.1 jmcneill * return pointer to the mphi message driver function table 55 1.1 jmcneill * -------------------------------------------------------------------- */ 56 1.1 jmcneill const VCHI_MESSAGE_DRIVER_T * 57 1.1 jmcneill vchi_mphi_message_driver_func_table(void) 58 1.1 jmcneill { 59 1.1 jmcneill return NULL; 60 1.1 jmcneill } 61 1.1 jmcneill 62 1.1 jmcneill /* ---------------------------------------------------------------------- 63 1.1 jmcneill * return a pointer to the 'single' connection driver fops 64 1.1 jmcneill * -------------------------------------------------------------------- */ 65 1.1 jmcneill const VCHI_CONNECTION_API_T * 66 1.1 jmcneill single_get_func_table(void) 67 1.1 jmcneill { 68 1.1 jmcneill return NULL; 69 1.1 jmcneill } 70 1.1 jmcneill 71 1.1 jmcneill VCHI_CONNECTION_T *vchi_create_connection( 72 1.1 jmcneill const VCHI_CONNECTION_API_T *function_table, 73 1.1 jmcneill const VCHI_MESSAGE_DRIVER_T *low_level) 74 1.1 jmcneill { 75 1.1 jmcneill (void)function_table; 76 1.1 jmcneill (void)low_level; 77 1.1 jmcneill return NULL; 78 1.1 jmcneill } 79 1.1 jmcneill 80 1.1 jmcneill /*********************************************************** 81 1.1 jmcneill * Name: vchi_msg_peek 82 1.1 jmcneill * 83 1.1 jmcneill * Arguments: const VCHI_SERVICE_HANDLE_T handle, 84 1.1 jmcneill * void **data, 85 1.1 jmcneill * uint32_t *msg_size, 86 1.1 jmcneill 87 1.1 jmcneill 88 1.1 jmcneill * VCHI_FLAGS_T flags 89 1.1 jmcneill * 90 1.1 jmcneill * Description: Routine to return a pointer to the current message (to allow in 91 1.1 jmcneill * place processing). The message can be removed using 92 1.1 jmcneill * vchi_msg_remove when you're finished 93 1.1 jmcneill * 94 1.1 jmcneill * Returns: int32_t - success == 0 95 1.1 jmcneill * 96 1.1 jmcneill ***********************************************************/ 97 1.1 jmcneill int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, 98 1.1 jmcneill void **data, 99 1.1 jmcneill uint32_t *msg_size, 100 1.1 jmcneill VCHI_FLAGS_T flags) 101 1.1 jmcneill { 102 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 103 1.1 jmcneill VCHIQ_HEADER_T *header; 104 1.1 jmcneill 105 1.1 jmcneill WARN_ON((flags != VCHI_FLAGS_NONE) && 106 1.1 jmcneill (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 107 1.1 jmcneill 108 1.1 jmcneill if (flags == VCHI_FLAGS_NONE) 109 1.1 jmcneill if (vchiu_queue_is_empty(&service->queue)) 110 1.1 jmcneill return -1; 111 1.1 jmcneill 112 1.1 jmcneill header = vchiu_queue_peek(&service->queue); 113 1.1 jmcneill 114 1.1 jmcneill *data = header->data; 115 1.1 jmcneill *msg_size = header->size; 116 1.1 jmcneill 117 1.1 jmcneill return 0; 118 1.1 jmcneill } 119 1.1 jmcneill EXPORT_SYMBOL(vchi_msg_peek); 120 1.1 jmcneill 121 1.1 jmcneill /*********************************************************** 122 1.1 jmcneill * Name: vchi_msg_remove 123 1.1 jmcneill * 124 1.1 jmcneill * Arguments: const VCHI_SERVICE_HANDLE_T handle, 125 1.1 jmcneill * 126 1.1 jmcneill * Description: Routine to remove a message (after it has been read with 127 1.1 jmcneill * vchi_msg_peek) 128 1.1 jmcneill * 129 1.1 jmcneill * Returns: int32_t - success == 0 130 1.1 jmcneill * 131 1.1 jmcneill ***********************************************************/ 132 1.1 jmcneill int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) 133 1.1 jmcneill { 134 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 135 1.1 jmcneill VCHIQ_HEADER_T *header; 136 1.1 jmcneill 137 1.1 jmcneill header = vchiu_queue_pop(&service->queue); 138 1.1 jmcneill 139 1.1 jmcneill vchiq_release_message(service->handle, header); 140 1.1 jmcneill 141 1.1 jmcneill return 0; 142 1.1 jmcneill } 143 1.1 jmcneill EXPORT_SYMBOL(vchi_msg_remove); 144 1.1 jmcneill 145 1.1 jmcneill /*********************************************************** 146 1.1 jmcneill * Name: vchi_msg_queue 147 1.1 jmcneill * 148 1.1 jmcneill * Arguments: VCHI_SERVICE_HANDLE_T handle, 149 1.1 jmcneill * const void *data, 150 1.1 jmcneill * uint32_t data_size, 151 1.1 jmcneill * VCHI_FLAGS_T flags, 152 1.1 jmcneill * void *msg_handle, 153 1.1 jmcneill * 154 1.1 jmcneill * Description: Thin wrapper to queue a message onto a connection 155 1.1 jmcneill * 156 1.1 jmcneill * Returns: int32_t - success == 0 157 1.1 jmcneill * 158 1.1 jmcneill ***********************************************************/ 159 1.1 jmcneill int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, 160 1.1 jmcneill const void *data, 161 1.1 jmcneill uint32_t data_size, 162 1.1 jmcneill VCHI_FLAGS_T flags, 163 1.1 jmcneill void *msg_handle) 164 1.1 jmcneill { 165 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 166 1.1 jmcneill VCHIQ_ELEMENT_T element = {data, data_size}; 167 1.1 jmcneill VCHIQ_STATUS_T status; 168 1.1 jmcneill 169 1.1 jmcneill (void)msg_handle; 170 1.1 jmcneill 171 1.1 jmcneill WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 172 1.1 jmcneill 173 1.1 jmcneill status = vchiq_queue_message(service->handle, &element, 1); 174 1.1 jmcneill 175 1.1 jmcneill /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to 176 1.1 jmcneill ** implement a retry mechanism since this function is supposed 177 1.1 jmcneill ** to block until queued 178 1.1 jmcneill */ 179 1.1 jmcneill while (status == VCHIQ_RETRY) { 180 1.1 jmcneill msleep(1); 181 1.1 jmcneill status = vchiq_queue_message(service->handle, &element, 1); 182 1.1 jmcneill } 183 1.1 jmcneill 184 1.1 jmcneill return vchiq_status_to_vchi(status); 185 1.1 jmcneill } 186 1.1 jmcneill EXPORT_SYMBOL(vchi_msg_queue); 187 1.1 jmcneill 188 1.1 jmcneill /*********************************************************** 189 1.1 jmcneill * Name: vchi_bulk_queue_receive 190 1.1 jmcneill * 191 1.1 jmcneill * Arguments: VCHI_BULK_HANDLE_T handle, 192 1.1 jmcneill * void *data_dst, 193 1.1 jmcneill * const uint32_t data_size, 194 1.1 jmcneill * VCHI_FLAGS_T flags 195 1.1 jmcneill * void *bulk_handle 196 1.1 jmcneill * 197 1.1 jmcneill * Description: Routine to setup a rcv buffer 198 1.1 jmcneill * 199 1.1 jmcneill * Returns: int32_t - success == 0 200 1.1 jmcneill * 201 1.1 jmcneill ***********************************************************/ 202 1.1 jmcneill int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, 203 1.1 jmcneill void *data_dst, 204 1.1 jmcneill uint32_t data_size, 205 1.1 jmcneill VCHI_FLAGS_T flags, 206 1.1 jmcneill void *bulk_handle) 207 1.1 jmcneill { 208 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 209 1.1 jmcneill VCHIQ_BULK_MODE_T mode; 210 1.1 jmcneill VCHIQ_STATUS_T status; 211 1.1 jmcneill 212 1.1 jmcneill switch ((int)flags) { 213 1.1 jmcneill case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 214 1.1 jmcneill | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 215 1.1 jmcneill WARN_ON(!service->callback); 216 1.1 jmcneill mode = VCHIQ_BULK_MODE_CALLBACK; 217 1.1 jmcneill break; 218 1.1 jmcneill case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 219 1.1 jmcneill mode = VCHIQ_BULK_MODE_BLOCKING; 220 1.1 jmcneill break; 221 1.1 jmcneill case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 222 1.1 jmcneill case VCHI_FLAGS_NONE: 223 1.1 jmcneill mode = VCHIQ_BULK_MODE_NOCALLBACK; 224 1.1 jmcneill break; 225 1.1 jmcneill default: 226 1.1 jmcneill WARN(1, "unsupported message\n"); 227 1.1 jmcneill return vchiq_status_to_vchi(VCHIQ_ERROR); 228 1.1 jmcneill } 229 1.1 jmcneill 230 1.1 jmcneill status = vchiq_bulk_receive(service->handle, data_dst, data_size, 231 1.1 jmcneill bulk_handle, mode); 232 1.1 jmcneill 233 1.1 jmcneill /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to 234 1.1 jmcneill ** implement a retry mechanism since this function is supposed 235 1.1 jmcneill ** to block until queued 236 1.1 jmcneill */ 237 1.1 jmcneill while (status == VCHIQ_RETRY) { 238 1.1 jmcneill msleep(1); 239 1.1 jmcneill status = vchiq_bulk_receive(service->handle, data_dst, 240 1.1 jmcneill data_size, bulk_handle, mode); 241 1.1 jmcneill } 242 1.1 jmcneill 243 1.1 jmcneill return vchiq_status_to_vchi(status); 244 1.1 jmcneill } 245 1.1 jmcneill EXPORT_SYMBOL(vchi_bulk_queue_receive); 246 1.1 jmcneill 247 1.1 jmcneill /*********************************************************** 248 1.1 jmcneill * Name: vchi_bulk_queue_transmit 249 1.1 jmcneill * 250 1.1 jmcneill * Arguments: VCHI_BULK_HANDLE_T handle, 251 1.2 skrll * void *data_src, 252 1.1 jmcneill * uint32_t data_size, 253 1.1 jmcneill * VCHI_FLAGS_T flags, 254 1.1 jmcneill * void *bulk_handle 255 1.1 jmcneill * 256 1.1 jmcneill * Description: Routine to transmit some data 257 1.1 jmcneill * 258 1.1 jmcneill * Returns: int32_t - success == 0 259 1.1 jmcneill * 260 1.1 jmcneill ***********************************************************/ 261 1.1 jmcneill int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, 262 1.1 jmcneill void *data_src, 263 1.1 jmcneill uint32_t data_size, 264 1.1 jmcneill VCHI_FLAGS_T flags, 265 1.1 jmcneill void *bulk_handle) 266 1.1 jmcneill { 267 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 268 1.1 jmcneill VCHIQ_BULK_MODE_T mode; 269 1.1 jmcneill VCHIQ_STATUS_T status; 270 1.1 jmcneill 271 1.1 jmcneill switch ((int)flags) { 272 1.1 jmcneill case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 273 1.1 jmcneill | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 274 1.1 jmcneill WARN_ON(!service->callback); 275 1.1 jmcneill mode = VCHIQ_BULK_MODE_CALLBACK; 276 1.1 jmcneill break; 277 1.1 jmcneill case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: 278 1.1 jmcneill case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 279 1.1 jmcneill mode = VCHIQ_BULK_MODE_BLOCKING; 280 1.1 jmcneill break; 281 1.1 jmcneill case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 282 1.1 jmcneill case VCHI_FLAGS_NONE: 283 1.1 jmcneill mode = VCHIQ_BULK_MODE_NOCALLBACK; 284 1.1 jmcneill break; 285 1.1 jmcneill default: 286 1.1 jmcneill WARN(1, "unsupported message\n"); 287 1.1 jmcneill return vchiq_status_to_vchi(VCHIQ_ERROR); 288 1.1 jmcneill } 289 1.1 jmcneill 290 1.1 jmcneill status = vchiq_bulk_transmit(service->handle, data_src, data_size, 291 1.1 jmcneill bulk_handle, mode); 292 1.1 jmcneill 293 1.1 jmcneill /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to 294 1.1 jmcneill ** implement a retry mechanism since this function is supposed 295 1.1 jmcneill ** to block until queued 296 1.1 jmcneill */ 297 1.1 jmcneill while (status == VCHIQ_RETRY) { 298 1.1 jmcneill msleep(1); 299 1.1 jmcneill status = vchiq_bulk_transmit(service->handle, data_src, 300 1.1 jmcneill data_size, bulk_handle, mode); 301 1.1 jmcneill } 302 1.1 jmcneill 303 1.1 jmcneill return vchiq_status_to_vchi(status); 304 1.1 jmcneill } 305 1.1 jmcneill EXPORT_SYMBOL(vchi_bulk_queue_transmit); 306 1.1 jmcneill 307 1.1 jmcneill /*********************************************************** 308 1.1 jmcneill * Name: vchi_msg_dequeue 309 1.1 jmcneill * 310 1.1 jmcneill * Arguments: VCHI_SERVICE_HANDLE_T handle, 311 1.1 jmcneill * void *data, 312 1.1 jmcneill * uint32_t max_data_size_to_read, 313 1.1 jmcneill * uint32_t *actual_msg_size 314 1.1 jmcneill * VCHI_FLAGS_T flags 315 1.1 jmcneill * 316 1.1 jmcneill * Description: Routine to dequeue a message into the supplied buffer 317 1.1 jmcneill * 318 1.1 jmcneill * Returns: int32_t - success == 0 319 1.1 jmcneill * 320 1.1 jmcneill ***********************************************************/ 321 1.1 jmcneill int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, 322 1.1 jmcneill void *data, 323 1.1 jmcneill uint32_t max_data_size_to_read, 324 1.1 jmcneill uint32_t *actual_msg_size, 325 1.1 jmcneill VCHI_FLAGS_T flags) 326 1.1 jmcneill { 327 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 328 1.1 jmcneill VCHIQ_HEADER_T *header; 329 1.1 jmcneill 330 1.1 jmcneill WARN_ON((flags != VCHI_FLAGS_NONE) && 331 1.1 jmcneill (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 332 1.1 jmcneill 333 1.1 jmcneill if (flags == VCHI_FLAGS_NONE) 334 1.1 jmcneill if (vchiu_queue_is_empty(&service->queue)) 335 1.1 jmcneill return -1; 336 1.1 jmcneill 337 1.1 jmcneill header = vchiu_queue_pop(&service->queue); 338 1.1 jmcneill 339 1.1 jmcneill memcpy(data, header->data, header->size < max_data_size_to_read ? 340 1.1 jmcneill header->size : max_data_size_to_read); 341 1.1 jmcneill 342 1.1 jmcneill *actual_msg_size = header->size; 343 1.1 jmcneill 344 1.1 jmcneill vchiq_release_message(service->handle, header); 345 1.1 jmcneill 346 1.1 jmcneill return 0; 347 1.1 jmcneill } 348 1.1 jmcneill EXPORT_SYMBOL(vchi_msg_dequeue); 349 1.1 jmcneill 350 1.1 jmcneill /*********************************************************** 351 1.1 jmcneill * Name: vchi_msg_queuev 352 1.1 jmcneill * 353 1.1 jmcneill * Arguments: VCHI_SERVICE_HANDLE_T handle, 354 1.1 jmcneill * VCHI_MSG_VECTOR_T *vector, 355 1.1 jmcneill * uint32_t count, 356 1.1 jmcneill * VCHI_FLAGS_T flags, 357 1.1 jmcneill * void *msg_handle 358 1.1 jmcneill * 359 1.1 jmcneill * Description: Thin wrapper to queue a message onto a connection 360 1.1 jmcneill * 361 1.1 jmcneill * Returns: int32_t - success == 0 362 1.1 jmcneill * 363 1.1 jmcneill ***********************************************************/ 364 1.1 jmcneill 365 1.1 jmcneill vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); 366 1.1 jmcneill vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == 367 1.1 jmcneill offsetof(VCHIQ_ELEMENT_T, data)); 368 1.1 jmcneill vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == 369 1.1 jmcneill offsetof(VCHIQ_ELEMENT_T, size)); 370 1.1 jmcneill 371 1.1 jmcneill int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, 372 1.1 jmcneill VCHI_MSG_VECTOR_T *vector, 373 1.1 jmcneill uint32_t count, 374 1.1 jmcneill VCHI_FLAGS_T flags, 375 1.1 jmcneill void *msg_handle) 376 1.1 jmcneill { 377 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 378 1.1 jmcneill 379 1.1 jmcneill (void)msg_handle; 380 1.1 jmcneill 381 1.1 jmcneill WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 382 1.1 jmcneill 383 1.1 jmcneill return vchiq_status_to_vchi(vchiq_queue_message(service->handle, 384 1.1 jmcneill (const VCHIQ_ELEMENT_T *)vector, count)); 385 1.1 jmcneill } 386 1.1 jmcneill EXPORT_SYMBOL(vchi_msg_queuev); 387 1.1 jmcneill 388 1.1 jmcneill /*********************************************************** 389 1.1 jmcneill * Name: vchi_held_msg_release 390 1.1 jmcneill * 391 1.7 mlelstv * Arguments: VCHI_HELD_MSG_T *message_handle 392 1.1 jmcneill * 393 1.1 jmcneill * Description: Routine to release a held message (after it has been read with 394 1.1 jmcneill * vchi_msg_hold) 395 1.1 jmcneill * 396 1.1 jmcneill * Returns: int32_t - success == 0 397 1.1 jmcneill * 398 1.1 jmcneill ***********************************************************/ 399 1.7 mlelstv int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message_handle) 400 1.1 jmcneill { 401 1.7 mlelstv SHIM_SERVICE_T *service; 402 1.7 mlelstv VCHIQ_HEADER_T *header; 403 1.7 mlelstv 404 1.7 mlelstv service = (SHIM_SERVICE_T *)message_handle->service; 405 1.7 mlelstv header = (VCHIQ_HEADER_T *)message_handle->message; 406 1.7 mlelstv 407 1.7 mlelstv vchiq_release_message(service->handle, header); 408 1.1 jmcneill 409 1.1 jmcneill return 0; 410 1.1 jmcneill } 411 1.6 skrll EXPORT_SYMBOL(vchi_held_msg_release); 412 1.1 jmcneill 413 1.1 jmcneill /*********************************************************** 414 1.1 jmcneill * Name: vchi_msg_hold 415 1.1 jmcneill * 416 1.1 jmcneill * Arguments: VCHI_SERVICE_HANDLE_T handle, 417 1.1 jmcneill * void **data, 418 1.1 jmcneill * uint32_t *msg_size, 419 1.1 jmcneill * VCHI_FLAGS_T flags, 420 1.1 jmcneill * VCHI_HELD_MSG_T *message_handle 421 1.1 jmcneill * 422 1.1 jmcneill * Description: Routine to return a pointer to the current message (to allow 423 1.1 jmcneill * in place processing). The message is dequeued - don't forget 424 1.1 jmcneill * to release the message using vchi_held_msg_release when you're 425 1.1 jmcneill * finished. 426 1.1 jmcneill * 427 1.1 jmcneill * Returns: int32_t - success == 0 428 1.1 jmcneill * 429 1.1 jmcneill ***********************************************************/ 430 1.1 jmcneill int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, 431 1.1 jmcneill void **data, 432 1.1 jmcneill uint32_t *msg_size, 433 1.1 jmcneill VCHI_FLAGS_T flags, 434 1.1 jmcneill VCHI_HELD_MSG_T *message_handle) 435 1.1 jmcneill { 436 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 437 1.1 jmcneill VCHIQ_HEADER_T *header; 438 1.1 jmcneill 439 1.1 jmcneill WARN_ON((flags != VCHI_FLAGS_NONE) && 440 1.1 jmcneill (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 441 1.1 jmcneill 442 1.1 jmcneill if (flags == VCHI_FLAGS_NONE) 443 1.1 jmcneill if (vchiu_queue_is_empty(&service->queue)) 444 1.1 jmcneill return -1; 445 1.1 jmcneill 446 1.1 jmcneill header = vchiu_queue_pop(&service->queue); 447 1.1 jmcneill 448 1.1 jmcneill *data = header->data; 449 1.1 jmcneill *msg_size = header->size; 450 1.1 jmcneill 451 1.1 jmcneill message_handle->service = 452 1.7 mlelstv (struct opaque_vchi_service_t *)(uintptr_t)service->handle; 453 1.1 jmcneill message_handle->message = header; 454 1.1 jmcneill 455 1.1 jmcneill return 0; 456 1.1 jmcneill } 457 1.6 skrll EXPORT_SYMBOL(vchi_msg_hold); 458 1.1 jmcneill 459 1.1 jmcneill /*********************************************************** 460 1.1 jmcneill * Name: vchi_initialise 461 1.1 jmcneill * 462 1.1 jmcneill * Arguments: VCHI_INSTANCE_T *instance_handle 463 1.1 jmcneill * 464 1.1 jmcneill * Description: Initialises the hardware but does not transmit anything 465 1.1 jmcneill * When run as a Host App this will be called twice hence the need 466 1.1 jmcneill * to malloc the state information 467 1.1 jmcneill * 468 1.1 jmcneill * Returns: 0 if successful, failure otherwise 469 1.1 jmcneill * 470 1.1 jmcneill ***********************************************************/ 471 1.1 jmcneill 472 1.1 jmcneill int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) 473 1.1 jmcneill { 474 1.1 jmcneill VCHIQ_INSTANCE_T instance; 475 1.1 jmcneill VCHIQ_STATUS_T status; 476 1.1 jmcneill 477 1.1 jmcneill status = vchiq_initialise(&instance); 478 1.1 jmcneill 479 1.1 jmcneill *instance_handle = (VCHI_INSTANCE_T)instance; 480 1.1 jmcneill 481 1.1 jmcneill return vchiq_status_to_vchi(status); 482 1.1 jmcneill } 483 1.1 jmcneill EXPORT_SYMBOL(vchi_initialise); 484 1.1 jmcneill 485 1.1 jmcneill /*********************************************************** 486 1.1 jmcneill * Name: vchi_connect 487 1.1 jmcneill * 488 1.1 jmcneill * Arguments: VCHI_CONNECTION_T **connections 489 1.1 jmcneill * const uint32_t num_connections 490 1.1 jmcneill * VCHI_INSTANCE_T instance_handle) 491 1.1 jmcneill * 492 1.1 jmcneill * Description: Starts the command service on each connection, 493 1.1 jmcneill * causing INIT messages to be pinged back and forth 494 1.1 jmcneill * 495 1.1 jmcneill * Returns: 0 if successful, failure otherwise 496 1.1 jmcneill * 497 1.1 jmcneill ***********************************************************/ 498 1.1 jmcneill int32_t vchi_connect(VCHI_CONNECTION_T **connections, 499 1.1 jmcneill const uint32_t num_connections, 500 1.1 jmcneill VCHI_INSTANCE_T instance_handle) 501 1.1 jmcneill { 502 1.1 jmcneill VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 503 1.1 jmcneill 504 1.1 jmcneill (void)connections; 505 1.1 jmcneill (void)num_connections; 506 1.1 jmcneill 507 1.1 jmcneill return vchiq_connect(instance); 508 1.1 jmcneill } 509 1.1 jmcneill EXPORT_SYMBOL(vchi_connect); 510 1.1 jmcneill 511 1.1 jmcneill 512 1.1 jmcneill /*********************************************************** 513 1.1 jmcneill * Name: vchi_disconnect 514 1.1 jmcneill * 515 1.1 jmcneill * Arguments: VCHI_INSTANCE_T instance_handle 516 1.1 jmcneill * 517 1.1 jmcneill * Description: Stops the command service on each connection, 518 1.1 jmcneill * causing DE-INIT messages to be pinged back and forth 519 1.1 jmcneill * 520 1.1 jmcneill * Returns: 0 if successful, failure otherwise 521 1.1 jmcneill * 522 1.1 jmcneill ***********************************************************/ 523 1.1 jmcneill int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) 524 1.1 jmcneill { 525 1.1 jmcneill VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 526 1.1 jmcneill return vchiq_status_to_vchi(vchiq_shutdown(instance)); 527 1.1 jmcneill } 528 1.1 jmcneill EXPORT_SYMBOL(vchi_disconnect); 529 1.1 jmcneill 530 1.1 jmcneill 531 1.1 jmcneill /*********************************************************** 532 1.1 jmcneill * Name: vchi_service_open 533 1.1 jmcneill * Name: vchi_service_create 534 1.1 jmcneill * 535 1.1 jmcneill * Arguments: VCHI_INSTANCE_T *instance_handle 536 1.1 jmcneill * SERVICE_CREATION_T *setup, 537 1.1 jmcneill * VCHI_SERVICE_HANDLE_T *handle 538 1.1 jmcneill * 539 1.1 jmcneill * Description: Routine to open a service 540 1.1 jmcneill * 541 1.1 jmcneill * Returns: int32_t - success == 0 542 1.1 jmcneill * 543 1.1 jmcneill ***********************************************************/ 544 1.1 jmcneill 545 1.1 jmcneill static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, 546 1.1 jmcneill VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) 547 1.1 jmcneill { 548 1.1 jmcneill SHIM_SERVICE_T *service = 549 1.1 jmcneill (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); 550 1.1 jmcneill 551 1.3 skrll if (!service->callback) 552 1.3 skrll goto release; 553 1.3 skrll 554 1.1 jmcneill switch (reason) { 555 1.1 jmcneill case VCHIQ_MESSAGE_AVAILABLE: 556 1.1 jmcneill vchiu_queue_push(&service->queue, header); 557 1.1 jmcneill 558 1.3 skrll service->callback(service->callback_param, 559 1.3 skrll VCHI_CALLBACK_MSG_AVAILABLE, NULL); 560 1.3 skrll 561 1.3 skrll goto done; 562 1.1 jmcneill break; 563 1.3 skrll 564 1.1 jmcneill case VCHIQ_BULK_TRANSMIT_DONE: 565 1.3 skrll service->callback(service->callback_param, 566 1.3 skrll VCHI_CALLBACK_BULK_SENT, bulk_user); 567 1.1 jmcneill break; 568 1.3 skrll 569 1.1 jmcneill case VCHIQ_BULK_RECEIVE_DONE: 570 1.3 skrll service->callback(service->callback_param, 571 1.3 skrll VCHI_CALLBACK_BULK_RECEIVED, bulk_user); 572 1.1 jmcneill break; 573 1.3 skrll 574 1.1 jmcneill case VCHIQ_SERVICE_CLOSED: 575 1.3 skrll service->callback(service->callback_param, 576 1.3 skrll VCHI_CALLBACK_SERVICE_CLOSED, NULL); 577 1.1 jmcneill break; 578 1.3 skrll 579 1.1 jmcneill case VCHIQ_SERVICE_OPENED: 580 1.1 jmcneill /* No equivalent VCHI reason */ 581 1.1 jmcneill break; 582 1.3 skrll 583 1.1 jmcneill case VCHIQ_BULK_TRANSMIT_ABORTED: 584 1.3 skrll service->callback(service->callback_param, 585 1.3 skrll VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, 586 1.3 skrll bulk_user); 587 1.1 jmcneill break; 588 1.3 skrll 589 1.1 jmcneill case VCHIQ_BULK_RECEIVE_ABORTED: 590 1.3 skrll service->callback(service->callback_param, 591 1.3 skrll VCHI_CALLBACK_BULK_RECEIVE_ABORTED, 592 1.3 skrll bulk_user); 593 1.1 jmcneill break; 594 1.3 skrll 595 1.1 jmcneill default: 596 1.1 jmcneill WARN(1, "not supported\n"); 597 1.1 jmcneill break; 598 1.1 jmcneill } 599 1.1 jmcneill 600 1.3 skrll release: 601 1.3 skrll vchiq_release_message(service->handle, header); 602 1.3 skrll done: 603 1.1 jmcneill return VCHIQ_SUCCESS; 604 1.1 jmcneill } 605 1.1 jmcneill 606 1.1 jmcneill static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, 607 1.1 jmcneill SERVICE_CREATION_T *setup) 608 1.1 jmcneill { 609 1.1 jmcneill SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); 610 1.1 jmcneill 611 1.1 jmcneill (void)instance; 612 1.1 jmcneill 613 1.1 jmcneill if (service) { 614 1.1 jmcneill if (vchiu_queue_init(&service->queue, 64)) { 615 1.1 jmcneill service->callback = setup->callback; 616 1.1 jmcneill service->callback_param = setup->callback_param; 617 1.1 jmcneill } else { 618 1.1 jmcneill kfree(service); 619 1.1 jmcneill service = NULL; 620 1.1 jmcneill } 621 1.1 jmcneill } 622 1.1 jmcneill 623 1.1 jmcneill return service; 624 1.1 jmcneill } 625 1.1 jmcneill 626 1.1 jmcneill static void service_free(SHIM_SERVICE_T *service) 627 1.1 jmcneill { 628 1.1 jmcneill if (service) { 629 1.1 jmcneill vchiu_queue_delete(&service->queue); 630 1.1 jmcneill kfree(service); 631 1.1 jmcneill } 632 1.1 jmcneill } 633 1.1 jmcneill 634 1.1 jmcneill int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, 635 1.1 jmcneill SERVICE_CREATION_T *setup, 636 1.1 jmcneill VCHI_SERVICE_HANDLE_T *handle) 637 1.1 jmcneill { 638 1.1 jmcneill VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 639 1.1 jmcneill SHIM_SERVICE_T *service = service_alloc(instance, setup); 640 1.4 jmcneill 641 1.4 jmcneill *handle = (VCHI_SERVICE_HANDLE_T)service; 642 1.4 jmcneill 643 1.1 jmcneill if (service) { 644 1.1 jmcneill VCHIQ_SERVICE_PARAMS_T params; 645 1.1 jmcneill VCHIQ_STATUS_T status; 646 1.1 jmcneill 647 1.1 jmcneill memset(¶ms, 0, sizeof(params)); 648 1.1 jmcneill params.fourcc = setup->service_id; 649 1.1 jmcneill params.callback = shim_callback; 650 1.1 jmcneill params.userdata = service; 651 1.1 jmcneill params.version = setup->version.version; 652 1.1 jmcneill params.version_min = setup->version.version_min; 653 1.1 jmcneill 654 1.1 jmcneill status = vchiq_open_service(instance, ¶ms, 655 1.1 jmcneill &service->handle); 656 1.1 jmcneill if (status != VCHIQ_SUCCESS) { 657 1.1 jmcneill service_free(service); 658 1.1 jmcneill service = NULL; 659 1.4 jmcneill *handle = NULL; 660 1.1 jmcneill } 661 1.1 jmcneill } 662 1.1 jmcneill 663 1.1 jmcneill return (service != NULL) ? 0 : -1; 664 1.1 jmcneill } 665 1.1 jmcneill EXPORT_SYMBOL(vchi_service_open); 666 1.1 jmcneill 667 1.1 jmcneill int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, 668 1.1 jmcneill SERVICE_CREATION_T *setup, 669 1.1 jmcneill VCHI_SERVICE_HANDLE_T *handle) 670 1.1 jmcneill { 671 1.1 jmcneill VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 672 1.1 jmcneill SHIM_SERVICE_T *service = service_alloc(instance, setup); 673 1.4 jmcneill 674 1.4 jmcneill *handle = (VCHI_SERVICE_HANDLE_T)service; 675 1.4 jmcneill 676 1.1 jmcneill if (service) { 677 1.1 jmcneill VCHIQ_SERVICE_PARAMS_T params; 678 1.1 jmcneill VCHIQ_STATUS_T status; 679 1.1 jmcneill 680 1.1 jmcneill memset(¶ms, 0, sizeof(params)); 681 1.1 jmcneill params.fourcc = setup->service_id; 682 1.1 jmcneill params.callback = shim_callback; 683 1.1 jmcneill params.userdata = service; 684 1.1 jmcneill params.version = setup->version.version; 685 1.1 jmcneill params.version_min = setup->version.version_min; 686 1.1 jmcneill status = vchiq_add_service(instance, ¶ms, &service->handle); 687 1.1 jmcneill 688 1.1 jmcneill if (status != VCHIQ_SUCCESS) { 689 1.1 jmcneill service_free(service); 690 1.1 jmcneill service = NULL; 691 1.4 jmcneill *handle = NULL; 692 1.1 jmcneill } 693 1.1 jmcneill } 694 1.1 jmcneill 695 1.1 jmcneill return (service != NULL) ? 0 : -1; 696 1.1 jmcneill } 697 1.1 jmcneill EXPORT_SYMBOL(vchi_service_create); 698 1.1 jmcneill 699 1.1 jmcneill int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) 700 1.1 jmcneill { 701 1.1 jmcneill int32_t ret = -1; 702 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 703 1.1 jmcneill if (service) { 704 1.1 jmcneill VCHIQ_STATUS_T status = vchiq_close_service(service->handle); 705 1.1 jmcneill if (status == VCHIQ_SUCCESS) { 706 1.1 jmcneill service_free(service); 707 1.1 jmcneill service = NULL; 708 1.1 jmcneill } 709 1.1 jmcneill 710 1.1 jmcneill ret = vchiq_status_to_vchi(status); 711 1.1 jmcneill } 712 1.1 jmcneill return ret; 713 1.1 jmcneill } 714 1.1 jmcneill EXPORT_SYMBOL(vchi_service_close); 715 1.1 jmcneill 716 1.1 jmcneill int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) 717 1.1 jmcneill { 718 1.1 jmcneill int32_t ret = -1; 719 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 720 1.1 jmcneill if (service) { 721 1.1 jmcneill VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); 722 1.1 jmcneill if (status == VCHIQ_SUCCESS) { 723 1.1 jmcneill service_free(service); 724 1.1 jmcneill service = NULL; 725 1.1 jmcneill } 726 1.1 jmcneill 727 1.1 jmcneill ret = vchiq_status_to_vchi(status); 728 1.1 jmcneill } 729 1.1 jmcneill return ret; 730 1.1 jmcneill } 731 1.1 jmcneill EXPORT_SYMBOL(vchi_service_destroy); 732 1.1 jmcneill 733 1.6 skrll int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, 734 1.6 skrll VCHI_SERVICE_OPTION_T option, 735 1.6 skrll int value) 736 1.6 skrll { 737 1.6 skrll int32_t ret = -1; 738 1.6 skrll SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 739 1.6 skrll VCHIQ_SERVICE_OPTION_T vchiq_option; 740 1.6 skrll switch (option) { 741 1.6 skrll case VCHI_SERVICE_OPTION_TRACE: 742 1.6 skrll vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; 743 1.6 skrll break; 744 1.6 skrll case VCHI_SERVICE_OPTION_SYNCHRONOUS: 745 1.6 skrll vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; 746 1.6 skrll break; 747 1.6 skrll default: 748 1.6 skrll service = NULL; 749 1.6 skrll break; 750 1.6 skrll } 751 1.6 skrll if (service) { 752 1.6 skrll VCHIQ_STATUS_T status = 753 1.6 skrll vchiq_set_service_option(service->handle, 754 1.6 skrll vchiq_option, 755 1.6 skrll value); 756 1.6 skrll 757 1.6 skrll ret = vchiq_status_to_vchi(status); 758 1.6 skrll } 759 1.6 skrll return ret; 760 1.6 skrll } 761 1.6 skrll EXPORT_SYMBOL(vchi_service_set_option); 762 1.6 skrll 763 1.1 jmcneill int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) 764 1.1 jmcneill { 765 1.1 jmcneill int32_t ret = -1; 766 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 767 1.1 jmcneill if(service) 768 1.1 jmcneill { 769 1.1 jmcneill VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); 770 1.1 jmcneill ret = vchiq_status_to_vchi( status ); 771 1.1 jmcneill } 772 1.1 jmcneill return ret; 773 1.1 jmcneill } 774 1.1 jmcneill EXPORT_SYMBOL(vchi_get_peer_version); 775 1.1 jmcneill 776 1.5 jmcneill #if notyet 777 1.1 jmcneill /* ---------------------------------------------------------------------- 778 1.3 skrll * read a uint32_t from buffer. 779 1.3 skrll * network format is defined to be little endian 780 1.3 skrll * -------------------------------------------------------------------- */ 781 1.3 skrll uint32_t 782 1.3 skrll vchi_readbuf_uint32(const void *_ptr) 783 1.3 skrll { 784 1.3 skrll const unsigned char *ptr = _ptr; 785 1.3 skrll return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 786 1.3 skrll } 787 1.3 skrll 788 1.3 skrll /* ---------------------------------------------------------------------- 789 1.1 jmcneill * write a uint32_t to buffer. 790 1.1 jmcneill * network format is defined to be little endian 791 1.1 jmcneill * -------------------------------------------------------------------- */ 792 1.3 skrll void 793 1.1 jmcneill vchi_writebuf_uint32(void *_ptr, uint32_t value) 794 1.1 jmcneill { 795 1.1 jmcneill unsigned char *ptr = _ptr; 796 1.1 jmcneill ptr[0] = (unsigned char)((value >> 0) & 0xFF); 797 1.1 jmcneill ptr[1] = (unsigned char)((value >> 8) & 0xFF); 798 1.1 jmcneill ptr[2] = (unsigned char)((value >> 16) & 0xFF); 799 1.1 jmcneill ptr[3] = (unsigned char)((value >> 24) & 0xFF); 800 1.1 jmcneill } 801 1.1 jmcneill 802 1.1 jmcneill /* ---------------------------------------------------------------------- 803 1.1 jmcneill * read a uint16_t from buffer. 804 1.1 jmcneill * network format is defined to be little endian 805 1.1 jmcneill * -------------------------------------------------------------------- */ 806 1.3 skrll uint16_t 807 1.1 jmcneill vchi_readbuf_uint16(const void *_ptr) 808 1.1 jmcneill { 809 1.1 jmcneill const unsigned char *ptr = _ptr; 810 1.1 jmcneill return ptr[0] | (ptr[1] << 8); 811 1.1 jmcneill } 812 1.1 jmcneill 813 1.1 jmcneill /* ---------------------------------------------------------------------- 814 1.1 jmcneill * write a uint16_t into the buffer. 815 1.1 jmcneill * network format is defined to be little endian 816 1.1 jmcneill * -------------------------------------------------------------------- */ 817 1.3 skrll void 818 1.1 jmcneill vchi_writebuf_uint16(void *_ptr, uint16_t value) 819 1.1 jmcneill { 820 1.1 jmcneill unsigned char *ptr = _ptr; 821 1.1 jmcneill ptr[0] = (value >> 0) & 0xFF; 822 1.1 jmcneill ptr[1] = (value >> 8) & 0xFF; 823 1.1 jmcneill } 824 1.1 jmcneill #endif 825 1.1 jmcneill 826 1.1 jmcneill /*********************************************************** 827 1.1 jmcneill * Name: vchi_service_use 828 1.1 jmcneill * 829 1.1 jmcneill * Arguments: const VCHI_SERVICE_HANDLE_T handle 830 1.1 jmcneill * 831 1.1 jmcneill * Description: Routine to increment refcount on a service 832 1.1 jmcneill * 833 1.1 jmcneill * Returns: void 834 1.1 jmcneill * 835 1.1 jmcneill ***********************************************************/ 836 1.1 jmcneill int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) 837 1.1 jmcneill { 838 1.1 jmcneill int32_t ret = -1; 839 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 840 1.1 jmcneill if (service) 841 1.1 jmcneill ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); 842 1.1 jmcneill return ret; 843 1.1 jmcneill } 844 1.1 jmcneill EXPORT_SYMBOL(vchi_service_use); 845 1.1 jmcneill 846 1.1 jmcneill /*********************************************************** 847 1.1 jmcneill * Name: vchi_service_release 848 1.1 jmcneill * 849 1.1 jmcneill * Arguments: const VCHI_SERVICE_HANDLE_T handle 850 1.1 jmcneill * 851 1.1 jmcneill * Description: Routine to decrement refcount on a service 852 1.1 jmcneill * 853 1.1 jmcneill * Returns: void 854 1.1 jmcneill * 855 1.1 jmcneill ***********************************************************/ 856 1.1 jmcneill int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) 857 1.1 jmcneill { 858 1.1 jmcneill int32_t ret = -1; 859 1.1 jmcneill SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 860 1.1 jmcneill if (service) 861 1.1 jmcneill ret = vchiq_status_to_vchi( 862 1.1 jmcneill vchiq_release_service(service->handle)); 863 1.1 jmcneill return ret; 864 1.1 jmcneill } 865 1.1 jmcneill EXPORT_SYMBOL(vchi_service_release); 866