From 5ed48c3e9af21e878fa33661fa5dbd2fc1e8af0f Mon Sep 17 00:00:00 2001
From: nifujia <nifujia1@hisilicon.com>
Date: Tue, 18 Jan 2022 21:23:43 +0800
Subject: [PATCH 094/108] scsi: hisi_sas:
 Disable-SATA-disk-phy-for-severe-I_T-nexus reset failure

mainline inclusion
from mainline-v5.16-rc1
commit 21c7e972475e6a975fbe97f8974c96fe4713077c
category: feature
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=21c7e972475e6a975fbe97f8974c96fe4713077c

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

If the softreset fails in the I_T reset, libsas will then continue to issue
a controller reset to try to recover.

However a faulty disk may cause the softreset to fail, and resetting the
controller will not help this scenario. Indeed, we will just continue the
cycle of error handle handling to try to recover.

So if the softreset fails upon certain conditions, just disable the phy
associated with the disk. The user needs to handle this problem.

Link: https://lore.kernel.org/r/1634041588-74824-5-git-send-email-john.garry@huawei.com
Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Ouyangdelong <ouyangdelong@huawei.com>
Signed-off-by: Nifujia <nifujia1@hisilicon.com>
Reviewed-by: Jason Yan <yanaijie@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>

 Conflicts:
	drivers/scsi/hisi_sas/hisi_sas_main.c
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 0ab8b324f82c..48644ab23e4c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1953,15 +1953,36 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
 	}
 	hisi_sas_dereg_device(hisi_hba, device);
 
-	if (dev_is_sata(device)) {
+	rc = hisi_sas_debug_I_T_nexus_reset(device);
+	if (rc == TMF_RESP_FUNC_COMPLETE && dev_is_sata(device)) {
+		struct sas_phy *local_phy;
+
 		rc = hisi_sas_softreset_ata_disk(device);
 		if (rc)
 			dev_err(dev, "I_T nexus reset: softreset failed  (%d)\n",
 				rc);
+		switch (rc) {
+		case -ECOMM:
+			rc = -ENODEV;
+			break;
+		case TMF_RESP_FUNC_FAILED:
+		case -EMSGSIZE:
+		case -EIO:
+			local_phy = sas_get_local_phy(device);
+			rc = sas_phy_enable(local_phy, 0);
+			if (!rc) {
+				local_phy->enabled = 0;
+				dev_err(dev, "Disabled local phy of ATA disk %016llx due to softreset fail (%d)\n",
+					SAS_ADDR(device->sas_addr), rc);
+				rc = -ENODEV;
+			}
+			sas_put_local_phy(local_phy);
+			break;
+		default:
+			break;
+		}
 	}
 
-	rc = hisi_sas_debug_I_T_nexus_reset(device);
-
 	if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
 		hisi_sas_release_task(hisi_hba, device);
 
-- 
2.27.0

