~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/message/i2o/driver.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 */
 
28
static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
 
29
module_param_named(max_drivers, i2o_max_drivers, uint, 0);
 
30
MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
 
31
 
 
32
/* I2O drivers lock and array */
 
33
static spinlock_t i2o_drivers_lock;
 
34
static 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
 */
 
46
static 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 */
 
62
struct bus_type i2o_bus_type = {
 
63
        .name = "i2o",
 
64
        .match = i2o_bus_match,
 
65
        .dev_attrs = i2o_device_attrs
 
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
 */
 
77
int 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(drv->name,
 
88
                                                   WQ_MEM_RECLAIM, 1);
 
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
                        return -EFAULT;
 
109
                }
 
110
 
 
111
        drv->context = i;
 
112
        i2o_drivers[i] = drv;
 
113
 
 
114
        spin_unlock_irqrestore(&i2o_drivers_lock, flags);
 
115
 
 
116
        osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
 
117
 
 
118
        list_for_each_entry(c, &i2o_controllers, list) {
 
119
                struct i2o_device *i2o_dev;
 
120
 
 
121
                i2o_driver_notify_controller_add(drv, c);
 
122
                list_for_each_entry(i2o_dev, &c->devices, list)
 
123
                    i2o_driver_notify_device_add(drv, i2o_dev);
 
124
        }
 
125
 
 
126
        rc = driver_register(&drv->driver);
 
127
        if (rc) {
 
128
                if (drv->event) {
 
129
                        destroy_workqueue(drv->event_queue);
 
130
                        drv->event_queue = NULL;
 
131
                }
 
132
        }
 
133
 
 
134
        return rc;
 
135
};
 
136
 
 
137
/**
 
138
 *      i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
 
139
 *      @drv: I2O driver which should be unregistered
 
140
 *
 
141
 *      Unregisters the OSM drv from the I2O core and cleanup event queues if
 
142
 *      necessary.
 
143
 */
 
144
void i2o_driver_unregister(struct i2o_driver *drv)
 
145
{
 
146
        struct i2o_controller *c;
 
147
        unsigned long flags;
 
148
 
 
149
        osm_debug("unregister driver %s\n", drv->name);
 
150
 
 
151
        driver_unregister(&drv->driver);
 
152
 
 
153
        list_for_each_entry(c, &i2o_controllers, list) {
 
154
                struct i2o_device *i2o_dev;
 
155
 
 
156
                list_for_each_entry(i2o_dev, &c->devices, list)
 
157
                    i2o_driver_notify_device_remove(drv, i2o_dev);
 
158
 
 
159
                i2o_driver_notify_controller_remove(drv, c);
 
160
        }
 
161
 
 
162
        spin_lock_irqsave(&i2o_drivers_lock, flags);
 
163
        i2o_drivers[drv->context] = NULL;
 
164
        spin_unlock_irqrestore(&i2o_drivers_lock, flags);
 
165
 
 
166
        if (drv->event_queue) {
 
167
                destroy_workqueue(drv->event_queue);
 
168
                drv->event_queue = NULL;
 
169
                osm_debug("event queue removed for %s\n", drv->name);
 
170
        }
 
171
};
 
172
 
 
173
/**
 
174
 *      i2o_driver_dispatch - dispatch an I2O reply message
 
175
 *      @c: I2O controller of the message
 
176
 *      @m: I2O message number
 
177
 *
 
178
 *      The reply is delivered to the driver from which the original message
 
179
 *      was. This function is only called from interrupt context.
 
180
 *
 
181
 *      Returns 0 on success and the message should not be flushed. Returns > 0
 
182
 *      on success and if the message should be flushed afterwords. Returns
 
183
 *      negative error code on failure (the message will be flushed too).
 
184
 */
 
185
int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
 
186
{
 
187
        struct i2o_driver *drv;
 
188
        struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
 
189
        u32 context = le32_to_cpu(msg->u.s.icntxt);
 
190
        unsigned long flags;
 
191
 
 
192
        if (unlikely(context >= i2o_max_drivers)) {
 
193
                osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
 
194
                         context);
 
195
                return -EIO;
 
196
        }
 
197
 
 
198
        spin_lock_irqsave(&i2o_drivers_lock, flags);
 
199
        drv = i2o_drivers[context];
 
200
        spin_unlock_irqrestore(&i2o_drivers_lock, flags);
 
201
 
 
202
        if (unlikely(!drv)) {
 
203
                osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
 
204
                         context);
 
205
                return -EIO;
 
206
        }
 
207
 
 
208
        if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
 
209
                struct i2o_device *dev, *tmp;
 
210
                struct i2o_event *evt;
 
211
                u16 size;
 
212
                u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
 
213
 
 
214
                osm_debug("event received from device %d\n", tid);
 
215
 
 
216
                if (!drv->event)
 
217
                        return -EIO;
 
218
 
 
219
                /* cut of header from message size (in 32-bit words) */
 
220
                size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
 
221
 
 
222
                evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
 
223
                if (!evt)
 
224
                        return -ENOMEM;
 
225
 
 
226
                evt->size = size;
 
227
                evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
 
228
                evt->event_indicator = le32_to_cpu(msg->body[0]);
 
229
                memcpy(&evt->data, &msg->body[1], size * 4);
 
230
 
 
231
                list_for_each_entry_safe(dev, tmp, &c->devices, list)
 
232
                    if (dev->lct_data.tid == tid) {
 
233
                        evt->i2o_dev = dev;
 
234
                        break;
 
235
                }
 
236
 
 
237
                INIT_WORK(&evt->work, drv->event);
 
238
                queue_work(drv->event_queue, &evt->work);
 
239
                return 1;
 
240
        }
 
241
 
 
242
        if (unlikely(!drv->reply)) {
 
243
                osm_debug("%s: Reply to driver %s, but no reply function"
 
244
                          " defined!\n", c->name, drv->name);
 
245
                return -EIO;
 
246
        }
 
247
 
 
248
        return drv->reply(c, m, msg);
 
249
}
 
250
 
 
251
/**
 
252
 *      i2o_driver_notify_controller_add_all - Send notify of added controller
 
253
 *      @c: newly added controller
 
254
 *
 
255
 *      Send notifications to all registered drivers that a new controller was
 
256
 *      added.
 
257
 */
 
258
void i2o_driver_notify_controller_add_all(struct i2o_controller *c)
 
259
{
 
260
        int i;
 
261
        struct i2o_driver *drv;
 
262
 
 
263
        for (i = 0; i < i2o_max_drivers; i++) {
 
264
                drv = i2o_drivers[i];
 
265
 
 
266
                if (drv)
 
267
                        i2o_driver_notify_controller_add(drv, c);
 
268
        }
 
269
}
 
270
 
 
271
/**
 
272
 *      i2o_driver_notify_controller_remove_all - Send notify of removed controller
 
273
 *      @c: controller that is being removed
 
274
 *
 
275
 *      Send notifications to all registered drivers that a controller was
 
276
 *      removed.
 
277
 */
 
278
void i2o_driver_notify_controller_remove_all(struct i2o_controller *c)
 
279
{
 
280
        int i;
 
281
        struct i2o_driver *drv;
 
282
 
 
283
        for (i = 0; i < i2o_max_drivers; i++) {
 
284
                drv = i2o_drivers[i];
 
285
 
 
286
                if (drv)
 
287
                        i2o_driver_notify_controller_remove(drv, c);
 
288
        }
 
289
}
 
290
 
 
291
/**
 
292
 *      i2o_driver_notify_device_add_all - Send notify of added device
 
293
 *      @i2o_dev: newly added I2O device
 
294
 *
 
295
 *      Send notifications to all registered drivers that a device was added.
 
296
 */
 
297
void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev)
 
298
{
 
299
        int i;
 
300
        struct i2o_driver *drv;
 
301
 
 
302
        for (i = 0; i < i2o_max_drivers; i++) {
 
303
                drv = i2o_drivers[i];
 
304
 
 
305
                if (drv)
 
306
                        i2o_driver_notify_device_add(drv, i2o_dev);
 
307
        }
 
308
}
 
309
 
 
310
/**
 
311
 *      i2o_driver_notify_device_remove_all - Send notify of removed device
 
312
 *      @i2o_dev: device that is being removed
 
313
 *
 
314
 *      Send notifications to all registered drivers that a device was removed.
 
315
 */
 
316
void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev)
 
317
{
 
318
        int i;
 
319
        struct i2o_driver *drv;
 
320
 
 
321
        for (i = 0; i < i2o_max_drivers; i++) {
 
322
                drv = i2o_drivers[i];
 
323
 
 
324
                if (drv)
 
325
                        i2o_driver_notify_device_remove(drv, i2o_dev);
 
326
        }
 
327
}
 
328
 
 
329
/**
 
330
 *      i2o_driver_init - initialize I2O drivers (OSMs)
 
331
 *
 
332
 *      Registers the I2O bus and allocate memory for the array of OSMs.
 
333
 *
 
334
 *      Returns 0 on success or negative error code on failure.
 
335
 */
 
336
int __init i2o_driver_init(void)
 
337
{
 
338
        int rc = 0;
 
339
 
 
340
        spin_lock_init(&i2o_drivers_lock);
 
341
 
 
342
        if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) {
 
343
                osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n",
 
344
                         i2o_max_drivers);
 
345
                i2o_max_drivers = I2O_MAX_DRIVERS;
 
346
        }
 
347
        osm_info("max drivers = %d\n", i2o_max_drivers);
 
348
 
 
349
        i2o_drivers =
 
350
            kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL);
 
351
        if (!i2o_drivers)
 
352
                return -ENOMEM;
 
353
 
 
354
        rc = bus_register(&i2o_bus_type);
 
355
 
 
356
        if (rc < 0)
 
357
                kfree(i2o_drivers);
 
358
 
 
359
        return rc;
 
360
};
 
361
 
 
362
/**
 
363
 *      i2o_driver_exit - clean up I2O drivers (OSMs)
 
364
 *
 
365
 *      Unregisters the I2O bus and frees driver array.
 
366
 */
 
367
void i2o_driver_exit(void)
 
368
{
 
369
        bus_unregister(&i2o_bus_type);
 
370
        kfree(i2o_drivers);
 
371
};
 
372
 
 
373
EXPORT_SYMBOL(i2o_driver_register);
 
374
EXPORT_SYMBOL(i2o_driver_unregister);
 
375
EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
 
376
EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
 
377
EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
 
378
EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);