diff options
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c')
-rw-r--r-- | drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 942 |
1 files changed, 440 insertions, 502 deletions
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 45de21c210c1..064d0db4c51e 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -44,18 +44,18 @@ #include <linux/highmem.h> #include <linux/pagemap.h> #include <linux/bug.h> -#include <linux/semaphore.h> +#include <linux/completion.h> #include <linux/list.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/compat.h> +#include <linux/dma-mapping.h> #include <soc/bcm2835/raspberrypi-firmware.h> #include "vchiq_core.h" #include "vchiq_ioctl.h" #include "vchiq_arm.h" #include "vchiq_debugfs.h" -#include "vchiq_killable.h" #define DEVICE_NAME "vchiq" @@ -63,8 +63,6 @@ #undef MODULE_PARAM_PREFIX #define MODULE_PARAM_PREFIX DEVICE_NAME "." -#define VCHIQ_MINOR 0 - /* Some per-instance constants */ #define MAX_COMPLETIONS 128 #define MAX_SERVICES 64 @@ -111,8 +109,8 @@ static const char *const resume_state_names[] = { static void suspend_timer_callback(struct timer_list *t); -typedef struct user_service_struct { - VCHIQ_SERVICE_T *service; +struct user_service { + struct vchiq_service *service; void *userdata; VCHIQ_INSTANCE_T instance; char is_vchi; @@ -121,11 +119,11 @@ typedef struct user_service_struct { int message_available_pos; int msg_insert; int msg_remove; - struct semaphore insert_event; - struct semaphore remove_event; - struct semaphore close_event; - VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; -} USER_SERVICE_T; + struct completion insert_event; + struct completion remove_event; + struct completion close_event; + struct vchiq_header *msg_queue[MSG_QUEUE_SIZE]; +}; struct bulk_waiter_node { struct bulk_waiter bulk_waiter; @@ -134,12 +132,12 @@ struct bulk_waiter_node { }; struct vchiq_instance_struct { - VCHIQ_STATE_T *state; - VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; + struct vchiq_state *state; + struct vchiq_completion_data completions[MAX_COMPLETIONS]; int completion_insert; int completion_remove; - struct semaphore insert_event; - struct semaphore remove_event; + struct completion insert_event; + struct completion remove_event; struct mutex completion_mutex; int connected; @@ -152,23 +150,23 @@ struct vchiq_instance_struct { struct list_head bulk_waiter_list; struct mutex bulk_waiter_list_mutex; - VCHIQ_DEBUGFS_NODE_T debugfs_node; + struct vchiq_debugfs_node debugfs_node; }; -typedef struct dump_context_struct { +struct dump_context { char __user *buf; size_t actual; size_t space; loff_t offset; -} DUMP_CONTEXT_T; +}; static struct cdev vchiq_cdev; static dev_t vchiq_devid; -static VCHIQ_STATE_T g_state; +static struct vchiq_state g_state; static struct class *vchiq_class; -static struct device *vchiq_dev; static DEFINE_SPINLOCK(msg_queue_spinlock); static struct platform_device *bcm2835_camera; +static struct platform_device *bcm2835_audio; static struct vchiq_drvdata bcm2835_drvdata = { .cache_line_size = 32, @@ -210,7 +208,7 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_STATE_T *state; + struct vchiq_state *state; VCHIQ_INSTANCE_T instance = NULL; int i; @@ -263,7 +261,7 @@ EXPORT_SYMBOL(vchiq_initialise); VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; + struct vchiq_state *state = instance->state; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -280,16 +278,11 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) "%s(%p): returning %d", __func__, instance, status); if (status == VCHIQ_SUCCESS) { - struct list_head *pos, *next; + struct bulk_waiter_node *waiter, *next; - list_for_each_safe(pos, next, - &instance->bulk_waiter_list) { - struct bulk_waiter_node *waiter; - - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry_safe(waiter, next, + &instance->bulk_waiter_list, list) { + list_del(&waiter->list); vchiq_log_info(vchiq_arm_log_level, "bulk_waiter - cleaned up %pK for pid %d", waiter, waiter->pid); @@ -310,7 +303,7 @@ static int vchiq_is_connected(VCHIQ_INSTANCE_T instance) VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; + struct vchiq_state *state = instance->state; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -338,12 +331,12 @@ EXPORT_SYMBOL(vchiq_connect); VCHIQ_STATUS_T vchiq_add_service( VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *phandle) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_state *state = instance->state; + struct vchiq_service *service = NULL; int srvstate; vchiq_log_trace(vchiq_core_log_level, @@ -377,12 +370,12 @@ EXPORT_SYMBOL(vchiq_add_service); VCHIQ_STATUS_T vchiq_open_service( VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *phandle) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_STATE_T *state = instance->state; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_state *state = instance->state; + struct vchiq_service *service = NULL; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -424,9 +417,9 @@ vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, - VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, - mode, VCHIQ_BULK_TRANSMIT); + status = vchiq_bulk_transfer(handle, (void *)data, size, + userdata, mode, + VCHIQ_BULK_TRANSMIT); break; case VCHIQ_BULK_MODE_BLOCKING: status = vchiq_blocking_bulk_transfer(handle, @@ -449,9 +442,8 @@ vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, - VCHI_MEM_HANDLE_INVALID, data, size, userdata, - mode, VCHIQ_BULK_RECEIVE); + status = vchiq_bulk_transfer(handle, data, size, userdata, + mode, VCHIQ_BULK_RECEIVE); break; case VCHIQ_BULK_MODE_BLOCKING: status = vchiq_blocking_bulk_transfer(handle, @@ -470,10 +462,9 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, unsigned int size, VCHIQ_BULK_DIR_T dir) { VCHIQ_INSTANCE_T instance; - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; VCHIQ_STATUS_T status; struct bulk_waiter_node *waiter = NULL; - struct list_head *pos; service = find_service_by_handle(handle); if (!service) @@ -484,20 +475,16 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, unlock_service(service); mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each(pos, &instance->bulk_waiter_list) { - if (list_entry(pos, struct bulk_waiter_node, - list)->pid == current->pid) { - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry(waiter, &instance->bulk_waiter_list, list) { + if (waiter->pid == current->pid) { + list_del(&waiter->list); break; } } mutex_unlock(&instance->bulk_waiter_list_mutex); if (waiter) { - VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { /* This thread has an outstanding bulk transfer. */ @@ -523,12 +510,11 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, } } - status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, - data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, - dir); + status = vchiq_bulk_transfer(handle, data, size, &waiter->bulk_waiter, + VCHIQ_BULK_MODE_BLOCKING, dir); if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { - VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { /* Cancel the signal when the transfer @@ -559,10 +545,10 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, static VCHIQ_STATUS_T add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, - void *bulk_userdata) + struct vchiq_header *header, struct user_service *user_service, + void *bulk_userdata) { - VCHIQ_COMPLETION_DATA_T *completion; + struct vchiq_completion_data *completion; int insert; DEBUG_INITIALISE(g_state.local) @@ -574,7 +560,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, vchiq_log_trace(vchiq_arm_log_level, "%s - completion queue full", __func__); DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); - if (down_interruptible(&instance->remove_event) != 0) { + if (wait_for_completion_killable( &instance->remove_event)) { vchiq_log_info(vchiq_arm_log_level, "service_callback interrupted"); return VCHIQ_RETRY; @@ -612,7 +598,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, insert++; instance->completion_insert = insert; - up(&instance->insert_event); + complete(&instance->insert_event); return VCHIQ_SUCCESS; } @@ -624,16 +610,16 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, ***************************************************************************/ static VCHIQ_STATUS_T -service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, - VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) +service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header, + VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) { /* How do we ensure the callback goes to the right client? - ** The service_user data points to a USER_SERVICE_T record containing - ** the original callback and the user state structure, which contains a - ** circular buffer for completion records. + ** The service_user data points to a user_service record + ** containing the original callback and the user state structure, which + ** contains a circular buffer for completion records. */ - USER_SERVICE_T *user_service; - VCHIQ_SERVICE_T *service; + struct user_service *user_service; + struct vchiq_service *service; VCHIQ_INSTANCE_T instance; bool skip_completion = false; @@ -643,7 +629,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, service = handle_to_service(handle); BUG_ON(!service); - user_service = (USER_SERVICE_T *)service->base.userdata; + user_service = (struct user_service *)service->base.userdata; instance = user_service->instance; if (!instance || instance->closing) @@ -685,7 +671,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, } DEBUG_TRACE(SERVICE_CALLBACK_LINE); - if (down_interruptible(&user_service->remove_event) + if (wait_for_completion_killable( + &user_service->remove_event) != 0) { vchiq_log_info(vchiq_arm_log_level, "%s interrupted", __func__); @@ -717,7 +704,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, } spin_unlock(&msg_queue_spinlock); - up(&user_service->insert_event); + complete(&user_service->insert_event); header = NULL; } @@ -746,7 +733,7 @@ user_service_free(void *userdata) * close_delivered * ***************************************************************************/ -static void close_delivered(USER_SERVICE_T *user_service) +static void close_delivered(struct user_service *user_service) { vchiq_log_info(vchiq_arm_log_level, "%s(handle=%x)", @@ -757,81 +744,55 @@ static void close_delivered(USER_SERVICE_T *user_service) unlock_service(user_service->service); /* Wake the user-thread blocked in close_ or remove_service */ - up(&user_service->close_event); + complete(&user_service->close_event); user_service->close_pending = 0; } } struct vchiq_io_copy_callback_context { - struct vchiq_element *current_element; - size_t current_element_offset; + struct vchiq_element *element; + size_t element_offset; unsigned long elements_to_go; - size_t current_offset; }; -static ssize_t -vchiq_ioc_copy_element_data( - void *context, - void *dest, - size_t offset, - size_t maxsize) +static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest, + size_t offset, size_t maxsize) { - long res; + struct vchiq_io_copy_callback_context *cc = context; + size_t total_bytes_copied = 0; size_t bytes_this_round; - struct vchiq_io_copy_callback_context *copy_context = - (struct vchiq_io_copy_callback_context *)context; - if (offset != copy_context->current_offset) - return 0; - - if (!copy_context->elements_to_go) - return 0; - - /* - * Complex logic here to handle the case of 0 size elements - * in the middle of the array of elements. - * - * Need to skip over these 0 size elements. - */ - while (1) { - bytes_this_round = min(copy_context->current_element->size - - copy_context->current_element_offset, - maxsize); + while (total_bytes_copied < maxsize) { + if (!cc->elements_to_go) + return total_bytes_copied; - if (bytes_this_round) - break; - - copy_context->elements_to_go--; - copy_context->current_element++; - copy_context->current_element_offset = 0; - - if (!copy_context->elements_to_go) - return 0; - } + if (!cc->element->size) { + cc->elements_to_go--; + cc->element++; + cc->element_offset = 0; + continue; + } - res = copy_from_user(dest, - copy_context->current_element->data + - copy_context->current_element_offset, - bytes_this_round); + bytes_this_round = min(cc->element->size - cc->element_offset, + maxsize - total_bytes_copied); - if (res != 0) - return -EFAULT; + if (copy_from_user(dest + total_bytes_copied, + cc->element->data + cc->element_offset, + bytes_this_round)) + return -EFAULT; - copy_context->current_element_offset += bytes_this_round; - copy_context->current_offset += bytes_this_round; + cc->element_offset += bytes_this_round; + total_bytes_copied += bytes_this_round; - /* - * Check if done with current element, and if so advance to the next. - */ - if (copy_context->current_element_offset == - copy_context->current_element->size) { - copy_context->elements_to_go--; - copy_context->current_element++; - copy_context->current_element_offset = 0; + if (cc->element_offset == cc->element->size) { + cc->elements_to_go--; + cc->element++; + cc->element_offset = 0; + } } - return bytes_this_round; + return maxsize; } /************************************************************************** @@ -848,10 +809,9 @@ vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle, unsigned long i; size_t total_size = 0; - context.current_element = elements; - context.current_element_offset = 0; + context.element = elements; + context.element_offset = 0; context.elements_to_go = count; - context.current_offset = 0; for (i = 0; i < count; i++) { if (!elements[i].data && elements[i].size != 0) @@ -874,7 +834,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { VCHIQ_INSTANCE_T instance = file->private_data; VCHIQ_STATUS_T status = VCHIQ_SUCCESS; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_service *service = NULL; long ret = 0; int i, rc; @@ -906,7 +866,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (status == VCHIQ_SUCCESS) { /* Wake the completion thread and ask it to exit */ instance->closing = 1; - up(&instance->insert_event); + complete(&instance->insert_event); } break; @@ -936,8 +896,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case VCHIQ_IOC_CREATE_SERVICE: { - VCHIQ_CREATE_SERVICE_T args; - USER_SERVICE_T *user_service = NULL; + struct vchiq_create_service args; + struct user_service *user_service = NULL; void *userdata; int srvstate; @@ -948,7 +908,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } - user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); + user_service = kmalloc(sizeof(*user_service), GFP_KERNEL); if (!user_service) { ret = -ENOMEM; break; @@ -987,9 +947,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) instance->completion_remove - 1; user_service->msg_insert = 0; user_service->msg_remove = 0; - sema_init(&user_service->insert_event, 0); - sema_init(&user_service->remove_event, 0); - sema_init(&user_service->close_event, 0); + init_completion(&user_service->insert_event); + init_completion(&user_service->remove_event); + init_completion(&user_service->close_event); if (args.is_open) { status = vchiq_open_service_internal @@ -1004,7 +964,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (copy_to_user((void __user *) - &(((VCHIQ_CREATE_SERVICE_T __user *) + &(((struct vchiq_create_service __user *) arg)->handle), (const void *)&service->handle, sizeof(service->handle)) != 0) { @@ -1019,55 +979,38 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } break; - case VCHIQ_IOC_CLOSE_SERVICE: { + case VCHIQ_IOC_CLOSE_SERVICE: + case VCHIQ_IOC_REMOVE_SERVICE: { VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + struct user_service *user_service; service = find_service_for_instance(instance, handle); - if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; - /* close_pending is false on first entry, and when the - wait in vchiq_close_service has been interrupted. */ - if (!user_service->close_pending) { - status = vchiq_close_service(service->handle); - if (status != VCHIQ_SUCCESS) - break; - } - - /* close_pending is true once the underlying service - has been closed until the client library calls the - CLOSE_DELIVERED ioctl, signalling close_event. */ - if (user_service->close_pending && - down_interruptible(&user_service->close_event)) - status = VCHIQ_RETRY; - } else + if (!service) { ret = -EINVAL; - } break; + break; + } - case VCHIQ_IOC_REMOVE_SERVICE: { - VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + user_service = service->base.userdata; - service = find_service_for_instance(instance, handle); - if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; - /* close_pending is false on first entry, and when the - wait in vchiq_close_service has been interrupted. */ - if (!user_service->close_pending) { - status = vchiq_remove_service(service->handle); - if (status != VCHIQ_SUCCESS) - break; - } + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ? + vchiq_close_service(service->handle) : + vchiq_remove_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } - /* close_pending is true once the underlying service - has been closed until the client library calls the - CLOSE_DELIVERED ioctl, signalling close_event. */ - if (user_service->close_pending && - down_interruptible(&user_service->close_event)) - status = VCHIQ_RETRY; - } else - ret = -EINVAL; - } break; + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + wait_for_completion_killable( + &user_service->close_event)) + status = VCHIQ_RETRY; + break; + } case VCHIQ_IOC_USE_SERVICE: case VCHIQ_IOC_RELEASE_SERVICE: { @@ -1097,7 +1040,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_QUEUE_MESSAGE: { - VCHIQ_QUEUE_MESSAGE_T args; + struct vchiq_queue_message args; if (copy_from_user (&args, (const void __user *)arg, @@ -1126,7 +1069,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { - VCHIQ_QUEUE_BULK_TRANSFER_T args; + struct vchiq_queue_bulk_transfer args; struct bulk_waiter_node *waiter = NULL; VCHIQ_BULK_DIR_T dir = @@ -1153,21 +1096,16 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -ENOMEM; break; } + args.userdata = &waiter->bulk_waiter; } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { - struct list_head *pos; - mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each(pos, &instance->bulk_waiter_list) { - if (list_entry(pos, struct bulk_waiter_node, - list)->pid == current->pid) { - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry(waiter, &instance->bulk_waiter_list, + list) { + if (waiter->pid == current->pid) { + list_del(&waiter->list); break; } - } mutex_unlock(&instance->bulk_waiter_list_mutex); if (!waiter) { @@ -1182,14 +1120,13 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) current->pid); args.userdata = &waiter->bulk_waiter; } - status = vchiq_bulk_transfer - (args.handle, - VCHI_MEM_HANDLE_INVALID, - args.data, args.size, - args.userdata, args.mode, - dir); + + status = vchiq_bulk_transfer(args.handle, args.data, args.size, + args.userdata, args.mode, dir); + if (!waiter) break; + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { if (waiter->bulk_waiter.bulk) { @@ -1212,7 +1149,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) waiter, current->pid); if (copy_to_user((void __user *) - &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) + &(((struct vchiq_queue_bulk_transfer __user *) arg)->mode), (const void *)&mode_waiting, sizeof(mode_waiting)) != 0) @@ -1221,7 +1158,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_AWAIT_COMPLETION: { - VCHIQ_AWAIT_COMPLETION_T args; + struct vchiq_await_completion args; DEBUG_TRACE(AWAIT_COMPLETION_LINE); if (!instance->connected) { @@ -1245,7 +1182,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) DEBUG_TRACE(AWAIT_COMPLETION_LINE); mutex_unlock(&instance->completion_mutex); - rc = down_interruptible(&instance->insert_event); + rc = wait_for_completion_killable( + &instance->insert_event); mutex_lock(&instance->completion_mutex); if (rc != 0) { DEBUG_TRACE(AWAIT_COMPLETION_LINE); @@ -1262,10 +1200,10 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int remove = instance->completion_remove; for (ret = 0; ret < args.count; ret++) { - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_SERVICE_T *service; - USER_SERVICE_T *user_service; - VCHIQ_HEADER_T *header; + struct vchiq_completion_data *completion; + struct vchiq_service *service; + struct user_service *user_service; + struct vchiq_header *header; if (remove == instance->completion_insert) break; @@ -1290,7 +1228,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int msglen; msglen = header->size + - sizeof(VCHIQ_HEADER_T); + sizeof(struct vchiq_header); /* This must be a VCHIQ-style service */ if (args.msgbufsize < msglen) { vchiq_log_error( @@ -1343,10 +1281,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) unlock_service(service); if (copy_to_user((void __user *)( - (size_t)args.buf + - ret * sizeof(VCHIQ_COMPLETION_DATA_T)), + (size_t)args.buf + ret * + sizeof(struct vchiq_completion_data)), completion, - sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { + sizeof(struct vchiq_completion_data)) + != 0) { if (ret == 0) ret = -EFAULT; break; @@ -1363,8 +1302,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (msgbufcount != args.msgbufcount) { if (copy_to_user((void __user *) - &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> - msgbufcount, + &((struct vchiq_await_completion *)arg) + ->msgbufcount, &msgbufcount, sizeof(msgbufcount)) != 0) { ret = -EFAULT; @@ -1373,15 +1312,15 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (ret != 0) - up(&instance->remove_event); + complete(&instance->remove_event); mutex_unlock(&instance->completion_mutex); DEBUG_TRACE(AWAIT_COMPLETION_LINE); } break; case VCHIQ_IOC_DEQUEUE_MESSAGE: { - VCHIQ_DEQUEUE_MESSAGE_T args; - USER_SERVICE_T *user_service; - VCHIQ_HEADER_T *header; + struct vchiq_dequeue_message args; + struct user_service *user_service; + struct vchiq_header *header; DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); if (copy_from_user @@ -1395,7 +1334,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EINVAL; break; } - user_service = (USER_SERVICE_T *)service->base.userdata; + user_service = (struct user_service *)service->base.userdata; if (user_service->is_vchi == 0) { ret = -EINVAL; break; @@ -1413,8 +1352,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) do { spin_unlock(&msg_queue_spinlock); DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); - if (down_interruptible( - &user_service->insert_event) != 0) { + if (wait_for_completion_killable( + &user_service->insert_event)) { vchiq_log_info(vchiq_arm_log_level, "DEQUEUE_MESSAGE interrupted"); ret = -EINTR; @@ -1436,7 +1375,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) user_service->msg_remove++; spin_unlock(&msg_queue_spinlock); - up(&user_service->remove_event); + complete(&user_service->remove_event); if (header == NULL) ret = -ENOTCONN; else if (header->size <= args.bufsize) { @@ -1468,8 +1407,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_GET_CONFIG: { - VCHIQ_GET_CONFIG_T args; - VCHIQ_CONFIG_T config; + struct vchiq_get_config args; + struct vchiq_config config; if (copy_from_user(&args, (const void __user *)arg, sizeof(args)) != 0) { @@ -1480,18 +1419,16 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EINVAL; break; } - status = vchiq_get_config(instance, args.config_size, &config); - if (status == VCHIQ_SUCCESS) { - if (copy_to_user((void __user *)args.pconfig, - &config, args.config_size) != 0) { - ret = -EFAULT; - break; - } + + vchiq_get_config(&config); + if (copy_to_user(args.pconfig, &config, args.config_size)) { + ret = -EFAULT; + break; } } break; case VCHIQ_IOC_SET_SERVICE_OPTION: { - VCHIQ_SET_SERVICE_OPTION_T args; + struct vchiq_set_service_option args; if (copy_from_user( &args, (const void __user *)arg, @@ -1524,8 +1461,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) service = find_closed_service_for_instance(instance, handle); if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; + struct user_service *user_service = + (struct user_service *)service->base.userdata; close_delivered(user_service); } else ret = -EINVAL; @@ -1593,7 +1530,7 @@ vchiq_compat_ioctl_create_service( unsigned int cmd, unsigned long arg) { - VCHIQ_CREATE_SERVICE_T __user *args; + struct vchiq_create_service __user *args; struct vchiq_create_service32 __user *ptrargs32 = (struct vchiq_create_service32 __user *)arg; struct vchiq_create_service32 args32; @@ -1656,8 +1593,8 @@ vchiq_compat_ioctl_queue_message(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_QUEUE_MESSAGE_T *args; - struct vchiq_element *elements; + struct vchiq_queue_message *args; + struct vchiq_element __user *elements; struct vchiq_queue_message32 args32; unsigned int count; @@ -1723,7 +1660,7 @@ vchiq_compat_ioctl_queue_bulk(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_QUEUE_BULK_TRANSFER_T *args; + struct vchiq_queue_bulk_transfer __user *args; struct vchiq_queue_bulk_transfer32 args32; struct vchiq_queue_bulk_transfer32 *ptrargs32 = (struct vchiq_queue_bulk_transfer32 *)arg; @@ -1789,16 +1726,16 @@ vchiq_compat_ioctl_await_completion(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_AWAIT_COMPLETION_T *args; - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_COMPLETION_DATA_T completiontemp; + struct vchiq_await_completion __user *args; + struct vchiq_completion_data __user *completion; + struct vchiq_completion_data completiontemp; struct vchiq_await_completion32 args32; struct vchiq_completion_data32 completion32; - unsigned int *msgbufcount32; + unsigned int __user *msgbufcount32; unsigned int msgbufcount_native; compat_uptr_t msgbuf32; - void *msgbuf; - void **msgbufptr; + void __user *msgbuf; + void * __user *msgbufptr; long ret; args = compat_alloc_user_space(sizeof(*args) + @@ -1807,11 +1744,11 @@ vchiq_compat_ioctl_await_completion(struct file *file, if (!args) return -EFAULT; - completion = (VCHIQ_COMPLETION_DATA_T *)(args + 1); - msgbufptr = (void __user **)(completion + 1); + completion = (struct vchiq_completion_data __user *)(args + 1); + msgbufptr = (void * __user *)(completion + 1); if (copy_from_user(&args32, - (struct vchiq_completion_data32 *)arg, + (struct vchiq_completion_data32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -1939,7 +1876,7 @@ vchiq_compat_ioctl_dequeue_message(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_DEQUEUE_MESSAGE_T *args; + struct vchiq_dequeue_message __user *args; struct vchiq_dequeue_message32 args32; args = compat_alloc_user_space(sizeof(*args)); @@ -1947,7 +1884,7 @@ vchiq_compat_ioctl_dequeue_message(struct file *file, return -EFAULT; if (copy_from_user(&args32, - (struct vchiq_dequeue_message32 *)arg, + (struct vchiq_dequeue_message32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -1974,7 +1911,7 @@ vchiq_compat_ioctl_get_config(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_GET_CONFIG_T *args; + struct vchiq_get_config __user *args; struct vchiq_get_config32 args32; args = compat_alloc_user_space(sizeof(*args)); @@ -1982,7 +1919,7 @@ vchiq_compat_ioctl_get_config(struct file *file, return -EFAULT; if (copy_from_user(&args32, - (struct vchiq_get_config32 *)arg, + (struct vchiq_get_config32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -2017,201 +1954,152 @@ vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #endif -/**************************************************************************** -* -* vchiq_open -* -***************************************************************************/ - -static int -vchiq_open(struct inode *inode, struct file *file) +static int vchiq_open(struct inode *inode, struct file *file) { - int dev = iminor(inode) & 0x0f; + struct vchiq_state *state = vchiq_get_state(); + VCHIQ_INSTANCE_T instance; vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); - switch (dev) { - case VCHIQ_MINOR: { - VCHIQ_STATE_T *state = vchiq_get_state(); - VCHIQ_INSTANCE_T instance; - if (!state) { - vchiq_log_error(vchiq_arm_log_level, + if (!state) { + vchiq_log_error(vchiq_arm_log_level, "vchiq has no connection to VideoCore"); - return -ENOTCONN; - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - if (!instance) - return -ENOMEM; + return -ENOTCONN; + } - instance->state = state; - instance->pid = current->tgid; + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; - vchiq_debugfs_add_instance(instance); + instance->state = state; + instance->pid = current->tgid; - sema_init(&instance->insert_event, 0); - sema_init(&instance->remove_event, 0); - mutex_init(&instance->completion_mutex); - mutex_init(&instance->bulk_waiter_list_mutex); - INIT_LIST_HEAD(&instance->bulk_waiter_list); + vchiq_debugfs_add_instance(instance); - file->private_data = instance; - } break; + init_completion(&instance->insert_event); + init_completion(&instance->remove_event); + mutex_init(&instance->completion_mutex); + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); - default: - vchiq_log_error(vchiq_arm_log_level, - "Unknown minor device: %d", dev); - return -ENXIO; - } + file->private_data = instance; return 0; } -/**************************************************************************** -* -* vchiq_release -* -***************************************************************************/ - -static int -vchiq_release(struct inode *inode, struct file *file) +static int vchiq_release(struct inode *inode, struct file *file) { - int dev = iminor(inode) & 0x0f; + VCHIQ_INSTANCE_T instance = file->private_data; + struct vchiq_state *state = vchiq_get_state(); + struct vchiq_service *service; int ret = 0; + int i; - switch (dev) { - case VCHIQ_MINOR: { - VCHIQ_INSTANCE_T instance = file->private_data; - VCHIQ_STATE_T *state = vchiq_get_state(); - VCHIQ_SERVICE_T *service; - int i; - - vchiq_log_info(vchiq_arm_log_level, - "%s: instance=%lx", - __func__, (unsigned long)instance); + vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__, + (unsigned long)instance); - if (!state) { - ret = -EPERM; - goto out; - } + if (!state) { + ret = -EPERM; + goto out; + } - /* Ensure videocore is awake to allow termination. */ - vchiq_use_internal(instance->state, NULL, - USE_TYPE_VCHIQ); + /* Ensure videocore is awake to allow termination. */ + vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ); - mutex_lock(&instance->completion_mutex); + mutex_lock(&instance->completion_mutex); - /* Wake the completion thread and ask it to exit */ - instance->closing = 1; - up(&instance->insert_event); + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + complete(&instance->insert_event); - mutex_unlock(&instance->completion_mutex); + mutex_unlock(&instance->completion_mutex); - /* Wake the slot handler if the completion queue is full. */ - up(&instance->remove_event); + /* Wake the slot handler if the completion queue is full. */ + complete(&instance->remove_event); - /* Mark all services for termination... */ - i = 0; - while ((service = next_service_by_instance(state, instance, - &i)) != NULL) { - USER_SERVICE_T *user_service = service->base.userdata; + /* Mark all services for termination... */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i))) { + struct user_service *user_service = service->base.userdata; - /* Wake the slot handler if the msg queue is full. */ - up(&user_service->remove_event); + /* Wake the slot handler if the msg queue is full. */ + complete(&user_service->remove_event); - vchiq_terminate_service_internal(service); - unlock_service(service); - } + vchiq_terminate_service_internal(service); + unlock_service(service); + } - /* ...and wait for them to die */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i)) - != NULL) { - USER_SERVICE_T *user_service = service->base.userdata; + /* ...and wait for them to die */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i))) { + struct user_service *user_service = service->base.userdata; - down(&service->remove_event); + wait_for_completion(&service->remove_event); - BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); - spin_lock(&msg_queue_spinlock); - - while (user_service->msg_remove != - user_service->msg_insert) { - VCHIQ_HEADER_T *header; - int m = user_service->msg_remove & - (MSG_QUEUE_SIZE - 1); + spin_lock(&msg_queue_spinlock); - header = user_service->msg_queue[m]; - user_service->msg_remove++; - spin_unlock(&msg_queue_spinlock); - - if (header) - vchiq_release_message( - service->handle, - header); - spin_lock(&msg_queue_spinlock); - } + while (user_service->msg_remove != user_service->msg_insert) { + struct vchiq_header *header; + int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1); + header = user_service->msg_queue[m]; + user_service->msg_remove++; spin_unlock(&msg_queue_spinlock); - unlock_service(service); + if (header) + vchiq_release_message(service->handle, header); + spin_lock(&msg_queue_spinlock); } - /* Release any closed services */ - while (instance->completion_remove != - instance->completion_insert) { - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_SERVICE_T *service; - - completion = &instance->completions[ - instance->completion_remove & - (MAX_COMPLETIONS - 1)]; - service = completion->service_userdata; - if (completion->reason == VCHIQ_SERVICE_CLOSED) { - USER_SERVICE_T *user_service = - service->base.userdata; - - /* Wake any blocked user-thread */ - if (instance->use_close_delivered) - up(&user_service->close_event); - unlock_service(service); - } - instance->completion_remove++; - } + spin_unlock(&msg_queue_spinlock); - /* Release the PEER service count. */ - vchiq_release_internal(instance->state, NULL); + unlock_service(service); + } - { - struct list_head *pos, *next; + /* Release any closed services */ + while (instance->completion_remove != + instance->completion_insert) { + struct vchiq_completion_data *completion; + struct vchiq_service *service; - list_for_each_safe(pos, next, - &instance->bulk_waiter_list) { - struct bulk_waiter_node *waiter; + completion = &instance->completions[ + instance->completion_remove & (MAX_COMPLETIONS - 1)]; + service = completion->service_userdata; + if (completion->reason == VCHIQ_SERVICE_CLOSED) { + struct user_service *user_service = + service->base.userdata; - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); - vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %pK for pid %d", - waiter, waiter->pid); - kfree(waiter); - } + /* Wake any blocked user-thread */ + if (instance->use_close_delivered) + complete(&user_service->close_event); + unlock_service(service); } + instance->completion_remove++; + } - vchiq_debugfs_remove_instance(instance); + /* Release the PEER service count. */ + vchiq_release_internal(instance->state, NULL); - kfree(instance); - file->private_data = NULL; - } break; + { + struct bulk_waiter_node *waiter, *next; - default: - vchiq_log_error(vchiq_arm_log_level, - "Unknown minor device: %d", dev); - ret = -ENXIO; + list_for_each_entry_safe(waiter, next, + &instance->bulk_waiter_list, list) { + list_del(&waiter->list); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %pK for pid %d", + waiter, waiter->pid); + kfree(waiter); + } } + vchiq_debugfs_remove_instance(instance); + + kfree(instance); + file->private_data = NULL; + out: return ret; } @@ -2225,7 +2113,7 @@ out: void vchiq_dump(void *dump_context, const char *str, int len) { - DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; + struct dump_context *context = (struct dump_context *)dump_context; if (context->actual < context->space) { int copy_bytes; @@ -2270,7 +2158,7 @@ vchiq_dump(void *dump_context, const char *str, int len) void vchiq_dump_platform_instances(void *dump_context) { - VCHIQ_STATE_T *state = vchiq_get_state(); + struct vchiq_state *state = vchiq_get_state(); char buf[80]; int len; int i; @@ -2279,7 +2167,7 @@ vchiq_dump_platform_instances(void *dump_context) marking those that have been dumped. */ for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; VCHIQ_INSTANCE_T instance; if (service && (service->base.callback == service_callback)) { @@ -2290,7 +2178,7 @@ vchiq_dump_platform_instances(void *dump_context) } for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; VCHIQ_INSTANCE_T instance; if (service && (service->base.callback == service_callback)) { @@ -2320,9 +2208,11 @@ vchiq_dump_platform_instances(void *dump_context) ***************************************************************************/ void -vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +vchiq_dump_platform_service_state(void *dump_context, + struct vchiq_service *service) { - USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; + struct user_service *user_service = + (struct user_service *)service->base.userdata; char buf[80]; int len; @@ -2353,7 +2243,7 @@ static ssize_t vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - DUMP_CONTEXT_T context; + struct dump_context context; context.buf = buf; context.actual = 0; @@ -2367,7 +2257,7 @@ vchiq_read(struct file *file, char __user *buf, return context.actual; } -VCHIQ_STATE_T * +struct vchiq_state * vchiq_get_state(void) { @@ -2398,9 +2288,9 @@ vchiq_fops = { */ int -vchiq_videocore_wanted(VCHIQ_STATE_T *state) +vchiq_videocore_wanted(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) /* autosuspend not supported - always return wanted */ @@ -2420,7 +2310,7 @@ vchiq_videocore_wanted(VCHIQ_STATE_T *state) static VCHIQ_STATUS_T vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, + struct vchiq_header *header, VCHIQ_SERVICE_HANDLE_T service_user, void *bulk_user) { @@ -2432,14 +2322,14 @@ vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, static int vchiq_keepalive_thread_func(void *v) { - VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_state *state = (struct vchiq_state *)v; + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T status; VCHIQ_INSTANCE_T instance; VCHIQ_SERVICE_HANDLE_T ka_handle; - VCHIQ_SERVICE_PARAMS_T params = { + struct vchiq_service_params params = { .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), .callback = vchiq_keepalive_vchiq_callback, .version = KEEPALIVE_VER, @@ -2470,7 +2360,7 @@ vchiq_keepalive_thread_func(void *v) while (1) { long rc = 0, uc = 0; - if (wait_for_completion_interruptible(&arm_state->ka_evt) + if (wait_for_completion_killable(&arm_state->ka_evt) != 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__); @@ -2511,7 +2401,8 @@ exit: } VCHIQ_STATUS_T -vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) +vchiq_arm_init_state(struct vchiq_state *state, + struct vchiq_arm_state *arm_state) { if (arm_state) { rwlock_init(&arm_state->susp_res_lock); @@ -2607,8 +2498,8 @@ vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) */ void -set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_suspend_status new_state) +set_suspend_state(struct vchiq_arm_state *arm_state, + enum vc_suspend_status new_state) { /* set the state in all cases */ arm_state->vc_suspend_state = new_state; @@ -2644,8 +2535,8 @@ set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, } void -set_resume_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_resume_status new_state) +set_resume_state(struct vchiq_arm_state *arm_state, + enum vc_resume_status new_state) { /* set the state in all cases */ arm_state->vc_resume_state = new_state; @@ -2673,7 +2564,7 @@ set_resume_state(VCHIQ_ARM_STATE_T *arm_state, /* should be called with the write lock held */ inline void -start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +start_suspend_timer(struct vchiq_arm_state *arm_state) { del_timer(&arm_state->suspend_timer); arm_state->suspend_timer.expires = jiffies + @@ -2684,7 +2575,7 @@ start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) /* should be called with the write lock held */ static inline void -stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +stop_suspend_timer(struct vchiq_arm_state *arm_state) { if (arm_state->suspend_timer_running) { del_timer(&arm_state->suspend_timer); @@ -2693,9 +2584,9 @@ stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) } static inline int -need_resume(VCHIQ_STATE_T *state) +need_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && @@ -2703,7 +2594,7 @@ need_resume(VCHIQ_STATE_T *state) } static int -block_resume(VCHIQ_ARM_STATE_T *arm_state) +block_resume(struct vchiq_arm_state *arm_state) { int status = VCHIQ_SUCCESS; const unsigned long timeout_val = @@ -2720,7 +2611,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " "blocked clients", __func__); - if (wait_for_completion_interruptible_timeout( + if (wait_for_completion_killable_timeout( &arm_state->blocked_blocker, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for " @@ -2746,7 +2637,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", __func__); - if (wait_for_completion_interruptible_timeout( + if (wait_for_completion_killable_timeout( &arm_state->vc_resume_complete, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for " @@ -2769,7 +2660,7 @@ out: } static inline void -unblock_resume(VCHIQ_ARM_STATE_T *arm_state) +unblock_resume(struct vchiq_arm_state *arm_state) { complete_all(&arm_state->resume_blocker); arm_state->resume_blocked = 0; @@ -2778,10 +2669,10 @@ unblock_resume(VCHIQ_ARM_STATE_T *arm_state) /* Initiate suspend via slot handler. Should be called with the write lock * held */ VCHIQ_STATUS_T -vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) +vchiq_arm_vcsuspend(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) goto out; @@ -2827,9 +2718,9 @@ out: } void -vchiq_platform_check_suspend(VCHIQ_STATE_T *state) +vchiq_platform_check_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int susp = 0; if (!arm_state) @@ -2854,9 +2745,9 @@ out: } static void -output_timeout_error(VCHIQ_STATE_T *state) +output_timeout_error(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); char err[50] = ""; int vc_use_count = arm_state->videocore_use_count; int active_services = state->unused_service; @@ -2867,7 +2758,7 @@ output_timeout_error(VCHIQ_STATE_T *state) goto output_msg; } for (i = 0; i < active_services; i++) { - VCHIQ_SERVICE_T *service_ptr = state->services[i]; + struct vchiq_service *service_ptr = state->services[i]; if (service_ptr && service_ptr->service_use_count && (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { @@ -2899,9 +2790,9 @@ output_msg: ** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. */ VCHIQ_STATUS_T -vchiq_arm_force_suspend(VCHIQ_STATE_T *state) +vchiq_arm_force_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T status = VCHIQ_ERROR; long rc = 0; int repeat = -1; @@ -2953,7 +2844,7 @@ vchiq_arm_force_suspend(VCHIQ_STATE_T *state) do { write_unlock_bh(&arm_state->susp_res_lock); - rc = wait_for_completion_interruptible_timeout( + rc = wait_for_completion_killable_timeout( &arm_state->vc_suspend_complete, msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); @@ -3010,9 +2901,9 @@ out: } void -vchiq_check_suspend(VCHIQ_STATE_T *state) +vchiq_check_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) goto out; @@ -3032,9 +2923,9 @@ out: } int -vchiq_arm_allow_resume(VCHIQ_STATE_T *state) +vchiq_arm_allow_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int resume = 0; int ret = -1; @@ -3049,7 +2940,7 @@ vchiq_arm_allow_resume(VCHIQ_STATE_T *state) write_unlock_bh(&arm_state->susp_res_lock); if (resume) { - if (wait_for_completion_interruptible( + if (wait_for_completion_killable( &arm_state->vc_resume_complete) < 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__); @@ -3076,9 +2967,9 @@ out: /* This function should be called with the write lock held */ int -vchiq_check_resume(VCHIQ_STATE_T *state) +vchiq_check_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int resume = 0; if (!arm_state) @@ -3098,10 +2989,10 @@ out: } VCHIQ_STATUS_T -vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - enum USE_TYPE_E use_type) +vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; @@ -3231,9 +3122,9 @@ out: } VCHIQ_STATUS_T -vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) +vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; @@ -3293,9 +3184,9 @@ out: } void -vchiq_on_remote_use(VCHIQ_STATE_T *state) +vchiq_on_remote_use(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_use_count); @@ -3303,9 +3194,9 @@ vchiq_on_remote_use(VCHIQ_STATE_T *state) } void -vchiq_on_remote_release(VCHIQ_STATE_T *state) +vchiq_on_remote_release(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_release_count); @@ -3313,18 +3204,18 @@ vchiq_on_remote_release(VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_use_service_internal(VCHIQ_SERVICE_T *service) +vchiq_use_service_internal(struct vchiq_service *service) { return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); } VCHIQ_STATUS_T -vchiq_release_service_internal(VCHIQ_SERVICE_T *service) +vchiq_release_service_internal(struct vchiq_service *service) { return vchiq_release_internal(service->state, service); } -VCHIQ_DEBUGFS_NODE_T * +struct vchiq_debugfs_node * vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) { return &instance->debugfs_node; @@ -3333,7 +3224,7 @@ vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) int vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int use_count = 0, i; i = 0; @@ -3360,7 +3251,7 @@ vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) void vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int i; i = 0; @@ -3374,8 +3265,9 @@ vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) static void suspend_timer_callback(struct timer_list *t) { - VCHIQ_ARM_STATE_T *arm_state = from_timer(arm_state, t, suspend_timer); - VCHIQ_STATE_T *state = arm_state->state; + struct vchiq_arm_state *arm_state = + from_timer(arm_state, t, suspend_timer); + struct vchiq_state *state = arm_state->state; vchiq_log_info(vchiq_susp_log_level, "%s - suspend timer expired - check suspend", __func__); @@ -3386,7 +3278,7 @@ VCHIQ_STATUS_T vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_use_internal(service->state, service, @@ -3400,7 +3292,7 @@ VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_use_internal(service->state, service, @@ -3414,7 +3306,7 @@ VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_release_internal(service->state, service); @@ -3430,9 +3322,9 @@ struct service_data_struct { }; void -vchiq_dump_service_use_state(VCHIQ_STATE_T *state) +vchiq_dump_service_use_state(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); struct service_data_struct *service_data; int i, found = 0; /* If there's more than 64 services, only dump ones with @@ -3464,7 +3356,7 @@ vchiq_dump_service_use_state(VCHIQ_STATE_T *state) only_nonzero = 1; for (i = 0; i < active_services; i++) { - VCHIQ_SERVICE_T *service_ptr = state->services[i]; + struct vchiq_service *service_ptr = state->services[i]; if (!service_ptr) continue; @@ -3516,9 +3408,9 @@ vchiq_dump_service_use_state(VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_check_service(VCHIQ_SERVICE_T *service) +vchiq_check_service(struct vchiq_service *service) { - VCHIQ_ARM_STATE_T *arm_state; + struct vchiq_arm_state *arm_state; VCHIQ_STATUS_T ret = VCHIQ_ERROR; if (!service || !service->state) @@ -3549,15 +3441,16 @@ out: } /* stub functions */ -void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) +void vchiq_on_remote_use_active(struct vchiq_state *state) { (void)state; } -void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, - VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) +void vchiq_platform_conn_state_changed(struct vchiq_state *state, + VCHIQ_CONNSTATE_T oldstate, + VCHIQ_CONNSTATE_T newstate) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); @@ -3593,11 +3486,34 @@ static const struct of_device_id vchiq_of_match[] = { }; MODULE_DEVICE_TABLE(of, vchiq_of_match); +static struct platform_device * +vchiq_register_child(struct platform_device *pdev, const char *name) +{ + struct platform_device_info pdevinfo; + struct platform_device *child; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + + pdevinfo.parent = &pdev->dev; + pdevinfo.name = name; + pdevinfo.id = PLATFORM_DEVID_NONE; + pdevinfo.dma_mask = DMA_BIT_MASK(32); + + child = platform_device_register_full(&pdevinfo); + if (IS_ERR(child)) { + dev_warn(&pdev->dev, "%s not registered\n", name); + child = NULL; + } + + return child; +} + static int vchiq_probe(struct platform_device *pdev) { struct device_node *fw_node; const struct of_device_id *of_id; struct vchiq_drvdata *drvdata; + struct device *vchiq_dev; int err; of_id = of_match_node(vchiq_of_match, pdev->dev.of_node); @@ -3623,34 +3539,22 @@ static int vchiq_probe(struct platform_device *pdev) if (err != 0) goto failed_platform_init; - err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); - if (err != 0) { - vchiq_log_error(vchiq_arm_log_level, - "Unable to allocate device number"); - goto failed_platform_init; - } cdev_init(&vchiq_cdev, &vchiq_fops); vchiq_cdev.owner = THIS_MODULE; err = cdev_add(&vchiq_cdev, vchiq_devid, 1); if (err != 0) { vchiq_log_error(vchiq_arm_log_level, "Unable to register device"); - goto failed_cdev_add; + goto failed_platform_init; } - /* create sysfs entries */ - vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); - err = PTR_ERR(vchiq_class); - if (IS_ERR(vchiq_class)) - goto failed_class_create; - - vchiq_dev = device_create(vchiq_class, NULL, - vchiq_devid, NULL, "vchiq"); - err = PTR_ERR(vchiq_dev); - if (IS_ERR(vchiq_dev)) + vchiq_dev = device_create(vchiq_class, &pdev->dev, vchiq_devid, NULL, + "vchiq"); + if (IS_ERR(vchiq_dev)) { + err = PTR_ERR(vchiq_dev); goto failed_device_create; + } - /* create debugfs entries */ vchiq_debugfs_init(); vchiq_log_info(vchiq_arm_log_level, @@ -3658,18 +3562,13 @@ static int vchiq_probe(struct platform_device *pdev) VCHIQ_VERSION, VCHIQ_VERSION_MIN, MAJOR(vchiq_devid), MINOR(vchiq_devid)); - bcm2835_camera = platform_device_register_data(&pdev->dev, - "bcm2835-camera", -1, - NULL, 0); + bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera"); + bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio"); return 0; failed_device_create: - class_destroy(vchiq_class); -failed_class_create: cdev_del(&vchiq_cdev); -failed_cdev_add: - unregister_chrdev_region(vchiq_devid, 1); failed_platform_init: vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); return err; @@ -3680,9 +3579,7 @@ static int vchiq_remove(struct platform_device *pdev) platform_device_unregister(bcm2835_camera); vchiq_debugfs_deinit(); device_destroy(vchiq_class, vchiq_devid); - class_destroy(vchiq_class); cdev_del(&vchiq_cdev); - unregister_chrdev_region(vchiq_devid, 1); return 0; } @@ -3695,7 +3592,48 @@ static struct platform_driver vchiq_driver = { .probe = vchiq_probe, .remove = vchiq_remove, }; -module_platform_driver(vchiq_driver); + +static int __init vchiq_driver_init(void) +{ + int ret; + + vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(vchiq_class)) { + pr_err("Failed to create vchiq class\n"); + return PTR_ERR(vchiq_class); + } + + ret = alloc_chrdev_region(&vchiq_devid, 0, 1, DEVICE_NAME); + if (ret) { + pr_err("Failed to allocate vchiq's chrdev region\n"); + goto class_destroy; + } + + ret = platform_driver_register(&vchiq_driver); + if (ret) { + pr_err("Failed to register vchiq driver\n"); + goto region_unregister; + } + + return 0; + +region_unregister: + platform_driver_unregister(&vchiq_driver); + +class_destroy: + class_destroy(vchiq_class); + + return ret; +} +module_init(vchiq_driver_init); + +static void __exit vchiq_driver_exit(void) +{ + platform_driver_unregister(&vchiq_driver); + unregister_chrdev_region(vchiq_devid, 1); + class_destroy(vchiq_class); +} +module_exit(vchiq_driver_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Videocore VCHIQ driver"); |