Commit df648afa authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: edif: Wait for app to ack on sess down

On session deletion, wait for app to acknowledge before moving on. This
allows both app and driver to stay in sync. In addition, this gives a
chance for authentication app to do any type of cleanup before moving on.

Link: https://lore.kernel.org/r/20220607044627.19563-4-njavali@marvell.com


Fixes: dd30706e ("scsi: qla2xxx: edif: Add key update")
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7a7b0b48
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2626,7 +2626,6 @@ typedef struct fc_port {
	struct {
		uint32_t	enable:1;	/* device is edif enabled/req'd */
		uint32_t	app_stop:2;
		uint32_t	app_started:1;
		uint32_t	aes_gmac:1;
		uint32_t	app_sess_online:1;
		uint32_t	tx_sa_set:1;
@@ -2637,6 +2636,7 @@ typedef struct fc_port {
		uint32_t	rx_rekey_cnt;
		uint64_t	tx_bytes;
		uint64_t	rx_bytes;
		uint8_t		sess_down_acked;
		uint8_t		auth_state;
		uint16_t	authok:1;
		uint16_t	rekey_cnt;
+54 −12
Original line number Diff line number Diff line
@@ -257,15 +257,9 @@ qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id)

	f = NULL;
	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
		if ((f->flags & FCF_FCSP_DEVICE)) {
			ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x2058,
			    "Found secure fcport - nn %8phN pn %8phN portid=0x%x, 0x%x.\n",
			    f->node_name, f->port_name,
			    f->d_id.b24, id->b24);
		if (f->d_id.b24 == id->b24)
			return f;
	}
	}
	return NULL;
}

@@ -526,7 +520,6 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

			fcport->edif.app_stop = 0;
			fcport->edif.app_sess_online = 0;
			fcport->edif.app_started = 1;

			if (fcport->scan_state != QLA_FCPORT_FOUND)
				continue;
@@ -628,9 +621,6 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

			fcport->send_els_logo = 1;
			qlt_schedule_sess_for_deletion(fcport);

			/* qla_edif_flush_sa_ctl_lists(fcport); */
			fcport->edif.app_started = 0;
		}
	}

@@ -1047,6 +1037,40 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
	return rval;
}

static int32_t
qla_edif_ack(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
{
	struct fc_port *fcport;
	struct aen_complete_cmd ack;
	struct fc_bsg_reply     *bsg_reply = bsg_job->reply;

	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
			  bsg_job->request_payload.sg_cnt, &ack, sizeof(ack));

	ql_dbg(ql_dbg_edif, vha, 0x70cf,
	       "%s: %06x event_code %x\n",
	       __func__, ack.port_id.b24, ack.event_code);

	fcport = qla2x00_find_fcport_by_pid(vha, &ack.port_id);
	SET_DID_STATUS(bsg_reply->result, DID_OK);

	if (!fcport) {
		ql_dbg(ql_dbg_edif, vha, 0x70cf,
		       "%s: unable to find fcport %06x \n",
		       __func__, ack.port_id.b24);
		return 0;
	}

	switch (ack.event_code) {
	case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
		fcport->edif.sess_down_acked = 1;
		break;
	default:
		break;
	}
	return 0;
}

int32_t
qla_edif_app_mgmt(struct bsg_job *bsg_job)
{
@@ -1109,6 +1133,9 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
	case QL_VND_SC_GET_STATS:
		rval = qla_edif_app_getstats(vha, bsg_job);
		break;
	case QL_VND_SC_AEN_COMPLETE:
		rval = qla_edif_ack(vha, bsg_job);
		break;
	default:
		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",
		    __func__,
@@ -3512,14 +3539,29 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
{
	u16 cnt = 0;

	if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) {
		ql_dbg(ql_dbg_disc, vha, 0xf09c,
			"%s: sess %8phN send port_offline event\n",
			__func__, sess->port_name);
		sess->edif.app_sess_online = 0;
		sess->edif.sess_down_acked = 0;
		qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SESSION_SHUTDOWN,
		    sess->d_id.b24, 0, sess);
		qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);

		while (!READ_ONCE(sess->edif.sess_down_acked) &&
		       !test_bit(VPORT_DELETE, &vha->dpc_flags)) {
			msleep(100);
			cnt++;
			if (cnt > 100)
				break;
		}
		sess->edif.sess_down_acked = 0;
		ql_dbg(ql_dbg_disc, vha, 0xf09c,
		       "%s: sess %8phN port_offline event completed\n",
		       __func__, sess->port_name);
	}
}

+0 −4
Original line number Diff line number Diff line
@@ -1480,7 +1480,6 @@ static int qla_chk_secure_login(scsi_qla_host_t *vha, fc_port_t *fcport,
				ql_dbg(ql_dbg_disc, vha, 0x20ef,
				    "%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n",
				    __func__, __LINE__, fcport->port_name);
				fcport->edif.app_started = 1;
				fcport->edif.app_sess_online = 1;

				qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_NEEDED,
@@ -5273,9 +5272,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
	INIT_LIST_HEAD(&fcport->edif.tx_sa_list);
	INIT_LIST_HEAD(&fcport->edif.rx_sa_list);

	if (vha->e_dbell.db_flags == EDB_ACTIVE)
		fcport->edif.app_started = 1;

	spin_lock_init(&fcport->edif.indx_list_lock);
	INIT_LIST_HEAD(&fcport->edif.edif_indx_list);

+19 −16
Original line number Diff line number Diff line
@@ -981,22 +981,6 @@ void qlt_free_session_done(struct work_struct *work)
		sess->send_els_logo);

	if (!IS_SW_RESV_ADDR(sess->d_id)) {
		if (ha->flags.edif_enabled &&
		    (!own || own->iocb.u.isp24.status_subcode == ELS_PLOGI)) {
			sess->edif.authok = 0;
			if (!ha->flags.host_shutting_down) {
				ql_dbg(ql_dbg_edif, vha, 0x911e,
					"%s wwpn %8phC calling qla2x00_release_all_sadb\n",
					__func__, sess->port_name);
				qla2x00_release_all_sadb(vha, sess);
			} else {
				ql_dbg(ql_dbg_edif, vha, 0x911e,
					"%s bypassing release_all_sadb\n",
					__func__);
			}
			qla_edif_clear_appdata(vha, sess);
			qla_edif_sess_down(vha, sess);
		}
		qla2x00_mark_device_lost(vha, sess, 0);

		if (sess->send_els_logo) {
@@ -1042,6 +1026,25 @@ void qlt_free_session_done(struct work_struct *work)
			sess->nvme_flag |= NVME_FLAG_DELETING;
			qla_nvme_unregister_remote_port(sess);
		}

		if (ha->flags.edif_enabled &&
		    (!own || (own &&
			      own->iocb.u.isp24.status_subcode == ELS_PLOGI))) {
			sess->edif.authok = 0;
			if (!ha->flags.host_shutting_down) {
				ql_dbg(ql_dbg_edif, vha, 0x911e,
				       "%s wwpn %8phC calling qla2x00_release_all_sadb\n",
				       __func__, sess->port_name);
				qla2x00_release_all_sadb(vha, sess);
			} else {
				ql_dbg(ql_dbg_edif, vha, 0x911e,
				       "%s bypassing release_all_sadb\n",
				       __func__);
			}

			qla_edif_clear_appdata(vha, sess);
			qla_edif_sess_down(vha, sess);
		}
	}

	/*