Commit 12cc5f92 authored by Umang Jain's avatar Umang Jain Committed by Greg Kroah-Hartman
Browse files

staging: vc04_services: Move spinlocks to vchiq_state



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: default avatarUmang Jain <umang.jain@ideasonboard.com>
Reviewed-by: default avatarStefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20240412075743.60712-9-umang.jain@ideasonboard.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6d0ef321
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@
#define KEEPALIVE_VER 1
#define KEEPALIVE_VER_MIN KEEPALIVE_VER

DEFINE_SPINLOCK(msg_queue_spinlock);
struct vchiq_state g_state;

/*
@@ -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 {
@@ -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 {
@@ -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");
@@ -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 &
@@ -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;
+0 −1
Original line number Diff line number Diff line
@@ -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 *
+20 −19
Original line number Diff line number Diff line
@@ -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[] = {
@@ -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) {
		/*
@@ -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) {
			/*
@@ -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);
		}
@@ -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
@@ -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)) {
@@ -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,
@@ -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);
@@ -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 =
@@ -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",
@@ -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);
@@ -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);
+7 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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
+12 −12
Original line number Diff line number Diff line
@@ -220,10 +220,10 @@ 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;
@@ -231,14 +231,14 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
		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)
@@ -247,7 +247,7 @@ 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;
	}
@@ -255,7 +255,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
	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) {
@@ -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;
@@ -1246,7 +1246,7 @@ 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;
@@ -1254,14 +1254,14 @@ static int vchiq_release(struct inode *inode, struct file *file)

			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);
	}