From 1bc9fed394dc8160191178e3250af71518ca073b Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 13 May 2022 08:34:38 +0000 Subject: [PATCH] scsi: hisi_sas: Change hisi_sas_control_phy() phyup timeout mainline inclusion from mainline-5.17-rc1 commit 512623de5239 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: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen Signed-off-by: Xingui Yang conflict: drivers/scsi/hisi_sas/hisi_sas.h drivers/scsi/hisi_sas/hisi_sas_main.c Reviewed-by: Xingui Yang Reviewed-by: kang fenglong Signed-off-by: Yongqiang Liu --- drivers/scsi/hisi_sas/hisi_sas.h | 1 + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 ++++++-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index f3bb10da8f86..a791401be7b3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -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; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6ee5168a6bd8..93df1c6b94c7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -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) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 61ff065e5d9b..e6e489778014 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -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); } } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a268a2ec686c..baae04adc8e4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -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); } } -- GitLab