[PATCH] staging: vc04_services: merge vchiq_kern_lib.c into vchiq_arm.c
Stefan Wahren
stefan.wahren at i2se.com
Sat Feb 3 02:48:01 PST 2018
[add Phil]
> Arnd Bergmann <arnd at arndb.de> hat am 2. Februar 2018 um 16:01 geschrieben:
>
>
> There are two incompatible definitions of 'vchiq_instance_struct', so
> passing them through vchiq_initialise(), vchiq_connect() or another
> such interface is broken, as shown by building the driver with link-time
> optimizations:
>
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h:129:0: error: type of 'vchiq_initialise' does not match original declaration [-Werror=lto-type-mismatch]
> extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance);
>
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c:68:0: note: 'vchiq_initialise' was previously declared here
> VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
>
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c:68:0: note: code may be misoptimized unless -fno-strict-aliasing is used
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h:131:0: error: type of 'vchiq_connect' does not match original declaration [-Werror=lto-type-mismatch]
> extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance);
>
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c:168:0: note: 'vchiq_connect' was previously declared here
> VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
>
> It's possible that only one of the two sides actually access the members,
> but it's clear that they need to agree on the layout. The easiest way
> to achieve this appears to be to merge the two files into one. I tried
> moving the structure definition into a shared header first, but ended
> up running into too many interdependencies that way.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
> drivers/staging/vc04_services/Makefile | 1 -
> .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 369 ++++++++++++++++++
> .../interface/vchiq_arm/vchiq_kern_lib.c | 431 ---------------------
> 3 files changed, 369 insertions(+), 432 deletions(-)
> delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
>
> diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile
> index 1ecb261e04ae..fb26b826e640 100644
> --- a/drivers/staging/vc04_services/Makefile
> +++ b/drivers/staging/vc04_services/Makefile
> @@ -4,7 +4,6 @@ obj-$(CONFIG_BCM2835_VCHIQ) += vchiq.o
> vchiq-objs := \
> interface/vchiq_arm/vchiq_core.o \
> interface/vchiq_arm/vchiq_arm.o \
> - interface/vchiq_arm/vchiq_kern_lib.o \
> interface/vchiq_arm/vchiq_2835_arm.o \
> interface/vchiq_arm/vchiq_debugfs.o \
> interface/vchiq_arm/vchiq_shim.o \
> 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 c2c440009cac..f5cefda49b22 100644
> --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
> +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
> @@ -193,6 +193,375 @@ static const char *const ioctl_names[] = {
> vchiq_static_assert(ARRAY_SIZE(ioctl_names) ==
> (VCHIQ_IOC_MAX + 1));
>
> +static VCHIQ_STATUS_T
> +vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> + unsigned int size, VCHIQ_BULK_DIR_T dir);
> +
> +#define VCHIQ_INIT_RETRIES 10
> +VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
> +{
> + VCHIQ_STATUS_T status = VCHIQ_ERROR;
> + VCHIQ_STATE_T *state;
> + VCHIQ_INSTANCE_T instance = NULL;
> + int i;
> +
> + vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
> +
> + /* VideoCore may not be ready due to boot up timing.
> + * It may never be ready if kernel and firmware are mismatched,so don't
> + * block forever.
> + */
> + for (i = 0; i < VCHIQ_INIT_RETRIES; i++) {
> + state = vchiq_get_state();
> + if (state)
> + break;
> + udelay(500);
> + }
> + if (i == VCHIQ_INIT_RETRIES) {
> + vchiq_log_error(vchiq_core_log_level,
> + "%s: videocore not initialized\n", __func__);
> + goto failed;
> + } else if (i > 0) {
> + vchiq_log_warning(vchiq_core_log_level,
> + "%s: videocore initialized after %d retries\n",
> + __func__, i);
> + }
> +
> + instance = kzalloc(sizeof(*instance), GFP_KERNEL);
> + if (!instance) {
> + vchiq_log_error(vchiq_core_log_level,
> + "%s: error allocating vchiq instance\n", __func__);
> + goto failed;
> + }
> +
> + instance->connected = 0;
> + instance->state = state;
> + mutex_init(&instance->bulk_waiter_list_mutex);
> + INIT_LIST_HEAD(&instance->bulk_waiter_list);
> +
> + *instance_out = instance;
> +
> + status = VCHIQ_SUCCESS;
> +
> +failed:
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p): returning %d", __func__, instance, status);
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_initialise);
> +
> +VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
> +{
> + VCHIQ_STATUS_T status;
> + VCHIQ_STATE_T *state = instance->state;
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p) called", __func__, instance);
> +
> + if (mutex_lock_killable(&state->mutex) != 0)
> + return VCHIQ_RETRY;
> +
> + /* Remove all services */
> + status = vchiq_shutdown_internal(state, instance);
> +
> + mutex_unlock(&state->mutex);
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p): returning %d", __func__, instance, status);
> +
> + if (status == VCHIQ_SUCCESS) {
> + struct list_head *pos, *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);
> + vchiq_log_info(vchiq_arm_log_level,
> + "bulk_waiter - cleaned up %pK for pid %d",
> + waiter, waiter->pid);
> + kfree(waiter);
> + }
> + kfree(instance);
> + }
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_shutdown);
> +
> +static int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
> +{
> + return instance->connected;
> +}
> +
> +VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
> +{
> + VCHIQ_STATUS_T status;
> + VCHIQ_STATE_T *state = instance->state;
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p) called", __func__, instance);
> +
> + if (mutex_lock_killable(&state->mutex) != 0) {
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s: call to mutex_lock failed", __func__);
> + status = VCHIQ_RETRY;
> + goto failed;
> + }
> + status = vchiq_connect_internal(state, instance);
> +
> + if (status == VCHIQ_SUCCESS)
> + instance->connected = 1;
> +
> + mutex_unlock(&state->mutex);
> +
> +failed:
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p): returning %d", __func__, instance, status);
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_connect);
> +
> +VCHIQ_STATUS_T vchiq_add_service(
> + VCHIQ_INSTANCE_T instance,
> + const VCHIQ_SERVICE_PARAMS_T *params,
> + VCHIQ_SERVICE_HANDLE_T *phandle)
> +{
> + VCHIQ_STATUS_T status;
> + VCHIQ_STATE_T *state = instance->state;
> + VCHIQ_SERVICE_T *service = NULL;
> + int srvstate;
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p) called", __func__, instance);
> +
> + *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> +
> + srvstate = vchiq_is_connected(instance)
> + ? VCHIQ_SRVSTATE_LISTENING
> + : VCHIQ_SRVSTATE_HIDDEN;
> +
> + service = vchiq_add_service_internal(
> + state,
> + params,
> + srvstate,
> + instance,
> + NULL);
> +
> + if (service) {
> + *phandle = service->handle;
> + status = VCHIQ_SUCCESS;
> + } else
> + status = VCHIQ_ERROR;
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p): returning %d", __func__, instance, status);
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_add_service);
> +
> +VCHIQ_STATUS_T vchiq_open_service(
> + VCHIQ_INSTANCE_T instance,
> + const VCHIQ_SERVICE_PARAMS_T *params,
> + VCHIQ_SERVICE_HANDLE_T *phandle)
> +{
> + VCHIQ_STATUS_T status = VCHIQ_ERROR;
> + VCHIQ_STATE_T *state = instance->state;
> + VCHIQ_SERVICE_T *service = NULL;
> +
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p) called", __func__, instance);
> +
> + *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> +
> + if (!vchiq_is_connected(instance))
> + goto failed;
> +
> + service = vchiq_add_service_internal(state,
> + params,
> + VCHIQ_SRVSTATE_OPENING,
> + instance,
> + NULL);
> +
> + if (service) {
> + *phandle = service->handle;
> + status = vchiq_open_service_internal(service, current->pid);
> + if (status != VCHIQ_SUCCESS) {
> + vchiq_remove_service(service->handle);
> + *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> + }
> + }
> +
> +failed:
> + vchiq_log_trace(vchiq_core_log_level,
> + "%s(%p): returning %d", __func__, instance, status);
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_open_service);
> +
> +VCHIQ_STATUS_T
> +vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
> + const void *data, unsigned int size, void *userdata)
> +{
> + return vchiq_bulk_transfer(handle,
> + VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,
> + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
> +}
> +EXPORT_SYMBOL(vchiq_queue_bulk_transmit);
> +
> +VCHIQ_STATUS_T
> +vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> + unsigned int size, void *userdata)
> +{
> + return vchiq_bulk_transfer(handle,
> + VCHI_MEM_HANDLE_INVALID, data, size, userdata,
> + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
> +}
> +EXPORT_SYMBOL(vchiq_queue_bulk_receive);
> +
> +VCHIQ_STATUS_T
> +vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data,
> + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
> +{
> + VCHIQ_STATUS_T status;
> +
> + 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);
> + break;
> + case VCHIQ_BULK_MODE_BLOCKING:
> + status = vchiq_blocking_bulk_transfer(handle,
> + (void *)data, size, VCHIQ_BULK_TRANSMIT);
> + break;
> + default:
> + return VCHIQ_ERROR;
> + }
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_bulk_transmit);
> +
> +VCHIQ_STATUS_T
> +vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
> +{
> + VCHIQ_STATUS_T status;
> +
> + 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);
> + break;
> + case VCHIQ_BULK_MODE_BLOCKING:
> + status = vchiq_blocking_bulk_transfer(handle,
> + (void *)data, size, VCHIQ_BULK_RECEIVE);
> + break;
> + default:
> + return VCHIQ_ERROR;
> + }
> +
> + return status;
> +}
> +EXPORT_SYMBOL(vchiq_bulk_receive);
> +
> +static VCHIQ_STATUS_T
> +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;
> + VCHIQ_STATUS_T status;
> + struct bulk_waiter_node *waiter = NULL;
> + struct list_head *pos;
> +
> + service = find_service_by_handle(handle);
> + if (!service)
> + return VCHIQ_ERROR;
> +
> + instance = service->instance;
> +
> + 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);
> + break;
> + }
> + }
> + mutex_unlock(&instance->bulk_waiter_list_mutex);
> +
> + if (waiter) {
> + VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
> +
> + if (bulk) {
> + /* This thread has an outstanding bulk transfer. */
> + if ((bulk->data != data) ||
> + (bulk->size != size)) {
> + /* This is not a retry of the previous one.
> + * Cancel the signal when the transfer
> + * completes.
> + */
> + spin_lock(&bulk_waiter_spinlock);
> + bulk->userdata = NULL;
> + spin_unlock(&bulk_waiter_spinlock);
> + }
> + }
> + }
> +
> + if (!waiter) {
> + waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL);
> + if (!waiter) {
> + vchiq_log_error(vchiq_core_log_level,
> + "%s - out of memory", __func__);
> + return VCHIQ_ERROR;
> + }
> + }
> +
> + status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID,
> + 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;
> +
> + if (bulk) {
> + /* Cancel the signal when the transfer
> + * completes.
> + */
> + spin_lock(&bulk_waiter_spinlock);
> + bulk->userdata = NULL;
> + spin_unlock(&bulk_waiter_spinlock);
> + }
> + kfree(waiter);
> + } else {
> + waiter->pid = current->pid;
> + mutex_lock(&instance->bulk_waiter_list_mutex);
> + list_add(&waiter->list, &instance->bulk_waiter_list);
> + mutex_unlock(&instance->bulk_waiter_list_mutex);
> + vchiq_log_info(vchiq_arm_log_level,
> + "saved bulk_waiter %pK for pid %d",
> + waiter, current->pid);
> + }
> +
> + return status;
> +}
> /****************************************************************************
> *
> * add_completion
> diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
> deleted file mode 100644
> index 43c89a08bda9..000000000000
> --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
> +++ /dev/null
> @@ -1,431 +0,0 @@
> -/**
> - * Copyright (c) 2010-2012 Broadcom. All rights reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - * 1. Redistributions of source code must retain the above copyright
> - * notice, this list of conditions, and the following disclaimer,
> - * without modification.
> - * 2. Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in the
> - * documentation and/or other materials provided with the distribution.
> - * 3. The names of the above-listed copyright holders may not be used
> - * to endorse or promote products derived from this software without
> - * specific prior written permission.
> - *
> - * ALTERNATIVELY, this software may be distributed under the terms of the
> - * GNU General Public License ("GPL") version 2, as published by the Free
> - * Software Foundation.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> - */
> -
> -/* ---- Include Files ---------------------------------------------------- */
> -
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> -#include <linux/mutex.h>
> -
> -#include "vchiq_core.h"
> -#include "vchiq_arm.h"
> -#include "vchiq_killable.h"
> -
> -/* ---- Public Variables ------------------------------------------------- */
> -
> -/* ---- Private Constants and Types -------------------------------------- */
> -
> -struct bulk_waiter_node {
> - struct bulk_waiter bulk_waiter;
> - int pid;
> - struct list_head list;
> -};
> -
> -struct vchiq_instance_struct {
> - VCHIQ_STATE_T *state;
> -
> - int connected;
> -
> - struct list_head bulk_waiter_list;
> - struct mutex bulk_waiter_list_mutex;
> -};
> -
> -static VCHIQ_STATUS_T
> -vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> - unsigned int size, VCHIQ_BULK_DIR_T dir);
> -
> -#define VCHIQ_INIT_RETRIES 10
> -VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
> -{
> - VCHIQ_STATUS_T status = VCHIQ_ERROR;
> - VCHIQ_STATE_T *state;
> - VCHIQ_INSTANCE_T instance = NULL;
> - int i;
> -
> - vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
> -
> - /* VideoCore may not be ready due to boot up timing.
> - * It may never be ready if kernel and firmware are mismatched,so don't
> - * block forever.
> - */
> - for (i = 0; i < VCHIQ_INIT_RETRIES; i++) {
> - state = vchiq_get_state();
> - if (state)
> - break;
> - udelay(500);
> - }
> - if (i == VCHIQ_INIT_RETRIES) {
> - vchiq_log_error(vchiq_core_log_level,
> - "%s: videocore not initialized\n", __func__);
> - goto failed;
> - } else if (i > 0) {
> - vchiq_log_warning(vchiq_core_log_level,
> - "%s: videocore initialized after %d retries\n",
> - __func__, i);
> - }
> -
> - instance = kzalloc(sizeof(*instance), GFP_KERNEL);
> - if (!instance) {
> - vchiq_log_error(vchiq_core_log_level,
> - "%s: error allocating vchiq instance\n", __func__);
> - goto failed;
> - }
> -
> - instance->connected = 0;
> - instance->state = state;
> - mutex_init(&instance->bulk_waiter_list_mutex);
> - INIT_LIST_HEAD(&instance->bulk_waiter_list);
> -
> - *instance_out = instance;
> -
> - status = VCHIQ_SUCCESS;
> -
> -failed:
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p): returning %d", __func__, instance, status);
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_initialise);
> -
> -VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
> -{
> - VCHIQ_STATUS_T status;
> - VCHIQ_STATE_T *state = instance->state;
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p) called", __func__, instance);
> -
> - if (mutex_lock_killable(&state->mutex) != 0)
> - return VCHIQ_RETRY;
> -
> - /* Remove all services */
> - status = vchiq_shutdown_internal(state, instance);
> -
> - mutex_unlock(&state->mutex);
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p): returning %d", __func__, instance, status);
> -
> - if (status == VCHIQ_SUCCESS) {
> - struct list_head *pos, *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);
> - vchiq_log_info(vchiq_arm_log_level,
> - "bulk_waiter - cleaned up %pK for pid %d",
> - waiter, waiter->pid);
> - kfree(waiter);
> - }
> - kfree(instance);
> - }
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_shutdown);
> -
> -static int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
> -{
> - return instance->connected;
> -}
> -
> -VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
> -{
> - VCHIQ_STATUS_T status;
> - VCHIQ_STATE_T *state = instance->state;
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p) called", __func__, instance);
> -
> - if (mutex_lock_killable(&state->mutex) != 0) {
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s: call to mutex_lock failed", __func__);
> - status = VCHIQ_RETRY;
> - goto failed;
> - }
> - status = vchiq_connect_internal(state, instance);
> -
> - if (status == VCHIQ_SUCCESS)
> - instance->connected = 1;
> -
> - mutex_unlock(&state->mutex);
> -
> -failed:
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p): returning %d", __func__, instance, status);
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_connect);
> -
> -VCHIQ_STATUS_T vchiq_add_service(
> - VCHIQ_INSTANCE_T instance,
> - const VCHIQ_SERVICE_PARAMS_T *params,
> - VCHIQ_SERVICE_HANDLE_T *phandle)
> -{
> - VCHIQ_STATUS_T status;
> - VCHIQ_STATE_T *state = instance->state;
> - VCHIQ_SERVICE_T *service = NULL;
> - int srvstate;
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p) called", __func__, instance);
> -
> - *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> -
> - srvstate = vchiq_is_connected(instance)
> - ? VCHIQ_SRVSTATE_LISTENING
> - : VCHIQ_SRVSTATE_HIDDEN;
> -
> - service = vchiq_add_service_internal(
> - state,
> - params,
> - srvstate,
> - instance,
> - NULL);
> -
> - if (service) {
> - *phandle = service->handle;
> - status = VCHIQ_SUCCESS;
> - } else
> - status = VCHIQ_ERROR;
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p): returning %d", __func__, instance, status);
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_add_service);
> -
> -VCHIQ_STATUS_T vchiq_open_service(
> - VCHIQ_INSTANCE_T instance,
> - const VCHIQ_SERVICE_PARAMS_T *params,
> - VCHIQ_SERVICE_HANDLE_T *phandle)
> -{
> - VCHIQ_STATUS_T status = VCHIQ_ERROR;
> - VCHIQ_STATE_T *state = instance->state;
> - VCHIQ_SERVICE_T *service = NULL;
> -
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p) called", __func__, instance);
> -
> - *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> -
> - if (!vchiq_is_connected(instance))
> - goto failed;
> -
> - service = vchiq_add_service_internal(state,
> - params,
> - VCHIQ_SRVSTATE_OPENING,
> - instance,
> - NULL);
> -
> - if (service) {
> - *phandle = service->handle;
> - status = vchiq_open_service_internal(service, current->pid);
> - if (status != VCHIQ_SUCCESS) {
> - vchiq_remove_service(service->handle);
> - *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
> - }
> - }
> -
> -failed:
> - vchiq_log_trace(vchiq_core_log_level,
> - "%s(%p): returning %d", __func__, instance, status);
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_open_service);
> -
> -VCHIQ_STATUS_T
> -vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
> - const void *data, unsigned int size, void *userdata)
> -{
> - return vchiq_bulk_transfer(handle,
> - VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,
> - VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
> -}
> -EXPORT_SYMBOL(vchiq_queue_bulk_transmit);
> -
> -VCHIQ_STATUS_T
> -vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> - unsigned int size, void *userdata)
> -{
> - return vchiq_bulk_transfer(handle,
> - VCHI_MEM_HANDLE_INVALID, data, size, userdata,
> - VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
> -}
> -EXPORT_SYMBOL(vchiq_queue_bulk_receive);
> -
> -VCHIQ_STATUS_T
> -vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data,
> - unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
> -{
> - VCHIQ_STATUS_T status;
> -
> - 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);
> - break;
> - case VCHIQ_BULK_MODE_BLOCKING:
> - status = vchiq_blocking_bulk_transfer(handle,
> - (void *)data, size, VCHIQ_BULK_TRANSMIT);
> - break;
> - default:
> - return VCHIQ_ERROR;
> - }
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_bulk_transmit);
> -
> -VCHIQ_STATUS_T
> -vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
> - unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
> -{
> - VCHIQ_STATUS_T status;
> -
> - 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);
> - break;
> - case VCHIQ_BULK_MODE_BLOCKING:
> - status = vchiq_blocking_bulk_transfer(handle,
> - (void *)data, size, VCHIQ_BULK_RECEIVE);
> - break;
> - default:
> - return VCHIQ_ERROR;
> - }
> -
> - return status;
> -}
> -EXPORT_SYMBOL(vchiq_bulk_receive);
> -
> -static VCHIQ_STATUS_T
> -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;
> - VCHIQ_STATUS_T status;
> - struct bulk_waiter_node *waiter = NULL;
> - struct list_head *pos;
> -
> - service = find_service_by_handle(handle);
> - if (!service)
> - return VCHIQ_ERROR;
> -
> - instance = service->instance;
> -
> - 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);
> - break;
> - }
> - }
> - mutex_unlock(&instance->bulk_waiter_list_mutex);
> -
> - if (waiter) {
> - VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
> -
> - if (bulk) {
> - /* This thread has an outstanding bulk transfer. */
> - if ((bulk->data != data) ||
> - (bulk->size != size)) {
> - /* This is not a retry of the previous one.
> - * Cancel the signal when the transfer
> - * completes.
> - */
> - spin_lock(&bulk_waiter_spinlock);
> - bulk->userdata = NULL;
> - spin_unlock(&bulk_waiter_spinlock);
> - }
> - }
> - }
> -
> - if (!waiter) {
> - waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL);
> - if (!waiter) {
> - vchiq_log_error(vchiq_core_log_level,
> - "%s - out of memory", __func__);
> - return VCHIQ_ERROR;
> - }
> - }
> -
> - status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID,
> - 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;
> -
> - if (bulk) {
> - /* Cancel the signal when the transfer
> - * completes.
> - */
> - spin_lock(&bulk_waiter_spinlock);
> - bulk->userdata = NULL;
> - spin_unlock(&bulk_waiter_spinlock);
> - }
> - kfree(waiter);
> - } else {
> - waiter->pid = current->pid;
> - mutex_lock(&instance->bulk_waiter_list_mutex);
> - list_add(&waiter->list, &instance->bulk_waiter_list);
> - mutex_unlock(&instance->bulk_waiter_list_mutex);
> - vchiq_log_info(vchiq_arm_log_level,
> - "saved bulk_waiter %pK for pid %d",
> - waiter, current->pid);
> - }
> -
> - return status;
> -}
> --
> 2.9.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
More information about the linux-rpi-kernel
mailing list