summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c458
1 files changed, 167 insertions, 291 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 8ba2f4eadcdd..0ebde2463005 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -374,13 +374,12 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
}
int
-lpfc_linkdown(struct lpfc_hba * phba)
+lpfc_linkdown(struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp, *next_ndlp;
- struct list_head *listp, *node_list[7];
- LPFC_MBOXQ_t *mb;
- int rc, i;
+ LPFC_MBOXQ_t *mb;
+ int rc;
psli = &phba->sli;
/* sysfs or selective reset may call this routine to clean up */
@@ -412,32 +411,18 @@ lpfc_linkdown(struct lpfc_hba * phba)
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_cmd(phba);
- /* Issue a LINK DOWN event to all nodes */
- node_list[0] = &phba->fc_npr_list; /* MUST do this list first */
- node_list[1] = &phba->fc_nlpmap_list;
- node_list[2] = &phba->fc_nlpunmap_list;
- node_list[3] = &phba->fc_prli_list;
- node_list[4] = &phba->fc_reglogin_list;
- node_list[5] = &phba->fc_adisc_list;
- node_list[6] = &phba->fc_plogi_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) {
-
+ /*
+ * Issue a LINK DOWN event to all nodes.
+ */
+ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+ /* free any ndlp's on unused list */
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+ lpfc_drop_node(phba, ndlp);
+ else /* otherwise, force node recovery. */
rc = lpfc_disc_state_machine(phba, ndlp, NULL,
- NLP_EVT_DEVICE_RECOVERY);
-
- }
+ NLP_EVT_DEVICE_RECOVERY);
}
- /* free any ndlp's on unused list */
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
- nlp_listp)
- lpfc_drop_node(phba, ndlp);
-
/* Setup myDID for link up if we are in pt2pt mode */
if (phba->fc_flag & FC_PT2PT) {
phba->fc_myDID = 0;
@@ -466,11 +451,9 @@ lpfc_linkdown(struct lpfc_hba * phba)
}
static int
-lpfc_linkup(struct lpfc_hba * phba)
+lpfc_linkup(struct lpfc_hba *phba)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
- struct list_head *listp, *node_list[7];
- int i;
fc_host_post_event(phba->host, fc_get_event_number(),
FCH_EVT_LINKUP, 0);
@@ -484,29 +467,20 @@ lpfc_linkup(struct lpfc_hba * phba)
spin_unlock_irq(phba->host->host_lock);
- node_list[0] = &phba->fc_plogi_list;
- 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 (phba->fc_flag & FC_LBIT) {
+ list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+ if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
if (ndlp->nlp_type & NLP_FABRIC) {
- /* On Linkup its safe to clean up the
+ /*
+ * On Linkup its safe to clean up the
* ndlp from Fabric connections.
*/
lpfc_nlp_set_state(phba, ndlp,
- NLP_STE_UNUSED_NODE);
+ NLP_STE_UNUSED_NODE);
} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
- /* Fail outstanding IO now since device
- * is marked for PLOGI.
+ /*
+ * Fail outstanding IO now since
+ * device is marked for PLOGI.
*/
lpfc_unreg_rpi(phba, ndlp);
}
@@ -515,9 +489,11 @@ lpfc_linkup(struct lpfc_hba * phba)
}
/* free any ndlp's on unused list */
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
- nlp_listp)
- lpfc_drop_node(phba, ndlp);
+ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+ nlp_listp) {
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+ lpfc_drop_node(phba, ndlp);
+ }
return 0;
}
@@ -1021,7 +997,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
*/
lpfc_issue_els_scr(phba, SCR_DID, 0);
- ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
+ ndlp = lpfc_findnode_did(phba, NameServer_DID);
if (!ndlp) {
/* Allocate a new node instance. If the pool is empty,
* start the discovery process and skip the Nameserver
@@ -1200,6 +1176,7 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
static void
lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
{
+ spin_lock_irq(phba->host->host_lock);
switch (state) {
case NLP_STE_UNUSED_NODE:
phba->fc_unused_cnt += count;
@@ -1226,107 +1203,7 @@ lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
phba->fc_npr_cnt += count;
break;
}
-}
-
-void
-lpfc_delink_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-{
- switch (ndlp->nlp_flag & NLP_LIST_MASK) {
- case NLP_UNUSED_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_PLOGI_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_ADISC_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_REGLOGIN_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_PRLI_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_UNMAPPED_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_MAPPED_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- case NLP_NPR_LIST:
- list_del_init(&ndlp->nlp_listp);
- break;
- }
-
- ndlp->nlp_flag &= ~NLP_LIST_MASK;
-}
-
-static int
-lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
-{
- struct lpfc_sli *psli;
-
- psli = &phba->sli;
- /* Sanity check to ensure we are not moving to / from the same list */
- if ((nlp->nlp_flag & NLP_LIST_MASK) == list)
- return 0;
-
- spin_lock_irq(phba->host->host_lock);
- lpfc_delink_node(phba, nlp);
-
- /* Add NPort <did> to <num> list */
- lpfc_printf_log(phba,
- KERN_INFO,
- LOG_NODE,
- "%d:0904 Add NPort x%x to %d list Data: x%x\n",
- phba->brd_no,
- nlp->nlp_DID, list, nlp->nlp_flag);
-
- switch (list) {
- case NLP_UNUSED_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the unused list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list);
- break;
- case NLP_PLOGI_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the plogi list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list);
- break;
- case NLP_ADISC_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the adisc list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list);
- break;
- case NLP_REGLOGIN_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the reglogin list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list);
- break;
- case NLP_PRLI_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the prli list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list);
- break;
- case NLP_UNMAPPED_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the unmap list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list);
- break;
- case NLP_MAPPED_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the map list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list);
- break;
- case NLP_NPR_LIST:
- nlp->nlp_flag |= list;
- /* Put it at the end of the npr list */
- list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
- break;
- }
-
spin_unlock_irq(phba->host->host_lock);
- return 0;
}
static void
@@ -1378,21 +1255,39 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
}
}
+static char *
+lpfc_nlp_state_name(char *buffer, size_t size, int state)
+{
+ static char *states[] = {
+ [NLP_STE_UNUSED_NODE] = "UNUSED",
+ [NLP_STE_PLOGI_ISSUE] = "PLOGI",
+ [NLP_STE_ADISC_ISSUE] = "ADISC",
+ [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN",
+ [NLP_STE_PRLI_ISSUE] = "PRLI",
+ [NLP_STE_UNMAPPED_NODE] = "UNMAPPED",
+ [NLP_STE_MAPPED_NODE] = "MAPPED",
+ [NLP_STE_NPR_NODE] = "NPR",
+ };
+
+ if (state < ARRAY_SIZE(states) && states[state])
+ strlcpy(buffer, states[state], size);
+ else
+ snprintf(buffer, size, "unknown (%d)", state);
+ return buffer;
+}
+
void
lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
{
int old_state = ndlp->nlp_state;
- static int list_id[] = {
- [NLP_STE_UNUSED_NODE] = NLP_UNUSED_LIST,
- [NLP_STE_PLOGI_ISSUE] = NLP_PLOGI_LIST,
- [NLP_STE_ADISC_ISSUE] = NLP_ADISC_LIST,
- [NLP_STE_REG_LOGIN_ISSUE] = NLP_REGLOGIN_LIST,
- [NLP_STE_PRLI_ISSUE] = NLP_PRLI_LIST,
- [NLP_STE_UNMAPPED_NODE] = NLP_UNMAPPED_LIST,
- [NLP_STE_MAPPED_NODE] = NLP_MAPPED_LIST,
- [NLP_STE_NPR_NODE] = NLP_NPR_LIST,
- };
+ char name1[16], name2[16];
+ lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+ "%d:0904 NPort state transition x%06x, %s -> %s\n",
+ phba->brd_no,
+ ndlp->nlp_DID,
+ lpfc_nlp_state_name(name1, sizeof(name1), old_state),
+ lpfc_nlp_state_name(name2, sizeof(name2), state));
if (old_state == NLP_STE_NPR_NODE &&
(ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
state != NLP_STE_NPR_NODE)
@@ -1402,13 +1297,15 @@ lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
ndlp->nlp_type &= ~NLP_FC_NODE;
}
- if (old_state && !list_empty(&ndlp->nlp_listp))
+ if (list_empty(&ndlp->nlp_listp)) {
+ spin_lock_irq(phba->host->host_lock);
+ list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
+ spin_unlock_irq(phba->host->host_lock);
+ } else if (old_state)
lpfc_nlp_counters(phba, old_state, -1);
ndlp->nlp_state = state;
- lpfc_nlp_list(phba, ndlp, list_id[state]);
lpfc_nlp_counters(phba, state, 1);
-
lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
}
@@ -1417,10 +1314,10 @@ lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
- spin_lock_irq(phba->host->host_lock);
if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
- lpfc_delink_node(phba, ndlp);
+ spin_lock_irq(phba->host->host_lock);
+ list_del_init(&ndlp->nlp_listp);
spin_unlock_irq(phba->host->host_lock);
lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
}
@@ -1430,10 +1327,10 @@ lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
- spin_lock_irq(phba->host->host_lock);
if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
- lpfc_delink_node(phba, ndlp);
+ spin_lock_irq(phba->host->host_lock);
+ list_del_init(&ndlp->nlp_listp);
spin_unlock_irq(phba->host->host_lock);
lpfc_nlp_put(ndlp);
}
@@ -1638,7 +1535,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* so it can be freed.
*/
static int
-lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
{
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
@@ -1708,7 +1605,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
}
- lpfc_freenode(phba, ndlp);
+ lpfc_cleanup_node(phba, ndlp);
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
put_device(&ndlp->rport->dev);
@@ -1719,7 +1616,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
static int
-lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
+lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
{
D_ID mydid;
D_ID ndlpdid;
@@ -1768,57 +1665,36 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
return 0;
}
-/* Search for a nodelist entry on a specific list */
+/* Search for a nodelist entry */
struct lpfc_nodelist *
-lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
+lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
{
struct lpfc_nodelist *ndlp;
- struct list_head *lists[]={&phba->fc_nlpunmap_list,
- &phba->fc_nlpmap_list,
- &phba->fc_plogi_list,
- &phba->fc_adisc_list,
- &phba->fc_reglogin_list,
- &phba->fc_prli_list,
- &phba->fc_npr_list,
- &phba->fc_unused_list};
- uint32_t search[]={NLP_SEARCH_UNMAPPED,
- NLP_SEARCH_MAPPED,
- NLP_SEARCH_PLOGI,
- NLP_SEARCH_ADISC,
- NLP_SEARCH_REGLOGIN,
- NLP_SEARCH_PRLI,
- NLP_SEARCH_NPR,
- NLP_SEARCH_UNUSED};
- int i;
uint32_t data1;
spin_lock_irq(phba->host->host_lock);
- for (i = 0; i < ARRAY_SIZE(lists); i++ ) {
- if (!(order & search[i]))
- continue;
- list_for_each_entry(ndlp, lists[i], nlp_listp) {
- if (lpfc_matchdid(phba, ndlp, did)) {
- data1 = (((uint32_t) ndlp->nlp_state << 24) |
- ((uint32_t) ndlp->nlp_xri << 16) |
- ((uint32_t) ndlp->nlp_type << 8) |
- ((uint32_t) ndlp->nlp_rpi & 0xff));
- lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
- "%d:0929 FIND node DID "
- " Data: x%p x%x x%x x%x\n",
- phba->brd_no,
- ndlp, ndlp->nlp_DID,
- ndlp->nlp_flag, data1);
- spin_unlock_irq(phba->host->host_lock);
- return ndlp;
- }
+ list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+ if (lpfc_matchdid(phba, ndlp, did)) {
+ data1 = (((uint32_t) ndlp->nlp_state << 24) |
+ ((uint32_t) ndlp->nlp_xri << 16) |
+ ((uint32_t) ndlp->nlp_type << 8) |
+ ((uint32_t) ndlp->nlp_rpi & 0xff));
+ lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+ "%d:0929 FIND node DID "
+ " Data: x%p x%x x%x x%x\n",
+ phba->brd_no,
+ ndlp, ndlp->nlp_DID,
+ ndlp->nlp_flag, data1);
+ spin_unlock_irq(phba->host->host_lock);
+ return ndlp;
}
}
spin_unlock_irq(phba->host->host_lock);
/* FIND node did <did> NOT FOUND */
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
- "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n",
- phba->brd_no, did, order);
+ "%d:0932 FIND node did x%x NOT FOUND.\n",
+ phba->brd_no, did);
return NULL;
}
@@ -1826,9 +1702,8 @@ struct lpfc_nodelist *
lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
{
struct lpfc_nodelist *ndlp;
- uint32_t flg;
- ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
+ ndlp = lpfc_findnode_did(phba, did);
if (!ndlp) {
if ((phba->fc_flag & FC_RSCN_MODE) &&
((lpfc_rscn_payload_check(phba, did) == 0)))
@@ -1854,8 +1729,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
} else
ndlp = NULL;
} else {
- flg = ndlp->nlp_flag & NLP_LIST_MASK;
- if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
+ if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
+ ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
return NULL;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -1915,8 +1790,9 @@ lpfc_disc_start(struct lpfc_hba * phba)
struct lpfc_sli *psli;
LPFC_MBOXQ_t *mbox;
struct lpfc_nodelist *ndlp, *next_ndlp;
- uint32_t did_changed, num_sent;
+ uint32_t num_sent;
uint32_t clear_la_pending;
+ int did_changed;
int rc;
psli = &phba->sli;
@@ -1950,14 +1826,13 @@ lpfc_disc_start(struct lpfc_hba * phba)
phba->fc_plogi_cnt, phba->fc_adisc_cnt);
/* If our did changed, we MUST do PLOGI */
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
- nlp_listp) {
- if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
- if (did_changed) {
- spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_ADISC;
- spin_unlock_irq(phba->host->host_lock);
- }
+ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+ if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+ (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+ did_changed) {
+ spin_lock_irq(phba->host->host_lock);
+ ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+ spin_unlock_irq(phba->host->host_lock);
}
}
@@ -2077,21 +1952,16 @@ lpfc_disc_flush_list(struct lpfc_hba * phba)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
- if (phba->fc_plogi_cnt) {
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
- nlp_listp) {
- lpfc_free_tx(phba, ndlp);
- lpfc_nlp_put(ndlp);
- }
- }
- if (phba->fc_adisc_cnt) {
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
- nlp_listp) {
- lpfc_free_tx(phba, ndlp);
- lpfc_nlp_put(ndlp);
+ if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
+ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+ nlp_listp) {
+ if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
+ ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
+ lpfc_free_tx(phba, ndlp);
+ lpfc_nlp_put(ndlp);
+ }
}
}
- return;
}
/*****************************************************************************/
@@ -2160,8 +2030,10 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
phba->brd_no);
/* Start discovery by sending FLOGI, clean up old rpis */
- list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
- nlp_listp) {
+ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+ nlp_listp) {
+ if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+ continue;
if (ndlp->nlp_type & NLP_FABRIC) {
/* Clean up the ndlp on Fabric connections */
lpfc_drop_node(phba, ndlp);
@@ -2205,7 +2077,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"login\n", phba->brd_no);
/* Next look for NameServer ndlp */
- ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
+ ndlp = lpfc_findnode_did(phba, NameServer_DID);
if (ndlp)
lpfc_nlp_put(ndlp);
/* Start discovery */
@@ -2220,9 +2092,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
phba->brd_no,
phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
- ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED,
- NameServer_DID);
- if (ndlp) {
+ ndlp = lpfc_findnode_did(phba, NameServer_DID);
+ if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
/* Try it one more time */
rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
@@ -2394,31 +2265,63 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
+static int
+lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param)
+{
+ uint16_t *rpi = param;
+
+ return ndlp->nlp_rpi == *rpi;
+}
+
+static int
+lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param)
+{
+ return memcmp(&ndlp->nlp_portname, param,
+ sizeof(ndlp->nlp_portname)) == 0;
+}
+
/*
- * This routine looks up the ndlp lists
- * for the given RPI. If rpi found
- * it return the node list pointer
- * else return NULL.
+ * Search node lists for a remote port matching filter criteria
+ * Caller needs to hold host_lock before calling this routine.
*/
struct lpfc_nodelist *
-__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
+__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
{
struct lpfc_nodelist *ndlp;
- struct list_head * lists[]={&phba->fc_nlpunmap_list,
- &phba->fc_nlpmap_list,
- &phba->fc_plogi_list,
- &phba->fc_adisc_list,
- &phba->fc_reglogin_list};
- int i;
- for (i = 0; i < ARRAY_SIZE(lists); i++ )
- list_for_each_entry(ndlp, lists[i], nlp_listp)
- if (ndlp->nlp_rpi == rpi) {
- return ndlp;
- }
+ list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+ if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
+ filter(ndlp, param))
+ return ndlp;
+ }
return NULL;
}
+/*
+ * Search node lists for a remote port matching filter criteria
+ * This routine is used when the caller does NOT have host_lock.
+ */
+struct lpfc_nodelist *
+lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+{
+ struct lpfc_nodelist *ndlp;
+
+ spin_lock_irq(phba->host->host_lock);
+ ndlp = __lpfc_find_node(phba, filter, param);
+ spin_unlock_irq(phba->host->host_lock);
+ return ndlp;
+}
+
+/*
+ * This routine looks up the ndlp lists for the given RPI. If rpi found it
+ * returns the node list pointer else return NULL.
+ */
+struct lpfc_nodelist *
+__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
+{
+ return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
+}
+
struct lpfc_nodelist *
lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
{
@@ -2431,44 +2334,16 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
}
/*
- * This routine looks up the ndlp lists
- * for the given WWPN. If WWPN found
- * it return the node list pointer
- * else return NULL.
+ * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
+ * returns the node list pointer else return NULL.
*/
struct lpfc_nodelist *
-lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order,
- struct lpfc_name * wwpn)
+lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
{
struct lpfc_nodelist *ndlp;
- struct list_head * lists[]={&phba->fc_nlpunmap_list,
- &phba->fc_nlpmap_list,
- &phba->fc_npr_list,
- &phba->fc_plogi_list,
- &phba->fc_adisc_list,
- &phba->fc_reglogin_list,
- &phba->fc_prli_list};
- uint32_t search[]={NLP_SEARCH_UNMAPPED,
- NLP_SEARCH_MAPPED,
- NLP_SEARCH_NPR,
- NLP_SEARCH_PLOGI,
- NLP_SEARCH_ADISC,
- NLP_SEARCH_REGLOGIN,
- NLP_SEARCH_PRLI};
- int i;
spin_lock_irq(phba->host->host_lock);
- for (i = 0; i < ARRAY_SIZE(lists); i++ ) {
- if (!(order & search[i]))
- continue;
- list_for_each_entry(ndlp, lists[i], nlp_listp) {
- if (memcmp(&ndlp->nlp_portname, wwpn,
- sizeof(struct lpfc_name)) == 0) {
- spin_unlock_irq(phba->host->host_lock);
- return ndlp;
- }
- }
- }
+ ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
spin_unlock_irq(phba->host->host_lock);
return NULL;
}
@@ -2484,6 +2359,7 @@ lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
ndlp->nlp_DID = did;
ndlp->nlp_phba = phba;
ndlp->nlp_sid = NLP_NO_SID;
+ INIT_LIST_HEAD(&ndlp->nlp_listp);
kref_init(&ndlp->kref);
return;
}