Commit 1bc9fed3 authored by Xiang Chen's avatar Xiang Chen Committed by Yongqiang Liu
Browse files

scsi: hisi_sas: Change hisi_sas_control_phy() phyup timeout

mainline inclusion
from mainline-5.17-rc1
commit 512623de
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4UT5N
CVE: NA

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

The time of phyup not only depends on the controller but also the type of
disk connected. As an example, from experience, for some SATA disks the
amount of time from reset/power-on to receive the D2H FIS for phyup can
take upto and more than 10s sometimes. According to the specification of
some SATA disks such as ST14000NM0018, the max time from power-on to ready
is 30s.

Based on this the current timeout of phyup at 2s which is not enough. So
set the value as HISI_SAS_WAIT_PHYUP_TIMEOUT (30s) in
hisi_sas_control_phy().

For v3 hw there is a pre-existing workaround for a HW bug, being that we
issue a link reset when the OOB occurs but the phyup does not. The current
phyup timeout is HISI_SAS_WAIT_PHYUP_TIMEOUT. So if this does occur from
when issuing a phy enable or similar via hisi_sas_control_phy(), the
subsequent HW workaround linkreset processing calls hisi_sas_control_phy(),
but this will pend the original phy reset timing out, so it is safe.

Link: https://lore.kernel.org/r/1645703489-87194-3-git-send-email-john.garry@huawei.com


Signed-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarXingui Yang <yangxingui@huawei.com>
conflict:
	drivers/scsi/hisi_sas/hisi_sas.h
	drivers/scsi/hisi_sas/hisi_sas_main.c
Reviewed-by: default avatarXingui Yang <yangxingui@huawei.com>
Reviewed-by: default avatarkang fenglong <kangfenglong@huawei.com>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent 8fdd6417
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@

#define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK | HISI_SAS_DIX_PROT_MASK)

#define HISI_SAS_WAIT_PHYUP_TIMEOUT	(30 * HZ)
#define CLEAR_ITCT_TIMEOUT	20

struct hisi_hba;
+6 −2
Original line number Diff line number Diff line
@@ -1783,6 +1783,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
	int rc, reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT ||
			      !dev_is_sata(device)) ? true : false;
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct device *dev = hisi_hba->dev;
	struct sas_ha_struct *sas_ha = &hisi_hba->sha;
	DECLARE_COMPLETION_ONSTACK(phyreset);

@@ -1809,7 +1810,8 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
		struct hisi_sas_phy *phy =
			container_of(sas_phy, struct hisi_sas_phy, sas_phy);
		/* Wait for I_T reset complete, time out after 2s */
		int ret = wait_for_completion_timeout(&phyreset, 2 * HZ);
		int ret = wait_for_completion_timeout(&phyreset,
				HISI_SAS_WAIT_PHYUP_TIMEOUT);
		unsigned long flags;

		spin_lock_irqsave(&phy->lock, flags);
@@ -1818,8 +1820,10 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
		spin_unlock_irqrestore(&phy->lock, flags);

		/* report PHY down if timed out */
		if (!ret)
		if (!ret) {
			dev_warn(dev, "phy%d reset timeout\n", sas_phy->id);
			hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
		}
	} else if (sas_dev->dev_status != HISI_SAS_DEV_INIT)
		/* Sleep 2s, wait for I_T reset at expander env except fail */
		if (!rc)
+1 −2
Original line number Diff line number Diff line
@@ -2874,7 +2874,6 @@ static const struct hisi_sas_hw_error port_ecc_axi_error[] = {
	},
};

#define WAIT_PHYUP_TIMEOUT_V2_HW 20
static void wait_phyup_timedout_v2_hw(struct timer_list *t)
{
	struct hisi_sas_phy *phy = from_timer(phy, t, timer);
@@ -2894,7 +2893,7 @@ static void phy_oob_ready_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
	if (!timer_pending(&phy->timer)) {
		dev_dbg(dev, "phy%d OOB ready\n", phy_no);
		phy->timer.function = wait_phyup_timedout_v2_hw;
		phy->timer.expires = jiffies + WAIT_PHYUP_TIMEOUT_V2_HW * HZ;
		phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT;
		add_timer(&phy->timer);
	}
}
+1 −2
Original line number Diff line number Diff line
@@ -1890,7 +1890,6 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, irq_value);
}

#define WAIT_PHYUP_TIMEOUT_V3_HW 20
static void wait_phyup_timedout_v3_hw(struct timer_list *t)
{
	struct hisi_sas_phy *phy = from_timer(phy, t, timer);
@@ -1917,7 +1916,7 @@ static void handle_chl_int0_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
		if (!timer_pending(&phy->timer)) {
			phy->timer.function = wait_phyup_timedout_v3_hw;
			phy->timer.expires = jiffies +
					WAIT_PHYUP_TIMEOUT_V3_HW * HZ;
					HISI_SAS_WAIT_PHYUP_TIMEOUT;
			add_timer(&phy->timer);
		}
	}