[SCSI] lpfc 8.3.11: NPIV changes
authorJames Smart <james.smart@emulex.com>
Mon, 15 Mar 2010 15:25:44 +0000 (11:25 -0400)
committerJames Bottomley <James.Bottomley@suse.de>
Sun, 11 Apr 2010 14:23:51 +0000 (09:23 -0500)
- Enable NPIV by default.
- Added code to handle unsolicited LOGO on physical port.

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_nportdisc.c

index 23b9320539e1344e675d22958243aca94528faeb..e35a4c71eb9a8c8755876b71d000dc01a7902262 100644 (file)
@@ -310,7 +310,9 @@ struct lpfc_vport {
 #define FC_NLP_MORE             0x40    /* More node to process in node tbl */
 #define FC_OFFLINE_MODE         0x80    /* Interface is offline for diag */
 #define FC_FABRIC               0x100   /* We are fabric attached */
+#define FC_VPORT_LOGO_RCVD      0x200    /* LOGO received on vport */
 #define FC_RSCN_DISCOVERY       0x400   /* Auth all devices after RSCN */
+#define FC_LOGO_RCVD_DID_CHNG   0x800    /* FDISC on phys port detect DID chng*/
 #define FC_SCSI_SCAN_TMO        0x4000  /* scsi scan timer running */
 #define FC_ABORT_DISCOVERY      0x8000  /* we want to abort discovery */
 #define FC_NDISC_ACTIVE         0x10000         /* NPort discovery active */
index 1849e33e68f91ef5facd2bfa23bc6037d952450b..5df15c65b35bf19b212bd55e5e942282658920e0 100644 (file)
@@ -1929,7 +1929,7 @@ int lpfc_enable_npiv = 0;
 module_param(lpfc_enable_npiv, int, 0);
 MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
 lpfc_param_show(enable_npiv);
-lpfc_param_init(enable_npiv, 0, 0, 1);
+lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO,
                         lpfc_enable_npiv_show, NULL);
 
index 0a337dab211c3cc49c77c8abaabe2e48016f6d42..9508661fe82518993518621a9567978c7e1fbc11 100644 (file)
@@ -864,6 +864,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        }
        spin_lock_irq(shost->host_lock);
        vport->fc_flag &= ~FC_VPORT_CVL_RCVD;
+       vport->fc_flag &= ~FC_VPORT_LOGO_RCVD;
        spin_unlock_irq(shost->host_lock);
 
        /*
@@ -6053,7 +6054,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                        spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
                        spin_unlock_irq(shost->host_lock);
-                       if (vport->port_type == LPFC_PHYSICAL_PORT)
+                       if (vport->port_type == LPFC_PHYSICAL_PORT
+                               && !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
                                lpfc_initial_flogi(vport);
                        else
                                lpfc_initial_fdisc(vport);
@@ -6289,6 +6291,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        }
        spin_lock_irq(shost->host_lock);
        vport->fc_flag &= ~FC_VPORT_CVL_RCVD;
+       vport->fc_flag &= ~FC_VPORT_LOGO_RCVD;
        vport->fc_flag |= FC_FABRIC;
        if (vport->phba->fc_topology == TOPOLOGY_LOOP)
                vport->fc_flag |=  FC_PUBLIC_LOOP;
@@ -6318,6 +6321,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
                if (phba->sli_rev == LPFC_SLI_REV4)
                        vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+               else
+                       vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG;
                spin_unlock_irq(shost->host_lock);
        }
 
index 7c4f389a2f674ea0a1048b853c8b093f3e4f44d8..d2b55f05aa026165e95d4ad60e7fdb05d521b70d 100644 (file)
@@ -3016,7 +3016,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
-               lpfc_start_fdiscs(phba);
+               /* when physical port receive logo donot start
+                * vport discovery */
+               if (!(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
+                       lpfc_start_fdiscs(phba);
+               else
+                       vport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG ;
                lpfc_do_scr_ns_plogi(phba, vport);
        }
 
index e331204a4d56a38c62398d76ffc76dd6f32be16e..e1086da690616378ab6715ead6a6ca44034d8d88 100644 (file)
@@ -493,6 +493,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
              struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
 {
        struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_hba    *phba = vport->phba;
+       struct lpfc_vport **vports;
+       int i, active_vlink_present = 0 ;
 
        /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
        /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
@@ -505,15 +508,44 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
        else
                lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
-       if ((ndlp->nlp_DID == Fabric_DID) &&
-               vport->port_type == LPFC_NPIV_PORT) {
+       if (ndlp->nlp_DID == Fabric_DID) {
+               if (vport->port_state <= LPFC_FDISC)
+                       goto out;
                lpfc_linkdown_port(vport);
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
                spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
+               vport->fc_flag |= FC_VPORT_LOGO_RCVD;
                spin_unlock_irq(shost->host_lock);
+               vports = lpfc_create_vport_work_array(phba);
+               if (vports) {
+                       for (i = 0; i <= phba->max_vports && vports[i] != NULL;
+                                       i++) {
+                               if ((!(vports[i]->fc_flag &
+                                       FC_VPORT_LOGO_RCVD)) &&
+                                       (vports[i]->port_state > LPFC_FDISC)) {
+                                       active_vlink_present = 1;
+                                       break;
+                               }
+                       }
+                       lpfc_destroy_vport_work_array(phba, vports);
+               }
 
-               ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
+               if (active_vlink_present) {
+                       /*
+                        * If there are other active VLinks present,
+                        * re-instantiate the Vlink using FDISC.
+                        */
+                       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       spin_lock_irq(shost->host_lock);
+                       ndlp->nlp_flag |= NLP_DELAY_TMO;
+                       spin_unlock_irq(shost->host_lock);
+                       ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
+                       vport->port_state = LPFC_FDISC;
+               } else {
+                       spin_lock_irq(shost->host_lock);
+                       phba->pport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG;
+                       spin_unlock_irq(shost->host_lock);
+                       lpfc_retry_pport_discovery(phba);
+               }
        } else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
                ((ndlp->nlp_type & NLP_FCP_TARGET) ||
                !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
@@ -526,6 +558,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
                ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
        }
+out:
        ndlp->nlp_prev_state = ndlp->nlp_state;
        lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);