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