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