[PATCH v5 15/16] rpmsg: char: no dynamic endpoint management for the default one

Arnaud Pouliquen
2021-02-19T11:21:03Z

Do not dynamically manage the default endpoint. The ept address must
not change.
This update is needed to manage the RPMSG_CREATE_DEV_IOCTL. In this
case a default endpoint is used and it's address must not change or
been reused by another service.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/rpmsg/rpmsg_char.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index c98b0e69679b..8d3f9d6c20ad 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -114,14 +114,23 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
struct rpmsg_endpoint *ept;
struct rpmsg_device *rpdev = eptdev->rpdev;
struct device *dev = &eptdev->dev;
+ u32 addr = eptdev->chinfo.src;

get_device(dev);

- ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
- if (!ept) {
- dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
- put_device(dev);
- return -EINVAL;
+ /*
+ * The RPMsg device can has been created by a ns announcement. In this
+ * case a default endpoint has been created. Reuse it to avoid to manage
+ * a new address on each open close.
+ */
+ ept = rpdev->ept;
+ if (!ept || addr != ept->addr) {
+ ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
+ if (!ept) {
+ dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
+ put_device(dev);
+ return -EINVAL;
+ }
}

eptdev->ept = ept;
@@ -133,12 +142,17 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
{
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
+ struct rpmsg_device *rpdev = eptdev->rpdev;
struct device *dev = &eptdev->dev;

- /* Close the endpoint, if it's not already destroyed by the parent */
+ /*
+ * Close the endpoint, if it's not already destroyed by the parent and it is not the
+ * default one.
+ */
mutex_lock(&eptdev->ept_lock);
if (eptdev->ept) {
- rpmsg_destroy_ept(eptdev->ept);
+ if (eptdev->ept != rpdev->ept)
+ rpmsg_destroy_ept(eptdev->ept);
eptdev->ept = NULL;
}
mutex_unlock(&eptdev->ept_lock);
--
2.17.1