Daniel Wagner 5adcb5
From: Quinn Tran <qutran@marvell.com>
Daniel Wagner 5adcb5
Date: Mon, 6 Jun 2022 21:46:19 -0700
Daniel Wagner 5adcb5
Subject: scsi: qla2xxx: edif: Wait for app to ack on sess down
Denis Kirjanov 718367
Patch-mainline: v5.20-rc1
Daniel Wagner 5adcb5
Git-commit: df648afa39da9c4d3af99c6c03dc3e9c7dfa99b0
Daniel Wagner 5adcb5
References: bsc#1201958
Daniel Wagner 5adcb5
Daniel Wagner 5adcb5
On session deletion, wait for app to acknowledge before moving on. This
Daniel Wagner 5adcb5
allows both app and driver to stay in sync. In addition, this gives a
Daniel Wagner 5adcb5
chance for authentication app to do any type of cleanup before moving on.
Daniel Wagner 5adcb5
Daniel Wagner 5adcb5
Link: https://lore.kernel.org/r/20220607044627.19563-4-njavali@marvell.com
Daniel Wagner 5adcb5
Fixes: dd30706e73b7 ("scsi: qla2xxx: edif: Add key update")
Daniel Wagner 5adcb5
Signed-off-by: Quinn Tran <qutran@marvell.com>
Daniel Wagner 5adcb5
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Daniel Wagner 5adcb5
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner 5adcb5
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner 5adcb5
---
Daniel Wagner 5adcb5
 drivers/scsi/qla2xxx/qla_def.h    |    2 -
Daniel Wagner 5adcb5
 drivers/scsi/qla2xxx/qla_edif.c   |   66 +++++++++++++++++++++++++++++++-------
Daniel Wagner 5adcb5
 drivers/scsi/qla2xxx/qla_init.c   |    4 --
Daniel Wagner 5adcb5
 drivers/scsi/qla2xxx/qla_target.c |   35 ++++++++++----------
Daniel Wagner 5adcb5
 4 files changed, 74 insertions(+), 33 deletions(-)
Daniel Wagner 5adcb5
Daniel Wagner 5adcb5
--- a/drivers/scsi/qla2xxx/qla_def.h
Daniel Wagner 5adcb5
+++ b/drivers/scsi/qla2xxx/qla_def.h
Daniel Wagner 5adcb5
@@ -2627,7 +2627,6 @@ typedef struct fc_port {
Daniel Wagner 5adcb5
 	struct {
Daniel Wagner 5adcb5
 		uint32_t	enable:1;	/* device is edif enabled/req'd */
Daniel Wagner 5adcb5
 		uint32_t	app_stop:2;
Daniel Wagner 5adcb5
-		uint32_t	app_started:1;
Daniel Wagner 5adcb5
 		uint32_t	aes_gmac:1;
Daniel Wagner 5adcb5
 		uint32_t	app_sess_online:1;
Daniel Wagner 5adcb5
 		uint32_t	tx_sa_set:1;
Daniel Wagner 5adcb5
@@ -2638,6 +2637,7 @@ typedef struct fc_port {
Daniel Wagner 5adcb5
 		uint32_t	rx_rekey_cnt;
Daniel Wagner 5adcb5
 		uint64_t	tx_bytes;
Daniel Wagner 5adcb5
 		uint64_t	rx_bytes;
Daniel Wagner 5adcb5
+		uint8_t		sess_down_acked;
Daniel Wagner 5adcb5
 		uint8_t		auth_state;
Daniel Wagner 5adcb5
 		uint16_t	authok:1;
Daniel Wagner 5adcb5
 		uint16_t	rekey_cnt;
Daniel Wagner 5adcb5
--- a/drivers/scsi/qla2xxx/qla_edif.c
Daniel Wagner 5adcb5
+++ b/drivers/scsi/qla2xxx/qla_edif.c
Daniel Wagner 5adcb5
@@ -257,14 +257,8 @@ qla2x00_find_fcport_by_pid(scsi_qla_host
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 	f = NULL;
Daniel Wagner 5adcb5
 	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
Daniel Wagner 5adcb5
-		if ((f->flags & FCF_FCSP_DEVICE)) {
Daniel Wagner 5adcb5
-			ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x2058,
Daniel Wagner 5adcb5
-			    "Found secure fcport - nn %8phN pn %8phN portid=0x%x, 0x%x.\n",
Daniel Wagner 5adcb5
-			    f->node_name, f->port_name,
Daniel Wagner 5adcb5
-			    f->d_id.b24, id->b24);
Daniel Wagner 5adcb5
-			if (f->d_id.b24 == id->b24)
Daniel Wagner 5adcb5
-				return f;
Daniel Wagner 5adcb5
-		}
Daniel Wagner 5adcb5
+		if (f->d_id.b24 == id->b24)
Daniel Wagner 5adcb5
+			return f;
Daniel Wagner 5adcb5
 	}
Daniel Wagner 5adcb5
 	return NULL;
Daniel Wagner 5adcb5
 }
Daniel Wagner 5adcb5
@@ -526,7 +520,6 @@ qla_edif_app_start(scsi_qla_host_t *vha,
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 			fcport->edif.app_stop = 0;
Daniel Wagner 5adcb5
 			fcport->edif.app_sess_online = 0;
Daniel Wagner 5adcb5
-			fcport->edif.app_started = 1;
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 			if (fcport->scan_state != QLA_FCPORT_FOUND)
Daniel Wagner 5adcb5
 				continue;
Daniel Wagner 5adcb5
@@ -628,9 +621,6 @@ qla_edif_app_stop(scsi_qla_host_t *vha,
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 			fcport->send_els_logo = 1;
Daniel Wagner 5adcb5
 			qlt_schedule_sess_for_deletion(fcport);
Daniel Wagner 5adcb5
-
Daniel Wagner 5adcb5
-			/* qla_edif_flush_sa_ctl_lists(fcport); */
Daniel Wagner 5adcb5
-			fcport->edif.app_started = 0;
Daniel Wagner 5adcb5
 		}
Daniel Wagner 5adcb5
 	}
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
@@ -1047,6 +1037,40 @@ qla_edif_app_getstats(scsi_qla_host_t *v
Daniel Wagner 5adcb5
 	return rval;
Daniel Wagner 5adcb5
 }
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
+static int32_t
Daniel Wagner 5adcb5
+qla_edif_ack(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
Daniel Wagner 5adcb5
+{
Daniel Wagner 5adcb5
+	struct fc_port *fcport;
Daniel Wagner 5adcb5
+	struct aen_complete_cmd ack;
Daniel Wagner 5adcb5
+	struct fc_bsg_reply     *bsg_reply = bsg_job->reply;
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
Daniel Wagner 5adcb5
+			  bsg_job->request_payload.sg_cnt, &ack, sizeof(ack));
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+	ql_dbg(ql_dbg_edif, vha, 0x70cf,
Daniel Wagner 5adcb5
+	       "%s: %06x event_code %x\n",
Daniel Wagner 5adcb5
+	       __func__, ack.port_id.b24, ack.event_code);
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+	fcport = qla2x00_find_fcport_by_pid(vha, &ack.port_id);
Daniel Wagner 5adcb5
+	SET_DID_STATUS(bsg_reply->result, DID_OK);
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+	if (!fcport) {
Daniel Wagner 5adcb5
+		ql_dbg(ql_dbg_edif, vha, 0x70cf,
Daniel Wagner 5adcb5
+		       "%s: unable to find fcport %06x \n",
Daniel Wagner 5adcb5
+		       __func__, ack.port_id.b24);
Daniel Wagner 5adcb5
+		return 0;
Daniel Wagner 5adcb5
+	}
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+	switch (ack.event_code) {
Daniel Wagner 5adcb5
+	case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
Daniel Wagner 5adcb5
+		fcport->edif.sess_down_acked = 1;
Daniel Wagner 5adcb5
+		break;
Daniel Wagner 5adcb5
+	default:
Daniel Wagner 5adcb5
+		break;
Daniel Wagner 5adcb5
+	}
Daniel Wagner 5adcb5
+	return 0;
Daniel Wagner 5adcb5
+}
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
 int32_t
Daniel Wagner 5adcb5
 qla_edif_app_mgmt(struct bsg_job *bsg_job)
Daniel Wagner 5adcb5
 {
Daniel Wagner 5adcb5
@@ -1109,6 +1133,9 @@ qla_edif_app_mgmt(struct bsg_job *bsg_jo
Daniel Wagner 5adcb5
 	case QL_VND_SC_GET_STATS:
Daniel Wagner 5adcb5
 		rval = qla_edif_app_getstats(vha, bsg_job);
Daniel Wagner 5adcb5
 		break;
Daniel Wagner 5adcb5
+	case QL_VND_SC_AEN_COMPLETE:
Daniel Wagner 5adcb5
+		rval = qla_edif_ack(vha, bsg_job);
Daniel Wagner 5adcb5
+		break;
Daniel Wagner 5adcb5
 	default:
Daniel Wagner 5adcb5
 		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",
Daniel Wagner 5adcb5
 		    __func__,
Daniel Wagner 5adcb5
@@ -3512,14 +3539,29 @@ int qla_edif_process_els(scsi_qla_host_t
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
Daniel Wagner 5adcb5
 {
Daniel Wagner 5adcb5
+	u16 cnt = 0;
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
 	if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) {
Daniel Wagner 5adcb5
 		ql_dbg(ql_dbg_disc, vha, 0xf09c,
Daniel Wagner 5adcb5
 			"%s: sess %8phN send port_offline event\n",
Daniel Wagner 5adcb5
 			__func__, sess->port_name);
Daniel Wagner 5adcb5
 		sess->edif.app_sess_online = 0;
Daniel Wagner 5adcb5
+		sess->edif.sess_down_acked = 0;
Daniel Wagner 5adcb5
 		qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SESSION_SHUTDOWN,
Daniel Wagner 5adcb5
 		    sess->d_id.b24, 0, sess);
Daniel Wagner 5adcb5
 		qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+		while (!READ_ONCE(sess->edif.sess_down_acked) &&
Daniel Wagner 5adcb5
+		       !test_bit(VPORT_DELETE, &vha->dpc_flags)) {
Daniel Wagner 5adcb5
+			msleep(100);
Daniel Wagner 5adcb5
+			cnt++;
Daniel Wagner 5adcb5
+			if (cnt > 100)
Daniel Wagner 5adcb5
+				break;
Daniel Wagner 5adcb5
+		}
Daniel Wagner 5adcb5
+		sess->edif.sess_down_acked = 0;
Daniel Wagner 5adcb5
+		ql_dbg(ql_dbg_disc, vha, 0xf09c,
Daniel Wagner 5adcb5
+		       "%s: sess %8phN port_offline event completed\n",
Daniel Wagner 5adcb5
+		       __func__, sess->port_name);
Daniel Wagner 5adcb5
 	}
Daniel Wagner 5adcb5
 }
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
--- a/drivers/scsi/qla2xxx/qla_init.c
Daniel Wagner 5adcb5
+++ b/drivers/scsi/qla2xxx/qla_init.c
Daniel Wagner 5adcb5
@@ -1483,7 +1483,6 @@ static int	qla_chk_secure_login(scsi_qla
Daniel Wagner 5adcb5
 				ql_dbg(ql_dbg_disc, vha, 0x20ef,
Daniel Wagner 5adcb5
 				    "%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n",
Daniel Wagner 5adcb5
 				    __func__, __LINE__, fcport->port_name);
Daniel Wagner 5adcb5
-				fcport->edif.app_started = 1;
Daniel Wagner 5adcb5
 				fcport->edif.app_sess_online = 1;
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 				qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_NEEDED,
Daniel Wagner 5adcb5
@@ -5274,9 +5273,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vh
Daniel Wagner 5adcb5
 	INIT_LIST_HEAD(&fcport->edif.tx_sa_list);
Daniel Wagner 5adcb5
 	INIT_LIST_HEAD(&fcport->edif.rx_sa_list);
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
-	if (vha->e_dbell.db_flags == EDB_ACTIVE)
Daniel Wagner 5adcb5
-		fcport->edif.app_started = 1;
Daniel Wagner 5adcb5
-
Daniel Wagner 5adcb5
 	spin_lock_init(&fcport->edif.indx_list_lock);
Daniel Wagner 5adcb5
 	INIT_LIST_HEAD(&fcport->edif.edif_indx_list);
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
--- a/drivers/scsi/qla2xxx/qla_target.c
Daniel Wagner 5adcb5
+++ b/drivers/scsi/qla2xxx/qla_target.c
Daniel Wagner 5adcb5
@@ -990,22 +990,6 @@ void qlt_free_session_done(struct work_s
Daniel Wagner 5adcb5
 		sess->send_els_logo);
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 	if (!IS_SW_RESV_ADDR(sess->d_id)) {
Daniel Wagner 5adcb5
-		if (ha->flags.edif_enabled &&
Daniel Wagner 5adcb5
-		    (!own || own->iocb.u.isp24.status_subcode == ELS_PLOGI)) {
Daniel Wagner 5adcb5
-			sess->edif.authok = 0;
Daniel Wagner 5adcb5
-			if (!ha->flags.host_shutting_down) {
Daniel Wagner 5adcb5
-				ql_dbg(ql_dbg_edif, vha, 0x911e,
Daniel Wagner 5adcb5
-					"%s wwpn %8phC calling qla2x00_release_all_sadb\n",
Daniel Wagner 5adcb5
-					__func__, sess->port_name);
Daniel Wagner 5adcb5
-				qla2x00_release_all_sadb(vha, sess);
Daniel Wagner 5adcb5
-			} else {
Daniel Wagner 5adcb5
-				ql_dbg(ql_dbg_edif, vha, 0x911e,
Daniel Wagner 5adcb5
-					"%s bypassing release_all_sadb\n",
Daniel Wagner 5adcb5
-					__func__);
Daniel Wagner 5adcb5
-			}
Daniel Wagner 5adcb5
-			qla_edif_clear_appdata(vha, sess);
Daniel Wagner 5adcb5
-			qla_edif_sess_down(vha, sess);
Daniel Wagner 5adcb5
-		}
Daniel Wagner 5adcb5
 		qla2x00_mark_device_lost(vha, sess, 0);
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 		if (sess->send_els_logo) {
Daniel Wagner 5adcb5
@@ -1051,6 +1035,25 @@ void qlt_free_session_done(struct work_s
Daniel Wagner 5adcb5
 			sess->nvme_flag |= NVME_FLAG_DELETING;
Daniel Wagner 5adcb5
 			qla_nvme_unregister_remote_port(sess);
Daniel Wagner 5adcb5
 		}
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+		if (ha->flags.edif_enabled &&
Daniel Wagner 5adcb5
+		    (!own || (own &&
Daniel Wagner 5adcb5
+			      own->iocb.u.isp24.status_subcode == ELS_PLOGI))) {
Daniel Wagner 5adcb5
+			sess->edif.authok = 0;
Daniel Wagner 5adcb5
+			if (!ha->flags.host_shutting_down) {
Daniel Wagner 5adcb5
+				ql_dbg(ql_dbg_edif, vha, 0x911e,
Daniel Wagner 5adcb5
+				       "%s wwpn %8phC calling qla2x00_release_all_sadb\n",
Daniel Wagner 5adcb5
+				       __func__, sess->port_name);
Daniel Wagner 5adcb5
+				qla2x00_release_all_sadb(vha, sess);
Daniel Wagner 5adcb5
+			} else {
Daniel Wagner 5adcb5
+				ql_dbg(ql_dbg_edif, vha, 0x911e,
Daniel Wagner 5adcb5
+				       "%s bypassing release_all_sadb\n",
Daniel Wagner 5adcb5
+				       __func__);
Daniel Wagner 5adcb5
+			}
Daniel Wagner 5adcb5
+
Daniel Wagner 5adcb5
+			qla_edif_clear_appdata(vha, sess);
Daniel Wagner 5adcb5
+			qla_edif_sess_down(vha, sess);
Daniel Wagner 5adcb5
+		}
Daniel Wagner 5adcb5
 	}
Daniel Wagner 5adcb5
 
Daniel Wagner 5adcb5
 	/*