Commit 0f3fce5c authored by Dan Williams's avatar Dan Williams Committed by James Bottomley

[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: default avatarMaciej Patelczyk <maciej.patelczyk@intel.com>
Tested-by: default avatarBartek Nowakowski <bartek.nowakowski@intel.com>
Tested-by: default avatarJacek Danecki <jacek.danecki@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 9487669f
...@@ -202,6 +202,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) ...@@ -202,6 +202,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
u8 sas_addr[SAS_ADDR_SIZE]; u8 sas_addr[SAS_ADDR_SIZE];
struct smp_resp *resp = rsp; struct smp_resp *resp = rsp;
struct discover_resp *dr = &resp->disc; struct discover_resp *dr = &resp->disc;
struct sas_ha_struct *ha = dev->port->ha;
struct expander_device *ex = &dev->ex_dev; struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id]; struct ex_phy *phy = &ex->ex_phy[phy_id];
struct sas_rphy *rphy = dev->rphy; 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,6 +210,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
char *type; char *type;
if (new_phy) { if (new_phy) {
if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)))
return;
phy->phy = sas_phy_alloc(&rphy->dev, phy_id); phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
/* FIXME: error_handling */ /* FIXME: error_handling */
...@@ -233,6 +236,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) ...@@ -233,6 +236,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
phy->attached_dev_type = to_dev_type(dr); phy->attached_dev_type = to_dev_type(dr);
if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
goto out;
phy->phy_id = phy_id; phy->phy_id = phy_id;
phy->linkrate = dr->linkrate; phy->linkrate = dr->linkrate;
phy->attached_sata_host = dr->attached_sata_host; 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,6 +271,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
return; return;
} }
out:
switch (phy->attached_dev_type) { switch (phy->attached_dev_type) {
case SATA_PENDING: case SATA_PENDING:
type = "stp pending"; type = "stp pending";
...@@ -304,7 +310,15 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) ...@@ -304,7 +310,15 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
else else
return; return;
SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n", /* if the attached device type changed and ata_eh is active,
* make sure we run revalidation when eh completes (see:
* sas_enable_revalidation)
*/
if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
SAS_ADDR(dev->sas_addr), phy->phy_id, SAS_ADDR(dev->sas_addr), phy->phy_id,
sas_route_char(dev, phy), phy->linkrate, sas_route_char(dev, phy), phy->linkrate,
SAS_ADDR(phy->attached_sas_addr), type); SAS_ADDR(phy->attached_sas_addr), type);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment