From 60d7b22d25930e5c3e03eca32047e3313fa76897 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Thu, 11 Mar 2021 15:04:08 +0100 Subject: rpmsg: char: Rename rpmsg_char_init to rpmsg_chrdev_init To be coherent with the other functions which are prefixed by rpmsg_chrdev, rename the rpmsg_char_init function. Reviewed-by: Bjorn Andersson Reviewed-by: Mathieu Poirier Signed-off-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210311140413.31725-2-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_char.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 4bbbacdbf3bb..9e33b53bbf56 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -543,7 +543,7 @@ static struct rpmsg_driver rpmsg_chrdev_driver = { }, }; -static int rpmsg_char_init(void) +static int rpmsg_chrdev_init(void) { int ret; @@ -569,7 +569,7 @@ static int rpmsg_char_init(void) return ret; } -postcore_initcall(rpmsg_char_init); +postcore_initcall(rpmsg_chrdev_init); static void rpmsg_chrdev_exit(void) { -- cgit v1.2.3 From b4ce7e2ebcc52ff907c5a922bf19c3dfa39dddb1 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Thu, 11 Mar 2021 15:04:11 +0100 Subject: rpmsg: char: Use rpmsg_sendto to specify the message destination address When the endpoint device is created by the application, a destination address is specified in the rpmsg_channel_info structure. Since the rpmsg_endpoint structure does not store the destination address, this destination address must be specified when sending a message. Replaces rpmsg_send with rpmsg_sendto to allow to specify the destination address. This implementation is requested for compatibly with some rpmsg backends like the virtio backend. For this, the GLINK an SMD drivers have been updated to support the rpmsg_sendto, even if the destination address is ignored for these backends. For these drivers, the rpmsg_send and rpmsg_trysend ops are preserved to avoid breaking the legacy. Signed-off-by: Arnaud Pouliquen Reviewed-by: Bjorn Andersson Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/20210311140413.31725-5-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 16 ++++++++++++++++ drivers/rpmsg/qcom_smd.c | 16 ++++++++++++++++ drivers/rpmsg/rpmsg_char.c | 4 ++-- 3 files changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 27a05167c18c..edae0c9a8236 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1332,6 +1332,20 @@ static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len) return __qcom_glink_send(channel, data, len, false); } +static int qcom_glink_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) +{ + struct glink_channel *channel = to_glink_channel(ept); + + return __qcom_glink_send(channel, data, len, true); +} + +static int qcom_glink_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) +{ + struct glink_channel *channel = to_glink_channel(ept); + + return __qcom_glink_send(channel, data, len, false); +} + /* * Finds the device_node for the glink child interested in this channel. */ @@ -1364,7 +1378,9 @@ static const struct rpmsg_device_ops glink_device_ops = { static const struct rpmsg_endpoint_ops glink_endpoint_ops = { .destroy_ept = qcom_glink_destroy_ept, .send = qcom_glink_send, + .sendto = qcom_glink_sendto, .trysend = qcom_glink_trysend, + .trysendto = qcom_glink_trysendto, }; static void qcom_glink_rpdev_release(struct device *dev) diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 19903de6268d..8da1b5cb31b3 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -974,6 +974,20 @@ static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len) return __qcom_smd_send(qsept->qsch, data, len, false); } +static int qcom_smd_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) +{ + struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); + + return __qcom_smd_send(qsept->qsch, data, len, true); +} + +static int qcom_smd_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) +{ + struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); + + return __qcom_smd_send(qsept->qsch, data, len, false); +} + static __poll_t qcom_smd_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait) { @@ -1038,7 +1052,9 @@ static const struct rpmsg_device_ops qcom_smd_device_ops = { static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = { .destroy_ept = qcom_smd_destroy_ept, .send = qcom_smd_send, + .sendto = qcom_smd_sendto, .trysend = qcom_smd_trysend, + .trysendto = qcom_smd_trysendto, .poll = qcom_smd_poll, }; diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 9e33b53bbf56..95a65f7a9d8d 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -239,9 +239,9 @@ static ssize_t rpmsg_eptdev_write_iter(struct kiocb *iocb, } if (filp->f_flags & O_NONBLOCK) - ret = rpmsg_trysend(eptdev->ept, kbuf, len); + ret = rpmsg_trysendto(eptdev->ept, kbuf, len, eptdev->chinfo.dst); else - ret = rpmsg_send(eptdev->ept, kbuf, len); + ret = rpmsg_sendto(eptdev->ept, kbuf, len, eptdev->chinfo.dst); unlock_eptdev: mutex_unlock(&eptdev->ept_lock); -- cgit v1.2.3 From c486682ae1e2b149add22f44cf413b3103e3ef39 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Thu, 11 Mar 2021 15:04:12 +0100 Subject: rpmsg: virtio: Register the rpmsg_char device Instantiate the rpmsg_char device on virtio RPMsg bus creation. This provides the capability, with the RPMSG_CREATE_EPT_IOCTL ioctl, to create RPMsg char device endpoints relying on the rpmsg_chrdev_create_eptdev API. Notice that the created endpoints are attached to the rpmsg_ctldev device, but not associated to a channel. As consequence, the endpoint source and destination addresses have to been specified and there is no channel creation and no name service announcement to inform the remote side. Reviewed-by: Bjorn Andersson Reviewed-by: Mathieu Poirier Signed-off-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210311140413.31725-6-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/virtio_rpmsg_bus.c | 62 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index e87d4cf926eb..8e49a3bacfc7 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -813,14 +813,57 @@ static void rpmsg_xmit_done(struct virtqueue *svq) wake_up_interruptible(&vrp->sendq); } +/* + * Called to expose to user a /dev/rpmsg_ctrlX interface allowing to + * create endpoint-to-endpoint communication without associated RPMsg channel. + * The endpoints are rattached to the ctrldev RPMsg device. + */ +static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev) +{ + struct virtproc_info *vrp = vdev->priv; + struct virtio_rpmsg_channel *vch; + struct rpmsg_device *rpdev_ctrl; + int err = 0; + + vch = kzalloc(sizeof(*vch), GFP_KERNEL); + if (!vch) + return ERR_PTR(-ENOMEM); + + /* Link the channel to the vrp */ + vch->vrp = vrp; + + /* Assign public information to the rpmsg_device */ + rpdev_ctrl = &vch->rpdev; + rpdev_ctrl->ops = &virtio_rpmsg_ops; + + rpdev_ctrl->dev.parent = &vrp->vdev->dev; + rpdev_ctrl->dev.release = virtio_rpmsg_release_device; + rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev); + + err = rpmsg_chrdev_register_device(rpdev_ctrl); + if (err) { + kfree(vch); + return ERR_PTR(err); + } + + return rpdev_ctrl; +} + +static void rpmsg_virtio_del_ctrl_dev(struct rpmsg_device *rpdev_ctrl) +{ + if (!rpdev_ctrl) + return; + kfree(to_virtio_rpmsg_channel(rpdev_ctrl)); +} + static int rpmsg_probe(struct virtio_device *vdev) { vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done }; static const char * const names[] = { "input", "output" }; struct virtqueue *vqs[2]; struct virtproc_info *vrp; - struct virtio_rpmsg_channel *vch; - struct rpmsg_device *rpdev_ns; + struct virtio_rpmsg_channel *vch = NULL; + struct rpmsg_device *rpdev_ns, *rpdev_ctrl; void *bufs_va; int err = 0, i; size_t total_buf_space; @@ -894,12 +937,18 @@ static int rpmsg_probe(struct virtio_device *vdev) vdev->priv = vrp; + rpdev_ctrl = rpmsg_virtio_add_ctrl_dev(vdev); + if (IS_ERR(rpdev_ctrl)) { + err = PTR_ERR(rpdev_ctrl); + goto free_coherent; + } + /* if supported by the remote processor, enable the name service */ if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) { vch = kzalloc(sizeof(*vch), GFP_KERNEL); if (!vch) { err = -ENOMEM; - goto free_coherent; + goto free_ctrldev; } /* Link the channel to our vrp */ @@ -915,7 +964,7 @@ static int rpmsg_probe(struct virtio_device *vdev) err = rpmsg_ns_register_device(rpdev_ns); if (err) - goto free_coherent; + goto free_vch; } /* @@ -939,8 +988,11 @@ static int rpmsg_probe(struct virtio_device *vdev) return 0; -free_coherent: +free_vch: kfree(vch); +free_ctrldev: + rpmsg_virtio_del_ctrl_dev(rpdev_ctrl); +free_coherent: dma_free_coherent(vdev->dev.parent, total_buf_space, bufs_va, vrp->bufs_dma); vqs_del: -- cgit v1.2.3 From 964e8bedd5a13a662e8e418ed763351c07d0dac7 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Thu, 11 Mar 2021 15:04:13 +0100 Subject: rpmsg: char: Return an error if device already open The rpmsg_create_ept function is invoked when the device is opened. As only one endpoint must be created per device. It is not possible to open the same device twice. But there is nothing to prevent multi open. Return -EBUSY when device is already opened to have a generic error instead of relying on the back-end to potentially detect the error. Without this patch for instance the GLINK driver return -EBUSY while the virtio bus return -ENOSPC. Reviewed-by: Bjorn Andersson Reviewed-by: Mathieu Poirier Signed-off-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210311140413.31725-7-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_char.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 95a65f7a9d8d..2bebc9b2d163 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -127,6 +127,9 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) struct rpmsg_device *rpdev = eptdev->rpdev; struct device *dev = &eptdev->dev; + if (eptdev->ept) + return -EBUSY; + get_device(dev); ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo); -- cgit v1.2.3 From 26594c6bbb60c6bc87e3762a86ceece57d164c66 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sat, 6 Mar 2021 05:36:24 -0800 Subject: rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data() When idr_find() returns NULL to intent, no error return code of qcom_glink_rx_data() is assigned. To fix this bug, ret is assigned with -ENOENT in this case. Fixes: 64f95f87920d ("rpmsg: glink: Use the local intents when receiving data") Reported-by: TOTE Robot Signed-off-by: Jia-Ju Bai Link: https://lore.kernel.org/r/20210306133624.17237-1-baijiaju1990@gmail.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index edae0c9a8236..05533c71b10e 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -857,6 +857,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) dev_err(glink->dev, "no intent found for channel %s intent %d", channel->name, liid); + ret = -ENOENT; goto advance_rx; } } -- cgit v1.2.3