0001
0002
0003
0004
0005 #include <linux/device.h>
0006 #include <linux/kernel.h>
0007 #include <linux/module.h>
0008 #include <linux/rpmsg.h>
0009 #include <linux/rpmsg/ns.h>
0010 #include <linux/slab.h>
0011
0012 #include "rpmsg_internal.h"
0013
0014
0015
0016
0017
0018
0019
0020
0021 int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
0022 {
0023 rpdev->src = RPMSG_NS_ADDR;
0024 rpdev->dst = RPMSG_NS_ADDR;
0025
0026 return rpmsg_register_device_override(rpdev, "rpmsg_ns");
0027 }
0028 EXPORT_SYMBOL(rpmsg_ns_register_device);
0029
0030
0031 static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
0032 void *priv, u32 src)
0033 {
0034 struct rpmsg_ns_msg *msg = data;
0035 struct rpmsg_device *newch;
0036 struct rpmsg_channel_info chinfo;
0037 struct device *dev = rpdev->dev.parent;
0038 int ret;
0039
0040 #if defined(CONFIG_DYNAMIC_DEBUG)
0041 dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1,
0042 data, len, true);
0043 #endif
0044
0045 if (len != sizeof(*msg)) {
0046 dev_err(dev, "malformed ns msg (%d)\n", len);
0047 return -EINVAL;
0048 }
0049
0050
0051 msg->name[RPMSG_NAME_SIZE - 1] = '\0';
0052
0053 strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
0054 chinfo.src = RPMSG_ADDR_ANY;
0055 chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr);
0056
0057 dev_info(dev, "%sing channel %s addr 0x%x\n",
0058 rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ?
0059 "destroy" : "creat", msg->name, chinfo.dst);
0060
0061 if (rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY) {
0062 ret = rpmsg_release_channel(rpdev, &chinfo);
0063 if (ret)
0064 dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
0065 } else {
0066 newch = rpmsg_create_channel(rpdev, &chinfo);
0067 if (!newch)
0068 dev_err(dev, "rpmsg_create_channel failed\n");
0069 }
0070
0071 return 0;
0072 }
0073
0074 static int rpmsg_ns_probe(struct rpmsg_device *rpdev)
0075 {
0076 struct rpmsg_endpoint *ns_ept;
0077 struct rpmsg_channel_info ns_chinfo = {
0078 .src = RPMSG_NS_ADDR,
0079 .dst = RPMSG_NS_ADDR,
0080 .name = "name_service",
0081 };
0082
0083
0084
0085
0086
0087
0088 ns_ept = rpmsg_create_ept(rpdev, rpmsg_ns_cb, NULL, ns_chinfo);
0089 if (!ns_ept) {
0090 dev_err(&rpdev->dev, "failed to create the ns ept\n");
0091 return -ENOMEM;
0092 }
0093 rpdev->ept = ns_ept;
0094
0095 return 0;
0096 }
0097
0098 static struct rpmsg_driver rpmsg_ns_driver = {
0099 .drv.name = KBUILD_MODNAME,
0100 .probe = rpmsg_ns_probe,
0101 };
0102
0103 static int rpmsg_ns_init(void)
0104 {
0105 int ret;
0106
0107 ret = register_rpmsg_driver(&rpmsg_ns_driver);
0108 if (ret < 0)
0109 pr_err("%s: Failed to register rpmsg driver\n", __func__);
0110
0111 return ret;
0112 }
0113 postcore_initcall(rpmsg_ns_init);
0114
0115 static void rpmsg_ns_exit(void)
0116 {
0117 unregister_rpmsg_driver(&rpmsg_ns_driver);
0118 }
0119 module_exit(rpmsg_ns_exit);
0120
0121 MODULE_DESCRIPTION("Name service announcement rpmsg driver");
0122 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
0123 MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
0124 MODULE_LICENSE("GPL v2");