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(struct device * dev,struct kobj_uevent_env * env)59 static 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 
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)170 struct 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 }
198 EXPORT_SYMBOL_GPL(ffa_device_register);
199 
ffa_device_unregister(struct ffa_device * ffa_dev)200 void ffa_device_unregister(struct ffa_device *ffa_dev)
201 {
202 	if (!ffa_dev)
203 		return;
204 
205 	device_unregister(&ffa_dev->dev);
206 }
207 EXPORT_SYMBOL_GPL(ffa_device_unregister);
208 
arm_ffa_bus_init(void)209 int arm_ffa_bus_init(void)
210 {
211 	return bus_register(&ffa_bus_type);
212 }
213 
arm_ffa_bus_exit(void)214 void arm_ffa_bus_exit(void)
215 {
216 	ffa_devices_unregister();
217 	bus_unregister(&ffa_bus_type);
218 }
219