aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/i2o/driver.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2015-02-03 08:18:55 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-02-03 18:58:39 -0500
commit2cbf7fe2d5d32a4747c1f8ad163e886dccad930c (patch)
tree9d7c6d230459353a94d074271e57ba4f7488a4c9 /drivers/message/i2o/driver.c
parent178cf7de6f1d3b95407f5a76af249fc924d42576 (diff)
i2o: move to staging
The I2O layer deals with a technology that to say the least didn't catch on in the market. The only relevant products are some of the AMI MegaRAID - which supported I2O and its native mode (The native mode is faster and runs on Linux), an obscure crypto ethernet card that's now so many years out of date nobody would use it, the old DPT controllers, which speak their own dialect and have their own driver - and ermm.. thats about it. We also know the code isn't in good shape as recently a patch was proposed and queried as buggy, which in turn showed the existing code was broken already by prior "clean up" and nobody had noticed that either. It's coding style robot code nothing more. Like some forgotten corridor cleaned relentlessly by a lost Roomba but where no user has trodden in years. Move it to staging and then to /dev/null. The headers remain as they are shared with dpt_i2o. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/message/i2o/driver.c')
-rw-r--r--drivers/message/i2o/driver.c382
1 files changed, 0 insertions, 382 deletions
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
deleted file mode 100644
index 1b18a0d1d05b..000000000000
--- a/drivers/message/i2o/driver.c
+++ /dev/null
@@ -1,382 +0,0 @@
1/*
2 * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
3 *
4 * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Fixes/additions:
12 * Markus Lidel <Markus.Lidel@shadowconnect.com>
13 * initial version.
14 */
15
16#include <linux/device.h>
17#include <linux/module.h>
18#include <linux/rwsem.h>
19#include <linux/i2o.h>
20#include <linux/workqueue.h>
21#include <linux/string.h>
22#include <linux/slab.h>
23#include "core.h"
24
25#define OSM_NAME "i2o"
26
27/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
28static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
29module_param_named(max_drivers, i2o_max_drivers, uint, 0);
30MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
31
32/* I2O drivers lock and array */
33static spinlock_t i2o_drivers_lock;
34static struct i2o_driver **i2o_drivers;
35
36/**
37 * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM)
38 * @dev: device which should be verified
39 * @drv: the driver to match against
40 *
41 * Used by the bus to check if the driver wants to handle the device.
42 *
43 * Returns 1 if the class ids of the driver match the class id of the
44 * device, otherwise 0.
45 */
46static int i2o_bus_match(struct device *dev, struct device_driver *drv)
47{
48 struct i2o_device *i2o_dev = to_i2o_device(dev);
49 struct i2o_driver *i2o_drv = to_i2o_driver(drv);
50 struct i2o_class_id *ids = i2o_drv->classes;
51
52 if (ids)
53 while (ids->class_id != I2O_CLASS_END) {
54 if (ids->class_id == i2o_dev->lct_data.class_id)
55 return 1;
56 ids++;
57 }
58 return 0;
59};
60
61/* I2O bus type */
62struct bus_type i2o_bus_type = {
63 .name = "i2o",
64 .match = i2o_bus_match,
65 .dev_groups = i2o_device_groups,
66};
67
68/**
69 * i2o_driver_register - Register a I2O driver (OSM) in the I2O core
70 * @drv: I2O driver which should be registered
71 *
72 * Registers the OSM drv in the I2O core and creates an event queues if
73 * necessary.
74 *
75 * Returns 0 on success or negative error code on failure.
76 */
77int i2o_driver_register(struct i2o_driver *drv)
78{
79 struct i2o_controller *c;
80 int i;
81 int rc = 0;
82 unsigned long flags;
83
84 osm_debug("Register driver %s\n", drv->name);
85
86 if (drv->event) {
87 drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1,
88 drv->name);
89 if (!drv->event_queue) {
90 osm_err("Could not initialize event queue for driver "
91 "%s\n", drv->name);
92 return -EFAULT;
93 }
94 osm_debug("Event queue initialized for driver %s\n", drv->name);
95 } else
96 drv->event_queue = NULL;
97
98 drv->driver.name = drv->name;
99 drv->driver.bus = &i2o_bus_type;
100
101 spin_lock_irqsave(&i2o_drivers_lock, flags);
102
103 for (i = 0; i2o_drivers[i]; i++)
104 if (i >= i2o_max_drivers) {
105 osm_err("too many drivers registered, increase "
106 "max_drivers\n");
107 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
108 rc = -EFAULT;
109 goto out;
110 }
111
112 drv->context = i;
113 i2o_drivers[i] = drv;
114
115 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
116
117 osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
118
119 list_for_each_entry(c, &i2o_controllers, list) {
120 struct i2o_device *i2o_dev;
121
122 i2o_driver_notify_controller_add(drv, c);
123 list_for_each_entry(i2o_dev, &c->devices, list)
124 i2o_driver_notify_device_add(drv, i2o_dev);
125 }
126
127 rc = driver_register(&drv->driver);
128 if (rc)
129 goto out;
130
131 return 0;
132out:
133 if (drv->event_queue) {
134 destroy_workqueue(drv->event_queue);
135 drv->event_queue = NULL;
136 }
137
138 return rc;
139};
140
141/**
142 * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
143 * @drv: I2O driver which should be unregistered
144 *
145 * Unregisters the OSM drv from the I2O core and cleanup event queues if
146 * necessary.
147 */
148void i2o_driver_unregister(struct i2o_driver *drv)
149{
150 struct i2o_controller *c;
151 unsigned long flags;
152
153 osm_debug("unregister driver %s\n", drv->name);
154
155 driver_unregister(&drv->driver);
156
157 list_for_each_entry(c, &i2o_controllers, list) {
158 struct i2o_device *i2o_dev;
159
160 list_for_each_entry(i2o_dev, &c->devices, list)
161 i2o_driver_notify_device_remove(drv, i2o_dev);
162
163 i2o_driver_notify_controller_remove(drv, c);
164 }
165
166 spin_lock_irqsave(&i2o_drivers_lock, flags);
167 i2o_drivers[drv->context] = NULL;
168 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
169
170 if (drv->event_queue) {
171 destroy_workqueue(drv->event_queue);
172 drv->event_queue = NULL;
173 osm_debug("event queue removed for %s\n", drv->name);
174 }
175};
176
177/**
178 * i2o_driver_dispatch - dispatch an I2O reply message
179 * @c: I2O controller of the message
180 * @m: I2O message number
181 *
182 * The reply is delivered to the driver from which the original message
183 * was. This function is only called from interrupt context.
184 *
185 * Returns 0 on success and the message should not be flushed. Returns > 0
186 * on success and if the message should be flushed afterwords. Returns
187 * negative error code on failure (the message will be flushed too).
188 */
189int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
190{
191 struct i2o_driver *drv;
192 struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
193 u32 context = le32_to_cpu(msg->u.s.icntxt);
194 unsigned long flags;
195
196 if (unlikely(context >= i2o_max_drivers)) {
197 osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
198 context);
199 return -EIO;
200 }
201
202 spin_lock_irqsave(&i2o_drivers_lock, flags);
203 drv = i2o_drivers[context];
204 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
205
206 if (unlikely(!drv)) {
207 osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
208 context);
209 return -EIO;
210 }
211
212 if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
213 struct i2o_device *dev, *tmp;
214 struct i2o_event *evt;
215 u16 size;
216 u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
217
218 osm_debug("event received from device %d\n", tid);
219
220 if (!drv->event)
221 return -EIO;
222
223 /* cut of header from message size (in 32-bit words) */
224 size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
225
226 evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
227 if (!evt)
228 return -ENOMEM;
229
230 evt->size = size;
231 evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
232 evt->event_indicator = le32_to_cpu(msg->body[0]);
233 memcpy(&evt->data, &msg->body[1], size * 4);
234
235 list_for_each_entry_safe(dev, tmp, &c->devices, list)
236 if (dev->lct_data.tid == tid) {
237 evt->i2o_dev = dev;
238 break;
239 }
240
241 INIT_WORK(&evt->work, drv->event);
242 queue_work(drv->event_queue, &evt->work);
243 return 1;
244 }
245
246 if (unlikely(!drv->reply)) {
247 osm_debug("%s: Reply to driver %s, but no reply function"
248 " defined!\n", c->name, drv->name);
249 return -EIO;
250 }
251
252 return drv->reply(c, m, msg);
253}
254
255/**
256 * i2o_driver_notify_controller_add_all - Send notify of added controller
257 * @c: newly added controller
258 *
259 * Send notifications to all registered drivers that a new controller was
260 * added.
261 */
262void i2o_driver_notify_controller_add_all(struct i2o_controller *c)
263{
264 int i;
265 struct i2o_driver *drv;
266
267 for (i = 0; i < i2o_max_drivers; i++) {
268 drv = i2o_drivers[i];
269
270 if (drv)
271 i2o_driver_notify_controller_add(drv, c);
272 }
273}
274
275/**
276 * i2o_driver_notify_controller_remove_all - Send notify of removed controller
277 * @c: controller that is being removed
278 *
279 * Send notifications to all registered drivers that a controller was
280 * removed.
281 */
282void i2o_driver_notify_controller_remove_all(struct i2o_controller *c)
283{
284 int i;
285 struct i2o_driver *drv;
286
287 for (i = 0; i < i2o_max_drivers; i++) {
288 drv = i2o_drivers[i];
289
290 if (drv)
291 i2o_driver_notify_controller_remove(drv, c);
292 }
293}
294
295/**
296 * i2o_driver_notify_device_add_all - Send notify of added device
297 * @i2o_dev: newly added I2O device
298 *
299 * Send notifications to all registered drivers that a device was added.
300 */
301void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev)
302{
303 int i;
304 struct i2o_driver *drv;
305
306 for (i = 0; i < i2o_max_drivers; i++) {
307 drv = i2o_drivers[i];
308
309 if (drv)
310 i2o_driver_notify_device_add(drv, i2o_dev);
311 }
312}
313
314/**
315 * i2o_driver_notify_device_remove_all - Send notify of removed device
316 * @i2o_dev: device that is being removed
317 *
318 * Send notifications to all registered drivers that a device was removed.
319 */
320void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev)
321{
322 int i;
323 struct i2o_driver *drv;
324
325 for (i = 0; i < i2o_max_drivers; i++) {
326 drv = i2o_drivers[i];
327
328 if (drv)
329 i2o_driver_notify_device_remove(drv, i2o_dev);
330 }
331}
332
333/**
334 * i2o_driver_init - initialize I2O drivers (OSMs)
335 *
336 * Registers the I2O bus and allocate memory for the array of OSMs.
337 *
338 * Returns 0 on success or negative error code on failure.
339 */
340int __init i2o_driver_init(void)
341{
342 int rc = 0;
343
344 spin_lock_init(&i2o_drivers_lock);
345
346 if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) {
347 osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n",
348 i2o_max_drivers);
349 i2o_max_drivers = I2O_MAX_DRIVERS;
350 }
351 osm_info("max drivers = %d\n", i2o_max_drivers);
352
353 i2o_drivers =
354 kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL);
355 if (!i2o_drivers)
356 return -ENOMEM;
357
358 rc = bus_register(&i2o_bus_type);
359
360 if (rc < 0)
361 kfree(i2o_drivers);
362
363 return rc;
364};
365
366/**
367 * i2o_driver_exit - clean up I2O drivers (OSMs)
368 *
369 * Unregisters the I2O bus and frees driver array.
370 */
371void i2o_driver_exit(void)
372{
373 bus_unregister(&i2o_bus_type);
374 kfree(i2o_drivers);
375};
376
377EXPORT_SYMBOL(i2o_driver_register);
378EXPORT_SYMBOL(i2o_driver_unregister);
379EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
380EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
381EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
382EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);