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