diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 1012 |
1 files changed, 671 insertions, 341 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 20f1a0713db2..4813beaaca8f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1,7 +1,7 @@ | |||
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-2005 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2006 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -92,15 +92,14 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) | |||
92 | } | 92 | } |
93 | } | 93 | } |
94 | 94 | ||
95 | return (1); | 95 | return 1; |
96 | 96 | ||
97 | } | 97 | } |
98 | 98 | ||
99 | static struct lpfc_iocbq * | 99 | static struct lpfc_iocbq * |
100 | lpfc_prep_els_iocb(struct lpfc_hba * phba, | 100 | lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, |
101 | uint8_t expectRsp, | 101 | uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp, |
102 | uint16_t cmdSize, | 102 | uint32_t did, uint32_t elscmd) |
103 | uint8_t retry, struct lpfc_nodelist * ndlp, uint32_t elscmd) | ||
104 | { | 103 | { |
105 | struct lpfc_sli_ring *pring; | 104 | struct lpfc_sli_ring *pring; |
106 | struct lpfc_iocbq *elsiocb; | 105 | struct lpfc_iocbq *elsiocb; |
@@ -181,7 +180,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
181 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; | 180 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; |
182 | if (expectRsp) { | 181 | if (expectRsp) { |
183 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); | 182 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); |
184 | icmd->un.elsreq64.remoteID = ndlp->nlp_DID; /* DID */ | 183 | icmd->un.elsreq64.remoteID = did; /* DID */ |
185 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; | 184 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; |
186 | } else { | 185 | } else { |
187 | icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64); | 186 | icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64); |
@@ -225,7 +224,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
225 | "%d:0116 Xmit ELS command x%x to remote " | 224 | "%d:0116 Xmit ELS command x%x to remote " |
226 | "NPORT x%x Data: x%x x%x\n", | 225 | "NPORT x%x Data: x%x x%x\n", |
227 | phba->brd_no, elscmd, | 226 | phba->brd_no, elscmd, |
228 | ndlp->nlp_DID, icmd->ulpIoTag, phba->hba_state); | 227 | did, icmd->ulpIoTag, phba->hba_state); |
229 | } else { | 228 | } else { |
230 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ | 229 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ |
231 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 230 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -235,7 +234,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
235 | ndlp->nlp_DID, icmd->ulpIoTag, cmdSize); | 234 | ndlp->nlp_DID, icmd->ulpIoTag, cmdSize); |
236 | } | 235 | } |
237 | 236 | ||
238 | return (elsiocb); | 237 | return elsiocb; |
239 | } | 238 | } |
240 | 239 | ||
241 | 240 | ||
@@ -446,9 +445,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba, | |||
446 | lpfc_printf_log(phba, | 445 | lpfc_printf_log(phba, |
447 | KERN_INFO, | 446 | KERN_INFO, |
448 | LOG_ELS, | 447 | LOG_ELS, |
449 | "%d:0100 FLOGI failure Data: x%x x%x\n", | 448 | "%d:0100 FLOGI failure Data: x%x x%x x%x\n", |
450 | phba->brd_no, | 449 | phba->brd_no, |
451 | irsp->ulpStatus, irsp->un.ulpWord[4]); | 450 | irsp->ulpStatus, irsp->un.ulpWord[4], |
451 | irsp->ulpTimeout); | ||
452 | goto flogifail; | 452 | goto flogifail; |
453 | } | 453 | } |
454 | 454 | ||
@@ -515,10 +515,10 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
515 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 515 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
516 | 516 | ||
517 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); | 517 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); |
518 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 518 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
519 | ndlp, ELS_CMD_FLOGI)) == 0) { | 519 | ndlp->nlp_DID, ELS_CMD_FLOGI); |
520 | return (1); | 520 | if (!elsiocb) |
521 | } | 521 | return 1; |
522 | 522 | ||
523 | icmd = &elsiocb->iocb; | 523 | icmd = &elsiocb->iocb; |
524 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 524 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -552,9 +552,9 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
552 | spin_unlock_irq(phba->host->host_lock); | 552 | spin_unlock_irq(phba->host->host_lock); |
553 | if (rc == IOCB_ERROR) { | 553 | if (rc == IOCB_ERROR) { |
554 | lpfc_els_free_iocb(phba, elsiocb); | 554 | lpfc_els_free_iocb(phba, elsiocb); |
555 | return (1); | 555 | return 1; |
556 | } | 556 | } |
557 | return (0); | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
560 | int | 560 | int |
@@ -611,29 +611,21 @@ lpfc_initial_flogi(struct lpfc_hba * phba) | |||
611 | { | 611 | { |
612 | struct lpfc_nodelist *ndlp; | 612 | struct lpfc_nodelist *ndlp; |
613 | 613 | ||
614 | /* First look for Fabric ndlp on the unmapped list */ | 614 | /* First look for the Fabric ndlp */ |
615 | 615 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID); | |
616 | if ((ndlp = | 616 | if (!ndlp) { |
617 | lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, | ||
618 | Fabric_DID)) == 0) { | ||
619 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 617 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
620 | if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) | 618 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
621 | == 0) { | 619 | if (!ndlp) |
622 | return (0); | 620 | return 0; |
623 | } | ||
624 | lpfc_nlp_init(phba, ndlp, Fabric_DID); | 621 | lpfc_nlp_init(phba, ndlp, Fabric_DID); |
625 | } | 622 | } else { |
626 | else { | 623 | lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); |
627 | phba->fc_unmap_cnt--; | ||
628 | list_del(&ndlp->nlp_listp); | ||
629 | spin_lock_irq(phba->host->host_lock); | ||
630 | ndlp->nlp_flag &= ~NLP_LIST_MASK; | ||
631 | spin_unlock_irq(phba->host->host_lock); | ||
632 | } | 624 | } |
633 | if (lpfc_issue_els_flogi(phba, ndlp, 0)) { | 625 | if (lpfc_issue_els_flogi(phba, ndlp, 0)) { |
634 | mempool_free( ndlp, phba->nlp_mem_pool); | 626 | mempool_free( ndlp, phba->nlp_mem_pool); |
635 | } | 627 | } |
636 | return (1); | 628 | return 1; |
637 | } | 629 | } |
638 | 630 | ||
639 | static void | 631 | static void |
@@ -659,38 +651,90 @@ lpfc_more_plogi(struct lpfc_hba * phba) | |||
659 | return; | 651 | return; |
660 | } | 652 | } |
661 | 653 | ||
654 | static struct lpfc_nodelist * | ||
655 | lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
656 | struct lpfc_nodelist *ndlp) | ||
657 | { | ||
658 | struct lpfc_nodelist *new_ndlp; | ||
659 | struct lpfc_dmabuf *pcmd, *prsp; | ||
660 | uint32_t *lp; | ||
661 | struct serv_parm *sp; | ||
662 | uint8_t name[sizeof (struct lpfc_name)]; | ||
663 | uint32_t rc; | ||
664 | |||
665 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
666 | prsp = (struct lpfc_dmabuf *) pcmd->list.next; | ||
667 | lp = (uint32_t *) prsp->virt; | ||
668 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | ||
669 | |||
670 | /* Now we to find out if the NPort we are logging into, matches the WWPN | ||
671 | * we have for that ndlp. If not, we have some work to do. | ||
672 | */ | ||
673 | new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); | ||
674 | |||
675 | memset(name, 0, sizeof (struct lpfc_name)); | ||
676 | rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)); | ||
677 | if (!rc || (new_ndlp == ndlp)) { | ||
678 | return ndlp; | ||
679 | } | ||
680 | |||
681 | if (!new_ndlp) { | ||
682 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); | ||
683 | if (!new_ndlp) | ||
684 | return ndlp; | ||
685 | |||
686 | lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID); | ||
687 | } | ||
688 | |||
689 | lpfc_unreg_rpi(phba, new_ndlp); | ||
690 | new_ndlp->nlp_prev_state = ndlp->nlp_state; | ||
691 | new_ndlp->nlp_DID = ndlp->nlp_DID; | ||
692 | new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | ||
693 | lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST); | ||
694 | |||
695 | /* Move this back to NPR list */ | ||
696 | lpfc_unreg_rpi(phba, ndlp); | ||
697 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ | ||
698 | ndlp->nlp_state = NLP_STE_NPR_NODE; | ||
699 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | ||
700 | |||
701 | return new_ndlp; | ||
702 | } | ||
703 | |||
662 | static void | 704 | static void |
663 | lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 705 | lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, |
664 | struct lpfc_iocbq * rspiocb) | 706 | struct lpfc_iocbq * rspiocb) |
665 | { | 707 | { |
666 | IOCB_t *irsp; | 708 | IOCB_t *irsp; |
667 | struct lpfc_sli *psli; | ||
668 | struct lpfc_nodelist *ndlp; | 709 | struct lpfc_nodelist *ndlp; |
669 | int disc, rc, did, type; | 710 | int disc, rc, did, type; |
670 | 711 | ||
671 | psli = &phba->sli; | ||
672 | 712 | ||
673 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 713 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
674 | cmdiocb->context_un.rsp_iocb = rspiocb; | 714 | cmdiocb->context_un.rsp_iocb = rspiocb; |
675 | 715 | ||
676 | irsp = &rspiocb->iocb; | 716 | irsp = &rspiocb->iocb; |
677 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 717 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, |
678 | spin_lock_irq(phba->host->host_lock); | 718 | irsp->un.elsreq64.remoteID); |
679 | ndlp->nlp_flag &= ~NLP_PLOGI_SND; | 719 | if (!ndlp) |
680 | spin_unlock_irq(phba->host->host_lock); | 720 | goto out; |
681 | 721 | ||
682 | /* Since ndlp can be freed in the disc state machine, note if this node | 722 | /* Since ndlp can be freed in the disc state machine, note if this node |
683 | * is being used during discovery. | 723 | * is being used during discovery. |
684 | */ | 724 | */ |
685 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | 725 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); |
726 | spin_lock_irq(phba->host->host_lock); | ||
727 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
728 | spin_unlock_irq(phba->host->host_lock); | ||
686 | rc = 0; | 729 | rc = 0; |
687 | 730 | ||
688 | /* PLOGI completes to NPort <nlp_DID> */ | 731 | /* PLOGI completes to NPort <nlp_DID> */ |
689 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 732 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
690 | "%d:0102 PLOGI completes to NPort x%x " | 733 | "%d:0102 PLOGI completes to NPort x%x " |
691 | "Data: x%x x%x x%x x%x\n", | 734 | "Data: x%x x%x x%x x%x x%x\n", |
692 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 735 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
693 | irsp->un.ulpWord[4], disc, phba->num_disc_nodes); | 736 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, |
737 | phba->num_disc_nodes); | ||
694 | 738 | ||
695 | /* Check to see if link went down during discovery */ | 739 | /* Check to see if link went down during discovery */ |
696 | if (lpfc_els_chk_latt(phba)) { | 740 | if (lpfc_els_chk_latt(phba)) { |
@@ -722,43 +766,28 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
722 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | 766 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || |
723 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 767 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || |
724 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 768 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
725 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | 769 | rc = NLP_STE_FREED_NODE; |
726 | } | 770 | } else { |
727 | else { | ||
728 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 771 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
729 | NLP_EVT_CMPL_PLOGI); | 772 | NLP_EVT_CMPL_PLOGI); |
730 | } | 773 | } |
731 | } else { | 774 | } else { |
732 | /* Good status, call state machine */ | 775 | /* Good status, call state machine */ |
776 | ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp); | ||
733 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 777 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
734 | NLP_EVT_CMPL_PLOGI); | 778 | NLP_EVT_CMPL_PLOGI); |
735 | } | 779 | } |
736 | 780 | ||
737 | if (type & NLP_FABRIC) { | ||
738 | /* If we cannot login to Nameserver, kick off discovery now */ | ||
739 | if ((did == NameServer_DID) && (rc == NLP_STE_FREED_NODE)) { | ||
740 | lpfc_disc_start(phba); | ||
741 | } | ||
742 | goto out; | ||
743 | } | ||
744 | |||
745 | if (disc && phba->num_disc_nodes) { | 781 | if (disc && phba->num_disc_nodes) { |
746 | /* Check to see if there are more PLOGIs to be sent */ | 782 | /* Check to see if there are more PLOGIs to be sent */ |
747 | lpfc_more_plogi(phba); | 783 | lpfc_more_plogi(phba); |
748 | } | 784 | } |
749 | 785 | ||
750 | if (rc != NLP_STE_FREED_NODE) { | 786 | if (phba->num_disc_nodes == 0) { |
751 | spin_lock_irq(phba->host->host_lock); | 787 | spin_lock_irq(phba->host->host_lock); |
752 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | 788 | phba->fc_flag &= ~FC_NDISC_ACTIVE; |
753 | spin_unlock_irq(phba->host->host_lock); | 789 | spin_unlock_irq(phba->host->host_lock); |
754 | } | ||
755 | 790 | ||
756 | if (phba->num_disc_nodes == 0) { | ||
757 | if(disc) { | ||
758 | spin_lock_irq(phba->host->host_lock); | ||
759 | phba->fc_flag &= ~FC_NDISC_ACTIVE; | ||
760 | spin_unlock_irq(phba->host->host_lock); | ||
761 | } | ||
762 | lpfc_can_disctmo(phba); | 791 | lpfc_can_disctmo(phba); |
763 | if (phba->fc_flag & FC_RSCN_MODE) { | 792 | if (phba->fc_flag & FC_RSCN_MODE) { |
764 | /* Check to see if more RSCNs came in while we were | 793 | /* Check to see if more RSCNs came in while we were |
@@ -781,8 +810,7 @@ out: | |||
781 | } | 810 | } |
782 | 811 | ||
783 | int | 812 | int |
784 | lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 813 | lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) |
785 | uint8_t retry) | ||
786 | { | 814 | { |
787 | struct serv_parm *sp; | 815 | struct serv_parm *sp; |
788 | IOCB_t *icmd; | 816 | IOCB_t *icmd; |
@@ -796,10 +824,10 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
796 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 824 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
797 | 825 | ||
798 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); | 826 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); |
799 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 827 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, 0, did, |
800 | ndlp, ELS_CMD_PLOGI)) == 0) { | 828 | ELS_CMD_PLOGI); |
801 | return (1); | 829 | if (!elsiocb) |
802 | } | 830 | return 1; |
803 | 831 | ||
804 | icmd = &elsiocb->iocb; | 832 | icmd = &elsiocb->iocb; |
805 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 833 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -819,15 +847,13 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
819 | phba->fc_stat.elsXmitPLOGI++; | 847 | phba->fc_stat.elsXmitPLOGI++; |
820 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; | 848 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; |
821 | spin_lock_irq(phba->host->host_lock); | 849 | spin_lock_irq(phba->host->host_lock); |
822 | ndlp->nlp_flag |= NLP_PLOGI_SND; | ||
823 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 850 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
824 | ndlp->nlp_flag &= ~NLP_PLOGI_SND; | ||
825 | spin_unlock_irq(phba->host->host_lock); | 851 | spin_unlock_irq(phba->host->host_lock); |
826 | lpfc_els_free_iocb(phba, elsiocb); | 852 | lpfc_els_free_iocb(phba, elsiocb); |
827 | return (1); | 853 | return 1; |
828 | } | 854 | } |
829 | spin_unlock_irq(phba->host->host_lock); | 855 | spin_unlock_irq(phba->host->host_lock); |
830 | return (0); | 856 | return 0; |
831 | } | 857 | } |
832 | 858 | ||
833 | static void | 859 | static void |
@@ -851,9 +877,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
851 | /* PRLI completes to NPort <nlp_DID> */ | 877 | /* PRLI completes to NPort <nlp_DID> */ |
852 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 878 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
853 | "%d:0103 PRLI completes to NPort x%x " | 879 | "%d:0103 PRLI completes to NPort x%x " |
854 | "Data: x%x x%x x%x\n", | 880 | "Data: x%x x%x x%x x%x\n", |
855 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 881 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
856 | irsp->un.ulpWord[4], phba->num_disc_nodes); | 882 | irsp->un.ulpWord[4], irsp->ulpTimeout, |
883 | phba->num_disc_nodes); | ||
857 | 884 | ||
858 | phba->fc_prli_sent--; | 885 | phba->fc_prli_sent--; |
859 | /* Check to see if link went down during discovery */ | 886 | /* Check to see if link went down during discovery */ |
@@ -873,8 +900,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
873 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 900 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || |
874 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 901 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
875 | goto out; | 902 | goto out; |
876 | } | 903 | } else { |
877 | else { | ||
878 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 904 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
879 | NLP_EVT_CMPL_PRLI); | 905 | NLP_EVT_CMPL_PRLI); |
880 | } | 906 | } |
@@ -904,10 +930,10 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
904 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 930 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
905 | 931 | ||
906 | cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); | 932 | cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); |
907 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 933 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
908 | ndlp, ELS_CMD_PRLI)) == 0) { | 934 | ndlp->nlp_DID, ELS_CMD_PRLI); |
909 | return (1); | 935 | if (!elsiocb) |
910 | } | 936 | return 1; |
911 | 937 | ||
912 | icmd = &elsiocb->iocb; | 938 | icmd = &elsiocb->iocb; |
913 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 939 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -943,11 +969,11 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
943 | ndlp->nlp_flag &= ~NLP_PRLI_SND; | 969 | ndlp->nlp_flag &= ~NLP_PRLI_SND; |
944 | spin_unlock_irq(phba->host->host_lock); | 970 | spin_unlock_irq(phba->host->host_lock); |
945 | lpfc_els_free_iocb(phba, elsiocb); | 971 | lpfc_els_free_iocb(phba, elsiocb); |
946 | return (1); | 972 | return 1; |
947 | } | 973 | } |
948 | spin_unlock_irq(phba->host->host_lock); | 974 | spin_unlock_irq(phba->host->host_lock); |
949 | phba->fc_prli_sent++; | 975 | phba->fc_prli_sent++; |
950 | return (0); | 976 | return 0; |
951 | } | 977 | } |
952 | 978 | ||
953 | static void | 979 | static void |
@@ -1016,21 +1042,22 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1016 | 1042 | ||
1017 | irsp = &(rspiocb->iocb); | 1043 | irsp = &(rspiocb->iocb); |
1018 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 1044 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
1019 | spin_lock_irq(phba->host->host_lock); | ||
1020 | ndlp->nlp_flag &= ~NLP_ADISC_SND; | ||
1021 | spin_unlock_irq(phba->host->host_lock); | ||
1022 | 1045 | ||
1023 | /* Since ndlp can be freed in the disc state machine, note if this node | 1046 | /* Since ndlp can be freed in the disc state machine, note if this node |
1024 | * is being used during discovery. | 1047 | * is being used during discovery. |
1025 | */ | 1048 | */ |
1026 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | 1049 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); |
1050 | spin_lock_irq(phba->host->host_lock); | ||
1051 | ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); | ||
1052 | spin_unlock_irq(phba->host->host_lock); | ||
1027 | 1053 | ||
1028 | /* ADISC completes to NPort <nlp_DID> */ | 1054 | /* ADISC completes to NPort <nlp_DID> */ |
1029 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1055 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
1030 | "%d:0104 ADISC completes to NPort x%x " | 1056 | "%d:0104 ADISC completes to NPort x%x " |
1031 | "Data: x%x x%x x%x x%x\n", | 1057 | "Data: x%x x%x x%x x%x x%x\n", |
1032 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 1058 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
1033 | irsp->un.ulpWord[4], disc, phba->num_disc_nodes); | 1059 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, |
1060 | phba->num_disc_nodes); | ||
1034 | 1061 | ||
1035 | /* Check to see if link went down during discovery */ | 1062 | /* Check to see if link went down during discovery */ |
1036 | if (lpfc_els_chk_latt(phba)) { | 1063 | if (lpfc_els_chk_latt(phba)) { |
@@ -1054,13 +1081,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1054 | } | 1081 | } |
1055 | /* ADISC failed */ | 1082 | /* ADISC failed */ |
1056 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1083 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
1057 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 1084 | if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || |
1058 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | 1085 | ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && |
1059 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 1086 | (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) && |
1060 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 1087 | (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) { |
1061 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | ||
1062 | } | ||
1063 | else { | ||
1064 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 1088 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
1065 | NLP_EVT_CMPL_ADISC); | 1089 | NLP_EVT_CMPL_ADISC); |
1066 | } | 1090 | } |
@@ -1112,9 +1136,6 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1112 | } | 1136 | } |
1113 | } | 1137 | } |
1114 | } | 1138 | } |
1115 | spin_lock_irq(phba->host->host_lock); | ||
1116 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
1117 | spin_unlock_irq(phba->host->host_lock); | ||
1118 | out: | 1139 | out: |
1119 | lpfc_els_free_iocb(phba, cmdiocb); | 1140 | lpfc_els_free_iocb(phba, cmdiocb); |
1120 | return; | 1141 | return; |
@@ -1136,10 +1157,10 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1136 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1157 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1137 | 1158 | ||
1138 | cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); | 1159 | cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); |
1139 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 1160 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1140 | ndlp, ELS_CMD_ADISC)) == 0) { | 1161 | ndlp->nlp_DID, ELS_CMD_ADISC); |
1141 | return (1); | 1162 | if (!elsiocb) |
1142 | } | 1163 | return 1; |
1143 | 1164 | ||
1144 | icmd = &elsiocb->iocb; | 1165 | icmd = &elsiocb->iocb; |
1145 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 1166 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -1163,10 +1184,10 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1163 | ndlp->nlp_flag &= ~NLP_ADISC_SND; | 1184 | ndlp->nlp_flag &= ~NLP_ADISC_SND; |
1164 | spin_unlock_irq(phba->host->host_lock); | 1185 | spin_unlock_irq(phba->host->host_lock); |
1165 | lpfc_els_free_iocb(phba, elsiocb); | 1186 | lpfc_els_free_iocb(phba, elsiocb); |
1166 | return (1); | 1187 | return 1; |
1167 | } | 1188 | } |
1168 | spin_unlock_irq(phba->host->host_lock); | 1189 | spin_unlock_irq(phba->host->host_lock); |
1169 | return (0); | 1190 | return 0; |
1170 | } | 1191 | } |
1171 | 1192 | ||
1172 | static void | 1193 | static void |
@@ -1190,9 +1211,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1190 | /* LOGO completes to NPort <nlp_DID> */ | 1211 | /* LOGO completes to NPort <nlp_DID> */ |
1191 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1212 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
1192 | "%d:0105 LOGO completes to NPort x%x " | 1213 | "%d:0105 LOGO completes to NPort x%x " |
1193 | "Data: x%x x%x x%x\n", | 1214 | "Data: x%x x%x x%x x%x\n", |
1194 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 1215 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
1195 | irsp->un.ulpWord[4], phba->num_disc_nodes); | 1216 | irsp->un.ulpWord[4], irsp->ulpTimeout, |
1217 | phba->num_disc_nodes); | ||
1196 | 1218 | ||
1197 | /* Check to see if link went down during discovery */ | 1219 | /* Check to see if link went down during discovery */ |
1198 | if (lpfc_els_chk_latt(phba)) | 1220 | if (lpfc_els_chk_latt(phba)) |
@@ -1211,18 +1233,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1211 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 1233 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || |
1212 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 1234 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
1213 | goto out; | 1235 | goto out; |
1214 | } | 1236 | } else { |
1215 | else { | ||
1216 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 1237 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
1217 | NLP_EVT_CMPL_LOGO); | 1238 | NLP_EVT_CMPL_LOGO); |
1218 | } | 1239 | } |
1219 | } else { | 1240 | } else { |
1220 | /* Good status, call state machine */ | 1241 | /* Good status, call state machine. |
1242 | * This will unregister the rpi if needed. | ||
1243 | */ | ||
1221 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); | 1244 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); |
1222 | |||
1223 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | ||
1224 | lpfc_unreg_rpi(phba, ndlp); | ||
1225 | } | ||
1226 | } | 1245 | } |
1227 | 1246 | ||
1228 | out: | 1247 | out: |
@@ -1245,10 +1264,10 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1245 | pring = &psli->ring[LPFC_ELS_RING]; | 1264 | pring = &psli->ring[LPFC_ELS_RING]; |
1246 | 1265 | ||
1247 | cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name)); | 1266 | cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name)); |
1248 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 1267 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1249 | ndlp, ELS_CMD_LOGO)) == 0) { | 1268 | ndlp->nlp_DID, ELS_CMD_LOGO); |
1250 | return (1); | 1269 | if (!elsiocb) |
1251 | } | 1270 | return 1; |
1252 | 1271 | ||
1253 | icmd = &elsiocb->iocb; | 1272 | icmd = &elsiocb->iocb; |
1254 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 1273 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -1268,10 +1287,10 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1268 | ndlp->nlp_flag &= ~NLP_LOGO_SND; | 1287 | ndlp->nlp_flag &= ~NLP_LOGO_SND; |
1269 | spin_unlock_irq(phba->host->host_lock); | 1288 | spin_unlock_irq(phba->host->host_lock); |
1270 | lpfc_els_free_iocb(phba, elsiocb); | 1289 | lpfc_els_free_iocb(phba, elsiocb); |
1271 | return (1); | 1290 | return 1; |
1272 | } | 1291 | } |
1273 | spin_unlock_irq(phba->host->host_lock); | 1292 | spin_unlock_irq(phba->host->host_lock); |
1274 | return (0); | 1293 | return 0; |
1275 | } | 1294 | } |
1276 | 1295 | ||
1277 | static void | 1296 | static void |
@@ -1286,9 +1305,10 @@ lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1286 | lpfc_printf_log(phba, | 1305 | lpfc_printf_log(phba, |
1287 | KERN_INFO, | 1306 | KERN_INFO, |
1288 | LOG_ELS, | 1307 | LOG_ELS, |
1289 | "%d:0106 ELS cmd tag x%x completes Data: x%x x%x\n", | 1308 | "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", |
1290 | phba->brd_no, | 1309 | phba->brd_no, |
1291 | irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4]); | 1310 | irsp->ulpIoTag, irsp->ulpStatus, |
1311 | irsp->un.ulpWord[4], irsp->ulpTimeout); | ||
1292 | 1312 | ||
1293 | /* Check to see if link went down during discovery */ | 1313 | /* Check to see if link went down during discovery */ |
1294 | lpfc_els_chk_latt(phba); | 1314 | lpfc_els_chk_latt(phba); |
@@ -1310,16 +1330,17 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1310 | psli = &phba->sli; | 1330 | psli = &phba->sli; |
1311 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1331 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1312 | cmdsize = (sizeof (uint32_t) + sizeof (SCR)); | 1332 | cmdsize = (sizeof (uint32_t) + sizeof (SCR)); |
1313 | if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) { | 1333 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
1314 | return (1); | 1334 | if (!ndlp) |
1315 | } | 1335 | return 1; |
1316 | 1336 | ||
1317 | lpfc_nlp_init(phba, ndlp, nportid); | 1337 | lpfc_nlp_init(phba, ndlp, nportid); |
1318 | 1338 | ||
1319 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 1339 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1320 | ndlp, ELS_CMD_SCR)) == 0) { | 1340 | ndlp->nlp_DID, ELS_CMD_SCR); |
1341 | if (!elsiocb) { | ||
1321 | mempool_free( ndlp, phba->nlp_mem_pool); | 1342 | mempool_free( ndlp, phba->nlp_mem_pool); |
1322 | return (1); | 1343 | return 1; |
1323 | } | 1344 | } |
1324 | 1345 | ||
1325 | icmd = &elsiocb->iocb; | 1346 | icmd = &elsiocb->iocb; |
@@ -1339,11 +1360,11 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1339 | spin_unlock_irq(phba->host->host_lock); | 1360 | spin_unlock_irq(phba->host->host_lock); |
1340 | mempool_free( ndlp, phba->nlp_mem_pool); | 1361 | mempool_free( ndlp, phba->nlp_mem_pool); |
1341 | lpfc_els_free_iocb(phba, elsiocb); | 1362 | lpfc_els_free_iocb(phba, elsiocb); |
1342 | return (1); | 1363 | return 1; |
1343 | } | 1364 | } |
1344 | spin_unlock_irq(phba->host->host_lock); | 1365 | spin_unlock_irq(phba->host->host_lock); |
1345 | mempool_free( ndlp, phba->nlp_mem_pool); | 1366 | mempool_free( ndlp, phba->nlp_mem_pool); |
1346 | return (0); | 1367 | return 0; |
1347 | } | 1368 | } |
1348 | 1369 | ||
1349 | static int | 1370 | static int |
@@ -1363,15 +1384,16 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1363 | psli = &phba->sli; | 1384 | psli = &phba->sli; |
1364 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 1385 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1365 | cmdsize = (sizeof (uint32_t) + sizeof (FARP)); | 1386 | cmdsize = (sizeof (uint32_t) + sizeof (FARP)); |
1366 | if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) { | 1387 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
1367 | return (1); | 1388 | if (!ndlp) |
1368 | } | 1389 | return 1; |
1369 | lpfc_nlp_init(phba, ndlp, nportid); | 1390 | lpfc_nlp_init(phba, ndlp, nportid); |
1370 | 1391 | ||
1371 | if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, | 1392 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1372 | ndlp, ELS_CMD_RNID)) == 0) { | 1393 | ndlp->nlp_DID, ELS_CMD_RNID); |
1394 | if (!elsiocb) { | ||
1373 | mempool_free( ndlp, phba->nlp_mem_pool); | 1395 | mempool_free( ndlp, phba->nlp_mem_pool); |
1374 | return (1); | 1396 | return 1; |
1375 | } | 1397 | } |
1376 | 1398 | ||
1377 | icmd = &elsiocb->iocb; | 1399 | icmd = &elsiocb->iocb; |
@@ -1405,11 +1427,51 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1405 | spin_unlock_irq(phba->host->host_lock); | 1427 | spin_unlock_irq(phba->host->host_lock); |
1406 | mempool_free( ndlp, phba->nlp_mem_pool); | 1428 | mempool_free( ndlp, phba->nlp_mem_pool); |
1407 | lpfc_els_free_iocb(phba, elsiocb); | 1429 | lpfc_els_free_iocb(phba, elsiocb); |
1408 | return (1); | 1430 | return 1; |
1409 | } | 1431 | } |
1410 | spin_unlock_irq(phba->host->host_lock); | 1432 | spin_unlock_irq(phba->host->host_lock); |
1411 | mempool_free( ndlp, phba->nlp_mem_pool); | 1433 | mempool_free( ndlp, phba->nlp_mem_pool); |
1412 | return (0); | 1434 | return 0; |
1435 | } | ||
1436 | |||
1437 | void | ||
1438 | lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp) | ||
1439 | { | ||
1440 | nlp->nlp_flag &= ~NLP_DELAY_TMO; | ||
1441 | del_timer_sync(&nlp->nlp_delayfunc); | ||
1442 | nlp->nlp_last_elscmd = 0; | ||
1443 | |||
1444 | if (!list_empty(&nlp->els_retry_evt.evt_listp)) | ||
1445 | list_del_init(&nlp->els_retry_evt.evt_listp); | ||
1446 | |||
1447 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
1448 | nlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
1449 | if (phba->num_disc_nodes) { | ||
1450 | /* Check to see if there are more | ||
1451 | * PLOGIs to be sent | ||
1452 | */ | ||
1453 | lpfc_more_plogi(phba); | ||
1454 | } | ||
1455 | |||
1456 | if (phba->num_disc_nodes == 0) { | ||
1457 | phba->fc_flag &= ~FC_NDISC_ACTIVE; | ||
1458 | lpfc_can_disctmo(phba); | ||
1459 | if (phba->fc_flag & FC_RSCN_MODE) { | ||
1460 | /* Check to see if more RSCNs | ||
1461 | * came in while we were | ||
1462 | * processing this one. | ||
1463 | */ | ||
1464 | if((phba->fc_rscn_id_cnt==0) && | ||
1465 | (!(phba->fc_flag & FC_RSCN_DISCOVERY))) { | ||
1466 | phba->fc_flag &= ~FC_RSCN_MODE; | ||
1467 | } | ||
1468 | else { | ||
1469 | lpfc_els_handle_rscn(phba); | ||
1470 | } | ||
1471 | } | ||
1472 | } | ||
1473 | } | ||
1474 | return; | ||
1413 | } | 1475 | } |
1414 | 1476 | ||
1415 | void | 1477 | void |
@@ -1450,8 +1512,9 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
1450 | 1512 | ||
1451 | phba = ndlp->nlp_phba; | 1513 | phba = ndlp->nlp_phba; |
1452 | spin_lock_irq(phba->host->host_lock); | 1514 | spin_lock_irq(phba->host->host_lock); |
1453 | did = (uint32_t) (ndlp->nlp_DID); | 1515 | did = ndlp->nlp_DID; |
1454 | cmd = (uint32_t) (ndlp->nlp_last_elscmd); | 1516 | cmd = ndlp->nlp_last_elscmd; |
1517 | ndlp->nlp_last_elscmd = 0; | ||
1455 | 1518 | ||
1456 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1519 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { |
1457 | spin_unlock_irq(phba->host->host_lock); | 1520 | spin_unlock_irq(phba->host->host_lock); |
@@ -1460,6 +1523,12 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
1460 | 1523 | ||
1461 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | 1524 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; |
1462 | spin_unlock_irq(phba->host->host_lock); | 1525 | spin_unlock_irq(phba->host->host_lock); |
1526 | /* | ||
1527 | * If a discovery event readded nlp_delayfunc after timer | ||
1528 | * firing and before processing the timer, cancel the | ||
1529 | * nlp_delayfunc. | ||
1530 | */ | ||
1531 | del_timer_sync(&ndlp->nlp_delayfunc); | ||
1463 | retry = ndlp->nlp_retry; | 1532 | retry = ndlp->nlp_retry; |
1464 | 1533 | ||
1465 | switch (cmd) { | 1534 | switch (cmd) { |
@@ -1467,24 +1536,32 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
1467 | lpfc_issue_els_flogi(phba, ndlp, retry); | 1536 | lpfc_issue_els_flogi(phba, ndlp, retry); |
1468 | break; | 1537 | break; |
1469 | case ELS_CMD_PLOGI: | 1538 | case ELS_CMD_PLOGI: |
1470 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 1539 | if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) { |
1471 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | 1540 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1472 | lpfc_issue_els_plogi(phba, ndlp, retry); | 1541 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
1542 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | ||
1543 | } | ||
1473 | break; | 1544 | break; |
1474 | case ELS_CMD_ADISC: | 1545 | case ELS_CMD_ADISC: |
1475 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; | 1546 | if (!lpfc_issue_els_adisc(phba, ndlp, retry)) { |
1476 | lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); | 1547 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1477 | lpfc_issue_els_adisc(phba, ndlp, retry); | 1548 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; |
1549 | lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); | ||
1550 | } | ||
1478 | break; | 1551 | break; |
1479 | case ELS_CMD_PRLI: | 1552 | case ELS_CMD_PRLI: |
1480 | ndlp->nlp_state = NLP_STE_PRLI_ISSUE; | 1553 | if (!lpfc_issue_els_prli(phba, ndlp, retry)) { |
1481 | lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); | 1554 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1482 | lpfc_issue_els_prli(phba, ndlp, retry); | 1555 | ndlp->nlp_state = NLP_STE_PRLI_ISSUE; |
1556 | lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); | ||
1557 | } | ||
1483 | break; | 1558 | break; |
1484 | case ELS_CMD_LOGO: | 1559 | case ELS_CMD_LOGO: |
1485 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1560 | if (!lpfc_issue_els_logo(phba, ndlp, retry)) { |
1486 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | 1561 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1487 | lpfc_issue_els_logo(phba, ndlp, retry); | 1562 | ndlp->nlp_state = NLP_STE_NPR_NODE; |
1563 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | ||
1564 | } | ||
1488 | break; | 1565 | break; |
1489 | } | 1566 | } |
1490 | return; | 1567 | return; |
@@ -1502,6 +1579,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1502 | int retry, maxretry; | 1579 | int retry, maxretry; |
1503 | int delay; | 1580 | int delay; |
1504 | uint32_t cmd; | 1581 | uint32_t cmd; |
1582 | uint32_t did; | ||
1505 | 1583 | ||
1506 | retry = 0; | 1584 | retry = 0; |
1507 | delay = 0; | 1585 | delay = 0; |
@@ -1510,6 +1588,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1510 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 1588 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
1511 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 1589 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
1512 | cmd = 0; | 1590 | cmd = 0; |
1591 | |||
1513 | /* Note: context2 may be 0 for internal driver abort | 1592 | /* Note: context2 may be 0 for internal driver abort |
1514 | * of delays ELS command. | 1593 | * of delays ELS command. |
1515 | */ | 1594 | */ |
@@ -1519,6 +1598,16 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1519 | cmd = *elscmd++; | 1598 | cmd = *elscmd++; |
1520 | } | 1599 | } |
1521 | 1600 | ||
1601 | if(ndlp) | ||
1602 | did = ndlp->nlp_DID; | ||
1603 | else { | ||
1604 | /* We should only hit this case for retrying PLOGI */ | ||
1605 | did = irsp->un.elsreq64.remoteID; | ||
1606 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); | ||
1607 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) | ||
1608 | return 1; | ||
1609 | } | ||
1610 | |||
1522 | switch (irsp->ulpStatus) { | 1611 | switch (irsp->ulpStatus) { |
1523 | case IOSTAT_FCP_RSP_ERROR: | 1612 | case IOSTAT_FCP_RSP_ERROR: |
1524 | case IOSTAT_REMOTE_STOP: | 1613 | case IOSTAT_REMOTE_STOP: |
@@ -1537,11 +1626,6 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1537 | 1626 | ||
1538 | case IOERR_SEQUENCE_TIMEOUT: | 1627 | case IOERR_SEQUENCE_TIMEOUT: |
1539 | retry = 1; | 1628 | retry = 1; |
1540 | if ((cmd == ELS_CMD_FLOGI) | ||
1541 | && (phba->fc_topology != TOPOLOGY_LOOP)) { | ||
1542 | delay = 1; | ||
1543 | maxretry = 48; | ||
1544 | } | ||
1545 | break; | 1629 | break; |
1546 | 1630 | ||
1547 | case IOERR_NO_RESOURCES: | 1631 | case IOERR_NO_RESOURCES: |
@@ -1612,9 +1696,8 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1612 | break; | 1696 | break; |
1613 | } | 1697 | } |
1614 | 1698 | ||
1615 | if (ndlp->nlp_DID == FDMI_DID) { | 1699 | if (did == FDMI_DID) |
1616 | retry = 1; | 1700 | retry = 1; |
1617 | } | ||
1618 | 1701 | ||
1619 | if ((++cmdiocb->retry) >= maxretry) { | 1702 | if ((++cmdiocb->retry) >= maxretry) { |
1620 | phba->fc_stat.elsRetryExceeded++; | 1703 | phba->fc_stat.elsRetryExceeded++; |
@@ -1628,7 +1711,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1628 | "%d:0107 Retry ELS command x%x to remote " | 1711 | "%d:0107 Retry ELS command x%x to remote " |
1629 | "NPORT x%x Data: x%x x%x\n", | 1712 | "NPORT x%x Data: x%x x%x\n", |
1630 | phba->brd_no, | 1713 | phba->brd_no, |
1631 | cmd, ndlp->nlp_DID, cmdiocb->retry, delay); | 1714 | cmd, did, cmdiocb->retry, delay); |
1632 | 1715 | ||
1633 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { | 1716 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { |
1634 | /* If discovery / RSCN timer is running, reset it */ | 1717 | /* If discovery / RSCN timer is running, reset it */ |
@@ -1639,54 +1722,61 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1639 | } | 1722 | } |
1640 | 1723 | ||
1641 | phba->fc_stat.elsXmitRetry++; | 1724 | phba->fc_stat.elsXmitRetry++; |
1642 | if (delay) { | 1725 | if (ndlp && delay) { |
1643 | phba->fc_stat.elsDelayRetry++; | 1726 | phba->fc_stat.elsDelayRetry++; |
1644 | ndlp->nlp_retry = cmdiocb->retry; | 1727 | ndlp->nlp_retry = cmdiocb->retry; |
1645 | 1728 | ||
1646 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 1729 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
1647 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1730 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
1648 | 1731 | ||
1732 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
1649 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1733 | ndlp->nlp_state = NLP_STE_NPR_NODE; |
1650 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | 1734 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); |
1651 | ndlp->nlp_last_elscmd = cmd; | 1735 | ndlp->nlp_last_elscmd = cmd; |
1652 | 1736 | ||
1653 | return (1); | 1737 | return 1; |
1654 | } | 1738 | } |
1655 | switch (cmd) { | 1739 | switch (cmd) { |
1656 | case ELS_CMD_FLOGI: | 1740 | case ELS_CMD_FLOGI: |
1657 | lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); | 1741 | lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); |
1658 | return (1); | 1742 | return 1; |
1659 | case ELS_CMD_PLOGI: | 1743 | case ELS_CMD_PLOGI: |
1660 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 1744 | if (ndlp) { |
1661 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | 1745 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1662 | lpfc_issue_els_plogi(phba, ndlp, cmdiocb->retry); | 1746 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
1663 | return (1); | 1747 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); |
1748 | } | ||
1749 | lpfc_issue_els_plogi(phba, did, cmdiocb->retry); | ||
1750 | return 1; | ||
1664 | case ELS_CMD_ADISC: | 1751 | case ELS_CMD_ADISC: |
1752 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
1665 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; | 1753 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; |
1666 | lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); | 1754 | lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); |
1667 | lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); | 1755 | lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); |
1668 | return (1); | 1756 | return 1; |
1669 | case ELS_CMD_PRLI: | 1757 | case ELS_CMD_PRLI: |
1758 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
1670 | ndlp->nlp_state = NLP_STE_PRLI_ISSUE; | 1759 | ndlp->nlp_state = NLP_STE_PRLI_ISSUE; |
1671 | lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); | 1760 | lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); |
1672 | lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); | 1761 | lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); |
1673 | return (1); | 1762 | return 1; |
1674 | case ELS_CMD_LOGO: | 1763 | case ELS_CMD_LOGO: |
1764 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
1675 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1765 | ndlp->nlp_state = NLP_STE_NPR_NODE; |
1676 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | 1766 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); |
1677 | lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); | 1767 | lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); |
1678 | return (1); | 1768 | return 1; |
1679 | } | 1769 | } |
1680 | } | 1770 | } |
1681 | 1771 | ||
1682 | /* No retry ELS command <elsCmd> to remote NPORT <did> */ | 1772 | /* No retry ELS command <elsCmd> to remote NPORT <did> */ |
1683 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1773 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
1684 | "%d:0108 No retry ELS command x%x to remote NPORT x%x " | 1774 | "%d:0108 No retry ELS command x%x to remote NPORT x%x " |
1685 | "Data: x%x x%x\n", | 1775 | "Data: x%x\n", |
1686 | phba->brd_no, | 1776 | phba->brd_no, |
1687 | cmd, ndlp->nlp_DID, cmdiocb->retry, ndlp->nlp_flag); | 1777 | cmd, did, cmdiocb->retry); |
1688 | 1778 | ||
1689 | return (0); | 1779 | return 0; |
1690 | } | 1780 | } |
1691 | 1781 | ||
1692 | int | 1782 | int |
@@ -1735,10 +1825,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1735 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, | 1825 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, |
1736 | ndlp->nlp_state, ndlp->nlp_rpi); | 1826 | ndlp->nlp_state, ndlp->nlp_rpi); |
1737 | 1827 | ||
1738 | spin_lock_irq(phba->host->host_lock); | ||
1739 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; | ||
1740 | spin_unlock_irq(phba->host->host_lock); | ||
1741 | |||
1742 | switch (ndlp->nlp_state) { | 1828 | switch (ndlp->nlp_state) { |
1743 | case NLP_STE_UNUSED_NODE: /* node is just allocated */ | 1829 | case NLP_STE_UNUSED_NODE: /* node is just allocated */ |
1744 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 1830 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
@@ -1776,11 +1862,12 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1776 | /* ELS response tag <ulpIoTag> completes */ | 1862 | /* ELS response tag <ulpIoTag> completes */ |
1777 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1863 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
1778 | "%d:0110 ELS response tag x%x completes " | 1864 | "%d:0110 ELS response tag x%x completes " |
1779 | "Data: x%x x%x x%x x%x x%x x%x\n", | 1865 | "Data: x%x x%x x%x x%x x%x x%x x%x\n", |
1780 | phba->brd_no, | 1866 | phba->brd_no, |
1781 | cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, | 1867 | cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, |
1782 | rspiocb->iocb.un.ulpWord[4], ndlp->nlp_DID, | 1868 | rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, |
1783 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 1869 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
1870 | ndlp->nlp_rpi); | ||
1784 | 1871 | ||
1785 | if (mbox) { | 1872 | if (mbox) { |
1786 | if ((rspiocb->iocb.ulpStatus == 0) | 1873 | if ((rspiocb->iocb.ulpStatus == 0) |
@@ -1791,6 +1878,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1791 | lpfc_unreg_rpi(phba, ndlp); | 1878 | lpfc_unreg_rpi(phba, ndlp); |
1792 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 1879 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
1793 | mbox->context2 = ndlp; | 1880 | mbox->context2 = ndlp; |
1881 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
1794 | ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE; | 1882 | ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE; |
1795 | lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); | 1883 | lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); |
1796 | if (lpfc_sli_issue_mbox(phba, mbox, | 1884 | if (lpfc_sli_issue_mbox(phba, mbox, |
@@ -1805,6 +1893,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1805 | mempool_free( mbox, phba->mbox_mem_pool); | 1893 | mempool_free( mbox, phba->mbox_mem_pool); |
1806 | if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { | 1894 | if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { |
1807 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 1895 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
1896 | ndlp = NULL; | ||
1808 | } | 1897 | } |
1809 | } | 1898 | } |
1810 | } | 1899 | } |
@@ -1839,10 +1928,11 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1839 | switch (flag) { | 1928 | switch (flag) { |
1840 | case ELS_CMD_ACC: | 1929 | case ELS_CMD_ACC: |
1841 | cmdsize = sizeof (uint32_t); | 1930 | cmdsize = sizeof (uint32_t); |
1842 | if ((elsiocb = | 1931 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
1843 | lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 1932 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
1844 | ndlp, ELS_CMD_ACC)) == 0) { | 1933 | if (!elsiocb) { |
1845 | return (1); | 1934 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; |
1935 | return 1; | ||
1846 | } | 1936 | } |
1847 | icmd = &elsiocb->iocb; | 1937 | icmd = &elsiocb->iocb; |
1848 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ | 1938 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ |
@@ -1852,11 +1942,11 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1852 | break; | 1942 | break; |
1853 | case ELS_CMD_PLOGI: | 1943 | case ELS_CMD_PLOGI: |
1854 | cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); | 1944 | cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); |
1855 | if ((elsiocb = | 1945 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
1856 | lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 1946 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
1857 | ndlp, ELS_CMD_ACC)) == 0) { | 1947 | if (!elsiocb) |
1858 | return (1); | 1948 | return 1; |
1859 | } | 1949 | |
1860 | icmd = &elsiocb->iocb; | 1950 | icmd = &elsiocb->iocb; |
1861 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ | 1951 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ |
1862 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 1952 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -1869,7 +1959,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1869 | memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); | 1959 | memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); |
1870 | break; | 1960 | break; |
1871 | default: | 1961 | default: |
1872 | return (1); | 1962 | return 1; |
1873 | } | 1963 | } |
1874 | 1964 | ||
1875 | if (newnode) | 1965 | if (newnode) |
@@ -1885,6 +1975,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1885 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 1975 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
1886 | 1976 | ||
1887 | if (ndlp->nlp_flag & NLP_LOGO_ACC) { | 1977 | if (ndlp->nlp_flag & NLP_LOGO_ACC) { |
1978 | spin_lock_irq(phba->host->host_lock); | ||
1979 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; | ||
1980 | spin_unlock_irq(phba->host->host_lock); | ||
1888 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; | 1981 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; |
1889 | } else { | 1982 | } else { |
1890 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 1983 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
@@ -1896,9 +1989,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1896 | spin_unlock_irq(phba->host->host_lock); | 1989 | spin_unlock_irq(phba->host->host_lock); |
1897 | if (rc == IOCB_ERROR) { | 1990 | if (rc == IOCB_ERROR) { |
1898 | lpfc_els_free_iocb(phba, elsiocb); | 1991 | lpfc_els_free_iocb(phba, elsiocb); |
1899 | return (1); | 1992 | return 1; |
1900 | } | 1993 | } |
1901 | return (0); | 1994 | return 0; |
1902 | } | 1995 | } |
1903 | 1996 | ||
1904 | int | 1997 | int |
@@ -1918,10 +2011,10 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | |||
1918 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2011 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1919 | 2012 | ||
1920 | cmdsize = 2 * sizeof (uint32_t); | 2013 | cmdsize = 2 * sizeof (uint32_t); |
1921 | if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2014 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
1922 | ndlp, ELS_CMD_LS_RJT)) == 0) { | 2015 | ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT); |
1923 | return (1); | 2016 | if (!elsiocb) |
1924 | } | 2017 | return 1; |
1925 | 2018 | ||
1926 | icmd = &elsiocb->iocb; | 2019 | icmd = &elsiocb->iocb; |
1927 | oldcmd = &oldiocb->iocb; | 2020 | oldcmd = &oldiocb->iocb; |
@@ -1948,9 +2041,9 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | |||
1948 | spin_unlock_irq(phba->host->host_lock); | 2041 | spin_unlock_irq(phba->host->host_lock); |
1949 | if (rc == IOCB_ERROR) { | 2042 | if (rc == IOCB_ERROR) { |
1950 | lpfc_els_free_iocb(phba, elsiocb); | 2043 | lpfc_els_free_iocb(phba, elsiocb); |
1951 | return (1); | 2044 | return 1; |
1952 | } | 2045 | } |
1953 | return (0); | 2046 | return 0; |
1954 | } | 2047 | } |
1955 | 2048 | ||
1956 | int | 2049 | int |
@@ -1971,10 +2064,10 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, | |||
1971 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2064 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
1972 | 2065 | ||
1973 | cmdsize = sizeof (uint32_t) + sizeof (ADISC); | 2066 | cmdsize = sizeof (uint32_t) + sizeof (ADISC); |
1974 | if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2067 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
1975 | ndlp, ELS_CMD_ACC)) == 0) { | 2068 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
1976 | return (1); | 2069 | if (!elsiocb) |
1977 | } | 2070 | return 1; |
1978 | 2071 | ||
1979 | /* Xmit ADISC ACC response tag <ulpIoTag> */ | 2072 | /* Xmit ADISC ACC response tag <ulpIoTag> */ |
1980 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2073 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -2006,9 +2099,9 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, | |||
2006 | spin_unlock_irq(phba->host->host_lock); | 2099 | spin_unlock_irq(phba->host->host_lock); |
2007 | if (rc == IOCB_ERROR) { | 2100 | if (rc == IOCB_ERROR) { |
2008 | lpfc_els_free_iocb(phba, elsiocb); | 2101 | lpfc_els_free_iocb(phba, elsiocb); |
2009 | return (1); | 2102 | return 1; |
2010 | } | 2103 | } |
2011 | return (0); | 2104 | return 0; |
2012 | } | 2105 | } |
2013 | 2106 | ||
2014 | int | 2107 | int |
@@ -2030,13 +2123,10 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, | |||
2030 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2123 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
2031 | 2124 | ||
2032 | cmdsize = sizeof (uint32_t) + sizeof (PRLI); | 2125 | cmdsize = sizeof (uint32_t) + sizeof (PRLI); |
2033 | if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2126 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, |
2034 | ndlp, | 2127 | ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); |
2035 | (ELS_CMD_ACC | | 2128 | if (!elsiocb) |
2036 | (ELS_CMD_PRLI & ~ELS_RSP_MASK)))) == | 2129 | return 1; |
2037 | 0) { | ||
2038 | return (1); | ||
2039 | } | ||
2040 | 2130 | ||
2041 | /* Xmit PRLI ACC response tag <ulpIoTag> */ | 2131 | /* Xmit PRLI ACC response tag <ulpIoTag> */ |
2042 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2132 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -2086,9 +2176,9 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, | |||
2086 | spin_unlock_irq(phba->host->host_lock); | 2176 | spin_unlock_irq(phba->host->host_lock); |
2087 | if (rc == IOCB_ERROR) { | 2177 | if (rc == IOCB_ERROR) { |
2088 | lpfc_els_free_iocb(phba, elsiocb); | 2178 | lpfc_els_free_iocb(phba, elsiocb); |
2089 | return (1); | 2179 | return 1; |
2090 | } | 2180 | } |
2091 | return (0); | 2181 | return 0; |
2092 | } | 2182 | } |
2093 | 2183 | ||
2094 | static int | 2184 | static int |
@@ -2114,10 +2204,10 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, | |||
2114 | if (format) | 2204 | if (format) |
2115 | cmdsize += sizeof (RNID_TOP_DISC); | 2205 | cmdsize += sizeof (RNID_TOP_DISC); |
2116 | 2206 | ||
2117 | if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2207 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
2118 | ndlp, ELS_CMD_ACC)) == 0) { | 2208 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
2119 | return (1); | 2209 | if (!elsiocb) |
2120 | } | 2210 | return 1; |
2121 | 2211 | ||
2122 | /* Xmit RNID ACC response tag <ulpIoTag> */ | 2212 | /* Xmit RNID ACC response tag <ulpIoTag> */ |
2123 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2213 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -2169,9 +2259,9 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, | |||
2169 | spin_unlock_irq(phba->host->host_lock); | 2259 | spin_unlock_irq(phba->host->host_lock); |
2170 | if (rc == IOCB_ERROR) { | 2260 | if (rc == IOCB_ERROR) { |
2171 | lpfc_els_free_iocb(phba, elsiocb); | 2261 | lpfc_els_free_iocb(phba, elsiocb); |
2172 | return (1); | 2262 | return 1; |
2173 | } | 2263 | } |
2174 | return (0); | 2264 | return 0; |
2175 | } | 2265 | } |
2176 | 2266 | ||
2177 | int | 2267 | int |
@@ -2187,6 +2277,7 @@ lpfc_els_disc_adisc(struct lpfc_hba * phba) | |||
2187 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 2277 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { |
2188 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 2278 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
2189 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 2279 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
2280 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
2190 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; | 2281 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; |
2191 | lpfc_nlp_list(phba, ndlp, | 2282 | lpfc_nlp_list(phba, ndlp, |
2192 | NLP_ADISC_LIST); | 2283 | NLP_ADISC_LIST); |
@@ -2208,7 +2299,7 @@ lpfc_els_disc_adisc(struct lpfc_hba * phba) | |||
2208 | phba->fc_flag &= ~FC_NLP_MORE; | 2299 | phba->fc_flag &= ~FC_NLP_MORE; |
2209 | spin_unlock_irq(phba->host->host_lock); | 2300 | spin_unlock_irq(phba->host->host_lock); |
2210 | } | 2301 | } |
2211 | return(sentadisc); | 2302 | return sentadisc; |
2212 | } | 2303 | } |
2213 | 2304 | ||
2214 | int | 2305 | int |
@@ -2224,9 +2315,10 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) | |||
2224 | if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) && | 2315 | if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) && |
2225 | (!(ndlp->nlp_flag & NLP_DELAY_TMO))) { | 2316 | (!(ndlp->nlp_flag & NLP_DELAY_TMO))) { |
2226 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 2317 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
2318 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
2227 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 2319 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
2228 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | 2320 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); |
2229 | lpfc_issue_els_plogi(phba, ndlp, 0); | 2321 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); |
2230 | sentplogi++; | 2322 | sentplogi++; |
2231 | phba->num_disc_nodes++; | 2323 | phba->num_disc_nodes++; |
2232 | if (phba->num_disc_nodes >= | 2324 | if (phba->num_disc_nodes >= |
@@ -2244,7 +2336,7 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) | |||
2244 | phba->fc_flag &= ~FC_NLP_MORE; | 2336 | phba->fc_flag &= ~FC_NLP_MORE; |
2245 | spin_unlock_irq(phba->host->host_lock); | 2337 | spin_unlock_irq(phba->host->host_lock); |
2246 | } | 2338 | } |
2247 | return(sentplogi); | 2339 | return sentplogi; |
2248 | } | 2340 | } |
2249 | 2341 | ||
2250 | int | 2342 | int |
@@ -2264,7 +2356,7 @@ lpfc_els_flush_rscn(struct lpfc_hba * phba) | |||
2264 | phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); | 2356 | phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); |
2265 | spin_unlock_irq(phba->host->host_lock); | 2357 | spin_unlock_irq(phba->host->host_lock); |
2266 | lpfc_can_disctmo(phba); | 2358 | lpfc_can_disctmo(phba); |
2267 | return (0); | 2359 | return 0; |
2268 | } | 2360 | } |
2269 | 2361 | ||
2270 | int | 2362 | int |
@@ -2285,7 +2377,7 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | |||
2285 | 2377 | ||
2286 | /* If we are doing a FULL RSCN rediscovery, match everything */ | 2378 | /* If we are doing a FULL RSCN rediscovery, match everything */ |
2287 | if (phba->fc_flag & FC_RSCN_DISCOVERY) { | 2379 | if (phba->fc_flag & FC_RSCN_DISCOVERY) { |
2288 | return (did); | 2380 | return did; |
2289 | } | 2381 | } |
2290 | 2382 | ||
2291 | for (i = 0; i < phba->fc_rscn_id_cnt; i++) { | 2383 | for (i = 0; i < phba->fc_rscn_id_cnt; i++) { |
@@ -2333,7 +2425,7 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | |||
2333 | } | 2425 | } |
2334 | } | 2426 | } |
2335 | } | 2427 | } |
2336 | return (match); | 2428 | return match; |
2337 | } | 2429 | } |
2338 | 2430 | ||
2339 | static int | 2431 | static int |
@@ -2365,17 +2457,15 @@ lpfc_rscn_recovery_check(struct lpfc_hba * phba) | |||
2365 | 2457 | ||
2366 | lpfc_disc_state_machine(phba, ndlp, NULL, | 2458 | lpfc_disc_state_machine(phba, ndlp, NULL, |
2367 | NLP_EVT_DEVICE_RECOVERY); | 2459 | NLP_EVT_DEVICE_RECOVERY); |
2368 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 2460 | |
2369 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | 2461 | /* Make sure NLP_DELAY_TMO is NOT running |
2370 | del_timer_sync(&ndlp->nlp_delayfunc); | 2462 | * after a device recovery event. |
2371 | if (!list_empty(&ndlp-> | 2463 | */ |
2372 | els_retry_evt.evt_listp)) | 2464 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
2373 | list_del_init(&ndlp-> | 2465 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
2374 | els_retry_evt.evt_listp); | ||
2375 | } | ||
2376 | } | 2466 | } |
2377 | } | 2467 | } |
2378 | return (0); | 2468 | return 0; |
2379 | } | 2469 | } |
2380 | 2470 | ||
2381 | static int | 2471 | static int |
@@ -2411,7 +2501,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2411 | if (phba->hba_state < LPFC_NS_QRY) { | 2501 | if (phba->hba_state < LPFC_NS_QRY) { |
2412 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2502 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, |
2413 | newnode); | 2503 | newnode); |
2414 | return (0); | 2504 | return 0; |
2415 | } | 2505 | } |
2416 | 2506 | ||
2417 | /* If we are already processing an RSCN, save the received | 2507 | /* If we are already processing an RSCN, save the received |
@@ -2453,7 +2543,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2453 | 2543 | ||
2454 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2544 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2455 | lpfc_rscn_recovery_check(phba); | 2545 | lpfc_rscn_recovery_check(phba); |
2456 | return (0); | 2546 | return 0; |
2457 | } | 2547 | } |
2458 | 2548 | ||
2459 | phba->fc_flag |= FC_RSCN_MODE; | 2549 | phba->fc_flag |= FC_RSCN_MODE; |
@@ -2472,7 +2562,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2472 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2562 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2473 | lpfc_rscn_recovery_check(phba); | 2563 | lpfc_rscn_recovery_check(phba); |
2474 | 2564 | ||
2475 | return (lpfc_els_handle_rscn(phba)); | 2565 | return lpfc_els_handle_rscn(phba); |
2476 | } | 2566 | } |
2477 | 2567 | ||
2478 | int | 2568 | int |
@@ -2494,40 +2584,41 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) | |||
2494 | 2584 | ||
2495 | /* To process RSCN, first compare RSCN data with NameServer */ | 2585 | /* To process RSCN, first compare RSCN data with NameServer */ |
2496 | phba->fc_ns_retry = 0; | 2586 | phba->fc_ns_retry = 0; |
2497 | if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, | 2587 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID); |
2498 | NameServer_DID))) { | 2588 | if (ndlp) { |
2499 | /* Good ndlp, issue CT Request to NameServer */ | 2589 | /* Good ndlp, issue CT Request to NameServer */ |
2500 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { | 2590 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { |
2501 | /* Wait for NameServer query cmpl before we can | 2591 | /* Wait for NameServer query cmpl before we can |
2502 | continue */ | 2592 | continue */ |
2503 | return (1); | 2593 | return 1; |
2504 | } | 2594 | } |
2505 | } else { | 2595 | } else { |
2506 | /* If login to NameServer does not exist, issue one */ | 2596 | /* If login to NameServer does not exist, issue one */ |
2507 | /* Good status, issue PLOGI to NameServer */ | 2597 | /* Good status, issue PLOGI to NameServer */ |
2508 | if ((ndlp = | 2598 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); |
2509 | lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID))) { | 2599 | if (ndlp) { |
2510 | /* Wait for NameServer login cmpl before we can | 2600 | /* Wait for NameServer login cmpl before we can |
2511 | continue */ | 2601 | continue */ |
2512 | return (1); | 2602 | return 1; |
2513 | } | 2603 | } |
2514 | if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) | 2604 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
2515 | == 0) { | 2605 | if (!ndlp) { |
2516 | lpfc_els_flush_rscn(phba); | 2606 | lpfc_els_flush_rscn(phba); |
2517 | return (0); | 2607 | return 0; |
2518 | } else { | 2608 | } else { |
2519 | lpfc_nlp_init(phba, ndlp, NameServer_DID); | 2609 | lpfc_nlp_init(phba, ndlp, NameServer_DID); |
2520 | ndlp->nlp_type |= NLP_FABRIC; | 2610 | ndlp->nlp_type |= NLP_FABRIC; |
2611 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
2521 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 2612 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
2522 | lpfc_issue_els_plogi(phba, ndlp, 0); | 2613 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); |
2523 | /* Wait for NameServer login cmpl before we can | 2614 | /* Wait for NameServer login cmpl before we can |
2524 | continue */ | 2615 | continue */ |
2525 | return (1); | 2616 | return 1; |
2526 | } | 2617 | } |
2527 | } | 2618 | } |
2528 | 2619 | ||
2529 | lpfc_els_flush_rscn(phba); | 2620 | lpfc_els_flush_rscn(phba); |
2530 | return (0); | 2621 | return 0; |
2531 | } | 2622 | } |
2532 | 2623 | ||
2533 | static int | 2624 | static int |
@@ -2561,7 +2652,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2561 | "%d:0113 An FLOGI ELS command x%x was received " | 2652 | "%d:0113 An FLOGI ELS command x%x was received " |
2562 | "from DID x%x in Loop Mode\n", | 2653 | "from DID x%x in Loop Mode\n", |
2563 | phba->brd_no, cmd, did); | 2654 | phba->brd_no, cmd, did); |
2564 | return (1); | 2655 | return 1; |
2565 | } | 2656 | } |
2566 | 2657 | ||
2567 | did = Fabric_DID; | 2658 | did = Fabric_DID; |
@@ -2577,7 +2668,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2577 | if (!rc) { | 2668 | if (!rc) { |
2578 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, | 2669 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, |
2579 | GFP_KERNEL)) == 0) { | 2670 | GFP_KERNEL)) == 0) { |
2580 | return (1); | 2671 | return 1; |
2581 | } | 2672 | } |
2582 | lpfc_linkdown(phba); | 2673 | lpfc_linkdown(phba); |
2583 | lpfc_init_link(phba, mbox, | 2674 | lpfc_init_link(phba, mbox, |
@@ -2590,9 +2681,8 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2590 | if (rc == MBX_NOT_FINISHED) { | 2681 | if (rc == MBX_NOT_FINISHED) { |
2591 | mempool_free( mbox, phba->mbox_mem_pool); | 2682 | mempool_free( mbox, phba->mbox_mem_pool); |
2592 | } | 2683 | } |
2593 | return (1); | 2684 | return 1; |
2594 | } | 2685 | } else if (rc > 0) { /* greater than */ |
2595 | else if (rc > 0) { /* greater than */ | ||
2596 | spin_lock_irq(phba->host->host_lock); | 2686 | spin_lock_irq(phba->host->host_lock); |
2597 | phba->fc_flag |= FC_PT2PT_PLOGI; | 2687 | phba->fc_flag |= FC_PT2PT_PLOGI; |
2598 | spin_unlock_irq(phba->host->host_lock); | 2688 | spin_unlock_irq(phba->host->host_lock); |
@@ -2606,13 +2696,13 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2606 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 2696 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
2607 | stat.un.b.vendorUnique = 0; | 2697 | stat.un.b.vendorUnique = 0; |
2608 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2698 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); |
2609 | return (1); | 2699 | return 1; |
2610 | } | 2700 | } |
2611 | 2701 | ||
2612 | /* Send back ACC */ | 2702 | /* Send back ACC */ |
2613 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); | 2703 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); |
2614 | 2704 | ||
2615 | return (0); | 2705 | return 0; |
2616 | } | 2706 | } |
2617 | 2707 | ||
2618 | static int | 2708 | static int |
@@ -2650,45 +2740,246 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, | |||
2650 | stat.un.b.vendorUnique = 0; | 2740 | stat.un.b.vendorUnique = 0; |
2651 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2741 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); |
2652 | } | 2742 | } |
2653 | return (0); | 2743 | return 0; |
2654 | } | 2744 | } |
2655 | 2745 | ||
2656 | static int | 2746 | static int |
2657 | lpfc_els_rcv_rrq(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2747 | lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, |
2748 | struct lpfc_nodelist * ndlp) | ||
2749 | { | ||
2750 | struct ls_rjt stat; | ||
2751 | |||
2752 | /* For now, unconditionally reject this command */ | ||
2753 | stat.un.b.lsRjtRsvd0 = 0; | ||
2754 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2755 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2756 | stat.un.b.vendorUnique = 0; | ||
2757 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2758 | return 0; | ||
2759 | } | ||
2760 | |||
2761 | static void | ||
2762 | lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | ||
2763 | { | ||
2764 | struct lpfc_sli *psli; | ||
2765 | struct lpfc_sli_ring *pring; | ||
2766 | MAILBOX_t *mb; | ||
2767 | IOCB_t *icmd; | ||
2768 | RPS_RSP *rps_rsp; | ||
2769 | uint8_t *pcmd; | ||
2770 | struct lpfc_iocbq *elsiocb; | ||
2771 | struct lpfc_nodelist *ndlp; | ||
2772 | uint16_t xri, status; | ||
2773 | uint32_t cmdsize; | ||
2774 | |||
2775 | psli = &phba->sli; | ||
2776 | pring = &psli->ring[LPFC_ELS_RING]; | ||
2777 | mb = &pmb->mb; | ||
2778 | |||
2779 | ndlp = (struct lpfc_nodelist *) pmb->context2; | ||
2780 | xri = (uint16_t) ((unsigned long)(pmb->context1)); | ||
2781 | pmb->context1 = 0; | ||
2782 | pmb->context2 = 0; | ||
2783 | |||
2784 | if (mb->mbxStatus) { | ||
2785 | mempool_free( pmb, phba->mbox_mem_pool); | ||
2786 | return; | ||
2787 | } | ||
2788 | |||
2789 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); | ||
2790 | mempool_free( pmb, phba->mbox_mem_pool); | ||
2791 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, | ||
2792 | ndlp->nlp_DID, ELS_CMD_ACC); | ||
2793 | if (!elsiocb) | ||
2794 | return; | ||
2795 | |||
2796 | icmd = &elsiocb->iocb; | ||
2797 | icmd->ulpContext = xri; | ||
2798 | |||
2799 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | ||
2800 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | ||
2801 | pcmd += sizeof (uint32_t); /* Skip past command */ | ||
2802 | rps_rsp = (RPS_RSP *)pcmd; | ||
2803 | |||
2804 | if (phba->fc_topology != TOPOLOGY_LOOP) | ||
2805 | status = 0x10; | ||
2806 | else | ||
2807 | status = 0x8; | ||
2808 | if (phba->fc_flag & FC_FABRIC) | ||
2809 | status |= 0x4; | ||
2810 | |||
2811 | rps_rsp->rsvd1 = 0; | ||
2812 | rps_rsp->portStatus = be16_to_cpu(status); | ||
2813 | rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt); | ||
2814 | rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt); | ||
2815 | rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt); | ||
2816 | rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt); | ||
2817 | rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord); | ||
2818 | rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt); | ||
2819 | |||
2820 | /* Xmit ELS RPS ACC response tag <ulpIoTag> */ | ||
2821 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
2822 | "%d:0128 Xmit ELS RPS ACC response tag x%x " | ||
2823 | "Data: x%x x%x x%x x%x x%x\n", | ||
2824 | phba->brd_no, | ||
2825 | elsiocb->iocb.ulpIoTag, | ||
2826 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | ||
2827 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | ||
2828 | |||
2829 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | ||
2830 | phba->fc_stat.elsXmitACC++; | ||
2831 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | ||
2832 | lpfc_els_free_iocb(phba, elsiocb); | ||
2833 | } | ||
2834 | return; | ||
2835 | } | ||
2836 | |||
2837 | static int | ||
2838 | lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
2658 | struct lpfc_nodelist * ndlp) | 2839 | struct lpfc_nodelist * ndlp) |
2659 | { | 2840 | { |
2660 | struct lpfc_dmabuf *pcmd; | ||
2661 | uint32_t *lp; | 2841 | uint32_t *lp; |
2842 | uint8_t flag; | ||
2843 | LPFC_MBOXQ_t *mbox; | ||
2844 | struct lpfc_dmabuf *pcmd; | ||
2845 | RPS *rps; | ||
2846 | struct ls_rjt stat; | ||
2847 | |||
2848 | if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && | ||
2849 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { | ||
2850 | stat.un.b.lsRjtRsvd0 = 0; | ||
2851 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2852 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2853 | stat.un.b.vendorUnique = 0; | ||
2854 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2855 | } | ||
2856 | |||
2857 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
2858 | lp = (uint32_t *) pcmd->virt; | ||
2859 | flag = (be32_to_cpu(*lp++) & 0xf); | ||
2860 | rps = (RPS *) lp; | ||
2861 | |||
2862 | if ((flag == 0) || | ||
2863 | ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || | ||
2864 | ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname, | ||
2865 | sizeof (struct lpfc_name)) == 0))) { | ||
2866 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) { | ||
2867 | lpfc_read_lnk_stat(phba, mbox); | ||
2868 | mbox->context1 = | ||
2869 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); | ||
2870 | mbox->context2 = ndlp; | ||
2871 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; | ||
2872 | if (lpfc_sli_issue_mbox (phba, mbox, | ||
2873 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { | ||
2874 | /* Mbox completion will send ELS Response */ | ||
2875 | return 0; | ||
2876 | } | ||
2877 | mempool_free(mbox, phba->mbox_mem_pool); | ||
2878 | } | ||
2879 | } | ||
2880 | stat.un.b.lsRjtRsvd0 = 0; | ||
2881 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2882 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2883 | stat.un.b.vendorUnique = 0; | ||
2884 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2885 | return 0; | ||
2886 | } | ||
2887 | |||
2888 | static int | ||
2889 | lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, | ||
2890 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | ||
2891 | { | ||
2662 | IOCB_t *icmd; | 2892 | IOCB_t *icmd; |
2893 | IOCB_t *oldcmd; | ||
2894 | RPL_RSP rpl_rsp; | ||
2895 | struct lpfc_iocbq *elsiocb; | ||
2663 | struct lpfc_sli_ring *pring; | 2896 | struct lpfc_sli_ring *pring; |
2664 | struct lpfc_sli *psli; | 2897 | struct lpfc_sli *psli; |
2665 | RRQ *rrq; | 2898 | uint8_t *pcmd; |
2666 | uint32_t cmd, did; | ||
2667 | 2899 | ||
2668 | psli = &phba->sli; | 2900 | psli = &phba->sli; |
2669 | pring = &psli->ring[LPFC_FCP_RING]; | 2901 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
2670 | icmd = &cmdiocb->iocb; | 2902 | |
2671 | did = icmd->un.elsreq64.remoteID; | 2903 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, |
2904 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | ||
2905 | if (!elsiocb) | ||
2906 | return 1; | ||
2907 | |||
2908 | icmd = &elsiocb->iocb; | ||
2909 | oldcmd = &oldiocb->iocb; | ||
2910 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ | ||
2911 | |||
2912 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | ||
2913 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | ||
2914 | pcmd += sizeof (uint16_t); | ||
2915 | *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize); | ||
2916 | pcmd += sizeof(uint16_t); | ||
2917 | |||
2918 | /* Setup the RPL ACC payload */ | ||
2919 | rpl_rsp.listLen = be32_to_cpu(1); | ||
2920 | rpl_rsp.index = 0; | ||
2921 | rpl_rsp.port_num_blk.portNum = 0; | ||
2922 | rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID); | ||
2923 | memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname, | ||
2924 | sizeof(struct lpfc_name)); | ||
2925 | |||
2926 | memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); | ||
2927 | |||
2928 | |||
2929 | /* Xmit ELS RPL ACC response tag <ulpIoTag> */ | ||
2930 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
2931 | "%d:0128 Xmit ELS RPL ACC response tag x%x " | ||
2932 | "Data: x%x x%x x%x x%x x%x\n", | ||
2933 | phba->brd_no, | ||
2934 | elsiocb->iocb.ulpIoTag, | ||
2935 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | ||
2936 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | ||
2937 | |||
2938 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | ||
2939 | |||
2940 | phba->fc_stat.elsXmitACC++; | ||
2941 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | ||
2942 | lpfc_els_free_iocb(phba, elsiocb); | ||
2943 | return 1; | ||
2944 | } | ||
2945 | return 0; | ||
2946 | } | ||
2947 | |||
2948 | static int | ||
2949 | lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
2950 | struct lpfc_nodelist * ndlp) | ||
2951 | { | ||
2952 | struct lpfc_dmabuf *pcmd; | ||
2953 | uint32_t *lp; | ||
2954 | uint32_t maxsize; | ||
2955 | uint16_t cmdsize; | ||
2956 | RPL *rpl; | ||
2957 | struct ls_rjt stat; | ||
2958 | |||
2959 | if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && | ||
2960 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { | ||
2961 | stat.un.b.lsRjtRsvd0 = 0; | ||
2962 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2963 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2964 | stat.un.b.vendorUnique = 0; | ||
2965 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2966 | } | ||
2967 | |||
2672 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 2968 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
2673 | lp = (uint32_t *) pcmd->virt; | 2969 | lp = (uint32_t *) pcmd->virt; |
2970 | rpl = (RPL *) (lp + 1); | ||
2674 | 2971 | ||
2675 | cmd = *lp++; | 2972 | maxsize = be32_to_cpu(rpl->maxsize); |
2676 | rrq = (RRQ *) lp; | ||
2677 | 2973 | ||
2678 | /* RRQ received */ | 2974 | /* We support only one port */ |
2679 | /* Get oxid / rxid from payload and abort it */ | 2975 | if ((rpl->index == 0) && |
2680 | spin_lock_irq(phba->host->host_lock); | 2976 | ((maxsize == 0) || |
2681 | if ((rrq->SID == be32_to_cpu(phba->fc_myDID))) { | 2977 | ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) { |
2682 | lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Oxid, | 2978 | cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP); |
2683 | LPFC_CTX_CTX); | ||
2684 | } else { | 2979 | } else { |
2685 | lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Rxid, | 2980 | cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); |
2686 | LPFC_CTX_CTX); | ||
2687 | } | 2981 | } |
2688 | 2982 | lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp); | |
2689 | spin_unlock_irq(phba->host->host_lock); | ||
2690 | /* ACCEPT the rrq request */ | ||
2691 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | ||
2692 | 2983 | ||
2693 | return 0; | 2984 | return 0; |
2694 | } | 2985 | } |
@@ -2720,7 +3011,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
2720 | 3011 | ||
2721 | /* We will only support match on WWPN or WWNN */ | 3012 | /* We will only support match on WWPN or WWNN */ |
2722 | if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) { | 3013 | if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) { |
2723 | return (0); | 3014 | return 0; |
2724 | } | 3015 | } |
2725 | 3016 | ||
2726 | cnt = 0; | 3017 | cnt = 0; |
@@ -2743,9 +3034,10 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
2743 | (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) { | 3034 | (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) { |
2744 | /* Log back into the node before sending the FARP. */ | 3035 | /* Log back into the node before sending the FARP. */ |
2745 | if (fp->Rflags & FARP_REQUEST_PLOGI) { | 3036 | if (fp->Rflags & FARP_REQUEST_PLOGI) { |
3037 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
2746 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 3038 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
2747 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | 3039 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); |
2748 | lpfc_issue_els_plogi(phba, ndlp, 0); | 3040 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); |
2749 | } | 3041 | } |
2750 | 3042 | ||
2751 | /* Send a FARP response to that node */ | 3043 | /* Send a FARP response to that node */ |
@@ -2754,7 +3046,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
2754 | } | 3046 | } |
2755 | } | 3047 | } |
2756 | } | 3048 | } |
2757 | return (0); | 3049 | return 0; |
2758 | } | 3050 | } |
2759 | 3051 | ||
2760 | static int | 3052 | static int |
@@ -2787,47 +3079,89 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba, | |||
2787 | 3079 | ||
2788 | static int | 3080 | static int |
2789 | lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 3081 | lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, |
2790 | struct lpfc_nodelist * ndlp) | 3082 | struct lpfc_nodelist * fan_ndlp) |
2791 | { | 3083 | { |
2792 | struct lpfc_dmabuf *pcmd; | 3084 | struct lpfc_dmabuf *pcmd; |
2793 | uint32_t *lp; | 3085 | uint32_t *lp; |
2794 | IOCB_t *icmd; | 3086 | IOCB_t *icmd; |
2795 | FAN *fp; | ||
2796 | uint32_t cmd, did; | 3087 | uint32_t cmd, did; |
3088 | FAN *fp; | ||
3089 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
3090 | |||
3091 | /* FAN received */ | ||
3092 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:265 FAN received\n", | ||
3093 | phba->brd_no); | ||
2797 | 3094 | ||
2798 | icmd = &cmdiocb->iocb; | 3095 | icmd = &cmdiocb->iocb; |
2799 | did = icmd->un.elsreq64.remoteID; | 3096 | did = icmd->un.elsreq64.remoteID; |
2800 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 3097 | pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; |
2801 | lp = (uint32_t *) pcmd->virt; | 3098 | lp = (uint32_t *)pcmd->virt; |
2802 | 3099 | ||
2803 | cmd = *lp++; | 3100 | cmd = *lp++; |
2804 | fp = (FAN *) lp; | 3101 | fp = (FAN *)lp; |
2805 | 3102 | ||
2806 | /* FAN received */ | 3103 | /* FAN received; Fan does not have a reply sequence */ |
2807 | |||
2808 | /* ACCEPT the FAN request */ | ||
2809 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | ||
2810 | 3104 | ||
2811 | if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { | 3105 | if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { |
2812 | /* The discovery state machine needs to take a different | 3106 | if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, |
2813 | * action if this node has switched fabrics | 3107 | sizeof(struct lpfc_name)) != 0) || |
2814 | */ | 3108 | (memcmp(&phba->fc_fabparam.portName, &fp->FportName, |
2815 | if ((memcmp(&fp->FportName, &phba->fc_fabparam.portName, | 3109 | sizeof(struct lpfc_name)) != 0)) { |
2816 | sizeof (struct lpfc_name)) != 0) | 3110 | /* |
2817 | || | 3111 | * This node has switched fabrics. FLOGI is required |
2818 | (memcmp(&fp->FnodeName, &phba->fc_fabparam.nodeName, | 3112 | * Clean up the old rpi's |
2819 | sizeof (struct lpfc_name)) != 0)) { | ||
2820 | /* This node has switched fabrics. An FLOGI is required | ||
2821 | * after the timeout | ||
2822 | */ | 3113 | */ |
2823 | return (0); | 3114 | |
3115 | list_for_each_entry_safe(ndlp, next_ndlp, | ||
3116 | &phba->fc_npr_list, nlp_listp) { | ||
3117 | |||
3118 | if (ndlp->nlp_type & NLP_FABRIC) { | ||
3119 | /* | ||
3120 | * Clean up old Fabric, Nameserver and | ||
3121 | * other NLP_FABRIC logins | ||
3122 | */ | ||
3123 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | ||
3124 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | ||
3125 | /* Fail outstanding I/O now since this | ||
3126 | * device is marked for PLOGI | ||
3127 | */ | ||
3128 | lpfc_unreg_rpi(phba, ndlp); | ||
3129 | } | ||
3130 | } | ||
3131 | |||
3132 | phba->hba_state = LPFC_FLOGI; | ||
3133 | lpfc_set_disctmo(phba); | ||
3134 | lpfc_initial_flogi(phba); | ||
3135 | return 0; | ||
2824 | } | 3136 | } |
3137 | /* Discovery not needed, | ||
3138 | * move the nodes to their original state. | ||
3139 | */ | ||
3140 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | ||
3141 | nlp_listp) { | ||
2825 | 3142 | ||
2826 | /* Start discovery */ | 3143 | switch (ndlp->nlp_prev_state) { |
3144 | case NLP_STE_UNMAPPED_NODE: | ||
3145 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | ||
3146 | ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; | ||
3147 | lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); | ||
3148 | break; | ||
3149 | |||
3150 | case NLP_STE_MAPPED_NODE: | ||
3151 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | ||
3152 | ndlp->nlp_state = NLP_STE_MAPPED_NODE; | ||
3153 | lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); | ||
3154 | break; | ||
3155 | |||
3156 | default: | ||
3157 | break; | ||
3158 | } | ||
3159 | } | ||
3160 | |||
3161 | /* Start discovery - this should just do CLEAR_LA */ | ||
2827 | lpfc_disc_start(phba); | 3162 | lpfc_disc_start(phba); |
2828 | } | 3163 | } |
2829 | 3164 | return 0; | |
2830 | return (0); | ||
2831 | } | 3165 | } |
2832 | 3166 | ||
2833 | void | 3167 | void |
@@ -2904,8 +3238,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
2904 | 3238 | ||
2905 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { | 3239 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { |
2906 | struct lpfc_nodelist *ndlp; | 3240 | struct lpfc_nodelist *ndlp; |
2907 | 3241 | spin_unlock_irq(phba->host->host_lock); | |
2908 | ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); | 3242 | ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); |
3243 | spin_lock_irq(phba->host->host_lock); | ||
2909 | remote_ID = ndlp->nlp_DID; | 3244 | remote_ID = ndlp->nlp_DID; |
2910 | if (cmd->un.elsreq64.bdl.ulpIoTag32) { | 3245 | if (cmd->un.elsreq64.bdl.ulpIoTag32) { |
2911 | lpfc_sli_issue_abort_iotag32(phba, | 3246 | lpfc_sli_issue_abort_iotag32(phba, |
@@ -2950,7 +3285,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
2950 | struct lpfc_dmabuf *pcmd; | 3285 | struct lpfc_dmabuf *pcmd; |
2951 | uint32_t *elscmd; | 3286 | uint32_t *elscmd; |
2952 | uint32_t els_command; | 3287 | uint32_t els_command; |
2953 | uint32_t remote_ID; | ||
2954 | 3288 | ||
2955 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 3289 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
2956 | spin_lock_irq(phba->host->host_lock); | 3290 | spin_lock_irq(phba->host->host_lock); |
@@ -2973,18 +3307,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
2973 | elscmd = (uint32_t *) (pcmd->virt); | 3307 | elscmd = (uint32_t *) (pcmd->virt); |
2974 | els_command = *elscmd; | 3308 | els_command = *elscmd; |
2975 | 3309 | ||
2976 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { | ||
2977 | struct lpfc_nodelist *ndlp; | ||
2978 | |||
2979 | ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); | ||
2980 | remote_ID = ndlp->nlp_DID; | ||
2981 | if (phba->hba_state == LPFC_HBA_READY) { | ||
2982 | continue; | ||
2983 | } | ||
2984 | } else { | ||
2985 | remote_ID = cmd->un.elsreq64.remoteID; | ||
2986 | } | ||
2987 | |||
2988 | list_del(&piocb->list); | 3310 | list_del(&piocb->list); |
2989 | pring->txcmplq_cnt--; | 3311 | pring->txcmplq_cnt--; |
2990 | 3312 | ||
@@ -2995,8 +3317,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
2995 | spin_unlock_irq(phba->host->host_lock); | 3317 | spin_unlock_irq(phba->host->host_lock); |
2996 | (piocb->iocb_cmpl) (phba, piocb, piocb); | 3318 | (piocb->iocb_cmpl) (phba, piocb, piocb); |
2997 | spin_lock_irq(phba->host->host_lock); | 3319 | spin_lock_irq(phba->host->host_lock); |
2998 | } | 3320 | } else |
2999 | else | ||
3000 | lpfc_sli_release_iocbq(phba, piocb); | 3321 | lpfc_sli_release_iocbq(phba, piocb); |
3001 | } | 3322 | } |
3002 | 3323 | ||
@@ -3010,18 +3331,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3010 | elscmd = (uint32_t *) (pcmd->virt); | 3331 | elscmd = (uint32_t *) (pcmd->virt); |
3011 | els_command = *elscmd; | 3332 | els_command = *elscmd; |
3012 | 3333 | ||
3013 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { | ||
3014 | struct lpfc_nodelist *ndlp; | ||
3015 | |||
3016 | ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); | ||
3017 | remote_ID = ndlp->nlp_DID; | ||
3018 | if (phba->hba_state == LPFC_HBA_READY) { | ||
3019 | continue; | ||
3020 | } | ||
3021 | } else { | ||
3022 | remote_ID = cmd->un.elsreq64.remoteID; | ||
3023 | } | ||
3024 | |||
3025 | list_del(&piocb->list); | 3334 | list_del(&piocb->list); |
3026 | pring->txcmplq_cnt--; | 3335 | pring->txcmplq_cnt--; |
3027 | 3336 | ||
@@ -3032,8 +3341,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3032 | spin_unlock_irq(phba->host->host_lock); | 3341 | spin_unlock_irq(phba->host->host_lock); |
3033 | (piocb->iocb_cmpl) (phba, piocb, piocb); | 3342 | (piocb->iocb_cmpl) (phba, piocb, piocb); |
3034 | spin_lock_irq(phba->host->host_lock); | 3343 | spin_lock_irq(phba->host->host_lock); |
3035 | } | 3344 | } else |
3036 | else | ||
3037 | lpfc_sli_release_iocbq(phba, piocb); | 3345 | lpfc_sli_release_iocbq(phba, piocb); |
3038 | } | 3346 | } |
3039 | spin_unlock_irq(phba->host->host_lock); | 3347 | spin_unlock_irq(phba->host->host_lock); |
@@ -3105,10 +3413,11 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3105 | } | 3413 | } |
3106 | 3414 | ||
3107 | did = icmd->un.rcvels.remoteID; | 3415 | did = icmd->un.rcvels.remoteID; |
3108 | if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) { | 3416 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); |
3417 | if (!ndlp) { | ||
3109 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 3418 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
3110 | if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) | 3419 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
3111 | == 0) { | 3420 | if (!ndlp) { |
3112 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 3421 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
3113 | kfree(mp); | 3422 | kfree(mp); |
3114 | drop_cmd = 1; | 3423 | drop_cmd = 1; |
@@ -3201,10 +3510,6 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3201 | phba->fc_stat.elsRcvFAN++; | 3510 | phba->fc_stat.elsRcvFAN++; |
3202 | lpfc_els_rcv_fan(phba, elsiocb, ndlp); | 3511 | lpfc_els_rcv_fan(phba, elsiocb, ndlp); |
3203 | break; | 3512 | break; |
3204 | case ELS_CMD_RRQ: | ||
3205 | phba->fc_stat.elsRcvRRQ++; | ||
3206 | lpfc_els_rcv_rrq(phba, elsiocb, ndlp); | ||
3207 | break; | ||
3208 | case ELS_CMD_PRLI: | 3513 | case ELS_CMD_PRLI: |
3209 | phba->fc_stat.elsRcvPRLI++; | 3514 | phba->fc_stat.elsRcvPRLI++; |
3210 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3515 | if (phba->hba_state < LPFC_DISC_AUTH) { |
@@ -3213,9 +3518,33 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3213 | } | 3518 | } |
3214 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); | 3519 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); |
3215 | break; | 3520 | break; |
3521 | case ELS_CMD_LIRR: | ||
3522 | phba->fc_stat.elsRcvLIRR++; | ||
3523 | lpfc_els_rcv_lirr(phba, elsiocb, ndlp); | ||
3524 | if (newnode) { | ||
3525 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3526 | } | ||
3527 | break; | ||
3528 | case ELS_CMD_RPS: | ||
3529 | phba->fc_stat.elsRcvRPS++; | ||
3530 | lpfc_els_rcv_rps(phba, elsiocb, ndlp); | ||
3531 | if (newnode) { | ||
3532 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3533 | } | ||
3534 | break; | ||
3535 | case ELS_CMD_RPL: | ||
3536 | phba->fc_stat.elsRcvRPL++; | ||
3537 | lpfc_els_rcv_rpl(phba, elsiocb, ndlp); | ||
3538 | if (newnode) { | ||
3539 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3540 | } | ||
3541 | break; | ||
3216 | case ELS_CMD_RNID: | 3542 | case ELS_CMD_RNID: |
3217 | phba->fc_stat.elsRcvRNID++; | 3543 | phba->fc_stat.elsRcvRNID++; |
3218 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); | 3544 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); |
3545 | if (newnode) { | ||
3546 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3547 | } | ||
3219 | break; | 3548 | break; |
3220 | default: | 3549 | default: |
3221 | /* Unsupported ELS command, reject */ | 3550 | /* Unsupported ELS command, reject */ |
@@ -3249,8 +3578,9 @@ dropit: | |||
3249 | if (drop_cmd == 1) { | 3578 | if (drop_cmd == 1) { |
3250 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 3579 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
3251 | "%d:0111 Dropping received ELS cmd " | 3580 | "%d:0111 Dropping received ELS cmd " |
3252 | "Data: x%x x%x\n", phba->brd_no, | 3581 | "Data: x%x x%x x%x\n", phba->brd_no, |
3253 | icmd->ulpStatus, icmd->un.ulpWord[4]); | 3582 | icmd->ulpStatus, icmd->un.ulpWord[4], |
3583 | icmd->ulpTimeout); | ||
3254 | phba->fc_stat.elsRcvDrop++; | 3584 | phba->fc_stat.elsRcvDrop++; |
3255 | } | 3585 | } |
3256 | return; | 3586 | return; |