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

scsi: lpfc: SLI path split: Refactor CT paths

This patch refactors the CT paths to use SLI-4 as the primary interface.

 - Introduce generic lpfc_sli_prep_gen_req jump table routine

 - Introduce generic lpfc_sli_prep_xmit_seq64 jump table routine

 - Rename lpfcdiag_loop_post_rxbufs to lpfcdiag_sli3_loop_post_rxbufs to
   indicate that it is an SLI3 only path

 - Create new prep_wqe routine for unsolicited ELS rsp WQEs.

 - 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-13-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 2d1928c5
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -968,6 +968,13 @@ struct lpfc_hba {
					    struct lpfc_dmabuf *bmp,
					    u16 cmd_size, u32 did, u32 elscmd,
					    u8 tmo, u8 expect_rsp);
	void (*__lpfc_sli_prep_gen_req)(struct lpfc_iocbq *cmdiocbq,
					struct lpfc_dmabuf *bmp, u16 rpi,
					u32 num_entry, u8 tmo);
	void (*__lpfc_sli_prep_xmit_seq64)(struct lpfc_iocbq *cmdiocbq,
					   struct lpfc_dmabuf *bmp, u16 rpi,
					   u16 ox_id, u32 num_entry, u8 rctl,
					   u8 last_seq, u8 cr_cx_cmd);

	/* expedite pool */
	struct lpfc_epd_pool epd_pool;
@@ -1849,6 +1856,15 @@ u16 get_job_rcvoxid(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
		return iocbq->iocb.unsli3.rcvsli3.ox_id;
}

static inline
u32 get_job_data_placed(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
	if (phba->sli_rev == LPFC_SLI_REV4)
		return iocbq->wcqe_cmpl.total_data_placed;
	else
		return iocbq->iocb.un.genreq64.bdl.bdeSize;
}

static inline
u32 get_job_els_rsp64_did(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
+106 −160
Original line number Diff line number Diff line
@@ -303,13 +303,12 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
	struct bsg_job_data *dd_data;
	struct bsg_job *job;
	struct fc_bsg_reply *bsg_reply;
	IOCB_t *rsp;
	struct lpfc_dmabuf *bmp, *cmp, *rmp;
	struct lpfc_nodelist *ndlp;
	struct lpfc_bsg_iocb *iocb;
	unsigned long flags;
	unsigned int rsp_size;
	int rc = 0;
	u32 ulp_status, ulp_word4, total_data_placed;

	dd_data = cmdiocbq->context1;

@@ -333,14 +332,16 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
	rmp = iocb->rmp;
	cmp = cmdiocbq->context2;
	bmp = cmdiocbq->context3;
	rsp = &rspiocbq->iocb;
	ulp_status = get_job_ulpstatus(phba, rspiocbq);
	ulp_word4 = get_job_word4(phba, rspiocbq);
	total_data_placed = get_job_data_placed(phba, rspiocbq);

	/* Copy the completed data or set the error status */

	if (job) {
		if (rsp->ulpStatus) {
			if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
				switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
		if (ulp_status) {
			if (ulp_status == IOSTAT_LOCAL_REJECT) {
				switch (ulp_word4 & IOERR_PARAM_MASK) {
				case IOERR_SEQUENCE_TIMEOUT:
					rc = -ETIMEDOUT;
					break;
@@ -355,10 +356,9 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
				rc = -EACCES;
			}
		} else {
			rsp_size = rsp->un.genreq64.bdl.bdeSize;
			bsg_reply->reply_payload_rcv_len =
				lpfc_bsg_copy_data(rmp, &job->reply_payload,
						   rsp_size, 0);
						   total_data_placed, 0);
		}
	}

@@ -388,22 +388,21 @@ static int
lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
{
	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
	struct lpfc_hba *phba = vport->phba;
	struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
	struct lpfc_hba *phba = vport->phba;
	struct lpfc_nodelist *ndlp = rdata->pnode;
	struct fc_bsg_reply *bsg_reply = job->reply;
	struct ulp_bde64 *bpl = NULL;
	uint32_t timeout;
	struct lpfc_iocbq *cmdiocbq = NULL;
	IOCB_t *cmd;
	struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
	int request_nseg;
	int reply_nseg;
	int request_nseg, reply_nseg;
	u32 num_entry;
	struct bsg_job_data *dd_data;
	unsigned long flags;
	uint32_t creg_val;
	int rc = 0;
	int iocb_stat;
	u16 ulp_context;

	/* in case no data is transferred */
	bsg_reply->reply_payload_rcv_len = 0;
@@ -426,8 +425,6 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
		goto free_dd;
	}

	cmd = &cmdiocbq->iocb;

	bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
	if (!bmp) {
		rc = -ENOMEM;
@@ -461,29 +458,21 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
		goto free_cmp;
	}

	cmd->un.genreq64.bdl.ulpIoTag32 = 0;
	cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
	cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
	cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
	cmd->un.genreq64.bdl.bdeSize =
		(request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
	cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
	cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
	cmd->un.genreq64.w5.hcsw.Dfctl = 0;
	cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
	cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
	cmd->ulpBdeCount = 1;
	cmd->ulpLe = 1;
	cmd->ulpClass = CLASS3;
	cmd->ulpContext = ndlp->nlp_rpi;
	num_entry = request_nseg + reply_nseg;

	if (phba->sli_rev == LPFC_SLI_REV4)
		cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
	cmd->ulpOwner = OWN_CHIP;
		ulp_context = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
	else
		ulp_context = ndlp->nlp_rpi;

	lpfc_sli_prep_gen_req(phba, cmdiocbq, bmp, ulp_context, num_entry,
			      phba->fc_ratov * 2);

	cmdiocbq->num_bdes = num_entry;
	cmdiocbq->vport = phba->pport;
	cmdiocbq->context2 = cmp;
	cmdiocbq->context3 = bmp;
	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
	timeout = phba->fc_ratov * 2;
	cmd->ulpTimeout = timeout;

	cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
	cmdiocbq->context1 = dd_data;
@@ -916,6 +905,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	struct lpfc_bsg_event *evt;
	struct event_data *evt_dat = NULL;
	struct lpfc_iocbq *iocbq;
	IOCB_t *iocb = NULL;
	size_t offset = 0;
	struct list_head head;
	struct ulp_bde64 *bde;
@@ -923,13 +913,13 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	int i;
	struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
	struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
	struct lpfc_hbq_entry *hbqe;
	struct lpfc_sli_ct_request *ct_req;
	struct bsg_job *job = NULL;
	struct fc_bsg_reply *bsg_reply;
	struct bsg_job_data *dd_data = NULL;
	unsigned long flags;
	int size = 0;
	u32 bde_count = 0;

	INIT_LIST_HEAD(&head);
	list_add_tail(&head, &piocbq->list);
@@ -959,12 +949,17 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
		if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
			/* take accumulated byte count from the last iocbq */
			iocbq = list_entry(head.prev, typeof(*iocbq), list);
			if (phba->sli_rev == LPFC_SLI_REV4)
				evt_dat->len = iocbq->wcqe_cmpl.total_data_placed;
			else
				evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len;
		} else {
			list_for_each_entry(iocbq, &head, list) {
				for (i = 0; i < iocbq->iocb.ulpBdeCount; i++)
				iocb = &iocbq->iocb;
				for (i = 0; i < iocb->ulpBdeCount;
				     i++)
					evt_dat->len +=
					iocbq->iocb.un.cont64[i].tus.f.bdeSize;
					iocb->un.cont64[i].tus.f.bdeSize;
			}
		}

@@ -986,20 +981,20 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
			if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
				bdeBuf1 = iocbq->context2;
				bdeBuf2 = iocbq->context3;

			}
			for (i = 0; i < iocbq->iocb.ulpBdeCount; i++) {
			if (phba->sli_rev == LPFC_SLI_REV4)
				bde_count = iocbq->wcqe_cmpl.word3;
			else
				bde_count = iocbq->iocb.ulpBdeCount;
			for (i = 0; i < bde_count; i++) {
				if (phba->sli3_options &
				    LPFC_SLI3_HBQ_ENABLED) {
					if (i == 0) {
						hbqe = (struct lpfc_hbq_entry *)
						  &iocbq->iocb.un.ulpWord[0];
						size = hbqe->bde.tus.f.bdeSize;
						size = iocbq->wqe.gen_req.bde.tus.f.bdeSize;
						dmabuf = bdeBuf1;
					} else if (i == 1) {
						hbqe = (struct lpfc_hbq_entry *)
							&iocbq->iocb.unsli3.
							sli3Words[4];
						size = hbqe->bde.tus.f.bdeSize;
						size = iocbq->unsol_rcv_len;
						dmabuf = bdeBuf2;
					}
					if ((offset + size) > evt_dat->len)
@@ -1086,14 +1081,15 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
						phba->ct_ctx[
						    evt_dat->immed_dat].SID);
			phba->ct_ctx[evt_dat->immed_dat].rxid =
				piocbq->iocb.ulpContext;
				get_job_ulpcontext(phba, piocbq);
			phba->ct_ctx[evt_dat->immed_dat].oxid =
				piocbq->iocb.unsli3.rcvsli3.ox_id;
				get_job_rcvoxid(phba, piocbq);
			phba->ct_ctx[evt_dat->immed_dat].SID =
				piocbq->iocb.un.rcvels.remoteID;
				bf_get(wqe_els_did,
				       &piocbq->wqe.xmit_els_rsp.wqe_dest);
			phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;
		} else
			evt_dat->immed_dat = piocbq->iocb.ulpContext;
			evt_dat->immed_dat = get_job_ulpcontext(phba, piocbq);

		evt_dat->type = FC_REG_CT_EVENT;
		list_add(&evt_dat->node, &evt->events_to_see);
@@ -1459,13 +1455,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
		  struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp,
		  int num_entry)
{
	IOCB_t *icmd;
	struct lpfc_iocbq *ctiocb = NULL;
	int rc = 0;
	struct lpfc_nodelist *ndlp = NULL;
	struct bsg_job_data *dd_data;
	unsigned long flags;
	uint32_t creg_val;
	u16 ulp_context, iotag;

	ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
	if (!ndlp) {
@@ -1492,62 +1488,36 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
		goto no_ctiocb;
	}

	icmd = &ctiocb->iocb;
	icmd->un.xseq64.bdl.ulpIoTag32 = 0;
	icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
	icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys);
	icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
	icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
	icmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
	icmd->un.xseq64.w5.hcsw.Dfctl = 0;
	icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL;
	icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;

	/* Fill in rest of iocb */
	icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
	icmd->ulpBdeCount = 1;
	icmd->ulpLe = 1;
	icmd->ulpClass = CLASS3;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		/* Do not issue unsol response if oxid not marked as valid */
		if (phba->ct_ctx[tag].valid != UNSOL_VALID) {
			rc = IOCB_ERROR;
			goto issue_ct_rsp_exit;
		}
		icmd->ulpContext = phba->ct_ctx[tag].rxid;
		icmd->unsli3.rcvsli3.ox_id = phba->ct_ctx[tag].oxid;
		ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
		if (!ndlp) {
			lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
				 "2721 ndlp null for oxid %x SID %x\n",
					icmd->ulpContext,
					phba->ct_ctx[tag].SID);
			rc = IOCB_ERROR;
			goto issue_ct_rsp_exit;
		}

		/* get a refernece count so the ndlp doesn't go away while
		 * we respond
		 */
		if (!lpfc_nlp_get(ndlp)) {
			rc = IOCB_ERROR;
			goto issue_ct_rsp_exit;
		}

		icmd->un.ulpWord[3] =
				phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
		lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp,
					 phba->sli4_hba.rpi_ids[ndlp->nlp_rpi],
					 phba->ct_ctx[tag].oxid, num_entry,
					 FC_RCTL_DD_SOL_CTL, 1,
					 CMD_XMIT_SEQUENCE64_WQE);

		/* The exchange is done, mark the entry as invalid */
		phba->ct_ctx[tag].valid = UNSOL_INVALID;
	} else
		icmd->ulpContext = (ushort) tag;
		iotag = get_wqe_reqtag(ctiocb);
	} else {
		lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp, 0, tag, num_entry,
					 FC_RCTL_DD_SOL_CTL, 1,
					 CMD_XMIT_SEQUENCE64_CX);
		ctiocb->num_bdes = num_entry;
		iotag = ctiocb->iocb.ulpIoTag;
	}

	icmd->ulpTimeout = phba->fc_ratov * 2;
	ulp_context = get_job_ulpcontext(phba, ctiocb);

	/* Xmit CT response on exchange <xid> */
	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
			"2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
		icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
			ulp_context, iotag, tag, phba->link_state);

	ctiocb->cmd_flag |= LPFC_IO_LIBDFC;
	ctiocb->vport = phba->pport;
@@ -2633,7 +2603,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
{
	struct lpfc_bsg_event *evt;
	struct lpfc_iocbq *cmdiocbq, *rspiocbq;
	IOCB_t *cmd, *rsp;
	struct lpfc_dmabuf *dmabuf;
	struct ulp_bde64 *bpl = NULL;
	struct lpfc_sli_ct_request *ctreq = NULL;
@@ -2641,6 +2610,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
	int time_left;
	int iocb_stat = IOCB_SUCCESS;
	unsigned long flags;
	u32 status;

	*txxri = 0;
	*rxxri = 0;
@@ -2684,9 +2654,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
		goto err_get_xri_exit;
	}

	cmd = &cmdiocbq->iocb;
	rsp = &rspiocbq->iocb;

	memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);

	ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;
@@ -2696,36 +2663,24 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
	ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_XRI_SETUP;
	ctreq->CommandResponse.bits.Size = 0;


	cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(dmabuf->phys);
	cmd->un.xseq64.bdl.addrLow = putPaddrLow(dmabuf->phys);
	cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
	cmd->un.xseq64.bdl.bdeSize = sizeof(*bpl);

	cmd->un.xseq64.w5.hcsw.Fctl = LA;
	cmd->un.xseq64.w5.hcsw.Dfctl = 0;
	cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
	cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;

	cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR;
	cmd->ulpBdeCount = 1;
	cmd->ulpLe = 1;
	cmd->ulpClass = CLASS3;
	cmd->ulpContext = rpi;

	cmdiocbq->context3 = dmabuf;
	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
	cmdiocbq->vport = phba->pport;
	cmdiocbq->cmd_cmpl = NULL;

	lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, dmabuf, rpi, 0, 1,
				 FC_RCTL_DD_SOL_CTL, 0, CMD_XMIT_SEQUENCE64_CR);

	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
				rspiocbq,
				(phba->fc_ratov * 2)
					     rspiocbq, (phba->fc_ratov * 2)
					     + LPFC_DRVR_TIMEOUT);
	if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) {

	status = get_job_ulpstatus(phba, rspiocbq);
	if (iocb_stat != IOCB_SUCCESS || status != IOCB_SUCCESS) {
		ret_val = -EIO;
		goto err_get_xri_exit;
	}
	*txxri =  rsp->ulpContext;
	*txxri = get_job_ulpcontext(phba, rspiocbq);

	evt->waiting = 1;
	evt->wait_time_stamp = jiffies;
@@ -2926,7 +2881,7 @@ diag_cmd_data_alloc(struct lpfc_hba *phba,
}

/**
 * lpfcdiag_loop_post_rxbufs - post the receive buffers for an unsol CT cmd
 * lpfcdiag_sli3_loop_post_rxbufs - post the receive buffers for an unsol CT cmd
 * @phba: Pointer to HBA context object
 * @rxxri: Receive exchange id
 * @len: Number of data bytes
@@ -2934,7 +2889,7 @@ diag_cmd_data_alloc(struct lpfc_hba *phba,
 * This function allocates and posts a data buffer of sufficient size to receive
 * an unsolicted CT command.
 **/
static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
static int lpfcdiag_sli3_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
					  size_t len)
{
	struct lpfc_sli_ring *pring;
@@ -2972,7 +2927,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
	/* Queue buffers for the receive exchange */
	num_bde = (uint32_t)rxbuffer->flag;
	dmp = &rxbuffer->dma;

	cmd = &cmdiocbq->iocb;
	i = 0;

@@ -3040,7 +2994,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
			ret_val = -EIO;
			goto err_post_rxbufs_exit;
		}

		cmd = &cmdiocbq->iocb;
		i = 0;
	}
@@ -3092,7 +3045,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
	size_t segment_len = 0, segment_offset = 0, current_offset = 0;
	uint16_t rpi = 0;
	struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL;
	IOCB_t *cmd, *rsp = NULL;
	union lpfc_wqe128 *cmdwqe, *rspwqe;
	struct lpfc_sli_ct_request *ctreq;
	struct lpfc_dmabuf *txbmp;
	struct ulp_bde64 *txbpl = NULL;
@@ -3185,7 +3138,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
			goto loopback_test_exit;
		}

		rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
		rc = lpfcdiag_sli3_loop_post_rxbufs(phba, rxxri, full_size);
		if (rc) {
			lpfcdiag_loop_self_unreg(phba, rpi);
			goto loopback_test_exit;
@@ -3228,9 +3181,12 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
		goto err_loopback_test_exit;
	}

	cmd = &cmdiocbq->iocb;
	if (phba->sli_rev < LPFC_SLI_REV4)
		rsp = &rspiocbq->iocb;
	cmdwqe = &cmdiocbq->wqe;
	memset(cmdwqe, 0, sizeof(union lpfc_wqe));
	if (phba->sli_rev < LPFC_SLI_REV4) {
		rspwqe = &rspiocbq->wqe;
		memset(rspwqe, 0, sizeof(union lpfc_wqe));
	}

	INIT_LIST_HEAD(&head);
	list_add_tail(&head, &txbuffer->dma.list);
@@ -3262,42 +3218,32 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
	/* Build the XMIT_SEQUENCE iocb */
	num_bde = (uint32_t)txbuffer->flag;

	cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys);
	cmd->un.xseq64.bdl.addrLow = putPaddrLow(txbmp->phys);
	cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
	cmd->un.xseq64.bdl.bdeSize = (num_bde * sizeof(struct ulp_bde64));

	cmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
	cmd->un.xseq64.w5.hcsw.Dfctl = 0;
	cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
	cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;

	cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
	cmd->ulpBdeCount = 1;
	cmd->ulpLe = 1;
	cmd->ulpClass = CLASS3;
	cmdiocbq->num_bdes = num_bde;
	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
	cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
	cmdiocbq->vport = phba->pport;
	cmdiocbq->cmd_cmpl = NULL;
	cmdiocbq->context3 = txbmp;

	if (phba->sli_rev < LPFC_SLI_REV4) {
		cmd->ulpContext = txxri;
		lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp, 0, txxri,
					 num_bde, FC_RCTL_DD_UNSOL_CTL, 1,
					 CMD_XMIT_SEQUENCE64_CX);

	} else {
		cmd->un.xseq64.bdl.ulpIoTag32 = 0;
		cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi];
		cmdiocbq->context3 = txbmp;
		lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp,
					 phba->sli4_hba.rpi_ids[rpi], 0xffff,
					 full_size, FC_RCTL_DD_UNSOL_CTL, 1,
					 CMD_XMIT_SEQUENCE64_WQE);
		cmdiocbq->sli4_xritag = NO_XRI;
		cmd->unsli3.rcvsli3.ox_id = 0xffff;
	}
	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
	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);

	if ((iocb_stat != IOCB_SUCCESS) ||
	    ((phba->sli_rev < LPFC_SLI_REV4) &&
	     (rsp->ulpStatus != IOSTAT_SUCCESS))) {
	if (iocb_stat != IOCB_SUCCESS ||
	    (phba->sli_rev < LPFC_SLI_REV4 &&
	     (get_job_ulpstatus(phba, rspiocbq) != IOSTAT_SUCCESS))) {
		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
				"3126 Failed loopback test issue iocb: "
				"iocb_stat:x%x\n", iocb_stat);
+8 −0
Original line number Diff line number Diff line
@@ -358,6 +358,14 @@ void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba,
			       struct lpfc_vport *vport,
			       struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
			       u32 elscmd, u8 tmo, u8 expect_rsp);
void lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
			   struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry,
			   u8 tmo);
void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba,
			      struct lpfc_iocbq *cmdiocbq,
			      struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
			      u32 num_entry, u8 rctl, u8 last_seq,
			      u8 cr_cx_cmd);
struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri);
struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba,
					    struct lpfc_iocbq *piocbq);
+157 −176

File changed.

Preview size limit exceeded, changes collapsed.

+328 −62

File changed.

Preview size limit exceeded, changes collapsed.

Loading