diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 1a16ee9b2e87..bba1fb6103f6 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -406,6 +406,41 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
406 | ndlp, mbox); | 406 | ndlp, mbox); |
407 | return 1; | 407 | return 1; |
408 | } | 408 | } |
409 | |||
410 | /* If the remote NPort logs into us, before we can initiate | ||
411 | * discovery to them, cleanup the NPort from discovery accordingly. | ||
412 | */ | ||
413 | if (ndlp->nlp_state == NLP_STE_NPR_NODE) { | ||
414 | spin_lock_irq(shost->host_lock); | ||
415 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | ||
416 | spin_unlock_irq(shost->host_lock); | ||
417 | del_timer_sync(&ndlp->nlp_delayfunc); | ||
418 | ndlp->nlp_last_elscmd = 0; | ||
419 | |||
420 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | ||
421 | list_del_init(&ndlp->els_retry_evt.evt_listp); | ||
422 | |||
423 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
424 | spin_lock_irq(shost->host_lock); | ||
425 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
426 | spin_unlock_irq(shost->host_lock); | ||
427 | if (vport->num_disc_nodes) { | ||
428 | /* Check to see if there are more | ||
429 | * PLOGIs to be sent | ||
430 | */ | ||
431 | lpfc_more_plogi(vport); | ||
432 | |||
433 | if (vport->num_disc_nodes == 0) { | ||
434 | spin_lock_irq(shost->host_lock); | ||
435 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
436 | spin_unlock_irq(shost->host_lock); | ||
437 | lpfc_can_disctmo(vport); | ||
438 | lpfc_end_rscn(vport); | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | |||
409 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); | 444 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); |
410 | return 1; | 445 | return 1; |
411 | 446 | ||
@@ -500,12 +535,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
500 | spin_unlock_irq(shost->host_lock); | 535 | spin_unlock_irq(shost->host_lock); |
501 | 536 | ||
502 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 537 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
503 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
504 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
505 | } else { | ||
506 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
507 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
508 | } | 538 | } |
539 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
540 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
509 | 541 | ||
510 | spin_lock_irq(shost->host_lock); | 542 | spin_lock_irq(shost->host_lock); |
511 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 543 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
@@ -593,6 +625,25 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
593 | return ndlp->nlp_state; | 625 | return ndlp->nlp_state; |
594 | } | 626 | } |
595 | 627 | ||
628 | static uint32_t | ||
629 | lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
630 | void *arg, uint32_t evt) | ||
631 | { | ||
632 | /* This transition is only legal if we previously | ||
633 | * rcv'ed a PLOGI. Since we don't want 2 discovery threads | ||
634 | * working on the same NPortID, do nothing for this thread | ||
635 | * to stop it. | ||
636 | */ | ||
637 | if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) { | ||
638 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
639 | "0253 Illegal State Transition: node x%x " | ||
640 | "event x%x, state x%x Data: x%x x%x\n", | ||
641 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, | ||
642 | ndlp->nlp_flag); | ||
643 | } | ||
644 | return ndlp->nlp_state; | ||
645 | } | ||
646 | |||
596 | /* Start of Discovery State Machine routines */ | 647 | /* Start of Discovery State Machine routines */ |
597 | 648 | ||
598 | static uint32_t | 649 | static uint32_t |
@@ -604,11 +655,8 @@ lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
604 | cmdiocb = (struct lpfc_iocbq *) arg; | 655 | cmdiocb = (struct lpfc_iocbq *) arg; |
605 | 656 | ||
606 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { | 657 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
607 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | ||
608 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
609 | return ndlp->nlp_state; | 658 | return ndlp->nlp_state; |
610 | } | 659 | } |
611 | lpfc_drop_node(vport, ndlp); | ||
612 | return NLP_STE_FREED_NODE; | 660 | return NLP_STE_FREED_NODE; |
613 | } | 661 | } |
614 | 662 | ||
@@ -617,7 +665,6 @@ lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
617 | void *arg, uint32_t evt) | 665 | void *arg, uint32_t evt) |
618 | { | 666 | { |
619 | lpfc_issue_els_logo(vport, ndlp, 0); | 667 | lpfc_issue_els_logo(vport, ndlp, 0); |
620 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
621 | return ndlp->nlp_state; | 668 | return ndlp->nlp_state; |
622 | } | 669 | } |
623 | 670 | ||
@@ -632,7 +679,6 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
632 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 679 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
633 | spin_unlock_irq(shost->host_lock); | 680 | spin_unlock_irq(shost->host_lock); |
634 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 681 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
635 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
636 | 682 | ||
637 | return ndlp->nlp_state; | 683 | return ndlp->nlp_state; |
638 | } | 684 | } |
@@ -641,7 +687,6 @@ static uint32_t | |||
641 | lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 687 | lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
642 | void *arg, uint32_t evt) | 688 | void *arg, uint32_t evt) |
643 | { | 689 | { |
644 | lpfc_drop_node(vport, ndlp); | ||
645 | return NLP_STE_FREED_NODE; | 690 | return NLP_STE_FREED_NODE; |
646 | } | 691 | } |
647 | 692 | ||
@@ -649,7 +694,6 @@ static uint32_t | |||
649 | lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 694 | lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
650 | void *arg, uint32_t evt) | 695 | void *arg, uint32_t evt) |
651 | { | 696 | { |
652 | lpfc_drop_node(vport, ndlp); | ||
653 | return NLP_STE_FREED_NODE; | 697 | return NLP_STE_FREED_NODE; |
654 | } | 698 | } |
655 | 699 | ||
@@ -864,7 +908,7 @@ out: | |||
864 | 908 | ||
865 | /* Free this node since the driver cannot login or has the wrong | 909 | /* Free this node since the driver cannot login or has the wrong |
866 | sparm */ | 910 | sparm */ |
867 | lpfc_drop_node(vport, ndlp); | 911 | lpfc_nlp_not_used(ndlp); |
868 | return NLP_STE_FREED_NODE; | 912 | return NLP_STE_FREED_NODE; |
869 | } | 913 | } |
870 | 914 | ||
@@ -1195,8 +1239,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1195 | * retry discovery. | 1239 | * retry discovery. |
1196 | */ | 1240 | */ |
1197 | if (mb->mbxStatus == MBXERR_RPI_FULL) { | 1241 | if (mb->mbxStatus == MBXERR_RPI_FULL) { |
1198 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | 1242 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1199 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1243 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1200 | return ndlp->nlp_state; | 1244 | return ndlp->nlp_state; |
1201 | } | 1245 | } |
1202 | 1246 | ||
@@ -1376,7 +1420,7 @@ out: | |||
1376 | lpfc_issue_els_logo(vport, ndlp, 0); | 1420 | lpfc_issue_els_logo(vport, ndlp, 0); |
1377 | 1421 | ||
1378 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1422 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1379 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1423 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1380 | return ndlp->nlp_state; | 1424 | return ndlp->nlp_state; |
1381 | } | 1425 | } |
1382 | 1426 | ||
@@ -1751,7 +1795,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1751 | 1795 | ||
1752 | irsp = &rspiocb->iocb; | 1796 | irsp = &rspiocb->iocb; |
1753 | if (irsp->ulpStatus) { | 1797 | if (irsp->ulpStatus) { |
1754 | lpfc_drop_node(vport, ndlp); | 1798 | lpfc_nlp_not_used(ndlp); |
1755 | return NLP_STE_FREED_NODE; | 1799 | return NLP_STE_FREED_NODE; |
1756 | } | 1800 | } |
1757 | return ndlp->nlp_state; | 1801 | return ndlp->nlp_state; |
@@ -1966,7 +2010,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1966 | lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */ | 2010 | lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */ |
1967 | lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */ | 2011 | lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */ |
1968 | lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */ | 2012 | lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */ |
1969 | lpfc_disc_illegal, /* CMPL_PLOGI */ | 2013 | lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */ |
1970 | lpfc_disc_illegal, /* CMPL_PRLI */ | 2014 | lpfc_disc_illegal, /* CMPL_PRLI */ |
1971 | lpfc_disc_illegal, /* CMPL_LOGO */ | 2015 | lpfc_disc_illegal, /* CMPL_LOGO */ |
1972 | lpfc_disc_illegal, /* CMPL_ADISC */ | 2016 | lpfc_disc_illegal, /* CMPL_ADISC */ |
@@ -1980,7 +2024,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1980 | lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */ | 2024 | lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */ |
1981 | lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */ | 2025 | lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */ |
1982 | lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */ | 2026 | lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */ |
1983 | lpfc_disc_illegal, /* CMPL_PLOGI */ | 2027 | lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */ |
1984 | lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */ | 2028 | lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */ |
1985 | lpfc_disc_illegal, /* CMPL_LOGO */ | 2029 | lpfc_disc_illegal, /* CMPL_LOGO */ |
1986 | lpfc_disc_illegal, /* CMPL_ADISC */ | 2030 | lpfc_disc_illegal, /* CMPL_ADISC */ |