Skip to content

Commit 8e68a45

Browse files
Xingui Yangmartinkpetersen
authored andcommitted
scsi: libsas: Fix disk not being scanned in after being removed
As of commit d8649fc ("scsi: libsas: Do discovery on empty PHY to update PHY info"), do discovery will send a new SMP_DISCOVER and update phy->phy_change_count. We found that if the disk is reconnected and phy change_count changes at this time, the disk scanning process will not be triggered. Therefore, call sas_set_ex_phy() to update the PHY info with the results of the last query. And because the previous phy info will be used when calling sas_unregister_devs_sas_addr(), sas_unregister_devs_sas_addr() should be called before sas_set_ex_phy(). Fixes: d8649fc ("scsi: libsas: Do discovery on empty PHY to update PHY info") Signed-off-by: Xingui Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: John Garry <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent a573452 commit 8e68a45

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

drivers/scsi/libsas/sas_expander.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
19451945
struct expander_device *ex = &dev->ex_dev;
19461946
struct ex_phy *phy = &ex->ex_phy[phy_id];
19471947
enum sas_device_type type = SAS_PHY_UNUSED;
1948+
struct smp_disc_resp *disc_resp;
19481949
u8 sas_addr[SAS_ADDR_SIZE];
19491950
char msg[80] = "";
19501951
int res;
@@ -1956,33 +1957,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
19561957
SAS_ADDR(dev->sas_addr), phy_id, msg);
19571958

19581959
memset(sas_addr, 0, SAS_ADDR_SIZE);
1959-
res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
1960+
disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
1961+
if (!disc_resp)
1962+
return -ENOMEM;
1963+
1964+
res = sas_get_phy_discover(dev, phy_id, disc_resp);
19601965
switch (res) {
19611966
case SMP_RESP_NO_PHY:
19621967
phy->phy_state = PHY_NOT_PRESENT;
19631968
sas_unregister_devs_sas_addr(dev, phy_id, last);
1964-
return res;
1969+
goto out_free_resp;
19651970
case SMP_RESP_PHY_VACANT:
19661971
phy->phy_state = PHY_VACANT;
19671972
sas_unregister_devs_sas_addr(dev, phy_id, last);
1968-
return res;
1973+
goto out_free_resp;
19691974
case SMP_RESP_FUNC_ACC:
19701975
break;
19711976
case -ECOMM:
19721977
break;
19731978
default:
1974-
return res;
1979+
goto out_free_resp;
19751980
}
19761981

1982+
if (res == 0)
1983+
sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);
1984+
19771985
if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
19781986
phy->phy_state = PHY_EMPTY;
19791987
sas_unregister_devs_sas_addr(dev, phy_id, last);
19801988
/*
1981-
* Even though the PHY is empty, for convenience we discover
1982-
* the PHY to update the PHY info, like negotiated linkrate.
1989+
* Even though the PHY is empty, for convenience we update
1990+
* the PHY info, like negotiated linkrate.
19831991
*/
1984-
sas_ex_phy_discover(dev, phy_id);
1985-
return res;
1992+
if (res == 0)
1993+
sas_set_ex_phy(dev, phy_id, disc_resp);
1994+
goto out_free_resp;
19861995
} else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
19871996
dev_type_flutter(type, phy->attached_dev_type)) {
19881997
struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
@@ -1994,7 +2003,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
19942003
action = ", needs recovery";
19952004
pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
19962005
SAS_ADDR(dev->sas_addr), phy_id, action);
1997-
return res;
2006+
goto out_free_resp;
19982007
}
19992008

20002009
/* we always have to delete the old device when we went here */
@@ -2003,7 +2012,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
20032012
SAS_ADDR(phy->attached_sas_addr));
20042013
sas_unregister_devs_sas_addr(dev, phy_id, last);
20052014

2006-
return sas_discover_new(dev, phy_id);
2015+
res = sas_discover_new(dev, phy_id);
2016+
out_free_resp:
2017+
kfree(disc_resp);
2018+
return res;
20072019
}
20082020

20092021
/**

0 commit comments

Comments
 (0)