1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 ARM Ltd. 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <linux/arm_ffa.h> 9 #include <linux/device.h> 10 #include <linux/fs.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/slab.h> 14 #include <linux/types.h> 15 16 #include "common.h" 17 18 #define FFA_UEVENT_MODALIAS_FMT "arm_ffa:%04x:%pUb" 19 20 static DEFINE_IDA(ffa_bus_id); 21 22 static int ffa_device_match(struct device *dev, const struct device_driver *drv) 23 { 24 const struct ffa_device_id *id_table; 25 struct ffa_device *ffa_dev; 26 27 id_table = to_ffa_driver(drv)->id_table; 28 ffa_dev = to_ffa_dev(dev); 29 if (!id_table) 30 return 0; 31 32 while (!uuid_is_null(&id_table->uuid)) { 33 /* 34 * FF-A v1.0 doesn't provide discovery of UUIDs, just the 35 * partition IDs, so match it unconditionally here and handle 36 * it via the installed bus notifier during driver binding. 37 */ 38 if (uuid_is_null(&ffa_dev->uuid)) 39 return 1; 40 41 if (uuid_equal(&ffa_dev->uuid, &id_table->uuid)) 42 return 1; 43 id_table++; 44 } 45 46 return 0; 47 } 48 49 static int ffa_device_probe(struct device *dev) 50 { 51 struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); 52 struct ffa_device *ffa_dev = to_ffa_dev(dev); 53 54 /* UUID can be still NULL with FF-A v1.0, so just skip probing them */ 55 if (uuid_is_null(&ffa_dev->uuid)) 56 return -ENODEV; 57 58 return ffa_drv->probe(ffa_dev); 59 } 60 61 static void ffa_device_remove(struct device *dev) 62 { 63 struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); 64 65 if (ffa_drv->remove) 66 ffa_drv->remove(to_ffa_dev(dev)); 67 } 68 69 static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env) 70 { 71 const struct ffa_device *ffa_dev = to_ffa_dev(dev); 72 73 return add_uevent_var(env, "MODALIAS=" FFA_UEVENT_MODALIAS_FMT, 74 ffa_dev->vm_id, &ffa_dev->uuid); 75 } 76 77 static ssize_t modalias_show(struct device *dev, 78 struct device_attribute *attr, char *buf) 79 { 80 struct ffa_device *ffa_dev = to_ffa_dev(dev); 81 82 return sysfs_emit(buf, FFA_UEVENT_MODALIAS_FMT, ffa_dev->vm_id, 83 &ffa_dev->uuid); 84 } 85 static DEVICE_ATTR_RO(modalias); 86 87 static ssize_t partition_id_show(struct device *dev, 88 struct device_attribute *attr, char *buf) 89 { 90 struct ffa_device *ffa_dev = to_ffa_dev(dev); 91 92 return sprintf(buf, "0x%04x\n", ffa_dev->vm_id); 93 } 94 static DEVICE_ATTR_RO(partition_id); 95 96 static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, 97 char *buf) 98 { 99 struct ffa_device *ffa_dev = to_ffa_dev(dev); 100 101 return sprintf(buf, "%pUb\n", &ffa_dev->uuid); 102 } 103 static DEVICE_ATTR_RO(uuid); 104 105 static struct attribute *ffa_device_attributes_attrs[] = { 106 &dev_attr_partition_id.attr, 107 &dev_attr_uuid.attr, 108 &dev_attr_modalias.attr, 109 NULL, 110 }; 111 ATTRIBUTE_GROUPS(ffa_device_attributes); 112 113 const struct bus_type ffa_bus_type = { 114 .name = "arm_ffa", 115 .match = ffa_device_match, 116 .probe = ffa_device_probe, 117 .remove = ffa_device_remove, 118 .uevent = ffa_device_uevent, 119 .dev_groups = ffa_device_attributes_groups, 120 }; 121 EXPORT_SYMBOL_GPL(ffa_bus_type); 122 123 int ffa_driver_register(struct ffa_driver *driver, struct module *owner, 124 const char *mod_name) 125 { 126 int ret; 127 128 if (!driver->probe || !driver->id_table) 129 return -EINVAL; 130 131 driver->driver.bus = &ffa_bus_type; 132 driver->driver.name = driver->name; 133 driver->driver.owner = owner; 134 driver->driver.mod_name = mod_name; 135 136 ret = driver_register(&driver->driver); 137 if (!ret) 138 pr_debug("registered new ffa driver %s\n", driver->name); 139 140 return ret; 141 } 142 EXPORT_SYMBOL_GPL(ffa_driver_register); 143 144 void ffa_driver_unregister(struct ffa_driver *driver) 145 { 146 driver_unregister(&driver->driver); 147 } 148 EXPORT_SYMBOL_GPL(ffa_driver_unregister); 149 150 static void ffa_release_device(struct device *dev) 151 { 152 struct ffa_device *ffa_dev = to_ffa_dev(dev); 153 154 ida_free(&ffa_bus_id, ffa_dev->id); 155 kfree(ffa_dev); 156 } 157 158 static int __ffa_devices_unregister(struct device *dev, void *data) 159 { 160 device_unregister(dev); 161 162 return 0; 163 } 164 165 void ffa_devices_unregister(void) 166 { 167 bus_for_each_dev(&ffa_bus_type, NULL, NULL, 168 __ffa_devices_unregister); 169 } 170 EXPORT_SYMBOL_GPL(ffa_devices_unregister); 171 172 bool ffa_device_is_valid(struct ffa_device *ffa_dev) 173 { 174 bool valid = false; 175 struct device *dev = NULL; 176 struct ffa_device *tmp_dev; 177 178 do { 179 dev = bus_find_next_device(&ffa_bus_type, dev); 180 tmp_dev = to_ffa_dev(dev); 181 if (tmp_dev == ffa_dev) { 182 valid = true; 183 break; 184 } 185 put_device(dev); 186 } while (dev); 187 188 put_device(dev); 189 190 return valid; 191 } 192 193 struct ffa_device * 194 ffa_device_register(const struct ffa_partition_info *part_info, 195 const struct ffa_ops *ops) 196 { 197 int id, ret; 198 struct device *dev; 199 struct ffa_device *ffa_dev; 200 201 if (!part_info) 202 return NULL; 203 204 id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL); 205 if (id < 0) 206 return NULL; 207 208 ffa_dev = kzalloc_obj(*ffa_dev); 209 if (!ffa_dev) { 210 ida_free(&ffa_bus_id, id); 211 return NULL; 212 } 213 214 dev = &ffa_dev->dev; 215 dev->bus = &ffa_bus_type; 216 dev->release = ffa_release_device; 217 dev->dma_mask = &dev->coherent_dma_mask; 218 dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); 219 220 ffa_dev->id = id; 221 ffa_dev->vm_id = part_info->id; 222 ffa_dev->properties = part_info->properties; 223 ffa_dev->ops = ops; 224 uuid_copy(&ffa_dev->uuid, &part_info->uuid); 225 226 ret = device_register(&ffa_dev->dev); 227 if (ret) { 228 dev_err(dev, "unable to register device %s err=%d\n", 229 dev_name(dev), ret); 230 put_device(dev); 231 return NULL; 232 } 233 234 return ffa_dev; 235 } 236 EXPORT_SYMBOL_GPL(ffa_device_register); 237 238 void ffa_device_unregister(struct ffa_device *ffa_dev) 239 { 240 if (!ffa_dev) 241 return; 242 243 device_unregister(&ffa_dev->dev); 244 } 245 EXPORT_SYMBOL_GPL(ffa_device_unregister); 246 247 static int __init arm_ffa_bus_init(void) 248 { 249 return bus_register(&ffa_bus_type); 250 } 251 subsys_initcall(arm_ffa_bus_init); 252 253 static void __exit arm_ffa_bus_exit(void) 254 { 255 ffa_devices_unregister(); 256 bus_unregister(&ffa_bus_type); 257 ida_destroy(&ffa_bus_id); 258 } 259 module_exit(arm_ffa_bus_exit); 260 261 MODULE_ALIAS("ffa-core"); 262 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 263 MODULE_DESCRIPTION("ARM FF-A bus"); 264 MODULE_LICENSE("GPL"); 265