diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:38:11 -0400 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 276 |
1 files changed, 195 insertions, 81 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 94ee9675b5b0..f2f4639eab59 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "lpfc_logmsg.h" | 37 | #include "lpfc_logmsg.h" |
38 | #include "lpfc_crtn.h" | 38 | #include "lpfc_crtn.h" |
39 | #include "lpfc_vport.h" | 39 | #include "lpfc_vport.h" |
40 | #include "lpfc_debugfs.h" | ||
40 | 41 | ||
41 | /* AlpaArray for assignment of scsid for scan-down and bind_method */ | 42 | /* AlpaArray for assignment of scsid for scan-down and bind_method */ |
42 | static uint8_t lpfcAlpaArray[] = { | 43 | static uint8_t lpfcAlpaArray[] = { |
@@ -77,6 +78,10 @@ lpfc_terminate_rport_io(struct fc_rport *rport) | |||
77 | 78 | ||
78 | phba = ndlp->vport->phba; | 79 | phba = ndlp->vport->phba; |
79 | 80 | ||
81 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, | ||
82 | "rport terminate: sid:x%x did:x%x flg:x%x", | ||
83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | ||
84 | |||
80 | if (ndlp->nlp_sid != NLP_NO_SID) { | 85 | if (ndlp->nlp_sid != NLP_NO_SID) { |
81 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 86 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
82 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 87 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); |
@@ -93,12 +98,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
93 | { | 98 | { |
94 | struct lpfc_rport_data *rdata; | 99 | struct lpfc_rport_data *rdata; |
95 | struct lpfc_nodelist * ndlp; | 100 | struct lpfc_nodelist * ndlp; |
96 | uint8_t *name; | ||
97 | int warn_on = 0; | ||
98 | struct lpfc_hba *phba; | ||
99 | struct lpfc_vport *vport; | 101 | struct lpfc_vport *vport; |
100 | int put_node; | 102 | struct lpfc_hba *phba; |
101 | int put_rport; | 103 | struct completion devloss_compl; |
104 | struct lpfc_work_evt *evtp; | ||
102 | 105 | ||
103 | rdata = rport->dd_data; | 106 | rdata = rport->dd_data; |
104 | ndlp = rdata->pnode; | 107 | ndlp = rdata->pnode; |
@@ -112,7 +115,70 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
112 | return; | 115 | return; |
113 | } | 116 | } |
114 | 117 | ||
118 | vport = ndlp->vport; | ||
119 | phba = vport->phba; | ||
120 | |||
121 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
122 | "rport devlosscb: sid:x%x did:x%x flg:x%x", | ||
123 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | ||
124 | |||
125 | init_completion(&devloss_compl); | ||
126 | evtp = &ndlp->dev_loss_evt; | ||
127 | |||
128 | if (!list_empty(&evtp->evt_listp)) | ||
129 | return; | ||
130 | |||
131 | spin_lock_irq(&phba->hbalock); | ||
132 | evtp->evt_arg1 = ndlp; | ||
133 | evtp->evt_arg2 = &devloss_compl; | ||
134 | evtp->evt = LPFC_EVT_DEV_LOSS; | ||
135 | list_add_tail(&evtp->evt_listp, &phba->work_list); | ||
136 | if (phba->work_wait) | ||
137 | wake_up(phba->work_wait); | ||
138 | |||
139 | spin_unlock_irq(&phba->hbalock); | ||
140 | |||
141 | wait_for_completion(&devloss_compl); | ||
142 | |||
143 | return; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * This function is called from the worker thread when dev_loss_tmo | ||
148 | * expire. | ||
149 | */ | ||
150 | void | ||
151 | lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | ||
152 | { | ||
153 | struct lpfc_rport_data *rdata; | ||
154 | struct fc_rport *rport; | ||
155 | struct lpfc_vport *vport; | ||
156 | struct lpfc_hba *phba; | ||
157 | uint8_t *name; | ||
158 | int warn_on = 0; | ||
159 | |||
160 | rport = ndlp->rport; | ||
161 | |||
162 | if (!rport) | ||
163 | return; | ||
164 | |||
165 | rdata = rport->dd_data; | ||
166 | name = (uint8_t *) &ndlp->nlp_portname; | ||
167 | vport = ndlp->vport; | ||
168 | phba = vport->phba; | ||
169 | |||
170 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
171 | "rport devlosstmo:did:x%x type:x%x id:x%x", | ||
172 | ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); | ||
173 | |||
174 | if (!(vport->load_flag & FC_UNLOADING) && | ||
175 | ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
176 | return; | ||
177 | |||
115 | if (ndlp->nlp_type & NLP_FABRIC) { | 178 | if (ndlp->nlp_type & NLP_FABRIC) { |
179 | int put_node; | ||
180 | int put_rport; | ||
181 | |||
116 | /* We will clean up these Nodes in linkup */ | 182 | /* We will clean up these Nodes in linkup */ |
117 | put_node = rdata->pnode != NULL; | 183 | put_node = rdata->pnode != NULL; |
118 | put_rport = ndlp->rport != NULL; | 184 | put_rport = ndlp->rport != NULL; |
@@ -125,15 +191,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
125 | return; | 191 | return; |
126 | } | 192 | } |
127 | 193 | ||
128 | name = (uint8_t *)&ndlp->nlp_portname; | ||
129 | vport = ndlp->vport; | ||
130 | phba = vport->phba; | ||
131 | |||
132 | if (!(vport->load_flag & FC_UNLOADING) && | ||
133 | ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
134 | return; | ||
135 | |||
136 | |||
137 | if (ndlp->nlp_sid != NLP_NO_SID) { | 194 | if (ndlp->nlp_sid != NLP_NO_SID) { |
138 | warn_on = 1; | 195 | warn_on = 1; |
139 | /* flush the target */ | 196 | /* flush the target */ |
@@ -171,6 +228,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
171 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) | 228 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) |
172 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); | 229 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); |
173 | else { | 230 | else { |
231 | int put_node; | ||
232 | int put_rport; | ||
233 | |||
174 | put_node = rdata->pnode != NULL; | 234 | put_node = rdata->pnode != NULL; |
175 | put_rport = ndlp->rport != NULL; | 235 | put_rport = ndlp->rport != NULL; |
176 | rdata->pnode = NULL; | 236 | rdata->pnode = NULL; |
@@ -180,7 +240,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
180 | if (put_rport) | 240 | if (put_rport) |
181 | put_device(&rport->dev); | 241 | put_device(&rport->dev); |
182 | } | 242 | } |
183 | return; | ||
184 | } | 243 | } |
185 | 244 | ||
186 | 245 | ||
@@ -206,12 +265,17 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
206 | spin_unlock_irq(&phba->hbalock); | 265 | spin_unlock_irq(&phba->hbalock); |
207 | free_evt = 1; | 266 | free_evt = 1; |
208 | switch (evtp->evt) { | 267 | switch (evtp->evt) { |
209 | case LPFC_EVT_DEV_LOSS: | 268 | case LPFC_EVT_DEV_LOSS_DELAY: |
210 | free_evt = 0; /* evt is part of ndlp */ | 269 | free_evt = 0; /* evt is part of ndlp */ |
211 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | 270 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); |
212 | vport = ndlp->vport; | 271 | vport = ndlp->vport; |
213 | if (!vport) | 272 | if (!vport) |
214 | break; | 273 | break; |
274 | |||
275 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
276 | "rport devlossdly:did:x%x flg:x%x", | ||
277 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
278 | |||
215 | if (!(vport->load_flag & FC_UNLOADING) && | 279 | if (!(vport->load_flag & FC_UNLOADING) && |
216 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | 280 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && |
217 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { | 281 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
@@ -224,6 +288,14 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
224 | lpfc_els_retry_delay_handler(ndlp); | 288 | lpfc_els_retry_delay_handler(ndlp); |
225 | free_evt = 0; /* evt is part of ndlp */ | 289 | free_evt = 0; /* evt is part of ndlp */ |
226 | break; | 290 | break; |
291 | case LPFC_EVT_DEV_LOSS: | ||
292 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); | ||
293 | lpfc_nlp_get(ndlp); | ||
294 | lpfc_dev_loss_tmo_handler(ndlp); | ||
295 | free_evt = 0; | ||
296 | complete((struct completion *)(evtp->evt_arg2)); | ||
297 | lpfc_nlp_put(ndlp); | ||
298 | break; | ||
227 | case LPFC_EVT_ONLINE: | 299 | case LPFC_EVT_ONLINE: |
228 | if (phba->link_state < LPFC_LINK_DOWN) | 300 | if (phba->link_state < LPFC_LINK_DOWN) |
229 | *(int *) (evtp->evt_arg1) = lpfc_online(phba); | 301 | *(int *) (evtp->evt_arg1) = lpfc_online(phba); |
@@ -272,13 +344,12 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
272 | 344 | ||
273 | } | 345 | } |
274 | 346 | ||
275 | static void | 347 | void |
276 | lpfc_work_done(struct lpfc_hba *phba) | 348 | lpfc_work_done(struct lpfc_hba *phba) |
277 | { | 349 | { |
278 | struct lpfc_sli_ring *pring; | 350 | struct lpfc_sli_ring *pring; |
279 | uint32_t ha_copy, control, work_port_events; | 351 | uint32_t ha_copy, status, control, work_port_events; |
280 | struct lpfc_vport *vport; | 352 | struct lpfc_vport *vport; |
281 | int i; | ||
282 | 353 | ||
283 | spin_lock_irq(&phba->hbalock); | 354 | spin_lock_irq(&phba->hbalock); |
284 | ha_copy = phba->work_ha; | 355 | ha_copy = phba->work_ha; |
@@ -310,6 +381,9 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
310 | if (work_port_events & WORKER_ELS_TMO) | 381 | if (work_port_events & WORKER_ELS_TMO) |
311 | lpfc_els_timeout_handler(vport); | 382 | lpfc_els_timeout_handler(vport); |
312 | 383 | ||
384 | if (work_port_events & WORKER_HB_TMO) | ||
385 | lpfc_hb_timeout_handler(phba); | ||
386 | |||
313 | if (work_port_events & WORKER_MBOX_TMO) | 387 | if (work_port_events & WORKER_MBOX_TMO) |
314 | lpfc_mbox_timeout_handler(phba); | 388 | lpfc_mbox_timeout_handler(phba); |
315 | 389 | ||
@@ -333,30 +407,31 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
333 | } | 407 | } |
334 | spin_unlock_irq(&phba->hbalock); | 408 | spin_unlock_irq(&phba->hbalock); |
335 | 409 | ||
336 | for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) { | 410 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
337 | pring = &phba->sli.ring[i]; | 411 | status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); |
338 | if ((ha_copy & HA_RXATT) | 412 | status >>= (4*LPFC_ELS_RING); |
339 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { | 413 | if ((status & HA_RXMASK) |
340 | if (pring->flag & LPFC_STOP_IOCB_MASK) { | 414 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { |
341 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 415 | if (pring->flag & LPFC_STOP_IOCB_MASK) { |
342 | } else { | 416 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
343 | lpfc_sli_handle_slow_ring_event(phba, pring, | 417 | } else { |
344 | (ha_copy & | 418 | lpfc_sli_handle_slow_ring_event(phba, pring, |
345 | HA_RXMASK)); | 419 | (status & |
346 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; | 420 | HA_RXMASK)); |
347 | } | 421 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; |
348 | /* | 422 | } |
349 | * Turn on Ring interrupts | 423 | /* |
350 | */ | 424 | * Turn on Ring interrupts |
351 | spin_lock_irq(&phba->hbalock); | 425 | */ |
352 | control = readl(phba->HCregaddr); | 426 | spin_lock_irq(&phba->hbalock); |
353 | control |= (HC_R0INT_ENA << i); | 427 | control = readl(phba->HCregaddr); |
428 | if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) { | ||
429 | control |= (HC_R0INT_ENA << LPFC_ELS_RING); | ||
354 | writel(control, phba->HCregaddr); | 430 | writel(control, phba->HCregaddr); |
355 | readl(phba->HCregaddr); /* flush */ | 431 | readl(phba->HCregaddr); /* flush */ |
356 | spin_unlock_irq(&phba->hbalock); | ||
357 | } | 432 | } |
433 | spin_unlock_irq(&phba->hbalock); | ||
358 | } | 434 | } |
359 | |||
360 | lpfc_work_list_done(phba); | 435 | lpfc_work_list_done(phba); |
361 | } | 436 | } |
362 | 437 | ||
@@ -365,7 +440,7 @@ check_work_wait_done(struct lpfc_hba *phba) | |||
365 | { | 440 | { |
366 | struct lpfc_vport *vport; | 441 | struct lpfc_vport *vport; |
367 | struct lpfc_sli_ring *pring; | 442 | struct lpfc_sli_ring *pring; |
368 | int i, rc = 0; | 443 | int rc = 0; |
369 | 444 | ||
370 | spin_lock_irq(&phba->hbalock); | 445 | spin_lock_irq(&phba->hbalock); |
371 | list_for_each_entry(vport, &phba->port_list, listentry) { | 446 | list_for_each_entry(vport, &phba->port_list, listentry) { |
@@ -380,13 +455,10 @@ check_work_wait_done(struct lpfc_hba *phba) | |||
380 | rc = 1; | 455 | rc = 1; |
381 | goto exit; | 456 | goto exit; |
382 | } | 457 | } |
383 | for (i = 0; i < phba->sli.num_rings; i++) { | 458 | |
384 | pring = &phba->sli.ring[i]; | 459 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
385 | if (pring->flag & LPFC_DEFERRED_RING_EVENT) { | 460 | if (pring->flag & LPFC_DEFERRED_RING_EVENT) |
386 | rc = 1; | 461 | rc = 1; |
387 | goto exit; | ||
388 | } | ||
389 | } | ||
390 | exit: | 462 | exit: |
391 | if (rc) | 463 | if (rc) |
392 | phba->work_found++; | 464 | phba->work_found++; |
@@ -506,6 +578,10 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |||
506 | 578 | ||
507 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | 579 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); |
508 | 580 | ||
581 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
582 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
583 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
584 | |||
509 | /* Cleanup any outstanding RSCN activity */ | 585 | /* Cleanup any outstanding RSCN activity */ |
510 | lpfc_els_flush_rscn(vport); | 586 | lpfc_els_flush_rscn(vport); |
511 | 587 | ||
@@ -617,6 +693,10 @@ lpfc_linkup_port(struct lpfc_vport *vport) | |||
617 | if ((vport->load_flag & FC_UNLOADING) != 0) | 693 | if ((vport->load_flag & FC_UNLOADING) != 0) |
618 | return; | 694 | return; |
619 | 695 | ||
696 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
697 | "Link Up: top:x%x speed:x%x flg:x%x", | ||
698 | phba->fc_topology, phba->fc_linkspeed, phba->link_flag); | ||
699 | |||
620 | /* If NPIV is not enabled, only bring the physical port up */ | 700 | /* If NPIV is not enabled, only bring the physical port up */ |
621 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 701 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
622 | (vport != phba->pport)) | 702 | (vport != phba->pport)) |
@@ -935,7 +1015,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
935 | } | 1015 | } |
936 | } else { | 1016 | } else { |
937 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { | 1017 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { |
938 | if (phba->max_vpi && lpfc_npiv_enable && | 1018 | if (phba->max_vpi && phba->cfg_npiv_enable && |
939 | (phba->sli_rev == 3)) | 1019 | (phba->sli_rev == 3)) |
940 | phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; | 1020 | phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; |
941 | } | 1021 | } |
@@ -1124,8 +1204,6 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1124 | "mb status = 0x%x\n", | 1204 | "mb status = 0x%x\n", |
1125 | phba->brd_no, vport->vpi, mb->mbxStatus); | 1205 | phba->brd_no, vport->vpi, mb->mbxStatus); |
1126 | break; | 1206 | break; |
1127 | default: | ||
1128 | phba->vpi_cnt--; | ||
1129 | } | 1207 | } |
1130 | vport->unreg_vpi_cmpl = VPORT_OK; | 1208 | vport->unreg_vpi_cmpl = VPORT_OK; |
1131 | mempool_free(pmb, phba->mbox_mem_pool); | 1209 | mempool_free(pmb, phba->mbox_mem_pool); |
@@ -1182,7 +1260,6 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1182 | vport->fc_myDID = 0; | 1260 | vport->fc_myDID = 0; |
1183 | goto out; | 1261 | goto out; |
1184 | } | 1262 | } |
1185 | phba->vpi_cnt++; | ||
1186 | 1263 | ||
1187 | vport->num_disc_nodes = 0; | 1264 | vport->num_disc_nodes = 0; |
1188 | /* go thru NPR list and issue ELS PLOGIs */ | 1265 | /* go thru NPR list and issue ELS PLOGIs */ |
@@ -1257,16 +1334,13 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1257 | 1334 | ||
1258 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) | 1335 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) |
1259 | lpfc_initial_fdisc(next_vport); | 1336 | lpfc_initial_fdisc(next_vport); |
1260 | else { | 1337 | else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
1261 | if (phba->sli3_options & | 1338 | lpfc_vport_set_state(vport, |
1262 | LPFC_SLI3_NPIV_ENABLED) { | 1339 | FC_VPORT_NO_FABRIC_SUPP); |
1263 | lpfc_vport_set_state(vport, | 1340 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
1264 | FC_VPORT_NO_FABRIC_SUPP); | ||
1265 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
1266 | "%d (%d):0259 No NPIV Fabric " | 1341 | "%d (%d):0259 No NPIV Fabric " |
1267 | "support\n", | 1342 | "support\n", |
1268 | phba->brd_no, vport->vpi); | 1343 | phba->brd_no, vport->vpi); |
1269 | } | ||
1270 | } | 1344 | } |
1271 | } | 1345 | } |
1272 | lpfc_do_scr_ns_plogi(phba, vport); | 1346 | lpfc_do_scr_ns_plogi(phba, vport); |
@@ -1377,6 +1451,11 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1377 | ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) { | 1451 | ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) { |
1378 | lpfc_nlp_put(ndlp); | 1452 | lpfc_nlp_put(ndlp); |
1379 | } | 1453 | } |
1454 | |||
1455 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
1456 | "rport add: did:x%x flg:x%x type x%x", | ||
1457 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
1458 | |||
1380 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); | 1459 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); |
1381 | if (!rport || !get_device(&rport->dev)) { | 1460 | if (!rport || !get_device(&rport->dev)) { |
1382 | dev_printk(KERN_WARNING, &phba->pcidev->dev, | 1461 | dev_printk(KERN_WARNING, &phba->pcidev->dev, |
@@ -1394,7 +1473,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1394 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; | 1473 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; |
1395 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) | 1474 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) |
1396 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 1475 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
1397 | del_timer_sync(&ndlp->nlp_initiator_tmr); | ||
1398 | 1476 | ||
1399 | 1477 | ||
1400 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) | 1478 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) |
@@ -1412,6 +1490,10 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) | |||
1412 | { | 1490 | { |
1413 | struct fc_rport *rport = ndlp->rport; | 1491 | struct fc_rport *rport = ndlp->rport; |
1414 | 1492 | ||
1493 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, | ||
1494 | "rport delete: did:x%x flg:x%x type x%x", | ||
1495 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
1496 | |||
1415 | fc_remote_port_delete(rport); | 1497 | fc_remote_port_delete(rport); |
1416 | 1498 | ||
1417 | return; | 1499 | return; |
@@ -1478,20 +1560,19 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1478 | if (new_state == NLP_STE_MAPPED_NODE || | 1560 | if (new_state == NLP_STE_MAPPED_NODE || |
1479 | new_state == NLP_STE_UNMAPPED_NODE) { | 1561 | new_state == NLP_STE_UNMAPPED_NODE) { |
1480 | vport->phba->nport_event_cnt++; | 1562 | vport->phba->nport_event_cnt++; |
1481 | /* | 1563 | /* |
1482 | * Tell the fc transport about the port, if we haven't | 1564 | * Tell the fc transport about the port, if we haven't |
1483 | * already. If we have, and it's a scsi entity, be | 1565 | * already. If we have, and it's a scsi entity, be |
1484 | * sure to unblock any attached scsi devices | 1566 | * sure to unblock any attached scsi devices |
1485 | */ | 1567 | */ |
1486 | lpfc_register_remote_port(vport, ndlp); | 1568 | lpfc_register_remote_port(vport, ndlp); |
1487 | } | 1569 | } |
1488 | 1570 | /* | |
1489 | /* | 1571 | * if we added to Mapped list, but the remote port |
1490 | * if we added to Mapped list, but the remote port | 1572 | * registration failed or assigned a target id outside |
1491 | * registration failed or assigned a target id outside | 1573 | * our presentable range - move the node to the |
1492 | * our presentable range - move the node to the | 1574 | * Unmapped List |
1493 | * Unmapped List | 1575 | */ |
1494 | */ | ||
1495 | if (new_state == NLP_STE_MAPPED_NODE && | 1576 | if (new_state == NLP_STE_MAPPED_NODE && |
1496 | (!ndlp->rport || | 1577 | (!ndlp->rport || |
1497 | ndlp->rport->scsi_target_id == -1 || | 1578 | ndlp->rport->scsi_target_id == -1 || |
@@ -1533,11 +1614,16 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1533 | char name1[16], name2[16]; | 1614 | char name1[16], name2[16]; |
1534 | 1615 | ||
1535 | lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE, | 1616 | lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE, |
1536 | "%d:0904 NPort state transition x%06x, %s -> %s\n", | 1617 | "%d (%d):0904 NPort state transition x%06x, %s -> %s\n", |
1537 | vport->phba->brd_no, | 1618 | vport->phba->brd_no, vport->vpi, |
1538 | ndlp->nlp_DID, | 1619 | ndlp->nlp_DID, |
1539 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), | 1620 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), |
1540 | lpfc_nlp_state_name(name2, sizeof(name2), state)); | 1621 | lpfc_nlp_state_name(name2, sizeof(name2), state)); |
1622 | |||
1623 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | ||
1624 | "node statechg did:x%x old:%d ste:%d", | ||
1625 | ndlp->nlp_DID, old_state, state); | ||
1626 | |||
1541 | if (old_state == NLP_STE_NPR_NODE && | 1627 | if (old_state == NLP_STE_NPR_NODE && |
1542 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && | 1628 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && |
1543 | state != NLP_STE_NPR_NODE) | 1629 | state != NLP_STE_NPR_NODE) |
@@ -1571,7 +1657,8 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1571 | spin_lock_irq(shost->host_lock); | 1657 | spin_lock_irq(shost->host_lock); |
1572 | list_del_init(&ndlp->nlp_listp); | 1658 | list_del_init(&ndlp->nlp_listp); |
1573 | spin_unlock_irq(shost->host_lock); | 1659 | spin_unlock_irq(shost->host_lock); |
1574 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, 0); | 1660 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, |
1661 | NLP_STE_UNUSED_NODE); | ||
1575 | } | 1662 | } |
1576 | 1663 | ||
1577 | void | 1664 | void |
@@ -1585,6 +1672,7 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1585 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | 1672 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); |
1586 | spin_lock_irq(shost->host_lock); | 1673 | spin_lock_irq(shost->host_lock); |
1587 | list_del_init(&ndlp->nlp_listp); | 1674 | list_del_init(&ndlp->nlp_listp); |
1675 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | ||
1588 | spin_unlock_irq(shost->host_lock); | 1676 | spin_unlock_irq(shost->host_lock); |
1589 | lpfc_nlp_put(ndlp); | 1677 | lpfc_nlp_put(ndlp); |
1590 | } | 1678 | } |
@@ -1609,6 +1697,13 @@ lpfc_set_disctmo(struct lpfc_vport *vport) | |||
1609 | tmo = ((phba->fc_ratov * 3) + 3); | 1697 | tmo = ((phba->fc_ratov * 3) + 3); |
1610 | } | 1698 | } |
1611 | 1699 | ||
1700 | |||
1701 | if (!timer_pending(&vport->fc_disctmo)) { | ||
1702 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
1703 | "set disc timer: tmo:x%x state:x%x flg:x%x", | ||
1704 | tmo, vport->port_state, vport->fc_flag); | ||
1705 | } | ||
1706 | |||
1612 | mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo); | 1707 | mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo); |
1613 | spin_lock_irq(shost->host_lock); | 1708 | spin_lock_irq(shost->host_lock); |
1614 | vport->fc_flag |= FC_DISC_TMO; | 1709 | vport->fc_flag |= FC_DISC_TMO; |
@@ -1635,6 +1730,10 @@ lpfc_can_disctmo(struct lpfc_vport *vport) | |||
1635 | struct lpfc_hba *phba = vport->phba; | 1730 | struct lpfc_hba *phba = vport->phba; |
1636 | unsigned long iflags; | 1731 | unsigned long iflags; |
1637 | 1732 | ||
1733 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
1734 | "can disc timer: state:x%x rtry:x%x flg:x%x", | ||
1735 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
1736 | |||
1638 | /* Turn off discovery timer if its running */ | 1737 | /* Turn off discovery timer if its running */ |
1639 | if (vport->fc_flag & FC_DISC_TMO) { | 1738 | if (vport->fc_flag & FC_DISC_TMO) { |
1640 | spin_lock_irqsave(shost->host_lock, iflags); | 1739 | spin_lock_irqsave(shost->host_lock, iflags); |
@@ -1898,13 +1997,17 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1898 | 1997 | ||
1899 | ndlp->nlp_last_elscmd = 0; | 1998 | ndlp->nlp_last_elscmd = 0; |
1900 | del_timer_sync(&ndlp->nlp_delayfunc); | 1999 | del_timer_sync(&ndlp->nlp_delayfunc); |
1901 | del_timer_sync(&ndlp->nlp_initiator_tmr); | ||
1902 | 2000 | ||
1903 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | 2001 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) |
1904 | list_del_init(&ndlp->els_retry_evt.evt_listp); | 2002 | list_del_init(&ndlp->els_retry_evt.evt_listp); |
1905 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) | 2003 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) |
1906 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | 2004 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
1907 | 2005 | ||
2006 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) { | ||
2007 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | ||
2008 | complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2)); | ||
2009 | } | ||
2010 | |||
1908 | lpfc_unreg_rpi(vport, ndlp); | 2011 | lpfc_unreg_rpi(vport, ndlp); |
1909 | 2012 | ||
1910 | return 0; | 2013 | return 0; |
@@ -2418,6 +2521,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2418 | vport->fc_flag &= ~FC_DISC_TMO; | 2521 | vport->fc_flag &= ~FC_DISC_TMO; |
2419 | spin_unlock_irq(shost->host_lock); | 2522 | spin_unlock_irq(shost->host_lock); |
2420 | 2523 | ||
2524 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
2525 | "disc timeout: state:x%x rtry:x%x flg:x%x", | ||
2526 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
2527 | |||
2421 | switch (vport->port_state) { | 2528 | switch (vport->port_state) { |
2422 | 2529 | ||
2423 | case LPFC_LOCAL_CFG_LINK: | 2530 | case LPFC_LOCAL_CFG_LINK: |
@@ -2743,7 +2850,7 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn) | |||
2743 | spin_lock_irq(shost->host_lock); | 2850 | spin_lock_irq(shost->host_lock); |
2744 | ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn); | 2851 | ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn); |
2745 | spin_unlock_irq(shost->host_lock); | 2852 | spin_unlock_irq(shost->host_lock); |
2746 | return NULL; | 2853 | return ndlp; |
2747 | } | 2854 | } |
2748 | 2855 | ||
2749 | void | 2856 | void |
@@ -2764,7 +2871,7 @@ lpfc_dev_loss_delay(unsigned long ptr) | |||
2764 | } | 2871 | } |
2765 | 2872 | ||
2766 | evtp->evt_arg1 = ndlp; | 2873 | evtp->evt_arg1 = ndlp; |
2767 | evtp->evt = LPFC_EVT_DEV_LOSS; | 2874 | evtp->evt = LPFC_EVT_DEV_LOSS_DELAY; |
2768 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 2875 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
2769 | if (phba->work_wait) | 2876 | if (phba->work_wait) |
2770 | lpfc_worker_wake_up(phba); | 2877 | lpfc_worker_wake_up(phba); |
@@ -2779,9 +2886,6 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2779 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); | 2886 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); |
2780 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); | 2887 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); |
2781 | INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp); | 2888 | INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp); |
2782 | init_timer(&ndlp->nlp_initiator_tmr); | ||
2783 | ndlp->nlp_initiator_tmr.function = lpfc_dev_loss_delay; | ||
2784 | ndlp->nlp_initiator_tmr.data = (unsigned long)ndlp; | ||
2785 | init_timer(&ndlp->nlp_delayfunc); | 2889 | init_timer(&ndlp->nlp_delayfunc); |
2786 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; | 2890 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; |
2787 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; | 2891 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; |
@@ -2790,6 +2894,11 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2790 | ndlp->nlp_sid = NLP_NO_SID; | 2894 | ndlp->nlp_sid = NLP_NO_SID; |
2791 | INIT_LIST_HEAD(&ndlp->nlp_listp); | 2895 | INIT_LIST_HEAD(&ndlp->nlp_listp); |
2792 | kref_init(&ndlp->kref); | 2896 | kref_init(&ndlp->kref); |
2897 | |||
2898 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | ||
2899 | "node init: did:x%x", | ||
2900 | ndlp->nlp_DID, 0, 0); | ||
2901 | |||
2793 | return; | 2902 | return; |
2794 | } | 2903 | } |
2795 | 2904 | ||
@@ -2798,6 +2907,11 @@ lpfc_nlp_release(struct kref *kref) | |||
2798 | { | 2907 | { |
2799 | struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, | 2908 | struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, |
2800 | kref); | 2909 | kref); |
2910 | |||
2911 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2912 | "node release: did:x%x flg:x%x type:x%x", | ||
2913 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
2914 | |||
2801 | lpfc_nlp_remove(ndlp->vport, ndlp); | 2915 | lpfc_nlp_remove(ndlp->vport, ndlp); |
2802 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); | 2916 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); |
2803 | } | 2917 | } |