aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-12-22 00:33:17 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 14:01:06 -0500
commitf41a0c441c3fe43e79ebeb75584dbb5bfa83e5cd (patch)
tree5a53adb90ebf31888184a9bff16ccc1869e2e4b3 /drivers/scsi/pm8001
parent3a9c5560f677690f65038f399f4f598c79b83186 (diff)
[SCSI] libsas: fix sas_find_local_phy(), take phy references
In the direct-attached case this routine returns the phy on which this device was first discovered. Which is broken if we want to support wide-targets, as this phy reference can become stale even though the port is still active. In the expander-attached case this routine tries to lookup the phy by scanning the attached sas addresses of the parent expander, and BUG_ONs if it can't find it. However since eh and the libsas workqueue run independently we can still be attempting device recovery via eh after libsas has recorded the device as detached. This is even easier to hit now that eh is blocked while device domain rediscovery takes place, and that libata is fed more timed out commands increasing the chances that it will try to recover the ata device. Arrange for dev->phy to always point to a last known good phy, it may be stale after the port is torn down, but it will catch up for wide port reconfigurations, and never be NULL. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 310860e37d98..3b11edd4a50c 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -967,12 +967,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
967 967
968 pm8001_dev = dev->lldd_dev; 968 pm8001_dev = dev->lldd_dev;
969 pm8001_ha = pm8001_find_ha_by_dev(dev); 969 pm8001_ha = pm8001_find_ha_by_dev(dev);
970 phy = sas_find_local_phy(dev); 970 phy = sas_get_local_phy(dev);
971 971
972 if (dev_is_sata(dev)) { 972 if (dev_is_sata(dev)) {
973 DECLARE_COMPLETION_ONSTACK(completion_setstate); 973 DECLARE_COMPLETION_ONSTACK(completion_setstate);
974 if (scsi_is_sas_phy_local(phy)) 974 if (scsi_is_sas_phy_local(phy)) {
975 return 0; 975 rc = 0;
976 goto out;
977 }
976 rc = sas_phy_reset(phy, 1); 978 rc = sas_phy_reset(phy, 1);
977 msleep(2000); 979 msleep(2000);
978 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , 980 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
@@ -981,12 +983,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
981 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, 983 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
982 pm8001_dev, 0x01); 984 pm8001_dev, 0x01);
983 wait_for_completion(&completion_setstate); 985 wait_for_completion(&completion_setstate);
984 } else{ 986 } else {
985 rc = sas_phy_reset(phy, 1); 987 rc = sas_phy_reset(phy, 1);
986 msleep(2000); 988 msleep(2000);
987 } 989 }
988 PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", 990 PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
989 pm8001_dev->device_id, rc)); 991 pm8001_dev->device_id, rc));
992 out:
993 sas_put_local_phy(phy);
990 return rc; 994 return rc;
991} 995}
992 996
@@ -998,10 +1002,11 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
998 struct pm8001_device *pm8001_dev = dev->lldd_dev; 1002 struct pm8001_device *pm8001_dev = dev->lldd_dev;
999 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); 1003 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
1000 if (dev_is_sata(dev)) { 1004 if (dev_is_sata(dev)) {
1001 struct sas_phy *phy = sas_find_local_phy(dev); 1005 struct sas_phy *phy = sas_get_local_phy(dev);
1002 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , 1006 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
1003 dev, 1, 0); 1007 dev, 1, 0);
1004 rc = sas_phy_reset(phy, 1); 1008 rc = sas_phy_reset(phy, 1);
1009 sas_put_local_phy(phy);
1005 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, 1010 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
1006 pm8001_dev, 0x01); 1011 pm8001_dev, 0x01);
1007 msleep(2000); 1012 msleep(2000);