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 SCMI_UEVENT_MODALIAS_FMT "arm_ffa:%04x:%pUb" 19 20static DEFINE_IDA(ffa_bus_id); 21 22static int ffa_device_match(struct device *dev, 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 30 while (!uuid_is_null(&id_table->uuid)) { 31 /* 32 * FF-A v1.0 doesn't provide discovery of UUIDs, just the 33 * partition IDs, so fetch the partitions IDs for this 34 * id_table UUID and assign the UUID to the device if the 35 * partition ID matches 36 */ 37 if (uuid_is_null(&ffa_dev->uuid)) 38 ffa_device_match_uuid(ffa_dev, &id_table->uuid); 39 40 if (uuid_equal(&ffa_dev->uuid, &id_table->uuid)) 41 return 1; 42 id_table++; 43 } 44 45 return 0; 46} 47 48static int ffa_device_probe(struct device *dev) 49{ 50 struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); 51 struct ffa_device *ffa_dev = to_ffa_dev(dev); 52 53 return ffa_drv->probe(ffa_dev); 54} 55 56static void ffa_device_remove(struct device *dev) 57{ 58 struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); 59 60 if (ffa_drv->remove) 61 ffa_drv->remove(to_ffa_dev(dev)); 62} 63 64static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env) 65{ 66 const struct ffa_device *ffa_dev = to_ffa_dev(dev); 67 68 return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT, 69 ffa_dev->vm_id, &ffa_dev->uuid); 70} 71 72static ssize_t modalias_show(struct device *dev, 73 struct device_attribute *attr, char *buf) 74{ 75 struct ffa_device *ffa_dev = to_ffa_dev(dev); 76 77 return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT, ffa_dev->vm_id, 78 &ffa_dev->uuid); 79} 80static DEVICE_ATTR_RO(modalias); 81 82static ssize_t partition_id_show(struct device *dev, 83 struct device_attribute *attr, char *buf) 84{ 85 struct ffa_device *ffa_dev = to_ffa_dev(dev); 86 87 return sprintf(buf, "0x%04x\n", ffa_dev->vm_id); 88} 89static DEVICE_ATTR_RO(partition_id); 90 91static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, 92 char *buf) 93{ 94 struct ffa_device *ffa_dev = to_ffa_dev(dev); 95 96 return sprintf(buf, "%pUb\n", &ffa_dev->uuid); 97} 98static DEVICE_ATTR_RO(uuid); 99 100static struct attribute *ffa_device_attributes_attrs[] = { 101 &dev_attr_partition_id.attr, 102 &dev_attr_uuid.attr, 103 &dev_attr_modalias.attr, 104 NULL, 105}; 106ATTRIBUTE_GROUPS(ffa_device_attributes); 107 108const struct bus_type ffa_bus_type = { 109 .name = "arm_ffa", 110 .match = ffa_device_match, 111 .probe = ffa_device_probe, 112 .remove = ffa_device_remove, 113 .uevent = ffa_device_uevent, 114 .dev_groups = ffa_device_attributes_groups, 115}; 116EXPORT_SYMBOL_GPL(ffa_bus_type); 117 118int ffa_driver_register(struct ffa_driver *driver, struct module *owner, 119 const char *mod_name) 120{ 121 int ret; 122 123 if (!driver->probe) 124 return -EINVAL; 125 126 driver->driver.bus = &ffa_bus_type; 127 driver->driver.name = driver->name; 128 driver->driver.owner = owner; 129 driver->driver.mod_name = mod_name; 130 131 ret = driver_register(&driver->driver); 132 if (!ret) 133 pr_debug("registered new ffa driver %s\n", driver->name); 134 135 return ret; 136} 137EXPORT_SYMBOL_GPL(ffa_driver_register); 138 139void ffa_driver_unregister(struct ffa_driver *driver) 140{ 141 driver_unregister(&driver->driver); 142} 143EXPORT_SYMBOL_GPL(ffa_driver_unregister); 144 145static void ffa_release_device(struct device *dev) 146{ 147 struct ffa_device *ffa_dev = to_ffa_dev(dev); 148 149 ida_free(&ffa_bus_id, ffa_dev->id); 150 kfree(ffa_dev); 151} 152 153static int __ffa_devices_unregister(struct device *dev, void *data) 154{ 155 device_unregister(dev); 156 157 return 0; 158} 159 160static void ffa_devices_unregister(void) 161{ 162 bus_for_each_dev(&ffa_bus_type, NULL, NULL, 163 __ffa_devices_unregister); 164} 165 166bool ffa_device_is_valid(struct ffa_device *ffa_dev) 167{ 168 bool valid = false; 169 struct device *dev = NULL; 170 struct ffa_device *tmp_dev; 171 172 do { 173 dev = bus_find_next_device(&ffa_bus_type, dev); 174 tmp_dev = to_ffa_dev(dev); 175 if (tmp_dev == ffa_dev) { 176 valid = true; 177 break; 178 } 179 put_device(dev); 180 } while (dev); 181 182 put_device(dev); 183 184 return valid; 185} 186 187struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, 188 const struct ffa_ops *ops) 189{ 190 int id, ret; 191 struct device *dev; 192 struct ffa_device *ffa_dev; 193 194 id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL); 195 if (id < 0) 196 return NULL; 197 198 ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL); 199 if (!ffa_dev) { 200 ida_free(&ffa_bus_id, id); 201 return NULL; 202 } 203 204 dev = &ffa_dev->dev; 205 dev->bus = &ffa_bus_type; 206 dev->release = ffa_release_device; 207 dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); 208 209 ffa_dev->id = id; 210 ffa_dev->vm_id = vm_id; 211 ffa_dev->ops = ops; 212 uuid_copy(&ffa_dev->uuid, uuid); 213 214 ret = device_register(&ffa_dev->dev); 215 if (ret) { 216 dev_err(dev, "unable to register device %s err=%d\n", 217 dev_name(dev), ret); 218 put_device(dev); 219 return NULL; 220 } 221 222 return ffa_dev; 223} 224EXPORT_SYMBOL_GPL(ffa_device_register); 225 226void ffa_device_unregister(struct ffa_device *ffa_dev) 227{ 228 if (!ffa_dev) 229 return; 230 231 device_unregister(&ffa_dev->dev); 232} 233EXPORT_SYMBOL_GPL(ffa_device_unregister); 234 235int arm_ffa_bus_init(void) 236{ 237 return bus_register(&ffa_bus_type); 238} 239 240void arm_ffa_bus_exit(void) 241{ 242 ffa_devices_unregister(); 243 bus_unregister(&ffa_bus_type); 244 ida_destroy(&ffa_bus_id); 245} 246