From d2ff0f84c1156dfd3646a4ca682b38413b409aa0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 23:01:00 +0200 Subject: rpmsg: move from strlcpy with unused retval to strscpy Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220818210100.7277-1-wsa+renesas@sang-engineering.com --- drivers/rpmsg/qcom_glink_ssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_ssr.c b/drivers/rpmsg/qcom_glink_ssr.c index 776d64446879..39ffa384c9b1 100644 --- a/drivers/rpmsg/qcom_glink_ssr.c +++ b/drivers/rpmsg/qcom_glink_ssr.c @@ -111,7 +111,7 @@ static int qcom_glink_ssr_notifier_call(struct notifier_block *nb, msg.command = cpu_to_le32(GLINK_SSR_DO_CLEANUP); msg.seq_num = cpu_to_le32(ssr->seq_num); msg.name_len = cpu_to_le32(strlen(ssr_name)); - strlcpy(msg.name, ssr_name, sizeof(msg.name)); + strscpy(msg.name, ssr_name, sizeof(msg.name)); ret = rpmsg_send(ssr->ept, &msg, sizeof(msg)); if (ret < 0) -- cgit v1.2.3 From 17b88a2050e9d1f89a53562f2adb709a8959e763 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Mon, 19 Sep 2022 16:23:59 +0530 Subject: rpmsg: char: Add lock to avoid race when rpmsg device is released When remote host goes down glink char device channel is freed and associated rpdev is destroyed through rpmsg_chrdev_eptdev_destroy(), At the same time user space apps can still try to open/poll rpmsg char device which will result in calling rpmsg_create_ept()/rpmsg_poll(). These functions will try to reference rpdev which has already been freed through rpmsg_chrdev_eptdev_destroy(). File operation functions and device removal function must be protected with lock. This patch adds existing ept lock in remove function as well. Signed-off-by: Deepak Kumar Singh Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1663584840-15762-2-git-send-email-quic_deesin@quicinc.com --- drivers/rpmsg/rpmsg_char.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 3e0b8f3496ed..a271fceb16f4 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -75,6 +75,7 @@ int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); mutex_lock(&eptdev->ept_lock); + eptdev->rpdev = NULL; if (eptdev->ept) { /* The default endpoint is released by the rpmsg core */ if (!eptdev->default_ept) @@ -128,6 +129,11 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) return -EBUSY; } + if (!eptdev->rpdev) { + mutex_unlock(&eptdev->ept_lock); + return -ENETRESET; + } + get_device(dev); /* @@ -279,7 +285,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait) if (!skb_queue_empty(&eptdev->queue)) mask |= EPOLLIN | EPOLLRDNORM; + mutex_lock(&eptdev->ept_lock); mask |= rpmsg_poll(eptdev->ept, filp, wait); + mutex_unlock(&eptdev->ept_lock); return mask; } -- cgit v1.2.3 From c23965b7f7d99bbb2604f1f02aa26fb6d1d5864d Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Mon, 19 Sep 2022 16:24:00 +0530 Subject: rpmsg: ctrl: Add lock to rpmsg_ctrldev_remove Call to rpmsg_ctrldev_ioctl() and rpmsg_ctrldev_remove() must be synchronized. In present code rpmsg_ctrldev_remove() is not protected with lock, therefore new char device creation can succeed through rpmsg_ctrldev_ioctl() call. At the same time call to rpmsg_ctrldev_remove() function for ctrl device removal will free associated rpdev device. As char device creation already succeeded, user space is free to issue open() call which maps to rpmsg_create_ept() in kernel. rpmsg_create_ept() function tries to reference rpdev which has already been freed through rpmsg_ctrldev_remove(). Issue is predominantly seen in aggressive reboot tests where rpmsg_ctrldev_ioctl() and rpmsg_ctrldev_remove() can race with each other. Adding lock in rpmsg_ctrldev_remove() avoids any new char device creation through rpmsg_ctrldev_ioctl() while remove call is already in progress. Signed-off-by: Deepak Kumar Singh Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1663584840-15762-3-git-send-email-quic_deesin@quicinc.com --- drivers/rpmsg/rpmsg_ctrl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c index 107da70fdbaa..433253835690 100644 --- a/drivers/rpmsg/rpmsg_ctrl.c +++ b/drivers/rpmsg/rpmsg_ctrl.c @@ -194,10 +194,12 @@ static void rpmsg_ctrldev_remove(struct rpmsg_device *rpdev) struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev); int ret; + mutex_lock(&ctrldev->ctrl_lock); /* Destroy all endpoints */ ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_eptdev_destroy); if (ret) dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret); + mutex_unlock(&ctrldev->ctrl_lock); cdev_device_del(&ctrldev->cdev, &ctrldev->dev); put_device(&ctrldev->dev); -- cgit v1.2.3 From f014eda5d5923a1d85f29dc7467cd90e9775cbfd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 9 Jan 2023 14:37:45 -0800 Subject: rpmsg: glink: Include types in qcom_glink_native.h Ensure that the used data types are available in qcom_glink_native.h, to silence LSP warnings. Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230109223745.1706152-1-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index 624184fc458e..e9a8671616c7 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -6,6 +6,8 @@ #ifndef __QCOM_GLINK_NATIVE_H__ #define __QCOM_GLINK_NATIVE_H__ +#include + #define GLINK_FEATURE_INTENT_REUSE BIT(0) #define GLINK_FEATURE_MIGRATION BIT(1) #define GLINK_FEATURE_TRACER_PKT BIT(2) @@ -24,6 +26,7 @@ struct qcom_glink_pipe { const void *data, size_t dlen); }; +struct device; struct qcom_glink; struct qcom_glink *qcom_glink_native_probe(struct device *dev, -- cgit v1.2.3 From 8278fd3144779d883779d1f5bcbf49da36587fd1 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:10 -0800 Subject: rpmsg: glink: Extract tx kick operation Refactor out the tx kick operations to its own function, in preparation for pushing the details to the individual transports. Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-2-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 115c0a1eddb1..5fd8b70271b7 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -303,6 +303,12 @@ 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_tx_kick(struct qcom_glink *glink) +{ + mbox_send_message(glink->mbox_chan, NULL); + mbox_client_txdone(glink->mbox_chan, 0); +} + static void qcom_glink_send_read_notify(struct qcom_glink *glink) { struct glink_msg msg; @@ -313,8 +319,7 @@ static void qcom_glink_send_read_notify(struct qcom_glink *glink) qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0); - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); + qcom_glink_tx_kick(glink); } static int qcom_glink_tx(struct qcom_glink *glink, @@ -355,9 +360,7 @@ static int qcom_glink_tx(struct qcom_glink *glink, } qcom_glink_tx_write(glink, hdr, hlen, data, dlen); - - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); + qcom_glink_tx_kick(glink); out: spin_unlock_irqrestore(&glink->tx_lock, flags); @@ -1046,9 +1049,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) break; case RPM_CMD_READ_NOTIF: qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); - - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); + qcom_glink_tx_kick(glink); break; case RPM_CMD_INTENT: qcom_glink_handle_intent(glink, param1, param2, avail); -- cgit v1.2.3 From ab9fdd41d970c38ddc0fd59e5f8f37e8d966d454 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:11 -0800 Subject: rpmsg: glink: smem: Wrap driver context The Glink SMEM driver allocates a struct device and hangs two devres-allocated pipe objects thereon. To facilitate the move of interrupt and mailbox handling to the driver, introduce a wrapper object capturing the device, glink reference and remote processor id. The type of the remoteproc reference is updated, as these are specifically targeting the SMEM implementation. Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-3-quic_bjorande@quicinc.com --- drivers/remoteproc/qcom_common.h | 3 ++- drivers/rpmsg/qcom_glink_smem.c | 43 ++++++++++++++++++++++++++++++---------- include/linux/rpmsg/qcom_glink.h | 12 +++++------ 3 files changed, 40 insertions(+), 18 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h index c35adf730be0..2747c7d9ba44 100644 --- a/drivers/remoteproc/qcom_common.h +++ b/drivers/remoteproc/qcom_common.h @@ -6,6 +6,7 @@ #include "remoteproc_internal.h" #include +struct qcom_glink_smem; struct qcom_sysmon; struct qcom_rproc_glink { @@ -15,7 +16,7 @@ struct qcom_rproc_glink { struct device *dev; struct device_node *node; - struct qcom_glink *edge; + struct qcom_glink_smem *edge; }; struct qcom_rproc_subdev { diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 579bc4443f6d..a9c477df4d68 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -33,6 +33,14 @@ #define SMEM_GLINK_NATIVE_XPRT_FIFO_0 479 #define SMEM_GLINK_NATIVE_XPRT_FIFO_1 480 +struct qcom_glink_smem { + struct device dev; + + struct qcom_glink *glink; + + u32 remote_pid; +}; + struct glink_smem_pipe { struct qcom_glink_pipe native; @@ -41,7 +49,7 @@ struct glink_smem_pipe { void *fifo; - int remote_pid; + struct qcom_glink_smem *smem; }; #define to_smem_pipe(p) container_of(p, struct glink_smem_pipe, native) @@ -49,13 +57,14 @@ struct glink_smem_pipe { static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) { struct glink_smem_pipe *pipe = to_smem_pipe(np); + struct qcom_glink_smem *smem = pipe->smem; size_t len; void *fifo; u32 head; u32 tail; if (!pipe->fifo) { - fifo = qcom_smem_get(pipe->remote_pid, + fifo = qcom_smem_get(smem->remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_1, &len); if (IS_ERR(fifo)) { pr_err("failed to acquire RX fifo handle: %ld\n", @@ -179,14 +188,17 @@ static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe, static void qcom_glink_smem_release(struct device *dev) { - kfree(dev); + struct qcom_glink_smem *smem = container_of(dev, struct qcom_glink_smem, dev); + + kfree(smem); } -struct qcom_glink *qcom_glink_smem_register(struct device *parent, - struct device_node *node) +struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, + struct device_node *node) { struct glink_smem_pipe *rx_pipe; struct glink_smem_pipe *tx_pipe; + struct qcom_glink_smem *smem; struct qcom_glink *glink; struct device *dev; u32 remote_pid; @@ -194,10 +206,12 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, size_t size; int ret; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) + smem = kzalloc(sizeof(*smem), GFP_KERNEL); + if (!smem) return ERR_PTR(-ENOMEM); + dev = &smem->dev; + dev->parent = parent; dev->of_node = node; dev->release = qcom_glink_smem_release; @@ -216,6 +230,8 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, goto err_put_dev; } + smem->remote_pid = remote_pid; + rx_pipe = devm_kzalloc(dev, sizeof(*rx_pipe), GFP_KERNEL); tx_pipe = devm_kzalloc(dev, sizeof(*tx_pipe), GFP_KERNEL); if (!rx_pipe || !tx_pipe) { @@ -264,14 +280,14 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, goto err_put_dev; } + rx_pipe->smem = smem; rx_pipe->native.avail = glink_smem_rx_avail; rx_pipe->native.peak = glink_smem_rx_peak; rx_pipe->native.advance = glink_smem_rx_advance; - rx_pipe->remote_pid = remote_pid; + tx_pipe->smem = smem; tx_pipe->native.avail = glink_smem_tx_avail; tx_pipe->native.write = glink_smem_tx_write; - tx_pipe->remote_pid = remote_pid; *rx_pipe->tail = 0; *tx_pipe->head = 0; @@ -285,7 +301,10 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, goto err_put_dev; } - return glink; + smem->glink = glink; + + return smem; + err_put_dev: device_unregister(dev); @@ -294,8 +313,10 @@ err_put_dev: } EXPORT_SYMBOL_GPL(qcom_glink_smem_register); -void qcom_glink_smem_unregister(struct qcom_glink *glink) +void qcom_glink_smem_unregister(struct qcom_glink_smem *smem) { + struct qcom_glink *glink = smem->glink; + qcom_glink_native_remove(glink); qcom_glink_native_unregister(glink); } diff --git a/include/linux/rpmsg/qcom_glink.h b/include/linux/rpmsg/qcom_glink.h index 22fc3a69b683..bfbd48f435fa 100644 --- a/include/linux/rpmsg/qcom_glink.h +++ b/include/linux/rpmsg/qcom_glink.h @@ -5,7 +5,7 @@ #include -struct qcom_glink; +struct qcom_glink_smem; #if IS_ENABLED(CONFIG_RPMSG_QCOM_GLINK) void qcom_glink_ssr_notify(const char *ssr_name); @@ -15,20 +15,20 @@ static inline void qcom_glink_ssr_notify(const char *ssr_name) {} #if IS_ENABLED(CONFIG_RPMSG_QCOM_GLINK_SMEM) -struct qcom_glink *qcom_glink_smem_register(struct device *parent, - struct device_node *node); -void qcom_glink_smem_unregister(struct qcom_glink *glink); +struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, + struct device_node *node); +void qcom_glink_smem_unregister(struct qcom_glink_smem *glink); #else -static inline struct qcom_glink * +static inline struct qcom_glink_smem * qcom_glink_smem_register(struct device *parent, struct device_node *node) { return NULL; } -static inline void qcom_glink_smem_unregister(struct qcom_glink *glink) {} +static inline void qcom_glink_smem_unregister(struct qcom_glink_smem *glink) {} #endif #endif -- cgit v1.2.3 From 178c3af447f92c58d5b1153df2cd02b755c083c8 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:12 -0800 Subject: rpmsg: glink: rpm: Wrap driver context As with the SMEM driver update, wrap the RPM context in a struct to facilitate the upcoming changes of moving IRQ and mailbox registration to the driver. Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-4-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_rpm.c | 44 +++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index f64f45d1a735..6443843df6ca 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -53,6 +53,13 @@ struct glink_rpm_pipe { void __iomem *fifo; }; +struct glink_rpm { + struct qcom_glink *glink; + + struct glink_rpm_pipe rx_pipe; + struct glink_rpm_pipe tx_pipe; +}; + static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); @@ -257,8 +264,7 @@ err_inval: static int glink_rpm_probe(struct platform_device *pdev) { struct qcom_glink *glink; - struct glink_rpm_pipe *rx_pipe; - struct glink_rpm_pipe *tx_pipe; + struct glink_rpm *rpm; struct device_node *np; void __iomem *msg_ram; size_t msg_ram_size; @@ -266,9 +272,8 @@ static int glink_rpm_probe(struct platform_device *pdev) struct resource r; int ret; - rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL); - tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL); - if (!rx_pipe || !tx_pipe) + rpm = devm_kzalloc(&pdev->dev, sizeof(*rpm), GFP_KERNEL); + if (!rpm) return -ENOMEM; np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", 0); @@ -283,36 +288,39 @@ static int glink_rpm_probe(struct platform_device *pdev) return -ENOMEM; ret = glink_rpm_parse_toc(dev, msg_ram, msg_ram_size, - rx_pipe, tx_pipe); + &rpm->rx_pipe, &rpm->tx_pipe); if (ret) return ret; /* Pipe specific accessors */ - rx_pipe->native.avail = glink_rpm_rx_avail; - rx_pipe->native.peak = glink_rpm_rx_peak; - rx_pipe->native.advance = glink_rpm_rx_advance; - tx_pipe->native.avail = glink_rpm_tx_avail; - tx_pipe->native.write = glink_rpm_tx_write; + rpm->rx_pipe.native.avail = glink_rpm_rx_avail; + rpm->rx_pipe.native.peak = glink_rpm_rx_peak; + rpm->rx_pipe.native.advance = glink_rpm_rx_advance; + rpm->tx_pipe.native.avail = glink_rpm_tx_avail; + rpm->tx_pipe.native.write = glink_rpm_tx_write; - writel(0, tx_pipe->head); - writel(0, rx_pipe->tail); + writel(0, rpm->tx_pipe.head); + writel(0, rpm->rx_pipe.tail); - glink = qcom_glink_native_probe(&pdev->dev, + glink = qcom_glink_native_probe(dev, 0, - &rx_pipe->native, - &tx_pipe->native, + &rpm->rx_pipe.native, + &rpm->tx_pipe.native, true); if (IS_ERR(glink)) return PTR_ERR(glink); - platform_set_drvdata(pdev, glink); + rpm->glink = glink; + + platform_set_drvdata(pdev, rpm); return 0; } static int glink_rpm_remove(struct platform_device *pdev) { - struct qcom_glink *glink = platform_get_drvdata(pdev); + struct glink_rpm *rpm = platform_get_drvdata(pdev); + struct qcom_glink *glink = rpm->glink; qcom_glink_native_remove(glink); -- cgit v1.2.3 From f424d1cbe8c7ef78a4b639502fa9904c4198387b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:13 -0800 Subject: rpmsg: glink: Move irq and mbox handling to transports Not all GLINK transports uses an interrupt and a mailbox instance. The interrupt for RPM needs to be IRQF_NOSUSPEND, while it seems reasonable for the SMEM interrupt to use irq_set_wake. The glink struct device is constructed in the SMEM and RPM drivers but torn down in the core driver. Move the interrupt and kick handling into the SMEM and RPM driver, to improve this and facilitate further improvements. Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-5-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 48 +++------------------------------- drivers/rpmsg/qcom_glink_native.h | 3 ++- drivers/rpmsg/qcom_glink_rpm.c | 50 ++++++++++++++++++++++++++++++++++- drivers/rpmsg/qcom_glink_smem.c | 55 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 107 insertions(+), 49 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 5fd8b70271b7..8dd8cf033b2d 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -78,11 +77,8 @@ struct glink_core_rx_intent { /** * struct qcom_glink - driver context, relates to one remote subsystem * @dev: reference to the associated struct device - * @mbox_client: mailbox client - * @mbox_chan: mailbox channel * @rx_pipe: pipe object for receive FIFO * @tx_pipe: pipe object for transmit FIFO - * @irq: IRQ for signaling incoming events * @rx_work: worker for handling received control messages * @rx_lock: protects the @rx_queue * @rx_queue: queue of received control messages to be processed in @rx_work @@ -98,14 +94,9 @@ struct glink_core_rx_intent { struct qcom_glink { struct device *dev; - struct mbox_client mbox_client; - struct mbox_chan *mbox_chan; - struct qcom_glink_pipe *rx_pipe; struct qcom_glink_pipe *tx_pipe; - int irq; - struct work_struct rx_work; spinlock_t rx_lock; struct list_head rx_queue; @@ -305,8 +296,7 @@ static void qcom_glink_tx_write(struct qcom_glink *glink, static void qcom_glink_tx_kick(struct qcom_glink *glink) { - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); + glink->tx_pipe->kick(glink->tx_pipe); } static void qcom_glink_send_read_notify(struct qcom_glink *glink) @@ -1004,9 +994,8 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) return 0; } -static irqreturn_t qcom_glink_native_intr(int irq, void *data) +void qcom_glink_native_rx(struct qcom_glink *glink) { - struct qcom_glink *glink = data; struct glink_msg msg; unsigned int param1; unsigned int param2; @@ -1075,9 +1064,8 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) if (ret) break; } - - return IRQ_HANDLED; } +EXPORT_SYMBOL(qcom_glink_native_rx); /* Locally initiated rpmsg_create_ept */ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, @@ -1723,7 +1711,6 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, struct qcom_glink_pipe *tx, bool intentless) { - int irq; int ret; struct qcom_glink *glink; @@ -1754,27 +1741,6 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, if (ret) dev_err(dev, "failed to add groups\n"); - glink->mbox_client.dev = dev; - glink->mbox_client.knows_txdone = true; - glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0); - if (IS_ERR(glink->mbox_chan)) { - if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER) - dev_err(dev, "failed to acquire IPC channel\n"); - return ERR_CAST(glink->mbox_chan); - } - - irq = of_irq_get(dev->of_node, 0); - ret = devm_request_irq(dev, irq, - qcom_glink_native_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, - "glink-native", glink); - if (ret) { - dev_err(dev, "failed to request IRQ\n"); - return ERR_PTR(ret); - } - - glink->irq = irq; - ret = qcom_glink_send_version(glink); if (ret) return ERR_PTR(ret); @@ -1800,7 +1766,6 @@ void qcom_glink_native_remove(struct qcom_glink *glink) int cid; int ret; - disable_irq(glink->irq); qcom_glink_cancel_rx_work(glink); ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); @@ -1817,15 +1782,8 @@ void qcom_glink_native_remove(struct qcom_glink *glink) idr_destroy(&glink->lcids); idr_destroy(&glink->rcids); - mbox_free_channel(glink->mbox_chan); } EXPORT_SYMBOL_GPL(qcom_glink_native_remove); -void qcom_glink_native_unregister(struct qcom_glink *glink) -{ - device_unregister(glink->dev); -} -EXPORT_SYMBOL_GPL(qcom_glink_native_unregister); - MODULE_DESCRIPTION("Qualcomm GLINK driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index e9a8671616c7..9462b37eccee 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -24,6 +24,7 @@ struct qcom_glink_pipe { void (*write)(struct qcom_glink_pipe *glink_pipe, const void *hdr, size_t hlen, const void *data, size_t dlen); + void (*kick)(struct qcom_glink_pipe *glink_pipe); }; struct device; @@ -35,6 +36,6 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, struct qcom_glink_pipe *tx, bool intentless); void qcom_glink_native_remove(struct qcom_glink *glink); +void qcom_glink_native_rx(struct qcom_glink *glink); -void qcom_glink_native_unregister(struct qcom_glink *glink); #endif diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 6443843df6ca..5179f834a10f 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,11 @@ struct glink_rpm_pipe { struct glink_rpm { struct qcom_glink *glink; + int irq; + + struct mbox_client mbox_client; + struct mbox_chan *mbox_chan; + struct glink_rpm_pipe rx_pipe; struct glink_rpm_pipe tx_pipe; }; @@ -186,6 +192,24 @@ static void glink_rpm_tx_write(struct qcom_glink_pipe *glink_pipe, writel(head, pipe->head); } +static void glink_rpm_tx_kick(struct qcom_glink_pipe *glink_pipe) +{ + struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); + struct glink_rpm *rpm = container_of(pipe, struct glink_rpm, tx_pipe); + + mbox_send_message(rpm->mbox_chan, NULL); + mbox_client_txdone(rpm->mbox_chan, 0); +} + +static irqreturn_t qcom_glink_rpm_intr(int irq, void *data) +{ + struct glink_rpm *rpm = data; + + qcom_glink_native_rx(rpm->glink); + + return IRQ_HANDLED; +} + static int glink_rpm_parse_toc(struct device *dev, void __iomem *msg_ram, size_t msg_ram_size, @@ -292,12 +316,28 @@ static int glink_rpm_probe(struct platform_device *pdev) if (ret) return ret; + rpm->irq = of_irq_get(dev->of_node, 0); + ret = devm_request_irq(dev, rpm->irq, qcom_glink_rpm_intr, + IRQF_NO_SUSPEND | IRQF_NO_AUTOEN, + "glink-rpm", rpm); + if (ret) { + dev_err(dev, "failed to request IRQ\n"); + return ret; + } + + rpm->mbox_client.dev = dev; + rpm->mbox_client.knows_txdone = true; + rpm->mbox_chan = mbox_request_channel(&rpm->mbox_client, 0); + if (IS_ERR(rpm->mbox_chan)) + return dev_err_probe(dev, PTR_ERR(rpm->mbox_chan), "failed to acquire IPC channel\n"); + /* Pipe specific accessors */ rpm->rx_pipe.native.avail = glink_rpm_rx_avail; rpm->rx_pipe.native.peak = glink_rpm_rx_peak; rpm->rx_pipe.native.advance = glink_rpm_rx_advance; rpm->tx_pipe.native.avail = glink_rpm_tx_avail; rpm->tx_pipe.native.write = glink_rpm_tx_write; + rpm->tx_pipe.native.kick = glink_rpm_tx_kick; writel(0, rpm->tx_pipe.head); writel(0, rpm->rx_pipe.tail); @@ -307,13 +347,17 @@ static int glink_rpm_probe(struct platform_device *pdev) &rpm->rx_pipe.native, &rpm->tx_pipe.native, true); - if (IS_ERR(glink)) + if (IS_ERR(glink)) { + mbox_free_channel(rpm->mbox_chan); return PTR_ERR(glink); + } rpm->glink = glink; platform_set_drvdata(pdev, rpm); + enable_irq(rpm->irq); + return 0; } @@ -322,8 +366,12 @@ static int glink_rpm_remove(struct platform_device *pdev) struct glink_rpm *rpm = platform_get_drvdata(pdev); struct qcom_glink *glink = rpm->glink; + disable_irq(rpm->irq); + qcom_glink_native_remove(glink); + mbox_free_channel(rpm->mbox_chan); + return 0; } diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index a9c477df4d68..05b4fe0a7387 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -36,8 +38,12 @@ struct qcom_glink_smem { struct device dev; + int irq; struct qcom_glink *glink; + struct mbox_client mbox_client; + struct mbox_chan *mbox_chan; + u32 remote_pid; }; @@ -186,6 +192,24 @@ static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe, *pipe->head = cpu_to_le32(head); } +static void glink_smem_tx_kick(struct qcom_glink_pipe *glink_pipe) +{ + struct glink_smem_pipe *pipe = to_smem_pipe(glink_pipe); + struct qcom_glink_smem *smem = pipe->smem; + + mbox_send_message(smem->mbox_chan, NULL); + mbox_client_txdone(smem->mbox_chan, 0); +} + +static irqreturn_t qcom_glink_smem_intr(int irq, void *data) +{ + struct qcom_glink_smem *smem = data; + + qcom_glink_native_rx(smem->glink); + + return IRQ_HANDLED; +} + static void qcom_glink_smem_release(struct device *dev) { struct qcom_glink_smem *smem = container_of(dev, struct qcom_glink_smem, dev); @@ -280,6 +304,24 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, goto err_put_dev; } + smem->irq = of_irq_get(smem->dev.of_node, 0); + ret = devm_request_irq(&smem->dev, smem->irq, qcom_glink_smem_intr, + IRQF_NO_SUSPEND | IRQF_NO_AUTOEN, + "glink-smem", smem); + if (ret) { + dev_err(&smem->dev, "failed to request IRQ\n"); + goto err_put_dev; + } + + smem->mbox_client.dev = &smem->dev; + smem->mbox_client.knows_txdone = true; + smem->mbox_chan = mbox_request_channel(&smem->mbox_client, 0); + if (IS_ERR(smem->mbox_chan)) { + ret = dev_err_probe(&smem->dev, PTR_ERR(smem->mbox_chan), + "failed to acquire IPC channel\n"); + goto err_put_dev; + } + rx_pipe->smem = smem; rx_pipe->native.avail = glink_smem_rx_avail; rx_pipe->native.peak = glink_smem_rx_peak; @@ -288,6 +330,7 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, tx_pipe->smem = smem; tx_pipe->native.avail = glink_smem_tx_avail; tx_pipe->native.write = glink_smem_tx_write; + tx_pipe->native.kick = glink_smem_tx_kick; *rx_pipe->tail = 0; *tx_pipe->head = 0; @@ -298,13 +341,17 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, false); if (IS_ERR(glink)) { ret = PTR_ERR(glink); - goto err_put_dev; + goto err_free_mbox; } smem->glink = glink; + enable_irq(smem->irq); + return smem; +err_free_mbox: + mbox_free_channel(smem->mbox_chan); err_put_dev: device_unregister(dev); @@ -317,8 +364,12 @@ void qcom_glink_smem_unregister(struct qcom_glink_smem *smem) { struct qcom_glink *glink = smem->glink; + disable_irq(smem->irq); + qcom_glink_native_remove(glink); - qcom_glink_native_unregister(glink); + + mbox_free_channel(smem->mbox_chan); + device_unregister(&smem->dev); } EXPORT_SYMBOL_GPL(qcom_glink_smem_unregister); -- cgit v1.2.3 From 9c96bacf1af51bc71898f31e025f08338c6ca4da Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:14 -0800 Subject: rpmsg: glink: Fail qcom_glink_tx() once remove has been initiated Upon removing the glink edge, communication is at best one-way. This means that the very common scenario of glink requesting intents will not be possible to serve. Typically a successful transmission results in the client waiting for a response, with some timeout and a mechanism for aborting that timeout. Because of this, once the glink edge is defunct once removal is commenced it's better to fail transmissions fast. Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-6-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 8dd8cf033b2d..946128c343f3 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -90,6 +90,7 @@ struct glink_core_rx_intent { * @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 + * @abort_tx: flag indicating that all tx attempts should fail */ struct qcom_glink { struct device *dev; @@ -111,6 +112,8 @@ struct qcom_glink { bool intentless; wait_queue_head_t tx_avail_notify; bool sent_read_notify; + + bool abort_tx; }; enum { @@ -326,12 +329,22 @@ static int qcom_glink_tx(struct qcom_glink *glink, spin_lock_irqsave(&glink->tx_lock, flags); + if (glink->abort_tx) { + ret = -EIO; + goto out; + } + while (qcom_glink_tx_avail(glink) < tlen) { if (!wait) { ret = -EAGAIN; goto out; } + if (glink->abort_tx) { + ret = -EIO; + goto out; + } + if (!glink->sent_read_notify) { glink->sent_read_notify = true; qcom_glink_send_read_notify(glink); @@ -1763,11 +1776,18 @@ static int qcom_glink_remove_device(struct device *dev, void *data) void qcom_glink_native_remove(struct qcom_glink *glink) { struct glink_channel *channel; + unsigned long flags; int cid; int ret; qcom_glink_cancel_rx_work(glink); + /* Fail all attempts at sending messages */ + spin_lock_irqsave(&glink->tx_lock, flags); + glink->abort_tx = true; + wake_up_all(&glink->tx_avail_notify); + spin_unlock_irqrestore(&glink->tx_lock, flags); + ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); if (ret) dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); -- cgit v1.2.3 From fb23b97346f9aaa9f7b7a996e7baf066c88d69bd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 Feb 2023 07:52:15 -0800 Subject: rpmsg: glink: Cancel pending intent requests at removal During removal of the glink edge interrupts are disabled and no more incoming messages are being serviced. In addition to the remote endpoint being defunct that means that any outstanding requests for intents will not be serviced, and qcom_glink_request_intent() will blindly wait for up to 10 seconds. Mark the intent request as not granted and complete the intent request completion to fail the waiting client immediately. Once the current intent request is failed, any potential clients waiting for the intent request mutex will not enter the same wait, as the qcom_glink_tx() call will fail fast. Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230213155215.1237059-7-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 946128c343f3..324c75d59a6f 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -423,6 +423,12 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink, complete(&channel->intent_req_comp); } +static void qcom_glink_intent_req_abort(struct glink_channel *channel) +{ + channel->intent_req_result = 0; + complete(&channel->intent_req_comp); +} + /** * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote * @glink: Ptr to the glink edge @@ -1788,6 +1794,12 @@ void qcom_glink_native_remove(struct qcom_glink *glink) wake_up_all(&glink->tx_avail_notify); spin_unlock_irqrestore(&glink->tx_lock, flags); + /* Abort any senders waiting for intent requests */ + spin_lock_irqsave(&glink->idr_lock, flags); + idr_for_each_entry(&glink->lcids, channel, cid) + qcom_glink_intent_req_abort(channel); + spin_unlock_irqrestore(&glink->idr_lock, flags); + ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); if (ret) dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); -- cgit v1.2.3 From a8f500c68673d385b437da678aaf9ebba0ab9db0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 14 Feb 2023 14:47:46 -0800 Subject: rpmsg: glink: Fix spelling of peek The code is peeking into the buffers, not peaking. Fix this throughout the glink drivers. Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230214224746.1996130-1-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 14 +++++++------- drivers/rpmsg/qcom_glink_native.h | 2 +- drivers/rpmsg/qcom_glink_rpm.c | 4 ++-- drivers/rpmsg/qcom_glink_smem.c | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 324c75d59a6f..7a3cac62ecfa 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -274,10 +274,10 @@ static size_t qcom_glink_rx_avail(struct qcom_glink *glink) return glink->rx_pipe->avail(glink->rx_pipe); } -static void qcom_glink_rx_peak(struct qcom_glink *glink, +static void qcom_glink_rx_peek(struct qcom_glink *glink, void *data, unsigned int offset, size_t count) { - glink->rx_pipe->peak(glink->rx_pipe, data, offset, count); + glink->rx_pipe->peek(glink->rx_pipe, data, offset, count); } static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count) @@ -808,7 +808,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) INIT_LIST_HEAD(&dcmd->node); - qcom_glink_rx_peak(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); + qcom_glink_rx_peek(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); spin_lock(&glink->rx_lock); list_add_tail(&dcmd->node, &glink->rx_queue); @@ -841,7 +841,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) return -EAGAIN; } - qcom_glink_rx_peak(glink, &hdr, 0, sizeof(hdr)); + qcom_glink_rx_peek(glink, &hdr, 0, sizeof(hdr)); chunk_size = le32_to_cpu(hdr.chunk_size); left_size = le32_to_cpu(hdr.left_size); @@ -906,7 +906,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) goto advance_rx; } - qcom_glink_rx_peak(glink, intent->data + intent->offset, + qcom_glink_rx_peek(glink, intent->data + intent->offset, sizeof(hdr), chunk_size); intent->offset += chunk_size; @@ -973,7 +973,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink, if (!msg) return; - qcom_glink_rx_peak(glink, msg, 0, msglen); + qcom_glink_rx_peek(glink, msg, 0, msglen); for (i = 0; i < count; ++i) { intent = kzalloc(sizeof(*intent), GFP_ATOMIC); @@ -1030,7 +1030,7 @@ void qcom_glink_native_rx(struct qcom_glink *glink) if (avail < sizeof(msg)) break; - qcom_glink_rx_peak(glink, &msg, 0, sizeof(msg)); + qcom_glink_rx_peek(glink, &msg, 0, sizeof(msg)); cmd = le16_to_cpu(msg.cmd); param1 = le16_to_cpu(msg.param1); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index 9462b37eccee..8dbec24de23e 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -17,7 +17,7 @@ struct qcom_glink_pipe { size_t (*avail)(struct qcom_glink_pipe *glink_pipe); - void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data, + void (*peek)(struct qcom_glink_pipe *glink_pipe, void *data, unsigned int offset, size_t count); void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count); diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 5179f834a10f..f94bb7d4f1ec 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -81,7 +81,7 @@ static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) return head - tail; } -static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe, +static void glink_rpm_rx_peek(struct qcom_glink_pipe *glink_pipe, void *data, unsigned int offset, size_t count) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); @@ -333,7 +333,7 @@ static int glink_rpm_probe(struct platform_device *pdev) /* Pipe specific accessors */ rpm->rx_pipe.native.avail = glink_rpm_rx_avail; - rpm->rx_pipe.native.peak = glink_rpm_rx_peak; + rpm->rx_pipe.native.peek = glink_rpm_rx_peek; rpm->rx_pipe.native.advance = glink_rpm_rx_advance; rpm->tx_pipe.native.avail = glink_rpm_tx_avail; rpm->tx_pipe.native.write = glink_rpm_tx_write; diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 05b4fe0a7387..7a982c60a8dd 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -91,7 +91,7 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) return head - tail; } -static void glink_smem_rx_peak(struct qcom_glink_pipe *np, +static void glink_smem_rx_peek(struct qcom_glink_pipe *np, void *data, unsigned int offset, size_t count) { struct glink_smem_pipe *pipe = to_smem_pipe(np); @@ -324,7 +324,7 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent, rx_pipe->smem = smem; rx_pipe->native.avail = glink_smem_rx_avail; - rx_pipe->native.peak = glink_smem_rx_peak; + rx_pipe->native.peek = glink_smem_rx_peek; rx_pipe->native.advance = glink_smem_rx_advance; tx_pipe->smem = smem; -- cgit v1.2.3 From 4e816d0318fdfe8932da80dbf04ba318b13e4b3a Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 14 Feb 2023 14:59:33 -0800 Subject: rpmsg: glink: Fix GLINK command prefix The upstream GLINK driver was first introduced to communicate with the RPM on MSM8996, presumably as an artifact from that era the command defines was prefixed RPM_CMD, while they actually are GLINK_CMDs. Let's rename these, to keep things tidy. No functional change. Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230214225933.2025595-1-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 98 +++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 7a3cac62ecfa..89c3381f06c3 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -183,20 +183,20 @@ struct glink_channel { static const struct rpmsg_endpoint_ops glink_endpoint_ops; -#define RPM_CMD_VERSION 0 -#define RPM_CMD_VERSION_ACK 1 -#define RPM_CMD_OPEN 2 -#define RPM_CMD_CLOSE 3 -#define RPM_CMD_OPEN_ACK 4 -#define RPM_CMD_INTENT 5 -#define RPM_CMD_RX_DONE 6 -#define RPM_CMD_RX_INTENT_REQ 7 -#define RPM_CMD_RX_INTENT_REQ_ACK 8 -#define RPM_CMD_TX_DATA 9 -#define RPM_CMD_CLOSE_ACK 11 -#define RPM_CMD_TX_DATA_CONT 12 -#define RPM_CMD_READ_NOTIF 13 -#define RPM_CMD_RX_DONE_W_REUSE 14 +#define GLINK_CMD_VERSION 0 +#define GLINK_CMD_VERSION_ACK 1 +#define GLINK_CMD_OPEN 2 +#define GLINK_CMD_CLOSE 3 +#define GLINK_CMD_OPEN_ACK 4 +#define GLINK_CMD_INTENT 5 +#define GLINK_CMD_RX_DONE 6 +#define GLINK_CMD_RX_INTENT_REQ 7 +#define GLINK_CMD_RX_INTENT_REQ_ACK 8 +#define GLINK_CMD_TX_DATA 9 +#define GLINK_CMD_CLOSE_ACK 11 +#define GLINK_CMD_TX_DATA_CONT 12 +#define GLINK_CMD_READ_NOTIF 13 +#define GLINK_CMD_RX_DONE_W_REUSE 14 #define GLINK_FEATURE_INTENTLESS BIT(1) @@ -306,7 +306,7 @@ 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.cmd = cpu_to_le16(GLINK_CMD_READ_NOTIF); msg.param1 = 0; msg.param2 = 0; @@ -375,7 +375,7 @@ static int qcom_glink_send_version(struct qcom_glink *glink) { struct glink_msg msg; - msg.cmd = cpu_to_le16(RPM_CMD_VERSION); + msg.cmd = cpu_to_le16(GLINK_CMD_VERSION); msg.param1 = cpu_to_le16(GLINK_VERSION_1); msg.param2 = cpu_to_le32(glink->features); @@ -386,7 +386,7 @@ static void qcom_glink_send_version_ack(struct qcom_glink *glink) { struct glink_msg msg; - msg.cmd = cpu_to_le16(RPM_CMD_VERSION_ACK); + msg.cmd = cpu_to_le16(GLINK_CMD_VERSION_ACK); msg.param1 = cpu_to_le16(GLINK_VERSION_1); msg.param2 = cpu_to_le32(glink->features); @@ -398,7 +398,7 @@ static void qcom_glink_send_open_ack(struct qcom_glink *glink, { struct glink_msg msg; - msg.cmd = cpu_to_le16(RPM_CMD_OPEN_ACK); + msg.cmd = cpu_to_le16(GLINK_CMD_OPEN_ACK); msg.param1 = cpu_to_le16(channel->rcid); msg.param2 = cpu_to_le32(0); @@ -430,11 +430,11 @@ static void qcom_glink_intent_req_abort(struct glink_channel *channel) } /** - * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote + * qcom_glink_send_open_req() - send a GLINK_CMD_OPEN request to the remote * @glink: Ptr to the glink edge * @channel: Ptr to the channel that the open req is sent * - * Allocates a local channel id and sends a RPM_CMD_OPEN message to the remote. + * Allocates a local channel id and sends a GLINK_CMD_OPEN message to the remote. * Will return with refcount held, regardless of outcome. * * Return: 0 on success, negative errno otherwise. @@ -463,7 +463,7 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink, channel->lcid = ret; - req.msg.cmd = cpu_to_le16(RPM_CMD_OPEN); + req.msg.cmd = cpu_to_le16(GLINK_CMD_OPEN); req.msg.param1 = cpu_to_le16(channel->lcid); req.msg.param2 = cpu_to_le32(name_len); strcpy(req.name, channel->name); @@ -488,7 +488,7 @@ static void qcom_glink_send_close_req(struct qcom_glink *glink, { struct glink_msg req; - req.cmd = cpu_to_le16(RPM_CMD_CLOSE); + req.cmd = cpu_to_le16(GLINK_CMD_CLOSE); req.param1 = cpu_to_le16(channel->lcid); req.param2 = 0; @@ -500,7 +500,7 @@ static void qcom_glink_send_close_ack(struct qcom_glink *glink, { struct glink_msg req; - req.cmd = cpu_to_le16(RPM_CMD_CLOSE_ACK); + req.cmd = cpu_to_le16(GLINK_CMD_CLOSE_ACK); req.param1 = cpu_to_le16(rcid); req.param2 = 0; @@ -531,7 +531,7 @@ static void qcom_glink_rx_done_work(struct work_struct *work) iid = intent->id; reuse = intent->reuse; - cmd.id = reuse ? RPM_CMD_RX_DONE_W_REUSE : RPM_CMD_RX_DONE; + cmd.id = reuse ? GLINK_CMD_RX_DONE_W_REUSE : GLINK_CMD_RX_DONE; cmd.lcid = cid; cmd.liid = iid; @@ -643,7 +643,7 @@ static int qcom_glink_send_intent_req_ack(struct qcom_glink *glink, { struct glink_msg msg; - msg.cmd = cpu_to_le16(RPM_CMD_RX_INTENT_REQ_ACK); + msg.cmd = cpu_to_le16(GLINK_CMD_RX_INTENT_REQ_ACK); msg.param1 = cpu_to_le16(channel->lcid); msg.param2 = cpu_to_le32(granted); @@ -674,7 +674,7 @@ static int qcom_glink_advertise_intent(struct qcom_glink *glink, } __packed; struct command cmd; - cmd.id = cpu_to_le16(RPM_CMD_INTENT); + cmd.id = cpu_to_le16(GLINK_CMD_INTENT); cmd.lcid = cpu_to_le16(channel->lcid); cmd.count = cpu_to_le32(1); cmd.size = cpu_to_le32(intent->size); @@ -1037,40 +1037,40 @@ void qcom_glink_native_rx(struct qcom_glink *glink) param2 = le32_to_cpu(msg.param2); switch (cmd) { - case RPM_CMD_VERSION: - case RPM_CMD_VERSION_ACK: - case RPM_CMD_CLOSE: - case RPM_CMD_CLOSE_ACK: - case RPM_CMD_RX_INTENT_REQ: + case GLINK_CMD_VERSION: + case GLINK_CMD_VERSION_ACK: + case GLINK_CMD_CLOSE: + case GLINK_CMD_CLOSE_ACK: + case GLINK_CMD_RX_INTENT_REQ: ret = qcom_glink_rx_defer(glink, 0); break; - case RPM_CMD_OPEN_ACK: + case GLINK_CMD_OPEN_ACK: ret = qcom_glink_rx_open_ack(glink, param1); qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; - case RPM_CMD_OPEN: + case GLINK_CMD_OPEN: ret = qcom_glink_rx_defer(glink, param2); break; - case RPM_CMD_TX_DATA: - case RPM_CMD_TX_DATA_CONT: + case GLINK_CMD_TX_DATA: + case GLINK_CMD_TX_DATA_CONT: ret = qcom_glink_rx_data(glink, avail); break; - case RPM_CMD_READ_NOTIF: + case GLINK_CMD_READ_NOTIF: qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); qcom_glink_tx_kick(glink); break; - case RPM_CMD_INTENT: + case GLINK_CMD_INTENT: qcom_glink_handle_intent(glink, param1, param2, avail); break; - case RPM_CMD_RX_DONE: + case GLINK_CMD_RX_DONE: qcom_glink_handle_rx_done(glink, param1, param2, false); qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; - case RPM_CMD_RX_DONE_W_REUSE: + case GLINK_CMD_RX_DONE_W_REUSE: qcom_glink_handle_rx_done(glink, param1, param2, true); qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; - case RPM_CMD_RX_INTENT_REQ_ACK: + case GLINK_CMD_RX_INTENT_REQ_ACK: qcom_glink_handle_intent_req_ack(glink, param1, param2); qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; @@ -1272,7 +1272,7 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, reinit_completion(&channel->intent_req_comp); - cmd.id = RPM_CMD_RX_INTENT_REQ; + cmd.id = GLINK_CMD_RX_INTENT_REQ; cmd.cid = channel->lcid; cmd.size = size; @@ -1346,7 +1346,7 @@ static int __qcom_glink_send(struct glink_channel *channel, chunk_size = SZ_8K; left_size = len - chunk_size; } - req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA); + req.msg.cmd = cpu_to_le16(GLINK_CMD_TX_DATA); req.msg.param1 = cpu_to_le16(channel->lcid); req.msg.param2 = cpu_to_le32(iid); req.chunk_size = cpu_to_le32(chunk_size); @@ -1367,7 +1367,7 @@ static int __qcom_glink_send(struct glink_channel *channel, chunk_size = SZ_8K; left_size -= chunk_size; - req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA_CONT); + req.msg.cmd = cpu_to_le16(GLINK_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); @@ -1631,22 +1631,22 @@ static void qcom_glink_work(struct work_struct *work) param2 = le32_to_cpu(msg->param2); switch (cmd) { - case RPM_CMD_VERSION: + case GLINK_CMD_VERSION: qcom_glink_receive_version(glink, param1, param2); break; - case RPM_CMD_VERSION_ACK: + case GLINK_CMD_VERSION_ACK: qcom_glink_receive_version_ack(glink, param1, param2); break; - case RPM_CMD_OPEN: + case GLINK_CMD_OPEN: qcom_glink_rx_open(glink, param1, msg->data); break; - case RPM_CMD_CLOSE: + case GLINK_CMD_CLOSE: qcom_glink_rx_close(glink, param1); break; - case RPM_CMD_CLOSE_ACK: + case GLINK_CMD_CLOSE_ACK: qcom_glink_rx_close_ack(glink, param1); break; - case RPM_CMD_RX_INTENT_REQ: + case GLINK_CMD_RX_INTENT_REQ: qcom_glink_handle_intent_req(glink, param1, param2); break; default: -- cgit v1.2.3 From 3e74ec2f39362bffbd42854acbb67c7f4cb808f9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 14 Feb 2023 15:42:31 -0800 Subject: rpmsg: glink: Avoid infinite loop on intent for missing channel In the event that an intent advertisement arrives on an unknown channel the fifo is not advanced, resulting in the same message being handled over and over. Fixes: dacbb35e930f ("rpmsg: glink: Receive and store the remote intent buffers") Signed-off-by: Bjorn Andersson Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230214234231.2069751-1-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 89c3381f06c3..b6c60bf86009 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -966,6 +966,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink, spin_unlock_irqrestore(&glink->idr_lock, flags); if (!channel) { dev_err(glink->dev, "intents for non-existing channel\n"); + qcom_glink_rx_advance(glink, ALIGN(msglen, 8)); return; } -- cgit v1.2.3 From fb80ef67e8ff6a00d3faad4cb348dafdb8eccfd8 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 9 Jan 2023 14:39:31 -0800 Subject: rpmsg: glink: Release driver_override Upon termination of the rpmsg_device, driver_override needs to be freed to avoid leaking the potentially assigned string. Fixes: 42cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override") Fixes: 39e47767ec9b ("rpmsg: Add driver_override device attribute for rpmsg_device") Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230109223931.1706429-1-quic_bjorande@quicinc.com --- drivers/rpmsg/qcom_glink_native.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index b6c60bf86009..01d2805fe30f 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1455,6 +1455,7 @@ static void qcom_glink_rpdev_release(struct device *dev) { struct rpmsg_device *rpdev = to_rpmsg_device(dev); + kfree(rpdev->driver_override); kfree(rpdev); } @@ -1698,6 +1699,7 @@ static void qcom_glink_device_release(struct device *dev) /* Release qcom_glink_alloc_channel() reference */ kref_put(&channel->refcount, qcom_glink_channel_release); + kfree(rpdev->driver_override); kfree(rpdev); } -- cgit v1.2.3