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