diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 125 |
1 files changed, 98 insertions, 27 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 0b662db23284..7afc757338de 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -421,13 +421,13 @@ fail: | |||
421 | * @vport: pointer to a host virtual N_Port data structure. | 421 | * @vport: pointer to a host virtual N_Port data structure. |
422 | * | 422 | * |
423 | * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for | 423 | * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for |
424 | * the @vport. This mailbox command is necessary for FCoE only. | 424 | * the @vport. This mailbox command is necessary for SLI4 port only. |
425 | * | 425 | * |
426 | * Return code | 426 | * Return code |
427 | * 0 - successfully issued REG_VFI for @vport | 427 | * 0 - successfully issued REG_VFI for @vport |
428 | * A failure code otherwise. | 428 | * A failure code otherwise. |
429 | **/ | 429 | **/ |
430 | static int | 430 | int |
431 | lpfc_issue_reg_vfi(struct lpfc_vport *vport) | 431 | lpfc_issue_reg_vfi(struct lpfc_vport *vport) |
432 | { | 432 | { |
433 | struct lpfc_hba *phba = vport->phba; | 433 | struct lpfc_hba *phba = vport->phba; |
@@ -438,10 +438,14 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) | |||
438 | int rc = 0; | 438 | int rc = 0; |
439 | 439 | ||
440 | sp = &phba->fc_fabparam; | 440 | sp = &phba->fc_fabparam; |
441 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 441 | /* move forward in case of SLI4 FC port loopback test */ |
442 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { | 442 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
443 | rc = -ENODEV; | 443 | !(phba->link_flag & LS_LOOPBACK_MODE)) { |
444 | goto fail; | 444 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
445 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { | ||
446 | rc = -ENODEV; | ||
447 | goto fail; | ||
448 | } | ||
445 | } | 449 | } |
446 | 450 | ||
447 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 451 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
@@ -487,6 +491,54 @@ fail: | |||
487 | } | 491 | } |
488 | 492 | ||
489 | /** | 493 | /** |
494 | * lpfc_issue_unreg_vfi - Unregister VFI for this vport's fabric login | ||
495 | * @vport: pointer to a host virtual N_Port data structure. | ||
496 | * | ||
497 | * This routine issues a UNREG_VFI mailbox with the vfi, vpi, fcfi triplet for | ||
498 | * the @vport. This mailbox command is necessary for SLI4 port only. | ||
499 | * | ||
500 | * Return code | ||
501 | * 0 - successfully issued REG_VFI for @vport | ||
502 | * A failure code otherwise. | ||
503 | **/ | ||
504 | int | ||
505 | lpfc_issue_unreg_vfi(struct lpfc_vport *vport) | ||
506 | { | ||
507 | struct lpfc_hba *phba = vport->phba; | ||
508 | struct Scsi_Host *shost; | ||
509 | LPFC_MBOXQ_t *mboxq; | ||
510 | int rc; | ||
511 | |||
512 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
513 | if (!mboxq) { | ||
514 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, | ||
515 | "2556 UNREG_VFI mbox allocation failed" | ||
516 | "HBA state x%x\n", phba->pport->port_state); | ||
517 | return -ENOMEM; | ||
518 | } | ||
519 | |||
520 | lpfc_unreg_vfi(mboxq, vport); | ||
521 | mboxq->vport = vport; | ||
522 | mboxq->mbox_cmpl = lpfc_unregister_vfi_cmpl; | ||
523 | |||
524 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
525 | if (rc == MBX_NOT_FINISHED) { | ||
526 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, | ||
527 | "2557 UNREG_VFI issue mbox failed rc x%x " | ||
528 | "HBA state x%x\n", | ||
529 | rc, phba->pport->port_state); | ||
530 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
531 | return -EIO; | ||
532 | } | ||
533 | |||
534 | shost = lpfc_shost_from_vport(vport); | ||
535 | spin_lock_irq(shost->host_lock); | ||
536 | vport->fc_flag &= ~FC_VFI_REGISTERED; | ||
537 | spin_unlock_irq(shost->host_lock); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | /** | ||
490 | * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean. | 542 | * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean. |
491 | * @vport: pointer to a host virtual N_Port data structure. | 543 | * @vport: pointer to a host virtual N_Port data structure. |
492 | * @sp: pointer to service parameter data structure. | 544 | * @sp: pointer to service parameter data structure. |
@@ -615,7 +667,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
615 | "1816 FLOGI NPIV supported, " | 667 | "1816 FLOGI NPIV supported, " |
616 | "response data 0x%x\n", | 668 | "response data 0x%x\n", |
617 | sp->cmn.response_multiple_NPort); | 669 | sp->cmn.response_multiple_NPort); |
670 | spin_lock_irq(&phba->hbalock); | ||
618 | phba->link_flag |= LS_NPIV_FAB_SUPPORTED; | 671 | phba->link_flag |= LS_NPIV_FAB_SUPPORTED; |
672 | spin_unlock_irq(&phba->hbalock); | ||
619 | } else { | 673 | } else { |
620 | /* Because we asked f/w for NPIV it still expects us | 674 | /* Because we asked f/w for NPIV it still expects us |
621 | to call reg_vnpid atleast for the physcial host */ | 675 | to call reg_vnpid atleast for the physcial host */ |
@@ -623,7 +677,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
623 | LOG_ELS | LOG_VPORT, | 677 | LOG_ELS | LOG_VPORT, |
624 | "1817 Fabric does not support NPIV " | 678 | "1817 Fabric does not support NPIV " |
625 | "- configuring single port mode.\n"); | 679 | "- configuring single port mode.\n"); |
680 | spin_lock_irq(&phba->hbalock); | ||
626 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; | 681 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; |
682 | spin_unlock_irq(&phba->hbalock); | ||
627 | } | 683 | } |
628 | } | 684 | } |
629 | 685 | ||
@@ -686,11 +742,16 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
686 | lpfc_do_scr_ns_plogi(phba, vport); | 742 | lpfc_do_scr_ns_plogi(phba, vport); |
687 | } else if (vport->fc_flag & FC_VFI_REGISTERED) | 743 | } else if (vport->fc_flag & FC_VFI_REGISTERED) |
688 | lpfc_issue_init_vpi(vport); | 744 | lpfc_issue_init_vpi(vport); |
689 | else | 745 | else { |
746 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
747 | "3135 Need register VFI: (x%x/%x)\n", | ||
748 | vport->fc_prevDID, vport->fc_myDID); | ||
690 | lpfc_issue_reg_vfi(vport); | 749 | lpfc_issue_reg_vfi(vport); |
750 | } | ||
691 | } | 751 | } |
692 | return 0; | 752 | return 0; |
693 | } | 753 | } |
754 | |||
694 | /** | 755 | /** |
695 | * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port | 756 | * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port |
696 | * @vport: pointer to a host virtual N_Port data structure. | 757 | * @vport: pointer to a host virtual N_Port data structure. |
@@ -907,9 +968,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
907 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no | 968 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no |
908 | * alpa map would take too long otherwise. | 969 | * alpa map would take too long otherwise. |
909 | */ | 970 | */ |
910 | if (phba->alpa_map[0] == 0) { | 971 | if (phba->alpa_map[0] == 0) |
911 | vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; | 972 | vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; |
912 | } | ||
913 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 973 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
914 | (!(vport->fc_flag & FC_VFI_REGISTERED) || | 974 | (!(vport->fc_flag & FC_VFI_REGISTERED) || |
915 | (vport->fc_prevDID != vport->fc_myDID))) { | 975 | (vport->fc_prevDID != vport->fc_myDID))) { |
@@ -1164,8 +1224,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) | |||
1164 | spin_lock_irq(&phba->hbalock); | 1224 | spin_lock_irq(&phba->hbalock); |
1165 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 1225 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
1166 | icmd = &iocb->iocb; | 1226 | icmd = &iocb->iocb; |
1167 | if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR && | 1227 | if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { |
1168 | icmd->un.elsreq64.bdl.ulpIoTag32) { | ||
1169 | ndlp = (struct lpfc_nodelist *)(iocb->context1); | 1228 | ndlp = (struct lpfc_nodelist *)(iocb->context1); |
1170 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) && | 1229 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) && |
1171 | (ndlp->nlp_DID == Fabric_DID)) | 1230 | (ndlp->nlp_DID == Fabric_DID)) |
@@ -4879,23 +4938,31 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4879 | sizeof(struct lpfc_name)); | 4938 | sizeof(struct lpfc_name)); |
4880 | 4939 | ||
4881 | if (!rc) { | 4940 | if (!rc) { |
4882 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4941 | if (phba->sli_rev < LPFC_SLI_REV4) { |
4883 | if (!mbox) | 4942 | mbox = mempool_alloc(phba->mbox_mem_pool, |
4943 | GFP_KERNEL); | ||
4944 | if (!mbox) | ||
4945 | return 1; | ||
4946 | lpfc_linkdown(phba); | ||
4947 | lpfc_init_link(phba, mbox, | ||
4948 | phba->cfg_topology, | ||
4949 | phba->cfg_link_speed); | ||
4950 | mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; | ||
4951 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
4952 | mbox->vport = vport; | ||
4953 | rc = lpfc_sli_issue_mbox(phba, mbox, | ||
4954 | MBX_NOWAIT); | ||
4955 | lpfc_set_loopback_flag(phba); | ||
4956 | if (rc == MBX_NOT_FINISHED) | ||
4957 | mempool_free(mbox, phba->mbox_mem_pool); | ||
4884 | return 1; | 4958 | return 1; |
4885 | 4959 | } else { | |
4886 | lpfc_linkdown(phba); | 4960 | /* abort the flogi coming back to ourselves |
4887 | lpfc_init_link(phba, mbox, | 4961 | * due to external loopback on the port. |
4888 | phba->cfg_topology, | 4962 | */ |
4889 | phba->cfg_link_speed); | 4963 | lpfc_els_abort_flogi(phba); |
4890 | mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; | 4964 | return 0; |
4891 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
4892 | mbox->vport = vport; | ||
4893 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | ||
4894 | lpfc_set_loopback_flag(phba); | ||
4895 | if (rc == MBX_NOT_FINISHED) { | ||
4896 | mempool_free(mbox, phba->mbox_mem_pool); | ||
4897 | } | 4965 | } |
4898 | return 1; | ||
4899 | } else if (rc > 0) { /* greater than */ | 4966 | } else if (rc > 0) { /* greater than */ |
4900 | spin_lock_irq(shost->host_lock); | 4967 | spin_lock_irq(shost->host_lock); |
4901 | vport->fc_flag |= FC_PT2PT_PLOGI; | 4968 | vport->fc_flag |= FC_PT2PT_PLOGI; |
@@ -5850,8 +5917,12 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
5850 | vport->fc_myDID = vport->fc_prevDID; | 5917 | vport->fc_myDID = vport->fc_prevDID; |
5851 | if (phba->sli_rev < LPFC_SLI_REV4) | 5918 | if (phba->sli_rev < LPFC_SLI_REV4) |
5852 | lpfc_issue_fabric_reglogin(vport); | 5919 | lpfc_issue_fabric_reglogin(vport); |
5853 | else | 5920 | else { |
5921 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
5922 | "3138 Need register VFI: (x%x/%x)\n", | ||
5923 | vport->fc_prevDID, vport->fc_myDID); | ||
5854 | lpfc_issue_reg_vfi(vport); | 5924 | lpfc_issue_reg_vfi(vport); |
5925 | } | ||
5855 | } | 5926 | } |
5856 | } | 5927 | } |
5857 | return 0; | 5928 | return 0; |