Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[platform/kernel/linux-starfive.git] / drivers / scsi / lpfc / lpfc_nportdisc.c
index fdf5e77..c4e1a07 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -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,7 +374,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        NULL);
                return 0;
        }
-       icmd = &cmdiocb->iocb;
+
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               wqe = &cmdiocb->wqe;
+       else
+               icmd = &cmdiocb->iocb;
 
        /* PLOGI chkparm OK */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
@@ -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 */
-               vport->fc_myDID = icmd->un.rcvels.parmRo;
+               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;
@@ -680,13 +700,13 @@ static int
 lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                struct lpfc_iocbq *cmdiocb)
 {
+       struct lpfc_hba *phba = vport->phba;
        struct lpfc_iocbq  *elsiocb;
        struct lpfc_dmabuf *pcmd;
        struct serv_parm   *sp;
        struct lpfc_name   *pnn, *ppn;
        struct ls_rjt stat;
        ADISC *ap;
-       IOCB_t *icmd;
        uint32_t *lp;
        uint32_t cmd;
 
@@ -704,8 +724,8 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                ppn = (struct lpfc_name *) & sp->portName;
        }
 
-       icmd = &cmdiocb->iocb;
-       if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
+       if (get_job_ulpstatus(phba, cmdiocb) == 0 &&
+           lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
 
                /*
                 * As soon as  we send ACC, the remote NPort can
@@ -716,7 +736,6 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        elsiocb = kmalloc(sizeof(struct lpfc_iocbq),
                                GFP_KERNEL);
                        if (elsiocb) {
-
                                /* Save info from cmd IOCB used in rsp */
                                memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb,
                                        sizeof(struct lpfc_iocbq));
@@ -1312,23 +1331,24 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
        struct lpfc_dmabuf *pcmd, *prsp, *mp;
        uint32_t *lp;
        uint32_t vid, flag;
-       IOCB_t *irsp;
        struct serv_parm *sp;
        uint32_t ed_tov;
        LPFC_MBOXQ_t *mbox;
        int rc;
+       u32 ulp_status;
+       u32 did;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
        if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
                /* Recovery from PLOGI collision logic */
                return ndlp->nlp_state;
        }
 
-       irsp = &rspiocb->iocb;
-
-       if (irsp->ulpStatus)
+       if (ulp_status)
                goto out;
 
        pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -1440,7 +1460,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
                goto out;
        }
 
-       if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
+       did = get_job_els_rsp64_did(phba, cmdiocb);
+
+       if (lpfc_reg_rpi(phba, vport->vpi, did,
                         (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
                switch (ndlp->nlp_DID) {
                case NameServer_DID:
@@ -1670,17 +1692,18 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
 {
        struct lpfc_hba   *phba = vport->phba;
        struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
        ADISC *ap;
        int rc;
+       u32 ulp_status;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
        ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
-       irsp = &rspiocb->iocb;
 
-       if ((irsp->ulpStatus) ||
+       if ((ulp_status) ||
            (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
                /* 1 sec timeout */
                mod_timer(&ndlp->nlp_delayfunc,
@@ -2123,14 +2146,16 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 {
        struct lpfc_iocbq *cmdiocb, *rspiocb;
        struct lpfc_hba   *phba = vport->phba;
-       IOCB_t *irsp;
        PRLI *npr;
        struct lpfc_nvme_prli *nvpr;
        void *temp_ptr;
+       u32 ulp_status;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
        /* A solicited PRLI is either FCP or NVME.  The PRLI cmd/rsp
         * format is different so NULL the two PRLI types so that the
         * driver correctly gets the correct context.
@@ -2138,13 +2163,12 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        npr = NULL;
        nvpr = NULL;
        temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
-       if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ)
+       if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ)
                npr = (PRLI *) temp_ptr;
-       else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ)
+       else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ)
                nvpr = (struct lpfc_nvme_prli *) temp_ptr;
 
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus) {
+       if (ulp_status) {
                if ((vport->port_type == LPFC_NPIV_PORT) &&
                    vport->cfg_restrict_login) {
                        goto out;
@@ -2743,16 +2767,18 @@ static uint32_t
 lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                         void *arg, uint32_t evt)
 {
+       struct lpfc_hba *phba = vport->phba;
        struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
+       u32 ulp_status;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus) {
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
+       if (ulp_status)
                return NLP_STE_FREED_NODE;
-       }
+
        return ndlp->nlp_state;
 }
 
@@ -2760,14 +2786,16 @@ static uint32_t
 lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        void *arg, uint32_t evt)
 {
+       struct lpfc_hba *phba = vport->phba;
        struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
+       u32 ulp_status;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
+       if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
                lpfc_drop_node(vport, ndlp);
                return NLP_STE_FREED_NODE;
        }
@@ -2794,14 +2822,16 @@ static uint32_t
 lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                         void *arg, uint32_t evt)
 {
+       struct lpfc_hba *phba = vport->phba;
        struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
+       u32 ulp_status;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
 
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+       ulp_status = get_job_ulpstatus(phba, rspiocb);
+
+       if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
                lpfc_drop_node(vport, ndlp);
                return NLP_STE_FREED_NODE;
        }