diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:43 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
commit | 87af33fe5f78c27cf9e43c6e586dd6efd4be3e40 (patch) | |
tree | e9960c6e95ed599672d5dcec0d3c4e428ae42799 /drivers/scsi/lpfc | |
parent | 98c9ea5c026ee47efe2a0f595078dbf199d08f50 (diff) |
[SCSI] lpfc 8.2.3 : FC Discovery Fixes
FC Discovery Fixes:
- Fix up lpfc_drop_node() vs lpfc_nlp_not_used() usage
- Clear ADISC flag when unregistering RPI and REMOVE ndlps if in recovery.
- Fix usage of UNUSED list and ndlps
- Fix PLOGI race conditions
- Reset link if NameServer PLOGI errors occur
- Synchronize GID_FT queries with PLOGI receptions
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 231 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 96 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 66 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 82 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 24 |
7 files changed, 300 insertions, 204 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 59164c6aa28f..338b5dd10a92 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -45,6 +45,7 @@ void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | |||
45 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); | 45 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); |
46 | void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove); | 46 | void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove); |
47 | int lpfc_linkdown(struct lpfc_hba *); | 47 | int lpfc_linkdown(struct lpfc_hba *); |
48 | void lpfc_port_link_failure(struct lpfc_vport *); | ||
48 | void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | 49 | void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); |
49 | 50 | ||
50 | void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | 51 | void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); |
@@ -74,6 +75,7 @@ void lpfc_disc_list_loopmap(struct lpfc_vport *); | |||
74 | void lpfc_disc_start(struct lpfc_vport *); | 75 | void lpfc_disc_start(struct lpfc_vport *); |
75 | void lpfc_disc_flush_list(struct lpfc_vport *); | 76 | void lpfc_disc_flush_list(struct lpfc_vport *); |
76 | void lpfc_cleanup_discovery_resources(struct lpfc_vport *); | 77 | void lpfc_cleanup_discovery_resources(struct lpfc_vport *); |
78 | void lpfc_cleanup(struct lpfc_vport *); | ||
77 | void lpfc_disc_timeout(unsigned long); | 79 | void lpfc_disc_timeout(unsigned long); |
78 | 80 | ||
79 | struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); | 81 | struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); |
@@ -91,6 +93,8 @@ void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *); | |||
91 | int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, | 93 | int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, |
92 | struct serv_parm *, uint32_t); | 94 | struct serv_parm *, uint32_t); |
93 | int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); | 95 | int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); |
96 | void lpfc_more_plogi(struct lpfc_vport *); | ||
97 | void lpfc_end_rscn(struct lpfc_vport *); | ||
94 | int lpfc_els_chk_latt(struct lpfc_vport *); | 98 | int lpfc_els_chk_latt(struct lpfc_vport *); |
95 | int lpfc_els_abort_flogi(struct lpfc_hba *); | 99 | int lpfc_els_abort_flogi(struct lpfc_hba *); |
96 | int lpfc_initial_flogi(struct lpfc_vport *); | 100 | int lpfc_initial_flogi(struct lpfc_vport *); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index c9422a8423ca..99bc1a1ecac2 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -103,7 +103,6 @@ struct lpfc_nodelist { | |||
103 | #define NLP_RM_DFLT_RPI 0x4000000 /* need to remove leftover dflt RPI */ | 103 | #define NLP_RM_DFLT_RPI 0x4000000 /* need to remove leftover dflt RPI */ |
104 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 104 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ |
105 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ | 105 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ |
106 | #define NLP_DELAYED_RM 0x20000000 /* Defer UNUSED List removal */ | ||
107 | 106 | ||
108 | /* There are 4 different double linked lists nodelist entries can reside on. | 107 | /* There are 4 different double linked lists nodelist entries can reside on. |
109 | * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used | 108 | * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 813eeca7ce1e..0a5006ea9909 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -575,8 +575,13 @@ flogifail: | |||
575 | 575 | ||
576 | /* Start discovery */ | 576 | /* Start discovery */ |
577 | lpfc_disc_start(vport); | 577 | lpfc_disc_start(vport); |
578 | } else if (((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || | ||
579 | ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && | ||
580 | (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) && | ||
581 | (phba->link_state != LPFC_CLEAR_LA)) { | ||
582 | /* If FLOGI failed enable link interrupt. */ | ||
583 | lpfc_issue_clear_la(phba, vport); | ||
578 | } | 584 | } |
579 | |||
580 | out: | 585 | out: |
581 | lpfc_els_free_iocb(phba, cmdiocb); | 586 | lpfc_els_free_iocb(phba, cmdiocb); |
582 | } | 587 | } |
@@ -711,13 +716,8 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
711 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | 716 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
712 | } else { | 717 | } else { |
713 | lpfc_dequeue_node(vport, ndlp); | 718 | lpfc_dequeue_node(vport, ndlp); |
714 | |||
715 | /* If we go thru this path, Fabric_DID ndlp is in the process | ||
716 | * of being removed. We need to bump the reference count by 1 | ||
717 | * so it stays around all through this link up period. | ||
718 | */ | ||
719 | lpfc_nlp_get(ndlp); | ||
720 | } | 719 | } |
720 | |||
721 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { | 721 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { |
722 | lpfc_nlp_put(ndlp); | 722 | lpfc_nlp_put(ndlp); |
723 | } | 723 | } |
@@ -746,7 +746,8 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) | |||
746 | } | 746 | } |
747 | return 1; | 747 | return 1; |
748 | } | 748 | } |
749 | static void | 749 | |
750 | void | ||
750 | lpfc_more_plogi(struct lpfc_vport *vport) | 751 | lpfc_more_plogi(struct lpfc_vport *vport) |
751 | { | 752 | { |
752 | int sentplogi; | 753 | int sentplogi; |
@@ -813,8 +814,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
813 | lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); | 814 | lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); |
814 | 815 | ||
815 | /* Move this back to NPR state */ | 816 | /* Move this back to NPR state */ |
816 | if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) | 817 | if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) { |
818 | /* The new_ndlp is replacing ndlp totally, so we need | ||
819 | * to put ndlp on UNUSED list and try to free it. | ||
820 | */ | ||
817 | lpfc_drop_node(vport, ndlp); | 821 | lpfc_drop_node(vport, ndlp); |
822 | } | ||
818 | else { | 823 | else { |
819 | lpfc_unreg_rpi(vport, ndlp); | 824 | lpfc_unreg_rpi(vport, ndlp); |
820 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ | 825 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ |
@@ -823,6 +828,27 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
823 | return new_ndlp; | 828 | return new_ndlp; |
824 | } | 829 | } |
825 | 830 | ||
831 | void | ||
832 | lpfc_end_rscn(struct lpfc_vport *vport) | ||
833 | { | ||
834 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
835 | |||
836 | if (vport->fc_flag & FC_RSCN_MODE) { | ||
837 | /* | ||
838 | * Check to see if more RSCNs came in while we were | ||
839 | * processing this one. | ||
840 | */ | ||
841 | if (vport->fc_rscn_id_cnt || | ||
842 | (vport->fc_flag & FC_RSCN_DISCOVERY) != 0) | ||
843 | lpfc_els_handle_rscn(vport); | ||
844 | else { | ||
845 | spin_lock_irq(shost->host_lock); | ||
846 | vport->fc_flag &= ~FC_RSCN_MODE; | ||
847 | spin_unlock_irq(shost->host_lock); | ||
848 | } | ||
849 | } | ||
850 | } | ||
851 | |||
826 | static void | 852 | static void |
827 | lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 853 | lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
828 | struct lpfc_iocbq *rspiocb) | 854 | struct lpfc_iocbq *rspiocb) |
@@ -893,13 +919,6 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
893 | goto out; | 919 | goto out; |
894 | } | 920 | } |
895 | /* PLOGI failed */ | 921 | /* PLOGI failed */ |
896 | if (ndlp->nlp_DID == NameServer_DID) { | ||
897 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
898 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
899 | "0250 Nameserver login error: " | ||
900 | "0x%x / 0x%x\n", | ||
901 | irsp->ulpStatus, irsp->un.ulpWord[4]); | ||
902 | } | ||
903 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 922 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
904 | if (lpfc_error_lost_link(irsp)) { | 923 | if (lpfc_error_lost_link(irsp)) { |
905 | rc = NLP_STE_FREED_NODE; | 924 | rc = NLP_STE_FREED_NODE; |
@@ -927,20 +946,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
927 | spin_unlock_irq(shost->host_lock); | 946 | spin_unlock_irq(shost->host_lock); |
928 | 947 | ||
929 | lpfc_can_disctmo(vport); | 948 | lpfc_can_disctmo(vport); |
930 | if (vport->fc_flag & FC_RSCN_MODE) { | 949 | lpfc_end_rscn(vport); |
931 | /* | ||
932 | * Check to see if more RSCNs came in while | ||
933 | * we were processing this one. | ||
934 | */ | ||
935 | if ((vport->fc_rscn_id_cnt == 0) && | ||
936 | (!(vport->fc_flag & FC_RSCN_DISCOVERY))) { | ||
937 | spin_lock_irq(shost->host_lock); | ||
938 | vport->fc_flag &= ~FC_RSCN_MODE; | ||
939 | spin_unlock_irq(shost->host_lock); | ||
940 | } else { | ||
941 | lpfc_els_handle_rscn(vport); | ||
942 | } | ||
943 | } | ||
944 | } | 950 | } |
945 | } | 951 | } |
946 | 952 | ||
@@ -1160,8 +1166,6 @@ lpfc_more_adisc(struct lpfc_vport *vport) | |||
1160 | static void | 1166 | static void |
1161 | lpfc_rscn_disc(struct lpfc_vport *vport) | 1167 | lpfc_rscn_disc(struct lpfc_vport *vport) |
1162 | { | 1168 | { |
1163 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1164 | |||
1165 | lpfc_can_disctmo(vport); | 1169 | lpfc_can_disctmo(vport); |
1166 | 1170 | ||
1167 | /* RSCN discovery */ | 1171 | /* RSCN discovery */ |
@@ -1170,19 +1174,7 @@ lpfc_rscn_disc(struct lpfc_vport *vport) | |||
1170 | if (lpfc_els_disc_plogi(vport)) | 1174 | if (lpfc_els_disc_plogi(vport)) |
1171 | return; | 1175 | return; |
1172 | 1176 | ||
1173 | if (vport->fc_flag & FC_RSCN_MODE) { | 1177 | lpfc_end_rscn(vport); |
1174 | /* Check to see if more RSCNs came in while we were | ||
1175 | * processing this one. | ||
1176 | */ | ||
1177 | if ((vport->fc_rscn_id_cnt == 0) && | ||
1178 | (!(vport->fc_flag & FC_RSCN_DISCOVERY))) { | ||
1179 | spin_lock_irq(shost->host_lock); | ||
1180 | vport->fc_flag &= ~FC_RSCN_MODE; | ||
1181 | spin_unlock_irq(shost->host_lock); | ||
1182 | } else { | ||
1183 | lpfc_els_handle_rscn(vport); | ||
1184 | } | ||
1185 | } | ||
1186 | } | 1178 | } |
1187 | 1179 | ||
1188 | static void | 1180 | static void |
@@ -1632,27 +1624,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1632 | return 0; | 1624 | return 0; |
1633 | } | 1625 | } |
1634 | 1626 | ||
1635 | static void | ||
1636 | lpfc_end_rscn(struct lpfc_vport *vport) | ||
1637 | { | ||
1638 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1639 | |||
1640 | if (vport->fc_flag & FC_RSCN_MODE) { | ||
1641 | /* | ||
1642 | * Check to see if more RSCNs came in while we were | ||
1643 | * processing this one. | ||
1644 | */ | ||
1645 | if (vport->fc_rscn_id_cnt || | ||
1646 | (vport->fc_flag & FC_RSCN_DISCOVERY) != 0) | ||
1647 | lpfc_els_handle_rscn(vport); | ||
1648 | else { | ||
1649 | spin_lock_irq(shost->host_lock); | ||
1650 | vport->fc_flag &= ~FC_RSCN_MODE; | ||
1651 | spin_unlock_irq(shost->host_lock); | ||
1652 | } | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | void | 1627 | void |
1657 | lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) | 1628 | lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) |
1658 | { | 1629 | { |
@@ -2069,6 +2040,32 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2069 | } | 2040 | } |
2070 | 2041 | ||
2071 | int | 2042 | int |
2043 | lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) | ||
2044 | { | ||
2045 | struct lpfc_dmabuf *buf_ptr; | ||
2046 | |||
2047 | /* Free the response before processing the command. */ | ||
2048 | if (!list_empty(&buf_ptr1->list)) { | ||
2049 | list_remove_head(&buf_ptr1->list, buf_ptr, | ||
2050 | struct lpfc_dmabuf, | ||
2051 | list); | ||
2052 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | ||
2053 | kfree(buf_ptr); | ||
2054 | } | ||
2055 | lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys); | ||
2056 | kfree(buf_ptr1); | ||
2057 | return 0; | ||
2058 | } | ||
2059 | |||
2060 | int | ||
2061 | lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr) | ||
2062 | { | ||
2063 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | ||
2064 | kfree(buf_ptr); | ||
2065 | return 0; | ||
2066 | } | ||
2067 | |||
2068 | int | ||
2072 | lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) | 2069 | lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) |
2073 | { | 2070 | { |
2074 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; | 2071 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; |
@@ -2080,22 +2077,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) | |||
2080 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ | 2077 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ |
2081 | if (elsiocb->context2) { | 2078 | if (elsiocb->context2) { |
2082 | buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; | 2079 | buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; |
2083 | /* Free the response before processing the command. */ | 2080 | lpfc_els_free_data(phba, buf_ptr1); |
2084 | if (!list_empty(&buf_ptr1->list)) { | ||
2085 | list_remove_head(&buf_ptr1->list, buf_ptr, | ||
2086 | struct lpfc_dmabuf, | ||
2087 | list); | ||
2088 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | ||
2089 | kfree(buf_ptr); | ||
2090 | } | ||
2091 | lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys); | ||
2092 | kfree(buf_ptr1); | ||
2093 | } | 2081 | } |
2094 | 2082 | ||
2095 | if (elsiocb->context3) { | 2083 | if (elsiocb->context3) { |
2096 | buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3; | 2084 | buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3; |
2097 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | 2085 | lpfc_els_free_bpl(phba, buf_ptr); |
2098 | kfree(buf_ptr); | ||
2099 | } | 2086 | } |
2100 | lpfc_sli_release_iocbq(phba, elsiocb); | 2087 | lpfc_sli_release_iocbq(phba, elsiocb); |
2101 | return 0; | 2088 | return 0; |
@@ -2119,15 +2106,15 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2119 | "Data: x%x x%x x%x\n", | 2106 | "Data: x%x x%x x%x\n", |
2120 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | 2107 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
2121 | ndlp->nlp_rpi); | 2108 | ndlp->nlp_rpi); |
2122 | switch (ndlp->nlp_state) { | 2109 | |
2123 | case NLP_STE_UNUSED_NODE: /* node is just allocated */ | 2110 | if (ndlp->nlp_state == NLP_STE_NPR_NODE) { |
2124 | lpfc_drop_node(vport, ndlp); | 2111 | /* NPort Recovery mode or node is just allocated */ |
2125 | break; | 2112 | if (!lpfc_nlp_not_used(ndlp)) { |
2126 | case NLP_STE_NPR_NODE: /* NPort Recovery mode */ | 2113 | /* If the ndlp is being used by another discovery |
2127 | lpfc_unreg_rpi(vport, ndlp); | 2114 | * thread, just unregister the RPI. |
2128 | break; | 2115 | */ |
2129 | default: | 2116 | lpfc_unreg_rpi(vport, ndlp); |
2130 | break; | 2117 | } |
2131 | } | 2118 | } |
2132 | lpfc_els_free_iocb(phba, cmdiocb); | 2119 | lpfc_els_free_iocb(phba, cmdiocb); |
2133 | return; | 2120 | return; |
@@ -2160,15 +2147,27 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2160 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 2147 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
2161 | struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL; | 2148 | struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL; |
2162 | struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL; | 2149 | struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL; |
2163 | IOCB_t *irsp; | 2150 | IOCB_t *irsp; |
2151 | uint8_t *pcmd; | ||
2164 | LPFC_MBOXQ_t *mbox = NULL; | 2152 | LPFC_MBOXQ_t *mbox = NULL; |
2165 | struct lpfc_dmabuf *mp = NULL; | 2153 | struct lpfc_dmabuf *mp = NULL; |
2154 | uint32_t ls_rjt = 0; | ||
2166 | 2155 | ||
2167 | irsp = &rspiocb->iocb; | 2156 | irsp = &rspiocb->iocb; |
2168 | 2157 | ||
2169 | if (cmdiocb->context_un.mbox) | 2158 | if (cmdiocb->context_un.mbox) |
2170 | mbox = cmdiocb->context_un.mbox; | 2159 | mbox = cmdiocb->context_un.mbox; |
2171 | 2160 | ||
2161 | /* First determine if this is a LS_RJT cmpl */ | ||
2162 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt); | ||
2163 | if (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT) { | ||
2164 | /* A LS_RJT associated with Default RPI cleanup | ||
2165 | * has its own seperate code path. | ||
2166 | */ | ||
2167 | if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI)) | ||
2168 | ls_rjt = 1; | ||
2169 | } | ||
2170 | |||
2172 | /* Check to see if link went down during discovery */ | 2171 | /* Check to see if link went down during discovery */ |
2173 | if (!ndlp || lpfc_els_chk_latt(vport)) { | 2172 | if (!ndlp || lpfc_els_chk_latt(vport)) { |
2174 | if (mbox) { | 2173 | if (mbox) { |
@@ -2247,7 +2246,16 @@ out: | |||
2247 | spin_lock_irq(shost->host_lock); | 2246 | spin_lock_irq(shost->host_lock); |
2248 | ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI); | 2247 | ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI); |
2249 | spin_unlock_irq(shost->host_lock); | 2248 | spin_unlock_irq(shost->host_lock); |
2249 | |||
2250 | /* If the node is not being used by another discovery thread, | ||
2251 | * and we are sending a reject, we are done with it. | ||
2252 | * Release driver reference count here and free associated | ||
2253 | * resources. | ||
2254 | */ | ||
2255 | if (ls_rjt) | ||
2256 | lpfc_nlp_not_used(ndlp); | ||
2250 | } | 2257 | } |
2258 | |||
2251 | lpfc_els_free_iocb(phba, cmdiocb); | 2259 | lpfc_els_free_iocb(phba, cmdiocb); |
2252 | return; | 2260 | return; |
2253 | } | 2261 | } |
@@ -2418,18 +2426,6 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2418 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; | 2426 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
2419 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2427 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2420 | 2428 | ||
2421 | /* If the node is in the UNUSED state, and we are sending | ||
2422 | * a reject, we are done with it. Release driver reference | ||
2423 | * count here. The outstanding els will release its reference on | ||
2424 | * completion, as long as the ndlp stays in the UNUSED list, | ||
2425 | * and the node can be freed then. | ||
2426 | */ | ||
2427 | if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) && | ||
2428 | !(ndlp->nlp_flag & NLP_DELAYED_RM)) { | ||
2429 | ndlp->nlp_flag |= NLP_DELAYED_RM; | ||
2430 | lpfc_nlp_put(ndlp); | ||
2431 | } | ||
2432 | |||
2433 | if (rc == IOCB_ERROR) { | 2429 | if (rc == IOCB_ERROR) { |
2434 | lpfc_els_free_iocb(phba, elsiocb); | 2430 | lpfc_els_free_iocb(phba, elsiocb); |
2435 | return 1; | 2431 | return 1; |
@@ -2715,7 +2711,10 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) | |||
2715 | } | 2711 | } |
2716 | } | 2712 | } |
2717 | } | 2713 | } |
2718 | if (sentplogi == 0) { | 2714 | if (sentplogi) { |
2715 | lpfc_set_disctmo(vport); | ||
2716 | } | ||
2717 | else { | ||
2719 | spin_lock_irq(shost->host_lock); | 2718 | spin_lock_irq(shost->host_lock); |
2720 | vport->fc_flag &= ~FC_NLP_MORE; | 2719 | vport->fc_flag &= ~FC_NLP_MORE; |
2721 | spin_unlock_irq(shost->host_lock); | 2720 | spin_unlock_irq(shost->host_lock); |
@@ -3533,6 +3532,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3533 | * other NLP_FABRIC logins | 3532 | * other NLP_FABRIC logins |
3534 | */ | 3533 | */ |
3535 | lpfc_drop_node(vport, ndlp); | 3534 | lpfc_drop_node(vport, ndlp); |
3535 | |||
3536 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 3536 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
3537 | /* Fail outstanding I/O now since this | 3537 | /* Fail outstanding I/O now since this |
3538 | * device is marked for PLOGI | 3538 | * device is marked for PLOGI |
@@ -3781,6 +3781,7 @@ static void | |||
3781 | lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 3781 | lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
3782 | struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) | 3782 | struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) |
3783 | { | 3783 | { |
3784 | struct Scsi_Host *shost; | ||
3784 | struct lpfc_nodelist *ndlp; | 3785 | struct lpfc_nodelist *ndlp; |
3785 | struct ls_rjt stat; | 3786 | struct ls_rjt stat; |
3786 | uint32_t *payload; | 3787 | uint32_t *payload; |
@@ -3826,6 +3827,14 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3826 | ndlp->nlp_type |= NLP_FABRIC; | 3827 | ndlp->nlp_type |= NLP_FABRIC; |
3827 | } | 3828 | } |
3828 | } | 3829 | } |
3830 | else { | ||
3831 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { | ||
3832 | /* This is simular to the new node path */ | ||
3833 | lpfc_nlp_get(ndlp); | ||
3834 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
3835 | newnode = 1; | ||
3836 | } | ||
3837 | } | ||
3829 | 3838 | ||
3830 | phba->fc_stat.elsRcvFrame++; | 3839 | phba->fc_stat.elsRcvFrame++; |
3831 | if (elsiocb->context1) | 3840 | if (elsiocb->context1) |
@@ -3853,6 +3862,12 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3853 | rjt_err = LSRJT_UNABLE_TPC; | 3862 | rjt_err = LSRJT_UNABLE_TPC; |
3854 | break; | 3863 | break; |
3855 | } | 3864 | } |
3865 | |||
3866 | shost = lpfc_shost_from_vport(vport); | ||
3867 | spin_lock_irq(shost->host_lock); | ||
3868 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | ||
3869 | spin_unlock_irq(shost->host_lock); | ||
3870 | |||
3856 | lpfc_disc_state_machine(vport, ndlp, elsiocb, | 3871 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
3857 | NLP_EVT_RCV_PLOGI); | 3872 | NLP_EVT_RCV_PLOGI); |
3858 | 3873 | ||
@@ -3864,7 +3879,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3864 | 3879 | ||
3865 | phba->fc_stat.elsRcvFLOGI++; | 3880 | phba->fc_stat.elsRcvFLOGI++; |
3866 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); | 3881 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); |
3867 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 3882 | if (newnode) |
3868 | lpfc_nlp_put(ndlp); | 3883 | lpfc_nlp_put(ndlp); |
3869 | break; | 3884 | break; |
3870 | case ELS_CMD_LOGO: | 3885 | case ELS_CMD_LOGO: |
@@ -3894,7 +3909,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3894 | case ELS_CMD_RSCN: | 3909 | case ELS_CMD_RSCN: |
3895 | phba->fc_stat.elsRcvRSCN++; | 3910 | phba->fc_stat.elsRcvRSCN++; |
3896 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); | 3911 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); |
3897 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 3912 | if (newnode) |
3898 | lpfc_nlp_put(ndlp); | 3913 | lpfc_nlp_put(ndlp); |
3899 | break; | 3914 | break; |
3900 | case ELS_CMD_ADISC: | 3915 | case ELS_CMD_ADISC: |
@@ -3966,7 +3981,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3966 | 3981 | ||
3967 | phba->fc_stat.elsRcvLIRR++; | 3982 | phba->fc_stat.elsRcvLIRR++; |
3968 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); | 3983 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); |
3969 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 3984 | if (newnode) |
3970 | lpfc_nlp_put(ndlp); | 3985 | lpfc_nlp_put(ndlp); |
3971 | break; | 3986 | break; |
3972 | case ELS_CMD_RPS: | 3987 | case ELS_CMD_RPS: |
@@ -3976,7 +3991,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3976 | 3991 | ||
3977 | phba->fc_stat.elsRcvRPS++; | 3992 | phba->fc_stat.elsRcvRPS++; |
3978 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); | 3993 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); |
3979 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 3994 | if (newnode) |
3980 | lpfc_nlp_put(ndlp); | 3995 | lpfc_nlp_put(ndlp); |
3981 | break; | 3996 | break; |
3982 | case ELS_CMD_RPL: | 3997 | case ELS_CMD_RPL: |
@@ -3986,7 +4001,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3986 | 4001 | ||
3987 | phba->fc_stat.elsRcvRPL++; | 4002 | phba->fc_stat.elsRcvRPL++; |
3988 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); | 4003 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); |
3989 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 4004 | if (newnode) |
3990 | lpfc_nlp_put(ndlp); | 4005 | lpfc_nlp_put(ndlp); |
3991 | break; | 4006 | break; |
3992 | case ELS_CMD_RNID: | 4007 | case ELS_CMD_RNID: |
@@ -3996,7 +4011,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3996 | 4011 | ||
3997 | phba->fc_stat.elsRcvRNID++; | 4012 | phba->fc_stat.elsRcvRNID++; |
3998 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); | 4013 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); |
3999 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 4014 | if (newnode) |
4000 | lpfc_nlp_put(ndlp); | 4015 | lpfc_nlp_put(ndlp); |
4001 | break; | 4016 | break; |
4002 | default: | 4017 | default: |
@@ -4011,7 +4026,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
4011 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 4026 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
4012 | "0115 Unknown ELS command x%x " | 4027 | "0115 Unknown ELS command x%x " |
4013 | "received from NPORT x%x\n", cmd, did); | 4028 | "received from NPORT x%x\n", cmd, did); |
4014 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) | 4029 | if (newnode) |
4015 | lpfc_nlp_put(ndlp); | 4030 | lpfc_nlp_put(ndlp); |
4016 | break; | 4031 | break; |
4017 | } | 4032 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e181a98caf16..f64ce88e8a06 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -157,6 +157,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
157 | struct lpfc_vport *vport; | 157 | struct lpfc_vport *vport; |
158 | struct lpfc_hba *phba; | 158 | struct lpfc_hba *phba; |
159 | uint8_t *name; | 159 | uint8_t *name; |
160 | int put_node; | ||
161 | int put_rport; | ||
160 | int warn_on = 0; | 162 | int warn_on = 0; |
161 | 163 | ||
162 | rport = ndlp->rport; | 164 | rport = ndlp->rport; |
@@ -178,9 +180,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
178 | return; | 180 | return; |
179 | 181 | ||
180 | if (ndlp->nlp_type & NLP_FABRIC) { | 182 | if (ndlp->nlp_type & NLP_FABRIC) { |
181 | int put_node; | ||
182 | int put_rport; | ||
183 | |||
184 | /* We will clean up these Nodes in linkup */ | 183 | /* We will clean up these Nodes in linkup */ |
185 | put_node = rdata->pnode != NULL; | 184 | put_node = rdata->pnode != NULL; |
186 | put_rport = ndlp->rport != NULL; | 185 | put_rport = ndlp->rport != NULL; |
@@ -222,23 +221,20 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
222 | ndlp->nlp_state, ndlp->nlp_rpi); | 221 | ndlp->nlp_state, ndlp->nlp_rpi); |
223 | } | 222 | } |
224 | 223 | ||
224 | put_node = rdata->pnode != NULL; | ||
225 | put_rport = ndlp->rport != NULL; | ||
226 | rdata->pnode = NULL; | ||
227 | ndlp->rport = NULL; | ||
228 | if (put_node) | ||
229 | lpfc_nlp_put(ndlp); | ||
230 | if (put_rport) | ||
231 | put_device(&rport->dev); | ||
232 | |||
225 | if (!(vport->load_flag & FC_UNLOADING) && | 233 | if (!(vport->load_flag & FC_UNLOADING) && |
226 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | 234 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && |
227 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && | 235 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && |
228 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) | 236 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) { |
229 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); | 237 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); |
230 | else { | ||
231 | int put_node; | ||
232 | int put_rport; | ||
233 | |||
234 | put_node = rdata->pnode != NULL; | ||
235 | put_rport = ndlp->rport != NULL; | ||
236 | rdata->pnode = NULL; | ||
237 | ndlp->rport = NULL; | ||
238 | if (put_node) | ||
239 | lpfc_nlp_put(ndlp); | ||
240 | if (put_rport) | ||
241 | put_device(&rport->dev); | ||
242 | } | 238 | } |
243 | } | 239 | } |
244 | 240 | ||
@@ -546,11 +542,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
546 | } | 542 | } |
547 | } | 543 | } |
548 | 544 | ||
549 | static void | 545 | void |
550 | lpfc_port_link_failure(struct lpfc_vport *vport) | 546 | lpfc_port_link_failure(struct lpfc_vport *vport) |
551 | { | 547 | { |
552 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
553 | |||
554 | /* Cleanup any outstanding RSCN activity */ | 548 | /* Cleanup any outstanding RSCN activity */ |
555 | lpfc_els_flush_rscn(vport); | 549 | lpfc_els_flush_rscn(vport); |
556 | 550 | ||
@@ -559,11 +553,6 @@ lpfc_port_link_failure(struct lpfc_vport *vport) | |||
559 | 553 | ||
560 | lpfc_cleanup_rpis(vport, 0); | 554 | lpfc_cleanup_rpis(vport, 0); |
561 | 555 | ||
562 | /* free any ndlp's on unused list */ | ||
563 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) | ||
564 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
565 | lpfc_drop_node(vport, ndlp); | ||
566 | |||
567 | /* Turn off discovery timer if its running */ | 556 | /* Turn off discovery timer if its running */ |
568 | lpfc_can_disctmo(vport); | 557 | lpfc_can_disctmo(vport); |
569 | } | 558 | } |
@@ -670,7 +659,6 @@ static void | |||
670 | lpfc_linkup_port(struct lpfc_vport *vport) | 659 | lpfc_linkup_port(struct lpfc_vport *vport) |
671 | { | 660 | { |
672 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 661 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
673 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
674 | struct lpfc_hba *phba = vport->phba; | 662 | struct lpfc_hba *phba = vport->phba; |
675 | 663 | ||
676 | if ((vport->load_flag & FC_UNLOADING) != 0) | 664 | if ((vport->load_flag & FC_UNLOADING) != 0) |
@@ -697,11 +685,6 @@ lpfc_linkup_port(struct lpfc_vport *vport) | |||
697 | if (vport->fc_flag & FC_LBIT) | 685 | if (vport->fc_flag & FC_LBIT) |
698 | lpfc_linkup_cleanup_nodes(vport); | 686 | lpfc_linkup_cleanup_nodes(vport); |
699 | 687 | ||
700 | /* free any ndlp's in unused state */ | ||
701 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | ||
702 | nlp_listp) | ||
703 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
704 | lpfc_drop_node(vport, ndlp); | ||
705 | } | 688 | } |
706 | 689 | ||
707 | static int | 690 | static int |
@@ -1345,7 +1328,9 @@ out: | |||
1345 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1328 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1346 | kfree(mp); | 1329 | kfree(mp); |
1347 | mempool_free(pmb, phba->mbox_mem_pool); | 1330 | mempool_free(pmb, phba->mbox_mem_pool); |
1348 | lpfc_drop_node(vport, ndlp); | 1331 | |
1332 | /* If no other thread is using the ndlp, free it */ | ||
1333 | lpfc_nlp_not_used(ndlp); | ||
1349 | 1334 | ||
1350 | if (phba->fc_topology == TOPOLOGY_LOOP) { | 1335 | if (phba->fc_topology == TOPOLOGY_LOOP) { |
1351 | /* | 1336 | /* |
@@ -1605,16 +1590,6 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1605 | ndlp->nlp_type &= ~NLP_FC_NODE; | 1590 | ndlp->nlp_type &= ~NLP_FC_NODE; |
1606 | } | 1591 | } |
1607 | 1592 | ||
1608 | if ((old_state == NLP_STE_UNUSED_NODE) && | ||
1609 | (state != NLP_STE_UNUSED_NODE) && | ||
1610 | (ndlp->nlp_flag & NLP_DELAYED_RM)) { | ||
1611 | /* We are using the ndlp after all, so reverse | ||
1612 | * the delayed removal of it. | ||
1613 | */ | ||
1614 | ndlp->nlp_flag &= ~NLP_DELAYED_RM; | ||
1615 | lpfc_nlp_get(ndlp); | ||
1616 | } | ||
1617 | |||
1618 | if (list_empty(&ndlp->nlp_listp)) { | 1593 | if (list_empty(&ndlp->nlp_listp)) { |
1619 | spin_lock_irq(shost->host_lock); | 1594 | spin_lock_irq(shost->host_lock); |
1620 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); | 1595 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); |
@@ -1646,9 +1621,16 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1646 | void | 1621 | void |
1647 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1622 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1648 | { | 1623 | { |
1624 | /* | ||
1625 | * Use of lpfc_drop_node and UNUSED list. lpfc_drop_node should | ||
1626 | * be used if we wish to issue the "last" lpfc_nlp_put() to remove | ||
1627 | * the ndlp from the vport. The ndlp resides on the UNUSED list | ||
1628 | * until ALL other outstanding threads have completed. Thus, if a | ||
1629 | * ndlp is on the UNUSED list already, we should never do another | ||
1630 | * lpfc_drop_node() on it. | ||
1631 | */ | ||
1649 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1632 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1650 | if (!(ndlp->nlp_flag & NLP_DELAYED_RM)) | 1633 | lpfc_nlp_put(ndlp); |
1651 | lpfc_nlp_put(ndlp); | ||
1652 | return; | 1634 | return; |
1653 | } | 1635 | } |
1654 | 1636 | ||
@@ -2116,6 +2098,12 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) | |||
2116 | } | 2098 | } |
2117 | if (vport->fc_flag & FC_RSCN_MODE) { | 2099 | if (vport->fc_flag & FC_RSCN_MODE) { |
2118 | if (lpfc_rscn_payload_check(vport, did)) { | 2100 | if (lpfc_rscn_payload_check(vport, did)) { |
2101 | /* If we've already recieved a PLOGI from this NPort | ||
2102 | * we don't need to try to discover it again. | ||
2103 | */ | ||
2104 | if (ndlp->nlp_flag & NLP_RCV_PLOGI) | ||
2105 | return NULL; | ||
2106 | |||
2119 | spin_lock_irq(shost->host_lock); | 2107 | spin_lock_irq(shost->host_lock); |
2120 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 2108 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
2121 | spin_unlock_irq(shost->host_lock); | 2109 | spin_unlock_irq(shost->host_lock); |
@@ -2128,8 +2116,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) | |||
2128 | } else | 2116 | } else |
2129 | ndlp = NULL; | 2117 | ndlp = NULL; |
2130 | } else { | 2118 | } else { |
2119 | /* If we've already recieved a PLOGI from this NPort, | ||
2120 | * or we are already in the process of discovery on it, | ||
2121 | * we don't need to try to discover it again. | ||
2122 | */ | ||
2131 | if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || | 2123 | if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || |
2132 | ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) | 2124 | ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
2125 | ndlp->nlp_flag & NLP_RCV_PLOGI) | ||
2133 | return NULL; | 2126 | return NULL; |
2134 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 2127 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
2135 | spin_lock_irq(shost->host_lock); | 2128 | spin_lock_irq(shost->host_lock); |
@@ -2497,6 +2490,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2497 | if (ndlp->nlp_type & NLP_FABRIC) { | 2490 | if (ndlp->nlp_type & NLP_FABRIC) { |
2498 | /* Clean up the ndlp on Fabric connections */ | 2491 | /* Clean up the ndlp on Fabric connections */ |
2499 | lpfc_drop_node(vport, ndlp); | 2492 | lpfc_drop_node(vport, ndlp); |
2493 | |||
2500 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 2494 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
2501 | /* Fail outstanding IO now since device | 2495 | /* Fail outstanding IO now since device |
2502 | * is marked for PLOGI. | 2496 | * is marked for PLOGI. |
@@ -2515,7 +2509,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2515 | /* Initial FLOGI timeout */ | 2509 | /* Initial FLOGI timeout */ |
2516 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 2510 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
2517 | "0222 Initial %s timeout\n", | 2511 | "0222 Initial %s timeout\n", |
2518 | vport->vpi ? "FLOGI" : "FDISC"); | 2512 | vport->vpi ? "FDISC" : "FLOGI"); |
2519 | 2513 | ||
2520 | /* Assume no Fabric and go on with discovery. | 2514 | /* Assume no Fabric and go on with discovery. |
2521 | * Check for outstanding ELS FLOGI to abort. | 2515 | * Check for outstanding ELS FLOGI to abort. |
@@ -2537,10 +2531,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2537 | /* Next look for NameServer ndlp */ | 2531 | /* Next look for NameServer ndlp */ |
2538 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 2532 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
2539 | if (ndlp) | 2533 | if (ndlp) |
2540 | lpfc_nlp_put(ndlp); | 2534 | lpfc_els_abort(phba, ndlp); |
2541 | /* Start discovery */ | 2535 | |
2542 | lpfc_disc_start(vport); | 2536 | /* ReStart discovery */ |
2543 | break; | 2537 | goto restart_disc; |
2544 | 2538 | ||
2545 | case LPFC_NS_QRY: | 2539 | case LPFC_NS_QRY: |
2546 | /* Check for wait for NameServer Rsp timeout */ | 2540 | /* Check for wait for NameServer Rsp timeout */ |
@@ -2559,6 +2553,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2559 | } | 2553 | } |
2560 | vport->fc_ns_retry = 0; | 2554 | vport->fc_ns_retry = 0; |
2561 | 2555 | ||
2556 | restart_disc: | ||
2562 | /* | 2557 | /* |
2563 | * Discovery is over. | 2558 | * Discovery is over. |
2564 | * set port_state to PORT_READY if SLI2. | 2559 | * set port_state to PORT_READY if SLI2. |
@@ -2731,8 +2726,7 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) | |||
2731 | struct lpfc_nodelist *ndlp; | 2726 | struct lpfc_nodelist *ndlp; |
2732 | 2727 | ||
2733 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { | 2728 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { |
2734 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE && | 2729 | if (filter(ndlp, param)) |
2735 | filter(ndlp, param)) | ||
2736 | return ndlp; | 2730 | return ndlp; |
2737 | } | 2731 | } |
2738 | return NULL; | 2732 | return NULL; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 729694d97597..ceb185fa3216 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1334,15 +1334,35 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) | |||
1334 | kfree(HashWorking); | 1334 | kfree(HashWorking); |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | static void | 1337 | void |
1338 | lpfc_cleanup(struct lpfc_vport *vport) | 1338 | lpfc_cleanup(struct lpfc_vport *vport) |
1339 | { | 1339 | { |
1340 | struct lpfc_hba *phba = vport->phba; | ||
1340 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1341 | struct lpfc_nodelist *ndlp, *next_ndlp; |
1341 | 1342 | ||
1342 | /* clean up phba - lpfc specific */ | 1343 | if (phba->link_state > LPFC_LINK_DOWN) |
1343 | lpfc_can_disctmo(vport); | 1344 | lpfc_port_link_failure(vport); |
1344 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) | 1345 | |
1345 | lpfc_nlp_put(ndlp); | 1346 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { |
1347 | if (ndlp->nlp_type & NLP_FABRIC) | ||
1348 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
1349 | NLP_EVT_DEVICE_RECOVERY); | ||
1350 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
1351 | NLP_EVT_DEVICE_RM); | ||
1352 | } | ||
1353 | |||
1354 | /* At this point, ALL ndlp's should be gone */ | ||
1355 | while (!list_empty(&vport->fc_nodes)) { | ||
1356 | |||
1357 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | ||
1358 | nlp_listp) { | ||
1359 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
1360 | "0233 Nodelist x%x not free: %d\n", | ||
1361 | ndlp->nlp_DID, | ||
1362 | atomic_read(&ndlp->kref.refcount)); | ||
1363 | lpfc_drop_node(vport, ndlp); | ||
1364 | } | ||
1365 | } | ||
1346 | return; | 1366 | return; |
1347 | } | 1367 | } |
1348 | 1368 | ||
@@ -1463,6 +1483,8 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
1463 | { | 1483 | { |
1464 | struct lpfc_vport *vport = phba->pport; | 1484 | struct lpfc_vport *vport = phba->pport; |
1465 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1485 | struct lpfc_nodelist *ndlp, *next_ndlp; |
1486 | struct lpfc_vport **vports; | ||
1487 | int i; | ||
1466 | 1488 | ||
1467 | if (vport->fc_flag & FC_OFFLINE_MODE) | 1489 | if (vport->fc_flag & FC_OFFLINE_MODE) |
1468 | return; | 1490 | return; |
@@ -1471,10 +1493,32 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
1471 | 1493 | ||
1472 | lpfc_linkdown(phba); | 1494 | lpfc_linkdown(phba); |
1473 | 1495 | ||
1474 | /* Issue an unreg_login to all nodes */ | 1496 | /* Issue an unreg_login to all nodes on all vports */ |
1475 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) | 1497 | vports = lpfc_create_vport_work_array(phba); |
1476 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) | 1498 | if (vports != NULL) { |
1477 | lpfc_unreg_rpi(vport, ndlp); | 1499 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { |
1500 | struct Scsi_Host *shost; | ||
1501 | |||
1502 | shost = lpfc_shost_from_vport(vports[i]); | ||
1503 | list_for_each_entry_safe(ndlp, next_ndlp, | ||
1504 | &vports[i]->fc_nodes, | ||
1505 | nlp_listp) { | ||
1506 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
1507 | continue; | ||
1508 | if (ndlp->nlp_type & NLP_FABRIC) { | ||
1509 | lpfc_disc_state_machine(vports[i], ndlp, | ||
1510 | NULL, NLP_EVT_DEVICE_RECOVERY); | ||
1511 | lpfc_disc_state_machine(vports[i], ndlp, | ||
1512 | NULL, NLP_EVT_DEVICE_RM); | ||
1513 | } | ||
1514 | spin_lock_irq(shost->host_lock); | ||
1515 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | ||
1516 | spin_unlock_irq(shost->host_lock); | ||
1517 | lpfc_unreg_rpi(vports[i], ndlp); | ||
1518 | } | ||
1519 | } | ||
1520 | } | ||
1521 | lpfc_destroy_vport_work_array(vports); | ||
1478 | 1522 | ||
1479 | lpfc_sli_flush_mbox_queue(phba); | 1523 | lpfc_sli_flush_mbox_queue(phba); |
1480 | } | 1524 | } |
@@ -1508,7 +1552,6 @@ lpfc_offline(struct lpfc_hba *phba) | |||
1508 | if (vports != NULL) | 1552 | if (vports != NULL) |
1509 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1553 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { |
1510 | shost = lpfc_shost_from_vport(vports[i]); | 1554 | shost = lpfc_shost_from_vport(vports[i]); |
1511 | lpfc_cleanup(vports[i]); | ||
1512 | spin_lock_irq(shost->host_lock); | 1555 | spin_lock_irq(shost->host_lock); |
1513 | vports[i]->work_port_events = 0; | 1556 | vports[i]->work_port_events = 0; |
1514 | vports[i]->fc_flag |= FC_OFFLINE_MODE; | 1557 | vports[i]->fc_flag |= FC_OFFLINE_MODE; |
@@ -2061,6 +2104,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2061 | 2104 | ||
2062 | fc_remove_host(shost); | 2105 | fc_remove_host(shost); |
2063 | scsi_remove_host(shost); | 2106 | scsi_remove_host(shost); |
2107 | lpfc_cleanup(vport); | ||
2108 | |||
2064 | /* | 2109 | /* |
2065 | * Bring down the SLI Layer. This step disable all interrupts, | 2110 | * Bring down the SLI Layer. This step disable all interrupts, |
2066 | * clears the rings, discards all mailbox commands, and resets | 2111 | * clears the rings, discards all mailbox commands, and resets |
@@ -2075,7 +2120,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2075 | spin_unlock_irq(&phba->hbalock); | 2120 | spin_unlock_irq(&phba->hbalock); |
2076 | 2121 | ||
2077 | lpfc_debugfs_terminate(vport); | 2122 | lpfc_debugfs_terminate(vport); |
2078 | lpfc_cleanup(vport); | ||
2079 | 2123 | ||
2080 | kthread_stop(phba->worker_thread); | 2124 | kthread_stop(phba->worker_thread); |
2081 | 2125 | ||
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 1a16ee9b2e87..bba1fb6103f6 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -406,6 +406,41 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
406 | ndlp, mbox); | 406 | ndlp, mbox); |
407 | return 1; | 407 | return 1; |
408 | } | 408 | } |
409 | |||
410 | /* If the remote NPort logs into us, before we can initiate | ||
411 | * discovery to them, cleanup the NPort from discovery accordingly. | ||
412 | */ | ||
413 | if (ndlp->nlp_state == NLP_STE_NPR_NODE) { | ||
414 | spin_lock_irq(shost->host_lock); | ||
415 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | ||
416 | spin_unlock_irq(shost->host_lock); | ||
417 | del_timer_sync(&ndlp->nlp_delayfunc); | ||
418 | ndlp->nlp_last_elscmd = 0; | ||
419 | |||
420 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | ||
421 | list_del_init(&ndlp->els_retry_evt.evt_listp); | ||
422 | |||
423 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
424 | spin_lock_irq(shost->host_lock); | ||
425 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
426 | spin_unlock_irq(shost->host_lock); | ||
427 | if (vport->num_disc_nodes) { | ||
428 | /* Check to see if there are more | ||
429 | * PLOGIs to be sent | ||
430 | */ | ||
431 | lpfc_more_plogi(vport); | ||
432 | |||
433 | if (vport->num_disc_nodes == 0) { | ||
434 | spin_lock_irq(shost->host_lock); | ||
435 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
436 | spin_unlock_irq(shost->host_lock); | ||
437 | lpfc_can_disctmo(vport); | ||
438 | lpfc_end_rscn(vport); | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | |||
409 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); | 444 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); |
410 | return 1; | 445 | return 1; |
411 | 446 | ||
@@ -500,12 +535,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
500 | spin_unlock_irq(shost->host_lock); | 535 | spin_unlock_irq(shost->host_lock); |
501 | 536 | ||
502 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 537 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
503 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
504 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
505 | } else { | ||
506 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
507 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
508 | } | 538 | } |
539 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
540 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
509 | 541 | ||
510 | spin_lock_irq(shost->host_lock); | 542 | spin_lock_irq(shost->host_lock); |
511 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 543 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
@@ -593,6 +625,25 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
593 | return ndlp->nlp_state; | 625 | return ndlp->nlp_state; |
594 | } | 626 | } |
595 | 627 | ||
628 | static uint32_t | ||
629 | lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
630 | void *arg, uint32_t evt) | ||
631 | { | ||
632 | /* This transition is only legal if we previously | ||
633 | * rcv'ed a PLOGI. Since we don't want 2 discovery threads | ||
634 | * working on the same NPortID, do nothing for this thread | ||
635 | * to stop it. | ||
636 | */ | ||
637 | if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) { | ||
638 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
639 | "0253 Illegal State Transition: node x%x " | ||
640 | "event x%x, state x%x Data: x%x x%x\n", | ||
641 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, | ||
642 | ndlp->nlp_flag); | ||
643 | } | ||
644 | return ndlp->nlp_state; | ||
645 | } | ||
646 | |||
596 | /* Start of Discovery State Machine routines */ | 647 | /* Start of Discovery State Machine routines */ |
597 | 648 | ||
598 | static uint32_t | 649 | static uint32_t |
@@ -604,11 +655,8 @@ lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
604 | cmdiocb = (struct lpfc_iocbq *) arg; | 655 | cmdiocb = (struct lpfc_iocbq *) arg; |
605 | 656 | ||
606 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { | 657 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
607 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | ||
608 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
609 | return ndlp->nlp_state; | 658 | return ndlp->nlp_state; |
610 | } | 659 | } |
611 | lpfc_drop_node(vport, ndlp); | ||
612 | return NLP_STE_FREED_NODE; | 660 | return NLP_STE_FREED_NODE; |
613 | } | 661 | } |
614 | 662 | ||
@@ -617,7 +665,6 @@ lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
617 | void *arg, uint32_t evt) | 665 | void *arg, uint32_t evt) |
618 | { | 666 | { |
619 | lpfc_issue_els_logo(vport, ndlp, 0); | 667 | lpfc_issue_els_logo(vport, ndlp, 0); |
620 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
621 | return ndlp->nlp_state; | 668 | return ndlp->nlp_state; |
622 | } | 669 | } |
623 | 670 | ||
@@ -632,7 +679,6 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
632 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 679 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
633 | spin_unlock_irq(shost->host_lock); | 680 | spin_unlock_irq(shost->host_lock); |
634 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 681 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
635 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
636 | 682 | ||
637 | return ndlp->nlp_state; | 683 | return ndlp->nlp_state; |
638 | } | 684 | } |
@@ -641,7 +687,6 @@ static uint32_t | |||
641 | lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 687 | lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
642 | void *arg, uint32_t evt) | 688 | void *arg, uint32_t evt) |
643 | { | 689 | { |
644 | lpfc_drop_node(vport, ndlp); | ||
645 | return NLP_STE_FREED_NODE; | 690 | return NLP_STE_FREED_NODE; |
646 | } | 691 | } |
647 | 692 | ||
@@ -649,7 +694,6 @@ static uint32_t | |||
649 | lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 694 | lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
650 | void *arg, uint32_t evt) | 695 | void *arg, uint32_t evt) |
651 | { | 696 | { |
652 | lpfc_drop_node(vport, ndlp); | ||
653 | return NLP_STE_FREED_NODE; | 697 | return NLP_STE_FREED_NODE; |
654 | } | 698 | } |
655 | 699 | ||
@@ -864,7 +908,7 @@ out: | |||
864 | 908 | ||
865 | /* Free this node since the driver cannot login or has the wrong | 909 | /* Free this node since the driver cannot login or has the wrong |
866 | sparm */ | 910 | sparm */ |
867 | lpfc_drop_node(vport, ndlp); | 911 | lpfc_nlp_not_used(ndlp); |
868 | return NLP_STE_FREED_NODE; | 912 | return NLP_STE_FREED_NODE; |
869 | } | 913 | } |
870 | 914 | ||
@@ -1195,8 +1239,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1195 | * retry discovery. | 1239 | * retry discovery. |
1196 | */ | 1240 | */ |
1197 | if (mb->mbxStatus == MBXERR_RPI_FULL) { | 1241 | if (mb->mbxStatus == MBXERR_RPI_FULL) { |
1198 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | 1242 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1199 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1243 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1200 | return ndlp->nlp_state; | 1244 | return ndlp->nlp_state; |
1201 | } | 1245 | } |
1202 | 1246 | ||
@@ -1376,7 +1420,7 @@ out: | |||
1376 | lpfc_issue_els_logo(vport, ndlp, 0); | 1420 | lpfc_issue_els_logo(vport, ndlp, 0); |
1377 | 1421 | ||
1378 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1422 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1379 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1423 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1380 | return ndlp->nlp_state; | 1424 | return ndlp->nlp_state; |
1381 | } | 1425 | } |
1382 | 1426 | ||
@@ -1751,7 +1795,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1751 | 1795 | ||
1752 | irsp = &rspiocb->iocb; | 1796 | irsp = &rspiocb->iocb; |
1753 | if (irsp->ulpStatus) { | 1797 | if (irsp->ulpStatus) { |
1754 | lpfc_drop_node(vport, ndlp); | 1798 | lpfc_nlp_not_used(ndlp); |
1755 | return NLP_STE_FREED_NODE; | 1799 | return NLP_STE_FREED_NODE; |
1756 | } | 1800 | } |
1757 | return ndlp->nlp_state; | 1801 | return ndlp->nlp_state; |
@@ -1966,7 +2010,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1966 | lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */ | 2010 | lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */ |
1967 | lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */ | 2011 | lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */ |
1968 | lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */ | 2012 | lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */ |
1969 | lpfc_disc_illegal, /* CMPL_PLOGI */ | 2013 | lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */ |
1970 | lpfc_disc_illegal, /* CMPL_PRLI */ | 2014 | lpfc_disc_illegal, /* CMPL_PRLI */ |
1971 | lpfc_disc_illegal, /* CMPL_LOGO */ | 2015 | lpfc_disc_illegal, /* CMPL_LOGO */ |
1972 | lpfc_disc_illegal, /* CMPL_ADISC */ | 2016 | lpfc_disc_illegal, /* CMPL_ADISC */ |
@@ -1980,7 +2024,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1980 | lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */ | 2024 | lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */ |
1981 | lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */ | 2025 | lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */ |
1982 | lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */ | 2026 | lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */ |
1983 | lpfc_disc_illegal, /* CMPL_PLOGI */ | 2027 | lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */ |
1984 | lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */ | 2028 | lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */ |
1985 | lpfc_disc_illegal, /* CMPL_LOGO */ | 2029 | lpfc_disc_illegal, /* CMPL_LOGO */ |
1986 | lpfc_disc_illegal, /* CMPL_ADISC */ | 2030 | lpfc_disc_illegal, /* CMPL_ADISC */ |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index fd07d9d7f507..378c01200b02 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -445,7 +445,6 @@ int | |||
445 | lpfc_vport_delete(struct fc_vport *fc_vport) | 445 | lpfc_vport_delete(struct fc_vport *fc_vport) |
446 | { | 446 | { |
447 | struct lpfc_nodelist *ndlp = NULL; | 447 | struct lpfc_nodelist *ndlp = NULL; |
448 | struct lpfc_nodelist *next_ndlp; | ||
449 | struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost; | 448 | struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost; |
450 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | 449 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; |
451 | struct lpfc_hba *phba = vport->phba; | 450 | struct lpfc_hba *phba = vport->phba; |
@@ -531,23 +530,20 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
531 | } | 530 | } |
532 | 531 | ||
533 | skip_logo: | 532 | skip_logo: |
533 | lpfc_cleanup(vport); | ||
534 | lpfc_sli_host_down(vport); | 534 | lpfc_sli_host_down(vport); |
535 | 535 | ||
536 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { | ||
537 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
538 | NLP_EVT_DEVICE_RECOVERY); | ||
539 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
540 | NLP_EVT_DEVICE_RM); | ||
541 | } | ||
542 | |||
543 | lpfc_stop_vport_timers(vport); | 536 | lpfc_stop_vport_timers(vport); |
544 | lpfc_unreg_all_rpis(vport); | 537 | lpfc_unreg_all_rpis(vport); |
545 | lpfc_unreg_default_rpis(vport); | 538 | |
546 | /* | 539 | if (!(phba->pport->load_flag & FC_UNLOADING)) { |
547 | * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the | 540 | lpfc_unreg_default_rpis(vport); |
548 | * scsi_host_put() to release the vport. | 541 | /* |
549 | */ | 542 | * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) |
550 | lpfc_mbx_unreg_vpi(vport); | 543 | * does the scsi_host_put() to release the vport. |
544 | */ | ||
545 | lpfc_mbx_unreg_vpi(vport); | ||
546 | } | ||
551 | 547 | ||
552 | lpfc_free_vpi(phba, vport->vpi); | 548 | lpfc_free_vpi(phba, vport->vpi); |
553 | vport->work_port_events = 0; | 549 | vport->work_port_events = 0; |