Commit f605baa3 authored by Yihang Li's avatar Yihang Li Committed by Slim6882
Browse files

[Backport]scsi: hisi_sas: Reset PHY again if phyup timeout

mainline inclusion
from mainline-v6.12-rc1
commit 64359afb7068e9fd1b3ffcf7b0fefb63d1a2ccdf
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBCN9K
CVE: NA
Reference: https://lore.kernel.org/r/20241008021822.2617339-6-liyihang9@huawei.com



------------------------------------------------------------------

In commit 89954f02 ("scsi: hisi_sas: Ensure all enabled PHYs up
during controller reset"), we enable PHYs in parallel through async
operations and wait for PHYs come up. However, for some directly
attached SATA disks, the PHY not come up after a timeout period and the
hardware is not ready.  At this time, we should get the latest PHY
hardware state, if the new PHY state is not ready but the old PHY state
is ready, call work HISI_PHYE_LINK_RESET to give it another chance to
phyup.

Signed-off-by: default avatarYihang Li <liyihang9@huawei.com>
Link: https://lore.kernel.org/r/20241008021822.2617339-6-liyihang9@huawei.com


Reviewed-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSlim6882 <yangjunshuo@huawei.com>
parent c526fc11
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -1475,6 +1475,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)

static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
{
	u32 new_state = hisi_hba->hw->get_phys_state(hisi_hba);
	struct asd_sas_port *_sas_port = NULL;
	int phy_no;

@@ -1488,7 +1489,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
			continue;

		/* Report PHY state change to libsas */
		if (state & BIT(phy_no)) {
		if (new_state & BIT(phy_no)) {
			if (do_port_check && sas_port && sas_port->port_dev) {
				struct domain_device *dev = sas_port->port_dev;

@@ -1501,6 +1502,16 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
			}
		} else {
			hisi_sas_phy_down(hisi_hba, phy_no, 0, GFP_KERNEL);

			/*
			 * The new_state is not ready but old_state is ready,
			 * the two possible causes:
			 * 1. The connected device is removed
			 * 2. Device exists but phyup timed out
			 */
			if (state & BIT(phy_no))
				hisi_sas_notify_phy_event(phy,
							  HISI_PHYE_LINK_RESET);
		}
	}
}