rpmsg: glink: Add TX_DATA_CONT command while sending
authorArun Kumar Neelakantam <aneela@codeaurora.org>
Thu, 30 Jul 2020 05:18:13 +0000 (10:48 +0530)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Fri, 15 Oct 2021 15:35:20 +0000 (10:35 -0500)
With current design the transport can send packets of size upto
FIFO_SIZE which is 16k and return failure for all packets above 16k.

Add TX_DATA_CONT command to send packets greater than 16k by splitting
into 8K chunks.

Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
Signed-off-by: Deepak Kumar Singh <deesin@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/1596086296-28529-4-git-send-email-deesin@codeaurora.org
drivers/rpmsg/qcom_glink_native.c

index c7b9de6550808b4eb24353e0dced59818ead6092..c525f667286de8585c43765c2fa763bfb79c4936 100644 (file)
@@ -1271,6 +1271,8 @@ static int __qcom_glink_send(struct glink_channel *channel,
        } __packed req;
        int ret;
        unsigned long flags;
+       int chunk_size = len;
+       int left_size = 0;
 
        if (!glink->intentless) {
                while (!intent) {
@@ -1304,18 +1306,46 @@ static int __qcom_glink_send(struct glink_channel *channel,
                iid = intent->id;
        }
 
+       if (wait && chunk_size > SZ_8K) {
+               chunk_size = SZ_8K;
+               left_size = len - chunk_size;
+       }
        req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
        req.msg.param1 = cpu_to_le16(channel->lcid);
        req.msg.param2 = cpu_to_le32(iid);
-       req.chunk_size = cpu_to_le32(len);
-       req.left_size = cpu_to_le32(0);
+       req.chunk_size = cpu_to_le32(chunk_size);
+       req.left_size = cpu_to_le32(left_size);
 
-       ret = qcom_glink_tx(glink, &req, sizeof(req), data, len, wait);
+       ret = qcom_glink_tx(glink, &req, sizeof(req), data, chunk_size, wait);
 
        /* Mark intent available if we failed */
-       if (ret && intent)
+       if (ret && intent) {
                intent->in_use = false;
+               return ret;
+       }
 
+       while (left_size > 0) {
+               data = (void *)((char *)data + chunk_size);
+               chunk_size = left_size;
+               if (chunk_size > SZ_8K)
+                       chunk_size = SZ_8K;
+               left_size -= chunk_size;
+
+               req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA_CONT);
+               req.msg.param1 = cpu_to_le16(channel->lcid);
+               req.msg.param2 = cpu_to_le32(iid);
+               req.chunk_size = cpu_to_le32(chunk_size);
+               req.left_size = cpu_to_le32(left_size);
+
+               ret = qcom_glink_tx(glink, &req, sizeof(req), data,
+                                   chunk_size, wait);
+
+               /* Mark intent available if we failed */
+               if (ret && intent) {
+                       intent->in_use = false;
+                       break;
+               }
+       }
        return ret;
 }