1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/blkdev.h>
23#include <linux/pci.h>
24#include <linux/slab.h>
25#include <linux/interrupt.h>
26
27#include <scsi/scsi.h>
28#include <scsi/scsi_device.h>
29#include <scsi/scsi_host.h>
30#include <scsi/scsi_transport_fc.h>
31
32#include "lpfc_hw4.h"
33#include "lpfc_hw.h"
34#include "lpfc_sli.h"
35#include "lpfc_sli4.h"
36#include "lpfc_nl.h"
37#include "lpfc_disc.h"
38#include "lpfc_scsi.h"
39#include "lpfc.h"
40#include "lpfc_logmsg.h"
41#include "lpfc_crtn.h"
42#include "lpfc_vport.h"
43#include "lpfc_debugfs.h"
44
45
46
47static int
48lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
49 struct lpfc_name *nn, struct lpfc_name *pn)
50{
51
52 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
53 return 0;
54
55
56
57
58 if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
59 return 0;
60
61 if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
62 return 0;
63
64
65 return 1;
66}
67
68int
69lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
70 struct serv_parm *sp, uint32_t class, int flogi)
71{
72 volatile struct serv_parm *hsp = &vport->fc_sparam;
73 uint16_t hsp_value, ssp_value = 0;
74
75
76
77
78
79
80
81
82 if (sp->cls1.classValid) {
83 if (!flogi) {
84 hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
85 hsp->cls1.rcvDataSizeLsb);
86 ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
87 sp->cls1.rcvDataSizeLsb);
88 if (!ssp_value)
89 goto bad_service_param;
90 if (ssp_value > hsp_value) {
91 sp->cls1.rcvDataSizeLsb =
92 hsp->cls1.rcvDataSizeLsb;
93 sp->cls1.rcvDataSizeMsb =
94 hsp->cls1.rcvDataSizeMsb;
95 }
96 }
97 } else if (class == CLASS1)
98 goto bad_service_param;
99 if (sp->cls2.classValid) {
100 if (!flogi) {
101 hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
102 hsp->cls2.rcvDataSizeLsb);
103 ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
104 sp->cls2.rcvDataSizeLsb);
105 if (!ssp_value)
106 goto bad_service_param;
107 if (ssp_value > hsp_value) {
108 sp->cls2.rcvDataSizeLsb =
109 hsp->cls2.rcvDataSizeLsb;
110 sp->cls2.rcvDataSizeMsb =
111 hsp->cls2.rcvDataSizeMsb;
112 }
113 }
114 } else if (class == CLASS2)
115 goto bad_service_param;
116 if (sp->cls3.classValid) {
117 if (!flogi) {
118 hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
119 hsp->cls3.rcvDataSizeLsb);
120 ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
121 sp->cls3.rcvDataSizeLsb);
122 if (!ssp_value)
123 goto bad_service_param;
124 if (ssp_value > hsp_value) {
125 sp->cls3.rcvDataSizeLsb =
126 hsp->cls3.rcvDataSizeLsb;
127 sp->cls3.rcvDataSizeMsb =
128 hsp->cls3.rcvDataSizeMsb;
129 }
130 }
131 } else if (class == CLASS3)
132 goto bad_service_param;
133
134
135
136
137
138
139 hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
140 ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
141 if (ssp_value > hsp_value) {
142 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
143 sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
144 (hsp->cmn.bbRcvSizeMsb & 0x0F);
145 }
146
147 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
148 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
149 return 1;
150bad_service_param:
151 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
152 "0207 Device %x "
153 "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
154 "invalid service parameters. Ignoring device.\n",
155 ndlp->nlp_DID,
156 sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
157 sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
158 sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
159 sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
160 return 0;
161}
162
163static void *
164lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
165 struct lpfc_iocbq *rspiocb)
166{
167 struct lpfc_dmabuf *pcmd, *prsp;
168 uint32_t *lp;
169 void *ptr = NULL;
170 IOCB_t *irsp;
171
172 irsp = &rspiocb->iocb;
173 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
174
175
176
177
178 if (pcmd) {
179 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf,
180 list);
181 if (prsp) {
182 lp = (uint32_t *) prsp->virt;
183 ptr = (void *)((uint8_t *)lp + sizeof(uint32_t));
184 }
185 } else {
186
187 if (!(irsp->ulpStatus)) {
188 irsp->ulpStatus = IOSTAT_LOCAL_REJECT;
189 irsp->un.ulpWord[4] = IOERR_SLI_ABORTED;
190 }
191 ptr = NULL;
192 }
193 return ptr;
194}
195
196
197
198
199
200
201
202
203int
204lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
205{
206 LIST_HEAD(completions);
207 LIST_HEAD(txcmplq_completions);
208 LIST_HEAD(abort_list);
209 struct lpfc_sli *psli = &phba->sli;
210 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
211 struct lpfc_iocbq *iocb, *next_iocb;
212
213
214 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
215 "2819 Abort outstanding I/O on NPort x%x "
216 "Data: x%x x%x x%x\n",
217 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
218 ndlp->nlp_rpi);
219
220 lpfc_fabric_abort_nport(ndlp);
221
222
223 spin_lock_irq(&phba->hbalock);
224 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
225
226 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
227
228 list_move_tail(&iocb->list, &completions);
229 }
230 }
231
232
233 list_splice_init(&pring->txcmplq, &txcmplq_completions);
234 spin_unlock_irq(&phba->hbalock);
235
236 list_for_each_entry_safe(iocb, next_iocb, &txcmplq_completions, list) {
237
238 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
239 list_add_tail(&iocb->dlist, &abort_list);
240 }
241 spin_lock_irq(&phba->hbalock);
242 list_splice(&txcmplq_completions, &pring->txcmplq);
243 spin_unlock_irq(&phba->hbalock);
244
245 list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
246 spin_lock_irq(&phba->hbalock);
247 list_del_init(&iocb->dlist);
248 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
249 spin_unlock_irq(&phba->hbalock);
250 }
251
252
253 lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
254 IOERR_SLI_ABORTED);
255
256 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
257 return 0;
258}
259
260static int
261lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
262 struct lpfc_iocbq *cmdiocb)
263{
264 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
265 struct lpfc_hba *phba = vport->phba;
266 struct lpfc_dmabuf *pcmd;
267 uint32_t *lp;
268 IOCB_t *icmd;
269 struct serv_parm *sp;
270 LPFC_MBOXQ_t *mbox;
271 struct ls_rjt stat;
272 int rc;
273
274 memset(&stat, 0, sizeof (struct ls_rjt));
275 if (vport->port_state <= LPFC_FDISC) {
276
277
278
279
280 if (vport->fc_flag & FC_PT2PT) {
281 lpfc_els_abort_flogi(phba);
282 if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
283
284
285
286
287 phba->fc_edtov = FF_DEF_EDTOV;
288 phba->fc_ratov = FF_DEF_RATOV;
289
290
291 lpfc_disc_start(vport);
292 } else
293 lpfc_initial_flogi(vport);
294 } else {
295 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
296 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
297 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
298 ndlp, NULL);
299 return 0;
300 }
301 }
302 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
303 lp = (uint32_t *) pcmd->virt;
304 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
305 if (wwn_to_u64(sp->portName.u.wwn) == 0) {
306 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
307 "0140 PLOGI Reject: invalid nname\n");
308 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
309 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;
310 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
311 NULL);
312 return 0;
313 }
314 if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {
315 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
316 "0141 PLOGI Reject: invalid pname\n");
317 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
318 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;
319 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
320 NULL);
321 return 0;
322 }
323 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
324
325 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
326 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
327 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
328 NULL);
329 return 0;
330 }
331 icmd = &cmdiocb->iocb;
332
333
334 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
335 "0114 PLOGI chkparm OK Data: x%x x%x x%x "
336 "x%x x%x x%x\n",
337 ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
338 ndlp->nlp_rpi, vport->port_state,
339 vport->fc_flag);
340
341 if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
342 ndlp->nlp_fcp_info |= CLASS2;
343 else
344 ndlp->nlp_fcp_info |= CLASS3;
345
346 ndlp->nlp_class_sup = 0;
347 if (sp->cls1.classValid)
348 ndlp->nlp_class_sup |= FC_COS_CLASS1;
349 if (sp->cls2.classValid)
350 ndlp->nlp_class_sup |= FC_COS_CLASS2;
351 if (sp->cls3.classValid)
352 ndlp->nlp_class_sup |= FC_COS_CLASS3;
353 if (sp->cls4.classValid)
354 ndlp->nlp_class_sup |= FC_COS_CLASS4;
355 ndlp->nlp_maxframe =
356 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
357
358
359 switch (ndlp->nlp_state) {
360 case NLP_STE_NPR_NODE:
361 if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
362 break;
363 case NLP_STE_REG_LOGIN_ISSUE:
364 case NLP_STE_PRLI_ISSUE:
365 case NLP_STE_UNMAPPED_NODE:
366 case NLP_STE_MAPPED_NODE:
367 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
368 return 1;
369 }
370
371
372 if ((vport->fc_flag & FC_PT2PT) &&
373 !(vport->fc_flag & FC_PT2PT_PLOGI)) {
374
375
376 vport->fc_myDID = icmd->un.rcvels.parmRo;
377 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
378 if (mbox == NULL)
379 goto out;
380 lpfc_config_link(phba, mbox);
381 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
382 mbox->vport = vport;
383 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
384 if (rc == MBX_NOT_FINISHED) {
385 mempool_free(mbox, phba->mbox_mem_pool);
386 goto out;
387 }
388
389
390
391
392
393 if (phba->sli_rev == LPFC_SLI_REV4)
394 lpfc_issue_reg_vfi(vport);
395
396 lpfc_can_disctmo(vport);
397 }
398 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
399 if (!mbox)
400 goto out;
401
402
403 if (phba->sli_rev == LPFC_SLI_REV4)
404 lpfc_unreg_rpi(vport, ndlp);
405
406 rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
407 (uint8_t *) sp, mbox, ndlp->nlp_rpi);
408 if (rc) {
409 mempool_free(mbox, phba->mbox_mem_pool);
410 goto out;
411 }
412
413
414
415
416 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
417
418
419
420
421 mbox->vport = vport;
422 spin_lock_irq(shost->host_lock);
423 ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
424 spin_unlock_irq(shost->host_lock);
425
426
427
428
429
430
431
432
433
434
435 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
436
437 lpfc_els_abort(phba, ndlp);
438 }
439
440 if ((vport->port_type == LPFC_NPIV_PORT &&
441 vport->cfg_restrict_login)) {
442
443
444
445
446
447
448 spin_lock_irq(shost->host_lock);
449 ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
450 spin_unlock_irq(shost->host_lock);
451 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
452 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
453 rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
454 ndlp, mbox);
455 if (rc)
456 mempool_free(mbox, phba->mbox_mem_pool);
457 return 1;
458 }
459 rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
460 if (rc)
461 mempool_free(mbox, phba->mbox_mem_pool);
462 return 1;
463out:
464 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
465 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
466 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
467 return 0;
468}
469
470
471
472
473
474
475
476
477
478static void
479lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
480{
481 struct lpfc_vport *vport;
482 struct lpfc_iocbq *elsiocb;
483 struct lpfc_nodelist *ndlp;
484 uint32_t cmd;
485
486 elsiocb = (struct lpfc_iocbq *)mboxq->context1;
487 ndlp = (struct lpfc_nodelist *) mboxq->context2;
488 vport = mboxq->vport;
489 cmd = elsiocb->drvrTimeout;
490
491 if (cmd == ELS_CMD_ADISC) {
492 lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);
493 } else {
494 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,
495 ndlp, NULL);
496 }
497 kfree(elsiocb);
498 mempool_free(mboxq, phba->mbox_mem_pool);
499}
500
501static int
502lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
503 struct lpfc_iocbq *cmdiocb)
504{
505 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
506 struct lpfc_iocbq *elsiocb;
507 struct lpfc_dmabuf *pcmd;
508 struct serv_parm *sp;
509 struct lpfc_name *pnn, *ppn;
510 struct ls_rjt stat;
511 ADISC *ap;
512 IOCB_t *icmd;
513 uint32_t *lp;
514 uint32_t cmd;
515
516 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
517 lp = (uint32_t *) pcmd->virt;
518
519 cmd = *lp++;
520 if (cmd == ELS_CMD_ADISC) {
521 ap = (ADISC *) lp;
522 pnn = (struct lpfc_name *) & ap->nodeName;
523 ppn = (struct lpfc_name *) & ap->portName;
524 } else {
525 sp = (struct serv_parm *) lp;
526 pnn = (struct lpfc_name *) & sp->nodeName;
527 ppn = (struct lpfc_name *) & sp->portName;
528 }
529
530 icmd = &cmdiocb->iocb;
531 if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
532
533
534
535
536
537
538 if (vport->phba->sli_rev == LPFC_SLI_REV4) {
539 elsiocb = kmalloc(sizeof(struct lpfc_iocbq),
540 GFP_KERNEL);
541 if (elsiocb) {
542
543
544 memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb,
545 sizeof(struct lpfc_iocbq));
546
547
548 elsiocb->drvrTimeout = cmd;
549
550 lpfc_sli4_resume_rpi(ndlp,
551 lpfc_mbx_cmpl_resume_rpi, elsiocb);
552 goto out;
553 }
554 }
555
556 if (cmd == ELS_CMD_ADISC) {
557 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
558 } else {
559 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
560 ndlp, NULL);
561 }
562out:
563
564 if (ndlp->nlp_type & NLP_FCP_TARGET)
565 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
566 else
567 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
568
569 return 1;
570 }
571
572 stat.un.b.lsRjtRsvd0 = 0;
573 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
574 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
575 stat.un.b.vendorUnique = 0;
576 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
577
578
579 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
580
581 spin_lock_irq(shost->host_lock);
582 ndlp->nlp_flag |= NLP_DELAY_TMO;
583 spin_unlock_irq(shost->host_lock);
584 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
585 ndlp->nlp_prev_state = ndlp->nlp_state;
586 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
587 return 0;
588}
589
590static int
591lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
592 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
593{
594 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
595 struct lpfc_hba *phba = vport->phba;
596 struct lpfc_vport **vports;
597 int i, active_vlink_present = 0 ;
598
599
600
601
602
603 spin_lock_irq(shost->host_lock);
604 ndlp->nlp_flag |= NLP_LOGO_ACC;
605 spin_unlock_irq(shost->host_lock);
606 if (els_cmd == ELS_CMD_PRLO)
607 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
608 else
609 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
610 if (ndlp->nlp_DID == Fabric_DID) {
611 if (vport->port_state <= LPFC_FDISC)
612 goto out;
613 lpfc_linkdown_port(vport);
614 spin_lock_irq(shost->host_lock);
615 vport->fc_flag |= FC_VPORT_LOGO_RCVD;
616 spin_unlock_irq(shost->host_lock);
617 vports = lpfc_create_vport_work_array(phba);
618 if (vports) {
619 for (i = 0; i <= phba->max_vports && vports[i] != NULL;
620 i++) {
621 if ((!(vports[i]->fc_flag &
622 FC_VPORT_LOGO_RCVD)) &&
623 (vports[i]->port_state > LPFC_FDISC)) {
624 active_vlink_present = 1;
625 break;
626 }
627 }
628 lpfc_destroy_vport_work_array(phba, vports);
629 }
630
631 if (active_vlink_present) {
632
633
634
635
636 mod_timer(&ndlp->nlp_delayfunc,
637 jiffies + msecs_to_jiffies(1000));
638 spin_lock_irq(shost->host_lock);
639 ndlp->nlp_flag |= NLP_DELAY_TMO;
640 spin_unlock_irq(shost->host_lock);
641 ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
642 vport->port_state = LPFC_FDISC;
643 } else {
644 spin_lock_irq(shost->host_lock);
645 phba->pport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG;
646 spin_unlock_irq(shost->host_lock);
647 lpfc_retry_pport_discovery(phba);
648 }
649 } else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
650 ((ndlp->nlp_type & NLP_FCP_TARGET) ||
651 !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
652 (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
653
654 mod_timer(&ndlp->nlp_delayfunc,
655 jiffies + msecs_to_jiffies(1000 * 1));
656 spin_lock_irq(shost->host_lock);
657 ndlp->nlp_flag |= NLP_DELAY_TMO;
658 spin_unlock_irq(shost->host_lock);
659
660 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
661 }
662out:
663 ndlp->nlp_prev_state = ndlp->nlp_state;
664 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
665
666 spin_lock_irq(shost->host_lock);
667 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
668 spin_unlock_irq(shost->host_lock);
669
670
671
672
673
674 return 0;
675}
676
677static void
678lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
679 struct lpfc_iocbq *cmdiocb)
680{
681 struct lpfc_dmabuf *pcmd;
682 uint32_t *lp;
683 PRLI *npr;
684 struct fc_rport *rport = ndlp->rport;
685 u32 roles;
686
687 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
688 lp = (uint32_t *) pcmd->virt;
689 npr = (PRLI *) ((uint8_t *) lp + sizeof (uint32_t));
690
691 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
692 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
693 if (npr->prliType == PRLI_FCP_TYPE) {
694 if (npr->initiatorFunc)
695 ndlp->nlp_type |= NLP_FCP_INITIATOR;
696 if (npr->targetFunc)
697 ndlp->nlp_type |= NLP_FCP_TARGET;
698 if (npr->Retry)
699 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
700 }
701 if (rport) {
702
703 roles = FC_RPORT_ROLE_UNKNOWN;
704 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
705 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
706 if (ndlp->nlp_type & NLP_FCP_TARGET)
707 roles |= FC_RPORT_ROLE_FCP_TARGET;
708
709 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
710 "rport rolechg: role:x%x did:x%x flg:x%x",
711 roles, ndlp->nlp_DID, ndlp->nlp_flag);
712
713 fc_remote_port_rolechg(rport, roles);
714 }
715}
716
717static uint32_t
718lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
719{
720 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
721
722 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
723 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
724 return 0;
725 }
726
727 if (!(vport->fc_flag & FC_PT2PT)) {
728
729 if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
730 ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
731 (ndlp->nlp_type & NLP_FCP_TARGET))) {
732 spin_lock_irq(shost->host_lock);
733 ndlp->nlp_flag |= NLP_NPR_ADISC;
734 spin_unlock_irq(shost->host_lock);
735 return 1;
736 }
737 }
738 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
739 lpfc_unreg_rpi(vport, ndlp);
740 return 0;
741}
742
743
744
745
746
747
748
749
750
751
752void
753lpfc_release_rpi(struct lpfc_hba *phba,
754 struct lpfc_vport *vport,
755 uint16_t rpi)
756{
757 LPFC_MBOXQ_t *pmb;
758 int rc;
759
760 pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
761 GFP_KERNEL);
762 if (!pmb)
763 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
764 "2796 mailbox memory allocation failed \n");
765 else {
766 lpfc_unreg_login(phba, vport->vpi, rpi, pmb);
767 pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
768 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
769 if (rc == MBX_NOT_FINISHED)
770 mempool_free(pmb, phba->mbox_mem_pool);
771 }
772}
773
774static uint32_t
775lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
776 void *arg, uint32_t evt)
777{
778 struct lpfc_hba *phba;
779 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
780 MAILBOX_t *mb;
781 uint16_t rpi;
782
783 phba = vport->phba;
784
785 if (!(phba->pport->load_flag & FC_UNLOADING) &&
786 (evt == NLP_EVT_CMPL_REG_LOGIN) &&
787 (!pmb->u.mb.mbxStatus)) {
788 mb = &pmb->u.mb;
789 rpi = pmb->u.mb.un.varWords[0];
790 lpfc_release_rpi(phba, vport, rpi);
791 }
792 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
793 "0271 Illegal State Transition: node x%x "
794 "event x%x, state x%x Data: x%x x%x\n",
795 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
796 ndlp->nlp_flag);
797 return ndlp->nlp_state;
798}
799
800static uint32_t
801lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
802 void *arg, uint32_t evt)
803{
804
805
806
807
808
809 if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
810 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
811 "0272 Illegal State Transition: node x%x "
812 "event x%x, state x%x Data: x%x x%x\n",
813 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
814 ndlp->nlp_flag);
815 }
816 return ndlp->nlp_state;
817}
818
819
820
821static uint32_t
822lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
823 void *arg, uint32_t evt)
824{
825 struct lpfc_iocbq *cmdiocb;
826
827 cmdiocb = (struct lpfc_iocbq *) arg;
828
829 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
830 return ndlp->nlp_state;
831 }
832 return NLP_STE_FREED_NODE;
833}
834
835static uint32_t
836lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
837 void *arg, uint32_t evt)
838{
839 lpfc_issue_els_logo(vport, ndlp, 0);
840 return ndlp->nlp_state;
841}
842
843static uint32_t
844lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
845 void *arg, uint32_t evt)
846{
847 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
848 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
849
850 spin_lock_irq(shost->host_lock);
851 ndlp->nlp_flag |= NLP_LOGO_ACC;
852 spin_unlock_irq(shost->host_lock);
853 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
854
855 return ndlp->nlp_state;
856}
857
858static uint32_t
859lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
860 void *arg, uint32_t evt)
861{
862 return NLP_STE_FREED_NODE;
863}
864
865static uint32_t
866lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
867 void *arg, uint32_t evt)
868{
869 return NLP_STE_FREED_NODE;
870}
871
872static uint32_t
873lpfc_device_recov_unused_node(struct lpfc_vport *vport,
874 struct lpfc_nodelist *ndlp,
875 void *arg, uint32_t evt)
876{
877 return ndlp->nlp_state;
878}
879
880static uint32_t
881lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
882 void *arg, uint32_t evt)
883{
884 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
885 struct lpfc_hba *phba = vport->phba;
886 struct lpfc_iocbq *cmdiocb = arg;
887 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
888 uint32_t *lp = (uint32_t *) pcmd->virt;
889 struct serv_parm *sp = (struct serv_parm *) (lp + 1);
890 struct ls_rjt stat;
891 int port_cmp;
892
893 memset(&stat, 0, sizeof (struct ls_rjt));
894
895
896
897
898 phba->fc_stat.elsLogiCol++;
899 port_cmp = memcmp(&vport->fc_portname, &sp->portName,
900 sizeof(struct lpfc_name));
901
902 if (port_cmp >= 0) {
903
904
905 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
906 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
907 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
908 NULL);
909 } else {
910 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) &&
911 (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
912 (vport->num_disc_nodes)) {
913 spin_lock_irq(shost->host_lock);
914 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
915 spin_unlock_irq(shost->host_lock);
916
917 lpfc_more_plogi(vport);
918 if (vport->num_disc_nodes == 0) {
919 spin_lock_irq(shost->host_lock);
920 vport->fc_flag &= ~FC_NDISC_ACTIVE;
921 spin_unlock_irq(shost->host_lock);
922 lpfc_can_disctmo(vport);
923 lpfc_end_rscn(vport);
924 }
925 }
926 }
927
928 return ndlp->nlp_state;
929}
930
931static uint32_t
932lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
933 void *arg, uint32_t evt)
934{
935 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
936 struct ls_rjt stat;
937
938 memset(&stat, 0, sizeof (struct ls_rjt));
939 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
940 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
941 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
942 return ndlp->nlp_state;
943}
944
945static uint32_t
946lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
947 void *arg, uint32_t evt)
948{
949 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
950
951
952 lpfc_els_abort(vport->phba, ndlp);
953
954 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
955 return ndlp->nlp_state;
956}
957
958static uint32_t
959lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
960 void *arg, uint32_t evt)
961{
962 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
963 struct lpfc_hba *phba = vport->phba;
964 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
965
966
967 lpfc_els_abort(phba, ndlp);
968
969 if (evt == NLP_EVT_RCV_LOGO) {
970 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
971 } else {
972 lpfc_issue_els_logo(vport, ndlp, 0);
973 }
974
975
976 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1));
977 spin_lock_irq(shost->host_lock);
978 ndlp->nlp_flag |= NLP_DELAY_TMO;
979 spin_unlock_irq(shost->host_lock);
980 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
981 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
982 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
983
984 return ndlp->nlp_state;
985}
986
987static uint32_t
988lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
989 struct lpfc_nodelist *ndlp,
990 void *arg,
991 uint32_t evt)
992{
993 struct lpfc_hba *phba = vport->phba;
994 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
995 struct lpfc_iocbq *cmdiocb, *rspiocb;
996 struct lpfc_dmabuf *pcmd, *prsp, *mp;
997 uint32_t *lp;
998 IOCB_t *irsp;
999 struct serv_parm *sp;
1000 LPFC_MBOXQ_t *mbox;
1001
1002 cmdiocb = (struct lpfc_iocbq *) arg;
1003 rspiocb = cmdiocb->context_un.rsp_iocb;
1004
1005 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
1006
1007 return ndlp->nlp_state;
1008 }
1009
1010 irsp = &rspiocb->iocb;
1011
1012 if (irsp->ulpStatus)
1013 goto out;
1014
1015 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
1016
1017 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
1018
1019 lp = (uint32_t *) prsp->virt;
1020 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
1021
1022
1023 if ((ndlp->nlp_DID != FDMI_DID) &&
1024 (wwn_to_u64(sp->portName.u.wwn) == 0 ||
1025 wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
1026 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1027 "0142 PLOGI RSP: Invalid WWN.\n");
1028 goto out;
1029 }
1030 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
1031 goto out;
1032
1033 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1034 "0121 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
1035 ndlp->nlp_DID, ndlp->nlp_state,
1036 ndlp->nlp_flag, ndlp->nlp_rpi);
1037 if (vport->cfg_fcp_class == 2 && (sp->cls2.classValid))
1038 ndlp->nlp_fcp_info |= CLASS2;
1039 else
1040 ndlp->nlp_fcp_info |= CLASS3;
1041
1042 ndlp->nlp_class_sup = 0;
1043 if (sp->cls1.classValid)
1044 ndlp->nlp_class_sup |= FC_COS_CLASS1;
1045 if (sp->cls2.classValid)
1046 ndlp->nlp_class_sup |= FC_COS_CLASS2;
1047 if (sp->cls3.classValid)
1048 ndlp->nlp_class_sup |= FC_COS_CLASS3;
1049 if (sp->cls4.classValid)
1050 ndlp->nlp_class_sup |= FC_COS_CLASS4;
1051 ndlp->nlp_maxframe =
1052 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
1053
1054 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1055 if (!mbox) {
1056 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1057 "0133 PLOGI: no memory for reg_login "
1058 "Data: x%x x%x x%x x%x\n",
1059 ndlp->nlp_DID, ndlp->nlp_state,
1060 ndlp->nlp_flag, ndlp->nlp_rpi);
1061 goto out;
1062 }
1063
1064 lpfc_unreg_rpi(vport, ndlp);
1065
1066 if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
1067 (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
1068 switch (ndlp->nlp_DID) {
1069 case NameServer_DID:
1070 mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
1071 break;
1072 case FDMI_DID:
1073 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
1074 break;
1075 default:
1076 ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
1077 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
1078 }
1079 mbox->context2 = lpfc_nlp_get(ndlp);
1080 mbox->vport = vport;
1081 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
1082 != MBX_NOT_FINISHED) {
1083 lpfc_nlp_set_state(vport, ndlp,
1084 NLP_STE_REG_LOGIN_ISSUE);
1085 return ndlp->nlp_state;
1086 }
1087 if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
1088 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
1089
1090
1091
1092 lpfc_nlp_put(ndlp);
1093 mp = (struct lpfc_dmabuf *) mbox->context1;
1094 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1095 kfree(mp);
1096 mempool_free(mbox, phba->mbox_mem_pool);
1097
1098 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1099 "0134 PLOGI: cannot issue reg_login "
1100 "Data: x%x x%x x%x x%x\n",
1101 ndlp->nlp_DID, ndlp->nlp_state,
1102 ndlp->nlp_flag, ndlp->nlp_rpi);
1103 } else {
1104 mempool_free(mbox, phba->mbox_mem_pool);
1105
1106 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1107 "0135 PLOGI: cannot format reg_login "
1108 "Data: x%x x%x x%x x%x\n",
1109 ndlp->nlp_DID, ndlp->nlp_state,
1110 ndlp->nlp_flag, ndlp->nlp_rpi);
1111 }
1112
1113
1114out:
1115 if (ndlp->nlp_DID == NameServer_DID) {
1116 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
1117 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1118 "0261 Cannot Register NameServer login\n");
1119 }
1120
1121
1122
1123
1124
1125
1126 ndlp->nlp_prev_state = ndlp->nlp_state;
1127 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1128 spin_lock_irq(shost->host_lock);
1129 ndlp->nlp_flag |= NLP_DEFER_RM;
1130 spin_unlock_irq(shost->host_lock);
1131 return NLP_STE_FREED_NODE;
1132}
1133
1134static uint32_t
1135lpfc_cmpl_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1136 void *arg, uint32_t evt)
1137{
1138 return ndlp->nlp_state;
1139}
1140
1141static uint32_t
1142lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport,
1143 struct lpfc_nodelist *ndlp, void *arg, uint32_t evt)
1144{
1145 struct lpfc_hba *phba;
1146 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1147 MAILBOX_t *mb = &pmb->u.mb;
1148 uint16_t rpi;
1149
1150 phba = vport->phba;
1151
1152 if (!(phba->pport->load_flag & FC_UNLOADING) &&
1153 !mb->mbxStatus) {
1154 rpi = pmb->u.mb.un.varWords[0];
1155 lpfc_release_rpi(phba, vport, rpi);
1156 }
1157 return ndlp->nlp_state;
1158}
1159
1160static uint32_t
1161lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1162 void *arg, uint32_t evt)
1163{
1164 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1165
1166 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1167 spin_lock_irq(shost->host_lock);
1168 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1169 spin_unlock_irq(shost->host_lock);
1170 return ndlp->nlp_state;
1171 } else {
1172
1173 lpfc_els_abort(vport->phba, ndlp);
1174
1175 lpfc_drop_node(vport, ndlp);
1176 return NLP_STE_FREED_NODE;
1177 }
1178}
1179
1180static uint32_t
1181lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
1182 struct lpfc_nodelist *ndlp,
1183 void *arg,
1184 uint32_t evt)
1185{
1186 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1187 struct lpfc_hba *phba = vport->phba;
1188
1189
1190
1191
1192 if (vport->fc_flag & FC_RSCN_DEFERRED)
1193 return ndlp->nlp_state;
1194
1195
1196 lpfc_els_abort(phba, ndlp);
1197
1198 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
1199 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1200 spin_lock_irq(shost->host_lock);
1201 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1202 spin_unlock_irq(shost->host_lock);
1203
1204 return ndlp->nlp_state;
1205}
1206
1207static uint32_t
1208lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1209 void *arg, uint32_t evt)
1210{
1211 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1212 struct lpfc_hba *phba = vport->phba;
1213 struct lpfc_iocbq *cmdiocb;
1214
1215
1216 lpfc_els_abort(phba, ndlp);
1217
1218 cmdiocb = (struct lpfc_iocbq *) arg;
1219
1220 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
1221 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1222 spin_lock_irq(shost->host_lock);
1223 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1224 spin_unlock_irq(shost->host_lock);
1225 if (vport->num_disc_nodes)
1226 lpfc_more_adisc(vport);
1227 }
1228 return ndlp->nlp_state;
1229 }
1230 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1231 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
1232 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
1233
1234 return ndlp->nlp_state;
1235}
1236
1237static uint32_t
1238lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1239 void *arg, uint32_t evt)
1240{
1241 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1242
1243 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
1244 return ndlp->nlp_state;
1245}
1246
1247static uint32_t
1248lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1249 void *arg, uint32_t evt)
1250{
1251 struct lpfc_hba *phba = vport->phba;
1252 struct lpfc_iocbq *cmdiocb;
1253
1254 cmdiocb = (struct lpfc_iocbq *) arg;
1255
1256
1257 lpfc_els_abort(phba, ndlp);
1258
1259 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
1260 return ndlp->nlp_state;
1261}
1262
1263static uint32_t
1264lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
1265 struct lpfc_nodelist *ndlp,
1266 void *arg, uint32_t evt)
1267{
1268 struct lpfc_iocbq *cmdiocb;
1269
1270 cmdiocb = (struct lpfc_iocbq *) arg;
1271
1272 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
1273 return ndlp->nlp_state;
1274}
1275
1276static uint32_t
1277lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1278 void *arg, uint32_t evt)
1279{
1280 struct lpfc_iocbq *cmdiocb;
1281
1282 cmdiocb = (struct lpfc_iocbq *) arg;
1283
1284
1285 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
1286 return ndlp->nlp_state;
1287}
1288
1289static uint32_t
1290lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
1291 struct lpfc_nodelist *ndlp,
1292 void *arg, uint32_t evt)
1293{
1294 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1295 struct lpfc_hba *phba = vport->phba;
1296 struct lpfc_iocbq *cmdiocb, *rspiocb;
1297 IOCB_t *irsp;
1298 ADISC *ap;
1299 int rc;
1300
1301 cmdiocb = (struct lpfc_iocbq *) arg;
1302 rspiocb = cmdiocb->context_un.rsp_iocb;
1303
1304 ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1305 irsp = &rspiocb->iocb;
1306
1307 if ((irsp->ulpStatus) ||
1308 (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
1309
1310 mod_timer(&ndlp->nlp_delayfunc,
1311 jiffies + msecs_to_jiffies(1000));
1312 spin_lock_irq(shost->host_lock);
1313 ndlp->nlp_flag |= NLP_DELAY_TMO;
1314 spin_unlock_irq(shost->host_lock);
1315 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
1316
1317 memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
1318 memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
1319
1320 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1321 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1322 lpfc_unreg_rpi(vport, ndlp);
1323 return ndlp->nlp_state;
1324 }
1325
1326 if (phba->sli_rev == LPFC_SLI_REV4) {
1327 rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);
1328 if (rc) {
1329
1330 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1331 return ndlp->nlp_state;
1332 }
1333 }
1334
1335 if (ndlp->nlp_type & NLP_FCP_TARGET) {
1336 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1337 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
1338 } else {
1339 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1340 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1341 }
1342
1343 return ndlp->nlp_state;
1344}
1345
1346static uint32_t
1347lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1348 void *arg, uint32_t evt)
1349{
1350 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1351
1352 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1353 spin_lock_irq(shost->host_lock);
1354 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1355 spin_unlock_irq(shost->host_lock);
1356 return ndlp->nlp_state;
1357 } else {
1358
1359 lpfc_els_abort(vport->phba, ndlp);
1360
1361 lpfc_drop_node(vport, ndlp);
1362 return NLP_STE_FREED_NODE;
1363 }
1364}
1365
1366static uint32_t
1367lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
1368 struct lpfc_nodelist *ndlp,
1369 void *arg,
1370 uint32_t evt)
1371{
1372 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1373 struct lpfc_hba *phba = vport->phba;
1374
1375
1376
1377
1378 if (vport->fc_flag & FC_RSCN_DEFERRED)
1379 return ndlp->nlp_state;
1380
1381
1382 lpfc_els_abort(phba, ndlp);
1383
1384 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1385 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1386 spin_lock_irq(shost->host_lock);
1387 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1388 spin_unlock_irq(shost->host_lock);
1389 lpfc_disc_set_adisc(vport, ndlp);
1390 return ndlp->nlp_state;
1391}
1392
1393static uint32_t
1394lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
1395 struct lpfc_nodelist *ndlp,
1396 void *arg,
1397 uint32_t evt)
1398{
1399 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1400
1401 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
1402 return ndlp->nlp_state;
1403}
1404
1405static uint32_t
1406lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
1407 struct lpfc_nodelist *ndlp,
1408 void *arg,
1409 uint32_t evt)
1410{
1411 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1412
1413 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
1414 return ndlp->nlp_state;
1415}
1416
1417static uint32_t
1418lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
1419 struct lpfc_nodelist *ndlp,
1420 void *arg,
1421 uint32_t evt)
1422{
1423 struct lpfc_hba *phba = vport->phba;
1424 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1425 LPFC_MBOXQ_t *mb;
1426 LPFC_MBOXQ_t *nextmb;
1427 struct lpfc_dmabuf *mp;
1428
1429 cmdiocb = (struct lpfc_iocbq *) arg;
1430
1431
1432 if ((mb = phba->sli.mbox_active)) {
1433 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
1434 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
1435 lpfc_nlp_put(ndlp);
1436 mb->context2 = NULL;
1437 mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1438 }
1439 }
1440
1441 spin_lock_irq(&phba->hbalock);
1442 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
1443 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
1444 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
1445 mp = (struct lpfc_dmabuf *) (mb->context1);
1446 if (mp) {
1447 __lpfc_mbuf_free(phba, mp->virt, mp->phys);
1448 kfree(mp);
1449 }
1450 lpfc_nlp_put(ndlp);
1451 list_del(&mb->list);
1452 phba->sli.mboxq_cnt--;
1453 mempool_free(mb, phba->mbox_mem_pool);
1454 }
1455 }
1456 spin_unlock_irq(&phba->hbalock);
1457
1458 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
1459 return ndlp->nlp_state;
1460}
1461
1462static uint32_t
1463lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
1464 struct lpfc_nodelist *ndlp,
1465 void *arg,
1466 uint32_t evt)
1467{
1468 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1469
1470 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
1471 return ndlp->nlp_state;
1472}
1473
1474static uint32_t
1475lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
1476 struct lpfc_nodelist *ndlp,
1477 void *arg,
1478 uint32_t evt)
1479{
1480 struct lpfc_iocbq *cmdiocb;
1481
1482 cmdiocb = (struct lpfc_iocbq *) arg;
1483 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
1484 return ndlp->nlp_state;
1485}
1486
1487static uint32_t
1488lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
1489 struct lpfc_nodelist *ndlp,
1490 void *arg,
1491 uint32_t evt)
1492{
1493 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1494 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1495 MAILBOX_t *mb = &pmb->u.mb;
1496 uint32_t did = mb->un.varWords[1];
1497
1498 if (mb->mbxStatus) {
1499
1500 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1501 "0246 RegLogin failed Data: x%x x%x x%x x%x "
1502 "x%x\n",
1503 did, mb->mbxStatus, vport->port_state,
1504 mb->un.varRegLogin.vpi,
1505 mb->un.varRegLogin.rpi);
1506
1507
1508
1509
1510 if (mb->mbxStatus == MBXERR_RPI_FULL) {
1511 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1512 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1513 return ndlp->nlp_state;
1514 }
1515
1516
1517 mod_timer(&ndlp->nlp_delayfunc,
1518 jiffies + msecs_to_jiffies(1000 * 1));
1519 spin_lock_irq(shost->host_lock);
1520 ndlp->nlp_flag |= NLP_DELAY_TMO;
1521 spin_unlock_irq(shost->host_lock);
1522 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
1523
1524 lpfc_issue_els_logo(vport, ndlp, 0);
1525 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1526 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1527 return ndlp->nlp_state;
1528 }
1529
1530
1531 if (vport->phba->sli_rev < LPFC_SLI_REV4)
1532 ndlp->nlp_rpi = mb->un.varWords[0];
1533
1534 ndlp->nlp_flag |= NLP_RPI_REGISTERED;
1535
1536
1537 if (!(ndlp->nlp_type & NLP_FABRIC)) {
1538 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1539 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
1540 lpfc_issue_els_prli(vport, ndlp, 0);
1541 } else {
1542 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1543 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1544 }
1545 return ndlp->nlp_state;
1546}
1547
1548static uint32_t
1549lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
1550 struct lpfc_nodelist *ndlp,
1551 void *arg,
1552 uint32_t evt)
1553{
1554 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1555
1556 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1557 spin_lock_irq(shost->host_lock);
1558 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1559 spin_unlock_irq(shost->host_lock);
1560 return ndlp->nlp_state;
1561 } else {
1562 lpfc_drop_node(vport, ndlp);
1563 return NLP_STE_FREED_NODE;
1564 }
1565}
1566
1567static uint32_t
1568lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
1569 struct lpfc_nodelist *ndlp,
1570 void *arg,
1571 uint32_t evt)
1572{
1573 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1574
1575
1576
1577
1578 if (vport->fc_flag & FC_RSCN_DEFERRED)
1579 return ndlp->nlp_state;
1580
1581 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1582 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1583 spin_lock_irq(shost->host_lock);
1584 ndlp->nlp_flag |= NLP_IGNR_REG_CMPL;
1585 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1586 spin_unlock_irq(shost->host_lock);
1587 lpfc_disc_set_adisc(vport, ndlp);
1588 return ndlp->nlp_state;
1589}
1590
1591static uint32_t
1592lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1593 void *arg, uint32_t evt)
1594{
1595 struct lpfc_iocbq *cmdiocb;
1596
1597 cmdiocb = (struct lpfc_iocbq *) arg;
1598
1599 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
1600 return ndlp->nlp_state;
1601}
1602
1603static uint32_t
1604lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1605 void *arg, uint32_t evt)
1606{
1607 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1608
1609 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
1610 return ndlp->nlp_state;
1611}
1612
1613static uint32_t
1614lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1615 void *arg, uint32_t evt)
1616{
1617 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1618
1619
1620 lpfc_els_abort(vport->phba, ndlp);
1621
1622 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
1623 return ndlp->nlp_state;
1624}
1625
1626static uint32_t
1627lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1628 void *arg, uint32_t evt)
1629{
1630 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1631
1632 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
1633 return ndlp->nlp_state;
1634}
1635
1636
1637
1638
1639
1640
1641static uint32_t
1642lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1643 void *arg, uint32_t evt)
1644{
1645 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1646
1647 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
1648 return ndlp->nlp_state;
1649}
1650
1651static uint32_t
1652lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1653 void *arg, uint32_t evt)
1654{
1655 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1656 struct lpfc_iocbq *cmdiocb, *rspiocb;
1657 struct lpfc_hba *phba = vport->phba;
1658 IOCB_t *irsp;
1659 PRLI *npr;
1660
1661 cmdiocb = (struct lpfc_iocbq *) arg;
1662 rspiocb = cmdiocb->context_un.rsp_iocb;
1663 npr = (PRLI *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1664
1665 irsp = &rspiocb->iocb;
1666 if (irsp->ulpStatus) {
1667 if ((vport->port_type == LPFC_NPIV_PORT) &&
1668 vport->cfg_restrict_login) {
1669 goto out;
1670 }
1671 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
1672 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1673 return ndlp->nlp_state;
1674 }
1675
1676
1677 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
1678 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1679 if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
1680 (npr->prliType == PRLI_FCP_TYPE)) {
1681 if (npr->initiatorFunc)
1682 ndlp->nlp_type |= NLP_FCP_INITIATOR;
1683 if (npr->targetFunc)
1684 ndlp->nlp_type |= NLP_FCP_TARGET;
1685 if (npr->Retry)
1686 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1687 }
1688 if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
1689 (vport->port_type == LPFC_NPIV_PORT) &&
1690 vport->cfg_restrict_login) {
1691out:
1692 spin_lock_irq(shost->host_lock);
1693 ndlp->nlp_flag |= NLP_TARGET_REMOVE;
1694 spin_unlock_irq(shost->host_lock);
1695 lpfc_issue_els_logo(vport, ndlp, 0);
1696
1697 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
1698 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1699 return ndlp->nlp_state;
1700 }
1701
1702 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
1703 if (ndlp->nlp_type & NLP_FCP_TARGET)
1704 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
1705 else
1706 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1707 return ndlp->nlp_state;
1708}
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728static uint32_t
1729lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1730 void *arg, uint32_t evt)
1731{
1732 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1733
1734 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1735 spin_lock_irq(shost->host_lock);
1736 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1737 spin_unlock_irq(shost->host_lock);
1738 return ndlp->nlp_state;
1739 } else {
1740
1741 lpfc_els_abort(vport->phba, ndlp);
1742
1743 lpfc_drop_node(vport, ndlp);
1744 return NLP_STE_FREED_NODE;
1745 }
1746}
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765static uint32_t
1766lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
1767 struct lpfc_nodelist *ndlp,
1768 void *arg,
1769 uint32_t evt)
1770{
1771 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1772 struct lpfc_hba *phba = vport->phba;
1773
1774
1775
1776
1777 if (vport->fc_flag & FC_RSCN_DEFERRED)
1778 return ndlp->nlp_state;
1779
1780
1781 lpfc_els_abort(phba, ndlp);
1782
1783 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
1784 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1785 spin_lock_irq(shost->host_lock);
1786 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1787 spin_unlock_irq(shost->host_lock);
1788 lpfc_disc_set_adisc(vport, ndlp);
1789 return ndlp->nlp_state;
1790}
1791
1792static uint32_t
1793lpfc_rcv_plogi_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1794 void *arg, uint32_t evt)
1795{
1796 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1797 struct ls_rjt stat;
1798
1799 memset(&stat, 0, sizeof(struct ls_rjt));
1800 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1801 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1802 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1803 return ndlp->nlp_state;
1804}
1805
1806static uint32_t
1807lpfc_rcv_prli_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1808 void *arg, uint32_t evt)
1809{
1810 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1811 struct ls_rjt stat;
1812
1813 memset(&stat, 0, sizeof(struct ls_rjt));
1814 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1815 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1816 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1817 return ndlp->nlp_state;
1818}
1819
1820static uint32_t
1821lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1822 void *arg, uint32_t evt)
1823{
1824 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1825 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1826
1827 spin_lock_irq(shost->host_lock);
1828 ndlp->nlp_flag &= NLP_LOGO_ACC;
1829 spin_unlock_irq(shost->host_lock);
1830 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
1831 return ndlp->nlp_state;
1832}
1833
1834static uint32_t
1835lpfc_rcv_padisc_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1836 void *arg, uint32_t evt)
1837{
1838 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1839 struct ls_rjt stat;
1840
1841 memset(&stat, 0, sizeof(struct ls_rjt));
1842 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1843 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1844 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1845 return ndlp->nlp_state;
1846}
1847
1848static uint32_t
1849lpfc_rcv_prlo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1850 void *arg, uint32_t evt)
1851{
1852 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1853 struct ls_rjt stat;
1854
1855 memset(&stat, 0, sizeof(struct ls_rjt));
1856 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1857 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1858 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1859 return ndlp->nlp_state;
1860}
1861
1862static uint32_t
1863lpfc_cmpl_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1864 void *arg, uint32_t evt)
1865{
1866 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1867
1868 ndlp->nlp_prev_state = NLP_STE_LOGO_ISSUE;
1869 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1870 spin_lock_irq(shost->host_lock);
1871 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1872 spin_unlock_irq(shost->host_lock);
1873 lpfc_disc_set_adisc(vport, ndlp);
1874 return ndlp->nlp_state;
1875}
1876
1877static uint32_t
1878lpfc_device_rm_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1879 void *arg, uint32_t evt)
1880{
1881
1882
1883
1884
1885
1886
1887 return ndlp->nlp_state;
1888}
1889
1890static uint32_t
1891lpfc_device_recov_logo_issue(struct lpfc_vport *vport,
1892 struct lpfc_nodelist *ndlp,
1893 void *arg, uint32_t evt)
1894{
1895
1896
1897
1898
1899
1900 return ndlp->nlp_state;
1901}
1902
1903static uint32_t
1904lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1905 void *arg, uint32_t evt)
1906{
1907 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1908
1909 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
1910 return ndlp->nlp_state;
1911}
1912
1913static uint32_t
1914lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1915 void *arg, uint32_t evt)
1916{
1917 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1918
1919 lpfc_rcv_prli(vport, ndlp, cmdiocb);
1920 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
1921 return ndlp->nlp_state;
1922}
1923
1924static uint32_t
1925lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1926 void *arg, uint32_t evt)
1927{
1928 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1929
1930 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
1931 return ndlp->nlp_state;
1932}
1933
1934static uint32_t
1935lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1936 void *arg, uint32_t evt)
1937{
1938 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1939
1940 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
1941 return ndlp->nlp_state;
1942}
1943
1944static uint32_t
1945lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1946 void *arg, uint32_t evt)
1947{
1948 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1949
1950 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
1951 return ndlp->nlp_state;
1952}
1953
1954static uint32_t
1955lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
1956 struct lpfc_nodelist *ndlp,
1957 void *arg,
1958 uint32_t evt)
1959{
1960 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1961
1962 ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
1963 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1964 spin_lock_irq(shost->host_lock);
1965 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1966 spin_unlock_irq(shost->host_lock);
1967 lpfc_disc_set_adisc(vport, ndlp);
1968
1969 return ndlp->nlp_state;
1970}
1971
1972static uint32_t
1973lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1974 void *arg, uint32_t evt)
1975{
1976 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1977
1978 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
1979 return ndlp->nlp_state;
1980}
1981
1982static uint32_t
1983lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1984 void *arg, uint32_t evt)
1985{
1986 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1987
1988 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
1989 return ndlp->nlp_state;
1990}
1991
1992static uint32_t
1993lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1994 void *arg, uint32_t evt)
1995{
1996 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1997
1998 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
1999 return ndlp->nlp_state;
2000}
2001
2002static uint32_t
2003lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
2004 struct lpfc_nodelist *ndlp,
2005 void *arg, uint32_t evt)
2006{
2007 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2008
2009 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
2010 return ndlp->nlp_state;
2011}
2012
2013static uint32_t
2014lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2015 void *arg, uint32_t evt)
2016{
2017 struct lpfc_hba *phba = vport->phba;
2018 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2019
2020
2021 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
2022 ndlp->nlp_sid, 0, LPFC_CTX_TGT);
2023
2024
2025 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
2026 return ndlp->nlp_state;
2027}
2028
2029static uint32_t
2030lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
2031 struct lpfc_nodelist *ndlp,
2032 void *arg,
2033 uint32_t evt)
2034{
2035 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2036
2037 ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
2038 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
2039 spin_lock_irq(shost->host_lock);
2040 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2041 spin_unlock_irq(shost->host_lock);
2042 lpfc_disc_set_adisc(vport, ndlp);
2043 return ndlp->nlp_state;
2044}
2045
2046static uint32_t
2047lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2048 void *arg, uint32_t evt)
2049{
2050 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2051 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2052
2053
2054 if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC))
2055 return ndlp->nlp_state;
2056 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
2057 lpfc_cancel_retry_delay_tmo(vport, ndlp);
2058 spin_lock_irq(shost->host_lock);
2059 ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC);
2060 spin_unlock_irq(shost->host_lock);
2061 } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
2062
2063 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
2064 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2065 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2066 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
2067 }
2068 }
2069 return ndlp->nlp_state;
2070}
2071
2072static uint32_t
2073lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2074 void *arg, uint32_t evt)
2075{
2076 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2077 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2078 struct ls_rjt stat;
2079
2080 memset(&stat, 0, sizeof (struct ls_rjt));
2081 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2082 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
2083 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
2084
2085 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
2086 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2087 spin_lock_irq(shost->host_lock);
2088 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2089 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2090 spin_unlock_irq(shost->host_lock);
2091 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2092 lpfc_issue_els_adisc(vport, ndlp, 0);
2093 } else {
2094 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2095 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2096 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
2097 }
2098 }
2099 return ndlp->nlp_state;
2100}
2101
2102static uint32_t
2103lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2104 void *arg, uint32_t evt)
2105{
2106 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2107
2108 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
2109 return ndlp->nlp_state;
2110}
2111
2112static uint32_t
2113lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2114 void *arg, uint32_t evt)
2115{
2116 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2117
2118 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
2119
2120
2121
2122
2123
2124 if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
2125 !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
2126 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2127 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2128 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2129 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2130 lpfc_issue_els_adisc(vport, ndlp, 0);
2131 } else {
2132 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2133 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2134 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
2135 }
2136 }
2137 return ndlp->nlp_state;
2138}
2139
2140static uint32_t
2141lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2142 void *arg, uint32_t evt)
2143{
2144 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2145 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2146
2147 spin_lock_irq(shost->host_lock);
2148 ndlp->nlp_flag |= NLP_LOGO_ACC;
2149 spin_unlock_irq(shost->host_lock);
2150
2151 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
2152
2153 if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
2154 mod_timer(&ndlp->nlp_delayfunc,
2155 jiffies + msecs_to_jiffies(1000 * 1));
2156 spin_lock_irq(shost->host_lock);
2157 ndlp->nlp_flag |= NLP_DELAY_TMO;
2158 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2159 spin_unlock_irq(shost->host_lock);
2160 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
2161 } else {
2162 spin_lock_irq(shost->host_lock);
2163 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2164 spin_unlock_irq(shost->host_lock);
2165 }
2166 return ndlp->nlp_state;
2167}
2168
2169static uint32_t
2170lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2171 void *arg, uint32_t evt)
2172{
2173 struct lpfc_iocbq *cmdiocb, *rspiocb;
2174 IOCB_t *irsp;
2175 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2176
2177 cmdiocb = (struct lpfc_iocbq *) arg;
2178 rspiocb = cmdiocb->context_un.rsp_iocb;
2179
2180 irsp = &rspiocb->iocb;
2181 if (irsp->ulpStatus) {
2182 spin_lock_irq(shost->host_lock);
2183 ndlp->nlp_flag |= NLP_DEFER_RM;
2184 spin_unlock_irq(shost->host_lock);
2185 return NLP_STE_FREED_NODE;
2186 }
2187 return ndlp->nlp_state;
2188}
2189
2190static uint32_t
2191lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2192 void *arg, uint32_t evt)
2193{
2194 struct lpfc_iocbq *cmdiocb, *rspiocb;
2195 IOCB_t *irsp;
2196
2197 cmdiocb = (struct lpfc_iocbq *) arg;
2198 rspiocb = cmdiocb->context_un.rsp_iocb;
2199
2200 irsp = &rspiocb->iocb;
2201 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
2202 lpfc_drop_node(vport, ndlp);
2203 return NLP_STE_FREED_NODE;
2204 }
2205 return ndlp->nlp_state;
2206}
2207
2208static uint32_t
2209lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2210 void *arg, uint32_t evt)
2211{
2212 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2213
2214
2215 if (ndlp->nlp_DID == Fabric_DID) {
2216 spin_lock_irq(shost->host_lock);
2217 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2218 spin_unlock_irq(shost->host_lock);
2219 }
2220 lpfc_unreg_rpi(vport, ndlp);
2221 return ndlp->nlp_state;
2222}
2223
2224static uint32_t
2225lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2226 void *arg, uint32_t evt)
2227{
2228 struct lpfc_iocbq *cmdiocb, *rspiocb;
2229 IOCB_t *irsp;
2230
2231 cmdiocb = (struct lpfc_iocbq *) arg;
2232 rspiocb = cmdiocb->context_un.rsp_iocb;
2233
2234 irsp = &rspiocb->iocb;
2235 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
2236 lpfc_drop_node(vport, ndlp);
2237 return NLP_STE_FREED_NODE;
2238 }
2239 return ndlp->nlp_state;
2240}
2241
2242static uint32_t
2243lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
2244 struct lpfc_nodelist *ndlp,
2245 void *arg, uint32_t evt)
2246{
2247 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
2248 MAILBOX_t *mb = &pmb->u.mb;
2249
2250 if (!mb->mbxStatus) {
2251
2252 if (vport->phba->sli_rev < LPFC_SLI_REV4)
2253 ndlp->nlp_rpi = mb->un.varWords[0];
2254 ndlp->nlp_flag |= NLP_RPI_REGISTERED;
2255 } else {
2256 if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
2257 lpfc_drop_node(vport, ndlp);
2258 return NLP_STE_FREED_NODE;
2259 }
2260 }
2261 return ndlp->nlp_state;
2262}
2263
2264static uint32_t
2265lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2266 void *arg, uint32_t evt)
2267{
2268 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2269
2270 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
2271 spin_lock_irq(shost->host_lock);
2272 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2273 spin_unlock_irq(shost->host_lock);
2274 return ndlp->nlp_state;
2275 }
2276 lpfc_drop_node(vport, ndlp);
2277 return NLP_STE_FREED_NODE;
2278}
2279
2280static uint32_t
2281lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2282 void *arg, uint32_t evt)
2283{
2284 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2285
2286
2287
2288
2289 if (vport->fc_flag & FC_RSCN_DEFERRED)
2290 return ndlp->nlp_state;
2291
2292 lpfc_cancel_retry_delay_tmo(vport, ndlp);
2293 spin_lock_irq(shost->host_lock);
2294 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2295 spin_unlock_irq(shost->host_lock);
2296 return ndlp->nlp_state;
2297}
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
2357 (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
2358
2359 lpfc_rcv_plogi_unused_node,
2360 lpfc_rcv_els_unused_node,
2361 lpfc_rcv_logo_unused_node,
2362 lpfc_rcv_els_unused_node,
2363 lpfc_rcv_els_unused_node,
2364 lpfc_rcv_els_unused_node,
2365 lpfc_disc_illegal,
2366 lpfc_disc_illegal,
2367 lpfc_cmpl_logo_unused_node,
2368 lpfc_disc_illegal,
2369 lpfc_disc_illegal,
2370 lpfc_device_rm_unused_node,
2371 lpfc_device_recov_unused_node,
2372
2373 lpfc_rcv_plogi_plogi_issue,
2374 lpfc_rcv_prli_plogi_issue,
2375 lpfc_rcv_logo_plogi_issue,
2376 lpfc_rcv_els_plogi_issue,
2377 lpfc_rcv_els_plogi_issue,
2378 lpfc_rcv_els_plogi_issue,
2379 lpfc_cmpl_plogi_plogi_issue,
2380 lpfc_disc_illegal,
2381 lpfc_cmpl_logo_plogi_issue,
2382 lpfc_disc_illegal,
2383 lpfc_cmpl_reglogin_plogi_issue,
2384 lpfc_device_rm_plogi_issue,
2385 lpfc_device_recov_plogi_issue,
2386
2387 lpfc_rcv_plogi_adisc_issue,
2388 lpfc_rcv_prli_adisc_issue,
2389 lpfc_rcv_logo_adisc_issue,
2390 lpfc_rcv_padisc_adisc_issue,
2391 lpfc_rcv_padisc_adisc_issue,
2392 lpfc_rcv_prlo_adisc_issue,
2393 lpfc_disc_illegal,
2394 lpfc_disc_illegal,
2395 lpfc_disc_illegal,
2396 lpfc_cmpl_adisc_adisc_issue,
2397 lpfc_disc_illegal,
2398 lpfc_device_rm_adisc_issue,
2399 lpfc_device_recov_adisc_issue,
2400
2401 lpfc_rcv_plogi_reglogin_issue,
2402 lpfc_rcv_prli_reglogin_issue,
2403 lpfc_rcv_logo_reglogin_issue,
2404 lpfc_rcv_padisc_reglogin_issue,
2405 lpfc_rcv_padisc_reglogin_issue,
2406 lpfc_rcv_prlo_reglogin_issue,
2407 lpfc_cmpl_plogi_illegal,
2408 lpfc_disc_illegal,
2409 lpfc_disc_illegal,
2410 lpfc_disc_illegal,
2411 lpfc_cmpl_reglogin_reglogin_issue,
2412 lpfc_device_rm_reglogin_issue,
2413 lpfc_device_recov_reglogin_issue,
2414
2415 lpfc_rcv_plogi_prli_issue,
2416 lpfc_rcv_prli_prli_issue,
2417 lpfc_rcv_logo_prli_issue,
2418 lpfc_rcv_padisc_prli_issue,
2419 lpfc_rcv_padisc_prli_issue,
2420 lpfc_rcv_prlo_prli_issue,
2421 lpfc_cmpl_plogi_illegal,
2422 lpfc_cmpl_prli_prli_issue,
2423 lpfc_disc_illegal,
2424 lpfc_disc_illegal,
2425 lpfc_disc_illegal,
2426 lpfc_device_rm_prli_issue,
2427 lpfc_device_recov_prli_issue,
2428
2429 lpfc_rcv_plogi_logo_issue,
2430 lpfc_rcv_prli_logo_issue,
2431 lpfc_rcv_logo_logo_issue,
2432 lpfc_rcv_padisc_logo_issue,
2433 lpfc_rcv_padisc_logo_issue,
2434 lpfc_rcv_prlo_logo_issue,
2435 lpfc_cmpl_plogi_illegal,
2436 lpfc_disc_illegal,
2437 lpfc_cmpl_logo_logo_issue,
2438 lpfc_disc_illegal,
2439 lpfc_disc_illegal,
2440 lpfc_device_rm_logo_issue,
2441 lpfc_device_recov_logo_issue,
2442
2443 lpfc_rcv_plogi_unmap_node,
2444 lpfc_rcv_prli_unmap_node,
2445 lpfc_rcv_logo_unmap_node,
2446 lpfc_rcv_padisc_unmap_node,
2447 lpfc_rcv_padisc_unmap_node,
2448 lpfc_rcv_prlo_unmap_node,
2449 lpfc_disc_illegal,
2450 lpfc_disc_illegal,
2451 lpfc_disc_illegal,
2452 lpfc_disc_illegal,
2453 lpfc_disc_illegal,
2454 lpfc_disc_illegal,
2455 lpfc_device_recov_unmap_node,
2456
2457 lpfc_rcv_plogi_mapped_node,
2458 lpfc_rcv_prli_mapped_node,
2459 lpfc_rcv_logo_mapped_node,
2460 lpfc_rcv_padisc_mapped_node,
2461 lpfc_rcv_padisc_mapped_node,
2462 lpfc_rcv_prlo_mapped_node,
2463 lpfc_disc_illegal,
2464 lpfc_disc_illegal,
2465 lpfc_disc_illegal,
2466 lpfc_disc_illegal,
2467 lpfc_disc_illegal,
2468 lpfc_disc_illegal,
2469 lpfc_device_recov_mapped_node,
2470
2471 lpfc_rcv_plogi_npr_node,
2472 lpfc_rcv_prli_npr_node,
2473 lpfc_rcv_logo_npr_node,
2474 lpfc_rcv_padisc_npr_node,
2475 lpfc_rcv_padisc_npr_node,
2476 lpfc_rcv_prlo_npr_node,
2477 lpfc_cmpl_plogi_npr_node,
2478 lpfc_cmpl_prli_npr_node,
2479 lpfc_cmpl_logo_npr_node,
2480 lpfc_cmpl_adisc_npr_node,
2481 lpfc_cmpl_reglogin_npr_node,
2482 lpfc_device_rm_npr_node,
2483 lpfc_device_recov_npr_node,
2484};
2485
2486int
2487lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2488 void *arg, uint32_t evt)
2489{
2490 uint32_t cur_state, rc;
2491 uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
2492 uint32_t);
2493 uint32_t got_ndlp = 0;
2494
2495 if (lpfc_nlp_get(ndlp))
2496 got_ndlp = 1;
2497
2498 cur_state = ndlp->nlp_state;
2499
2500
2501 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2502 "0211 DSM in event x%x on NPort x%x in "
2503 "state %d Data: x%x\n",
2504 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
2505
2506 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2507 "DSM in: evt:%d ste:%d did:x%x",
2508 evt, cur_state, ndlp->nlp_DID);
2509
2510 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
2511 rc = (func) (vport, ndlp, arg, evt);
2512
2513
2514 if (got_ndlp) {
2515 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2516 "0212 DSM out state %d on NPort x%x Data: x%x\n",
2517 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2518
2519 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2520 "DSM out: ste:%d did:x%x flg:x%x",
2521 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2522
2523 lpfc_nlp_put(ndlp);
2524 } else {
2525 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2526 "0213 DSM out state %d on NPort free\n", rc);
2527
2528 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2529 "DSM out: ste:%d did:x%x flg:x%x",
2530 rc, 0, 0);
2531 }
2532
2533 return rc;
2534}
2535