diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:53:08 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:15 -0400 |
commit | 685f0bf7afe087940d34f98ac0fd1df84091d360 (patch) | |
tree | 7e7fbfc856f13a3c4c64e14784b7050812753521 /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 329f9bc735b4665d42267259b1612191f72c4d42 (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.c | 458 |
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 | ||
376 | int | 376 | int |
377 | lpfc_linkdown(struct lpfc_hba * phba) | 377 | lpfc_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 | ||
468 | static int | 453 | static int |
469 | lpfc_linkup(struct lpfc_hba * phba) | 454 | lpfc_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) | |||
1200 | static void | 1176 | static void |
1201 | lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) | 1177 | lpfc_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 | |||
1231 | void | ||
1232 | lpfc_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 | |||
1264 | static int | ||
1265 | lpfc_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 | ||
1332 | static void | 1209 | static void |
@@ -1378,21 +1255,39 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
1378 | } | 1255 | } |
1379 | } | 1256 | } |
1380 | 1257 | ||
1258 | static char * | ||
1259 | lpfc_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 | |||
1381 | void | 1279 | void |
1382 | lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) | 1280 | lpfc_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 | */ |
1640 | static int | 1537 | static int |
1641 | lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1538 | lpfc_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 | ||
1721 | static int | 1618 | static int |
1722 | lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | 1619 | lpfc_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 */ |
1772 | struct lpfc_nodelist * | 1669 | struct lpfc_nodelist * |
1773 | lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) | 1670 | lpfc_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 * | |||
1826 | lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | 1702 | lpfc_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 | ||
2268 | static int | ||
2269 | lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param) | ||
2270 | { | ||
2271 | uint16_t *rpi = param; | ||
2272 | |||
2273 | return ndlp->nlp_rpi == *rpi; | ||
2274 | } | ||
2275 | |||
2276 | static int | ||
2277 | lpfc_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 | */ |
2403 | struct lpfc_nodelist * | 2287 | struct 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 | */ | ||
2304 | struct lpfc_nodelist * | ||
2305 | lpfc_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 | */ | ||
2319 | struct 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 | |||
2422 | struct lpfc_nodelist * | 2325 | struct lpfc_nodelist * |
2423 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | 2326 | lpfc_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 | */ |
2439 | struct lpfc_nodelist * | 2340 | struct lpfc_nodelist * |
2440 | lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, | 2341 | lpfc_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 | } |