aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-03-20 16:24:29 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-04-23 07:10:34 -0400
commit0f3fce5cc77e1f35758ef0e46a989e76e5046a7b (patch)
treea167f2e1403dd7e2e61d4423cc2ac0a6e1bc35a2 /drivers/scsi/libsas
parent9487669fc225092cf315e1291ece28e23e6754f3 (diff)
[SCSI] libsas: fix ata_eh clobbering ex_phys via smp_ata_check_ready
The check_ready implementation in the expander-attached ata device case polls on sas_ex_phy_discover(). The effect is that the ex_phy fields (critically ->attached_sas_addr) can change. When ata_eh ends and libsas comes along to revalidate the domain sas_unregister_devs_sas_addr() can fail to lookup devices to remove, or fail to re-add an ata device that ata_eh marked as disabled. So change the code to skip the sas_address and change count updates when ata_eh is active. Cc: Jack Wang <jack_wang@usish.com> Tested-by: Maciej Patelczyk <maciej.patelczyk@intel.com> Tested-by: Bartek Nowakowski <bartek.nowakowski@intel.com> Tested-by: Jacek Danecki <jacek.danecki@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/sas_expander.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 37c3c3f5f35d..c1f91b1c27c3 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;
@@ -266,6 +271,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
266 return; 271 return;
267 } 272 }
268 273
274 out:
269 switch (phy->attached_dev_type) { 275 switch (phy->attached_dev_type) {
270 case SATA_PENDING: 276 case SATA_PENDING:
271 type = "stp pending"; 277 type = "stp pending";
@@ -304,7 +310,15 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
304 else 310 else
305 return; 311 return;
306 312
307 SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n", 313 /* if the attached device type changed and ata_eh is active,
314 * make sure we run revalidation when eh completes (see:
315 * sas_enable_revalidation)
316 */
317 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
318 set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
319
320 SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
321 test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
308 SAS_ADDR(dev->sas_addr), phy->phy_id, 322 SAS_ADDR(dev->sas_addr), phy->phy_id,
309 sas_route_char(dev, phy), phy->linkrate, 323 sas_route_char(dev, phy), phy->linkrate,
310 SAS_ADDR(phy->attached_sas_addr), type); 324 SAS_ADDR(phy->attached_sas_addr), type);