aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_expander.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r--drivers/scsi/libsas/sas_expander.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index d31e6fa466f7..dc70c180e115 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -667,8 +667,9 @@ static struct domain_device *sas_ex_discover_end_dev(
667 return child; 667 return child;
668 668
669 out_list_del: 669 out_list_del:
670 sas_rphy_free(child->rphy);
671 child->rphy = NULL;
670 list_del(&child->dev_list_node); 672 list_del(&child->dev_list_node);
671 sas_rphy_free(rphy);
672 out_free: 673 out_free:
673 sas_port_delete(phy->port); 674 sas_port_delete(phy->port);
674 out_err: 675 out_err:
@@ -677,6 +678,29 @@ static struct domain_device *sas_ex_discover_end_dev(
677 return NULL; 678 return NULL;
678} 679}
679 680
681/* See if this phy is part of a wide port */
682static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
683{
684 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
685 int i;
686
687 for (i = 0; i < parent->ex_dev.num_phys; i++) {
688 struct ex_phy *ephy = &parent->ex_dev.ex_phy[i];
689
690 if (ephy == phy)
691 continue;
692
693 if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
694 SAS_ADDR_SIZE) && ephy->port) {
695 sas_port_add_phy(ephy->port, phy->phy);
696 phy->phy_state = PHY_DEVICE_DISCOVERED;
697 return 0;
698 }
699 }
700
701 return -ENODEV;
702}
703
680static struct domain_device *sas_ex_discover_expander( 704static struct domain_device *sas_ex_discover_expander(
681 struct domain_device *parent, int phy_id) 705 struct domain_device *parent, int phy_id)
682{ 706{
@@ -809,6 +833,13 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
809 return res; 833 return res;
810 } 834 }
811 835
836 res = sas_ex_join_wide_port(dev, phy_id);
837 if (!res) {
838 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
839 phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
840 return res;
841 }
842
812 switch (ex_phy->attached_dev_type) { 843 switch (ex_phy->attached_dev_type) {
813 case SAS_END_DEV: 844 case SAS_END_DEV:
814 child = sas_ex_discover_end_dev(dev, phy_id); 845 child = sas_ex_discover_end_dev(dev, phy_id);
@@ -1431,14 +1462,23 @@ int sas_discover_root_expander(struct domain_device *dev)
1431 int res; 1462 int res;
1432 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); 1463 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
1433 1464
1434 sas_rphy_add(dev->rphy); 1465 res = sas_rphy_add(dev->rphy);
1466 if (res)
1467 goto out_err;
1435 1468
1436 ex->level = dev->port->disc.max_level; /* 0 */ 1469 ex->level = dev->port->disc.max_level; /* 0 */
1437 res = sas_discover_expander(dev); 1470 res = sas_discover_expander(dev);
1438 if (!res) 1471 if (res)
1439 sas_ex_bfs_disc(dev->port); 1472 goto out_err2;
1473
1474 sas_ex_bfs_disc(dev->port);
1440 1475
1441 return res; 1476 return res;
1477
1478out_err2:
1479 sas_rphy_remove(dev->rphy);
1480out_err:
1481 return res;
1442} 1482}
1443 1483
1444/* ---------- Domain revalidation ---------- */ 1484/* ---------- Domain revalidation ---------- */