]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: lpfc: SLI path split: Introduce lpfc_prep_wqe
authorJames Smart <jsmart2021@gmail.com>
Fri, 25 Feb 2022 02:22:54 +0000 (18:22 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 15 Mar 2022 17:51:48 +0000 (13:51 -0400)
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: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_sli.c

index 6688a575904f25128c46ef94423c6a03d92f5fd4..1a97426e72de8e09cf5d4e74d3ba5d4a3a36ea42 100644 (file)
@@ -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);
index 435428fdaa6e16c19543b5343e96f727feedaed3..51febb73e9a6460fe296cea4853cc54610952aad 100644 (file)
@@ -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 *,
index 19e2f8086a6dafd6ef3b92b1c42553199a33d307..8a19e990881192d1f1750a36edbc1438ef618d05 100644 (file)
@@ -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) {
index dde8532f91acfe8c813f5d520745cd182d9ec343..93ff63ee96dd0ddda715c3707e1442248da78870 100644 (file)
@@ -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);
index c87d902862c6cf65415b98c6bce01cc12889703a..6867933c6ab66b721d23d1ac28fb6c953c58a764 100644 (file)
@@ -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);
+}