diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/rapidio/rio-scan.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/rapidio/rio-scan.c')
-rw-r--r-- | drivers/rapidio/rio-scan.c | 329 |
1 files changed, 162 insertions, 167 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 8070e074c739..ee893581d4b7 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -46,9 +46,8 @@ static void rio_init_em(struct rio_dev *rdev); | |||
46 | DEFINE_SPINLOCK(rio_global_list_lock); | 46 | DEFINE_SPINLOCK(rio_global_list_lock); |
47 | 47 | ||
48 | static int next_destid = 0; | 48 | static int next_destid = 0; |
49 | static int next_switchid = 0; | ||
50 | static int next_net = 0; | 49 | static int next_net = 0; |
51 | static int next_comptag; | 50 | static int next_comptag = 1; |
52 | 51 | ||
53 | static struct timer_list rio_enum_timer = | 52 | static struct timer_list rio_enum_timer = |
54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); | 53 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); |
@@ -121,27 +120,6 @@ static int rio_clear_locks(struct rio_mport *port) | |||
121 | u32 result; | 120 | u32 result; |
122 | int ret = 0; | 121 | int ret = 0; |
123 | 122 | ||
124 | /* Assign component tag to all devices */ | ||
125 | next_comptag = 1; | ||
126 | rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++); | ||
127 | |||
128 | list_for_each_entry(rdev, &rio_devices, global_list) { | ||
129 | /* Mark device as discovered */ | ||
130 | rio_read_config_32(rdev, | ||
131 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
132 | &result); | ||
133 | rio_write_config_32(rdev, | ||
134 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
135 | result | RIO_PORT_GEN_DISCOVERED); | ||
136 | |||
137 | rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag); | ||
138 | rdev->comp_tag = next_comptag++; | ||
139 | if (next_comptag >= 0x10000) { | ||
140 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
141 | break; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* Release host device id locks */ | 123 | /* Release host device id locks */ |
146 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, | 124 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, |
147 | port->host_deviceid); | 125 | port->host_deviceid); |
@@ -162,6 +140,15 @@ static int rio_clear_locks(struct rio_mport *port) | |||
162 | rdev->vid, rdev->did); | 140 | rdev->vid, rdev->did); |
163 | ret = -EINVAL; | 141 | ret = -EINVAL; |
164 | } | 142 | } |
143 | |||
144 | /* Mark device as discovered and enable master */ | ||
145 | rio_read_config_32(rdev, | ||
146 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
147 | &result); | ||
148 | result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER; | ||
149 | rio_write_config_32(rdev, | ||
150 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
151 | result); | ||
165 | } | 152 | } |
166 | 153 | ||
167 | return ret; | 154 | return ret; |
@@ -308,7 +295,7 @@ static int __devinit rio_add_device(struct rio_dev *rdev) | |||
308 | } | 295 | } |
309 | 296 | ||
310 | /** | 297 | /** |
311 | * rio_enable_rx_tx_port - enable input reciever and output transmitter of | 298 | * rio_enable_rx_tx_port - enable input receiver and output transmitter of |
312 | * given port | 299 | * given port |
313 | * @port: Master port associated with the RIO network | 300 | * @port: Master port associated with the RIO network |
314 | * @local: local=1 select local port otherwise a far device is reached | 301 | * @local: local=1 select local port otherwise a far device is reached |
@@ -390,12 +377,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
390 | struct rio_dev *rdev; | 377 | struct rio_dev *rdev; |
391 | struct rio_switch *rswitch = NULL; | 378 | struct rio_switch *rswitch = NULL; |
392 | int result, rdid; | 379 | int result, rdid; |
380 | size_t size; | ||
381 | u32 swpinfo = 0; | ||
382 | |||
383 | size = sizeof(struct rio_dev); | ||
384 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
385 | RIO_PEF_CAR, &result)) | ||
386 | return NULL; | ||
393 | 387 | ||
394 | rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); | 388 | if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { |
389 | rio_mport_read_config_32(port, destid, hopcount, | ||
390 | RIO_SWP_INFO_CAR, &swpinfo); | ||
391 | if (result & RIO_PEF_SWITCH) { | ||
392 | size += (RIO_GET_TOTAL_PORTS(swpinfo) * | ||
393 | sizeof(rswitch->nextdev[0])) + sizeof(*rswitch); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | rdev = kzalloc(size, GFP_KERNEL); | ||
395 | if (!rdev) | 398 | if (!rdev) |
396 | return NULL; | 399 | return NULL; |
397 | 400 | ||
398 | rdev->net = net; | 401 | rdev->net = net; |
402 | rdev->pef = result; | ||
403 | rdev->swpinfo = swpinfo; | ||
399 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, | 404 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, |
400 | &result); | 405 | &result); |
401 | rdev->did = result >> 16; | 406 | rdev->did = result >> 16; |
@@ -409,8 +414,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
409 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, | 414 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, |
410 | &result); | 415 | &result); |
411 | rdev->asm_rev = result >> 16; | 416 | rdev->asm_rev = result >> 16; |
412 | rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, | ||
413 | &rdev->pef); | ||
414 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { | 417 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { |
415 | rdev->efptr = result & 0xffff; | 418 | rdev->efptr = result & 0xffff; |
416 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, | 419 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, |
@@ -425,6 +428,21 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
425 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, | 428 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, |
426 | &rdev->dst_ops); | 429 | &rdev->dst_ops); |
427 | 430 | ||
431 | if (do_enum) { | ||
432 | /* Assign component tag to device */ | ||
433 | if (next_comptag >= 0x10000) { | ||
434 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
435 | goto cleanup; | ||
436 | } | ||
437 | rio_mport_write_config_32(port, destid, hopcount, | ||
438 | RIO_COMPONENT_TAG_CSR, next_comptag); | ||
439 | rdev->comp_tag = next_comptag++; | ||
440 | } else { | ||
441 | rio_mport_read_config_32(port, destid, hopcount, | ||
442 | RIO_COMPONENT_TAG_CSR, | ||
443 | &rdev->comp_tag); | ||
444 | } | ||
445 | |||
428 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { | 446 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { |
429 | if (do_enum) { | 447 | if (do_enum) { |
430 | rio_set_device_id(port, destid, hopcount, next_destid); | 448 | rio_set_device_id(port, destid, hopcount, next_destid); |
@@ -433,20 +451,20 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
433 | next_destid++; | 451 | next_destid++; |
434 | } else | 452 | } else |
435 | rdev->destid = rio_get_device_id(port, destid, hopcount); | 453 | rdev->destid = rio_get_device_id(port, destid, hopcount); |
436 | } else | 454 | |
437 | /* Switch device has an associated destID */ | 455 | rdev->hopcount = 0xff; |
438 | rdev->destid = RIO_INVALID_DESTID; | 456 | } else { |
457 | /* Switch device has an associated destID which | ||
458 | * will be adjusted later | ||
459 | */ | ||
460 | rdev->destid = destid; | ||
461 | rdev->hopcount = hopcount; | ||
462 | } | ||
439 | 463 | ||
440 | /* If a PE has both switch and other functions, show it as a switch */ | 464 | /* If a PE has both switch and other functions, show it as a switch */ |
441 | if (rio_is_switch(rdev)) { | 465 | if (rio_is_switch(rdev)) { |
442 | rio_mport_read_config_32(port, destid, hopcount, | 466 | rswitch = rdev->rswitch; |
443 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | 467 | rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; |
444 | rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); | ||
445 | if (!rswitch) | ||
446 | goto cleanup; | ||
447 | rswitch->switchid = next_switchid; | ||
448 | rswitch->hopcount = hopcount; | ||
449 | rswitch->destid = destid; | ||
450 | rswitch->port_ok = 0; | 468 | rswitch->port_ok = 0; |
451 | rswitch->route_table = kzalloc(sizeof(u8)* | 469 | rswitch->route_table = kzalloc(sizeof(u8)* |
452 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), | 470 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), |
@@ -457,14 +475,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
457 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); | 475 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); |
458 | rdid++) | 476 | rdid++) |
459 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; | 477 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; |
460 | rdev->rswitch = rswitch; | ||
461 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, | 478 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
462 | rdev->rswitch->switchid); | 479 | rswitch->switchid); |
463 | rio_switch_init(rdev, do_enum); | 480 | rio_switch_init(rdev, do_enum); |
464 | 481 | ||
465 | if (do_enum && rdev->rswitch->clr_table) | 482 | if (do_enum && rswitch->clr_table) |
466 | rdev->rswitch->clr_table(port, destid, hopcount, | 483 | rswitch->clr_table(port, destid, hopcount, |
467 | RIO_GLOBAL_TABLE); | 484 | RIO_GLOBAL_TABLE); |
468 | 485 | ||
469 | list_add_tail(&rswitch->node, &rio_switches); | 486 | list_add_tail(&rswitch->node, &rio_switches); |
470 | 487 | ||
@@ -478,6 +495,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
478 | } | 495 | } |
479 | 496 | ||
480 | rdev->dev.bus = &rio_bus_type; | 497 | rdev->dev.bus = &rio_bus_type; |
498 | rdev->dev.parent = &rio_bus; | ||
481 | 499 | ||
482 | device_initialize(&rdev->dev); | 500 | device_initialize(&rdev->dev); |
483 | rdev->dev.release = rio_release_dev; | 501 | rdev->dev.release = rio_release_dev; |
@@ -499,10 +517,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
499 | return rdev; | 517 | return rdev; |
500 | 518 | ||
501 | cleanup: | 519 | cleanup: |
502 | if (rswitch) { | 520 | if (rio_is_switch(rdev)) |
503 | kfree(rswitch->route_table); | 521 | kfree(rswitch->route_table); |
504 | kfree(rswitch); | 522 | |
505 | } | ||
506 | kfree(rdev); | 523 | kfree(rdev); |
507 | return NULL; | 524 | return NULL; |
508 | } | 525 | } |
@@ -625,8 +642,7 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | |||
625 | 642 | ||
626 | /** | 643 | /** |
627 | * rio_route_add_entry- Add a route entry to a switch routing table | 644 | * rio_route_add_entry- Add a route entry to a switch routing table |
628 | * @mport: Master port to send transaction | 645 | * @rdev: RIO device |
629 | * @rswitch: Switch device | ||
630 | * @table: Routing table ID | 646 | * @table: Routing table ID |
631 | * @route_destid: Destination ID to be routed | 647 | * @route_destid: Destination ID to be routed |
632 | * @route_port: Port number to be routed | 648 | * @route_port: Port number to be routed |
@@ -640,31 +656,31 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | |||
640 | * on failure. | 656 | * on failure. |
641 | */ | 657 | */ |
642 | static int | 658 | static int |
643 | rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, | 659 | rio_route_add_entry(struct rio_dev *rdev, |
644 | u16 table, u16 route_destid, u8 route_port, int lock) | 660 | u16 table, u16 route_destid, u8 route_port, int lock) |
645 | { | 661 | { |
646 | int rc; | 662 | int rc; |
647 | 663 | ||
648 | if (lock) { | 664 | if (lock) { |
649 | rc = rio_lock_device(mport, rswitch->destid, | 665 | rc = rio_lock_device(rdev->net->hport, rdev->destid, |
650 | rswitch->hopcount, 1000); | 666 | rdev->hopcount, 1000); |
651 | if (rc) | 667 | if (rc) |
652 | return rc; | 668 | return rc; |
653 | } | 669 | } |
654 | 670 | ||
655 | rc = rswitch->add_entry(mport, rswitch->destid, | 671 | rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid, |
656 | rswitch->hopcount, table, | 672 | rdev->hopcount, table, |
657 | route_destid, route_port); | 673 | route_destid, route_port); |
658 | if (lock) | 674 | if (lock) |
659 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | 675 | rio_unlock_device(rdev->net->hport, rdev->destid, |
676 | rdev->hopcount); | ||
660 | 677 | ||
661 | return rc; | 678 | return rc; |
662 | } | 679 | } |
663 | 680 | ||
664 | /** | 681 | /** |
665 | * rio_route_get_entry- Read a route entry in a switch routing table | 682 | * rio_route_get_entry- Read a route entry in a switch routing table |
666 | * @mport: Master port to send transaction | 683 | * @rdev: RIO device |
667 | * @rswitch: Switch device | ||
668 | * @table: Routing table ID | 684 | * @table: Routing table ID |
669 | * @route_destid: Destination ID to be routed | 685 | * @route_destid: Destination ID to be routed |
670 | * @route_port: Pointer to read port number into | 686 | * @route_port: Pointer to read port number into |
@@ -678,23 +694,24 @@ rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, | |||
678 | * on failure. | 694 | * on failure. |
679 | */ | 695 | */ |
680 | static int | 696 | static int |
681 | rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, | 697 | rio_route_get_entry(struct rio_dev *rdev, u16 table, |
682 | u16 route_destid, u8 *route_port, int lock) | 698 | u16 route_destid, u8 *route_port, int lock) |
683 | { | 699 | { |
684 | int rc; | 700 | int rc; |
685 | 701 | ||
686 | if (lock) { | 702 | if (lock) { |
687 | rc = rio_lock_device(mport, rswitch->destid, | 703 | rc = rio_lock_device(rdev->net->hport, rdev->destid, |
688 | rswitch->hopcount, 1000); | 704 | rdev->hopcount, 1000); |
689 | if (rc) | 705 | if (rc) |
690 | return rc; | 706 | return rc; |
691 | } | 707 | } |
692 | 708 | ||
693 | rc = rswitch->get_entry(mport, rswitch->destid, | 709 | rc = rdev->rswitch->get_entry(rdev->net->hport, rdev->destid, |
694 | rswitch->hopcount, table, | 710 | rdev->hopcount, table, |
695 | route_destid, route_port); | 711 | route_destid, route_port); |
696 | if (lock) | 712 | if (lock) |
697 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | 713 | rio_unlock_device(rdev->net->hport, rdev->destid, |
714 | rdev->hopcount); | ||
698 | 715 | ||
699 | return rc; | 716 | return rc; |
700 | } | 717 | } |
@@ -718,86 +735,53 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) | |||
718 | } | 735 | } |
719 | 736 | ||
720 | /** | 737 | /** |
721 | * rio_get_swpinfo_inport- Gets the ingress port number | ||
722 | * @mport: Master port to send transaction | ||
723 | * @destid: Destination ID associated with the switch | ||
724 | * @hopcount: Number of hops to the device | ||
725 | * | ||
726 | * Returns port number being used to access the switch device. | ||
727 | */ | ||
728 | static u8 | ||
729 | rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) | ||
730 | { | ||
731 | u32 result; | ||
732 | |||
733 | rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, | ||
734 | &result); | ||
735 | |||
736 | return (u8) (result & 0xff); | ||
737 | } | ||
738 | |||
739 | /** | ||
740 | * rio_get_swpinfo_tports- Gets total number of ports on the switch | ||
741 | * @mport: Master port to send transaction | ||
742 | * @destid: Destination ID associated with the switch | ||
743 | * @hopcount: Number of hops to the device | ||
744 | * | ||
745 | * Returns total numbers of ports implemented by the switch device. | ||
746 | */ | ||
747 | static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, | ||
748 | u8 hopcount) | ||
749 | { | ||
750 | u32 result; | ||
751 | |||
752 | rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, | ||
753 | &result); | ||
754 | |||
755 | return RIO_GET_TOTAL_PORTS(result); | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * rio_net_add_mport- Add a master port to a RIO network | ||
760 | * @net: RIO network | ||
761 | * @port: Master port to add | ||
762 | * | ||
763 | * Adds a master port to the network list of associated master | ||
764 | * ports.. | ||
765 | */ | ||
766 | static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) | ||
767 | { | ||
768 | spin_lock(&rio_global_list_lock); | ||
769 | list_add_tail(&port->nnode, &net->mports); | ||
770 | spin_unlock(&rio_global_list_lock); | ||
771 | } | ||
772 | |||
773 | /** | ||
774 | * rio_enum_peer- Recursively enumerate a RIO network through a master port | 738 | * rio_enum_peer- Recursively enumerate a RIO network through a master port |
775 | * @net: RIO network being enumerated | 739 | * @net: RIO network being enumerated |
776 | * @port: Master port to send transactions | 740 | * @port: Master port to send transactions |
777 | * @hopcount: Number of hops into the network | 741 | * @hopcount: Number of hops into the network |
742 | * @prev: Previous RIO device connected to the enumerated one | ||
743 | * @prev_port: Port on previous RIO device | ||
778 | * | 744 | * |
779 | * Recursively enumerates a RIO network. Transactions are sent via the | 745 | * Recursively enumerates a RIO network. Transactions are sent via the |
780 | * master port passed in @port. | 746 | * master port passed in @port. |
781 | */ | 747 | */ |
782 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | 748 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, |
783 | u8 hopcount) | 749 | u8 hopcount, struct rio_dev *prev, int prev_port) |
784 | { | 750 | { |
785 | int port_num; | 751 | int port_num; |
786 | int num_ports; | ||
787 | int cur_destid; | 752 | int cur_destid; |
788 | int sw_destid; | 753 | int sw_destid; |
789 | int sw_inport; | 754 | int sw_inport; |
790 | struct rio_dev *rdev; | 755 | struct rio_dev *rdev; |
791 | u16 destid; | 756 | u16 destid; |
757 | u32 regval; | ||
792 | int tmp; | 758 | int tmp; |
793 | 759 | ||
760 | if (rio_mport_chk_dev_access(port, | ||
761 | RIO_ANY_DESTID(port->sys_size), hopcount)) { | ||
762 | pr_debug("RIO: device access check failed\n"); | ||
763 | return -1; | ||
764 | } | ||
765 | |||
794 | if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { | 766 | if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { |
795 | pr_debug("RIO: PE already discovered by this host\n"); | 767 | pr_debug("RIO: PE already discovered by this host\n"); |
796 | /* | 768 | /* |
797 | * Already discovered by this host. Add it as another | 769 | * Already discovered by this host. Add it as another |
798 | * master port for the current network. | 770 | * link to the existing device. |
799 | */ | 771 | */ |
800 | rio_net_add_mport(net, port); | 772 | rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), |
773 | hopcount, RIO_COMPONENT_TAG_CSR, ®val); | ||
774 | |||
775 | if (regval) { | ||
776 | rdev = rio_get_comptag((regval & 0xffff), NULL); | ||
777 | |||
778 | if (rdev && prev && rio_is_switch(prev)) { | ||
779 | pr_debug("RIO: redundant path to %s\n", | ||
780 | rio_name(rdev)); | ||
781 | prev->rswitch->nextdev[prev_port] = rdev; | ||
782 | } | ||
783 | } | ||
784 | |||
801 | return 0; | 785 | return 0; |
802 | } | 786 | } |
803 | 787 | ||
@@ -828,33 +812,34 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
828 | if (rdev) { | 812 | if (rdev) { |
829 | /* Add device to the global and bus/net specific list. */ | 813 | /* Add device to the global and bus/net specific list. */ |
830 | list_add_tail(&rdev->net_list, &net->devices); | 814 | list_add_tail(&rdev->net_list, &net->devices); |
815 | rdev->prev = prev; | ||
816 | if (prev && rio_is_switch(prev)) | ||
817 | prev->rswitch->nextdev[prev_port] = rdev; | ||
831 | } else | 818 | } else |
832 | return -1; | 819 | return -1; |
833 | 820 | ||
834 | if (rio_is_switch(rdev)) { | 821 | if (rio_is_switch(rdev)) { |
835 | next_switchid++; | 822 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); |
836 | sw_inport = rio_get_swpinfo_inport(port, | 823 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
837 | RIO_ANY_DESTID(port->sys_size), hopcount); | ||
838 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | ||
839 | port->host_deviceid, sw_inport, 0); | 824 | port->host_deviceid, sw_inport, 0); |
840 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; | 825 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; |
841 | 826 | ||
842 | for (destid = 0; destid < next_destid; destid++) { | 827 | for (destid = 0; destid < next_destid; destid++) { |
843 | if (destid == port->host_deviceid) | 828 | if (destid == port->host_deviceid) |
844 | continue; | 829 | continue; |
845 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 830 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
846 | destid, sw_inport, 0); | 831 | destid, sw_inport, 0); |
847 | rdev->rswitch->route_table[destid] = sw_inport; | 832 | rdev->rswitch->route_table[destid] = sw_inport; |
848 | } | 833 | } |
849 | 834 | ||
850 | num_ports = | ||
851 | rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size), | ||
852 | hopcount); | ||
853 | pr_debug( | 835 | pr_debug( |
854 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 836 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
855 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 837 | rio_name(rdev), rdev->vid, rdev->did, |
838 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); | ||
856 | sw_destid = next_destid; | 839 | sw_destid = next_destid; |
857 | for (port_num = 0; port_num < num_ports; port_num++) { | 840 | for (port_num = 0; |
841 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); | ||
842 | port_num++) { | ||
858 | /*Enable Input Output Port (transmitter reviever)*/ | 843 | /*Enable Input Output Port (transmitter reviever)*/ |
859 | rio_enable_rx_tx_port(port, 0, | 844 | rio_enable_rx_tx_port(port, 0, |
860 | RIO_ANY_DESTID(port->sys_size), | 845 | RIO_ANY_DESTID(port->sys_size), |
@@ -874,12 +859,12 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
874 | "RIO: scanning device on port %d\n", | 859 | "RIO: scanning device on port %d\n", |
875 | port_num); | 860 | port_num); |
876 | rdev->rswitch->port_ok |= (1 << port_num); | 861 | rdev->rswitch->port_ok |= (1 << port_num); |
877 | rio_route_add_entry(port, rdev->rswitch, | 862 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
878 | RIO_GLOBAL_TABLE, | ||
879 | RIO_ANY_DESTID(port->sys_size), | 863 | RIO_ANY_DESTID(port->sys_size), |
880 | port_num, 0); | 864 | port_num, 0); |
881 | 865 | ||
882 | if (rio_enum_peer(net, port, hopcount + 1) < 0) | 866 | if (rio_enum_peer(net, port, hopcount + 1, |
867 | rdev, port_num) < 0) | ||
883 | return -1; | 868 | return -1; |
884 | 869 | ||
885 | /* Update routing tables */ | 870 | /* Update routing tables */ |
@@ -888,7 +873,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
888 | destid < next_destid; destid++) { | 873 | destid < next_destid; destid++) { |
889 | if (destid == port->host_deviceid) | 874 | if (destid == port->host_deviceid) |
890 | continue; | 875 | continue; |
891 | rio_route_add_entry(port, rdev->rswitch, | 876 | rio_route_add_entry(rdev, |
892 | RIO_GLOBAL_TABLE, | 877 | RIO_GLOBAL_TABLE, |
893 | destid, | 878 | destid, |
894 | port_num, | 879 | port_num, |
@@ -927,7 +912,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
927 | next_destid++; | 912 | next_destid++; |
928 | } | 913 | } |
929 | 914 | ||
930 | rdev->rswitch->destid = sw_destid; | 915 | rdev->destid = sw_destid; |
931 | } else | 916 | } else |
932 | pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", | 917 | pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", |
933 | rio_name(rdev), rdev->vid, rdev->did); | 918 | rio_name(rdev), rdev->vid, rdev->did); |
@@ -945,10 +930,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
945 | */ | 930 | */ |
946 | static int rio_enum_complete(struct rio_mport *port) | 931 | static int rio_enum_complete(struct rio_mport *port) |
947 | { | 932 | { |
948 | u32 tag_csr; | 933 | u32 regval; |
949 | 934 | ||
950 | rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); | 935 | rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR, |
951 | return (tag_csr & 0xffff) ? 1 : 0; | 936 | ®val); |
937 | return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0; | ||
952 | } | 938 | } |
953 | 939 | ||
954 | /** | 940 | /** |
@@ -957,16 +943,17 @@ static int rio_enum_complete(struct rio_mport *port) | |||
957 | * @port: Master port to send transactions | 943 | * @port: Master port to send transactions |
958 | * @destid: Current destination ID in network | 944 | * @destid: Current destination ID in network |
959 | * @hopcount: Number of hops into the network | 945 | * @hopcount: Number of hops into the network |
946 | * @prev: previous rio_dev | ||
947 | * @prev_port: previous port number | ||
960 | * | 948 | * |
961 | * Recursively discovers a RIO network. Transactions are sent via the | 949 | * Recursively discovers a RIO network. Transactions are sent via the |
962 | * master port passed in @port. | 950 | * master port passed in @port. |
963 | */ | 951 | */ |
964 | static int __devinit | 952 | static int __devinit |
965 | rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | 953 | rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, |
966 | u8 hopcount) | 954 | u8 hopcount, struct rio_dev *prev, int prev_port) |
967 | { | 955 | { |
968 | u8 port_num, route_port; | 956 | u8 port_num, route_port; |
969 | int num_ports; | ||
970 | struct rio_dev *rdev; | 957 | struct rio_dev *rdev; |
971 | u16 ndestid; | 958 | u16 ndestid; |
972 | 959 | ||
@@ -974,22 +961,24 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
974 | if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { | 961 | if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { |
975 | /* Add device to the global and bus/net specific list. */ | 962 | /* Add device to the global and bus/net specific list. */ |
976 | list_add_tail(&rdev->net_list, &net->devices); | 963 | list_add_tail(&rdev->net_list, &net->devices); |
964 | rdev->prev = prev; | ||
965 | if (prev && rio_is_switch(prev)) | ||
966 | prev->rswitch->nextdev[prev_port] = rdev; | ||
977 | } else | 967 | } else |
978 | return -1; | 968 | return -1; |
979 | 969 | ||
980 | if (rio_is_switch(rdev)) { | 970 | if (rio_is_switch(rdev)) { |
981 | next_switchid++; | ||
982 | |||
983 | /* Associated destid is how we accessed this switch */ | 971 | /* Associated destid is how we accessed this switch */ |
984 | rdev->rswitch->destid = destid; | 972 | rdev->destid = destid; |
985 | 973 | ||
986 | num_ports = rio_get_swpinfo_tports(port, destid, hopcount); | ||
987 | pr_debug( | 974 | pr_debug( |
988 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 975 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
989 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 976 | rio_name(rdev), rdev->vid, rdev->did, |
990 | for (port_num = 0; port_num < num_ports; port_num++) { | 977 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); |
991 | if (rio_get_swpinfo_inport(port, destid, hopcount) == | 978 | for (port_num = 0; |
992 | port_num) | 979 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); |
980 | port_num++) { | ||
981 | if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num) | ||
993 | continue; | 982 | continue; |
994 | 983 | ||
995 | if (rio_sport_is_active | 984 | if (rio_sport_is_active |
@@ -1003,7 +992,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
1003 | for (ndestid = 0; | 992 | for (ndestid = 0; |
1004 | ndestid < RIO_ANY_DESTID(port->sys_size); | 993 | ndestid < RIO_ANY_DESTID(port->sys_size); |
1005 | ndestid++) { | 994 | ndestid++) { |
1006 | rio_route_get_entry(port, rdev->rswitch, | 995 | rio_route_get_entry(rdev, |
1007 | RIO_GLOBAL_TABLE, | 996 | RIO_GLOBAL_TABLE, |
1008 | ndestid, | 997 | ndestid, |
1009 | &route_port, 0); | 998 | &route_port, 0); |
@@ -1011,9 +1000,11 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
1011 | break; | 1000 | break; |
1012 | } | 1001 | } |
1013 | 1002 | ||
1003 | if (ndestid == RIO_ANY_DESTID(port->sys_size)) | ||
1004 | continue; | ||
1014 | rio_unlock_device(port, destid, hopcount); | 1005 | rio_unlock_device(port, destid, hopcount); |
1015 | if (rio_disc_peer | 1006 | if (rio_disc_peer(net, port, ndestid, |
1016 | (net, port, ndestid, hopcount + 1) < 0) | 1007 | hopcount + 1, rdev, port_num) < 0) |
1017 | return -1; | 1008 | return -1; |
1018 | } | 1009 | } |
1019 | } | 1010 | } |
@@ -1089,14 +1080,14 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) | |||
1089 | */ | 1080 | */ |
1090 | static void rio_update_route_tables(struct rio_mport *port) | 1081 | static void rio_update_route_tables(struct rio_mport *port) |
1091 | { | 1082 | { |
1092 | struct rio_dev *rdev; | 1083 | struct rio_dev *rdev, *swrdev; |
1093 | struct rio_switch *rswitch; | 1084 | struct rio_switch *rswitch; |
1094 | u8 sport; | 1085 | u8 sport; |
1095 | u16 destid; | 1086 | u16 destid; |
1096 | 1087 | ||
1097 | list_for_each_entry(rdev, &rio_devices, global_list) { | 1088 | list_for_each_entry(rdev, &rio_devices, global_list) { |
1098 | 1089 | ||
1099 | destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid; | 1090 | destid = rdev->destid; |
1100 | 1091 | ||
1101 | list_for_each_entry(rswitch, &rio_switches, node) { | 1092 | list_for_each_entry(rswitch, &rio_switches, node) { |
1102 | 1093 | ||
@@ -1104,15 +1095,16 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
1104 | continue; | 1095 | continue; |
1105 | 1096 | ||
1106 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { | 1097 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { |
1098 | swrdev = sw_to_rio_dev(rswitch); | ||
1099 | |||
1107 | /* Skip if destid ends in empty switch*/ | 1100 | /* Skip if destid ends in empty switch*/ |
1108 | if (rswitch->destid == destid) | 1101 | if (swrdev->destid == destid) |
1109 | continue; | 1102 | continue; |
1110 | 1103 | ||
1111 | sport = rio_get_swpinfo_inport(port, | 1104 | sport = RIO_GET_PORT_NUM(swrdev->swpinfo); |
1112 | rswitch->destid, rswitch->hopcount); | ||
1113 | 1105 | ||
1114 | if (rswitch->add_entry) { | 1106 | if (rswitch->add_entry) { |
1115 | rio_route_add_entry(port, rswitch, | 1107 | rio_route_add_entry(swrdev, |
1116 | RIO_GLOBAL_TABLE, destid, | 1108 | RIO_GLOBAL_TABLE, destid, |
1117 | sport, 0); | 1109 | sport, 0); |
1118 | rswitch->route_table[destid] = sport; | 1110 | rswitch->route_table[destid] = sport; |
@@ -1184,7 +1176,11 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1184 | /* Enable Input Output Port (transmitter reviever) */ | 1176 | /* Enable Input Output Port (transmitter reviever) */ |
1185 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | 1177 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); |
1186 | 1178 | ||
1187 | if (rio_enum_peer(net, mport, 0) < 0) { | 1179 | /* Set component tag for host */ |
1180 | rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, | ||
1181 | next_comptag++); | ||
1182 | |||
1183 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { | ||
1188 | /* A higher priority host won enumeration, bail. */ | 1184 | /* A higher priority host won enumeration, bail. */ |
1189 | printk(KERN_INFO | 1185 | printk(KERN_INFO |
1190 | "RIO: master port %d device has lost enumeration to a remote host\n", | 1186 | "RIO: master port %d device has lost enumeration to a remote host\n", |
@@ -1220,21 +1216,20 @@ static void rio_build_route_tables(void) | |||
1220 | 1216 | ||
1221 | list_for_each_entry(rdev, &rio_devices, global_list) | 1217 | list_for_each_entry(rdev, &rio_devices, global_list) |
1222 | if (rio_is_switch(rdev)) { | 1218 | if (rio_is_switch(rdev)) { |
1223 | rio_lock_device(rdev->net->hport, rdev->rswitch->destid, | 1219 | rio_lock_device(rdev->net->hport, rdev->destid, |
1224 | rdev->rswitch->hopcount, 1000); | 1220 | rdev->hopcount, 1000); |
1225 | for (i = 0; | 1221 | for (i = 0; |
1226 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); | 1222 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); |
1227 | i++) { | 1223 | i++) { |
1228 | if (rio_route_get_entry | 1224 | if (rio_route_get_entry(rdev, |
1229 | (rdev->net->hport, rdev->rswitch, | 1225 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) |
1230 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) | ||
1231 | continue; | 1226 | continue; |
1232 | rdev->rswitch->route_table[i] = sport; | 1227 | rdev->rswitch->route_table[i] = sport; |
1233 | } | 1228 | } |
1234 | 1229 | ||
1235 | rio_unlock_device(rdev->net->hport, | 1230 | rio_unlock_device(rdev->net->hport, |
1236 | rdev->rswitch->destid, | 1231 | rdev->destid, |
1237 | rdev->rswitch->hopcount); | 1232 | rdev->hopcount); |
1238 | } | 1233 | } |
1239 | } | 1234 | } |
1240 | 1235 | ||
@@ -1301,7 +1296,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport) | |||
1301 | mport->host_deviceid); | 1296 | mport->host_deviceid); |
1302 | 1297 | ||
1303 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), | 1298 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), |
1304 | 0) < 0) { | 1299 | 0, NULL, 0) < 0) { |
1305 | printk(KERN_INFO | 1300 | printk(KERN_INFO |
1306 | "RIO: master port %d device has failed discovery\n", | 1301 | "RIO: master port %d device has failed discovery\n", |
1307 | mport->id); | 1302 | mport->id); |