diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-02-08 18:49:26 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-11 18:52:57 -0500 |
commit | e47c9093531d3406a8ae38acca4ce207ef70cc0e (patch) | |
tree | cb115ec0b7981a100ef39ecfc68a36aa7e3e0f2e /drivers/scsi/lpfc/lpfc_els.c | |
parent | 4660c8ed5aaed99d82785499f034a8cc9199866d (diff) |
[SCSI] lpfc 8.2.5 : Correct ndlp referencing issues
Correct ndlp referencing issues:
- Fix ndlp kref issues due to race conditions between threads
- Fix cancel els delay retry event which missed an ndlp reference count
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 237 |
1 files changed, 169 insertions, 68 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c6b739dc6bc3..39268e6a1a05 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.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-2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2008 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 * |
@@ -113,6 +113,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
113 | 113 | ||
114 | if (elsiocb == NULL) | 114 | if (elsiocb == NULL) |
115 | return NULL; | 115 | return NULL; |
116 | |||
116 | icmd = &elsiocb->iocb; | 117 | icmd = &elsiocb->iocb; |
117 | 118 | ||
118 | /* fill in BDEs for command */ | 119 | /* fill in BDEs for command */ |
@@ -134,9 +135,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
134 | if (!prsp || !prsp->virt) | 135 | if (!prsp || !prsp->virt) |
135 | goto els_iocb_free_prsp_exit; | 136 | goto els_iocb_free_prsp_exit; |
136 | INIT_LIST_HEAD(&prsp->list); | 137 | INIT_LIST_HEAD(&prsp->list); |
137 | } else { | 138 | } else |
138 | prsp = NULL; | 139 | prsp = NULL; |
139 | } | ||
140 | 140 | ||
141 | /* Allocate buffer for Buffer ptr list */ | 141 | /* Allocate buffer for Buffer ptr list */ |
142 | pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 142 | pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
@@ -246,7 +246,7 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | |||
246 | 246 | ||
247 | sp = &phba->fc_fabparam; | 247 | sp = &phba->fc_fabparam; |
248 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 248 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
249 | if (!ndlp) { | 249 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
250 | err = 1; | 250 | err = 1; |
251 | goto fail; | 251 | goto fail; |
252 | } | 252 | } |
@@ -282,6 +282,9 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | |||
282 | 282 | ||
283 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; | 283 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; |
284 | mbox->vport = vport; | 284 | mbox->vport = vport; |
285 | /* increment the reference count on ndlp to hold reference | ||
286 | * for the callback routine. | ||
287 | */ | ||
285 | mbox->context2 = lpfc_nlp_get(ndlp); | 288 | mbox->context2 = lpfc_nlp_get(ndlp); |
286 | 289 | ||
287 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 290 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
@@ -293,6 +296,9 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | |||
293 | return 0; | 296 | return 0; |
294 | 297 | ||
295 | fail_issue_reg_login: | 298 | fail_issue_reg_login: |
299 | /* decrement the reference count on ndlp just incremented | ||
300 | * for the failed mbox command. | ||
301 | */ | ||
296 | lpfc_nlp_put(ndlp); | 302 | lpfc_nlp_put(ndlp); |
297 | mp = (struct lpfc_dmabuf *) mbox->context1; | 303 | mp = (struct lpfc_dmabuf *) mbox->context1; |
298 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 304 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
@@ -381,6 +387,8 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
381 | */ | 387 | */ |
382 | list_for_each_entry_safe(np, next_np, | 388 | list_for_each_entry_safe(np, next_np, |
383 | &vport->fc_nodes, nlp_listp) { | 389 | &vport->fc_nodes, nlp_listp) { |
390 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
391 | continue; | ||
384 | if ((np->nlp_state != NLP_STE_NPR_NODE) || | 392 | if ((np->nlp_state != NLP_STE_NPR_NODE) || |
385 | !(np->nlp_flag & NLP_NPR_ADISC)) | 393 | !(np->nlp_flag & NLP_NPR_ADISC)) |
386 | continue; | 394 | continue; |
@@ -456,6 +464,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
456 | mempool_free(mbox, phba->mbox_mem_pool); | 464 | mempool_free(mbox, phba->mbox_mem_pool); |
457 | goto fail; | 465 | goto fail; |
458 | } | 466 | } |
467 | /* Decrement ndlp reference count indicating that ndlp can be | ||
468 | * safely released when other references to it are done. | ||
469 | */ | ||
459 | lpfc_nlp_put(ndlp); | 470 | lpfc_nlp_put(ndlp); |
460 | 471 | ||
461 | ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID); | 472 | ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID); |
@@ -467,22 +478,29 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
467 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 478 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
468 | if (!ndlp) | 479 | if (!ndlp) |
469 | goto fail; | 480 | goto fail; |
470 | |||
471 | lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID); | 481 | lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID); |
482 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
483 | ndlp = lpfc_enable_node(vport, ndlp, | ||
484 | NLP_STE_UNUSED_NODE); | ||
485 | if(!ndlp) | ||
486 | goto fail; | ||
472 | } | 487 | } |
473 | 488 | ||
474 | memcpy(&ndlp->nlp_portname, &sp->portName, | 489 | memcpy(&ndlp->nlp_portname, &sp->portName, |
475 | sizeof(struct lpfc_name)); | 490 | sizeof(struct lpfc_name)); |
476 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, | 491 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, |
477 | sizeof(struct lpfc_name)); | 492 | sizeof(struct lpfc_name)); |
493 | /* Set state will put ndlp onto node list if not already done */ | ||
478 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 494 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
479 | spin_lock_irq(shost->host_lock); | 495 | spin_lock_irq(shost->host_lock); |
480 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 496 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
481 | spin_unlock_irq(shost->host_lock); | 497 | spin_unlock_irq(shost->host_lock); |
482 | } else { | 498 | } else |
483 | /* This side will wait for the PLOGI */ | 499 | /* This side will wait for the PLOGI, decrement ndlp reference |
500 | * count indicating that ndlp can be released when other | ||
501 | * references to it are done. | ||
502 | */ | ||
484 | lpfc_nlp_put(ndlp); | 503 | lpfc_nlp_put(ndlp); |
485 | } | ||
486 | 504 | ||
487 | /* If we are pt2pt with another NPort, force NPIV off! */ | 505 | /* If we are pt2pt with another NPort, force NPIV off! */ |
488 | phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; | 506 | phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; |
@@ -728,16 +746,21 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
728 | if (!ndlp) | 746 | if (!ndlp) |
729 | return 0; | 747 | return 0; |
730 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | 748 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
731 | } else { | 749 | /* Put ndlp onto node list */ |
732 | lpfc_dequeue_node(vport, ndlp); | 750 | lpfc_enqueue_node(vport, ndlp); |
751 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
752 | /* re-setup ndlp without removing from node list */ | ||
753 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
754 | if (!ndlp) | ||
755 | return 0; | ||
733 | } | 756 | } |
734 | 757 | ||
735 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { | 758 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) |
736 | /* This decrement of reference count to node shall kick off | 759 | /* This decrement of reference count to node shall kick off |
737 | * the release of the node. | 760 | * the release of the node. |
738 | */ | 761 | */ |
739 | lpfc_nlp_put(ndlp); | 762 | lpfc_nlp_put(ndlp); |
740 | } | 763 | |
741 | return 1; | 764 | return 1; |
742 | } | 765 | } |
743 | 766 | ||
@@ -755,9 +778,15 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) | |||
755 | if (!ndlp) | 778 | if (!ndlp) |
756 | return 0; | 779 | return 0; |
757 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | 780 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
758 | } else { | 781 | /* Put ndlp onto node list */ |
759 | lpfc_dequeue_node(vport, ndlp); | 782 | lpfc_enqueue_node(vport, ndlp); |
783 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
784 | /* re-setup ndlp without removing from node list */ | ||
785 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
786 | if (!ndlp) | ||
787 | return 0; | ||
760 | } | 788 | } |
789 | |||
761 | if (lpfc_issue_els_fdisc(vport, ndlp, 0)) { | 790 | if (lpfc_issue_els_fdisc(vport, ndlp, 0)) { |
762 | /* decrement node reference count to trigger the release of | 791 | /* decrement node reference count to trigger the release of |
763 | * the node. | 792 | * the node. |
@@ -816,7 +845,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
816 | */ | 845 | */ |
817 | new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName); | 846 | new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName); |
818 | 847 | ||
819 | if (new_ndlp == ndlp) | 848 | if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) |
820 | return ndlp; | 849 | return ndlp; |
821 | 850 | ||
822 | if (!new_ndlp) { | 851 | if (!new_ndlp) { |
@@ -827,8 +856,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
827 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); | 856 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); |
828 | if (!new_ndlp) | 857 | if (!new_ndlp) |
829 | return ndlp; | 858 | return ndlp; |
830 | |||
831 | lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); | 859 | lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); |
860 | } else if (!NLP_CHK_NODE_ACT(new_ndlp)) { | ||
861 | new_ndlp = lpfc_enable_node(vport, new_ndlp, | ||
862 | NLP_STE_UNUSED_NODE); | ||
863 | if (!new_ndlp) | ||
864 | return ndlp; | ||
832 | } | 865 | } |
833 | 866 | ||
834 | lpfc_unreg_rpi(vport, new_ndlp); | 867 | lpfc_unreg_rpi(vport, new_ndlp); |
@@ -839,6 +872,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
839 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 872 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
840 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | 873 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; |
841 | 874 | ||
875 | /* Set state will put new_ndlp on to node list if not already done */ | ||
842 | lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); | 876 | lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); |
843 | 877 | ||
844 | /* Move this back to NPR state */ | 878 | /* Move this back to NPR state */ |
@@ -912,7 +946,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
912 | irsp->un.elsreq64.remoteID); | 946 | irsp->un.elsreq64.remoteID); |
913 | 947 | ||
914 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); | 948 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); |
915 | if (!ndlp) { | 949 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
916 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 950 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
917 | "0136 PLOGI completes to NPort x%x " | 951 | "0136 PLOGI completes to NPort x%x " |
918 | "with no ndlp. Data: x%x x%x x%x\n", | 952 | "with no ndlp. Data: x%x x%x x%x\n", |
@@ -962,12 +996,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
962 | } | 996 | } |
963 | /* PLOGI failed */ | 997 | /* PLOGI failed */ |
964 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 998 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
965 | if (lpfc_error_lost_link(irsp)) { | 999 | if (lpfc_error_lost_link(irsp)) |
966 | rc = NLP_STE_FREED_NODE; | 1000 | rc = NLP_STE_FREED_NODE; |
967 | } else { | 1001 | else |
968 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1002 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
969 | NLP_EVT_CMPL_PLOGI); | 1003 | NLP_EVT_CMPL_PLOGI); |
970 | } | ||
971 | } else { | 1004 | } else { |
972 | /* Good status, call state machine */ | 1005 | /* Good status, call state machine */ |
973 | prsp = list_entry(((struct lpfc_dmabuf *) | 1006 | prsp = list_entry(((struct lpfc_dmabuf *) |
@@ -1015,8 +1048,10 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) | |||
1015 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1048 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1016 | 1049 | ||
1017 | ndlp = lpfc_findnode_did(vport, did); | 1050 | ndlp = lpfc_findnode_did(vport, did); |
1018 | /* If ndlp if not NULL, we will bump the reference count on it */ | 1051 | if (ndlp && !NLP_CHK_NODE_ACT(ndlp)) |
1052 | ndlp = NULL; | ||
1019 | 1053 | ||
1054 | /* If ndlp is not NULL, we will bump the reference count on it */ | ||
1020 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); | 1055 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
1021 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, | 1056 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, |
1022 | ELS_CMD_PLOGI); | 1057 | ELS_CMD_PLOGI); |
@@ -1097,18 +1132,15 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1097 | } | 1132 | } |
1098 | /* PRLI failed */ | 1133 | /* PRLI failed */ |
1099 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1134 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
1100 | if (lpfc_error_lost_link(irsp)) { | 1135 | if (lpfc_error_lost_link(irsp)) |
1101 | goto out; | 1136 | goto out; |
1102 | } else { | 1137 | else |
1103 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1138 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1104 | NLP_EVT_CMPL_PRLI); | 1139 | NLP_EVT_CMPL_PRLI); |
1105 | } | 1140 | } else |
1106 | } else { | ||
1107 | /* Good status, call state machine */ | 1141 | /* Good status, call state machine */ |
1108 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1142 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1109 | NLP_EVT_CMPL_PRLI); | 1143 | NLP_EVT_CMPL_PRLI); |
1110 | } | ||
1111 | |||
1112 | out: | 1144 | out: |
1113 | lpfc_els_free_iocb(phba, cmdiocb); | 1145 | lpfc_els_free_iocb(phba, cmdiocb); |
1114 | return; | 1146 | return; |
@@ -1275,15 +1307,13 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1275 | } | 1307 | } |
1276 | /* ADISC failed */ | 1308 | /* ADISC failed */ |
1277 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1309 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
1278 | if (!lpfc_error_lost_link(irsp)) { | 1310 | if (!lpfc_error_lost_link(irsp)) |
1279 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1311 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1280 | NLP_EVT_CMPL_ADISC); | 1312 | NLP_EVT_CMPL_ADISC); |
1281 | } | 1313 | } else |
1282 | } else { | ||
1283 | /* Good status, call state machine */ | 1314 | /* Good status, call state machine */ |
1284 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1315 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1285 | NLP_EVT_CMPL_ADISC); | 1316 | NLP_EVT_CMPL_ADISC); |
1286 | } | ||
1287 | 1317 | ||
1288 | if (disc && vport->num_disc_nodes) { | 1318 | if (disc && vport->num_disc_nodes) { |
1289 | /* Check to see if there are more ADISCs to be sent */ | 1319 | /* Check to see if there are more ADISCs to be sent */ |
@@ -1443,14 +1473,12 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1443 | else | 1473 | else |
1444 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1474 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1445 | NLP_EVT_CMPL_LOGO); | 1475 | NLP_EVT_CMPL_LOGO); |
1446 | } else { | 1476 | } else |
1447 | /* Good status, call state machine. | 1477 | /* Good status, call state machine. |
1448 | * This will unregister the rpi if needed. | 1478 | * This will unregister the rpi if needed. |
1449 | */ | 1479 | */ |
1450 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1480 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1451 | NLP_EVT_CMPL_LOGO); | 1481 | NLP_EVT_CMPL_LOGO); |
1452 | } | ||
1453 | |||
1454 | out: | 1482 | out: |
1455 | lpfc_els_free_iocb(phba, cmdiocb); | 1483 | lpfc_els_free_iocb(phba, cmdiocb); |
1456 | return; | 1484 | return; |
@@ -1556,11 +1584,19 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1556 | psli = &phba->sli; | 1584 | psli = &phba->sli; |
1557 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1585 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1558 | cmdsize = (sizeof(uint32_t) + sizeof(SCR)); | 1586 | cmdsize = (sizeof(uint32_t) + sizeof(SCR)); |
1559 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
1560 | if (!ndlp) | ||
1561 | return 1; | ||
1562 | 1587 | ||
1563 | lpfc_nlp_init(vport, ndlp, nportid); | 1588 | ndlp = lpfc_findnode_did(vport, nportid); |
1589 | if (!ndlp) { | ||
1590 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
1591 | if (!ndlp) | ||
1592 | return 1; | ||
1593 | lpfc_nlp_init(vport, ndlp, nportid); | ||
1594 | lpfc_enqueue_node(vport, ndlp); | ||
1595 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
1596 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
1597 | if (!ndlp) | ||
1598 | return 1; | ||
1599 | } | ||
1564 | 1600 | ||
1565 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | 1601 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1566 | ndlp->nlp_DID, ELS_CMD_SCR); | 1602 | ndlp->nlp_DID, ELS_CMD_SCR); |
@@ -1623,11 +1659,19 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1623 | psli = &phba->sli; | 1659 | psli = &phba->sli; |
1624 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1660 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1625 | cmdsize = (sizeof(uint32_t) + sizeof(FARP)); | 1661 | cmdsize = (sizeof(uint32_t) + sizeof(FARP)); |
1626 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
1627 | if (!ndlp) | ||
1628 | return 1; | ||
1629 | 1662 | ||
1630 | lpfc_nlp_init(vport, ndlp, nportid); | 1663 | ndlp = lpfc_findnode_did(vport, nportid); |
1664 | if (!ndlp) { | ||
1665 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
1666 | if (!ndlp) | ||
1667 | return 1; | ||
1668 | lpfc_nlp_init(vport, ndlp, nportid); | ||
1669 | lpfc_enqueue_node(vport, ndlp); | ||
1670 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
1671 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
1672 | if (!ndlp) | ||
1673 | return 1; | ||
1674 | } | ||
1631 | 1675 | ||
1632 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | 1676 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1633 | ndlp->nlp_DID, ELS_CMD_RNID); | 1677 | ndlp->nlp_DID, ELS_CMD_RNID); |
@@ -1657,7 +1701,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1657 | memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name)); | 1701 | memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name)); |
1658 | memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); | 1702 | memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); |
1659 | ondlp = lpfc_findnode_did(vport, nportid); | 1703 | ondlp = lpfc_findnode_did(vport, nportid); |
1660 | if (ondlp) { | 1704 | if (ondlp && NLP_CHK_NODE_ACT(ondlp)) { |
1661 | memcpy(&fp->OportName, &ondlp->nlp_portname, | 1705 | memcpy(&fp->OportName, &ondlp->nlp_portname, |
1662 | sizeof(struct lpfc_name)); | 1706 | sizeof(struct lpfc_name)); |
1663 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, | 1707 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, |
@@ -1690,6 +1734,7 @@ void | |||
1690 | lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) | 1734 | lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) |
1691 | { | 1735 | { |
1692 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1736 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1737 | struct lpfc_work_evt *evtp; | ||
1693 | 1738 | ||
1694 | spin_lock_irq(shost->host_lock); | 1739 | spin_lock_irq(shost->host_lock); |
1695 | nlp->nlp_flag &= ~NLP_DELAY_TMO; | 1740 | nlp->nlp_flag &= ~NLP_DELAY_TMO; |
@@ -1697,8 +1742,12 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) | |||
1697 | del_timer_sync(&nlp->nlp_delayfunc); | 1742 | del_timer_sync(&nlp->nlp_delayfunc); |
1698 | nlp->nlp_last_elscmd = 0; | 1743 | nlp->nlp_last_elscmd = 0; |
1699 | 1744 | ||
1700 | if (!list_empty(&nlp->els_retry_evt.evt_listp)) | 1745 | if (!list_empty(&nlp->els_retry_evt.evt_listp)) { |
1701 | list_del_init(&nlp->els_retry_evt.evt_listp); | 1746 | list_del_init(&nlp->els_retry_evt.evt_listp); |
1747 | /* Decrement nlp reference count held for the delayed retry */ | ||
1748 | evtp = &nlp->els_retry_evt; | ||
1749 | lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); | ||
1750 | } | ||
1702 | 1751 | ||
1703 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { | 1752 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { |
1704 | spin_lock_irq(shost->host_lock); | 1753 | spin_lock_irq(shost->host_lock); |
@@ -1842,13 +1891,14 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1842 | cmd = *elscmd++; | 1891 | cmd = *elscmd++; |
1843 | } | 1892 | } |
1844 | 1893 | ||
1845 | if (ndlp) | 1894 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) |
1846 | did = ndlp->nlp_DID; | 1895 | did = ndlp->nlp_DID; |
1847 | else { | 1896 | else { |
1848 | /* We should only hit this case for retrying PLOGI */ | 1897 | /* We should only hit this case for retrying PLOGI */ |
1849 | did = irsp->un.elsreq64.remoteID; | 1898 | did = irsp->un.elsreq64.remoteID; |
1850 | ndlp = lpfc_findnode_did(vport, did); | 1899 | ndlp = lpfc_findnode_did(vport, did); |
1851 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) | 1900 | if ((!ndlp || !NLP_CHK_NODE_ACT(ndlp)) |
1901 | && (cmd != ELS_CMD_PLOGI)) | ||
1852 | return 1; | 1902 | return 1; |
1853 | } | 1903 | } |
1854 | 1904 | ||
@@ -2322,6 +2372,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2322 | if ((rspiocb->iocb.ulpStatus == 0) | 2372 | if ((rspiocb->iocb.ulpStatus == 0) |
2323 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { | 2373 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { |
2324 | lpfc_unreg_rpi(vport, ndlp); | 2374 | lpfc_unreg_rpi(vport, ndlp); |
2375 | /* Increment reference count to ndlp to hold the | ||
2376 | * reference to ndlp for the callback function. | ||
2377 | */ | ||
2325 | mbox->context2 = lpfc_nlp_get(ndlp); | 2378 | mbox->context2 = lpfc_nlp_get(ndlp); |
2326 | mbox->vport = vport; | 2379 | mbox->vport = vport; |
2327 | if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) { | 2380 | if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) { |
@@ -2335,9 +2388,13 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2335 | NLP_STE_REG_LOGIN_ISSUE); | 2388 | NLP_STE_REG_LOGIN_ISSUE); |
2336 | } | 2389 | } |
2337 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) | 2390 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
2338 | != MBX_NOT_FINISHED) { | 2391 | != MBX_NOT_FINISHED) |
2339 | goto out; | 2392 | goto out; |
2340 | } | 2393 | else |
2394 | /* Decrement the ndlp reference count we | ||
2395 | * set for this failed mailbox command. | ||
2396 | */ | ||
2397 | lpfc_nlp_put(ndlp); | ||
2341 | 2398 | ||
2342 | /* ELS rsp: Cannot issue reg_login for <NPortid> */ | 2399 | /* ELS rsp: Cannot issue reg_login for <NPortid> */ |
2343 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 2400 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
@@ -2796,6 +2853,8 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) | |||
2796 | 2853 | ||
2797 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ | 2854 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ |
2798 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { | 2855 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { |
2856 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
2857 | continue; | ||
2799 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && | 2858 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2800 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && | 2859 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2801 | (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { | 2860 | (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { |
@@ -2833,6 +2892,8 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) | |||
2833 | 2892 | ||
2834 | /* go thru NPR nodes and issue any remaining ELS PLOGIs */ | 2893 | /* go thru NPR nodes and issue any remaining ELS PLOGIs */ |
2835 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { | 2894 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { |
2895 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
2896 | continue; | ||
2836 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && | 2897 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2837 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && | 2898 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2838 | (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && | 2899 | (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && |
@@ -2943,7 +3004,8 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) | |||
2943 | */ | 3004 | */ |
2944 | 3005 | ||
2945 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { | 3006 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { |
2946 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE || | 3007 | if (!NLP_CHK_NODE_ACT(ndlp) || |
3008 | ndlp->nlp_state == NLP_STE_UNUSED_NODE || | ||
2947 | lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0) | 3009 | lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0) |
2948 | continue; | 3010 | continue; |
2949 | 3011 | ||
@@ -3145,7 +3207,8 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) | |||
3145 | vport->num_disc_nodes = 0; | 3207 | vport->num_disc_nodes = 0; |
3146 | 3208 | ||
3147 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 3209 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
3148 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 3210 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) |
3211 | && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | ||
3149 | /* Good ndlp, issue CT Request to NameServer */ | 3212 | /* Good ndlp, issue CT Request to NameServer */ |
3150 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0) | 3213 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0) |
3151 | /* Wait for NameServer query cmpl before we can | 3214 | /* Wait for NameServer query cmpl before we can |
@@ -3155,25 +3218,35 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) | |||
3155 | /* If login to NameServer does not exist, issue one */ | 3218 | /* If login to NameServer does not exist, issue one */ |
3156 | /* Good status, issue PLOGI to NameServer */ | 3219 | /* Good status, issue PLOGI to NameServer */ |
3157 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 3220 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
3158 | if (ndlp) | 3221 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) |
3159 | /* Wait for NameServer login cmpl before we can | 3222 | /* Wait for NameServer login cmpl before we can |
3160 | continue */ | 3223 | continue */ |
3161 | return 1; | 3224 | return 1; |
3162 | 3225 | ||
3163 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 3226 | if (ndlp) { |
3164 | if (!ndlp) { | 3227 | ndlp = lpfc_enable_node(vport, ndlp, |
3165 | lpfc_els_flush_rscn(vport); | 3228 | NLP_STE_PLOGI_ISSUE); |
3166 | return 0; | 3229 | if (!ndlp) { |
3230 | lpfc_els_flush_rscn(vport); | ||
3231 | return 0; | ||
3232 | } | ||
3233 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | ||
3167 | } else { | 3234 | } else { |
3235 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
3236 | if (!ndlp) { | ||
3237 | lpfc_els_flush_rscn(vport); | ||
3238 | return 0; | ||
3239 | } | ||
3168 | lpfc_nlp_init(vport, ndlp, NameServer_DID); | 3240 | lpfc_nlp_init(vport, ndlp, NameServer_DID); |
3169 | ndlp->nlp_type |= NLP_FABRIC; | ||
3170 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3241 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3171 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 3242 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
3172 | lpfc_issue_els_plogi(vport, NameServer_DID, 0); | ||
3173 | /* Wait for NameServer login cmpl before we can | ||
3174 | continue */ | ||
3175 | return 1; | ||
3176 | } | 3243 | } |
3244 | ndlp->nlp_type |= NLP_FABRIC; | ||
3245 | lpfc_issue_els_plogi(vport, NameServer_DID, 0); | ||
3246 | /* Wait for NameServer login cmpl before we can | ||
3247 | * continue | ||
3248 | */ | ||
3249 | return 1; | ||
3177 | } | 3250 | } |
3178 | 3251 | ||
3179 | lpfc_els_flush_rscn(vport); | 3252 | lpfc_els_flush_rscn(vport); |
@@ -3672,6 +3745,8 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3672 | 3745 | ||
3673 | list_for_each_entry_safe(ndlp, next_ndlp, | 3746 | list_for_each_entry_safe(ndlp, next_ndlp, |
3674 | &vport->fc_nodes, nlp_listp) { | 3747 | &vport->fc_nodes, nlp_listp) { |
3748 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
3749 | continue; | ||
3675 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | 3750 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) |
3676 | continue; | 3751 | continue; |
3677 | if (ndlp->nlp_type & NLP_FABRIC) { | 3752 | if (ndlp->nlp_type & NLP_FABRIC) { |
@@ -3697,6 +3772,8 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3697 | */ | 3772 | */ |
3698 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | 3773 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, |
3699 | nlp_listp) { | 3774 | nlp_listp) { |
3775 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
3776 | continue; | ||
3700 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | 3777 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) |
3701 | continue; | 3778 | continue; |
3702 | 3779 | ||
@@ -3936,7 +4013,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3936 | uint32_t cmd, did, newnode, rjt_err = 0; | 4013 | uint32_t cmd, did, newnode, rjt_err = 0; |
3937 | IOCB_t *icmd = &elsiocb->iocb; | 4014 | IOCB_t *icmd = &elsiocb->iocb; |
3938 | 4015 | ||
3939 | if (vport == NULL || elsiocb->context2 == NULL) | 4016 | if (!vport || !(elsiocb->context2)) |
3940 | goto dropit; | 4017 | goto dropit; |
3941 | 4018 | ||
3942 | newnode = 0; | 4019 | newnode = 0; |
@@ -3971,14 +4048,20 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3971 | lpfc_nlp_init(vport, ndlp, did); | 4048 | lpfc_nlp_init(vport, ndlp, did); |
3972 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 4049 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
3973 | newnode = 1; | 4050 | newnode = 1; |
3974 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { | 4051 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) |
3975 | ndlp->nlp_type |= NLP_FABRIC; | 4052 | ndlp->nlp_type |= NLP_FABRIC; |
4053 | } else { | ||
4054 | if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
4055 | ndlp = lpfc_enable_node(vport, ndlp, | ||
4056 | NLP_STE_UNUSED_NODE); | ||
4057 | if (!ndlp) | ||
4058 | goto dropit; | ||
3976 | } | 4059 | } |
3977 | } | ||
3978 | else { | ||
3979 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { | 4060 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { |
3980 | /* This is simular to the new node path */ | 4061 | /* This is simular to the new node path */ |
3981 | lpfc_nlp_get(ndlp); | 4062 | ndlp = lpfc_nlp_get(ndlp); |
4063 | if (!ndlp) | ||
4064 | goto dropit; | ||
3982 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 4065 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
3983 | newnode = 1; | 4066 | newnode = 1; |
3984 | } | 4067 | } |
@@ -3987,6 +4070,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3987 | phba->fc_stat.elsRcvFrame++; | 4070 | phba->fc_stat.elsRcvFrame++; |
3988 | if (elsiocb->context1) | 4071 | if (elsiocb->context1) |
3989 | lpfc_nlp_put(elsiocb->context1); | 4072 | lpfc_nlp_put(elsiocb->context1); |
4073 | |||
3990 | elsiocb->context1 = lpfc_nlp_get(ndlp); | 4074 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
3991 | elsiocb->vport = vport; | 4075 | elsiocb->vport = vport; |
3992 | 4076 | ||
@@ -4314,6 +4398,18 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) | |||
4314 | } | 4398 | } |
4315 | lpfc_nlp_init(vport, ndlp, NameServer_DID); | 4399 | lpfc_nlp_init(vport, ndlp, NameServer_DID); |
4316 | ndlp->nlp_type |= NLP_FABRIC; | 4400 | ndlp->nlp_type |= NLP_FABRIC; |
4401 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
4402 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
4403 | if (!ndlp) { | ||
4404 | if (phba->fc_topology == TOPOLOGY_LOOP) { | ||
4405 | lpfc_disc_start(vport); | ||
4406 | return; | ||
4407 | } | ||
4408 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
4409 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
4410 | "0348 NameServer login: node freed\n"); | ||
4411 | return; | ||
4412 | } | ||
4317 | } | 4413 | } |
4318 | 4414 | ||
4319 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 4415 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
@@ -4471,7 +4567,6 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4471 | irsp->ulpStatus, irsp->un.ulpWord[4]); | 4567 | irsp->ulpStatus, irsp->un.ulpWord[4]); |
4472 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) | 4568 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) |
4473 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 4569 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
4474 | |||
4475 | lpfc_nlp_put(ndlp); | 4570 | lpfc_nlp_put(ndlp); |
4476 | /* giving up on FDISC. Cancel discovery timer */ | 4571 | /* giving up on FDISC. Cancel discovery timer */ |
4477 | lpfc_can_disctmo(vport); | 4572 | lpfc_can_disctmo(vport); |
@@ -4492,8 +4587,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4492 | */ | 4587 | */ |
4493 | list_for_each_entry_safe(np, next_np, | 4588 | list_for_each_entry_safe(np, next_np, |
4494 | &vport->fc_nodes, nlp_listp) { | 4589 | &vport->fc_nodes, nlp_listp) { |
4495 | if (np->nlp_state != NLP_STE_NPR_NODE | 4590 | if (!NLP_CHK_NODE_ACT(ndlp) || |
4496 | || !(np->nlp_flag & NLP_NPR_ADISC)) | 4591 | (np->nlp_state != NLP_STE_NPR_NODE) || |
4592 | !(np->nlp_flag & NLP_NPR_ADISC)) | ||
4497 | continue; | 4593 | continue; |
4498 | spin_lock_irq(shost->host_lock); | 4594 | spin_lock_irq(shost->host_lock); |
4499 | np->nlp_flag &= ~NLP_NPR_ADISC; | 4595 | np->nlp_flag &= ~NLP_NPR_ADISC; |
@@ -4599,6 +4695,8 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4599 | { | 4695 | { |
4600 | struct lpfc_vport *vport = cmdiocb->vport; | 4696 | struct lpfc_vport *vport = cmdiocb->vport; |
4601 | IOCB_t *irsp; | 4697 | IOCB_t *irsp; |
4698 | struct lpfc_nodelist *ndlp; | ||
4699 | ndlp = (struct lpfc_nodelist *)cmdiocb->context1; | ||
4602 | 4700 | ||
4603 | irsp = &rspiocb->iocb; | 4701 | irsp = &rspiocb->iocb; |
4604 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | 4702 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
@@ -4607,6 +4705,9 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4607 | 4705 | ||
4608 | lpfc_els_free_iocb(phba, cmdiocb); | 4706 | lpfc_els_free_iocb(phba, cmdiocb); |
4609 | vport->unreg_vpi_cmpl = VPORT_ERROR; | 4707 | vport->unreg_vpi_cmpl = VPORT_ERROR; |
4708 | |||
4709 | /* Trigger the release of the ndlp after logo */ | ||
4710 | lpfc_nlp_put(ndlp); | ||
4610 | } | 4711 | } |
4611 | 4712 | ||
4612 | int | 4713 | int |