aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:53:08 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:15 -0400
commit685f0bf7afe087940d34f98ac0fd1df84091d360 (patch)
tree7e7fbfc856f13a3c4c64e14784b7050812753521 /drivers/scsi/lpfc/lpfc_hbadisc.c
parent329f9bc735b4665d42267259b1612191f72c4d42 (diff)
[SCSI] lpfc 8.1.12 : Collapse discovery lists to a single node list
Collapse discovery lists to a single node list. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
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,
374} 374}
375 375
376int 376int
377lpfc_linkdown(struct lpfc_hba * phba) 377lpfc_linkdown(struct lpfc_hba *phba)
378{ 378{
379 struct lpfc_sli *psli; 379 struct lpfc_sli *psli;
380 struct lpfc_nodelist *ndlp, *next_ndlp; 380 struct lpfc_nodelist *ndlp, *next_ndlp;
381 struct list_head *listp, *node_list[7]; 381 LPFC_MBOXQ_t *mb;
382 LPFC_MBOXQ_t *mb; 382 int rc;
383 int rc, i;
384 383
385 psli = &phba->sli; 384 psli = &phba->sli;
386 /* sysfs or selective reset may call this routine to clean up */ 385 /* sysfs or selective reset may call this routine to clean up */
@@ -412,32 +411,18 @@ lpfc_linkdown(struct lpfc_hba * phba)
412 /* Cleanup any outstanding ELS commands */ 411 /* Cleanup any outstanding ELS commands */
413 lpfc_els_flush_cmd(phba); 412 lpfc_els_flush_cmd(phba);
414 413
415 /* Issue a LINK DOWN event to all nodes */ 414 /*
416 node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ 415 * Issue a LINK DOWN event to all nodes.
417 node_list[1] = &phba->fc_nlpmap_list; 416 */
418 node_list[2] = &phba->fc_nlpunmap_list; 417 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
419 node_list[3] = &phba->fc_prli_list; 418 /* free any ndlp's on unused list */
420 node_list[4] = &phba->fc_reglogin_list; 419 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
421 node_list[5] = &phba->fc_adisc_list; 420 lpfc_drop_node(phba, ndlp);
422 node_list[6] = &phba->fc_plogi_list; 421 else /* otherwise, force node recovery. */
423 for (i = 0; i < 7; i++) {
424 listp = node_list[i];
425 if (list_empty(listp))
426 continue;
427
428 list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
429
430 rc = lpfc_disc_state_machine(phba, ndlp, NULL, 422 rc = lpfc_disc_state_machine(phba, ndlp, NULL,
431 NLP_EVT_DEVICE_RECOVERY); 423 NLP_EVT_DEVICE_RECOVERY);
432
433 }
434 } 424 }
435 425
436 /* free any ndlp's on unused list */
437 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
438 nlp_listp)
439 lpfc_drop_node(phba, ndlp);
440
441 /* Setup myDID for link up if we are in pt2pt mode */ 426 /* Setup myDID for link up if we are in pt2pt mode */
442 if (phba->fc_flag & FC_PT2PT) { 427 if (phba->fc_flag & FC_PT2PT) {
443 phba->fc_myDID = 0; 428 phba->fc_myDID = 0;
@@ -466,11 +451,9 @@ lpfc_linkdown(struct lpfc_hba * phba)
466} 451}
467 452
468static int 453static int
469lpfc_linkup(struct lpfc_hba * phba) 454lpfc_linkup(struct lpfc_hba *phba)
470{ 455{
471 struct lpfc_nodelist *ndlp, *next_ndlp; 456 struct lpfc_nodelist *ndlp, *next_ndlp;
472 struct list_head *listp, *node_list[7];
473 int i;
474 457
475 fc_host_post_event(phba->host, fc_get_event_number(), 458 fc_host_post_event(phba->host, fc_get_event_number(),
476 FCH_EVT_LINKUP, 0); 459 FCH_EVT_LINKUP, 0);
@@ -484,29 +467,20 @@ lpfc_linkup(struct lpfc_hba * phba)
484 spin_unlock_irq(phba->host->host_lock); 467 spin_unlock_irq(phba->host->host_lock);
485 468
486 469
487 node_list[0] = &phba->fc_plogi_list; 470 if (phba->fc_flag & FC_LBIT) {
488 node_list[1] = &phba->fc_adisc_list; 471 list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
489 node_list[2] = &phba->fc_reglogin_list; 472 if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
490 node_list[3] = &phba->fc_prli_list;
491 node_list[4] = &phba->fc_nlpunmap_list;
492 node_list[5] = &phba->fc_nlpmap_list;
493 node_list[6] = &phba->fc_npr_list;
494 for (i = 0; i < 7; i++) {
495 listp = node_list[i];
496 if (list_empty(listp))
497 continue;
498
499 list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
500 if (phba->fc_flag & FC_LBIT) {
501 if (ndlp->nlp_type & NLP_FABRIC) { 473 if (ndlp->nlp_type & NLP_FABRIC) {
502 /* On Linkup its safe to clean up the 474 /*
475 * On Linkup its safe to clean up the
503 * ndlp from Fabric connections. 476 * ndlp from Fabric connections.
504 */ 477 */
505 lpfc_nlp_set_state(phba, ndlp, 478 lpfc_nlp_set_state(phba, ndlp,
506 NLP_STE_UNUSED_NODE); 479 NLP_STE_UNUSED_NODE);
507 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { 480 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
508 /* Fail outstanding IO now since device 481 /*
509 * is marked for PLOGI. 482 * Fail outstanding IO now since
483 * device is marked for PLOGI.
510 */ 484 */
511 lpfc_unreg_rpi(phba, ndlp); 485 lpfc_unreg_rpi(phba, ndlp);
512 } 486 }
@@ -515,9 +489,11 @@ lpfc_linkup(struct lpfc_hba * phba)
515 } 489 }
516 490
517 /* free any ndlp's on unused list */ 491 /* free any ndlp's on unused list */
518 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, 492 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
519 nlp_listp) 493 nlp_listp) {
520 lpfc_drop_node(phba, ndlp); 494 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
495 lpfc_drop_node(phba, ndlp);
496 }
521 497
522 return 0; 498 return 0;
523} 499}
@@ -1021,7 +997,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1021 */ 997 */
1022 lpfc_issue_els_scr(phba, SCR_DID, 0); 998 lpfc_issue_els_scr(phba, SCR_DID, 0);
1023 999
1024 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); 1000 ndlp = lpfc_findnode_did(phba, NameServer_DID);
1025 if (!ndlp) { 1001 if (!ndlp) {
1026 /* Allocate a new node instance. If the pool is empty, 1002 /* Allocate a new node instance. If the pool is empty,
1027 * start the discovery process and skip the Nameserver 1003 * start the discovery process and skip the Nameserver
@@ -1200,6 +1176,7 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1200static void 1176static void
1201lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) 1177lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
1202{ 1178{
1179 spin_lock_irq(phba->host->host_lock);
1203 switch (state) { 1180 switch (state) {
1204 case NLP_STE_UNUSED_NODE: 1181 case NLP_STE_UNUSED_NODE:
1205 phba->fc_unused_cnt += count; 1182 phba->fc_unused_cnt += count;
@@ -1226,107 +1203,7 @@ lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
1226 phba->fc_npr_cnt += count; 1203 phba->fc_npr_cnt += count;
1227 break; 1204 break;
1228 } 1205 }
1229}
1230
1231void
1232lpfc_delink_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1233{
1234 switch (ndlp->nlp_flag & NLP_LIST_MASK) {
1235 case NLP_UNUSED_LIST:
1236 list_del_init(&ndlp->nlp_listp);
1237 break;
1238 case NLP_PLOGI_LIST:
1239 list_del_init(&ndlp->nlp_listp);
1240 break;
1241 case NLP_ADISC_LIST:
1242 list_del_init(&ndlp->nlp_listp);
1243 break;
1244 case NLP_REGLOGIN_LIST:
1245 list_del_init(&ndlp->nlp_listp);
1246 break;
1247 case NLP_PRLI_LIST:
1248 list_del_init(&ndlp->nlp_listp);
1249 break;
1250 case NLP_UNMAPPED_LIST:
1251 list_del_init(&ndlp->nlp_listp);
1252 break;
1253 case NLP_MAPPED_LIST:
1254 list_del_init(&ndlp->nlp_listp);
1255 break;
1256 case NLP_NPR_LIST:
1257 list_del_init(&ndlp->nlp_listp);
1258 break;
1259 }
1260
1261 ndlp->nlp_flag &= ~NLP_LIST_MASK;
1262}
1263
1264static int
1265lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1266{
1267 struct lpfc_sli *psli;
1268
1269 psli = &phba->sli;
1270 /* Sanity check to ensure we are not moving to / from the same list */
1271 if ((nlp->nlp_flag & NLP_LIST_MASK) == list)
1272 return 0;
1273
1274 spin_lock_irq(phba->host->host_lock);
1275 lpfc_delink_node(phba, nlp);
1276
1277 /* Add NPort <did> to <num> list */
1278 lpfc_printf_log(phba,
1279 KERN_INFO,
1280 LOG_NODE,
1281 "%d:0904 Add NPort x%x to %d list Data: x%x\n",
1282 phba->brd_no,
1283 nlp->nlp_DID, list, nlp->nlp_flag);
1284
1285 switch (list) {
1286 case NLP_UNUSED_LIST:
1287 nlp->nlp_flag |= list;
1288 /* Put it at the end of the unused list */
1289 list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list);
1290 break;
1291 case NLP_PLOGI_LIST:
1292 nlp->nlp_flag |= list;
1293 /* Put it at the end of the plogi list */
1294 list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list);
1295 break;
1296 case NLP_ADISC_LIST:
1297 nlp->nlp_flag |= list;
1298 /* Put it at the end of the adisc list */
1299 list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list);
1300 break;
1301 case NLP_REGLOGIN_LIST:
1302 nlp->nlp_flag |= list;
1303 /* Put it at the end of the reglogin list */
1304 list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list);
1305 break;
1306 case NLP_PRLI_LIST:
1307 nlp->nlp_flag |= list;
1308 /* Put it at the end of the prli list */
1309 list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list);
1310 break;
1311 case NLP_UNMAPPED_LIST:
1312 nlp->nlp_flag |= list;
1313 /* Put it at the end of the unmap list */
1314 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list);
1315 break;
1316 case NLP_MAPPED_LIST:
1317 nlp->nlp_flag |= list;
1318 /* Put it at the end of the map list */
1319 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list);
1320 break;
1321 case NLP_NPR_LIST:
1322 nlp->nlp_flag |= list;
1323 /* Put it at the end of the npr list */
1324 list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
1325 break;
1326 }
1327
1328 spin_unlock_irq(phba->host->host_lock); 1206 spin_unlock_irq(phba->host->host_lock);
1329 return 0;
1330} 1207}
1331 1208
1332static void 1209static void
@@ -1378,21 +1255,39 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
1378 } 1255 }
1379} 1256}
1380 1257
1258static char *
1259lpfc_nlp_state_name(char *buffer, size_t size, int state)
1260{
1261 static char *states[] = {
1262 [NLP_STE_UNUSED_NODE] = "UNUSED",
1263 [NLP_STE_PLOGI_ISSUE] = "PLOGI",
1264 [NLP_STE_ADISC_ISSUE] = "ADISC",
1265 [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN",
1266 [NLP_STE_PRLI_ISSUE] = "PRLI",
1267 [NLP_STE_UNMAPPED_NODE] = "UNMAPPED",
1268 [NLP_STE_MAPPED_NODE] = "MAPPED",
1269 [NLP_STE_NPR_NODE] = "NPR",
1270 };
1271
1272 if (state < ARRAY_SIZE(states) && states[state])
1273 strlcpy(buffer, states[state], size);
1274 else
1275 snprintf(buffer, size, "unknown (%d)", state);
1276 return buffer;
1277}
1278
1381void 1279void
1382lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) 1280lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
1383{ 1281{
1384 int old_state = ndlp->nlp_state; 1282 int old_state = ndlp->nlp_state;
1385 static int list_id[] = { 1283 char name1[16], name2[16];
1386 [NLP_STE_UNUSED_NODE] = NLP_UNUSED_LIST,
1387 [NLP_STE_PLOGI_ISSUE] = NLP_PLOGI_LIST,
1388 [NLP_STE_ADISC_ISSUE] = NLP_ADISC_LIST,
1389 [NLP_STE_REG_LOGIN_ISSUE] = NLP_REGLOGIN_LIST,
1390 [NLP_STE_PRLI_ISSUE] = NLP_PRLI_LIST,
1391 [NLP_STE_UNMAPPED_NODE] = NLP_UNMAPPED_LIST,
1392 [NLP_STE_MAPPED_NODE] = NLP_MAPPED_LIST,
1393 [NLP_STE_NPR_NODE] = NLP_NPR_LIST,
1394 };
1395 1284
1285 lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
1286 "%d:0904 NPort state transition x%06x, %s -> %s\n",
1287 phba->brd_no,
1288 ndlp->nlp_DID,
1289 lpfc_nlp_state_name(name1, sizeof(name1), old_state),
1290 lpfc_nlp_state_name(name2, sizeof(name2), state));
1396 if (old_state == NLP_STE_NPR_NODE && 1291 if (old_state == NLP_STE_NPR_NODE &&
1397 (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && 1292 (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
1398 state != NLP_STE_NPR_NODE) 1293 state != NLP_STE_NPR_NODE)
@@ -1402,13 +1297,15 @@ lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
1402 ndlp->nlp_type &= ~NLP_FC_NODE; 1297 ndlp->nlp_type &= ~NLP_FC_NODE;
1403 } 1298 }
1404 1299
1405 if (old_state && !list_empty(&ndlp->nlp_listp)) 1300 if (list_empty(&ndlp->nlp_listp)) {
1301 spin_lock_irq(phba->host->host_lock);
1302 list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
1303 spin_unlock_irq(phba->host->host_lock);
1304 } else if (old_state)
1406 lpfc_nlp_counters(phba, old_state, -1); 1305 lpfc_nlp_counters(phba, old_state, -1);
1407 1306
1408 ndlp->nlp_state = state; 1307 ndlp->nlp_state = state;
1409 lpfc_nlp_list(phba, ndlp, list_id[state]);
1410 lpfc_nlp_counters(phba, state, 1); 1308 lpfc_nlp_counters(phba, state, 1);
1411
1412 lpfc_nlp_state_cleanup(phba, ndlp, old_state, state); 1309 lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
1413} 1310}
1414 1311
@@ -1417,10 +1314,10 @@ lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1417{ 1314{
1418 if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) 1315 if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
1419 lpfc_cancel_retry_delay_tmo(phba, ndlp); 1316 lpfc_cancel_retry_delay_tmo(phba, ndlp);
1420 spin_lock_irq(phba->host->host_lock);
1421 if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) 1317 if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
1422 lpfc_nlp_counters(phba, ndlp->nlp_state, -1); 1318 lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
1423 lpfc_delink_node(phba, ndlp); 1319 spin_lock_irq(phba->host->host_lock);
1320 list_del_init(&ndlp->nlp_listp);
1424 spin_unlock_irq(phba->host->host_lock); 1321 spin_unlock_irq(phba->host->host_lock);
1425 lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0); 1322 lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
1426} 1323}
@@ -1430,10 +1327,10 @@ lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1430{ 1327{
1431 if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) 1328 if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
1432 lpfc_cancel_retry_delay_tmo(phba, ndlp); 1329 lpfc_cancel_retry_delay_tmo(phba, ndlp);
1433 spin_lock_irq(phba->host->host_lock);
1434 if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) 1330 if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
1435 lpfc_nlp_counters(phba, ndlp->nlp_state, -1); 1331 lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
1436 lpfc_delink_node(phba, ndlp); 1332 spin_lock_irq(phba->host->host_lock);
1333 list_del_init(&ndlp->nlp_listp);
1437 spin_unlock_irq(phba->host->host_lock); 1334 spin_unlock_irq(phba->host->host_lock);
1438 lpfc_nlp_put(ndlp); 1335 lpfc_nlp_put(ndlp);
1439} 1336}
@@ -1638,7 +1535,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1638 * so it can be freed. 1535 * so it can be freed.
1639 */ 1536 */
1640static int 1537static int
1641lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) 1538lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1642{ 1539{
1643 LPFC_MBOXQ_t *mb; 1540 LPFC_MBOXQ_t *mb;
1644 LPFC_MBOXQ_t *nextmb; 1541 LPFC_MBOXQ_t *nextmb;
@@ -1708,7 +1605,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1708 lpfc_cancel_retry_delay_tmo(phba, ndlp); 1605 lpfc_cancel_retry_delay_tmo(phba, ndlp);
1709 } 1606 }
1710 1607
1711 lpfc_freenode(phba, ndlp); 1608 lpfc_cleanup_node(phba, ndlp);
1712 1609
1713 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { 1610 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
1714 put_device(&ndlp->rport->dev); 1611 put_device(&ndlp->rport->dev);
@@ -1719,7 +1616,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1719} 1616}
1720 1617
1721static int 1618static int
1722lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) 1619lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
1723{ 1620{
1724 D_ID mydid; 1621 D_ID mydid;
1725 D_ID ndlpdid; 1622 D_ID ndlpdid;
@@ -1768,57 +1665,36 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
1768 return 0; 1665 return 0;
1769} 1666}
1770 1667
1771/* Search for a nodelist entry on a specific list */ 1668/* Search for a nodelist entry */
1772struct lpfc_nodelist * 1669struct lpfc_nodelist *
1773lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) 1670lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
1774{ 1671{
1775 struct lpfc_nodelist *ndlp; 1672 struct lpfc_nodelist *ndlp;
1776 struct list_head *lists[]={&phba->fc_nlpunmap_list,
1777 &phba->fc_nlpmap_list,
1778 &phba->fc_plogi_list,
1779 &phba->fc_adisc_list,
1780 &phba->fc_reglogin_list,
1781 &phba->fc_prli_list,
1782 &phba->fc_npr_list,
1783 &phba->fc_unused_list};
1784 uint32_t search[]={NLP_SEARCH_UNMAPPED,
1785 NLP_SEARCH_MAPPED,
1786 NLP_SEARCH_PLOGI,
1787 NLP_SEARCH_ADISC,
1788 NLP_SEARCH_REGLOGIN,
1789 NLP_SEARCH_PRLI,
1790 NLP_SEARCH_NPR,
1791 NLP_SEARCH_UNUSED};
1792 int i;
1793 uint32_t data1; 1673 uint32_t data1;
1794 1674
1795 spin_lock_irq(phba->host->host_lock); 1675 spin_lock_irq(phba->host->host_lock);
1796 for (i = 0; i < ARRAY_SIZE(lists); i++ ) { 1676 list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
1797 if (!(order & search[i])) 1677 if (lpfc_matchdid(phba, ndlp, did)) {
1798 continue; 1678 data1 = (((uint32_t) ndlp->nlp_state << 24) |
1799 list_for_each_entry(ndlp, lists[i], nlp_listp) { 1679 ((uint32_t) ndlp->nlp_xri << 16) |
1800 if (lpfc_matchdid(phba, ndlp, did)) { 1680 ((uint32_t) ndlp->nlp_type << 8) |
1801 data1 = (((uint32_t) ndlp->nlp_state << 24) | 1681 ((uint32_t) ndlp->nlp_rpi & 0xff));
1802 ((uint32_t) ndlp->nlp_xri << 16) | 1682 lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
1803 ((uint32_t) ndlp->nlp_type << 8) | 1683 "%d:0929 FIND node DID "
1804 ((uint32_t) ndlp->nlp_rpi & 0xff)); 1684 " Data: x%p x%x x%x x%x\n",
1805 lpfc_printf_log(phba, KERN_INFO, LOG_NODE, 1685 phba->brd_no,
1806 "%d:0929 FIND node DID " 1686 ndlp, ndlp->nlp_DID,
1807 " Data: x%p x%x x%x x%x\n", 1687 ndlp->nlp_flag, data1);
1808 phba->brd_no, 1688 spin_unlock_irq(phba->host->host_lock);
1809 ndlp, ndlp->nlp_DID, 1689 return ndlp;
1810 ndlp->nlp_flag, data1);
1811 spin_unlock_irq(phba->host->host_lock);
1812 return ndlp;
1813 }
1814 } 1690 }
1815 } 1691 }
1816 spin_unlock_irq(phba->host->host_lock); 1692 spin_unlock_irq(phba->host->host_lock);
1817 1693
1818 /* FIND node did <did> NOT FOUND */ 1694 /* FIND node did <did> NOT FOUND */
1819 lpfc_printf_log(phba, KERN_INFO, LOG_NODE, 1695 lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
1820 "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", 1696 "%d:0932 FIND node did x%x NOT FOUND.\n",
1821 phba->brd_no, did, order); 1697 phba->brd_no, did);
1822 return NULL; 1698 return NULL;
1823} 1699}
1824 1700
@@ -1826,9 +1702,8 @@ struct lpfc_nodelist *
1826lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) 1702lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
1827{ 1703{
1828 struct lpfc_nodelist *ndlp; 1704 struct lpfc_nodelist *ndlp;
1829 uint32_t flg;
1830 1705
1831 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); 1706 ndlp = lpfc_findnode_did(phba, did);
1832 if (!ndlp) { 1707 if (!ndlp) {
1833 if ((phba->fc_flag & FC_RSCN_MODE) && 1708 if ((phba->fc_flag & FC_RSCN_MODE) &&
1834 ((lpfc_rscn_payload_check(phba, did) == 0))) 1709 ((lpfc_rscn_payload_check(phba, did) == 0)))
@@ -1854,8 +1729,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
1854 } else 1729 } else
1855 ndlp = NULL; 1730 ndlp = NULL;
1856 } else { 1731 } else {
1857 flg = ndlp->nlp_flag & NLP_LIST_MASK; 1732 if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
1858 if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) 1733 ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
1859 return NULL; 1734 return NULL;
1860 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); 1735 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
1861 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 1736 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -1915,8 +1790,9 @@ lpfc_disc_start(struct lpfc_hba * phba)
1915 struct lpfc_sli *psli; 1790 struct lpfc_sli *psli;
1916 LPFC_MBOXQ_t *mbox; 1791 LPFC_MBOXQ_t *mbox;
1917 struct lpfc_nodelist *ndlp, *next_ndlp; 1792 struct lpfc_nodelist *ndlp, *next_ndlp;
1918 uint32_t did_changed, num_sent; 1793 uint32_t num_sent;
1919 uint32_t clear_la_pending; 1794 uint32_t clear_la_pending;
1795 int did_changed;
1920 int rc; 1796 int rc;
1921 1797
1922 psli = &phba->sli; 1798 psli = &phba->sli;
@@ -1950,14 +1826,13 @@ lpfc_disc_start(struct lpfc_hba * phba)
1950 phba->fc_plogi_cnt, phba->fc_adisc_cnt); 1826 phba->fc_plogi_cnt, phba->fc_adisc_cnt);
1951 1827
1952 /* If our did changed, we MUST do PLOGI */ 1828 /* If our did changed, we MUST do PLOGI */
1953 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, 1829 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
1954 nlp_listp) { 1830 if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
1955 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { 1831 (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
1956 if (did_changed) { 1832 did_changed) {
1957 spin_lock_irq(phba->host->host_lock); 1833 spin_lock_irq(phba->host->host_lock);
1958 ndlp->nlp_flag &= ~NLP_NPR_ADISC; 1834 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
1959 spin_unlock_irq(phba->host->host_lock); 1835 spin_unlock_irq(phba->host->host_lock);
1960 }
1961 } 1836 }
1962 } 1837 }
1963 1838
@@ -2077,21 +1952,16 @@ lpfc_disc_flush_list(struct lpfc_hba * phba)
2077{ 1952{
2078 struct lpfc_nodelist *ndlp, *next_ndlp; 1953 struct lpfc_nodelist *ndlp, *next_ndlp;
2079 1954
2080 if (phba->fc_plogi_cnt) { 1955 if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
2081 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, 1956 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
2082 nlp_listp) { 1957 nlp_listp) {
2083 lpfc_free_tx(phba, ndlp); 1958 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
2084 lpfc_nlp_put(ndlp); 1959 ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
2085 } 1960 lpfc_free_tx(phba, ndlp);
2086 } 1961 lpfc_nlp_put(ndlp);
2087 if (phba->fc_adisc_cnt) { 1962 }
2088 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
2089 nlp_listp) {
2090 lpfc_free_tx(phba, ndlp);
2091 lpfc_nlp_put(ndlp);
2092 } 1963 }
2093 } 1964 }
2094 return;
2095} 1965}
2096 1966
2097/*****************************************************************************/ 1967/*****************************************************************************/
@@ -2160,8 +2030,10 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
2160 phba->brd_no); 2030 phba->brd_no);
2161 2031
2162 /* Start discovery by sending FLOGI, clean up old rpis */ 2032 /* Start discovery by sending FLOGI, clean up old rpis */
2163 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, 2033 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
2164 nlp_listp) { 2034 nlp_listp) {
2035 if (ndlp->nlp_state != NLP_STE_NPR_NODE)
2036 continue;
2165 if (ndlp->nlp_type & NLP_FABRIC) { 2037 if (ndlp->nlp_type & NLP_FABRIC) {
2166 /* Clean up the ndlp on Fabric connections */ 2038 /* Clean up the ndlp on Fabric connections */
2167 lpfc_drop_node(phba, ndlp); 2039 lpfc_drop_node(phba, ndlp);
@@ -2205,7 +2077,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
2205 "login\n", phba->brd_no); 2077 "login\n", phba->brd_no);
2206 2078
2207 /* Next look for NameServer ndlp */ 2079 /* Next look for NameServer ndlp */
2208 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); 2080 ndlp = lpfc_findnode_did(phba, NameServer_DID);
2209 if (ndlp) 2081 if (ndlp)
2210 lpfc_nlp_put(ndlp); 2082 lpfc_nlp_put(ndlp);
2211 /* Start discovery */ 2083 /* Start discovery */
@@ -2220,9 +2092,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
2220 phba->brd_no, 2092 phba->brd_no,
2221 phba->fc_ns_retry, LPFC_MAX_NS_RETRY); 2093 phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
2222 2094
2223 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, 2095 ndlp = lpfc_findnode_did(phba, NameServer_DID);
2224 NameServer_DID); 2096 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
2225 if (ndlp) {
2226 if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { 2097 if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
2227 /* Try it one more time */ 2098 /* Try it one more time */
2228 rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); 2099 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)
2394 return; 2265 return;
2395} 2266}
2396 2267
2268static int
2269lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param)
2270{
2271 uint16_t *rpi = param;
2272
2273 return ndlp->nlp_rpi == *rpi;
2274}
2275
2276static int
2277lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param)
2278{
2279 return memcmp(&ndlp->nlp_portname, param,
2280 sizeof(ndlp->nlp_portname)) == 0;
2281}
2282
2397/* 2283/*
2398 * This routine looks up the ndlp lists 2284 * Search node lists for a remote port matching filter criteria
2399 * for the given RPI. If rpi found 2285 * Caller needs to hold host_lock before calling this routine.
2400 * it return the node list pointer
2401 * else return NULL.
2402 */ 2286 */
2403struct lpfc_nodelist * 2287struct lpfc_nodelist *
2404__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) 2288__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
2405{ 2289{
2406 struct lpfc_nodelist *ndlp; 2290 struct lpfc_nodelist *ndlp;
2407 struct list_head * lists[]={&phba->fc_nlpunmap_list,
2408 &phba->fc_nlpmap_list,
2409 &phba->fc_plogi_list,
2410 &phba->fc_adisc_list,
2411 &phba->fc_reglogin_list};
2412 int i;
2413 2291
2414 for (i = 0; i < ARRAY_SIZE(lists); i++ ) 2292 list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
2415 list_for_each_entry(ndlp, lists[i], nlp_listp) 2293 if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
2416 if (ndlp->nlp_rpi == rpi) { 2294 filter(ndlp, param))
2417 return ndlp; 2295 return ndlp;
2418 } 2296 }
2419 return NULL; 2297 return NULL;
2420} 2298}
2421 2299
2300/*
2301 * Search node lists for a remote port matching filter criteria
2302 * This routine is used when the caller does NOT have host_lock.
2303 */
2304struct lpfc_nodelist *
2305lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
2306{
2307 struct lpfc_nodelist *ndlp;
2308
2309 spin_lock_irq(phba->host->host_lock);
2310 ndlp = __lpfc_find_node(phba, filter, param);
2311 spin_unlock_irq(phba->host->host_lock);
2312 return ndlp;
2313}
2314
2315/*
2316 * This routine looks up the ndlp lists for the given RPI. If rpi found it
2317 * returns the node list pointer else return NULL.
2318 */
2319struct lpfc_nodelist *
2320__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
2321{
2322 return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
2323}
2324
2422struct lpfc_nodelist * 2325struct lpfc_nodelist *
2423lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) 2326lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
2424{ 2327{
@@ -2431,44 +2334,16 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
2431} 2334}
2432 2335
2433/* 2336/*
2434 * This routine looks up the ndlp lists 2337 * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
2435 * for the given WWPN. If WWPN found 2338 * returns the node list pointer else return NULL.
2436 * it return the node list pointer
2437 * else return NULL.
2438 */ 2339 */
2439struct lpfc_nodelist * 2340struct lpfc_nodelist *
2440lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, 2341lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
2441 struct lpfc_name * wwpn)
2442{ 2342{
2443 struct lpfc_nodelist *ndlp; 2343 struct lpfc_nodelist *ndlp;
2444 struct list_head * lists[]={&phba->fc_nlpunmap_list,
2445 &phba->fc_nlpmap_list,
2446 &phba->fc_npr_list,
2447 &phba->fc_plogi_list,
2448 &phba->fc_adisc_list,
2449 &phba->fc_reglogin_list,
2450 &phba->fc_prli_list};
2451 uint32_t search[]={NLP_SEARCH_UNMAPPED,
2452 NLP_SEARCH_MAPPED,
2453 NLP_SEARCH_NPR,
2454 NLP_SEARCH_PLOGI,
2455 NLP_SEARCH_ADISC,
2456 NLP_SEARCH_REGLOGIN,
2457 NLP_SEARCH_PRLI};
2458 int i;
2459 2344
2460 spin_lock_irq(phba->host->host_lock); 2345 spin_lock_irq(phba->host->host_lock);
2461 for (i = 0; i < ARRAY_SIZE(lists); i++ ) { 2346 ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
2462 if (!(order & search[i]))
2463 continue;
2464 list_for_each_entry(ndlp, lists[i], nlp_listp) {
2465 if (memcmp(&ndlp->nlp_portname, wwpn,
2466 sizeof(struct lpfc_name)) == 0) {
2467 spin_unlock_irq(phba->host->host_lock);
2468 return ndlp;
2469 }
2470 }
2471 }
2472 spin_unlock_irq(phba->host->host_lock); 2347 spin_unlock_irq(phba->host->host_lock);
2473 return NULL; 2348 return NULL;
2474} 2349}
@@ -2484,6 +2359,7 @@ lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
2484 ndlp->nlp_DID = did; 2359 ndlp->nlp_DID = did;
2485 ndlp->nlp_phba = phba; 2360 ndlp->nlp_phba = phba;
2486 ndlp->nlp_sid = NLP_NO_SID; 2361 ndlp->nlp_sid = NLP_NO_SID;
2362 INIT_LIST_HEAD(&ndlp->nlp_listp);
2487 kref_init(&ndlp->kref); 2363 kref_init(&ndlp->kref);
2488 return; 2364 return;
2489} 2365}