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.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f84084bba2f0..1b831c55ec6e 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -199,6 +199,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
199 phy->virtual = dr->virtual; 199 phy->virtual = dr->virtual;
200 phy->last_da_index = -1; 200 phy->last_da_index = -1;
201 201
202 phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
203 phy->phy->identify.device_type = phy->attached_dev_type;
202 phy->phy->identify.initiator_port_protocols = phy->attached_iproto; 204 phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
203 phy->phy->identify.target_port_protocols = phy->attached_tproto; 205 phy->phy->identify.target_port_protocols = phy->attached_tproto;
204 phy->phy->identify.phy_identifier = phy_id; 206 phy->phy->identify.phy_identifier = phy_id;
@@ -329,6 +331,7 @@ static void ex_assign_report_general(struct domain_device *dev,
329 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 331 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
330 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 332 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
331 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 333 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
334 dev->ex_dev.t2t_supp = rg->t2t_supp;
332 dev->ex_dev.conf_route_table = rg->conf_route_table; 335 dev->ex_dev.conf_route_table = rg->conf_route_table;
333 dev->ex_dev.configuring = rg->configuring; 336 dev->ex_dev.configuring = rg->configuring;
334 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8); 337 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
@@ -751,7 +754,10 @@ static struct domain_device *sas_ex_discover_end_dev(
751 out_list_del: 754 out_list_del:
752 sas_rphy_free(child->rphy); 755 sas_rphy_free(child->rphy);
753 child->rphy = NULL; 756 child->rphy = NULL;
757
758 spin_lock_irq(&parent->port->dev_list_lock);
754 list_del(&child->dev_list_node); 759 list_del(&child->dev_list_node);
760 spin_unlock_irq(&parent->port->dev_list_lock);
755 out_free: 761 out_free:
756 sas_port_delete(phy->port); 762 sas_port_delete(phy->port);
757 out_err: 763 out_err:
@@ -1133,15 +1139,17 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
1133 }; 1139 };
1134 struct domain_device *parent = child->parent; 1140 struct domain_device *parent = child->parent;
1135 1141
1136 sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x " 1142 sas_printk("%s ex %016llx (T2T supp:%d) phy 0x%x <--> %s ex %016llx "
1137 "has %c:%c routing link!\n", 1143 "(T2T supp:%d) phy 0x%x has %c:%c routing link!\n",
1138 1144
1139 ex_type[parent->dev_type], 1145 ex_type[parent->dev_type],
1140 SAS_ADDR(parent->sas_addr), 1146 SAS_ADDR(parent->sas_addr),
1147 parent->ex_dev.t2t_supp,
1141 parent_phy->phy_id, 1148 parent_phy->phy_id,
1142 1149
1143 ex_type[child->dev_type], 1150 ex_type[child->dev_type],
1144 SAS_ADDR(child->sas_addr), 1151 SAS_ADDR(child->sas_addr),
1152 child->ex_dev.t2t_supp,
1145 child_phy->phy_id, 1153 child_phy->phy_id,
1146 1154
1147 ra_char[parent_phy->routing_attr], 1155 ra_char[parent_phy->routing_attr],
@@ -1238,10 +1246,15 @@ static int sas_check_parent_topology(struct domain_device *child)
1238 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1246 sas_print_parent_topology_bug(child, parent_phy, child_phy);
1239 res = -ENODEV; 1247 res = -ENODEV;
1240 } 1248 }
1241 } else if (parent_phy->routing_attr == TABLE_ROUTING && 1249 } else if (parent_phy->routing_attr == TABLE_ROUTING) {
1242 child_phy->routing_attr != SUBTRACTIVE_ROUTING) { 1250 if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
1243 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1251 (child_phy->routing_attr == TABLE_ROUTING &&
1244 res = -ENODEV; 1252 child_ex->t2t_supp && parent_ex->t2t_supp)) {
1253 /* All good */;
1254 } else {
1255 sas_print_parent_topology_bug(child, parent_phy, child_phy);
1256 res = -ENODEV;
1257 }
1245 } 1258 }
1246 break; 1259 break;
1247 case FANOUT_DEV: 1260 case FANOUT_DEV:
@@ -1721,7 +1734,7 @@ static int sas_find_bcast_dev(struct domain_device *dev,
1721 list_for_each_entry(ch, &ex->children, siblings) { 1734 list_for_each_entry(ch, &ex->children, siblings) {
1722 if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) { 1735 if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) {
1723 res = sas_find_bcast_dev(ch, src_dev); 1736 res = sas_find_bcast_dev(ch, src_dev);
1724 if (src_dev) 1737 if (*src_dev)
1725 return res; 1738 return res;
1726 } 1739 }
1727 } 1740 }
@@ -1729,7 +1742,7 @@ out:
1729 return res; 1742 return res;
1730} 1743}
1731 1744
1732static void sas_unregister_ex_tree(struct domain_device *dev) 1745static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev)
1733{ 1746{
1734 struct expander_device *ex = &dev->ex_dev; 1747 struct expander_device *ex = &dev->ex_dev;
1735 struct domain_device *child, *n; 1748 struct domain_device *child, *n;
@@ -1738,11 +1751,11 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
1738 child->gone = 1; 1751 child->gone = 1;
1739 if (child->dev_type == EDGE_DEV || 1752 if (child->dev_type == EDGE_DEV ||
1740 child->dev_type == FANOUT_DEV) 1753 child->dev_type == FANOUT_DEV)
1741 sas_unregister_ex_tree(child); 1754 sas_unregister_ex_tree(port, child);
1742 else 1755 else
1743 sas_unregister_dev(child); 1756 sas_unregister_dev(port, child);
1744 } 1757 }
1745 sas_unregister_dev(dev); 1758 sas_unregister_dev(port, dev);
1746} 1759}
1747 1760
1748static void sas_unregister_devs_sas_addr(struct domain_device *parent, 1761static void sas_unregister_devs_sas_addr(struct domain_device *parent,
@@ -1759,9 +1772,9 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1759 child->gone = 1; 1772 child->gone = 1;
1760 if (child->dev_type == EDGE_DEV || 1773 if (child->dev_type == EDGE_DEV ||
1761 child->dev_type == FANOUT_DEV) 1774 child->dev_type == FANOUT_DEV)
1762 sas_unregister_ex_tree(child); 1775 sas_unregister_ex_tree(parent->port, child);
1763 else 1776 else
1764 sas_unregister_dev(child); 1777 sas_unregister_dev(parent->port, child);
1765 break; 1778 break;
1766 } 1779 }
1767 } 1780 }
@@ -1769,10 +1782,12 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1769 sas_disable_routing(parent, phy->attached_sas_addr); 1782 sas_disable_routing(parent, phy->attached_sas_addr);
1770 } 1783 }
1771 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 1784 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
1772 sas_port_delete_phy(phy->port, phy->phy); 1785 if (phy->port) {
1773 if (phy->port->num_phys == 0) 1786 sas_port_delete_phy(phy->port, phy->phy);
1774 sas_port_delete(phy->port); 1787 if (phy->port->num_phys == 0)
1775 phy->port = NULL; 1788 sas_port_delete(phy->port);
1789 phy->port = NULL;
1790 }
1776} 1791}
1777 1792
1778static int sas_discover_bfs_by_root_level(struct domain_device *root, 1793static int sas_discover_bfs_by_root_level(struct domain_device *root,