Michal Suchanek 4940e9
From cedd78cf13852882ab79b738c4025c74921374b2 Mon Sep 17 00:00:00 2001
Michal Suchanek 4940e9
From: Tyrel Datwyler <tyreld@linux.ibm.com>
Michal Suchanek 4940e9
Date: Thu, 11 Feb 2021 12:57:40 -0600
Michal Suchanek 4940e9
Subject: [PATCH 2/4] ibmvfc: fix invalid sub-CRQ handles after hard reset
Michal Suchanek 4940e9
Michal Suchanek 4940e9
References: bsc#1182632 ltc#191222
Michal Suchanek 4940e9
Patch-mainline: submitted https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=229197
Michal Suchanek 4940e9
Michal Suchanek 4940e9
A hard reset results in a complete transport disconnect such that the
Michal Suchanek 4940e9
CRQ connection with the partner VIOS is broken. This has the side effect
Michal Suchanek 4940e9
of also invalidating the associated sub-CRQs. The current code assumes
Michal Suchanek 4940e9
that the sub-CRQs are perserved resulting in a protocol violation after
Michal Suchanek 4940e9
trying to reconnect them with the VIOS. This introduces an infinite loop
Michal Suchanek 4940e9
such that the VIOS forces a disconnect after each subsequent attempt to
Michal Suchanek 4940e9
re-register with invalid handles.
Michal Suchanek 4940e9
Michal Suchanek 4940e9
Avoid the aforementioned issue by releasing the sub-CRQs prior to CRQ
Michal Suchanek 4940e9
disconnect, and driving a reinitialization of the sub-CRQs once a new
Michal Suchanek 4940e9
CRQ is registered with the hypervisor.
Michal Suchanek 4940e9
Michal Suchanek 4940e9
fixes: faacf8c5f1d5 ("ibmvfc: add alloc/dealloc routines for SCSI Sub-CRQ Channels")
Michal Suchanek 4940e9
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Michal Suchanek 4940e9
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
Michal Suchanek 4940e9
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 4940e9
---
Michal Suchanek 4940e9
 drivers/scsi/ibmvscsi/ibmvfc.c | 21 +++++++++------------
Michal Suchanek 4940e9
 1 file changed, 9 insertions(+), 12 deletions(-)
Michal Suchanek 4940e9
Michal Suchanek 4940e9
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 4940e9
index 7be437e9d805..5030e1e974e7 100644
Michal Suchanek 4940e9
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 4940e9
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 4940e9
@@ -158,6 +158,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *);
Michal Suchanek 4940e9
 static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *);
Michal Suchanek 4940e9
 static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
+static void ibmvfc_release_sub_crqs(struct ibmvfc_host *);
Michal Suchanek 4940e9
+static void ibmvfc_init_sub_crqs(struct ibmvfc_host *);
Michal Suchanek 4940e9
+
Michal Suchanek 4940e9
 static const char *unknown_error = "unknown error";
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
 static long h_reg_sub_crq(unsigned long unit_address, unsigned long ioba,
Michal Suchanek 4940e9
@@ -926,8 +929,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
Michal Suchanek 4940e9
 	unsigned long flags;
Michal Suchanek 4940e9
 	struct vio_dev *vdev = to_vio_dev(vhost->dev);
Michal Suchanek 4940e9
 	struct ibmvfc_queue *crq = &vhost->crq;
Michal Suchanek 4940e9
-	struct ibmvfc_queue *scrq;
Michal Suchanek 4940e9
-	int i;
Michal Suchanek 4940e9
+
Michal Suchanek 4940e9
+	ibmvfc_release_sub_crqs(vhost);
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
 	/* Close the CRQ */
Michal Suchanek 4940e9
 	do {
Michal Suchanek 4940e9
@@ -947,16 +950,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
Michal Suchanek 4940e9
 	memset(crq->msgs.crq, 0, PAGE_SIZE);
Michal Suchanek 4940e9
 	crq->cur = 0;
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
-	if (vhost->scsi_scrqs.scrqs) {
Michal Suchanek 4940e9
-		for (i = 0; i < nr_scsi_hw_queues; i++) {
Michal Suchanek 4940e9
-			scrq = &vhost->scsi_scrqs.scrqs[i];
Michal Suchanek 4940e9
-			spin_lock(scrq->q_lock);
Michal Suchanek 4940e9
-			memset(scrq->msgs.scrq, 0, PAGE_SIZE);
Michal Suchanek 4940e9
-			scrq->cur = 0;
Michal Suchanek 4940e9
-			spin_unlock(scrq->q_lock);
Michal Suchanek 4940e9
-		}
Michal Suchanek 4940e9
-	}
Michal Suchanek 4940e9
-
Michal Suchanek 4940e9
 	/* And re-open it again */
Michal Suchanek 4940e9
 	rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
Michal Suchanek 4940e9
 				crq->msg_token, PAGE_SIZE);
Michal Suchanek 4940e9
@@ -966,6 +959,9 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
Michal Suchanek 4940e9
 		dev_warn(vhost->dev, "Partner adapter not ready\n");
Michal Suchanek 4940e9
 	else if (rc != 0)
Michal Suchanek 4940e9
 		dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc);
Michal Suchanek 4940e9
+
Michal Suchanek 4940e9
+	ibmvfc_init_sub_crqs(vhost);
Michal Suchanek 4940e9
+
Michal Suchanek 4940e9
 	spin_unlock(vhost->crq.q_lock);
Michal Suchanek 4940e9
 	spin_unlock_irqrestore(vhost->host->host_lock, flags);
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
@@ -5694,6 +5690,7 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
 	free_irq(scrq->irq, scrq);
Michal Suchanek 4940e9
 	irq_dispose_mapping(scrq->irq);
Michal Suchanek 4940e9
+	scrq->irq = 0;
Michal Suchanek 4940e9
 
Michal Suchanek 4940e9
 	do {
Michal Suchanek 4940e9
 		rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,
Michal Suchanek 4940e9
-- 
Michal Suchanek 4940e9
2.26.2
Michal Suchanek 4940e9