Skip to content

Commit

Permalink
staging: vc04_services: Move spinlocks to vchiq_state
Browse files Browse the repository at this point in the history
The msg_queue_spinlock, quota_spinlock and bulk_waiter_spinlock
are allocated globally. Instead move them to struct vchiq_state
and initialise them in vchiq_init_state().

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20240412075743.60712-9-umang.jain@ideasonboard.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Umang Jain authored and Greg Kroah-Hartman committed Apr 18, 2024
1 parent 6d0ef32 commit 12cc5f9
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 41 deletions.
17 changes: 8 additions & 9 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
#define KEEPALIVE_VER 1
#define KEEPALIVE_VER_MIN KEEPALIVE_VER

DEFINE_SPINLOCK(msg_queue_spinlock);
struct vchiq_state g_state;

/*
Expand Down Expand Up @@ -985,9 +984,9 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
* This is not a retry of the previous one.
* Cancel the signal when the transfer completes.
*/
spin_lock(&bulk_waiter_spinlock);
spin_lock(&service->state->bulk_waiter_spinlock);
bulk->userdata = NULL;
spin_unlock(&bulk_waiter_spinlock);
spin_unlock(&service->state->bulk_waiter_spinlock);
}
}
} else {
Expand All @@ -1004,9 +1003,9 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl

if (bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&bulk_waiter_spinlock);
spin_lock(&service->state->bulk_waiter_spinlock);
bulk->userdata = NULL;
spin_unlock(&bulk_waiter_spinlock);
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
} else {
Expand Down Expand Up @@ -1127,10 +1126,10 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
reason, header, instance, bulk_userdata);

if (header && user_service->is_vchi) {
spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);
while (user_service->msg_insert ==
(user_service->msg_remove + MSG_QUEUE_SIZE)) {
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
DEBUG_COUNT(MSG_QUEUE_FULL_COUNT);
dev_dbg(service->state->dev, "arm: msg queue full\n");
Expand Down Expand Up @@ -1167,7 +1166,7 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
return -EINVAL;
}
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);
}

user_service->msg_queue[user_service->msg_insert &
Expand All @@ -1186,7 +1185,7 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
skip_completion = true;
}

spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);
complete(&user_service->insert_event);

header = NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ struct vchiq_instance {
struct vchiq_debugfs_node debugfs_node;
};

extern spinlock_t msg_queue_spinlock;
extern struct vchiq_state g_state;

extern struct vchiq_state *
Expand Down
39 changes: 20 additions & 19 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,6 @@ static inline void check_sizes(void)
BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SERVICES);
}

DEFINE_SPINLOCK(bulk_waiter_spinlock);
static DEFINE_SPINLOCK(quota_spinlock);

static unsigned int handle_seq;

static const char *const srvstate_names[] = {
Expand Down Expand Up @@ -724,11 +721,11 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
struct vchiq_service_quota *quota = &state->service_quotas[port];
int count;

spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
count = quota->message_use_count;
if (count > 0)
quota->message_use_count = count - 1;
spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);

if (count == quota->message_quota) {
/*
Expand All @@ -747,11 +744,11 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
/* Set the found bit for this service */
BITSET_SET(service_found, port);

spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
count = quota->slot_use_count;
if (count > 0)
quota->slot_use_count = count - 1;
spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);

if (count > 0) {
/*
Expand Down Expand Up @@ -837,11 +834,11 @@ process_free_queue(struct vchiq_state *state, u32 *service_found,
if (data_found) {
int count;

spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
count = state->data_use_count;
if (count > 0)
state->data_use_count = count - 1;
spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);
if (count == state->data_quota)
complete(&state->data_quota_event);
}
Expand Down Expand Up @@ -940,7 +937,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,

quota = &state->service_quotas[service->localport];

spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);

/*
* Ensure this service doesn't use more than its quota of
Expand All @@ -955,14 +952,14 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
while ((tx_end_index != state->previous_data_index) &&
(state->data_use_count == state->data_quota)) {
VCHIQ_STATS_INC(state, data_stalls);
spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);
mutex_unlock(&state->slot_mutex);

if (wait_for_completion_interruptible(&state->data_quota_event))
return -EAGAIN;

mutex_lock(&state->slot_mutex);
spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1);
if ((tx_end_index == state->previous_data_index) ||
(state->data_use_count < state->data_quota)) {
Expand All @@ -975,7 +972,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
while ((quota->message_use_count == quota->message_quota) ||
((tx_end_index != quota->previous_tx_index) &&
(quota->slot_use_count == quota->slot_quota))) {
spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);
dev_dbg(state->dev,
"core: %d: qm:%d %s,%zx - quota stall (msg %d, slot %d)\n",
state->id, service->localport, msg_type_str(type), size,
Expand All @@ -993,11 +990,11 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
mutex_unlock(&state->slot_mutex);
return -EHOSTDOWN;
}
spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1);
}

spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);
}

header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING);
Expand Down Expand Up @@ -1040,7 +1037,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
header->data,
min_t(size_t, 16, callback_result));

spin_lock(&quota_spinlock);
spin_lock(&state->quota_spinlock);
quota->message_use_count++;

tx_end_index =
Expand All @@ -1066,7 +1063,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
slot_use_count = 0;
}

spin_unlock(&quota_spinlock);
spin_unlock(&state->quota_spinlock);

if (slot_use_count)
dev_dbg(state->dev, "core: %d: qm:%d %s,%zx - slot_use->%d (hdr %p)\n",
Expand Down Expand Up @@ -1322,13 +1319,13 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {
struct bulk_waiter *waiter;

spin_lock(&bulk_waiter_spinlock);
spin_lock(&service->state->bulk_waiter_spinlock);
waiter = bulk->userdata;
if (waiter) {
waiter->actual = bulk->actual;
complete(&waiter->event);
}
spin_unlock(&bulk_waiter_spinlock);
spin_unlock(&service->state->bulk_waiter_spinlock);
} else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) {
enum vchiq_reason reason =
get_bulk_reason(bulk);
Expand Down Expand Up @@ -2169,6 +2166,10 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, s
mutex_init(&state->sync_mutex);
mutex_init(&state->bulk_transfer_mutex);

spin_lock_init(&state->msg_queue_spinlock);
spin_lock_init(&state->bulk_waiter_spinlock);
spin_lock_init(&state->quota_spinlock);

init_completion(&state->slot_available_event);
init_completion(&state->slot_remove_event);
init_completion(&state->data_quota_event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/kthread.h>
#include <linux/kref.h>
#include <linux/rcupdate.h>
#include <linux/spinlock_types.h>
#include <linux/wait.h>

#include "../../include/linux/raspberrypi/vchiq.h"
Expand Down Expand Up @@ -348,6 +349,12 @@ struct vchiq_state {

struct mutex bulk_transfer_mutex;

spinlock_t msg_queue_spinlock;

spinlock_t bulk_waiter_spinlock;

spinlock_t quota_spinlock;

/*
* Indicates the byte position within the stream from where the next
* message will be read. The least significant bits are an index into
Expand Down
24 changes: 12 additions & 12 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,25 +220,25 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
goto out;
}

spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);
if (user_service->msg_remove == user_service->msg_insert) {
if (!args->blocking) {
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
ret = -EWOULDBLOCK;
goto out;
}
user_service->dequeue_pending = 1;
ret = 0;
do {
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
if (wait_for_completion_interruptible(&user_service->insert_event)) {
dev_dbg(service->state->dev, "arm: DEQUEUE_MESSAGE interrupted\n");
ret = -EINTR;
break;
}
spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);
} while (user_service->msg_remove == user_service->msg_insert);

if (ret)
Expand All @@ -247,15 +247,15 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,

if (WARN_ON_ONCE((int)(user_service->msg_insert -
user_service->msg_remove) < 0)) {
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);
ret = -EINVAL;
goto out;
}

header = user_service->msg_queue[user_service->msg_remove &
(MSG_QUEUE_SIZE - 1)];
user_service->msg_remove++;
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);

complete(&user_service->remove_event);
if (!header) {
Expand Down Expand Up @@ -340,9 +340,9 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
!waiter->bulk_waiter.bulk) {
if (waiter->bulk_waiter.bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&bulk_waiter_spinlock);
spin_lock(&service->state->bulk_waiter_spinlock);
waiter->bulk_waiter.bulk->userdata = NULL;
spin_unlock(&bulk_waiter_spinlock);
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
ret = 0;
Expand Down Expand Up @@ -1246,22 +1246,22 @@ static int vchiq_release(struct inode *inode, struct file *file)
break;
}

spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);

while (user_service->msg_remove != user_service->msg_insert) {
struct vchiq_header *header;
int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1);

header = user_service->msg_queue[m];
user_service->msg_remove++;
spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);

if (header)
vchiq_release_message(instance, service->handle, header);
spin_lock(&msg_queue_spinlock);
spin_lock(&service->state->msg_queue_spinlock);
}

spin_unlock(&msg_queue_spinlock);
spin_unlock(&service->state->msg_queue_spinlock);

vchiq_service_put(service);
}
Expand Down

0 comments on commit 12cc5f9

Please sign in to comment.