diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:33 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
commit | 98c9ea5c026ee47efe2a0f595078dbf199d08f50 (patch) | |
tree | 4d07a863ed26b1d3efec0d198ce456e20fad3954 /drivers | |
parent | 0b727fea7a700e223bf52fb1eaf4c3a27c4340db (diff) |
[SCSI] lpfc 8.2.3 : Miscellaneous Small Fixes - part 1
Miscellaneous Small Fixes - part 1
- Fix typo kmzlloc -> kzalloc
- Fix discovery ndlp use after free panic
- Fix link event causing flood of 0108 messages
- Relieve some mbox congestion on link up with 100 vports
- Fix broken vport parameters
- Prevent lock recursion in logo_reglogin_issue
- Split uses of error variable in lpfc_pci_probe_one into retval and error
- Remove completion code related to dev_loss_tmo
- Remove unused LPFC_MAX_HBQ #define
- Don't compare pointers to 0 for sparse
- Make 2 functions static for sparse
- Fix default rpi cleanup code causing rogue ndlps to remain on the NPR list
- Remove annoying ELS messages when driver is unloaded
- Fix Cannot issue Register Fabric login problems on link up
- Remove LPFC_EVT_DEV_LOSS_DELAY
- Fix FC port swap test leads to device going offline
- Fix vport CT flags to only be set when accepted
- Add code to handle signals during vport_create
- Fix too many retries in FC-AL mode
- Pull lpfc_port_link_failure out of lpfc_linkdown_port
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 62 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 62 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 154 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 123 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 42 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 46 |
12 files changed, 372 insertions, 148 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 356dede9cd65..e8e9905828c9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -2363,13 +2363,67 @@ struct fc_function_template lpfc_transport_functions = { | |||
2363 | .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, | 2363 | .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, |
2364 | .terminate_rport_io = lpfc_terminate_rport_io, | 2364 | .terminate_rport_io = lpfc_terminate_rport_io, |
2365 | 2365 | ||
2366 | /* Vport fields are filled in at runtime based on enable_npiv */ | ||
2367 | .vport_create = NULL, | ||
2368 | .vport_delete = NULL, | ||
2369 | .vport_disable = NULL, | ||
2370 | .dd_fcvport_size = sizeof(struct lpfc_vport *), | 2366 | .dd_fcvport_size = sizeof(struct lpfc_vport *), |
2371 | }; | 2367 | }; |
2372 | 2368 | ||
2369 | struct fc_function_template lpfc_vport_transport_functions = { | ||
2370 | /* fixed attributes the driver supports */ | ||
2371 | .show_host_node_name = 1, | ||
2372 | .show_host_port_name = 1, | ||
2373 | .show_host_supported_classes = 1, | ||
2374 | .show_host_supported_fc4s = 1, | ||
2375 | .show_host_supported_speeds = 1, | ||
2376 | .show_host_maxframe_size = 1, | ||
2377 | |||
2378 | /* dynamic attributes the driver supports */ | ||
2379 | .get_host_port_id = lpfc_get_host_port_id, | ||
2380 | .show_host_port_id = 1, | ||
2381 | |||
2382 | .get_host_port_type = lpfc_get_host_port_type, | ||
2383 | .show_host_port_type = 1, | ||
2384 | |||
2385 | .get_host_port_state = lpfc_get_host_port_state, | ||
2386 | .show_host_port_state = 1, | ||
2387 | |||
2388 | /* active_fc4s is shown but doesn't change (thus no get function) */ | ||
2389 | .show_host_active_fc4s = 1, | ||
2390 | |||
2391 | .get_host_speed = lpfc_get_host_speed, | ||
2392 | .show_host_speed = 1, | ||
2393 | |||
2394 | .get_host_fabric_name = lpfc_get_host_fabric_name, | ||
2395 | .show_host_fabric_name = 1, | ||
2396 | |||
2397 | /* | ||
2398 | * The LPFC driver treats linkdown handling as target loss events | ||
2399 | * so there are no sysfs handlers for link_down_tmo. | ||
2400 | */ | ||
2401 | |||
2402 | .get_fc_host_stats = lpfc_get_stats, | ||
2403 | .reset_fc_host_stats = lpfc_reset_stats, | ||
2404 | |||
2405 | .dd_fcrport_size = sizeof(struct lpfc_rport_data), | ||
2406 | .show_rport_maxframe_size = 1, | ||
2407 | .show_rport_supported_classes = 1, | ||
2408 | |||
2409 | .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo, | ||
2410 | .show_rport_dev_loss_tmo = 1, | ||
2411 | |||
2412 | .get_starget_port_id = lpfc_get_starget_port_id, | ||
2413 | .show_starget_port_id = 1, | ||
2414 | |||
2415 | .get_starget_node_name = lpfc_get_starget_node_name, | ||
2416 | .show_starget_node_name = 1, | ||
2417 | |||
2418 | .get_starget_port_name = lpfc_get_starget_port_name, | ||
2419 | .show_starget_port_name = 1, | ||
2420 | |||
2421 | .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, | ||
2422 | .terminate_rport_io = lpfc_terminate_rport_io, | ||
2423 | |||
2424 | .vport_disable = lpfc_vport_disable, | ||
2425 | }; | ||
2426 | |||
2373 | void | 2427 | void |
2374 | lpfc_get_cfgparam(struct lpfc_hba *phba) | 2428 | lpfc_get_cfgparam(struct lpfc_hba *phba) |
2375 | { | 2429 | { |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index be4b6584167a..59164c6aa28f 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -68,6 +68,7 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, | |||
68 | void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t); | 68 | void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t); |
69 | struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); | 69 | struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); |
70 | int lpfc_nlp_put(struct lpfc_nodelist *); | 70 | int lpfc_nlp_put(struct lpfc_nodelist *); |
71 | int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); | ||
71 | struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t); | 72 | struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t); |
72 | void lpfc_disc_list_loopmap(struct lpfc_vport *); | 73 | void lpfc_disc_list_loopmap(struct lpfc_vport *); |
73 | void lpfc_disc_start(struct lpfc_vport *); | 74 | void lpfc_disc_start(struct lpfc_vport *); |
@@ -260,6 +261,7 @@ extern struct class_device_attribute *lpfc_vport_attrs[]; | |||
260 | extern struct scsi_host_template lpfc_template; | 261 | extern struct scsi_host_template lpfc_template; |
261 | extern struct scsi_host_template lpfc_vport_template; | 262 | extern struct scsi_host_template lpfc_vport_template; |
262 | extern struct fc_function_template lpfc_transport_functions; | 263 | extern struct fc_function_template lpfc_transport_functions; |
264 | extern struct fc_function_template lpfc_vport_transport_functions; | ||
263 | extern int lpfc_sli_mode; | 265 | extern int lpfc_sli_mode; |
264 | extern int lpfc_enable_npiv; | 266 | extern int lpfc_enable_npiv; |
265 | 267 | ||
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index dbe020e66b09..e8bd7c122f1e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -458,7 +458,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
458 | ((lpfc_find_vport_by_did(phba, Did) == NULL) || | 458 | ((lpfc_find_vport_by_did(phba, Did) == NULL) || |
459 | vport->cfg_peer_port_login)) { | 459 | vport->cfg_peer_port_login)) { |
460 | if ((vport->port_type != LPFC_NPIV_PORT) || | 460 | if ((vport->port_type != LPFC_NPIV_PORT) || |
461 | (!vport->ct_flags & FC_CT_RFF_ID) || | 461 | (!(vport->ct_flags & FC_CT_RFF_ID)) || |
462 | (!vport->cfg_restrict_login)) { | 462 | (!vport->cfg_restrict_login)) { |
463 | ndlp = lpfc_setup_disc_node(vport, Did); | 463 | ndlp = lpfc_setup_disc_node(vport, Did); |
464 | if (ndlp) { | 464 | if (ndlp) { |
@@ -854,8 +854,16 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
854 | IOCB_t *irsp = &rspiocb->iocb; | 854 | IOCB_t *irsp = &rspiocb->iocb; |
855 | struct lpfc_vport *vport = cmdiocb->vport; | 855 | struct lpfc_vport *vport = cmdiocb->vport; |
856 | 856 | ||
857 | if (irsp->ulpStatus == IOSTAT_SUCCESS) | 857 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
858 | vport->ct_flags |= FC_CT_RFT_ID; | 858 | struct lpfc_dmabuf *outp; |
859 | struct lpfc_sli_ct_request *CTrsp; | ||
860 | |||
861 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
862 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
863 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
864 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) | ||
865 | vport->ct_flags |= FC_CT_RFT_ID; | ||
866 | } | ||
859 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); | 867 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); |
860 | return; | 868 | return; |
861 | } | 869 | } |
@@ -867,8 +875,16 @@ lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
867 | IOCB_t *irsp = &rspiocb->iocb; | 875 | IOCB_t *irsp = &rspiocb->iocb; |
868 | struct lpfc_vport *vport = cmdiocb->vport; | 876 | struct lpfc_vport *vport = cmdiocb->vport; |
869 | 877 | ||
870 | if (irsp->ulpStatus == IOSTAT_SUCCESS) | 878 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
871 | vport->ct_flags |= FC_CT_RNN_ID; | 879 | struct lpfc_dmabuf *outp; |
880 | struct lpfc_sli_ct_request *CTrsp; | ||
881 | |||
882 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
883 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
884 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
885 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) | ||
886 | vport->ct_flags |= FC_CT_RNN_ID; | ||
887 | } | ||
872 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); | 888 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); |
873 | return; | 889 | return; |
874 | } | 890 | } |
@@ -880,8 +896,16 @@ lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
880 | IOCB_t *irsp = &rspiocb->iocb; | 896 | IOCB_t *irsp = &rspiocb->iocb; |
881 | struct lpfc_vport *vport = cmdiocb->vport; | 897 | struct lpfc_vport *vport = cmdiocb->vport; |
882 | 898 | ||
883 | if (irsp->ulpStatus == IOSTAT_SUCCESS) | 899 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
884 | vport->ct_flags |= FC_CT_RSPN_ID; | 900 | struct lpfc_dmabuf *outp; |
901 | struct lpfc_sli_ct_request *CTrsp; | ||
902 | |||
903 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
904 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
905 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
906 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) | ||
907 | vport->ct_flags |= FC_CT_RSPN_ID; | ||
908 | } | ||
885 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); | 909 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); |
886 | return; | 910 | return; |
887 | } | 911 | } |
@@ -893,8 +917,16 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
893 | IOCB_t *irsp = &rspiocb->iocb; | 917 | IOCB_t *irsp = &rspiocb->iocb; |
894 | struct lpfc_vport *vport = cmdiocb->vport; | 918 | struct lpfc_vport *vport = cmdiocb->vport; |
895 | 919 | ||
896 | if (irsp->ulpStatus == IOSTAT_SUCCESS) | 920 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
897 | vport->ct_flags |= FC_CT_RSNN_NN; | 921 | struct lpfc_dmabuf *outp; |
922 | struct lpfc_sli_ct_request *CTrsp; | ||
923 | |||
924 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
925 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
926 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
927 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) | ||
928 | vport->ct_flags |= FC_CT_RSNN_NN; | ||
929 | } | ||
898 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); | 930 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); |
899 | return; | 931 | return; |
900 | } | 932 | } |
@@ -918,8 +950,16 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
918 | IOCB_t *irsp = &rspiocb->iocb; | 950 | IOCB_t *irsp = &rspiocb->iocb; |
919 | struct lpfc_vport *vport = cmdiocb->vport; | 951 | struct lpfc_vport *vport = cmdiocb->vport; |
920 | 952 | ||
921 | if (irsp->ulpStatus == IOSTAT_SUCCESS) | 953 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
922 | vport->ct_flags |= FC_CT_RFF_ID; | 954 | struct lpfc_dmabuf *outp; |
955 | struct lpfc_sli_ct_request *CTrsp; | ||
956 | |||
957 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
958 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
959 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
960 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) | ||
961 | vport->ct_flags |= FC_CT_RFF_ID; | ||
962 | } | ||
923 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); | 963 | lpfc_cmpl_ct(phba, cmdiocb, rspiocb); |
924 | return; | 964 | return; |
925 | } | 965 | } |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index aacac9ac5381..c9422a8423ca 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -36,7 +36,6 @@ enum lpfc_work_type { | |||
36 | LPFC_EVT_WARM_START, | 36 | LPFC_EVT_WARM_START, |
37 | LPFC_EVT_KILL, | 37 | LPFC_EVT_KILL, |
38 | LPFC_EVT_ELS_RETRY, | 38 | LPFC_EVT_ELS_RETRY, |
39 | LPFC_EVT_DEV_LOSS_DELAY, | ||
40 | LPFC_EVT_DEV_LOSS, | 39 | LPFC_EVT_DEV_LOSS, |
41 | }; | 40 | }; |
42 | 41 | ||
@@ -104,6 +103,7 @@ struct lpfc_nodelist { | |||
104 | #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 */ |
105 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 104 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ |
106 | #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 | 107 | ||
108 | /* There are 4 different double linked lists nodelist entries can reside on. | 108 | /* 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 | 109 | * 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 b73612d4fc53..813eeca7ce1e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -109,9 +109,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
109 | 109 | ||
110 | /* fill in BDEs for command */ | 110 | /* fill in BDEs for command */ |
111 | /* Allocate buffer for command payload */ | 111 | /* Allocate buffer for command payload */ |
112 | if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) || | 112 | pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
113 | ((pcmd->virt = lpfc_mbuf_alloc(phba, | 113 | if (pcmd) |
114 | MEM_PRI, &(pcmd->phys))) == 0)) { | 114 | pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys); |
115 | if (!pcmd || !pcmd->virt) { | ||
115 | kfree(pcmd); | 116 | kfree(pcmd); |
116 | 117 | ||
117 | lpfc_sli_release_iocbq(phba, elsiocb); | 118 | lpfc_sli_release_iocbq(phba, elsiocb); |
@@ -126,7 +127,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
126 | if (prsp) | 127 | if (prsp) |
127 | prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 128 | prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
128 | &prsp->phys); | 129 | &prsp->phys); |
129 | if (prsp == 0 || prsp->virt == 0) { | 130 | if (!prsp || !prsp->virt) { |
130 | kfree(prsp); | 131 | kfree(prsp); |
131 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 132 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
132 | kfree(pcmd); | 133 | kfree(pcmd); |
@@ -143,7 +144,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
143 | if (pbuflist) | 144 | if (pbuflist) |
144 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 145 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
145 | &pbuflist->phys); | 146 | &pbuflist->phys); |
146 | if (pbuflist == 0 || pbuflist->virt == 0) { | 147 | if (!pbuflist || !pbuflist->virt) { |
147 | lpfc_sli_release_iocbq(phba, elsiocb); | 148 | lpfc_sli_release_iocbq(phba, elsiocb); |
148 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 149 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
149 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); | 150 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); |
@@ -234,15 +235,20 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | |||
234 | struct lpfc_nodelist *ndlp; | 235 | struct lpfc_nodelist *ndlp; |
235 | struct serv_parm *sp; | 236 | struct serv_parm *sp; |
236 | int rc; | 237 | int rc; |
238 | int err = 0; | ||
237 | 239 | ||
238 | sp = &phba->fc_fabparam; | 240 | sp = &phba->fc_fabparam; |
239 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 241 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
240 | if (!ndlp) | 242 | if (!ndlp) { |
243 | err = 1; | ||
241 | goto fail; | 244 | goto fail; |
245 | } | ||
242 | 246 | ||
243 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 247 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
244 | if (!mbox) | 248 | if (!mbox) { |
249 | err = 2; | ||
245 | goto fail; | 250 | goto fail; |
251 | } | ||
246 | 252 | ||
247 | vport->port_state = LPFC_FABRIC_CFG_LINK; | 253 | vport->port_state = LPFC_FABRIC_CFG_LINK; |
248 | lpfc_config_link(phba, mbox); | 254 | lpfc_config_link(phba, mbox); |
@@ -250,24 +256,32 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | |||
250 | mbox->vport = vport; | 256 | mbox->vport = vport; |
251 | 257 | ||
252 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 258 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
253 | if (rc == MBX_NOT_FINISHED) | 259 | if (rc == MBX_NOT_FINISHED) { |
260 | err = 3; | ||
254 | goto fail_free_mbox; | 261 | goto fail_free_mbox; |
262 | } | ||
255 | 263 | ||
256 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 264 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
257 | if (!mbox) | 265 | if (!mbox) { |
266 | err = 4; | ||
258 | goto fail; | 267 | goto fail; |
268 | } | ||
259 | rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, | 269 | rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, |
260 | 0); | 270 | 0); |
261 | if (rc) | 271 | if (rc) { |
272 | err = 5; | ||
262 | goto fail_free_mbox; | 273 | goto fail_free_mbox; |
274 | } | ||
263 | 275 | ||
264 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; | 276 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; |
265 | mbox->vport = vport; | 277 | mbox->vport = vport; |
266 | mbox->context2 = lpfc_nlp_get(ndlp); | 278 | mbox->context2 = lpfc_nlp_get(ndlp); |
267 | 279 | ||
268 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 280 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
269 | if (rc == MBX_NOT_FINISHED) | 281 | if (rc == MBX_NOT_FINISHED) { |
282 | err = 6; | ||
270 | goto fail_issue_reg_login; | 283 | goto fail_issue_reg_login; |
284 | } | ||
271 | 285 | ||
272 | return 0; | 286 | return 0; |
273 | 287 | ||
@@ -282,7 +296,7 @@ fail_free_mbox: | |||
282 | fail: | 296 | fail: |
283 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 297 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
284 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 298 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
285 | "0249 Cannot issue Register Fabric login\n"); | 299 | "0249 Cannot issue Register Fabric login: Err %d\n", err); |
286 | return -ENXIO; | 300 | return -ENXIO; |
287 | } | 301 | } |
288 | 302 | ||
@@ -684,6 +698,9 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
684 | struct lpfc_hba *phba = vport->phba; | 698 | struct lpfc_hba *phba = vport->phba; |
685 | struct lpfc_nodelist *ndlp; | 699 | struct lpfc_nodelist *ndlp; |
686 | 700 | ||
701 | vport->port_state = LPFC_FLOGI; | ||
702 | lpfc_set_disctmo(vport); | ||
703 | |||
687 | /* First look for the Fabric ndlp */ | 704 | /* First look for the Fabric ndlp */ |
688 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 705 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
689 | if (!ndlp) { | 706 | if (!ndlp) { |
@@ -694,6 +711,12 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
694 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | 711 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
695 | } else { | 712 | } else { |
696 | lpfc_dequeue_node(vport, ndlp); | 713 | 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); | ||
697 | } | 720 | } |
698 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { | 721 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { |
699 | lpfc_nlp_put(ndlp); | 722 | lpfc_nlp_put(ndlp); |
@@ -932,6 +955,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) | |||
932 | struct lpfc_hba *phba = vport->phba; | 955 | struct lpfc_hba *phba = vport->phba; |
933 | struct serv_parm *sp; | 956 | struct serv_parm *sp; |
934 | IOCB_t *icmd; | 957 | IOCB_t *icmd; |
958 | struct lpfc_nodelist *ndlp; | ||
935 | struct lpfc_iocbq *elsiocb; | 959 | struct lpfc_iocbq *elsiocb; |
936 | struct lpfc_sli_ring *pring; | 960 | struct lpfc_sli_ring *pring; |
937 | struct lpfc_sli *psli; | 961 | struct lpfc_sli *psli; |
@@ -942,8 +966,11 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) | |||
942 | psli = &phba->sli; | 966 | psli = &phba->sli; |
943 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 967 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
944 | 968 | ||
969 | ndlp = lpfc_findnode_did(vport, did); | ||
970 | /* If ndlp if not NULL, we will bump the reference count on it */ | ||
971 | |||
945 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); | 972 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
946 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did, | 973 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, |
947 | ELS_CMD_PLOGI); | 974 | ELS_CMD_PLOGI); |
948 | if (!elsiocb) | 975 | if (!elsiocb) |
949 | return 1; | 976 | return 1; |
@@ -1412,6 +1439,13 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1412 | psli = &phba->sli; | 1439 | psli = &phba->sli; |
1413 | pring = &psli->ring[LPFC_ELS_RING]; | 1440 | pring = &psli->ring[LPFC_ELS_RING]; |
1414 | 1441 | ||
1442 | spin_lock_irq(shost->host_lock); | ||
1443 | if (ndlp->nlp_flag & NLP_LOGO_SND) { | ||
1444 | spin_unlock_irq(shost->host_lock); | ||
1445 | return 0; | ||
1446 | } | ||
1447 | spin_unlock_irq(shost->host_lock); | ||
1448 | |||
1415 | cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name); | 1449 | cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name); |
1416 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | 1450 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1417 | ndlp->nlp_DID, ELS_CMD_LOGO); | 1451 | ndlp->nlp_DID, ELS_CMD_LOGO); |
@@ -1758,6 +1792,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1758 | uint32_t *elscmd; | 1792 | uint32_t *elscmd; |
1759 | struct ls_rjt stat; | 1793 | struct ls_rjt stat; |
1760 | int retry = 0, maxretry = lpfc_max_els_tries, delay = 0; | 1794 | int retry = 0, maxretry = lpfc_max_els_tries, delay = 0; |
1795 | int logerr = 0; | ||
1761 | uint32_t cmd = 0; | 1796 | uint32_t cmd = 0; |
1762 | uint32_t did; | 1797 | uint32_t did; |
1763 | 1798 | ||
@@ -1814,6 +1849,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1814 | break; | 1849 | break; |
1815 | 1850 | ||
1816 | case IOERR_NO_RESOURCES: | 1851 | case IOERR_NO_RESOURCES: |
1852 | logerr = 1; /* HBA out of resources */ | ||
1817 | retry = 1; | 1853 | retry = 1; |
1818 | if (cmdiocb->retry > 100) | 1854 | if (cmdiocb->retry > 100) |
1819 | delay = 100; | 1855 | delay = 100; |
@@ -1842,6 +1878,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1842 | 1878 | ||
1843 | case IOSTAT_NPORT_BSY: | 1879 | case IOSTAT_NPORT_BSY: |
1844 | case IOSTAT_FABRIC_BSY: | 1880 | case IOSTAT_FABRIC_BSY: |
1881 | logerr = 1; /* Fabric / Remote NPort out of resources */ | ||
1845 | retry = 1; | 1882 | retry = 1; |
1846 | break; | 1883 | break; |
1847 | 1884 | ||
@@ -1922,6 +1959,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1922 | if (did == FDMI_DID) | 1959 | if (did == FDMI_DID) |
1923 | retry = 1; | 1960 | retry = 1; |
1924 | 1961 | ||
1962 | if ((cmd == ELS_CMD_FLOGI) && | ||
1963 | (phba->fc_topology != TOPOLOGY_LOOP)) { | ||
1964 | /* FLOGI retry policy */ | ||
1965 | retry = 1; | ||
1966 | maxretry = 48; | ||
1967 | if (cmdiocb->retry >= 32) | ||
1968 | delay = 1000; | ||
1969 | } | ||
1970 | |||
1925 | if ((++cmdiocb->retry) >= maxretry) { | 1971 | if ((++cmdiocb->retry) >= maxretry) { |
1926 | phba->fc_stat.elsRetryExceeded++; | 1972 | phba->fc_stat.elsRetryExceeded++; |
1927 | retry = 0; | 1973 | retry = 0; |
@@ -2005,11 +2051,20 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2005 | } | 2051 | } |
2006 | } | 2052 | } |
2007 | /* No retry ELS command <elsCmd> to remote NPORT <did> */ | 2053 | /* No retry ELS command <elsCmd> to remote NPORT <did> */ |
2008 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 2054 | if (logerr) { |
2055 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
2056 | "0137 No retry ELS command x%x to remote " | ||
2057 | "NPORT x%x: Out of Resources: Error:x%x/%x\n", | ||
2058 | cmd, did, irsp->ulpStatus, | ||
2059 | irsp->un.ulpWord[4]); | ||
2060 | } | ||
2061 | else { | ||
2062 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
2009 | "0108 No retry ELS command x%x to remote " | 2063 | "0108 No retry ELS command x%x to remote " |
2010 | "NPORT x%x Retried:%d Error:x%x/%x\n", | 2064 | "NPORT x%x Retried:%d Error:x%x/%x\n", |
2011 | cmd, did, cmdiocb->retry, irsp->ulpStatus, | 2065 | cmd, did, cmdiocb->retry, irsp->ulpStatus, |
2012 | irsp->un.ulpWord[4]); | 2066 | irsp->un.ulpWord[4]); |
2067 | } | ||
2013 | return 0; | 2068 | return 0; |
2014 | } | 2069 | } |
2015 | 2070 | ||
@@ -2089,6 +2144,12 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2089 | kfree(mp); | 2144 | kfree(mp); |
2090 | mempool_free(pmb, phba->mbox_mem_pool); | 2145 | mempool_free(pmb, phba->mbox_mem_pool); |
2091 | lpfc_nlp_put(ndlp); | 2146 | lpfc_nlp_put(ndlp); |
2147 | |||
2148 | /* This is the end of the default RPI cleanup logic for this | ||
2149 | * ndlp. If no other discovery threads are using this ndlp. | ||
2150 | * we should free all resources associated with it. | ||
2151 | */ | ||
2152 | lpfc_nlp_not_used(ndlp); | ||
2092 | return; | 2153 | return; |
2093 | } | 2154 | } |
2094 | 2155 | ||
@@ -2118,6 +2179,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2118 | } | 2179 | } |
2119 | mempool_free(mbox, phba->mbox_mem_pool); | 2180 | mempool_free(mbox, phba->mbox_mem_pool); |
2120 | } | 2181 | } |
2182 | if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI)) | ||
2183 | if (lpfc_nlp_not_used(ndlp)) | ||
2184 | ndlp = NULL; | ||
2121 | goto out; | 2185 | goto out; |
2122 | } | 2186 | } |
2123 | 2187 | ||
@@ -2153,15 +2217,22 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2153 | != MBX_NOT_FINISHED) { | 2217 | != MBX_NOT_FINISHED) { |
2154 | goto out; | 2218 | goto out; |
2155 | } | 2219 | } |
2156 | lpfc_nlp_put(ndlp); | 2220 | |
2157 | /* NOTE: we should have messages for unsuccessful | 2221 | /* ELS rsp: Cannot issue reg_login for <NPortid> */ |
2158 | reglogin */ | 2222 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
2223 | "0138 ELS rsp: Cannot issue reg_login for x%x " | ||
2224 | "Data: x%x x%x x%x\n", | ||
2225 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | ||
2226 | ndlp->nlp_rpi); | ||
2227 | |||
2228 | if (lpfc_nlp_not_used(ndlp)) | ||
2229 | ndlp = NULL; | ||
2159 | } else { | 2230 | } else { |
2160 | /* Do not drop node for lpfc_els_abort'ed ELS cmds */ | 2231 | /* Do not drop node for lpfc_els_abort'ed ELS cmds */ |
2161 | if (!lpfc_error_lost_link(irsp) && | 2232 | if (!lpfc_error_lost_link(irsp) && |
2162 | ndlp->nlp_flag & NLP_ACC_REGLOGIN) { | 2233 | ndlp->nlp_flag & NLP_ACC_REGLOGIN) { |
2163 | lpfc_drop_node(vport, ndlp); | 2234 | if (lpfc_nlp_not_used(ndlp)) |
2164 | ndlp = NULL; | 2235 | ndlp = NULL; |
2165 | } | 2236 | } |
2166 | } | 2237 | } |
2167 | mp = (struct lpfc_dmabuf *) mbox->context1; | 2238 | mp = (struct lpfc_dmabuf *) mbox->context1; |
@@ -2350,10 +2421,14 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2350 | /* If the node is in the UNUSED state, and we are sending | 2421 | /* If the node is in the UNUSED state, and we are sending |
2351 | * a reject, we are done with it. Release driver reference | 2422 | * a reject, we are done with it. Release driver reference |
2352 | * count here. The outstanding els will release its reference on | 2423 | * count here. The outstanding els will release its reference on |
2353 | * completion and the node can be freed then. | 2424 | * completion, as long as the ndlp stays in the UNUSED list, |
2425 | * and the node can be freed then. | ||
2354 | */ | 2426 | */ |
2355 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | 2427 | if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) && |
2428 | !(ndlp->nlp_flag & NLP_DELAYED_RM)) { | ||
2429 | ndlp->nlp_flag |= NLP_DELAYED_RM; | ||
2356 | lpfc_nlp_put(ndlp); | 2430 | lpfc_nlp_put(ndlp); |
2431 | } | ||
2357 | 2432 | ||
2358 | if (rc == IOCB_ERROR) { | 2433 | if (rc == IOCB_ERROR) { |
2359 | lpfc_els_free_iocb(phba, elsiocb); | 2434 | lpfc_els_free_iocb(phba, elsiocb); |
@@ -3466,8 +3541,6 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3466 | } | 3541 | } |
3467 | } | 3542 | } |
3468 | 3543 | ||
3469 | vport->port_state = LPFC_FLOGI; | ||
3470 | lpfc_set_disctmo(vport); | ||
3471 | lpfc_initial_flogi(vport); | 3544 | lpfc_initial_flogi(vport); |
3472 | return 0; | 3545 | return 0; |
3473 | } | 3546 | } |
@@ -3747,11 +3820,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3747 | goto dropit; | 3820 | goto dropit; |
3748 | 3821 | ||
3749 | lpfc_nlp_init(vport, ndlp, did); | 3822 | lpfc_nlp_init(vport, ndlp, did); |
3823 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
3750 | newnode = 1; | 3824 | newnode = 1; |
3751 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { | 3825 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { |
3752 | ndlp->nlp_type |= NLP_FABRIC; | 3826 | ndlp->nlp_type |= NLP_FABRIC; |
3753 | } | 3827 | } |
3754 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
3755 | } | 3828 | } |
3756 | 3829 | ||
3757 | phba->fc_stat.elsRcvFrame++; | 3830 | phba->fc_stat.elsRcvFrame++; |
@@ -3791,8 +3864,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3791 | 3864 | ||
3792 | phba->fc_stat.elsRcvFLOGI++; | 3865 | phba->fc_stat.elsRcvFLOGI++; |
3793 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); | 3866 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); |
3794 | if (newnode) | 3867 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3795 | lpfc_drop_node(vport, ndlp); | 3868 | lpfc_nlp_put(ndlp); |
3796 | break; | 3869 | break; |
3797 | case ELS_CMD_LOGO: | 3870 | case ELS_CMD_LOGO: |
3798 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3871 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3821,8 +3894,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3821 | case ELS_CMD_RSCN: | 3894 | case ELS_CMD_RSCN: |
3822 | phba->fc_stat.elsRcvRSCN++; | 3895 | phba->fc_stat.elsRcvRSCN++; |
3823 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); | 3896 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); |
3824 | if (newnode) | 3897 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3825 | lpfc_drop_node(vport, ndlp); | 3898 | lpfc_nlp_put(ndlp); |
3826 | break; | 3899 | break; |
3827 | case ELS_CMD_ADISC: | 3900 | case ELS_CMD_ADISC: |
3828 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3901 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3893,8 +3966,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3893 | 3966 | ||
3894 | phba->fc_stat.elsRcvLIRR++; | 3967 | phba->fc_stat.elsRcvLIRR++; |
3895 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); | 3968 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); |
3896 | if (newnode) | 3969 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3897 | lpfc_drop_node(vport, ndlp); | 3970 | lpfc_nlp_put(ndlp); |
3898 | break; | 3971 | break; |
3899 | case ELS_CMD_RPS: | 3972 | case ELS_CMD_RPS: |
3900 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3973 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3903,8 +3976,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3903 | 3976 | ||
3904 | phba->fc_stat.elsRcvRPS++; | 3977 | phba->fc_stat.elsRcvRPS++; |
3905 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); | 3978 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); |
3906 | if (newnode) | 3979 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3907 | lpfc_drop_node(vport, ndlp); | 3980 | lpfc_nlp_put(ndlp); |
3908 | break; | 3981 | break; |
3909 | case ELS_CMD_RPL: | 3982 | case ELS_CMD_RPL: |
3910 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3983 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3913,8 +3986,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3913 | 3986 | ||
3914 | phba->fc_stat.elsRcvRPL++; | 3987 | phba->fc_stat.elsRcvRPL++; |
3915 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); | 3988 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); |
3916 | if (newnode) | 3989 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3917 | lpfc_drop_node(vport, ndlp); | 3990 | lpfc_nlp_put(ndlp); |
3918 | break; | 3991 | break; |
3919 | case ELS_CMD_RNID: | 3992 | case ELS_CMD_RNID: |
3920 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3993 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3923,8 +3996,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3923 | 3996 | ||
3924 | phba->fc_stat.elsRcvRNID++; | 3997 | phba->fc_stat.elsRcvRNID++; |
3925 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); | 3998 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); |
3926 | if (newnode) | 3999 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3927 | lpfc_drop_node(vport, ndlp); | 4000 | lpfc_nlp_put(ndlp); |
3928 | break; | 4001 | break; |
3929 | default: | 4002 | default: |
3930 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 4003 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
@@ -3938,8 +4011,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3938 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 4011 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
3939 | "0115 Unknown ELS command x%x " | 4012 | "0115 Unknown ELS command x%x " |
3940 | "received from NPORT x%x\n", cmd, did); | 4013 | "received from NPORT x%x\n", cmd, did); |
3941 | if (newnode) | 4014 | if (newnode && (!(ndlp->nlp_flag & NLP_DELAYED_RM))) |
3942 | lpfc_drop_node(vport, ndlp); | 4015 | lpfc_nlp_put(ndlp); |
3943 | break; | 4016 | break; |
3944 | } | 4017 | } |
3945 | 4018 | ||
@@ -3955,10 +4028,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3955 | return; | 4028 | return; |
3956 | 4029 | ||
3957 | dropit: | 4030 | dropit: |
3958 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 4031 | if (vport && !(vport->load_flag & FC_UNLOADING)) |
4032 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
3959 | "(%d):0111 Dropping received ELS cmd " | 4033 | "(%d):0111 Dropping received ELS cmd " |
3960 | "Data: x%x x%x x%x\n", | 4034 | "Data: x%x x%x x%x\n", |
3961 | vport ? vport->vpi : 0xffff, icmd->ulpStatus, | 4035 | vport->vpi, icmd->ulpStatus, |
3962 | icmd->un.ulpWord[4], icmd->ulpTimeout); | 4036 | icmd->un.ulpWord[4], icmd->ulpTimeout); |
3963 | phba->fc_stat.elsRcvDrop++; | 4037 | phba->fc_stat.elsRcvDrop++; |
3964 | } | 4038 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 6f5bf8189950..e181a98caf16 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -107,7 +107,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
107 | struct lpfc_nodelist * ndlp; | 107 | struct lpfc_nodelist * ndlp; |
108 | struct lpfc_vport *vport; | 108 | struct lpfc_vport *vport; |
109 | struct lpfc_hba *phba; | 109 | struct lpfc_hba *phba; |
110 | struct completion devloss_compl; | ||
111 | struct lpfc_work_evt *evtp; | 110 | struct lpfc_work_evt *evtp; |
112 | 111 | ||
113 | rdata = rport->dd_data; | 112 | rdata = rport->dd_data; |
@@ -129,7 +128,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
129 | "rport devlosscb: sid:x%x did:x%x flg:x%x", | 128 | "rport devlosscb: sid:x%x did:x%x flg:x%x", |
130 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | 129 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); |
131 | 130 | ||
132 | init_completion(&devloss_compl); | ||
133 | evtp = &ndlp->dev_loss_evt; | 131 | evtp = &ndlp->dev_loss_evt; |
134 | 132 | ||
135 | if (!list_empty(&evtp->evt_listp)) | 133 | if (!list_empty(&evtp->evt_listp)) |
@@ -137,7 +135,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
137 | 135 | ||
138 | spin_lock_irq(&phba->hbalock); | 136 | spin_lock_irq(&phba->hbalock); |
139 | evtp->evt_arg1 = ndlp; | 137 | evtp->evt_arg1 = ndlp; |
140 | evtp->evt_arg2 = &devloss_compl; | ||
141 | evtp->evt = LPFC_EVT_DEV_LOSS; | 138 | evtp->evt = LPFC_EVT_DEV_LOSS; |
142 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 139 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
143 | if (phba->work_wait) | 140 | if (phba->work_wait) |
@@ -145,8 +142,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
145 | 142 | ||
146 | spin_unlock_irq(&phba->hbalock); | 143 | spin_unlock_irq(&phba->hbalock); |
147 | 144 | ||
148 | wait_for_completion(&devloss_compl); | ||
149 | |||
150 | return; | 145 | return; |
151 | } | 146 | } |
152 | 147 | ||
@@ -260,7 +255,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
260 | { | 255 | { |
261 | struct lpfc_work_evt *evtp = NULL; | 256 | struct lpfc_work_evt *evtp = NULL; |
262 | struct lpfc_nodelist *ndlp; | 257 | struct lpfc_nodelist *ndlp; |
263 | struct lpfc_vport *vport; | ||
264 | int free_evt; | 258 | int free_evt; |
265 | 259 | ||
266 | spin_lock_irq(&phba->hbalock); | 260 | spin_lock_irq(&phba->hbalock); |
@@ -270,24 +264,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
270 | spin_unlock_irq(&phba->hbalock); | 264 | spin_unlock_irq(&phba->hbalock); |
271 | free_evt = 1; | 265 | free_evt = 1; |
272 | switch (evtp->evt) { | 266 | switch (evtp->evt) { |
273 | case LPFC_EVT_DEV_LOSS_DELAY: | ||
274 | free_evt = 0; /* evt is part of ndlp */ | ||
275 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | ||
276 | vport = ndlp->vport; | ||
277 | if (!vport) | ||
278 | break; | ||
279 | |||
280 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
281 | "rport devlossdly:did:x%x flg:x%x", | ||
282 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
283 | |||
284 | if (!(vport->load_flag & FC_UNLOADING) && | ||
285 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | ||
286 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { | ||
287 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
288 | NLP_EVT_DEVICE_RM); | ||
289 | } | ||
290 | break; | ||
291 | case LPFC_EVT_ELS_RETRY: | 267 | case LPFC_EVT_ELS_RETRY: |
292 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | 268 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); |
293 | lpfc_els_retry_delay_handler(ndlp); | 269 | lpfc_els_retry_delay_handler(ndlp); |
@@ -298,7 +274,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
298 | lpfc_nlp_get(ndlp); | 274 | lpfc_nlp_get(ndlp); |
299 | lpfc_dev_loss_tmo_handler(ndlp); | 275 | lpfc_dev_loss_tmo_handler(ndlp); |
300 | free_evt = 0; | 276 | free_evt = 0; |
301 | complete((struct completion *)(evtp->evt_arg2)); | ||
302 | lpfc_nlp_put(ndlp); | 277 | lpfc_nlp_put(ndlp); |
303 | break; | 278 | break; |
304 | case LPFC_EVT_ONLINE: | 279 | case LPFC_EVT_ONLINE: |
@@ -552,7 +527,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
552 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | 527 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
553 | continue; | 528 | continue; |
554 | 529 | ||
555 | if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) | 530 | if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || |
531 | ((vport->port_type == LPFC_NPIV_PORT) && | ||
532 | (ndlp->nlp_DID == NameServer_DID))) | ||
556 | lpfc_unreg_rpi(vport, ndlp); | 533 | lpfc_unreg_rpi(vport, ndlp); |
557 | 534 | ||
558 | /* Leave Fabric nodes alone on link down */ | 535 | /* Leave Fabric nodes alone on link down */ |
@@ -570,16 +547,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
570 | } | 547 | } |
571 | 548 | ||
572 | static void | 549 | static void |
573 | lpfc_linkdown_port(struct lpfc_vport *vport) | 550 | lpfc_port_link_failure(struct lpfc_vport *vport) |
574 | { | 551 | { |
575 | struct lpfc_nodelist *ndlp, *next_ndlp; | 552 | struct lpfc_nodelist *ndlp, *next_ndlp; |
576 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
577 | |||
578 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | ||
579 | |||
580 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
581 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
582 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
583 | 553 | ||
584 | /* Cleanup any outstanding RSCN activity */ | 554 | /* Cleanup any outstanding RSCN activity */ |
585 | lpfc_els_flush_rscn(vport); | 555 | lpfc_els_flush_rscn(vport); |
@@ -598,6 +568,21 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |||
598 | lpfc_can_disctmo(vport); | 568 | lpfc_can_disctmo(vport); |
599 | } | 569 | } |
600 | 570 | ||
571 | static void | ||
572 | lpfc_linkdown_port(struct lpfc_vport *vport) | ||
573 | { | ||
574 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
575 | |||
576 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | ||
577 | |||
578 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
579 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
580 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
581 | |||
582 | lpfc_port_link_failure(vport); | ||
583 | |||
584 | } | ||
585 | |||
601 | int | 586 | int |
602 | lpfc_linkdown(struct lpfc_hba *phba) | 587 | lpfc_linkdown(struct lpfc_hba *phba) |
603 | { | 588 | { |
@@ -851,8 +836,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
851 | * LPFC_FLOGI while waiting for FLOGI cmpl | 836 | * LPFC_FLOGI while waiting for FLOGI cmpl |
852 | */ | 837 | */ |
853 | if (vport->port_state != LPFC_FLOGI) { | 838 | if (vport->port_state != LPFC_FLOGI) { |
854 | vport->port_state = LPFC_FLOGI; | ||
855 | lpfc_set_disctmo(vport); | ||
856 | lpfc_initial_flogi(vport); | 839 | lpfc_initial_flogi(vport); |
857 | } | 840 | } |
858 | return; | 841 | return; |
@@ -1622,6 +1605,16 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1622 | ndlp->nlp_type &= ~NLP_FC_NODE; | 1605 | ndlp->nlp_type &= ~NLP_FC_NODE; |
1623 | } | 1606 | } |
1624 | 1607 | ||
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 | |||
1625 | if (list_empty(&ndlp->nlp_listp)) { | 1618 | if (list_empty(&ndlp->nlp_listp)) { |
1626 | spin_lock_irq(shost->host_lock); | 1619 | spin_lock_irq(shost->host_lock); |
1627 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); | 1620 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); |
@@ -1654,7 +1647,9 @@ void | |||
1654 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1647 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1655 | { | 1648 | { |
1656 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1649 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1657 | lpfc_nlp_put(ndlp); | 1650 | if (!(ndlp->nlp_flag & NLP_DELAYED_RM)) |
1651 | lpfc_nlp_put(ndlp); | ||
1652 | return; | ||
1658 | } | 1653 | } |
1659 | 1654 | ||
1660 | /* | 1655 | /* |
@@ -1975,11 +1970,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1975 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) | 1970 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) |
1976 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | 1971 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
1977 | 1972 | ||
1978 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) { | ||
1979 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | ||
1980 | complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2)); | ||
1981 | } | ||
1982 | |||
1983 | lpfc_unreg_rpi(vport, ndlp); | 1973 | lpfc_unreg_rpi(vport, ndlp); |
1984 | 1974 | ||
1985 | return 0; | 1975 | return 0; |
@@ -2418,7 +2408,6 @@ lpfc_disc_flush_list(struct lpfc_vport *vport) | |||
2418 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || | 2408 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
2419 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { | 2409 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { |
2420 | lpfc_free_tx(phba, ndlp); | 2410 | lpfc_free_tx(phba, ndlp); |
2421 | lpfc_nlp_put(ndlp); | ||
2422 | } | 2411 | } |
2423 | } | 2412 | } |
2424 | } | 2413 | } |
@@ -2516,8 +2505,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2516 | } | 2505 | } |
2517 | } | 2506 | } |
2518 | if (vport->port_state != LPFC_FLOGI) { | 2507 | if (vport->port_state != LPFC_FLOGI) { |
2519 | vport->port_state = LPFC_FLOGI; | ||
2520 | lpfc_set_disctmo(vport); | ||
2521 | lpfc_initial_flogi(vport); | 2508 | lpfc_initial_flogi(vport); |
2522 | } | 2509 | } |
2523 | break; | 2510 | break; |
@@ -2828,6 +2815,9 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2828 | return; | 2815 | return; |
2829 | } | 2816 | } |
2830 | 2817 | ||
2818 | /* This routine releases all resources associated with a specifc NPort's ndlp | ||
2819 | * and mempool_free's the nodelist. | ||
2820 | */ | ||
2831 | static void | 2821 | static void |
2832 | lpfc_nlp_release(struct kref *kref) | 2822 | lpfc_nlp_release(struct kref *kref) |
2833 | { | 2823 | { |
@@ -2842,16 +2832,57 @@ lpfc_nlp_release(struct kref *kref) | |||
2842 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); | 2832 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); |
2843 | } | 2833 | } |
2844 | 2834 | ||
2835 | /* This routine bumps the reference count for a ndlp structure to ensure | ||
2836 | * that one discovery thread won't free a ndlp while another discovery thread | ||
2837 | * is using it. | ||
2838 | */ | ||
2845 | struct lpfc_nodelist * | 2839 | struct lpfc_nodelist * |
2846 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) | 2840 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) |
2847 | { | 2841 | { |
2848 | if (ndlp) | 2842 | if (ndlp) { |
2843 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2844 | "node get: did:x%x flg:x%x refcnt:x%x", | ||
2845 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2846 | atomic_read(&ndlp->kref.refcount)); | ||
2849 | kref_get(&ndlp->kref); | 2847 | kref_get(&ndlp->kref); |
2848 | } | ||
2850 | return ndlp; | 2849 | return ndlp; |
2851 | } | 2850 | } |
2852 | 2851 | ||
2852 | |||
2853 | /* This routine decrements the reference count for a ndlp structure. If the | ||
2854 | * count goes to 0, this indicates the the associated nodelist should be freed. | ||
2855 | */ | ||
2853 | int | 2856 | int |
2854 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) | 2857 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) |
2855 | { | 2858 | { |
2859 | if (ndlp) { | ||
2860 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2861 | "node put: did:x%x flg:x%x refcnt:x%x", | ||
2862 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2863 | atomic_read(&ndlp->kref.refcount)); | ||
2864 | } | ||
2856 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; | 2865 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; |
2857 | } | 2866 | } |
2867 | |||
2868 | /* This routine free's the specified nodelist if it is not in use | ||
2869 | * by any other discovery thread. This routine returns 1 if the ndlp | ||
2870 | * is not being used by anyone and has been freed. A return value of | ||
2871 | * 0 indicates it is being used by another discovery thread and the | ||
2872 | * refcount is left unchanged. | ||
2873 | */ | ||
2874 | int | ||
2875 | lpfc_nlp_not_used(struct lpfc_nodelist *ndlp) | ||
2876 | { | ||
2877 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2878 | "node not used: did:x%x flg:x%x refcnt:x%x", | ||
2879 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2880 | atomic_read(&ndlp->kref.refcount)); | ||
2881 | |||
2882 | if (atomic_read(&ndlp->kref.refcount) == 1) { | ||
2883 | lpfc_nlp_put(ndlp); | ||
2884 | return 1; | ||
2885 | } | ||
2886 | return 0; | ||
2887 | } | ||
2888 | |||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 8c7fdb8487e0..729694d97597 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1143,9 +1143,8 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt, | |||
1143 | /* Allocate buffer to post */ | 1143 | /* Allocate buffer to post */ |
1144 | mp1 = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); | 1144 | mp1 = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); |
1145 | if (mp1) | 1145 | if (mp1) |
1146 | mp1->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 1146 | mp1->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp1->phys); |
1147 | &mp1->phys); | 1147 | if (!mp1 || !mp1->virt) { |
1148 | if (mp1 == 0 || mp1->virt == 0) { | ||
1149 | kfree(mp1); | 1148 | kfree(mp1); |
1150 | lpfc_sli_release_iocbq(phba, iocb); | 1149 | lpfc_sli_release_iocbq(phba, iocb); |
1151 | pring->missbufcnt = cnt; | 1150 | pring->missbufcnt = cnt; |
@@ -1159,7 +1158,7 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt, | |||
1159 | if (mp2) | 1158 | if (mp2) |
1160 | mp2->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 1159 | mp2->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
1161 | &mp2->phys); | 1160 | &mp2->phys); |
1162 | if (mp2 == 0 || mp2->virt == 0) { | 1161 | if (!mp2 || !mp2->virt) { |
1163 | kfree(mp2); | 1162 | kfree(mp2); |
1164 | lpfc_mbuf_free(phba, mp1->virt, mp1->phys); | 1163 | lpfc_mbuf_free(phba, mp1->virt, mp1->phys); |
1165 | kfree(mp1); | 1164 | kfree(mp1); |
@@ -1762,7 +1761,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1762 | struct Scsi_Host *shost = NULL; | 1761 | struct Scsi_Host *shost = NULL; |
1763 | void *ptr; | 1762 | void *ptr; |
1764 | unsigned long bar0map_len, bar2map_len; | 1763 | unsigned long bar0map_len, bar2map_len; |
1765 | int error = -ENODEV; | 1764 | int error = -ENODEV, retval; |
1766 | int i, hbq_count; | 1765 | int i, hbq_count; |
1767 | uint16_t iotag; | 1766 | uint16_t iotag; |
1768 | 1767 | ||
@@ -1878,9 +1877,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1878 | lpfc_sli_setup(phba); | 1877 | lpfc_sli_setup(phba); |
1879 | lpfc_sli_queue_setup(phba); | 1878 | lpfc_sli_queue_setup(phba); |
1880 | 1879 | ||
1881 | error = lpfc_mem_alloc(phba); | 1880 | retval = lpfc_mem_alloc(phba); |
1882 | if (error) | 1881 | if (retval) { |
1882 | error = retval; | ||
1883 | goto out_free_hbqslimp; | 1883 | goto out_free_hbqslimp; |
1884 | } | ||
1884 | 1885 | ||
1885 | /* Initialize and populate the iocb list per host. */ | 1886 | /* Initialize and populate the iocb list per host. */ |
1886 | INIT_LIST_HEAD(&phba->lpfc_iocb_list); | 1887 | INIT_LIST_HEAD(&phba->lpfc_iocb_list); |
@@ -1946,8 +1947,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1946 | pci_set_drvdata(pdev, shost); | 1947 | pci_set_drvdata(pdev, shost); |
1947 | 1948 | ||
1948 | if (phba->cfg_use_msi) { | 1949 | if (phba->cfg_use_msi) { |
1949 | error = pci_enable_msi(phba->pcidev); | 1950 | retval = pci_enable_msi(phba->pcidev); |
1950 | if (!error) | 1951 | if (!retval) |
1951 | phba->using_msi = 1; | 1952 | phba->using_msi = 1; |
1952 | else | 1953 | else |
1953 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 1954 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
@@ -1955,11 +1956,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1955 | "with IRQ\n"); | 1956 | "with IRQ\n"); |
1956 | } | 1957 | } |
1957 | 1958 | ||
1958 | error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, | 1959 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, |
1959 | LPFC_DRIVER_NAME, phba); | 1960 | LPFC_DRIVER_NAME, phba); |
1960 | if (error) { | 1961 | if (retval) { |
1961 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 1962 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
1962 | "0451 Enable interrupt handler failed\n"); | 1963 | "0451 Enable interrupt handler failed\n"); |
1964 | error = retval; | ||
1963 | goto out_disable_msi; | 1965 | goto out_disable_msi; |
1964 | } | 1966 | } |
1965 | 1967 | ||
@@ -1969,11 +1971,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1969 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; | 1971 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; |
1970 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; | 1972 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; |
1971 | 1973 | ||
1972 | if (lpfc_alloc_sysfs_attr(vport)) | 1974 | if (lpfc_alloc_sysfs_attr(vport)) { |
1975 | error = -ENOMEM; | ||
1973 | goto out_free_irq; | 1976 | goto out_free_irq; |
1977 | } | ||
1974 | 1978 | ||
1975 | if (lpfc_sli_hba_setup(phba)) | 1979 | if (lpfc_sli_hba_setup(phba)) { |
1980 | error = -ENODEV; | ||
1976 | goto out_remove_device; | 1981 | goto out_remove_device; |
1982 | } | ||
1977 | 1983 | ||
1978 | /* | 1984 | /* |
1979 | * hba setup may have changed the hba_queue_depth so we need to adjust | 1985 | * hba setup may have changed the hba_queue_depth so we need to adjust |
@@ -2303,14 +2309,12 @@ lpfc_init(void) | |||
2303 | if (lpfc_transport_template == NULL) | 2309 | if (lpfc_transport_template == NULL) |
2304 | return -ENOMEM; | 2310 | return -ENOMEM; |
2305 | if (lpfc_enable_npiv) { | 2311 | if (lpfc_enable_npiv) { |
2306 | lpfc_transport_functions.vport_create = NULL; | ||
2307 | lpfc_transport_functions.vport_delete = NULL; | ||
2308 | lpfc_transport_functions.issue_fc_host_lip = NULL; | ||
2309 | lpfc_transport_functions.vport_disable = lpfc_vport_disable; | ||
2310 | lpfc_vport_transport_template = | 2312 | lpfc_vport_transport_template = |
2311 | fc_attach_transport(&lpfc_transport_functions); | 2313 | fc_attach_transport(&lpfc_vport_transport_functions); |
2312 | if (lpfc_vport_transport_template == NULL) | 2314 | if (lpfc_vport_transport_template == NULL) { |
2315 | fc_release_transport(lpfc_transport_template); | ||
2313 | return -ENOMEM; | 2316 | return -ENOMEM; |
2317 | } | ||
2314 | } | 2318 | } |
2315 | error = pci_register_driver(&lpfc_driver); | 2319 | error = pci_register_driver(&lpfc_driver); |
2316 | if (error) { | 2320 | if (error) { |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 7256be3f4e2f..6b64e573ad4e 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -288,8 +288,10 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) | |||
288 | 288 | ||
289 | /* Get a buffer to hold the HBAs Service Parameters */ | 289 | /* Get a buffer to hold the HBAs Service Parameters */ |
290 | 290 | ||
291 | if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) || | 291 | mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); |
292 | ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { | 292 | if (mp) |
293 | mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); | ||
294 | if (!mp || !mp->virt) { | ||
293 | kfree(mp); | 295 | kfree(mp); |
294 | mb->mbxCommand = MBX_READ_SPARM64; | 296 | mb->mbxCommand = MBX_READ_SPARM64; |
295 | /* READ_SPARAM: no buffers */ | 297 | /* READ_SPARAM: no buffers */ |
@@ -387,8 +389,10 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
387 | mb->mbxOwner = OWN_HOST; | 389 | mb->mbxOwner = OWN_HOST; |
388 | 390 | ||
389 | /* Get a buffer to hold NPorts Service Parameters */ | 391 | /* Get a buffer to hold NPorts Service Parameters */ |
390 | if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) || | 392 | mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); |
391 | ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { | 393 | if (mp) |
394 | mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); | ||
395 | if (!mp || !mp->virt) { | ||
392 | kfree(mp); | 396 | kfree(mp); |
393 | mb->mbxCommand = MBX_REG_LOGIN64; | 397 | mb->mbxCommand = MBX_REG_LOGIN64; |
394 | /* REG_LOGIN: no buffers */ | 398 | /* REG_LOGIN: no buffers */ |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 71fd00127351..1a16ee9b2e87 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1135,7 +1135,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, | |||
1135 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 1135 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
1136 | mp = (struct lpfc_dmabuf *) (mb->context1); | 1136 | mp = (struct lpfc_dmabuf *) (mb->context1); |
1137 | if (mp) { | 1137 | if (mp) { |
1138 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1138 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1139 | kfree(mp); | 1139 | kfree(mp); |
1140 | } | 1140 | } |
1141 | lpfc_nlp_put(ndlp); | 1141 | lpfc_nlp_put(ndlp); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 744bad627596..49f2fdd2ba2b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -1914,8 +1914,8 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) | |||
1914 | "0329 Kill HBA Data: x%x x%x\n", | 1914 | "0329 Kill HBA Data: x%x x%x\n", |
1915 | phba->pport->port_state, psli->sli_flag); | 1915 | phba->pport->port_state, psli->sli_flag); |
1916 | 1916 | ||
1917 | if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, | 1917 | pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
1918 | GFP_KERNEL)) == 0) | 1918 | if (!pmb) |
1919 | return 1; | 1919 | return 1; |
1920 | 1920 | ||
1921 | /* Disable the error attention */ | 1921 | /* Disable the error attention */ |
@@ -2809,7 +2809,7 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2809 | /* | 2809 | /* |
2810 | * Lockless version of lpfc_sli_issue_iocb. | 2810 | * Lockless version of lpfc_sli_issue_iocb. |
2811 | */ | 2811 | */ |
2812 | int | 2812 | static int |
2813 | __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 2813 | __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
2814 | struct lpfc_iocbq *piocb, uint32_t flag) | 2814 | struct lpfc_iocbq *piocb, uint32_t flag) |
2815 | { | 2815 | { |
@@ -2954,7 +2954,7 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) | |||
2954 | return 0; | 2954 | return 0; |
2955 | } | 2955 | } |
2956 | 2956 | ||
2957 | void | 2957 | static void |
2958 | lpfc_sli_async_event_handler(struct lpfc_hba * phba, | 2958 | lpfc_sli_async_event_handler(struct lpfc_hba * phba, |
2959 | struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq) | 2959 | struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq) |
2960 | { | 2960 | { |
@@ -3717,7 +3717,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
3717 | unsigned long flag; | 3717 | unsigned long flag; |
3718 | 3718 | ||
3719 | /* The caller must leave context1 empty. */ | 3719 | /* The caller must leave context1 empty. */ |
3720 | if (pmboxq->context1 != 0) | 3720 | if (pmboxq->context1) |
3721 | return MBX_NOT_FINISHED; | 3721 | return MBX_NOT_FINISHED; |
3722 | 3722 | ||
3723 | /* setup wake call as IOCB callback */ | 3723 | /* setup wake call as IOCB callback */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 44c3fd9c22f4..5fcfe88e2a3f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -197,9 +197,6 @@ struct lpfc_hbq_init { | |||
197 | uint32_t add_count; /* number to allocate when starved */ | 197 | uint32_t add_count; /* number to allocate when starved */ |
198 | } ; | 198 | } ; |
199 | 199 | ||
200 | #define LPFC_MAX_HBQ 16 | ||
201 | |||
202 | |||
203 | /* Structure used to hold SLI statistical counters and info */ | 200 | /* Structure used to hold SLI statistical counters and info */ |
204 | struct lpfc_sli_stat { | 201 | struct lpfc_sli_stat { |
205 | uint64_t mbox_stat_err; /* Mbox cmds completed status error */ | 202 | uint64_t mbox_stat_err; /* Mbox cmds completed status error */ |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 3b705ccc771a..fd07d9d7f507 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -125,15 +125,26 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport) | |||
125 | pmb->vport = vport; | 125 | pmb->vport = vport; |
126 | rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2); | 126 | rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2); |
127 | if (rc != MBX_SUCCESS) { | 127 | if (rc != MBX_SUCCESS) { |
128 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, | 128 | if (signal_pending(current)) { |
129 | "1818 VPort failed init, mbxCmd x%x " | 129 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, |
130 | "READ_SPARM mbxStatus x%x, rc = x%x\n", | 130 | "1830 Signal aborted mbxCmd x%x\n", |
131 | mb->mbxCommand, mb->mbxStatus, rc); | 131 | mb->mbxCommand); |
132 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 132 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
133 | kfree(mp); | 133 | kfree(mp); |
134 | if (rc != MBX_TIMEOUT) | 134 | if (rc != MBX_TIMEOUT) |
135 | mempool_free(pmb, phba->mbox_mem_pool); | 135 | mempool_free(pmb, phba->mbox_mem_pool); |
136 | return -EIO; | 136 | return -EINTR; |
137 | } else { | ||
138 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, | ||
139 | "1818 VPort failed init, mbxCmd x%x " | ||
140 | "READ_SPARM mbxStatus x%x, rc = x%x\n", | ||
141 | mb->mbxCommand, mb->mbxStatus, rc); | ||
142 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
143 | kfree(mp); | ||
144 | if (rc != MBX_TIMEOUT) | ||
145 | mempool_free(pmb, phba->mbox_mem_pool); | ||
146 | return -EIO; | ||
147 | } | ||
137 | } | 148 | } |
138 | 149 | ||
139 | memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm)); | 150 | memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm)); |
@@ -204,6 +215,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |||
204 | int instance; | 215 | int instance; |
205 | int vpi; | 216 | int vpi; |
206 | int rc = VPORT_ERROR; | 217 | int rc = VPORT_ERROR; |
218 | int status; | ||
207 | 219 | ||
208 | if ((phba->sli_rev < 3) || | 220 | if ((phba->sli_rev < 3) || |
209 | !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { | 221 | !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { |
@@ -248,13 +260,19 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |||
248 | vport->vpi = vpi; | 260 | vport->vpi = vpi; |
249 | lpfc_debugfs_initialize(vport); | 261 | lpfc_debugfs_initialize(vport); |
250 | 262 | ||
251 | if (lpfc_vport_sparm(phba, vport)) { | 263 | if ((status = lpfc_vport_sparm(phba, vport))) { |
252 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | 264 | if (status == -EINTR) { |
253 | "1813 Create VPORT failed. " | 265 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
254 | "Cannot get sparam\n"); | 266 | "1831 Create VPORT Interrupted.\n"); |
267 | rc = VPORT_ERROR; | ||
268 | } else { | ||
269 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | ||
270 | "1813 Create VPORT failed. " | ||
271 | "Cannot get sparam\n"); | ||
272 | rc = VPORT_NORESOURCES; | ||
273 | } | ||
255 | lpfc_free_vpi(phba, vpi); | 274 | lpfc_free_vpi(phba, vpi); |
256 | destroy_port(vport); | 275 | destroy_port(vport); |
257 | rc = VPORT_NORESOURCES; | ||
258 | goto error_out; | 276 | goto error_out; |
259 | } | 277 | } |
260 | 278 | ||