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.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 05acd9e35fc4..caa0525d2523 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -202,6 +202,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
202 u8 sas_addr[SAS_ADDR_SIZE]; 202 u8 sas_addr[SAS_ADDR_SIZE];
203 struct smp_resp *resp = rsp; 203 struct smp_resp *resp = rsp;
204 struct discover_resp *dr = &resp->disc; 204 struct discover_resp *dr = &resp->disc;
205 struct sas_ha_struct *ha = dev->port->ha;
205 struct expander_device *ex = &dev->ex_dev; 206 struct expander_device *ex = &dev->ex_dev;
206 struct ex_phy *phy = &ex->ex_phy[phy_id]; 207 struct ex_phy *phy = &ex->ex_phy[phy_id];
207 struct sas_rphy *rphy = dev->rphy; 208 struct sas_rphy *rphy = dev->rphy;
@@ -209,6 +210,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
209 char *type; 210 char *type;
210 211
211 if (new_phy) { 212 if (new_phy) {
213 if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)))
214 return;
212 phy->phy = sas_phy_alloc(&rphy->dev, phy_id); 215 phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
213 216
214 /* FIXME: error_handling */ 217 /* FIXME: error_handling */
@@ -233,6 +236,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
233 memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 236 memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
234 237
235 phy->attached_dev_type = to_dev_type(dr); 238 phy->attached_dev_type = to_dev_type(dr);
239 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
240 goto out;
236 phy->phy_id = phy_id; 241 phy->phy_id = phy_id;
237 phy->linkrate = dr->linkrate; 242 phy->linkrate = dr->linkrate;
238 phy->attached_sata_host = dr->attached_sata_host; 243 phy->attached_sata_host = dr->attached_sata_host;
@@ -240,7 +245,14 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
240 phy->attached_sata_ps = dr->attached_sata_ps; 245 phy->attached_sata_ps = dr->attached_sata_ps;
241 phy->attached_iproto = dr->iproto << 1; 246 phy->attached_iproto = dr->iproto << 1;
242 phy->attached_tproto = dr->tproto << 1; 247 phy->attached_tproto = dr->tproto << 1;
243 memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE); 248 /* help some expanders that fail to zero sas_address in the 'no
249 * device' case
250 */
251 if (phy->attached_dev_type == NO_DEVICE ||
252 phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
253 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
254 else
255 memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
244 phy->attached_phy_id = dr->attached_phy_id; 256 phy->attached_phy_id = dr->attached_phy_id;
245 phy->phy_change_count = dr->change_count; 257 phy->phy_change_count = dr->change_count;
246 phy->routing_attr = dr->routing_attr; 258 phy->routing_attr = dr->routing_attr;
@@ -266,6 +278,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
266 return; 278 return;
267 } 279 }
268 280
281 out:
269 switch (phy->attached_dev_type) { 282 switch (phy->attached_dev_type) {
270 case SATA_PENDING: 283 case SATA_PENDING:
271 type = "stp pending"; 284 type = "stp pending";
@@ -304,7 +317,15 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
304 else 317 else
305 return; 318 return;
306 319
307 SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n", 320 /* if the attached device type changed and ata_eh is active,
321 * make sure we run revalidation when eh completes (see:
322 * sas_enable_revalidation)
323 */
324 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
325 set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
326
327 SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
328 test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
308 SAS_ADDR(dev->sas_addr), phy->phy_id, 329 SAS_ADDR(dev->sas_addr), phy->phy_id,
309 sas_route_char(dev, phy), phy->linkrate, 330 sas_route_char(dev, phy), phy->linkrate,
310 SAS_ADDR(phy->attached_sas_addr), type); 331 SAS_ADDR(phy->attached_sas_addr), type);
@@ -776,13 +797,16 @@ static struct domain_device *sas_ex_discover_end_dev(
776 if (res) 797 if (res)
777 goto out_free; 798 goto out_free;
778 799
800 sas_init_dev(child);
801 res = sas_ata_init(child);
802 if (res)
803 goto out_free;
779 rphy = sas_end_device_alloc(phy->port); 804 rphy = sas_end_device_alloc(phy->port);
780 if (unlikely(!rphy)) 805 if (!rphy)
781 goto out_free; 806 goto out_free;
782 807
783 sas_init_dev(child);
784
785 child->rphy = rphy; 808 child->rphy = rphy;
809 get_device(&rphy->dev);
786 810
787 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 811 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
788 812
@@ -806,6 +830,7 @@ static struct domain_device *sas_ex_discover_end_dev(
806 sas_init_dev(child); 830 sas_init_dev(child);
807 831
808 child->rphy = rphy; 832 child->rphy = rphy;
833 get_device(&rphy->dev);
809 sas_fill_in_rphy(child, rphy); 834 sas_fill_in_rphy(child, rphy);
810 835
811 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 836 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
@@ -830,8 +855,6 @@ static struct domain_device *sas_ex_discover_end_dev(
830 855
831 out_list_del: 856 out_list_del:
832 sas_rphy_free(child->rphy); 857 sas_rphy_free(child->rphy);
833 child->rphy = NULL;
834
835 list_del(&child->disco_list_node); 858 list_del(&child->disco_list_node);
836 spin_lock_irq(&parent->port->dev_list_lock); 859 spin_lock_irq(&parent->port->dev_list_lock);
837 list_del(&child->dev_list_node); 860 list_del(&child->dev_list_node);
@@ -911,6 +934,7 @@ static struct domain_device *sas_ex_discover_expander(
911 } 934 }
912 port = parent->port; 935 port = parent->port;
913 child->rphy = rphy; 936 child->rphy = rphy;
937 get_device(&rphy->dev);
914 edev = rphy_to_expander_device(rphy); 938 edev = rphy_to_expander_device(rphy);
915 child->dev_type = phy->attached_dev_type; 939 child->dev_type = phy->attached_dev_type;
916 kref_get(&parent->kref); 940 kref_get(&parent->kref);
@@ -934,6 +958,7 @@ static struct domain_device *sas_ex_discover_expander(
934 958
935 res = sas_discover_expander(child); 959 res = sas_discover_expander(child);
936 if (res) { 960 if (res) {
961 sas_rphy_delete(rphy);
937 spin_lock_irq(&parent->port->dev_list_lock); 962 spin_lock_irq(&parent->port->dev_list_lock);
938 list_del(&child->dev_list_node); 963 list_del(&child->dev_list_node);
939 spin_unlock_irq(&parent->port->dev_list_lock); 964 spin_unlock_irq(&parent->port->dev_list_lock);
@@ -1718,9 +1743,17 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
1718 int phy_change_count = 0; 1743 int phy_change_count = 0;
1719 1744
1720 res = sas_get_phy_change_count(dev, i, &phy_change_count); 1745 res = sas_get_phy_change_count(dev, i, &phy_change_count);
1721 if (res) 1746 switch (res) {
1722 goto out; 1747 case SMP_RESP_PHY_VACANT:
1723 else if (phy_change_count != ex->ex_phy[i].phy_change_count) { 1748 case SMP_RESP_NO_PHY:
1749 continue;
1750 case SMP_RESP_FUNC_ACC:
1751 break;
1752 default:
1753 return res;
1754 }
1755
1756 if (phy_change_count != ex->ex_phy[i].phy_change_count) {
1724 if (update) 1757 if (update)
1725 ex->ex_phy[i].phy_change_count = 1758 ex->ex_phy[i].phy_change_count =
1726 phy_change_count; 1759 phy_change_count;
@@ -1728,8 +1761,7 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
1728 return 0; 1761 return 0;
1729 } 1762 }
1730 } 1763 }
1731out: 1764 return 0;
1732 return res;
1733} 1765}
1734 1766
1735static int sas_get_ex_change_count(struct domain_device *dev, int *ecc) 1767static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)