Commit c9f8735b authored by Jamie Wellnitz's avatar Jamie Wellnitz Committed by James Bottomley

[SCSI] lpfc 8.1.2: Misc FC Discovery changes :

Misc FC Discovery changes :
   - Added FC_BYPASSED_MODE statistic
   - Corrected some log message data
   - Fix up Discovery infrastructure to support FAN:
       Allow Fabric entities to flow thru DSM
       Fix up linkup/linkdown unregister login processing for Fabric entities
       Clean up Discovery code
       Utilize nodev_tmo for Fabric entities
   - Use of 3 * ratov for CT handling timeouts
   - Fix up DSM to make more appropriate decisions and clean up code.
Signed-off-by: default avatarJamie Wellnitz <Jamie.Wellnitz@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent b28485ac
...@@ -247,6 +247,7 @@ struct lpfc_hba { ...@@ -247,6 +247,7 @@ struct lpfc_hba {
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
uint32_t fc_topology; /* link topology, from LINK INIT */ uint32_t fc_topology; /* link topology, from LINK INIT */
......
...@@ -260,8 +260,10 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp, ...@@ -260,8 +260,10 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL; icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL;
icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP; icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP;
if (!tmo) if (!tmo) {
tmo = (2 * phba->fc_ratov) + 1; /* FC spec states we need 3 * ratov for CT requests */
tmo = (3 * phba->fc_ratov);
}
icmd->ulpTimeout = tmo; icmd->ulpTimeout = tmo;
icmd->ulpBdeCount = 1; icmd->ulpBdeCount = 1;
icmd->ulpLe = 1; icmd->ulpLe = 1;
...@@ -449,6 +451,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, ...@@ -449,6 +451,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
CTrsp = (struct lpfc_sli_ct_request *) outp->virt; CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
if (CTrsp->CommandResponse.bits.CmdRsp == if (CTrsp->CommandResponse.bits.CmdRsp ==
be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0239 NameServer Rsp "
"Data: x%x\n",
phba->brd_no,
phba->fc_flag);
lpfc_ns_rsp(phba, outp, lpfc_ns_rsp(phba, outp,
(uint32_t) (irsp->un.genreq64.bdl.bdeSize)); (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
} else if (CTrsp->CommandResponse.bits.CmdRsp == } else if (CTrsp->CommandResponse.bits.CmdRsp ==
......
This diff is collapsed.
...@@ -283,16 +283,18 @@ lpfc_linkdown(struct lpfc_hba * phba) ...@@ -283,16 +283,18 @@ lpfc_linkdown(struct lpfc_hba * phba)
{ {
struct lpfc_sli *psli; struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp, *next_ndlp; struct lpfc_nodelist *ndlp, *next_ndlp;
struct list_head *listp; struct list_head *listp, *node_list[7];
struct list_head *node_list[7];
LPFC_MBOXQ_t *mb; LPFC_MBOXQ_t *mb;
int rc, i; int rc, i;
psli = &phba->sli; psli = &phba->sli;
/* sysfs or selective reset may call this routine to clean up */
if (phba->hba_state > LPFC_LINK_DOWN) {
spin_lock_irq(phba->host->host_lock); spin_lock_irq(phba->host->host_lock);
phba->hba_state = LPFC_LINK_DOWN; phba->hba_state = LPFC_LINK_DOWN;
spin_unlock_irq(phba->host->host_lock); spin_unlock_irq(phba->host->host_lock);
}
/* Clean up any firmware default rpi's */ /* Clean up any firmware default rpi's */
if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
...@@ -324,17 +326,6 @@ lpfc_linkdown(struct lpfc_hba * phba) ...@@ -324,17 +326,6 @@ lpfc_linkdown(struct lpfc_hba * phba)
continue; continue;
list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
/* Fabric nodes are not handled thru state machine for
link down */
if (ndlp->nlp_type & NLP_FABRIC) {
/* Remove ALL Fabric nodes except Fabric_DID */
if (ndlp->nlp_DID != Fabric_DID) {
/* Take it off current list and free */
lpfc_nlp_list(phba, ndlp,
NLP_NO_LIST);
}
}
else {
rc = lpfc_disc_state_machine(phba, ndlp, NULL, rc = lpfc_disc_state_machine(phba, ndlp, NULL,
NLP_EVT_DEVICE_RECOVERY); NLP_EVT_DEVICE_RECOVERY);
...@@ -352,7 +343,6 @@ lpfc_linkdown(struct lpfc_hba * phba) ...@@ -352,7 +343,6 @@ lpfc_linkdown(struct lpfc_hba * phba)
} }
} }
} }
}
/* free any ndlp's on unused list */ /* free any ndlp's on unused list */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
...@@ -391,6 +381,8 @@ static int ...@@ -391,6 +381,8 @@ static int
lpfc_linkup(struct lpfc_hba * phba) lpfc_linkup(struct lpfc_hba * phba)
{ {
struct lpfc_nodelist *ndlp, *next_ndlp; struct lpfc_nodelist *ndlp, *next_ndlp;
struct list_head *listp, *node_list[7];
int i;
spin_lock_irq(phba->host->host_lock); spin_lock_irq(phba->host->host_lock);
phba->hba_state = LPFC_LINK_UP; phba->hba_state = LPFC_LINK_UP;
...@@ -401,14 +393,33 @@ lpfc_linkup(struct lpfc_hba * phba) ...@@ -401,14 +393,33 @@ lpfc_linkup(struct lpfc_hba * phba)
spin_unlock_irq(phba->host->host_lock); spin_unlock_irq(phba->host->host_lock);
/* node_list[0] = &phba->fc_plogi_list;
* Clean up old Fabric NLP_FABRIC logins. node_list[1] = &phba->fc_adisc_list;
node_list[2] = &phba->fc_reglogin_list;
node_list[3] = &phba->fc_prli_list;
node_list[4] = &phba->fc_nlpunmap_list;
node_list[5] = &phba->fc_nlpmap_list;
node_list[6] = &phba->fc_npr_list;
for (i = 0; i < 7; i++) {
listp = node_list[i];
if (list_empty(listp))
continue;
list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
if (phba->fc_flag & FC_LBIT) {
if (ndlp->nlp_type & NLP_FABRIC) {
/* On Linkup its safe to clean up the
* ndlp from Fabric connections.
*/ */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, lpfc_nlp_list(phba, ndlp,
nlp_listp) { NLP_UNUSED_LIST);
if (ndlp->nlp_DID == Fabric_DID) { } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
/* Take it off current list and free */ /* Fail outstanding IO now since device
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); * is marked for PLOGI.
*/
lpfc_unreg_rpi(phba, ndlp);
}
}
} }
} }
...@@ -784,6 +795,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -784,6 +795,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
memcpy(&phba->alpa_map[0], mp->virt, 128); memcpy(&phba->alpa_map[0], mp->virt, 128);
spin_lock_irq(phba->host->host_lock);
if (la->pb)
phba->fc_flag |= FC_BYPASSED_MODE;
else
phba->fc_flag &= ~FC_BYPASSED_MODE;
spin_unlock_irq(phba->host->host_lock);
if (((phba->fc_eventTag + 1) < la->eventTag) || if (((phba->fc_eventTag + 1) < la->eventTag) ||
(phba->fc_eventTag == la->eventTag)) { (phba->fc_eventTag == la->eventTag)) {
phba->fc_stat.LinkMultiEvent++; phba->fc_stat.LinkMultiEvent++;
...@@ -904,32 +922,36 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -904,32 +922,36 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
*/ */
lpfc_issue_els_scr(phba, SCR_DID, 0); lpfc_issue_els_scr(phba, SCR_DID, 0);
/* Allocate a new node instance. If the pool is empty, just ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
* start the discovery process and skip the Nameserver login if (!ndlp) {
* process. This is attempted again later on. Otherwise, issue /* Allocate a new node instance. If the pool is empty,
* a Port Login (PLOGI) to the NameServer * start the discovery process and skip the Nameserver
* login process. This is attempted again later on.
* Otherwise, issue a Port Login (PLOGI) to NameServer.
*/ */
if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
== 0) { if (!ndlp) {
lpfc_disc_start(phba); lpfc_disc_start(phba);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free( pmb, phba->mbox_mem_pool);
return;
} else { } else {
lpfc_nlp_init(phba, ndlp, NameServer_DID); lpfc_nlp_init(phba, ndlp, NameServer_DID);
ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_type |= NLP_FABRIC;
}
}
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
lpfc_issue_els_plogi(phba, ndlp, 0); lpfc_issue_els_plogi(phba, ndlp, 0);
if (phba->cfg_fdmi_on) { if (phba->cfg_fdmi_on) {
if ((ndlp_fdmi = mempool_alloc( ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
phba->nlp_mem_pool, GFP_KERNEL);
GFP_KERNEL))) { if (ndlp_fdmi) {
lpfc_nlp_init(phba, ndlp_fdmi, lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID);
FDMI_DID);
ndlp_fdmi->nlp_type |= NLP_FABRIC; ndlp_fdmi->nlp_type |= NLP_FABRIC;
ndlp_fdmi->nlp_state = ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE;
NLP_STE_PLOGI_ISSUE; lpfc_issue_els_plogi(phba, ndlp_fdmi, 0);
lpfc_issue_els_plogi(phba, ndlp_fdmi,
0);
}
} }
} }
} }
...@@ -937,7 +959,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -937,7 +959,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbuf_free(phba, mp->virt, mp->phys); lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp); kfree(mp);
mempool_free( pmb, phba->mbox_mem_pool); mempool_free( pmb, phba->mbox_mem_pool);
return; return;
} }
...@@ -1241,14 +1262,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) ...@@ -1241,14 +1262,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
phba->fc_npr_cnt++; phba->fc_npr_cnt++;
/* if (!(nlp->nlp_flag & NLP_NODEV_TMO)) {
* Sanity check for Fabric entity.
* Set nodev_tmo for NPR state, for Fabric use 1 sec.
*/
if (nlp->nlp_type & NLP_FABRIC) {
mod_timer(&nlp->nlp_tmofunc, jiffies + HZ);
}
else {
mod_timer(&nlp->nlp_tmofunc, mod_timer(&nlp->nlp_tmofunc,
jiffies + HZ * phba->cfg_nodev_tmo); jiffies + HZ * phba->cfg_nodev_tmo);
} }
...@@ -1314,7 +1328,15 @@ lpfc_set_disctmo(struct lpfc_hba * phba) ...@@ -1314,7 +1328,15 @@ lpfc_set_disctmo(struct lpfc_hba * phba)
{ {
uint32_t tmo; uint32_t tmo;
tmo = ((phba->fc_ratov * 2) + 1); if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
/* For FAN, timeout should be greater then edtov */
tmo = (((phba->fc_edtov + 999) / 1000) + 1);
} else {
/* Normal discovery timeout should be > then ELS/CT timeout
* FC spec states we need 3 * ratov for CT requests
*/
tmo = ((phba->fc_ratov * 3) + 3);
}
mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo); mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo);
spin_lock_irq(phba->host->host_lock); spin_lock_irq(phba->host->host_lock);
...@@ -1846,8 +1868,9 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) ...@@ -1846,8 +1868,9 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
uint32_t flg; uint32_t flg;
if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) { ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
if ((phba->hba_state == LPFC_HBA_READY) && if (!ndlp) {
if ((phba->fc_flag & FC_RSCN_MODE) &&
((lpfc_rscn_payload_check(phba, did) == 0))) ((lpfc_rscn_payload_check(phba, did) == 0)))
return NULL; return NULL;
ndlp = (struct lpfc_nodelist *) ndlp = (struct lpfc_nodelist *)
...@@ -1860,10 +1883,23 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) ...@@ -1860,10 +1883,23 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
ndlp->nlp_flag |= NLP_NPR_2B_DISC; ndlp->nlp_flag |= NLP_NPR_2B_DISC;
return ndlp; return ndlp;
} }
if ((phba->hba_state == LPFC_HBA_READY) && if (phba->fc_flag & FC_RSCN_MODE) {
(phba->fc_flag & FC_RSCN_MODE)) {
if (lpfc_rscn_payload_check(phba, did)) { if (lpfc_rscn_payload_check(phba, did)) {
ndlp->nlp_flag |= NLP_NPR_2B_DISC; ndlp->nlp_flag |= NLP_NPR_2B_DISC;
/* Since this node is marked for discovery,
* delay timeout is not needed.
*/
if (ndlp->nlp_flag & NLP_DELAY_TMO) {
ndlp->nlp_flag &= ~NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
del_timer_sync(&ndlp->nlp_delayfunc);
spin_lock_irq(phba->host->host_lock);
if (!list_empty(&ndlp->els_retry_evt.
evt_listp))
list_del_init(&ndlp->els_retry_evt.
evt_listp);
}
} }
else { else {
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
...@@ -1872,10 +1908,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) ...@@ -1872,10 +1908,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
} }
else { else {
flg = ndlp->nlp_flag & NLP_LIST_MASK; flg = ndlp->nlp_flag & NLP_LIST_MASK;
if ((flg == NLP_ADISC_LIST) || if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
(flg == NLP_PLOGI_LIST)) {
return NULL; return NULL;
}
ndlp->nlp_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
ndlp->nlp_flag |= NLP_NPR_2B_DISC; ndlp->nlp_flag |= NLP_NPR_2B_DISC;
...@@ -2174,7 +2208,7 @@ static void ...@@ -2174,7 +2208,7 @@ static void
lpfc_disc_timeout_handler(struct lpfc_hba *phba) lpfc_disc_timeout_handler(struct lpfc_hba *phba)
{ {
struct lpfc_sli *psli; struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp, *next_ndlp;
LPFC_MBOXQ_t *clearlambox, *initlinkmbox; LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
int rc, clrlaerr = 0; int rc, clrlaerr = 0;
...@@ -2201,10 +2235,20 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) ...@@ -2201,10 +2235,20 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"%d:0221 FAN timeout\n", "%d:0221 FAN timeout\n",
phba->brd_no); phba->brd_no);
/* Forget about FAN, Start discovery by sending a FLOGI /* Start discovery by sending FLOGI, clean up old rpis */
* hba_state is identically LPFC_FLOGI while waiting for FLOGI list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
* cmpl nlp_listp) {
if (ndlp->nlp_type & NLP_FABRIC) {
/* Clean up the ndlp on Fabric connections */
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
/* Fail outstanding IO now since device
* is marked for PLOGI.
*/ */
lpfc_unreg_rpi(phba, ndlp);
}
}
phba->hba_state = LPFC_FLOGI; phba->hba_state = LPFC_FLOGI;
lpfc_set_disctmo(phba); lpfc_set_disctmo(phba);
lpfc_initial_flogi(phba); lpfc_initial_flogi(phba);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment