diff mbox series

[v2,04/10] qla2xxx: Add extraction of auth_els from the wire

Message ID 20210531070545.32072-5-njavali@marvell.com (mailing list archive)
State Superseded
Headers show
Series qla2xxx: Add EDIF support | 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 is a continuation of previous patch where
authentication messages sent from remote device has arrived.
Each message is extracted and placed in a buffer for application
to retrieve. The FC frame header will be stripped leaving
behind the AUTH ELS payload. It is up to the application
to strip the AUTH ELS header to get to the actual authentication
message.

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/qla_def.h    |   2 +-
 drivers/scsi/qla2xxx/qla_edif.c   | 191 ++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_gbl.h    |   7 +-
 drivers/scsi/qla2xxx/qla_isr.c    | 182 ++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_os.c     |  11 +-
 drivers/scsi/qla2xxx/qla_target.c |  36 +++---
 6 files changed, 404 insertions(+), 25 deletions(-)

Comments

Hannes Reinecke June 1, 2021, 12:51 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 is a continuation of previous patch where
> authentication messages sent from remote device has arrived.
> Each message is extracted and placed in a buffer for application
> to retrieve. The FC frame header will be stripped leaving
> behind the AUTH ELS payload. It is up to the application
> to strip the AUTH ELS header to get to the actual authentication
> message.
> 
> 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/qla_def.h    |   2 +-
>  drivers/scsi/qla2xxx/qla_edif.c   | 191 ++++++++++++++++++++++++++++++
>  drivers/scsi/qla2xxx/qla_gbl.h    |   7 +-
>  drivers/scsi/qla2xxx/qla_isr.c    | 182 ++++++++++++++++++++++++++++
>  drivers/scsi/qla2xxx/qla_os.c     |  11 +-
>  drivers/scsi/qla2xxx/qla_target.c |  36 +++---
>  6 files changed, 404 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 517a4a4c178e..e47a7b3618d6 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -3907,7 +3907,6 @@ struct qlt_hw_data {
>  	int num_act_qpairs;
>  #define DEFAULT_NAQP 2
>  	spinlock_t atio_lock ____cacheline_aligned;
> -	struct btree_head32 host_map;
>  };
>  
>  #define MAX_QFULL_CMDS_ALLOC	8192
> @@ -4682,6 +4681,7 @@ struct qla_hw_data {
>  	struct qla_hw_data_stat stat;
>  	pci_error_state_t pci_error_state;
>  	struct dma_pool *purex_dma_pool;
> +	struct btree_head32 host_map;
>  	struct els_reject elsrej;
>  };
>  
> diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> index 4c788f4588ca..df8dff447c6a 100644
> --- a/drivers/scsi/qla2xxx/qla_edif.c
> +++ b/drivers/scsi/qla2xxx/qla_edif.c
> @@ -684,6 +684,44 @@ qla_enode_stop(scsi_qla_host_t *vha)
>   *  returns: enode pointer with buffers
>   *           NULL on error
>   */
> +static struct enode *
> +qla_enode_alloc(scsi_qla_host_t *vha, uint32_t ntype)
> +{
> +	struct enode		*node;
> +	struct purexevent	*purex;
> +
> +	node = kzalloc(RX_ELS_SIZE, GFP_ATOMIC);
> +	if (!node)
> +		return NULL;
> +
> +	purex = &node->u.purexinfo;
> +	purex->msgp = (u8 *)(node + 1);
> +	purex->msgp_len = ELS_MAX_PAYLOAD;
> +
> +	node->dinfo.lstate = LSTATE_OFF;
> +
> +	node->ntype = ntype;
> +	INIT_LIST_HEAD(&node->list);
> +	return node;
> +}
> +
> +/* adds a already alllocated enode to the linked list */
> +static bool
> +qla_enode_add(scsi_qla_host_t *vha, struct enode *ptr)
> +{
> +	unsigned long flags;
> +
> +	ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x9109,
> +	    "%s add enode for type=%x, cnt=%x\n",
> +	    __func__, ptr->ntype, ptr->dinfo.nodecnt);
> +
> +	spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
> +	ptr->dinfo.lstate = LSTATE_ON;
> +	list_add_tail(&ptr->list, &vha->pur_cinfo.head);
> +	spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);

See the comment to the previous patch.
LSTATE_ON and LSTATE_OFF can be replaced with a check to list_empty()

> +
> +	return true;
> +}
>  
>  static struct enode *
>  qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2)
> @@ -783,6 +821,32 @@ qla_pur_get_pending(scsi_qla_host_t *vha, fc_port_t *fcport, struct bsg_job *bsg
>  
>  	return 0;
>  }
> +
> +/* it is assume qpair lock is held */
> +static int
> +qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp,
> +	struct qla_els_pt_arg *a)
> +{
> +	struct els_entry_24xx *els_iocb;
> +
> +	els_iocb = __qla2x00_alloc_iocbs(qp, NULL);
> +	if (!els_iocb) {
> +		ql_log(ql_log_warn, vha, 0x700c,
> +		    "qla2x00_alloc_iocbs failed.\n");
> +		return QLA_FUNCTION_FAILED;
> +	}
> +
> +	qla_els_pt_iocb(vha, els_iocb, a);
> +
> +	ql_dbg(ql_dbg_edif, vha, 0x0183,
> +	    "Sending ELS reject...\n");
> +	ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185,
> +	    vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c));
> +	/* -- */

Meaning what?

> +	wmb();
> +	qla2x00_start_iocbs(vha, qp->req);
> +	return 0;
> +}
>  /* function called when app is stopping */
>  
>  void
> @@ -796,6 +860,133 @@ qla_edb_stop(scsi_qla_host_t *vha)
>  	}
>  }
>  
> +void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
> +{
> +	struct purex_entry_24xx *p = *pkt;
> +	struct enode		*ptr;
> +	int		sid;
> +	u16 totlen;
> +	struct purexevent	*purex;
> +	struct scsi_qla_host *host = NULL;
> +	int rc;
> +	struct fc_port *fcport;
> +	struct qla_els_pt_arg a;
> +	be_id_t beid;
> +
> +	memset(&a, 0, sizeof(a));
> +
> +	a.els_opcode = ELS_AUTH_ELS;
> +	a.nport_handle = p->nport_handle;
> +	a.rx_xchg_address = p->rx_xchg_addr;
> +	a.did.b.domain = p->s_id[2];
> +	a.did.b.area   = p->s_id[1];
> +	a.did.b.al_pa  = p->s_id[0];
> +	a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);
> +	a.tx_addr = vha->hw->elsrej.cdma;
> +	a.vp_idx = vha->vp_idx;
> +	a.control_flags = EPD_ELS_RJT;
> +
> +	sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);
> +	/*
> +	 * ql_dbg(ql_dbg_edif, vha, 0x09108,
> +	 *	  "%s rec'vd sid=0x%x\n", __func__, sid);
> +	 */

Please move to 'dev_dbg' if you need it, or remove it.

> +
> +	totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
> +	if (le16_to_cpu(p->status_flags) & 0x8000) {
> +		totlen = le16_to_cpu(p->trunc_frame_size);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	if (totlen > MAX_PAYLOAD) {
> +		ql_dbg(ql_dbg_edif, vha, 0x0910d,
> +		    "%s WARNING: verbose ELS frame received (totlen=%x)\n",
> +		    __func__, totlen);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	if (!vha->hw->flags.edif_enabled) {
> +		/* edif support not enabled */
> +		ql_dbg(ql_dbg_edif, vha, 0x910e, "%s edif not enabled\n",
> +		    __func__);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	ptr = qla_enode_alloc(vha, N_PUREX);
> +	if (!ptr) {
> +		ql_dbg(ql_dbg_edif, vha, 0x09109,
> +		    "WARNING: enode allloc failed for sid=%x\n",
> +		    sid);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	purex = &ptr->u.purexinfo;
> +	purex->pur_info.pur_sid = a.did;
> +	purex->pur_info.pur_pend = 0;
> +	purex->pur_info.pur_bytes_rcvd = totlen;
> +	purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);
> +	purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);
> +	purex->pur_info.pur_did.b.domain =  p->d_id[2];
> +	purex->pur_info.pur_did.b.area =  p->d_id[1];
> +	purex->pur_info.pur_did.b.al_pa =  p->d_id[0];
> +	purex->pur_info.vp_idx = p->vp_idx;
> +
> +	rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp,
> +		purex->msgp_len);
> +	if (rc) {
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		qla_enode_free(vha, ptr);
> +		return;
> +	}
> +	/*
> +	 * ql_dump_buffer(ql_dbg_edif, vha, 0x70e0,
> +	 *   purex->msgp, purex->pur_info.pur_bytes_rcvd);
> +	 */

Same here.

> +	beid.al_pa = purex->pur_info.pur_did.b.al_pa;
> +	beid.area   = purex->pur_info.pur_did.b.area;
> +	beid.domain = purex->pur_info.pur_did.b.domain;
> +	host = qla_find_host_by_d_id(vha, beid);
> +	if (!host) {
> +		ql_log(ql_log_fatal, vha, 0x508b,
> +		    "%s Drop ELS due to unable to find host %06x\n",
> +		    __func__, purex->pur_info.pur_did.b24);
> +
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		qla_enode_free(vha, ptr);
> +		return;
> +	}
> +
> +	fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);
> +
> +	if (host->e_dbell.db_flags != EDB_ACTIVE ||
> +	    (fcport && fcport->loop_id == FC_NO_LOOP_ID)) {
> +		ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",
> +		    __func__, host->e_dbell.db_flags,
> +		    fcport ? fcport->d_id.b24 : 0);
> +
> +		qla_els_reject_iocb(host, (*rsp)->qpair, &a);
> +		qla_enode_free(host, ptr);
> +		return;
> +	}
> +
> +	/* add the local enode to the list */
> +	qla_enode_add(host, ptr);
> +
> +	ql_dbg(ql_dbg_edif, host, 0x0910c,
> +	    "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
> +	    __func__, purex->pur_info.pur_bytes_rcvd,
> +	    purex->pur_info.pur_sid.b24,
> +	    purex->pur_info.pur_did.b24, p->rx_xchg_addr);
> +}
> +
>  static void qla_parse_auth_els_ctl(struct srb *sp)
>  {
>  	struct qla_els_pt_arg *a = &sp->u.bsg_cmd.u.els_arg;
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 7ff05aa10b2d..a4cb8092e97e 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -582,6 +582,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id);
>  fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
>  fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
>  fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
> +void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp);
>  
>  /*
>   * Global Function Prototypes in qla_sup.c source file.
> @@ -644,6 +645,8 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
>  
>  extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
>  extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
> +int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt,
> +	struct rsp_que **rsp, u8 *buf, u32 buf_len);
>  
>  /*
>   * Global Function Prototypes in qla_dbg.c source file.
> @@ -929,6 +932,7 @@ extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
>  extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
>  	response_t *);
>  
> +struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha, be_id_t d_id);
>  int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
>  	struct imm_ntfy_from_isp *, int);
>  void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
> @@ -941,7 +945,7 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
>  void qla24xx_delete_sess_fn(struct work_struct *);
>  void qlt_unknown_atio_work_fn(struct work_struct *);
>  void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
> -void qlt_remove_target_resources(struct qla_hw_data *);
> +void qla_remove_hostmap(struct qla_hw_data *ha);
>  void qlt_clr_qp_table(struct scsi_qla_host *vha);
>  void qlt_set_mode(struct scsi_qla_host *);
>  int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
> @@ -961,6 +965,7 @@ 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 qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp);
>  void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
>  
>  #define QLA2XX_HW_ERROR			BIT_0
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index a130a2db2cba..ea7635af03a8 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -169,6 +169,128 @@ qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
>  	dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma);
>  }
>  
> +/* it is assumed pkt is the head iocb, not the continuation iocb */
> +void __qla_consume_iocb(struct scsi_qla_host *vha,
> +	void **pkt, struct rsp_que **rsp)
> +{
> +	struct rsp_que *rsp_q = *rsp;
> +	response_t *new_pkt;
> +	uint16_t entry_count_remaining;
> +	struct purex_entry_24xx *purex = *pkt;
> +
> +	entry_count_remaining = purex->entry_count;
> +	while (entry_count_remaining > 0) {
> +		new_pkt = rsp_q->ring_ptr;
> +		*pkt = new_pkt;
> +
> +		rsp_q->ring_index++;
> +		if (rsp_q->ring_index == rsp_q->length) {
> +			rsp_q->ring_index = 0;
> +			rsp_q->ring_ptr = rsp_q->ring;
> +		} else {
> +			rsp_q->ring_ptr++;
> +		}
> +
> +		new_pkt->signature = RESPONSE_PROCESSED;
> +		// flush signature

No C++ comments, please.

> +		wmb();
> +		--entry_count_remaining;
> +	}
> +}
> +
> +int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
> +	void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
> +{
> +	struct purex_entry_24xx *purex = *pkt;
> +	struct rsp_que *rsp_q = *rsp;
> +	sts_cont_entry_t *new_pkt;
> +	uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
> +	uint16_t buffer_copy_offset = 0;
> +	uint16_t entry_count_remaining;
> +	u16 tpad;
> +
> +	entry_count_remaining = purex->entry_count;
> +	total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
> +		- PURX_ELS_HEADER_SIZE;
> +
> +	/* end of payload may not end in 4bytes boundary.  Need to
> +	 * round up / pad for room to swap, before saving data
> +	 */
> +	tpad = roundup(total_bytes, 4);
> +
> +	if (buf_len < tpad) {
> +		ql_dbg(ql_dbg_async, vha, 0x5084,
> +		    "%s buffer is too small %d < %d\n",
> +		    __func__, buf_len, tpad);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return -EIO;
> +	}
> +
> +	pending_bytes = total_bytes = tpad;
> +	no_bytes = (pending_bytes > sizeof(purex->els_frame_payload))  ?
> +	sizeof(purex->els_frame_payload) : pending_bytes;
> +
> +	memcpy(buf, &purex->els_frame_payload[0], no_bytes);
> +	buffer_copy_offset += no_bytes;
> +	pending_bytes -= no_bytes;
> +	--entry_count_remaining;
> +
> +	((response_t *)purex)->signature = RESPONSE_PROCESSED;
> +	// flush signature

Same here.

> +	wmb();
> +
> +	do {
> +		while ((total_bytes > 0) && (entry_count_remaining > 0)) {
> +			new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
> +			*pkt = new_pkt;
> +
> +			if (new_pkt->entry_type != STATUS_CONT_TYPE) {
> +				ql_log(ql_log_warn, vha, 0x507a,
> +				    "Unexpected IOCB type, partial data 0x%x\n",
> +				    buffer_copy_offset);
> +				break;
> +			}
> +
> +			rsp_q->ring_index++;
> +			if (rsp_q->ring_index == rsp_q->length) {
> +				rsp_q->ring_index = 0;
> +				rsp_q->ring_ptr = rsp_q->ring;
> +			} else {
> +				rsp_q->ring_ptr++;
> +			}
> +			no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
> +			    sizeof(new_pkt->data) : pending_bytes;
> +			if ((buffer_copy_offset + no_bytes) <= total_bytes) {
> +				memcpy((buf + buffer_copy_offset), new_pkt->data,
> +				    no_bytes);
> +				buffer_copy_offset += no_bytes;
> +				pending_bytes -= no_bytes;
> +				--entry_count_remaining;
> +			} else {
> +				ql_log(ql_log_warn, vha, 0x5044,
> +				    "Attempt to copy more that we got, optimizing..%x\n",
> +				    buffer_copy_offset);
> +				memcpy((buf + buffer_copy_offset), new_pkt->data,
> +				    total_bytes - buffer_copy_offset);
> +			}
> +
> +			((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
> +			// flush signature

And here.

> +			wmb();
> +		}
> +
> +		if (pending_bytes != 0 || entry_count_remaining != 0) {
> +			ql_log(ql_log_fatal, vha, 0x508b,
> +			    "Dropping partial Data, underrun bytes = 0x%x, entry cnts 0x%x\n",
> +			    total_bytes, entry_count_remaining);
> +			return -EIO;
> +		}
> +	} while (entry_count_remaining > 0);
> +
> +	be32_to_cpu_array((u32 *)buf, (__be32 *)buf, total_bytes >> 2);
> +	return 0;
> +}
> +
>  /**
>   * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
>   * @irq: interrupt number
> @@ -1727,6 +1849,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
>  	srb_t *sp;
>  	uint16_t index;
>  
> +	if (pkt->handle == QLA_SKIP_HANDLE)
> +		return NULL;
>  	index = LSW(pkt->handle);
>  	if (index >= req->num_outstanding_cmds) {
>  		ql_log(ql_log_warn, vha, 0x5031,
> @@ -3530,6 +3654,55 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
>  	sp->done(sp, comp_status);
>  }
>  
> +/* check for all continuation iocbs are available. */
> +static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
> +	struct rsp_que *rsp, response_t *pkt)
> +{
> +	int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
> +	response_t *end_pkt;
> +	int rc = 0;
> +	u32 rsp_q_in;
> +
> +	if (pkt->entry_count == 1)
> +		return rc;
> +
> +	/* ring_index was pre-increment. set it back to current pkt */
> +	if (rsp->ring_index == 0)
> +		start_pkt_ring_index = rsp->length - 1;
> +	else
> +		start_pkt_ring_index = rsp->ring_index - 1;
> +
> +	if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
> +		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
> +			rsp->length - 1;
> +	else
> +		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
> +
> +	end_pkt = rsp->ring + end_pkt_ring_index;
> +
> +	//  next pkt = end_pkt + 1

I don't think that this serves any purpose ...

> +	n_ring_index = end_pkt_ring_index + 1;
> +	if (n_ring_index >= rsp->length)
> +		n_ring_index = 0;
> +
> +	rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
> +		rd_reg_dword(rsp->rsp_q_in);
> +
> +	/* rsp_q_in is either wrapped or pointing beyond endpkt */
> +	if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
> +			rsp_q_in >= n_ring_index)
> +		// all IOCBs arrived.

No C++ comments, please.

> +		rc = 0;
> +	else
> +		rc = -EIO;
> +
> +	ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
> +		"%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
> +		__func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
> +		rsp_q_in, rc);
> +	return rc;
> +}
> +
>  /**
>   * qla24xx_process_response_queue() - Process response queue entries.
>   * @vha: SCSI driver HA context
> @@ -3670,6 +3843,15 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
>  						 qla27xx_process_purex_fpin);
>  				break;
>  
> +			case ELS_AUTH_ELS:
> +				if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
> +					ql_dbg(ql_dbg_init, vha, 0x5091,
> +					    "Defer processing ELS opcode %#x...\n",
> +					    purex_entry->els_frame_payload[3]);
> +					return;
> +				}
> +				qla24xx_auth_els(vha, (void **)&pkt, &rsp);
> +				break;
>  			default:
>  				ql_log(ql_log_warn, vha, 0x509c,
>  				       "Discarding ELS Request opcode 0x%x\n",
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 5e39977af9ba..6be06b994c43 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -3797,7 +3797,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
>  	qla2x00_free_sysfs_attr(base_vha, true);
>  
>  	fc_remove_host(base_vha->host);
> -	qlt_remove_target_resources(ha);
>  
>  	scsi_remove_host(base_vha->host);
>  
> @@ -3974,15 +3973,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
>  	struct req_que **req, struct rsp_que **rsp)
>  {
>  	char	name[16];
> +	int rc;
>  
>  	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
>  		&ha->init_cb_dma, GFP_KERNEL);
>  	if (!ha->init_cb)
>  		goto fail;
>  
> -	if (qlt_mem_alloc(ha) < 0)
> +	rc = btree_init32(&ha->host_map);
> +	if (rc)
>  		goto fail_free_init_cb;
>  
> +	if (qlt_mem_alloc(ha) < 0)
> +		goto fail_free_btree;
> +
>  	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
>  		qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
>  	if (!ha->gid_list)
> @@ -4386,6 +4390,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
>  	ha->gid_list_dma = 0;
>  fail_free_tgt_mem:
>  	qlt_mem_free(ha);
> +fail_free_btree:
> +	btree_destroy32(&ha->host_map);
>  fail_free_init_cb:
>  	dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
>  	ha->init_cb_dma);
> @@ -4802,6 +4808,7 @@ qla2x00_mem_free(struct qla_hw_data *ha)
>  	ha->dif_bundl_pool = NULL;
>  
>  	qlt_mem_free(ha);
> +	qla_remove_hostmap(ha);
>  
>  	if (ha->init_cb)
>  		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
> diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
> index abf18b88579c..365e64ebef8b 100644
> --- a/drivers/scsi/qla2xxx/qla_target.c
> +++ b/drivers/scsi/qla2xxx/qla_target.c
> @@ -197,7 +197,7 @@ struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha,
>  
>  	key = be_to_port_id(d_id).b24;
>  
> -	host = btree_lookup32(&vha->hw->tgt.host_map, key);
> +	host = btree_lookup32(&vha->hw->host_map, key);
>  	if (!host)
>  		ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
>  		    "Unable to find host %06x\n", key);
> @@ -6442,15 +6442,15 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
>  	return 0;
>  }
>  
> -void qlt_remove_target_resources(struct qla_hw_data *ha)
> +void qla_remove_hostmap(struct qla_hw_data *ha)
>  {
>  	struct scsi_qla_host *node;
>  	u32 key = 0;
>  
> -	btree_for_each_safe32(&ha->tgt.host_map, key, node)
> -		btree_remove32(&ha->tgt.host_map, key);
> +	btree_for_each_safe32(&ha->host_map, key, node)
> +		btree_remove32(&ha->host_map, key);
>  
> -	btree_destroy32(&ha->tgt.host_map);
> +	btree_destroy32(&ha->host_map);
>  }
>  
>  static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
> @@ -7078,8 +7078,7 @@ qlt_modify_vp_config(struct scsi_qla_host *vha,
>  void
>  qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>  {
> -	int rc;
> -
> +	mutex_init(&base_vha->vha_tgt.tgt_mutex);
>  	if (!QLA_TGT_MODE_ENABLED())
>  		return;
>  
> @@ -7092,7 +7091,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>  		ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
>  	}
>  
> -	mutex_init(&base_vha->vha_tgt.tgt_mutex);
>  	mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
>  
>  	INIT_LIST_HEAD(&base_vha->unknown_atio_list);
> @@ -7101,11 +7099,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>  
>  	qlt_clear_mode(base_vha);
>  
> -	rc = btree_init32(&ha->tgt.host_map);
> -	if (rc)
> -		ql_log(ql_log_info, base_vha, 0xd03d,
> -		    "Unable to initialize ha->host_map btree\n");
> -
>  	qlt_update_vp_map(base_vha, SET_VP_IDX);
>  }
>  
> @@ -7226,21 +7219,20 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
>  	u32 key;
>  	int rc;
>  
> -	if (!QLA_TGT_MODE_ENABLED())
> -		return;
> -
>  	key = vha->d_id.b24;
>  
>  	switch (cmd) {
>  	case SET_VP_IDX:
> +		if (!QLA_TGT_MODE_ENABLED())
> +			return;
>  		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
>  		break;
>  	case SET_AL_PA:
> -		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
> +		slot = btree_lookup32(&vha->hw->host_map, key);
>  		if (!slot) {
>  			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
>  			    "Save vha in host_map %p %06x\n", vha, key);
> -			rc = btree_insert32(&vha->hw->tgt.host_map,
> +			rc = btree_insert32(&vha->hw->host_map,
>  				key, vha, GFP_ATOMIC);
>  			if (rc)
>  				ql_log(ql_log_info, vha, 0xd03e,
> @@ -7250,17 +7242,19 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
>  		}
>  		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
>  		    "replace existing vha in host_map %p %06x\n", vha, key);
> -		btree_update32(&vha->hw->tgt.host_map, key, vha);
> +		btree_update32(&vha->hw->host_map, key, vha);
>  		break;
>  	case RESET_VP_IDX:
> +		if (!QLA_TGT_MODE_ENABLED())
> +			return;
>  		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
>  		break;
>  	case RESET_AL_PA:
>  		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
>  		   "clear vha in host_map %p %06x\n", vha, key);
> -		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
> +		slot = btree_lookup32(&vha->hw->host_map, key);
>  		if (slot)
> -			btree_remove32(&vha->hw->tgt.host_map, key);
> +			btree_remove32(&vha->hw->host_map, key);
>  		vha->d_id.b24 = 0;
>  		break;
>  	}
> 
Cheers,

Hannes
Himanshu Madhani June 3, 2021, 9:10 p.m. UTC | #2
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.
> 

^^^  I see this paragraph repeated for all 1-9 patches. I would like you 
to clean up and use only changes to the patch in the commit message. 
You can always reference EDIF feature in commit message but don't have 
to copy same test to all 9  patches.

> This patch is a continuation of previous patch where
> authentication messages sent from remote device has arrived.
> Each message is extracted and placed in a buffer for application
> to retrieve. The FC frame header will be stripped leaving
> behind the AUTH ELS payload. It is up to the application
> to strip the AUTH ELS header to get to the actual authentication
> message.
> 
> 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/qla_def.h    |   2 +-
>   drivers/scsi/qla2xxx/qla_edif.c   | 191 ++++++++++++++++++++++++++++++
>   drivers/scsi/qla2xxx/qla_gbl.h    |   7 +-
>   drivers/scsi/qla2xxx/qla_isr.c    | 182 ++++++++++++++++++++++++++++
>   drivers/scsi/qla2xxx/qla_os.c     |  11 +-
>   drivers/scsi/qla2xxx/qla_target.c |  36 +++---
>   6 files changed, 404 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 517a4a4c178e..e47a7b3618d6 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -3907,7 +3907,6 @@ struct qlt_hw_data {
>   	int num_act_qpairs;
>   #define DEFAULT_NAQP 2
>   	spinlock_t atio_lock ____cacheline_aligned;
> -	struct btree_head32 host_map;
>   };
>   
>   #define MAX_QFULL_CMDS_ALLOC	8192
> @@ -4682,6 +4681,7 @@ struct qla_hw_data {
>   	struct qla_hw_data_stat stat;
>   	pci_error_state_t pci_error_state;
>   	struct dma_pool *purex_dma_pool;
> +	struct btree_head32 host_map;
>   	struct els_reject elsrej;
>   };
>   
> diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
> index 4c788f4588ca..df8dff447c6a 100644
> --- a/drivers/scsi/qla2xxx/qla_edif.c
> +++ b/drivers/scsi/qla2xxx/qla_edif.c
> @@ -684,6 +684,44 @@ qla_enode_stop(scsi_qla_host_t *vha)
>    *  returns: enode pointer with buffers
>    *           NULL on error
>    */
> +static struct enode *
> +qla_enode_alloc(scsi_qla_host_t *vha, uint32_t ntype)
> +{
> +	struct enode		*node;
> +	struct purexevent	*purex;
> +
> +	node = kzalloc(RX_ELS_SIZE, GFP_ATOMIC);
> +	if (!node)
> +		return NULL;
> +
> +	purex = &node->u.purexinfo;
> +	purex->msgp = (u8 *)(node + 1);
> +	purex->msgp_len = ELS_MAX_PAYLOAD;
> +
> +	node->dinfo.lstate = LSTATE_OFF;
> +
> +	node->ntype = ntype;
> +	INIT_LIST_HEAD(&node->list);
> +	return node;
> +}
> +
> +/* adds a already alllocated enode to the linked list */
> +static bool
> +qla_enode_add(scsi_qla_host_t *vha, struct enode *ptr)
> +{
> +	unsigned long flags;
> +
> +	ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x9109,
> +	    "%s add enode for type=%x, cnt=%x\n",
> +	    __func__, ptr->ntype, ptr->dinfo.nodecnt);
> +
> +	spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
> +	ptr->dinfo.lstate = LSTATE_ON;
> +	list_add_tail(&ptr->list, &vha->pur_cinfo.head);
> +	spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
> +
> +	return true;
> +}
>   
>   static struct enode *
>   qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2)
> @@ -783,6 +821,32 @@ qla_pur_get_pending(scsi_qla_host_t *vha, fc_port_t *fcport, struct bsg_job *bsg
>   
>   	return 0;
>   }
> +
> +/* it is assume qpair lock is held */
> +static int
> +qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp,
> +	struct qla_els_pt_arg *a)
> +{
> +	struct els_entry_24xx *els_iocb;
> +
> +	els_iocb = __qla2x00_alloc_iocbs(qp, NULL);
> +	if (!els_iocb) {
> +		ql_log(ql_log_warn, vha, 0x700c,
> +		    "qla2x00_alloc_iocbs failed.\n");
> +		return QLA_FUNCTION_FAILED;
> +	}
> +
> +	qla_els_pt_iocb(vha, els_iocb, a);
> +
> +	ql_dbg(ql_dbg_edif, vha, 0x0183,
> +	    "Sending ELS reject...\n");
> +	ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185,
> +	    vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c));
> +	/* -- */
> +	wmb();
> +	qla2x00_start_iocbs(vha, qp->req);
> +	return 0;
> +}
>   /* function called when app is stopping */
>   
>   void
> @@ -796,6 +860,133 @@ qla_edb_stop(scsi_qla_host_t *vha)
>   	}
>   }
>   
> +void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
> +{
> +	struct purex_entry_24xx *p = *pkt;
> +	struct enode		*ptr;
> +	int		sid;
> +	u16 totlen;
> +	struct purexevent	*purex;
> +	struct scsi_qla_host *host = NULL;
> +	int rc;
> +	struct fc_port *fcport;
> +	struct qla_els_pt_arg a;
> +	be_id_t beid;
> +
> +	memset(&a, 0, sizeof(a));
> +
> +	a.els_opcode = ELS_AUTH_ELS;
> +	a.nport_handle = p->nport_handle;
> +	a.rx_xchg_address = p->rx_xchg_addr;
> +	a.did.b.domain = p->s_id[2];
> +	a.did.b.area   = p->s_id[1];
> +	a.did.b.al_pa  = p->s_id[0];
> +	a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);
> +	a.tx_addr = vha->hw->elsrej.cdma;
> +	a.vp_idx = vha->vp_idx;
> +	a.control_flags = EPD_ELS_RJT;
> +
> +	sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);
> +	/*
> +	 * ql_dbg(ql_dbg_edif, vha, 0x09108,
> +	 *	  "%s rec'vd sid=0x%x\n", __func__, sid);
> +	 */
> +

Why not use ql_dbg(ql_dbg_edif + ql_dbg_verbose) option.

if this was just for development debugging then remove it rather than 
leaving it commented out.


> +	totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
> +	if (le16_to_cpu(p->status_flags) & 0x8000) {
> +		totlen = le16_to_cpu(p->trunc_frame_size);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	if (totlen > MAX_PAYLOAD) {
> +		ql_dbg(ql_dbg_edif, vha, 0x0910d,
> +		    "%s WARNING: verbose ELS frame received (totlen=%x)\n",
> +		    __func__, totlen);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	if (!vha->hw->flags.edif_enabled) {
> +		/* edif support not enabled */
> +		ql_dbg(ql_dbg_edif, vha, 0x910e, "%s edif not enabled\n",
> +		    __func__);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	ptr = qla_enode_alloc(vha, N_PUREX);
> +	if (!ptr) {
> +		ql_dbg(ql_dbg_edif, vha, 0x09109,
> +		    "WARNING: enode allloc failed for sid=%x\n",
> +		    sid);
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return;
> +	}
> +
> +	purex = &ptr->u.purexinfo;
> +	purex->pur_info.pur_sid = a.did;
> +	purex->pur_info.pur_pend = 0;
> +	purex->pur_info.pur_bytes_rcvd = totlen;
> +	purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);
> +	purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);
> +	purex->pur_info.pur_did.b.domain =  p->d_id[2];
> +	purex->pur_info.pur_did.b.area =  p->d_id[1];
> +	purex->pur_info.pur_did.b.al_pa =  p->d_id[0];
> +	purex->pur_info.vp_idx = p->vp_idx;
> +
> +	rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp,
> +		purex->msgp_len);
> +	if (rc) {
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		qla_enode_free(vha, ptr);
> +		return;
> +	}
> +	/*
> +	 * ql_dump_buffer(ql_dbg_edif, vha, 0x70e0,
> +	 *   purex->msgp, purex->pur_info.pur_bytes_rcvd);
> +	 */

Ditto here.. why not use ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose) 
option. you might want to know buffer content while debugging EDIF issues.

> +	beid.al_pa = purex->pur_info.pur_did.b.al_pa;
> +	beid.area   = purex->pur_info.pur_did.b.area;
> +	beid.domain = purex->pur_info.pur_did.b.domain;
> +	host = qla_find_host_by_d_id(vha, beid);
> +	if (!host) {
> +		ql_log(ql_log_fatal, vha, 0x508b,
> +		    "%s Drop ELS due to unable to find host %06x\n",
> +		    __func__, purex->pur_info.pur_did.b24);
> +
> +		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
> +		qla_enode_free(vha, ptr);
> +		return;
> +	}
> +
> +	fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);
> +
> +	if (host->e_dbell.db_flags != EDB_ACTIVE ||
> +	    (fcport && fcport->loop_id == FC_NO_LOOP_ID)) {
> +		ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",
> +		    __func__, host->e_dbell.db_flags,
> +		    fcport ? fcport->d_id.b24 : 0);
> +
> +		qla_els_reject_iocb(host, (*rsp)->qpair, &a);
> +		qla_enode_free(host, ptr);
> +		return;
> +	}
> +
> +	/* add the local enode to the list */
> +	qla_enode_add(host, ptr);
> +
> +	ql_dbg(ql_dbg_edif, host, 0x0910c,
> +	    "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
> +	    __func__, purex->pur_info.pur_bytes_rcvd,
> +	    purex->pur_info.pur_sid.b24,
> +	    purex->pur_info.pur_did.b24, p->rx_xchg_addr);
> +}
> +
>   static void qla_parse_auth_els_ctl(struct srb *sp)
>   {
>   	struct qla_els_pt_arg *a = &sp->u.bsg_cmd.u.els_arg;
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 7ff05aa10b2d..a4cb8092e97e 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -582,6 +582,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id);
>   fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
>   fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
>   fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
> +void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp);
>   
>   /*
>    * Global Function Prototypes in qla_sup.c source file.
> @@ -644,6 +645,8 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
>   
>   extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
>   extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
> +int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt,
> +	struct rsp_que **rsp, u8 *buf, u32 buf_len);
>   
>   /*
>    * Global Function Prototypes in qla_dbg.c source file.
> @@ -929,6 +932,7 @@ extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
>   extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
>   	response_t *);
>   
> +struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha, be_id_t d_id);
>   int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
>   	struct imm_ntfy_from_isp *, int);
>   void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
> @@ -941,7 +945,7 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
>   void qla24xx_delete_sess_fn(struct work_struct *);
>   void qlt_unknown_atio_work_fn(struct work_struct *);
>   void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
> -void qlt_remove_target_resources(struct qla_hw_data *);
> +void qla_remove_hostmap(struct qla_hw_data *ha);
>   void qlt_clr_qp_table(struct scsi_qla_host *vha);
>   void qlt_set_mode(struct scsi_qla_host *);
>   int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
> @@ -961,6 +965,7 @@ 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 qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp);
>   void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
>   
>   #define QLA2XX_HW_ERROR			BIT_0
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index a130a2db2cba..ea7635af03a8 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -169,6 +169,128 @@ qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
>   	dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma);
>   }
>   
> +/* it is assumed pkt is the head iocb, not the continuation iocb */
> +void __qla_consume_iocb(struct scsi_qla_host *vha,
> +	void **pkt, struct rsp_que **rsp)
> +{
> +	struct rsp_que *rsp_q = *rsp;
> +	response_t *new_pkt;
> +	uint16_t entry_count_remaining;
> +	struct purex_entry_24xx *purex = *pkt;
> +
> +	entry_count_remaining = purex->entry_count;
> +	while (entry_count_remaining > 0) {
> +		new_pkt = rsp_q->ring_ptr;
> +		*pkt = new_pkt;
> +
> +		rsp_q->ring_index++;
> +		if (rsp_q->ring_index == rsp_q->length) {
> +			rsp_q->ring_index = 0;
> +			rsp_q->ring_ptr = rsp_q->ring;
> +		} else {
> +			rsp_q->ring_ptr++;
> +		}
> +
> +		new_pkt->signature = RESPONSE_PROCESSED;
> +		// flush signature

remove this comment.

> +		wmb();
> +		--entry_count_remaining;
> +	}
> +}
> +
> +int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
> +	void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
> +{
> +	struct purex_entry_24xx *purex = *pkt;
> +	struct rsp_que *rsp_q = *rsp;
> +	sts_cont_entry_t *new_pkt;
> +	uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
> +	uint16_t buffer_copy_offset = 0;
> +	uint16_t entry_count_remaining;
> +	u16 tpad;
> +
> +	entry_count_remaining = purex->entry_count;
> +	total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
> +		- PURX_ELS_HEADER_SIZE;
> +
> +	/* end of payload may not end in 4bytes boundary.  Need to
> +	 * round up / pad for room to swap, before saving data
> +	 */

fix comment style

> +	tpad = roundup(total_bytes, 4);
> +
> +	if (buf_len < tpad) {
> +		ql_dbg(ql_dbg_async, vha, 0x5084,
> +		    "%s buffer is too small %d < %d\n",
> +		    __func__, buf_len, tpad);
> +		__qla_consume_iocb(vha, pkt, rsp);
> +		return -EIO;
> +	}
> +
> +	pending_bytes = total_bytes = tpad;
> +	no_bytes = (pending_bytes > sizeof(purex->els_frame_payload))  ?
> +	sizeof(purex->els_frame_payload) : pending_bytes;

use proper indentation

> +	memcpy(buf, &purex->els_frame_payload[0], no_bytes);
> +	buffer_copy_offset += no_bytes;
> +	pending_bytes -= no_bytes;
> +	--entry_count_remaining;
> +
> +	((response_t *)purex)->signature = RESPONSE_PROCESSED;
> +	// flush signature

remove or fix style

> +	wmb();
> +
> +	do {
> +		while ((total_bytes > 0) && (entry_count_remaining > 0)) {
> +			new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
> +			*pkt = new_pkt;
> +
> +			if (new_pkt->entry_type != STATUS_CONT_TYPE) {
> +				ql_log(ql_log_warn, vha, 0x507a,
> +				    "Unexpected IOCB type, partial data 0x%x\n",
> +				    buffer_copy_offset);
> +				break;
> +			}
> +
> +			rsp_q->ring_index++;
> +			if (rsp_q->ring_index == rsp_q->length) {
> +				rsp_q->ring_index = 0;
> +				rsp_q->ring_ptr = rsp_q->ring;
> +			} else {
> +				rsp_q->ring_ptr++;
> +			}
> +			no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
> +			    sizeof(new_pkt->data) : pending_bytes;
> +			if ((buffer_copy_offset + no_bytes) <= total_bytes) {
> +				memcpy((buf + buffer_copy_offset), new_pkt->data,
> +				    no_bytes);
> +				buffer_copy_offset += no_bytes;
> +				pending_bytes -= no_bytes;
> +				--entry_count_remaining;
> +			} else {
> +				ql_log(ql_log_warn, vha, 0x5044,
> +				    "Attempt to copy more that we got, optimizing..%x\n",
> +				    buffer_copy_offset);
> +				memcpy((buf + buffer_copy_offset), new_pkt->data,
> +				    total_bytes - buffer_copy_offset);
> +			}
> +
> +			((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
> +			// flush signature

ditto here... remove or fix comment style

> +			wmb();
> +		}
> +
> +		if (pending_bytes != 0 || entry_count_remaining != 0) {
> +			ql_log(ql_log_fatal, vha, 0x508b,
> +			    "Dropping partial Data, underrun bytes = 0x%x, entry cnts 0x%x\n",
> +			    total_bytes, entry_count_remaining);
> +			return -EIO;
> +		}
> +	} while (entry_count_remaining > 0);
> +
> +	be32_to_cpu_array((u32 *)buf, (__be32 *)buf, total_bytes >> 2);

need new line here

> +	return 0;
> +}
> +
>   /**
>    * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
>    * @irq: interrupt number
> @@ -1727,6 +1849,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
>   	srb_t *sp;
>   	uint16_t index;
>   
> +	if (pkt->handle == QLA_SKIP_HANDLE)
> +		return NULL;

need new line here

>   	index = LSW(pkt->handle);
>   	if (index >= req->num_outstanding_cmds) {
>   		ql_log(ql_log_warn, vha, 0x5031,
> @@ -3530,6 +3654,55 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
>   	sp->done(sp, comp_status);
>   }
>   
> +/* check for all continuation iocbs are available. */
> +static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
> +	struct rsp_que *rsp, response_t *pkt)
> +{
> +	int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
> +	response_t *end_pkt;
> +	int rc = 0;
> +	u32 rsp_q_in;
> +
> +	if (pkt->entry_count == 1)
> +		return rc;
> +
> +	/* ring_index was pre-increment. set it back to current pkt */
> +	if (rsp->ring_index == 0)
> +		start_pkt_ring_index = rsp->length - 1;
> +	else
> +		start_pkt_ring_index = rsp->ring_index - 1;
> +
> +	if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
> +		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
> +			rsp->length - 1;
> +	else
> +		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
> +
> +	end_pkt = rsp->ring + end_pkt_ring_index;
> +
> +	//  next pkt = end_pkt + 1

remove debug code

> +	n_ring_index = end_pkt_ring_index + 1;
> +	if (n_ring_index >= rsp->length)
> +		n_ring_index = 0;
> +
> +	rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
> +		rd_reg_dword(rsp->rsp_q_in);
> +
> +	/* rsp_q_in is either wrapped or pointing beyond endpkt */
> +	if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
> +			rsp_q_in >= n_ring_index)
> +		// all IOCBs arrived.
remove comment
> +		rc = 0;
> +	else
> +		rc = -EIO;
> +
> +	ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
> +		"%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
> +		__func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
> +		rsp_q_in, rc);

need a new line here

> +	return rc;
> +}
> +
>   /**
>    * qla24xx_process_response_queue() - Process response queue entries.
>    * @vha: SCSI driver HA context
> @@ -3670,6 +3843,15 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
>   						 qla27xx_process_purex_fpin);
>   				break;
>   
> +			case ELS_AUTH_ELS:
> +				if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
> +					ql_dbg(ql_dbg_init, vha, 0x5091,
> +					    "Defer processing ELS opcode %#x...\n",
> +					    purex_entry->els_frame_payload[3]);
> +					return;
> +				}
> +				qla24xx_auth_els(vha, (void **)&pkt, &rsp);
> +				break;
>   			default:
>   				ql_log(ql_log_warn, vha, 0x509c,
>   				       "Discarding ELS Request opcode 0x%x\n",
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 5e39977af9ba..6be06b994c43 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -3797,7 +3797,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
>   	qla2x00_free_sysfs_attr(base_vha, true);
>   
>   	fc_remove_host(base_vha->host);
> -	qlt_remove_target_resources(ha);
>   
>   	scsi_remove_host(base_vha->host);
>   
> @@ -3974,15 +3973,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
>   	struct req_que **req, struct rsp_que **rsp)
>   {
>   	char	name[16];
> +	int rc;
>   
>   	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
>   		&ha->init_cb_dma, GFP_KERNEL);
>   	if (!ha->init_cb)
>   		goto fail;
>   
> -	if (qlt_mem_alloc(ha) < 0)
> +	rc = btree_init32(&ha->host_map);
> +	if (rc)
>   		goto fail_free_init_cb;
>   
> +	if (qlt_mem_alloc(ha) < 0)
> +		goto fail_free_btree;
> +
>   	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
>   		qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
>   	if (!ha->gid_list)
> @@ -4386,6 +4390,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
>   	ha->gid_list_dma = 0;
>   fail_free_tgt_mem:
>   	qlt_mem_free(ha);
> +fail_free_btree:
> +	btree_destroy32(&ha->host_map);
>   fail_free_init_cb:
>   	dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
>   	ha->init_cb_dma);
> @@ -4802,6 +4808,7 @@ qla2x00_mem_free(struct qla_hw_data *ha)
>   	ha->dif_bundl_pool = NULL;
>   
>   	qlt_mem_free(ha);
> +	qla_remove_hostmap(ha);
>   
>   	if (ha->init_cb)
>   		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
> diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
> index abf18b88579c..365e64ebef8b 100644
> --- a/drivers/scsi/qla2xxx/qla_target.c
> +++ b/drivers/scsi/qla2xxx/qla_target.c
> @@ -197,7 +197,7 @@ struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha,
>   
>   	key = be_to_port_id(d_id).b24;
>   
> -	host = btree_lookup32(&vha->hw->tgt.host_map, key);
> +	host = btree_lookup32(&vha->hw->host_map, key);
>   	if (!host)
>   		ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
>   		    "Unable to find host %06x\n", key);
> @@ -6442,15 +6442,15 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
>   	return 0;
>   }
>   
> -void qlt_remove_target_resources(struct qla_hw_data *ha)
> +void qla_remove_hostmap(struct qla_hw_data *ha)
>   {
>   	struct scsi_qla_host *node;
>   	u32 key = 0;
>   
> -	btree_for_each_safe32(&ha->tgt.host_map, key, node)
> -		btree_remove32(&ha->tgt.host_map, key);
> +	btree_for_each_safe32(&ha->host_map, key, node)
> +		btree_remove32(&ha->host_map, key);
>   
> -	btree_destroy32(&ha->tgt.host_map);
> +	btree_destroy32(&ha->host_map);
>   }
>   
>   static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
> @@ -7078,8 +7078,7 @@ qlt_modify_vp_config(struct scsi_qla_host *vha,
>   void
>   qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>   {
> -	int rc;
> -
> +	mutex_init(&base_vha->vha_tgt.tgt_mutex);
>   	if (!QLA_TGT_MODE_ENABLED())
>   		return;
>   
> @@ -7092,7 +7091,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>   		ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
>   	}
>   
> -	mutex_init(&base_vha->vha_tgt.tgt_mutex);
>   	mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
>   
>   	INIT_LIST_HEAD(&base_vha->unknown_atio_list);
> @@ -7101,11 +7099,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
>   
>   	qlt_clear_mode(base_vha);
>   
> -	rc = btree_init32(&ha->tgt.host_map);
> -	if (rc)
> -		ql_log(ql_log_info, base_vha, 0xd03d,
> -		    "Unable to initialize ha->host_map btree\n");
> -
>   	qlt_update_vp_map(base_vha, SET_VP_IDX);
>   }
>   
> @@ -7226,21 +7219,20 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
>   	u32 key;
>   	int rc;
>   
> -	if (!QLA_TGT_MODE_ENABLED())
> -		return;
> -
>   	key = vha->d_id.b24;
>   
>   	switch (cmd) {
>   	case SET_VP_IDX:
> +		if (!QLA_TGT_MODE_ENABLED())
> +			return;
>   		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
>   		break;
>   	case SET_AL_PA:
> -		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
> +		slot = btree_lookup32(&vha->hw->host_map, key);
>   		if (!slot) {
>   			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
>   			    "Save vha in host_map %p %06x\n", vha, key);
> -			rc = btree_insert32(&vha->hw->tgt.host_map,
> +			rc = btree_insert32(&vha->hw->host_map,
>   				key, vha, GFP_ATOMIC);
>   			if (rc)
>   				ql_log(ql_log_info, vha, 0xd03e,
> @@ -7250,17 +7242,19 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
>   		}
>   		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
>   		    "replace existing vha in host_map %p %06x\n", vha, key);
> -		btree_update32(&vha->hw->tgt.host_map, key, vha);
> +		btree_update32(&vha->hw->host_map, key, vha);
>   		break;
>   	case RESET_VP_IDX:
> +		if (!QLA_TGT_MODE_ENABLED())
> +			return;
>   		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
>   		break;
>   	case RESET_AL_PA:
>   		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
>   		   "clear vha in host_map %p %06x\n", vha, key);
> -		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
> +		slot = btree_lookup32(&vha->hw->host_map, key);
>   		if (slot)
> -			btree_remove32(&vha->hw->tgt.host_map, key);
> +			btree_remove32(&vha->hw->host_map, key);
>   		vha->d_id.b24 = 0;
>   		break;
>   	}
>
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 517a4a4c178e..e47a7b3618d6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3907,7 +3907,6 @@  struct qlt_hw_data {
 	int num_act_qpairs;
 #define DEFAULT_NAQP 2
 	spinlock_t atio_lock ____cacheline_aligned;
-	struct btree_head32 host_map;
 };
 
 #define MAX_QFULL_CMDS_ALLOC	8192
@@ -4682,6 +4681,7 @@  struct qla_hw_data {
 	struct qla_hw_data_stat stat;
 	pci_error_state_t pci_error_state;
 	struct dma_pool *purex_dma_pool;
+	struct btree_head32 host_map;
 	struct els_reject elsrej;
 };
 
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
index 4c788f4588ca..df8dff447c6a 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -684,6 +684,44 @@  qla_enode_stop(scsi_qla_host_t *vha)
  *  returns: enode pointer with buffers
  *           NULL on error
  */
+static struct enode *
+qla_enode_alloc(scsi_qla_host_t *vha, uint32_t ntype)
+{
+	struct enode		*node;
+	struct purexevent	*purex;
+
+	node = kzalloc(RX_ELS_SIZE, GFP_ATOMIC);
+	if (!node)
+		return NULL;
+
+	purex = &node->u.purexinfo;
+	purex->msgp = (u8 *)(node + 1);
+	purex->msgp_len = ELS_MAX_PAYLOAD;
+
+	node->dinfo.lstate = LSTATE_OFF;
+
+	node->ntype = ntype;
+	INIT_LIST_HEAD(&node->list);
+	return node;
+}
+
+/* adds a already alllocated enode to the linked list */
+static bool
+qla_enode_add(scsi_qla_host_t *vha, struct enode *ptr)
+{
+	unsigned long flags;
+
+	ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x9109,
+	    "%s add enode for type=%x, cnt=%x\n",
+	    __func__, ptr->ntype, ptr->dinfo.nodecnt);
+
+	spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
+	ptr->dinfo.lstate = LSTATE_ON;
+	list_add_tail(&ptr->list, &vha->pur_cinfo.head);
+	spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
+
+	return true;
+}
 
 static struct enode *
 qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2)
@@ -783,6 +821,32 @@  qla_pur_get_pending(scsi_qla_host_t *vha, fc_port_t *fcport, struct bsg_job *bsg
 
 	return 0;
 }
+
+/* it is assume qpair lock is held */
+static int
+qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp,
+	struct qla_els_pt_arg *a)
+{
+	struct els_entry_24xx *els_iocb;
+
+	els_iocb = __qla2x00_alloc_iocbs(qp, NULL);
+	if (!els_iocb) {
+		ql_log(ql_log_warn, vha, 0x700c,
+		    "qla2x00_alloc_iocbs failed.\n");
+		return QLA_FUNCTION_FAILED;
+	}
+
+	qla_els_pt_iocb(vha, els_iocb, a);
+
+	ql_dbg(ql_dbg_edif, vha, 0x0183,
+	    "Sending ELS reject...\n");
+	ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185,
+	    vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c));
+	/* -- */
+	wmb();
+	qla2x00_start_iocbs(vha, qp->req);
+	return 0;
+}
 /* function called when app is stopping */
 
 void
@@ -796,6 +860,133 @@  qla_edb_stop(scsi_qla_host_t *vha)
 	}
 }
 
+void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
+{
+	struct purex_entry_24xx *p = *pkt;
+	struct enode		*ptr;
+	int		sid;
+	u16 totlen;
+	struct purexevent	*purex;
+	struct scsi_qla_host *host = NULL;
+	int rc;
+	struct fc_port *fcport;
+	struct qla_els_pt_arg a;
+	be_id_t beid;
+
+	memset(&a, 0, sizeof(a));
+
+	a.els_opcode = ELS_AUTH_ELS;
+	a.nport_handle = p->nport_handle;
+	a.rx_xchg_address = p->rx_xchg_addr;
+	a.did.b.domain = p->s_id[2];
+	a.did.b.area   = p->s_id[1];
+	a.did.b.al_pa  = p->s_id[0];
+	a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);
+	a.tx_addr = vha->hw->elsrej.cdma;
+	a.vp_idx = vha->vp_idx;
+	a.control_flags = EPD_ELS_RJT;
+
+	sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);
+	/*
+	 * ql_dbg(ql_dbg_edif, vha, 0x09108,
+	 *	  "%s rec'vd sid=0x%x\n", __func__, sid);
+	 */
+
+	totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
+	if (le16_to_cpu(p->status_flags) & 0x8000) {
+		totlen = le16_to_cpu(p->trunc_frame_size);
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		__qla_consume_iocb(vha, pkt, rsp);
+		return;
+	}
+
+	if (totlen > MAX_PAYLOAD) {
+		ql_dbg(ql_dbg_edif, vha, 0x0910d,
+		    "%s WARNING: verbose ELS frame received (totlen=%x)\n",
+		    __func__, totlen);
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		__qla_consume_iocb(vha, pkt, rsp);
+		return;
+	}
+
+	if (!vha->hw->flags.edif_enabled) {
+		/* edif support not enabled */
+		ql_dbg(ql_dbg_edif, vha, 0x910e, "%s edif not enabled\n",
+		    __func__);
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		__qla_consume_iocb(vha, pkt, rsp);
+		return;
+	}
+
+	ptr = qla_enode_alloc(vha, N_PUREX);
+	if (!ptr) {
+		ql_dbg(ql_dbg_edif, vha, 0x09109,
+		    "WARNING: enode allloc failed for sid=%x\n",
+		    sid);
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		__qla_consume_iocb(vha, pkt, rsp);
+		return;
+	}
+
+	purex = &ptr->u.purexinfo;
+	purex->pur_info.pur_sid = a.did;
+	purex->pur_info.pur_pend = 0;
+	purex->pur_info.pur_bytes_rcvd = totlen;
+	purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);
+	purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);
+	purex->pur_info.pur_did.b.domain =  p->d_id[2];
+	purex->pur_info.pur_did.b.area =  p->d_id[1];
+	purex->pur_info.pur_did.b.al_pa =  p->d_id[0];
+	purex->pur_info.vp_idx = p->vp_idx;
+
+	rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp,
+		purex->msgp_len);
+	if (rc) {
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		qla_enode_free(vha, ptr);
+		return;
+	}
+	/*
+	 * ql_dump_buffer(ql_dbg_edif, vha, 0x70e0,
+	 *   purex->msgp, purex->pur_info.pur_bytes_rcvd);
+	 */
+	beid.al_pa = purex->pur_info.pur_did.b.al_pa;
+	beid.area   = purex->pur_info.pur_did.b.area;
+	beid.domain = purex->pur_info.pur_did.b.domain;
+	host = qla_find_host_by_d_id(vha, beid);
+	if (!host) {
+		ql_log(ql_log_fatal, vha, 0x508b,
+		    "%s Drop ELS due to unable to find host %06x\n",
+		    __func__, purex->pur_info.pur_did.b24);
+
+		qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+		qla_enode_free(vha, ptr);
+		return;
+	}
+
+	fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);
+
+	if (host->e_dbell.db_flags != EDB_ACTIVE ||
+	    (fcport && fcport->loop_id == FC_NO_LOOP_ID)) {
+		ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",
+		    __func__, host->e_dbell.db_flags,
+		    fcport ? fcport->d_id.b24 : 0);
+
+		qla_els_reject_iocb(host, (*rsp)->qpair, &a);
+		qla_enode_free(host, ptr);
+		return;
+	}
+
+	/* add the local enode to the list */
+	qla_enode_add(host, ptr);
+
+	ql_dbg(ql_dbg_edif, host, 0x0910c,
+	    "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
+	    __func__, purex->pur_info.pur_bytes_rcvd,
+	    purex->pur_info.pur_sid.b24,
+	    purex->pur_info.pur_did.b24, p->rx_xchg_addr);
+}
+
 static void qla_parse_auth_els_ctl(struct srb *sp)
 {
 	struct qla_els_pt_arg *a = &sp->u.bsg_cmd.u.els_arg;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7ff05aa10b2d..a4cb8092e97e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -582,6 +582,7 @@  qla2xxx_msix_rsp_q_hs(int irq, void *dev_id);
 fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
 fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
 fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
+void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp);
 
 /*
  * Global Function Prototypes in qla_sup.c source file.
@@ -644,6 +645,8 @@  extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
 
 extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
 extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
+int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt,
+	struct rsp_que **rsp, u8 *buf, u32 buf_len);
 
 /*
  * Global Function Prototypes in qla_dbg.c source file.
@@ -929,6 +932,7 @@  extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
 extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
 	response_t *);
 
+struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha, be_id_t d_id);
 int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 	struct imm_ntfy_from_isp *, int);
 void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
@@ -941,7 +945,7 @@  extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
 void qla24xx_delete_sess_fn(struct work_struct *);
 void qlt_unknown_atio_work_fn(struct work_struct *);
 void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
-void qlt_remove_target_resources(struct qla_hw_data *);
+void qla_remove_hostmap(struct qla_hw_data *ha);
 void qlt_clr_qp_table(struct scsi_qla_host *vha);
 void qlt_set_mode(struct scsi_qla_host *);
 int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
@@ -961,6 +965,7 @@  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 qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp);
 void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
 
 #define QLA2XX_HW_ERROR			BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a130a2db2cba..ea7635af03a8 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -169,6 +169,128 @@  qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
 	dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma);
 }
 
+/* it is assumed pkt is the head iocb, not the continuation iocb */
+void __qla_consume_iocb(struct scsi_qla_host *vha,
+	void **pkt, struct rsp_que **rsp)
+{
+	struct rsp_que *rsp_q = *rsp;
+	response_t *new_pkt;
+	uint16_t entry_count_remaining;
+	struct purex_entry_24xx *purex = *pkt;
+
+	entry_count_remaining = purex->entry_count;
+	while (entry_count_remaining > 0) {
+		new_pkt = rsp_q->ring_ptr;
+		*pkt = new_pkt;
+
+		rsp_q->ring_index++;
+		if (rsp_q->ring_index == rsp_q->length) {
+			rsp_q->ring_index = 0;
+			rsp_q->ring_ptr = rsp_q->ring;
+		} else {
+			rsp_q->ring_ptr++;
+		}
+
+		new_pkt->signature = RESPONSE_PROCESSED;
+		// flush signature
+		wmb();
+		--entry_count_remaining;
+	}
+}
+
+int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
+	void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
+{
+	struct purex_entry_24xx *purex = *pkt;
+	struct rsp_que *rsp_q = *rsp;
+	sts_cont_entry_t *new_pkt;
+	uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
+	uint16_t buffer_copy_offset = 0;
+	uint16_t entry_count_remaining;
+	u16 tpad;
+
+	entry_count_remaining = purex->entry_count;
+	total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
+		- PURX_ELS_HEADER_SIZE;
+
+	/* end of payload may not end in 4bytes boundary.  Need to
+	 * round up / pad for room to swap, before saving data
+	 */
+	tpad = roundup(total_bytes, 4);
+
+	if (buf_len < tpad) {
+		ql_dbg(ql_dbg_async, vha, 0x5084,
+		    "%s buffer is too small %d < %d\n",
+		    __func__, buf_len, tpad);
+		__qla_consume_iocb(vha, pkt, rsp);
+		return -EIO;
+	}
+
+	pending_bytes = total_bytes = tpad;
+	no_bytes = (pending_bytes > sizeof(purex->els_frame_payload))  ?
+	sizeof(purex->els_frame_payload) : pending_bytes;
+
+	memcpy(buf, &purex->els_frame_payload[0], no_bytes);
+	buffer_copy_offset += no_bytes;
+	pending_bytes -= no_bytes;
+	--entry_count_remaining;
+
+	((response_t *)purex)->signature = RESPONSE_PROCESSED;
+	// flush signature
+	wmb();
+
+	do {
+		while ((total_bytes > 0) && (entry_count_remaining > 0)) {
+			new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
+			*pkt = new_pkt;
+
+			if (new_pkt->entry_type != STATUS_CONT_TYPE) {
+				ql_log(ql_log_warn, vha, 0x507a,
+				    "Unexpected IOCB type, partial data 0x%x\n",
+				    buffer_copy_offset);
+				break;
+			}
+
+			rsp_q->ring_index++;
+			if (rsp_q->ring_index == rsp_q->length) {
+				rsp_q->ring_index = 0;
+				rsp_q->ring_ptr = rsp_q->ring;
+			} else {
+				rsp_q->ring_ptr++;
+			}
+			no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
+			    sizeof(new_pkt->data) : pending_bytes;
+			if ((buffer_copy_offset + no_bytes) <= total_bytes) {
+				memcpy((buf + buffer_copy_offset), new_pkt->data,
+				    no_bytes);
+				buffer_copy_offset += no_bytes;
+				pending_bytes -= no_bytes;
+				--entry_count_remaining;
+			} else {
+				ql_log(ql_log_warn, vha, 0x5044,
+				    "Attempt to copy more that we got, optimizing..%x\n",
+				    buffer_copy_offset);
+				memcpy((buf + buffer_copy_offset), new_pkt->data,
+				    total_bytes - buffer_copy_offset);
+			}
+
+			((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
+			// flush signature
+			wmb();
+		}
+
+		if (pending_bytes != 0 || entry_count_remaining != 0) {
+			ql_log(ql_log_fatal, vha, 0x508b,
+			    "Dropping partial Data, underrun bytes = 0x%x, entry cnts 0x%x\n",
+			    total_bytes, entry_count_remaining);
+			return -EIO;
+		}
+	} while (entry_count_remaining > 0);
+
+	be32_to_cpu_array((u32 *)buf, (__be32 *)buf, total_bytes >> 2);
+	return 0;
+}
+
 /**
  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
  * @irq: interrupt number
@@ -1727,6 +1849,8 @@  qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
 	srb_t *sp;
 	uint16_t index;
 
+	if (pkt->handle == QLA_SKIP_HANDLE)
+		return NULL;
 	index = LSW(pkt->handle);
 	if (index >= req->num_outstanding_cmds) {
 		ql_log(ql_log_warn, vha, 0x5031,
@@ -3530,6 +3654,55 @@  void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
 	sp->done(sp, comp_status);
 }
 
+/* check for all continuation iocbs are available. */
+static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
+	struct rsp_que *rsp, response_t *pkt)
+{
+	int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
+	response_t *end_pkt;
+	int rc = 0;
+	u32 rsp_q_in;
+
+	if (pkt->entry_count == 1)
+		return rc;
+
+	/* ring_index was pre-increment. set it back to current pkt */
+	if (rsp->ring_index == 0)
+		start_pkt_ring_index = rsp->length - 1;
+	else
+		start_pkt_ring_index = rsp->ring_index - 1;
+
+	if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
+		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
+			rsp->length - 1;
+	else
+		end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
+
+	end_pkt = rsp->ring + end_pkt_ring_index;
+
+	//  next pkt = end_pkt + 1
+	n_ring_index = end_pkt_ring_index + 1;
+	if (n_ring_index >= rsp->length)
+		n_ring_index = 0;
+
+	rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
+		rd_reg_dword(rsp->rsp_q_in);
+
+	/* rsp_q_in is either wrapped or pointing beyond endpkt */
+	if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
+			rsp_q_in >= n_ring_index)
+		// all IOCBs arrived.
+		rc = 0;
+	else
+		rc = -EIO;
+
+	ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
+		"%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
+		__func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
+		rsp_q_in, rc);
+	return rc;
+}
+
 /**
  * qla24xx_process_response_queue() - Process response queue entries.
  * @vha: SCSI driver HA context
@@ -3670,6 +3843,15 @@  void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 						 qla27xx_process_purex_fpin);
 				break;
 
+			case ELS_AUTH_ELS:
+				if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
+					ql_dbg(ql_dbg_init, vha, 0x5091,
+					    "Defer processing ELS opcode %#x...\n",
+					    purex_entry->els_frame_payload[3]);
+					return;
+				}
+				qla24xx_auth_els(vha, (void **)&pkt, &rsp);
+				break;
 			default:
 				ql_log(ql_log_warn, vha, 0x509c,
 				       "Discarding ELS Request opcode 0x%x\n",
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 5e39977af9ba..6be06b994c43 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3797,7 +3797,6 @@  qla2x00_remove_one(struct pci_dev *pdev)
 	qla2x00_free_sysfs_attr(base_vha, true);
 
 	fc_remove_host(base_vha->host);
-	qlt_remove_target_resources(ha);
 
 	scsi_remove_host(base_vha->host);
 
@@ -3974,15 +3973,20 @@  qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 	struct req_que **req, struct rsp_que **rsp)
 {
 	char	name[16];
+	int rc;
 
 	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
 		&ha->init_cb_dma, GFP_KERNEL);
 	if (!ha->init_cb)
 		goto fail;
 
-	if (qlt_mem_alloc(ha) < 0)
+	rc = btree_init32(&ha->host_map);
+	if (rc)
 		goto fail_free_init_cb;
 
+	if (qlt_mem_alloc(ha) < 0)
+		goto fail_free_btree;
+
 	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
 		qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
 	if (!ha->gid_list)
@@ -4386,6 +4390,8 @@  qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 	ha->gid_list_dma = 0;
 fail_free_tgt_mem:
 	qlt_mem_free(ha);
+fail_free_btree:
+	btree_destroy32(&ha->host_map);
 fail_free_init_cb:
 	dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
 	ha->init_cb_dma);
@@ -4802,6 +4808,7 @@  qla2x00_mem_free(struct qla_hw_data *ha)
 	ha->dif_bundl_pool = NULL;
 
 	qlt_mem_free(ha);
+	qla_remove_hostmap(ha);
 
 	if (ha->init_cb)
 		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index abf18b88579c..365e64ebef8b 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -197,7 +197,7 @@  struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha,
 
 	key = be_to_port_id(d_id).b24;
 
-	host = btree_lookup32(&vha->hw->tgt.host_map, key);
+	host = btree_lookup32(&vha->hw->host_map, key);
 	if (!host)
 		ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
 		    "Unable to find host %06x\n", key);
@@ -6442,15 +6442,15 @@  int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
 	return 0;
 }
 
-void qlt_remove_target_resources(struct qla_hw_data *ha)
+void qla_remove_hostmap(struct qla_hw_data *ha)
 {
 	struct scsi_qla_host *node;
 	u32 key = 0;
 
-	btree_for_each_safe32(&ha->tgt.host_map, key, node)
-		btree_remove32(&ha->tgt.host_map, key);
+	btree_for_each_safe32(&ha->host_map, key, node)
+		btree_remove32(&ha->host_map, key);
 
-	btree_destroy32(&ha->tgt.host_map);
+	btree_destroy32(&ha->host_map);
 }
 
 static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
@@ -7078,8 +7078,7 @@  qlt_modify_vp_config(struct scsi_qla_host *vha,
 void
 qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 {
-	int rc;
-
+	mutex_init(&base_vha->vha_tgt.tgt_mutex);
 	if (!QLA_TGT_MODE_ENABLED())
 		return;
 
@@ -7092,7 +7091,6 @@  qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 		ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
 	}
 
-	mutex_init(&base_vha->vha_tgt.tgt_mutex);
 	mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
 
 	INIT_LIST_HEAD(&base_vha->unknown_atio_list);
@@ -7101,11 +7099,6 @@  qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 
 	qlt_clear_mode(base_vha);
 
-	rc = btree_init32(&ha->tgt.host_map);
-	if (rc)
-		ql_log(ql_log_info, base_vha, 0xd03d,
-		    "Unable to initialize ha->host_map btree\n");
-
 	qlt_update_vp_map(base_vha, SET_VP_IDX);
 }
 
@@ -7226,21 +7219,20 @@  qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
 	u32 key;
 	int rc;
 
-	if (!QLA_TGT_MODE_ENABLED())
-		return;
-
 	key = vha->d_id.b24;
 
 	switch (cmd) {
 	case SET_VP_IDX:
+		if (!QLA_TGT_MODE_ENABLED())
+			return;
 		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
 		break;
 	case SET_AL_PA:
-		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+		slot = btree_lookup32(&vha->hw->host_map, key);
 		if (!slot) {
 			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
 			    "Save vha in host_map %p %06x\n", vha, key);
-			rc = btree_insert32(&vha->hw->tgt.host_map,
+			rc = btree_insert32(&vha->hw->host_map,
 				key, vha, GFP_ATOMIC);
 			if (rc)
 				ql_log(ql_log_info, vha, 0xd03e,
@@ -7250,17 +7242,19 @@  qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
 		}
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
 		    "replace existing vha in host_map %p %06x\n", vha, key);
-		btree_update32(&vha->hw->tgt.host_map, key, vha);
+		btree_update32(&vha->hw->host_map, key, vha);
 		break;
 	case RESET_VP_IDX:
+		if (!QLA_TGT_MODE_ENABLED())
+			return;
 		vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
 		break;
 	case RESET_AL_PA:
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
 		   "clear vha in host_map %p %06x\n", vha, key);
-		slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+		slot = btree_lookup32(&vha->hw->host_map, key);
 		if (slot)
-			btree_remove32(&vha->hw->tgt.host_map, key);
+			btree_remove32(&vha->hw->host_map, key);
 		vha->d_id.b24 = 0;
 		break;
 	}