Commit 2d1928c5 authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

scsi: lpfc: SLI path split: Refactor misc ELS paths

This patch refactors the remaining ELS paths to use SLI-4 as the primary
interface. Paths include RRQ, RSCN, unsolicited ELS RQST and RSP paths, ELS
timeouts, etc.:

 - Remove unused routines lpfc_sli4_bpl2sgl and lpfc_sli4_iocb2wqe

 - Conversion away from using SLI-3 iocb structures to set/access fields in
   common routines. Use the new generic get/set routines that were added.
   This move changes code from indirect structure references to using local
   variables with the generic routines.

 - Refactor routines when setting non-generic fields, to have both SLI3 and
   SLI4 specific sections. This replaces the set-as-SLI3 then translate to
   SLI4 behavior of the past.

Link: https://lore.kernel.org/r/20220225022308.16486-12-jsmart2021@gmail.com


Co-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 35184980
Loading
Loading
Loading
Loading
+138 −86
Original line number Diff line number Diff line
@@ -1227,18 +1227,20 @@ static void
lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			struct lpfc_iocbq *rspiocb)
{
	IOCB_t *irsp;
	uint32_t *pcmd;
	uint32_t cmd;
	u32 ulp_status, ulp_word4;

	pcmd = (uint32_t *)(((struct lpfc_dmabuf *)cmdiocb->context2)->virt);
	cmd = *pcmd;
	irsp = &rspiocb->iocb;

	ulp_status = get_job_ulpstatus(phba, rspiocb);
	ulp_word4 = get_job_word4(phba, rspiocb);

	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
			"6445 ELS completes after LINK_DOWN: "
			" Status %x/%x cmd x%x flg x%x\n",
			irsp->ulpStatus, irsp->un.ulpWord[4], cmd,
			ulp_status, ulp_word4, cmd,
			cmdiocb->cmd_flag);

	if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) {
@@ -1907,40 +1909,40 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		  struct lpfc_iocbq *rspiocb)
{
	struct lpfc_vport *vport = cmdiocb->vport;
	IOCB_t *irsp;
	struct lpfc_nodelist *ndlp = cmdiocb->context1;
	struct lpfc_node_rrq *rrq;
	u32 ulp_status = get_job_ulpstatus(phba, rspiocb);
	u32 ulp_word4 = get_job_word4(phba, rspiocb);

	/* we pass cmdiocb to state machine which needs rspiocb as well */
	rrq = cmdiocb->context_un.rrq;
	cmdiocb->context_un.rsp_iocb = rspiocb;

	irsp = &rspiocb->iocb;
	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
		"RRQ cmpl:      status:x%x/x%x did:x%x",
		irsp->ulpStatus, irsp->un.ulpWord[4],
		irsp->un.elsreq64.remoteID);
		ulp_status, ulp_word4,
		get_job_els_rsp64_did(phba, cmdiocb));


	/* rrq completes to NPort <nlp_DID> */
	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
			 "2880 RRQ completes to DID x%x "
			 "Data: x%x x%x x%x x%x x%x\n",
			 irsp->un.elsreq64.remoteID,
			 irsp->ulpStatus, irsp->un.ulpWord[4],
			 irsp->ulpTimeout, rrq->xritag, rrq->rxid);
			 ndlp->nlp_DID, ulp_status, ulp_word4,
			 get_wqe_tmo(cmdiocb), rrq->xritag, rrq->rxid);

	if (irsp->ulpStatus) {
	if (ulp_status) {
		/* Check for retry */
		/* RRQ failed Don't print the vport to vport rjts */
		if (irsp->ulpStatus != IOSTAT_LS_RJT ||
			(((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) &&
			((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) ||
		if (ulp_status != IOSTAT_LS_RJT ||
		    (((ulp_word4) >> 16 != LSRJT_INVALID_CMD) &&
		     ((ulp_word4) >> 16 != LSRJT_UNABLE_TPC)) ||
		    (phba)->pport->cfg_log_verbose & LOG_ELS)
			lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
					 "2881 RRQ failure DID:%06X Status:"
					 "x%x/x%x\n",
					 ndlp->nlp_DID, irsp->ulpStatus,
					 irsp->un.ulpWord[4]);
					 ndlp->nlp_DID, ulp_status,
					 ulp_word4);
	}

	lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
@@ -5322,7 +5324,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
			if (!lpfc_unreg_rpi(vport, ndlp) &&
			    (!(vport->fc_flag & FC_PT2PT))) {
				if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) {
				if (ndlp->nlp_state ==  NLP_STE_PLOGI_ISSUE ||
				    ndlp->nlp_state ==
				     NLP_STE_REG_LOGIN_ISSUE) {
					lpfc_printf_vlog(vport, KERN_INFO,
							 LOG_DISCOVERY,
							 "0314 PLOGI recov "
@@ -5403,6 +5407,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	    (vport && vport->port_type == LPFC_NPIV_PORT) &&
	    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
	    ndlp->nlp_flag & NLP_RELEASE_RPI) {
		if (ndlp->nlp_state !=  NLP_STE_PLOGI_ISSUE &&
		    ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
			lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
			spin_lock_irq(&ndlp->lock);
			ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
@@ -5410,6 +5416,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			spin_unlock_irq(&ndlp->lock);
			lpfc_drop_node(vport, ndlp);
		}
	}

	/* Release the originating I/O reference. */
	lpfc_els_free_iocb(phba, cmdiocb);
@@ -7902,6 +7909,13 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,

			lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
				ndlp, NULL);
			/* Restart disctmo if its already running */
			if (vport->fc_flag & FC_DISC_TMO) {
				tmo = ((phba->fc_ratov * 3) + 3);
				mod_timer(&vport->fc_disctmo,
					  jiffies +
					  msecs_to_jiffies(1000 * tmo));
			}
			return 0;
		}
	}
@@ -9260,6 +9274,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
	uint32_t timeout;
	uint32_t remote_ID = 0xffffffff;
	LIST_HEAD(abort_list);
	u32 ulp_command = 0, ulp_context = 0, did = 0, iotag = 0;


	timeout = (uint32_t)(phba->fc_ratov << 1);
@@ -9276,11 +9291,21 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
		spin_lock(&pring->ring_lock);

	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
		ulp_command = get_job_cmnd(phba, piocb);
		ulp_context = get_job_ulpcontext(phba, piocb);
		did = get_job_els_rsp64_did(phba, piocb);

		if (phba->sli_rev == LPFC_SLI_REV4) {
			iotag = get_wqe_reqtag(piocb);
		} else {
			cmd = &piocb->iocb;
			iotag = cmd->ulpIoTag;
		}

		if ((piocb->cmd_flag & LPFC_IO_LIBDFC) != 0 ||
		    piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
		    piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
		    ulp_command == CMD_ABORT_XRI_CX ||
		    ulp_command == CMD_ABORT_XRI_CN ||
		    ulp_command == CMD_CLOSE_XRI_CN)
			continue;

		if (piocb->vport != vport)
@@ -9304,11 +9329,11 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
		}

		remote_ID = 0xffffffff;
		if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
			remote_ID = cmd->un.elsreq64.remoteID;
		else {
		if (ulp_command != CMD_GEN_REQUEST64_CR) {
			remote_ID = did;
		} else {
			struct lpfc_nodelist *ndlp;
			ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
			ndlp = __lpfc_findnode_rpi(vport, ulp_context);
			if (ndlp)
				remote_ID = ndlp->nlp_DID;
		}
@@ -9319,11 +9344,11 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
	spin_unlock_irq(&phba->hbalock);

	list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
		cmd = &piocb->iocb;
		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
			 "0127 ELS timeout Data: x%x x%x x%x "
			 "x%x\n", els_command,
			 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
			 remote_ID, ulp_command, iotag);

		spin_lock_irq(&phba->hbalock);
		list_del_init(&piocb->dlist);
		lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL);
@@ -9366,7 +9391,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
	struct lpfc_hba  *phba = vport->phba;
	struct lpfc_sli_ring *pring;
	struct lpfc_iocbq *tmp_iocb, *piocb;
	IOCB_t *cmd = NULL;
	u32 ulp_command;
	unsigned long iflags = 0;

	lpfc_fabric_abort_vport(vport);
@@ -9403,8 +9428,8 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
		/* On the ELS ring we can have ELS_REQUESTs or
		 * GEN_REQUESTs waiting for a response.
		 */
		cmd = &piocb->iocb;
		if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
		ulp_command = get_job_cmnd(phba, piocb);
		if (ulp_command == CMD_ELS_REQUEST64_CR) {
			list_add_tail(&piocb->dlist, &abort_list);

			/* If the link is down when flushing ELS commands
@@ -9417,7 +9442,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
			if (phba->link_state == LPFC_LINK_DOWN)
				piocb->cmd_cmpl = lpfc_cmpl_els_link_down;
		}
		if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR)
		if (ulp_command == CMD_GEN_REQUEST64_CR)
			list_add_tail(&piocb->dlist, &abort_list);
	}

@@ -9448,16 +9473,17 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
	 * just queue them up for lpfc_sli_cancel_iocbs
	 */
	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
		cmd = &piocb->iocb;
		ulp_command = get_job_cmnd(phba, piocb);

		if (piocb->cmd_flag & LPFC_IO_LIBDFC)
			continue;

		/* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
		if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
		    cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
		    cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
		    cmd->ulpCommand == CMD_ABORT_XRI_CN)
		if (ulp_command == CMD_QUE_RING_BUF_CN ||
		    ulp_command == CMD_QUE_RING_BUF64_CN ||
		    ulp_command == CMD_CLOSE_XRI_CN ||
		    ulp_command == CMD_ABORT_XRI_CN ||
		    ulp_command == CMD_ABORT_XRI_CX)
			continue;

		if (piocb->vport != vport)
@@ -9471,7 +9497,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
	if (vport == phba->pport) {
		list_for_each_entry_safe(piocb, tmp_iocb,
					 &phba->fabric_iocb_list, list) {
			cmd = &piocb->iocb;
			list_del_init(&piocb->list);
			list_add_tail(&piocb->list, &abort_list);
		}
@@ -9539,12 +9564,16 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
	struct ls_rjt stat;
	struct lpfc_nodelist *ndlp;
	uint32_t *pcmd;
	u32 ulp_status, ulp_word4;

	ndlp = cmdiocbp->context1;
	if (!ndlp)
		return;

	if (rspiocbp->iocb.ulpStatus == IOSTAT_LS_RJT) {
	ulp_status = get_job_ulpstatus(phba, rspiocbp);
	ulp_word4 = get_job_word4(phba, rspiocbp);

	if (ulp_status == IOSTAT_LS_RJT) {
		lsrjt_event.header.event_type = FC_REG_ELS_EVENT;
		lsrjt_event.header.subcategory = LPFC_EVENT_LSRJT_RCV;
		memcpy(lsrjt_event.header.wwpn, &ndlp->nlp_portname,
@@ -9554,7 +9583,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
		pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
			cmdiocbp->context2)->virt);
		lsrjt_event.command = (pcmd != NULL) ? *pcmd : 0;
		stat.un.lsRjtError = be32_to_cpu(rspiocbp->iocb.un.ulpWord[4]);
		stat.un.ls_rjt_error_be = cpu_to_be32(ulp_word4);
		lsrjt_event.reason_code = stat.un.b.lsRjtRsnCode;
		lsrjt_event.explanation = stat.un.b.lsRjtRsnCodeExp;
		fc_host_post_vendor_event(shost,
@@ -9564,10 +9593,10 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
			LPFC_NL_VENDOR_ID);
		return;
	}
	if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
		(rspiocbp->iocb.ulpStatus == IOSTAT_FABRIC_BSY)) {
	if (ulp_status == IOSTAT_NPORT_BSY ||
	    ulp_status == IOSTAT_FABRIC_BSY) {
		fabric_event.event_type = FC_REG_FABRIC_EVENT;
		if (rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY)
		if (ulp_status == IOSTAT_NPORT_BSY)
			fabric_event.subcategory = LPFC_EVENT_PORT_BUSY;
		else
			fabric_event.subcategory = LPFC_EVENT_FABRIC_BUSY;
@@ -10080,27 +10109,32 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
	struct lpfc_nodelist *ndlp;
	struct ls_rjt stat;
	uint32_t *payload, payload_len;
	uint32_t cmd, did, newnode;
	u32 *payload, payload_len;
	u32 cmd = 0, did = 0, newnode, status = 0;
	uint8_t rjt_exp, rjt_err = 0, init_link = 0;
	IOCB_t *icmd = &elsiocb->iocb;
	struct lpfc_wcqe_complete *wcqe_cmpl = NULL;
	LPFC_MBOXQ_t *mbox;

	if (!vport || !(elsiocb->context2))
		goto dropit;

	newnode = 0;
	wcqe_cmpl = &elsiocb->wcqe_cmpl;
	payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
	if (phba->sli_rev == LPFC_SLI_REV4)
		payload_len = wcqe_cmpl->total_data_placed;
	else
		payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len;
	status = get_job_ulpstatus(phba, elsiocb);
	cmd = *payload;
	if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
		lpfc_sli3_post_buffer(phba, pring, 1);

	did = icmd->un.rcvels.remoteID;
	if (icmd->ulpStatus) {
	did = get_job_els_rsp64_did(phba, elsiocb);
	if (status) {
		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
			"RCV Unsol ELS:  status:x%x/x%x did:x%x",
			icmd->ulpStatus, icmd->un.ulpWord[4], did);
			status, get_job_word4(phba, elsiocb), did);
		goto dropit;
	}

@@ -10186,7 +10220,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
			 * the vfi. This is done in lpfc_rcv_plogi but
			 * that is called after the reg_vfi.
			 */
			vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo;
			vport->fc_myDID =
				bf_get(els_rsp64_sid,
				       &elsiocb->wqe.xmit_els_rsp);
			lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
					 "3312 Remote port assigned DID x%x "
					 "%x\n", vport->fc_myDID,
@@ -10531,8 +10567,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	if (vport && !(vport->load_flag & FC_UNLOADING))
		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
			"0111 Dropping received ELS cmd "
			"Data: x%x x%x x%x\n",
			icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout);
			"Data: x%x x%x x%x x%x\n",
			cmd, status, get_job_word4(phba, elsiocb), did);

	phba->fc_stat.elsRcvDrop++;
}

@@ -10552,20 +10589,31 @@ void
lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
		     struct lpfc_iocbq *elsiocb)
{
	struct lpfc_vport *vport = phba->pport;
	IOCB_t *icmd = &elsiocb->iocb;
	dma_addr_t paddr;
	struct lpfc_vport *vport = elsiocb->vport;
	u32 ulp_command, status, parameter, bde_count = 0;
	IOCB_t *icmd;
	struct lpfc_wcqe_complete *wcqe_cmpl = NULL;
	struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
	struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
	dma_addr_t paddr;

	elsiocb->context1 = NULL;
	elsiocb->context2 = NULL;
	elsiocb->context3 = NULL;

	if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
	wcqe_cmpl = &elsiocb->wcqe_cmpl;
	ulp_command = get_job_cmnd(phba, elsiocb);
	status = get_job_ulpstatus(phba, elsiocb);
	parameter = get_job_word4(phba, elsiocb);
	if (phba->sli_rev == LPFC_SLI_REV4)
		bde_count = wcqe_cmpl->word3;
	else
		bde_count = elsiocb->iocb.ulpBdeCount;

	if (status == IOSTAT_NEED_BUFFER) {
		lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
	} else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
		   (icmd->un.ulpWord[4] & IOERR_PARAM_MASK) ==
	} else if (status == IOSTAT_LOCAL_REJECT &&
		   (parameter & IOERR_PARAM_MASK) ==
		   IOERR_RCV_BUFFER_WAITING) {
		phba->fc_stat.NoRcvBuf++;
		/* Not enough posted buffers; Try posting more buffers */
@@ -10574,32 +10622,43 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
		return;
	}

	if (phba->sli_rev == LPFC_SLI_REV3) {
		icmd = &elsiocb->iocb;
		if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
	    (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
	     icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
		    (ulp_command == CMD_IOCB_RCV_ELS64_CX ||
		     ulp_command == CMD_IOCB_RCV_SEQ64_CX)) {
			if (icmd->unsli3.rcvsli3.vpi == 0xffff)
				vport = phba->pport;
			else
				vport = lpfc_find_vport_by_vpid(phba,
						icmd->unsli3.rcvsli3.vpi);
		}
	}

	/* If there are no BDEs associated
	 * with this IOCB, there is nothing to do.
	 */
	if (icmd->ulpBdeCount == 0)
	if (bde_count == 0)
		return;

	/* type of ELS cmd is first 32bit word
	 * in packet
	 */
	/* Account for SLI2 or SLI3 and later unsolicited buffering */
	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
		elsiocb->context2 = bdeBuf1;
		if (bde_count == 2)
			elsiocb->context3 = bdeBuf2;
	} else {
		icmd = &elsiocb->iocb;
		paddr = getPaddr(icmd->un.cont64[0].addrHigh,
				 icmd->un.cont64[0].addrLow);
		elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
							     paddr);
		if (bde_count == 2) {
			paddr = getPaddr(icmd->un.cont64[1].addrHigh,
					 icmd->un.cont64[1].addrLow);
			elsiocb->context3 = lpfc_sli_ringpostbuf_get(phba,
								       pring,
								       paddr);
		}
	}

	lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
@@ -10612,16 +10671,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
		elsiocb->context2 = NULL;
	}

	/* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
	if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
	    icmd->ulpBdeCount == 2) {
		elsiocb->context2 = bdeBuf2;
		lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
		/* free mp if we are done with it */
		if (elsiocb->context2) {
			lpfc_in_buf_free(phba, elsiocb->context2);
			elsiocb->context2 = NULL;
		}
	if (elsiocb->context3) {
		lpfc_in_buf_free(phba, elsiocb->context3);
		elsiocb->context3 = NULL;
	}
}

+26 −18
Original line number Diff line number Diff line
@@ -5059,7 +5059,8 @@ lpfc_can_disctmo(struct lpfc_vport *vport)
		vport->port_state, vport->fc_ns_retry, vport->fc_flag);

	/* Turn off discovery timer if its running */
	if (vport->fc_flag & FC_DISC_TMO) {
	if (vport->fc_flag & FC_DISC_TMO ||
	    timer_pending(&vport->fc_disctmo)) {
		spin_lock_irqsave(shost->host_lock, iflags);
		vport->fc_flag &= ~FC_DISC_TMO;
		spin_unlock_irqrestore(shost->host_lock, iflags);
@@ -5088,20 +5089,26 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
		    struct lpfc_iocbq *iocb,
		    struct lpfc_nodelist *ndlp)
{
	IOCB_t *icmd = &iocb->iocb;
	struct lpfc_vport *vport = ndlp->vport;
	u8 ulp_command;
	u16 ulp_context;
	u32 remote_id;

	if (iocb->vport != vport)
		return 0;

	ulp_command = get_job_cmnd(phba, iocb);
	ulp_context = get_job_ulpcontext(phba, iocb);
	remote_id = get_job_els_rsp64_did(phba, iocb);

	if (pring->ringno == LPFC_ELS_RING) {
		switch (icmd->ulpCommand) {
		switch (ulp_command) {
		case CMD_GEN_REQUEST64_CR:
			if (iocb->context_un.ndlp == ndlp)
				return 1;
			fallthrough;
		case CMD_ELS_REQUEST64_CR:
			if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
			if (remote_id == ndlp->nlp_DID)
				return 1;
			fallthrough;
		case CMD_XMIT_ELS_RSP64_CX:
@@ -5114,10 +5121,9 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
		    (ndlp->nlp_flag & NLP_DELAY_TMO)) {
			return 0;
		}
		if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) {
		if (ulp_context == ndlp->nlp_rpi)
			return 1;
	}
	}
	return 0;
}

@@ -6027,9 +6033,9 @@ static void
lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
	LIST_HEAD(completions);
	IOCB_t     *icmd;
	struct lpfc_iocbq    *iocb, *next_iocb;
	struct lpfc_sli_ring *pring;
	u32 ulp_command;

	pring = lpfc_phba_elsring(phba);
	if (unlikely(!pring))
@@ -6040,12 +6046,13 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
	 */
	spin_lock_irq(&phba->hbalock);
	list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
		if (iocb->context1 != ndlp) {
		if (iocb->context1 != ndlp)
			continue;
		}
		icmd = &iocb->iocb;
		if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
		    (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {

		ulp_command = get_job_cmnd(phba, iocb);

		if (ulp_command == CMD_ELS_REQUEST64_CR ||
		    ulp_command == CMD_XMIT_ELS_RSP64_CX) {

			list_move_tail(&iocb->list, &completions);
		}
@@ -6053,12 +6060,13 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)

	/* Next check the txcmplq */
	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
		if (iocb->context1 != ndlp) {
		if (iocb->context1 != ndlp)
			continue;
		}
		icmd = &iocb->iocb;
		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR ||
		    icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) {

		ulp_command = get_job_cmnd(phba, iocb);

		if (ulp_command == CMD_ELS_REQUEST64_CR ||
		    ulp_command == CMD_XMIT_ELS_RSP64_CX) {
			lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
		}
	}
+29 −9
Original line number Diff line number Diff line
@@ -171,9 +171,8 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	struct lpfc_dmabuf *pcmd, *prsp;
	uint32_t *lp;
	void     *ptr = NULL;
	IOCB_t   *irsp;
	u32 ulp_status = get_job_ulpstatus(phba, rspiocb);

	irsp = &rspiocb->iocb;
	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;

	/* For lpfc_els_abort, context2 could be zero'ed to delay
@@ -187,10 +186,16 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			ptr = (void *)((uint8_t *)lp + sizeof(uint32_t));
		}
	} else {
		/* Force ulpStatus error since we are returning NULL ptr */
		if (!(irsp->ulpStatus)) {
			irsp->ulpStatus = IOSTAT_LOCAL_REJECT;
			irsp->un.ulpWord[4] = IOERR_SLI_ABORTED;
		/* Force ulp_status error since we are returning NULL ptr */
		if (!(ulp_status)) {
			if (phba->sli_rev == LPFC_SLI_REV4) {
				bf_set(lpfc_wcqe_c_status, &rspiocb->wcqe_cmpl,
				       IOSTAT_LOCAL_REJECT);
				rspiocb->wcqe_cmpl.parameter = IOERR_SLI_ABORTED;
			} else {
				rspiocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
				rspiocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;
			}
		}
		ptr = NULL;
	}
@@ -325,6 +330,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	struct lpfc_dmabuf *mp;
	uint64_t nlp_portwwn = 0;
	uint32_t *lp;
	union lpfc_wqe128 *wqe;
	IOCB_t *icmd;
	struct serv_parm *sp;
	uint32_t ed_tov;
@@ -334,6 +340,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	struct ls_rjt stat;
	uint32_t vid, flag;
	int rc;
	u32 remote_did;

	memset(&stat, 0, sizeof (struct ls_rjt));
	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -367,6 +374,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
			NULL);
		return 0;
	}

	if (phba->sli_rev == LPFC_SLI_REV4)
		wqe = &cmdiocb->wqe;
	else
		icmd = &cmdiocb->iocb;

	/* PLOGI chkparm OK */
@@ -457,7 +468,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	if ((vport->fc_flag & FC_PT2PT) &&
	    !(vport->fc_flag & FC_PT2PT_PLOGI)) {
		/* rcv'ed PLOGI decides what our NPortId will be */
		if (phba->sli_rev == LPFC_SLI_REV4) {
			vport->fc_myDID = bf_get(els_rsp64_sid,
						 &cmdiocb->wqe.xmit_els_rsp);
		} else {
			vport->fc_myDID = icmd->un.rcvels.parmRo;
		}

		/* If there is an outstanding FLOGI, abort it now.
		 * The remote NPort is not going to ACC our FLOGI
@@ -538,7 +554,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	/* Issue REG_LOGIN first, before ACCing the PLOGI, thus we will
	 * always be deferring the ACC.
	 */
	rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
	if (phba->sli_rev == LPFC_SLI_REV4)
		remote_did = bf_get(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest);
	else
		remote_did = icmd->un.rcvels.remoteID;
	rc = lpfc_reg_rpi(phba, vport->vpi, remote_did,
			    (uint8_t *)sp, login_mbox, ndlp->nlp_rpi);
	if (rc)
		goto out;
+48 −761

File changed.

Preview size limit exceeded, changes collapsed.