lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 3 Feb 2018 11:48:01 +0100 (CET)
From:   Stefan Wahren <stefan.wahren@...e.com>
To:     Eric Anholt <eric@...olt.net>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Arnd Bergmann <arnd@...db.de>,
        Phil Elwell <phil@...pberrypi.org>
Cc:     linux-kernel@...r.kernel.org, devel@...verdev.osuosl.org,
        linux-rpi-kernel@...ts.infradead.org,
        linux-arm-kernel@...ts.infradead.org
Subject: Re: [PATCH] staging: vc04_services: merge vchiq_kern_lib.c into
 vchiq_arm.c

[add Phil]

> Arnd Bergmann <arnd@...db.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@...db.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@...ts.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ