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"); 127