Skip to content

Commit 950a738

Browse files
arnopoandersson
authored andcommitted
rpmsg: Turn name service into a stand alone driver
Make the RPMSG name service announcement a stand alone driver so that it can be reused by other subsystems. It is also the first step in making the functionatlity transport independent, i.e that is not tied to virtIO. Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Co-developed-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Co-developed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Link: https://lore.kernel.org/r/20201120214245.172963-9-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
1 parent 5548811 commit 950a738

File tree

5 files changed

+159
-67
lines changed

5 files changed

+159
-67
lines changed

drivers/rpmsg/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ config RPMSG_CHAR
1515
in /dev. They make it possible for user-space programs to send and
1616
receive rpmsg packets.
1717

18+
config RPMSG_NS
19+
tristate "RPMSG name service announcement"
20+
depends on RPMSG
21+
help
22+
Say Y here to enable the support of the name service announcement
23+
channel that probes the associated RPMsg device on remote endpoint
24+
service announcement.
25+
1826
config RPMSG_MTK_SCP
1927
tristate "MediaTek SCP"
2028
depends on MTK_SCP
@@ -62,6 +70,7 @@ config RPMSG_VIRTIO
6270
tristate "Virtio RPMSG bus driver"
6371
depends on HAS_DMA
6472
select RPMSG
73+
select RPMSG_NS
6574
select VIRTIO
6675

6776
endmenu

drivers/rpmsg/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_RPMSG) += rpmsg_core.o
33
obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
4+
obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o
45
obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o
56
qcom_glink-objs := qcom_glink_native.o qcom_glink_ssr.o
67
obj-$(CONFIG_RPMSG_QCOM_GLINK) += qcom_glink.o

drivers/rpmsg/rpmsg_ns.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) STMicroelectronics 2020 - All Rights Reserved
4+
*/
5+
#include <linux/device.h>
6+
#include <linux/kernel.h>
7+
#include <linux/module.h>
8+
#include <linux/rpmsg.h>
9+
#include <linux/rpmsg/ns.h>
10+
#include <linux/slab.h>
11+
12+
#include "rpmsg_internal.h"
13+
14+
/**
15+
* rpmsg_ns_register_device() - register name service device based on rpdev
16+
* @rpdev: prepared rpdev to be used for creating endpoints
17+
*
18+
* This function wraps rpmsg_register_device() preparing the rpdev for use as
19+
* basis for the rpmsg name service device.
20+
*/
21+
int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
22+
{
23+
strcpy(rpdev->id.name, "rpmsg_ns");
24+
rpdev->driver_override = "rpmsg_ns";
25+
rpdev->src = RPMSG_NS_ADDR;
26+
rpdev->dst = RPMSG_NS_ADDR;
27+
28+
return rpmsg_register_device(rpdev);
29+
}
30+
EXPORT_SYMBOL(rpmsg_ns_register_device);
31+
32+
/* invoked when a name service announcement arrives */
33+
static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
34+
void *priv, u32 src)
35+
{
36+
struct rpmsg_ns_msg *msg = data;
37+
struct rpmsg_device *newch;
38+
struct rpmsg_channel_info chinfo;
39+
struct device *dev = rpdev->dev.parent;
40+
int ret;
41+
42+
#if defined(CONFIG_DYNAMIC_DEBUG)
43+
dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1,
44+
data, len, true);
45+
#endif
46+
47+
if (len != sizeof(*msg)) {
48+
dev_err(dev, "malformed ns msg (%d)\n", len);
49+
return -EINVAL;
50+
}
51+
52+
/* don't trust the remote processor for null terminating the name */
53+
msg->name[RPMSG_NAME_SIZE - 1] = '\0';
54+
55+
strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
56+
chinfo.src = RPMSG_ADDR_ANY;
57+
chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr);
58+
59+
dev_info(dev, "%sing channel %s addr 0x%x\n",
60+
rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ?
61+
"destroy" : "creat", msg->name, chinfo.dst);
62+
63+
if (rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY) {
64+
ret = rpmsg_release_channel(rpdev, &chinfo);
65+
if (ret)
66+
dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
67+
} else {
68+
newch = rpmsg_create_channel(rpdev, &chinfo);
69+
if (!newch)
70+
dev_err(dev, "rpmsg_create_channel failed\n");
71+
}
72+
73+
return 0;
74+
}
75+
76+
static int rpmsg_ns_probe(struct rpmsg_device *rpdev)
77+
{
78+
struct rpmsg_endpoint *ns_ept;
79+
struct rpmsg_channel_info ns_chinfo = {
80+
.src = RPMSG_NS_ADDR,
81+
.dst = RPMSG_NS_ADDR,
82+
.name = "name_service",
83+
};
84+
85+
/*
86+
* Create the NS announcement service endpoint associated to the RPMsg
87+
* device. The endpoint will be automatically destroyed when the RPMsg
88+
* device will be deleted.
89+
*/
90+
ns_ept = rpmsg_create_ept(rpdev, rpmsg_ns_cb, NULL, ns_chinfo);
91+
if (!ns_ept) {
92+
dev_err(&rpdev->dev, "failed to create the ns ept\n");
93+
return -ENOMEM;
94+
}
95+
rpdev->ept = ns_ept;
96+
97+
return 0;
98+
}
99+
100+
static struct rpmsg_driver rpmsg_ns_driver = {
101+
.drv.name = KBUILD_MODNAME,
102+
.probe = rpmsg_ns_probe,
103+
};
104+
105+
static int rpmsg_ns_init(void)
106+
{
107+
int ret;
108+
109+
ret = register_rpmsg_driver(&rpmsg_ns_driver);
110+
if (ret < 0)
111+
pr_err("%s: Failed to register rpmsg driver\n", __func__);
112+
113+
return ret;
114+
}
115+
postcore_initcall(rpmsg_ns_init);
116+
117+
static void rpmsg_ns_exit(void)
118+
{
119+
unregister_rpmsg_driver(&rpmsg_ns_driver);
120+
}
121+
module_exit(rpmsg_ns_exit);
122+
123+
MODULE_DESCRIPTION("Name service announcement rpmsg driver");
124+
MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
125+
MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
126+
MODULE_LICENSE("GPL v2");

drivers/rpmsg/virtio_rpmsg_bus.c

Lines changed: 20 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
* @endpoints_lock: lock of the endpoints set
5050
* @sendq: wait queue of sending contexts waiting for a tx buffers
5151
* @sleepers: number of senders that are waiting for a tx buffer
52-
* @ns_ept: the bus's name service endpoint
5352
*
5453
* This structure stores the rpmsg state of a given virtio remote processor
5554
* device (there might be several virtio proc devices for each physical
@@ -68,7 +67,6 @@ struct virtproc_info {
6867
struct mutex endpoints_lock;
6968
wait_queue_head_t sendq;
7069
atomic_t sleepers;
71-
struct rpmsg_endpoint *ns_ept;
7270
};
7371

7472
/* The feature bitmap for virtio rpmsg */
@@ -815,69 +813,14 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
815813
wake_up_interruptible(&vrp->sendq);
816814
}
817815

818-
/* invoked when a name service announcement arrives */
819-
static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
820-
void *priv, u32 src)
821-
{
822-
struct rpmsg_ns_msg *msg = data;
823-
struct rpmsg_device *newch;
824-
struct rpmsg_channel_info chinfo;
825-
struct virtproc_info *vrp = priv;
826-
struct device *dev = &vrp->vdev->dev;
827-
bool little_endian = virtio_is_little_endian(vrp->vdev);
828-
int ret;
829-
830-
#if defined(CONFIG_DYNAMIC_DEBUG)
831-
dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1,
832-
data, len, true);
833-
#endif
834-
835-
if (len != sizeof(*msg)) {
836-
dev_err(dev, "malformed ns msg (%d)\n", len);
837-
return -EINVAL;
838-
}
839-
840-
/*
841-
* the name service ept does _not_ belong to a real rpmsg channel,
842-
* and is handled by the rpmsg bus itself.
843-
* for sanity reasons, make sure a valid rpdev has _not_ sneaked
844-
* in somehow.
845-
*/
846-
if (rpdev) {
847-
dev_err(dev, "anomaly: ns ept has an rpdev handle\n");
848-
return -EINVAL;
849-
}
850-
851-
/* don't trust the remote processor for null terminating the name */
852-
msg->name[RPMSG_NAME_SIZE - 1] = '\0';
853-
854-
strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
855-
chinfo.src = RPMSG_ADDR_ANY;
856-
chinfo.dst = __rpmsg32_to_cpu(little_endian, msg->addr);
857-
858-
dev_info(dev, "%sing channel %s addr 0x%x\n",
859-
__rpmsg32_to_cpu(little_endian, msg->flags) & RPMSG_NS_DESTROY ?
860-
"destroy" : "creat", msg->name, chinfo.dst);
861-
862-
if (__rpmsg32_to_cpu(little_endian, msg->flags) & RPMSG_NS_DESTROY) {
863-
ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
864-
if (ret)
865-
dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
866-
} else {
867-
newch = __rpmsg_create_channel(vrp, &chinfo);
868-
if (!newch)
869-
dev_err(dev, "rpmsg_create_channel failed\n");
870-
}
871-
872-
return 0;
873-
}
874-
875816
static int rpmsg_probe(struct virtio_device *vdev)
876817
{
877818
vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done };
878819
static const char * const names[] = { "input", "output" };
879820
struct virtqueue *vqs[2];
880821
struct virtproc_info *vrp;
822+
struct virtio_rpmsg_channel *vch;
823+
struct rpmsg_device *rpdev_ns;
881824
void *bufs_va;
882825
int err = 0, i;
883826
size_t total_buf_space;
@@ -953,14 +896,26 @@ static int rpmsg_probe(struct virtio_device *vdev)
953896

954897
/* if supported by the remote processor, enable the name service */
955898
if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) {
956-
/* a dedicated endpoint handles the name service msgs */
957-
vrp->ns_ept = __rpmsg_create_ept(vrp, NULL, rpmsg_ns_cb,
958-
vrp, RPMSG_NS_ADDR);
959-
if (!vrp->ns_ept) {
960-
dev_err(&vdev->dev, "failed to create the ns ept\n");
899+
vch = kzalloc(sizeof(*vch), GFP_KERNEL);
900+
if (!vch) {
961901
err = -ENOMEM;
962902
goto free_coherent;
963903
}
904+
905+
/* Link the channel to our vrp */
906+
vch->vrp = vrp;
907+
908+
/* Assign public information to the rpmsg_device */
909+
rpdev_ns = &vch->rpdev;
910+
rpdev_ns->ops = &virtio_rpmsg_ops;
911+
rpdev_ns->little_endian = virtio_is_little_endian(vrp->vdev);
912+
913+
rpdev_ns->dev.parent = &vrp->vdev->dev;
914+
rpdev_ns->dev.release = virtio_rpmsg_release_device;
915+
916+
err = rpmsg_ns_register_device(rpdev_ns);
917+
if (err)
918+
goto free_coherent;
964919
}
965920

966921
/*
@@ -985,6 +940,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
985940
return 0;
986941

987942
free_coherent:
943+
kfree(vch);
988944
dma_free_coherent(vdev->dev.parent, total_buf_space,
989945
bufs_va, vrp->bufs_dma);
990946
vqs_del:
@@ -1013,9 +969,6 @@ static void rpmsg_remove(struct virtio_device *vdev)
1013969
if (ret)
1014970
dev_warn(&vdev->dev, "can't remove rpmsg device: %d\n", ret);
1015971

1016-
if (vrp->ns_ept)
1017-
__rpmsg_destroy_ept(vrp, vrp->ns_ept);
1018-
1019972
idr_destroy(&vrp->endpoints);
1020973

1021974
vdev->config->del_vqs(vrp->vdev);

include/linux/rpmsg/ns.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define _LINUX_RPMSG_NS_H
55

66
#include <linux/mod_devicetable.h>
7+
#include <linux/rpmsg.h>
78
#include <linux/rpmsg/byteorder.h>
89
#include <linux/types.h>
910

@@ -39,4 +40,6 @@ enum rpmsg_ns_flags {
3940
/* Address 53 is reserved for advertising remote services */
4041
#define RPMSG_NS_ADDR (53)
4142

43+
int rpmsg_ns_register_device(struct rpmsg_device *rpdev);
44+
4245
#endif

0 commit comments

Comments
 (0)