Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2021 ARM Ltd.
0004  */
0005 
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/arm_ffa.h>
0009 #include <linux/device.h>
0010 #include <linux/fs.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/types.h>
0015 
0016 #include "common.h"
0017 
0018 static int ffa_device_match(struct device *dev, struct device_driver *drv)
0019 {
0020     const struct ffa_device_id *id_table;
0021     struct ffa_device *ffa_dev;
0022 
0023     id_table = to_ffa_driver(drv)->id_table;
0024     ffa_dev = to_ffa_dev(dev);
0025 
0026     while (!uuid_is_null(&id_table->uuid)) {
0027         /*
0028          * FF-A v1.0 doesn't provide discovery of UUIDs, just the
0029          * partition IDs, so fetch the partitions IDs for this
0030          * id_table UUID and assign the UUID to the device if the
0031          * partition ID matches
0032          */
0033         if (uuid_is_null(&ffa_dev->uuid))
0034             ffa_device_match_uuid(ffa_dev, &id_table->uuid);
0035 
0036         if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
0037             return 1;
0038         id_table++;
0039     }
0040 
0041     return 0;
0042 }
0043 
0044 static int ffa_device_probe(struct device *dev)
0045 {
0046     struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
0047     struct ffa_device *ffa_dev = to_ffa_dev(dev);
0048 
0049     return ffa_drv->probe(ffa_dev);
0050 }
0051 
0052 static void ffa_device_remove(struct device *dev)
0053 {
0054     struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
0055 
0056     ffa_drv->remove(to_ffa_dev(dev));
0057 }
0058 
0059 static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
0060 {
0061     struct ffa_device *ffa_dev = to_ffa_dev(dev);
0062 
0063     return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
0064                   ffa_dev->vm_id, &ffa_dev->uuid);
0065 }
0066 
0067 static ssize_t partition_id_show(struct device *dev,
0068                  struct device_attribute *attr, char *buf)
0069 {
0070     struct ffa_device *ffa_dev = to_ffa_dev(dev);
0071 
0072     return sprintf(buf, "0x%04x\n", ffa_dev->vm_id);
0073 }
0074 static DEVICE_ATTR_RO(partition_id);
0075 
0076 static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
0077              char *buf)
0078 {
0079     struct ffa_device *ffa_dev = to_ffa_dev(dev);
0080 
0081     return sprintf(buf, "%pUb\n", &ffa_dev->uuid);
0082 }
0083 static DEVICE_ATTR_RO(uuid);
0084 
0085 static struct attribute *ffa_device_attributes_attrs[] = {
0086     &dev_attr_partition_id.attr,
0087     &dev_attr_uuid.attr,
0088     NULL,
0089 };
0090 ATTRIBUTE_GROUPS(ffa_device_attributes);
0091 
0092 struct bus_type ffa_bus_type = {
0093     .name       = "arm_ffa",
0094     .match      = ffa_device_match,
0095     .probe      = ffa_device_probe,
0096     .remove     = ffa_device_remove,
0097     .uevent     = ffa_device_uevent,
0098     .dev_groups = ffa_device_attributes_groups,
0099 };
0100 EXPORT_SYMBOL_GPL(ffa_bus_type);
0101 
0102 int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
0103             const char *mod_name)
0104 {
0105     int ret;
0106 
0107     if (!driver->probe)
0108         return -EINVAL;
0109 
0110     driver->driver.bus = &ffa_bus_type;
0111     driver->driver.name = driver->name;
0112     driver->driver.owner = owner;
0113     driver->driver.mod_name = mod_name;
0114 
0115     ret = driver_register(&driver->driver);
0116     if (!ret)
0117         pr_debug("registered new ffa driver %s\n", driver->name);
0118 
0119     return ret;
0120 }
0121 EXPORT_SYMBOL_GPL(ffa_driver_register);
0122 
0123 void ffa_driver_unregister(struct ffa_driver *driver)
0124 {
0125     driver_unregister(&driver->driver);
0126 }
0127 EXPORT_SYMBOL_GPL(ffa_driver_unregister);
0128 
0129 static void ffa_release_device(struct device *dev)
0130 {
0131     struct ffa_device *ffa_dev = to_ffa_dev(dev);
0132 
0133     kfree(ffa_dev);
0134 }
0135 
0136 static int __ffa_devices_unregister(struct device *dev, void *data)
0137 {
0138     device_unregister(dev);
0139 
0140     return 0;
0141 }
0142 
0143 static void ffa_devices_unregister(void)
0144 {
0145     bus_for_each_dev(&ffa_bus_type, NULL, NULL,
0146              __ffa_devices_unregister);
0147 }
0148 
0149 bool ffa_device_is_valid(struct ffa_device *ffa_dev)
0150 {
0151     bool valid = false;
0152     struct device *dev = NULL;
0153     struct ffa_device *tmp_dev;
0154 
0155     do {
0156         dev = bus_find_next_device(&ffa_bus_type, dev);
0157         tmp_dev = to_ffa_dev(dev);
0158         if (tmp_dev == ffa_dev) {
0159             valid = true;
0160             break;
0161         }
0162         put_device(dev);
0163     } while (dev);
0164 
0165     put_device(dev);
0166 
0167     return valid;
0168 }
0169 
0170 struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
0171 {
0172     int ret;
0173     struct device *dev;
0174     struct ffa_device *ffa_dev;
0175 
0176     ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
0177     if (!ffa_dev)
0178         return NULL;
0179 
0180     dev = &ffa_dev->dev;
0181     dev->bus = &ffa_bus_type;
0182     dev->release = ffa_release_device;
0183     dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
0184 
0185     ffa_dev->vm_id = vm_id;
0186     uuid_copy(&ffa_dev->uuid, uuid);
0187 
0188     ret = device_register(&ffa_dev->dev);
0189     if (ret) {
0190         dev_err(dev, "unable to register device %s err=%d\n",
0191             dev_name(dev), ret);
0192         put_device(dev);
0193         return NULL;
0194     }
0195 
0196     return ffa_dev;
0197 }
0198 EXPORT_SYMBOL_GPL(ffa_device_register);
0199 
0200 void ffa_device_unregister(struct ffa_device *ffa_dev)
0201 {
0202     if (!ffa_dev)
0203         return;
0204 
0205     device_unregister(&ffa_dev->dev);
0206 }
0207 EXPORT_SYMBOL_GPL(ffa_device_unregister);
0208 
0209 int arm_ffa_bus_init(void)
0210 {
0211     return bus_register(&ffa_bus_type);
0212 }
0213 
0214 void arm_ffa_bus_exit(void)
0215 {
0216     ffa_devices_unregister();
0217     bus_unregister(&ffa_bus_type);
0218 }