[SCSI] lpfc 8.3.29: SLI related fixes
authorJames Smart <james.smart@emulex.com>
Wed, 18 Jan 2012 21:24:06 +0000 (16:24 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 19 Feb 2012 14:08:52 +0000 (08:08 -0600)
SLI related fixes:

- Fix REG_RPI fails on SLI4 HBA putting NPort into NPR state (126230)
- Fix ELS FDISC failing with local reject / invalid RPI. (126350)
- Fix reset port when reset is needed during fw_dump (125807)
- Fix unbounded firmware revision string from port cause panic (126560)
- Fix driver behavior when receiving an ADISC (126654)
- Fix driver not returning when bad ndlp found in abts error event
  handling (126209)
- Add more driver logs in area of SLI4 port error attention and reset
  recovery (126813, 124466)
- Fix failure in handling large CQ/EQ identifiers in an IOV
  environment (126856)
- Fix for driver using duplicate RPIs after lancer port reset (126723)
- Clear vport->fc_myDID in lpfc_els_issue_fdisc to guarentee a
  zero SID (126779, 126897)
- Fix for SLI4 Port delivery for BLS ABORT ACC (126289)

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/lpfc/lpfc_attr.c
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_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index f6697cb0e21607fe154753859582c719693225c7..296ad5bc42400692116686ac764570a350181896 100644 (file)
@@ -353,7 +353,7 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
        struct lpfc_hba   *phba = vport->phba;
        uint32_t if_type;
        uint8_t sli_family;
-       char fwrev[32];
+       char fwrev[FW_REV_STR_SIZE];
        int len;
 
        lpfc_decode_firmware_rev(phba, fwrev, 1);
@@ -922,11 +922,15 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
        rc = lpfc_sli4_pdev_status_reg_wait(phba);
 
        if (rc == -EPERM) {
-               /* no privilage for reset, restore if needed */
-               if (before_fc_flag & FC_OFFLINE_MODE)
-                       goto out;
+               /* no privilage for reset */
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "3150 No privilage to perform the requested "
+                               "access: x%x\n", reg_val);
        } else if (rc == -EIO) {
                /* reset failed, there is nothing more we can do */
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "3153 Fail to perform the requested "
+                               "access: x%x\n", reg_val);
                return rc;
        }
 
index 6cb360d47ba3c410537228a08d205f18de453c69..141e4b40bb552122cb7f827e0fc448be104d5502 100644 (file)
@@ -3980,7 +3980,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
                                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                                "3106 Handled SLI_CONFIG "
-                                               "subsys_fcoe, opcode:x%x\n",
+                                               "subsys_comn, opcode:x%x\n",
                                                opcode);
                                rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
                                                        nemb_mse, dmabuf);
@@ -3988,7 +3988,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        default:
                                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                                "3107 Reject SLI_CONFIG "
-                                               "subsys_fcoe, opcode:x%x\n",
+                                               "subsys_comn, opcode:x%x\n",
                                                opcode);
                                rc = -EPERM;
                                break;
index 26924b7a6cdebf1feca844dbe9233be6cc51c63c..330dd7192a7f0216373228d0aab44156caf4e019 100644 (file)
@@ -462,3 +462,4 @@ int lpfc_issue_unreg_vfi(struct lpfc_vport *);
 int lpfc_selective_reset(struct lpfc_hba *);
 int lpfc_sli4_read_config(struct lpfc_hba *phba);
 int lpfc_scsi_buf_update(struct lpfc_hba *phba);
+void lpfc_sli4_node_prep(struct lpfc_hba *phba);
index 707081d0a2265ad88e7d4b18c25ca0d51d2a9998..93e96b3c9097aff51694c6f7cc6f35dd695deead 100644 (file)
@@ -1076,7 +1076,7 @@ int
 lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
        size_t size)
 {
-       char fwrev[16];
+       char fwrev[FW_REV_STR_SIZE];
        int n;
 
        lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
@@ -1834,7 +1834,7 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
        uint8_t *fwname;
 
        if (phba->sli_rev == LPFC_SLI_REV4)
-               sprintf(fwrevision, "%s", vp->rev.opFwName);
+               snprintf(fwrevision, FW_REV_STR_SIZE, "%s", vp->rev.opFwName);
        else if (vp->rev.rBit) {
                if (psli->sli_flag & LPFC_SLI_ACTIVE)
                        rev = vp->rev.sli2FwRev;
index 7afc757338de2de3137ed2643e5c4a1ac8701af1..2e7709f680bcae8cf97dfbd9c4912602e3a04de0 100644 (file)
@@ -7172,7 +7172,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        goto out;
                /* FDISC failed */
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-                                "0126 FDISC failed. (%d/%d)\n",
+                                "0126 FDISC failed. (x%x/x%x)\n",
                                 irsp->ulpStatus, irsp->un.ulpWord[4]);
                goto fdisc_failed;
        }
@@ -7283,6 +7283,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        int rc;
 
        vport->port_state = LPFC_FDISC;
+       vport->fc_myDID = 0;
        cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
        elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
                                     ELS_CMD_FDISC);
index 7b3dbf316bb3d6832b504f95ecec87c4128d6908..5f280b5ae3db8a9a8df45044422e203bde93748f 100644 (file)
@@ -70,6 +70,7 @@
 /* vendor ID used in SCSI netlink calls */
 #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX)
 
+#define FW_REV_STR_SIZE        32
 /* Common Transport structures and definitions */
 
 union CtRevisionId {
index e5bfa7f334e38c9a5f872225cd27bb82f9ac84fb..cc19bc1b5ace2d3c8deb4b52dadb77fe4c922aa7 100644 (file)
@@ -715,12 +715,20 @@ struct lpfc_register {
 #define lpfc_eqcq_doorbell_eqci_SHIFT          9
 #define lpfc_eqcq_doorbell_eqci_MASK           0x0001
 #define lpfc_eqcq_doorbell_eqci_WORD           word0
-#define lpfc_eqcq_doorbell_cqid_SHIFT          0
-#define lpfc_eqcq_doorbell_cqid_MASK           0x03FF
-#define lpfc_eqcq_doorbell_cqid_WORD           word0
-#define lpfc_eqcq_doorbell_eqid_SHIFT          0
-#define lpfc_eqcq_doorbell_eqid_MASK           0x01FF
-#define lpfc_eqcq_doorbell_eqid_WORD           word0
+#define lpfc_eqcq_doorbell_cqid_lo_SHIFT       0
+#define lpfc_eqcq_doorbell_cqid_lo_MASK                0x03FF
+#define lpfc_eqcq_doorbell_cqid_lo_WORD                word0
+#define lpfc_eqcq_doorbell_cqid_hi_SHIFT       11
+#define lpfc_eqcq_doorbell_cqid_hi_MASK                0x001F
+#define lpfc_eqcq_doorbell_cqid_hi_WORD                word0
+#define lpfc_eqcq_doorbell_eqid_lo_SHIFT       0
+#define lpfc_eqcq_doorbell_eqid_lo_MASK                0x01FF
+#define lpfc_eqcq_doorbell_eqid_lo_WORD                word0
+#define lpfc_eqcq_doorbell_eqid_hi_SHIFT       11
+#define lpfc_eqcq_doorbell_eqid_hi_MASK                0x001F
+#define lpfc_eqcq_doorbell_eqid_hi_WORD                word0
+#define LPFC_CQID_HI_FIELD_SHIFT               10
+#define LPFC_EQID_HI_FIELD_SHIFT               9
 
 #define LPFC_BMBX                      0x0160
 #define lpfc_bmbx_addr_SHIFT           2
@@ -3313,7 +3321,11 @@ struct xmit_bls_rsp64_wqe {
        uint32_t rsrvd4;
        struct wqe_did  wqe_dest;
        struct wqe_common wqe_com; /* words 6-11 */
-       uint32_t rsvd_12_15[4];
+       uint32_t word12;
+#define xmit_bls_rsp64_temprpi_SHIFT  0
+#define xmit_bls_rsp64_temprpi_MASK   0x0000ffff
+#define xmit_bls_rsp64_temprpi_WORD   word12
+       uint32_t rsvd_13_15[3];
 };
 
 struct wqe_rctl_dfctl {
index d670b1c410ece1e03075b4c9fc4588431aa84762..f3ad7349f5d130a84aeadf2fb575919256e2cd11 100644 (file)
@@ -1475,8 +1475,12 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
                                phba->sli4_hba.u.if_type2.STATUSregaddr,
                                &portstat_reg.word0);
                /* consider PCI bus read error as pci_channel_offline */
-               if (pci_rd_rc1 == -EIO)
+               if (pci_rd_rc1 == -EIO) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3151 PCI bus read access failure: x%x\n",
+                               readl(phba->sli4_hba.u.if_type2.STATUSregaddr));
                        return;
+               }
                reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
                reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
                if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
@@ -1526,6 +1530,9 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
                        }
                        /* fall through for not able to recover */
                }
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3152 Unrecoverable error, bring the port "
+                               "offline\n");
                lpfc_sli4_offline_eratt(phba);
                break;
        case LPFC_SLI_INTF_IF_TYPE_1:
@@ -2513,6 +2520,42 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
        }
 }
 
+/**
+ * lpfc_sli4_node_prep - Assign RPIs for active nodes.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * Allocate RPIs for all active remote nodes. This is needed whenever
+ * an SLI4 adapter is reset and the driver is not unloading. Its purpose
+ * is to fixup the temporary rpi assignments.
+ **/
+void
+lpfc_sli4_node_prep(struct lpfc_hba *phba)
+{
+       struct lpfc_nodelist  *ndlp, *next_ndlp;
+       struct lpfc_vport **vports;
+       int i;
+
+       if (phba->sli_rev != LPFC_SLI_REV4)
+               return;
+
+       vports = lpfc_create_vport_work_array(phba);
+       if (vports != NULL) {
+               for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+                       if (vports[i]->load_flag & FC_UNLOADING)
+                               continue;
+
+                       list_for_each_entry_safe(ndlp, next_ndlp,
+                                                &vports[i]->fc_nodes,
+                                                nlp_listp) {
+                               if (NLP_CHK_NODE_ACT(ndlp))
+                                       ndlp->nlp_rpi =
+                                               lpfc_sli4_alloc_rpi(phba);
+                       }
+               }
+       }
+       lpfc_destroy_vport_work_array(phba, vports);
+}
+
 /**
  * lpfc_online - Initialize and bring a HBA online
  * @phba: pointer to lpfc hba data structure.
@@ -2654,6 +2697,15 @@ lpfc_offline_prep(struct lpfc_hba * phba)
                                }
                                spin_lock_irq(shost->host_lock);
                                ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+
+                               /*
+                                * Whenever an SLI4 port goes offline, free the
+                                * RPI.  A new RPI when the adapter port comes
+                                * back online.
+                                */
+                               if (phba->sli_rev == LPFC_SLI_REV4)
+                                       lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
+
                                spin_unlock_irq(shost->host_lock);
                                lpfc_unreg_rpi(vports[i], ndlp);
                        }
@@ -7224,19 +7276,17 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                                        rc = -ENODEV;
                                        goto out;
                                }
-                               if (bf_get(lpfc_sliport_status_rdy, &reg_data))
-                                       break;
-                               if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
+                               if (bf_get(lpfc_sliport_status_rn, &reg_data))
                                        reset_again++;
+                               if (bf_get(lpfc_sliport_status_rdy, &reg_data))
                                        break;
-                               }
                        }
 
                        /*
                         * If the port responds to the init request with
                         * reset needed, delay for a bit and restart the loop.
                         */
-                       if (reset_again) {
+                       if (reset_again && (rdy_chk < 1000)) {
                                msleep(10);
                                reset_again = 0;
                                continue;
@@ -9059,7 +9109,7 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
 int
 lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
 {
-       char fwrev[32];
+       char fwrev[FW_REV_STR_SIZE];
        struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data;
        struct list_head dma_buffer_list;
        int i, rc = 0;
index e8bb0055994316a790db82111163295efa5ba7be..32b6d72cd98da8ac98355c9a7de1a526d12660de 100644 (file)
@@ -48,6 +48,10 @@ static int
 lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                 struct lpfc_name *nn, struct lpfc_name *pn)
 {
+       /* First, we MUST have a RPI registered */
+       if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
+               return 0;
+
        /* Compare the ADISC rsp WWNN / WWPN matches our internal node
         * table entry for that node.
         */
@@ -385,6 +389,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        if (!mbox)
                goto out;
 
+       /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               lpfc_unreg_rpi(vport, ndlp);
+
        rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
                            (uint8_t *) sp, mbox, ndlp->nlp_rpi);
        if (rc) {
@@ -445,11 +453,42 @@ out:
        return 0;
 }
 
+/**
+ * lpfc_mbx_cmpl_resume_rpi - Resume RPI completion routine
+ * @phba: pointer to lpfc hba data structure.
+ * @mboxq: pointer to mailbox object
+ *
+ * This routine is invoked to issue a completion to a rcv'ed
+ * ADISC or PDISC after the paused RPI has been resumed.
+ **/
+static void
+lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+       struct lpfc_vport *vport;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_nodelist *ndlp;
+       uint32_t cmd;
+
+       elsiocb = (struct lpfc_iocbq *)mboxq->context1;
+       ndlp = (struct lpfc_nodelist *) mboxq->context2;
+       vport = mboxq->vport;
+       cmd = elsiocb->drvrTimeout;
+
+       if (cmd == ELS_CMD_ADISC) {
+               lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);
+       } else {
+               lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,
+                       ndlp, NULL);
+       }
+       kfree(elsiocb);
+}
+
 static int
 lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                struct lpfc_iocbq *cmdiocb)
 {
        struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_iocbq  *elsiocb;
        struct lpfc_dmabuf *pcmd;
        struct serv_parm   *sp;
        struct lpfc_name   *pnn, *ppn;
@@ -475,12 +514,43 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
        icmd = &cmdiocb->iocb;
        if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
+
+               /*
+                * As soon as  we send ACC, the remote NPort can
+                * start sending us data. Thus, for SLI4 we must
+                * resume the RPI before the ACC goes out.
+                */
+               if (vport->phba->sli_rev == LPFC_SLI_REV4) {
+                       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));
+
+                               /* Save the ELS cmd */
+                               elsiocb->drvrTimeout = cmd;
+
+                               lpfc_sli4_resume_rpi(ndlp,
+                                       lpfc_mbx_cmpl_resume_rpi, elsiocb);
+                               goto out;
+                       }
+               }
+
                if (cmd == ELS_CMD_ADISC) {
                        lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
                } else {
-                       lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
-                                        NULL);
+                       lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
+                               ndlp, NULL);
                }
+out:
+               /* If we are authenticated, move to the proper state */
+               if (ndlp->nlp_type & NLP_FCP_TARGET)
+                       lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
+               else
+                       lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
+
                return 1;
        }
        /* Reject this request because invalid parameters */
@@ -1229,7 +1299,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
        }
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
-               rc = lpfc_sli4_resume_rpi(ndlp);
+               rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);
                if (rc) {
                        /* Stay in state and retry. */
                        ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
index 42ea367ddba7a350dc16504f002cba677eb9d270..1a391e2df3b3d46a8ee5976ff66e089df2cf72e6 100644 (file)
@@ -293,7 +293,9 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm)
        }
        bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released);
        bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_EVENT);
-       bf_set(lpfc_eqcq_doorbell_eqid, &doorbell, q->queue_id);
+       bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell,
+                       (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT));
+       bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id);
        writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr);
        /* PCI read to flush PCI pipeline on re-arming for INTx mode */
        if ((q->phba->intr_type == INTx) && (arm == LPFC_QUEUE_REARM))
@@ -372,7 +374,9 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm)
                bf_set(lpfc_eqcq_doorbell_arm, &doorbell, 1);
        bf_set(lpfc_eqcq_doorbell_num_released, &doorbell, released);
        bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_COMPLETION);
-       bf_set(lpfc_eqcq_doorbell_cqid, &doorbell, q->queue_id);
+       bf_set(lpfc_eqcq_doorbell_cqid_hi, &doorbell,
+                       (q->queue_id >> LPFC_CQID_HI_FIELD_SHIFT));
+       bf_set(lpfc_eqcq_doorbell_cqid_lo, &doorbell, q->queue_id);
        writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr);
        return released;
 }
@@ -5596,6 +5600,8 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
                for (i = 0; i < count; i++)
                        phba->sli4_hba.rpi_ids[i] = base + i;
 
+               lpfc_sli4_node_prep(phba);
+
                /* VPIs. */
                count = phba->sli4_hba.max_cfg_param.max_vpi;
                base = phba->sli4_hba.max_cfg_param.vpi_base;
@@ -7555,6 +7561,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
 
        sgl  = (struct sli4_sge *)sglq->sgl;
        icmd = &piocbq->iocb;
+       if (icmd->ulpCommand == CMD_XMIT_BLS_RSP64_CX)
+               return sglq->sli4_xritag;
        if (icmd->un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) {
                numBdes = icmd->un.genreq64.bdl.bdeSize /
                                sizeof(struct ulp_bde64);
@@ -7756,6 +7764,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
                        if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
                                *pcmd == ELS_CMD_SCR ||
+                               *pcmd == ELS_CMD_FDISC ||
                                *pcmd == ELS_CMD_PLOGI)) {
                                bf_set(els_req64_sp, &wqe->els_req, 1);
                                bf_set(els_req64_sid, &wqe->els_req,
@@ -7982,6 +7991,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                xritag = 0;
                break;
        case CMD_XMIT_BLS_RSP64_CX:
+               ndlp = (struct lpfc_nodelist *)iocbq->context1;
                /* As BLS ABTS RSP WQE is very different from other WQEs,
                 * we re-construct this WQE here based on information in
                 * iocbq from scratch.
@@ -8008,8 +8018,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                }
                bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
                bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
+
+               /* Use CT=VPI */
+               bf_set(wqe_els_did, &wqe->xmit_bls_rsp.wqe_dest,
+                       ndlp->nlp_DID);
+               bf_set(xmit_bls_rsp64_temprpi, &wqe->xmit_bls_rsp,
+                       iocbq->iocb.ulpContext);
+               bf_set(wqe_ct, &wqe->xmit_bls_rsp.wqe_com, 1);
                bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com,
-                      iocbq->iocb.ulpContext);
+                       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);
@@ -8073,8 +8090,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
 
        if (piocb->sli4_xritag == NO_XRI) {
                if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
-                   piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN ||
-                   piocb->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX)
+                   piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
                        sglq = NULL;
                else {
                        if (pring->txq_cnt) {
@@ -8384,10 +8400,13 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
 {
        struct lpfc_vport *vport;
 
-       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
                lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                                "3115 Node Context not found, driver "
                                "ignoring abts err event\n");
+               return;
+       }
+
        vport = ndlp->vport;
        lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
                        "3116 Port generated FCP XRI ABORT event on "
@@ -14042,6 +14061,13 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
 {
        if (cmd_iocbq)
                lpfc_sli_release_iocbq(phba, cmd_iocbq);
+
+       /* Failure means BLS ABORT RSP did not get delivered to remote node*/
+       if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus)
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                       "3154 BLS ABORT RSP failed, data:  x%x/x%x\n",
+                       rsp_iocbq->iocb.ulpStatus,
+                       rsp_iocbq->iocb.un.ulpWord[4]);
 }
 
 /**
@@ -14748,7 +14774,8 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba)
  * provided rpi via a bitmask.
  **/
 int
-lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp)
+lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
+       void (*cmpl)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *arg)
 {
        LPFC_MBOXQ_t *mboxq;
        struct lpfc_hba *phba = ndlp->phba;
@@ -14761,6 +14788,12 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp)
 
        /* Post all rpi memory regions to the port. */
        lpfc_resume_rpi(mboxq, ndlp);
+       if (cmpl) {
+               mboxq->mbox_cmpl = cmpl;
+               mboxq->context1 = arg;
+               mboxq->context2 = ndlp;
+       }
+       mboxq->vport = ndlp->vport;
        rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
index 3f266e2c54e0d7f57131b91b4aa3bb1dd1dc9cf6..c19d139618b729ed7d7f5b8dfb99406e59e25236 100644 (file)
@@ -633,7 +633,8 @@ void lpfc_sli4_free_rpi(struct lpfc_hba *, int);
 void lpfc_sli4_remove_rpis(struct lpfc_hba *);
 void lpfc_sli4_async_event_proc(struct lpfc_hba *);
 void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
-int lpfc_sli4_resume_rpi(struct lpfc_nodelist *);
+int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
+                       void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
 void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *);
 void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *);
 void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,