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