Blob Blame History Raw
From c73a4d53dfbd548504334171623695c98baffb83 Mon Sep 17 00:00:00 2001
From: Saurav Kashyap <skashyap@marvell.com>
Date: Fri, 20 Oct 2023 14:12:35 +0530
Subject: [PATCH 2/2] qedf: Wait for stag work during unload.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Patch-mainline: not yet, waiting for upstream submission by Marvell
References: bsc#1214852
Acked-by: Martin Wilck <mwilck@suse.com>
---
 drivers/scsi/qedf/qedf.h      |    1 +
 drivers/scsi/qedf/qedf_main.c |   24 +++++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -354,6 +354,7 @@ struct qedf_ctx {
 #define QEDF_IN_RECOVERY		5
 #define QEDF_DBG_STOP_IO		6
 #define QEDF_PROBING			8
+#define QEDF_STAG_IN_PROGRESS		9
 	unsigned long flags; /* Miscellaneous state flags */
 	int fipvlan_retries;
 	u8 num_queues;
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -318,11 +318,17 @@ static struct fc_seq *qedf_elsct_send(st
 	 */
 	if (resp == fc_lport_flogi_resp) {
 		qedf->flogi_cnt++;
+		qedf->flogi_pending++;
+
+                if (test_bit(QEDF_UNLOADING, &qedf->flags)) {
+                        QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n");
+                        qedf->flogi_pending = 0;
+                }
+
 		if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) {
 			schedule_delayed_work(&qedf->stag_work, 2);
 			return NULL;
 		}
-		qedf->flogi_pending++;
 		return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp,
 		    arg, timeout);
 	}
@@ -912,6 +918,7 @@ void qedf_ctx_soft_reset(struct fc_lport
 	struct qed_link_output if_link;
 
 	if (lport->vport) {
+		clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
 		printk_ratelimited("Cannot issue host reset on NPIV port.\n");
 		return;
 	}
@@ -935,6 +942,7 @@ void qedf_ctx_soft_reset(struct fc_lport
 	qed_ops->common->get_link(qedf->cdev, &if_link);
 	/* Bail if the physical link is not up */
 	if (!if_link.link_up) {
+		clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
 		QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
 			  "Physical link is not up.\n");
 		return;
@@ -949,6 +957,7 @@ void qedf_ctx_soft_reset(struct fc_lport
 		  "Queue link up work.\n");
 	queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
 	    0);
+	clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
 }
 
 /* Reset the host by gracefully logging out and then logging back in */
@@ -3722,6 +3731,7 @@ static void __qedf_remove(struct pci_dev
 {
 	struct qedf_ctx *qedf;
 	int rc;
+	int cnt = 0;
 
 	if (!pdev) {
 		QEDF_ERR(NULL, "pdev is NULL.\n");
@@ -3739,6 +3749,17 @@ static void __qedf_remove(struct pci_dev
 		return;
 	}
 
+stag_in_prog:
+        if (test_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags)) {
+                QEDF_ERR(&qedf->dbg_ctx, "Stag in progress, cnt=%d.\n", cnt);
+                cnt++;
+
+                if (cnt < 5) {
+                        msleep(500);
+                        goto stag_in_prog;
+                }
+        }
+
 	if (mode != QEDF_MODE_RECOVERY)
 		set_bit(QEDF_UNLOADING, &qedf->flags);
 
@@ -4003,6 +4024,7 @@ void qedf_stag_change_work(struct work_s
 		return;
 	}
 
+	set_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
 
 	printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.",
 			dev_name(&qedf->pdev->dev), __func__, __LINE__,