aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c')
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c243
1 files changed, 118 insertions, 125 deletions
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 7fe20d4b7ba2..45ed30bfdbf5 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -13,6 +13,7 @@
#include <linux/rcupdate.h>
#include <linux/sched/signal.h>
+#include "vchiq_arm.h"
#include "vchiq_core.h"
#define VCHIQ_SLOT_HANDLER_STACK 8192
@@ -161,7 +162,6 @@ int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT;
DEFINE_SPINLOCK(bulk_waiter_spinlock);
static DEFINE_SPINLOCK(quota_spinlock);
-struct vchiq_state *vchiq_states[VCHIQ_MAX_STATES];
static unsigned int handle_seq;
static const char *const srvstate_names[] = {
@@ -205,27 +205,27 @@ release_message_sync(struct vchiq_state *state, struct vchiq_header *header);
static const char *msg_type_str(unsigned int msg_type)
{
switch (msg_type) {
- case VCHIQ_MSG_PADDING: return "PADDING";
- case VCHIQ_MSG_CONNECT: return "CONNECT";
- case VCHIQ_MSG_OPEN: return "OPEN";
- case VCHIQ_MSG_OPENACK: return "OPENACK";
- case VCHIQ_MSG_CLOSE: return "CLOSE";
- case VCHIQ_MSG_DATA: return "DATA";
- case VCHIQ_MSG_BULK_RX: return "BULK_RX";
- case VCHIQ_MSG_BULK_TX: return "BULK_TX";
- case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE";
- case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE";
- case VCHIQ_MSG_PAUSE: return "PAUSE";
- case VCHIQ_MSG_RESUME: return "RESUME";
- case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE";
- case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE";
- case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE";
+ case VCHIQ_MSG_PADDING: return "PADDING";
+ case VCHIQ_MSG_CONNECT: return "CONNECT";
+ case VCHIQ_MSG_OPEN: return "OPEN";
+ case VCHIQ_MSG_OPENACK: return "OPENACK";
+ case VCHIQ_MSG_CLOSE: return "CLOSE";
+ case VCHIQ_MSG_DATA: return "DATA";
+ case VCHIQ_MSG_BULK_RX: return "BULK_RX";
+ case VCHIQ_MSG_BULK_TX: return "BULK_TX";
+ case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE";
+ case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE";
+ case VCHIQ_MSG_PAUSE: return "PAUSE";
+ case VCHIQ_MSG_RESUME: return "RESUME";
+ case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE";
+ case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE";
+ case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE";
}
return "???";
}
static inline void
-vchiq_set_service_state(struct vchiq_service *service, int newstate)
+set_service_state(struct vchiq_service *service, int newstate)
{
vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s",
service->state->id, service->localport,
@@ -234,13 +234,19 @@ vchiq_set_service_state(struct vchiq_service *service, int newstate)
service->srvstate = newstate;
}
+struct vchiq_service *handle_to_service(struct vchiq_instance *instance, unsigned int handle)
+{
+ int idx = handle & (VCHIQ_MAX_SERVICES - 1);
+
+ return rcu_dereference(instance->state->services[idx]);
+}
struct vchiq_service *
-find_service_by_handle(unsigned int handle)
+find_service_by_handle(struct vchiq_instance *instance, unsigned int handle)
{
struct vchiq_service *service;
rcu_read_lock();
- service = handle_to_service(handle);
+ service = handle_to_service(instance, handle);
if (service && service->srvstate != VCHIQ_SRVSTATE_FREE &&
service->handle == handle &&
kref_get_unless_zero(&service->ref_count)) {
@@ -255,9 +261,9 @@ find_service_by_handle(unsigned int handle)
}
struct vchiq_service *
-find_service_by_port(struct vchiq_state *state, int localport)
+find_service_by_port(struct vchiq_state *state, unsigned int localport)
{
- if ((unsigned int)localport <= VCHIQ_PORT_MAX) {
+ if (localport <= VCHIQ_PORT_MAX) {
struct vchiq_service *service;
rcu_read_lock();
@@ -271,7 +277,7 @@ find_service_by_port(struct vchiq_state *state, int localport)
rcu_read_unlock();
}
vchiq_log_info(vchiq_core_log_level,
- "Invalid port %d", localport);
+ "Invalid port %u", localport);
return NULL;
}
@@ -281,7 +287,7 @@ find_service_for_instance(struct vchiq_instance *instance, unsigned int handle)
struct vchiq_service *service;
rcu_read_lock();
- service = handle_to_service(handle);
+ service = handle_to_service(instance, handle);
if (service && service->srvstate != VCHIQ_SRVSTATE_FREE &&
service->handle == handle &&
service->instance == instance &&
@@ -302,7 +308,7 @@ find_closed_service_for_instance(struct vchiq_instance *instance, unsigned int h
struct vchiq_service *service;
rcu_read_lock();
- service = handle_to_service(handle);
+ service = handle_to_service(instance, handle);
if (service &&
(service->srvstate == VCHIQ_SRVSTATE_FREE ||
service->srvstate == VCHIQ_SRVSTATE_CLOSED) &&
@@ -398,26 +404,26 @@ vchiq_service_put(struct vchiq_service *service)
}
int
-vchiq_get_client_id(unsigned int handle)
+vchiq_get_client_id(struct vchiq_instance *instance, unsigned int handle)
{
struct vchiq_service *service;
int id;
rcu_read_lock();
- service = handle_to_service(handle);
+ service = handle_to_service(instance, handle);
id = service ? service->client_id : 0;
rcu_read_unlock();
return id;
}
void *
-vchiq_get_service_userdata(unsigned int handle)
+vchiq_get_service_userdata(struct vchiq_instance *instance, unsigned int handle)
{
void *userdata;
struct vchiq_service *service;
rcu_read_lock();
- service = handle_to_service(handle);
+ service = handle_to_service(instance, handle);
userdata = service ? service->base.userdata : NULL;
rcu_read_unlock();
return userdata;
@@ -466,7 +472,8 @@ make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %pK, %pK)",
service->state->id, service->localport, reason_names[reason],
header, bulk_userdata);
- status = service->base.callback(reason, header, service->handle, bulk_userdata);
+ status = service->base.callback(service->instance, reason, header, service->handle,
+ bulk_userdata);
if (status == VCHIQ_ERROR) {
vchiq_log_warning(vchiq_core_log_level,
"%d: ignoring ERROR from callback to service %x",
@@ -475,7 +482,7 @@ make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
}
if (reason != VCHIQ_MESSAGE_AVAILABLE)
- vchiq_release_message(service->handle, header);
+ vchiq_release_message(service->instance, service->handle, header);
return status;
}
@@ -521,6 +528,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
return 0;
}
event->armed = 0;
+ /* Ensure that the peer sees that we are not waiting (armed == 0). */
wmb();
}
@@ -643,6 +651,7 @@ request_poll(struct vchiq_state *state, struct vchiq_service *service,
skip_service:
state->poll_needed = 1;
+ /* Ensure the slot handler thread sees the poll_needed flag. */
wmb();
/* ... and ensure the slot handler runs. */
@@ -872,9 +881,8 @@ copy_message_data(ssize_t (*copy_callback)(void *context, void *dest, size_t off
ssize_t callback_result;
size_t max_bytes = size - pos;
- callback_result =
- copy_callback(context, dest + pos,
- pos, max_bytes);
+ callback_result = copy_callback(context, dest + pos, pos,
+ max_bytes);
if (callback_result < 0)
return callback_result;
@@ -1028,8 +1036,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
if (callback_result < 0) {
mutex_unlock(&state->slot_mutex);
- VCHIQ_SERVICE_STATS_INC(service,
- error_count);
+ VCHIQ_SERVICE_STATS_INC(service, error_count);
return VCHIQ_ERROR;
}
@@ -1037,8 +1044,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
VCHIQ_LOG_INFO))
vchiq_log_dump_mem("Sent", 0,
header->data,
- min((size_t)16,
- (size_t)callback_result));
+ min_t(size_t, 16, callback_result));
spin_lock(&quota_spinlock);
quota->message_use_count++;
@@ -1122,7 +1128,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
wmb();
if (service && (type == VCHIQ_MSG_CLOSE))
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
+ set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK))
mutex_unlock(&state->slot_mutex);
@@ -1152,6 +1158,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
remote_event_wait(&state->sync_release_event, &local->sync_release);
+ /* Ensure that reads don't overtake the remote_event_wait. */
rmb();
header = (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state,
@@ -1177,8 +1184,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
if (callback_result < 0) {
mutex_unlock(&state->slot_mutex);
- VCHIQ_SERVICE_STATS_INC(service,
- error_count);
+ VCHIQ_SERVICE_STATS_INC(service, error_count);
return VCHIQ_ERROR;
}
@@ -1187,8 +1193,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
VCHIQ_LOG_INFO))
vchiq_log_dump_mem("Sent", 0,
header->data,
- min((size_t)16,
- (size_t)callback_result));
+ min_t(size_t, 16, callback_result));
VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
@@ -1446,7 +1451,7 @@ abort_outstanding_bulks(struct vchiq_service *service,
}
if (queue->process != queue->local_insert) {
- vchiq_complete_bulk(bulk);
+ vchiq_complete_bulk(service->instance, bulk);
vchiq_log_info(SRVTRACE_LEVEL(service),
"%s %c%c%c%c d:%d ABORTED - tx len:%d, rx len:%d",
@@ -1524,15 +1529,17 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
if (queue_message_sync(state, NULL, openack_id, memcpy_copy_callback,
&ack_payload, sizeof(ack_payload), 0) == VCHIQ_RETRY)
goto bail_not_ready;
+
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
} else {
if (queue_message(state, NULL, openack_id, memcpy_copy_callback,
&ack_payload, sizeof(ack_payload), 0) == VCHIQ_RETRY)
goto bail_not_ready;
- }
- /* The service is now open */
- vchiq_set_service_state(service, service->sync ? VCHIQ_SRVSTATE_OPENSYNC
- : VCHIQ_SRVSTATE_OPEN);
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPEN);
+ }
}
/* Success - the message has been dealt with */
@@ -1666,7 +1673,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
service->peer_version);
if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
service->remoteport = remoteport;
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN);
+ set_service_state(service, VCHIQ_SRVSTATE_OPEN);
complete(&service->remove_event);
} else {
vchiq_log_error(vchiq_core_log_level, "OPENACK received in state %s",
@@ -1772,7 +1779,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
DEBUG_TRACE(PARSE_LINE);
WARN_ON(queue->process == queue->local_insert);
- vchiq_complete_bulk(bulk);
+ vchiq_complete_bulk(service->instance, bulk);
queue->process++;
mutex_unlock(&service->bulk_mutex);
DEBUG_TRACE(PARSE_LINE);
@@ -1955,6 +1962,7 @@ slot_handler_func(void *v)
DEBUG_TRACE(SLOT_HANDLER_LINE);
remote_event_wait(&state->trigger_event, &local->trigger);
+ /* Ensure that reads don't overtake the remote_event_wait. */
rmb();
DEBUG_TRACE(SLOT_HANDLER_LINE);
@@ -2017,6 +2025,7 @@ sync_func(void *v)
remote_event_wait(&state->sync_trigger_event, &local->sync_trigger);
+ /* Ensure that reads don't overtake the remote_event_wait. */
rmb();
msgid = header->msgid;
@@ -2063,7 +2072,7 @@ sync_func(void *v)
service->peer_version);
if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
service->remoteport = remoteport;
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
+ set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
service->sync = 1;
complete(&service->remove_event);
}
@@ -2097,16 +2106,6 @@ sync_func(void *v)
return 0;
}
-static void
-init_bulk_queue(struct vchiq_bulk_queue *queue)
-{
- queue->local_insert = 0;
- queue->remote_insert = 0;
- queue->process = 0;
- queue->remote_notify = 0;
- queue->remove = 0;
-}
-
inline const char *
get_conn_state_name(enum vchiq_connstate conn_state)
{
@@ -2155,18 +2154,13 @@ vchiq_init_slots(void *mem_base, int mem_size)
}
int
-vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero)
+vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, struct device *dev)
{
struct vchiq_shared_state *local;
struct vchiq_shared_state *remote;
char threadname[16];
int i, ret;
- if (vchiq_states[0]) {
- pr_err("%s: VCHIQ state already initialized\n", __func__);
- return -EINVAL;
- }
-
local = &slot_zero->slave;
remote = &slot_zero->master;
@@ -2182,6 +2176,8 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero)
memset(state, 0, sizeof(struct vchiq_state));
+ state->dev = dev;
+
/*
* initialize shared state pointers
*/
@@ -2220,8 +2216,7 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero)
state->default_slot_quota = state->slot_queue_available / 2;
state->default_message_quota =
- min((unsigned short)(state->default_slot_quota * 256),
- (unsigned short)~0);
+ min_t(unsigned short, state->default_slot_quota * 256, ~0);
state->previous_data_index = -1;
state->data_use_count = 0;
@@ -2286,8 +2281,6 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero)
wake_up_process(state->recycle_thread);
wake_up_process(state->sync_thread);
- vchiq_states[0] = state;
-
/* Indicate readiness to the other side */
local->initialised = 1;
@@ -2301,11 +2294,15 @@ fail_free_handler_thread:
return ret;
}
-void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header)
+void vchiq_msg_queue_push(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_header *header)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
int pos;
+ if (!service)
+ return;
+
while (service->msg_queue_write == service->msg_queue_read +
VCHIQ_MAX_SLOTS) {
if (wait_for_completion_interruptible(&service->msg_queue_pop))
@@ -2320,12 +2317,15 @@ void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header)
}
EXPORT_SYMBOL(vchiq_msg_queue_push);
-struct vchiq_header *vchiq_msg_hold(unsigned int handle)
+struct vchiq_header *vchiq_msg_hold(struct vchiq_instance *instance, unsigned int handle)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
struct vchiq_header *header;
int pos;
+ if (!service)
+ return NULL;
+
if (service->msg_queue_write == service->msg_queue_read)
return NULL;
@@ -2371,7 +2371,7 @@ vchiq_add_service_internal(struct vchiq_state *state,
if (ret)
return NULL;
- service = kmalloc(sizeof(*service), GFP_KERNEL);
+ service = kzalloc(sizeof(*service), GFP_KERNEL);
if (!service)
return service;
@@ -2387,28 +2387,17 @@ vchiq_add_service_internal(struct vchiq_state *state,
service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ?
VCHIQ_FOURCC_INVALID : params->fourcc;
- service->client_id = 0;
service->auto_close = 1;
- service->sync = 0;
- service->closing = 0;
- service->trace = 0;
atomic_set(&service->poll_flags, 0);
service->version = params->version;
service->version_min = params->version_min;
service->state = state;
service->instance = instance;
- service->service_use_count = 0;
- service->msg_queue_read = 0;
- service->msg_queue_write = 0;
- init_bulk_queue(&service->bulk_tx);
- init_bulk_queue(&service->bulk_rx);
init_completion(&service->remove_event);
init_completion(&service->bulk_remove_event);
init_completion(&service->msg_queue_pop);
init_completion(&service->msg_queue_push);
mutex_init(&service->bulk_mutex);
- memset(&service->stats, 0, sizeof(service->stats));
- memset(&service->msg_queue, 0, sizeof(service->msg_queue));
/*
* Although it is perfectly possible to use a spinlock
@@ -2486,7 +2475,7 @@ vchiq_add_service_internal(struct vchiq_state *state,
- 1;
/* Bring this service online */
- vchiq_set_service_state(service, srvstate);
+ set_service_state(service, srvstate);
vchiq_log_info(vchiq_core_msg_log_level, "%s Service %c%c%c%c SrcPort:%d",
(srvstate == VCHIQ_SRVSTATE_OPENING) ? "Open" : "Add",
@@ -2642,7 +2631,7 @@ close_service_complete(struct vchiq_service *service, int failstate)
} else {
newstate = VCHIQ_SRVSTATE_CLOSED;
}
- vchiq_set_service_state(service, newstate);
+ set_service_state(service, newstate);
break;
case VCHIQ_SRVSTATE_LISTENING:
break;
@@ -2678,7 +2667,7 @@ close_service_complete(struct vchiq_service *service, int failstate)
complete(&service->remove_event);
}
} else {
- vchiq_set_service_state(service, failstate);
+ set_service_state(service, failstate);
}
return status;
@@ -2711,9 +2700,8 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
} else {
service->client_id = 0;
service->remoteport = VCHIQ_PORT_FREE;
- if (service->srvstate ==
- VCHIQ_SRVSTATE_CLOSEWAIT)
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
+ set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
}
complete(&service->remove_event);
} else {
@@ -2723,7 +2711,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
case VCHIQ_SRVSTATE_OPENING:
if (close_recvd) {
/* The open was rejected - tell the user */
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT);
+ set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT);
complete(&service->remove_event);
} else {
/* Shutdown mid-open - let the other side know */
@@ -2754,8 +2742,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
if (!close_recvd) {
/* Change the state while the mutex is still held */
- vchiq_set_service_state(service,
- VCHIQ_SRVSTATE_CLOSESENT);
+ set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
mutex_unlock(&state->slot_mutex);
if (service->sync)
mutex_unlock(&state->sync_mutex);
@@ -2763,7 +2750,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
}
/* Change the state while the mutex is still held */
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD);
+ set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD);
mutex_unlock(&state->slot_mutex);
if (service->sync)
mutex_unlock(&state->sync_mutex);
@@ -2788,7 +2775,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
case VCHIQ_SRVSTATE_CLOSERECVD:
if (!close_recvd && is_server)
/* Force into LISTENING mode */
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
+ set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
status = close_service_complete(service, VCHIQ_SRVSTATE_CLOSERECVD);
break;
@@ -2837,7 +2824,7 @@ vchiq_free_service_internal(struct vchiq_service *service)
return;
}
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);
+ set_service_state(service, VCHIQ_SRVSTATE_FREE);
complete(&service->remove_event);
@@ -2855,7 +2842,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
i = 0;
while ((service = next_service_by_instance(state, instance, &i)) != NULL) {
if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)
- vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
+ set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
vchiq_service_put(service);
}
@@ -2887,16 +2874,16 @@ vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instan
/* Find all services registered to this client and remove them. */
i = 0;
while ((service = next_service_by_instance(state, instance, &i)) != NULL) {
- (void)vchiq_remove_service(service->handle);
+ (void)vchiq_remove_service(instance, service->handle);
vchiq_service_put(service);
}
}
enum vchiq_status
-vchiq_close_service(unsigned int handle)
+vchiq_close_service(struct vchiq_instance *instance, unsigned int handle)
{
/* Unregister the service */
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
enum vchiq_status status = VCHIQ_SUCCESS;
if (!service)
@@ -2918,7 +2905,7 @@ vchiq_close_service(unsigned int handle)
status = vchiq_close_service_internal(service, NO_CLOSE_RECVD);
WARN_ON(status == VCHIQ_RETRY);
} else {
- /* Mark the service for termination by the slot handler */
+ /* Mark the service for termination by the slot handler */
request_poll(service->state, service, VCHIQ_POLL_TERMINATE);
}
@@ -2951,10 +2938,10 @@ vchiq_close_service(unsigned int handle)
EXPORT_SYMBOL(vchiq_close_service);
enum vchiq_status
-vchiq_remove_service(unsigned int handle)
+vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle)
{
/* Unregister the service */
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
enum vchiq_status status = VCHIQ_SUCCESS;
if (!service)
@@ -3017,11 +3004,11 @@ vchiq_remove_service(unsigned int handle)
* When called in blocking mode, the userdata field points to a bulk_waiter
* structure.
*/
-enum vchiq_status vchiq_bulk_transfer(unsigned int handle, void *offset, void __user *uoffset,
- int size, void *userdata, enum vchiq_bulk_mode mode,
- enum vchiq_bulk_dir dir)
+enum vchiq_status vchiq_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
+ void *offset, void __user *uoffset, int size, void *userdata,
+ enum vchiq_bulk_mode mode, enum vchiq_bulk_dir dir)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
struct vchiq_bulk_queue *queue;
struct vchiq_bulk *bulk;
struct vchiq_state *state;
@@ -3096,9 +3083,13 @@ enum vchiq_status vchiq_bulk_transfer(unsigned int handle, void *offset, void __
bulk->size = size;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
- if (vchiq_prepare_bulk_data(bulk, offset, uoffset, size, dir))
+ if (vchiq_prepare_bulk_data(instance, bulk, offset, uoffset, size, dir))
goto unlock_error_exit;
+ /*
+ * Ensure that the bulk data record is visible to the peer
+ * before proceeding.
+ */
wmb();
vchiq_log_info(vchiq_core_log_level, "%d: bt (%d->%d) %cx %x@%pad %pK",
@@ -3160,7 +3151,7 @@ waiting:
unlock_both_error_exit:
mutex_unlock(&state->slot_mutex);
cancel_bulk_error_exit:
- vchiq_complete_bulk(bulk);
+ vchiq_complete_bulk(service->instance, bulk);
unlock_error_exit:
mutex_unlock(&service->bulk_mutex);
@@ -3171,13 +3162,13 @@ error_exit:
}
enum vchiq_status
-vchiq_queue_message(unsigned int handle,
+vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle,
ssize_t (*copy_callback)(void *context, void *dest,
size_t offset, size_t maxsize),
void *context,
size_t size)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
enum vchiq_status status = VCHIQ_ERROR;
int data_id;
@@ -3220,12 +3211,13 @@ error_exit:
return status;
}
-int vchiq_queue_kernel_message(unsigned int handle, void *data, unsigned int size)
+int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, void *data,
+ unsigned int size)
{
enum vchiq_status status;
while (1) {
- status = vchiq_queue_message(handle, memcpy_copy_callback,
+ status = vchiq_queue_message(instance, handle, memcpy_copy_callback,
data, size);
/*
@@ -3244,10 +3236,10 @@ int vchiq_queue_kernel_message(unsigned int handle, void *data, unsigned int siz
EXPORT_SYMBOL(vchiq_queue_kernel_message);
void
-vchiq_release_message(unsigned int handle,
+vchiq_release_message(struct vchiq_instance *instance, unsigned int handle,
struct vchiq_header *header)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
struct vchiq_shared_state *remote;
struct vchiq_state *state;
int slot_index;
@@ -3286,10 +3278,10 @@ release_message_sync(struct vchiq_state *state, struct vchiq_header *header)
}
enum vchiq_status
-vchiq_get_peer_version(unsigned int handle, short *peer_version)
+vchiq_get_peer_version(struct vchiq_instance *instance, unsigned int handle, short *peer_version)
{
enum vchiq_status status = VCHIQ_ERROR;
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
if (!service)
goto exit;
@@ -3321,9 +3313,10 @@ void vchiq_get_config(struct vchiq_config *config)
}
int
-vchiq_set_service_option(unsigned int handle, enum vchiq_service_option option, int value)
+vchiq_set_service_option(struct vchiq_instance *instance, unsigned int handle,
+ enum vchiq_service_option option, int value)
{
- struct vchiq_service *service = find_service_by_handle(handle);
+ struct vchiq_service *service = find_service_by_handle(instance, handle);
struct vchiq_service_quota *quota;
int ret = -EINVAL;
@@ -3666,10 +3659,10 @@ enum vchiq_status vchiq_send_remote_use_active(struct vchiq_state *state)
void vchiq_log_dump_mem(const char *label, u32 addr, const void *void_mem, size_t num_bytes)
{
- const u8 *mem = void_mem;
- size_t offset;
- char line_buf[100];
- char *s;
+ const u8 *mem = void_mem;
+ size_t offset;
+ char line_buf[100];
+ char *s;
while (num_bytes > 0) {
s = line_buf;