1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * RapidIO driver support |
4 | * |
5 | * Copyright 2005 MontaVista Software, Inc. |
6 | * Matt Porter <mporter@kernel.crashing.org> |
7 | */ |
8 | |
9 | #include <linux/init.h> |
10 | #include <linux/module.h> |
11 | #include <linux/rio.h> |
12 | #include <linux/rio_ids.h> |
13 | #include <linux/rio_drv.h> |
14 | |
15 | #include "rio.h" |
16 | |
17 | /** |
18 | * rio_match_device - Tell if a RIO device has a matching RIO device id structure |
19 | * @id: the RIO device id structure to match against |
20 | * @rdev: the RIO device structure to match against |
21 | * |
22 | * Used from driver probe and bus matching to check whether a RIO device |
23 | * matches a device id structure provided by a RIO driver. Returns the |
24 | * matching &struct rio_device_id or %NULL if there is no match. |
25 | */ |
26 | static const struct rio_device_id *rio_match_device(const struct rio_device_id |
27 | *id, |
28 | const struct rio_dev *rdev) |
29 | { |
30 | while (id->vid || id->asm_vid) { |
31 | if (((id->vid == RIO_ANY_ID) || (id->vid == rdev->vid)) && |
32 | ((id->did == RIO_ANY_ID) || (id->did == rdev->did)) && |
33 | ((id->asm_vid == RIO_ANY_ID) |
34 | || (id->asm_vid == rdev->asm_vid)) |
35 | && ((id->asm_did == RIO_ANY_ID) |
36 | || (id->asm_did == rdev->asm_did))) |
37 | return id; |
38 | id++; |
39 | } |
40 | return NULL; |
41 | } |
42 | |
43 | /** |
44 | * rio_dev_get - Increments the reference count of the RIO device structure |
45 | * |
46 | * @rdev: RIO device being referenced |
47 | * |
48 | * Each live reference to a device should be refcounted. |
49 | * |
50 | * Drivers for RIO devices should normally record such references in |
51 | * their probe() methods, when they bind to a device, and release |
52 | * them by calling rio_dev_put(), in their disconnect() methods. |
53 | */ |
54 | struct rio_dev *rio_dev_get(struct rio_dev *rdev) |
55 | { |
56 | if (rdev) |
57 | get_device(dev: &rdev->dev); |
58 | |
59 | return rdev; |
60 | } |
61 | |
62 | /** |
63 | * rio_dev_put - Release a use of the RIO device structure |
64 | * |
65 | * @rdev: RIO device being disconnected |
66 | * |
67 | * Must be called when a user of a device is finished with it. |
68 | * When the last user of the device calls this function, the |
69 | * memory of the device is freed. |
70 | */ |
71 | void rio_dev_put(struct rio_dev *rdev) |
72 | { |
73 | if (rdev) |
74 | put_device(dev: &rdev->dev); |
75 | } |
76 | |
77 | /** |
78 | * rio_device_probe - Tell if a RIO device structure has a matching RIO device id structure |
79 | * @dev: the RIO device structure to match against |
80 | * |
81 | * return 0 and set rio_dev->driver when drv claims rio_dev, else error |
82 | */ |
83 | static int rio_device_probe(struct device *dev) |
84 | { |
85 | struct rio_driver *rdrv = to_rio_driver(dev->driver); |
86 | struct rio_dev *rdev = to_rio_dev(dev); |
87 | int error = -ENODEV; |
88 | const struct rio_device_id *id; |
89 | |
90 | if (!rdev->driver && rdrv->probe) { |
91 | if (!rdrv->id_table) |
92 | return error; |
93 | id = rio_match_device(id: rdrv->id_table, rdev); |
94 | rio_dev_get(rdev); |
95 | if (id) |
96 | error = rdrv->probe(rdev, id); |
97 | if (error >= 0) { |
98 | rdev->driver = rdrv; |
99 | error = 0; |
100 | } else |
101 | rio_dev_put(rdev); |
102 | } |
103 | return error; |
104 | } |
105 | |
106 | /** |
107 | * rio_device_remove - Remove a RIO device from the system |
108 | * |
109 | * @dev: the RIO device structure to match against |
110 | * |
111 | * Remove a RIO device from the system. If it has an associated |
112 | * driver, then run the driver remove() method. Then update |
113 | * the reference count. |
114 | */ |
115 | static void rio_device_remove(struct device *dev) |
116 | { |
117 | struct rio_dev *rdev = to_rio_dev(dev); |
118 | struct rio_driver *rdrv = rdev->driver; |
119 | |
120 | if (rdrv) { |
121 | if (rdrv->remove) |
122 | rdrv->remove(rdev); |
123 | rdev->driver = NULL; |
124 | } |
125 | |
126 | rio_dev_put(rdev); |
127 | } |
128 | |
129 | static void rio_device_shutdown(struct device *dev) |
130 | { |
131 | struct rio_dev *rdev = to_rio_dev(dev); |
132 | struct rio_driver *rdrv = rdev->driver; |
133 | |
134 | dev_dbg(dev, "RIO: %s\n" , __func__); |
135 | |
136 | if (rdrv && rdrv->shutdown) |
137 | rdrv->shutdown(rdev); |
138 | } |
139 | |
140 | /** |
141 | * rio_register_driver - register a new RIO driver |
142 | * @rdrv: the RIO driver structure to register |
143 | * |
144 | * Adds a &struct rio_driver to the list of registered drivers. |
145 | * Returns a negative value on error, otherwise 0. If no error |
146 | * occurred, the driver remains registered even if no device |
147 | * was claimed during registration. |
148 | */ |
149 | int rio_register_driver(struct rio_driver *rdrv) |
150 | { |
151 | /* initialize common driver fields */ |
152 | rdrv->driver.name = rdrv->name; |
153 | rdrv->driver.bus = &rio_bus_type; |
154 | |
155 | /* register with core */ |
156 | return driver_register(drv: &rdrv->driver); |
157 | } |
158 | |
159 | /** |
160 | * rio_unregister_driver - unregister a RIO driver |
161 | * @rdrv: the RIO driver structure to unregister |
162 | * |
163 | * Deletes the &struct rio_driver from the list of registered RIO |
164 | * drivers, gives it a chance to clean up by calling its remove() |
165 | * function for each device it was responsible for, and marks those |
166 | * devices as driverless. |
167 | */ |
168 | void rio_unregister_driver(struct rio_driver *rdrv) |
169 | { |
170 | driver_unregister(drv: &rdrv->driver); |
171 | } |
172 | |
173 | void rio_attach_device(struct rio_dev *rdev) |
174 | { |
175 | rdev->dev.bus = &rio_bus_type; |
176 | } |
177 | EXPORT_SYMBOL_GPL(rio_attach_device); |
178 | |
179 | /** |
180 | * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure |
181 | * @dev: the standard device structure to match against |
182 | * @drv: the standard driver structure containing the ids to match against |
183 | * |
184 | * Used by a driver to check whether a RIO device present in the |
185 | * system is in its list of supported devices. Returns 1 if |
186 | * there is a matching &struct rio_device_id or 0 if there is |
187 | * no match. |
188 | */ |
189 | static int rio_match_bus(struct device *dev, struct device_driver *drv) |
190 | { |
191 | struct rio_dev *rdev = to_rio_dev(dev); |
192 | struct rio_driver *rdrv = to_rio_driver(drv); |
193 | const struct rio_device_id *id = rdrv->id_table; |
194 | const struct rio_device_id *found_id; |
195 | |
196 | if (!id) |
197 | goto out; |
198 | |
199 | found_id = rio_match_device(id, rdev); |
200 | |
201 | if (found_id) |
202 | return 1; |
203 | |
204 | out:return 0; |
205 | } |
206 | |
207 | static int rio_uevent(const struct device *dev, struct kobj_uevent_env *env) |
208 | { |
209 | const struct rio_dev *rdev; |
210 | |
211 | if (!dev) |
212 | return -ENODEV; |
213 | |
214 | rdev = to_rio_dev(dev); |
215 | if (!rdev) |
216 | return -ENODEV; |
217 | |
218 | if (add_uevent_var(env, format: "MODALIAS=rapidio:v%04Xd%04Xav%04Xad%04X" , |
219 | rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did)) |
220 | return -ENOMEM; |
221 | return 0; |
222 | } |
223 | |
224 | struct class rio_mport_class = { |
225 | .name = "rapidio_port" , |
226 | .dev_groups = rio_mport_groups, |
227 | }; |
228 | EXPORT_SYMBOL_GPL(rio_mport_class); |
229 | |
230 | struct bus_type rio_bus_type = { |
231 | .name = "rapidio" , |
232 | .match = rio_match_bus, |
233 | .dev_groups = rio_dev_groups, |
234 | .bus_groups = rio_bus_groups, |
235 | .probe = rio_device_probe, |
236 | .remove = rio_device_remove, |
237 | .shutdown = rio_device_shutdown, |
238 | .uevent = rio_uevent, |
239 | }; |
240 | |
241 | /** |
242 | * rio_bus_init - Register the RapidIO bus with the device model |
243 | * |
244 | * Registers the RIO mport device class and RIO bus type with the Linux |
245 | * device model. |
246 | */ |
247 | static int __init rio_bus_init(void) |
248 | { |
249 | int ret; |
250 | |
251 | ret = class_register(class: &rio_mport_class); |
252 | if (!ret) { |
253 | ret = bus_register(bus: &rio_bus_type); |
254 | if (ret) |
255 | class_unregister(class: &rio_mport_class); |
256 | } |
257 | return ret; |
258 | } |
259 | |
260 | postcore_initcall(rio_bus_init); |
261 | |
262 | EXPORT_SYMBOL_GPL(rio_register_driver); |
263 | EXPORT_SYMBOL_GPL(rio_unregister_driver); |
264 | EXPORT_SYMBOL_GPL(rio_bus_type); |
265 | EXPORT_SYMBOL_GPL(rio_dev_get); |
266 | EXPORT_SYMBOL_GPL(rio_dev_put); |
267 | |