]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Functions to handle I2O controllers and I2O message handling | |
3 | * | |
4 | * Copyright (C) 1999-2002 Red Hat Software | |
5 | * | |
6 | * Written by Alan Cox, Building Number Three Ltd | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. | |
12 | * | |
13 | * A lot of the I2O message side code from this is taken from the | |
14 | * Red Creek RCPCI45 adapter driver by Red Creek Communications | |
15 | * | |
16 | * Fixes/additions: | |
17 | * Philipp Rumpf | |
96de0e25 JE |
18 | * Juha Sievänen <[email protected]> |
19 | * Auvo Häkkinen <[email protected]> | |
1da177e4 LT |
20 | * Deepak Saxena <[email protected]> |
21 | * Boji T Kannanthanam <[email protected]> | |
22 | * Alan Cox <[email protected]>: | |
23 | * Ported to Linux 2.5. | |
24 | * Markus Lidel <[email protected]>: | |
25 | * Minor fixes for 2.6. | |
26 | */ | |
27 | ||
28 | #include <linux/module.h> | |
29 | #include <linux/i2o.h> | |
30 | #include <linux/delay.h> | |
4e57b681 | 31 | #include <linux/sched.h> |
9e87545f | 32 | #include "core.h" |
1da177e4 | 33 | |
9e87545f | 34 | #define OSM_NAME "i2o" |
f6ed39a6 | 35 | #define OSM_VERSION "1.325" |
1da177e4 LT |
36 | #define OSM_DESCRIPTION "I2O subsystem" |
37 | ||
38 | /* global I2O controller list */ | |
39 | LIST_HEAD(i2o_controllers); | |
40 | ||
41 | /* | |
42 | * global I2O System Table. Contains information about all the IOPs in the | |
43 | * system. Used to inform IOPs about each others existence. | |
44 | */ | |
45 | static struct i2o_dma i2o_systab; | |
46 | ||
47 | static int i2o_hrt_get(struct i2o_controller *c); | |
48 | ||
1da177e4 LT |
49 | /** |
50 | * i2o_msg_get_wait - obtain an I2O message from the IOP | |
51 | * @c: I2O controller | |
52 | * @msg: pointer to a I2O message pointer | |
53 | * @wait: how long to wait until timeout | |
54 | * | |
55 | * This function waits up to wait seconds for a message slot to be | |
56 | * available. | |
57 | * | |
58 | * On a success the message is returned and the pointer to the message is | |
59 | * set in msg. The returned message is the physical page frame offset | |
60 | * address from the read port (see the i2o spec). If no message is | |
61 | * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. | |
62 | */ | |
a1a5ea70 | 63 | struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) |
1da177e4 LT |
64 | { |
65 | unsigned long timeout = jiffies + wait * HZ; | |
a1a5ea70 | 66 | struct i2o_message *msg; |
1da177e4 | 67 | |
a1a5ea70 | 68 | while (IS_ERR(msg = i2o_msg_get(c))) { |
1da177e4 | 69 | if (time_after(jiffies, timeout)) { |
9e87545f ML |
70 | osm_debug("%s: Timeout waiting for message frame.\n", |
71 | c->name); | |
a1a5ea70 | 72 | return ERR_PTR(-ETIMEDOUT); |
1da177e4 | 73 | } |
6521018d | 74 | schedule_timeout_uninterruptible(1); |
1da177e4 LT |
75 | } |
76 | ||
a1a5ea70 | 77 | return msg; |
1da177e4 LT |
78 | }; |
79 | ||
80 | #if BITS_PER_LONG == 64 | |
81 | /** | |
82 | * i2o_cntxt_list_add - Append a pointer to context list and return a id | |
83 | * @c: controller to which the context list belong | |
84 | * @ptr: pointer to add to the context list | |
85 | * | |
86 | * Because the context field in I2O is only 32-bit large, on 64-bit the | |
87 | * pointer is to large to fit in the context field. The i2o_cntxt_list | |
88 | * functions therefore map pointers to context fields. | |
89 | * | |
90 | * Returns context id > 0 on success or 0 on failure. | |
91 | */ | |
92 | u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) | |
93 | { | |
94 | struct i2o_context_list_element *entry; | |
95 | unsigned long flags; | |
96 | ||
97 | if (!ptr) | |
f33213ec ML |
98 | osm_err("%s: couldn't add NULL pointer to context list!\n", |
99 | c->name); | |
1da177e4 LT |
100 | |
101 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); | |
102 | if (!entry) { | |
f33213ec ML |
103 | osm_err("%s: Could not allocate memory for context list element" |
104 | "\n", c->name); | |
1da177e4 LT |
105 | return 0; |
106 | } | |
107 | ||
108 | entry->ptr = ptr; | |
109 | entry->timestamp = jiffies; | |
110 | INIT_LIST_HEAD(&entry->list); | |
111 | ||
112 | spin_lock_irqsave(&c->context_list_lock, flags); | |
113 | ||
114 | if (unlikely(atomic_inc_and_test(&c->context_list_counter))) | |
115 | atomic_inc(&c->context_list_counter); | |
116 | ||
117 | entry->context = atomic_read(&c->context_list_counter); | |
118 | ||
119 | list_add(&entry->list, &c->context_list); | |
120 | ||
121 | spin_unlock_irqrestore(&c->context_list_lock, flags); | |
122 | ||
f33213ec | 123 | osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); |
1da177e4 LT |
124 | |
125 | return entry->context; | |
126 | }; | |
127 | ||
128 | /** | |
129 | * i2o_cntxt_list_remove - Remove a pointer from the context list | |
130 | * @c: controller to which the context list belong | |
131 | * @ptr: pointer which should be removed from the context list | |
132 | * | |
133 | * Removes a previously added pointer from the context list and returns | |
134 | * the matching context id. | |
135 | * | |
136 | * Returns context id on succes or 0 on failure. | |
137 | */ | |
138 | u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) | |
139 | { | |
140 | struct i2o_context_list_element *entry; | |
141 | u32 context = 0; | |
142 | unsigned long flags; | |
143 | ||
144 | spin_lock_irqsave(&c->context_list_lock, flags); | |
145 | list_for_each_entry(entry, &c->context_list, list) | |
146 | if (entry->ptr == ptr) { | |
147 | list_del(&entry->list); | |
148 | context = entry->context; | |
149 | kfree(entry); | |
150 | break; | |
151 | } | |
152 | spin_unlock_irqrestore(&c->context_list_lock, flags); | |
153 | ||
154 | if (!context) | |
f33213ec ML |
155 | osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, |
156 | ptr); | |
1da177e4 | 157 | |
f33213ec ML |
158 | osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, |
159 | context, ptr); | |
1da177e4 LT |
160 | |
161 | return context; | |
162 | }; | |
163 | ||
164 | /** | |
165 | * i2o_cntxt_list_get - Get a pointer from the context list and remove it | |
166 | * @c: controller to which the context list belong | |
167 | * @context: context id to which the pointer belong | |
168 | * | |
169 | * Returns pointer to the matching context id on success or NULL on | |
170 | * failure. | |
171 | */ | |
172 | void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) | |
173 | { | |
174 | struct i2o_context_list_element *entry; | |
175 | unsigned long flags; | |
176 | void *ptr = NULL; | |
177 | ||
178 | spin_lock_irqsave(&c->context_list_lock, flags); | |
179 | list_for_each_entry(entry, &c->context_list, list) | |
180 | if (entry->context == context) { | |
181 | list_del(&entry->list); | |
182 | ptr = entry->ptr; | |
183 | kfree(entry); | |
184 | break; | |
185 | } | |
186 | spin_unlock_irqrestore(&c->context_list_lock, flags); | |
187 | ||
188 | if (!ptr) | |
f33213ec | 189 | osm_warn("%s: context id %d not found\n", c->name, context); |
1da177e4 | 190 | |
f33213ec ML |
191 | osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, |
192 | ptr); | |
1da177e4 LT |
193 | |
194 | return ptr; | |
195 | }; | |
196 | ||
197 | /** | |
198 | * i2o_cntxt_list_get_ptr - Get a context id from the context list | |
199 | * @c: controller to which the context list belong | |
200 | * @ptr: pointer to which the context id should be fetched | |
201 | * | |
202 | * Returns context id which matches to the pointer on succes or 0 on | |
203 | * failure. | |
204 | */ | |
205 | u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) | |
206 | { | |
207 | struct i2o_context_list_element *entry; | |
208 | u32 context = 0; | |
209 | unsigned long flags; | |
210 | ||
211 | spin_lock_irqsave(&c->context_list_lock, flags); | |
212 | list_for_each_entry(entry, &c->context_list, list) | |
213 | if (entry->ptr == ptr) { | |
214 | context = entry->context; | |
215 | break; | |
216 | } | |
217 | spin_unlock_irqrestore(&c->context_list_lock, flags); | |
218 | ||
219 | if (!context) | |
f33213ec ML |
220 | osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, |
221 | ptr); | |
1da177e4 | 222 | |
f33213ec ML |
223 | osm_debug("%s: get context id from context list %p -> %d\n", c->name, |
224 | ptr, context); | |
1da177e4 LT |
225 | |
226 | return context; | |
227 | }; | |
228 | #endif | |
229 | ||
230 | /** | |
231 | * i2o_iop_find - Find an I2O controller by id | |
232 | * @unit: unit number of the I2O controller to search for | |
233 | * | |
234 | * Lookup the I2O controller on the controller list. | |
235 | * | |
236 | * Returns pointer to the I2O controller on success or NULL if not found. | |
237 | */ | |
238 | struct i2o_controller *i2o_find_iop(int unit) | |
239 | { | |
240 | struct i2o_controller *c; | |
241 | ||
242 | list_for_each_entry(c, &i2o_controllers, list) { | |
243 | if (c->unit == unit) | |
244 | return c; | |
245 | } | |
246 | ||
247 | return NULL; | |
248 | }; | |
249 | ||
250 | /** | |
251 | * i2o_iop_find_device - Find a I2O device on an I2O controller | |
252 | * @c: I2O controller where the I2O device hangs on | |
253 | * @tid: TID of the I2O device to search for | |
254 | * | |
255 | * Searches the devices of the I2O controller for a device with TID tid and | |
256 | * returns it. | |
257 | * | |
258 | * Returns a pointer to the I2O device if found, otherwise NULL. | |
259 | */ | |
260 | struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) | |
261 | { | |
262 | struct i2o_device *dev; | |
263 | ||
264 | list_for_each_entry(dev, &c->devices, list) | |
265 | if (dev->lct_data.tid == tid) | |
266 | return dev; | |
267 | ||
268 | return NULL; | |
269 | }; | |
270 | ||
271 | /** | |
272 | * i2o_quiesce_controller - quiesce controller | |
273 | * @c: controller | |
274 | * | |
275 | * Quiesce an IOP. Causes IOP to make external operation quiescent | |
276 | * (i2o 'READY' state). Internal operation of the IOP continues normally. | |
277 | * | |
278 | * Returns 0 on success or negative error code on failure. | |
279 | */ | |
280 | static int i2o_iop_quiesce(struct i2o_controller *c) | |
281 | { | |
a1a5ea70 | 282 | struct i2o_message *msg; |
1da177e4 LT |
283 | i2o_status_block *sb = c->status_block.virt; |
284 | int rc; | |
285 | ||
286 | i2o_status_get(c); | |
287 | ||
288 | /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ | |
289 | if ((sb->iop_state != ADAPTER_STATE_READY) && | |
290 | (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) | |
291 | return 0; | |
292 | ||
a1a5ea70 ML |
293 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
294 | if (IS_ERR(msg)) | |
295 | return PTR_ERR(msg); | |
1da177e4 | 296 | |
a1a5ea70 ML |
297 | msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); |
298 | msg->u.head[1] = | |
299 | cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | | |
300 | ADAPTER_TID); | |
1da177e4 LT |
301 | |
302 | /* Long timeout needed for quiesce if lots of devices */ | |
a1a5ea70 | 303 | if ((rc = i2o_msg_post_wait(c, msg, 240))) |
f33213ec | 304 | osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); |
1da177e4 | 305 | else |
f33213ec | 306 | osm_debug("%s: Quiesced.\n", c->name); |
1da177e4 LT |
307 | |
308 | i2o_status_get(c); // Entered READY state | |
309 | ||
310 | return rc; | |
311 | }; | |
312 | ||
313 | /** | |
314 | * i2o_iop_enable - move controller from ready to OPERATIONAL | |
315 | * @c: I2O controller | |
316 | * | |
317 | * Enable IOP. This allows the IOP to resume external operations and | |
318 | * reverses the effect of a quiesce. Returns zero or an error code if | |
319 | * an error occurs. | |
320 | */ | |
321 | static int i2o_iop_enable(struct i2o_controller *c) | |
322 | { | |
a1a5ea70 | 323 | struct i2o_message *msg; |
1da177e4 LT |
324 | i2o_status_block *sb = c->status_block.virt; |
325 | int rc; | |
326 | ||
327 | i2o_status_get(c); | |
328 | ||
329 | /* Enable only allowed on READY state */ | |
330 | if (sb->iop_state != ADAPTER_STATE_READY) | |
331 | return -EINVAL; | |
332 | ||
a1a5ea70 ML |
333 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
334 | if (IS_ERR(msg)) | |
335 | return PTR_ERR(msg); | |
1da177e4 | 336 | |
a1a5ea70 ML |
337 | msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); |
338 | msg->u.head[1] = | |
339 | cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | | |
340 | ADAPTER_TID); | |
1da177e4 LT |
341 | |
342 | /* How long of a timeout do we need? */ | |
a1a5ea70 | 343 | if ((rc = i2o_msg_post_wait(c, msg, 240))) |
f33213ec | 344 | osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); |
1da177e4 | 345 | else |
f33213ec | 346 | osm_debug("%s: Enabled.\n", c->name); |
1da177e4 LT |
347 | |
348 | i2o_status_get(c); // entered OPERATIONAL state | |
349 | ||
350 | return rc; | |
351 | }; | |
352 | ||
353 | /** | |
354 | * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system | |
355 | * | |
356 | * Quiesce all I2O controllers which are connected to the system. | |
357 | */ | |
358 | static inline void i2o_iop_quiesce_all(void) | |
359 | { | |
360 | struct i2o_controller *c, *tmp; | |
361 | ||
362 | list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { | |
363 | if (!c->no_quiesce) | |
364 | i2o_iop_quiesce(c); | |
365 | } | |
366 | }; | |
367 | ||
368 | /** | |
369 | * i2o_iop_enable_all - Enables all controllers on the system | |
370 | * | |
371 | * Enables all I2O controllers which are connected to the system. | |
372 | */ | |
373 | static inline void i2o_iop_enable_all(void) | |
374 | { | |
375 | struct i2o_controller *c, *tmp; | |
376 | ||
377 | list_for_each_entry_safe(c, tmp, &i2o_controllers, list) | |
378 | i2o_iop_enable(c); | |
379 | }; | |
380 | ||
381 | /** | |
382 | * i2o_clear_controller - Bring I2O controller into HOLD state | |
383 | * @c: controller | |
384 | * | |
385 | * Clear an IOP to HOLD state, ie. terminate external operations, clear all | |
386 | * input queues and prepare for a system restart. IOP's internal operation | |
387 | * continues normally and the outbound queue is alive. The IOP is not | |
388 | * expected to rebuild its LCT. | |
389 | * | |
390 | * Returns 0 on success or negative error code on failure. | |
391 | */ | |
392 | static int i2o_iop_clear(struct i2o_controller *c) | |
393 | { | |
a1a5ea70 | 394 | struct i2o_message *msg; |
1da177e4 LT |
395 | int rc; |
396 | ||
a1a5ea70 ML |
397 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
398 | if (IS_ERR(msg)) | |
399 | return PTR_ERR(msg); | |
1da177e4 LT |
400 | |
401 | /* Quiesce all IOPs first */ | |
402 | i2o_iop_quiesce_all(); | |
403 | ||
a1a5ea70 ML |
404 | msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); |
405 | msg->u.head[1] = | |
406 | cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | | |
407 | ADAPTER_TID); | |
1da177e4 | 408 | |
a1a5ea70 | 409 | if ((rc = i2o_msg_post_wait(c, msg, 30))) |
f33213ec | 410 | osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); |
1da177e4 | 411 | else |
f33213ec | 412 | osm_debug("%s: Cleared.\n", c->name); |
1da177e4 LT |
413 | |
414 | /* Enable all IOPs */ | |
415 | i2o_iop_enable_all(); | |
416 | ||
1da177e4 LT |
417 | return rc; |
418 | } | |
419 | ||
f10378ff ML |
420 | /** |
421 | * i2o_iop_init_outbound_queue - setup the outbound message queue | |
422 | * @c: I2O controller | |
423 | * | |
424 | * Clear and (re)initialize IOP's outbound queue and post the message | |
425 | * frames to the IOP. | |
426 | * | |
a1a5ea70 | 427 | * Returns 0 on success or negative error code on failure. |
f10378ff ML |
428 | */ |
429 | static int i2o_iop_init_outbound_queue(struct i2o_controller *c) | |
430 | { | |
f10378ff | 431 | u32 m; |
a1a5ea70 ML |
432 | volatile u8 *status = c->status.virt; |
433 | struct i2o_message *msg; | |
f10378ff ML |
434 | ulong timeout; |
435 | int i; | |
436 | ||
437 | osm_debug("%s: Initializing Outbound Queue...\n", c->name); | |
438 | ||
9e87545f | 439 | memset(c->status.virt, 0, 4); |
f10378ff | 440 | |
a1a5ea70 ML |
441 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
442 | if (IS_ERR(msg)) | |
443 | return PTR_ERR(msg); | |
444 | ||
445 | msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); | |
446 | msg->u.head[1] = | |
447 | cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | | |
448 | ADAPTER_TID); | |
449 | msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); | |
450 | msg->u.s.tcntxt = cpu_to_le32(0x00000000); | |
451 | msg->body[0] = cpu_to_le32(PAGE_SIZE); | |
f10378ff | 452 | /* Outbound msg frame size in words and Initcode */ |
a1a5ea70 ML |
453 | msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); |
454 | msg->body[2] = cpu_to_le32(0xd0000004); | |
455 | msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); | |
456 | msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); | |
f10378ff | 457 | |
a1a5ea70 | 458 | i2o_msg_post(c, msg); |
f10378ff ML |
459 | |
460 | timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; | |
461 | while (*status <= I2O_CMD_IN_PROGRESS) { | |
462 | if (time_after(jiffies, timeout)) { | |
463 | osm_warn("%s: Timeout Initializing\n", c->name); | |
464 | return -ETIMEDOUT; | |
465 | } | |
6521018d | 466 | schedule_timeout_uninterruptible(1); |
f10378ff ML |
467 | } |
468 | ||
469 | m = c->out_queue.phys; | |
470 | ||
471 | /* Post frames */ | |
9e87545f | 472 | for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { |
f10378ff ML |
473 | i2o_flush_reply(c, m); |
474 | udelay(1); /* Promise */ | |
9e87545f | 475 | m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); |
f10378ff ML |
476 | } |
477 | ||
478 | return 0; | |
479 | } | |
480 | ||
1da177e4 LT |
481 | /** |
482 | * i2o_iop_reset - reset an I2O controller | |
483 | * @c: controller to reset | |
484 | * | |
485 | * Reset the IOP into INIT state and wait until IOP gets into RESET state. | |
486 | * Terminate all external operations, clear IOP's inbound and outbound | |
487 | * queues, terminate all DDMs, and reload the IOP's operating environment | |
488 | * and all local DDMs. The IOP rebuilds its LCT. | |
489 | */ | |
490 | static int i2o_iop_reset(struct i2o_controller *c) | |
491 | { | |
9e87545f | 492 | volatile u8 *status = c->status.virt; |
a1a5ea70 | 493 | struct i2o_message *msg; |
1da177e4 LT |
494 | unsigned long timeout; |
495 | i2o_status_block *sb = c->status_block.virt; | |
496 | int rc = 0; | |
497 | ||
9e87545f | 498 | osm_debug("%s: Resetting controller\n", c->name); |
1da177e4 | 499 | |
a1a5ea70 ML |
500 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
501 | if (IS_ERR(msg)) | |
502 | return PTR_ERR(msg); | |
1da177e4 | 503 | |
9e87545f | 504 | memset(c->status_block.virt, 0, 8); |
1da177e4 LT |
505 | |
506 | /* Quiesce all IOPs first */ | |
507 | i2o_iop_quiesce_all(); | |
508 | ||
a1a5ea70 ML |
509 | msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); |
510 | msg->u.head[1] = | |
511 | cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | | |
512 | ADAPTER_TID); | |
513 | msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); | |
514 | msg->u.s.tcntxt = cpu_to_le32(0x00000000); | |
515 | msg->body[0] = cpu_to_le32(0x00000000); | |
516 | msg->body[1] = cpu_to_le32(0x00000000); | |
517 | msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); | |
518 | msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); | |
1da177e4 | 519 | |
a1a5ea70 | 520 | i2o_msg_post(c, msg); |
1da177e4 LT |
521 | |
522 | /* Wait for a reply */ | |
523 | timeout = jiffies + I2O_TIMEOUT_RESET * HZ; | |
524 | while (!*status) { | |
f10378ff | 525 | if (time_after(jiffies, timeout)) |
1da177e4 | 526 | break; |
1da177e4 | 527 | |
6521018d | 528 | schedule_timeout_uninterruptible(1); |
1da177e4 LT |
529 | } |
530 | ||
f10378ff ML |
531 | switch (*status) { |
532 | case I2O_CMD_REJECTED: | |
533 | osm_warn("%s: IOP reset rejected\n", c->name); | |
534 | rc = -EPERM; | |
535 | break; | |
536 | ||
537 | case I2O_CMD_IN_PROGRESS: | |
1da177e4 LT |
538 | /* |
539 | * Once the reset is sent, the IOP goes into the INIT state | |
f10378ff ML |
540 | * which is indeterminate. We need to wait until the IOP has |
541 | * rebooted before we can let the system talk to it. We read | |
542 | * the inbound Free_List until a message is available. If we | |
543 | * can't read one in the given ammount of time, we assume the | |
544 | * IOP could not reboot properly. | |
1da177e4 | 545 | */ |
f33213ec ML |
546 | osm_debug("%s: Reset in progress, waiting for reboot...\n", |
547 | c->name); | |
1da177e4 | 548 | |
a1a5ea70 | 549 | while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { |
1da177e4 | 550 | if (time_after(jiffies, timeout)) { |
f33213ec | 551 | osm_err("%s: IOP reset timeout.\n", c->name); |
a1a5ea70 | 552 | rc = PTR_ERR(msg); |
1da177e4 LT |
553 | goto exit; |
554 | } | |
6521018d | 555 | schedule_timeout_uninterruptible(1); |
1da177e4 | 556 | } |
a1a5ea70 | 557 | i2o_msg_nop(c, msg); |
1da177e4 | 558 | |
f10378ff ML |
559 | /* from here all quiesce commands are safe */ |
560 | c->no_quiesce = 0; | |
1da177e4 | 561 | |
f10378ff ML |
562 | /* verify if controller is in state RESET */ |
563 | i2o_status_get(c); | |
564 | ||
565 | if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) | |
566 | osm_warn("%s: reset completed, but adapter not in RESET" | |
567 | " state.\n", c->name); | |
568 | else | |
569 | osm_debug("%s: reset completed.\n", c->name); | |
570 | ||
571 | break; | |
572 | ||
573 | default: | |
574 | osm_err("%s: IOP reset timeout.\n", c->name); | |
575 | rc = -ETIMEDOUT; | |
576 | break; | |
577 | } | |
1da177e4 LT |
578 | |
579 | exit: | |
580 | /* Enable all IOPs */ | |
581 | i2o_iop_enable_all(); | |
582 | ||
583 | return rc; | |
584 | }; | |
585 | ||
1da177e4 LT |
586 | /** |
587 | * i2o_iop_activate - Bring controller up to HOLD | |
588 | * @c: controller | |
589 | * | |
590 | * This function brings an I2O controller into HOLD state. The adapter | |
591 | * is reset if necessary and then the queues and resource table are read. | |
592 | * | |
593 | * Returns 0 on success or negative error code on failure. | |
594 | */ | |
595 | static int i2o_iop_activate(struct i2o_controller *c) | |
596 | { | |
1da177e4 LT |
597 | i2o_status_block *sb = c->status_block.virt; |
598 | int rc; | |
f10378ff | 599 | int state; |
1da177e4 LT |
600 | |
601 | /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ | |
602 | /* In READY state, Get status */ | |
603 | ||
604 | rc = i2o_status_get(c); | |
605 | if (rc) { | |
f33213ec ML |
606 | osm_info("%s: Unable to obtain status, attempting a reset.\n", |
607 | c->name); | |
f10378ff ML |
608 | rc = i2o_iop_reset(c); |
609 | if (rc) | |
1da177e4 LT |
610 | return rc; |
611 | } | |
612 | ||
613 | if (sb->i2o_version > I2OVER15) { | |
f33213ec ML |
614 | osm_err("%s: Not running version 1.5 of the I2O Specification." |
615 | "\n", c->name); | |
1da177e4 LT |
616 | return -ENODEV; |
617 | } | |
618 | ||
619 | switch (sb->iop_state) { | |
620 | case ADAPTER_STATE_FAULTED: | |
f33213ec | 621 | osm_err("%s: hardware fault\n", c->name); |
f10378ff | 622 | return -EFAULT; |
1da177e4 LT |
623 | |
624 | case ADAPTER_STATE_READY: | |
625 | case ADAPTER_STATE_OPERATIONAL: | |
626 | case ADAPTER_STATE_HOLD: | |
627 | case ADAPTER_STATE_FAILED: | |
f33213ec | 628 | osm_debug("%s: already running, trying to reset...\n", c->name); |
f10378ff ML |
629 | rc = i2o_iop_reset(c); |
630 | if (rc) | |
631 | return rc; | |
1da177e4 LT |
632 | } |
633 | ||
f10378ff ML |
634 | /* preserve state */ |
635 | state = sb->iop_state; | |
636 | ||
1da177e4 LT |
637 | rc = i2o_iop_init_outbound_queue(c); |
638 | if (rc) | |
639 | return rc; | |
640 | ||
f10378ff ML |
641 | /* if adapter was not in RESET state clear now */ |
642 | if (state != ADAPTER_STATE_RESET) | |
643 | i2o_iop_clear(c); | |
1da177e4 | 644 | |
f10378ff | 645 | i2o_status_get(c); |
1da177e4 | 646 | |
f10378ff ML |
647 | if (sb->iop_state != ADAPTER_STATE_HOLD) { |
648 | osm_err("%s: failed to bring IOP into HOLD state\n", c->name); | |
649 | return -EIO; | |
1da177e4 LT |
650 | } |
651 | ||
f10378ff | 652 | return i2o_hrt_get(c); |
1da177e4 LT |
653 | }; |
654 | ||
655 | /** | |
656 | * i2o_iop_systab_set - Set the I2O System Table of the specified IOP | |
657 | * @c: I2O controller to which the system table should be send | |
658 | * | |
659 | * Before the systab could be set i2o_systab_build() must be called. | |
660 | * | |
661 | * Returns 0 on success or negative error code on failure. | |
662 | */ | |
663 | static int i2o_iop_systab_set(struct i2o_controller *c) | |
664 | { | |
a1a5ea70 | 665 | struct i2o_message *msg; |
1da177e4 LT |
666 | i2o_status_block *sb = c->status_block.virt; |
667 | struct device *dev = &c->pdev->dev; | |
668 | struct resource *root; | |
669 | int rc; | |
670 | ||
671 | if (sb->current_mem_size < sb->desired_mem_size) { | |
672 | struct resource *res = &c->mem_resource; | |
673 | res->name = c->pdev->bus->name; | |
674 | res->flags = IORESOURCE_MEM; | |
675 | res->start = 0; | |
676 | res->end = 0; | |
f33213ec | 677 | osm_info("%s: requires private memory resources.\n", c->name); |
1da177e4 LT |
678 | root = pci_find_parent_resource(c->pdev, res); |
679 | if (root == NULL) | |
f33213ec | 680 | osm_warn("%s: Can't find parent resource!\n", c->name); |
1da177e4 LT |
681 | if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ |
682 | NULL, NULL) >= 0) { | |
683 | c->mem_alloc = 1; | |
684 | sb->current_mem_size = 1 + res->end - res->start; | |
685 | sb->current_mem_base = res->start; | |
e29419ff GKH |
686 | osm_info("%s: allocated %llu bytes of PCI memory at " |
687 | "0x%016llX.\n", c->name, | |
688 | (unsigned long long)(1 + res->end - res->start), | |
689 | (unsigned long long)res->start); | |
1da177e4 LT |
690 | } |
691 | } | |
692 | ||
693 | if (sb->current_io_size < sb->desired_io_size) { | |
694 | struct resource *res = &c->io_resource; | |
695 | res->name = c->pdev->bus->name; | |
696 | res->flags = IORESOURCE_IO; | |
697 | res->start = 0; | |
698 | res->end = 0; | |
f33213ec | 699 | osm_info("%s: requires private memory resources.\n", c->name); |
1da177e4 LT |
700 | root = pci_find_parent_resource(c->pdev, res); |
701 | if (root == NULL) | |
f33213ec | 702 | osm_warn("%s: Can't find parent resource!\n", c->name); |
1da177e4 LT |
703 | if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ |
704 | NULL, NULL) >= 0) { | |
705 | c->io_alloc = 1; | |
706 | sb->current_io_size = 1 + res->end - res->start; | |
707 | sb->current_mem_base = res->start; | |
e29419ff GKH |
708 | osm_info("%s: allocated %llu bytes of PCI I/O at " |
709 | "0x%016llX.\n", c->name, | |
710 | (unsigned long long)(1 + res->end - res->start), | |
711 | (unsigned long long)res->start); | |
1da177e4 LT |
712 | } |
713 | } | |
714 | ||
a1a5ea70 ML |
715 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
716 | if (IS_ERR(msg)) | |
717 | return PTR_ERR(msg); | |
1da177e4 LT |
718 | |
719 | i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, | |
720 | PCI_DMA_TODEVICE); | |
721 | if (!i2o_systab.phys) { | |
a1a5ea70 | 722 | i2o_msg_nop(c, msg); |
1da177e4 LT |
723 | return -ENOMEM; |
724 | } | |
725 | ||
a1a5ea70 ML |
726 | msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); |
727 | msg->u.head[1] = | |
728 | cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | | |
729 | ADAPTER_TID); | |
1da177e4 LT |
730 | |
731 | /* | |
732 | * Provide three SGL-elements: | |
733 | * System table (SysTab), Private memory space declaration and | |
734 | * Private i/o space declaration | |
1da177e4 LT |
735 | */ |
736 | ||
a1a5ea70 ML |
737 | msg->body[0] = cpu_to_le32(c->unit + 2); |
738 | msg->body[1] = cpu_to_le32(0x00000000); | |
739 | msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); | |
740 | msg->body[3] = cpu_to_le32(i2o_systab.phys); | |
741 | msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); | |
742 | msg->body[5] = cpu_to_le32(sb->current_mem_base); | |
743 | msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); | |
744 | msg->body[6] = cpu_to_le32(sb->current_io_base); | |
1da177e4 | 745 | |
a1a5ea70 | 746 | rc = i2o_msg_post_wait(c, msg, 120); |
1da177e4 LT |
747 | |
748 | dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, | |
749 | PCI_DMA_TODEVICE); | |
750 | ||
751 | if (rc < 0) | |
f33213ec ML |
752 | osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, |
753 | -rc); | |
1da177e4 | 754 | else |
f33213ec | 755 | osm_debug("%s: SysTab set.\n", c->name); |
1da177e4 | 756 | |
1da177e4 LT |
757 | return rc; |
758 | } | |
759 | ||
760 | /** | |
761 | * i2o_iop_online - Bring a controller online into OPERATIONAL state. | |
762 | * @c: I2O controller | |
763 | * | |
764 | * Send the system table and enable the I2O controller. | |
765 | * | |
2e1973a3 | 766 | * Returns 0 on success or negative error code on failure. |
1da177e4 LT |
767 | */ |
768 | static int i2o_iop_online(struct i2o_controller *c) | |
769 | { | |
770 | int rc; | |
771 | ||
772 | rc = i2o_iop_systab_set(c); | |
773 | if (rc) | |
774 | return rc; | |
775 | ||
776 | /* In READY state */ | |
f33213ec | 777 | osm_debug("%s: Attempting to enable...\n", c->name); |
1da177e4 LT |
778 | rc = i2o_iop_enable(c); |
779 | if (rc) | |
780 | return rc; | |
781 | ||
782 | return 0; | |
783 | }; | |
784 | ||
785 | /** | |
786 | * i2o_iop_remove - Remove the I2O controller from the I2O core | |
787 | * @c: I2O controller | |
788 | * | |
789 | * Remove the I2O controller from the I2O core. If devices are attached to | |
790 | * the controller remove these also and finally reset the controller. | |
791 | */ | |
792 | void i2o_iop_remove(struct i2o_controller *c) | |
793 | { | |
794 | struct i2o_device *dev, *tmp; | |
795 | ||
f33213ec | 796 | osm_debug("%s: deleting controller\n", c->name); |
1da177e4 LT |
797 | |
798 | i2o_driver_notify_controller_remove_all(c); | |
799 | ||
800 | list_del(&c->list); | |
801 | ||
802 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | |
803 | i2o_device_remove(dev); | |
804 | ||
f88e119c ML |
805 | device_del(&c->device); |
806 | ||
1da177e4 LT |
807 | /* Ask the IOP to switch to RESET state */ |
808 | i2o_iop_reset(c); | |
809 | } | |
810 | ||
811 | /** | |
812 | * i2o_systab_build - Build system table | |
813 | * | |
814 | * The system table contains information about all the IOPs in the system | |
815 | * (duh) and is used by the Executives on the IOPs to establish peer2peer | |
816 | * connections. We're not supporting peer2peer at the moment, but this | |
817 | * will be needed down the road for things like lan2lan forwarding. | |
818 | * | |
819 | * Returns 0 on success or negative error code on failure. | |
820 | */ | |
821 | static int i2o_systab_build(void) | |
822 | { | |
823 | struct i2o_controller *c, *tmp; | |
824 | int num_controllers = 0; | |
825 | u32 change_ind = 0; | |
826 | int count = 0; | |
827 | struct i2o_sys_tbl *systab = i2o_systab.virt; | |
828 | ||
829 | list_for_each_entry_safe(c, tmp, &i2o_controllers, list) | |
830 | num_controllers++; | |
831 | ||
832 | if (systab) { | |
833 | change_ind = systab->change_ind; | |
834 | kfree(i2o_systab.virt); | |
835 | } | |
836 | ||
837 | /* Header + IOPs */ | |
838 | i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * | |
839 | sizeof(struct i2o_sys_tbl_entry); | |
840 | ||
f6ed39a6 | 841 | systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); |
1da177e4 | 842 | if (!systab) { |
f33213ec | 843 | osm_err("unable to allocate memory for System Table\n"); |
1da177e4 LT |
844 | return -ENOMEM; |
845 | } | |
1da177e4 LT |
846 | |
847 | systab->version = I2OVERSION; | |
848 | systab->change_ind = change_ind + 1; | |
849 | ||
850 | list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { | |
851 | i2o_status_block *sb; | |
852 | ||
853 | if (count >= num_controllers) { | |
f33213ec ML |
854 | osm_err("controller added while building system table" |
855 | "\n"); | |
1da177e4 LT |
856 | break; |
857 | } | |
858 | ||
859 | sb = c->status_block.virt; | |
860 | ||
861 | /* | |
862 | * Get updated IOP state so we have the latest information | |
863 | * | |
864 | * We should delete the controller at this point if it | |
865 | * doesn't respond since if it's not on the system table | |
866 | * it is techninically not part of the I2O subsystem... | |
867 | */ | |
868 | if (unlikely(i2o_status_get(c))) { | |
f33213ec ML |
869 | osm_err("%s: Deleting b/c could not get status while " |
870 | "attempting to build system table\n", c->name); | |
1da177e4 LT |
871 | i2o_iop_remove(c); |
872 | continue; // try the next one | |
873 | } | |
874 | ||
875 | systab->iops[count].org_id = sb->org_id; | |
876 | systab->iops[count].iop_id = c->unit + 2; | |
877 | systab->iops[count].seg_num = 0; | |
878 | systab->iops[count].i2o_version = sb->i2o_version; | |
879 | systab->iops[count].iop_state = sb->iop_state; | |
880 | systab->iops[count].msg_type = sb->msg_type; | |
881 | systab->iops[count].frame_size = sb->inbound_frame_size; | |
882 | systab->iops[count].last_changed = change_ind; | |
883 | systab->iops[count].iop_capabilities = sb->iop_capabilities; | |
f88e119c ML |
884 | systab->iops[count].inbound_low = |
885 | i2o_dma_low(c->base.phys + I2O_IN_PORT); | |
886 | systab->iops[count].inbound_high = | |
887 | i2o_dma_high(c->base.phys + I2O_IN_PORT); | |
1da177e4 LT |
888 | |
889 | count++; | |
890 | } | |
891 | ||
892 | systab->num_entries = count; | |
893 | ||
894 | return 0; | |
895 | }; | |
896 | ||
897 | /** | |
898 | * i2o_parse_hrt - Parse the hardware resource table. | |
899 | * @c: I2O controller | |
900 | * | |
901 | * We don't do anything with it except dumping it (in debug mode). | |
902 | * | |
903 | * Returns 0. | |
904 | */ | |
905 | static int i2o_parse_hrt(struct i2o_controller *c) | |
906 | { | |
907 | i2o_dump_hrt(c); | |
908 | return 0; | |
909 | }; | |
910 | ||
911 | /** | |
912 | * i2o_status_get - Get the status block from the I2O controller | |
913 | * @c: I2O controller | |
914 | * | |
915 | * Issue a status query on the controller. This updates the attached | |
916 | * status block. The status block could then be accessed through | |
917 | * c->status_block. | |
918 | * | |
fc1323bb | 919 | * Returns 0 on success or negative error code on failure. |
1da177e4 LT |
920 | */ |
921 | int i2o_status_get(struct i2o_controller *c) | |
922 | { | |
a1a5ea70 | 923 | struct i2o_message *msg; |
9e87545f | 924 | volatile u8 *status_block; |
1da177e4 LT |
925 | unsigned long timeout; |
926 | ||
927 | status_block = (u8 *) c->status_block.virt; | |
9e87545f | 928 | memset(c->status_block.virt, 0, sizeof(i2o_status_block)); |
1da177e4 | 929 | |
a1a5ea70 ML |
930 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
931 | if (IS_ERR(msg)) | |
932 | return PTR_ERR(msg); | |
1da177e4 | 933 | |
a1a5ea70 ML |
934 | msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); |
935 | msg->u.head[1] = | |
936 | cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | | |
937 | ADAPTER_TID); | |
938 | msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); | |
939 | msg->u.s.tcntxt = cpu_to_le32(0x00000000); | |
940 | msg->body[0] = cpu_to_le32(0x00000000); | |
941 | msg->body[1] = cpu_to_le32(0x00000000); | |
942 | msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); | |
943 | msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); | |
944 | msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ | |
1da177e4 | 945 | |
a1a5ea70 | 946 | i2o_msg_post(c, msg); |
1da177e4 LT |
947 | |
948 | /* Wait for a reply */ | |
949 | timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; | |
950 | while (status_block[87] != 0xFF) { | |
951 | if (time_after(jiffies, timeout)) { | |
f33213ec | 952 | osm_err("%s: Get status timeout.\n", c->name); |
1da177e4 LT |
953 | return -ETIMEDOUT; |
954 | } | |
955 | ||
6521018d | 956 | schedule_timeout_uninterruptible(1); |
1da177e4 LT |
957 | } |
958 | ||
959 | #ifdef DEBUG | |
960 | i2o_debug_state(c); | |
961 | #endif | |
962 | ||
963 | return 0; | |
964 | } | |
965 | ||
966 | /* | |
967 | * i2o_hrt_get - Get the Hardware Resource Table from the I2O controller | |
968 | * @c: I2O controller from which the HRT should be fetched | |
969 | * | |
970 | * The HRT contains information about possible hidden devices but is | |
971 | * mostly useless to us. | |
972 | * | |
2e1973a3 | 973 | * Returns 0 on success or negative error code on failure. |
1da177e4 LT |
974 | */ |
975 | static int i2o_hrt_get(struct i2o_controller *c) | |
976 | { | |
977 | int rc; | |
978 | int i; | |
979 | i2o_hrt *hrt = c->hrt.virt; | |
980 | u32 size = sizeof(i2o_hrt); | |
981 | struct device *dev = &c->pdev->dev; | |
982 | ||
983 | for (i = 0; i < I2O_HRT_GET_TRIES; i++) { | |
a1a5ea70 | 984 | struct i2o_message *msg; |
1da177e4 | 985 | |
a1a5ea70 ML |
986 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
987 | if (IS_ERR(msg)) | |
988 | return PTR_ERR(msg); | |
1da177e4 | 989 | |
a1a5ea70 ML |
990 | msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); |
991 | msg->u.head[1] = | |
992 | cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | | |
993 | ADAPTER_TID); | |
994 | msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); | |
995 | msg->body[1] = cpu_to_le32(c->hrt.phys); | |
1da177e4 | 996 | |
a1a5ea70 | 997 | rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); |
1da177e4 LT |
998 | |
999 | if (rc < 0) { | |
f33213ec ML |
1000 | osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, |
1001 | -rc); | |
1da177e4 LT |
1002 | return rc; |
1003 | } | |
1004 | ||
1005 | size = hrt->num_entries * hrt->entry_len << 2; | |
1006 | if (size > c->hrt.len) { | |
1007 | if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL)) | |
1008 | return -ENOMEM; | |
1009 | else | |
1010 | hrt = c->hrt.virt; | |
1011 | } else | |
1012 | return i2o_parse_hrt(c); | |
1013 | } | |
1014 | ||
f33213ec ML |
1015 | osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, |
1016 | I2O_HRT_GET_TRIES); | |
1da177e4 LT |
1017 | |
1018 | return -EBUSY; | |
1019 | } | |
1020 | ||
f88e119c ML |
1021 | /** |
1022 | * i2o_iop_release - release the memory for a I2O controller | |
1023 | * @dev: I2O controller which should be released | |
1024 | * | |
1025 | * Release the allocated memory. This function is called if refcount of | |
1026 | * device reaches 0 automatically. | |
1027 | */ | |
1028 | static void i2o_iop_release(struct device *dev) | |
1029 | { | |
1030 | struct i2o_controller *c = to_i2o_controller(dev); | |
1031 | ||
1032 | i2o_iop_free(c); | |
1033 | }; | |
1034 | ||
1da177e4 LT |
1035 | /** |
1036 | * i2o_iop_alloc - Allocate and initialize a i2o_controller struct | |
1037 | * | |
1038 | * Allocate the necessary memory for a i2o_controller struct and | |
a1a5ea70 | 1039 | * initialize the lists and message mempool. |
1da177e4 LT |
1040 | * |
1041 | * Returns a pointer to the I2O controller or a negative error code on | |
1042 | * failure. | |
1043 | */ | |
1044 | struct i2o_controller *i2o_iop_alloc(void) | |
1045 | { | |
1046 | static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ | |
1047 | struct i2o_controller *c; | |
a1a5ea70 | 1048 | char poolname[32]; |
1da177e4 | 1049 | |
f6ed39a6 | 1050 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
1da177e4 | 1051 | if (!c) { |
f33213ec ML |
1052 | osm_err("i2o: Insufficient memory to allocate a I2O controller." |
1053 | "\n"); | |
1da177e4 LT |
1054 | return ERR_PTR(-ENOMEM); |
1055 | } | |
1da177e4 | 1056 | |
a1a5ea70 ML |
1057 | c->unit = unit++; |
1058 | sprintf(c->name, "iop%d", c->unit); | |
1059 | ||
1060 | snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); | |
1061 | if (i2o_pool_alloc | |
57a62fed | 1062 | (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), |
a1a5ea70 ML |
1063 | I2O_MSG_INPOOL_MIN)) { |
1064 | kfree(c); | |
1065 | return ERR_PTR(-ENOMEM); | |
1066 | }; | |
1067 | ||
1da177e4 LT |
1068 | INIT_LIST_HEAD(&c->devices); |
1069 | spin_lock_init(&c->lock); | |
9ac16252 | 1070 | mutex_init(&c->lct_lock); |
1da177e4 | 1071 | |
f88e119c | 1072 | device_initialize(&c->device); |
9e87545f | 1073 | |
f88e119c | 1074 | c->device.release = &i2o_iop_release; |
9e87545f | 1075 | |
f88e119c ML |
1076 | snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); |
1077 | ||
1da177e4 LT |
1078 | #if BITS_PER_LONG == 64 |
1079 | spin_lock_init(&c->context_list_lock); | |
1080 | atomic_set(&c->context_list_counter, 0); | |
1081 | INIT_LIST_HEAD(&c->context_list); | |
1082 | #endif | |
1083 | ||
1084 | return c; | |
1085 | }; | |
1086 | ||
1da177e4 LT |
1087 | /** |
1088 | * i2o_iop_add - Initialize the I2O controller and add him to the I2O core | |
1089 | * @c: controller | |
1090 | * | |
1091 | * Initialize the I2O controller and if no error occurs add him to the I2O | |
1092 | * core. | |
1093 | * | |
1094 | * Returns 0 on success or negative error code on failure. | |
1095 | */ | |
1096 | int i2o_iop_add(struct i2o_controller *c) | |
1097 | { | |
1098 | int rc; | |
1099 | ||
9e87545f ML |
1100 | if ((rc = device_add(&c->device))) { |
1101 | osm_err("%s: could not add controller\n", c->name); | |
f88e119c ML |
1102 | goto iop_reset; |
1103 | } | |
1104 | ||
9e87545f ML |
1105 | osm_info("%s: Activating I2O controller...\n", c->name); |
1106 | osm_info("%s: This may take a few minutes if there are many devices\n", | |
1107 | c->name); | |
1da177e4 LT |
1108 | |
1109 | if ((rc = i2o_iop_activate(c))) { | |
9e87545f | 1110 | osm_err("%s: could not activate controller\n", c->name); |
24791bd4 | 1111 | goto device_del; |
1da177e4 LT |
1112 | } |
1113 | ||
9e87545f | 1114 | osm_debug("%s: building sys table...\n", c->name); |
1da177e4 | 1115 | |
f88e119c | 1116 | if ((rc = i2o_systab_build())) |
24791bd4 | 1117 | goto device_del; |
1da177e4 | 1118 | |
9e87545f | 1119 | osm_debug("%s: online controller...\n", c->name); |
1da177e4 | 1120 | |
f88e119c | 1121 | if ((rc = i2o_iop_online(c))) |
24791bd4 | 1122 | goto device_del; |
1da177e4 | 1123 | |
9e87545f | 1124 | osm_debug("%s: getting LCT...\n", c->name); |
1da177e4 | 1125 | |
f88e119c | 1126 | if ((rc = i2o_exec_lct_get(c))) |
24791bd4 | 1127 | goto device_del; |
1da177e4 LT |
1128 | |
1129 | list_add(&c->list, &i2o_controllers); | |
1130 | ||
1131 | i2o_driver_notify_controller_add_all(c); | |
1132 | ||
9e87545f | 1133 | osm_info("%s: Controller added\n", c->name); |
1da177e4 LT |
1134 | |
1135 | return 0; | |
f88e119c | 1136 | |
9e87545f ML |
1137 | device_del: |
1138 | device_del(&c->device); | |
1139 | ||
1140 | iop_reset: | |
f88e119c ML |
1141 | i2o_iop_reset(c); |
1142 | ||
1143 | return rc; | |
1da177e4 LT |
1144 | }; |
1145 | ||
1146 | /** | |
1147 | * i2o_event_register - Turn on/off event notification for a I2O device | |
1148 | * @dev: I2O device which should receive the event registration request | |
1149 | * @drv: driver which want to get notified | |
1150 | * @tcntxt: transaction context to use with this notifier | |
1151 | * @evt_mask: mask of events | |
1152 | * | |
1153 | * Create and posts an event registration message to the task. No reply | |
1154 | * is waited for, or expected. If you do not want further notifications, | |
1155 | * call the i2o_event_register again with a evt_mask of 0. | |
1156 | * | |
a1a5ea70 | 1157 | * Returns 0 on success or negative error code on failure. |
1da177e4 LT |
1158 | */ |
1159 | int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, | |
1160 | int tcntxt, u32 evt_mask) | |
1161 | { | |
1162 | struct i2o_controller *c = dev->iop; | |
a1a5ea70 | 1163 | struct i2o_message *msg; |
1da177e4 | 1164 | |
a1a5ea70 ML |
1165 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
1166 | if (IS_ERR(msg)) | |
1167 | return PTR_ERR(msg); | |
1da177e4 | 1168 | |
a1a5ea70 ML |
1169 | msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); |
1170 | msg->u.head[1] = | |
1171 | cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> | |
1172 | lct_data.tid); | |
1173 | msg->u.s.icntxt = cpu_to_le32(drv->context); | |
1174 | msg->u.s.tcntxt = cpu_to_le32(tcntxt); | |
1175 | msg->body[0] = cpu_to_le32(evt_mask); | |
1da177e4 | 1176 | |
a1a5ea70 | 1177 | i2o_msg_post(c, msg); |
1da177e4 LT |
1178 | |
1179 | return 0; | |
1180 | }; | |
1181 | ||
1182 | /** | |
1183 | * i2o_iop_init - I2O main initialization function | |
1184 | * | |
1185 | * Initialize the I2O drivers (OSM) functions, register the Executive OSM, | |
1186 | * initialize the I2O PCI part and finally initialize I2O device stuff. | |
1187 | * | |
1188 | * Returns 0 on success or negative error code on failure. | |
1189 | */ | |
1190 | static int __init i2o_iop_init(void) | |
1191 | { | |
1192 | int rc = 0; | |
1193 | ||
1194 | printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); | |
1195 | ||
9e87545f | 1196 | if ((rc = i2o_driver_init())) |
24791bd4 | 1197 | goto exit; |
9e87545f ML |
1198 | |
1199 | if ((rc = i2o_exec_init())) | |
1da177e4 LT |
1200 | goto driver_exit; |
1201 | ||
9e87545f | 1202 | if ((rc = i2o_pci_init())) |
1da177e4 LT |
1203 | goto exec_exit; |
1204 | ||
1205 | return 0; | |
1206 | ||
1207 | exec_exit: | |
1208 | i2o_exec_exit(); | |
1209 | ||
1210 | driver_exit: | |
1211 | i2o_driver_exit(); | |
1212 | ||
1da177e4 LT |
1213 | exit: |
1214 | return rc; | |
1215 | } | |
1216 | ||
1217 | /** | |
1218 | * i2o_iop_exit - I2O main exit function | |
1219 | * | |
1220 | * Removes I2O controllers from PCI subsystem and shut down OSMs. | |
1221 | */ | |
1222 | static void __exit i2o_iop_exit(void) | |
1223 | { | |
1224 | i2o_pci_exit(); | |
1225 | i2o_exec_exit(); | |
1226 | i2o_driver_exit(); | |
1da177e4 LT |
1227 | }; |
1228 | ||
1229 | module_init(i2o_iop_init); | |
1230 | module_exit(i2o_iop_exit); | |
1231 | ||
1232 | MODULE_AUTHOR("Red Hat Software"); | |
1233 | MODULE_LICENSE("GPL"); | |
1234 | MODULE_DESCRIPTION(OSM_DESCRIPTION); | |
1235 | MODULE_VERSION(OSM_VERSION); | |
1236 | ||
1237 | #if BITS_PER_LONG == 64 | |
1238 | EXPORT_SYMBOL(i2o_cntxt_list_add); | |
1239 | EXPORT_SYMBOL(i2o_cntxt_list_get); | |
1240 | EXPORT_SYMBOL(i2o_cntxt_list_remove); | |
1241 | EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); | |
1242 | #endif | |
1243 | EXPORT_SYMBOL(i2o_msg_get_wait); | |
1da177e4 LT |
1244 | EXPORT_SYMBOL(i2o_find_iop); |
1245 | EXPORT_SYMBOL(i2o_iop_find_device); | |
1246 | EXPORT_SYMBOL(i2o_event_register); | |
1247 | EXPORT_SYMBOL(i2o_status_get); | |
1248 | EXPORT_SYMBOL(i2o_controllers); |