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

Commit ecfaace1 authored by Chris Lew's avatar Chris Lew
Browse files

rpmsg: glink: Add IPC logging support for glink_native



Instrument IPC logging for glink_native to track glink commands in
case there is an error.

Change-Id: I75c76da0a800aecabacaea5992e40a0382490034
Signed-off-by: default avatarChris Lew <clew@codeaurora.org>
parent 5dfea24b
Loading
Loading
Loading
Loading
+72 −1
Original line number Diff line number Diff line
@@ -28,10 +28,33 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/mailbox_client.h>
#include <linux/ipc_logging.h>

#include "rpmsg_internal.h"
#include "qcom_glink_native.h"

#define GLINK_LOG_PAGE_CNT 2
#define GLINK_INFO(ctxt, x, ...)					  \
do {									  \
	if (ctxt)							  \
		ipc_log_string(ctxt, "[%s]: "x, __func__, ##__VA_ARGS__); \
} while (0)

#define CH_INFO(ch, x, ...)						     \
do {									     \
	if (ch->glink && ch->glink->ilc)				     \
		ipc_log_string(ch->glink->ilc, "%s[%d:%d] %s: "x, ch->name,  \
			       ch->lcid, ch->rcid, __func__, ##__VA_ARGS__); \
} while (0)


#define GLINK_ERR(ctxt, x, ...)						  \
do {									  \
	pr_err_ratelimited("[%s]: "x, __func__, ##__VA_ARGS__);		  \
	if (ctxt)							  \
		ipc_log_string(ctxt, "[%s]: "x, __func__, ##__VA_ARGS__); \
} while (0)

#define GLINK_NAME_SIZE		32
#define GLINK_VERSION_1		1

@@ -98,6 +121,7 @@ struct glink_core_rx_intent {
 * @idr_lock:	synchronizes @lcids and @rcids modifications
 * @lcids:	idr of all channels with a known local channel id
 * @rcids:	idr of all channels with a known remote channel id
 * @ilc:	ipc logging context reference
 */
struct qcom_glink {
	struct device *dev;
@@ -124,6 +148,8 @@ struct qcom_glink {
	unsigned long features;

	bool intentless;

	void *ilc;
};

enum {
@@ -256,6 +282,7 @@ static void qcom_glink_channel_release(struct kref *ref)
						     refcount);
	unsigned long flags;

	CH_INFO(channel, "\n");
	spin_lock_irqsave(&channel->intent_lock, flags);
	idr_destroy(&channel->liids);
	idr_destroy(&channel->riids);
@@ -340,6 +367,7 @@ static int qcom_glink_send_version(struct qcom_glink *glink)
	msg.param1 = cpu_to_le16(GLINK_VERSION_1);
	msg.param2 = cpu_to_le32(glink->features);

	GLINK_INFO(glink->ilc, "vers:%d features:%d\n", msg.param1, msg.param2);
	return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
}

@@ -351,6 +379,7 @@ static void qcom_glink_send_version_ack(struct qcom_glink *glink)
	msg.param1 = cpu_to_le16(GLINK_VERSION_1);
	msg.param2 = cpu_to_le32(glink->features);

	GLINK_INFO(glink->ilc, "vers:%d features:%d\n", msg.param1, msg.param2);
	qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
}

@@ -363,6 +392,7 @@ static void qcom_glink_send_open_ack(struct qcom_glink *glink,
	msg.param1 = cpu_to_le16(channel->rcid);
	msg.param2 = cpu_to_le32(0);

	CH_INFO(channel, "\n");
	qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
}

@@ -382,6 +412,7 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink,

	channel->intent_req_result = granted;
	complete(&channel->intent_req_comp);
	CH_INFO(channel, "\n");
}

/**
@@ -417,6 +448,7 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink,
		return ret;

	channel->lcid = ret;
	CH_INFO(channel, "\n");

	req.msg.cmd = cpu_to_le16(RPM_CMD_OPEN);
	req.msg.param1 = cpu_to_le16(channel->lcid);
@@ -430,6 +462,8 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink,
	return 0;

remove_idr:
	CH_INFO(channel, "remote_idr\n");

	spin_lock_irqsave(&glink->idr_lock, flags);
	idr_remove(&glink->lcids, channel->lcid);
	channel->lcid = 0;
@@ -447,6 +481,7 @@ static void qcom_glink_send_close_req(struct qcom_glink *glink,
	req.param1 = cpu_to_le16(channel->lcid);
	req.param2 = 0;

	CH_INFO(channel, "\n");
	qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
}

@@ -459,6 +494,7 @@ static void qcom_glink_send_close_ack(struct qcom_glink *glink,
	req.param1 = cpu_to_le16(rcid);
	req.param2 = 0;

	GLINK_INFO(glink->ilc, "rcid:%d\n", rcid);
	qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
}

@@ -490,6 +526,7 @@ static void qcom_glink_rx_done_work(struct work_struct *work)
		cmd.lcid = cid;
		cmd.liid = iid;

		CH_INFO(channel, "reuse:%d liid:%d", reuse, iid);
		qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true);
		if (!reuse) {
			kfree(intent->data);
@@ -540,6 +577,8 @@ static void qcom_glink_receive_version(struct qcom_glink *glink,
				       u32 version,
				       u32 features)
{
	GLINK_INFO(glink->ilc, "vers:%d features:%d\n", version, features);

	switch (version) {
	case 0:
		break;
@@ -567,6 +606,8 @@ static void qcom_glink_receive_version_ack(struct qcom_glink *glink,
					   u32 version,
					   u32 features)
{
	GLINK_INFO(glink->ilc, "vers:%d features:%d\n", version, features);

	switch (version) {
	case 0:
		/* Version negotiation failed */
@@ -602,6 +643,7 @@ static int qcom_glink_send_intent_req_ack(struct qcom_glink *glink,
	msg.param1 = cpu_to_le16(channel->lcid);
	msg.param2 = cpu_to_le32(granted);

	CH_INFO(channel, "\n");
	qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);

	return 0;
@@ -635,6 +677,9 @@ static int qcom_glink_advertise_intent(struct qcom_glink *glink,
	cmd.size = cpu_to_le32(intent->size);
	cmd.liid = cpu_to_le32(intent->id);

	CH_INFO(channel, "count:%d size:%d liid:%d\n", 1,
		intent->size, intent->id);

	qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true);

	return 0;
@@ -705,6 +750,7 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink,
	}

	intent->in_use = false;
	CH_INFO(channel, "reuse:%d iid:%d\n", reuse, intent->id);

	if (!reuse) {
		idr_remove(&channel->riids, intent->id);
@@ -818,6 +864,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
		/* Drop the message */
		goto advance_rx;
	}
	CH_INFO(channel, "chunk_size:%d left_size:%d\n", chunk_size, left_size);

	if (glink->intentless) {
		/* Might have an ongoing, fragmented, message to append */
@@ -940,6 +987,8 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
		intent->id = le32_to_cpu(msg->intents[i].iid);
		intent->size = le32_to_cpu(msg->intents[i].size);

		CH_INFO(channel, "riid:%d size:%d\n", intent->id, intent->size);

		spin_lock_irqsave(&channel->intent_lock, flags);
		ret = idr_alloc(&channel->riids, intent,
				intent->id, intent->id + 1, GFP_ATOMIC);
@@ -947,6 +996,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,

		if (ret < 0)
			dev_err(glink->dev, "failed to store remote intent\n");

	}

	kfree(msg);
@@ -965,6 +1015,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
		return -EINVAL;
	}

	CH_INFO(channel, "\n");
	complete(&channel->open_ack);

	return 0;
@@ -1056,6 +1107,7 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink,
	if (IS_ERR(channel))
		return ERR_CAST(channel);

	CH_INFO(channel, "\n");
	ret = qcom_glink_send_open_req(glink, channel);
	if (ret)
		goto release_channel;
@@ -1073,12 +1125,15 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink,
	return channel;

err_timeout:
	CH_INFO(channel, "err_timeout\n");

	/* qcom_glink_send_open_req() did register the channel in lcids*/
	spin_lock_irqsave(&glink->idr_lock, flags);
	idr_remove(&glink->lcids, channel->lcid);
	spin_unlock_irqrestore(&glink->idr_lock, flags);

release_channel:
	CH_INFO(channel, "release_channel\n");
	/* Release qcom_glink_send_open_req() reference */
	kref_put(&channel->refcount, qcom_glink_channel_release);
	/* Release qcom_glink_alloc_channel() reference */
@@ -1093,6 +1148,8 @@ static int qcom_glink_create_remote(struct qcom_glink *glink,
{
	int ret;

	CH_INFO(channel, "\n");

	qcom_glink_send_open_ack(glink, channel);

	ret = qcom_glink_send_open_req(glink, channel);
@@ -1108,6 +1165,8 @@ static int qcom_glink_create_remote(struct qcom_glink *glink,
	return 0;

close_link:
	CH_INFO(channel, "close_link %d\n", ret);

	/*
	 * Send a close request to "undo" our open-ack. The close-ack will
	 * release the last reference.
@@ -1235,6 +1294,8 @@ static int qcom_glink_request_intent(struct qcom_glink *glink,
	cmd.cid = channel->lcid;
	cmd.size = size;

	CH_INFO(channel, "size:%d\n", size);

	ret = qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true);
	if (ret)
		goto unlock;
@@ -1439,17 +1500,21 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid,

		channel->rpdev = rpdev;
	}
	CH_INFO(channel, "\n");

	return 0;

free_rpdev:
	CH_INFO(channel, "free_rpdev\n");
	kfree(rpdev);
rcid_remove:
	CH_INFO(channel, "rcid_remove\n");
	spin_lock_irqsave(&glink->idr_lock, flags);
	idr_remove(&glink->rcids, channel->rcid);
	channel->rcid = 0;
	spin_unlock_irqrestore(&glink->idr_lock, flags);
free_channel:
	CH_INFO(channel, "free_channel\n");
	/* Release the reference, iff we took it */
	if (create_device)
		kref_put(&channel->refcount, qcom_glink_channel_release);
@@ -1468,6 +1533,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
	spin_unlock_irqrestore(&glink->idr_lock, flags);
	if (WARN(!channel, "close request on unknown channel\n"))
		return;
	CH_INFO(channel, "\n");

	/* cancel pending rx_done work */
	cancel_work_sync(&channel->intent_work);
@@ -1501,6 +1567,7 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)
		spin_unlock_irqrestore(&glink->idr_lock, flags);
		return;
	}
	CH_INFO(channel, "\n");

	idr_remove(&glink->lcids, channel->lcid);
	channel->lcid = 0;
@@ -1662,13 +1729,17 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
	glink->irq = irq;

	ret = qcom_glink_send_version(glink);
	if (ret)
	if (ret) {
		dev_err(dev, "failed to send version %d\n", ret);
		return ERR_PTR(ret);
	}

	ret = qcom_glink_create_chrdev(glink);
	if (ret)
		dev_err(glink->dev, "failed to register chrdev\n");

	glink->ilc = ipc_log_context_create(GLINK_LOG_PAGE_CNT, glink->name, 0);

	return glink;
}
EXPORT_SYMBOL_GPL(qcom_glink_native_probe);