Daniel Wagner feefdb
From: Quinn Tran <qutran@marvell.com>
Daniel Wagner feefdb
Date: Tue, 26 Oct 2021 04:54:05 -0700
Daniel Wagner feefdb
Subject: scsi: qla2xxx: edif: Flush stale events and msgs on session down
Daniel Wagner feefdb
Patch-mainline: v5.16-rc1
Daniel Wagner feefdb
Git-commit: b1af26c245545a289b331c7b71996ecd88321540
Daniel Wagner feefdb
References: git-fixes
Daniel Wagner feefdb
Daniel Wagner feefdb
On session down, driver will flush all stale messages and doorbell
Daniel Wagner feefdb
events. This prevents authentication application from having to process
Daniel Wagner feefdb
stale data.
Daniel Wagner feefdb
Daniel Wagner feefdb
Link: https://lore.kernel.org/r/20211026115412.27691-7-njavali@marvell.com
Daniel Wagner feefdb
Fixes: 4de067e5df12 ("scsi: qla2xxx: edif: Add N2N support for EDIF")
Daniel Wagner feefdb
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Daniel Wagner feefdb
Co-developed-by: Karunakara Merugu <kmerugu@marvell.com>
Daniel Wagner feefdb
Signed-off-by: Karunakara Merugu <kmerugu@marvell.com>
Daniel Wagner feefdb
Signed-off-by: Quinn Tran <qutran@marvell.com>
Daniel Wagner feefdb
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Daniel Wagner feefdb
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner feefdb
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner feefdb
---
Daniel Wagner feefdb
 drivers/scsi/qla2xxx/qla_edif.c   |   96 +++++++++++++++++++++++++++++++++++++-
Daniel Wagner feefdb
 drivers/scsi/qla2xxx/qla_gbl.h    |    2 
Daniel Wagner feefdb
 drivers/scsi/qla2xxx/qla_target.c |    1 
Daniel Wagner feefdb
 3 files changed, 98 insertions(+), 1 deletion(-)
Daniel Wagner feefdb
Daniel Wagner feefdb
--- a/drivers/scsi/qla2xxx/qla_edif.c
Daniel Wagner feefdb
+++ b/drivers/scsi/qla2xxx/qla_edif.c
Daniel Wagner feefdb
@@ -1593,6 +1593,40 @@ qla_enode_stop(scsi_qla_host_t *vha)
Daniel Wagner feefdb
 	spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
Daniel Wagner feefdb
 }
Daniel Wagner feefdb
 
Daniel Wagner feefdb
+static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid)
Daniel Wagner feefdb
+{
Daniel Wagner feefdb
+	unsigned    long flags;
Daniel Wagner feefdb
+	struct enode    *e, *tmp;
Daniel Wagner feefdb
+	struct purexevent   *purex;
Daniel Wagner feefdb
+	LIST_HEAD(enode_list);
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
Daniel Wagner feefdb
+		ql_dbg(ql_dbg_edif, vha, 0x09102,
Daniel Wagner feefdb
+		       "%s enode not active\n", __func__);
Daniel Wagner feefdb
+		return;
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+	spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
Daniel Wagner feefdb
+	list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) {
Daniel Wagner feefdb
+		purex = &e->u.purexinfo;
Daniel Wagner feefdb
+		if (purex->pur_info.pur_sid.b24 == portid.b24) {
Daniel Wagner feefdb
+			ql_dbg(ql_dbg_edif, vha, 0x911d,
Daniel Wagner feefdb
+			    "%s free ELS sid=%06x. xchg %x, nb=%xh\n",
Daniel Wagner feefdb
+			    __func__, portid.b24,
Daniel Wagner feefdb
+			    purex->pur_info.pur_rx_xchg_address,
Daniel Wagner feefdb
+			    purex->pur_info.pur_bytes_rcvd);
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+			list_del_init(&e->list);
Daniel Wagner feefdb
+			list_add_tail(&e->list, &enode_list);
Daniel Wagner feefdb
+		}
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+	spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	list_for_each_entry_safe(e, tmp, &enode_list, list) {
Daniel Wagner feefdb
+		list_del_init(&e->list);
Daniel Wagner feefdb
+		qla_enode_free(vha, e);
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+}
Daniel Wagner feefdb
+
Daniel Wagner feefdb
 /*
Daniel Wagner feefdb
  *  allocate enode struct and populate buffer
Daniel Wagner feefdb
  *  returns: enode pointer with buffers
Daniel Wagner feefdb
@@ -1792,6 +1826,57 @@ qla_edb_node_free(scsi_qla_host_t *vha,
Daniel Wagner feefdb
 	node->ntype = N_UNDEF;
Daniel Wagner feefdb
 }
Daniel Wagner feefdb
 
Daniel Wagner feefdb
+static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid)
Daniel Wagner feefdb
+{
Daniel Wagner feefdb
+	unsigned long flags;
Daniel Wagner feefdb
+	struct edb_node *e, *tmp;
Daniel Wagner feefdb
+	port_id_t sid;
Daniel Wagner feefdb
+	LIST_HEAD(edb_list);
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	if (vha->e_dbell.db_flags != EDB_ACTIVE) {
Daniel Wagner feefdb
+		/* doorbell list not enabled */
Daniel Wagner feefdb
+		ql_dbg(ql_dbg_edif, vha, 0x09102,
Daniel Wagner feefdb
+		       "%s doorbell not enabled\n", __func__);
Daniel Wagner feefdb
+		return;
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	/* grab lock so list doesn't move */
Daniel Wagner feefdb
+	spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
Daniel Wagner feefdb
+	list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) {
Daniel Wagner feefdb
+		switch (e->ntype) {
Daniel Wagner feefdb
+		case VND_CMD_AUTH_STATE_NEEDED:
Daniel Wagner feefdb
+		case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
Daniel Wagner feefdb
+			sid = e->u.plogi_did;
Daniel Wagner feefdb
+			break;
Daniel Wagner feefdb
+		case VND_CMD_AUTH_STATE_ELS_RCVD:
Daniel Wagner feefdb
+			sid = e->u.els_sid;
Daniel Wagner feefdb
+			break;
Daniel Wagner feefdb
+		case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
Daniel Wagner feefdb
+			/* app wants to see this  */
Daniel Wagner feefdb
+			continue;
Daniel Wagner feefdb
+		default:
Daniel Wagner feefdb
+			ql_log(ql_log_warn, vha, 0x09102,
Daniel Wagner feefdb
+			       "%s unknown node type: %x\n", __func__, e->ntype);
Daniel Wagner feefdb
+			sid.b24 = 0;
Daniel Wagner feefdb
+			break;
Daniel Wagner feefdb
+		}
Daniel Wagner feefdb
+		if (sid.b24 == portid.b24) {
Daniel Wagner feefdb
+			ql_dbg(ql_dbg_edif, vha, 0x910f,
Daniel Wagner feefdb
+			       "%s free doorbell event : node type = %x %p\n",
Daniel Wagner feefdb
+			       __func__, e->ntype, e);
Daniel Wagner feefdb
+			list_del_init(&e->list);
Daniel Wagner feefdb
+			list_add_tail(&e->list, &edb_list);
Daniel Wagner feefdb
+		}
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+	spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	list_for_each_entry_safe(e, tmp, &edb_list, list) {
Daniel Wagner feefdb
+		qla_edb_node_free(vha, e);
Daniel Wagner feefdb
+		list_del_init(&e->list);
Daniel Wagner feefdb
+		kfree(e);
Daniel Wagner feefdb
+	}
Daniel Wagner feefdb
+}
Daniel Wagner feefdb
+
Daniel Wagner feefdb
 /* function called when app is stopping */
Daniel Wagner feefdb
 
Daniel Wagner feefdb
 void
Daniel Wagner feefdb
@@ -2378,7 +2463,7 @@ void qla24xx_auth_els(scsi_qla_host_t *v
Daniel Wagner feefdb
 	ql_dbg(ql_dbg_edif, host, 0x0910c,
Daniel Wagner feefdb
 	    "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
Daniel Wagner feefdb
 	    __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24,
Daniel Wagner feefdb
-	    purex->pur_info.pur_did.b24, p->rx_xchg_addr);
Daniel Wagner feefdb
+	    purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address);
Daniel Wagner feefdb
 
Daniel Wagner feefdb
 	qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL);
Daniel Wagner feefdb
 }
Daniel Wagner feefdb
@@ -3401,3 +3486,12 @@ void qla_edif_sess_down(struct scsi_qla_
Daniel Wagner feefdb
 		qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
Daniel Wagner feefdb
 	}
Daniel Wagner feefdb
 }
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport)
Daniel Wagner feefdb
+{
Daniel Wagner feefdb
+	if (!(fcport->flags & FCF_FCSP_DEVICE))
Daniel Wagner feefdb
+		return;
Daniel Wagner feefdb
+
Daniel Wagner feefdb
+	qla_edb_clear(vha, fcport->d_id);
Daniel Wagner feefdb
+	qla_enode_clear(vha, fcport->d_id);
Daniel Wagner feefdb
+}
Daniel Wagner feefdb
--- a/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner feefdb
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner feefdb
@@ -143,6 +143,8 @@ void qlt_chk_edif_rx_sa_delete_pending(s
Daniel Wagner feefdb
 void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport);
Daniel Wagner feefdb
 int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob);
Daniel Wagner feefdb
 void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess);
Daniel Wagner feefdb
+void qla_edif_clear_appdata(struct scsi_qla_host *vha,
Daniel Wagner feefdb
+			    struct fc_port *fcport);
Daniel Wagner feefdb
 const char *sc_to_str(uint16_t cmd);
Daniel Wagner feefdb
 
Daniel Wagner feefdb
 /*
Daniel Wagner feefdb
--- a/drivers/scsi/qla2xxx/qla_target.c
Daniel Wagner feefdb
+++ b/drivers/scsi/qla2xxx/qla_target.c
Daniel Wagner feefdb
@@ -1012,6 +1012,7 @@ void qlt_free_session_done(struct work_s
Daniel Wagner feefdb
 					"%s bypassing release_all_sadb\n",
Daniel Wagner feefdb
 					__func__);
Daniel Wagner feefdb
 			}
Daniel Wagner feefdb
+			qla_edif_clear_appdata(vha, sess);
Daniel Wagner feefdb
 			qla_edif_sess_down(vha, sess);
Daniel Wagner feefdb
 		}
Daniel Wagner feefdb
 		qla2x00_mark_device_lost(vha, sess, 0);