Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * IEEE 1394 for Linux | |
3 | * | |
4 | * Core support: hpsb_packet management, packet handling and forwarding to | |
5 | * highlevel or lowlevel code | |
6 | * | |
7 | * Copyright (C) 1999, 2000 Andreas E. Bombe | |
8 | * 2002 Manfred Weihs <weihs@ict.tuwien.ac.at> | |
9 | * | |
10 | * This code is licensed under the GPL. See the file COPYING in the root | |
11 | * directory of the kernel sources for details. | |
12 | * | |
13 | * | |
14 | * Contributions: | |
15 | * | |
16 | * Manfred Weihs <weihs@ict.tuwien.ac.at> | |
17 | * loopback functionality in hpsb_send_packet | |
18 | * allow highlevel drivers to disable automatic response generation | |
19 | * and to generate responses themselves (deferred) | |
20 | * | |
21 | */ | |
22 | ||
1da177e4 LT |
23 | #include <linux/kernel.h> |
24 | #include <linux/list.h> | |
25 | #include <linux/string.h> | |
26 | #include <linux/init.h> | |
27 | #include <linux/slab.h> | |
28 | #include <linux/interrupt.h> | |
29 | #include <linux/module.h> | |
30 | #include <linux/moduleparam.h> | |
31 | #include <linux/bitops.h> | |
32 | #include <linux/kdev_t.h> | |
83144186 | 33 | #include <linux/freezer.h> |
1da177e4 | 34 | #include <linux/suspend.h> |
f654240f | 35 | #include <linux/kthread.h> |
3dc5ea9b PP |
36 | #include <linux/preempt.h> |
37 | #include <linux/time.h> | |
1da177e4 | 38 | |
3dc5ea9b | 39 | #include <asm/system.h> |
1da177e4 | 40 | #include <asm/byteorder.h> |
1da177e4 LT |
41 | |
42 | #include "ieee1394_types.h" | |
43 | #include "ieee1394.h" | |
44 | #include "hosts.h" | |
45 | #include "ieee1394_core.h" | |
46 | #include "highlevel.h" | |
47 | #include "ieee1394_transactions.h" | |
48 | #include "csr.h" | |
49 | #include "nodemgr.h" | |
50 | #include "dma.h" | |
51 | #include "iso.h" | |
52 | #include "config_roms.h" | |
53 | ||
54 | /* | |
55 | * Disable the nodemgr detection and config rom reading functionality. | |
56 | */ | |
1934b8b6 | 57 | static int disable_nodemgr; |
1da177e4 LT |
58 | module_param(disable_nodemgr, int, 0444); |
59 | MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); | |
60 | ||
61 | /* Disable Isochronous Resource Manager functionality */ | |
62 | int hpsb_disable_irm = 0; | |
23e93f17 | 63 | module_param_named(disable_irm, hpsb_disable_irm, bool, 0444); |
1da177e4 LT |
64 | MODULE_PARM_DESC(disable_irm, |
65 | "Disable Isochronous Resource Manager functionality."); | |
66 | ||
67 | /* We are GPL, so treat us special */ | |
68 | MODULE_LICENSE("GPL"); | |
69 | ||
70 | /* Some globals used */ | |
71 | const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; | |
7e25ab91 | 72 | struct class *hpsb_protocol_class; |
1da177e4 LT |
73 | |
74 | #ifdef CONFIG_IEEE1394_VERBOSEDEBUG | |
db2fd664 | 75 | static void dump_packet(const char *text, quadlet_t *data, int size, int speed) |
1da177e4 LT |
76 | { |
77 | int i; | |
78 | ||
79 | size /= 4; | |
80 | size = (size > 4 ? 4 : size); | |
81 | ||
82 | printk(KERN_DEBUG "ieee1394: %s", text); | |
db2fd664 JM |
83 | if (speed > -1 && speed < 6) |
84 | printk(" at %s", hpsb_speedto_str[speed]); | |
85 | printk(":"); | |
1da177e4 LT |
86 | for (i = 0; i < size; i++) |
87 | printk(" %08x", data[i]); | |
88 | printk("\n"); | |
89 | } | |
90 | #else | |
611aa19f | 91 | #define dump_packet(a,b,c,d) do {} while (0) |
1da177e4 LT |
92 | #endif |
93 | ||
94 | static void abort_requests(struct hpsb_host *host); | |
95 | static void queue_packet_complete(struct hpsb_packet *packet); | |
96 | ||
97 | ||
98 | /** | |
afd6546d | 99 | * hpsb_set_packet_complete_task - set task that runs when a packet completes |
1da177e4 LT |
100 | * @packet: the packet whose completion we want the task added to |
101 | * @routine: function to call | |
102 | * @data: data (if any) to pass to the above function | |
afd6546d SR |
103 | * |
104 | * Set the task that runs when a packet completes. You cannot call this more | |
105 | * than once on a single packet before it is sent. | |
7542e0e6 SR |
106 | * |
107 | * Typically, the complete @routine is responsible to call hpsb_free_packet(). | |
1da177e4 LT |
108 | */ |
109 | void hpsb_set_packet_complete_task(struct hpsb_packet *packet, | |
110 | void (*routine)(void *), void *data) | |
111 | { | |
112 | WARN_ON(packet->complete_routine != NULL); | |
113 | packet->complete_routine = routine; | |
114 | packet->complete_data = data; | |
115 | return; | |
116 | } | |
117 | ||
118 | /** | |
119 | * hpsb_alloc_packet - allocate new packet structure | |
7542e0e6 | 120 | * @data_size: size of the data block to be allocated, in bytes |
1da177e4 LT |
121 | * |
122 | * This function allocates, initializes and returns a new &struct hpsb_packet. | |
7542e0e6 SR |
123 | * It can be used in interrupt context. A header block is always included and |
124 | * initialized with zeros. Its size is big enough to contain all possible 1394 | |
125 | * headers. The data block is only allocated if @data_size is not zero. | |
1da177e4 LT |
126 | * |
127 | * For packets for which responses will be received the @data_size has to be big | |
128 | * enough to contain the response's data block since no further allocation | |
129 | * occurs at response matching time. | |
130 | * | |
131 | * The packet's generation value will be set to the current generation number | |
132 | * for ease of use. Remember to overwrite it with your own recorded generation | |
133 | * number if you can not be sure that your code will not race with a bus reset. | |
134 | * | |
135 | * Return value: A pointer to a &struct hpsb_packet or NULL on allocation | |
136 | * failure. | |
137 | */ | |
138 | struct hpsb_packet *hpsb_alloc_packet(size_t data_size) | |
139 | { | |
7542e0e6 | 140 | struct hpsb_packet *packet; |
1da177e4 LT |
141 | |
142 | data_size = ((data_size + 3) & ~3); | |
143 | ||
7542e0e6 SR |
144 | packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC); |
145 | if (!packet) | |
1da177e4 LT |
146 | return NULL; |
147 | ||
1da177e4 LT |
148 | packet->state = hpsb_unused; |
149 | packet->generation = -1; | |
150 | INIT_LIST_HEAD(&packet->driver_list); | |
7542e0e6 | 151 | INIT_LIST_HEAD(&packet->queue); |
1da177e4 LT |
152 | atomic_set(&packet->refcnt, 1); |
153 | ||
154 | if (data_size) { | |
7542e0e6 SR |
155 | packet->data = packet->embedded_data; |
156 | packet->allocated_data_size = data_size; | |
1da177e4 | 157 | } |
1da177e4 LT |
158 | return packet; |
159 | } | |
160 | ||
1da177e4 LT |
161 | /** |
162 | * hpsb_free_packet - free packet and data associated with it | |
163 | * @packet: packet to free (is NULL safe) | |
164 | * | |
7542e0e6 | 165 | * Frees @packet->data only if it was allocated through hpsb_alloc_packet(). |
1da177e4 LT |
166 | */ |
167 | void hpsb_free_packet(struct hpsb_packet *packet) | |
168 | { | |
169 | if (packet && atomic_dec_and_test(&packet->refcnt)) { | |
7542e0e6 SR |
170 | BUG_ON(!list_empty(&packet->driver_list) || |
171 | !list_empty(&packet->queue)); | |
172 | kfree(packet); | |
1da177e4 LT |
173 | } |
174 | } | |
175 | ||
afd6546d SR |
176 | /** |
177 | * hpsb_reset_bus - initiate bus reset on the given host | |
178 | * @host: host controller whose bus to reset | |
179 | * @type: one of enum reset_types | |
180 | * | |
181 | * Returns 1 if bus reset already in progress, 0 otherwise. | |
182 | */ | |
1da177e4 LT |
183 | int hpsb_reset_bus(struct hpsb_host *host, int type) |
184 | { | |
741854e4 SR |
185 | if (!host->in_bus_reset) { |
186 | host->driver->devctl(host, RESET_BUS, type); | |
187 | return 0; | |
188 | } else { | |
189 | return 1; | |
190 | } | |
1da177e4 LT |
191 | } |
192 | ||
3dc5ea9b PP |
193 | /** |
194 | * hpsb_read_cycle_timer - read cycle timer register and system time | |
195 | * @host: host whose isochronous cycle timer register is read | |
196 | * @cycle_timer: address of bitfield to return the register contents | |
197 | * @local_time: address to return the system time | |
198 | * | |
199 | * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This | |
200 | * format is also read from non-OHCI controllers. * @local_time contains the | |
201 | * system time in microseconds since the Epoch, read at the moment when the | |
202 | * cycle timer was read. | |
203 | * | |
204 | * Return value: 0 for success or error number otherwise. | |
205 | */ | |
206 | int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, | |
207 | u64 *local_time) | |
208 | { | |
209 | int ctr; | |
210 | struct timeval tv; | |
211 | unsigned long flags; | |
212 | ||
213 | if (!host || !cycle_timer || !local_time) | |
214 | return -EINVAL; | |
215 | ||
216 | preempt_disable(); | |
217 | local_irq_save(flags); | |
218 | ||
219 | ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0); | |
220 | if (ctr) | |
221 | do_gettimeofday(&tv); | |
222 | ||
223 | local_irq_restore(flags); | |
224 | preempt_enable(); | |
225 | ||
226 | if (!ctr) | |
227 | return -EIO; | |
228 | *cycle_timer = ctr; | |
229 | *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; | |
230 | return 0; | |
231 | } | |
1da177e4 | 232 | |
afd6546d SR |
233 | /** |
234 | * hpsb_bus_reset - notify a bus reset to the core | |
235 | * | |
236 | * For host driver module usage. Safe to use in interrupt context, although | |
237 | * quite complex; so you may want to run it in the bottom rather than top half. | |
238 | * | |
239 | * Returns 1 if bus reset already in progress, 0 otherwise. | |
240 | */ | |
1da177e4 LT |
241 | int hpsb_bus_reset(struct hpsb_host *host) |
242 | { | |
741854e4 SR |
243 | if (host->in_bus_reset) { |
244 | HPSB_NOTICE("%s called while bus reset already in progress", | |
1da177e4 | 245 | __FUNCTION__); |
741854e4 SR |
246 | return 1; |
247 | } | |
1da177e4 | 248 | |
741854e4 SR |
249 | abort_requests(host); |
250 | host->in_bus_reset = 1; | |
251 | host->irm_id = -1; | |
1da177e4 | 252 | host->is_irm = 0; |
741854e4 | 253 | host->busmgr_id = -1; |
1da177e4 LT |
254 | host->is_busmgr = 0; |
255 | host->is_cycmst = 0; | |
741854e4 SR |
256 | host->node_count = 0; |
257 | host->selfid_count = 0; | |
1da177e4 | 258 | |
741854e4 | 259 | return 0; |
1da177e4 LT |
260 | } |
261 | ||
262 | ||
263 | /* | |
264 | * Verify num_of_selfids SelfIDs and return number of nodes. Return zero in | |
265 | * case verification failed. | |
266 | */ | |
267 | static int check_selfids(struct hpsb_host *host) | |
268 | { | |
741854e4 SR |
269 | int nodeid = -1; |
270 | int rest_of_selfids = host->selfid_count; | |
271 | struct selfid *sid = (struct selfid *)host->topology_map; | |
272 | struct ext_selfid *esid; | |
273 | int esid_seq = 23; | |
1da177e4 LT |
274 | |
275 | host->nodes_active = 0; | |
276 | ||
741854e4 SR |
277 | while (rest_of_selfids--) { |
278 | if (!sid->extended) { | |
279 | nodeid++; | |
280 | esid_seq = 0; | |
1da177e4 | 281 | |
741854e4 SR |
282 | if (sid->phy_id != nodeid) { |
283 | HPSB_INFO("SelfIDs failed monotony check with " | |
284 | "%d", sid->phy_id); | |
285 | return 0; | |
286 | } | |
1da177e4 LT |
287 | |
288 | if (sid->link_active) { | |
289 | host->nodes_active++; | |
290 | if (sid->contender) | |
291 | host->irm_id = LOCAL_BUS | sid->phy_id; | |
292 | } | |
741854e4 SR |
293 | } else { |
294 | esid = (struct ext_selfid *)sid; | |
295 | ||
296 | if ((esid->phy_id != nodeid) | |
297 | || (esid->seq_nr != esid_seq)) { | |
298 | HPSB_INFO("SelfIDs failed monotony check with " | |
299 | "%d/%d", esid->phy_id, esid->seq_nr); | |
300 | return 0; | |
301 | } | |
302 | esid_seq++; | |
303 | } | |
304 | sid++; | |
305 | } | |
306 | ||
307 | esid = (struct ext_selfid *)(sid - 1); | |
308 | while (esid->extended) { | |
309 | if ((esid->porta == SELFID_PORT_PARENT) || | |
d7758461 SR |
310 | (esid->portb == SELFID_PORT_PARENT) || |
311 | (esid->portc == SELFID_PORT_PARENT) || | |
312 | (esid->portd == SELFID_PORT_PARENT) || | |
313 | (esid->porte == SELFID_PORT_PARENT) || | |
314 | (esid->portf == SELFID_PORT_PARENT) || | |
315 | (esid->portg == SELFID_PORT_PARENT) || | |
316 | (esid->porth == SELFID_PORT_PARENT)) { | |
1da177e4 LT |
317 | HPSB_INFO("SelfIDs failed root check on " |
318 | "extended SelfID"); | |
319 | return 0; | |
741854e4 SR |
320 | } |
321 | esid--; | |
322 | } | |
1da177e4 | 323 | |
741854e4 | 324 | sid = (struct selfid *)esid; |
d7758461 SR |
325 | if ((sid->port0 == SELFID_PORT_PARENT) || |
326 | (sid->port1 == SELFID_PORT_PARENT) || | |
327 | (sid->port2 == SELFID_PORT_PARENT)) { | |
1da177e4 LT |
328 | HPSB_INFO("SelfIDs failed root check"); |
329 | return 0; | |
741854e4 | 330 | } |
1da177e4 LT |
331 | |
332 | host->node_count = nodeid + 1; | |
741854e4 | 333 | return 1; |
1da177e4 LT |
334 | } |
335 | ||
336 | static void build_speed_map(struct hpsb_host *host, int nodecount) | |
337 | { | |
1da177e4 | 338 | u8 cldcnt[nodecount]; |
741854e4 | 339 | u8 *map = host->speed_map; |
647dcb5f | 340 | u8 *speedcap = host->speed; |
741854e4 SR |
341 | struct selfid *sid; |
342 | struct ext_selfid *esid; | |
343 | int i, j, n; | |
344 | ||
345 | for (i = 0; i < (nodecount * 64); i += 64) { | |
346 | for (j = 0; j < nodecount; j++) { | |
347 | map[i+j] = IEEE1394_SPEED_MAX; | |
348 | } | |
349 | } | |
350 | ||
351 | for (i = 0; i < nodecount; i++) { | |
352 | cldcnt[i] = 0; | |
353 | } | |
354 | ||
355 | /* find direct children count and speed */ | |
356 | for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1], | |
357 | n = nodecount - 1; | |
358 | (void *)sid >= (void *)host->topology_map; sid--) { | |
359 | if (sid->extended) { | |
360 | esid = (struct ext_selfid *)sid; | |
1da177e4 | 361 | |
d7758461 SR |
362 | if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++; |
363 | if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++; | |
364 | if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++; | |
365 | if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++; | |
366 | if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++; | |
367 | if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++; | |
368 | if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++; | |
369 | if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++; | |
1da177e4 | 370 | } else { |
d7758461 SR |
371 | if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++; |
372 | if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++; | |
373 | if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++; | |
1da177e4 | 374 | |
741854e4 SR |
375 | speedcap[n] = sid->speed; |
376 | n--; | |
377 | } | |
378 | } | |
379 | ||
380 | /* set self mapping */ | |
381 | for (i = 0; i < nodecount; i++) { | |
382 | map[64*i + i] = speedcap[i]; | |
383 | } | |
384 | ||
385 | /* fix up direct children count to total children count; | |
386 | * also fix up speedcaps for sibling and parent communication */ | |
387 | for (i = 1; i < nodecount; i++) { | |
388 | for (j = cldcnt[i], n = i - 1; j > 0; j--) { | |
389 | cldcnt[i] += cldcnt[n]; | |
390 | speedcap[n] = min(speedcap[n], speedcap[i]); | |
391 | n -= cldcnt[n] + 1; | |
392 | } | |
393 | } | |
394 | ||
395 | for (n = 0; n < nodecount; n++) { | |
396 | for (i = n - cldcnt[n]; i <= n; i++) { | |
397 | for (j = 0; j < (n - cldcnt[n]); j++) { | |
398 | map[j*64 + i] = map[i*64 + j] = | |
399 | min(map[i*64 + j], speedcap[n]); | |
400 | } | |
401 | for (j = n + 1; j < nodecount; j++) { | |
402 | map[j*64 + i] = map[i*64 + j] = | |
403 | min(map[i*64 + j], speedcap[n]); | |
404 | } | |
405 | } | |
406 | } | |
647dcb5f | 407 | |
433a87d5 | 408 | #if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX |
647dcb5f BC |
409 | /* assume maximum speed for 1394b PHYs, nodemgr will correct it */ |
410 | for (n = 0; n < nodecount; n++) | |
433a87d5 | 411 | if (speedcap[n] == SELFID_SPEED_UNKNOWN) |
647dcb5f | 412 | speedcap[n] = IEEE1394_SPEED_MAX; |
433a87d5 | 413 | #endif |
1da177e4 LT |
414 | } |
415 | ||
416 | ||
afd6546d SR |
417 | /** |
418 | * hpsb_selfid_received - hand over received selfid packet to the core | |
419 | * | |
420 | * For host driver module usage. Safe to use in interrupt context. | |
421 | * | |
422 | * The host driver should have done a successful complement check (second | |
423 | * quadlet is complement of first) beforehand. | |
424 | */ | |
1da177e4 LT |
425 | void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) |
426 | { | |
741854e4 SR |
427 | if (host->in_bus_reset) { |
428 | HPSB_VERBOSE("Including SelfID 0x%x", sid); | |
429 | host->topology_map[host->selfid_count++] = sid; | |
430 | } else { | |
431 | HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", | |
1da177e4 | 432 | sid, NODEID_TO_BUS(host->node_id)); |
741854e4 | 433 | } |
1da177e4 LT |
434 | } |
435 | ||
afd6546d SR |
436 | /** |
437 | * hpsb_selfid_complete - notify completion of SelfID stage to the core | |
438 | * | |
439 | * For host driver module usage. Safe to use in interrupt context, although | |
440 | * quite complex; so you may want to run it in the bottom rather than top half. | |
441 | * | |
442 | * Notify completion of SelfID stage to the core and report new physical ID | |
443 | * and whether host is root now. | |
444 | */ | |
1da177e4 LT |
445 | void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) |
446 | { | |
447 | if (!host->in_bus_reset) | |
448 | HPSB_NOTICE("SelfID completion called outside of bus reset!"); | |
449 | ||
741854e4 SR |
450 | host->node_id = LOCAL_BUS | phyid; |
451 | host->is_root = isroot; | |
1da177e4 | 452 | |
741854e4 SR |
453 | if (!check_selfids(host)) { |
454 | if (host->reset_retries++ < 20) { | |
455 | /* selfid stage did not complete without error */ | |
456 | HPSB_NOTICE("Error in SelfID stage, resetting"); | |
1da177e4 LT |
457 | host->in_bus_reset = 0; |
458 | /* this should work from ohci1394 now... */ | |
741854e4 SR |
459 | hpsb_reset_bus(host, LONG_RESET); |
460 | return; | |
461 | } else { | |
462 | HPSB_NOTICE("Stopping out-of-control reset loop"); | |
463 | HPSB_NOTICE("Warning - topology map and speed map will not be valid"); | |
1da177e4 | 464 | host->reset_retries = 0; |
741854e4 SR |
465 | } |
466 | } else { | |
1da177e4 | 467 | host->reset_retries = 0; |
741854e4 SR |
468 | build_speed_map(host, host->node_count); |
469 | } | |
1da177e4 LT |
470 | |
471 | HPSB_VERBOSE("selfid_complete called with successful SelfID stage " | |
472 | "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id); | |
473 | ||
741854e4 SR |
474 | /* irm_id is kept up to date by check_selfids() */ |
475 | if (host->irm_id == host->node_id) { | |
476 | host->is_irm = 1; | |
477 | } else { | |
478 | host->is_busmgr = 0; | |
479 | host->is_irm = 0; | |
480 | } | |
1da177e4 | 481 | |
741854e4 | 482 | if (isroot) { |
1da177e4 LT |
483 | host->driver->devctl(host, ACT_CYCLE_MASTER, 1); |
484 | host->is_cycmst = 1; | |
485 | } | |
486 | atomic_inc(&host->generation); | |
487 | host->in_bus_reset = 0; | |
741854e4 | 488 | highlevel_host_reset(host); |
1da177e4 LT |
489 | } |
490 | ||
002a98f1 | 491 | static DEFINE_SPINLOCK(pending_packets_lock); |
7542e0e6 | 492 | |
afd6546d SR |
493 | /** |
494 | * hpsb_packet_sent - notify core of sending a packet | |
495 | * | |
496 | * For host driver module usage. Safe to call from within a transmit packet | |
497 | * routine. | |
498 | * | |
499 | * Notify core of sending a packet. Ackcode is the ack code returned for async | |
500 | * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE | |
501 | * for other cases (internal errors that don't justify a panic). | |
502 | */ | |
1da177e4 | 503 | void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, |
741854e4 | 504 | int ackcode) |
1da177e4 LT |
505 | { |
506 | unsigned long flags; | |
507 | ||
7542e0e6 | 508 | spin_lock_irqsave(&pending_packets_lock, flags); |
1da177e4 LT |
509 | |
510 | packet->ack_code = ackcode; | |
511 | ||
512 | if (packet->no_waiter || packet->state == hpsb_complete) { | |
513 | /* if packet->no_waiter, must not have a tlabel allocated */ | |
7542e0e6 | 514 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 LT |
515 | hpsb_free_packet(packet); |
516 | return; | |
517 | } | |
518 | ||
519 | atomic_dec(&packet->refcnt); /* drop HC's reference */ | |
7542e0e6 | 520 | /* here the packet must be on the host->pending_packets queue */ |
1da177e4 LT |
521 | |
522 | if (ackcode != ACK_PENDING || !packet->expect_response) { | |
523 | packet->state = hpsb_complete; | |
7542e0e6 SR |
524 | list_del_init(&packet->queue); |
525 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
526 | queue_packet_complete(packet); |
527 | return; | |
528 | } | |
529 | ||
530 | packet->state = hpsb_pending; | |
531 | packet->sendtime = jiffies; | |
532 | ||
7542e0e6 | 533 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 LT |
534 | |
535 | mod_timer(&host->timeout, jiffies + host->timeout_interval); | |
536 | } | |
537 | ||
538 | /** | |
539 | * hpsb_send_phy_config - transmit a PHY configuration packet on the bus | |
540 | * @host: host that PHY config packet gets sent through | |
541 | * @rootid: root whose force_root bit should get set (-1 = don't set force_root) | |
542 | * @gapcnt: gap count value to set (-1 = don't set gap count) | |
543 | * | |
afd6546d SR |
544 | * This function sends a PHY config packet on the bus through the specified |
545 | * host. | |
1da177e4 | 546 | * |
afd6546d | 547 | * Return value: 0 for success or negative error number otherwise. |
1da177e4 LT |
548 | */ |
549 | int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) | |
550 | { | |
551 | struct hpsb_packet *packet; | |
546513f9 | 552 | quadlet_t d = 0; |
1da177e4 LT |
553 | int retval = 0; |
554 | ||
555 | if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || | |
556 | (rootid == -1 && gapcnt == -1)) { | |
557 | HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", | |
558 | rootid, gapcnt); | |
559 | return -EINVAL; | |
560 | } | |
561 | ||
1da177e4 | 562 | if (rootid != -1) |
546513f9 | 563 | d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT; |
1da177e4 | 564 | if (gapcnt != -1) |
546513f9 | 565 | d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT; |
1da177e4 | 566 | |
546513f9 SR |
567 | packet = hpsb_make_phypacket(host, d); |
568 | if (!packet) | |
569 | return -ENOMEM; | |
1da177e4 LT |
570 | |
571 | packet->generation = get_hpsb_generation(host); | |
1da177e4 LT |
572 | retval = hpsb_send_packet_and_wait(packet); |
573 | hpsb_free_packet(packet); | |
574 | ||
575 | return retval; | |
576 | } | |
577 | ||
578 | /** | |
579 | * hpsb_send_packet - transmit a packet on the bus | |
580 | * @packet: packet to send | |
581 | * | |
582 | * The packet is sent through the host specified in the packet->host field. | |
583 | * Before sending, the packet's transmit speed is automatically determined | |
584 | * using the local speed map when it is an async, non-broadcast packet. | |
585 | * | |
586 | * Possibilities for failure are that host is either not initialized, in bus | |
587 | * reset, the packet's generation number doesn't match the current generation | |
588 | * number or the host reports a transmit error. | |
589 | * | |
590 | * Return value: 0 on success, negative errno on failure. | |
591 | */ | |
592 | int hpsb_send_packet(struct hpsb_packet *packet) | |
593 | { | |
594 | struct hpsb_host *host = packet->host; | |
595 | ||
741854e4 | 596 | if (host->is_shutdown) |
1da177e4 LT |
597 | return -EINVAL; |
598 | if (host->in_bus_reset || | |
599 | (packet->generation != get_hpsb_generation(host))) | |
741854e4 | 600 | return -EAGAIN; |
1da177e4 | 601 | |
741854e4 | 602 | packet->state = hpsb_queued; |
1da177e4 LT |
603 | |
604 | /* This just seems silly to me */ | |
605 | WARN_ON(packet->no_waiter && packet->expect_response); | |
606 | ||
607 | if (!packet->no_waiter || packet->expect_response) { | |
7542e0e6 SR |
608 | unsigned long flags; |
609 | ||
1da177e4 | 610 | atomic_inc(&packet->refcnt); |
1934b8b6 BC |
611 | /* Set the initial "sendtime" to 10 seconds from now, to |
612 | prevent premature expiry. If a packet takes more than | |
613 | 10 seconds to hit the wire, we have bigger problems :) */ | |
6262d062 | 614 | packet->sendtime = jiffies + 10 * HZ; |
7542e0e6 SR |
615 | spin_lock_irqsave(&pending_packets_lock, flags); |
616 | list_add_tail(&packet->queue, &host->pending_packets); | |
617 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
618 | } |
619 | ||
741854e4 | 620 | if (packet->node_id == host->node_id) { |
1da177e4 LT |
621 | /* it is a local request, so handle it locally */ |
622 | ||
741854e4 SR |
623 | quadlet_t *data; |
624 | size_t size = packet->data_size + packet->header_size; | |
1da177e4 | 625 | |
741854e4 SR |
626 | data = kmalloc(size, GFP_ATOMIC); |
627 | if (!data) { | |
628 | HPSB_ERR("unable to allocate memory for concatenating header and data"); | |
629 | return -ENOMEM; | |
630 | } | |
1da177e4 | 631 | |
741854e4 | 632 | memcpy(data, packet->header, packet->header_size); |
1da177e4 | 633 | |
741854e4 | 634 | if (packet->data_size) |
1da177e4 LT |
635 | memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size); |
636 | ||
741854e4 | 637 | dump_packet("send packet local", packet->header, packet->header_size, -1); |
1da177e4 | 638 | |
741854e4 SR |
639 | hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE); |
640 | hpsb_packet_received(host, data, size, 0); | |
1da177e4 | 641 | |
741854e4 | 642 | kfree(data); |
1da177e4 | 643 | |
741854e4 SR |
644 | return 0; |
645 | } | |
1da177e4 | 646 | |
647dcb5f BC |
647 | if (packet->type == hpsb_async && |
648 | NODEID_TO_NODE(packet->node_id) != ALL_NODES) | |
741854e4 | 649 | packet->speed_code = |
647dcb5f | 650 | host->speed[NODEID_TO_NODE(packet->node_id)]; |
1da177e4 | 651 | |
741854e4 | 652 | dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); |
1da177e4 | 653 | |
741854e4 | 654 | return host->driver->transmit_packet(host, packet); |
1da177e4 LT |
655 | } |
656 | ||
657 | /* We could just use complete() directly as the packet complete | |
658 | * callback, but this is more typesafe, in the sense that we get a | |
659 | * compiler error if the prototype for complete() changes. */ | |
660 | ||
661 | static void complete_packet(void *data) | |
662 | { | |
663 | complete((struct completion *) data); | |
664 | } | |
665 | ||
afd6546d SR |
666 | /** |
667 | * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes | |
668 | * @packet: packet to send | |
669 | * | |
670 | * Return value: 0 on success, negative errno on failure. | |
671 | */ | |
1da177e4 LT |
672 | int hpsb_send_packet_and_wait(struct hpsb_packet *packet) |
673 | { | |
674 | struct completion done; | |
675 | int retval; | |
676 | ||
677 | init_completion(&done); | |
678 | hpsb_set_packet_complete_task(packet, complete_packet, &done); | |
679 | retval = hpsb_send_packet(packet); | |
680 | if (retval == 0) | |
681 | wait_for_completion(&done); | |
682 | ||
683 | return retval; | |
684 | } | |
685 | ||
686 | static void send_packet_nocare(struct hpsb_packet *packet) | |
687 | { | |
741854e4 SR |
688 | if (hpsb_send_packet(packet) < 0) { |
689 | hpsb_free_packet(packet); | |
690 | } | |
1da177e4 LT |
691 | } |
692 | ||
7542e0e6 SR |
693 | static size_t packet_size_to_data_size(size_t packet_size, size_t header_size, |
694 | size_t buffer_size, int tcode) | |
695 | { | |
696 | size_t ret = packet_size <= header_size ? 0 : packet_size - header_size; | |
697 | ||
698 | if (unlikely(ret > buffer_size)) | |
699 | ret = buffer_size; | |
700 | ||
701 | if (unlikely(ret + header_size != packet_size)) | |
504945c9 | 702 | HPSB_ERR("unexpected packet size %zd (tcode %d), bug?", |
7542e0e6 SR |
703 | packet_size, tcode); |
704 | return ret; | |
705 | } | |
1da177e4 LT |
706 | |
707 | static void handle_packet_response(struct hpsb_host *host, int tcode, | |
708 | quadlet_t *data, size_t size) | |
709 | { | |
7542e0e6 SR |
710 | struct hpsb_packet *packet; |
711 | int tlabel = (data[0] >> 10) & 0x3f; | |
712 | size_t header_size; | |
741854e4 | 713 | unsigned long flags; |
1da177e4 | 714 | |
7542e0e6 | 715 | spin_lock_irqsave(&pending_packets_lock, flags); |
1da177e4 | 716 | |
7542e0e6 SR |
717 | list_for_each_entry(packet, &host->pending_packets, queue) |
718 | if (packet->tlabel == tlabel && | |
719 | packet->node_id == (data[1] >> 16)) | |
720 | goto found; | |
1da177e4 | 721 | |
7542e0e6 SR |
722 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
723 | HPSB_DEBUG("unsolicited response packet received - %s", | |
724 | "no tlabel match"); | |
725 | dump_packet("contents", data, 16, -1); | |
726 | return; | |
1da177e4 | 727 | |
7542e0e6 | 728 | found: |
741854e4 SR |
729 | switch (packet->tcode) { |
730 | case TCODE_WRITEQ: | |
731 | case TCODE_WRITEB: | |
7542e0e6 | 732 | if (unlikely(tcode != TCODE_WRITE_RESPONSE)) |
1da177e4 | 733 | break; |
7542e0e6 SR |
734 | header_size = 12; |
735 | size = 0; | |
736 | goto dequeue; | |
737 | ||
741854e4 | 738 | case TCODE_READQ: |
7542e0e6 | 739 | if (unlikely(tcode != TCODE_READQ_RESPONSE)) |
1da177e4 | 740 | break; |
7542e0e6 SR |
741 | header_size = 16; |
742 | size = 0; | |
743 | goto dequeue; | |
744 | ||
741854e4 | 745 | case TCODE_READB: |
7542e0e6 | 746 | if (unlikely(tcode != TCODE_READB_RESPONSE)) |
1da177e4 | 747 | break; |
7542e0e6 SR |
748 | header_size = 16; |
749 | size = packet_size_to_data_size(size, header_size, | |
750 | packet->allocated_data_size, | |
751 | tcode); | |
752 | goto dequeue; | |
753 | ||
741854e4 | 754 | case TCODE_LOCK_REQUEST: |
7542e0e6 | 755 | if (unlikely(tcode != TCODE_LOCK_RESPONSE)) |
1da177e4 | 756 | break; |
7542e0e6 SR |
757 | header_size = 16; |
758 | size = packet_size_to_data_size(min(size, (size_t)(16 + 8)), | |
759 | header_size, | |
760 | packet->allocated_data_size, | |
761 | tcode); | |
762 | goto dequeue; | |
741854e4 | 763 | } |
1da177e4 | 764 | |
7542e0e6 SR |
765 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
766 | HPSB_DEBUG("unsolicited response packet received - %s", | |
767 | "tcode mismatch"); | |
768 | dump_packet("contents", data, 16, -1); | |
769 | return; | |
1da177e4 | 770 | |
7542e0e6 SR |
771 | dequeue: |
772 | list_del_init(&packet->queue); | |
773 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
774 | |
775 | if (packet->state == hpsb_queued) { | |
776 | packet->sendtime = jiffies; | |
777 | packet->ack_code = ACK_PENDING; | |
778 | } | |
1da177e4 | 779 | packet->state = hpsb_complete; |
7542e0e6 SR |
780 | |
781 | memcpy(packet->header, data, header_size); | |
782 | if (size) | |
783 | memcpy(packet->data, data + 4, size); | |
1da177e4 LT |
784 | |
785 | queue_packet_complete(packet); | |
786 | } | |
787 | ||
788 | ||
789 | static struct hpsb_packet *create_reply_packet(struct hpsb_host *host, | |
790 | quadlet_t *data, size_t dsize) | |
791 | { | |
741854e4 | 792 | struct hpsb_packet *p; |
1da177e4 | 793 | |
741854e4 SR |
794 | p = hpsb_alloc_packet(dsize); |
795 | if (unlikely(p == NULL)) { | |
796 | /* FIXME - send data_error response */ | |
7542e0e6 | 797 | HPSB_ERR("out of memory, cannot send response packet"); |
741854e4 SR |
798 | return NULL; |
799 | } | |
1da177e4 | 800 | |
741854e4 SR |
801 | p->type = hpsb_async; |
802 | p->state = hpsb_unused; | |
803 | p->host = host; | |
804 | p->node_id = data[1] >> 16; | |
805 | p->tlabel = (data[0] >> 10) & 0x3f; | |
806 | p->no_waiter = 1; | |
1da177e4 LT |
807 | |
808 | p->generation = get_hpsb_generation(host); | |
809 | ||
810 | if (dsize % 4) | |
811 | p->data[dsize / 4] = 0; | |
812 | ||
741854e4 | 813 | return p; |
1da177e4 LT |
814 | } |
815 | ||
816 | #define PREP_ASYNC_HEAD_RCODE(tc) \ | |
817 | packet->tcode = tc; \ | |
818 | packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ | |
819 | | (1 << 8) | (tc << 4); \ | |
820 | packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \ | |
821 | packet->header[2] = 0 | |
822 | ||
823 | static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, | |
741854e4 | 824 | quadlet_t data) |
1da177e4 LT |
825 | { |
826 | PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE); | |
827 | packet->header[3] = data; | |
828 | packet->header_size = 16; | |
829 | packet->data_size = 0; | |
830 | } | |
831 | ||
832 | static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, | |
741854e4 | 833 | int length) |
1da177e4 LT |
834 | { |
835 | if (rcode != RCODE_COMPLETE) | |
836 | length = 0; | |
837 | ||
838 | PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); | |
839 | packet->header[3] = length << 16; | |
840 | packet->header_size = 16; | |
841 | packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); | |
842 | } | |
843 | ||
844 | static void fill_async_write_resp(struct hpsb_packet *packet, int rcode) | |
845 | { | |
846 | PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); | |
1da177e4 LT |
847 | packet->header_size = 12; |
848 | packet->data_size = 0; | |
849 | } | |
850 | ||
851 | static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, | |
741854e4 | 852 | int length) |
1da177e4 LT |
853 | { |
854 | if (rcode != RCODE_COMPLETE) | |
855 | length = 0; | |
856 | ||
857 | PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE); | |
858 | packet->header[3] = (length << 16) | extcode; | |
859 | packet->header_size = 16; | |
860 | packet->data_size = length; | |
861 | } | |
862 | ||
1da177e4 | 863 | static void handle_incoming_packet(struct hpsb_host *host, int tcode, |
d4c60085 SR |
864 | quadlet_t *data, size_t size, |
865 | int write_acked) | |
1da177e4 | 866 | { |
741854e4 SR |
867 | struct hpsb_packet *packet; |
868 | int length, rcode, extcode; | |
869 | quadlet_t buffer; | |
870 | nodeid_t source = data[1] >> 16; | |
871 | nodeid_t dest = data[0] >> 16; | |
872 | u16 flags = (u16) data[0]; | |
873 | u64 addr; | |
874 | ||
d4c60085 SR |
875 | /* FIXME? |
876 | * Out-of-bounds lengths are left for highlevel_read|write to cap. */ | |
741854e4 SR |
877 | |
878 | switch (tcode) { | |
879 | case TCODE_WRITEQ: | |
880 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
d4c60085 | 881 | rcode = highlevel_write(host, source, dest, data + 3, |
1da177e4 | 882 | addr, 4, flags); |
d4c60085 | 883 | goto handle_write_request; |
741854e4 SR |
884 | |
885 | case TCODE_WRITEB: | |
886 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
d4c60085 SR |
887 | rcode = highlevel_write(host, source, dest, data + 4, |
888 | addr, data[3] >> 16, flags); | |
889 | handle_write_request: | |
890 | if (rcode < 0 || write_acked || | |
891 | NODEID_TO_NODE(data[0] >> 16) == NODE_MASK) | |
892 | return; | |
893 | /* not a broadcast write, reply */ | |
894 | packet = create_reply_packet(host, data, 0); | |
895 | if (packet) { | |
741854e4 SR |
896 | fill_async_write_resp(packet, rcode); |
897 | send_packet_nocare(packet); | |
898 | } | |
d4c60085 | 899 | return; |
741854e4 SR |
900 | |
901 | case TCODE_READQ: | |
902 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
903 | rcode = highlevel_read(host, source, &buffer, addr, 4, flags); | |
d4c60085 SR |
904 | if (rcode < 0) |
905 | return; | |
741854e4 | 906 | |
d4c60085 SR |
907 | packet = create_reply_packet(host, data, 0); |
908 | if (packet) { | |
741854e4 SR |
909 | fill_async_readquad_resp(packet, rcode, buffer); |
910 | send_packet_nocare(packet); | |
911 | } | |
d4c60085 | 912 | return; |
741854e4 SR |
913 | |
914 | case TCODE_READB: | |
915 | length = data[3] >> 16; | |
d4c60085 SR |
916 | packet = create_reply_packet(host, data, length); |
917 | if (!packet) | |
918 | return; | |
741854e4 SR |
919 | |
920 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
921 | rcode = highlevel_read(host, source, packet->data, addr, | |
922 | length, flags); | |
d4c60085 | 923 | if (rcode < 0) { |
741854e4 | 924 | hpsb_free_packet(packet); |
d4c60085 | 925 | return; |
741854e4 | 926 | } |
d4c60085 SR |
927 | fill_async_readblock_resp(packet, rcode, length); |
928 | send_packet_nocare(packet); | |
929 | return; | |
741854e4 SR |
930 | |
931 | case TCODE_LOCK_REQUEST: | |
932 | length = data[3] >> 16; | |
933 | extcode = data[3] & 0xffff; | |
934 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
935 | ||
d4c60085 SR |
936 | packet = create_reply_packet(host, data, 8); |
937 | if (!packet) | |
938 | return; | |
741854e4 | 939 | |
d4c60085 | 940 | if (extcode == 0 || extcode >= 7) { |
741854e4 SR |
941 | /* let switch default handle error */ |
942 | length = 0; | |
943 | } | |
944 | ||
945 | switch (length) { | |
946 | case 4: | |
947 | rcode = highlevel_lock(host, source, packet->data, addr, | |
d4c60085 | 948 | data[4], 0, extcode, flags); |
741854e4 SR |
949 | fill_async_lock_resp(packet, rcode, extcode, 4); |
950 | break; | |
951 | case 8: | |
d4c60085 SR |
952 | if (extcode != EXTCODE_FETCH_ADD && |
953 | extcode != EXTCODE_LITTLE_ADD) { | |
741854e4 SR |
954 | rcode = highlevel_lock(host, source, |
955 | packet->data, addr, | |
956 | data[5], data[4], | |
957 | extcode, flags); | |
958 | fill_async_lock_resp(packet, rcode, extcode, 4); | |
959 | } else { | |
960 | rcode = highlevel_lock64(host, source, | |
961 | (octlet_t *)packet->data, addr, | |
962 | *(octlet_t *)(data + 4), 0ULL, | |
963 | extcode, flags); | |
964 | fill_async_lock_resp(packet, rcode, extcode, 8); | |
965 | } | |
966 | break; | |
967 | case 16: | |
968 | rcode = highlevel_lock64(host, source, | |
969 | (octlet_t *)packet->data, addr, | |
970 | *(octlet_t *)(data + 6), | |
971 | *(octlet_t *)(data + 4), | |
972 | extcode, flags); | |
973 | fill_async_lock_resp(packet, rcode, extcode, 8); | |
974 | break; | |
975 | default: | |
976 | rcode = RCODE_TYPE_ERROR; | |
d4c60085 | 977 | fill_async_lock_resp(packet, rcode, extcode, 0); |
741854e4 SR |
978 | } |
979 | ||
d4c60085 | 980 | if (rcode < 0) |
741854e4 | 981 | hpsb_free_packet(packet); |
d4c60085 SR |
982 | else |
983 | send_packet_nocare(packet); | |
984 | return; | |
741854e4 | 985 | } |
1da177e4 | 986 | } |
1da177e4 | 987 | |
afd6546d SR |
988 | /** |
989 | * hpsb_packet_received - hand over received packet to the core | |
990 | * | |
991 | * For host driver module usage. | |
992 | * | |
993 | * The contents of data are expected to be the full packet but with the CRCs | |
994 | * left out (data block follows header immediately), with the header (i.e. the | |
995 | * first four quadlets) in machine byte order and the data block in big endian. | |
996 | * *@data can be safely overwritten after this call. | |
997 | * | |
998 | * If the packet is a write request, @write_acked is to be set to true if it was | |
999 | * ack_complete'd already, false otherwise. This argument is ignored for any | |
1000 | * other packet type. | |
1001 | */ | |
1da177e4 | 1002 | void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, |
741854e4 | 1003 | int write_acked) |
1da177e4 | 1004 | { |
741854e4 SR |
1005 | int tcode; |
1006 | ||
7542e0e6 SR |
1007 | if (unlikely(host->in_bus_reset)) { |
1008 | HPSB_DEBUG("received packet during reset; ignoring"); | |
741854e4 SR |
1009 | return; |
1010 | } | |
1011 | ||
1012 | dump_packet("received packet", data, size, -1); | |
1013 | ||
1014 | tcode = (data[0] >> 4) & 0xf; | |
1015 | ||
1016 | switch (tcode) { | |
1017 | case TCODE_WRITE_RESPONSE: | |
1018 | case TCODE_READQ_RESPONSE: | |
1019 | case TCODE_READB_RESPONSE: | |
1020 | case TCODE_LOCK_RESPONSE: | |
1021 | handle_packet_response(host, tcode, data, size); | |
1022 | break; | |
1023 | ||
1024 | case TCODE_WRITEQ: | |
1025 | case TCODE_WRITEB: | |
1026 | case TCODE_READQ: | |
1027 | case TCODE_READB: | |
1028 | case TCODE_LOCK_REQUEST: | |
1029 | handle_incoming_packet(host, tcode, data, size, write_acked); | |
1030 | break; | |
1031 | ||
741854e4 SR |
1032 | case TCODE_CYCLE_START: |
1033 | /* simply ignore this packet if it is passed on */ | |
1034 | break; | |
1035 | ||
1036 | default: | |
7542e0e6 SR |
1037 | HPSB_DEBUG("received packet with bogus transaction code %d", |
1038 | tcode); | |
741854e4 SR |
1039 | break; |
1040 | } | |
1da177e4 LT |
1041 | } |
1042 | ||
1da177e4 LT |
1043 | static void abort_requests(struct hpsb_host *host) |
1044 | { | |
7542e0e6 SR |
1045 | struct hpsb_packet *packet, *p; |
1046 | struct list_head tmp; | |
1047 | unsigned long flags; | |
1da177e4 LT |
1048 | |
1049 | host->driver->devctl(host, CANCEL_REQUESTS, 0); | |
1050 | ||
7542e0e6 SR |
1051 | INIT_LIST_HEAD(&tmp); |
1052 | spin_lock_irqsave(&pending_packets_lock, flags); | |
1053 | list_splice_init(&host->pending_packets, &tmp); | |
1054 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 | 1055 | |
7542e0e6 SR |
1056 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1057 | list_del_init(&packet->queue); | |
1da177e4 LT |
1058 | packet->state = hpsb_complete; |
1059 | packet->ack_code = ACKX_ABORTED; | |
1060 | queue_packet_complete(packet); | |
1061 | } | |
1062 | } | |
1063 | ||
1064 | void abort_timedouts(unsigned long __opaque) | |
1065 | { | |
1066 | struct hpsb_host *host = (struct hpsb_host *)__opaque; | |
7542e0e6 SR |
1067 | struct hpsb_packet *packet, *p; |
1068 | struct list_head tmp; | |
1069 | unsigned long flags, expire, j; | |
1da177e4 LT |
1070 | |
1071 | spin_lock_irqsave(&host->csr.lock, flags); | |
1072 | expire = host->csr.expire; | |
1073 | spin_unlock_irqrestore(&host->csr.lock, flags); | |
1074 | ||
7542e0e6 SR |
1075 | j = jiffies; |
1076 | INIT_LIST_HEAD(&tmp); | |
1077 | spin_lock_irqsave(&pending_packets_lock, flags); | |
1da177e4 | 1078 | |
7542e0e6 SR |
1079 | list_for_each_entry_safe(packet, p, &host->pending_packets, queue) { |
1080 | if (time_before(packet->sendtime + expire, j)) | |
1081 | list_move_tail(&packet->queue, &tmp); | |
1082 | else | |
1da177e4 LT |
1083 | /* Since packets are added to the tail, the oldest |
1084 | * ones are first, always. When we get to one that | |
1085 | * isn't timed out, the rest aren't either. */ | |
1086 | break; | |
1da177e4 | 1087 | } |
7542e0e6 SR |
1088 | if (!list_empty(&host->pending_packets)) |
1089 | mod_timer(&host->timeout, j + host->timeout_interval); | |
1da177e4 | 1090 | |
7542e0e6 | 1091 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 | 1092 | |
7542e0e6 SR |
1093 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1094 | list_del_init(&packet->queue); | |
1095 | packet->state = hpsb_complete; | |
1096 | packet->ack_code = ACKX_TIMEOUT; | |
1097 | queue_packet_complete(packet); | |
1098 | } | |
1da177e4 LT |
1099 | } |
1100 | ||
f654240f | 1101 | static struct task_struct *khpsbpkt_thread; |
7542e0e6 | 1102 | static LIST_HEAD(hpsbpkt_queue); |
1da177e4 LT |
1103 | |
1104 | static void queue_packet_complete(struct hpsb_packet *packet) | |
1105 | { | |
7542e0e6 SR |
1106 | unsigned long flags; |
1107 | ||
1da177e4 LT |
1108 | if (packet->no_waiter) { |
1109 | hpsb_free_packet(packet); | |
1110 | return; | |
1111 | } | |
1112 | if (packet->complete_routine != NULL) { | |
7542e0e6 SR |
1113 | spin_lock_irqsave(&pending_packets_lock, flags); |
1114 | list_add_tail(&packet->queue, &hpsbpkt_queue); | |
1115 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
f654240f | 1116 | wake_up_process(khpsbpkt_thread); |
1da177e4 LT |
1117 | } |
1118 | return; | |
1119 | } | |
1120 | ||
7542e0e6 SR |
1121 | /* |
1122 | * Kernel thread which handles packets that are completed. This way the | |
1123 | * packet's "complete" function is asynchronously run in process context. | |
1124 | * Only packets which have a "complete" function may be sent here. | |
1125 | */ | |
1da177e4 LT |
1126 | static int hpsbpkt_thread(void *__hi) |
1127 | { | |
7542e0e6 SR |
1128 | struct hpsb_packet *packet, *p; |
1129 | struct list_head tmp; | |
1130 | int may_schedule; | |
1da177e4 | 1131 | |
f654240f | 1132 | while (!kthread_should_stop()) { |
1da177e4 | 1133 | |
7542e0e6 SR |
1134 | INIT_LIST_HEAD(&tmp); |
1135 | spin_lock_irq(&pending_packets_lock); | |
1136 | list_splice_init(&hpsbpkt_queue, &tmp); | |
1137 | spin_unlock_irq(&pending_packets_lock); | |
1da177e4 | 1138 | |
7542e0e6 SR |
1139 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1140 | list_del_init(&packet->queue); | |
1141 | packet->complete_routine(packet->complete_data); | |
1da177e4 | 1142 | } |
1da177e4 | 1143 | |
f654240f | 1144 | set_current_state(TASK_INTERRUPTIBLE); |
7542e0e6 SR |
1145 | spin_lock_irq(&pending_packets_lock); |
1146 | may_schedule = list_empty(&hpsbpkt_queue); | |
1147 | spin_unlock_irq(&pending_packets_lock); | |
1148 | if (may_schedule) | |
f654240f BC |
1149 | schedule(); |
1150 | __set_current_state(TASK_RUNNING); | |
1151 | } | |
1152 | return 0; | |
1da177e4 LT |
1153 | } |
1154 | ||
1155 | static int __init ieee1394_init(void) | |
1156 | { | |
1157 | int i, ret; | |
1158 | ||
1da177e4 LT |
1159 | /* non-fatal error */ |
1160 | if (hpsb_init_config_roms()) { | |
1161 | HPSB_ERR("Failed to initialize some config rom entries.\n"); | |
1162 | HPSB_ERR("Some features may not be available\n"); | |
1163 | } | |
1164 | ||
f654240f BC |
1165 | khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt"); |
1166 | if (IS_ERR(khpsbpkt_thread)) { | |
1da177e4 | 1167 | HPSB_ERR("Failed to start hpsbpkt thread!\n"); |
f654240f | 1168 | ret = PTR_ERR(khpsbpkt_thread); |
1da177e4 LT |
1169 | goto exit_cleanup_config_roms; |
1170 | } | |
1171 | ||
1172 | if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) { | |
1173 | HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); | |
1174 | ret = -ENODEV; | |
1175 | goto exit_release_kernel_thread; | |
1176 | } | |
1177 | ||
1da177e4 LT |
1178 | ret = bus_register(&ieee1394_bus_type); |
1179 | if (ret < 0) { | |
1180 | HPSB_INFO("bus register failed"); | |
a8748445 | 1181 | goto release_chrdev; |
1da177e4 LT |
1182 | } |
1183 | ||
1184 | for (i = 0; fw_bus_attrs[i]; i++) { | |
1185 | ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1186 | if (ret < 0) { | |
1187 | while (i >= 0) { | |
1188 | bus_remove_file(&ieee1394_bus_type, | |
1189 | fw_bus_attrs[i--]); | |
1190 | } | |
1191 | bus_unregister(&ieee1394_bus_type); | |
a8748445 | 1192 | goto release_chrdev; |
1da177e4 LT |
1193 | } |
1194 | } | |
1195 | ||
1196 | ret = class_register(&hpsb_host_class); | |
1197 | if (ret < 0) | |
1198 | goto release_all_bus; | |
1199 | ||
7e25ab91 | 1200 | hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol"); |
1da177e4 LT |
1201 | if (IS_ERR(hpsb_protocol_class)) { |
1202 | ret = PTR_ERR(hpsb_protocol_class); | |
1203 | goto release_class_host; | |
1204 | } | |
1205 | ||
1206 | ret = init_csr(); | |
1207 | if (ret) { | |
1208 | HPSB_INFO("init csr failed"); | |
1209 | ret = -ENOMEM; | |
1210 | goto release_class_protocol; | |
1211 | } | |
1212 | ||
1213 | if (disable_nodemgr) { | |
1214 | HPSB_INFO("nodemgr and IRM functionality disabled"); | |
1215 | /* We shouldn't contend for IRM with nodemgr disabled, since | |
1216 | nodemgr implements functionality required of ieee1394a-2000 | |
1217 | IRMs */ | |
1218 | hpsb_disable_irm = 1; | |
741854e4 | 1219 | |
1da177e4 LT |
1220 | return 0; |
1221 | } | |
1222 | ||
1223 | if (hpsb_disable_irm) { | |
1224 | HPSB_INFO("IRM functionality disabled"); | |
1225 | } | |
1226 | ||
1227 | ret = init_ieee1394_nodemgr(); | |
1228 | if (ret < 0) { | |
1229 | HPSB_INFO("init nodemgr failed"); | |
1230 | goto cleanup_csr; | |
1231 | } | |
1232 | ||
1233 | return 0; | |
1234 | ||
1235 | cleanup_csr: | |
1236 | cleanup_csr(); | |
1237 | release_class_protocol: | |
7e25ab91 | 1238 | class_destroy(hpsb_protocol_class); |
1da177e4 LT |
1239 | release_class_host: |
1240 | class_unregister(&hpsb_host_class); | |
1241 | release_all_bus: | |
1242 | for (i = 0; fw_bus_attrs[i]; i++) | |
1243 | bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1244 | bus_unregister(&ieee1394_bus_type); | |
1da177e4 LT |
1245 | release_chrdev: |
1246 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); | |
1247 | exit_release_kernel_thread: | |
f654240f | 1248 | kthread_stop(khpsbpkt_thread); |
1da177e4 LT |
1249 | exit_cleanup_config_roms: |
1250 | hpsb_cleanup_config_roms(); | |
1251 | return ret; | |
1252 | } | |
1253 | ||
1254 | static void __exit ieee1394_cleanup(void) | |
1255 | { | |
1256 | int i; | |
1257 | ||
1258 | if (!disable_nodemgr) | |
1259 | cleanup_ieee1394_nodemgr(); | |
1260 | ||
1261 | cleanup_csr(); | |
1262 | ||
7e25ab91 | 1263 | class_destroy(hpsb_protocol_class); |
1da177e4 LT |
1264 | class_unregister(&hpsb_host_class); |
1265 | for (i = 0; fw_bus_attrs[i]; i++) | |
1266 | bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1267 | bus_unregister(&ieee1394_bus_type); | |
1268 | ||
f654240f | 1269 | kthread_stop(khpsbpkt_thread); |
1da177e4 LT |
1270 | |
1271 | hpsb_cleanup_config_roms(); | |
1272 | ||
1273 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); | |
1da177e4 LT |
1274 | } |
1275 | ||
be7963b7 | 1276 | module_init(ieee1394_init); |
1da177e4 LT |
1277 | module_exit(ieee1394_cleanup); |
1278 | ||
1279 | /* Exported symbols */ | |
1280 | ||
1281 | /** hosts.c **/ | |
1282 | EXPORT_SYMBOL(hpsb_alloc_host); | |
1283 | EXPORT_SYMBOL(hpsb_add_host); | |
3360177c | 1284 | EXPORT_SYMBOL(hpsb_resume_host); |
1da177e4 LT |
1285 | EXPORT_SYMBOL(hpsb_remove_host); |
1286 | EXPORT_SYMBOL(hpsb_update_config_rom_image); | |
1287 | ||
1288 | /** ieee1394_core.c **/ | |
1289 | EXPORT_SYMBOL(hpsb_speedto_str); | |
1290 | EXPORT_SYMBOL(hpsb_protocol_class); | |
1291 | EXPORT_SYMBOL(hpsb_set_packet_complete_task); | |
1292 | EXPORT_SYMBOL(hpsb_alloc_packet); | |
1293 | EXPORT_SYMBOL(hpsb_free_packet); | |
1da177e4 | 1294 | EXPORT_SYMBOL(hpsb_send_packet); |
1da177e4 | 1295 | EXPORT_SYMBOL(hpsb_reset_bus); |
3dc5ea9b | 1296 | EXPORT_SYMBOL(hpsb_read_cycle_timer); |
1da177e4 LT |
1297 | EXPORT_SYMBOL(hpsb_bus_reset); |
1298 | EXPORT_SYMBOL(hpsb_selfid_received); | |
1299 | EXPORT_SYMBOL(hpsb_selfid_complete); | |
1300 | EXPORT_SYMBOL(hpsb_packet_sent); | |
1301 | EXPORT_SYMBOL(hpsb_packet_received); | |
1302 | EXPORT_SYMBOL_GPL(hpsb_disable_irm); | |
1303 | ||
1304 | /** ieee1394_transactions.c **/ | |
1305 | EXPORT_SYMBOL(hpsb_get_tlabel); | |
1306 | EXPORT_SYMBOL(hpsb_free_tlabel); | |
1307 | EXPORT_SYMBOL(hpsb_make_readpacket); | |
1308 | EXPORT_SYMBOL(hpsb_make_writepacket); | |
1309 | EXPORT_SYMBOL(hpsb_make_streampacket); | |
1310 | EXPORT_SYMBOL(hpsb_make_lockpacket); | |
1311 | EXPORT_SYMBOL(hpsb_make_lock64packet); | |
1312 | EXPORT_SYMBOL(hpsb_make_phypacket); | |
1da177e4 LT |
1313 | EXPORT_SYMBOL(hpsb_read); |
1314 | EXPORT_SYMBOL(hpsb_write); | |
1da177e4 LT |
1315 | EXPORT_SYMBOL(hpsb_packet_success); |
1316 | ||
1317 | /** highlevel.c **/ | |
1318 | EXPORT_SYMBOL(hpsb_register_highlevel); | |
1319 | EXPORT_SYMBOL(hpsb_unregister_highlevel); | |
1320 | EXPORT_SYMBOL(hpsb_register_addrspace); | |
1321 | EXPORT_SYMBOL(hpsb_unregister_addrspace); | |
1322 | EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); | |
1da177e4 LT |
1323 | EXPORT_SYMBOL(hpsb_get_hostinfo); |
1324 | EXPORT_SYMBOL(hpsb_create_hostinfo); | |
1325 | EXPORT_SYMBOL(hpsb_destroy_hostinfo); | |
1326 | EXPORT_SYMBOL(hpsb_set_hostinfo_key); | |
1327 | EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); | |
1328 | EXPORT_SYMBOL(hpsb_set_hostinfo); | |
1da177e4 LT |
1329 | |
1330 | /** nodemgr.c **/ | |
1331 | EXPORT_SYMBOL(hpsb_node_fill_packet); | |
1332 | EXPORT_SYMBOL(hpsb_node_write); | |
ed30c26e | 1333 | EXPORT_SYMBOL(__hpsb_register_protocol); |
1da177e4 | 1334 | EXPORT_SYMBOL(hpsb_unregister_protocol); |
1da177e4 LT |
1335 | |
1336 | /** csr.c **/ | |
1337 | EXPORT_SYMBOL(hpsb_update_config_rom); | |
1338 | ||
1339 | /** dma.c **/ | |
1340 | EXPORT_SYMBOL(dma_prog_region_init); | |
1341 | EXPORT_SYMBOL(dma_prog_region_alloc); | |
1342 | EXPORT_SYMBOL(dma_prog_region_free); | |
1343 | EXPORT_SYMBOL(dma_region_init); | |
1344 | EXPORT_SYMBOL(dma_region_alloc); | |
1345 | EXPORT_SYMBOL(dma_region_free); | |
1346 | EXPORT_SYMBOL(dma_region_sync_for_cpu); | |
1347 | EXPORT_SYMBOL(dma_region_sync_for_device); | |
1348 | EXPORT_SYMBOL(dma_region_mmap); | |
1349 | EXPORT_SYMBOL(dma_region_offset_to_bus); | |
1350 | ||
1351 | /** iso.c **/ | |
1352 | EXPORT_SYMBOL(hpsb_iso_xmit_init); | |
1353 | EXPORT_SYMBOL(hpsb_iso_recv_init); | |
1354 | EXPORT_SYMBOL(hpsb_iso_xmit_start); | |
1355 | EXPORT_SYMBOL(hpsb_iso_recv_start); | |
1356 | EXPORT_SYMBOL(hpsb_iso_recv_listen_channel); | |
1357 | EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel); | |
1358 | EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); | |
1359 | EXPORT_SYMBOL(hpsb_iso_stop); | |
1360 | EXPORT_SYMBOL(hpsb_iso_shutdown); | |
1361 | EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); | |
1362 | EXPORT_SYMBOL(hpsb_iso_xmit_sync); | |
1363 | EXPORT_SYMBOL(hpsb_iso_recv_release_packets); | |
1364 | EXPORT_SYMBOL(hpsb_iso_n_ready); | |
1365 | EXPORT_SYMBOL(hpsb_iso_packet_sent); | |
1366 | EXPORT_SYMBOL(hpsb_iso_packet_received); | |
1367 | EXPORT_SYMBOL(hpsb_iso_wake); | |
1368 | EXPORT_SYMBOL(hpsb_iso_recv_flush); | |
1369 | ||
1370 | /** csr1212.c **/ | |
1da177e4 | 1371 | EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); |
1da177e4 | 1372 | EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); |
c1a37f2c SR |
1373 | EXPORT_SYMBOL(csr1212_get_keyval); |
1374 | EXPORT_SYMBOL(csr1212_new_directory); | |
1da177e4 | 1375 | EXPORT_SYMBOL(csr1212_parse_keyval); |
c1a37f2c SR |
1376 | EXPORT_SYMBOL(csr1212_read); |
1377 | EXPORT_SYMBOL(csr1212_release_keyval); |