1
2
3
4
5
6
7
8
9
10
11#include <linux/kernel.h>
12#include <linux/config.h>
13#include <linux/list.h>
14#include <linux/slab.h>
15#include <linux/smp_lock.h>
16#include <linux/interrupt.h>
17#include <linux/kmod.h>
18#include <linux/completion.h>
19#include <linux/delay.h>
20#ifdef CONFIG_PROC_FS
21#include <linux/proc_fs.h>
22#endif
23
24#include "ieee1394_types.h"
25#include "ieee1394.h"
26#include "nodemgr.h"
27#include "hosts.h"
28#include "ieee1394_transactions.h"
29#include "highlevel.h"
30#include "csr.h"
31#include "nodemgr.h"
32
33
34
35static char *nodemgr_find_oui_name(int oui)
36{
37#ifdef CONFIG_IEEE1394_OUI_DB
38 extern struct oui_list_struct {
39 int oui;
40 char *name;
41 } oui_list[];
42 int i;
43
44 for (i = 0; oui_list[i].name; i++)
45 if (oui_list[i].oui == oui)
46 return oui_list[i].name;
47#endif
48 return NULL;
49}
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77static DECLARE_MUTEX(nodemgr_serialize);
78static LIST_HEAD(node_list);
79static LIST_HEAD(driver_list);
80static LIST_HEAD(unit_directory_list);
81
82
83struct host_info {
84 struct hpsb_host *host;
85 struct completion exited;
86 struct semaphore reset_sem;
87 int pid;
88 char daemon_name[15];
89};
90
91static struct hpsb_highlevel nodemgr_highlevel;
92
93#ifdef CONFIG_PROC_FS
94
95#define PUTF(fmt, args...) \
96do { \
97 len += sprintf(page + len, fmt, ## args); \
98 pos = begin + len; \
99 if (pos < off) { \
100 len = 0; \
101 begin = pos; \
102 } \
103 if (pos > off + count) \
104 goto done_proc; \
105} while (0)
106
107
108static int raw1394_read_proc(char *page, char **start, off_t off,
109 int count, int *eof, void *data)
110{
111 struct list_head *lh;
112 struct node_entry *ne;
113 off_t begin = 0, pos = 0;
114 int len = 0;
115
116 if (down_interruptible(&nodemgr_serialize))
117 return -EINTR;
118
119 list_for_each(lh, &node_list) {
120 struct list_head *l;
121 int ud_count = 0, lud_count = 0;
122
123 ne = list_entry(lh, struct node_entry, list);
124 if (!ne)
125 continue;
126
127 PUTF("Node[" NODE_BUS_FMT "] GUID[%016Lx]:\n",
128 NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
129
130
131 PUTF(" Vendor ID: `%s' [0x%06x]\n",
132 ne->vendor_name ?: "Unknown", ne->vendor_id);
133 PUTF(" Capabilities: 0x%06x\n", ne->capabilities);
134 PUTF(" Bus Options:\n");
135 PUTF(" IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d)\n"
136 " LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n",
137 ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
138 ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
139 ne->busopt.max_rec, ne->busopt.cyc_clk_acc);
140
141
142 if (ne->host != NULL && ne->host->node_id == ne->nodeid) {
143 PUTF(" Host Node Status:\n");
144 PUTF(" Host Driver : %s\n", ne->host->driver->name);
145 PUTF(" Nodes connected : %d\n", ne->host->node_count);
146 PUTF(" Nodes active : %d\n", ne->host->nodes_active);
147 PUTF(" SelfIDs received: %d\n", ne->host->selfid_count);
148 PUTF(" Irm ID : [" NODE_BUS_FMT "]\n",
149 NODE_BUS_ARGS(ne->host, ne->host->irm_id));
150 PUTF(" BusMgr ID : [" NODE_BUS_FMT "]\n",
151 NODE_BUS_ARGS(ne->host, ne->host->busmgr_id));
152 PUTF(" In Bus Reset : %s\n", ne->host->in_bus_reset ? "yes" : "no");
153 PUTF(" Root : %s\n", ne->host->is_root ? "yes" : "no");
154 PUTF(" Cycle Master : %s\n", ne->host->is_cycmst ? "yes" : "no");
155 PUTF(" IRM : %s\n", ne->host->is_irm ? "yes" : "no");
156 PUTF(" Bus Manager : %s\n", ne->host->is_busmgr ? "yes" : "no");
157 }
158
159
160 list_for_each (l, &ne->unit_directories) {
161 struct unit_directory *ud = list_entry (l, struct unit_directory, node_list);
162 int printed = 0;
163
164 if (ud->parent == NULL)
165 PUTF(" Unit Directory %d:\n", lud_count++);
166 else
167 PUTF(" Logical Unit Directory %d:\n", ud_count++);
168 if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
169 PUTF(" Vendor/Model ID: %s [%06x]",
170 ud->vendor_name ?: "Unknown", ud->vendor_id);
171 printed = 1;
172 }
173 if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
174 if (!printed)
175 PUTF(" Vendor/Model ID: %s [%06x]",
176 ne->vendor_name ?: "Unknown", ne->vendor_id);
177 PUTF(" / %s [%06x]", ud->model_name ?: "Unknown", ud->model_id);
178 printed = 1;
179 }
180 if (printed)
181 PUTF("\n");
182
183 if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
184 PUTF(" Software Specifier ID: %06x\n", ud->specifier_id);
185 if (ud->flags & UNIT_DIRECTORY_VERSION)
186 PUTF(" Software Version: %06x\n", ud->version);
187 if (ud->driver)
188 PUTF(" Driver: %s\n", ud->driver->name);
189 PUTF(" Length (in quads): %d\n", ud->length);
190 }
191
192 }
193
194done_proc:
195 up(&nodemgr_serialize);
196
197 *start = page + (off - begin);
198 len -= (off - begin);
199 if (len > count)
200 len = count;
201 else {
202 *eof = 1;
203 if (len <= 0)
204 return 0;
205 }
206
207 return len;
208}
209
210#undef PUTF
211#endif
212
213static void nodemgr_process_config_rom(struct node_entry *ne,
214 quadlet_t busoptions);
215
216static int nodemgr_read_quadlet(struct hpsb_host *host,
217 nodeid_t nodeid, unsigned int generation,
218 octlet_t address, quadlet_t *quad)
219{
220 int i;
221 int ret = 0;
222
223 for (i = 0; i < 3; i++) {
224 ret = hpsb_read(host, nodeid, generation, address, quad, 4);
225 if (!ret)
226 break;
227
228 set_current_state(TASK_INTERRUPTIBLE);
229 if (schedule_timeout (HZ/3))
230 return -1;
231 }
232 *quad = be32_to_cpu(*quad);
233
234 return ret;
235}
236
237static int nodemgr_size_text_leaf(struct hpsb_host *host,
238 nodeid_t nodeid, unsigned int generation,
239 octlet_t address)
240{
241 quadlet_t quad;
242 int size = 0;
243
244 if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
245 return -1;
246
247 if (CONFIG_ROM_KEY(quad) == CONFIG_ROM_DESCRIPTOR_LEAF) {
248
249 address += 4 * CONFIG_ROM_VALUE(quad);
250 if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
251 return -1;
252
253 size = CONFIG_ROM_LEAF_LENGTH(quad);
254 }
255
256 return size;
257}
258
259static int nodemgr_read_text_leaf(struct node_entry *ne,
260 octlet_t address,
261 quadlet_t *quadp)
262{
263 quadlet_t quad;
264 int i, size, ret;
265
266 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)
267 || CONFIG_ROM_KEY(quad) != CONFIG_ROM_DESCRIPTOR_LEAF)
268 return -1;
269
270
271 address += 4 * CONFIG_ROM_VALUE(quad);
272 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
273 return -1;
274
275
276 size = CONFIG_ROM_LEAF_LENGTH(quad) - 2;
277 if (size <= 0)
278 return -1;
279
280 address += 4;
281 for (i = 0; i < 2; i++, address += 4, quadp++) {
282 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, quadp))
283 return -1;
284 }
285
286
287 ret = -ENXIO;
288 for (; size > 0; size--, address += 4, quadp++) {
289 for (i = 0; i < 3; i++) {
290 ret = hpsb_node_read(ne, address, quadp, 4);
291 if (ret != -EAGAIN)
292 break;
293 }
294 if (ret)
295 break;
296 }
297
298 return ret;
299}
300
301static struct node_entry *nodemgr_scan_root_directory
302 (struct hpsb_host *host, nodeid_t nodeid, unsigned int generation)
303{
304 octlet_t address;
305 quadlet_t quad;
306 int length;
307 int code, size, total_size;
308 struct node_entry *ne;
309
310 address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
311
312 if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
313 return NULL;
314
315 if (CONFIG_ROM_BUS_INFO_LENGTH(quad) == 1)
316 return NULL;
317
318 address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
319
320 if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
321 return NULL;
322 length = CONFIG_ROM_ROOT_LENGTH(quad);
323 address += 4;
324
325 size = 0;
326 total_size = sizeof(struct node_entry);
327 for (; length > 0; length--, address += 4) {
328 if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
329 return NULL;
330 code = CONFIG_ROM_KEY(quad);
331
332 if (code == CONFIG_ROM_VENDOR_ID && length > 0) {
333
334
335 size = nodemgr_size_text_leaf(host, nodeid, generation,
336 address + 4);
337 if (size > 0) {
338 address += 4;
339 length--;
340 total_size += (size + 1) * sizeof (quadlet_t);
341 } else if (size < 0)
342 return NULL;
343 }
344 }
345 ne = kmalloc(total_size, GFP_KERNEL);
346
347 if (!ne)
348 return NULL;
349
350 memset(ne, 0, total_size);
351
352 if (size != 0) {
353 ne->vendor_name = (const char *) &(ne->quadlets[2]);
354 ne->quadlets[size] = 0;
355 } else {
356 ne->vendor_name = NULL;
357 }
358
359 return ne;
360}
361
362static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
363 struct host_info *hi,
364 nodeid_t nodeid, unsigned int generation)
365{
366 struct hpsb_host *host = hi->host;
367 struct node_entry *ne;
368
369 ne = nodemgr_scan_root_directory (host, nodeid, generation);
370 if (!ne) return NULL;
371
372 INIT_LIST_HEAD(&ne->list);
373 INIT_LIST_HEAD(&ne->unit_directories);
374 ne->host = host;
375 ne->nodeid = nodeid;
376 ne->generation = generation;
377 ne->guid = guid;
378 ne->guid_vendor_id = (guid >> 40) & 0xffffff;
379 ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
380
381 list_add_tail(&ne->list, &node_list);
382
383 nodemgr_process_config_rom (ne, busoptions);
384
385 HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
386 (host->node_id == nodeid) ? "Host" : "Node",
387 NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
388
389 return ne;
390}
391
392static struct node_entry *find_entry_by_guid(u64 guid)
393{
394 struct list_head *lh;
395 struct node_entry *ne;
396
397 list_for_each(lh, &node_list) {
398 ne = list_entry(lh, struct node_entry, list);
399 if (ne->guid == guid) return ne;
400 }
401
402 return NULL;
403}
404
405static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid)
406{
407 struct list_head *lh;
408 struct node_entry *ne;
409
410 list_for_each(lh, &node_list) {
411 ne = list_entry(lh, struct node_entry, list);
412 if (ne->nodeid == nodeid && ne->host == host)
413 return ne;
414 }
415
416 return NULL;
417}
418
419static struct unit_directory *nodemgr_scan_unit_directory
420 (struct node_entry *ne, octlet_t address)
421{
422 struct unit_directory *ud;
423 quadlet_t quad;
424 u8 flags, todo;
425 int length, size, total_size, count;
426 int vendor_name_size, model_name_size;
427
428 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
429 return NULL;
430 length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
431 address += 4;
432
433 size = 0;
434 total_size = sizeof (struct unit_directory);
435 flags = 0;
436 count = 0;
437 vendor_name_size = 0;
438 model_name_size = 0;
439 for (; length > 0; length--, address += 4) {
440 int code;
441 quadlet_t value;
442
443 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
444 address, &quad))
445 return NULL;
446 code = CONFIG_ROM_KEY(quad);
447 value = CONFIG_ROM_VALUE(quad);
448
449 todo = 0;
450 switch (code) {
451 case CONFIG_ROM_VENDOR_ID:
452 todo = UNIT_DIRECTORY_VENDOR_TEXT;
453 break;
454
455 case CONFIG_ROM_MODEL_ID:
456 todo = UNIT_DIRECTORY_MODEL_TEXT;
457 break;
458
459 case CONFIG_ROM_SPECIFIER_ID:
460 case CONFIG_ROM_UNIT_SW_VERSION:
461 break;
462
463 case CONFIG_ROM_DESCRIPTOR_LEAF:
464 case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
465
466 break;
467
468 default:
469
470
471
472 code &= CONFIG_ROM_KEY_TYPE_MASK;
473 if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
474 count++;
475 break;
476 }
477
478 if (todo && length > 0) {
479
480
481 size = nodemgr_size_text_leaf(ne->host,
482 ne->nodeid,
483 ne->generation,
484 address + 4);
485
486 if (todo == UNIT_DIRECTORY_VENDOR_TEXT)
487 vendor_name_size = size;
488 else
489 model_name_size = size;
490
491 if (size > 0) {
492 address += 4;
493 length--;
494 flags |= todo;
495 total_size += (size + 1) * sizeof (quadlet_t);
496 }
497 else if (size < 0)
498 return NULL;
499 }
500 }
501
502 total_size += count * sizeof (quadlet_t);
503 ud = kmalloc (total_size, GFP_KERNEL);
504
505 if (ud != NULL) {
506 memset (ud, 0, total_size);
507 ud->flags = flags;
508 ud->length = count;
509 ud->vendor_name_size = vendor_name_size;
510 ud->model_name_size = model_name_size;
511 }
512
513 return ud;
514}
515
516
517
518
519
520static struct unit_directory * nodemgr_process_unit_directory
521 (struct node_entry *ne, octlet_t address, struct unit_directory *parent)
522{
523 struct unit_directory *ud;
524 quadlet_t quad;
525 quadlet_t *infop;
526 int length;
527 struct unit_directory *ud_temp = NULL;
528
529 if (!(ud = nodemgr_scan_unit_directory(ne, address)))
530 goto unit_directory_error;
531
532 ud->ne = ne;
533 ud->address = address;
534
535 if (parent) {
536 ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
537 ud->parent = parent;
538 }
539
540 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
541 address, &quad))
542 goto unit_directory_error;
543 length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
544 address += 4;
545
546 infop = (quadlet_t *) ud->quadlets;
547 for (; length > 0; length--, address += 4) {
548 int code;
549 quadlet_t value;
550 quadlet_t *quadp;
551
552 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
553 address, &quad))
554 goto unit_directory_error;
555 code = CONFIG_ROM_KEY(quad) ;
556 value = CONFIG_ROM_VALUE(quad);
557
558 switch (code) {
559 case CONFIG_ROM_VENDOR_ID:
560 ud->vendor_id = value;
561 ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
562
563 if (ud->vendor_id)
564 ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id);
565
566 if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) {
567 length--;
568 address += 4;
569 quadp = &(ud->quadlets[ud->length]);
570 if (nodemgr_read_text_leaf(ne, address, quadp) == 0
571 && quadp[0] == 0 && quadp[1] == 0) {
572
573
574 quadp[ud->vendor_name_size] = 0;
575 ud->vendor_name
576 = (const char *) &(quadp[2]);
577 }
578 }
579 break;
580
581 case CONFIG_ROM_MODEL_ID:
582 ud->model_id = value;
583 ud->flags |= UNIT_DIRECTORY_MODEL_ID;
584 if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) {
585 length--;
586 address += 4;
587 quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]);
588 if (nodemgr_read_text_leaf(ne, address, quadp) == 0
589 && quadp[0] == 0 && quadp[1] == 0) {
590
591
592 quadp[ud->model_name_size] = 0;
593 ud->model_name
594 = (const char *) &(quadp[2]);
595 }
596 }
597 break;
598
599 case CONFIG_ROM_SPECIFIER_ID:
600 ud->specifier_id = value;
601 ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
602 break;
603
604 case CONFIG_ROM_UNIT_SW_VERSION:
605 ud->version = value;
606 ud->flags |= UNIT_DIRECTORY_VERSION;
607 break;
608
609 case CONFIG_ROM_DESCRIPTOR_LEAF:
610 case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
611
612 break;
613
614 case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY:
615 ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
616 ud_temp = nodemgr_process_unit_directory(ne, address + value * 4, ud);
617
618 if (ud_temp == NULL)
619 break;
620
621
622 if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
623 !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
624 {
625 ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID;
626 ud_temp->vendor_id = ud->vendor_id;
627 }
628 if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
629 !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
630 {
631 ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID;
632 ud_temp->model_id = ud->model_id;
633 }
634 if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
635 !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
636 {
637 ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
638 ud_temp->specifier_id = ud->specifier_id;
639 }
640 if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
641 !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
642 {
643 ud_temp->flags |= UNIT_DIRECTORY_VERSION;
644 ud_temp->version = ud->version;
645 }
646
647 break;
648
649 default:
650
651
652
653 code &= CONFIG_ROM_KEY_TYPE_MASK;
654 if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
655 *infop++ = quad;
656 break;
657 }
658 }
659
660 list_add_tail(&ud->node_list, &ne->unit_directories);
661 list_add_tail(&ud->driver_list, &unit_directory_list);
662
663 return ud;
664
665unit_directory_error:
666 if (ud != NULL)
667 kfree(ud);
668 return NULL;
669}
670
671
672static void nodemgr_process_root_directory(struct node_entry *ne)
673{
674 octlet_t address;
675 quadlet_t quad;
676 int length;
677
678 address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
679
680 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
681 address, &quad))
682 return;
683 address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
684
685 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
686 address, &quad))
687 return;
688 length = CONFIG_ROM_ROOT_LENGTH(quad);
689 address += 4;
690
691 for (; length > 0; length--, address += 4) {
692 int code, value;
693
694 if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
695 address, &quad))
696 return;
697 code = CONFIG_ROM_KEY(quad);
698 value = CONFIG_ROM_VALUE(quad);
699
700 switch (code) {
701 case CONFIG_ROM_VENDOR_ID:
702 ne->vendor_id = value;
703
704 if (ne->vendor_id)
705 ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id);
706
707
708
709 if (ne->vendor_name != NULL) {
710 length--;
711 address += 4;
712 if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0
713 || ne->quadlets[0] != 0 || ne->quadlets[1] != 0)
714
715
716 ne->vendor_name = NULL;
717 }
718 break;
719
720 case CONFIG_ROM_NODE_CAPABILITES:
721 ne->capabilities = value;
722 break;
723
724 case CONFIG_ROM_UNIT_DIRECTORY:
725 nodemgr_process_unit_directory(ne, address + value * 4, NULL);
726 break;
727
728 case CONFIG_ROM_DESCRIPTOR_LEAF:
729 case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
730
731 break;
732 }
733 }
734}
735
736#ifdef CONFIG_HOTPLUG
737
738static void nodemgr_call_policy(char *verb, struct unit_directory *ud)
739{
740 char *argv [3], **envp, *buf, *scratch;
741 int i = 0, value;
742
743 if (!hotplug_path [0])
744 return;
745 if (!current->fs->root)
746 return;
747 if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) {
748 HPSB_DEBUG ("ENOMEM");
749 return;
750 }
751 if (!(buf = kmalloc(256, GFP_KERNEL))) {
752 kfree(envp);
753 HPSB_DEBUG("ENOMEM2");
754 return;
755 }
756
757
758 argv[0] = hotplug_path;
759 argv[1] = "ieee1394";
760 argv[2] = 0;
761
762
763 envp[i++] = "HOME=/";
764 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
765
766#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
767
768 envp[i++] = "DEBUG=kernel";
769#endif
770
771
772
773 scratch = buf;
774
775 envp[i++] = scratch;
776 scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
777 envp[i++] = scratch;
778 scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->vendor_id) + 1;
779 envp[i++] = scratch;
780 scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1;
781 envp[i++] = scratch;
782 scratch += sprintf(scratch, "SPECIFIER_ID=%06x", ud->specifier_id) + 1;
783 envp[i++] = scratch;
784 scratch += sprintf(scratch, "VERSION=%06x", ud->version) + 1;
785 envp[i++] = 0;
786
787
788 HPSB_VERBOSE("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid);
789
790 value = call_usermodehelper(argv[0], argv, envp);
791 kfree(buf);
792 kfree(envp);
793 if (value != 0)
794 HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value);
795}
796
797#else
798
799static inline void
800nodemgr_call_policy(char *verb, struct unit_directory *ud)
801{
802 HPSB_VERBOSE("NodeMgr: nodemgr_call_policy(): hotplug not enabled");
803 return;
804}
805
806#endif
807
808static void nodemgr_claim_unit_directory(struct unit_directory *ud,
809 struct hpsb_protocol_driver *driver)
810{
811 ud->driver = driver;
812 list_move_tail(&ud->driver_list, &driver->unit_directories);
813}
814
815static void nodemgr_release_unit_directory(struct unit_directory *ud)
816{
817 ud->driver = NULL;
818 list_move_tail(&ud->driver_list, &unit_directory_list);
819}
820
821void hpsb_release_unit_directory(struct unit_directory *ud)
822{
823 down(&nodemgr_serialize);
824 nodemgr_release_unit_directory(ud);
825 up(&nodemgr_serialize);
826}
827
828static void nodemgr_free_unit_directories(struct node_entry *ne)
829{
830 struct list_head *lh, *next;
831 struct unit_directory *ud;
832
833 list_for_each_safe(lh, next, &ne->unit_directories) {
834 ud = list_entry(lh, struct unit_directory, node_list);
835
836 if (ud->driver && ud->driver->disconnect)
837 ud->driver->disconnect(ud);
838
839 nodemgr_release_unit_directory(ud);
840 nodemgr_call_policy("remove", ud);
841
842 list_del(&ud->driver_list);
843 list_del(&ud->node_list);
844
845 kfree(ud);
846 }
847}
848
849static struct ieee1394_device_id *
850nodemgr_match_driver(struct hpsb_protocol_driver *driver,
851 struct unit_directory *ud)
852{
853 struct ieee1394_device_id *id;
854
855 for (id = driver->id_table; id->match_flags != 0; id++) {
856 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
857 id->vendor_id != ud->vendor_id)
858 continue;
859
860 if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
861 id->model_id != ud->model_id)
862 continue;
863
864 if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
865 id->specifier_id != ud->specifier_id)
866 continue;
867
868
869 if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
870 !(id->version & ud->version))
871 continue;
872
873 return id;
874 }
875
876 return NULL;
877}
878
879static struct hpsb_protocol_driver *
880nodemgr_find_driver(struct unit_directory *ud)
881{
882 struct list_head *l;
883 struct hpsb_protocol_driver *match, *driver;
884 struct ieee1394_device_id *device_id;
885
886 match = NULL;
887 list_for_each(l, &driver_list) {
888 driver = list_entry(l, struct hpsb_protocol_driver, list);
889 device_id = nodemgr_match_driver(driver, ud);
890
891 if (device_id != NULL) {
892 match = driver;
893 break;
894 }
895 }
896
897 return match;
898}
899
900static void nodemgr_bind_drivers (struct node_entry *ne)
901{
902 struct list_head *lh;
903 struct hpsb_protocol_driver *driver;
904 struct unit_directory *ud;
905
906 list_for_each(lh, &ne->unit_directories) {
907 ud = list_entry(lh, struct unit_directory, node_list);
908 driver = nodemgr_find_driver(ud);
909 if (driver && (!driver->probe || driver->probe(ud) == 0))
910 nodemgr_claim_unit_directory(ud, driver);
911 nodemgr_call_policy("add", ud);
912 }
913}
914
915
916int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
917{
918 struct unit_directory *ud;
919 struct list_head *lh, *next;
920
921 if (down_interruptible(&nodemgr_serialize))
922 return -EINTR;
923
924 list_add_tail(&driver->list, &driver_list);
925
926 INIT_LIST_HEAD(&driver->unit_directories);
927
928 list_for_each_safe (lh, next, &unit_directory_list) {
929 ud = list_entry(lh, struct unit_directory, driver_list);
930
931 if (nodemgr_match_driver(driver, ud) &&
932 (!driver->probe || driver->probe(ud) == 0))
933 nodemgr_claim_unit_directory(ud, driver);
934 }
935
936 up(&nodemgr_serialize);
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955 return 0;
956}
957
958void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
959{
960 struct list_head *lh, *next;
961 struct unit_directory *ud;
962
963 down(&nodemgr_serialize);
964
965 list_del(&driver->list);
966
967 list_for_each_safe (lh, next, &driver->unit_directories) {
968 ud = list_entry(lh, struct unit_directory, driver_list);
969
970 if (ud->driver && ud->driver->disconnect)
971 ud->driver->disconnect(ud);
972
973 nodemgr_release_unit_directory(ud);
974 }
975
976 up(&nodemgr_serialize);
977}
978
979static void nodemgr_process_config_rom(struct node_entry *ne,
980 quadlet_t busoptions)
981{
982 ne->busopt.irmc = (busoptions >> 31) & 1;
983 ne->busopt.cmc = (busoptions >> 30) & 1;
984 ne->busopt.isc = (busoptions >> 29) & 1;
985 ne->busopt.bmc = (busoptions >> 28) & 1;
986 ne->busopt.pmc = (busoptions >> 27) & 1;
987 ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
988 ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
989 ne->busopt.generation = (busoptions >> 4) & 0xf;
990 ne->busopt.lnkspd = busoptions & 0x7;
991
992 HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
993 "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
994 busoptions, ne->busopt.irmc, ne->busopt.cmc,
995 ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
996 ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
997 ne->busopt.generation, ne->busopt.lnkspd);
998
999
1000
1001
1002
1003
1004
1005 nodemgr_free_unit_directories(ne);
1006 nodemgr_process_root_directory(ne);
1007 nodemgr_bind_drivers(ne);
1008}
1009
1010
1011
1012
1013
1014
1015
1016
1017static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
1018 struct host_info *hi, nodeid_t nodeid,
1019 unsigned int generation)
1020{
1021 struct list_head *lh;
1022 struct unit_directory *ud;
1023
1024 if (ne->nodeid != nodeid) {
1025 HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
1026 NODE_BUS_ARGS(ne->host, ne->nodeid),
1027 NODE_BUS_ARGS(ne->host, nodeid));
1028 ne->nodeid = nodeid;
1029 }
1030
1031 ne->generation = generation;
1032
1033 if (ne->busopt.generation != ((busoptions >> 4) & 0xf))
1034 nodemgr_process_config_rom (ne, busoptions);
1035
1036 list_for_each (lh, &ne->unit_directories) {
1037 ud = list_entry (lh, struct unit_directory, node_list);
1038 if (ud->driver && ud->driver->update != NULL)
1039 ud->driver->update(ud);
1040 }
1041}
1042
1043static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation,
1044 quadlet_t *buffer, int buffer_length)
1045{
1046 octlet_t addr = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
1047 unsigned header_size;
1048 int i;
1049
1050
1051
1052
1053
1054
1055 HPSB_VERBOSE("Initiating ConfigROM request for node " NODE_BUS_FMT,
1056 NODE_BUS_ARGS(host, nodeid));
1057
1058
1059
1060
1061
1062
1063
1064
1065 for (i = 0; i < 4; i++) {
1066 if (nodemgr_read_quadlet(host, nodeid, generation,
1067 addr, &buffer[0]) < 0) {
1068 HPSB_ERR("ConfigROM quadlet transaction error for node "
1069 NODE_BUS_FMT, NODE_BUS_ARGS(host, nodeid));
1070 return -1;
1071 }
1072 if (buffer[0])
1073 break;
1074
1075 set_current_state(TASK_INTERRUPTIBLE);
1076 if (schedule_timeout (HZ/4))
1077 return -1;
1078 }
1079
1080 header_size = buffer[0] >> 24;
1081 addr += 4;
1082
1083 if (header_size == 1) {
1084 HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM. "
1085 "Vendor is %08x",
1086 NODE_BUS_ARGS(host, nodeid), buffer[0] & 0x00ffffff);
1087 return -1;
1088 }
1089
1090 if (header_size < 4) {
1091 HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM "
1092 "format (%d quads), cannot parse",
1093 NODE_BUS_ARGS(host, nodeid), header_size);
1094 return -1;
1095 }
1096
1097 for (i = 1; i < buffer_length; i++, addr += 4) {
1098 if (nodemgr_read_quadlet(host, nodeid, generation,
1099 addr, &buffer[i]) < 0) {
1100 HPSB_ERR("ConfigROM quadlet transaction "
1101 "error for node " NODE_BUS_FMT,
1102 NODE_BUS_ARGS(host, nodeid));
1103 return -1;
1104 }
1105 }
1106
1107 return 0;
1108}
1109
1110static void nodemgr_remove_node(struct node_entry *ne)
1111{
1112 HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
1113 NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
1114
1115 nodemgr_free_unit_directories(ne);
1116 list_del(&ne->list);
1117 kfree(ne);
1118
1119 return;
1120}
1121
1122
1123
1124static void nodemgr_node_probe_one(struct host_info *hi,
1125 nodeid_t nodeid, int generation)
1126{
1127 struct hpsb_host *host = hi->host;
1128 struct node_entry *ne;
1129 quadlet_t buffer[5];
1130 octlet_t guid;
1131
1132
1133
1134
1135 if (read_businfo_block (host, nodeid, generation,
1136 buffer, sizeof(buffer) >> 2))
1137 return;
1138
1139 if (buffer[1] != IEEE1394_BUSID_MAGIC) {
1140
1141
1142
1143
1144
1145
1146
1147 HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",
1148 NODE_BUS_ARGS(host, nodeid), buffer[1]);
1149 }
1150
1151 guid = ((u64)buffer[3] << 32) | buffer[4];
1152 ne = find_entry_by_guid(guid);
1153
1154 if (!ne)
1155 nodemgr_create_node(guid, buffer[2], hi, nodeid, generation);
1156 else
1157 nodemgr_update_node(ne, buffer[2], hi, nodeid, generation);
1158
1159 return;
1160}
1161
1162static void nodemgr_node_probe_cleanup(struct hpsb_host *host, unsigned int generation)
1163{
1164 struct list_head *lh, *next;
1165 struct node_entry *ne;
1166
1167
1168
1169 list_for_each_safe(lh, next, &node_list) {
1170 ne = list_entry(lh, struct node_entry, list);
1171
1172
1173 if (ne->host != host)
1174 continue;
1175
1176
1177
1178
1179
1180 if (ne->generation != generation)
1181 nodemgr_remove_node(ne);
1182 }
1183
1184 return;
1185}
1186
1187static void nodemgr_node_probe(struct host_info *hi, int generation)
1188{
1189 int count;
1190 struct hpsb_host *host = hi->host;
1191 struct selfid *sid = (struct selfid *)host->topology_map;
1192 nodeid_t nodeid = LOCAL_BUS;
1193
1194
1195 for (count = host->selfid_count; count; count--, sid++) {
1196 if (sid->extended)
1197 continue;
1198
1199 if (!sid->link_active) {
1200 nodeid++;
1201 continue;
1202 }
1203 nodemgr_node_probe_one(hi, nodeid++, generation);
1204 }
1205
1206
1207
1208
1209
1210
1211
1212 if (generation == get_hpsb_generation(host))
1213 nodemgr_node_probe_cleanup(host, generation);
1214
1215 return;
1216}
1217
1218
1219
1220
1221static void nodemgr_do_irm_duties(struct hpsb_host *host)
1222{
1223 quadlet_t bc;
1224
1225 if (!host->is_irm)
1226 return;
1227
1228 host->csr.broadcast_channel |= 0x40000000;
1229
1230 bc = cpu_to_be32(host->csr.broadcast_channel);
1231
1232 hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
1233 (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
1234 &bc, sizeof(quadlet_t));
1235
1236
1237
1238
1239 if (host->busmgr_id == 0xffff && host->node_count > 1)
1240 {
1241 u16 root_node = host->node_count - 1;
1242 struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS);
1243
1244 if (ne && ne->busopt.cmc)
1245 hpsb_send_phy_config(host, root_node, -1);
1246 else {
1247 HPSB_DEBUG("The root node is not cycle master capable; "
1248 "selecting a new root node and resetting...");
1249 hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
1250 hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
1251 }
1252 }
1253}
1254
1255
1256
1257
1258static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
1259{
1260 quadlet_t bc;
1261 int status;
1262
1263 if (host->is_irm)
1264 return 1;
1265
1266 status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
1267 get_hpsb_generation(host),
1268 (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
1269 &bc, sizeof(quadlet_t));
1270
1271 if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
1272
1273
1274 HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting...");
1275
1276 if (cycles >= 5) {
1277
1278 HPSB_DEBUG("Stopping reset loop for IRM sanity");
1279 return 1;
1280 }
1281
1282 hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
1283 hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
1284
1285 return 0;
1286 }
1287
1288 return 1;
1289}
1290
1291static int nodemgr_host_thread(void *__hi)
1292{
1293 struct host_info *hi = (struct host_info *)__hi;
1294 struct hpsb_host *host = hi->host;
1295 int reset_cycles = 0;
1296
1297
1298 daemonize();
1299
1300 strcpy(current->comm, hi->daemon_name);
1301
1302
1303
1304 while (!down_interruptible(&hi->reset_sem) &&
1305 !down_interruptible(&nodemgr_serialize)) {
1306 unsigned int generation = 0;
1307 int i;
1308
1309
1310
1311 for (i = 0; i < 4 ; i++) {
1312 set_current_state(TASK_INTERRUPTIBLE);
1313 if (schedule_timeout(HZ/16)) {
1314 up(&nodemgr_serialize);
1315 goto caught_signal;
1316 }
1317
1318
1319
1320
1321
1322
1323 generation = get_hpsb_generation(host);
1324
1325
1326
1327 while (!down_trylock(&hi->reset_sem))
1328 i = 0;
1329 }
1330
1331 if (!nodemgr_check_irm_capability(host, reset_cycles++)) {
1332
1333 up(&nodemgr_serialize);
1334 continue;
1335 }
1336
1337 reset_cycles = 0;
1338
1339 nodemgr_node_probe(hi, generation);
1340 nodemgr_do_irm_duties(host);
1341
1342 up(&nodemgr_serialize);
1343 }
1344
1345caught_signal:
1346 HPSB_VERBOSE("NodeMgr: Exiting thread");
1347
1348 complete_and_exit(&hi->exited, 0);
1349}
1350
1351struct node_entry *hpsb_guid_get_entry(u64 guid)
1352{
1353 struct node_entry *ne;
1354
1355 down(&nodemgr_serialize);
1356 ne = find_entry_by_guid(guid);
1357 up(&nodemgr_serialize);
1358
1359 return ne;
1360}
1361
1362struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid)
1363{
1364 struct node_entry *ne;
1365
1366 down(&nodemgr_serialize);
1367 ne = find_entry_by_nodeid(host, nodeid);
1368 up(&nodemgr_serialize);
1369
1370 return ne;
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
1389{
1390 pkt->host = ne->host;
1391 pkt->generation = ne->generation;
1392 barrier();
1393 pkt->node_id = ne->nodeid;
1394}
1395
1396int hpsb_node_read(struct node_entry *ne, u64 addr,
1397 quadlet_t *buffer, size_t length)
1398{
1399 unsigned int generation = ne->generation;
1400
1401 barrier();
1402 return hpsb_read(ne->host, ne->nodeid, generation,
1403 addr, buffer, length);
1404}
1405
1406int hpsb_node_write(struct node_entry *ne, u64 addr,
1407 quadlet_t *buffer, size_t length)
1408{
1409 unsigned int generation = ne->generation;
1410
1411 barrier();
1412 return hpsb_write(ne->host, ne->nodeid, generation,
1413 addr, buffer, length);
1414}
1415
1416int hpsb_node_lock(struct node_entry *ne, u64 addr,
1417 int extcode, quadlet_t *data, quadlet_t arg)
1418{
1419 unsigned int generation = ne->generation;
1420
1421 barrier();
1422 return hpsb_lock(ne->host, ne->nodeid, generation,
1423 addr, extcode, data, arg);
1424}
1425
1426static void nodemgr_add_host(struct hpsb_host *host)
1427{
1428 struct host_info *hi;
1429
1430 hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi));
1431
1432 if (!hi) {
1433 HPSB_ERR ("NodeMgr: out of memory in add host");
1434 return;
1435 }
1436
1437 hi->host = host;
1438 init_completion(&hi->exited);
1439 sema_init(&hi->reset_sem, 0);
1440
1441 sprintf(hi->daemon_name, "knodemgrd_%d", host->id);
1442
1443 hi->pid = kernel_thread(nodemgr_host_thread, hi,
1444 CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
1445
1446 if (hi->pid < 0) {
1447 HPSB_ERR ("NodeMgr: failed to start %s thread for %s",
1448 hi->daemon_name, host->driver->name);
1449 hpsb_destroy_hostinfo(&nodemgr_highlevel, host);
1450 return;
1451 }
1452
1453 return;
1454}
1455
1456static void nodemgr_host_reset(struct hpsb_host *host)
1457{
1458 struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
1459
1460 if (hi != NULL) {
1461 HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name);
1462 up(&hi->reset_sem);
1463 } else
1464 HPSB_ERR ("NodeMgr: could not process reset of unused host");
1465
1466 return;
1467}
1468
1469static void nodemgr_remove_host(struct hpsb_host *host)
1470{
1471 struct list_head *lh, *next;
1472 struct node_entry *ne;
1473 struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
1474
1475 if (hi) {
1476 if (hi->pid >= 0) {
1477 kill_proc(hi->pid, SIGTERM, 1);
1478 wait_for_completion(&hi->exited);
1479 }
1480 } else
1481 HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
1482 host->driver->name);
1483
1484 down(&nodemgr_serialize);
1485
1486
1487
1488 list_for_each_safe(lh, next, &node_list) {
1489 ne = list_entry(lh, struct node_entry, list);
1490
1491 if (ne->host == host)
1492 nodemgr_remove_node(ne);
1493 }
1494
1495 up(&nodemgr_serialize);
1496
1497 return;
1498}
1499
1500static struct hpsb_highlevel nodemgr_highlevel = {
1501 .name = "Node manager",
1502 .add_host = nodemgr_add_host,
1503 .host_reset = nodemgr_host_reset,
1504 .remove_host = nodemgr_remove_host,
1505};
1506
1507#define PROC_ENTRY "devices"
1508
1509void init_ieee1394_nodemgr(void)
1510{
1511#ifdef CONFIG_PROC_FS
1512 if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, raw1394_read_proc, NULL))
1513 HPSB_ERR("Can't create devices procfs entry");
1514#endif
1515 hpsb_register_highlevel(&nodemgr_highlevel);
1516}
1517
1518void cleanup_ieee1394_nodemgr(void)
1519{
1520 hpsb_unregister_highlevel(&nodemgr_highlevel);
1521#ifdef CONFIG_PROC_FS
1522 remove_proc_entry(PROC_ENTRY, ieee1394_procfs_entry);
1523#endif
1524}
1525