PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c

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