diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:38 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:27:39 -0400 |
commit | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (patch) | |
tree | fadb1d8f1a817c2f85937b5e9c3b830bdecb5555 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | ed957684294618602b48f1950b0c9bbcb036583f (diff) |
[SCSI] lpfc: NPIV: add NPIV support on top of SLI-3
NPIV support is added to the driver. It utilizes the interfaces of
the fc transport for the creation and deletion of vports. Within the
driver, a new Scsi_Host is created for each NPIV instance, and is
paired with a new instance of a FC port. This allows N FC Port
elements to share a single Adapter.
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_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 298 |
1 files changed, 207 insertions, 91 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index b1727481a1e6..50a247602a6b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * |
@@ -35,6 +35,7 @@ | |||
35 | #include "lpfc.h" | 35 | #include "lpfc.h" |
36 | #include "lpfc_logmsg.h" | 36 | #include "lpfc_logmsg.h" |
37 | #include "lpfc_crtn.h" | 37 | #include "lpfc_crtn.h" |
38 | #include "lpfc_vport.h" | ||
38 | 39 | ||
39 | 40 | ||
40 | /* Called to verify a rcv'ed ADISC was intended for us. */ | 41 | /* Called to verify a rcv'ed ADISC was intended for us. */ |
@@ -74,12 +75,14 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
74 | hsp->cls1.rcvDataSizeLsb; | 75 | hsp->cls1.rcvDataSizeLsb; |
75 | ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | | 76 | ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | |
76 | sp->cls1.rcvDataSizeLsb; | 77 | sp->cls1.rcvDataSizeLsb; |
78 | if (!ssp_value) | ||
79 | goto bad_service_param; | ||
77 | if (ssp_value > hsp_value) { | 80 | if (ssp_value > hsp_value) { |
78 | sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; | 81 | sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; |
79 | sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; | 82 | sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; |
80 | } | 83 | } |
81 | } else if (class == CLASS1) { | 84 | } else if (class == CLASS1) { |
82 | return 0; | 85 | goto bad_service_param; |
83 | } | 86 | } |
84 | 87 | ||
85 | if (sp->cls2.classValid) { | 88 | if (sp->cls2.classValid) { |
@@ -87,12 +90,14 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
87 | hsp->cls2.rcvDataSizeLsb; | 90 | hsp->cls2.rcvDataSizeLsb; |
88 | ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | | 91 | ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | |
89 | sp->cls2.rcvDataSizeLsb; | 92 | sp->cls2.rcvDataSizeLsb; |
93 | if (!ssp_value) | ||
94 | goto bad_service_param; | ||
90 | if (ssp_value > hsp_value) { | 95 | if (ssp_value > hsp_value) { |
91 | sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; | 96 | sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; |
92 | sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; | 97 | sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; |
93 | } | 98 | } |
94 | } else if (class == CLASS2) { | 99 | } else if (class == CLASS2) { |
95 | return 0; | 100 | goto bad_service_param; |
96 | } | 101 | } |
97 | 102 | ||
98 | if (sp->cls3.classValid) { | 103 | if (sp->cls3.classValid) { |
@@ -100,12 +105,14 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
100 | hsp->cls3.rcvDataSizeLsb; | 105 | hsp->cls3.rcvDataSizeLsb; |
101 | ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | | 106 | ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | |
102 | sp->cls3.rcvDataSizeLsb; | 107 | sp->cls3.rcvDataSizeLsb; |
108 | if (!ssp_value) | ||
109 | goto bad_service_param; | ||
103 | if (ssp_value > hsp_value) { | 110 | if (ssp_value > hsp_value) { |
104 | sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; | 111 | sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; |
105 | sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; | 112 | sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; |
106 | } | 113 | } |
107 | } else if (class == CLASS3) { | 114 | } else if (class == CLASS3) { |
108 | return 0; | 115 | goto bad_service_param; |
109 | } | 116 | } |
110 | 117 | ||
111 | /* | 118 | /* |
@@ -124,11 +131,22 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
124 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); | 131 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); |
125 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); | 132 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); |
126 | return 1; | 133 | return 1; |
134 | bad_service_param: | ||
135 | lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, | ||
136 | "%d (%d):0207 Device %x " | ||
137 | "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent " | ||
138 | "invalid service parameters. Ignoring device.\n", | ||
139 | vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, | ||
140 | sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1], | ||
141 | sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3], | ||
142 | sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5], | ||
143 | sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]); | ||
144 | return 0; | ||
127 | } | 145 | } |
128 | 146 | ||
129 | static void * | 147 | static void * |
130 | lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 148 | lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
131 | struct lpfc_iocbq *rspiocb) | 149 | struct lpfc_iocbq *rspiocb) |
132 | { | 150 | { |
133 | struct lpfc_dmabuf *pcmd, *prsp; | 151 | struct lpfc_dmabuf *pcmd, *prsp; |
134 | uint32_t *lp; | 152 | uint32_t *lp; |
@@ -176,10 +194,12 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
176 | 194 | ||
177 | /* Abort outstanding I/O on NPort <nlp_DID> */ | 195 | /* Abort outstanding I/O on NPort <nlp_DID> */ |
178 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 196 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
179 | "%d:0205 Abort outstanding I/O on NPort x%x " | 197 | "%d (%d):0205 Abort outstanding I/O on NPort x%x " |
180 | "Data: x%x x%x x%x\n", | 198 | "Data: x%x x%x x%x\n", |
181 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, | 199 | phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, |
182 | ndlp->nlp_state, ndlp->nlp_rpi); | 200 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
201 | |||
202 | lpfc_fabric_abort_nport(ndlp); | ||
183 | 203 | ||
184 | /* First check the txq */ | 204 | /* First check the txq */ |
185 | spin_lock_irq(&phba->hbalock); | 205 | spin_lock_irq(&phba->hbalock); |
@@ -198,15 +218,16 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
198 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 218 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
199 | /* Check to see if iocb matches the nport we are looking | 219 | /* Check to see if iocb matches the nport we are looking |
200 | for */ | 220 | for */ |
201 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) | 221 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
202 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 222 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
223 | } | ||
203 | } | 224 | } |
204 | spin_unlock_irq(&phba->hbalock); | 225 | spin_unlock_irq(&phba->hbalock); |
205 | 226 | ||
206 | while (!list_empty(&completions)) { | 227 | while (!list_empty(&completions)) { |
207 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | 228 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
208 | cmd = &iocb->iocb; | 229 | cmd = &iocb->iocb; |
209 | list_del(&iocb->list); | 230 | list_del_init(&iocb->list); |
210 | 231 | ||
211 | if (!iocb->iocb_cmpl) | 232 | if (!iocb->iocb_cmpl) |
212 | lpfc_sli_release_iocbq(phba, iocb); | 233 | lpfc_sli_release_iocbq(phba, iocb); |
@@ -225,7 +246,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
225 | 246 | ||
226 | static int | 247 | static int |
227 | lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 248 | lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
228 | struct lpfc_iocbq *cmdiocb) | 249 | struct lpfc_iocbq *cmdiocb) |
229 | { | 250 | { |
230 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 251 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
231 | struct lpfc_hba *phba = vport->phba; | 252 | struct lpfc_hba *phba = vport->phba; |
@@ -244,7 +265,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
244 | * the FLOGI and resend it first. | 265 | * the FLOGI and resend it first. |
245 | */ | 266 | */ |
246 | if (vport->fc_flag & FC_PT2PT) { | 267 | if (vport->fc_flag & FC_PT2PT) { |
247 | lpfc_els_abort_flogi(phba); | 268 | lpfc_els_abort_flogi(phba); |
248 | if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { | 269 | if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { |
249 | /* If the other side is supposed to initiate | 270 | /* If the other side is supposed to initiate |
250 | * the PLOGI anyway, just ACC it now and | 271 | * the PLOGI anyway, just ACC it now and |
@@ -279,8 +300,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
279 | 300 | ||
280 | /* PLOGI chkparm OK */ | 301 | /* PLOGI chkparm OK */ |
281 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 302 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
282 | "%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", | 303 | "%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", |
283 | phba->brd_no, | 304 | phba->brd_no, vport->vpi, |
284 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, | 305 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, |
285 | ndlp->nlp_rpi); | 306 | ndlp->nlp_rpi); |
286 | 307 | ||
@@ -314,8 +335,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
314 | return 1; | 335 | return 1; |
315 | } | 336 | } |
316 | 337 | ||
317 | if ((vport->fc_flag & FC_PT2PT) | 338 | if ((vport->fc_flag & FC_PT2PT) && |
318 | && !(vport->fc_flag & FC_PT2PT_PLOGI)) { | 339 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { |
319 | /* rcv'ed PLOGI decides what our NPortId will be */ | 340 | /* rcv'ed PLOGI decides what our NPortId will be */ |
320 | vport->fc_myDID = icmd->un.rcvels.parmRo; | 341 | vport->fc_myDID = icmd->un.rcvels.parmRo; |
321 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 342 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
@@ -327,7 +348,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
327 | rc = lpfc_sli_issue_mbox | 348 | rc = lpfc_sli_issue_mbox |
328 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); | 349 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); |
329 | if (rc == MBX_NOT_FINISHED) { | 350 | if (rc == MBX_NOT_FINISHED) { |
330 | mempool_free( mbox, phba->mbox_mem_pool); | 351 | mempool_free(mbox, phba->mbox_mem_pool); |
331 | goto out; | 352 | goto out; |
332 | } | 353 | } |
333 | 354 | ||
@@ -337,8 +358,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
337 | if (!mbox) | 358 | if (!mbox) |
338 | goto out; | 359 | goto out; |
339 | 360 | ||
340 | rc = lpfc_reg_login(phba, icmd->un.rcvels.remoteID, (uint8_t *) sp, | 361 | rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID, |
341 | mbox, 0); | 362 | (uint8_t *) sp, mbox, 0); |
342 | if (rc) { | 363 | if (rc) { |
343 | mempool_free(mbox, phba->mbox_mem_pool); | 364 | mempool_free(mbox, phba->mbox_mem_pool); |
344 | goto out; | 365 | goto out; |
@@ -415,7 +436,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
415 | lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); | 436 | lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); |
416 | } else { | 437 | } else { |
417 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, | 438 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, |
418 | NULL, 0); | 439 | NULL, 0); |
419 | } | 440 | } |
420 | return 1; | 441 | return 1; |
421 | } | 442 | } |
@@ -457,7 +478,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
457 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 478 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
458 | 479 | ||
459 | if (!(ndlp->nlp_type & NLP_FABRIC) || | 480 | if (!(ndlp->nlp_type & NLP_FABRIC) || |
460 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 481 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
461 | /* Only try to re-login if this is NOT a Fabric Node */ | 482 | /* Only try to re-login if this is NOT a Fabric Node */ |
462 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 483 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
463 | spin_lock_irq(shost->host_lock); | 484 | spin_lock_irq(shost->host_lock); |
@@ -499,8 +520,7 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
499 | 520 | ||
500 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | 521 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
501 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | 522 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
502 | if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && | 523 | if (npr->prliType == PRLI_FCP_TYPE) { |
503 | (npr->prliType == PRLI_FCP_TYPE)) { | ||
504 | if (npr->initiatorFunc) | 524 | if (npr->initiatorFunc) |
505 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | 525 | ndlp->nlp_type |= NLP_FCP_INITIATOR; |
506 | if (npr->targetFunc) | 526 | if (npr->targetFunc) |
@@ -526,15 +546,16 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
526 | struct lpfc_hba *phba = vport->phba; | 546 | struct lpfc_hba *phba = vport->phba; |
527 | 547 | ||
528 | /* Check config parameter use-adisc or FCP-2 */ | 548 | /* Check config parameter use-adisc or FCP-2 */ |
529 | if (phba->cfg_use_adisc == 0 && | 549 | if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || |
530 | (vport->fc_flag & FC_RSCN_MODE) == 0 && | 550 | ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
531 | (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) == 0) | 551 | spin_lock_irq(shost->host_lock); |
532 | return 0; | 552 | ndlp->nlp_flag |= NLP_NPR_ADISC; |
533 | 553 | spin_unlock_irq(shost->host_lock); | |
534 | spin_lock_irq(shost->host_lock); | 554 | return 1; |
535 | ndlp->nlp_flag |= NLP_NPR_ADISC; | 555 | } |
536 | spin_unlock_irq(shost->host_lock); | 556 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
537 | return 1; | 557 | lpfc_unreg_rpi(vport, ndlp); |
558 | return 0; | ||
538 | } | 559 | } |
539 | 560 | ||
540 | static uint32_t | 561 | static uint32_t |
@@ -542,9 +563,9 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
542 | void *arg, uint32_t evt) | 563 | void *arg, uint32_t evt) |
543 | { | 564 | { |
544 | lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, | 565 | lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, |
545 | "%d:0253 Illegal State Transition: node x%x event x%x, " | 566 | "%d (%d):0253 Illegal State Transition: node x%x " |
546 | "state x%x Data: x%x x%x\n", | 567 | "event x%x, state x%x Data: x%x x%x\n", |
547 | vport->phba->brd_no, | 568 | vport->phba->brd_no, vport->vpi, |
548 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, | 569 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, |
549 | ndlp->nlp_flag); | 570 | ndlp->nlp_flag); |
550 | return ndlp->nlp_state; | 571 | return ndlp->nlp_state; |
@@ -629,7 +650,7 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
629 | */ | 650 | */ |
630 | phba->fc_stat.elsLogiCol++; | 651 | phba->fc_stat.elsLogiCol++; |
631 | port_cmp = memcmp(&vport->fc_portname, &sp->portName, | 652 | port_cmp = memcmp(&vport->fc_portname, &sp->portName, |
632 | sizeof (struct lpfc_name)); | 653 | sizeof(struct lpfc_name)); |
633 | 654 | ||
634 | if (port_cmp >= 0) { | 655 | if (port_cmp >= 0) { |
635 | /* Reject this request because the remote node will accept | 656 | /* Reject this request because the remote node will accept |
@@ -645,12 +666,26 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
645 | } | 666 | } |
646 | 667 | ||
647 | static uint32_t | 668 | static uint32_t |
669 | lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
670 | void *arg, uint32_t evt) | ||
671 | { | ||
672 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | ||
673 | struct ls_rjt stat; | ||
674 | |||
675 | memset(&stat, 0, sizeof (struct ls_rjt)); | ||
676 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; | ||
677 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
678 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | ||
679 | return ndlp->nlp_state; | ||
680 | } | ||
681 | |||
682 | static uint32_t | ||
648 | lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 683 | lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
649 | void *arg, uint32_t evt) | 684 | void *arg, uint32_t evt) |
650 | { | 685 | { |
651 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 686 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
652 | 687 | ||
653 | /* software abort outstanding PLOGI */ | 688 | /* software abort outstanding PLOGI */ |
654 | lpfc_els_abort(vport->phba, ndlp); | 689 | lpfc_els_abort(vport->phba, ndlp); |
655 | 690 | ||
656 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); | 691 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
@@ -724,9 +759,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, | |||
724 | 759 | ||
725 | /* PLOGI chkparm OK */ | 760 | /* PLOGI chkparm OK */ |
726 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 761 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
727 | "%d:0121 PLOGI chkparm OK " | 762 | "%d (%d):0121 PLOGI chkparm OK " |
728 | "Data: x%x x%x x%x x%x\n", | 763 | "Data: x%x x%x x%x x%x\n", |
729 | phba->brd_no, | 764 | phba->brd_no, vport->vpi, |
730 | ndlp->nlp_DID, ndlp->nlp_state, | 765 | ndlp->nlp_DID, ndlp->nlp_state, |
731 | ndlp->nlp_flag, ndlp->nlp_rpi); | 766 | ndlp->nlp_flag, ndlp->nlp_rpi); |
732 | 767 | ||
@@ -748,13 +783,20 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, | |||
748 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; | 783 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
749 | 784 | ||
750 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 785 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
751 | if (!mbox) | 786 | if (!mbox) { |
787 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
788 | "%d (%d):0133 PLOGI: no memory for reg_login " | ||
789 | "Data: x%x x%x x%x x%x\n", | ||
790 | phba->brd_no, vport->vpi, | ||
791 | ndlp->nlp_DID, ndlp->nlp_state, | ||
792 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
752 | goto out; | 793 | goto out; |
794 | } | ||
753 | 795 | ||
754 | lpfc_unreg_rpi(vport, ndlp); | 796 | lpfc_unreg_rpi(vport, ndlp); |
755 | 797 | ||
756 | if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp, | 798 | if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID, |
757 | mbox, 0) == 0) { | 799 | (uint8_t *) sp, mbox, 0) == 0) { |
758 | switch (ndlp->nlp_DID) { | 800 | switch (ndlp->nlp_DID) { |
759 | case NameServer_DID: | 801 | case NameServer_DID: |
760 | mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; | 802 | mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; |
@@ -775,16 +817,37 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, | |||
775 | return ndlp->nlp_state; | 817 | return ndlp->nlp_state; |
776 | } | 818 | } |
777 | lpfc_nlp_put(ndlp); | 819 | lpfc_nlp_put(ndlp); |
778 | mp = (struct lpfc_dmabuf *)mbox->context1; | 820 | mp = (struct lpfc_dmabuf *) mbox->context1; |
779 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 821 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
780 | kfree(mp); | 822 | kfree(mp); |
781 | mempool_free(mbox, phba->mbox_mem_pool); | 823 | mempool_free(mbox, phba->mbox_mem_pool); |
824 | |||
825 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
826 | "%d (%d):0134 PLOGI: cannot issue reg_login " | ||
827 | "Data: x%x x%x x%x x%x\n", | ||
828 | phba->brd_no, vport->vpi, | ||
829 | ndlp->nlp_DID, ndlp->nlp_state, | ||
830 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
782 | } else { | 831 | } else { |
783 | mempool_free(mbox, phba->mbox_mem_pool); | 832 | mempool_free(mbox, phba->mbox_mem_pool); |
833 | |||
834 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
835 | "%d (%d):0135 PLOGI: cannot format reg_login " | ||
836 | "Data: x%x x%x x%x x%x\n", | ||
837 | phba->brd_no, vport->vpi, | ||
838 | ndlp->nlp_DID, ndlp->nlp_state, | ||
839 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
784 | } | 840 | } |
785 | 841 | ||
786 | 842 | ||
787 | out: | 843 | out: |
844 | if (ndlp->nlp_DID == NameServer_DID) { | ||
845 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
846 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
847 | "%d (%d):0261 Cannot Register NameServer login\n", | ||
848 | phba->brd_no, vport->vpi); | ||
849 | } | ||
850 | |||
788 | /* Free this node since the driver cannot login or has the wrong | 851 | /* Free this node since the driver cannot login or has the wrong |
789 | sparm */ | 852 | sparm */ |
790 | lpfc_drop_node(vport, ndlp); | 853 | lpfc_drop_node(vport, ndlp); |
@@ -820,12 +883,18 @@ lpfc_device_recov_plogi_issue(struct lpfc_vport *vport, | |||
820 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 883 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
821 | struct lpfc_hba *phba = vport->phba; | 884 | struct lpfc_hba *phba = vport->phba; |
822 | 885 | ||
886 | /* Don't do anything that will mess up processing of the | ||
887 | * previous RSCN. | ||
888 | */ | ||
889 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
890 | return ndlp->nlp_state; | ||
891 | |||
823 | /* software abort outstanding PLOGI */ | 892 | /* software abort outstanding PLOGI */ |
824 | lpfc_els_abort(phba, ndlp); | 893 | lpfc_els_abort(phba, ndlp); |
825 | 894 | ||
826 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; | 895 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; |
827 | spin_lock_irq(shost->host_lock); | ||
828 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 896 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
897 | spin_lock_irq(shost->host_lock); | ||
829 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 898 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
830 | spin_unlock_irq(shost->host_lock); | 899 | spin_unlock_irq(shost->host_lock); |
831 | 900 | ||
@@ -924,7 +993,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, | |||
924 | irsp = &rspiocb->iocb; | 993 | irsp = &rspiocb->iocb; |
925 | 994 | ||
926 | if ((irsp->ulpStatus) || | 995 | if ((irsp->ulpStatus) || |
927 | (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { | 996 | (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { |
928 | /* 1 sec timeout */ | 997 | /* 1 sec timeout */ |
929 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 998 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
930 | spin_lock_irq(shost->host_lock); | 999 | spin_lock_irq(shost->host_lock); |
@@ -980,6 +1049,12 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, | |||
980 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1049 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
981 | struct lpfc_hba *phba = vport->phba; | 1050 | struct lpfc_hba *phba = vport->phba; |
982 | 1051 | ||
1052 | /* Don't do anything that will mess up processing of the | ||
1053 | * previous RSCN. | ||
1054 | */ | ||
1055 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1056 | return ndlp->nlp_state; | ||
1057 | |||
983 | /* software abort outstanding ADISC */ | 1058 | /* software abort outstanding ADISC */ |
984 | lpfc_els_abort(phba, ndlp); | 1059 | lpfc_els_abort(phba, ndlp); |
985 | 1060 | ||
@@ -987,9 +1062,8 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, | |||
987 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1062 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
988 | spin_lock_irq(shost->host_lock); | 1063 | spin_lock_irq(shost->host_lock); |
989 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1064 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
990 | ndlp->nlp_flag |= NLP_NPR_ADISC; | ||
991 | spin_unlock_irq(shost->host_lock); | 1065 | spin_unlock_irq(shost->host_lock); |
992 | 1066 | lpfc_disc_set_adisc(vport, ndlp); | |
993 | return ndlp->nlp_state; | 1067 | return ndlp->nlp_state; |
994 | } | 1068 | } |
995 | 1069 | ||
@@ -1035,6 +1109,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, | |||
1035 | if ((mb = phba->sli.mbox_active)) { | 1109 | if ((mb = phba->sli.mbox_active)) { |
1036 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && | 1110 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && |
1037 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 1111 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
1112 | lpfc_nlp_put(ndlp); | ||
1038 | mb->context2 = NULL; | 1113 | mb->context2 = NULL; |
1039 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 1114 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
1040 | } | 1115 | } |
@@ -1049,6 +1124,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, | |||
1049 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1124 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1050 | kfree(mp); | 1125 | kfree(mp); |
1051 | } | 1126 | } |
1127 | lpfc_nlp_put(ndlp); | ||
1052 | list_del(&mb->list); | 1128 | list_del(&mb->list); |
1053 | mempool_free(mb, phba->mbox_mem_pool); | 1129 | mempool_free(mb, phba->mbox_mem_pool); |
1054 | } | 1130 | } |
@@ -1099,8 +1175,9 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1099 | if (mb->mbxStatus) { | 1175 | if (mb->mbxStatus) { |
1100 | /* RegLogin failed */ | 1176 | /* RegLogin failed */ |
1101 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 1177 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
1102 | "%d:0246 RegLogin failed Data: x%x x%x x%x\n", | 1178 | "%d (%d):0246 RegLogin failed Data: x%x x%x " |
1103 | phba->brd_no, | 1179 | "x%x\n", |
1180 | phba->brd_no, vport->vpi, | ||
1104 | did, mb->mbxStatus, vport->port_state); | 1181 | did, mb->mbxStatus, vport->port_state); |
1105 | 1182 | ||
1106 | /* | 1183 | /* |
@@ -1167,11 +1244,18 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, | |||
1167 | { | 1244 | { |
1168 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1245 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1169 | 1246 | ||
1247 | /* Don't do anything that will mess up processing of the | ||
1248 | * previous RSCN. | ||
1249 | */ | ||
1250 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1251 | return ndlp->nlp_state; | ||
1252 | |||
1170 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1253 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1171 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1254 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1172 | spin_lock_irq(shost->host_lock); | 1255 | spin_lock_irq(shost->host_lock); |
1173 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1256 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1174 | spin_unlock_irq(shost->host_lock); | 1257 | spin_unlock_irq(shost->host_lock); |
1258 | lpfc_disc_set_adisc(vport, ndlp); | ||
1175 | return ndlp->nlp_state; | 1259 | return ndlp->nlp_state; |
1176 | } | 1260 | } |
1177 | 1261 | ||
@@ -1239,6 +1323,7 @@ static uint32_t | |||
1239 | lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 1323 | lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1240 | void *arg, uint32_t evt) | 1324 | void *arg, uint32_t evt) |
1241 | { | 1325 | { |
1326 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1242 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1327 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
1243 | struct lpfc_hba *phba = vport->phba; | 1328 | struct lpfc_hba *phba = vport->phba; |
1244 | IOCB_t *irsp; | 1329 | IOCB_t *irsp; |
@@ -1267,29 +1352,45 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1267 | if (npr->Retry) | 1352 | if (npr->Retry) |
1268 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; | 1353 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; |
1269 | } | 1354 | } |
1355 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && | ||
1356 | (vport->port_type == LPFC_NPIV_PORT) && | ||
1357 | phba->cfg_vport_restrict_login) { | ||
1358 | spin_lock_irq(shost->host_lock); | ||
1359 | ndlp->nlp_flag |= NLP_TARGET_REMOVE; | ||
1360 | spin_unlock_irq(shost->host_lock); | ||
1361 | lpfc_issue_els_logo(vport, ndlp, 0); | ||
1362 | |||
1363 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | ||
1364 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
1365 | return ndlp->nlp_state; | ||
1366 | } | ||
1270 | 1367 | ||
1271 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1368 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1272 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); | 1369 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
1370 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); | ||
1371 | else | ||
1372 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
1273 | return ndlp->nlp_state; | 1373 | return ndlp->nlp_state; |
1274 | } | 1374 | } |
1275 | 1375 | ||
1276 | /*! lpfc_device_rm_prli_issue | 1376 | /*! lpfc_device_rm_prli_issue |
1277 | * | 1377 | * |
1278 | * \pre | 1378 | * \pre |
1279 | * \post | 1379 | * \post |
1280 | * \param phba | 1380 | * \param phba |
1281 | * \param ndlp | 1381 | * \param ndlp |
1282 | * \param arg | 1382 | * \param arg |
1283 | * \param evt | 1383 | * \param evt |
1284 | * \return uint32_t | 1384 | * \return uint32_t |
1285 | * | 1385 | * |
1286 | * \b Description: | 1386 | * \b Description: |
1287 | * This routine is envoked when we a request to remove a nport we are in the | 1387 | * This routine is envoked when we a request to remove a nport we are in the |
1288 | * process of PRLIing. We should software abort outstanding prli, unreg | 1388 | * process of PRLIing. We should software abort outstanding prli, unreg |
1289 | * login, send a logout. We will change node state to UNUSED_NODE, put it | 1389 | * login, send a logout. We will change node state to UNUSED_NODE, put it |
1290 | * in plogi state so it can be freed when LOGO completes. | 1390 | * on plogi list so it can be freed when LOGO completes. |
1291 | * | 1391 | * |
1292 | */ | 1392 | */ |
1393 | |||
1293 | static uint32_t | 1394 | static uint32_t |
1294 | lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 1395 | lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1295 | void *arg, uint32_t evt) | 1396 | void *arg, uint32_t evt) |
@@ -1312,21 +1413,21 @@ lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1312 | 1413 | ||
1313 | 1414 | ||
1314 | /*! lpfc_device_recov_prli_issue | 1415 | /*! lpfc_device_recov_prli_issue |
1315 | * | 1416 | * |
1316 | * \pre | 1417 | * \pre |
1317 | * \post | 1418 | * \post |
1318 | * \param phba | 1419 | * \param phba |
1319 | * \param ndlp | 1420 | * \param ndlp |
1320 | * \param arg | 1421 | * \param arg |
1321 | * \param evt | 1422 | * \param evt |
1322 | * \return uint32_t | 1423 | * \return uint32_t |
1323 | * | 1424 | * |
1324 | * \b Description: | 1425 | * \b Description: |
1325 | * The routine is envoked when the state of a device is unknown, like | 1426 | * The routine is envoked when the state of a device is unknown, like |
1326 | * during a link down. We should remove the nodelist entry from the | 1427 | * during a link down. We should remove the nodelist entry from the |
1327 | * unmapped list, issue a UNREG_LOGIN, do a software abort of the | 1428 | * unmapped list, issue a UNREG_LOGIN, do a software abort of the |
1328 | * outstanding PRLI command, then free the node entry. | 1429 | * outstanding PRLI command, then free the node entry. |
1329 | */ | 1430 | */ |
1330 | static uint32_t | 1431 | static uint32_t |
1331 | lpfc_device_recov_prli_issue(struct lpfc_vport *vport, | 1432 | lpfc_device_recov_prli_issue(struct lpfc_vport *vport, |
1332 | struct lpfc_nodelist *ndlp, | 1433 | struct lpfc_nodelist *ndlp, |
@@ -1336,6 +1437,12 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, | |||
1336 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1437 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1337 | struct lpfc_hba *phba = vport->phba; | 1438 | struct lpfc_hba *phba = vport->phba; |
1338 | 1439 | ||
1440 | /* Don't do anything that will mess up processing of the | ||
1441 | * previous RSCN. | ||
1442 | */ | ||
1443 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1444 | return ndlp->nlp_state; | ||
1445 | |||
1339 | /* software abort outstanding PRLI */ | 1446 | /* software abort outstanding PRLI */ |
1340 | lpfc_els_abort(phba, ndlp); | 1447 | lpfc_els_abort(phba, ndlp); |
1341 | 1448 | ||
@@ -1344,6 +1451,7 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, | |||
1344 | spin_lock_irq(shost->host_lock); | 1451 | spin_lock_irq(shost->host_lock); |
1345 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1452 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1346 | spin_unlock_irq(shost->host_lock); | 1453 | spin_unlock_irq(shost->host_lock); |
1454 | lpfc_disc_set_adisc(vport, ndlp); | ||
1347 | return ndlp->nlp_state; | 1455 | return ndlp->nlp_state; |
1348 | } | 1456 | } |
1349 | 1457 | ||
@@ -1466,7 +1574,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1466 | 1574 | ||
1467 | /* flush the target */ | 1575 | /* flush the target */ |
1468 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1576 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
1469 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 1577 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); |
1470 | 1578 | ||
1471 | /* Treat like rcv logo */ | 1579 | /* Treat like rcv logo */ |
1472 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); | 1580 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); |
@@ -1573,8 +1681,9 @@ lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1573 | * here will affect the counting of discovery threads. | 1681 | * here will affect the counting of discovery threads. |
1574 | */ | 1682 | */ |
1575 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && | 1683 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && |
1576 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){ | 1684 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
1577 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 1685 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
1686 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | ||
1578 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1687 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1579 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); | 1688 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
1580 | lpfc_issue_els_adisc(vport, ndlp, 0); | 1689 | lpfc_issue_els_adisc(vport, ndlp, 0); |
@@ -1719,6 +1828,12 @@ lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1719 | { | 1828 | { |
1720 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1829 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1721 | 1830 | ||
1831 | /* Don't do anything that will mess up processing of the | ||
1832 | * previous RSCN. | ||
1833 | */ | ||
1834 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1835 | return ndlp->nlp_state; | ||
1836 | |||
1722 | spin_lock_irq(shost->host_lock); | 1837 | spin_lock_irq(shost->host_lock); |
1723 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1838 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1724 | spin_unlock_irq(shost->host_lock); | 1839 | spin_unlock_irq(shost->host_lock); |
@@ -1803,7 +1918,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1803 | lpfc_disc_illegal, /* DEVICE_RECOVERY */ | 1918 | lpfc_disc_illegal, /* DEVICE_RECOVERY */ |
1804 | 1919 | ||
1805 | lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ | 1920 | lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ |
1806 | lpfc_rcv_els_plogi_issue, /* RCV_PRLI */ | 1921 | lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */ |
1807 | lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */ | 1922 | lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */ |
1808 | lpfc_rcv_els_plogi_issue, /* RCV_ADISC */ | 1923 | lpfc_rcv_els_plogi_issue, /* RCV_ADISC */ |
1809 | lpfc_rcv_els_plogi_issue, /* RCV_PDISC */ | 1924 | lpfc_rcv_els_plogi_issue, /* RCV_PDISC */ |
@@ -1915,9 +2030,9 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1915 | 2030 | ||
1916 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ | 2031 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ |
1917 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 2032 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
1918 | "%d:0211 DSM in event x%x on NPort x%x in state %d " | 2033 | "%d (%d):0211 DSM in event x%x on NPort x%x in " |
1919 | "Data: x%x\n", | 2034 | "state %d Data: x%x\n", |
1920 | phba->brd_no, | 2035 | phba->brd_no, vport->vpi, |
1921 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); | 2036 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); |
1922 | 2037 | ||
1923 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; | 2038 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; |
@@ -1925,9 +2040,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1925 | 2040 | ||
1926 | /* DSM out state <rc> on NPort <nlp_DID> */ | 2041 | /* DSM out state <rc> on NPort <nlp_DID> */ |
1927 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 2042 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
1928 | "%d:0212 DSM out state %d on NPort x%x Data: x%x\n", | 2043 | "%d (%d):0212 DSM out state %d on NPort x%x " |
1929 | phba->brd_no, | 2044 | "Data: x%x\n", |
1930 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | 2045 | phba->brd_no, vport->vpi, |
2046 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | ||
1931 | 2047 | ||
1932 | lpfc_nlp_put(ndlp); | 2048 | lpfc_nlp_put(ndlp); |
1933 | 2049 | ||