From 08de420a8014ed3fd83b2436f7e8bd9c4fcd9afe Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 17 Aug 2021 23:04:33 -0700 Subject: rpmsg: glink: Replace strncpy() with strscpy_pad() The use of strncpy() is considered deprecated for NUL-terminated strings[1]. Replace strncpy() with strscpy_pad() (as it seems this case expects the NUL padding to fill the allocation following the flexible array). This additionally silences a warning seen when building under -Warray-bounds: ./include/linux/fortify-string.h:38:30: warning: '__builtin_strncpy' offset 24 from the object at '__mptr' is out of the bounds of referenced subobject 'data' with type 'u8[]' {aka 'unsigned char[]'} at offset 24 [-Warray-bounds] 38 | #define __underlying_strncpy __builtin_strncpy | ^ ./include/linux/fortify-string.h:50:9: note: in expansion of macro '__underlying_strncpy' 50 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ drivers/rpmsg/qcom_glink_native.c: In function 'qcom_glink_work': drivers/rpmsg/qcom_glink_native.c:36:5: note: subobject 'data' declared here 36 | u8 data[]; | ^~~~ [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings Cc: Andy Gross Cc: Bjorn Andersson Cc: Ohad Ben-Cohen Cc: Mathieu Poirier Cc: linux-arm-msm@vger.kernel.org Cc: linux-remoteproc@vger.kernel.org Signed-off-by: Kees Cook Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/lkml/20210728020745.GB35706@embeddedor Link: https://lore.kernel.org/r/20210818060533.3569517-4-keescook@chromium.org Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 05533c71b10e..c7b9de655080 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1440,7 +1440,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, } rpdev->ept = &channel->ept; - strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE); + strscpy_pad(rpdev->id.name, name, RPMSG_NAME_SIZE); rpdev->src = RPMSG_ADDR_ANY; rpdev->dst = RPMSG_ADDR_ANY; rpdev->ops = &glink_device_ops; -- cgit v1.2.3 From 537d3af1bee8ad1415fda9b622d1ea6d1ae76dfa Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Mon, 12 Jul 2021 14:39:12 +0200 Subject: rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined According to the description of the rpmsg_create_ept in rpmsg_core.c the function should return NULL on error. Fixes: 2c8a57088045 ("rpmsg: Provide function stubs for API") Signed-off-by: Arnaud Pouliquen Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/20210712123912.10672-1-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- include/linux/rpmsg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index d97dcd049f18..a8dcf8a9ae88 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -231,7 +231,7 @@ static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev /* This shouldn't be possible */ WARN_ON(1); - return ERR_PTR(-ENXIO); + return NULL; } static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) -- cgit v1.2.3 From 54c9237a97e00e506ed18e89b12690a9ddfe4a56 Mon Sep 17 00:00:00 2001 From: Tinghan Shen Date: Fri, 24 Sep 2021 11:39:34 +0800 Subject: rpmsg: Change naming of mediatek rpmsg property Change from "mtk,rpmsg-name" to "mediatek,rpmsg-name" to sync with the vendor name defined in vendor-prefixes.yaml. Signed-off-by: Tinghan Shen Link: https://lore.kernel.org/r/20210924033935.2127-6-tinghan.shen@mediatek.com [Fixed capital letter in title] Signed-off-by: Mathieu Poirier Signed-off-by: Bjorn Andersson --- drivers/rpmsg/mtk_rpmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/mtk_rpmsg.c b/drivers/rpmsg/mtk_rpmsg.c index 96a17ec29140..5b4404b8be4c 100644 --- a/drivers/rpmsg/mtk_rpmsg.c +++ b/drivers/rpmsg/mtk_rpmsg.c @@ -183,7 +183,7 @@ mtk_rpmsg_match_device_subnode(struct device_node *node, const char *channel) int ret; for_each_available_child_of_node(node, child) { - ret = of_property_read_string(child, "mtk,rpmsg-name", &name); + ret = of_property_read_string(child, "mediatek,rpmsg-name", &name); if (ret) continue; -- cgit v1.2.3 From f0d1be1482aaab1aaadf68aa959f6d4c098a8e8f Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 11 Aug 2021 20:31:25 +0800 Subject: rpmsg: virtio: Remove unused including Remove including that don't need it. Signed-off-by: Cai Huoqing Reviewed-by: Mathieu Poirier Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210811123125.143-1-caihuoqing@baidu.com --- drivers/rpmsg/virtio_rpmsg_bus.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 8e49a3bacfc7..a0634ef0420b 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 63b8d79916672d35069962d87d1540c534cb2438 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 28 Sep 2021 16:29:02 +0300 Subject: rpmsg: virtio_rpmsg_bus: use dev_warn_ratelimited for msg with no recipient Even though it may be user-space's fault for this error (some application terminated or crashed without cleaning up it's endpoint), the rpmsg communication should not overflow the syslog with too many messages. A dev_warn_ratelimited() seems like a good alternative in case this can occur. Signed-off-by: Alexandru Ardelean Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210928132902.1594277-1-aardelean@deviqon.com --- drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index a0634ef0420b..5da622eb1c8f 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -748,7 +748,7 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, /* farewell, ept, we don't need you anymore */ kref_put(&ept->refcount, __ept_release); } else - dev_warn(dev, "msg received with no recipient\n"); + dev_warn_ratelimited(dev, "msg received with no recipient\n"); /* publish the real size of the buffer */ rpmsg_sg_init(&sg, msg, vrp->buf_size); -- cgit v1.2.3 From 8956927faed366b60b0355f4a4317a10e281ced7 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 30 Jul 2020 10:48:13 +0530 Subject: rpmsg: glink: Add TX_DATA_CONT command while sending 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 Signed-off-by: Deepak Kumar Singh Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1596086296-28529-4-git-send-email-deesin@codeaurora.org --- drivers/rpmsg/qcom_glink_native.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index c7b9de655080..c525f667286d 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -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; } -- cgit v1.2.3 From c7c182d4447e172f87e37d6c04879b94b8635b37 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 30 Jul 2020 10:48:14 +0530 Subject: rpmsg: glink: Remove the rpmsg dev in close_ack Un-register and register of rpmsg driver is sending invalid open_ack on closed channel. To avoid sending invalid open_ack case unregister the rpmsg device after receiving the local_close_ack from remote side. Signed-off-by: Deepak Kumar Singh Signed-off-by: Arun Kumar Neelakantam [bjorn: s/strlcpy/strscpy/] Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1596086296-28529-5-git-send-email-deesin@codeaurora.org --- drivers/rpmsg/qcom_glink_native.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index c525f667286d..ac710dc03710 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1524,6 +1524,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid) rpmsg_unregister_device(glink->dev, &chinfo); } + channel->rpdev = NULL; qcom_glink_send_close_ack(glink, channel->rcid); @@ -1537,6 +1538,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid) static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) { + struct rpmsg_channel_info chinfo; struct glink_channel *channel; unsigned long flags; @@ -1551,6 +1553,16 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) channel->lcid = 0; spin_unlock_irqrestore(&glink->idr_lock, flags); + /* Decouple the potential rpdev from the channel */ + if (channel->rpdev) { + strscpy(chinfo.name, channel->name, sizeof(chinfo.name)); + chinfo.src = RPMSG_ADDR_ANY; + chinfo.dst = RPMSG_ADDR_ANY; + + rpmsg_unregister_device(glink->dev, &chinfo); + } + channel->rpdev = NULL; + kref_put(&channel->refcount, qcom_glink_channel_release); } -- cgit v1.2.3 From 343ba27b6f9d473ec3e602cc648300eb03a7fa05 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 30 Jul 2020 10:48:15 +0530 Subject: rpmsg: glink: Remove channel decouple from rpdev release If a channel is being rapidly restarting and the kobj release worker is busy, there is a chance the rpdev_release function will run after the channel struct itself has been released. There should not be a need to decouple the channel from rpdev in the rpdev release since that should only happen from the close commands. Signed-off-by: Chris Lew Signed-off-by: Deepak Kumar Singh Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1596086296-28529-6-git-send-email-deesin@codeaurora.org --- drivers/rpmsg/qcom_glink_native.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index ac710dc03710..c1207aa88bdf 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1417,9 +1417,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = { static void qcom_glink_rpdev_release(struct device *dev) { struct rpmsg_device *rpdev = to_rpmsg_device(dev); - struct glink_channel *channel = to_glink_channel(rpdev->ept); - channel->rpdev = NULL; kfree(rpdev); } -- cgit v1.2.3 From b16a37e1846c9573a847a56fa2f31ba833dae45a Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 30 Jul 2020 10:48:16 +0530 Subject: rpmsg: glink: Send READ_NOTIFY command in FIFO full case The current design sleeps unconditionally in TX FIFO full case and wakeup only after sleep timer expires which adds random delays in clients TX path. Avoid sleep and use READ_NOTIFY command so that writer can be woken up when remote notifies about read completion by sending IRQ. Signed-off-by: Deepak Kumar Singh Signed-off-by: Arun Kumar Neelakantam Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1596086296-28529-7-git-send-email-deesin@codeaurora.org --- drivers/rpmsg/qcom_glink_native.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index c1207aa88bdf..3f377a795b33 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -92,6 +92,8 @@ struct glink_core_rx_intent { * @rcids: idr of all channels with a known remote channel id * @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 */ struct qcom_glink { struct device *dev; @@ -118,6 +120,8 @@ struct qcom_glink { unsigned long features; bool intentless; + wait_queue_head_t tx_avail_notify; + bool sent_read_notify; }; enum { @@ -301,6 +305,20 @@ static void qcom_glink_tx_write(struct qcom_glink *glink, glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); } +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; + + 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) @@ -321,12 +339,21 @@ static int qcom_glink_tx(struct qcom_glink *glink, 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, 10 * HZ); spin_lock_irqsave(&glink->tx_lock, flags); + + if (qcom_glink_tx_avail(glink) >= tlen) + glink->sent_read_notify = false; } qcom_glink_tx_write(glink, hdr, hlen, data, dlen); @@ -986,6 +1013,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)) @@ -1540,6 +1570,9 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) struct glink_channel *channel; unsigned long flags; + /* To wakeup any blocking writers */ + wake_up_all(&glink->tx_avail_notify); + spin_lock_irqsave(&glink->idr_lock, flags); channel = idr_find(&glink->lcids, lcid); if (WARN(!channel, "close ack on unknown channel\n")) { @@ -1710,6 +1743,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); -- cgit v1.2.3