diff options
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c')
-rw-r--r-- | drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c | 617 |
1 files changed, 0 insertions, 617 deletions
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c deleted file mode 100644 index 75d87b6992c4..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ /dev/null @@ -1,617 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ -#include <linux/module.h> -#include <linux/types.h> - -#include "../vchi/vchi.h" -#include "vchiq.h" -#include "vchiq_core.h" - -#include "vchiq_util.h" - -struct shim_service { - unsigned int handle; - - struct vchiu_queue queue; - - vchi_callback callback; - void *callback_param; -}; - -/*********************************************************** - * Name: vchi_msg_peek - * - * Arguments: struct vchi_service_handle *handle, - * void **data, - * uint32_t *msg_size, - - * enum vchi_flags flags - * - * Description: Routine to return a pointer to the current message (to allow in - * place processing). The message can be removed using - * vchi_msg_remove when you're finished - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_peek(struct vchi_service_handle *handle, - void **data, - uint32_t *msg_size, - enum vchi_flags flags) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_peek(&service->queue); - - *data = header->data; - *msg_size = header->size; - - return 0; -} -EXPORT_SYMBOL(vchi_msg_peek); - -/*********************************************************** - * Name: vchi_msg_remove - * - * Arguments: struct vchi_service_handle *handle, - * - * Description: Routine to remove a message (after it has been read with - * vchi_msg_peek) - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_remove(struct vchi_service_handle *handle) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - header = vchiu_queue_pop(&service->queue); - - vchiq_release_message(service->handle, header); - - return 0; -} -EXPORT_SYMBOL(vchi_msg_remove); - -int vchi_queue_kernel_message(struct vchi_service_handle *handle, void *data, - unsigned int size) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_status status; - - while (1) { - status = vchiq_queue_kernel_message(service->handle, data, - size); - - /* - * vchiq_queue_message() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_queue_kernel_message); - -/*********************************************************** - * Name: vchi_bulk_queue_receive - * - * Arguments: VCHI_BULK_HANDLE_T handle, - * void *data_dst, - * const uint32_t data_size, - * enum vchi_flags flags - * void *bulk_handle - * - * Description: Routine to setup a rcv buffer - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_bulk_queue_receive(struct vchi_service_handle *handle, void *data_dst, - uint32_t data_size, enum vchi_flags flags, - void *bulk_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_bulk_mode mode; - enum vchiq_status status; - - switch ((int)flags) { - case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE - | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - WARN_ON(!service->callback); - mode = VCHIQ_BULK_MODE_CALLBACK; - break; - case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: - mode = VCHIQ_BULK_MODE_BLOCKING; - break; - case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - case VCHI_FLAGS_NONE: - mode = VCHIQ_BULK_MODE_NOCALLBACK; - break; - default: - WARN(1, "unsupported message\n"); - return VCHIQ_ERROR; - } - - while (1) { - status = vchiq_bulk_receive(service->handle, data_dst, - data_size, bulk_handle, mode); - /* - * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_bulk_queue_receive); - -/*********************************************************** - * Name: vchi_bulk_queue_transmit - * - * Arguments: VCHI_BULK_HANDLE_T handle, - * const void *data_src, - * uint32_t data_size, - * enum vchi_flags flags, - * void *bulk_handle - * - * Description: Routine to transmit some data - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_bulk_queue_transmit(struct vchi_service_handle *handle, - const void *data_src, - uint32_t data_size, - enum vchi_flags flags, - void *bulk_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_bulk_mode mode; - enum vchiq_status status; - - switch ((int)flags) { - case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE - | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - WARN_ON(!service->callback); - mode = VCHIQ_BULK_MODE_CALLBACK; - break; - case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: - case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: - mode = VCHIQ_BULK_MODE_BLOCKING; - break; - case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - case VCHI_FLAGS_NONE: - mode = VCHIQ_BULK_MODE_NOCALLBACK; - break; - default: - WARN(1, "unsupported message\n"); - return VCHIQ_ERROR; - } - - while (1) { - status = vchiq_bulk_transmit(service->handle, data_src, - data_size, bulk_handle, mode); - - /* - * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_bulk_queue_transmit); - -/*********************************************************** - * Name: vchi_msg_dequeue - * - * Arguments: struct vchi_service_handle *handle, - * void *data, - * uint32_t max_data_size_to_read, - * uint32_t *actual_msg_size - * enum vchi_flags flags - * - * Description: Routine to dequeue a message into the supplied buffer - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_dequeue(struct vchi_service_handle *handle, void *data, - uint32_t max_data_size_to_read, - uint32_t *actual_msg_size, enum vchi_flags flags) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_pop(&service->queue); - - memcpy(data, header->data, header->size < max_data_size_to_read ? - header->size : max_data_size_to_read); - - *actual_msg_size = header->size; - - vchiq_release_message(service->handle, header); - - return 0; -} -EXPORT_SYMBOL(vchi_msg_dequeue); - -/*********************************************************** - * Name: vchi_held_msg_release - * - * Arguments: struct vchi_held_msg *message - * - * Description: Routine to release a held message (after it has been read with - * vchi_msg_hold) - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_held_msg_release(struct vchi_held_msg *message) -{ - /* - * Convert the service field pointer back to an - * unsigned int which is an int. - * This pointer is opaque to everything except - * vchi_msg_hold which simply upcasted the int - * to a pointer. - */ - - vchiq_release_message((unsigned int)(long)message->service, - (struct vchiq_header *)message->message); - - return 0; -} -EXPORT_SYMBOL(vchi_held_msg_release); - -/*********************************************************** - * Name: vchi_msg_hold - * - * Arguments: struct vchi_service_handle *handle, - * void **data, - * uint32_t *msg_size, - * enum vchi_flags flags, - * struct vchi_held_msg *message_handle - * - * Description: Routine to return a pointer to the current message (to allow - * in place processing). The message is dequeued - don't forget - * to release the message using vchi_held_msg_release when you're - * finished. - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_hold(struct vchi_service_handle *handle, void **data, - uint32_t *msg_size, enum vchi_flags flags, - struct vchi_held_msg *message_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_pop(&service->queue); - - *data = header->data; - *msg_size = header->size; - - /* - * upcast the unsigned int which is an int - * to a pointer and stuff it in the held message. - * This pointer is opaque to everything except - * vchi_held_msg_release which simply downcasts it back - * to an int. - */ - - message_handle->service = - (struct opaque_vchi_service_t *)(long)service->handle; - message_handle->message = header; - - return 0; -} -EXPORT_SYMBOL(vchi_msg_hold); - -/*********************************************************** - * Name: vchi_initialise - * - * Arguments: struct vchi_instance_handle **instance_handle - * - * Description: Initialises the hardware but does not transmit anything - * When run as a Host App this will be called twice hence the need - * to malloc the state information - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ - -int32_t vchi_initialise(struct vchi_instance_handle **instance_handle) -{ - struct vchiq_instance *instance; - enum vchiq_status status; - - status = vchiq_initialise(&instance); - - *instance_handle = (struct vchi_instance_handle *)instance; - - return status; -} -EXPORT_SYMBOL(vchi_initialise); - -/*********************************************************** - * Name: vchi_connect - * - * Arguments: struct vchi_instance_handle *instance_handle - * - * Description: Starts the command service on each connection, - * causing INIT messages to be pinged back and forth - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ -int32_t vchi_connect(struct vchi_instance_handle *instance_handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - - return vchiq_connect(instance); -} -EXPORT_SYMBOL(vchi_connect); - -/*********************************************************** - * Name: vchi_disconnect - * - * Arguments: struct vchi_instance_handle *instance_handle - * - * Description: Stops the command service on each connection, - * causing DE-INIT messages to be pinged back and forth - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ -int32_t vchi_disconnect(struct vchi_instance_handle *instance_handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - - return vchiq_shutdown(instance); -} -EXPORT_SYMBOL(vchi_disconnect); - -/*********************************************************** - * Name: vchi_service_open - * Name: vchi_service_create - * - * Arguments: struct vchi_instance_handle *instance_handle - * struct service_creation *setup, - * struct vchi_service_handle **handle - * - * Description: Routine to open a service - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ - -static enum vchiq_status shim_callback(enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *bulk_user) -{ - struct shim_service *service = - (struct shim_service *)VCHIQ_GET_SERVICE_USERDATA(handle); - - if (!service->callback) - goto release; - - switch (reason) { - case VCHIQ_MESSAGE_AVAILABLE: - vchiu_queue_push(&service->queue, header); - - service->callback(service->callback_param, - VCHI_CALLBACK_MSG_AVAILABLE, NULL); - - break; - - case VCHIQ_BULK_TRANSMIT_DONE: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_SENT, bulk_user); - break; - - case VCHIQ_BULK_RECEIVE_DONE: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_RECEIVED, bulk_user); - break; - - case VCHIQ_SERVICE_CLOSED: - service->callback(service->callback_param, - VCHI_CALLBACK_SERVICE_CLOSED, NULL); - break; - - case VCHIQ_BULK_TRANSMIT_ABORTED: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, - bulk_user); - break; - - case VCHIQ_BULK_RECEIVE_ABORTED: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_RECEIVE_ABORTED, - bulk_user); - break; - - default: - WARN(1, "not supported\n"); - break; - } - -release: - return VCHIQ_SUCCESS; -} - -static struct shim_service *service_alloc(struct vchiq_instance *instance, - struct service_creation *setup) -{ - struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL); - - (void)instance; - - if (service) { - if (!vchiu_queue_init(&service->queue, 64)) { - service->callback = setup->callback; - service->callback_param = setup->callback_param; - } else { - kfree(service); - service = NULL; - } - } - - return service; -} - -static void service_free(struct shim_service *service) -{ - if (service) { - vchiu_queue_delete(&service->queue); - kfree(service); - } -} - -int32_t vchi_service_open(struct vchi_instance_handle *instance_handle, - struct service_creation *setup, - struct vchi_service_handle **handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - struct shim_service *service = service_alloc(instance, setup); - - *handle = (struct vchi_service_handle *)service; - - if (service) { - struct vchiq_service_params params; - enum vchiq_status status; - - memset(¶ms, 0, sizeof(params)); - params.fourcc = setup->service_id; - params.callback = shim_callback; - params.userdata = service; - params.version = setup->version.version; - params.version_min = setup->version.version_min; - - status = vchiq_open_service(instance, ¶ms, - &service->handle); - if (status != VCHIQ_SUCCESS) { - service_free(service); - service = NULL; - *handle = NULL; - } - } - - return service ? 0 : -1; -} -EXPORT_SYMBOL(vchi_service_open); - -int32_t vchi_service_close(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - struct shim_service *service = (struct shim_service *)handle; - - if (service) { - enum vchiq_status status = vchiq_close_service(service->handle); - if (status == VCHIQ_SUCCESS) - service_free(service); - - ret = status; - } - return ret; -} -EXPORT_SYMBOL(vchi_service_close); - -int32_t vchi_get_peer_version(const struct vchi_service_handle *handle, short *peer_version) -{ - int32_t ret = -1; - struct shim_service *service = (struct shim_service *)handle; - - if (service) { - enum vchiq_status status; - - status = vchiq_get_peer_version(service->handle, peer_version); - ret = status; - } - return ret; -} -EXPORT_SYMBOL(vchi_get_peer_version); - -/*********************************************************** - * Name: vchi_service_use - * - * Arguments: const struct vchi_service_handle *handle - * - * Description: Routine to increment refcount on a service - * - * Returns: void - * - ***********************************************************/ -int32_t vchi_service_use(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - - struct shim_service *service = (struct shim_service *)handle; - if (service) - ret = vchiq_use_service(service->handle); - return ret; -} -EXPORT_SYMBOL(vchi_service_use); - -/*********************************************************** - * Name: vchi_service_release - * - * Arguments: const struct vchi_service_handle *handle - * - * Description: Routine to decrement refcount on a service - * - * Returns: void - * - ***********************************************************/ -int32_t vchi_service_release(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - - struct shim_service *service = (struct shim_service *)handle; - if (service) - ret = vchiq_release_service(service->handle); - return ret; -} -EXPORT_SYMBOL(vchi_service_release); |