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

Commit c80f88e5 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "rpmsg: glink: Send READ_NOTIFY command in FIFO full case"

parents f840f48a 17a12f2a
Loading
Loading
Loading
Loading
+43 −5
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2016-2017, Linaro Ltd
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/idr.h>
@@ -121,6 +121,8 @@ struct glink_core_rx_intent {
 * @in_reset:	reset status of this edge
 * @features:	remote features
 * @intentless:	flag to indicate that there is no intent
 * @tx_avail_notify: Waitqueue for pending tx tasks
 * @sent_read_notify: flag to check cmd sent or not
 * @ilc:	ipc logging context reference
 */
struct qcom_glink {
@@ -154,6 +156,9 @@ struct qcom_glink {

	bool intentless;

	wait_queue_head_t tx_avail_notify;
	bool sent_read_notify;

	void *ilc;
};

@@ -357,6 +362,22 @@ static void qcom_glink_pipe_reset(struct qcom_glink *glink)
		glink->rx_pipe->reset(glink->rx_pipe);
}

static void qcom_glink_send_read_notify(struct qcom_glink *glink)
{
	struct glink_msg msg;

	msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF);
	msg.param1 = 0;
	msg.param2 = 0;

	GLINK_INFO(glink->ilc, "send READ NOTIFY cmd\n");

	qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0);

	mbox_send_message(glink->mbox_chan, NULL);
	mbox_client_txdone(glink->mbox_chan, 0);
}

static int qcom_glink_tx(struct qcom_glink *glink,
			 const void *hdr, size_t hlen,
			 const void *data, size_t dlen, bool wait)
@@ -380,17 +401,27 @@ static int qcom_glink_tx(struct qcom_glink *glink,
			goto out;
		}

		if (atomic_read(&glink->in_reset)) {
			ret = -ECONNRESET;
			goto out;
		if (!glink->sent_read_notify) {
			glink->sent_read_notify = true;
			qcom_glink_send_read_notify(glink);
		}

		/* Wait without holding the tx_lock */
		spin_unlock_irqrestore(&glink->tx_lock, flags);

		usleep_range(10000, 15000);
		wait_event_timeout(glink->tx_avail_notify,
				   (qcom_glink_tx_avail(glink) >= tlen
				   || atomic_read(&glink->in_reset)), 10 * HZ);

		spin_lock_irqsave(&glink->tx_lock, flags);

		if (atomic_read(&glink->in_reset)) {
			ret = -ECONNRESET;
			goto out;
		}

		if (qcom_glink_tx_avail(glink) >= tlen)
			glink->sent_read_notify = false;
	}

	qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -1158,6 +1189,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data)
	unsigned int cmd;
	int ret = 0;

	/* To wakeup any blocking writers */
	wake_up_all(&glink->tx_avail_notify);

	for (;;) {
		avail = qcom_glink_rx_avail(glink);
		if (avail < sizeof(msg))
@@ -1904,6 +1938,9 @@ static void qcom_glink_notif_reset(void *data)
		return;
	atomic_inc(&glink->in_reset);

	/* To wakeup any blocking writers */
	wake_up_all(&glink->tx_avail_notify);

	spin_lock_irqsave(&glink->idr_lock, flags);
	idr_for_each_entry(&glink->lcids, channel, cid) {
		wake_up(&channel->intent_req_event);
@@ -1952,6 +1989,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
	spin_lock_init(&glink->rx_lock);
	INIT_LIST_HEAD(&glink->rx_queue);
	INIT_WORK(&glink->rx_work, qcom_glink_work);
	init_waitqueue_head(&glink->tx_avail_notify);

	spin_lock_init(&glink->idr_lock);
	idr_init(&glink->lcids);