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