lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 18 Jul 2018 22:14:27 +0800
From:   John Garry <john.garry@...wei.com>
To:     <jejb@...ux.vnet.ibm.com>, <martin.petersen@...cle.com>
CC:     <linux-scsi@...r.kernel.org>, <linuxarm@...wei.com>,
        <linux-kernel@...r.kernel.org>,
        Xiaofei Tan <tanxiaofei@...wei.com>,
        "John Garry" <john.garry@...wei.com>
Subject: [PATCH 3/9] scsi: hisi_sas: Fix the failure of recovering PHY from STP link timeout

From: Xiaofei Tan <tanxiaofei@...wei.com>

There is an issue that link reset can't recover PHY when STP link timeout.
Because current process of enabling PHY for v3 hw will wait last
transmission done. The time of one transmission depends IO size, disk
model and so on. Normally, it should be shorter than 50ms. But the last
transmission could be never done for some abnormal scenarios, such as STP
link timeout.

This patch is to fix the issue. Check PHY status after starting process of
enabling PHY for 50ms. If the PHY is still active, we disable it forcibly
by PHY reset. Of course, we need to clear the PHY reset bit when enable
PHY.

Besides, the function disable_phy_v3_hw() should not be suitable to call
in interrupts for hilink bug for this 50ms delay. Then, we do link reset
for hilink bug directly. The change is that we don't clear the invalid
dword count register. This is better. Because we should not clear such
error count while not saved.

Signed-off-by: Xiaofei Tan <tanxiaofei@...wei.com>
Signed-off-by: John Garry <john.garry@...wei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index d7c3774..70a6aa2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -120,6 +120,8 @@
 #define PHY_CFG_ENA_MSK			(0x1 << PHY_CFG_ENA_OFF)
 #define PHY_CFG_DC_OPT_OFF		2
 #define PHY_CFG_DC_OPT_MSK		(0x1 << PHY_CFG_DC_OPT_OFF)
+#define PHY_CFG_PHY_RST_OFF		3
+#define PHY_CFG_PHY_RST_MSK		(0x1 << PHY_CFG_PHY_RST_OFF)
 #define PROG_PHY_LINK_RATE		(PORT_BASE + 0x8)
 #define PHY_CTRL			(PORT_BASE + 0x14)
 #define PHY_CTRL_RESET_OFF		0
@@ -760,15 +762,25 @@ static void enable_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 	u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
 
 	cfg |= PHY_CFG_ENA_MSK;
+	cfg &= ~PHY_CFG_PHY_RST_MSK;
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
 static void disable_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
 	u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
+	u32 state;
 
 	cfg &= ~PHY_CFG_ENA_MSK;
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
+
+	mdelay(50);
+
+	state = hisi_sas_read32(hisi_hba, PHY_STATE);
+	if (state & BIT(phy_no)) {
+		cfg |= PHY_CFG_PHY_RST_MSK;
+		hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
+	}
 }
 
 static void start_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
@@ -1385,8 +1397,6 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 			hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
 	}
 
-	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, irq_value);
-
 	if ((irq_value & BIT(CHL_INT2_RX_INVLD_DW_OFF)) &&
 	    (pci_dev->revision == 0x20)) {
 		u32 reg_value;
@@ -1396,15 +1406,11 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 				HILINK_ERR_DFX, reg_value,
 				!((reg_value >> 8) & BIT(phy_no)),
 				1000, 10000);
-		if (rc) {
-			disable_phy_v3_hw(hisi_hba, phy_no);
-			hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
-					     BIT(CHL_INT2_RX_INVLD_DW_OFF));
-			hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
-			mdelay(1);
-			enable_phy_v3_hw(hisi_hba, phy_no);
-		}
+		if (rc)
+			hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
 	}
+
+	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, irq_value);
 }
 
 static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
-- 
1.9.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ