All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] hisi_sas: Some misc patches for next
@ 2021-10-12 12:26 John Garry
  2021-10-12 12:26 ` [PATCH 1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback John Garry
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: John Garry @ 2021-10-12 12:26 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: yanaijie, linux-scsi, linux-kernel, linuxarm, John Garry

This small series includes the following:
- Relocate the init device functionality to a more appropriate location
- Make the phy control function synchronous
- For faulty SATA disk, disable their phy to stop spinning in the error
  handler
- For previous patch we need to export a libsas phy control function

Thanks!

Luo Jiaxing (2):
  scsi: libsas: Export sas_phy_enable()
  scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset
    failure

Xiang Chen (2):
  scsi: hisi_sas: Initialise devices in .slave_alloc callback
  scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy()

 drivers/scsi/hisi_sas/hisi_sas.h       |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 89 ++++++++++++++++++++------
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 13 +---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 19 ++----
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 11 +---
 drivers/scsi/libsas/sas_init.c         |  3 +-
 include/scsi/libsas.h                  |  1 +
 7 files changed, 84 insertions(+), 53 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
@ 2021-10-12 12:26 ` John Garry
  2021-10-12 12:26 ` [PATCH 2/4] scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy() John Garry
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: John Garry @ 2021-10-12 12:26 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: yanaijie, linux-scsi, linux-kernel, linuxarm, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

Put the driver custom SCSI device initialize procedure in the more
appropriate callback from the SCSI midlayer, and not from the libsas dev
found callback.

The .slave_alloc interface is called prior to sending any IO to the device,
which is what we want.

Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h       |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 17 ++++++++++++++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  2 +-
 5 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 57be32ba0109..2213a91923a5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -649,6 +649,7 @@ extern int hisi_sas_probe(struct platform_device *pdev,
 extern int hisi_sas_remove(struct platform_device *pdev);
 
 extern int hisi_sas_slave_configure(struct scsi_device *sdev);
+extern int hisi_sas_slave_alloc(struct scsi_device *sdev);
 extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);
 extern void hisi_sas_scan_start(struct Scsi_Host *shost);
 extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index bb1c8ef3a76f..0835ba7c0ac2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -756,6 +756,20 @@ static int hisi_sas_init_device(struct domain_device *device)
 	return rc;
 }
 
+int hisi_sas_slave_alloc(struct scsi_device *sdev)
+{
+	struct domain_device *ddev;
+	int rc;
+
+	rc = sas_slave_alloc(sdev);
+	if (rc)
+		return rc;
+	ddev = sdev_to_domain_dev(sdev);
+
+	return hisi_sas_init_device(ddev);
+}
+EXPORT_SYMBOL_GPL(hisi_sas_slave_alloc);
+
 static int hisi_sas_dev_found(struct domain_device *device)
 {
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
@@ -802,9 +816,6 @@ static int hisi_sas_dev_found(struct domain_device *device)
 	dev_info(dev, "dev[%d:%x] found\n",
 		sas_dev->device_id, sas_dev->dev_type);
 
-	rc = hisi_sas_init_device(device);
-	if (rc)
-		goto err_out;
 	sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
 	return 0;
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 862f4e8b7eb5..51e7d12f5053 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1771,7 +1771,7 @@ static struct scsi_host_template sht_v1_hw = {
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
-	.slave_alloc		= sas_slave_alloc,
+	.slave_alloc		= hisi_sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 236cf65c2f97..741a62e6bf77 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3584,7 +3584,7 @@ static struct scsi_host_template sht_v2_hw = {
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
-	.slave_alloc		= sas_slave_alloc,
+	.slave_alloc		= hisi_sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index f4517f3eb922..114a59654525 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -3157,7 +3157,7 @@ static struct scsi_host_template sht_v3_hw = {
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
-	.slave_alloc		= sas_slave_alloc,
+	.slave_alloc		= hisi_sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 #ifdef CONFIG_COMPAT
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy()
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
  2021-10-12 12:26 ` [PATCH 1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback John Garry
@ 2021-10-12 12:26 ` John Garry
  2021-10-12 12:26 ` [PATCH 3/4] scsi: libsas: Export sas_phy_enable() John Garry
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: John Garry @ 2021-10-12 12:26 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: yanaijie, linux-scsi, linux-kernel, linuxarm, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

When issuing a hardreset/linkreset/phy_set_linkrate from sysfs, the phy
will be disabled and re-enabled for the directly attached scenario.

It takes some time for the phy to come back up after re-enabling the phy.
If the controller becomes suspended while waiting for the phy to come
back, the phy up may be lost (along with the disk).

To solve the problem, wait for the phy up to occur with a timeout. Indeed
this is already done in hisi_sas_debug_I_T_nexus_reset() for local phys,
so just relocate the functionality to hisi_sas_control_phy().

Since the HA workqueue is drained when suspending the controller, and the
phy control function is called from the same workqueue, we can guarantee
that the controller will not be suspended during this period.

Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 43 +++++++++++++++++++-------
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 11 ++-----
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 17 ++--------
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  9 ++----
 4 files changed, 39 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 0835ba7c0ac2..5b091388c095 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1146,9 +1146,17 @@ static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
 static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
 				void *funcdata)
 {
+	struct hisi_sas_phy *phy = container_of(sas_phy,
+			struct hisi_sas_phy, sas_phy);
 	struct sas_ha_struct *sas_ha = sas_phy->ha;
 	struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
+	struct device *dev = hisi_hba->dev;
+	DECLARE_COMPLETION_ONSTACK(completion);
 	int phy_no = sas_phy->id;
+	u8 sts = phy->phy_attached;
+	int ret = 0;
+
+	phy->reset_completion = &completion;
 
 	switch (func) {
 	case PHY_FUNC_HARD_RESET:
@@ -1163,21 +1171,35 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
 
 	case PHY_FUNC_DISABLE:
 		hisi_sas_phy_enable(hisi_hba, phy_no, 0);
-		break;
+		goto out;
 
 	case PHY_FUNC_SET_LINK_RATE:
-		return hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
+		ret = hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
+		break;
+
 	case PHY_FUNC_GET_EVENTS:
 		if (hisi_hba->hw->get_events) {
 			hisi_hba->hw->get_events(hisi_hba, phy_no);
-			break;
+			goto out;
 		}
 		fallthrough;
 	case PHY_FUNC_RELEASE_SPINUP_HOLD:
 	default:
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
-	return 0;
+
+	if (sts && !wait_for_completion_timeout(&completion, 2 * HZ)) {
+		dev_warn(dev, "phy%d wait phyup timed out for func %d\n",
+			 phy_no, func);
+		if (phy->in_reset)
+			ret = -ETIMEDOUT;
+	}
+
+out:
+	phy->reset_completion = NULL;
+
+	return ret;
 }
 
 static void hisi_sas_task_done(struct sas_task *task)
@@ -1783,7 +1805,6 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
 	struct sas_ha_struct *sas_ha = &hisi_hba->sha;
-	DECLARE_COMPLETION_ONSTACK(phyreset);
 	int rc, reset_type;
 
 	if (!local_phy->enabled) {
@@ -1796,8 +1817,11 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
 			sas_ha->sas_phy[local_phy->number];
 		struct hisi_sas_phy *phy =
 			container_of(sas_phy, struct hisi_sas_phy, sas_phy);
+		unsigned long flags;
+
+		spin_lock_irqsave(&phy->lock, flags);
 		phy->in_reset = 1;
-		phy->reset_completion = &phyreset;
+		spin_unlock_irqrestore(&phy->lock, flags);
 	}
 
 	reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT ||
@@ -1811,17 +1835,14 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
 			sas_ha->sas_phy[local_phy->number];
 		struct hisi_sas_phy *phy =
 			container_of(sas_phy, struct hisi_sas_phy, sas_phy);
-		int ret = wait_for_completion_timeout(&phyreset,
-						I_T_NEXUS_RESET_PHYUP_TIMEOUT);
 		unsigned long flags;
 
 		spin_lock_irqsave(&phy->lock, flags);
-		phy->reset_completion = NULL;
 		phy->in_reset = 0;
 		spin_unlock_irqrestore(&phy->lock, flags);
 
 		/* report PHY down if timed out */
-		if (!ret)
+		if (rc == -ETIMEDOUT)
 			hisi_sas_phy_down(hisi_hba, sas_phy->id, 0, GFP_KERNEL);
 	} else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) {
 		/*
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 51e7d12f5053..b4951ff9ca51 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1327,7 +1327,6 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
 	u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
 	struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
 	irqreturn_t res = IRQ_HANDLED;
-	unsigned long flags;
 
 	irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2);
 	if (!(irq_value & CHL_INT2_SL_PHY_ENA_MSK)) {
@@ -1380,15 +1379,9 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
 		phy->identify.target_port_protocols =
 			SAS_PROTOCOL_SMP;
 	hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
-
-	spin_lock_irqsave(&phy->lock, flags);
-	if (phy->reset_completion) {
-		phy->in_reset = 0;
-		complete(phy->reset_completion);
-	}
-	spin_unlock_irqrestore(&phy->lock, flags);
-
 end:
+	if (phy->reset_completion)
+		complete(phy->reset_completion);
 	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
 			     CHL_INT2_SL_PHY_ENA_MSK);
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 741a62e6bf77..45eb0b98d00b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2641,7 +2641,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 	struct device *dev = hisi_hba->dev;
 	u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
 	struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
-	unsigned long flags;
 
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
 
@@ -2696,14 +2695,9 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 			set_link_timer_quirk(hisi_hba);
 	}
 	hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
-	spin_lock_irqsave(&phy->lock, flags);
-	if (phy->reset_completion) {
-		phy->in_reset = 0;
-		complete(phy->reset_completion);
-	}
-	spin_unlock_irqrestore(&phy->lock, flags);
-
 end:
+	if (phy->reset_completion)
+		complete(phy->reset_completion);
 	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 			     CHL_INT0_SL_PHY_ENABLE_MSK);
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
@@ -3204,7 +3198,6 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
 	u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate;
 	irqreturn_t res = IRQ_HANDLED;
 	u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
-	unsigned long flags;
 	int phy_no, offset;
 
 	del_timer(&phy->timer);
@@ -3280,12 +3273,8 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
 	phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
 	hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
 
-	spin_lock_irqsave(&phy->lock, flags);
-	if (phy->reset_completion) {
-		phy->in_reset = 0;
+	if (phy->reset_completion)
 		complete(phy->reset_completion);
-	}
-	spin_unlock_irqrestore(&phy->lock, flags);
 end:
 	hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp);
 	hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 114a59654525..2082b066aca7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1482,7 +1482,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
 	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
 	struct asd_sas_phy *sas_phy = &phy->sas_phy;
 	struct device *dev = hisi_hba->dev;
-	unsigned long flags;
 
 	del_timer(&phy->timer);
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
@@ -1564,13 +1563,9 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
 	phy->phy_attached = 1;
 	hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
 	res = IRQ_HANDLED;
-	spin_lock_irqsave(&phy->lock, flags);
-	if (phy->reset_completion) {
-		phy->in_reset = 0;
-		complete(phy->reset_completion);
-	}
-	spin_unlock_irqrestore(&phy->lock, flags);
 end:
+	if (phy->reset_completion)
+		complete(phy->reset_completion);
 	hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 			     CHL_INT0_SL_PHY_ENABLE_MSK);
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] scsi: libsas: Export sas_phy_enable()
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
  2021-10-12 12:26 ` [PATCH 1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback John Garry
  2021-10-12 12:26 ` [PATCH 2/4] scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy() John Garry
@ 2021-10-12 12:26 ` John Garry
  2021-10-12 12:26 ` [PATCH 4/4] scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure John Garry
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: John Garry @ 2021-10-12 12:26 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: yanaijie, linux-scsi, linux-kernel, linuxarm, Luo Jiaxing, John Garry

From: Luo Jiaxing <luojiaxing@huawei.com>

Export sas_phy_enable(), so LLDDs can directly use it to control
remote phys.

We already do this for companion function sas_phy_reset().

Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/libsas/sas_init.c | 3 ++-
 include/scsi/libsas.h          | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 37cc92837fdf..b640e09af6a4 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -254,7 +254,7 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
 	}
 }
 
-static int sas_phy_enable(struct sas_phy *phy, int enable)
+int sas_phy_enable(struct sas_phy *phy, int enable)
 {
 	int ret;
 	enum phy_func cmd;
@@ -286,6 +286,7 @@ static int sas_phy_enable(struct sas_phy *phy, int enable)
 	}
 	return ret;
 }
+EXPORT_SYMBOL_GPL(sas_phy_enable);
 
 int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 {
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 6fe125a71b60..79e4903bd414 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -664,6 +664,7 @@ extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
 
 int sas_set_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates);
 int sas_phy_reset(struct sas_phy *phy, int hard_reset);
+int sas_phy_enable(struct sas_phy *phy, int enable);
 extern int sas_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
 extern int sas_target_alloc(struct scsi_target *);
 extern int sas_slave_configure(struct scsi_device *);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
                   ` (2 preceding siblings ...)
  2021-10-12 12:26 ` [PATCH 3/4] scsi: libsas: Export sas_phy_enable() John Garry
@ 2021-10-12 12:26 ` John Garry
  2021-10-13  2:46 ` [PATCH 0/4] hisi_sas: Some misc patches for next Martin K. Petersen
  2021-10-21  3:42 ` Martin K. Petersen
  5 siblings, 0 replies; 7+ messages in thread
From: John Garry @ 2021-10-12 12:26 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: yanaijie, linux-scsi, linux-kernel, linuxarm, Luo Jiaxing, John Garry

From: Luo Jiaxing <luojiaxing@huawei.com>

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.

Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 29 ++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 5b091388c095..f206c433de32 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1870,14 +1870,33 @@ 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 == TMF_RESP_FUNC_FAILED)
-			return TMF_RESP_FUNC_FAILED;
+		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.26.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] hisi_sas: Some misc patches for next
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
                   ` (3 preceding siblings ...)
  2021-10-12 12:26 ` [PATCH 4/4] scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure John Garry
@ 2021-10-13  2:46 ` Martin K. Petersen
  2021-10-21  3:42 ` Martin K. Petersen
  5 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2021-10-13  2:46 UTC (permalink / raw)
  To: John Garry
  Cc: jejb, martin.petersen, yanaijie, linux-scsi, linux-kernel, linuxarm


John,

> This small series includes the following:
> - Relocate the init device functionality to a more appropriate location
> - Make the phy control function synchronous
> - For faulty SATA disk, disable their phy to stop spinning in the error
>   handler
> - For previous patch we need to export a libsas phy control function

Applied to 5.16/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] hisi_sas: Some misc patches for next
  2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
                   ` (4 preceding siblings ...)
  2021-10-13  2:46 ` [PATCH 0/4] hisi_sas: Some misc patches for next Martin K. Petersen
@ 2021-10-21  3:42 ` Martin K. Petersen
  5 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2021-10-21  3:42 UTC (permalink / raw)
  To: John Garry, jejb
  Cc: Martin K . Petersen, linuxarm, yanaijie, linux-scsi, linux-kernel

On Tue, 12 Oct 2021 20:26:24 +0800, John Garry wrote:

> This small series includes the following:
> - Relocate the init device functionality to a more appropriate location
> - Make the phy control function synchronous
> - For faulty SATA disk, disable their phy to stop spinning in the error
>   handler
> - For previous patch we need to export a libsas phy control function
> 
> [...]

Applied to 5.16/scsi-queue, thanks!

[1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback
      https://git.kernel.org/mkp/scsi/c/36c6b7613ef1
[2/4] scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy()
      https://git.kernel.org/mkp/scsi/c/046ab7d0f594
[3/4] scsi: libsas: Export sas_phy_enable()
      https://git.kernel.org/mkp/scsi/c/00aeaf329a3a
[4/4] scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure
      https://git.kernel.org/mkp/scsi/c/21c7e972475e

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-10-21  3:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-12 12:26 [PATCH 0/4] hisi_sas: Some misc patches for next John Garry
2021-10-12 12:26 ` [PATCH 1/4] scsi: hisi_sas: Initialise devices in .slave_alloc callback John Garry
2021-10-12 12:26 ` [PATCH 2/4] scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy() John Garry
2021-10-12 12:26 ` [PATCH 3/4] scsi: libsas: Export sas_phy_enable() John Garry
2021-10-12 12:26 ` [PATCH 4/4] scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure John Garry
2021-10-13  2:46 ` [PATCH 0/4] hisi_sas: Some misc patches for next Martin K. Petersen
2021-10-21  3:42 ` Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.