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

Commit 4ae7b668 authored by Chris Lew's avatar Chris Lew
Browse files

rpmsg: glink: Move intent work to private workqueue



The rx done command is time sensitive for some remote processors. The
remote will not release memory until this ack is sent to them. Create a
kthread a queue the rx_done work on this worker instead of using the
global workthread.

Change-Id: I34a6a2e8e63f8e82c59b4f5a67e29cc5729c57a1
Signed-off-by: default avatarChris Lew <clew@codeaurora.org>
parent 21ef7b06
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/mailbox_client.h>
#include <linux/ipc_logging.h>

@@ -114,6 +115,8 @@ struct glink_core_rx_intent {
 * @rx_pipe:	pipe object for receive FIFO
 * @tx_pipe:	pipe object for transmit FIFO
 * @irq:	IRQ for signaling incoming events
 * @kworker:	kworker to handle rx_done work
 * @task:	kthread running @kworker
 * @rx_work:	worker for handling received control messages
 * @rx_lock:	protects the @rx_queue
 * @rx_queue:	queue of received control messages to be processed in @rx_work
@@ -136,6 +139,9 @@ struct qcom_glink {

	int irq;

	struct kthread_worker kworker;
	struct task_struct *task;

	struct work_struct rx_work;
	spinlock_t rx_lock;
	struct list_head rx_queue;
@@ -200,7 +206,7 @@ struct glink_channel {
	spinlock_t intent_lock;
	struct idr liids;
	struct idr riids;
	struct work_struct intent_work;
	struct kthread_work intent_work;
	struct list_head done_intents;

	struct glink_core_rx_intent *buf;
@@ -240,7 +246,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;

#define GLINK_FEATURE_INTENTLESS	BIT(1)

static void qcom_glink_rx_done_work(struct work_struct *work);
static void qcom_glink_rx_done_work(struct kthread_work *work);

static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
						      const char *name)
@@ -264,7 +270,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
	init_completion(&channel->intent_req_comp);

	INIT_LIST_HEAD(&channel->done_intents);
	INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
	kthread_init_work(&channel->intent_work, qcom_glink_rx_done_work);

	idr_init(&channel->liids);
	idr_init(&channel->riids);
@@ -280,6 +286,8 @@ static void qcom_glink_channel_release(struct kref *ref)
	unsigned long flags;

	CH_INFO(channel, "\n");
	kthread_cancel_work_sync(&channel->intent_work);

	spin_lock_irqsave(&channel->intent_lock, flags);
	idr_destroy(&channel->liids);
	idr_destroy(&channel->riids);
@@ -504,7 +512,7 @@ static void qcom_glink_send_close_ack(struct qcom_glink *glink,
	qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
}

static void qcom_glink_rx_done_work(struct work_struct *work)
static void qcom_glink_rx_done_work(struct kthread_work *work)
{
	struct glink_channel *channel = container_of(work, struct glink_channel,
						     intent_work);
@@ -566,7 +574,7 @@ static void qcom_glink_rx_done(struct qcom_glink *glink,
	list_add_tail(&intent->node, &channel->done_intents);
	spin_unlock(&channel->intent_lock);

	schedule_work(&channel->intent_work);
	kthread_queue_work(&glink->kworker, &channel->intent_work);
}

/**
@@ -1610,7 +1618,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
	CH_INFO(channel, "\n");

	/* cancel pending rx_done work */
	cancel_work_sync(&channel->intent_work);
	kthread_cancel_work_sync(&channel->intent_work);

	if (channel->rpdev) {
		strlcpy(chinfo.name, channel->name, sizeof(chinfo.name));
@@ -1800,6 +1808,15 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
		return ERR_CAST(glink->mbox_chan);
	}

	kthread_init_worker(&glink->kworker);
	glink->task = kthread_run(kthread_worker_fn, &glink->kworker,
				  "glink_%s", glink->name);
	if (IS_ERR(glink->task)) {
		dev_err(dev, "failed to spawn intent kthread %d\n",
			PTR_ERR(glink->task));
		return ERR_CAST(glink->task);
	}

	irq = of_irq_get(dev->of_node, 0);
	ret = devm_request_irq(dev, irq,
			       qcom_glink_native_intr,
@@ -1864,6 +1881,8 @@ void qcom_glink_native_remove(struct qcom_glink *glink)
	idr_destroy(&glink->rcids);
	spin_unlock_irqrestore(&glink->idr_lock, flags);

	kthread_flush_worker(&glink->kworker);
	kthread_stop(glink->task);
	qcom_glink_pipe_reset(glink);
	mbox_free_channel(glink->mbox_chan);
}