diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 49 |
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 | ||
1732 | static void sas_unregister_ex_tree(struct domain_device *dev) | 1745 | static 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 | ||
1748 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, | 1761 | static 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 | ||
1778 | static int sas_discover_bfs_by_root_level(struct domain_device *root, | 1793 | static int sas_discover_bfs_by_root_level(struct domain_device *root, |