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", | |
b1ce1fd7 | 245 | __func__); |
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 | 375 | speedcap[n] = sid->speed; |
a6ca4f70 PDM |
376 | if (speedcap[n] > host->csr.lnk_spd) |
377 | speedcap[n] = host->csr.lnk_spd; | |
741854e4 SR |
378 | n--; |
379 | } | |
380 | } | |
381 | ||
382 | /* set self mapping */ | |
383 | for (i = 0; i < nodecount; i++) { | |
384 | map[64*i + i] = speedcap[i]; | |
385 | } | |
386 | ||
387 | /* fix up direct children count to total children count; | |
388 | * also fix up speedcaps for sibling and parent communication */ | |
389 | for (i = 1; i < nodecount; i++) { | |
390 | for (j = cldcnt[i], n = i - 1; j > 0; j--) { | |
391 | cldcnt[i] += cldcnt[n]; | |
392 | speedcap[n] = min(speedcap[n], speedcap[i]); | |
393 | n -= cldcnt[n] + 1; | |
394 | } | |
395 | } | |
396 | ||
397 | for (n = 0; n < nodecount; n++) { | |
398 | for (i = n - cldcnt[n]; i <= n; i++) { | |
399 | for (j = 0; j < (n - cldcnt[n]); j++) { | |
400 | map[j*64 + i] = map[i*64 + j] = | |
401 | min(map[i*64 + j], speedcap[n]); | |
402 | } | |
403 | for (j = n + 1; j < nodecount; j++) { | |
404 | map[j*64 + i] = map[i*64 + j] = | |
405 | min(map[i*64 + j], speedcap[n]); | |
406 | } | |
407 | } | |
408 | } | |
647dcb5f | 409 | |
433a87d5 | 410 | #if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX |
647dcb5f BC |
411 | /* assume maximum speed for 1394b PHYs, nodemgr will correct it */ |
412 | for (n = 0; n < nodecount; n++) | |
433a87d5 | 413 | if (speedcap[n] == SELFID_SPEED_UNKNOWN) |
647dcb5f | 414 | speedcap[n] = IEEE1394_SPEED_MAX; |
433a87d5 | 415 | #endif |
1da177e4 LT |
416 | } |
417 | ||
418 | ||
afd6546d SR |
419 | /** |
420 | * hpsb_selfid_received - hand over received selfid packet to the core | |
421 | * | |
422 | * For host driver module usage. Safe to use in interrupt context. | |
423 | * | |
424 | * The host driver should have done a successful complement check (second | |
425 | * quadlet is complement of first) beforehand. | |
426 | */ | |
1da177e4 LT |
427 | void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) |
428 | { | |
741854e4 SR |
429 | if (host->in_bus_reset) { |
430 | HPSB_VERBOSE("Including SelfID 0x%x", sid); | |
431 | host->topology_map[host->selfid_count++] = sid; | |
432 | } else { | |
433 | HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", | |
1da177e4 | 434 | sid, NODEID_TO_BUS(host->node_id)); |
741854e4 | 435 | } |
1da177e4 LT |
436 | } |
437 | ||
afd6546d SR |
438 | /** |
439 | * hpsb_selfid_complete - notify completion of SelfID stage to the core | |
440 | * | |
441 | * For host driver module usage. Safe to use in interrupt context, although | |
442 | * quite complex; so you may want to run it in the bottom rather than top half. | |
443 | * | |
444 | * Notify completion of SelfID stage to the core and report new physical ID | |
445 | * and whether host is root now. | |
446 | */ | |
1da177e4 LT |
447 | void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) |
448 | { | |
449 | if (!host->in_bus_reset) | |
450 | HPSB_NOTICE("SelfID completion called outside of bus reset!"); | |
451 | ||
741854e4 SR |
452 | host->node_id = LOCAL_BUS | phyid; |
453 | host->is_root = isroot; | |
1da177e4 | 454 | |
741854e4 SR |
455 | if (!check_selfids(host)) { |
456 | if (host->reset_retries++ < 20) { | |
457 | /* selfid stage did not complete without error */ | |
458 | HPSB_NOTICE("Error in SelfID stage, resetting"); | |
1da177e4 LT |
459 | host->in_bus_reset = 0; |
460 | /* this should work from ohci1394 now... */ | |
741854e4 SR |
461 | hpsb_reset_bus(host, LONG_RESET); |
462 | return; | |
463 | } else { | |
464 | HPSB_NOTICE("Stopping out-of-control reset loop"); | |
465 | HPSB_NOTICE("Warning - topology map and speed map will not be valid"); | |
1da177e4 | 466 | host->reset_retries = 0; |
741854e4 SR |
467 | } |
468 | } else { | |
1da177e4 | 469 | host->reset_retries = 0; |
741854e4 SR |
470 | build_speed_map(host, host->node_count); |
471 | } | |
1da177e4 LT |
472 | |
473 | HPSB_VERBOSE("selfid_complete called with successful SelfID stage " | |
474 | "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id); | |
475 | ||
741854e4 SR |
476 | /* irm_id is kept up to date by check_selfids() */ |
477 | if (host->irm_id == host->node_id) { | |
478 | host->is_irm = 1; | |
479 | } else { | |
480 | host->is_busmgr = 0; | |
481 | host->is_irm = 0; | |
482 | } | |
1da177e4 | 483 | |
741854e4 | 484 | if (isroot) { |
1da177e4 LT |
485 | host->driver->devctl(host, ACT_CYCLE_MASTER, 1); |
486 | host->is_cycmst = 1; | |
487 | } | |
488 | atomic_inc(&host->generation); | |
489 | host->in_bus_reset = 0; | |
741854e4 | 490 | highlevel_host_reset(host); |
1da177e4 LT |
491 | } |
492 | ||
002a98f1 | 493 | static DEFINE_SPINLOCK(pending_packets_lock); |
7542e0e6 | 494 | |
afd6546d SR |
495 | /** |
496 | * hpsb_packet_sent - notify core of sending a packet | |
497 | * | |
498 | * For host driver module usage. Safe to call from within a transmit packet | |
499 | * routine. | |
500 | * | |
501 | * Notify core of sending a packet. Ackcode is the ack code returned for async | |
502 | * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE | |
503 | * for other cases (internal errors that don't justify a panic). | |
504 | */ | |
1da177e4 | 505 | void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, |
741854e4 | 506 | int ackcode) |
1da177e4 LT |
507 | { |
508 | unsigned long flags; | |
509 | ||
7542e0e6 | 510 | spin_lock_irqsave(&pending_packets_lock, flags); |
1da177e4 LT |
511 | |
512 | packet->ack_code = ackcode; | |
513 | ||
514 | if (packet->no_waiter || packet->state == hpsb_complete) { | |
515 | /* if packet->no_waiter, must not have a tlabel allocated */ | |
7542e0e6 | 516 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 LT |
517 | hpsb_free_packet(packet); |
518 | return; | |
519 | } | |
520 | ||
521 | atomic_dec(&packet->refcnt); /* drop HC's reference */ | |
7542e0e6 | 522 | /* here the packet must be on the host->pending_packets queue */ |
1da177e4 LT |
523 | |
524 | if (ackcode != ACK_PENDING || !packet->expect_response) { | |
525 | packet->state = hpsb_complete; | |
7542e0e6 SR |
526 | list_del_init(&packet->queue); |
527 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
528 | queue_packet_complete(packet); |
529 | return; | |
530 | } | |
531 | ||
532 | packet->state = hpsb_pending; | |
533 | packet->sendtime = jiffies; | |
534 | ||
7542e0e6 | 535 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 LT |
536 | |
537 | mod_timer(&host->timeout, jiffies + host->timeout_interval); | |
538 | } | |
539 | ||
540 | /** | |
541 | * hpsb_send_phy_config - transmit a PHY configuration packet on the bus | |
542 | * @host: host that PHY config packet gets sent through | |
543 | * @rootid: root whose force_root bit should get set (-1 = don't set force_root) | |
544 | * @gapcnt: gap count value to set (-1 = don't set gap count) | |
545 | * | |
afd6546d SR |
546 | * This function sends a PHY config packet on the bus through the specified |
547 | * host. | |
1da177e4 | 548 | * |
afd6546d | 549 | * Return value: 0 for success or negative error number otherwise. |
1da177e4 LT |
550 | */ |
551 | int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) | |
552 | { | |
553 | struct hpsb_packet *packet; | |
546513f9 | 554 | quadlet_t d = 0; |
1da177e4 LT |
555 | int retval = 0; |
556 | ||
557 | if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || | |
558 | (rootid == -1 && gapcnt == -1)) { | |
559 | HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", | |
560 | rootid, gapcnt); | |
561 | return -EINVAL; | |
562 | } | |
563 | ||
1da177e4 | 564 | if (rootid != -1) |
546513f9 | 565 | d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT; |
1da177e4 | 566 | if (gapcnt != -1) |
546513f9 | 567 | d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT; |
1da177e4 | 568 | |
546513f9 SR |
569 | packet = hpsb_make_phypacket(host, d); |
570 | if (!packet) | |
571 | return -ENOMEM; | |
1da177e4 LT |
572 | |
573 | packet->generation = get_hpsb_generation(host); | |
1da177e4 LT |
574 | retval = hpsb_send_packet_and_wait(packet); |
575 | hpsb_free_packet(packet); | |
576 | ||
577 | return retval; | |
578 | } | |
579 | ||
580 | /** | |
581 | * hpsb_send_packet - transmit a packet on the bus | |
582 | * @packet: packet to send | |
583 | * | |
584 | * The packet is sent through the host specified in the packet->host field. | |
585 | * Before sending, the packet's transmit speed is automatically determined | |
586 | * using the local speed map when it is an async, non-broadcast packet. | |
587 | * | |
588 | * Possibilities for failure are that host is either not initialized, in bus | |
589 | * reset, the packet's generation number doesn't match the current generation | |
590 | * number or the host reports a transmit error. | |
591 | * | |
592 | * Return value: 0 on success, negative errno on failure. | |
593 | */ | |
594 | int hpsb_send_packet(struct hpsb_packet *packet) | |
595 | { | |
596 | struct hpsb_host *host = packet->host; | |
597 | ||
741854e4 | 598 | if (host->is_shutdown) |
1da177e4 LT |
599 | return -EINVAL; |
600 | if (host->in_bus_reset || | |
601 | (packet->generation != get_hpsb_generation(host))) | |
741854e4 | 602 | return -EAGAIN; |
1da177e4 | 603 | |
741854e4 | 604 | packet->state = hpsb_queued; |
1da177e4 LT |
605 | |
606 | /* This just seems silly to me */ | |
607 | WARN_ON(packet->no_waiter && packet->expect_response); | |
608 | ||
609 | if (!packet->no_waiter || packet->expect_response) { | |
7542e0e6 SR |
610 | unsigned long flags; |
611 | ||
1da177e4 | 612 | atomic_inc(&packet->refcnt); |
1934b8b6 BC |
613 | /* Set the initial "sendtime" to 10 seconds from now, to |
614 | prevent premature expiry. If a packet takes more than | |
615 | 10 seconds to hit the wire, we have bigger problems :) */ | |
6262d062 | 616 | packet->sendtime = jiffies + 10 * HZ; |
7542e0e6 SR |
617 | spin_lock_irqsave(&pending_packets_lock, flags); |
618 | list_add_tail(&packet->queue, &host->pending_packets); | |
619 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
620 | } |
621 | ||
741854e4 | 622 | if (packet->node_id == host->node_id) { |
1da177e4 LT |
623 | /* it is a local request, so handle it locally */ |
624 | ||
741854e4 SR |
625 | quadlet_t *data; |
626 | size_t size = packet->data_size + packet->header_size; | |
1da177e4 | 627 | |
741854e4 SR |
628 | data = kmalloc(size, GFP_ATOMIC); |
629 | if (!data) { | |
630 | HPSB_ERR("unable to allocate memory for concatenating header and data"); | |
631 | return -ENOMEM; | |
632 | } | |
1da177e4 | 633 | |
741854e4 | 634 | memcpy(data, packet->header, packet->header_size); |
1da177e4 | 635 | |
741854e4 | 636 | if (packet->data_size) |
1da177e4 LT |
637 | memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size); |
638 | ||
741854e4 | 639 | dump_packet("send packet local", packet->header, packet->header_size, -1); |
1da177e4 | 640 | |
741854e4 SR |
641 | hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE); |
642 | hpsb_packet_received(host, data, size, 0); | |
1da177e4 | 643 | |
741854e4 | 644 | kfree(data); |
1da177e4 | 645 | |
741854e4 SR |
646 | return 0; |
647 | } | |
1da177e4 | 648 | |
647dcb5f BC |
649 | if (packet->type == hpsb_async && |
650 | NODEID_TO_NODE(packet->node_id) != ALL_NODES) | |
741854e4 | 651 | packet->speed_code = |
647dcb5f | 652 | host->speed[NODEID_TO_NODE(packet->node_id)]; |
1da177e4 | 653 | |
741854e4 | 654 | dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); |
1da177e4 | 655 | |
741854e4 | 656 | return host->driver->transmit_packet(host, packet); |
1da177e4 LT |
657 | } |
658 | ||
659 | /* We could just use complete() directly as the packet complete | |
660 | * callback, but this is more typesafe, in the sense that we get a | |
661 | * compiler error if the prototype for complete() changes. */ | |
662 | ||
663 | static void complete_packet(void *data) | |
664 | { | |
665 | complete((struct completion *) data); | |
666 | } | |
667 | ||
afd6546d SR |
668 | /** |
669 | * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes | |
670 | * @packet: packet to send | |
671 | * | |
672 | * Return value: 0 on success, negative errno on failure. | |
673 | */ | |
1da177e4 LT |
674 | int hpsb_send_packet_and_wait(struct hpsb_packet *packet) |
675 | { | |
676 | struct completion done; | |
677 | int retval; | |
678 | ||
679 | init_completion(&done); | |
680 | hpsb_set_packet_complete_task(packet, complete_packet, &done); | |
681 | retval = hpsb_send_packet(packet); | |
682 | if (retval == 0) | |
683 | wait_for_completion(&done); | |
684 | ||
685 | return retval; | |
686 | } | |
687 | ||
688 | static void send_packet_nocare(struct hpsb_packet *packet) | |
689 | { | |
741854e4 SR |
690 | if (hpsb_send_packet(packet) < 0) { |
691 | hpsb_free_packet(packet); | |
692 | } | |
1da177e4 LT |
693 | } |
694 | ||
7542e0e6 SR |
695 | static size_t packet_size_to_data_size(size_t packet_size, size_t header_size, |
696 | size_t buffer_size, int tcode) | |
697 | { | |
698 | size_t ret = packet_size <= header_size ? 0 : packet_size - header_size; | |
699 | ||
700 | if (unlikely(ret > buffer_size)) | |
701 | ret = buffer_size; | |
702 | ||
703 | if (unlikely(ret + header_size != packet_size)) | |
504945c9 | 704 | HPSB_ERR("unexpected packet size %zd (tcode %d), bug?", |
7542e0e6 SR |
705 | packet_size, tcode); |
706 | return ret; | |
707 | } | |
1da177e4 LT |
708 | |
709 | static void handle_packet_response(struct hpsb_host *host, int tcode, | |
710 | quadlet_t *data, size_t size) | |
711 | { | |
7542e0e6 SR |
712 | struct hpsb_packet *packet; |
713 | int tlabel = (data[0] >> 10) & 0x3f; | |
714 | size_t header_size; | |
741854e4 | 715 | unsigned long flags; |
1da177e4 | 716 | |
7542e0e6 | 717 | spin_lock_irqsave(&pending_packets_lock, flags); |
1da177e4 | 718 | |
7542e0e6 SR |
719 | list_for_each_entry(packet, &host->pending_packets, queue) |
720 | if (packet->tlabel == tlabel && | |
721 | packet->node_id == (data[1] >> 16)) | |
722 | goto found; | |
1da177e4 | 723 | |
7542e0e6 SR |
724 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
725 | HPSB_DEBUG("unsolicited response packet received - %s", | |
726 | "no tlabel match"); | |
727 | dump_packet("contents", data, 16, -1); | |
728 | return; | |
1da177e4 | 729 | |
7542e0e6 | 730 | found: |
741854e4 SR |
731 | switch (packet->tcode) { |
732 | case TCODE_WRITEQ: | |
733 | case TCODE_WRITEB: | |
7542e0e6 | 734 | if (unlikely(tcode != TCODE_WRITE_RESPONSE)) |
1da177e4 | 735 | break; |
7542e0e6 SR |
736 | header_size = 12; |
737 | size = 0; | |
738 | goto dequeue; | |
739 | ||
741854e4 | 740 | case TCODE_READQ: |
7542e0e6 | 741 | if (unlikely(tcode != TCODE_READQ_RESPONSE)) |
1da177e4 | 742 | break; |
7542e0e6 SR |
743 | header_size = 16; |
744 | size = 0; | |
745 | goto dequeue; | |
746 | ||
741854e4 | 747 | case TCODE_READB: |
7542e0e6 | 748 | if (unlikely(tcode != TCODE_READB_RESPONSE)) |
1da177e4 | 749 | break; |
7542e0e6 SR |
750 | header_size = 16; |
751 | size = packet_size_to_data_size(size, header_size, | |
752 | packet->allocated_data_size, | |
753 | tcode); | |
754 | goto dequeue; | |
755 | ||
741854e4 | 756 | case TCODE_LOCK_REQUEST: |
7542e0e6 | 757 | if (unlikely(tcode != TCODE_LOCK_RESPONSE)) |
1da177e4 | 758 | break; |
7542e0e6 SR |
759 | header_size = 16; |
760 | size = packet_size_to_data_size(min(size, (size_t)(16 + 8)), | |
761 | header_size, | |
762 | packet->allocated_data_size, | |
763 | tcode); | |
764 | goto dequeue; | |
741854e4 | 765 | } |
1da177e4 | 766 | |
7542e0e6 SR |
767 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
768 | HPSB_DEBUG("unsolicited response packet received - %s", | |
769 | "tcode mismatch"); | |
770 | dump_packet("contents", data, 16, -1); | |
771 | return; | |
1da177e4 | 772 | |
7542e0e6 SR |
773 | dequeue: |
774 | list_del_init(&packet->queue); | |
775 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 LT |
776 | |
777 | if (packet->state == hpsb_queued) { | |
778 | packet->sendtime = jiffies; | |
779 | packet->ack_code = ACK_PENDING; | |
780 | } | |
1da177e4 | 781 | packet->state = hpsb_complete; |
7542e0e6 SR |
782 | |
783 | memcpy(packet->header, data, header_size); | |
784 | if (size) | |
785 | memcpy(packet->data, data + 4, size); | |
1da177e4 LT |
786 | |
787 | queue_packet_complete(packet); | |
788 | } | |
789 | ||
790 | ||
791 | static struct hpsb_packet *create_reply_packet(struct hpsb_host *host, | |
792 | quadlet_t *data, size_t dsize) | |
793 | { | |
741854e4 | 794 | struct hpsb_packet *p; |
1da177e4 | 795 | |
741854e4 SR |
796 | p = hpsb_alloc_packet(dsize); |
797 | if (unlikely(p == NULL)) { | |
798 | /* FIXME - send data_error response */ | |
7542e0e6 | 799 | HPSB_ERR("out of memory, cannot send response packet"); |
741854e4 SR |
800 | return NULL; |
801 | } | |
1da177e4 | 802 | |
741854e4 SR |
803 | p->type = hpsb_async; |
804 | p->state = hpsb_unused; | |
805 | p->host = host; | |
806 | p->node_id = data[1] >> 16; | |
807 | p->tlabel = (data[0] >> 10) & 0x3f; | |
808 | p->no_waiter = 1; | |
1da177e4 LT |
809 | |
810 | p->generation = get_hpsb_generation(host); | |
811 | ||
812 | if (dsize % 4) | |
813 | p->data[dsize / 4] = 0; | |
814 | ||
741854e4 | 815 | return p; |
1da177e4 LT |
816 | } |
817 | ||
818 | #define PREP_ASYNC_HEAD_RCODE(tc) \ | |
819 | packet->tcode = tc; \ | |
820 | packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ | |
821 | | (1 << 8) | (tc << 4); \ | |
822 | packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \ | |
823 | packet->header[2] = 0 | |
824 | ||
825 | static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, | |
741854e4 | 826 | quadlet_t data) |
1da177e4 LT |
827 | { |
828 | PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE); | |
829 | packet->header[3] = data; | |
830 | packet->header_size = 16; | |
831 | packet->data_size = 0; | |
832 | } | |
833 | ||
834 | static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, | |
741854e4 | 835 | int length) |
1da177e4 LT |
836 | { |
837 | if (rcode != RCODE_COMPLETE) | |
838 | length = 0; | |
839 | ||
840 | PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); | |
841 | packet->header[3] = length << 16; | |
842 | packet->header_size = 16; | |
843 | packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); | |
844 | } | |
845 | ||
846 | static void fill_async_write_resp(struct hpsb_packet *packet, int rcode) | |
847 | { | |
848 | PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); | |
1da177e4 LT |
849 | packet->header_size = 12; |
850 | packet->data_size = 0; | |
851 | } | |
852 | ||
853 | static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, | |
741854e4 | 854 | int length) |
1da177e4 LT |
855 | { |
856 | if (rcode != RCODE_COMPLETE) | |
857 | length = 0; | |
858 | ||
859 | PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE); | |
860 | packet->header[3] = (length << 16) | extcode; | |
861 | packet->header_size = 16; | |
862 | packet->data_size = length; | |
863 | } | |
864 | ||
1da177e4 | 865 | static void handle_incoming_packet(struct hpsb_host *host, int tcode, |
d4c60085 SR |
866 | quadlet_t *data, size_t size, |
867 | int write_acked) | |
1da177e4 | 868 | { |
741854e4 SR |
869 | struct hpsb_packet *packet; |
870 | int length, rcode, extcode; | |
871 | quadlet_t buffer; | |
872 | nodeid_t source = data[1] >> 16; | |
873 | nodeid_t dest = data[0] >> 16; | |
874 | u16 flags = (u16) data[0]; | |
875 | u64 addr; | |
876 | ||
d4c60085 SR |
877 | /* FIXME? |
878 | * Out-of-bounds lengths are left for highlevel_read|write to cap. */ | |
741854e4 SR |
879 | |
880 | switch (tcode) { | |
881 | case TCODE_WRITEQ: | |
882 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
d4c60085 | 883 | rcode = highlevel_write(host, source, dest, data + 3, |
1da177e4 | 884 | addr, 4, flags); |
d4c60085 | 885 | goto handle_write_request; |
741854e4 SR |
886 | |
887 | case TCODE_WRITEB: | |
888 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
d4c60085 SR |
889 | rcode = highlevel_write(host, source, dest, data + 4, |
890 | addr, data[3] >> 16, flags); | |
891 | handle_write_request: | |
892 | if (rcode < 0 || write_acked || | |
893 | NODEID_TO_NODE(data[0] >> 16) == NODE_MASK) | |
894 | return; | |
895 | /* not a broadcast write, reply */ | |
896 | packet = create_reply_packet(host, data, 0); | |
897 | if (packet) { | |
741854e4 SR |
898 | fill_async_write_resp(packet, rcode); |
899 | send_packet_nocare(packet); | |
900 | } | |
d4c60085 | 901 | return; |
741854e4 SR |
902 | |
903 | case TCODE_READQ: | |
904 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
905 | rcode = highlevel_read(host, source, &buffer, addr, 4, flags); | |
d4c60085 SR |
906 | if (rcode < 0) |
907 | return; | |
741854e4 | 908 | |
d4c60085 SR |
909 | packet = create_reply_packet(host, data, 0); |
910 | if (packet) { | |
741854e4 SR |
911 | fill_async_readquad_resp(packet, rcode, buffer); |
912 | send_packet_nocare(packet); | |
913 | } | |
d4c60085 | 914 | return; |
741854e4 SR |
915 | |
916 | case TCODE_READB: | |
917 | length = data[3] >> 16; | |
d4c60085 SR |
918 | packet = create_reply_packet(host, data, length); |
919 | if (!packet) | |
920 | return; | |
741854e4 SR |
921 | |
922 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
923 | rcode = highlevel_read(host, source, packet->data, addr, | |
924 | length, flags); | |
d4c60085 | 925 | if (rcode < 0) { |
741854e4 | 926 | hpsb_free_packet(packet); |
d4c60085 | 927 | return; |
741854e4 | 928 | } |
d4c60085 SR |
929 | fill_async_readblock_resp(packet, rcode, length); |
930 | send_packet_nocare(packet); | |
931 | return; | |
741854e4 SR |
932 | |
933 | case TCODE_LOCK_REQUEST: | |
934 | length = data[3] >> 16; | |
935 | extcode = data[3] & 0xffff; | |
936 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | |
937 | ||
d4c60085 SR |
938 | packet = create_reply_packet(host, data, 8); |
939 | if (!packet) | |
940 | return; | |
741854e4 | 941 | |
d4c60085 | 942 | if (extcode == 0 || extcode >= 7) { |
741854e4 SR |
943 | /* let switch default handle error */ |
944 | length = 0; | |
945 | } | |
946 | ||
947 | switch (length) { | |
948 | case 4: | |
949 | rcode = highlevel_lock(host, source, packet->data, addr, | |
d4c60085 | 950 | data[4], 0, extcode, flags); |
741854e4 SR |
951 | fill_async_lock_resp(packet, rcode, extcode, 4); |
952 | break; | |
953 | case 8: | |
d4c60085 SR |
954 | if (extcode != EXTCODE_FETCH_ADD && |
955 | extcode != EXTCODE_LITTLE_ADD) { | |
741854e4 SR |
956 | rcode = highlevel_lock(host, source, |
957 | packet->data, addr, | |
958 | data[5], data[4], | |
959 | extcode, flags); | |
960 | fill_async_lock_resp(packet, rcode, extcode, 4); | |
961 | } else { | |
962 | rcode = highlevel_lock64(host, source, | |
963 | (octlet_t *)packet->data, addr, | |
964 | *(octlet_t *)(data + 4), 0ULL, | |
965 | extcode, flags); | |
966 | fill_async_lock_resp(packet, rcode, extcode, 8); | |
967 | } | |
968 | break; | |
969 | case 16: | |
970 | rcode = highlevel_lock64(host, source, | |
971 | (octlet_t *)packet->data, addr, | |
972 | *(octlet_t *)(data + 6), | |
973 | *(octlet_t *)(data + 4), | |
974 | extcode, flags); | |
975 | fill_async_lock_resp(packet, rcode, extcode, 8); | |
976 | break; | |
977 | default: | |
978 | rcode = RCODE_TYPE_ERROR; | |
d4c60085 | 979 | fill_async_lock_resp(packet, rcode, extcode, 0); |
741854e4 SR |
980 | } |
981 | ||
d4c60085 | 982 | if (rcode < 0) |
741854e4 | 983 | hpsb_free_packet(packet); |
d4c60085 SR |
984 | else |
985 | send_packet_nocare(packet); | |
986 | return; | |
741854e4 | 987 | } |
1da177e4 | 988 | } |
1da177e4 | 989 | |
afd6546d SR |
990 | /** |
991 | * hpsb_packet_received - hand over received packet to the core | |
992 | * | |
993 | * For host driver module usage. | |
994 | * | |
995 | * The contents of data are expected to be the full packet but with the CRCs | |
996 | * left out (data block follows header immediately), with the header (i.e. the | |
997 | * first four quadlets) in machine byte order and the data block in big endian. | |
998 | * *@data can be safely overwritten after this call. | |
999 | * | |
1000 | * If the packet is a write request, @write_acked is to be set to true if it was | |
1001 | * ack_complete'd already, false otherwise. This argument is ignored for any | |
1002 | * other packet type. | |
1003 | */ | |
1da177e4 | 1004 | void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, |
741854e4 | 1005 | int write_acked) |
1da177e4 | 1006 | { |
741854e4 SR |
1007 | int tcode; |
1008 | ||
7542e0e6 SR |
1009 | if (unlikely(host->in_bus_reset)) { |
1010 | HPSB_DEBUG("received packet during reset; ignoring"); | |
741854e4 SR |
1011 | return; |
1012 | } | |
1013 | ||
1014 | dump_packet("received packet", data, size, -1); | |
1015 | ||
1016 | tcode = (data[0] >> 4) & 0xf; | |
1017 | ||
1018 | switch (tcode) { | |
1019 | case TCODE_WRITE_RESPONSE: | |
1020 | case TCODE_READQ_RESPONSE: | |
1021 | case TCODE_READB_RESPONSE: | |
1022 | case TCODE_LOCK_RESPONSE: | |
1023 | handle_packet_response(host, tcode, data, size); | |
1024 | break; | |
1025 | ||
1026 | case TCODE_WRITEQ: | |
1027 | case TCODE_WRITEB: | |
1028 | case TCODE_READQ: | |
1029 | case TCODE_READB: | |
1030 | case TCODE_LOCK_REQUEST: | |
1031 | handle_incoming_packet(host, tcode, data, size, write_acked); | |
1032 | break; | |
1033 | ||
741854e4 SR |
1034 | case TCODE_CYCLE_START: |
1035 | /* simply ignore this packet if it is passed on */ | |
1036 | break; | |
1037 | ||
1038 | default: | |
7542e0e6 SR |
1039 | HPSB_DEBUG("received packet with bogus transaction code %d", |
1040 | tcode); | |
741854e4 SR |
1041 | break; |
1042 | } | |
1da177e4 LT |
1043 | } |
1044 | ||
1da177e4 LT |
1045 | static void abort_requests(struct hpsb_host *host) |
1046 | { | |
7542e0e6 SR |
1047 | struct hpsb_packet *packet, *p; |
1048 | struct list_head tmp; | |
1049 | unsigned long flags; | |
1da177e4 LT |
1050 | |
1051 | host->driver->devctl(host, CANCEL_REQUESTS, 0); | |
1052 | ||
7542e0e6 SR |
1053 | INIT_LIST_HEAD(&tmp); |
1054 | spin_lock_irqsave(&pending_packets_lock, flags); | |
1055 | list_splice_init(&host->pending_packets, &tmp); | |
1056 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
1da177e4 | 1057 | |
7542e0e6 SR |
1058 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1059 | list_del_init(&packet->queue); | |
1da177e4 LT |
1060 | packet->state = hpsb_complete; |
1061 | packet->ack_code = ACKX_ABORTED; | |
1062 | queue_packet_complete(packet); | |
1063 | } | |
1064 | } | |
1065 | ||
1066 | void abort_timedouts(unsigned long __opaque) | |
1067 | { | |
1068 | struct hpsb_host *host = (struct hpsb_host *)__opaque; | |
7542e0e6 SR |
1069 | struct hpsb_packet *packet, *p; |
1070 | struct list_head tmp; | |
1071 | unsigned long flags, expire, j; | |
1da177e4 LT |
1072 | |
1073 | spin_lock_irqsave(&host->csr.lock, flags); | |
1074 | expire = host->csr.expire; | |
1075 | spin_unlock_irqrestore(&host->csr.lock, flags); | |
1076 | ||
7542e0e6 SR |
1077 | j = jiffies; |
1078 | INIT_LIST_HEAD(&tmp); | |
1079 | spin_lock_irqsave(&pending_packets_lock, flags); | |
1da177e4 | 1080 | |
7542e0e6 SR |
1081 | list_for_each_entry_safe(packet, p, &host->pending_packets, queue) { |
1082 | if (time_before(packet->sendtime + expire, j)) | |
1083 | list_move_tail(&packet->queue, &tmp); | |
1084 | else | |
1da177e4 LT |
1085 | /* Since packets are added to the tail, the oldest |
1086 | * ones are first, always. When we get to one that | |
1087 | * isn't timed out, the rest aren't either. */ | |
1088 | break; | |
1da177e4 | 1089 | } |
7542e0e6 SR |
1090 | if (!list_empty(&host->pending_packets)) |
1091 | mod_timer(&host->timeout, j + host->timeout_interval); | |
1da177e4 | 1092 | |
7542e0e6 | 1093 | spin_unlock_irqrestore(&pending_packets_lock, flags); |
1da177e4 | 1094 | |
7542e0e6 SR |
1095 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1096 | list_del_init(&packet->queue); | |
1097 | packet->state = hpsb_complete; | |
1098 | packet->ack_code = ACKX_TIMEOUT; | |
1099 | queue_packet_complete(packet); | |
1100 | } | |
1da177e4 LT |
1101 | } |
1102 | ||
f654240f | 1103 | static struct task_struct *khpsbpkt_thread; |
7542e0e6 | 1104 | static LIST_HEAD(hpsbpkt_queue); |
1da177e4 LT |
1105 | |
1106 | static void queue_packet_complete(struct hpsb_packet *packet) | |
1107 | { | |
7542e0e6 SR |
1108 | unsigned long flags; |
1109 | ||
1da177e4 LT |
1110 | if (packet->no_waiter) { |
1111 | hpsb_free_packet(packet); | |
1112 | return; | |
1113 | } | |
1114 | if (packet->complete_routine != NULL) { | |
7542e0e6 SR |
1115 | spin_lock_irqsave(&pending_packets_lock, flags); |
1116 | list_add_tail(&packet->queue, &hpsbpkt_queue); | |
1117 | spin_unlock_irqrestore(&pending_packets_lock, flags); | |
f654240f | 1118 | wake_up_process(khpsbpkt_thread); |
1da177e4 LT |
1119 | } |
1120 | return; | |
1121 | } | |
1122 | ||
7542e0e6 SR |
1123 | /* |
1124 | * Kernel thread which handles packets that are completed. This way the | |
1125 | * packet's "complete" function is asynchronously run in process context. | |
1126 | * Only packets which have a "complete" function may be sent here. | |
1127 | */ | |
1da177e4 LT |
1128 | static int hpsbpkt_thread(void *__hi) |
1129 | { | |
7542e0e6 SR |
1130 | struct hpsb_packet *packet, *p; |
1131 | struct list_head tmp; | |
1132 | int may_schedule; | |
1da177e4 | 1133 | |
f654240f | 1134 | while (!kthread_should_stop()) { |
1da177e4 | 1135 | |
7542e0e6 SR |
1136 | INIT_LIST_HEAD(&tmp); |
1137 | spin_lock_irq(&pending_packets_lock); | |
1138 | list_splice_init(&hpsbpkt_queue, &tmp); | |
1139 | spin_unlock_irq(&pending_packets_lock); | |
1da177e4 | 1140 | |
7542e0e6 SR |
1141 | list_for_each_entry_safe(packet, p, &tmp, queue) { |
1142 | list_del_init(&packet->queue); | |
1143 | packet->complete_routine(packet->complete_data); | |
1da177e4 | 1144 | } |
1da177e4 | 1145 | |
f654240f | 1146 | set_current_state(TASK_INTERRUPTIBLE); |
7542e0e6 SR |
1147 | spin_lock_irq(&pending_packets_lock); |
1148 | may_schedule = list_empty(&hpsbpkt_queue); | |
1149 | spin_unlock_irq(&pending_packets_lock); | |
1150 | if (may_schedule) | |
f654240f BC |
1151 | schedule(); |
1152 | __set_current_state(TASK_RUNNING); | |
1153 | } | |
1154 | return 0; | |
1da177e4 LT |
1155 | } |
1156 | ||
1157 | static int __init ieee1394_init(void) | |
1158 | { | |
1159 | int i, ret; | |
1160 | ||
1da177e4 LT |
1161 | /* non-fatal error */ |
1162 | if (hpsb_init_config_roms()) { | |
1163 | HPSB_ERR("Failed to initialize some config rom entries.\n"); | |
1164 | HPSB_ERR("Some features may not be available\n"); | |
1165 | } | |
1166 | ||
f654240f BC |
1167 | khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt"); |
1168 | if (IS_ERR(khpsbpkt_thread)) { | |
1da177e4 | 1169 | HPSB_ERR("Failed to start hpsbpkt thread!\n"); |
f654240f | 1170 | ret = PTR_ERR(khpsbpkt_thread); |
1da177e4 LT |
1171 | goto exit_cleanup_config_roms; |
1172 | } | |
1173 | ||
1174 | if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) { | |
1175 | HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); | |
1176 | ret = -ENODEV; | |
1177 | goto exit_release_kernel_thread; | |
1178 | } | |
1179 | ||
1da177e4 LT |
1180 | ret = bus_register(&ieee1394_bus_type); |
1181 | if (ret < 0) { | |
1182 | HPSB_INFO("bus register failed"); | |
a8748445 | 1183 | goto release_chrdev; |
1da177e4 LT |
1184 | } |
1185 | ||
1186 | for (i = 0; fw_bus_attrs[i]; i++) { | |
1187 | ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1188 | if (ret < 0) { | |
1189 | while (i >= 0) { | |
1190 | bus_remove_file(&ieee1394_bus_type, | |
1191 | fw_bus_attrs[i--]); | |
1192 | } | |
1193 | bus_unregister(&ieee1394_bus_type); | |
a8748445 | 1194 | goto release_chrdev; |
1da177e4 LT |
1195 | } |
1196 | } | |
1197 | ||
1198 | ret = class_register(&hpsb_host_class); | |
1199 | if (ret < 0) | |
1200 | goto release_all_bus; | |
1201 | ||
7e25ab91 | 1202 | hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol"); |
1da177e4 LT |
1203 | if (IS_ERR(hpsb_protocol_class)) { |
1204 | ret = PTR_ERR(hpsb_protocol_class); | |
1205 | goto release_class_host; | |
1206 | } | |
1207 | ||
1208 | ret = init_csr(); | |
1209 | if (ret) { | |
1210 | HPSB_INFO("init csr failed"); | |
1211 | ret = -ENOMEM; | |
1212 | goto release_class_protocol; | |
1213 | } | |
1214 | ||
1215 | if (disable_nodemgr) { | |
1216 | HPSB_INFO("nodemgr and IRM functionality disabled"); | |
1217 | /* We shouldn't contend for IRM with nodemgr disabled, since | |
1218 | nodemgr implements functionality required of ieee1394a-2000 | |
1219 | IRMs */ | |
1220 | hpsb_disable_irm = 1; | |
741854e4 | 1221 | |
1da177e4 LT |
1222 | return 0; |
1223 | } | |
1224 | ||
1225 | if (hpsb_disable_irm) { | |
1226 | HPSB_INFO("IRM functionality disabled"); | |
1227 | } | |
1228 | ||
1229 | ret = init_ieee1394_nodemgr(); | |
1230 | if (ret < 0) { | |
1231 | HPSB_INFO("init nodemgr failed"); | |
1232 | goto cleanup_csr; | |
1233 | } | |
1234 | ||
1235 | return 0; | |
1236 | ||
1237 | cleanup_csr: | |
1238 | cleanup_csr(); | |
1239 | release_class_protocol: | |
7e25ab91 | 1240 | class_destroy(hpsb_protocol_class); |
1da177e4 LT |
1241 | release_class_host: |
1242 | class_unregister(&hpsb_host_class); | |
1243 | release_all_bus: | |
1244 | for (i = 0; fw_bus_attrs[i]; i++) | |
1245 | bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1246 | bus_unregister(&ieee1394_bus_type); | |
1da177e4 LT |
1247 | release_chrdev: |
1248 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); | |
1249 | exit_release_kernel_thread: | |
f654240f | 1250 | kthread_stop(khpsbpkt_thread); |
1da177e4 LT |
1251 | exit_cleanup_config_roms: |
1252 | hpsb_cleanup_config_roms(); | |
1253 | return ret; | |
1254 | } | |
1255 | ||
1256 | static void __exit ieee1394_cleanup(void) | |
1257 | { | |
1258 | int i; | |
1259 | ||
1260 | if (!disable_nodemgr) | |
1261 | cleanup_ieee1394_nodemgr(); | |
1262 | ||
1263 | cleanup_csr(); | |
1264 | ||
7e25ab91 | 1265 | class_destroy(hpsb_protocol_class); |
1da177e4 LT |
1266 | class_unregister(&hpsb_host_class); |
1267 | for (i = 0; fw_bus_attrs[i]; i++) | |
1268 | bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); | |
1269 | bus_unregister(&ieee1394_bus_type); | |
1270 | ||
f654240f | 1271 | kthread_stop(khpsbpkt_thread); |
1da177e4 LT |
1272 | |
1273 | hpsb_cleanup_config_roms(); | |
1274 | ||
1275 | unregister_chrdev_region(IEEE1394_CORE_DEV, 256); | |
1da177e4 LT |
1276 | } |
1277 | ||
be7963b7 | 1278 | module_init(ieee1394_init); |
1da177e4 LT |
1279 | module_exit(ieee1394_cleanup); |
1280 | ||
1281 | /* Exported symbols */ | |
1282 | ||
1283 | /** hosts.c **/ | |
1284 | EXPORT_SYMBOL(hpsb_alloc_host); | |
1285 | EXPORT_SYMBOL(hpsb_add_host); | |
3360177c | 1286 | EXPORT_SYMBOL(hpsb_resume_host); |
1da177e4 LT |
1287 | EXPORT_SYMBOL(hpsb_remove_host); |
1288 | EXPORT_SYMBOL(hpsb_update_config_rom_image); | |
1289 | ||
1290 | /** ieee1394_core.c **/ | |
1291 | EXPORT_SYMBOL(hpsb_speedto_str); | |
1292 | EXPORT_SYMBOL(hpsb_protocol_class); | |
1293 | EXPORT_SYMBOL(hpsb_set_packet_complete_task); | |
1294 | EXPORT_SYMBOL(hpsb_alloc_packet); | |
1295 | EXPORT_SYMBOL(hpsb_free_packet); | |
1da177e4 | 1296 | EXPORT_SYMBOL(hpsb_send_packet); |
1da177e4 | 1297 | EXPORT_SYMBOL(hpsb_reset_bus); |
3dc5ea9b | 1298 | EXPORT_SYMBOL(hpsb_read_cycle_timer); |
1da177e4 LT |
1299 | EXPORT_SYMBOL(hpsb_bus_reset); |
1300 | EXPORT_SYMBOL(hpsb_selfid_received); | |
1301 | EXPORT_SYMBOL(hpsb_selfid_complete); | |
1302 | EXPORT_SYMBOL(hpsb_packet_sent); | |
1303 | EXPORT_SYMBOL(hpsb_packet_received); | |
1304 | EXPORT_SYMBOL_GPL(hpsb_disable_irm); | |
1305 | ||
1306 | /** ieee1394_transactions.c **/ | |
1307 | EXPORT_SYMBOL(hpsb_get_tlabel); | |
1308 | EXPORT_SYMBOL(hpsb_free_tlabel); | |
1309 | EXPORT_SYMBOL(hpsb_make_readpacket); | |
1310 | EXPORT_SYMBOL(hpsb_make_writepacket); | |
1311 | EXPORT_SYMBOL(hpsb_make_streampacket); | |
1312 | EXPORT_SYMBOL(hpsb_make_lockpacket); | |
1313 | EXPORT_SYMBOL(hpsb_make_lock64packet); | |
1314 | EXPORT_SYMBOL(hpsb_make_phypacket); | |
1da177e4 LT |
1315 | EXPORT_SYMBOL(hpsb_read); |
1316 | EXPORT_SYMBOL(hpsb_write); | |
1da177e4 LT |
1317 | EXPORT_SYMBOL(hpsb_packet_success); |
1318 | ||
1319 | /** highlevel.c **/ | |
1320 | EXPORT_SYMBOL(hpsb_register_highlevel); | |
1321 | EXPORT_SYMBOL(hpsb_unregister_highlevel); | |
1322 | EXPORT_SYMBOL(hpsb_register_addrspace); | |
1323 | EXPORT_SYMBOL(hpsb_unregister_addrspace); | |
1324 | EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); | |
1da177e4 LT |
1325 | EXPORT_SYMBOL(hpsb_get_hostinfo); |
1326 | EXPORT_SYMBOL(hpsb_create_hostinfo); | |
1327 | EXPORT_SYMBOL(hpsb_destroy_hostinfo); | |
1328 | EXPORT_SYMBOL(hpsb_set_hostinfo_key); | |
1329 | EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); | |
1330 | EXPORT_SYMBOL(hpsb_set_hostinfo); | |
1da177e4 LT |
1331 | |
1332 | /** nodemgr.c **/ | |
1333 | EXPORT_SYMBOL(hpsb_node_fill_packet); | |
1334 | EXPORT_SYMBOL(hpsb_node_write); | |
ed30c26e | 1335 | EXPORT_SYMBOL(__hpsb_register_protocol); |
1da177e4 | 1336 | EXPORT_SYMBOL(hpsb_unregister_protocol); |
1da177e4 LT |
1337 | |
1338 | /** csr.c **/ | |
1339 | EXPORT_SYMBOL(hpsb_update_config_rom); | |
1340 | ||
1341 | /** dma.c **/ | |
1342 | EXPORT_SYMBOL(dma_prog_region_init); | |
1343 | EXPORT_SYMBOL(dma_prog_region_alloc); | |
1344 | EXPORT_SYMBOL(dma_prog_region_free); | |
1345 | EXPORT_SYMBOL(dma_region_init); | |
1346 | EXPORT_SYMBOL(dma_region_alloc); | |
1347 | EXPORT_SYMBOL(dma_region_free); | |
1348 | EXPORT_SYMBOL(dma_region_sync_for_cpu); | |
1349 | EXPORT_SYMBOL(dma_region_sync_for_device); | |
1350 | EXPORT_SYMBOL(dma_region_mmap); | |
1351 | EXPORT_SYMBOL(dma_region_offset_to_bus); | |
1352 | ||
1353 | /** iso.c **/ | |
1354 | EXPORT_SYMBOL(hpsb_iso_xmit_init); | |
1355 | EXPORT_SYMBOL(hpsb_iso_recv_init); | |
1356 | EXPORT_SYMBOL(hpsb_iso_xmit_start); | |
1357 | EXPORT_SYMBOL(hpsb_iso_recv_start); | |
1358 | EXPORT_SYMBOL(hpsb_iso_recv_listen_channel); | |
1359 | EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel); | |
1360 | EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); | |
1361 | EXPORT_SYMBOL(hpsb_iso_stop); | |
1362 | EXPORT_SYMBOL(hpsb_iso_shutdown); | |
1363 | EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); | |
1364 | EXPORT_SYMBOL(hpsb_iso_xmit_sync); | |
1365 | EXPORT_SYMBOL(hpsb_iso_recv_release_packets); | |
1366 | EXPORT_SYMBOL(hpsb_iso_n_ready); | |
1367 | EXPORT_SYMBOL(hpsb_iso_packet_sent); | |
1368 | EXPORT_SYMBOL(hpsb_iso_packet_received); | |
1369 | EXPORT_SYMBOL(hpsb_iso_wake); | |
1370 | EXPORT_SYMBOL(hpsb_iso_recv_flush); | |
1371 | ||
1372 | /** csr1212.c **/ | |
1da177e4 | 1373 | EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); |
1da177e4 | 1374 | EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); |
c1a37f2c SR |
1375 | EXPORT_SYMBOL(csr1212_get_keyval); |
1376 | EXPORT_SYMBOL(csr1212_new_directory); | |
1da177e4 | 1377 | EXPORT_SYMBOL(csr1212_parse_keyval); |
c1a37f2c SR |
1378 | EXPORT_SYMBOL(csr1212_read); |
1379 | EXPORT_SYMBOL(csr1212_release_keyval); |