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.c59
1 files changed, 32 insertions, 27 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 51f0af241eb7..45d14cd6b356 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -378,12 +378,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
378 struct rio_dev *rdev; 378 struct rio_dev *rdev;
379 struct rio_switch *rswitch = NULL; 379 struct rio_switch *rswitch = NULL;
380 int result, rdid; 380 int result, rdid;
381 size_t size;
382 u32 swpinfo = 0;
381 383
382 rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); 384 size = sizeof(struct rio_dev);
385 if (rio_mport_read_config_32(port, destid, hopcount,
386 RIO_PEF_CAR, &result))
387 return NULL;
388
389 if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
390 rio_mport_read_config_32(port, destid, hopcount,
391 RIO_SWP_INFO_CAR, &swpinfo);
392 if (result & RIO_PEF_SWITCH) {
393 size += (RIO_GET_TOTAL_PORTS(swpinfo) *
394 sizeof(rswitch->nextdev[0])) + sizeof(*rswitch);
395 }
396 }
397
398 rdev = kzalloc(size, GFP_KERNEL);
383 if (!rdev) 399 if (!rdev)
384 return NULL; 400 return NULL;
385 401
386 rdev->net = net; 402 rdev->net = net;
403 rdev->pef = result;
404 rdev->swpinfo = swpinfo;
387 rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, 405 rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR,
388 &result); 406 &result);
389 rdev->did = result >> 16; 407 rdev->did = result >> 16;
@@ -397,8 +415,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, 415 rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR,
398 &result); 416 &result);
399 rdev->asm_rev = result >> 16; 417 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) { 418 if (rdev->pef & RIO_PEF_EXT_FEATURES) {
403 rdev->efptr = result & 0xffff; 419 rdev->efptr = result & 0xffff;
404 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, 420 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
@@ -408,11 +424,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
408 hopcount, RIO_EFB_ERR_MGMNT); 424 hopcount, RIO_EFB_ERR_MGMNT);
409 } 425 }
410 426
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, 427 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
417 &rdev->src_ops); 428 &rdev->src_ops);
418 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, 429 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
@@ -449,12 +460,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
449 460
450 /* If a PE has both switch and other functions, show it as a switch */ 461 /* If a PE has both switch and other functions, show it as a switch */
451 if (rio_is_switch(rdev)) { 462 if (rio_is_switch(rdev)) {
452 rswitch = kzalloc(sizeof(*rswitch) + 463 rswitch = rdev->rswitch;
453 RIO_GET_TOTAL_PORTS(rdev->swpinfo) *
454 sizeof(rswitch->nextdev[0]),
455 GFP_KERNEL);
456 if (!rswitch)
457 goto cleanup;
458 rswitch->switchid = next_switchid; 464 rswitch->switchid = next_switchid;
459 rswitch->port_ok = 0; 465 rswitch->port_ok = 0;
460 rswitch->route_table = kzalloc(sizeof(u8)* 466 rswitch->route_table = kzalloc(sizeof(u8)*
@@ -466,15 +472,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
466 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); 472 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
467 rdid++) 473 rdid++)
468 rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 474 rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
469 rdev->rswitch = rswitch;
470 rswitch->rdev = rdev;
471 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 475 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
472 rdev->rswitch->switchid); 476 rswitch->switchid);
473 rio_switch_init(rdev, do_enum); 477 rio_switch_init(rdev, do_enum);
474 478
475 if (do_enum && rdev->rswitch->clr_table) 479 if (do_enum && rswitch->clr_table)
476 rdev->rswitch->clr_table(port, destid, hopcount, 480 rswitch->clr_table(port, destid, hopcount,
477 RIO_GLOBAL_TABLE); 481 RIO_GLOBAL_TABLE);
478 482
479 list_add_tail(&rswitch->node, &rio_switches); 483 list_add_tail(&rswitch->node, &rio_switches);
480 484
@@ -510,10 +514,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
510 return rdev; 514 return rdev;
511 515
512cleanup: 516cleanup:
513 if (rswitch) { 517 if (rswitch->route_table)
514 kfree(rswitch->route_table); 518 kfree(rswitch->route_table);
515 kfree(rswitch); 519
516 }
517 kfree(rdev); 520 kfree(rdev);
518 return NULL; 521 return NULL;
519} 522}
@@ -1072,7 +1075,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1072 */ 1075 */
1073static void rio_update_route_tables(struct rio_mport *port) 1076static void rio_update_route_tables(struct rio_mport *port)
1074{ 1077{
1075 struct rio_dev *rdev; 1078 struct rio_dev *rdev, *swrdev;
1076 struct rio_switch *rswitch; 1079 struct rio_switch *rswitch;
1077 u8 sport; 1080 u8 sport;
1078 u16 destid; 1081 u16 destid;
@@ -1087,14 +1090,16 @@ static void rio_update_route_tables(struct rio_mport *port)
1087 continue; 1090 continue;
1088 1091
1089 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 1092 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
1093 swrdev = sw_to_rio_dev(rswitch);
1094
1090 /* Skip if destid ends in empty switch*/ 1095 /* Skip if destid ends in empty switch*/
1091 if (rswitch->rdev->destid == destid) 1096 if (swrdev->destid == destid)
1092 continue; 1097 continue;
1093 1098
1094 sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); 1099 sport = RIO_GET_PORT_NUM(swrdev->swpinfo);
1095 1100
1096 if (rswitch->add_entry) { 1101 if (rswitch->add_entry) {
1097 rio_route_add_entry(rswitch->rdev, 1102 rio_route_add_entry(swrdev,
1098 RIO_GLOBAL_TABLE, destid, 1103 RIO_GLOBAL_TABLE, destid,
1099 sport, 0); 1104 sport, 0);
1100 rswitch->route_table[destid] = sport; 1105 rswitch->route_table[destid] = sport;