diff options
author | Matt Porter <mporter@kernel.crashing.org> | 2005-11-07 04:00:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 10:53:46 -0500 |
commit | 394b701ce4fbfde919a9bcbf84cb4820a7c6d47c (patch) | |
tree | a397fff4043a9810e753fb81224349bd36db45b8 /drivers/rapidio/rio-driver.c | |
parent | d217d5450f11d8c907c0458d175b0dc999b4d06d (diff) |
[PATCH] RapidIO support: core base
Adds a RapidIO subsystem to the kernel. RIO is a switched fabric interconnect
used in higher-end embedded applications. The curious can look at the specs
over at http://www.rapidio.org
The core code implements enumeration/discovery, management of
devices/resources, and interfaces for RIO drivers.
There's a lot more to do to take advantages of all the hardware features.
However, this should provide a good base for folks with RIO hardware to start
contributing.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/rapidio/rio-driver.c')
-rw-r--r-- | drivers/rapidio/rio-driver.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c new file mode 100644 index 000000000000..dc749609699a --- /dev/null +++ b/drivers/rapidio/rio-driver.c | |||
@@ -0,0 +1,229 @@ | |||
1 | /* | ||
2 | * RapidIO driver support | ||
3 | * | ||
4 | * Copyright 2005 MontaVista Software, Inc. | ||
5 | * Matt Porter <mporter@kernel.crashing.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/rio.h> | ||
16 | #include <linux/rio_ids.h> | ||
17 | |||
18 | #include "rio.h" | ||
19 | |||
20 | /** | ||
21 | * rio_match_device - Tell if a RIO device has a matching RIO device id structure | ||
22 | * @id: the RIO device id structure to match against | ||
23 | * @rdev: the RIO device structure to match against | ||
24 | * | ||
25 | * Used from driver probe and bus matching to check whether a RIO device | ||
26 | * matches a device id structure provided by a RIO driver. Returns the | ||
27 | * matching &struct rio_device_id or %NULL if there is no match. | ||
28 | */ | ||
29 | static const struct rio_device_id *rio_match_device(const struct rio_device_id | ||
30 | *id, | ||
31 | const struct rio_dev *rdev) | ||
32 | { | ||
33 | while (id->vid || id->asm_vid) { | ||
34 | if (((id->vid == RIO_ANY_ID) || (id->vid == rdev->vid)) && | ||
35 | ((id->did == RIO_ANY_ID) || (id->did == rdev->did)) && | ||
36 | ((id->asm_vid == RIO_ANY_ID) | ||
37 | || (id->asm_vid == rdev->asm_vid)) | ||
38 | && ((id->asm_did == RIO_ANY_ID) | ||
39 | || (id->asm_did == rdev->asm_did))) | ||
40 | return id; | ||
41 | id++; | ||
42 | } | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * rio_dev_get - Increments the reference count of the RIO device structure | ||
48 | * | ||
49 | * @rdev: RIO device being referenced | ||
50 | * | ||
51 | * Each live reference to a device should be refcounted. | ||
52 | * | ||
53 | * Drivers for RIO devices should normally record such references in | ||
54 | * their probe() methods, when they bind to a device, and release | ||
55 | * them by calling rio_dev_put(), in their disconnect() methods. | ||
56 | */ | ||
57 | struct rio_dev *rio_dev_get(struct rio_dev *rdev) | ||
58 | { | ||
59 | if (rdev) | ||
60 | get_device(&rdev->dev); | ||
61 | |||
62 | return rdev; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * rio_dev_put - Release a use of the RIO device structure | ||
67 | * | ||
68 | * @rdev: RIO device being disconnected | ||
69 | * | ||
70 | * Must be called when a user of a device is finished with it. | ||
71 | * When the last user of the device calls this function, the | ||
72 | * memory of the device is freed. | ||
73 | */ | ||
74 | void rio_dev_put(struct rio_dev *rdev) | ||
75 | { | ||
76 | if (rdev) | ||
77 | put_device(&rdev->dev); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * rio_device_probe - Tell if a RIO device structure has a matching RIO | ||
82 | * device id structure | ||
83 | * @id: the RIO device id structure to match against | ||
84 | * @dev: the RIO device structure to match against | ||
85 | * | ||
86 | * return 0 and set rio_dev->driver when drv claims rio_dev, else error | ||
87 | */ | ||
88 | static int rio_device_probe(struct device *dev) | ||
89 | { | ||
90 | struct rio_driver *rdrv = to_rio_driver(dev->driver); | ||
91 | struct rio_dev *rdev = to_rio_dev(dev); | ||
92 | int error = -ENODEV; | ||
93 | const struct rio_device_id *id; | ||
94 | |||
95 | if (!rdev->driver && rdrv->probe) { | ||
96 | if (!rdrv->id_table) | ||
97 | return error; | ||
98 | id = rio_match_device(rdrv->id_table, rdev); | ||
99 | rio_dev_get(rdev); | ||
100 | if (id) | ||
101 | error = rdrv->probe(rdev, id); | ||
102 | if (error >= 0) { | ||
103 | rdev->driver = rdrv; | ||
104 | error = 0; | ||
105 | rio_dev_put(rdev); | ||
106 | } | ||
107 | } | ||
108 | return error; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * rio_device_remove - Remove a RIO device from the system | ||
113 | * | ||
114 | * @dev: the RIO device structure to match against | ||
115 | * | ||
116 | * Remove a RIO device from the system. If it has an associated | ||
117 | * driver, then run the driver remove() method. Then update | ||
118 | * the reference count. | ||
119 | */ | ||
120 | static int rio_device_remove(struct device *dev) | ||
121 | { | ||
122 | struct rio_dev *rdev = to_rio_dev(dev); | ||
123 | struct rio_driver *rdrv = rdev->driver; | ||
124 | |||
125 | if (rdrv) { | ||
126 | if (rdrv->remove) | ||
127 | rdrv->remove(rdev); | ||
128 | rdev->driver = NULL; | ||
129 | } | ||
130 | |||
131 | rio_dev_put(rdev); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * rio_register_driver - register a new RIO driver | ||
138 | * @rdrv: the RIO driver structure to register | ||
139 | * | ||
140 | * Adds a &struct rio_driver to the list of registered drivers | ||
141 | * Returns a negative value on error, otherwise 0. If no error | ||
142 | * occurred, the driver remains registered even if no device | ||
143 | * was claimed during registration. | ||
144 | */ | ||
145 | int rio_register_driver(struct rio_driver *rdrv) | ||
146 | { | ||
147 | /* initialize common driver fields */ | ||
148 | rdrv->driver.name = rdrv->name; | ||
149 | rdrv->driver.bus = &rio_bus_type; | ||
150 | rdrv->driver.probe = rio_device_probe; | ||
151 | rdrv->driver.remove = rio_device_remove; | ||
152 | |||
153 | /* register with core */ | ||
154 | return driver_register(&rdrv->driver); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * rio_unregister_driver - unregister a RIO driver | ||
159 | * @rdrv: the RIO driver structure to unregister | ||
160 | * | ||
161 | * Deletes the &struct rio_driver from the list of registered RIO | ||
162 | * drivers, gives it a chance to clean up by calling its remove() | ||
163 | * function for each device it was responsible for, and marks those | ||
164 | * devices as driverless. | ||
165 | */ | ||
166 | void rio_unregister_driver(struct rio_driver *rdrv) | ||
167 | { | ||
168 | driver_unregister(&rdrv->driver); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * rio_match_bus - Tell if a RIO device structure has a matching RIO | ||
173 | * driver device id structure | ||
174 | * @dev: the standard device structure to match against | ||
175 | * @drv: the standard driver structure containing the ids to match against | ||
176 | * | ||
177 | * Used by a driver to check whether a RIO device present in the | ||
178 | * system is in its list of supported devices. Returns 1 if | ||
179 | * there is a matching &struct rio_device_id or 0 if there is | ||
180 | * no match. | ||
181 | */ | ||
182 | static int rio_match_bus(struct device *dev, struct device_driver *drv) | ||
183 | { | ||
184 | struct rio_dev *rdev = to_rio_dev(dev); | ||
185 | struct rio_driver *rdrv = to_rio_driver(drv); | ||
186 | const struct rio_device_id *id = rdrv->id_table; | ||
187 | const struct rio_device_id *found_id; | ||
188 | |||
189 | if (!id) | ||
190 | goto out; | ||
191 | |||
192 | found_id = rio_match_device(id, rdev); | ||
193 | |||
194 | if (found_id) | ||
195 | return 1; | ||
196 | |||
197 | out:return 0; | ||
198 | } | ||
199 | |||
200 | static struct device rio_bus = { | ||
201 | .bus_id = "rapidio", | ||
202 | }; | ||
203 | |||
204 | struct bus_type rio_bus_type = { | ||
205 | .name = "rapidio", | ||
206 | .match = rio_match_bus, | ||
207 | .dev_attrs = rio_dev_attrs | ||
208 | }; | ||
209 | |||
210 | /** | ||
211 | * rio_bus_init - Register the RapidIO bus with the device model | ||
212 | * | ||
213 | * Registers the RIO bus device and RIO bus type with the Linux | ||
214 | * device model. | ||
215 | */ | ||
216 | static int __init rio_bus_init(void) | ||
217 | { | ||
218 | if (device_register(&rio_bus) < 0) | ||
219 | printk("RIO: failed to register RIO bus device\n"); | ||
220 | return bus_register(&rio_bus_type); | ||
221 | } | ||
222 | |||
223 | postcore_initcall(rio_bus_init); | ||
224 | |||
225 | EXPORT_SYMBOL_GPL(rio_register_driver); | ||
226 | EXPORT_SYMBOL_GPL(rio_unregister_driver); | ||
227 | EXPORT_SYMBOL_GPL(rio_bus_type); | ||
228 | EXPORT_SYMBOL_GPL(rio_dev_get); | ||
229 | EXPORT_SYMBOL_GPL(rio_dev_put); | ||