lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240518124234.2671651-6-s-vadapalli@ti.com>
Date: Sat, 18 May 2024 18:12:11 +0530
From: Siddharth Vadapalli <s-vadapalli@...com>
To: <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
        <pabeni@...hat.com>, <corbet@....net>, <rogerq@...nel.org>,
        <danishanwar@...com>, <vladimir.oltean@....com>
CC: <netdev@...r.kernel.org>, <linux-doc@...r.kernel.org>,
        <linux-kernel@...r.kernel.org>, <linux-arm-kernel@...ts.infradead.org>,
        <vigneshr@...com>, <misael.lopez@...com>, <srk@...com>,
        <s-vadapalli@...com>
Subject: [RFC PATCH net-next 05/28] net: ethernet: ti: cpsw-proxy-client: enable message exchange with EthFw

Add a new function which sends RPMsg requests to EthFw and shares the
response for the request. The RPMsg callback function copies the response
it receives from EthFw to the driver's private member, thereby allowing
the response to be shared with the newly added function which sends the
request.

Signed-off-by: Siddharth Vadapalli <s-vadapalli@...com>
---
 drivers/net/ethernet/ti/cpsw-proxy-client.c | 112 +++++++++++++++++++-
 1 file changed, 111 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ti/cpsw-proxy-client.c b/drivers/net/ethernet/ti/cpsw-proxy-client.c
index 3533f4ce1e3f..70b8cfe67921 100644
--- a/drivers/net/ethernet/ti/cpsw-proxy-client.c
+++ b/drivers/net/ethernet/ti/cpsw-proxy-client.c
@@ -12,6 +12,8 @@
 
 #include "ethfw_abi.h"
 
+#define ETHFW_RESPONSE_TIMEOUT_MS	500
+
 struct cpsw_proxy_req_params {
 	struct message	req_msg;	/* Request message to be filled */
 	u32		token;
@@ -31,16 +33,50 @@ struct cpsw_proxy_req_params {
 struct cpsw_proxy_priv {
 	struct rpmsg_device		*rpdev;
 	struct device			*dev;
+	struct cpsw_proxy_req_params	req_params;
+	struct message			resp_msg;
+	struct completion		wait_for_response;
+	int				resp_msg_len;
 };
 
 static int cpsw_proxy_client_cb(struct rpmsg_device *rpdev, void *data,
 				int len, void *priv, u32 src)
 {
+	struct cpsw_proxy_priv *proxy_priv = dev_get_drvdata(&rpdev->dev);
+	struct response_message_header *resp_msg_hdr;
+	struct message *msg = (struct message *)data;
+	struct cpsw_proxy_req_params *req_params;
 	struct device *dev = &rpdev->dev;
+	u32 msg_type, resp_id;
 
 	dev_dbg(dev, "callback invoked\n");
+	msg_type = msg->msg_hdr.msg_type;
+	switch (msg_type) {
+	case ETHFW_MSG_RESPONSE:
+		resp_msg_hdr = (struct response_message_header *)msg;
+		resp_id = resp_msg_hdr->response_id;
+		req_params = &proxy_priv->req_params;
 
-	return 0;
+		if (unlikely(resp_id == req_params->request_id - 1)) {
+			dev_info(dev, "ignoring late response for request: %u\n",
+				 resp_id);
+			return 0;
+		} else if (unlikely(resp_id != req_params->request_id)) {
+			dev_err(dev, "expected response id: %u but received %u\n",
+				req_params->request_id, resp_id);
+			return -EINVAL;
+		}
+
+		/* Share response */
+		memcpy(&proxy_priv->resp_msg, msg, len);
+		proxy_priv->resp_msg_len = len;
+		complete(&proxy_priv->wait_for_response);
+		return 0;
+
+	default:
+		dev_err(dev, "unsupported message received from EthFw\n");
+		return -EOPNOTSUPP;
+	}
 }
 
 static int create_request_message(struct cpsw_proxy_req_params *req_params)
@@ -166,6 +202,79 @@ static int create_request_message(struct cpsw_proxy_req_params *req_params)
 	return 0;
 }
 
+/* Send a request to EthFw and receive the response for request.
+ * Since the response is received by the callback function, it is
+ * copied to "resp_msg" member of "struct cpsw_proxy_priv" to
+ * allow sharing it with the following function.
+ *
+ * The request parameters within proxy_priv are expected to be set
+ * correctly by the caller. The caller is also expected to acquire
+ * lock before invoking this function, since requests and responses
+ * to/from EthFw are serialized.
+ */
+static int send_request_get_response(struct cpsw_proxy_priv *proxy_priv,
+				     struct message *response)
+{
+	struct cpsw_proxy_req_params *req_params = &proxy_priv->req_params;
+	struct message *send_msg = &req_params->req_msg;
+	struct rpmsg_device *rpdev = proxy_priv->rpdev;
+	struct response_message_header *resp_msg_hdr;
+	struct device *dev = proxy_priv->dev;
+	unsigned long timeout;
+	u32 resp_status;
+	bool retry = 0;
+	int ret;
+
+	ret = create_request_message(req_params);
+	if (ret) {
+		dev_err(dev, "failed to create request %d\n", ret);
+		goto err;
+	}
+
+	/* Send request and wait for callback function to acknowledge
+	 * receiving the response.
+	 */
+	reinit_completion(&proxy_priv->wait_for_response);
+	ret = rpmsg_send(rpdev->ept, (void *)(send_msg),
+			 sizeof(struct message));
+	if (ret) {
+		dev_err(dev, "failed to send rpmsg\n");
+		goto err;
+	}
+	timeout = msecs_to_jiffies(ETHFW_RESPONSE_TIMEOUT_MS);
+	ret = wait_for_completion_timeout(&proxy_priv->wait_for_response,
+					  timeout);
+	if (!ret) {
+		dev_err(dev, "response timedout\n");
+		ret = -ETIMEDOUT;
+		goto err;
+	}
+	ret = 0;
+
+	/* Store response shared by callback function */
+	memcpy(response, &proxy_priv->resp_msg, proxy_priv->resp_msg_len);
+	resp_msg_hdr = (struct response_message_header *)response;
+	resp_status = resp_msg_hdr->response_status;
+
+	if (unlikely(resp_status != ETHFW_RES_OK)) {
+		if (resp_status == ETHFW_RES_TRY_AGAIN) {
+			dev_info(dev, "resending request\n");
+			ret = -EAGAIN;
+			retry = 1;
+		} else {
+			dev_err(dev, "bad response status: %d\n", resp_status);
+			ret = -EIO;
+		}
+	}
+
+err:
+	req_params->request_id++;
+	if (retry)
+		ret = send_request_get_response(proxy_priv, response);
+
+	return ret;
+}
+
 static int cpsw_proxy_client_probe(struct rpmsg_device *rpdev)
 {
 	struct cpsw_proxy_priv *proxy_priv;
@@ -176,6 +285,7 @@ static int cpsw_proxy_client_probe(struct rpmsg_device *rpdev)
 
 	proxy_priv->rpdev = rpdev;
 	proxy_priv->dev = &rpdev->dev;
+	dev_set_drvdata(proxy_priv->dev, proxy_priv);
 	dev_dbg(proxy_priv->dev, "driver probed\n");
 
 	return 0;
-- 
2.40.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ