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 int ret; 24 25 strcpy(rpdev->id.name, "rpmsg_ns"); 26 ret = driver_set_override(&rpdev->dev, &rpdev->driver_override, 27 rpdev->id.name, strlen(rpdev->id.name)); 28 if (ret) 29 return ret; 30 31 rpdev->src = RPMSG_NS_ADDR; 32 rpdev->dst = RPMSG_NS_ADDR; 33 34 ret = rpmsg_register_device(rpdev); 35 if (ret) 36 kfree(rpdev->driver_override); 37 38 return ret; 39 } 40 EXPORT_SYMBOL(rpmsg_ns_register_device); 41 42 /* invoked when a name service announcement arrives */ 43 static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len, 44 void *priv, u32 src) 45 { 46 struct rpmsg_ns_msg *msg = data; 47 struct rpmsg_device *newch; 48 struct rpmsg_channel_info chinfo; 49 struct device *dev = rpdev->dev.parent; 50 int ret; 51 52 #if defined(CONFIG_DYNAMIC_DEBUG) 53 dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1, 54 data, len, true); 55 #endif 56 57 if (len != sizeof(*msg)) { 58 dev_err(dev, "malformed ns msg (%d)\n", len); 59 return -EINVAL; 60 } 61 62 /* don't trust the remote processor for null terminating the name */ 63 msg->name[RPMSG_NAME_SIZE - 1] = '\0'; 64 65 strncpy(chinfo.name, msg->name, sizeof(chinfo.name)); 66 chinfo.src = RPMSG_ADDR_ANY; 67 chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr); 68 69 dev_info(dev, "%sing channel %s addr 0x%x\n", 70 rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ? 71 "destroy" : "creat", msg->name, chinfo.dst); 72 73 if (rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY) { 74 ret = rpmsg_release_channel(rpdev, &chinfo); 75 if (ret) 76 dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); 77 } else { 78 newch = rpmsg_create_channel(rpdev, &chinfo); 79 if (!newch) 80 dev_err(dev, "rpmsg_create_channel failed\n"); 81 } 82 83 return 0; 84 } 85 86 static int rpmsg_ns_probe(struct rpmsg_device *rpdev) 87 { 88 struct rpmsg_endpoint *ns_ept; 89 struct rpmsg_channel_info ns_chinfo = { 90 .src = RPMSG_NS_ADDR, 91 .dst = RPMSG_NS_ADDR, 92 .name = "name_service", 93 }; 94 95 /* 96 * Create the NS announcement service endpoint associated to the RPMsg 97 * device. The endpoint will be automatically destroyed when the RPMsg 98 * device will be deleted. 99 */ 100 ns_ept = rpmsg_create_ept(rpdev, rpmsg_ns_cb, NULL, ns_chinfo); 101 if (!ns_ept) { 102 dev_err(&rpdev->dev, "failed to create the ns ept\n"); 103 return -ENOMEM; 104 } 105 rpdev->ept = ns_ept; 106 107 return 0; 108 } 109 110 static struct rpmsg_driver rpmsg_ns_driver = { 111 .drv.name = KBUILD_MODNAME, 112 .probe = rpmsg_ns_probe, 113 }; 114 115 static int rpmsg_ns_init(void) 116 { 117 int ret; 118 119 ret = register_rpmsg_driver(&rpmsg_ns_driver); 120 if (ret < 0) 121 pr_err("%s: Failed to register rpmsg driver\n", __func__); 122 123 return ret; 124 } 125 postcore_initcall(rpmsg_ns_init); 126 127 static void rpmsg_ns_exit(void) 128 { 129 unregister_rpmsg_driver(&rpmsg_ns_driver); 130 } 131 module_exit(rpmsg_ns_exit); 132 133 MODULE_DESCRIPTION("Name service announcement rpmsg driver"); 134 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 135 MODULE_ALIAS("rpmsg:" KBUILD_MODNAME); 136 MODULE_LICENSE("GPL v2"); 137