提交 f27e47bc 编写于 作者: N Nicolas Saenz Julienne 提交者: Greg Kroah-Hartman

staging: vchiq: use completions instead of semaphores

It is preferred in the kernel to avoid using semaphores to wait for
events, as they are optimised for the opposite situation; where the
common case is that they are available and may block only occasionally.
FYI see this thread: https://lkml.org/lkml/2008/4/11/323.

Also completions are semantically more explicit in this case.
Signed-off-by: NNicolas Saenz Julienne <nsaenzjulienne@suse.de>
Acked-by: NStefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 51c07126
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/semaphore.h> #include <linux/completion.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -121,9 +121,9 @@ typedef struct user_service_struct { ...@@ -121,9 +121,9 @@ typedef struct user_service_struct {
int message_available_pos; int message_available_pos;
int msg_insert; int msg_insert;
int msg_remove; int msg_remove;
struct semaphore insert_event; struct completion insert_event;
struct semaphore remove_event; struct completion remove_event;
struct semaphore close_event; struct completion close_event;
VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
} USER_SERVICE_T; } USER_SERVICE_T;
...@@ -138,8 +138,8 @@ struct vchiq_instance_struct { ...@@ -138,8 +138,8 @@ struct vchiq_instance_struct {
VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];
int completion_insert; int completion_insert;
int completion_remove; int completion_remove;
struct semaphore insert_event; struct completion insert_event;
struct semaphore remove_event; struct completion remove_event;
struct mutex completion_mutex; struct mutex completion_mutex;
int connected; int connected;
...@@ -562,7 +562,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, ...@@ -562,7 +562,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
vchiq_log_trace(vchiq_arm_log_level, vchiq_log_trace(vchiq_arm_log_level,
"%s - completion queue full", __func__); "%s - completion queue full", __func__);
DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
if (down_interruptible(&instance->remove_event) != 0) { if (wait_for_completion_interruptible(
&instance->remove_event)) {
vchiq_log_info(vchiq_arm_log_level, vchiq_log_info(vchiq_arm_log_level,
"service_callback interrupted"); "service_callback interrupted");
return VCHIQ_RETRY; return VCHIQ_RETRY;
...@@ -600,7 +601,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, ...@@ -600,7 +601,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
insert++; insert++;
instance->completion_insert = insert; instance->completion_insert = insert;
up(&instance->insert_event); complete(&instance->insert_event);
return VCHIQ_SUCCESS; return VCHIQ_SUCCESS;
} }
...@@ -673,7 +674,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, ...@@ -673,7 +674,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
} }
DEBUG_TRACE(SERVICE_CALLBACK_LINE); DEBUG_TRACE(SERVICE_CALLBACK_LINE);
if (down_interruptible(&user_service->remove_event) if (wait_for_completion_interruptible(
&user_service->remove_event)
!= 0) { != 0) {
vchiq_log_info(vchiq_arm_log_level, vchiq_log_info(vchiq_arm_log_level,
"%s interrupted", __func__); "%s interrupted", __func__);
...@@ -705,7 +707,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, ...@@ -705,7 +707,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
} }
spin_unlock(&msg_queue_spinlock); spin_unlock(&msg_queue_spinlock);
up(&user_service->insert_event); complete(&user_service->insert_event);
header = NULL; header = NULL;
} }
...@@ -745,7 +747,7 @@ static void close_delivered(USER_SERVICE_T *user_service) ...@@ -745,7 +747,7 @@ static void close_delivered(USER_SERVICE_T *user_service)
unlock_service(user_service->service); unlock_service(user_service->service);
/* Wake the user-thread blocked in close_ or remove_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; user_service->close_pending = 0;
} }
...@@ -867,7 +869,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -867,7 +869,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (status == VCHIQ_SUCCESS) { if (status == VCHIQ_SUCCESS) {
/* Wake the completion thread and ask it to exit */ /* Wake the completion thread and ask it to exit */
instance->closing = 1; instance->closing = 1;
up(&instance->insert_event); complete(&instance->insert_event);
} }
break; break;
...@@ -948,9 +950,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -948,9 +950,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
instance->completion_remove - 1; instance->completion_remove - 1;
user_service->msg_insert = 0; user_service->msg_insert = 0;
user_service->msg_remove = 0; user_service->msg_remove = 0;
sema_init(&user_service->insert_event, 0); init_completion(&user_service->insert_event);
sema_init(&user_service->remove_event, 0); init_completion(&user_service->remove_event);
sema_init(&user_service->close_event, 0); init_completion(&user_service->close_event);
if (args.is_open) { if (args.is_open) {
status = vchiq_open_service_internal status = vchiq_open_service_internal
...@@ -1007,7 +1009,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1007,7 +1009,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
has been closed until the client library calls the has been closed until the client library calls the
CLOSE_DELIVERED ioctl, signalling close_event. */ CLOSE_DELIVERED ioctl, signalling close_event. */
if (user_service->close_pending && if (user_service->close_pending &&
down_interruptible(&user_service->close_event)) wait_for_completion_interruptible(
&user_service->close_event))
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
break; break;
} }
...@@ -1182,7 +1185,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1182,7 +1185,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DEBUG_TRACE(AWAIT_COMPLETION_LINE); DEBUG_TRACE(AWAIT_COMPLETION_LINE);
mutex_unlock(&instance->completion_mutex); mutex_unlock(&instance->completion_mutex);
rc = down_interruptible(&instance->insert_event); rc = wait_for_completion_interruptible(
&instance->insert_event);
mutex_lock(&instance->completion_mutex); mutex_lock(&instance->completion_mutex);
if (rc != 0) { if (rc != 0) {
DEBUG_TRACE(AWAIT_COMPLETION_LINE); DEBUG_TRACE(AWAIT_COMPLETION_LINE);
...@@ -1310,7 +1314,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1310,7 +1314,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
if (ret != 0) if (ret != 0)
up(&instance->remove_event); complete(&instance->remove_event);
mutex_unlock(&instance->completion_mutex); mutex_unlock(&instance->completion_mutex);
DEBUG_TRACE(AWAIT_COMPLETION_LINE); DEBUG_TRACE(AWAIT_COMPLETION_LINE);
} break; } break;
...@@ -1350,8 +1354,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1350,8 +1354,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
do { do {
spin_unlock(&msg_queue_spinlock); spin_unlock(&msg_queue_spinlock);
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
if (down_interruptible( if (wait_for_completion_interruptible(
&user_service->insert_event) != 0) { &user_service->insert_event)) {
vchiq_log_info(vchiq_arm_log_level, vchiq_log_info(vchiq_arm_log_level,
"DEQUEUE_MESSAGE interrupted"); "DEQUEUE_MESSAGE interrupted");
ret = -EINTR; ret = -EINTR;
...@@ -1373,7 +1377,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1373,7 +1377,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
user_service->msg_remove++; user_service->msg_remove++;
spin_unlock(&msg_queue_spinlock); spin_unlock(&msg_queue_spinlock);
up(&user_service->remove_event); complete(&user_service->remove_event);
if (header == NULL) if (header == NULL)
ret = -ENOTCONN; ret = -ENOTCONN;
else if (header->size <= args.bufsize) { else if (header->size <= args.bufsize) {
...@@ -1979,8 +1983,8 @@ vchiq_open(struct inode *inode, struct file *file) ...@@ -1979,8 +1983,8 @@ vchiq_open(struct inode *inode, struct file *file)
vchiq_debugfs_add_instance(instance); vchiq_debugfs_add_instance(instance);
sema_init(&instance->insert_event, 0); init_completion(&instance->insert_event);
sema_init(&instance->remove_event, 0); init_completion(&instance->remove_event);
mutex_init(&instance->completion_mutex); mutex_init(&instance->completion_mutex);
mutex_init(&instance->bulk_waiter_list_mutex); mutex_init(&instance->bulk_waiter_list_mutex);
INIT_LIST_HEAD(&instance->bulk_waiter_list); INIT_LIST_HEAD(&instance->bulk_waiter_list);
...@@ -2033,12 +2037,12 @@ vchiq_release(struct inode *inode, struct file *file) ...@@ -2033,12 +2037,12 @@ vchiq_release(struct inode *inode, struct file *file)
/* Wake the completion thread and ask it to exit */ /* Wake the completion thread and ask it to exit */
instance->closing = 1; instance->closing = 1;
up(&instance->insert_event); complete(&instance->insert_event);
mutex_unlock(&instance->completion_mutex); mutex_unlock(&instance->completion_mutex);
/* Wake the slot handler if the completion queue is full. */ /* Wake the slot handler if the completion queue is full. */
up(&instance->remove_event); complete(&instance->remove_event);
/* Mark all services for termination... */ /* Mark all services for termination... */
i = 0; i = 0;
...@@ -2047,7 +2051,7 @@ vchiq_release(struct inode *inode, struct file *file) ...@@ -2047,7 +2051,7 @@ vchiq_release(struct inode *inode, struct file *file)
USER_SERVICE_T *user_service = service->base.userdata; USER_SERVICE_T *user_service = service->base.userdata;
/* Wake the slot handler if the msg queue is full. */ /* Wake the slot handler if the msg queue is full. */
up(&user_service->remove_event); complete(&user_service->remove_event);
vchiq_terminate_service_internal(service); vchiq_terminate_service_internal(service);
unlock_service(service); unlock_service(service);
...@@ -2059,7 +2063,7 @@ vchiq_release(struct inode *inode, struct file *file) ...@@ -2059,7 +2063,7 @@ vchiq_release(struct inode *inode, struct file *file)
!= NULL) { != NULL) {
USER_SERVICE_T *user_service = service->base.userdata; USER_SERVICE_T *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);
...@@ -2103,7 +2107,7 @@ vchiq_release(struct inode *inode, struct file *file) ...@@ -2103,7 +2107,7 @@ vchiq_release(struct inode *inode, struct file *file)
/* Wake any blocked user-thread */ /* Wake any blocked user-thread */
if (instance->use_close_delivered) if (instance->use_close_delivered)
up(&user_service->close_event); complete(&user_service->close_event);
unlock_service(service); unlock_service(service);
} }
instance->completion_remove++; instance->completion_remove++;
......
...@@ -376,7 +376,7 @@ mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) ...@@ -376,7 +376,7 @@ mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread)
/* Unblock any sending thread. */ /* Unblock any sending thread. */
service_quota = &state->service_quotas[service->localport]; service_quota = &state->service_quotas[service->localport];
up(&service_quota->quota_event); complete(&service_quota->quota_event);
} }
static void static void
...@@ -432,9 +432,9 @@ remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) ...@@ -432,9 +432,9 @@ remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event)
event->armed = 1; event->armed = 1;
dsb(sy); dsb(sy);
if (!event->fired) { if (!event->fired) {
if (down_interruptible( if (wait_for_completion_interruptible(
(struct semaphore *) (struct completion *)
((char *)state + event->event)) != 0) { ((char *)state + event->event))) {
event->armed = 0; event->armed = 0;
return 0; return 0;
} }
...@@ -451,7 +451,7 @@ static inline void ...@@ -451,7 +451,7 @@ static inline void
remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event)
{ {
event->armed = 0; event->armed = 0;
up((struct semaphore *)((char *)state + event->event)); complete((struct completion *)((char *)state + event->event));
} }
static inline void static inline void
...@@ -581,7 +581,7 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) ...@@ -581,7 +581,7 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
/* If there is no free slot... */ /* If there is no free slot... */
if (down_trylock(&state->slot_available_event) != 0) { if (!try_wait_for_completion(&state->slot_available_event)) {
/* ...wait for one. */ /* ...wait for one. */
VCHIQ_STATS_INC(state, slot_stalls); VCHIQ_STATS_INC(state, slot_stalls);
...@@ -592,13 +592,13 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) ...@@ -592,13 +592,13 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
remote_event_signal(&state->remote->trigger); remote_event_signal(&state->remote->trigger);
if (!is_blocking || if (!is_blocking ||
(down_interruptible( (wait_for_completion_interruptible(
&state->slot_available_event) != 0)) &state->slot_available_event)))
return NULL; /* No space available */ return NULL; /* No space available */
} }
if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) { if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) {
up(&state->slot_available_event); complete(&state->slot_available_event);
pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos); pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos);
return NULL; return NULL;
} }
...@@ -678,7 +678,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) ...@@ -678,7 +678,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
/* Signal the service that it /* Signal the service that it
** has dropped below its quota ** has dropped below its quota
*/ */
up(&service_quota->quota_event); complete(&service_quota->quota_event);
else if (count == 0) { else if (count == 0) {
vchiq_log_error(vchiq_core_log_level, vchiq_log_error(vchiq_core_log_level,
"service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", "service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)",
...@@ -703,7 +703,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) ...@@ -703,7 +703,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
/* Signal the service in case /* Signal the service in case
** it has dropped below its ** it has dropped below its
** quota */ ** quota */
up(&service_quota->quota_event); complete(&service_quota->quota_event);
vchiq_log_trace( vchiq_log_trace(
vchiq_core_log_level, vchiq_core_log_level,
"%d: pfq:%d %x@%pK - slot_use->%d", "%d: pfq:%d %x@%pK - slot_use->%d",
...@@ -744,7 +744,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) ...@@ -744,7 +744,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
count - 1; count - 1;
spin_unlock(&quota_spinlock); spin_unlock(&quota_spinlock);
if (count == state->data_quota) if (count == state->data_quota)
up(&state->data_quota_event); complete(&state->data_quota_event);
} }
/* /*
...@@ -754,7 +754,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) ...@@ -754,7 +754,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
mb(); mb();
state->slot_queue_available = slot_queue_available; state->slot_queue_available = slot_queue_available;
up(&state->slot_available_event); complete(&state->slot_available_event);
} }
} }
...@@ -862,8 +862,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, ...@@ -862,8 +862,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
spin_unlock(&quota_spinlock); spin_unlock(&quota_spinlock);
mutex_unlock(&state->slot_mutex); mutex_unlock(&state->slot_mutex);
if (down_interruptible(&state->data_quota_event) if (wait_for_completion_interruptible(
!= 0) &state->data_quota_event))
return VCHIQ_RETRY; return VCHIQ_RETRY;
mutex_lock(&state->slot_mutex); mutex_lock(&state->slot_mutex);
...@@ -873,7 +873,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, ...@@ -873,7 +873,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
if ((tx_end_index == state->previous_data_index) || if ((tx_end_index == state->previous_data_index) ||
(state->data_use_count < state->data_quota)) { (state->data_use_count < state->data_quota)) {
/* Pass the signal on to other waiters */ /* Pass the signal on to other waiters */
up(&state->data_quota_event); complete(&state->data_quota_event);
break; break;
} }
} }
...@@ -893,8 +893,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, ...@@ -893,8 +893,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
service_quota->slot_use_count); service_quota->slot_use_count);
VCHIQ_SERVICE_STATS_INC(service, quota_stalls); VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
mutex_unlock(&state->slot_mutex); mutex_unlock(&state->slot_mutex);
if (down_interruptible(&service_quota->quota_event) if (wait_for_completion_interruptible(
!= 0) &service_quota->quota_event))
return VCHIQ_RETRY; return VCHIQ_RETRY;
if (service->closing) if (service->closing)
return VCHIQ_ERROR; return VCHIQ_ERROR;
...@@ -1251,7 +1251,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, ...@@ -1251,7 +1251,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,
waiter = bulk->userdata; waiter = bulk->userdata;
if (waiter) { if (waiter) {
waiter->actual = bulk->actual; waiter->actual = bulk->actual;
up(&waiter->event); complete(&waiter->event);
} }
spin_unlock(&bulk_waiter_spinlock); spin_unlock(&bulk_waiter_spinlock);
} else if (bulk->mode == } else if (bulk->mode ==
...@@ -1274,7 +1274,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, ...@@ -1274,7 +1274,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,
} }
queue->remove++; queue->remove++;
up(&service->bulk_remove_event); complete(&service->bulk_remove_event);
} }
if (!retry_poll) if (!retry_poll)
status = VCHIQ_SUCCESS; status = VCHIQ_SUCCESS;
...@@ -1667,7 +1667,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) ...@@ -1667,7 +1667,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
service->remoteport = remoteport; service->remoteport = remoteport;
vchiq_set_service_state(service, vchiq_set_service_state(service,
VCHIQ_SRVSTATE_OPEN); VCHIQ_SRVSTATE_OPEN);
up(&service->remove_event); complete(&service->remove_event);
} else } else
vchiq_log_error(vchiq_core_log_level, vchiq_log_error(vchiq_core_log_level,
"OPENACK received in state %s", "OPENACK received in state %s",
...@@ -1721,7 +1721,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) ...@@ -1721,7 +1721,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
"%d: prs CONNECT@%pK", state->id, header); "%d: prs CONNECT@%pK", state->id, header);
state->version_common = ((VCHIQ_SLOT_ZERO_T *) state->version_common = ((VCHIQ_SLOT_ZERO_T *)
state->slot_data)->version; state->slot_data)->version;
up(&state->connect); complete(&state->connect);
break; break;
case VCHIQ_MSG_BULK_RX: case VCHIQ_MSG_BULK_RX:
case VCHIQ_MSG_BULK_TX: case VCHIQ_MSG_BULK_TX:
...@@ -2055,7 +2055,7 @@ sync_func(void *v) ...@@ -2055,7 +2055,7 @@ sync_func(void *v)
vchiq_set_service_state(service, vchiq_set_service_state(service,
VCHIQ_SRVSTATE_OPENSYNC); VCHIQ_SRVSTATE_OPENSYNC);
service->sync = 1; service->sync = 1;
up(&service->remove_event); complete(&service->remove_event);
} }
release_message_sync(state, header); release_message_sync(state, header);
break; break;
...@@ -2194,33 +2194,33 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero) ...@@ -2194,33 +2194,33 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero)
initialize events and mutexes initialize events and mutexes
*/ */
sema_init(&state->connect, 0); init_completion(&state->connect);
mutex_init(&state->mutex); mutex_init(&state->mutex);
sema_init(&state->trigger_event, 0); init_completion(&state->trigger_event);
sema_init(&state->recycle_event, 0); init_completion(&state->recycle_event);
sema_init(&state->sync_trigger_event, 0); init_completion(&state->sync_trigger_event);
sema_init(&state->sync_release_event, 0); init_completion(&state->sync_release_event);
mutex_init(&state->slot_mutex); mutex_init(&state->slot_mutex);
mutex_init(&state->recycle_mutex); mutex_init(&state->recycle_mutex);
mutex_init(&state->sync_mutex); mutex_init(&state->sync_mutex);
mutex_init(&state->bulk_transfer_mutex); mutex_init(&state->bulk_transfer_mutex);
sema_init(&state->slot_available_event, 0); init_completion(&state->slot_available_event);
sema_init(&state->slot_remove_event, 0); init_completion(&state->slot_remove_event);
sema_init(&state->data_quota_event, 0); init_completion(&state->data_quota_event);
state->slot_queue_available = 0; state->slot_queue_available = 0;
for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { for (i = 0; i < VCHIQ_MAX_SERVICES; i++) {
VCHIQ_SERVICE_QUOTA_T *service_quota = VCHIQ_SERVICE_QUOTA_T *service_quota =
&state->service_quotas[i]; &state->service_quotas[i];
sema_init(&service_quota->quota_event, 0); init_completion(&service_quota->quota_event);
} }
for (i = local->slot_first; i <= local->slot_last; i++) { for (i = local->slot_first; i <= local->slot_last; i++) {
local->slot_queue[state->slot_queue_available++] = i; local->slot_queue[state->slot_queue_available++] = i;
up(&state->slot_available_event); complete(&state->slot_available_event);
} }
state->default_slot_quota = state->slot_queue_available/2; state->default_slot_quota = state->slot_queue_available/2;
...@@ -2354,8 +2354,8 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state, ...@@ -2354,8 +2354,8 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state,
service->service_use_count = 0; service->service_use_count = 0;
init_bulk_queue(&service->bulk_tx); init_bulk_queue(&service->bulk_tx);
init_bulk_queue(&service->bulk_rx); init_bulk_queue(&service->bulk_rx);
sema_init(&service->remove_event, 0); init_completion(&service->remove_event);
sema_init(&service->bulk_remove_event, 0); init_completion(&service->bulk_remove_event);
mutex_init(&service->bulk_mutex); mutex_init(&service->bulk_mutex);
memset(&service->stats, 0, sizeof(service->stats)); memset(&service->stats, 0, sizeof(service->stats));
...@@ -2470,7 +2470,7 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) ...@@ -2470,7 +2470,7 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id)
QMFLAGS_IS_BLOCKING); QMFLAGS_IS_BLOCKING);
if (status == VCHIQ_SUCCESS) { if (status == VCHIQ_SUCCESS) {
/* Wait for the ACK/NAK */ /* Wait for the ACK/NAK */
if (down_interruptible(&service->remove_event) != 0) { if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
vchiq_release_service_internal(service); vchiq_release_service_internal(service);
} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&
...@@ -2622,7 +2622,7 @@ close_service_complete(VCHIQ_SERVICE_T *service, int failstate) ...@@ -2622,7 +2622,7 @@ close_service_complete(VCHIQ_SERVICE_T *service, int failstate)
if (is_server) if (is_server)
service->closing = 0; service->closing = 0;
up(&service->remove_event); complete(&service->remove_event);
} }
} else } else
vchiq_set_service_state(service, failstate); vchiq_set_service_state(service, failstate);
...@@ -2663,7 +2663,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) ...@@ -2663,7 +2663,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)
vchiq_set_service_state(service, vchiq_set_service_state(service,
VCHIQ_SRVSTATE_LISTENING); VCHIQ_SRVSTATE_LISTENING);
} }
up(&service->remove_event); complete(&service->remove_event);
} else } else
vchiq_free_service_internal(service); vchiq_free_service_internal(service);
break; break;
...@@ -2672,7 +2672,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) ...@@ -2672,7 +2672,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)
/* The open was rejected - tell the user */ /* The open was rejected - tell the user */
vchiq_set_service_state(service, vchiq_set_service_state(service,
VCHIQ_SRVSTATE_CLOSEWAIT); VCHIQ_SRVSTATE_CLOSEWAIT);
up(&service->remove_event); complete(&service->remove_event);
} else { } else {
/* Shutdown mid-open - let the other side know */ /* Shutdown mid-open - let the other side know */
status = queue_message(state, service, status = queue_message(state, service,
...@@ -2805,7 +2805,7 @@ vchiq_free_service_internal(VCHIQ_SERVICE_T *service) ...@@ -2805,7 +2805,7 @@ vchiq_free_service_internal(VCHIQ_SERVICE_T *service)
vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);
up(&service->remove_event); complete(&service->remove_event);
/* Release the initial lock */ /* Release the initial lock */
unlock_service(service); unlock_service(service);
...@@ -2837,11 +2837,11 @@ vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) ...@@ -2837,11 +2837,11 @@ vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)
} }
if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
if (down_interruptible(&state->connect) != 0) if (wait_for_completion_interruptible(&state->connect))
return VCHIQ_RETRY; return VCHIQ_RETRY;
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
up(&state->connect); complete(&state->connect);
} }
return VCHIQ_SUCCESS; return VCHIQ_SUCCESS;
...@@ -2936,7 +2936,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) ...@@ -2936,7 +2936,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
} }
while (1) { while (1) {
if (down_interruptible(&service->remove_event) != 0) { if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
break; break;
} }
...@@ -2997,7 +2997,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) ...@@ -2997,7 +2997,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
request_poll(service->state, service, VCHIQ_POLL_REMOVE); request_poll(service->state, service, VCHIQ_POLL_REMOVE);
} }
while (1) { while (1) {
if (down_interruptible(&service->remove_event) != 0) { if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
break; break;
} }
...@@ -3054,7 +3054,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, ...@@ -3054,7 +3054,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
break; break;
case VCHIQ_BULK_MODE_BLOCKING: case VCHIQ_BULK_MODE_BLOCKING:
bulk_waiter = (struct bulk_waiter *)userdata; bulk_waiter = (struct bulk_waiter *)userdata;
sema_init(&bulk_waiter->event, 0); init_completion(&bulk_waiter->event);
bulk_waiter->actual = 0; bulk_waiter->actual = 0;
bulk_waiter->bulk = NULL; bulk_waiter->bulk = NULL;
break; break;
...@@ -3080,8 +3080,8 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, ...@@ -3080,8 +3080,8 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
do { do {
mutex_unlock(&service->bulk_mutex); mutex_unlock(&service->bulk_mutex);
if (down_interruptible(&service->bulk_remove_event) if (wait_for_completion_interruptible(
!= 0) { &service->bulk_remove_event)) {
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
goto error_exit; goto error_exit;
} }
...@@ -3157,7 +3157,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, ...@@ -3157,7 +3157,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
if (bulk_waiter) { if (bulk_waiter) {
bulk_waiter->bulk = bulk; bulk_waiter->bulk = bulk;
if (down_interruptible(&bulk_waiter->event) != 0) if (wait_for_completion_interruptible(&bulk_waiter->event))
status = VCHIQ_RETRY; status = VCHIQ_RETRY;
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
status = VCHIQ_ERROR; status = VCHIQ_ERROR;
...@@ -3326,7 +3326,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, ...@@ -3326,7 +3326,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
service_quota->message_use_count)) { service_quota->message_use_count)) {
/* Signal the service that it may have /* Signal the service that it may have
** dropped below its quota */ ** dropped below its quota */
up(&service_quota->quota_event); complete(&service_quota->quota_event);
} }
status = VCHIQ_SUCCESS; status = VCHIQ_SUCCESS;
} }
...@@ -3347,7 +3347,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, ...@@ -3347,7 +3347,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
service_quota->slot_use_count)) service_quota->slot_use_count))
/* Signal the service that it may have /* Signal the service that it may have
** dropped below its quota */ ** dropped below its quota */
up(&service_quota->quota_event); complete(&service_quota->quota_event);
status = VCHIQ_SUCCESS; status = VCHIQ_SUCCESS;
} }
} break; } break;
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#define VCHIQ_CORE_H #define VCHIQ_CORE_H
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/semaphore.h> #include <linux/completion.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include "vchiq_cfg.h" #include "vchiq_cfg.h"
...@@ -307,8 +307,8 @@ typedef struct vchiq_service_struct { ...@@ -307,8 +307,8 @@ typedef struct vchiq_service_struct {
VCHIQ_BULK_QUEUE_T bulk_tx; VCHIQ_BULK_QUEUE_T bulk_tx;
VCHIQ_BULK_QUEUE_T bulk_rx; VCHIQ_BULK_QUEUE_T bulk_rx;
struct semaphore remove_event; struct completion remove_event;
struct semaphore bulk_remove_event; struct completion bulk_remove_event;
struct mutex bulk_mutex; struct mutex bulk_mutex;
struct service_stats_struct { struct service_stats_struct {
...@@ -337,7 +337,7 @@ typedef struct vchiq_service_quota_struct { ...@@ -337,7 +337,7 @@ typedef struct vchiq_service_quota_struct {
unsigned short slot_use_count; unsigned short slot_use_count;
unsigned short message_quota; unsigned short message_quota;
unsigned short message_use_count; unsigned short message_use_count;
struct semaphore quota_event; struct completion quota_event;
int previous_tx_index; int previous_tx_index;
} VCHIQ_SERVICE_QUOTA_T; } VCHIQ_SERVICE_QUOTA_T;
...@@ -410,7 +410,7 @@ struct vchiq_state_struct { ...@@ -410,7 +410,7 @@ struct vchiq_state_struct {
unsigned short default_message_quota; unsigned short default_message_quota;
/* Event indicating connect message received */ /* Event indicating connect message received */
struct semaphore connect; struct completion connect;
/* Mutex protecting services */ /* Mutex protecting services */
struct mutex mutex; struct mutex mutex;
...@@ -426,16 +426,16 @@ struct vchiq_state_struct { ...@@ -426,16 +426,16 @@ struct vchiq_state_struct {
struct task_struct *sync_thread; struct task_struct *sync_thread;
/* Local implementation of the trigger remote event */ /* Local implementation of the trigger remote event */
struct semaphore trigger_event; struct completion trigger_event;
/* Local implementation of the recycle remote event */ /* Local implementation of the recycle remote event */
struct semaphore recycle_event; struct completion recycle_event;
/* Local implementation of the sync trigger remote event */ /* Local implementation of the sync trigger remote event */
struct semaphore sync_trigger_event; struct completion sync_trigger_event;
/* Local implementation of the sync release remote event */ /* Local implementation of the sync release remote event */
struct semaphore sync_release_event; struct completion sync_release_event;
char *tx_data; char *tx_data;
char *rx_data; char *rx_data;
...@@ -481,12 +481,12 @@ struct vchiq_state_struct { ...@@ -481,12 +481,12 @@ struct vchiq_state_struct {
int unused_service; int unused_service;
/* Signalled when a free slot becomes available. */ /* Signalled when a free slot becomes available. */
struct semaphore slot_available_event; struct completion slot_available_event;
struct semaphore slot_remove_event; struct completion slot_remove_event;
/* Signalled when a free data slot becomes available. */ /* Signalled when a free data slot becomes available. */
struct semaphore data_quota_event; struct completion data_quota_event;
struct state_stats_struct { struct state_stats_struct {
int slot_stalls; int slot_stalls;
...@@ -505,7 +505,7 @@ struct vchiq_state_struct { ...@@ -505,7 +505,7 @@ struct vchiq_state_struct {
struct bulk_waiter { struct bulk_waiter {
VCHIQ_BULK_T *bulk; VCHIQ_BULK_T *bulk;
struct semaphore event; struct completion event;
int actual; int actual;
}; };
......
...@@ -48,8 +48,8 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) ...@@ -48,8 +48,8 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
queue->write = 0; queue->write = 0;
queue->initialized = 1; queue->initialized = 1;
sema_init(&queue->pop, 0); init_completion(&queue->pop);
sema_init(&queue->push, 0); init_completion(&queue->push);
queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
if (!queue->storage) { if (!queue->storage) {
...@@ -80,7 +80,7 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) ...@@ -80,7 +80,7 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
return; return;
while (queue->write == queue->read + queue->size) { while (queue->write == queue->read + queue->size) {
if (down_interruptible(&queue->pop) != 0) if (wait_for_completion_interruptible(&queue->pop))
flush_signals(current); flush_signals(current);
} }
...@@ -100,17 +100,17 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) ...@@ -100,17 +100,17 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
queue->write++; queue->write++;
up(&queue->push); complete(&queue->push);
} }
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
{ {
while (queue->write == queue->read) { while (queue->write == queue->read) {
if (down_interruptible(&queue->push) != 0) if (wait_for_completion_interruptible(&queue->push))
flush_signals(current); flush_signals(current);
} }
up(&queue->push); // We haven't removed anything from the queue. complete(&queue->push); // We haven't removed anything from the queue.
/* /*
* Read from queue->storage must be visible after read from * Read from queue->storage must be visible after read from
...@@ -126,7 +126,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) ...@@ -126,7 +126,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
VCHIQ_HEADER_T *header; VCHIQ_HEADER_T *header;
while (queue->write == queue->read) { while (queue->write == queue->read) {
if (down_interruptible(&queue->push) != 0) if (wait_for_completion_interruptible(&queue->push))
flush_signals(current); flush_signals(current);
} }
...@@ -146,7 +146,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) ...@@ -146,7 +146,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
queue->read++; queue->read++;
up(&queue->pop); complete(&queue->pop);
return header; return header;
} }
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#define VCHIQ_UTIL_H #define VCHIQ_UTIL_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/semaphore.h> #include <linux/completion.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/kthread.h> #include <linux/kthread.h>
...@@ -60,8 +60,8 @@ typedef struct { ...@@ -60,8 +60,8 @@ typedef struct {
int write; int write;
int initialized; int initialized;
struct semaphore pop; struct completion pop;
struct semaphore push; struct completion push;
VCHIQ_HEADER_T **storage; VCHIQ_HEADER_T **storage;
} VCHIU_QUEUE_T; } VCHIU_QUEUE_T;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册