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

Commit a458aa11 authored by Manoj Prabhu B's avatar Manoj Prabhu B Committed by Gerrit - the friendly Code Review server
Browse files

diag: Replace mutex with spinlock for synchronization



Synchronize rpmsg info init variables with spinlock instead of
mutex in an atomic context while freeing up the peripheral buffers.

Change-Id: Ia25c312c0a7c60d032615388758c80a06c3b78d7
Signed-off-by: default avatarManoj Prabhu B <bmanoj@codeaurora.org>
parent 8f0f3b0c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -759,7 +759,7 @@ struct diagchar_dev {
	int dci_tag;
	int dci_client_id[MAX_DCI_CLIENTS];
	struct mutex dci_mutex;
	struct mutex rpmsginfo_mutex[NUM_PERIPHERALS];
	spinlock_t rpmsginfo_lock[NUM_PERIPHERALS];
	int num_dci_client;
	unsigned char *apps_dci_buf;
	int dci_state;
+1 −1
Original line number Diff line number Diff line
@@ -4228,7 +4228,7 @@ static int __init diagchar_init(void)
	mutex_init(&driver->hdlc_recovery_mutex);
	for (i = 0; i < NUM_PERIPHERALS; i++) {
		mutex_init(&driver->diagfwd_channel_mutex[i]);
		mutex_init(&driver->rpmsginfo_mutex[i]);
		spin_lock_init(&driver->rpmsginfo_lock[i]);
		driver->diag_id_sent[i] = 0;
	}
	init_waitqueue_head(&driver->wait_q);
+67 −37
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
#include "diagfwd_rpmsg.h"
#include "diag_ipc_logging.h"

#define PERI_RPMSG rpmsg_info->peripheral

struct diag_rpmsg_read_work {
	struct diag_rpmsg_info *rpmsg_info;
	const void *ptr_read_done;
@@ -389,16 +391,17 @@ static void diag_state_open_rpmsg(void *ctxt)
static void diag_rpmsg_queue_read(void *ctxt)
{
	struct diag_rpmsg_info *rpmsg_info = NULL;
	unsigned long flags;

	if (!ctxt)
		return;

	rpmsg_info = (struct diag_rpmsg_info *)ctxt;
	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (rpmsg_info->hdl && rpmsg_info->wq &&
		atomic_read(&rpmsg_info->opened))
		queue_work(rpmsg_info->wq, &(rpmsg_info->read_work));
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
}

static void diag_state_close_rpmsg(void *ctxt)
@@ -432,6 +435,7 @@ static int diag_rpmsg_read(void *ctxt, unsigned char *buf, int buf_len)
	struct diag_rpmsg_info *rpmsg_info =  NULL;
	struct diagfwd_info *fwd_info = NULL;
	int ret_val = 0;
	unsigned long flags;

	if (!ctxt || !buf || buf_len <= 0)
		return -EIO;
@@ -442,15 +446,16 @@ static int diag_rpmsg_read(void *ctxt, unsigned char *buf, int buf_len)
		return -EIO;
	}

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (!atomic_read(&rpmsg_info->opened) ||
		!rpmsg_info->hdl || !rpmsg_info->inited) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			"diag:RPMSG channel not opened");
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return -EIO;
	}
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	fwd_info = rpmsg_info->fwd_ctxt;

@@ -474,22 +479,25 @@ static void diag_rpmsg_read_work_fn(struct work_struct *work)
	struct diag_rpmsg_info *rpmsg_info = container_of(work,
							struct diag_rpmsg_info,
							read_work);
	unsigned long flags;

	if (!rpmsg_info)
		return;

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	if (!atomic_read(&rpmsg_info->opened)) {
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return;
	}
	if (!rpmsg_info->inited) {
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		diag_ws_release();
		return;
	}
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	diagfwd_channel_read(rpmsg_info->fwd_ctxt);
}
@@ -499,6 +507,7 @@ static int diag_rpmsg_write(void *ctxt, unsigned char *buf, int len)
	struct diag_rpmsg_info *rpmsg_info = NULL;
	int err = 0;
	struct rpmsg_device *rpdev = NULL;
	unsigned long flags;

	if (!ctxt || !buf)
		return -EIO;
@@ -510,15 +519,16 @@ static int diag_rpmsg_write(void *ctxt, unsigned char *buf, int len)
		return -EINVAL;
	}

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (!rpmsg_info->inited || !rpmsg_info->hdl ||
		!atomic_read(&rpmsg_info->opened)) {
		pr_err_ratelimited("diag: In %s, rpmsg not inited, rpmsg_info: %pK, buf: %pK, len: %d\n",
				 __func__, rpmsg_info, buf, len);
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return -ENODEV;
	}
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	rpdev = (struct rpmsg_device *)rpmsg_info->hdl;
	err = rpmsg_send(rpdev->ept, buf, len);
@@ -537,15 +547,18 @@ static void diag_rpmsg_late_init_work_fn(struct work_struct *work)
	struct diag_rpmsg_info *rpmsg_info = container_of(work,
							struct diag_rpmsg_info,
							late_init_work);
	unsigned long flags;

	if (!rpmsg_info)
		return;

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (!rpmsg_info->hdl) {
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return;
	}
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	diagfwd_channel_open(rpmsg_info->fwd_ctxt);
	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "rpmsg late init p: %d t: %d\n",
@@ -558,15 +571,18 @@ static void diag_rpmsg_open_work_fn(struct work_struct *work)
	struct diag_rpmsg_info *rpmsg_info = container_of(work,
							struct diag_rpmsg_info,
							open_work);
	unsigned long flags;

	if (!rpmsg_info)
		return;

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (!rpmsg_info->inited) {
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return;
	}
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);

	if (rpmsg_info->type != TYPE_CNTL) {
		diagfwd_channel_open(rpmsg_info->fwd_ctxt);
@@ -581,16 +597,19 @@ static void diag_rpmsg_close_work_fn(struct work_struct *work)
	struct diag_rpmsg_info *rpmsg_info = container_of(work,
							struct diag_rpmsg_info,
							close_work);
	unsigned long flags;

	if (!rpmsg_info)
		return;

	mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	if (!rpmsg_info->inited || !rpmsg_info->hdl) {
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		return;
	}
	rpmsg_info->hdl = NULL;
	mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	diagfwd_channel_close(rpmsg_info->fwd_ctxt);
}

@@ -703,18 +722,20 @@ static void rpmsg_late_init(struct diag_rpmsg_info *rpmsg_info)

int diag_rpmsg_init_peripheral(uint8_t peripheral)
{
	unsigned long flags;

	if (peripheral >= NUM_PERIPHERALS) {
		pr_err("diag: In %s, invalid peripheral %d\n", __func__,
			peripheral);
		return -EINVAL;
	}

	mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
	spin_lock_irqsave(&driver->rpmsginfo_lock[peripheral], flags);
	rpmsg_late_init(&rpmsg_data[peripheral]);
	rpmsg_late_init(&rpmsg_dci[peripheral]);
	rpmsg_late_init(&rpmsg_cmd[peripheral]);
	rpmsg_late_init(&rpmsg_dci_cmd[peripheral]);
	mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[peripheral], flags);

	return 0;
}
@@ -722,6 +743,7 @@ int diag_rpmsg_init_peripheral(uint8_t peripheral)
static void __diag_rpmsg_init(struct diag_rpmsg_info *rpmsg_info)
{
	char wq_name[DIAG_RPMSG_NAME_SZ + 12];
	unsigned long flags;

	if (!rpmsg_info)
		return;
@@ -741,6 +763,7 @@ static void __diag_rpmsg_init(struct diag_rpmsg_info *rpmsg_info)
	INIT_WORK(&(rpmsg_info->close_work), diag_rpmsg_close_work_fn);
	INIT_WORK(&(rpmsg_info->read_work), diag_rpmsg_read_work_fn);
	INIT_WORK(&(rpmsg_info->late_init_work), diag_rpmsg_late_init_work_fn);
	spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
	rpmsg_info->hdl = NULL;
	rpmsg_info->fwd_ctxt = NULL;
	atomic_set(&rpmsg_info->opened, 0);
@@ -749,6 +772,7 @@ static void __diag_rpmsg_init(struct diag_rpmsg_info *rpmsg_info)
		"%s initialized fwd_ctxt: %pK hdl: %pK\n",
		rpmsg_info->name, rpmsg_info->fwd_ctxt,
		rpmsg_info->hdl);
	spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
}

void diag_rpmsg_invalidate(void *ctxt, struct diagfwd_info *fwd_ctxt)
@@ -766,28 +790,26 @@ int diag_rpmsg_init(void)
{
	uint8_t peripheral;
	struct diag_rpmsg_info *rpmsg_info = NULL;
	unsigned long flags;

	for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
		if (peripheral != PERIPHERAL_WDSP)
			continue;
		rpmsg_info = &rpmsg_cntl[peripheral];
		mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
		__diag_rpmsg_init(rpmsg_info);
		mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
		diagfwd_cntl_register(TRANSPORT_RPMSG, rpmsg_info->peripheral,
					(void *)rpmsg_info, &rpmsg_ops,
					&(rpmsg_info->fwd_ctxt));
		mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
		spin_lock_irqsave(&driver->rpmsginfo_lock[peripheral], flags);
		rpmsg_info->inited = 1;
		mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[peripheral],
			flags);
		diagfwd_channel_open(rpmsg_info->fwd_ctxt);
		diagfwd_late_open(rpmsg_info->fwd_ctxt);
		mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
		__diag_rpmsg_init(&rpmsg_data[peripheral]);
		__diag_rpmsg_init(&rpmsg_cmd[peripheral]);
		__diag_rpmsg_init(&rpmsg_dci[peripheral]);
		__diag_rpmsg_init(&rpmsg_dci_cmd[peripheral]);
		mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
	}
	return 0;
}
@@ -814,27 +836,31 @@ static void __diag_rpmsg_exit(struct diag_rpmsg_info *rpmsg_info)
void diag_rpmsg_early_exit(void)
{
	int peripheral = 0;
	unsigned long flags;

	for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
		if (peripheral != PERIPHERAL_WDSP)
			continue;
		mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
		spin_lock_irqsave(&driver->rpmsginfo_lock[peripheral], flags);
		__diag_rpmsg_exit(&rpmsg_cntl[peripheral]);
		mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[peripheral],
			flags);
	}
}

void diag_rpmsg_exit(void)
{
	int peripheral = 0;
	unsigned long flags;

	for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
		mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
		spin_lock_irqsave(&driver->rpmsginfo_lock[peripheral], flags);
		__diag_rpmsg_exit(&rpmsg_data[peripheral]);
		__diag_rpmsg_exit(&rpmsg_cmd[peripheral]);
		__diag_rpmsg_exit(&rpmsg_dci[peripheral]);
		__diag_rpmsg_exit(&rpmsg_dci_cmd[peripheral]);
		mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[peripheral],
			flags);
	}
}

@@ -860,6 +886,7 @@ static struct diag_rpmsg_info *diag_get_rpmsg_ptr(char *name)
static int diag_rpmsg_probe(struct rpmsg_device *rpdev)
{
	struct diag_rpmsg_info *rpmsg_info = NULL;
	unsigned long flags;

	if (!rpdev)
		return 0;
@@ -869,10 +896,11 @@ static int diag_rpmsg_probe(struct rpmsg_device *rpdev)
	rpmsg_info = diag_get_rpmsg_ptr(rpdev->id.name);
	if (rpmsg_info) {

		mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
		rpmsg_info->hdl = rpdev;
		atomic_set(&rpmsg_info->opened, 1);
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);

		dev_set_drvdata(&rpdev->dev, rpmsg_info);
		diagfwd_channel_read(rpmsg_info->fwd_ctxt);
@@ -885,15 +913,17 @@ static int diag_rpmsg_probe(struct rpmsg_device *rpdev)
static void diag_rpmsg_remove(struct rpmsg_device *rpdev)
{
	struct diag_rpmsg_info *rpmsg_info = NULL;
	unsigned long flags;

	if (!rpdev)
		return;

	rpmsg_info = diag_get_rpmsg_ptr(rpdev->id.name);
	if (rpmsg_info) {
		mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_lock_irqsave(&driver->rpmsginfo_lock[PERI_RPMSG], flags);
		atomic_set(&rpmsg_info->opened, 0);
		mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
		spin_unlock_irqrestore(&driver->rpmsginfo_lock[PERI_RPMSG],
			flags);
		queue_work(rpmsg_info->wq, &rpmsg_info->close_work);
	}
}