[SCSI] lpfc 8.3.28: Add Loopback support for SLI4 adapters
[linux-2.6-block.git] / drivers / scsi / lpfc / lpfc_hbadisc.c
index d96498581ebe989568ab217cc38ee026689d13a8..678a4b11059c3ad7feccadf7a8428d6436a3e218 100644 (file)
@@ -1074,6 +1074,12 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 
        mempool_free(pmb, phba->mbox_mem_pool);
 
+       /* don't perform discovery for SLI4 loopback diagnostic test */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           !(phba->hba_flag & HBA_FCOE_MODE) &&
+           (phba->link_flag & LS_LOOPBACK_MODE))
+               return;
+
        if (phba->fc_topology == LPFC_TOPOLOGY_LOOP &&
            vport->fc_flag & FC_PUBLIC_LOOP &&
            !(vport->fc_flag & FC_LBIT)) {
@@ -2847,10 +2853,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                        lpfc_disc_list_loopmap(vport);
                        /* Start discovery */
                        lpfc_disc_start(vport);
-                       goto fail_free_mem;
+                       goto out_free_mem;
                }
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-               goto fail_free_mem;
+               goto out_free_mem;
        }
        /* The VPI is implicitly registered when the VFI is registered */
        spin_lock_irq(shost->host_lock);
@@ -2860,6 +2866,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI;
        spin_unlock_irq(shost->host_lock);
 
+       /* In case SLI4 FC loopback test, we are ready */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           (phba->link_flag & LS_LOOPBACK_MODE)) {
+               phba->link_state = LPFC_HBA_READY;
+               goto out_free_mem;
+       }
+
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
                /* For private loop just start discovery and we are done. */
                if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
@@ -2874,7 +2887,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                }
        }
 
-fail_free_mem:
+out_free_mem:
        mempool_free(mboxq, phba->mbox_mem_pool);
        lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
        kfree(dmabuf);
@@ -3235,15 +3248,14 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        } else if (bf_get(lpfc_mbx_read_top_att_type, la) ==
                   LPFC_ATT_LINK_DOWN) {
                phba->fc_stat.LinkDown++;
-               if (phba->link_flag & LS_LOOPBACK_MODE) {
+               if (phba->link_flag & LS_LOOPBACK_MODE)
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "1308 Link Down Event in loop back mode "
                                "x%x received "
                                "Data: x%x x%x x%x\n",
                                la->eventTag, phba->fc_eventTag,
                                phba->pport->port_state, vport->fc_flag);
-               }
-               else {
+               else
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "1305 Link Down Event x%x received "
                                "Data: x%x x%x x%x x%x x%x\n",
@@ -3251,7 +3263,6 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                phba->pport->port_state, vport->fc_flag,
                                bf_get(lpfc_mbx_read_top_mm, la),
                                bf_get(lpfc_mbx_read_top_fa, la));
-               }
                lpfc_mbx_issue_link_down(phba);
        }
        if ((bf_get(lpfc_mbx_read_top_mm, la)) &&
@@ -5682,7 +5693,7 @@ out:
  *
  * This function frees memory associated with the mailbox command.
  */
-static void
+void
 lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
        struct lpfc_vport *vport = mboxq->vport;
@@ -5734,7 +5745,6 @@ lpfc_unregister_fcfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 int
 lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
 {
-       LPFC_MBOXQ_t *mbox;
        struct lpfc_vport **vports;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host *shost;
@@ -5770,35 +5780,9 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
 
-       /* Unregister VFI */
-       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!mbox) {
-               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(mbox, phba->pport);
-       mbox->vport = phba->pport;
-       mbox->mbox_cmpl = lpfc_unregister_vfi_cmpl;
-
-       rc = lpfc_sli_issue_mbox(phba, mbox, 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(mbox, phba->mbox_mem_pool);
-               return -EIO;
-       }
-
-       shost = lpfc_shost_from_vport(phba->pport);
-       spin_lock_irq(shost->host_lock);
-       phba->pport->fc_flag &= ~FC_VFI_REGISTERED;
-       spin_unlock_irq(shost->host_lock);
-
-       return 0;
+       /* Unregister the physical port VFI */
+       rc = lpfc_issue_unreg_vfi(phba->pport);
+       return rc;
 }
 
 /**