aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_port.c
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/libsas/sas_port.c
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/libsas/sas_port.c')
-rw-r--r--drivers/scsi/libsas/sas_port.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 2980bde4e34a..31adcd1b4191 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -108,9 +108,6 @@ static void sas_form_port(struct asd_sas_phy *phy)
108 port->num_phys++; 108 port->num_phys++;
109 port->phy_mask |= (1U << phy->id); 109 port->phy_mask |= (1U << phy->id);
110 110
111 if (!port->phy)
112 port->phy = phy->phy;
113
114 if (*(u64 *)port->attached_sas_addr == 0) { 111 if (*(u64 *)port->attached_sas_addr == 0) {
115 port->class = phy->class; 112 port->class = phy->class;
116 memcpy(port->attached_sas_addr, phy->attached_sas_addr, 113 memcpy(port->attached_sas_addr, phy->attached_sas_addr,
@@ -175,8 +172,10 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone)
175 sas_unregister_domain_devices(port); 172 sas_unregister_domain_devices(port);
176 sas_port_delete(port->port); 173 sas_port_delete(port->port);
177 port->port = NULL; 174 port->port = NULL;
178 } else 175 } else {
179 sas_port_delete_phy(port->port, phy->phy); 176 sas_port_delete_phy(port->port, phy->phy);
177 sas_device_set_phy(dev, port->port);
178 }
180 179
181 if (si->dft->lldd_port_deformed) 180 if (si->dft->lldd_port_deformed)
182 si->dft->lldd_port_deformed(phy); 181 si->dft->lldd_port_deformed(phy);