Commit 8e68a458 authored by Xingui Yang's avatar Xingui Yang Committed by Martin K. Petersen

scsi: libsas: Fix disk not being scanned in after being removed

As of commit d8649fc1 ("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: d8649fc1 ("scsi: libsas: Do discovery on empty PHY to update PHY info")
Signed-off-by: default avatarXingui Yang <yangxingui@huawei.com>
Link: https://lore.kernel.org/r/20240307141413.48049-3-yangxingui@huawei.comReviewed-by: default avatarJohn Garry <john.g.garry@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a5734527
...@@ -1945,6 +1945,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, ...@@ -1945,6 +1945,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
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];
enum sas_device_type type = SAS_PHY_UNUSED; enum sas_device_type type = SAS_PHY_UNUSED;
struct smp_disc_resp *disc_resp;
u8 sas_addr[SAS_ADDR_SIZE]; u8 sas_addr[SAS_ADDR_SIZE];
char msg[80] = ""; char msg[80] = "";
int res; int res;
...@@ -1956,33 +1957,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, ...@@ -1956,33 +1957,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
SAS_ADDR(dev->sas_addr), phy_id, msg); SAS_ADDR(dev->sas_addr), phy_id, msg);
memset(sas_addr, 0, SAS_ADDR_SIZE); memset(sas_addr, 0, SAS_ADDR_SIZE);
res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type); disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
if (!disc_resp)
return -ENOMEM;
res = sas_get_phy_discover(dev, phy_id, disc_resp);
switch (res) { switch (res) {
case SMP_RESP_NO_PHY: case SMP_RESP_NO_PHY:
phy->phy_state = PHY_NOT_PRESENT; phy->phy_state = PHY_NOT_PRESENT;
sas_unregister_devs_sas_addr(dev, phy_id, last); sas_unregister_devs_sas_addr(dev, phy_id, last);
return res; goto out_free_resp;
case SMP_RESP_PHY_VACANT: case SMP_RESP_PHY_VACANT:
phy->phy_state = PHY_VACANT; phy->phy_state = PHY_VACANT;
sas_unregister_devs_sas_addr(dev, phy_id, last); sas_unregister_devs_sas_addr(dev, phy_id, last);
return res; goto out_free_resp;
case SMP_RESP_FUNC_ACC: case SMP_RESP_FUNC_ACC:
break; break;
case -ECOMM: case -ECOMM:
break; break;
default: default:
return res; goto out_free_resp;
} }
if (res == 0)
sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);
if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) { if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
phy->phy_state = PHY_EMPTY; phy->phy_state = PHY_EMPTY;
sas_unregister_devs_sas_addr(dev, phy_id, last); sas_unregister_devs_sas_addr(dev, phy_id, last);
/* /*
* Even though the PHY is empty, for convenience we discover * Even though the PHY is empty, for convenience we update
* the PHY to update the PHY info, like negotiated linkrate. * the PHY info, like negotiated linkrate.
*/ */
sas_ex_phy_discover(dev, phy_id); if (res == 0)
return res; sas_set_ex_phy(dev, phy_id, disc_resp);
goto out_free_resp;
} else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) && } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
dev_type_flutter(type, phy->attached_dev_type)) { dev_type_flutter(type, phy->attached_dev_type)) {
struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id); 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, ...@@ -1994,7 +2003,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
action = ", needs recovery"; action = ", needs recovery";
pr_debug("ex %016llx phy%02d broadcast flutter%s\n", pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
SAS_ADDR(dev->sas_addr), phy_id, action); SAS_ADDR(dev->sas_addr), phy_id, action);
return res; goto out_free_resp;
} }
/* we always have to delete the old device when we went here */ /* 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, ...@@ -2003,7 +2012,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
SAS_ADDR(phy->attached_sas_addr)); SAS_ADDR(phy->attached_sas_addr));
sas_unregister_devs_sas_addr(dev, phy_id, last); sas_unregister_devs_sas_addr(dev, phy_id, last);
return sas_discover_new(dev, phy_id); res = sas_discover_new(dev, phy_id);
out_free_resp:
kfree(disc_resp);
return res;
} }
/** /**
......
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