From: Jie Zhan zhanjie9@hisilicon.com
mainline inclusion from mainline-v6.2-rc1 commit 3c2673a09cf1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6V6I1 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
SATA devices on an expander may be removed and not be found again when I_T nexus reset and revalidation are processed simultaneously.
The issue comes from:
- Revalidation can remove SATA devices in link reset, e.g. in hisi_sas_clear_nexus_ha().
- However, hisi_sas_debug_I_T_nexus_reset() polls the state of a SATA device on an expander after sending link_reset, where it calls: hisi_sas_debug_I_T_nexus_reset sas_ata_wait_after_reset ata_wait_after_reset ata_wait_ready smp_ata_check_ready sas_ex_phy_discover sas_ex_phy_discover_helper sas_set_ex_phy
The ex_phy's change count is updated in sas_set_ex_phy(), so SATA devices after a link reset may not be found later through revalidation.
A similar issue was reported in: commit 0f3fce5cc77e ("[SCSI] libsas: fix ata_eh clobbering ex_phys via smp_ata_check_ready") commit 87c8331fcf72 ("[SCSI] libsas: prevent domain rediscovery competing with ata error handling").
To address this issue, in hisi_sas_debug_I_T_nexus_reset(), we now call smp_ata_check_ready_type() that only polls the device type while not updating the ex_phy's data of libsas.
Fixes: 71453bd9d1bf ("scsi: hisi_sas: Use sas_ata_wait_after_reset() in IT nexus reset") Signed-off-by: Jie Zhan zhanjie9@hisilicon.com Link: https://lore.kernel.org/r/20221118083714.4034612-5-zhanjie9@hisilicon.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: xiabing xiabing12@h-partners.com --- drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index dc9957b0d6a1..6ed2c969708d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1885,13 +1885,15 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) return rc; }
+ /* Remote phy */ if (rc) return rc;
- /* Remote phy */ if (dev_is_sata(device)) { - rc = sas_ata_wait_after_reset(device, - HISI_SAS_WAIT_PHYUP_TIMEOUT); + struct ata_link *link = &device->sata_dev.ap->link; + + rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT, + smp_ata_check_ready_type); } else { msleep(2000); }