aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio/rio-scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rapidio/rio-scan.c')
-rw-r--r--drivers/rapidio/rio-scan.c160
1 files changed, 85 insertions, 75 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 1eb82c4c712..467e82bd092 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -46,7 +46,6 @@ static void rio_init_em(struct rio_dev *rdev);
46DEFINE_SPINLOCK(rio_global_list_lock); 46DEFINE_SPINLOCK(rio_global_list_lock);
47 47
48static int next_destid = 0; 48static int next_destid = 0;
49static int next_switchid = 0;
50static int next_net = 0; 49static int next_net = 0;
51static int next_comptag = 1; 50static int next_comptag = 1;
52 51
@@ -378,12 +377,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
378 struct rio_dev *rdev; 377 struct rio_dev *rdev;
379 struct rio_switch *rswitch = NULL; 378 struct rio_switch *rswitch = NULL;
380 int result, rdid; 379 int result, rdid;
380 size_t size;
381 u32 swpinfo = 0;
381 382
382 rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); 383 size = sizeof(struct rio_dev);
384 if (rio_mport_read_config_32(port, destid, hopcount,
385 RIO_PEF_CAR, &result))
386 return NULL;
387
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);
383 if (!rdev) 398 if (!rdev)
384 return NULL; 399 return NULL;
385 400
386 rdev->net = net; 401 rdev->net = net;
402 rdev->pef = result;
403 rdev->swpinfo = swpinfo;
387 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,
388 &result); 405 &result);
389 rdev->did = result >> 16; 406 rdev->did = result >> 16;
@@ -397,8 +414,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
397 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,
398 &result); 415 &result);
399 rdev->asm_rev = result >> 16; 416 rdev->asm_rev = result >> 16;
400 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
401 &rdev->pef);
402 if (rdev->pef & RIO_PEF_EXT_FEATURES) { 417 if (rdev->pef & RIO_PEF_EXT_FEATURES) {
403 rdev->efptr = result & 0xffff; 418 rdev->efptr = result & 0xffff;
404 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, 419 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
@@ -408,11 +423,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
408 hopcount, RIO_EFB_ERR_MGMNT); 423 hopcount, RIO_EFB_ERR_MGMNT);
409 } 424 }
410 425
411 if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
412 rio_mport_read_config_32(port, destid, hopcount,
413 RIO_SWP_INFO_CAR, &rdev->swpinfo);
414 }
415
416 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 426 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
417 &rdev->src_ops); 427 &rdev->src_ops);
418 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,
@@ -427,6 +437,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
427 rio_mport_write_config_32(port, destid, hopcount, 437 rio_mport_write_config_32(port, destid, hopcount,
428 RIO_COMPONENT_TAG_CSR, next_comptag); 438 RIO_COMPONENT_TAG_CSR, next_comptag);
429 rdev->comp_tag = 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);
430 } 444 }
431 445
432 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)) {
@@ -437,21 +451,20 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
437 next_destid++; 451 next_destid++;
438 } else 452 } else
439 rdev->destid = rio_get_device_id(port, destid, hopcount); 453 rdev->destid = rio_get_device_id(port, destid, hopcount);
440 } else 454
441 /* Switch device has an associated destID */ 455 rdev->hopcount = 0xff;
442 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 }
443 463
444 /* 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 */
445 if (rio_is_switch(rdev)) { 465 if (rio_is_switch(rdev)) {
446 rswitch = kzalloc(sizeof(*rswitch) + 466 rswitch = rdev->rswitch;
447 RIO_GET_TOTAL_PORTS(rdev->swpinfo) * 467 rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID;
448 sizeof(rswitch->nextdev[0]),
449 GFP_KERNEL);
450 if (!rswitch)
451 goto cleanup;
452 rswitch->switchid = next_switchid;
453 rswitch->hopcount = hopcount;
454 rswitch->destid = destid;
455 rswitch->port_ok = 0; 468 rswitch->port_ok = 0;
456 rswitch->route_table = kzalloc(sizeof(u8)* 469 rswitch->route_table = kzalloc(sizeof(u8)*
457 RIO_MAX_ROUTE_ENTRIES(port->sys_size), 470 RIO_MAX_ROUTE_ENTRIES(port->sys_size),
@@ -462,15 +475,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
462 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); 475 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
463 rdid++) 476 rdid++)
464 rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 477 rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
465 rdev->rswitch = rswitch;
466 rswitch->rdev = rdev;
467 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 478 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
468 rdev->rswitch->switchid); 479 rswitch->switchid);
469 rio_switch_init(rdev, do_enum); 480 rio_switch_init(rdev, do_enum);
470 481
471 if (do_enum && rdev->rswitch->clr_table) 482 if (do_enum && rswitch->clr_table)
472 rdev->rswitch->clr_table(port, destid, hopcount, 483 rswitch->clr_table(port, destid, hopcount,
473 RIO_GLOBAL_TABLE); 484 RIO_GLOBAL_TABLE);
474 485
475 list_add_tail(&rswitch->node, &rio_switches); 486 list_add_tail(&rswitch->node, &rio_switches);
476 487
@@ -506,10 +517,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
506 return rdev; 517 return rdev;
507 518
508cleanup: 519cleanup:
509 if (rswitch) { 520 if (rswitch->route_table)
510 kfree(rswitch->route_table); 521 kfree(rswitch->route_table);
511 kfree(rswitch); 522
512 }
513 kfree(rdev); 523 kfree(rdev);
514 return NULL; 524 return NULL;
515} 525}
@@ -632,8 +642,7 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
632 642
633/** 643/**
634 * 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
635 * @mport: Master port to send transaction 645 * @rdev: RIO device
636 * @rswitch: Switch device
637 * @table: Routing table ID 646 * @table: Routing table ID
638 * @route_destid: Destination ID to be routed 647 * @route_destid: Destination ID to be routed
639 * @route_port: Port number to be routed 648 * @route_port: Port number to be routed
@@ -647,31 +656,31 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
647 * on failure. 656 * on failure.
648 */ 657 */
649static int 658static int
650rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, 659rio_route_add_entry(struct rio_dev *rdev,
651 u16 table, u16 route_destid, u8 route_port, int lock) 660 u16 table, u16 route_destid, u8 route_port, int lock)
652{ 661{
653 int rc; 662 int rc;
654 663
655 if (lock) { 664 if (lock) {
656 rc = rio_lock_device(mport, rswitch->destid, 665 rc = rio_lock_device(rdev->net->hport, rdev->destid,
657 rswitch->hopcount, 1000); 666 rdev->hopcount, 1000);
658 if (rc) 667 if (rc)
659 return rc; 668 return rc;
660 } 669 }
661 670
662 rc = rswitch->add_entry(mport, rswitch->destid, 671 rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid,
663 rswitch->hopcount, table, 672 rdev->hopcount, table,
664 route_destid, route_port); 673 route_destid, route_port);
665 if (lock) 674 if (lock)
666 rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); 675 rio_unlock_device(rdev->net->hport, rdev->destid,
676 rdev->hopcount);
667 677
668 return rc; 678 return rc;
669} 679}
670 680
671/** 681/**
672 * 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
673 * @mport: Master port to send transaction 683 * @rdev: RIO device
674 * @rswitch: Switch device
675 * @table: Routing table ID 684 * @table: Routing table ID
676 * @route_destid: Destination ID to be routed 685 * @route_destid: Destination ID to be routed
677 * @route_port: Pointer to read port number into 686 * @route_port: Pointer to read port number into
@@ -685,23 +694,24 @@ rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch,
685 * on failure. 694 * on failure.
686 */ 695 */
687static int 696static int
688rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, 697rio_route_get_entry(struct rio_dev *rdev, u16 table,
689 u16 route_destid, u8 *route_port, int lock) 698 u16 route_destid, u8 *route_port, int lock)
690{ 699{
691 int rc; 700 int rc;
692 701
693 if (lock) { 702 if (lock) {
694 rc = rio_lock_device(mport, rswitch->destid, 703 rc = rio_lock_device(rdev->net->hport, rdev->destid,
695 rswitch->hopcount, 1000); 704 rdev->hopcount, 1000);
696 if (rc) 705 if (rc)
697 return rc; 706 return rc;
698 } 707 }
699 708
700 rc = rswitch->get_entry(mport, rswitch->destid, 709 rc = rdev->rswitch->get_entry(rdev->net->hport, rdev->destid,
701 rswitch->hopcount, table, 710 rdev->hopcount, table,
702 route_destid, route_port); 711 route_destid, route_port);
703 if (lock) 712 if (lock)
704 rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); 713 rio_unlock_device(rdev->net->hport, rdev->destid,
714 rdev->hopcount);
705 715
706 return rc; 716 return rc;
707} 717}
@@ -809,16 +819,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
809 return -1; 819 return -1;
810 820
811 if (rio_is_switch(rdev)) { 821 if (rio_is_switch(rdev)) {
812 next_switchid++;
813 sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); 822 sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
814 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 823 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
815 port->host_deviceid, sw_inport, 0); 824 port->host_deviceid, sw_inport, 0);
816 rdev->rswitch->route_table[port->host_deviceid] = sw_inport; 825 rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
817 826
818 for (destid = 0; destid < next_destid; destid++) { 827 for (destid = 0; destid < next_destid; destid++) {
819 if (destid == port->host_deviceid) 828 if (destid == port->host_deviceid)
820 continue; 829 continue;
821 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 830 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
822 destid, sw_inport, 0); 831 destid, sw_inport, 0);
823 rdev->rswitch->route_table[destid] = sw_inport; 832 rdev->rswitch->route_table[destid] = sw_inport;
824 } 833 }
@@ -850,8 +859,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
850 "RIO: scanning device on port %d\n", 859 "RIO: scanning device on port %d\n",
851 port_num); 860 port_num);
852 rdev->rswitch->port_ok |= (1 << port_num); 861 rdev->rswitch->port_ok |= (1 << port_num);
853 rio_route_add_entry(port, rdev->rswitch, 862 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
854 RIO_GLOBAL_TABLE,
855 RIO_ANY_DESTID(port->sys_size), 863 RIO_ANY_DESTID(port->sys_size),
856 port_num, 0); 864 port_num, 0);
857 865
@@ -865,7 +873,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
865 destid < next_destid; destid++) { 873 destid < next_destid; destid++) {
866 if (destid == port->host_deviceid) 874 if (destid == port->host_deviceid)
867 continue; 875 continue;
868 rio_route_add_entry(port, rdev->rswitch, 876 rio_route_add_entry(rdev,
869 RIO_GLOBAL_TABLE, 877 RIO_GLOBAL_TABLE,
870 destid, 878 destid,
871 port_num, 879 port_num,
@@ -904,7 +912,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
904 next_destid++; 912 next_destid++;
905 } 913 }
906 914
907 rdev->rswitch->destid = sw_destid; 915 rdev->destid = sw_destid;
908 } else 916 } else
909 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",
910 rio_name(rdev), rdev->vid, rdev->did); 918 rio_name(rdev), rdev->vid, rdev->did);
@@ -941,7 +949,7 @@ static int rio_enum_complete(struct rio_mport *port)
941 */ 949 */
942static int __devinit 950static int __devinit
943rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, 951rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
944 u8 hopcount) 952 u8 hopcount, struct rio_dev *prev, int prev_port)
945{ 953{
946 u8 port_num, route_port; 954 u8 port_num, route_port;
947 struct rio_dev *rdev; 955 struct rio_dev *rdev;
@@ -951,14 +959,15 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
951 if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { 959 if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) {
952 /* Add device to the global and bus/net specific list. */ 960 /* Add device to the global and bus/net specific list. */
953 list_add_tail(&rdev->net_list, &net->devices); 961 list_add_tail(&rdev->net_list, &net->devices);
962 rdev->prev = prev;
963 if (prev && rio_is_switch(prev))
964 prev->rswitch->nextdev[prev_port] = rdev;
954 } else 965 } else
955 return -1; 966 return -1;
956 967
957 if (rio_is_switch(rdev)) { 968 if (rio_is_switch(rdev)) {
958 next_switchid++;
959
960 /* Associated destid is how we accessed this switch */ 969 /* Associated destid is how we accessed this switch */
961 rdev->rswitch->destid = destid; 970 rdev->destid = destid;
962 971
963 pr_debug( 972 pr_debug(
964 "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 973 "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
@@ -981,7 +990,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
981 for (ndestid = 0; 990 for (ndestid = 0;
982 ndestid < RIO_ANY_DESTID(port->sys_size); 991 ndestid < RIO_ANY_DESTID(port->sys_size);
983 ndestid++) { 992 ndestid++) {
984 rio_route_get_entry(port, rdev->rswitch, 993 rio_route_get_entry(rdev,
985 RIO_GLOBAL_TABLE, 994 RIO_GLOBAL_TABLE,
986 ndestid, 995 ndestid,
987 &route_port, 0); 996 &route_port, 0);
@@ -992,8 +1001,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
992 if (ndestid == RIO_ANY_DESTID(port->sys_size)) 1001 if (ndestid == RIO_ANY_DESTID(port->sys_size))
993 continue; 1002 continue;
994 rio_unlock_device(port, destid, hopcount); 1003 rio_unlock_device(port, destid, hopcount);
995 if (rio_disc_peer 1004 if (rio_disc_peer(net, port, ndestid,
996 (net, port, ndestid, hopcount + 1) < 0) 1005 hopcount + 1, rdev, port_num) < 0)
997 return -1; 1006 return -1;
998 } 1007 }
999 } 1008 }
@@ -1069,14 +1078,14 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1069 */ 1078 */
1070static void rio_update_route_tables(struct rio_mport *port) 1079static void rio_update_route_tables(struct rio_mport *port)
1071{ 1080{
1072 struct rio_dev *rdev; 1081 struct rio_dev *rdev, *swrdev;
1073 struct rio_switch *rswitch; 1082 struct rio_switch *rswitch;
1074 u8 sport; 1083 u8 sport;
1075 u16 destid; 1084 u16 destid;
1076 1085
1077 list_for_each_entry(rdev, &rio_devices, global_list) { 1086 list_for_each_entry(rdev, &rio_devices, global_list) {
1078 1087
1079 destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid; 1088 destid = rdev->destid;
1080 1089
1081 list_for_each_entry(rswitch, &rio_switches, node) { 1090 list_for_each_entry(rswitch, &rio_switches, node) {
1082 1091
@@ -1084,14 +1093,16 @@ static void rio_update_route_tables(struct rio_mport *port)
1084 continue; 1093 continue;
1085 1094
1086 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 1095 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
1096 swrdev = sw_to_rio_dev(rswitch);
1097
1087 /* Skip if destid ends in empty switch*/ 1098 /* Skip if destid ends in empty switch*/
1088 if (rswitch->destid == destid) 1099 if (swrdev->destid == destid)
1089 continue; 1100 continue;
1090 1101
1091 sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); 1102 sport = RIO_GET_PORT_NUM(swrdev->swpinfo);
1092 1103
1093 if (rswitch->add_entry) { 1104 if (rswitch->add_entry) {
1094 rio_route_add_entry(port, rswitch, 1105 rio_route_add_entry(swrdev,
1095 RIO_GLOBAL_TABLE, destid, 1106 RIO_GLOBAL_TABLE, destid,
1096 sport, 0); 1107 sport, 0);
1097 rswitch->route_table[destid] = sport; 1108 rswitch->route_table[destid] = sport;
@@ -1203,21 +1214,20 @@ static void rio_build_route_tables(void)
1203 1214
1204 list_for_each_entry(rdev, &rio_devices, global_list) 1215 list_for_each_entry(rdev, &rio_devices, global_list)
1205 if (rio_is_switch(rdev)) { 1216 if (rio_is_switch(rdev)) {
1206 rio_lock_device(rdev->net->hport, rdev->rswitch->destid, 1217 rio_lock_device(rdev->net->hport, rdev->destid,
1207 rdev->rswitch->hopcount, 1000); 1218 rdev->hopcount, 1000);
1208 for (i = 0; 1219 for (i = 0;
1209 i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); 1220 i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
1210 i++) { 1221 i++) {
1211 if (rio_route_get_entry 1222 if (rio_route_get_entry(rdev,
1212 (rdev->net->hport, rdev->rswitch, 1223 RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
1213 RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
1214 continue; 1224 continue;
1215 rdev->rswitch->route_table[i] = sport; 1225 rdev->rswitch->route_table[i] = sport;
1216 } 1226 }
1217 1227
1218 rio_unlock_device(rdev->net->hport, 1228 rio_unlock_device(rdev->net->hport,
1219 rdev->rswitch->destid, 1229 rdev->destid,
1220 rdev->rswitch->hopcount); 1230 rdev->hopcount);
1221 } 1231 }
1222} 1232}
1223 1233
@@ -1284,7 +1294,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
1284 mport->host_deviceid); 1294 mport->host_deviceid);
1285 1295
1286 if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), 1296 if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
1287 0) < 0) { 1297 0, NULL, 0) < 0) {
1288 printk(KERN_INFO 1298 printk(KERN_INFO
1289 "RIO: master port %d device has failed discovery\n", 1299 "RIO: master port %d device has failed discovery\n",
1290 mport->id); 1300 mport->id);