diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 884 |
1 files changed, 424 insertions, 460 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c39564e85e94..61caa8d379e2 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2006 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -109,6 +109,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
109 | return; | 109 | return; |
110 | } | 110 | } |
111 | 111 | ||
112 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
113 | return; | ||
114 | |||
112 | name = (uint8_t *)&ndlp->nlp_portname; | 115 | name = (uint8_t *)&ndlp->nlp_portname; |
113 | phba = ndlp->nlp_phba; | 116 | phba = ndlp->nlp_phba; |
114 | 117 | ||
@@ -147,11 +150,17 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
147 | ndlp->nlp_state, ndlp->nlp_rpi); | 150 | ndlp->nlp_state, ndlp->nlp_rpi); |
148 | } | 151 | } |
149 | 152 | ||
150 | ndlp->rport = NULL; | 153 | if (!(phba->fc_flag & FC_UNLOADING) && |
151 | rdata->pnode = NULL; | 154 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && |
152 | 155 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && | |
153 | if (!(phba->fc_flag & FC_UNLOADING)) | 156 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) |
154 | lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM); | 157 | lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM); |
158 | else { | ||
159 | rdata->pnode = NULL; | ||
160 | ndlp->rport = NULL; | ||
161 | lpfc_nlp_put(ndlp); | ||
162 | put_device(&rport->dev); | ||
163 | } | ||
155 | 164 | ||
156 | return; | 165 | return; |
157 | } | 166 | } |
@@ -182,29 +191,35 @@ lpfc_work_list_done(struct lpfc_hba * phba) | |||
182 | *(int *)(evtp->evt_arg1) = 0; | 191 | *(int *)(evtp->evt_arg1) = 0; |
183 | complete((struct completion *)(evtp->evt_arg2)); | 192 | complete((struct completion *)(evtp->evt_arg2)); |
184 | break; | 193 | break; |
185 | case LPFC_EVT_OFFLINE: | 194 | case LPFC_EVT_OFFLINE_PREP: |
186 | if (phba->hba_state >= LPFC_LINK_DOWN) | 195 | if (phba->hba_state >= LPFC_LINK_DOWN) |
187 | lpfc_offline(phba); | 196 | lpfc_offline_prep(phba); |
197 | *(int *)(evtp->evt_arg1) = 0; | ||
198 | complete((struct completion *)(evtp->evt_arg2)); | ||
199 | break; | ||
200 | case LPFC_EVT_OFFLINE: | ||
201 | lpfc_offline(phba); | ||
188 | lpfc_sli_brdrestart(phba); | 202 | lpfc_sli_brdrestart(phba); |
189 | *(int *)(evtp->evt_arg1) = | 203 | *(int *)(evtp->evt_arg1) = |
190 | lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY); | 204 | lpfc_sli_brdready(phba, HS_FFRDY | HS_MBRDY); |
205 | lpfc_unblock_mgmt_io(phba); | ||
191 | complete((struct completion *)(evtp->evt_arg2)); | 206 | complete((struct completion *)(evtp->evt_arg2)); |
192 | break; | 207 | break; |
193 | case LPFC_EVT_WARM_START: | 208 | case LPFC_EVT_WARM_START: |
194 | if (phba->hba_state >= LPFC_LINK_DOWN) | 209 | lpfc_offline(phba); |
195 | lpfc_offline(phba); | ||
196 | lpfc_reset_barrier(phba); | 210 | lpfc_reset_barrier(phba); |
197 | lpfc_sli_brdreset(phba); | 211 | lpfc_sli_brdreset(phba); |
198 | lpfc_hba_down_post(phba); | 212 | lpfc_hba_down_post(phba); |
199 | *(int *)(evtp->evt_arg1) = | 213 | *(int *)(evtp->evt_arg1) = |
200 | lpfc_sli_brdready(phba, HS_MBRDY); | 214 | lpfc_sli_brdready(phba, HS_MBRDY); |
215 | lpfc_unblock_mgmt_io(phba); | ||
201 | complete((struct completion *)(evtp->evt_arg2)); | 216 | complete((struct completion *)(evtp->evt_arg2)); |
202 | break; | 217 | break; |
203 | case LPFC_EVT_KILL: | 218 | case LPFC_EVT_KILL: |
204 | if (phba->hba_state >= LPFC_LINK_DOWN) | 219 | lpfc_offline(phba); |
205 | lpfc_offline(phba); | ||
206 | *(int *)(evtp->evt_arg1) | 220 | *(int *)(evtp->evt_arg1) |
207 | = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); | 221 | = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); |
222 | lpfc_unblock_mgmt_io(phba); | ||
208 | complete((struct completion *)(evtp->evt_arg2)); | 223 | complete((struct completion *)(evtp->evt_arg2)); |
209 | break; | 224 | break; |
210 | } | 225 | } |
@@ -359,13 +374,12 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2, | |||
359 | } | 374 | } |
360 | 375 | ||
361 | int | 376 | int |
362 | lpfc_linkdown(struct lpfc_hba * phba) | 377 | lpfc_linkdown(struct lpfc_hba *phba) |
363 | { | 378 | { |
364 | struct lpfc_sli *psli; | 379 | struct lpfc_sli *psli; |
365 | struct lpfc_nodelist *ndlp, *next_ndlp; | 380 | struct lpfc_nodelist *ndlp, *next_ndlp; |
366 | struct list_head *listp, *node_list[7]; | 381 | LPFC_MBOXQ_t *mb; |
367 | LPFC_MBOXQ_t *mb; | 382 | int rc; |
368 | int rc, i; | ||
369 | 383 | ||
370 | psli = &phba->sli; | 384 | psli = &phba->sli; |
371 | /* sysfs or selective reset may call this routine to clean up */ | 385 | /* sysfs or selective reset may call this routine to clean up */ |
@@ -397,31 +411,16 @@ lpfc_linkdown(struct lpfc_hba * phba) | |||
397 | /* Cleanup any outstanding ELS commands */ | 411 | /* Cleanup any outstanding ELS commands */ |
398 | lpfc_els_flush_cmd(phba); | 412 | lpfc_els_flush_cmd(phba); |
399 | 413 | ||
400 | /* Issue a LINK DOWN event to all nodes */ | 414 | /* |
401 | node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ | 415 | * Issue a LINK DOWN event to all nodes. |
402 | node_list[1] = &phba->fc_nlpmap_list; | 416 | */ |
403 | node_list[2] = &phba->fc_nlpunmap_list; | 417 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
404 | node_list[3] = &phba->fc_prli_list; | 418 | /* free any ndlp's on unused list */ |
405 | node_list[4] = &phba->fc_reglogin_list; | 419 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
406 | node_list[5] = &phba->fc_adisc_list; | 420 | lpfc_drop_node(phba, ndlp); |
407 | node_list[6] = &phba->fc_plogi_list; | 421 | else /* otherwise, force node recovery. */ |
408 | for (i = 0; i < 7; i++) { | ||
409 | listp = node_list[i]; | ||
410 | if (list_empty(listp)) | ||
411 | continue; | ||
412 | |||
413 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { | ||
414 | |||
415 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, | 422 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, |
416 | NLP_EVT_DEVICE_RECOVERY); | 423 | NLP_EVT_DEVICE_RECOVERY); |
417 | |||
418 | } | ||
419 | } | ||
420 | |||
421 | /* free any ndlp's on unused list */ | ||
422 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | ||
423 | nlp_listp) { | ||
424 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | ||
425 | } | 424 | } |
426 | 425 | ||
427 | /* Setup myDID for link up if we are in pt2pt mode */ | 426 | /* Setup myDID for link up if we are in pt2pt mode */ |
@@ -452,11 +451,9 @@ lpfc_linkdown(struct lpfc_hba * phba) | |||
452 | } | 451 | } |
453 | 452 | ||
454 | static int | 453 | static int |
455 | lpfc_linkup(struct lpfc_hba * phba) | 454 | lpfc_linkup(struct lpfc_hba *phba) |
456 | { | 455 | { |
457 | struct lpfc_nodelist *ndlp, *next_ndlp; | 456 | struct lpfc_nodelist *ndlp, *next_ndlp; |
458 | struct list_head *listp, *node_list[7]; | ||
459 | int i; | ||
460 | 457 | ||
461 | fc_host_post_event(phba->host, fc_get_event_number(), | 458 | fc_host_post_event(phba->host, fc_get_event_number(), |
462 | FCH_EVT_LINKUP, 0); | 459 | FCH_EVT_LINKUP, 0); |
@@ -470,29 +467,20 @@ lpfc_linkup(struct lpfc_hba * phba) | |||
470 | spin_unlock_irq(phba->host->host_lock); | 467 | spin_unlock_irq(phba->host->host_lock); |
471 | 468 | ||
472 | 469 | ||
473 | node_list[0] = &phba->fc_plogi_list; | 470 | if (phba->fc_flag & FC_LBIT) { |
474 | node_list[1] = &phba->fc_adisc_list; | 471 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
475 | node_list[2] = &phba->fc_reglogin_list; | 472 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) { |
476 | node_list[3] = &phba->fc_prli_list; | ||
477 | node_list[4] = &phba->fc_nlpunmap_list; | ||
478 | node_list[5] = &phba->fc_nlpmap_list; | ||
479 | node_list[6] = &phba->fc_npr_list; | ||
480 | for (i = 0; i < 7; i++) { | ||
481 | listp = node_list[i]; | ||
482 | if (list_empty(listp)) | ||
483 | continue; | ||
484 | |||
485 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { | ||
486 | if (phba->fc_flag & FC_LBIT) { | ||
487 | if (ndlp->nlp_type & NLP_FABRIC) { | 473 | if (ndlp->nlp_type & NLP_FABRIC) { |
488 | /* On Linkup its safe to clean up the | 474 | /* |
475 | * On Linkup its safe to clean up the | ||
489 | * ndlp from Fabric connections. | 476 | * ndlp from Fabric connections. |
490 | */ | 477 | */ |
491 | lpfc_nlp_list(phba, ndlp, | 478 | lpfc_nlp_set_state(phba, ndlp, |
492 | NLP_UNUSED_LIST); | 479 | NLP_STE_UNUSED_NODE); |
493 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 480 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
494 | /* Fail outstanding IO now since device | 481 | /* |
495 | * is marked for PLOGI. | 482 | * Fail outstanding IO now since |
483 | * device is marked for PLOGI. | ||
496 | */ | 484 | */ |
497 | lpfc_unreg_rpi(phba, ndlp); | 485 | lpfc_unreg_rpi(phba, ndlp); |
498 | } | 486 | } |
@@ -501,9 +489,10 @@ lpfc_linkup(struct lpfc_hba * phba) | |||
501 | } | 489 | } |
502 | 490 | ||
503 | /* free any ndlp's on unused list */ | 491 | /* free any ndlp's on unused list */ |
504 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | 492 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
505 | nlp_listp) { | 493 | nlp_listp) { |
506 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 494 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
495 | lpfc_drop_node(phba, ndlp); | ||
507 | } | 496 | } |
508 | 497 | ||
509 | return 0; | 498 | return 0; |
@@ -734,6 +723,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
734 | case LA_4GHZ_LINK: | 723 | case LA_4GHZ_LINK: |
735 | phba->fc_linkspeed = LA_4GHZ_LINK; | 724 | phba->fc_linkspeed = LA_4GHZ_LINK; |
736 | break; | 725 | break; |
726 | case LA_8GHZ_LINK: | ||
727 | phba->fc_linkspeed = LA_8GHZ_LINK; | ||
728 | break; | ||
737 | default: | 729 | default: |
738 | phba->fc_linkspeed = LA_UNKNW_LINK; | 730 | phba->fc_linkspeed = LA_UNKNW_LINK; |
739 | break; | 731 | break; |
@@ -889,12 +881,21 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
889 | 881 | ||
890 | if (la->attType == AT_LINK_UP) { | 882 | if (la->attType == AT_LINK_UP) { |
891 | phba->fc_stat.LinkUp++; | 883 | phba->fc_stat.LinkUp++; |
892 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | 884 | if (phba->fc_flag & FC_LOOPBACK_MODE) { |
885 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, | ||
886 | "%d:1306 Link Up Event in loop back mode " | ||
887 | "x%x received Data: x%x x%x x%x x%x\n", | ||
888 | phba->brd_no, la->eventTag, phba->fc_eventTag, | ||
889 | la->granted_AL_PA, la->UlnkSpeed, | ||
890 | phba->alpa_map[0]); | ||
891 | } else { | ||
892 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | ||
893 | "%d:1303 Link Up Event x%x received " | 893 | "%d:1303 Link Up Event x%x received " |
894 | "Data: x%x x%x x%x x%x\n", | 894 | "Data: x%x x%x x%x x%x\n", |
895 | phba->brd_no, la->eventTag, phba->fc_eventTag, | 895 | phba->brd_no, la->eventTag, phba->fc_eventTag, |
896 | la->granted_AL_PA, la->UlnkSpeed, | 896 | la->granted_AL_PA, la->UlnkSpeed, |
897 | phba->alpa_map[0]); | 897 | phba->alpa_map[0]); |
898 | } | ||
898 | lpfc_mbx_process_link_up(phba, la); | 899 | lpfc_mbx_process_link_up(phba, la); |
899 | } else { | 900 | } else { |
900 | phba->fc_stat.LinkDown++; | 901 | phba->fc_stat.LinkDown++; |
@@ -940,6 +941,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
940 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 941 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
941 | kfree(mp); | 942 | kfree(mp); |
942 | mempool_free( pmb, phba->mbox_mem_pool); | 943 | mempool_free( pmb, phba->mbox_mem_pool); |
944 | lpfc_nlp_put(ndlp); | ||
943 | 945 | ||
944 | return; | 946 | return; |
945 | } | 947 | } |
@@ -966,11 +968,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
966 | ndlp = (struct lpfc_nodelist *) pmb->context2; | 968 | ndlp = (struct lpfc_nodelist *) pmb->context2; |
967 | mp = (struct lpfc_dmabuf *) (pmb->context1); | 969 | mp = (struct lpfc_dmabuf *) (pmb->context1); |
968 | 970 | ||
971 | pmb->context1 = NULL; | ||
972 | pmb->context2 = NULL; | ||
973 | |||
969 | if (mb->mbxStatus) { | 974 | if (mb->mbxStatus) { |
970 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 975 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
971 | kfree(mp); | 976 | kfree(mp); |
972 | mempool_free( pmb, phba->mbox_mem_pool); | 977 | mempool_free(pmb, phba->mbox_mem_pool); |
973 | mempool_free( ndlp, phba->nlp_mem_pool); | 978 | lpfc_nlp_put(ndlp); |
974 | 979 | ||
975 | /* FLOGI failed, so just use loop map to make discovery list */ | 980 | /* FLOGI failed, so just use loop map to make discovery list */ |
976 | lpfc_disc_list_loopmap(phba); | 981 | lpfc_disc_list_loopmap(phba); |
@@ -980,12 +985,11 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
980 | return; | 985 | return; |
981 | } | 986 | } |
982 | 987 | ||
983 | pmb->context1 = NULL; | ||
984 | |||
985 | ndlp->nlp_rpi = mb->un.varWords[0]; | 988 | ndlp->nlp_rpi = mb->un.varWords[0]; |
986 | ndlp->nlp_type |= NLP_FABRIC; | 989 | ndlp->nlp_type |= NLP_FABRIC; |
987 | ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; | 990 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); |
988 | lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); | 991 | |
992 | lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */ | ||
989 | 993 | ||
990 | if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { | 994 | if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { |
991 | /* This NPort has been assigned an NPort_ID by the fabric as a | 995 | /* This NPort has been assigned an NPort_ID by the fabric as a |
@@ -996,7 +1000,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
996 | */ | 1000 | */ |
997 | lpfc_issue_els_scr(phba, SCR_DID, 0); | 1001 | lpfc_issue_els_scr(phba, SCR_DID, 0); |
998 | 1002 | ||
999 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); | 1003 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
1000 | if (!ndlp) { | 1004 | if (!ndlp) { |
1001 | /* Allocate a new node instance. If the pool is empty, | 1005 | /* Allocate a new node instance. If the pool is empty, |
1002 | * start the discovery process and skip the Nameserver | 1006 | * start the discovery process and skip the Nameserver |
@@ -1008,15 +1012,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1008 | lpfc_disc_start(phba); | 1012 | lpfc_disc_start(phba); |
1009 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1013 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1010 | kfree(mp); | 1014 | kfree(mp); |
1011 | mempool_free( pmb, phba->mbox_mem_pool); | 1015 | mempool_free(pmb, phba->mbox_mem_pool); |
1012 | return; | 1016 | return; |
1013 | } else { | 1017 | } else { |
1014 | lpfc_nlp_init(phba, ndlp, NameServer_DID); | 1018 | lpfc_nlp_init(phba, ndlp, NameServer_DID); |
1015 | ndlp->nlp_type |= NLP_FABRIC; | 1019 | ndlp->nlp_type |= NLP_FABRIC; |
1016 | } | 1020 | } |
1017 | } | 1021 | } |
1018 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 1022 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); |
1019 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | ||
1020 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); | 1023 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); |
1021 | if (phba->cfg_fdmi_on) { | 1024 | if (phba->cfg_fdmi_on) { |
1022 | ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, | 1025 | ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, |
@@ -1032,7 +1035,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1032 | 1035 | ||
1033 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1036 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1034 | kfree(mp); | 1037 | kfree(mp); |
1035 | mempool_free( pmb, phba->mbox_mem_pool); | 1038 | mempool_free(pmb, phba->mbox_mem_pool); |
1036 | return; | 1039 | return; |
1037 | } | 1040 | } |
1038 | 1041 | ||
@@ -1057,10 +1060,11 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1057 | mp = (struct lpfc_dmabuf *) (pmb->context1); | 1060 | mp = (struct lpfc_dmabuf *) (pmb->context1); |
1058 | 1061 | ||
1059 | if (mb->mbxStatus) { | 1062 | if (mb->mbxStatus) { |
1063 | lpfc_nlp_put(ndlp); | ||
1060 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1064 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1061 | kfree(mp); | 1065 | kfree(mp); |
1062 | mempool_free( pmb, phba->mbox_mem_pool); | 1066 | mempool_free(pmb, phba->mbox_mem_pool); |
1063 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 1067 | lpfc_drop_node(phba, ndlp); |
1064 | 1068 | ||
1065 | /* RegLogin failed, so just use loop map to make discovery | 1069 | /* RegLogin failed, so just use loop map to make discovery |
1066 | list */ | 1070 | list */ |
@@ -1075,8 +1079,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1075 | 1079 | ||
1076 | ndlp->nlp_rpi = mb->un.varWords[0]; | 1080 | ndlp->nlp_rpi = mb->un.varWords[0]; |
1077 | ndlp->nlp_type |= NLP_FABRIC; | 1081 | ndlp->nlp_type |= NLP_FABRIC; |
1078 | ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; | 1082 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); |
1079 | lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); | ||
1080 | 1083 | ||
1081 | if (phba->hba_state < LPFC_HBA_READY) { | 1084 | if (phba->hba_state < LPFC_HBA_READY) { |
1082 | /* Link up discovery requires Fabrib registration. */ | 1085 | /* Link up discovery requires Fabrib registration. */ |
@@ -1093,6 +1096,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1093 | lpfc_disc_start(phba); | 1096 | lpfc_disc_start(phba); |
1094 | } | 1097 | } |
1095 | 1098 | ||
1099 | lpfc_nlp_put(ndlp); | ||
1096 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1100 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1097 | kfree(mp); | 1101 | kfree(mp); |
1098 | mempool_free( pmb, phba->mbox_mem_pool); | 1102 | mempool_free( pmb, phba->mbox_mem_pool); |
@@ -1101,8 +1105,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1101 | } | 1105 | } |
1102 | 1106 | ||
1103 | static void | 1107 | static void |
1104 | lpfc_register_remote_port(struct lpfc_hba * phba, | 1108 | lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
1105 | struct lpfc_nodelist * ndlp) | ||
1106 | { | 1109 | { |
1107 | struct fc_rport *rport; | 1110 | struct fc_rport *rport; |
1108 | struct lpfc_rport_data *rdata; | 1111 | struct lpfc_rport_data *rdata; |
@@ -1114,8 +1117,19 @@ lpfc_register_remote_port(struct lpfc_hba * phba, | |||
1114 | rport_ids.port_id = ndlp->nlp_DID; | 1117 | rport_ids.port_id = ndlp->nlp_DID; |
1115 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 1118 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
1116 | 1119 | ||
1120 | /* | ||
1121 | * We leave our node pointer in rport->dd_data when we unregister a | ||
1122 | * FCP target port. But fc_remote_port_add zeros the space to which | ||
1123 | * rport->dd_data points. So, if we're reusing a previously | ||
1124 | * registered port, drop the reference that we took the last time we | ||
1125 | * registered the port. | ||
1126 | */ | ||
1127 | if (ndlp->rport && ndlp->rport->dd_data && | ||
1128 | *(struct lpfc_rport_data **) ndlp->rport->dd_data) { | ||
1129 | lpfc_nlp_put(ndlp); | ||
1130 | } | ||
1117 | ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); | 1131 | ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); |
1118 | if (!rport) { | 1132 | if (!rport || !get_device(&rport->dev)) { |
1119 | dev_printk(KERN_WARNING, &phba->pcidev->dev, | 1133 | dev_printk(KERN_WARNING, &phba->pcidev->dev, |
1120 | "Warning: fc_remote_port_add failed\n"); | 1134 | "Warning: fc_remote_port_add failed\n"); |
1121 | return; | 1135 | return; |
@@ -1125,7 +1139,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba, | |||
1125 | rport->maxframe_size = ndlp->nlp_maxframe; | 1139 | rport->maxframe_size = ndlp->nlp_maxframe; |
1126 | rport->supported_classes = ndlp->nlp_class_sup; | 1140 | rport->supported_classes = ndlp->nlp_class_sup; |
1127 | rdata = rport->dd_data; | 1141 | rdata = rport->dd_data; |
1128 | rdata->pnode = ndlp; | 1142 | rdata->pnode = lpfc_nlp_get(ndlp); |
1129 | 1143 | ||
1130 | if (ndlp->nlp_type & NLP_FCP_TARGET) | 1144 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
1131 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; | 1145 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; |
@@ -1145,8 +1159,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba, | |||
1145 | } | 1159 | } |
1146 | 1160 | ||
1147 | static void | 1161 | static void |
1148 | lpfc_unregister_remote_port(struct lpfc_hba * phba, | 1162 | lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
1149 | struct lpfc_nodelist * ndlp) | ||
1150 | { | 1163 | { |
1151 | struct fc_rport *rport = ndlp->rport; | 1164 | struct fc_rport *rport = ndlp->rport; |
1152 | struct lpfc_rport_data *rdata = rport->dd_data; | 1165 | struct lpfc_rport_data *rdata = rport->dd_data; |
@@ -1154,6 +1167,8 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba, | |||
1154 | if (rport->scsi_target_id == -1) { | 1167 | if (rport->scsi_target_id == -1) { |
1155 | ndlp->rport = NULL; | 1168 | ndlp->rport = NULL; |
1156 | rdata->pnode = NULL; | 1169 | rdata->pnode = NULL; |
1170 | lpfc_nlp_put(ndlp); | ||
1171 | put_device(&rport->dev); | ||
1157 | } | 1172 | } |
1158 | 1173 | ||
1159 | fc_remote_port_delete(rport); | 1174 | fc_remote_port_delete(rport); |
@@ -1161,178 +1176,70 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba, | |||
1161 | return; | 1176 | return; |
1162 | } | 1177 | } |
1163 | 1178 | ||
1164 | int | 1179 | static void |
1165 | lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | 1180 | lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) |
1166 | { | 1181 | { |
1167 | enum { none, unmapped, mapped } rport_add = none, rport_del = none; | ||
1168 | struct lpfc_sli *psli; | ||
1169 | |||
1170 | psli = &phba->sli; | ||
1171 | /* Sanity check to ensure we are not moving to / from the same list */ | ||
1172 | if ((nlp->nlp_flag & NLP_LIST_MASK) == list) | ||
1173 | if (list != NLP_NO_LIST) | ||
1174 | return 0; | ||
1175 | |||
1176 | spin_lock_irq(phba->host->host_lock); | 1182 | spin_lock_irq(phba->host->host_lock); |
1177 | switch (nlp->nlp_flag & NLP_LIST_MASK) { | 1183 | switch (state) { |
1178 | case NLP_NO_LIST: /* Not on any list */ | 1184 | case NLP_STE_UNUSED_NODE: |
1185 | phba->fc_unused_cnt += count; | ||
1179 | break; | 1186 | break; |
1180 | case NLP_UNUSED_LIST: | 1187 | case NLP_STE_PLOGI_ISSUE: |
1181 | phba->fc_unused_cnt--; | 1188 | phba->fc_plogi_cnt += count; |
1182 | list_del(&nlp->nlp_listp); | ||
1183 | break; | 1189 | break; |
1184 | case NLP_PLOGI_LIST: | 1190 | case NLP_STE_ADISC_ISSUE: |
1185 | phba->fc_plogi_cnt--; | 1191 | phba->fc_adisc_cnt += count; |
1186 | list_del(&nlp->nlp_listp); | ||
1187 | break; | 1192 | break; |
1188 | case NLP_ADISC_LIST: | 1193 | case NLP_STE_REG_LOGIN_ISSUE: |
1189 | phba->fc_adisc_cnt--; | 1194 | phba->fc_reglogin_cnt += count; |
1190 | list_del(&nlp->nlp_listp); | ||
1191 | break; | 1195 | break; |
1192 | case NLP_REGLOGIN_LIST: | 1196 | case NLP_STE_PRLI_ISSUE: |
1193 | phba->fc_reglogin_cnt--; | 1197 | phba->fc_prli_cnt += count; |
1194 | list_del(&nlp->nlp_listp); | ||
1195 | break; | 1198 | break; |
1196 | case NLP_PRLI_LIST: | 1199 | case NLP_STE_UNMAPPED_NODE: |
1197 | phba->fc_prli_cnt--; | 1200 | phba->fc_unmap_cnt += count; |
1198 | list_del(&nlp->nlp_listp); | ||
1199 | break; | 1201 | break; |
1200 | case NLP_UNMAPPED_LIST: | 1202 | case NLP_STE_MAPPED_NODE: |
1201 | phba->fc_unmap_cnt--; | 1203 | phba->fc_map_cnt += count; |
1202 | list_del(&nlp->nlp_listp); | ||
1203 | nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; | ||
1204 | nlp->nlp_type &= ~NLP_FC_NODE; | ||
1205 | phba->nport_event_cnt++; | ||
1206 | if (nlp->rport) | ||
1207 | rport_del = unmapped; | ||
1208 | break; | 1204 | break; |
1209 | case NLP_MAPPED_LIST: | 1205 | case NLP_STE_NPR_NODE: |
1210 | phba->fc_map_cnt--; | 1206 | phba->fc_npr_cnt += count; |
1211 | list_del(&nlp->nlp_listp); | ||
1212 | phba->nport_event_cnt++; | ||
1213 | if (nlp->rport) | ||
1214 | rport_del = mapped; | ||
1215 | break; | ||
1216 | case NLP_NPR_LIST: | ||
1217 | phba->fc_npr_cnt--; | ||
1218 | list_del(&nlp->nlp_listp); | ||
1219 | /* Stop delay tmo if taking node off NPR list */ | ||
1220 | if ((nlp->nlp_flag & NLP_DELAY_TMO) && | ||
1221 | (list != NLP_NPR_LIST)) { | ||
1222 | spin_unlock_irq(phba->host->host_lock); | ||
1223 | lpfc_cancel_retry_delay_tmo(phba, nlp); | ||
1224 | spin_lock_irq(phba->host->host_lock); | ||
1225 | } | ||
1226 | break; | 1207 | break; |
1227 | } | 1208 | } |
1209 | spin_unlock_irq(phba->host->host_lock); | ||
1210 | } | ||
1228 | 1211 | ||
1229 | nlp->nlp_flag &= ~NLP_LIST_MASK; | 1212 | static void |
1230 | 1213 | lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |
1231 | /* Add NPort <did> to <num> list */ | 1214 | int old_state, int new_state) |
1232 | lpfc_printf_log(phba, | 1215 | { |
1233 | KERN_INFO, | 1216 | if (new_state == NLP_STE_UNMAPPED_NODE) { |
1234 | LOG_NODE, | 1217 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
1235 | "%d:0904 Add NPort x%x to %d list Data: x%x\n", | 1218 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
1236 | phba->brd_no, | 1219 | ndlp->nlp_type |= NLP_FC_NODE; |
1237 | nlp->nlp_DID, list, nlp->nlp_flag); | 1220 | } |
1238 | 1221 | if (new_state == NLP_STE_MAPPED_NODE) | |
1239 | switch (list) { | 1222 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
1240 | case NLP_NO_LIST: /* No list, just remove it */ | 1223 | if (new_state == NLP_STE_NPR_NODE) |
1241 | spin_unlock_irq(phba->host->host_lock); | 1224 | ndlp->nlp_flag &= ~NLP_RCV_PLOGI; |
1242 | lpfc_nlp_remove(phba, nlp); | 1225 | |
1243 | spin_lock_irq(phba->host->host_lock); | 1226 | /* Transport interface */ |
1244 | /* as node removed - stop further transport calls */ | 1227 | if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE || |
1245 | rport_del = none; | 1228 | old_state == NLP_STE_UNMAPPED_NODE)) { |
1246 | break; | ||
1247 | case NLP_UNUSED_LIST: | ||
1248 | nlp->nlp_flag |= list; | ||
1249 | /* Put it at the end of the unused list */ | ||
1250 | list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); | ||
1251 | phba->fc_unused_cnt++; | ||
1252 | break; | ||
1253 | case NLP_PLOGI_LIST: | ||
1254 | nlp->nlp_flag |= list; | ||
1255 | /* Put it at the end of the plogi list */ | ||
1256 | list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); | ||
1257 | phba->fc_plogi_cnt++; | ||
1258 | break; | ||
1259 | case NLP_ADISC_LIST: | ||
1260 | nlp->nlp_flag |= list; | ||
1261 | /* Put it at the end of the adisc list */ | ||
1262 | list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); | ||
1263 | phba->fc_adisc_cnt++; | ||
1264 | break; | ||
1265 | case NLP_REGLOGIN_LIST: | ||
1266 | nlp->nlp_flag |= list; | ||
1267 | /* Put it at the end of the reglogin list */ | ||
1268 | list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); | ||
1269 | phba->fc_reglogin_cnt++; | ||
1270 | break; | ||
1271 | case NLP_PRLI_LIST: | ||
1272 | nlp->nlp_flag |= list; | ||
1273 | /* Put it at the end of the prli list */ | ||
1274 | list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); | ||
1275 | phba->fc_prli_cnt++; | ||
1276 | break; | ||
1277 | case NLP_UNMAPPED_LIST: | ||
1278 | rport_add = unmapped; | ||
1279 | /* ensure all vestiges of "mapped" significance are gone */ | ||
1280 | nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | ||
1281 | nlp->nlp_flag |= list; | ||
1282 | /* Put it at the end of the unmap list */ | ||
1283 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); | ||
1284 | phba->fc_unmap_cnt++; | ||
1285 | phba->nport_event_cnt++; | ||
1286 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; | ||
1287 | nlp->nlp_type |= NLP_FC_NODE; | ||
1288 | break; | ||
1289 | case NLP_MAPPED_LIST: | ||
1290 | rport_add = mapped; | ||
1291 | nlp->nlp_flag |= list; | ||
1292 | /* Put it at the end of the map list */ | ||
1293 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); | ||
1294 | phba->fc_map_cnt++; | ||
1295 | phba->nport_event_cnt++; | 1229 | phba->nport_event_cnt++; |
1296 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; | 1230 | lpfc_unregister_remote_port(phba, ndlp); |
1297 | break; | ||
1298 | case NLP_NPR_LIST: | ||
1299 | nlp->nlp_flag |= list; | ||
1300 | /* Put it at the end of the npr list */ | ||
1301 | list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); | ||
1302 | phba->fc_npr_cnt++; | ||
1303 | |||
1304 | nlp->nlp_flag &= ~NLP_RCV_PLOGI; | ||
1305 | break; | ||
1306 | case NLP_JUST_DQ: | ||
1307 | break; | ||
1308 | } | 1231 | } |
1309 | 1232 | ||
1310 | spin_unlock_irq(phba->host->host_lock); | 1233 | if (new_state == NLP_STE_MAPPED_NODE || |
1311 | 1234 | new_state == NLP_STE_UNMAPPED_NODE) { | |
1312 | /* | 1235 | phba->nport_event_cnt++; |
1313 | * We make all the calls into the transport after we have | ||
1314 | * moved the node between lists. This so that we don't | ||
1315 | * release the lock while in-between lists. | ||
1316 | */ | ||
1317 | |||
1318 | /* Don't upcall midlayer if we're unloading */ | ||
1319 | if (!(phba->fc_flag & FC_UNLOADING)) { | ||
1320 | /* | ||
1321 | * We revalidate the rport pointer as the "add" function | ||
1322 | * may have removed the remote port. | ||
1323 | */ | ||
1324 | if ((rport_del != none) && nlp->rport) | ||
1325 | lpfc_unregister_remote_port(phba, nlp); | ||
1326 | |||
1327 | if (rport_add != none) { | ||
1328 | /* | 1236 | /* |
1329 | * Tell the fc transport about the port, if we haven't | 1237 | * Tell the fc transport about the port, if we haven't |
1330 | * already. If we have, and it's a scsi entity, be | 1238 | * already. If we have, and it's a scsi entity, be |
1331 | * sure to unblock any attached scsi devices | 1239 | * sure to unblock any attached scsi devices |
1332 | */ | 1240 | */ |
1333 | if ((!nlp->rport) || (nlp->rport->port_state == | 1241 | lpfc_register_remote_port(phba, ndlp); |
1334 | FC_PORTSTATE_BLOCKED)) | 1242 | } |
1335 | lpfc_register_remote_port(phba, nlp); | ||
1336 | 1243 | ||
1337 | /* | 1244 | /* |
1338 | * if we added to Mapped list, but the remote port | 1245 | * if we added to Mapped list, but the remote port |
@@ -1340,19 +1247,95 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1340 | * our presentable range - move the node to the | 1247 | * our presentable range - move the node to the |
1341 | * Unmapped List | 1248 | * Unmapped List |
1342 | */ | 1249 | */ |
1343 | if ((rport_add == mapped) && | 1250 | if (new_state == NLP_STE_MAPPED_NODE && |
1344 | ((!nlp->rport) || | 1251 | (!ndlp->rport || |
1345 | (nlp->rport->scsi_target_id == -1) || | 1252 | ndlp->rport->scsi_target_id == -1 || |
1346 | (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) { | 1253 | ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) { |
1347 | nlp->nlp_state = NLP_STE_UNMAPPED_NODE; | 1254 | spin_lock_irq(phba->host->host_lock); |
1348 | spin_lock_irq(phba->host->host_lock); | 1255 | ndlp->nlp_flag |= NLP_TGT_NO_SCSIID; |
1349 | nlp->nlp_flag |= NLP_TGT_NO_SCSIID; | 1256 | spin_unlock_irq(phba->host->host_lock); |
1350 | spin_unlock_irq(phba->host->host_lock); | 1257 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); |
1351 | lpfc_nlp_list(phba, nlp, NLP_UNMAPPED_LIST); | ||
1352 | } | ||
1353 | } | ||
1354 | } | 1258 | } |
1355 | return 0; | 1259 | } |
1260 | |||
1261 | static char * | ||
1262 | lpfc_nlp_state_name(char *buffer, size_t size, int state) | ||
1263 | { | ||
1264 | static char *states[] = { | ||
1265 | [NLP_STE_UNUSED_NODE] = "UNUSED", | ||
1266 | [NLP_STE_PLOGI_ISSUE] = "PLOGI", | ||
1267 | [NLP_STE_ADISC_ISSUE] = "ADISC", | ||
1268 | [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN", | ||
1269 | [NLP_STE_PRLI_ISSUE] = "PRLI", | ||
1270 | [NLP_STE_UNMAPPED_NODE] = "UNMAPPED", | ||
1271 | [NLP_STE_MAPPED_NODE] = "MAPPED", | ||
1272 | [NLP_STE_NPR_NODE] = "NPR", | ||
1273 | }; | ||
1274 | |||
1275 | if (state < ARRAY_SIZE(states) && states[state]) | ||
1276 | strlcpy(buffer, states[state], size); | ||
1277 | else | ||
1278 | snprintf(buffer, size, "unknown (%d)", state); | ||
1279 | return buffer; | ||
1280 | } | ||
1281 | |||
1282 | void | ||
1283 | lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) | ||
1284 | { | ||
1285 | int old_state = ndlp->nlp_state; | ||
1286 | char name1[16], name2[16]; | ||
1287 | |||
1288 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1289 | "%d:0904 NPort state transition x%06x, %s -> %s\n", | ||
1290 | phba->brd_no, | ||
1291 | ndlp->nlp_DID, | ||
1292 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), | ||
1293 | lpfc_nlp_state_name(name2, sizeof(name2), state)); | ||
1294 | if (old_state == NLP_STE_NPR_NODE && | ||
1295 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && | ||
1296 | state != NLP_STE_NPR_NODE) | ||
1297 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | ||
1298 | if (old_state == NLP_STE_UNMAPPED_NODE) { | ||
1299 | ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; | ||
1300 | ndlp->nlp_type &= ~NLP_FC_NODE; | ||
1301 | } | ||
1302 | |||
1303 | if (list_empty(&ndlp->nlp_listp)) { | ||
1304 | spin_lock_irq(phba->host->host_lock); | ||
1305 | list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes); | ||
1306 | spin_unlock_irq(phba->host->host_lock); | ||
1307 | } else if (old_state) | ||
1308 | lpfc_nlp_counters(phba, old_state, -1); | ||
1309 | |||
1310 | ndlp->nlp_state = state; | ||
1311 | lpfc_nlp_counters(phba, state, 1); | ||
1312 | lpfc_nlp_state_cleanup(phba, ndlp, old_state, state); | ||
1313 | } | ||
1314 | |||
1315 | void | ||
1316 | lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | ||
1317 | { | ||
1318 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | ||
1319 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | ||
1320 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | ||
1321 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); | ||
1322 | spin_lock_irq(phba->host->host_lock); | ||
1323 | list_del_init(&ndlp->nlp_listp); | ||
1324 | spin_unlock_irq(phba->host->host_lock); | ||
1325 | lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0); | ||
1326 | } | ||
1327 | |||
1328 | void | ||
1329 | lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | ||
1330 | { | ||
1331 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | ||
1332 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | ||
1333 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | ||
1334 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); | ||
1335 | spin_lock_irq(phba->host->host_lock); | ||
1336 | list_del_init(&ndlp->nlp_listp); | ||
1337 | spin_unlock_irq(phba->host->host_lock); | ||
1338 | lpfc_nlp_put(ndlp); | ||
1356 | } | 1339 | } |
1357 | 1340 | ||
1358 | /* | 1341 | /* |
@@ -1464,6 +1447,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, | |||
1464 | static int | 1447 | static int |
1465 | lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1448 | lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1466 | { | 1449 | { |
1450 | LIST_HEAD(completions); | ||
1467 | struct lpfc_sli *psli; | 1451 | struct lpfc_sli *psli; |
1468 | struct lpfc_sli_ring *pring; | 1452 | struct lpfc_sli_ring *pring; |
1469 | struct lpfc_iocbq *iocb, *next_iocb; | 1453 | struct lpfc_iocbq *iocb, *next_iocb; |
@@ -1492,29 +1476,29 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1492 | (phba, pring, iocb, ndlp))) { | 1476 | (phba, pring, iocb, ndlp))) { |
1493 | /* It matches, so deque and call compl | 1477 | /* It matches, so deque and call compl |
1494 | with an error */ | 1478 | with an error */ |
1495 | list_del(&iocb->list); | 1479 | list_move_tail(&iocb->list, |
1480 | &completions); | ||
1496 | pring->txq_cnt--; | 1481 | pring->txq_cnt--; |
1497 | if (iocb->iocb_cmpl) { | ||
1498 | icmd = &iocb->iocb; | ||
1499 | icmd->ulpStatus = | ||
1500 | IOSTAT_LOCAL_REJECT; | ||
1501 | icmd->un.ulpWord[4] = | ||
1502 | IOERR_SLI_ABORTED; | ||
1503 | spin_unlock_irq(phba->host-> | ||
1504 | host_lock); | ||
1505 | (iocb->iocb_cmpl) (phba, | ||
1506 | iocb, iocb); | ||
1507 | spin_lock_irq(phba->host-> | ||
1508 | host_lock); | ||
1509 | } else | ||
1510 | lpfc_sli_release_iocbq(phba, | ||
1511 | iocb); | ||
1512 | } | 1482 | } |
1513 | } | 1483 | } |
1514 | spin_unlock_irq(phba->host->host_lock); | 1484 | spin_unlock_irq(phba->host->host_lock); |
1515 | 1485 | ||
1516 | } | 1486 | } |
1517 | } | 1487 | } |
1488 | |||
1489 | while (!list_empty(&completions)) { | ||
1490 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
1491 | list_del(&iocb->list); | ||
1492 | |||
1493 | if (iocb->iocb_cmpl) { | ||
1494 | icmd = &iocb->iocb; | ||
1495 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
1496 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
1497 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
1498 | } else | ||
1499 | lpfc_sli_release_iocbq(phba, iocb); | ||
1500 | } | ||
1501 | |||
1518 | return 0; | 1502 | return 0; |
1519 | } | 1503 | } |
1520 | 1504 | ||
@@ -1554,7 +1538,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1554 | * so it can be freed. | 1538 | * so it can be freed. |
1555 | */ | 1539 | */ |
1556 | static int | 1540 | static int |
1557 | lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1541 | lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1558 | { | 1542 | { |
1559 | LPFC_MBOXQ_t *mb; | 1543 | LPFC_MBOXQ_t *mb; |
1560 | LPFC_MBOXQ_t *nextmb; | 1544 | LPFC_MBOXQ_t *nextmb; |
@@ -1567,17 +1551,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1567 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, | 1551 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, |
1568 | ndlp->nlp_state, ndlp->nlp_rpi); | 1552 | ndlp->nlp_state, ndlp->nlp_rpi); |
1569 | 1553 | ||
1570 | lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); | 1554 | lpfc_dequeue_node(phba, ndlp); |
1571 | |||
1572 | /* | ||
1573 | * if unloading the driver - just leave the remote port in place. | ||
1574 | * The driver unload will force the attached devices to detach | ||
1575 | * and flush cache's w/o generating flush errors. | ||
1576 | */ | ||
1577 | if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { | ||
1578 | lpfc_unregister_remote_port(phba, ndlp); | ||
1579 | ndlp->nlp_sid = NLP_NO_SID; | ||
1580 | } | ||
1581 | 1555 | ||
1582 | /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ | 1556 | /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ |
1583 | if ((mb = phba->sli.mbox_active)) { | 1557 | if ((mb = phba->sli.mbox_active)) { |
@@ -1599,11 +1573,12 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1599 | } | 1573 | } |
1600 | list_del(&mb->list); | 1574 | list_del(&mb->list); |
1601 | mempool_free(mb, phba->mbox_mem_pool); | 1575 | mempool_free(mb, phba->mbox_mem_pool); |
1576 | lpfc_nlp_put(ndlp); | ||
1602 | } | 1577 | } |
1603 | } | 1578 | } |
1604 | spin_unlock_irq(phba->host->host_lock); | 1579 | spin_unlock_irq(phba->host->host_lock); |
1605 | 1580 | ||
1606 | lpfc_els_abort(phba,ndlp,0); | 1581 | lpfc_els_abort(phba,ndlp); |
1607 | spin_lock_irq(phba->host->host_lock); | 1582 | spin_lock_irq(phba->host->host_lock); |
1608 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | 1583 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; |
1609 | spin_unlock_irq(phba->host->host_lock); | 1584 | spin_unlock_irq(phba->host->host_lock); |
@@ -1624,27 +1599,27 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1624 | * If we are in the middle of using the nlp in the discovery state | 1599 | * If we are in the middle of using the nlp in the discovery state |
1625 | * machine, defer the free till we reach the end of the state machine. | 1600 | * machine, defer the free till we reach the end of the state machine. |
1626 | */ | 1601 | */ |
1627 | int | 1602 | static void |
1628 | lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1603 | lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
1629 | { | 1604 | { |
1605 | struct lpfc_rport_data *rdata; | ||
1630 | 1606 | ||
1631 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 1607 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { |
1632 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1608 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
1633 | } | 1609 | } |
1634 | 1610 | ||
1635 | if (ndlp->nlp_disc_refcnt) { | 1611 | lpfc_cleanup_node(phba, ndlp); |
1636 | spin_lock_irq(phba->host->host_lock); | 1612 | |
1637 | ndlp->nlp_flag |= NLP_DELAY_REMOVE; | 1613 | if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { |
1638 | spin_unlock_irq(phba->host->host_lock); | 1614 | put_device(&ndlp->rport->dev); |
1639 | } else { | 1615 | rdata = ndlp->rport->dd_data; |
1640 | lpfc_freenode(phba, ndlp); | 1616 | rdata->pnode = NULL; |
1641 | mempool_free( ndlp, phba->nlp_mem_pool); | 1617 | ndlp->rport = NULL; |
1642 | } | 1618 | } |
1643 | return 0; | ||
1644 | } | 1619 | } |
1645 | 1620 | ||
1646 | static int | 1621 | static int |
1647 | lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | 1622 | lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) |
1648 | { | 1623 | { |
1649 | D_ID mydid; | 1624 | D_ID mydid; |
1650 | D_ID ndlpdid; | 1625 | D_ID ndlpdid; |
@@ -1693,57 +1668,36 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | |||
1693 | return 0; | 1668 | return 0; |
1694 | } | 1669 | } |
1695 | 1670 | ||
1696 | /* Search for a nodelist entry on a specific list */ | 1671 | /* Search for a nodelist entry */ |
1697 | struct lpfc_nodelist * | 1672 | struct lpfc_nodelist * |
1698 | lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) | 1673 | lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did) |
1699 | { | 1674 | { |
1700 | struct lpfc_nodelist *ndlp; | 1675 | struct lpfc_nodelist *ndlp; |
1701 | struct list_head *lists[]={&phba->fc_nlpunmap_list, | ||
1702 | &phba->fc_nlpmap_list, | ||
1703 | &phba->fc_plogi_list, | ||
1704 | &phba->fc_adisc_list, | ||
1705 | &phba->fc_reglogin_list, | ||
1706 | &phba->fc_prli_list, | ||
1707 | &phba->fc_npr_list, | ||
1708 | &phba->fc_unused_list}; | ||
1709 | uint32_t search[]={NLP_SEARCH_UNMAPPED, | ||
1710 | NLP_SEARCH_MAPPED, | ||
1711 | NLP_SEARCH_PLOGI, | ||
1712 | NLP_SEARCH_ADISC, | ||
1713 | NLP_SEARCH_REGLOGIN, | ||
1714 | NLP_SEARCH_PRLI, | ||
1715 | NLP_SEARCH_NPR, | ||
1716 | NLP_SEARCH_UNUSED}; | ||
1717 | int i; | ||
1718 | uint32_t data1; | 1676 | uint32_t data1; |
1719 | 1677 | ||
1720 | spin_lock_irq(phba->host->host_lock); | 1678 | spin_lock_irq(phba->host->host_lock); |
1721 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) { | 1679 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
1722 | if (!(order & search[i])) | 1680 | if (lpfc_matchdid(phba, ndlp, did)) { |
1723 | continue; | 1681 | data1 = (((uint32_t) ndlp->nlp_state << 24) | |
1724 | list_for_each_entry(ndlp, lists[i], nlp_listp) { | 1682 | ((uint32_t) ndlp->nlp_xri << 16) | |
1725 | if (lpfc_matchdid(phba, ndlp, did)) { | 1683 | ((uint32_t) ndlp->nlp_type << 8) | |
1726 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | 1684 | ((uint32_t) ndlp->nlp_rpi & 0xff)); |
1727 | ((uint32_t) ndlp->nlp_xri << 16) | | 1685 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1728 | ((uint32_t) ndlp->nlp_type << 8) | | 1686 | "%d:0929 FIND node DID " |
1729 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | 1687 | " Data: x%p x%x x%x x%x\n", |
1730 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | 1688 | phba->brd_no, |
1731 | "%d:0929 FIND node DID " | 1689 | ndlp, ndlp->nlp_DID, |
1732 | " Data: x%p x%x x%x x%x\n", | 1690 | ndlp->nlp_flag, data1); |
1733 | phba->brd_no, | 1691 | spin_unlock_irq(phba->host->host_lock); |
1734 | ndlp, ndlp->nlp_DID, | 1692 | return ndlp; |
1735 | ndlp->nlp_flag, data1); | ||
1736 | spin_unlock_irq(phba->host->host_lock); | ||
1737 | return ndlp; | ||
1738 | } | ||
1739 | } | 1693 | } |
1740 | } | 1694 | } |
1741 | spin_unlock_irq(phba->host->host_lock); | 1695 | spin_unlock_irq(phba->host->host_lock); |
1742 | 1696 | ||
1743 | /* FIND node did <did> NOT FOUND */ | 1697 | /* FIND node did <did> NOT FOUND */ |
1744 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | 1698 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1745 | "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", | 1699 | "%d:0932 FIND node did x%x NOT FOUND.\n", |
1746 | phba->brd_no, did, order); | 1700 | phba->brd_no, did); |
1747 | return NULL; | 1701 | return NULL; |
1748 | } | 1702 | } |
1749 | 1703 | ||
@@ -1751,9 +1705,8 @@ struct lpfc_nodelist * | |||
1751 | lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | 1705 | lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) |
1752 | { | 1706 | { |
1753 | struct lpfc_nodelist *ndlp; | 1707 | struct lpfc_nodelist *ndlp; |
1754 | uint32_t flg; | ||
1755 | 1708 | ||
1756 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); | 1709 | ndlp = lpfc_findnode_did(phba, did); |
1757 | if (!ndlp) { | 1710 | if (!ndlp) { |
1758 | if ((phba->fc_flag & FC_RSCN_MODE) && | 1711 | if ((phba->fc_flag & FC_RSCN_MODE) && |
1759 | ((lpfc_rscn_payload_check(phba, did) == 0))) | 1712 | ((lpfc_rscn_payload_check(phba, did) == 0))) |
@@ -1763,8 +1716,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | |||
1763 | if (!ndlp) | 1716 | if (!ndlp) |
1764 | return NULL; | 1717 | return NULL; |
1765 | lpfc_nlp_init(phba, ndlp, did); | 1718 | lpfc_nlp_init(phba, ndlp, did); |
1766 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1719 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); |
1767 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | ||
1768 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1720 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
1769 | return ndlp; | 1721 | return ndlp; |
1770 | } | 1722 | } |
@@ -1780,11 +1732,10 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | |||
1780 | } else | 1732 | } else |
1781 | ndlp = NULL; | 1733 | ndlp = NULL; |
1782 | } else { | 1734 | } else { |
1783 | flg = ndlp->nlp_flag & NLP_LIST_MASK; | 1735 | if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || |
1784 | if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) | 1736 | ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) |
1785 | return NULL; | 1737 | return NULL; |
1786 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1738 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); |
1787 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | ||
1788 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1739 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
1789 | } | 1740 | } |
1790 | return ndlp; | 1741 | return ndlp; |
@@ -1842,8 +1793,9 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1842 | struct lpfc_sli *psli; | 1793 | struct lpfc_sli *psli; |
1843 | LPFC_MBOXQ_t *mbox; | 1794 | LPFC_MBOXQ_t *mbox; |
1844 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1795 | struct lpfc_nodelist *ndlp, *next_ndlp; |
1845 | uint32_t did_changed, num_sent; | 1796 | uint32_t num_sent; |
1846 | uint32_t clear_la_pending; | 1797 | uint32_t clear_la_pending; |
1798 | int did_changed; | ||
1847 | int rc; | 1799 | int rc; |
1848 | 1800 | ||
1849 | psli = &phba->sli; | 1801 | psli = &phba->sli; |
@@ -1877,14 +1829,13 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1877 | phba->fc_plogi_cnt, phba->fc_adisc_cnt); | 1829 | phba->fc_plogi_cnt, phba->fc_adisc_cnt); |
1878 | 1830 | ||
1879 | /* If our did changed, we MUST do PLOGI */ | 1831 | /* If our did changed, we MUST do PLOGI */ |
1880 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 1832 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
1881 | nlp_listp) { | 1833 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
1882 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1834 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
1883 | if (did_changed) { | 1835 | did_changed) { |
1884 | spin_lock_irq(phba->host->host_lock); | 1836 | spin_lock_irq(phba->host->host_lock); |
1885 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1837 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1886 | spin_unlock_irq(phba->host->host_lock); | 1838 | spin_unlock_irq(phba->host->host_lock); |
1887 | } | ||
1888 | } | 1839 | } |
1889 | } | 1840 | } |
1890 | 1841 | ||
@@ -1944,11 +1895,11 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1944 | static void | 1895 | static void |
1945 | lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1896 | lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1946 | { | 1897 | { |
1898 | LIST_HEAD(completions); | ||
1947 | struct lpfc_sli *psli; | 1899 | struct lpfc_sli *psli; |
1948 | IOCB_t *icmd; | 1900 | IOCB_t *icmd; |
1949 | struct lpfc_iocbq *iocb, *next_iocb; | 1901 | struct lpfc_iocbq *iocb, *next_iocb; |
1950 | struct lpfc_sli_ring *pring; | 1902 | struct lpfc_sli_ring *pring; |
1951 | struct lpfc_dmabuf *mp; | ||
1952 | 1903 | ||
1953 | psli = &phba->sli; | 1904 | psli = &phba->sli; |
1954 | pring = &psli->ring[LPFC_ELS_RING]; | 1905 | pring = &psli->ring[LPFC_ELS_RING]; |
@@ -1956,6 +1907,7 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1956 | /* Error matching iocb on txq or txcmplq | 1907 | /* Error matching iocb on txq or txcmplq |
1957 | * First check the txq. | 1908 | * First check the txq. |
1958 | */ | 1909 | */ |
1910 | spin_lock_irq(phba->host->host_lock); | ||
1959 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 1911 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
1960 | if (iocb->context1 != ndlp) { | 1912 | if (iocb->context1 != ndlp) { |
1961 | continue; | 1913 | continue; |
@@ -1964,9 +1916,8 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1964 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || | 1916 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || |
1965 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { | 1917 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { |
1966 | 1918 | ||
1967 | list_del(&iocb->list); | 1919 | list_move_tail(&iocb->list, &completions); |
1968 | pring->txq_cnt--; | 1920 | pring->txq_cnt--; |
1969 | lpfc_els_free_iocb(phba, iocb); | ||
1970 | } | 1921 | } |
1971 | } | 1922 | } |
1972 | 1923 | ||
@@ -1978,43 +1929,22 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1978 | icmd = &iocb->iocb; | 1929 | icmd = &iocb->iocb; |
1979 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || | 1930 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || |
1980 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { | 1931 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { |
1932 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | ||
1933 | } | ||
1934 | } | ||
1935 | spin_unlock_irq(phba->host->host_lock); | ||
1981 | 1936 | ||
1982 | iocb->iocb_cmpl = NULL; | 1937 | while (!list_empty(&completions)) { |
1983 | /* context2 = cmd, context2->next = rsp, context3 = | 1938 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
1984 | bpl */ | 1939 | list_del(&iocb->list); |
1985 | if (iocb->context2) { | ||
1986 | /* Free the response IOCB before handling the | ||
1987 | command. */ | ||
1988 | |||
1989 | mp = (struct lpfc_dmabuf *) (iocb->context2); | ||
1990 | mp = list_get_first(&mp->list, | ||
1991 | struct lpfc_dmabuf, | ||
1992 | list); | ||
1993 | if (mp) { | ||
1994 | /* Delay before releasing rsp buffer to | ||
1995 | * give UNREG mbox a chance to take | ||
1996 | * effect. | ||
1997 | */ | ||
1998 | list_add(&mp->list, | ||
1999 | &phba->freebufList); | ||
2000 | } | ||
2001 | lpfc_mbuf_free(phba, | ||
2002 | ((struct lpfc_dmabuf *) | ||
2003 | iocb->context2)->virt, | ||
2004 | ((struct lpfc_dmabuf *) | ||
2005 | iocb->context2)->phys); | ||
2006 | kfree(iocb->context2); | ||
2007 | } | ||
2008 | 1940 | ||
2009 | if (iocb->context3) { | 1941 | if (iocb->iocb_cmpl) { |
2010 | lpfc_mbuf_free(phba, | 1942 | icmd = &iocb->iocb; |
2011 | ((struct lpfc_dmabuf *) | 1943 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
2012 | iocb->context3)->virt, | 1944 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
2013 | ((struct lpfc_dmabuf *) | 1945 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
2014 | iocb->context3)->phys); | 1946 | } else |
2015 | kfree(iocb->context3); | 1947 | lpfc_sli_release_iocbq(phba, iocb); |
2016 | } | ||
2017 | } | ||
2018 | } | 1948 | } |
2019 | 1949 | ||
2020 | return; | 1950 | return; |
@@ -2025,21 +1955,16 @@ lpfc_disc_flush_list(struct lpfc_hba * phba) | |||
2025 | { | 1955 | { |
2026 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1956 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2027 | 1957 | ||
2028 | if (phba->fc_plogi_cnt) { | 1958 | if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) { |
2029 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, | 1959 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
2030 | nlp_listp) { | 1960 | nlp_listp) { |
2031 | lpfc_free_tx(phba, ndlp); | 1961 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
2032 | lpfc_nlp_remove(phba, ndlp); | 1962 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { |
2033 | } | 1963 | lpfc_free_tx(phba, ndlp); |
2034 | } | 1964 | lpfc_nlp_put(ndlp); |
2035 | if (phba->fc_adisc_cnt) { | 1965 | } |
2036 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | ||
2037 | nlp_listp) { | ||
2038 | lpfc_free_tx(phba, ndlp); | ||
2039 | lpfc_nlp_remove(phba, ndlp); | ||
2040 | } | 1966 | } |
2041 | } | 1967 | } |
2042 | return; | ||
2043 | } | 1968 | } |
2044 | 1969 | ||
2045 | /*****************************************************************************/ | 1970 | /*****************************************************************************/ |
@@ -2108,11 +2033,13 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2108 | phba->brd_no); | 2033 | phba->brd_no); |
2109 | 2034 | ||
2110 | /* Start discovery by sending FLOGI, clean up old rpis */ | 2035 | /* Start discovery by sending FLOGI, clean up old rpis */ |
2111 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 2036 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
2112 | nlp_listp) { | 2037 | nlp_listp) { |
2038 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | ||
2039 | continue; | ||
2113 | if (ndlp->nlp_type & NLP_FABRIC) { | 2040 | if (ndlp->nlp_type & NLP_FABRIC) { |
2114 | /* Clean up the ndlp on Fabric connections */ | 2041 | /* Clean up the ndlp on Fabric connections */ |
2115 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 2042 | lpfc_drop_node(phba, ndlp); |
2116 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 2043 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
2117 | /* Fail outstanding IO now since device | 2044 | /* Fail outstanding IO now since device |
2118 | * is marked for PLOGI. | 2045 | * is marked for PLOGI. |
@@ -2153,9 +2080,9 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2153 | "login\n", phba->brd_no); | 2080 | "login\n", phba->brd_no); |
2154 | 2081 | ||
2155 | /* Next look for NameServer ndlp */ | 2082 | /* Next look for NameServer ndlp */ |
2156 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); | 2083 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2157 | if (ndlp) | 2084 | if (ndlp) |
2158 | lpfc_nlp_remove(phba, ndlp); | 2085 | lpfc_nlp_put(ndlp); |
2159 | /* Start discovery */ | 2086 | /* Start discovery */ |
2160 | lpfc_disc_start(phba); | 2087 | lpfc_disc_start(phba); |
2161 | break; | 2088 | break; |
@@ -2168,9 +2095,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2168 | phba->brd_no, | 2095 | phba->brd_no, |
2169 | phba->fc_ns_retry, LPFC_MAX_NS_RETRY); | 2096 | phba->fc_ns_retry, LPFC_MAX_NS_RETRY); |
2170 | 2097 | ||
2171 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, | 2098 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2172 | NameServer_DID); | 2099 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
2173 | if (ndlp) { | ||
2174 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 2100 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
2175 | /* Try it one more time */ | 2101 | /* Try it one more time */ |
2176 | rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); | 2102 | rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); |
@@ -2220,6 +2146,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2220 | initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0; | 2146 | initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0; |
2221 | rc = lpfc_sli_issue_mbox(phba, initlinkmbox, | 2147 | rc = lpfc_sli_issue_mbox(phba, initlinkmbox, |
2222 | (MBX_NOWAIT | MBX_STOP_IOCB)); | 2148 | (MBX_NOWAIT | MBX_STOP_IOCB)); |
2149 | lpfc_set_loopback_flag(phba); | ||
2223 | if (rc == MBX_NOT_FINISHED) | 2150 | if (rc == MBX_NOT_FINISHED) |
2224 | mempool_free(initlinkmbox, phba->mbox_mem_pool); | 2151 | mempool_free(initlinkmbox, phba->mbox_mem_pool); |
2225 | 2152 | ||
@@ -2317,8 +2244,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
2317 | 2244 | ||
2318 | ndlp->nlp_rpi = mb->un.varWords[0]; | 2245 | ndlp->nlp_rpi = mb->un.varWords[0]; |
2319 | ndlp->nlp_type |= NLP_FABRIC; | 2246 | ndlp->nlp_type |= NLP_FABRIC; |
2320 | ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; | 2247 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); |
2321 | lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); | ||
2322 | 2248 | ||
2323 | /* Start issuing Fabric-Device Management Interface (FDMI) | 2249 | /* Start issuing Fabric-Device Management Interface (FDMI) |
2324 | * command to 0xfffffa (FDMI well known port) | 2250 | * command to 0xfffffa (FDMI well known port) |
@@ -2333,87 +2259,100 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
2333 | mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); | 2259 | mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); |
2334 | } | 2260 | } |
2335 | 2261 | ||
2262 | /* Mailbox took a reference to the node */ | ||
2263 | lpfc_nlp_put(ndlp); | ||
2336 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2264 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
2337 | kfree(mp); | 2265 | kfree(mp); |
2338 | mempool_free( pmb, phba->mbox_mem_pool); | 2266 | mempool_free(pmb, phba->mbox_mem_pool); |
2339 | 2267 | ||
2340 | return; | 2268 | return; |
2341 | } | 2269 | } |
2342 | 2270 | ||
2271 | static int | ||
2272 | lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param) | ||
2273 | { | ||
2274 | uint16_t *rpi = param; | ||
2275 | |||
2276 | return ndlp->nlp_rpi == *rpi; | ||
2277 | } | ||
2278 | |||
2279 | static int | ||
2280 | lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param) | ||
2281 | { | ||
2282 | return memcmp(&ndlp->nlp_portname, param, | ||
2283 | sizeof(ndlp->nlp_portname)) == 0; | ||
2284 | } | ||
2285 | |||
2286 | /* | ||
2287 | * Search node lists for a remote port matching filter criteria | ||
2288 | * Caller needs to hold host_lock before calling this routine. | ||
2289 | */ | ||
2290 | struct lpfc_nodelist * | ||
2291 | __lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) | ||
2292 | { | ||
2293 | struct lpfc_nodelist *ndlp; | ||
2294 | |||
2295 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { | ||
2296 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE && | ||
2297 | filter(ndlp, param)) | ||
2298 | return ndlp; | ||
2299 | } | ||
2300 | return NULL; | ||
2301 | } | ||
2302 | |||
2343 | /* | 2303 | /* |
2344 | * This routine looks up the ndlp lists | 2304 | * Search node lists for a remote port matching filter criteria |
2345 | * for the given RPI. If rpi found | 2305 | * This routine is used when the caller does NOT have host_lock. |
2346 | * it return the node list pointer | ||
2347 | * else return NULL. | ||
2348 | */ | 2306 | */ |
2349 | struct lpfc_nodelist * | 2307 | struct lpfc_nodelist * |
2308 | lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) | ||
2309 | { | ||
2310 | struct lpfc_nodelist *ndlp; | ||
2311 | |||
2312 | spin_lock_irq(phba->host->host_lock); | ||
2313 | ndlp = __lpfc_find_node(phba, filter, param); | ||
2314 | spin_unlock_irq(phba->host->host_lock); | ||
2315 | return ndlp; | ||
2316 | } | ||
2317 | |||
2318 | /* | ||
2319 | * This routine looks up the ndlp lists for the given RPI. If rpi found it | ||
2320 | * returns the node list pointer else return NULL. | ||
2321 | */ | ||
2322 | struct lpfc_nodelist * | ||
2323 | __lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi) | ||
2324 | { | ||
2325 | return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi); | ||
2326 | } | ||
2327 | |||
2328 | struct lpfc_nodelist * | ||
2350 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | 2329 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) |
2351 | { | 2330 | { |
2352 | struct lpfc_nodelist *ndlp; | 2331 | struct lpfc_nodelist *ndlp; |
2353 | struct list_head * lists[]={&phba->fc_nlpunmap_list, | ||
2354 | &phba->fc_nlpmap_list, | ||
2355 | &phba->fc_plogi_list, | ||
2356 | &phba->fc_adisc_list, | ||
2357 | &phba->fc_reglogin_list}; | ||
2358 | int i; | ||
2359 | 2332 | ||
2360 | spin_lock_irq(phba->host->host_lock); | 2333 | spin_lock_irq(phba->host->host_lock); |
2361 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) | 2334 | ndlp = __lpfc_findnode_rpi(phba, rpi); |
2362 | list_for_each_entry(ndlp, lists[i], nlp_listp) | ||
2363 | if (ndlp->nlp_rpi == rpi) { | ||
2364 | spin_unlock_irq(phba->host->host_lock); | ||
2365 | return ndlp; | ||
2366 | } | ||
2367 | spin_unlock_irq(phba->host->host_lock); | 2335 | spin_unlock_irq(phba->host->host_lock); |
2368 | return NULL; | 2336 | return ndlp; |
2369 | } | 2337 | } |
2370 | 2338 | ||
2371 | /* | 2339 | /* |
2372 | * This routine looks up the ndlp lists | 2340 | * This routine looks up the ndlp lists for the given WWPN. If WWPN found it |
2373 | * for the given WWPN. If WWPN found | 2341 | * returns the node list pointer else return NULL. |
2374 | * it return the node list pointer | ||
2375 | * else return NULL. | ||
2376 | */ | 2342 | */ |
2377 | struct lpfc_nodelist * | 2343 | struct lpfc_nodelist * |
2378 | lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, | 2344 | lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn) |
2379 | struct lpfc_name * wwpn) | ||
2380 | { | 2345 | { |
2381 | struct lpfc_nodelist *ndlp; | 2346 | struct lpfc_nodelist *ndlp; |
2382 | struct list_head * lists[]={&phba->fc_nlpunmap_list, | ||
2383 | &phba->fc_nlpmap_list, | ||
2384 | &phba->fc_npr_list, | ||
2385 | &phba->fc_plogi_list, | ||
2386 | &phba->fc_adisc_list, | ||
2387 | &phba->fc_reglogin_list, | ||
2388 | &phba->fc_prli_list}; | ||
2389 | uint32_t search[]={NLP_SEARCH_UNMAPPED, | ||
2390 | NLP_SEARCH_MAPPED, | ||
2391 | NLP_SEARCH_NPR, | ||
2392 | NLP_SEARCH_PLOGI, | ||
2393 | NLP_SEARCH_ADISC, | ||
2394 | NLP_SEARCH_REGLOGIN, | ||
2395 | NLP_SEARCH_PRLI}; | ||
2396 | int i; | ||
2397 | 2347 | ||
2398 | spin_lock_irq(phba->host->host_lock); | 2348 | spin_lock_irq(phba->host->host_lock); |
2399 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) { | 2349 | ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn); |
2400 | if (!(order & search[i])) | ||
2401 | continue; | ||
2402 | list_for_each_entry(ndlp, lists[i], nlp_listp) { | ||
2403 | if (memcmp(&ndlp->nlp_portname, wwpn, | ||
2404 | sizeof(struct lpfc_name)) == 0) { | ||
2405 | spin_unlock_irq(phba->host->host_lock); | ||
2406 | return ndlp; | ||
2407 | } | ||
2408 | } | ||
2409 | } | ||
2410 | spin_unlock_irq(phba->host->host_lock); | 2350 | spin_unlock_irq(phba->host->host_lock); |
2411 | return NULL; | 2351 | return NULL; |
2412 | } | 2352 | } |
2413 | 2353 | ||
2414 | void | 2354 | void |
2415 | lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 2355 | lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) |
2416 | uint32_t did) | ||
2417 | { | 2356 | { |
2418 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); | 2357 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); |
2419 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); | 2358 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); |
@@ -2423,5 +2362,30 @@ lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
2423 | ndlp->nlp_DID = did; | 2362 | ndlp->nlp_DID = did; |
2424 | ndlp->nlp_phba = phba; | 2363 | ndlp->nlp_phba = phba; |
2425 | ndlp->nlp_sid = NLP_NO_SID; | 2364 | ndlp->nlp_sid = NLP_NO_SID; |
2365 | INIT_LIST_HEAD(&ndlp->nlp_listp); | ||
2366 | kref_init(&ndlp->kref); | ||
2426 | return; | 2367 | return; |
2427 | } | 2368 | } |
2369 | |||
2370 | void | ||
2371 | lpfc_nlp_release(struct kref *kref) | ||
2372 | { | ||
2373 | struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, | ||
2374 | kref); | ||
2375 | lpfc_nlp_remove(ndlp->nlp_phba, ndlp); | ||
2376 | mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool); | ||
2377 | } | ||
2378 | |||
2379 | struct lpfc_nodelist * | ||
2380 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) | ||
2381 | { | ||
2382 | if (ndlp) | ||
2383 | kref_get(&ndlp->kref); | ||
2384 | return ndlp; | ||
2385 | } | ||
2386 | |||
2387 | int | ||
2388 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) | ||
2389 | { | ||
2390 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; | ||
2391 | } | ||