]> Git Repo - linux.git/blob - drivers/firmware/arm_ffa/bus.c
fs/binfmt_elf: use PT_LOAD p_align values for static PIE
[linux.git] / drivers / firmware / arm_ffa / bus.c
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 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
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
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
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
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
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
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
123 void ffa_driver_unregister(struct ffa_driver *driver)
124 {
125         driver_unregister(&driver->driver);
126 }
127 EXPORT_SYMBOL_GPL(ffa_driver_unregister);
128
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
136 static int __ffa_devices_unregister(struct device *dev, void *data)
137 {
138         device_unregister(dev);
139
140         return 0;
141 }
142
143 static void ffa_devices_unregister(void)
144 {
145         bus_for_each_dev(&ffa_bus_type, NULL, NULL,
146                          __ffa_devices_unregister);
147 }
148
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
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
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
209 int arm_ffa_bus_init(void)
210 {
211         return bus_register(&ffa_bus_type);
212 }
213
214 void arm_ffa_bus_exit(void)
215 {
216         ffa_devices_unregister();
217         bus_unregister(&ffa_bus_type);
218 }
This page took 0.045943 seconds and 4 git commands to generate.