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
ffa_device_match(struct device * dev,struct device_driver * drv)18 static 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
ffa_device_probe(struct device * dev)44 static 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
ffa_device_remove(struct device * dev)52 static 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
ffa_device_uevent(const struct device * dev,struct kobj_uevent_env * env)59 static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
60 {
61 const 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
partition_id_show(struct device * dev,struct device_attribute * attr,char * buf)67 static 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 }
74 static DEVICE_ATTR_RO(partition_id);
75
uuid_show(struct device * dev,struct device_attribute * attr,char * buf)76 static 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 }
83 static DEVICE_ATTR_RO(uuid);
84
85 static struct attribute *ffa_device_attributes_attrs[] = {
86 &dev_attr_partition_id.attr,
87 &dev_attr_uuid.attr,
88 NULL,
89 };
90 ATTRIBUTE_GROUPS(ffa_device_attributes);
91
92 struct 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 };
100 EXPORT_SYMBOL_GPL(ffa_bus_type);
101
ffa_driver_register(struct ffa_driver * driver,struct module * owner,const char * mod_name)102 int 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 }
121 EXPORT_SYMBOL_GPL(ffa_driver_register);
122
ffa_driver_unregister(struct ffa_driver * driver)123 void ffa_driver_unregister(struct ffa_driver *driver)
124 {
125 driver_unregister(&driver->driver);
126 }
127 EXPORT_SYMBOL_GPL(ffa_driver_unregister);
128
ffa_release_device(struct device * dev)129 static 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
__ffa_devices_unregister(struct device * dev,void * data)136 static int __ffa_devices_unregister(struct device *dev, void *data)
137 {
138 device_unregister(dev);
139
140 return 0;
141 }
142
ffa_devices_unregister(void)143 static void ffa_devices_unregister(void)
144 {
145 bus_for_each_dev(&ffa_bus_type, NULL, NULL,
146 __ffa_devices_unregister);
147 }
148
ffa_device_is_valid(struct ffa_device * ffa_dev)149 bool 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
ffa_device_register(const uuid_t * uuid,int vm_id,const struct ffa_ops * ops)170 struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
171 const struct ffa_ops *ops)
172 {
173 int ret;
174 struct device *dev;
175 struct ffa_device *ffa_dev;
176
177 ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
178 if (!ffa_dev)
179 return NULL;
180
181 dev = &ffa_dev->dev;
182 dev->bus = &ffa_bus_type;
183 dev->release = ffa_release_device;
184 dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
185
186 ffa_dev->vm_id = vm_id;
187 ffa_dev->ops = ops;
188 uuid_copy(&ffa_dev->uuid, uuid);
189
190 ret = device_register(&ffa_dev->dev);
191 if (ret) {
192 dev_err(dev, "unable to register device %s err=%d\n",
193 dev_name(dev), ret);
194 put_device(dev);
195 return NULL;
196 }
197
198 return ffa_dev;
199 }
200 EXPORT_SYMBOL_GPL(ffa_device_register);
201
ffa_device_unregister(struct ffa_device * ffa_dev)202 void ffa_device_unregister(struct ffa_device *ffa_dev)
203 {
204 if (!ffa_dev)
205 return;
206
207 device_unregister(&ffa_dev->dev);
208 }
209 EXPORT_SYMBOL_GPL(ffa_device_unregister);
210
arm_ffa_bus_init(void)211 int arm_ffa_bus_init(void)
212 {
213 return bus_register(&ffa_bus_type);
214 }
215
arm_ffa_bus_exit(void)216 void arm_ffa_bus_exit(void)
217 {
218 ffa_devices_unregister();
219 bus_unregister(&ffa_bus_type);
220 }
221