diff mbox series

[v2,01/10] qla2xxx: Add start + stop bsg's

Message ID 20210531070545.32072-2-njavali@marvell.com
State Superseded
Headers show
Series [v2,01/10] qla2xxx: Add start + stop bsg's | expand

Commit Message

Nilesh Javali May 31, 2021, 7:05 a.m. UTC
From: Quinn Tran <qutran@marvell.com>

Latest FC adapter from Marvell has the ability to encrypt
data in flight (EDIF) feature. This feature require an
application (ex: ipsec, etc) to act as an authenticator.

This patch add 2 new BSG calls:
QL_VND_SC_APP_START: application will announce its present
to driver with this call. Driver will restart all
connections to see if remote device support security or not.

QL_VND_SC_APP_STOP: application announce it's in the process
of exiting. Driver will restart all connections to revert
back to non-secure. Provided the remote device is willing
to allow a non-secure connection.

Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com>
Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com>
Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/Makefile       |   3 +-
 drivers/scsi/qla2xxx/qla_bsg.c      |   3 +
 drivers/scsi/qla2xxx/qla_bsg.h      |   3 +
 drivers/scsi/qla2xxx/qla_dbg.h      |   1 +
 drivers/scsi/qla2xxx/qla_def.h      |  70 ++++--
 drivers/scsi/qla2xxx/qla_edif.c     | 349 ++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_edif.h     |  32 +++
 drivers/scsi/qla2xxx/qla_edif_bsg.h | 225 ++++++++++++++++++
 drivers/scsi/qla2xxx/qla_gbl.h      |   4 +
 9 files changed, 666 insertions(+), 24 deletions(-)
 create mode 100644 drivers/scsi/qla2xxx/qla_edif.c
 create mode 100644 drivers/scsi/qla2xxx/qla_edif.h
 create mode 100644 drivers/scsi/qla2xxx/qla_edif_bsg.h

Comments

Hannes Reinecke June 1, 2021, 12:33 p.m. UTC | #1
On 5/31/21 9:05 AM, Nilesh Javali wrote:
> From: Quinn Tran <qutran@marvell.com>

> 

> Latest FC adapter from Marvell has the ability to encrypt

> data in flight (EDIF) feature. This feature require an

> application (ex: ipsec, etc) to act as an authenticator.

> 

> This patch add 2 new BSG calls:

> QL_VND_SC_APP_START: application will announce its present

> to driver with this call. Driver will restart all

> connections to see if remote device support security or not.

> 

> QL_VND_SC_APP_STOP: application announce it's in the process

> of exiting. Driver will restart all connections to revert

> back to non-secure. Provided the remote device is willing

> to allow a non-secure connection.

> 

> Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com>

> Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com>

> Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com>

> Signed-off-by: Quinn Tran <qutran@marvell.com>

> Signed-off-by: Nilesh Javali <njavali@marvell.com>

> ---

>  drivers/scsi/qla2xxx/Makefile       |   3 +-

>  drivers/scsi/qla2xxx/qla_bsg.c      |   3 +

>  drivers/scsi/qla2xxx/qla_bsg.h      |   3 +

>  drivers/scsi/qla2xxx/qla_dbg.h      |   1 +

>  drivers/scsi/qla2xxx/qla_def.h      |  70 ++++--

>  drivers/scsi/qla2xxx/qla_edif.c     | 349 ++++++++++++++++++++++++++++

>  drivers/scsi/qla2xxx/qla_edif.h     |  32 +++

>  drivers/scsi/qla2xxx/qla_edif_bsg.h | 225 ++++++++++++++++++

>  drivers/scsi/qla2xxx/qla_gbl.h      |   4 +

>  9 files changed, 666 insertions(+), 24 deletions(-)

>  create mode 100644 drivers/scsi/qla2xxx/qla_edif.c

>  create mode 100644 drivers/scsi/qla2xxx/qla_edif.h

>  create mode 100644 drivers/scsi/qla2xxx/qla_edif_bsg.h

> 

> diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile

> index 17d5bc1cc56b..cbc1303e761e 100644

> --- a/drivers/scsi/qla2xxx/Makefile

> +++ b/drivers/scsi/qla2xxx/Makefile

> @@ -1,7 +1,8 @@

>  # SPDX-License-Identifier: GPL-2.0

>  qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \

>  		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \

> -		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o

> +		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o \

> +		qla_edif.o

>  

>  obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o

>  obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o

> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c

> index d42b2ad84049..e6cccbcc7a1b 100644

> --- a/drivers/scsi/qla2xxx/qla_bsg.c

> +++ b/drivers/scsi/qla2xxx/qla_bsg.c

> @@ -2840,6 +2840,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)

>  	case QL_VND_DPORT_DIAGNOSTICS:

>  		return qla2x00_do_dport_diagnostics(bsg_job);

>  

> +	case QL_VND_EDIF_MGMT:

> +		return qla_edif_app_mgmt(bsg_job);

> +

>  	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:

>  		return qla2x00_get_flash_image_status(bsg_job);

>  

> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h

> index 0274e99e4a12..dd793cf8bc1e 100644

> --- a/drivers/scsi/qla2xxx/qla_bsg.h

> +++ b/drivers/scsi/qla2xxx/qla_bsg.h

> @@ -31,6 +31,7 @@

>  #define QL_VND_DPORT_DIAGNOSTICS	0x19

>  #define QL_VND_GET_PRIV_STATS_EX	0x1A

>  #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E

> +#define QL_VND_EDIF_MGMT                0X1F

>  #define QL_VND_MANAGE_HOST_STATS	0x23

>  #define QL_VND_GET_HOST_STATS		0x24

>  #define QL_VND_GET_TGT_STATS		0x25

> @@ -294,4 +295,6 @@ struct qla_active_regions {

>  	uint8_t reserved[32];

>  } __packed;

>  

> +#include "qla_edif_bsg.h"

> +

>  #endif

> diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h

> index 9eb708e5e22e..f1f6c740bdcd 100644

> --- a/drivers/scsi/qla2xxx/qla_dbg.h

> +++ b/drivers/scsi/qla2xxx/qla_dbg.h

> @@ -367,6 +367,7 @@ ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);

>  #define ql_dbg_tgt_mgt	0x00002000 /* Target mode management */

>  #define ql_dbg_tgt_tmr	0x00001000 /* Target mode task management */

>  #define ql_dbg_tgt_dif  0x00000800 /* Target mode dif */

> +#define ql_dbg_edif	0x00000400 /* edif and purex debug */

>  

>  extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,

>  	uint32_t, void **);

> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h

> index def4d99f80e9..ac3b9b39d741 100644

> --- a/drivers/scsi/qla2xxx/qla_def.h

> +++ b/drivers/scsi/qla2xxx/qla_def.h

> @@ -49,6 +49,28 @@ typedef struct {

>  	uint8_t domain;

>  } le_id_t;

>  

> +/*

> + * 24 bit port ID type definition.

> + */

> +typedef union {

> +	uint32_t b24 : 24;

> +	struct {

> +#ifdef __BIG_ENDIAN

> +		uint8_t domain;

> +		uint8_t area;

> +		uint8_t al_pa;

> +#elif defined(__LITTLE_ENDIAN)

> +		uint8_t al_pa;

> +		uint8_t area;

> +		uint8_t domain;

> +#else

> +#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"

> +#endif

> +		uint8_t rsvd_1;

> +	} b;

> +} port_id_t;

> +#define INVALID_PORT_ID	0xFFFFFF

> +

>  #include "qla_bsg.h"

>  #include "qla_dsd.h"

>  #include "qla_nx.h"

> @@ -345,6 +367,8 @@ struct name_list_extended {

>  #define FW_MAX_EXCHANGES_CNT (32 * 1024)

>  #define REDUCE_EXCHANGES_CNT  (8 * 1024)

>  

> +#define SET_DID_STATUS(stat_var, status) (stat_var = status << 16)

> +

>  struct req_que;

>  struct qla_tgt_sess;

>  

> @@ -373,29 +397,6 @@ struct srb_cmd {

>  

>  /* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */

>  #define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)

> -

> -/*

> - * 24 bit port ID type definition.

> - */

> -typedef union {

> -	uint32_t b24 : 24;

> -

> -	struct {

> -#ifdef __BIG_ENDIAN

> -		uint8_t domain;

> -		uint8_t area;

> -		uint8_t al_pa;

> -#elif defined(__LITTLE_ENDIAN)

> -		uint8_t al_pa;

> -		uint8_t area;

> -		uint8_t domain;

> -#else

> -#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"

> -#endif

> -		uint8_t rsvd_1;

> -	} b;

> -} port_id_t;

> -#define INVALID_PORT_ID	0xFFFFFF

>  #define ISP_REG16_DISCONNECT 0xFFFF

>  

>  static inline le_id_t be_id_to_le(be_id_t id)

> @@ -2424,6 +2425,7 @@ enum discovery_state {

>  	DSC_LOGIN_COMPLETE,

>  	DSC_ADISC,

>  	DSC_DELETE_PEND,

> +	DSC_LOGIN_AUTH_PEND,

>  };

>  

>  enum login_state {	/* FW control Target side */

> @@ -2563,6 +2565,22 @@ typedef struct fc_port {

>  	u64 tgt_short_link_down_cnt;

>  	u64 tgt_link_down_time;

>  	u64 dev_loss_tmo;

> +	/*

> +	 * EDIF parameters for encryption.

> +	 */

> +	struct {

> +		uint16_t	enable:1;	// device is edif enabled/req'd

> +		uint16_t	app_stop:2;

> +		uint16_t	app_started:1;

> +		uint16_t	secured_login:1;

> +		uint16_t	app_sess_online:1;


How very uncommon; defining a uint16_t bitfield.
Why not make it uint32_t?
But adding it to the start of the structure you also induced a possible
padding here; the compiler will most likely pad it to 64 bit here.

> +		uint32_t	tx_rekey_cnt;

> +		uint32_t	rx_rekey_cnt;

> +		// delayed rx delete data structure list

> +		uint64_t	tx_bytes;

> +		uint64_t	rx_bytes;

> +		uint8_t		non_secured_login;


Isn't this just a bit? Can't it be merged with the flags above?

> +	} edif;

>  } fc_port_t;

>  

>  enum {

> @@ -2616,6 +2634,7 @@ static const char * const port_dstate_str[] = {

>  #define FCF_ASYNC_SENT		BIT_3

>  #define FCF_CONF_COMP_SUPPORTED BIT_4

>  #define FCF_ASYNC_ACTIVE	BIT_5

> +#define FCF_FCSP_DEVICE		BIT_6

>  

>  /* No loop ID flag. */

>  #define FC_NO_LOOP_ID		0x1000

> @@ -3933,6 +3952,7 @@ struct qla_hw_data {

>  		uint32_t	scm_supported_f:1;

>  				/* Enabled in Driver */

>  		uint32_t	scm_enabled:1;

> +		uint32_t	edif_enabled:1;

>  		uint32_t	max_req_queue_warned:1;

>  		uint32_t	plogi_template_valid:1;

>  		uint32_t	port_isolated:1;

> @@ -4656,6 +4676,8 @@ struct purex_item {

>  	} iocb;

>  };

>  

> +#include "qla_edif.h"

> +

>  #define SCM_FLAG_RDF_REJECT		0x00

>  #define SCM_FLAG_RDF_COMPLETED		0x01

>  

> @@ -4884,6 +4906,8 @@ typedef struct scsi_qla_host {

>  	u64 reset_cmd_err_cnt;

>  	u64 link_down_time;

>  	u64 short_link_down_cnt;

> +	struct edif_dbell e_dbell;

> +	struct pur_core pur_cinfo;

>  } scsi_qla_host_t;

>  

>  struct qla27xx_image_status {

> diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c

> new file mode 100644

> index 000000000000..38d79ef2e700

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif.c

> @@ -0,0 +1,349 @@

> +// SPDX-License-Identifier: GPL-2.0-only

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (c)  2021     Marvell

> + */

> +#include "qla_def.h"

> +//#include "qla_edif.h"

> +


Add a commented out header in a new file?
Why?

> +#include <linux/kthread.h>

> +#include <linux/vmalloc.h>

> +#include <linux/delay.h>

> +#include <scsi/scsi_tcq.h>

> +

> +static void

> +qla_edif_sa_ctl_init(scsi_qla_host_t *vha, struct fc_port  *fcport)

> +{

> +	ql_dbg(ql_dbg_edif, vha, 0x2058,

> +		"Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%02x%02x%02x.\n",

> +		fcport->node_name, fcport->port_name,

> +		fcport->d_id.b.domain, fcport->d_id.b.area,

> +		fcport->d_id.b.al_pa);

> +

> +	fcport->edif.tx_rekey_cnt = 0;

> +	fcport->edif.rx_rekey_cnt = 0;

> +

> +	fcport->edif.tx_bytes = 0;

> +	fcport->edif.rx_bytes = 0;

> +}

> +

> +static int

> +qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)

> +{

> +	int rval = 0;	/* assume failure */

> +

> +	/* check that the app is allow/known to the driver */

> +

> +	/* TODO: edif: implement key/cert check for permitted apps... */

> +

> +	if (appid.app_vid == 0x73730001) {


Huh? A hard-coded value?
Please don't. Use a #define here to make it clear what this value is
supposed to mean.

> +		rval = 1;

> +		ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d, "%s app id ok\n", __func__);

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",

> +		    __func__, appid.app_vid);

> +	}

> +

> +	return rval;

> +}


And you can kill 'rval' by just call 'return' in the if branches.
Plus this function should probably be a 'bool' function ...

> +

> +/*

> + * reset the session to auth wait.

> + */

> +static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state,

> +		int waitonly)

> +{

> +	int cnt, max_cnt = 200;

> +	bool traced = false;

> +

> +	fcport->keep_nport_handle = 1;

> +

> +	if (!waitonly) {

> +		qla2x00_set_fcport_disc_state(fcport, state);

> +		qlt_schedule_sess_for_deletion(fcport);

> +	} else {

> +		qla2x00_set_fcport_disc_state(fcport, state);

> +	}

> +

> +	ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +		"%s: waiting for session, max_cnt=%u\n",

> +		__func__, max_cnt);

> +

> +	cnt = 0;

> +

> +	if (waitonly) {

> +		/* Marker wait min 10 msecs. */

> +		msleep(50);

> +		cnt += 50;

> +	}

> +	while (1) {

> +		if (!traced) {

> +			ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +			"%s: session sleep.\n",

> +			__func__);

> +			traced = true;

> +		}

> +		msleep(20);

> +		cnt++;

> +		if (waitonly && (fcport->disc_state == state ||

> +			fcport->disc_state == DSC_LOGIN_COMPLETE))

> +			break;

> +		if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)

> +			break;

> +		if (cnt > max_cnt)

> +			break;

> +	}

> +

> +	if (!waitonly) {

> +		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +	"%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",

> +		    __func__, fcport->port_name, fcport->loop_id,

> +		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);

> +	} else {

> +		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +	"%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",

> +		    __func__, fcport->port_name, fcport->loop_id,

> +		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);


Indentation.

> +	}

> +}

> +

> +/*

> + * event that the app has started. Clear and start doorbell

> + */

> +static int

> +qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

> +{

> +	int32_t			rval = 0;

> +	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;

> +	struct app_start	appstart;

> +	struct app_start_reply	appreply;

> +	struct fc_port  *fcport, *tf;

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__);

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appstart,

> +	    sizeof(struct app_start));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n",

> +	     __func__, appstart.app_info.app_vid, appstart.app_start_flags);

> +

> +	if (vha->e_dbell.db_flags != EDB_ACTIVE) {

> +		/* mark doorbell as active since an app is now present */

> +		vha->e_dbell.db_flags = EDB_ACTIVE;

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n",

> +		     __func__);

> +	}

> +

> +	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {

> +		if ((fcport->flags & FCF_FCSP_DEVICE)) {

> +			ql_dbg(ql_dbg_edif, vha, 0xf084,

> +			    "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n",

> +			    __func__, fcport, fcport->port_name,

> +			    fcport->loop_id, fcport->d_id.b24,

> +			    fcport->logout_on_delete);

> +

> +			if (atomic_read(&vha->loop_state) == LOOP_DOWN)

> +				break;

> +

> +			if (!fcport->edif.secured_login)

> +				continue;

> +

> +			fcport->edif.app_started = 1;

> +			if (fcport->edif.app_stop ||

> +			    (fcport->disc_state != DSC_LOGIN_COMPLETE &&

> +			     fcport->disc_state != DSC_LOGIN_PEND &&

> +			     fcport->disc_state != DSC_DELETED)) {

> +				/* no activity */

> +				fcport->edif.app_stop = 0;

> +

> +				ql_dbg(ql_dbg_edif, vha, 0x911e,

> +				    "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",

> +				    __func__, fcport->port_name);

> +				fcport->edif.app_sess_online = 1;

> +				qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0);

> +			}

> +			qla_edif_sa_ctl_init(vha, fcport);

> +		}

> +	}

> +

> +	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {

> +		/* mark as active since an app is now present */

> +		vha->pur_cinfo.enode_flags = ENODE_ACTIVE;

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911f, "%s enode already active\n",

> +		     __func__);

> +	}

> +

> +	appreply.host_support_edif = vha->hw->flags.edif_enabled;

> +	appreply.edif_enode_active = vha->pur_cinfo.enode_flags;

> +	appreply.edif_edb_active = vha->e_dbell.db_flags;

> +

> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply) +

> +	    sizeof(struct app_start_reply);

> +

> +	SET_DID_STATUS(bsg_reply->result, DID_OK);

> +

> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,

> +	    bsg_job->reply_payload.sg_cnt, &appreply,

> +	    sizeof(struct app_start_reply));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d,

> +	    "%s app start completed with 0x%x\n",

> +	    __func__, rval);

> +

> +	return rval;

> +}

> +

> +/*

> + * notification from the app that the app is stopping.

> + * actions:	stop and doorbell

> + *		stop and clear enode

> + */

> +static int

> +qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

> +{

> +	int32_t                 rval = 0;

> +	struct app_stop         appstop;

> +	struct fc_bsg_reply     *bsg_reply = bsg_job->reply;

> +	struct fc_port  *fcport, *tf;

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appstop,

> +	    sizeof(struct app_stop));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s Stopping APP: app_vid=%x\n",

> +	    __func__, appstop.app_info.app_vid);

> +

> +	/* Call db stop and enode stop functions */

> +

> +	/* if we leave this running short waits are operational < 16 secs */

> +	qla_enode_stop(vha);        /* stop enode */

> +	qla_edb_stop(vha);          /* stop db */

> +

> +	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {

> +		if (fcport->edif.non_secured_login)

> +			continue;

> +

> +		if (fcport->flags & FCF_FCSP_DEVICE) {

> +			ql_dbg(ql_dbg_edif, vha, 0xf084,

> +	"%s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d\n",


Indentation

> +			    __func__, fcport,

> +			    fcport->port_name, fcport->loop_id,

> +			    fcport->d_id.b24, fcport->logout_on_delete,

> +			    fcport->keep_nport_handle, fcport->send_els_logo);

> +

> +			if (atomic_read(&vha->loop_state) == LOOP_DOWN)

> +				break;

> +

> +			fcport->edif.app_stop = 1;

> +			ql_dbg(ql_dbg_edif, vha, 0x911e,

> +				"%s wwpn %8phC calling qla_edif_reset_auth_wait\n",

> +				__func__, fcport->port_name);

> +

> +			fcport->send_els_logo = 1;

> +			qlt_schedule_sess_for_deletion(fcport);

> +

> +			/* qla_edif_flush_sa_ctl_lists(fcport); */

> +			fcport->edif.app_started = 0;

> +		}

> +	}

> +

> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +	SET_DID_STATUS(bsg_reply->result, DID_OK);

> +

> +	/* no return interface to app - it assumes we cleaned up ok */

> +

> +	return rval;

> +}

> +

> +int32_t

> +qla_edif_app_mgmt(struct bsg_job *bsg_job)

> +{

> +	struct fc_bsg_request	*bsg_request = bsg_job->request;

> +	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;

> +	struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);

> +	scsi_qla_host_t		*vha = shost_priv(host);

> +	struct app_id		appcheck;

> +	bool done = true;

> +	int32_t         rval = 0;

> +	uint32_t	vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s vnd subcmd=%x\n",

> +	    __func__, vnd_sc);

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appcheck,

> +	    sizeof(struct app_id));

> +

> +	if (!vha->hw->flags.edif_enabled ||

> +		test_bit(VPORT_DELETE, &vha->dpc_flags)) {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d,

> +		    "%s edif not enabled or vp delete. bsg ptr done %p\n",

> +		    __func__, bsg_job);

> +

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		goto done;

> +	}

> +

> +	if (qla_edif_app_check(vha, appcheck) == 0) {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d,

> +		    "%s app checked failed.\n",

> +		    __func__);

> +

> +		bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		goto done;

> +	}

> +

> +	switch (vnd_sc) {

> +	case QL_VND_SC_APP_START:

> +		rval = qla_edif_app_start(vha, bsg_job);

> +		break;

> +	case QL_VND_SC_APP_STOP:

> +		rval = qla_edif_app_stop(vha, bsg_job);

> +		break;

> +	default:

> +		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",

> +		    __func__,

> +		    bsg_request->rqst_data.h_vendor.vendor_cmd[1]);

> +		rval = EXT_STATUS_INVALID_PARAM;

> +		bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		break;

> +	}

> +

> +done:

> +	if (done) {

> +		ql_dbg(ql_dbg_user, vha, 0x7009,

> +		    "%s: %d  bsg ptr done %p\n", __func__, __LINE__, bsg_job);

> +		bsg_job_done(bsg_job, bsg_reply->result,

> +		    bsg_reply->reply_payload_rcv_len);

> +	}

> +

> +	return rval;

> +}

> +void

> +qla_enode_stop(scsi_qla_host_t *vha)

> +{

> +	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {

> +		/* doorbell list not enabled */

> +		ql_dbg(ql_dbg_edif, vha, 0x09102,

> +		    "%s enode not active\n", __func__);

> +		return;

> +	}

> +}

> +

> +/* function called when app is stopping */

> +

> +void

> +qla_edb_stop(scsi_qla_host_t *vha)

> +{

> +	if (vha->e_dbell.db_flags != EDB_ACTIVE) {

> +		/* doorbell list not enabled */

> +		ql_dbg(ql_dbg_edif, vha, 0x09102,

> +		    "%s doorbell not enabled\n", __func__);

> +		return;

> +	}

> +}

> diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h

> new file mode 100644

> index 000000000000..dc0a08570a0b

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif.h

> @@ -0,0 +1,32 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (c)  2021    Marvell

> + */

> +#ifndef __QLA_EDIF_H

> +#define __QLA_EDIF_H

> +

> +struct qla_scsi_host;

> +

> +enum enode_flags_t {

> +	ENODE_ACTIVE = 0x1,	// means that app has started

> +};

> +

> +struct pur_core {

> +	enum enode_flags_t	enode_flags;

> +	spinlock_t		pur_lock;       /* protects list */

> +	struct  list_head	head;

> +};

> +

> +enum db_flags_t {

> +	EDB_ACTIVE = 0x1,

> +};

> +

> +struct edif_dbell {

> +	enum db_flags_t		db_flags;

> +	spinlock_t		db_lock;	/* protects list */

> +	struct  list_head	head;

> +	struct	completion	dbell;		/* doorbell ring */

> +};

> +

> +#endif	/* __QLA_EDIF_H */

> diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h

> new file mode 100644

> index 000000000000..9c05b78253e7

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h

> @@ -0,0 +1,225 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (C)  2018-	    Marvell

> + *

> + */

> +#ifndef __QLA_EDIF_BSG_H

> +#define __QLA_EDIF_BSG_H

> +

> +/* BSG Vendor specific commands */

> +#define	ELS_MAX_PAYLOAD		1024

> +#ifndef	WWN_SIZE

> +#define WWN_SIZE		8       /* Size of WWPN, WWN & WWNN */

> +#endif

> +#define	VND_CMD_APP_RESERVED_SIZE	32

> +

> +enum auth_els_sub_cmd {

> +	SEND_ELS = 0,

> +	SEND_ELS_REPLY,

> +	PULL_ELS,

> +};

> +

> +struct extra_auth_els {

> +	enum auth_els_sub_cmd sub_cmd;

> +	uint32_t        extra_rx_xchg_address; // FC_ELS_ACC | FC_ELS_RJT

> +	uint8_t         extra_control_flags;

> +#define BSG_CTL_FLAG_INIT       0

> +#define BSG_CTL_FLAG_LS_ACC     1

> +#define BSG_CTL_FLAG_LS_RJT     2

> +#define BSG_CTL_FLAG_TRM        3

> +	uint8_t         extra_rsvd[3];

> +} __packed;

> +

> +struct qla_bsg_auth_els_request {

> +	struct fc_bsg_request r;

> +	struct extra_auth_els e;

> +};

> +

> +struct qla_bsg_auth_els_reply {

> +	struct fc_bsg_reply r;

> +	uint32_t rx_xchg_address;

> +};

> +

> +struct app_id {

> +	int		app_vid;

> +	uint8_t		app_key[32];

> +} __packed;

> +

> +struct app_start_reply {

> +	uint32_t	host_support_edif;	// 0=disable, 1=enable

> +	uint32_t	edif_enode_active;	// 0=disable, 1=enable

> +	uint32_t	edif_edb_active;	// 0=disable, 1=enable

> +	uint32_t	reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +struct app_start {

> +	struct app_id	app_info;

> +	uint32_t	prli_to;	// timer plogi/prli to complete

> +	uint32_t	key_shred;	// timer before shredding old keys

> +	uint8_t         app_start_flags;

> +	uint8_t         reserved[VND_CMD_APP_RESERVED_SIZE - 1];

> +} __packed;

> +

> +struct app_stop {

> +	struct app_id	app_info;

> +	char		buf[16];

> +} __packed;

> +

> +struct app_plogi_reply {

> +	uint32_t	prli_status;  // 0=failed, 1=succeeded

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +#define	RECFG_TIME	1

> +#define	RECFG_BYTES	2

> +

> +struct app_rekey_cfg {

> +	struct app_id app_info;

> +	uint8_t	 rekey_mode;	// 1=time based (in sec), 2: bytes based

> +	port_id_t d_id;		// 000 = all entries; anything else

> +				//    specifies a specific d_id

> +	uint8_t	 force;		// 0=no force to change config if

> +				//    existing rekey mode changed,

> +				// 1=force to re auth and change

> +				//    existing rekey mode if different

> +	union {

> +		int64_t bytes;	// # of bytes before rekey, 0=no limit

> +		int64_t time;	// # of seconds before rekey, 0=no time limit

> +	} rky_units;

> +

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +struct app_pinfo_req {

> +	struct app_id app_info;

> +	uint8_t	 num_ports;	// space allocated for app_pinfo_reply_t.ports[]

> +	port_id_t remote_pid;

> +	uint8_t	 reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +struct app_pinfo {

> +	port_id_t remote_pid;   // contains device d_id

> +	uint8_t	remote_wwpn[WWN_SIZE];

> +	uint8_t	remote_type;	// contains TGT or INIT

> +#define	VND_CMD_RTYPE_UNKNOWN		0

> +#define	VND_CMD_RTYPE_TARGET		1

> +#define	VND_CMD_RTYPE_INITIATOR		2

> +	uint8_t	remote_state;	// 0=bad, 1=good

> +	uint8_t	auth_state;	// 0=auth N/A (unsecured fcport),

> +				// 1=auth req'd

> +				// 2=auth done

> +	uint8_t	rekey_mode;	// 1=time based, 2=bytes based

> +	int64_t	rekey_count;	// # of times device rekeyed

> +	int64_t	rekey_config_value;     // orig rekey value (MB or sec)

> +					// (0 for no limit)

> +	int64_t	rekey_consumed_value;   // remaining MB/time,0=no limit

> +

> +	uint8_t	reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +/* AUTH States */

> +#define	VND_CMD_AUTH_STATE_UNDEF	0

> +#define	VND_CMD_AUTH_STATE_SESSION_SHUTDOWN	1

> +#define	VND_CMD_AUTH_STATE_NEEDED	2

> +#define	VND_CMD_AUTH_STATE_ELS_RCVD	3

> +#define	VND_CMD_AUTH_STATE_SAUPDATE_COMPL 4

> +

> +struct app_pinfo_reply {

> +	uint8_t		port_count;	// possible value => 0 to 255

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +	struct app_pinfo ports[0];	// variable - specified by app_pinfo_req num_ports

> +} __packed;

> +

> +struct app_sinfo_req {

> +	struct app_id	app_info;

> +	uint8_t		num_ports;	// app space alloc for elem[]

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +// temp data - actual data TBD

> +struct app_sinfo {

> +	uint8_t	remote_wwpn[WWN_SIZE];

> +	int64_t	rekey_count;	// # of times device rekeyed

> +	uint8_t	rekey_mode;	// 1=time based (in sec), 2: bytes based

> +	int64_t	tx_bytes;	// orig rekey value

> +	int64_t	rx_bytes;	// amount left

> +} __packed;

> +

> +struct app_stats_reply {

> +	uint8_t		elem_count;	// possible value => 0 to 255

> +	struct app_sinfo elem[0];	// specified by app_sinfo_t elem_count

> +} __packed;

> +

> +struct qla_sa_update_frame {

> +	struct app_id	app_info;

> +	uint16_t	flags;

> +#define SAU_FLG_INV		0x01	// delete key

> +#define SAU_FLG_TX		0x02	// 1=tx, 0 = rx

> +#define SAU_FLG_FORCE_DELETE	0x08	// force RX sa_index delete

> +#define SAU_FLG_GMAC_MODE	0x20	// GMAC mode is cleartext for the IO (i.e. NULL encryption)

> +#define SAU_FLG_KEY128          0x40

> +#define SAU_FLG_KEY256          0x80

> +	uint16_t        fast_sa_index:10,

> +			reserved:6;

> +	uint32_t	salt;

> +	uint32_t	spi;

> +	uint8_t		sa_key[32];

> +	uint8_t		node_name[WWN_SIZE];

> +	uint8_t		port_name[WWN_SIZE];

> +	port_id_t	port_id;

> +} __packed;

> +

> +// used for edif mgmt bsg interface

> +#define	QL_VND_SC_UNDEF		0

> +#define	QL_VND_SC_SA_UPDATE	1	// sa key info

> +#define	QL_VND_SC_APP_START	2	// app started event

> +#define	QL_VND_SC_APP_STOP	3	// app stopped event

> +#define	QL_VND_SC_AUTH_OK	4	// plogi auth'd ok

> +#define	QL_VND_SC_AUTH_FAIL	5	// plogi auth bad

> +#define	QL_VND_SC_REKEY_CONFIG	6	// auth rekey set parms (time/data)

> +#define	QL_VND_SC_GET_FCINFO	7	// get port info

> +#define	QL_VND_SC_GET_STATS	8	// get edif stats

> +

> +/* Application interface data structure for rtn data */

> +#define	EXT_DEF_EVENT_DATA_SIZE	64

> +struct edif_app_dbell {

> +	uint32_t	event_code;

> +	uint32_t	event_data_size;

> +	union  {

> +		port_id_t	port_id;

> +		uint8_t		event_data[EXT_DEF_EVENT_DATA_SIZE];

> +	};

> +} __packed;

> +

> +struct edif_sa_update_aen {

> +	port_id_t port_id;

> +	uint32_t key_type;	/* Tx (1) or RX (2) */

> +	uint32_t status;	/* 0 succes,  1 failed, 2 timeout , 3 error */

> +	uint8_t		reserved[16];

> +} __packed;

> +

> +#define	QL_VND_SA_STAT_SUCCESS	0

> +#define	QL_VND_SA_STAT_FAILED	1

> +#define	QL_VND_SA_STAT_TIMEOUT	2

> +#define	QL_VND_SA_STAT_ERROR	3

> +

> +#define	QL_VND_RX_SA_KEY	1

> +#define	QL_VND_TX_SA_KEY	2

> +

> +/* App defines for plogi auth'd ok and plogi auth bad requests */

> +struct auth_complete_cmd {

> +	struct app_id app_info;

> +#define PL_TYPE_WWPN    1

> +#define PL_TYPE_DID     2

> +	uint32_t    type;

> +	union {

> +		uint8_t  wwpn[WWN_SIZE];

> +		port_id_t d_id;

> +	} u;

> +	uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +#define RX_DELAY_DELETE_TIMEOUT 20			// 30 second timeout

> +

> +#endif	/* QLA_EDIF_BSG_H */

> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h

> index fae5cae6f0a8..02c10caed18b 100644

> --- a/drivers/scsi/qla2xxx/qla_gbl.h

> +++ b/drivers/scsi/qla2xxx/qla_gbl.h

> @@ -953,6 +953,10 @@ extern void qla_nvme_abort_process_comp_status

>  

>  /* nvme.c */

>  void qla_nvme_unregister_remote_port(struct fc_port *fcport);

> +void qla_edb_stop(scsi_qla_host_t *vha);

> +int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job);

> +void qla_enode_init(scsi_qla_host_t *vha);

> +void qla_enode_stop(scsi_qla_host_t *vha);

>  void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);

>  

>  #define QLA2XX_HW_ERROR			BIT_0

> 

Isn't this an optional feature?
Maybe make it a compile-time option to enable EDIF?

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		        Kernel Storage Architect
hare@suse.de			               +49 911 74053 688
SUSE Software Solutions Germany GmbH, 90409 Nürnberg
GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
Himanshu Madhani June 3, 2021, 6:09 p.m. UTC | #2
Hi Nilesh,


On 5/31/21 2:05 AM, Nilesh Javali wrote:
> From: Quinn Tran <qutran@marvell.com>

> 

> Latest FC adapter from Marvell has the ability to encrypt

> data in flight (EDIF) feature. This feature require an

> application (ex: ipsec, etc) to act as an authenticator.

> 

> This patch add 2 new BSG calls:

> QL_VND_SC_APP_START: application will announce its present

> to driver with this call. Driver will restart all

> connections to see if remote device support security or not.

> 

> QL_VND_SC_APP_STOP: application announce it's in the process

> of exiting. Driver will restart all connections to revert

> back to non-secure. Provided the remote device is willing

> to allow a non-secure connection.

> 

> Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com>

> Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com>

> Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com>

> Signed-off-by: Quinn Tran <qutran@marvell.com>

> Signed-off-by: Nilesh Javali <njavali@marvell.com>

> ---

>   drivers/scsi/qla2xxx/Makefile       |   3 +-

>   drivers/scsi/qla2xxx/qla_bsg.c      |   3 +

>   drivers/scsi/qla2xxx/qla_bsg.h      |   3 +

>   drivers/scsi/qla2xxx/qla_dbg.h      |   1 +

>   drivers/scsi/qla2xxx/qla_def.h      |  70 ++++--

>   drivers/scsi/qla2xxx/qla_edif.c     | 349 ++++++++++++++++++++++++++++

>   drivers/scsi/qla2xxx/qla_edif.h     |  32 +++

>   drivers/scsi/qla2xxx/qla_edif_bsg.h | 225 ++++++++++++++++++

>   drivers/scsi/qla2xxx/qla_gbl.h      |   4 +

>   9 files changed, 666 insertions(+), 24 deletions(-)

>   create mode 100644 drivers/scsi/qla2xxx/qla_edif.c

>   create mode 100644 drivers/scsi/qla2xxx/qla_edif.h

>   create mode 100644 drivers/scsi/qla2xxx/qla_edif_bsg.h

> 

> diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile

> index 17d5bc1cc56b..cbc1303e761e 100644

> --- a/drivers/scsi/qla2xxx/Makefile

> +++ b/drivers/scsi/qla2xxx/Makefile

> @@ -1,7 +1,8 @@

>   # SPDX-License-Identifier: GPL-2.0

>   qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \

>   		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \

> -		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o

> +		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o \

> +		qla_edif.o

>   

>   obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o

>   obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o

> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c

> index d42b2ad84049..e6cccbcc7a1b 100644

> --- a/drivers/scsi/qla2xxx/qla_bsg.c

> +++ b/drivers/scsi/qla2xxx/qla_bsg.c

> @@ -2840,6 +2840,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)

>   	case QL_VND_DPORT_DIAGNOSTICS:

>   		return qla2x00_do_dport_diagnostics(bsg_job);

>   

> +	case QL_VND_EDIF_MGMT:

> +		return qla_edif_app_mgmt(bsg_job);

> +

>   	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:

>   		return qla2x00_get_flash_image_status(bsg_job);

>   

> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h

> index 0274e99e4a12..dd793cf8bc1e 100644

> --- a/drivers/scsi/qla2xxx/qla_bsg.h

> +++ b/drivers/scsi/qla2xxx/qla_bsg.h

> @@ -31,6 +31,7 @@

>   #define QL_VND_DPORT_DIAGNOSTICS	0x19

>   #define QL_VND_GET_PRIV_STATS_EX	0x1A

>   #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E

> +#define QL_VND_EDIF_MGMT                0X1F

>   #define QL_VND_MANAGE_HOST_STATS	0x23

>   #define QL_VND_GET_HOST_STATS		0x24

>   #define QL_VND_GET_TGT_STATS		0x25

> @@ -294,4 +295,6 @@ struct qla_active_regions {

>   	uint8_t reserved[32];

>   } __packed;

>   

> +#include "qla_edif_bsg.h"

> +

>   #endif

> diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h

> index 9eb708e5e22e..f1f6c740bdcd 100644

> --- a/drivers/scsi/qla2xxx/qla_dbg.h

> +++ b/drivers/scsi/qla2xxx/qla_dbg.h

> @@ -367,6 +367,7 @@ ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);

>   #define ql_dbg_tgt_mgt	0x00002000 /* Target mode management */

>   #define ql_dbg_tgt_tmr	0x00001000 /* Target mode task management */

>   #define ql_dbg_tgt_dif  0x00000800 /* Target mode dif */

> +#define ql_dbg_edif	0x00000400 /* edif and purex debug */

>   

>   extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,

>   	uint32_t, void **);

> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h

> index def4d99f80e9..ac3b9b39d741 100644

> --- a/drivers/scsi/qla2xxx/qla_def.h

> +++ b/drivers/scsi/qla2xxx/qla_def.h

> @@ -49,6 +49,28 @@ typedef struct {

>   	uint8_t domain;

>   } le_id_t;

>   

> +/*

> + * 24 bit port ID type definition.

> + */

> +typedef union {

> +	uint32_t b24 : 24;

> +	struct {

> +#ifdef __BIG_ENDIAN

> +		uint8_t domain;

> +		uint8_t area;

> +		uint8_t al_pa;

> +#elif defined(__LITTLE_ENDIAN)

> +		uint8_t al_pa;

> +		uint8_t area;

> +		uint8_t domain;

> +#else

> +#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"

> +#endif

> +		uint8_t rsvd_1;

> +	} b;

> +} port_id_t;

> +#define INVALID_PORT_ID	0xFFFFFF

> +

>   #include "qla_bsg.h"

>   #include "qla_dsd.h"

>   #include "qla_nx.h"

> @@ -345,6 +367,8 @@ struct name_list_extended {

>   #define FW_MAX_EXCHANGES_CNT (32 * 1024)

>   #define REDUCE_EXCHANGES_CNT  (8 * 1024)

>   

> +#define SET_DID_STATUS(stat_var, status) (stat_var = status << 16)

> +

>   struct req_que;

>   struct qla_tgt_sess;

>   

> @@ -373,29 +397,6 @@ struct srb_cmd {

>   

>   /* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */

>   #define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)

> -

> -/*

> - * 24 bit port ID type definition.

> - */

> -typedef union {

> -	uint32_t b24 : 24;

> -

> -	struct {

> -#ifdef __BIG_ENDIAN

> -		uint8_t domain;

> -		uint8_t area;

> -		uint8_t al_pa;

> -#elif defined(__LITTLE_ENDIAN)

> -		uint8_t al_pa;

> -		uint8_t area;

> -		uint8_t domain;

> -#else

> -#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"

> -#endif

> -		uint8_t rsvd_1;

> -	} b;

> -} port_id_t;

> -#define INVALID_PORT_ID	0xFFFFFF

>   #define ISP_REG16_DISCONNECT 0xFFFF

>   

>   static inline le_id_t be_id_to_le(be_id_t id)

> @@ -2424,6 +2425,7 @@ enum discovery_state {

>   	DSC_LOGIN_COMPLETE,

>   	DSC_ADISC,

>   	DSC_DELETE_PEND,

> +	DSC_LOGIN_AUTH_PEND,

>   };

>   

>   enum login_state {	/* FW control Target side */

> @@ -2563,6 +2565,22 @@ typedef struct fc_port {

>   	u64 tgt_short_link_down_cnt;

>   	u64 tgt_link_down_time;

>   	u64 dev_loss_tmo;

> +	/*

> +	 * EDIF parameters for encryption.

> +	 */

> +	struct {

> +		uint16_t	enable:1;	// device is edif enabled/req'd

> +		uint16_t	app_stop:2;

> +		uint16_t	app_started:1;

> +		uint16_t	secured_login:1;

> +		uint16_t	app_sess_online:1;

> +		uint32_t	tx_rekey_cnt;

> +		uint32_t	rx_rekey_cnt;

> +		// delayed rx delete data structure list

> +		uint64_t	tx_bytes;

> +		uint64_t	rx_bytes;

> +		uint8_t		non_secured_login;

> +	} edif;

>   } fc_port_t;

>   


Same nit as Hannes about using uint16_t, while correcting that please 
use Linux styles for comment throuout this patch. I would suggest scan 
through all patches and fix it in v2.


>   enum {

> @@ -2616,6 +2634,7 @@ static const char * const port_dstate_str[] = {

>   #define FCF_ASYNC_SENT		BIT_3

>   #define FCF_CONF_COMP_SUPPORTED BIT_4

>   #define FCF_ASYNC_ACTIVE	BIT_5

> +#define FCF_FCSP_DEVICE		BIT_6

>   

>   /* No loop ID flag. */

>   #define FC_NO_LOOP_ID		0x1000

> @@ -3933,6 +3952,7 @@ struct qla_hw_data {

>   		uint32_t	scm_supported_f:1;

>   				/* Enabled in Driver */

>   		uint32_t	scm_enabled:1;

> +		uint32_t	edif_enabled:1;

>   		uint32_t	max_req_queue_warned:1;

>   		uint32_t	plogi_template_valid:1;

>   		uint32_t	port_isolated:1;

> @@ -4656,6 +4676,8 @@ struct purex_item {

>   	} iocb;

>   };

>   

> +#include "qla_edif.h"

> +

>   #define SCM_FLAG_RDF_REJECT		0x00

>   #define SCM_FLAG_RDF_COMPLETED		0x01

>   

> @@ -4884,6 +4906,8 @@ typedef struct scsi_qla_host {

>   	u64 reset_cmd_err_cnt;

>   	u64 link_down_time;

>   	u64 short_link_down_cnt;

> +	struct edif_dbell e_dbell;

> +	struct pur_core pur_cinfo;

>   } scsi_qla_host_t;

>   

>   struct qla27xx_image_status {

> diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c

> new file mode 100644

> index 000000000000..38d79ef2e700

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif.c

> @@ -0,0 +1,349 @@

> +// SPDX-License-Identifier: GPL-2.0-only

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (c)  2021     Marvell

> + */

> +#include "qla_def.h"

> +//#include "qla_edif.h"

> +


why comment out?  if not needed remove rather than comment it out.

> +#include <linux/kthread.h>

> +#include <linux/vmalloc.h>

> +#include <linux/delay.h>

> +#include <scsi/scsi_tcq.h>

> +

> +static void

> +qla_edif_sa_ctl_init(scsi_qla_host_t *vha, struct fc_port  *fcport)

> +{

> +	ql_dbg(ql_dbg_edif, vha, 0x2058,

> +		"Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%02x%02x%02x.\n",

> +		fcport->node_name, fcport->port_name,

> +		fcport->d_id.b.domain, fcport->d_id.b.area,

> +		fcport->d_id.b.al_pa);

> +

> +	fcport->edif.tx_rekey_cnt = 0;

> +	fcport->edif.rx_rekey_cnt = 0;

> +

> +	fcport->edif.tx_bytes = 0;

> +	fcport->edif.rx_bytes = 0;

> +}

> +

> +static int

> +qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)

> +{

> +	int rval = 0;	/* assume failure */


Comment above does not make sense if you are assiging rval = 0.

> +

> +	/* check that the app is allow/known to the driver */

> +

> +	/* TODO: edif: implement key/cert check for permitted apps... */

> +

> +	if (appid.app_vid == 0x73730001) {

> +		rval = 1;

> +		ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d, "%s app id ok\n", __func__);

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",

> +		    __func__, appid.app_vid);

> +	}

> +

> +	return rval;

> +}

> +


please use kernel-doc format for the funtion description

> +/*

> + * reset the session to auth wait.

> + */

> +static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state,

> +		int waitonly)

> +{

> +	int cnt, max_cnt = 200;

> +	bool traced = false;

> +

> +	fcport->keep_nport_handle = 1;

> +

> +	if (!waitonly) {

> +		qla2x00_set_fcport_disc_state(fcport, state);

> +		qlt_schedule_sess_for_deletion(fcport);

> +	} else {

> +		qla2x00_set_fcport_disc_state(fcport, state);

> +	}

> +

> +	ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +		"%s: waiting for session, max_cnt=%u\n",

> +		__func__, max_cnt);

> +

> +	cnt = 0;

> +

> +	if (waitonly) {

> +		/* Marker wait min 10 msecs. */

> +		msleep(50);

> +		cnt += 50;

> +	}

> +	while (1) {

> +		if (!traced) {

> +			ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +			"%s: session sleep.\n",

> +			__func__);


fix indentation for the print statement and no need for multiple lines 
for the parameters.

> +			traced = true;

> +		}

> +		msleep(20);

> +		cnt++;

> +		if (waitonly && (fcport->disc_state == state ||

> +			fcport->disc_state == DSC_LOGIN_COMPLETE))

> +			break;

> +		if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)

> +			break;

> +		if (cnt > max_cnt)

> +			break;

> +	}

> +

> +	if (!waitonly) {

> +		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +	"%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",


fix indentation

> +		    __func__, fcport->port_name, fcport->loop_id,

> +		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);

> +	} else {

> +		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +	"%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",


ditto. fix indentation

> +		    __func__, fcport->port_name, fcport->loop_id,

> +		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);

> +	}

> +}

> +

> +/*

> + * event that the app has started. Clear and start doorbell

> + */


use kernel-doc style

> +static int

> +qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

> +{

> +	int32_t			rval = 0;

> +	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;

> +	struct app_start	appstart;

> +	struct app_start_reply	appreply;

> +	struct fc_port  *fcport, *tf;

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__);

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appstart,

> +	    sizeof(struct app_start));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n",

> +	     __func__, appstart.app_info.app_vid, appstart.app_start_flags);

> +

> +	if (vha->e_dbell.db_flags != EDB_ACTIVE) {

> +		/* mark doorbell as active since an app is now present */

> +		vha->e_dbell.db_flags = EDB_ACTIVE;

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n",

> +		     __func__);

> +	}

> +

> +	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {

> +		if ((fcport->flags & FCF_FCSP_DEVICE)) {

> +			ql_dbg(ql_dbg_edif, vha, 0xf084,

> +			    "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n",

> +			    __func__, fcport, fcport->port_name,

> +			    fcport->loop_id, fcport->d_id.b24,

> +			    fcport->logout_on_delete);

> +

> +			if (atomic_read(&vha->loop_state) == LOOP_DOWN)

> +				break;

> +

> +			if (!fcport->edif.secured_login)

> +				continue;

> +

> +			fcport->edif.app_started = 1;

> +			if (fcport->edif.app_stop ||

> +			    (fcport->disc_state != DSC_LOGIN_COMPLETE &&

> +			     fcport->disc_state != DSC_LOGIN_PEND &&

> +			     fcport->disc_state != DSC_DELETED)) {

> +				/* no activity */

> +				fcport->edif.app_stop = 0;

> +

> +				ql_dbg(ql_dbg_edif, vha, 0x911e,

> +				    "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",

> +				    __func__, fcport->port_name);

> +				fcport->edif.app_sess_online = 1;

> +				qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0);

> +			}

> +			qla_edif_sa_ctl_init(vha, fcport);

> +		}

> +	}

> +

> +	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {

> +		/* mark as active since an app is now present */

> +		vha->pur_cinfo.enode_flags = ENODE_ACTIVE;

> +	} else {

> +		ql_dbg(ql_dbg_edif, vha, 0x911f, "%s enode already active\n",

> +		     __func__);

> +	}

> +

> +	appreply.host_support_edif = vha->hw->flags.edif_enabled;

> +	appreply.edif_enode_active = vha->pur_cinfo.enode_flags;

> +	appreply.edif_edb_active = vha->e_dbell.db_flags;

> +

> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply) +

> +	    sizeof(struct app_start_reply);

> +

> +	SET_DID_STATUS(bsg_reply->result, DID_OK);

> +

> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,

> +	    bsg_job->reply_payload.sg_cnt, &appreply,

> +	    sizeof(struct app_start_reply));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d,

> +	    "%s app start completed with 0x%x\n",

> +	    __func__, rval);

> +

> +	return rval;

> +}

> +

> +/*

> + * notification from the app that the app is stopping.

> + * actions:	stop and doorbell

> + *		stop and clear enode

> + */


use kernel-doc style

> +static int

> +qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)

> +{

> +	int32_t                 rval = 0;

> +	struct app_stop         appstop;

> +	struct fc_bsg_reply     *bsg_reply = bsg_job->reply;

> +	struct fc_port  *fcport, *tf;

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appstop,

> +	    sizeof(struct app_stop));

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s Stopping APP: app_vid=%x\n",

> +	    __func__, appstop.app_info.app_vid);

> +

> +	/* Call db stop and enode stop functions */

> +

> +	/* if we leave this running short waits are operational < 16 secs */

> +	qla_enode_stop(vha);        /* stop enode */



I don't really understand useage of the above stop fucntion, it prints 
message and returns back after checking vha->pur_cinfo.enode_flags, but 
does not take any action *if* the enode *is* active?


> +	qla_edb_stop(vha);          /* stop db */

> +


Same here for this function, it just prints message that doorbell is not 
enabled, but does not take any action if it *is* enabled.

Am I missing something?


> +	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {

> +		if (fcport->edif.non_secured_login)

> +			continue;

> +

> +		if (fcport->flags & FCF_FCSP_DEVICE) {

> +			ql_dbg(ql_dbg_edif, vha, 0xf084,

> +	"%s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d\n",


fix indentation

> +			    __func__, fcport,

> +			    fcport->port_name, fcport->loop_id,

> +			    fcport->d_id.b24, fcport->logout_on_delete,

> +			    fcport->keep_nport_handle, fcport->send_els_logo);

> +

> +			if (atomic_read(&vha->loop_state) == LOOP_DOWN)

> +				break;

> +

> +			fcport->edif.app_stop = 1;

> +			ql_dbg(ql_dbg_edif, vha, 0x911e,

> +				"%s wwpn %8phC calling qla_edif_reset_auth_wait\n",

> +				__func__, fcport->port_name);

> +

> +			fcport->send_els_logo = 1;

> +			qlt_schedule_sess_for_deletion(fcport);

> +

> +			/* qla_edif_flush_sa_ctl_lists(fcport); */

> +			fcport->edif.app_started = 0;

> +		}

> +	}

> +

> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +	SET_DID_STATUS(bsg_reply->result, DID_OK);

> +

> +	/* no return interface to app - it assumes we cleaned up ok */

> +

> +	return rval;

> +}

> +

> +int32_t

> +qla_edif_app_mgmt(struct bsg_job *bsg_job)

> +{

> +	struct fc_bsg_request	*bsg_request = bsg_job->request;

> +	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;

> +	struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);

> +	scsi_qla_host_t		*vha = shost_priv(host);

> +	struct app_id		appcheck;

> +	bool done = true;

> +	int32_t         rval = 0;

> +	uint32_t	vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];

> +

> +	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s vnd subcmd=%x\n",

> +	    __func__, vnd_sc);

> +

> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,

> +	    bsg_job->request_payload.sg_cnt, &appcheck,

> +	    sizeof(struct app_id));

> +

> +	if (!vha->hw->flags.edif_enabled ||

> +		test_bit(VPORT_DELETE, &vha->dpc_flags)) {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d,

> +		    "%s edif not enabled or vp delete. bsg ptr done %p\n",

> +		    __func__, bsg_job);

> +

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		goto done;

> +	}

> +

> +	if (qla_edif_app_check(vha, appcheck) == 0) {

> +		ql_dbg(ql_dbg_edif, vha, 0x911d,

> +		    "%s app checked failed.\n",

> +		    __func__);

> +

> +		bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		goto done;

> +	}

> +

> +	switch (vnd_sc) {

> +	case QL_VND_SC_APP_START:

> +		rval = qla_edif_app_start(vha, bsg_job);

> +		break;

> +	case QL_VND_SC_APP_STOP:

> +		rval = qla_edif_app_stop(vha, bsg_job);

> +		break;

> +	default:

> +		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",

> +		    __func__,

> +		    bsg_request->rqst_data.h_vendor.vendor_cmd[1]);

> +		rval = EXT_STATUS_INVALID_PARAM;

> +		bsg_job->reply_len = sizeof(struct fc_bsg_reply);

> +		SET_DID_STATUS(bsg_reply->result, DID_ERROR);

> +		break;

> +	}

> +

> +done:

> +	if (done) {

> +		ql_dbg(ql_dbg_user, vha, 0x7009,

> +		    "%s: %d  bsg ptr done %p\n", __func__, __LINE__, bsg_job);

> +		bsg_job_done(bsg_job, bsg_reply->result,

> +		    bsg_reply->reply_payload_rcv_len);

> +	}

> +

> +	return rval;

> +}

> +void

> +qla_enode_stop(scsi_qla_host_t *vha)

> +{

> +	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {

> +		/* doorbell list not enabled */

> +		ql_dbg(ql_dbg_edif, vha, 0x09102,

> +		    "%s enode not active\n", __func__);

> +		return;

> +	}

> +}

> +

> +/* function called when app is stopping */

> +

> +void

> +qla_edb_stop(scsi_qla_host_t *vha)

> +{

> +	if (vha->e_dbell.db_flags != EDB_ACTIVE) {

> +		/* doorbell list not enabled */

> +		ql_dbg(ql_dbg_edif, vha, 0x09102,

> +		    "%s doorbell not enabled\n", __func__);

> +		return;

> +	}

> +}

> diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h

> new file mode 100644

> index 000000000000..dc0a08570a0b

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif.h

> @@ -0,0 +1,32 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (c)  2021    Marvell

> + */

> +#ifndef __QLA_EDIF_H

> +#define __QLA_EDIF_H

> +

> +struct qla_scsi_host;

> +

> +enum enode_flags_t {

> +	ENODE_ACTIVE = 0x1,	// means that app has started

> +};

> +


fix comment style

> +struct pur_core {

> +	enum enode_flags_t	enode_flags;

> +	spinlock_t		pur_lock;       /* protects list */


do we really need this comment?

> +	struct  list_head	head;

> +};

> +

> +enum db_flags_t {

> +	EDB_ACTIVE = 0x1,

> +};

> +

> +struct edif_dbell {

> +	enum db_flags_t		db_flags;

> +	spinlock_t		db_lock;	/* protects list */


same here this comment is not addign any value

> +	struct  list_head	head;

> +	struct	completion	dbell;		/* doorbell ring */

> +};

> +

> +#endif	/* __QLA_EDIF_H */

> diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h

> new file mode 100644

> index 000000000000..9c05b78253e7

> --- /dev/null

> +++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h

> @@ -0,0 +1,225 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Marvell Fibre Channel HBA Driver

> + * Copyright (C)  2018-	    Marvell

> + *

> + */

> +#ifndef __QLA_EDIF_BSG_H

> +#define __QLA_EDIF_BSG_H

> +

> +/* BSG Vendor specific commands */

> +#define	ELS_MAX_PAYLOAD		1024

> +#ifndef	WWN_SIZE

> +#define WWN_SIZE		8       /* Size of WWPN, WWN & WWNN */

> +#endif

> +#define	VND_CMD_APP_RESERVED_SIZE	32

> +

> +enum auth_els_sub_cmd {

> +	SEND_ELS = 0,

> +	SEND_ELS_REPLY,

> +	PULL_ELS,

> +};

> +

> +struct extra_auth_els {

> +	enum auth_els_sub_cmd sub_cmd;

> +	uint32_t        extra_rx_xchg_address; // FC_ELS_ACC | FC_ELS_RJT


fix comment

> +	uint8_t         extra_control_flags;

> +#define BSG_CTL_FLAG_INIT       0

> +#define BSG_CTL_FLAG_LS_ACC     1

> +#define BSG_CTL_FLAG_LS_RJT     2

> +#define BSG_CTL_FLAG_TRM        3

> +	uint8_t         extra_rsvd[3];

> +} __packed;

> +

> +struct qla_bsg_auth_els_request {

> +	struct fc_bsg_request r;

> +	struct extra_auth_els e;

> +};

> +

> +struct qla_bsg_auth_els_reply {

> +	struct fc_bsg_reply r;

> +	uint32_t rx_xchg_address;

> +};

> +

> +struct app_id {

> +	int		app_vid;

> +	uint8_t		app_key[32];

> +} __packed;

> +

> +struct app_start_reply {

> +	uint32_t	host_support_edif;	// 0=disable, 1=enable

> +	uint32_t	edif_enode_active;	// 0=disable, 1=enable

> +	uint32_t	edif_edb_active;	// 0=disable, 1=enable

> +	uint32_t	reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;


fix comments

> +

> +struct app_start {

> +	struct app_id	app_info;

> +	uint32_t	prli_to;	// timer plogi/prli to complete

> +	uint32_t	key_shred;	// timer before shredding old keys

> +	uint8_t         app_start_flags;

> +	uint8_t         reserved[VND_CMD_APP_RESERVED_SIZE - 1];

> +} __packed;


fix comments
> +

> +struct app_stop {

> +	struct app_id	app_info;

> +	char		buf[16];

> +} __packed;

> +

> +struct app_plogi_reply {

> +	uint32_t	prli_status;  // 0=failed, 1=succeeded


fix comment

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +#define	RECFG_TIME	1

> +#define	RECFG_BYTES	2

> +

> +struct app_rekey_cfg {

> +	struct app_id app_info;

> +	uint8_t	 rekey_mode;	// 1=time based (in sec), 2: bytes based

> +	port_id_t d_id;		// 000 = all entries; anything else

> +				//    specifies a specific d_id

> +	uint8_t	 force;		// 0=no force to change config if

> +				//    existing rekey mode changed,

> +				// 1=force to re auth and change

> +				//    existing rekey mode if different

> +	union {

> +		int64_t bytes;	// # of bytes before rekey, 0=no limit

> +		int64_t time;	// # of seconds before rekey, 0=no time limit

> +	} rky_units;

> +

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +


fix comments

> +struct app_pinfo_req {

> +	struct app_id app_info;

> +	uint8_t	 num_ports;	// space allocated for app_pinfo_reply_t.ports[]


fix comment

> +	port_id_t remote_pid;

> +	uint8_t	 reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +struct app_pinfo {

> +	port_id_t remote_pid;   // contains device d_id

> +	uint8_t	remote_wwpn[WWN_SIZE];

> +	uint8_t	remote_type;	// contains TGT or INIT

> +#define	VND_CMD_RTYPE_UNKNOWN		0

> +#define	VND_CMD_RTYPE_TARGET		1

> +#define	VND_CMD_RTYPE_INITIATOR		2

> +	uint8_t	remote_state;	// 0=bad, 1=good

> +	uint8_t	auth_state;	// 0=auth N/A (unsecured fcport),

> +				// 1=auth req'd

> +				// 2=auth done

> +	uint8_t	rekey_mode;	// 1=time based, 2=bytes based

> +	int64_t	rekey_count;	// # of times device rekeyed

> +	int64_t	rekey_config_value;     // orig rekey value (MB or sec)

> +					// (0 for no limit)

> +	int64_t	rekey_consumed_value;   // remaining MB/time,0=no limit

> +


fix comments

> +	uint8_t	reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +/* AUTH States */

> +#define	VND_CMD_AUTH_STATE_UNDEF	0

> +#define	VND_CMD_AUTH_STATE_SESSION_SHUTDOWN	1

> +#define	VND_CMD_AUTH_STATE_NEEDED	2

> +#define	VND_CMD_AUTH_STATE_ELS_RCVD	3

> +#define	VND_CMD_AUTH_STATE_SAUPDATE_COMPL 4

> +

> +struct app_pinfo_reply {

> +	uint8_t		port_count;	// possible value => 0 to 255

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +	struct app_pinfo ports[0];	// variable - specified by app_pinfo_req num_ports

> +} __packed;

fix comments

> +

> +struct app_sinfo_req {

> +	struct app_id	app_info;

> +	uint8_t		num_ports;	// app space alloc for elem[]


fix comment

> +	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +// temp data - actual data TBD


what does this mean? elaborate or remove this

> +struct app_sinfo {

> +	uint8_t	remote_wwpn[WWN_SIZE];

> +	int64_t	rekey_count;	// # of times device rekeyed

> +	uint8_t	rekey_mode;	// 1=time based (in sec), 2: bytes based

> +	int64_t	tx_bytes;	// orig rekey value

> +	int64_t	rx_bytes;	// amount left

> +} __packed;


fix comments

> +

> +struct app_stats_reply {

> +	uint8_t		elem_count;	// possible value => 0 to 255

> +	struct app_sinfo elem[0];	// specified by app_sinfo_t elem_count

> +} __packed;

> +

fix comments

> +struct qla_sa_update_frame {

> +	struct app_id	app_info;

> +	uint16_t	flags;

> +#define SAU_FLG_INV		0x01	// delete key

> +#define SAU_FLG_TX		0x02	// 1=tx, 0 = rx

> +#define SAU_FLG_FORCE_DELETE	0x08	// force RX sa_index delete

> +#define SAU_FLG_GMAC_MODE	0x20	// GMAC mode is cleartext for the IO (i.e. NULL encryption)


fix comments

> +#define SAU_FLG_KEY128          0x40

> +#define SAU_FLG_KEY256          0x80

> +	uint16_t        fast_sa_index:10,

> +			reserved:6;

> +	uint32_t	salt;

> +	uint32_t	spi;

> +	uint8_t		sa_key[32];

> +	uint8_t		node_name[WWN_SIZE];

> +	uint8_t		port_name[WWN_SIZE];

> +	port_id_t	port_id;

> +} __packed;

> +

> +// used for edif mgmt bsg interface

> +#define	QL_VND_SC_UNDEF		0

> +#define	QL_VND_SC_SA_UPDATE	1	// sa key info

> +#define	QL_VND_SC_APP_START	2	// app started event

> +#define	QL_VND_SC_APP_STOP	3	// app stopped event

> +#define	QL_VND_SC_AUTH_OK	4	// plogi auth'd ok

> +#define	QL_VND_SC_AUTH_FAIL	5	// plogi auth bad

> +#define	QL_VND_SC_REKEY_CONFIG	6	// auth rekey set parms (time/data)

> +#define	QL_VND_SC_GET_FCINFO	7	// get port info

> +#define	QL_VND_SC_GET_STATS	8	// get edif stats


fix comments

> +

> +/* Application interface data structure for rtn data */

> +#define	EXT_DEF_EVENT_DATA_SIZE	64

> +struct edif_app_dbell {

> +	uint32_t	event_code;

> +	uint32_t	event_data_size;

> +	union  {

> +		port_id_t	port_id;

> +		uint8_t		event_data[EXT_DEF_EVENT_DATA_SIZE];

> +	};

> +} __packed;

> +

> +struct edif_sa_update_aen {

> +	port_id_t port_id;

> +	uint32_t key_type;	/* Tx (1) or RX (2) */

> +	uint32_t status;	/* 0 succes,  1 failed, 2 timeout , 3 error */

> +	uint8_t		reserved[16];

> +} __packed;

> +

> +#define	QL_VND_SA_STAT_SUCCESS	0

> +#define	QL_VND_SA_STAT_FAILED	1

> +#define	QL_VND_SA_STAT_TIMEOUT	2

> +#define	QL_VND_SA_STAT_ERROR	3

> +

> +#define	QL_VND_RX_SA_KEY	1

> +#define	QL_VND_TX_SA_KEY	2

> +

> +/* App defines for plogi auth'd ok and plogi auth bad requests */

> +struct auth_complete_cmd {

> +	struct app_id app_info;

> +#define PL_TYPE_WWPN    1

> +#define PL_TYPE_DID     2

> +	uint32_t    type;

> +	union {

> +		uint8_t  wwpn[WWN_SIZE];

> +		port_id_t d_id;

> +	} u;

> +	uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];

> +} __packed;

> +

> +#define RX_DELAY_DELETE_TIMEOUT 20			// 30 second timeout


fix comment

> +

> +#endif	/* QLA_EDIF_BSG_H */

> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h

> index fae5cae6f0a8..02c10caed18b 100644

> --- a/drivers/scsi/qla2xxx/qla_gbl.h

> +++ b/drivers/scsi/qla2xxx/qla_gbl.h

> @@ -953,6 +953,10 @@ extern void qla_nvme_abort_process_comp_status

>   

>   /* nvme.c */

>   void qla_nvme_unregister_remote_port(struct fc_port *fcport);

> +void qla_edb_stop(scsi_qla_host_t *vha);

> +int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job);

> +void qla_enode_init(scsi_qla_host_t *vha);

> +void qla_enode_stop(scsi_qla_host_t *vha);

>   void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);

>   

>   #define QLA2XX_HW_ERROR			BIT_0

> 


-- 
Himanshu Madhani                                Oracle Linux Engineering
Quinn Tran June 4, 2021, 6:40 p.m. UTC | #3
Hannes,
Thanks for the review.

> +		uint16_t	secured_login:1;

> +		uint16_t	app_sess_online:1;


How very uncommon; defining a uint16_t bitfield.
Why not make it uint32_t?
But adding it to the start of the structure you also induced a possible padding here; the compiler will most likely pad it to 64 bit here.

QT: ack.  Will make it uniform with v3.

> +#include "qla_def.h"

> +//#include "qla_edif.h"

> +


Add a commented out header in a new file?
Why?

QT:   short indicision while splitting the patch.  Will fix in next version.

> +	if (appid.app_vid == 0x73730001) {


Huh? A hard-coded value?
Please don't. Use a #define here to make it clear what this value is supposed to mean.

QT:  ack. Will fix in v3.

> +

> +	return rval;

> +}


And you can kill 'rval' by just call 'return' in the if branches.
Plus this function should probably be a 'bool' function ...

QT: ack. Will fix in v3.

> +		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,

> +	"%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",

> +		    __func__, fcport->port_name, fcport->loop_id,

> +		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);


Indentation.
QT:  ack. will make msg shorter for various indentation.

----
> 

Isn't this an optional feature?
Maybe make it a compile-time option to enable EDIF?

QT:  It is.  There is a driver knob that control the feature comes in patch 9 of this series.


Regards,
Quinn Tran
Quinn Tran June 4, 2021, 7:04 p.m. UTC | #4
Himanshu,

Thanks for reviewing.

> +	} edif;

>   } fc_port_t;

>   


Same nit as Hannes about using uint16_t, while correcting that please use Linux styles for comment throuout this patch. I would suggest scan through all patches and fix it in v2.

QT: ack. Will do for next re-submission.


> +#include "qla_def.h"

> +//#include "qla_edif.h"

> +


why comment out?  if not needed remove rather than comment it out.

QT:  short indicision in the patch splitting. Will fix in v3

> +static int

> +qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid) {

> +	int rval = 0;	/* assume failure */


Comment above does not make sense if you are assiging rval = 0.

QT: will revise in v3.

----
please use kernel-doc format for the funtion description

> +/*

> + * reset the session to auth wait.

> + */


QT: will have to circle back to this in the future phase as part of overall prettiness.

> +			__func__);


fix indentation for the print statement and no need for multiple lines for the parameters.

QT: ack. On all indentation comment.  I was following checkpatch recommendation.

----

> +	/* if we leave this running short waits are operational < 16 secs */

> +	qla_enode_stop(vha);        /* stop enode */



I don't really understand useage of the above stop fucntion, it prints message and returns back after checking vha->pur_cinfo.enode_flags, but does not take any action *if* the enode *is* active?

QT: will remove nondescript comment.   Those were past comment left behind, while the code intention has changed over time.  The intent here is to do cleanup if user shutdown (ex: ipsec stop).

-----
> +	qla_edb_stop(vha);          /* stop db */

> +


Same here for this function, it just prints message that doorbell is not enabled, but does not take any action if it *is* enabled.

Am I missing something?

QT:  Due to the patch splitting, this call is more of a skeleton here.   From the sum of all the patches, it perform various cleanup as part of user shutdown.

------
> +#define RX_DELAY_DELETE_TIMEOUT 20			// 30 second timeout


fix comment

QT:  Ack.  Will fix in v3


Regards,
Quinn Tran
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 17d5bc1cc56b..cbc1303e761e 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,7 +1,8 @@ 
 # SPDX-License-Identifier: GPL-2.0
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
 		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
-		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o
+		qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o \
+		qla_edif.o
 
 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
 obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index d42b2ad84049..e6cccbcc7a1b 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2840,6 +2840,9 @@  qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
 	case QL_VND_DPORT_DIAGNOSTICS:
 		return qla2x00_do_dport_diagnostics(bsg_job);
 
+	case QL_VND_EDIF_MGMT:
+		return qla_edif_app_mgmt(bsg_job);
+
 	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
 		return qla2x00_get_flash_image_status(bsg_job);
 
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 0274e99e4a12..dd793cf8bc1e 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -31,6 +31,7 @@ 
 #define QL_VND_DPORT_DIAGNOSTICS	0x19
 #define QL_VND_GET_PRIV_STATS_EX	0x1A
 #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
+#define QL_VND_EDIF_MGMT                0X1F
 #define QL_VND_MANAGE_HOST_STATS	0x23
 #define QL_VND_GET_HOST_STATS		0x24
 #define QL_VND_GET_TGT_STATS		0x25
@@ -294,4 +295,6 @@  struct qla_active_regions {
 	uint8_t reserved[32];
 } __packed;
 
+#include "qla_edif_bsg.h"
+
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 9eb708e5e22e..f1f6c740bdcd 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -367,6 +367,7 @@  ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
 #define ql_dbg_tgt_mgt	0x00002000 /* Target mode management */
 #define ql_dbg_tgt_tmr	0x00001000 /* Target mode task management */
 #define ql_dbg_tgt_dif  0x00000800 /* Target mode dif */
+#define ql_dbg_edif	0x00000400 /* edif and purex debug */
 
 extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
 	uint32_t, void **);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index def4d99f80e9..ac3b9b39d741 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -49,6 +49,28 @@  typedef struct {
 	uint8_t domain;
 } le_id_t;
 
+/*
+ * 24 bit port ID type definition.
+ */
+typedef union {
+	uint32_t b24 : 24;
+	struct {
+#ifdef __BIG_ENDIAN
+		uint8_t domain;
+		uint8_t area;
+		uint8_t al_pa;
+#elif defined(__LITTLE_ENDIAN)
+		uint8_t al_pa;
+		uint8_t area;
+		uint8_t domain;
+#else
+#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
+#endif
+		uint8_t rsvd_1;
+	} b;
+} port_id_t;
+#define INVALID_PORT_ID	0xFFFFFF
+
 #include "qla_bsg.h"
 #include "qla_dsd.h"
 #include "qla_nx.h"
@@ -345,6 +367,8 @@  struct name_list_extended {
 #define FW_MAX_EXCHANGES_CNT (32 * 1024)
 #define REDUCE_EXCHANGES_CNT  (8 * 1024)
 
+#define SET_DID_STATUS(stat_var, status) (stat_var = status << 16)
+
 struct req_que;
 struct qla_tgt_sess;
 
@@ -373,29 +397,6 @@  struct srb_cmd {
 
 /* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
 #define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)
-
-/*
- * 24 bit port ID type definition.
- */
-typedef union {
-	uint32_t b24 : 24;
-
-	struct {
-#ifdef __BIG_ENDIAN
-		uint8_t domain;
-		uint8_t area;
-		uint8_t al_pa;
-#elif defined(__LITTLE_ENDIAN)
-		uint8_t al_pa;
-		uint8_t area;
-		uint8_t domain;
-#else
-#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
-#endif
-		uint8_t rsvd_1;
-	} b;
-} port_id_t;
-#define INVALID_PORT_ID	0xFFFFFF
 #define ISP_REG16_DISCONNECT 0xFFFF
 
 static inline le_id_t be_id_to_le(be_id_t id)
@@ -2424,6 +2425,7 @@  enum discovery_state {
 	DSC_LOGIN_COMPLETE,
 	DSC_ADISC,
 	DSC_DELETE_PEND,
+	DSC_LOGIN_AUTH_PEND,
 };
 
 enum login_state {	/* FW control Target side */
@@ -2563,6 +2565,22 @@  typedef struct fc_port {
 	u64 tgt_short_link_down_cnt;
 	u64 tgt_link_down_time;
 	u64 dev_loss_tmo;
+	/*
+	 * EDIF parameters for encryption.
+	 */
+	struct {
+		uint16_t	enable:1;	// device is edif enabled/req'd
+		uint16_t	app_stop:2;
+		uint16_t	app_started:1;
+		uint16_t	secured_login:1;
+		uint16_t	app_sess_online:1;
+		uint32_t	tx_rekey_cnt;
+		uint32_t	rx_rekey_cnt;
+		// delayed rx delete data structure list
+		uint64_t	tx_bytes;
+		uint64_t	rx_bytes;
+		uint8_t		non_secured_login;
+	} edif;
 } fc_port_t;
 
 enum {
@@ -2616,6 +2634,7 @@  static const char * const port_dstate_str[] = {
 #define FCF_ASYNC_SENT		BIT_3
 #define FCF_CONF_COMP_SUPPORTED BIT_4
 #define FCF_ASYNC_ACTIVE	BIT_5
+#define FCF_FCSP_DEVICE		BIT_6
 
 /* No loop ID flag. */
 #define FC_NO_LOOP_ID		0x1000
@@ -3933,6 +3952,7 @@  struct qla_hw_data {
 		uint32_t	scm_supported_f:1;
 				/* Enabled in Driver */
 		uint32_t	scm_enabled:1;
+		uint32_t	edif_enabled:1;
 		uint32_t	max_req_queue_warned:1;
 		uint32_t	plogi_template_valid:1;
 		uint32_t	port_isolated:1;
@@ -4656,6 +4676,8 @@  struct purex_item {
 	} iocb;
 };
 
+#include "qla_edif.h"
+
 #define SCM_FLAG_RDF_REJECT		0x00
 #define SCM_FLAG_RDF_COMPLETED		0x01
 
@@ -4884,6 +4906,8 @@  typedef struct scsi_qla_host {
 	u64 reset_cmd_err_cnt;
 	u64 link_down_time;
 	u64 short_link_down_cnt;
+	struct edif_dbell e_dbell;
+	struct pur_core pur_cinfo;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
new file mode 100644
index 000000000000..38d79ef2e700
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -0,0 +1,349 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (c)  2021     Marvell
+ */
+#include "qla_def.h"
+//#include "qla_edif.h"
+
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <scsi/scsi_tcq.h>
+
+static void
+qla_edif_sa_ctl_init(scsi_qla_host_t *vha, struct fc_port  *fcport)
+{
+	ql_dbg(ql_dbg_edif, vha, 0x2058,
+		"Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%02x%02x%02x.\n",
+		fcport->node_name, fcport->port_name,
+		fcport->d_id.b.domain, fcport->d_id.b.area,
+		fcport->d_id.b.al_pa);
+
+	fcport->edif.tx_rekey_cnt = 0;
+	fcport->edif.rx_rekey_cnt = 0;
+
+	fcport->edif.tx_bytes = 0;
+	fcport->edif.rx_bytes = 0;
+}
+
+static int
+qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)
+{
+	int rval = 0;	/* assume failure */
+
+	/* check that the app is allow/known to the driver */
+
+	/* TODO: edif: implement key/cert check for permitted apps... */
+
+	if (appid.app_vid == 0x73730001) {
+		rval = 1;
+		ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d, "%s app id ok\n", __func__);
+	} else {
+		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",
+		    __func__, appid.app_vid);
+	}
+
+	return rval;
+}
+
+/*
+ * reset the session to auth wait.
+ */
+static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state,
+		int waitonly)
+{
+	int cnt, max_cnt = 200;
+	bool traced = false;
+
+	fcport->keep_nport_handle = 1;
+
+	if (!waitonly) {
+		qla2x00_set_fcport_disc_state(fcport, state);
+		qlt_schedule_sess_for_deletion(fcport);
+	} else {
+		qla2x00_set_fcport_disc_state(fcport, state);
+	}
+
+	ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+		"%s: waiting for session, max_cnt=%u\n",
+		__func__, max_cnt);
+
+	cnt = 0;
+
+	if (waitonly) {
+		/* Marker wait min 10 msecs. */
+		msleep(50);
+		cnt += 50;
+	}
+	while (1) {
+		if (!traced) {
+			ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+			"%s: session sleep.\n",
+			__func__);
+			traced = true;
+		}
+		msleep(20);
+		cnt++;
+		if (waitonly && (fcport->disc_state == state ||
+			fcport->disc_state == DSC_LOGIN_COMPLETE))
+			break;
+		if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)
+			break;
+		if (cnt > max_cnt)
+			break;
+	}
+
+	if (!waitonly) {
+		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+	"%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",
+		    __func__, fcport->port_name, fcport->loop_id,
+		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);
+	} else {
+		ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+	"%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",
+		    __func__, fcport->port_name, fcport->loop_id,
+		    fcport->d_id.b24, fcport, fcport->disc_state, cnt);
+	}
+}
+
+/*
+ * event that the app has started. Clear and start doorbell
+ */
+static int
+qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+	int32_t			rval = 0;
+	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;
+	struct app_start	appstart;
+	struct app_start_reply	appreply;
+	struct fc_port  *fcport, *tf;
+
+	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__);
+
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+	    bsg_job->request_payload.sg_cnt, &appstart,
+	    sizeof(struct app_start));
+
+	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n",
+	     __func__, appstart.app_info.app_vid, appstart.app_start_flags);
+
+	if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+		/* mark doorbell as active since an app is now present */
+		vha->e_dbell.db_flags = EDB_ACTIVE;
+	} else {
+		ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n",
+		     __func__);
+	}
+
+	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+		if ((fcport->flags & FCF_FCSP_DEVICE)) {
+			ql_dbg(ql_dbg_edif, vha, 0xf084,
+			    "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n",
+			    __func__, fcport, fcport->port_name,
+			    fcport->loop_id, fcport->d_id.b24,
+			    fcport->logout_on_delete);
+
+			if (atomic_read(&vha->loop_state) == LOOP_DOWN)
+				break;
+
+			if (!fcport->edif.secured_login)
+				continue;
+
+			fcport->edif.app_started = 1;
+			if (fcport->edif.app_stop ||
+			    (fcport->disc_state != DSC_LOGIN_COMPLETE &&
+			     fcport->disc_state != DSC_LOGIN_PEND &&
+			     fcport->disc_state != DSC_DELETED)) {
+				/* no activity */
+				fcport->edif.app_stop = 0;
+
+				ql_dbg(ql_dbg_edif, vha, 0x911e,
+				    "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",
+				    __func__, fcport->port_name);
+				fcport->edif.app_sess_online = 1;
+				qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0);
+			}
+			qla_edif_sa_ctl_init(vha, fcport);
+		}
+	}
+
+	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
+		/* mark as active since an app is now present */
+		vha->pur_cinfo.enode_flags = ENODE_ACTIVE;
+	} else {
+		ql_dbg(ql_dbg_edif, vha, 0x911f, "%s enode already active\n",
+		     __func__);
+	}
+
+	appreply.host_support_edif = vha->hw->flags.edif_enabled;
+	appreply.edif_enode_active = vha->pur_cinfo.enode_flags;
+	appreply.edif_edb_active = vha->e_dbell.db_flags;
+
+	bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
+	    sizeof(struct app_start_reply);
+
+	SET_DID_STATUS(bsg_reply->result, DID_OK);
+
+	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+	    bsg_job->reply_payload.sg_cnt, &appreply,
+	    sizeof(struct app_start_reply));
+
+	ql_dbg(ql_dbg_edif, vha, 0x911d,
+	    "%s app start completed with 0x%x\n",
+	    __func__, rval);
+
+	return rval;
+}
+
+/*
+ * notification from the app that the app is stopping.
+ * actions:	stop and doorbell
+ *		stop and clear enode
+ */
+static int
+qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+	int32_t                 rval = 0;
+	struct app_stop         appstop;
+	struct fc_bsg_reply     *bsg_reply = bsg_job->reply;
+	struct fc_port  *fcport, *tf;
+
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+	    bsg_job->request_payload.sg_cnt, &appstop,
+	    sizeof(struct app_stop));
+
+	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s Stopping APP: app_vid=%x\n",
+	    __func__, appstop.app_info.app_vid);
+
+	/* Call db stop and enode stop functions */
+
+	/* if we leave this running short waits are operational < 16 secs */
+	qla_enode_stop(vha);        /* stop enode */
+	qla_edb_stop(vha);          /* stop db */
+
+	list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+		if (fcport->edif.non_secured_login)
+			continue;
+
+		if (fcport->flags & FCF_FCSP_DEVICE) {
+			ql_dbg(ql_dbg_edif, vha, 0xf084,
+	"%s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d\n",
+			    __func__, fcport,
+			    fcport->port_name, fcport->loop_id,
+			    fcport->d_id.b24, fcport->logout_on_delete,
+			    fcport->keep_nport_handle, fcport->send_els_logo);
+
+			if (atomic_read(&vha->loop_state) == LOOP_DOWN)
+				break;
+
+			fcport->edif.app_stop = 1;
+			ql_dbg(ql_dbg_edif, vha, 0x911e,
+				"%s wwpn %8phC calling qla_edif_reset_auth_wait\n",
+				__func__, fcport->port_name);
+
+			fcport->send_els_logo = 1;
+			qlt_schedule_sess_for_deletion(fcport);
+
+			/* qla_edif_flush_sa_ctl_lists(fcport); */
+			fcport->edif.app_started = 0;
+		}
+	}
+
+	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+	SET_DID_STATUS(bsg_reply->result, DID_OK);
+
+	/* no return interface to app - it assumes we cleaned up ok */
+
+	return rval;
+}
+
+int32_t
+qla_edif_app_mgmt(struct bsg_job *bsg_job)
+{
+	struct fc_bsg_request	*bsg_request = bsg_job->request;
+	struct fc_bsg_reply	*bsg_reply = bsg_job->reply;
+	struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
+	scsi_qla_host_t		*vha = shost_priv(host);
+	struct app_id		appcheck;
+	bool done = true;
+	int32_t         rval = 0;
+	uint32_t	vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
+
+	ql_dbg(ql_dbg_edif, vha, 0x911d, "%s vnd subcmd=%x\n",
+	    __func__, vnd_sc);
+
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+	    bsg_job->request_payload.sg_cnt, &appcheck,
+	    sizeof(struct app_id));
+
+	if (!vha->hw->flags.edif_enabled ||
+		test_bit(VPORT_DELETE, &vha->dpc_flags)) {
+		ql_dbg(ql_dbg_edif, vha, 0x911d,
+		    "%s edif not enabled or vp delete. bsg ptr done %p\n",
+		    __func__, bsg_job);
+
+		SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+		goto done;
+	}
+
+	if (qla_edif_app_check(vha, appcheck) == 0) {
+		ql_dbg(ql_dbg_edif, vha, 0x911d,
+		    "%s app checked failed.\n",
+		    __func__);
+
+		bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+		SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+		goto done;
+	}
+
+	switch (vnd_sc) {
+	case QL_VND_SC_APP_START:
+		rval = qla_edif_app_start(vha, bsg_job);
+		break;
+	case QL_VND_SC_APP_STOP:
+		rval = qla_edif_app_stop(vha, bsg_job);
+		break;
+	default:
+		ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",
+		    __func__,
+		    bsg_request->rqst_data.h_vendor.vendor_cmd[1]);
+		rval = EXT_STATUS_INVALID_PARAM;
+		bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+		SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+		break;
+	}
+
+done:
+	if (done) {
+		ql_dbg(ql_dbg_user, vha, 0x7009,
+		    "%s: %d  bsg ptr done %p\n", __func__, __LINE__, bsg_job);
+		bsg_job_done(bsg_job, bsg_reply->result,
+		    bsg_reply->reply_payload_rcv_len);
+	}
+
+	return rval;
+}
+void
+qla_enode_stop(scsi_qla_host_t *vha)
+{
+	if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
+		/* doorbell list not enabled */
+		ql_dbg(ql_dbg_edif, vha, 0x09102,
+		    "%s enode not active\n", __func__);
+		return;
+	}
+}
+
+/* function called when app is stopping */
+
+void
+qla_edb_stop(scsi_qla_host_t *vha)
+{
+	if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+		/* doorbell list not enabled */
+		ql_dbg(ql_dbg_edif, vha, 0x09102,
+		    "%s doorbell not enabled\n", __func__);
+		return;
+	}
+}
diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h
new file mode 100644
index 000000000000..dc0a08570a0b
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif.h
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (c)  2021    Marvell
+ */
+#ifndef __QLA_EDIF_H
+#define __QLA_EDIF_H
+
+struct qla_scsi_host;
+
+enum enode_flags_t {
+	ENODE_ACTIVE = 0x1,	// means that app has started
+};
+
+struct pur_core {
+	enum enode_flags_t	enode_flags;
+	spinlock_t		pur_lock;       /* protects list */
+	struct  list_head	head;
+};
+
+enum db_flags_t {
+	EDB_ACTIVE = 0x1,
+};
+
+struct edif_dbell {
+	enum db_flags_t		db_flags;
+	spinlock_t		db_lock;	/* protects list */
+	struct  list_head	head;
+	struct	completion	dbell;		/* doorbell ring */
+};
+
+#endif	/* __QLA_EDIF_H */
diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h
new file mode 100644
index 000000000000..9c05b78253e7
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h
@@ -0,0 +1,225 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (C)  2018-	    Marvell
+ *
+ */
+#ifndef __QLA_EDIF_BSG_H
+#define __QLA_EDIF_BSG_H
+
+/* BSG Vendor specific commands */
+#define	ELS_MAX_PAYLOAD		1024
+#ifndef	WWN_SIZE
+#define WWN_SIZE		8       /* Size of WWPN, WWN & WWNN */
+#endif
+#define	VND_CMD_APP_RESERVED_SIZE	32
+
+enum auth_els_sub_cmd {
+	SEND_ELS = 0,
+	SEND_ELS_REPLY,
+	PULL_ELS,
+};
+
+struct extra_auth_els {
+	enum auth_els_sub_cmd sub_cmd;
+	uint32_t        extra_rx_xchg_address; // FC_ELS_ACC | FC_ELS_RJT
+	uint8_t         extra_control_flags;
+#define BSG_CTL_FLAG_INIT       0
+#define BSG_CTL_FLAG_LS_ACC     1
+#define BSG_CTL_FLAG_LS_RJT     2
+#define BSG_CTL_FLAG_TRM        3
+	uint8_t         extra_rsvd[3];
+} __packed;
+
+struct qla_bsg_auth_els_request {
+	struct fc_bsg_request r;
+	struct extra_auth_els e;
+};
+
+struct qla_bsg_auth_els_reply {
+	struct fc_bsg_reply r;
+	uint32_t rx_xchg_address;
+};
+
+struct app_id {
+	int		app_vid;
+	uint8_t		app_key[32];
+} __packed;
+
+struct app_start_reply {
+	uint32_t	host_support_edif;	// 0=disable, 1=enable
+	uint32_t	edif_enode_active;	// 0=disable, 1=enable
+	uint32_t	edif_edb_active;	// 0=disable, 1=enable
+	uint32_t	reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_start {
+	struct app_id	app_info;
+	uint32_t	prli_to;	// timer plogi/prli to complete
+	uint32_t	key_shred;	// timer before shredding old keys
+	uint8_t         app_start_flags;
+	uint8_t         reserved[VND_CMD_APP_RESERVED_SIZE - 1];
+} __packed;
+
+struct app_stop {
+	struct app_id	app_info;
+	char		buf[16];
+} __packed;
+
+struct app_plogi_reply {
+	uint32_t	prli_status;  // 0=failed, 1=succeeded
+	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+#define	RECFG_TIME	1
+#define	RECFG_BYTES	2
+
+struct app_rekey_cfg {
+	struct app_id app_info;
+	uint8_t	 rekey_mode;	// 1=time based (in sec), 2: bytes based
+	port_id_t d_id;		// 000 = all entries; anything else
+				//    specifies a specific d_id
+	uint8_t	 force;		// 0=no force to change config if
+				//    existing rekey mode changed,
+				// 1=force to re auth and change
+				//    existing rekey mode if different
+	union {
+		int64_t bytes;	// # of bytes before rekey, 0=no limit
+		int64_t time;	// # of seconds before rekey, 0=no time limit
+	} rky_units;
+
+	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_pinfo_req {
+	struct app_id app_info;
+	uint8_t	 num_ports;	// space allocated for app_pinfo_reply_t.ports[]
+	port_id_t remote_pid;
+	uint8_t	 reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_pinfo {
+	port_id_t remote_pid;   // contains device d_id
+	uint8_t	remote_wwpn[WWN_SIZE];
+	uint8_t	remote_type;	// contains TGT or INIT
+#define	VND_CMD_RTYPE_UNKNOWN		0
+#define	VND_CMD_RTYPE_TARGET		1
+#define	VND_CMD_RTYPE_INITIATOR		2
+	uint8_t	remote_state;	// 0=bad, 1=good
+	uint8_t	auth_state;	// 0=auth N/A (unsecured fcport),
+				// 1=auth req'd
+				// 2=auth done
+	uint8_t	rekey_mode;	// 1=time based, 2=bytes based
+	int64_t	rekey_count;	// # of times device rekeyed
+	int64_t	rekey_config_value;     // orig rekey value (MB or sec)
+					// (0 for no limit)
+	int64_t	rekey_consumed_value;   // remaining MB/time,0=no limit
+
+	uint8_t	reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+/* AUTH States */
+#define	VND_CMD_AUTH_STATE_UNDEF	0
+#define	VND_CMD_AUTH_STATE_SESSION_SHUTDOWN	1
+#define	VND_CMD_AUTH_STATE_NEEDED	2
+#define	VND_CMD_AUTH_STATE_ELS_RCVD	3
+#define	VND_CMD_AUTH_STATE_SAUPDATE_COMPL 4
+
+struct app_pinfo_reply {
+	uint8_t		port_count;	// possible value => 0 to 255
+	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];
+	struct app_pinfo ports[0];	// variable - specified by app_pinfo_req num_ports
+} __packed;
+
+struct app_sinfo_req {
+	struct app_id	app_info;
+	uint8_t		num_ports;	// app space alloc for elem[]
+	uint8_t		reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+// temp data - actual data TBD
+struct app_sinfo {
+	uint8_t	remote_wwpn[WWN_SIZE];
+	int64_t	rekey_count;	// # of times device rekeyed
+	uint8_t	rekey_mode;	// 1=time based (in sec), 2: bytes based
+	int64_t	tx_bytes;	// orig rekey value
+	int64_t	rx_bytes;	// amount left
+} __packed;
+
+struct app_stats_reply {
+	uint8_t		elem_count;	// possible value => 0 to 255
+	struct app_sinfo elem[0];	// specified by app_sinfo_t elem_count
+} __packed;
+
+struct qla_sa_update_frame {
+	struct app_id	app_info;
+	uint16_t	flags;
+#define SAU_FLG_INV		0x01	// delete key
+#define SAU_FLG_TX		0x02	// 1=tx, 0 = rx
+#define SAU_FLG_FORCE_DELETE	0x08	// force RX sa_index delete
+#define SAU_FLG_GMAC_MODE	0x20	// GMAC mode is cleartext for the IO (i.e. NULL encryption)
+#define SAU_FLG_KEY128          0x40
+#define SAU_FLG_KEY256          0x80
+	uint16_t        fast_sa_index:10,
+			reserved:6;
+	uint32_t	salt;
+	uint32_t	spi;
+	uint8_t		sa_key[32];
+	uint8_t		node_name[WWN_SIZE];
+	uint8_t		port_name[WWN_SIZE];
+	port_id_t	port_id;
+} __packed;
+
+// used for edif mgmt bsg interface
+#define	QL_VND_SC_UNDEF		0
+#define	QL_VND_SC_SA_UPDATE	1	// sa key info
+#define	QL_VND_SC_APP_START	2	// app started event
+#define	QL_VND_SC_APP_STOP	3	// app stopped event
+#define	QL_VND_SC_AUTH_OK	4	// plogi auth'd ok
+#define	QL_VND_SC_AUTH_FAIL	5	// plogi auth bad
+#define	QL_VND_SC_REKEY_CONFIG	6	// auth rekey set parms (time/data)
+#define	QL_VND_SC_GET_FCINFO	7	// get port info
+#define	QL_VND_SC_GET_STATS	8	// get edif stats
+
+/* Application interface data structure for rtn data */
+#define	EXT_DEF_EVENT_DATA_SIZE	64
+struct edif_app_dbell {
+	uint32_t	event_code;
+	uint32_t	event_data_size;
+	union  {
+		port_id_t	port_id;
+		uint8_t		event_data[EXT_DEF_EVENT_DATA_SIZE];
+	};
+} __packed;
+
+struct edif_sa_update_aen {
+	port_id_t port_id;
+	uint32_t key_type;	/* Tx (1) or RX (2) */
+	uint32_t status;	/* 0 succes,  1 failed, 2 timeout , 3 error */
+	uint8_t		reserved[16];
+} __packed;
+
+#define	QL_VND_SA_STAT_SUCCESS	0
+#define	QL_VND_SA_STAT_FAILED	1
+#define	QL_VND_SA_STAT_TIMEOUT	2
+#define	QL_VND_SA_STAT_ERROR	3
+
+#define	QL_VND_RX_SA_KEY	1
+#define	QL_VND_TX_SA_KEY	2
+
+/* App defines for plogi auth'd ok and plogi auth bad requests */
+struct auth_complete_cmd {
+	struct app_id app_info;
+#define PL_TYPE_WWPN    1
+#define PL_TYPE_DID     2
+	uint32_t    type;
+	union {
+		uint8_t  wwpn[WWN_SIZE];
+		port_id_t d_id;
+	} u;
+	uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+#define RX_DELAY_DELETE_TIMEOUT 20			// 30 second timeout
+
+#endif	/* QLA_EDIF_BSG_H */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fae5cae6f0a8..02c10caed18b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -953,6 +953,10 @@  extern void qla_nvme_abort_process_comp_status
 
 /* nvme.c */
 void qla_nvme_unregister_remote_port(struct fc_port *fcport);
+void qla_edb_stop(scsi_qla_host_t *vha);
+int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job);
+void qla_enode_init(scsi_qla_host_t *vha);
+void qla_enode_stop(scsi_qla_host_t *vha);
 void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
 
 #define QLA2XX_HW_ERROR			BIT_0