[SCSI] lpfc 8.3.28: Add Loopback support for SLI4 adapters
[deliverable/linux.git] / drivers / scsi / lpfc / lpfc_els.c
index 0b662db232848ddfe22bac96f3df1c624e4cce0b..7afc757338de2de3137ed2643e5c4a1ac8701af1 100644 (file)
@@ -421,13 +421,13 @@ fail:
  * @vport: pointer to a host virtual N_Port data structure.
  *
  * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for
- * the @vport. This mailbox command is necessary for FCoE only.
+ * the @vport. This mailbox command is necessary for SLI4 port only.
  *
  * Return code
  *   0 - successfully issued REG_VFI for @vport
  *   A failure code otherwise.
  **/
-static int
+int
 lpfc_issue_reg_vfi(struct lpfc_vport *vport)
 {
        struct lpfc_hba  *phba = vport->phba;
@@ -438,10 +438,14 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
        int rc = 0;
 
        sp = &phba->fc_fabparam;
-       ndlp = lpfc_findnode_did(vport, Fabric_DID);
-       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
-               rc = -ENODEV;
-               goto fail;
+       /* move forward in case of SLI4 FC port loopback test */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           !(phba->link_flag & LS_LOOPBACK_MODE)) {
+               ndlp = lpfc_findnode_did(vport, Fabric_DID);
+               if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+                       rc = -ENODEV;
+                       goto fail;
+               }
        }
 
        dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
@@ -486,6 +490,54 @@ fail:
        return rc;
 }
 
+/**
+ * lpfc_issue_unreg_vfi - Unregister VFI for this vport's fabric login
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues a UNREG_VFI mailbox with the vfi, vpi, fcfi triplet for
+ * the @vport. This mailbox command is necessary for SLI4 port only.
+ *
+ * Return code
+ *   0 - successfully issued REG_VFI for @vport
+ *   A failure code otherwise.
+ **/
+int
+lpfc_issue_unreg_vfi(struct lpfc_vport *vport)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct Scsi_Host *shost;
+       LPFC_MBOXQ_t *mboxq;
+       int rc;
+
+       mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+                               "2556 UNREG_VFI mbox allocation failed"
+                               "HBA state x%x\n", phba->pport->port_state);
+               return -ENOMEM;
+       }
+
+       lpfc_unreg_vfi(mboxq, vport);
+       mboxq->vport = vport;
+       mboxq->mbox_cmpl = lpfc_unregister_vfi_cmpl;
+
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
+       if (rc == MBX_NOT_FINISHED) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+                               "2557 UNREG_VFI issue mbox failed rc x%x "
+                               "HBA state x%x\n",
+                               rc, phba->pport->port_state);
+               mempool_free(mboxq, phba->mbox_mem_pool);
+               return -EIO;
+       }
+
+       shost = lpfc_shost_from_vport(vport);
+       spin_lock_irq(shost->host_lock);
+       vport->fc_flag &= ~FC_VFI_REGISTERED;
+       spin_unlock_irq(shost->host_lock);
+       return 0;
+}
+
 /**
  * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean.
  * @vport: pointer to a host virtual N_Port data structure.
@@ -615,7 +667,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                         "1816 FLOGI NPIV supported, "
                                         "response data 0x%x\n",
                                         sp->cmn.response_multiple_NPort);
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
+                       spin_unlock_irq(&phba->hbalock);
                } else {
                        /* Because we asked f/w for NPIV it still expects us
                        to call reg_vnpid atleast for the physcial host */
@@ -623,7 +677,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                         LOG_ELS | LOG_VPORT,
                                         "1817 Fabric does not support NPIV "
                                         "- configuring single port mode.\n");
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+                       spin_unlock_irq(&phba->hbalock);
                }
        }
 
@@ -686,11 +742,16 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        lpfc_do_scr_ns_plogi(phba, vport);
                } else if (vport->fc_flag & FC_VFI_REGISTERED)
                        lpfc_issue_init_vpi(vport);
-               else
+               else {
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                       "3135 Need register VFI: (x%x/%x)\n",
+                                       vport->fc_prevDID, vport->fc_myDID);
                        lpfc_issue_reg_vfi(vport);
+               }
        }
        return 0;
 }
+
 /**
  * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port
  * @vport: pointer to a host virtual N_Port data structure.
@@ -907,9 +968,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
                 * alpa map would take too long otherwise.
                 */
-               if (phba->alpa_map[0] == 0) {
+               if (phba->alpa_map[0] == 0)
                        vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
-               }
                if ((phba->sli_rev == LPFC_SLI_REV4) &&
                    (!(vport->fc_flag & FC_VFI_REGISTERED) ||
                     (vport->fc_prevDID != vport->fc_myDID))) {
@@ -1164,8 +1224,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
        spin_lock_irq(&phba->hbalock);
        list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
                icmd = &iocb->iocb;
-               if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
-                   icmd->un.elsreq64.bdl.ulpIoTag32) {
+               if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
                        if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
                            (ndlp->nlp_DID == Fabric_DID))
@@ -4879,23 +4938,31 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                            sizeof(struct lpfc_name));
 
                if (!rc) {
-                       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-                       if (!mbox)
+                       if (phba->sli_rev < LPFC_SLI_REV4) {
+                               mbox = mempool_alloc(phba->mbox_mem_pool,
+                                                    GFP_KERNEL);
+                               if (!mbox)
+                                       return 1;
+                               lpfc_linkdown(phba);
+                               lpfc_init_link(phba, mbox,
+                                              phba->cfg_topology,
+                                              phba->cfg_link_speed);
+                               mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
+                               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+                               mbox->vport = vport;
+                               rc = lpfc_sli_issue_mbox(phba, mbox,
+                                                        MBX_NOWAIT);
+                               lpfc_set_loopback_flag(phba);
+                               if (rc == MBX_NOT_FINISHED)
+                                       mempool_free(mbox, phba->mbox_mem_pool);
                                return 1;
-
-                       lpfc_linkdown(phba);
-                       lpfc_init_link(phba, mbox,
-                                      phba->cfg_topology,
-                                      phba->cfg_link_speed);
-                       mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
-                       mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-                       mbox->vport = vport;
-                       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-                       lpfc_set_loopback_flag(phba);
-                       if (rc == MBX_NOT_FINISHED) {
-                               mempool_free(mbox, phba->mbox_mem_pool);
+                       } else {
+                               /* abort the flogi coming back to ourselves
+                                * due to external loopback on the port.
+                                */
+                               lpfc_els_abort_flogi(phba);
+                               return 0;
                        }
-                       return 1;
                } else if (rc > 0) {    /* greater than */
                        spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_PT2PT_PLOGI;
@@ -5850,8 +5917,12 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        vport->fc_myDID = vport->fc_prevDID;
                        if (phba->sli_rev < LPFC_SLI_REV4)
                                lpfc_issue_fabric_reglogin(vport);
-                       else
+                       else {
+                               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                       "3138 Need register VFI: (x%x/%x)\n",
+                                       vport->fc_prevDID, vport->fc_myDID);
                                lpfc_issue_reg_vfi(vport);
+                       }
                }
        }
        return 0;
This page took 0.045123 seconds and 5 git commands to generate.