Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e238d71 authored by Bryan O'Donoghue's avatar Bryan O'Donoghue Committed by Greg Kroah-Hartman
Browse files

greybus: loopback: Convert cross-thread mutex to spinlock while relaxing connect locks



This patch converts the cross-thread mutex used to synchronize threads with
respect to each other to a spinlock. This is done to enable taking of locks
in the following patches while in atomic context. A small re-order of
locking in connection setup/tear-down is done to minimize the amount of
time spent in spinlock_irqsave().

Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent b933fa4a
Loading
Loading
Loading
Loading
+17 −11
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/kfifo.h>
#include <linux/kfifo.h>
#include <linux/debugfs.h>
#include <linux/debugfs.h>
#include <linux/list_sort.h>
#include <linux/list_sort.h>
#include <linux/spinlock.h>


#include <asm/div64.h>
#include <asm/div64.h>


@@ -39,7 +40,8 @@ struct gb_loopback_device {
	u32 count;
	u32 count;
	size_t size_max;
	size_t size_max;


	struct mutex mutex;
	/* We need to take a lock in atomic context */
	spinlock_t lock;
	struct list_head list;
	struct list_head list;
};
};


@@ -731,6 +733,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	struct gb_loopback *gb;
	struct gb_loopback *gb;
	int retval;
	int retval;
	char name[DEBUGFS_NAMELEN];
	char name[DEBUGFS_NAMELEN];
	unsigned long flags;


	gb = kzalloc(sizeof(*gb), GFP_KERNEL);
	gb = kzalloc(sizeof(*gb), GFP_KERNEL);
	if (!gb)
	if (!gb)
@@ -739,14 +742,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	init_waitqueue_head(&gb->wq);
	init_waitqueue_head(&gb->wq);
	gb_loopback_reset_stats(gb);
	gb_loopback_reset_stats(gb);


	mutex_lock(&gb_dev.mutex);
	if (!gb_dev.count) {
	if (!gb_dev.count) {
		/* Calculate maximum payload */
		/* Calculate maximum payload */
		gb_dev.size_max = gb_operation_get_payload_size_max(connection);
		gb_dev.size_max = gb_operation_get_payload_size_max(connection);
		if (gb_dev.size_max <=
		if (gb_dev.size_max <=
			sizeof(struct gb_loopback_transfer_request)) {
			sizeof(struct gb_loopback_transfer_request)) {
			retval = -EINVAL;
			retval = -EINVAL;
			goto out_sysfs;
			goto out_kzalloc;
		}
		}
		gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request);
		gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request);
	}
	}
@@ -783,10 +785,12 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
		goto out_kfifo1;
		goto out_kfifo1;
	}
	}


	spin_lock_irqsave(&gb_dev.lock, flags);
	gb_loopback_insert_id(gb);
	gb_loopback_insert_id(gb);
	gb_connection_latency_tag_enable(connection);
	gb_dev.count++;
	gb_dev.count++;
	mutex_unlock(&gb_dev.mutex);
	spin_unlock_irqrestore(&gb_dev.lock, flags);

	gb_connection_latency_tag_enable(connection);
	return 0;
	return 0;


out_kfifo1:
out_kfifo1:
@@ -798,7 +802,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
out_sysfs:
out_sysfs:
	debugfs_remove(gb->file);
	debugfs_remove(gb->file);
	connection->bundle->private = NULL;
	connection->bundle->private = NULL;
	mutex_unlock(&gb_dev.mutex);
out_kzalloc:
	kfree(gb);
	kfree(gb);


	return retval;
	return retval;
@@ -807,22 +811,24 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
static void gb_loopback_connection_exit(struct gb_connection *connection)
static void gb_loopback_connection_exit(struct gb_connection *connection)
{
{
	struct gb_loopback *gb = connection->bundle->private;
	struct gb_loopback *gb = connection->bundle->private;
	unsigned long flags;


	if (!IS_ERR_OR_NULL(gb->task))
	if (!IS_ERR_OR_NULL(gb->task))
		kthread_stop(gb->task);
		kthread_stop(gb->task);


	mutex_lock(&gb_dev.mutex);

	connection->bundle->private = NULL;
	connection->bundle->private = NULL;
	kfifo_free(&gb->kfifo_lat);
	kfifo_free(&gb->kfifo_lat);
	kfifo_free(&gb->kfifo_ts);
	kfifo_free(&gb->kfifo_ts);
	gb_connection_latency_tag_disable(connection);
	gb_connection_latency_tag_disable(connection);
	gb_dev.count--;
	sysfs_remove_groups(&connection->bundle->dev.kobj,
	sysfs_remove_groups(&connection->bundle->dev.kobj,
			    loopback_groups);
			    loopback_groups);
	debugfs_remove(gb->file);
	debugfs_remove(gb->file);

	spin_lock_irqsave(&gb_dev.lock, flags);
	gb_dev.count--;
	list_del(&gb->entry);
	list_del(&gb->entry);
	mutex_unlock(&gb_dev.mutex);
	spin_unlock_irqrestore(&gb_dev.lock, flags);

	kfree(gb);
	kfree(gb);
}
}


@@ -841,7 +847,7 @@ static int loopback_init(void)
	int retval;
	int retval;


	INIT_LIST_HEAD(&gb_dev.list);
	INIT_LIST_HEAD(&gb_dev.list);
	mutex_init(&gb_dev.mutex);
	spin_lock_init(&gb_dev.lock);
	gb_dev.root = debugfs_create_dir("gb_loopback", NULL);
	gb_dev.root = debugfs_create_dir("gb_loopback", NULL);


	retval = gb_protocol_register(&loopback_protocol);
	retval = gb_protocol_register(&loopback_protocol);