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

scsi: lpfc: SLI path split: Introduce lpfc_prep_wqe

Introduce lpfc_prep_wqe routine.

The lpfc_prep_wqe() routine is used with lpfc_sli_issue_iocb() and
lpfc_sli_issue_iocb_wait(). The routine performs additional SLI-4 wqe field
setting that the generic routines did not perform as they kept their
actions compatible with both SLI3 and SLI4.

Link: https://lore.kernel.org/r/20220225022308.16486-4-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 1b64aa9e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3290,6 +3290,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
	cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
	cmdiocbq->vport = phba->pport;
	cmdiocbq->cmd_cmpl = NULL;

	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
					     rspiocbq, (phba->fc_ratov * 2) +
					     LPFC_DRVR_TIMEOUT);
+1 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ void lpfc_els_timeout_handler(struct lpfc_vport *);
struct lpfc_iocbq *lpfc_prep_els_iocb(struct lpfc_vport *, uint8_t, uint16_t,
				      uint8_t, struct lpfc_nodelist *,
				      uint32_t, uint32_t);
void lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job);
void lpfc_hb_timeout_handler(struct lpfc_hba *);

void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
+1 −0
Original line number Diff line number Diff line
@@ -659,6 +659,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
	geniocb->context_un.ndlp = lpfc_nlp_get(ndlp);
	if (!geniocb->context_un.ndlp)
		goto out;

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0);

	if (rc == IOCB_ERROR) {
+2 −0
Original line number Diff line number Diff line
@@ -2861,6 +2861,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
			      "Issue ADISC:   did:x%x refcnt %d",
			      ndlp->nlp_DID, kref_read(&ndlp->kref), 0);

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
		lpfc_els_free_iocb(phba, elsiocb);
@@ -3085,6 +3086,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
			      "Issue LOGO:      did:x%x refcnt %d",
			      ndlp->nlp_DID, kref_read(&ndlp->kref), 0);

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
		lpfc_els_free_iocb(phba, elsiocb);
+195 −2
Original line number Diff line number Diff line
@@ -11251,6 +11251,8 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
	int rc;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		lpfc_sli_prep_wqe(phba, piocb);
		eq = phba->sli4_hba.hdwq[piocb->hba_wqidx].hba_eq;
		pring = lpfc_sli4_calc_ring(phba, piocb);
@@ -13074,9 +13076,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
	unsigned long iflags;
	bool iocb_completed = true;
	if (phba->sli_rev >= LPFC_SLI_REV4)
	if (phba->sli_rev >= LPFC_SLI_REV4) {
		lpfc_sli_prep_wqe(phba, piocb);
		pring = lpfc_sli4_calc_ring(phba, piocb);
	else
	} else
		pring = &phba->sli.sli3_ring[ring_number];
	/*
	 * If the caller has provided a response iocbq buffer, then context2
@@ -22448,3 +22452,192 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
	spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
}
/**
 * lpfc_sli_prep_wqe - Prepare WQE for the command to be posted
 * @phba: phba object
 * @job: job entry of the command to be posted.
 *
 * Fill the common fields of the wqe for each of the command.
 *
 * Return codes:
 *	None
 **/
void
lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job)
{
	u8 cmnd;
	u32 *pcmd;
	u32 if_type = 0;
	u32 fip, abort_tag;
	struct lpfc_nodelist *ndlp = NULL;
	union lpfc_wqe128 *wqe = &job->wqe;
	struct lpfc_dmabuf *context2;
	u32 els_id = LPFC_ELS_ID_DEFAULT;
	u8 command_type = ELS_COMMAND_NON_FIP;
	fip = phba->hba_flag & HBA_FIP_SUPPORT;
	/* The fcp commands will set command type */
	if (job->cmd_flag &  LPFC_IO_FCP)
		command_type = FCP_COMMAND;
	else if (fip && (job->cmd_flag & LPFC_FIP_ELS_ID_MASK))
		command_type = ELS_COMMAND_FIP;
	else
		command_type = ELS_COMMAND_NON_FIP;
	abort_tag = job->iotag;
	cmnd = bf_get(wqe_cmnd, &wqe->els_req.wqe_com);
	switch (cmnd) {
	case CMD_ELS_REQUEST64_WQE:
		if (job->cmd_flag & LPFC_IO_LIBDFC)
			ndlp = job->context_un.ndlp;
		else
			ndlp = (struct lpfc_nodelist *)job->context1;
		/* CCP CCPE PV PRI in word10 were set in the memcpy */
		if (command_type == ELS_COMMAND_FIP)
			els_id = ((job->cmd_flag & LPFC_FIP_ELS_ID_MASK)
				  >> LPFC_FIP_ELS_ID_SHIFT);
		if_type = bf_get(lpfc_sli_intf_if_type,
				 &phba->sli4_hba.sli_intf);
		if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
			context2 = (struct lpfc_dmabuf *)job->context2;
			pcmd = (u32 *)context2->virt;
			if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
				     *pcmd == ELS_CMD_SCR ||
				     *pcmd == ELS_CMD_RDF ||
				     *pcmd == ELS_CMD_EDC ||
				     *pcmd == ELS_CMD_RSCN_XMT ||
				     *pcmd == ELS_CMD_FDISC ||
				     *pcmd == ELS_CMD_LOGO ||
				     *pcmd == ELS_CMD_QFPA ||
				     *pcmd == ELS_CMD_UVEM ||
				     *pcmd == ELS_CMD_PLOGI)) {
				bf_set(els_req64_sp, &wqe->els_req, 1);
				bf_set(els_req64_sid, &wqe->els_req,
				       job->vport->fc_myDID);
				if ((*pcmd == ELS_CMD_FLOGI) &&
				    !(phba->fc_topology ==
				      LPFC_TOPOLOGY_LOOP))
					bf_set(els_req64_sid, &wqe->els_req, 0);
				bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
				bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
				       phba->vpi_ids[job->vport->vpi]);
			} else if (pcmd) {
				bf_set(wqe_ct, &wqe->els_req.wqe_com, 0);
				bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
				       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
			}
		}
		bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com,
		       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
		bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id);
		bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1);
		bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ);
		bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1);
		bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE);
		bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0);
		break;
	case CMD_XMIT_ELS_RSP64_WQE:
		ndlp = (struct lpfc_nodelist *)job->context1;
		/* word4 */
		wqe->xmit_els_rsp.word4 = 0;
		if_type = bf_get(lpfc_sli_intf_if_type,
				 &phba->sli4_hba.sli_intf);
		if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
			if (job->vport->fc_flag & FC_PT2PT) {
				bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
				bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
				       job->vport->fc_myDID);
				if (job->vport->fc_myDID == Fabric_DID) {
					bf_set(wqe_els_did,
					       &wqe->xmit_els_rsp.wqe_dest, 0);
				}
			}
		}
		bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1);
		bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE);
		bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1);
		bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com,
		       LPFC_WQE_LENLOC_WORD3);
		bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0);
		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
			bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
			bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
			       job->vport->fc_myDID);
			bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1);
		}
		if (phba->sli_rev == LPFC_SLI_REV4) {
			bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp,
			       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
			if (bf_get(wqe_ct, &wqe->xmit_els_rsp.wqe_com))
				bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com,
				       phba->vpi_ids[job->vport->vpi]);
		}
		command_type = OTHER_COMMAND;
		break;
	case CMD_GEN_REQUEST64_WQE:
		/* Word 10 */
		bf_set(wqe_dbde, &wqe->gen_req.wqe_com, 1);
		bf_set(wqe_iod, &wqe->gen_req.wqe_com, LPFC_WQE_IOD_READ);
		bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1);
		bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE);
		bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0);
		command_type = OTHER_COMMAND;
		break;
	case CMD_XMIT_SEQUENCE64_WQE:
		if (phba->link_flag & LS_LOOPBACK_MODE)
			bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
		wqe->xmit_sequence.rsvd3 = 0;
		bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0);
		bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1);
		bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com,
		       LPFC_WQE_IOD_WRITE);
		bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com,
		       LPFC_WQE_LENLOC_WORD12);
		bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0);
		command_type = OTHER_COMMAND;
		break;
	case CMD_XMIT_BLS_RSP64_WQE:
		bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
		bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
		bf_set(wqe_ct, &wqe->xmit_bls_rsp.wqe_com, 1);
		bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com,
		       phba->vpi_ids[phba->pport->vpi]);
		bf_set(wqe_qosd, &wqe->xmit_bls_rsp.wqe_com, 1);
		bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com,
		       LPFC_WQE_LENLOC_NONE);
		/* Overwrite the pre-set comnd type with OTHER_COMMAND */
		command_type = OTHER_COMMAND;
		break;
	case CMD_FCP_ICMND64_WQE:	/* task mgmt commands */
	case CMD_ABORT_XRI_WQE:		/* abort iotag */
	case CMD_SEND_FRAME:		/* mds loopback */
		/* cases already formatted for sli4 wqe - no chgs necessary */
		return;
	default:
		dump_stack();
		lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
				"6207 Invalid command 0x%x\n",
				cmnd);
		break;
	}
	wqe->generic.wqe_com.abort_tag = abort_tag;
	bf_set(wqe_reqtag, &wqe->generic.wqe_com, job->iotag);
	bf_set(wqe_cmd_type, &wqe->generic.wqe_com, command_type);
	bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
}