diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-05-22 14:52:59 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 12:25:24 -0400 |
commit | 6fb120a7ed882aae9636545142a51cf3182a3ace (patch) | |
tree | 7e830b09907286288f20f60c0f104d5fbec9998d /drivers/scsi/lpfc/lpfc_els.c | |
parent | 04c684968487eb4f98728363a97b8da48f3bb958 (diff) |
[SCSI] lpfc 8.3.2 : Addition of SLI4 Interface - FCOE Discovery support
SLI4 supports both FC and FCOE, with some extended topology objects.
This patch adss support for the objects, and updates the disovery
engines for their use.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 179 |
1 files changed, 156 insertions, 23 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 2c034a554c88..a3b56d7f72f4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -388,6 +388,75 @@ fail: | |||
388 | } | 388 | } |
389 | 389 | ||
390 | /** | 390 | /** |
391 | * lpfc_issue_reg_vfi - Register VFI for this vport's fabric login | ||
392 | * @vport: pointer to a host virtual N_Port data structure. | ||
393 | * | ||
394 | * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for | ||
395 | * the @vport. This mailbox command is necessary for FCoE only. | ||
396 | * | ||
397 | * Return code | ||
398 | * 0 - successfully issued REG_VFI for @vport | ||
399 | * A failure code otherwise. | ||
400 | **/ | ||
401 | static int | ||
402 | lpfc_issue_reg_vfi(struct lpfc_vport *vport) | ||
403 | { | ||
404 | struct lpfc_hba *phba = vport->phba; | ||
405 | LPFC_MBOXQ_t *mboxq; | ||
406 | struct lpfc_nodelist *ndlp; | ||
407 | struct serv_parm *sp; | ||
408 | struct lpfc_dmabuf *dmabuf; | ||
409 | int rc = 0; | ||
410 | |||
411 | sp = &phba->fc_fabparam; | ||
412 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | ||
413 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { | ||
414 | rc = -ENODEV; | ||
415 | goto fail; | ||
416 | } | ||
417 | |||
418 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
419 | if (!dmabuf) { | ||
420 | rc = -ENOMEM; | ||
421 | goto fail; | ||
422 | } | ||
423 | dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys); | ||
424 | if (!dmabuf->virt) { | ||
425 | rc = -ENOMEM; | ||
426 | goto fail_free_dmabuf; | ||
427 | } | ||
428 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
429 | if (!mboxq) { | ||
430 | rc = -ENOMEM; | ||
431 | goto fail_free_coherent; | ||
432 | } | ||
433 | vport->port_state = LPFC_FABRIC_CFG_LINK; | ||
434 | memcpy(dmabuf->virt, &phba->fc_fabparam, sizeof(vport->fc_sparam)); | ||
435 | lpfc_reg_vfi(mboxq, vport, dmabuf->phys); | ||
436 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi; | ||
437 | mboxq->vport = vport; | ||
438 | mboxq->context1 = dmabuf; | ||
439 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
440 | if (rc == MBX_NOT_FINISHED) { | ||
441 | rc = -ENXIO; | ||
442 | goto fail_free_mbox; | ||
443 | } | ||
444 | return 0; | ||
445 | |||
446 | fail_free_mbox: | ||
447 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
448 | fail_free_coherent: | ||
449 | lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); | ||
450 | fail_free_dmabuf: | ||
451 | kfree(dmabuf); | ||
452 | fail: | ||
453 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
454 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
455 | "0289 Issue Register VFI failed: Err %d\n", rc); | ||
456 | return rc; | ||
457 | } | ||
458 | |||
459 | /** | ||
391 | * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port | 460 | * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port |
392 | * @vport: pointer to a host virtual N_Port data structure. | 461 | * @vport: pointer to a host virtual N_Port data structure. |
393 | * @ndlp: pointer to a node-list data structure. | 462 | * @ndlp: pointer to a node-list data structure. |
@@ -499,17 +568,24 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
499 | } | 568 | } |
500 | } | 569 | } |
501 | 570 | ||
502 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE); | 571 | if (phba->sli_rev < LPFC_SLI_REV4) { |
503 | 572 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE); | |
504 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED && | 573 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED && |
505 | vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) { | 574 | vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) |
506 | lpfc_register_new_vport(phba, vport, ndlp); | 575 | lpfc_register_new_vport(phba, vport, ndlp); |
507 | return 0; | 576 | else |
577 | lpfc_issue_fabric_reglogin(vport); | ||
578 | } else { | ||
579 | ndlp->nlp_type |= NLP_FABRIC; | ||
580 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
581 | if (vport->vfi_state & LPFC_VFI_REGISTERED) { | ||
582 | lpfc_start_fdiscs(phba); | ||
583 | lpfc_do_scr_ns_plogi(phba, vport); | ||
584 | } else | ||
585 | lpfc_issue_reg_vfi(vport); | ||
508 | } | 586 | } |
509 | lpfc_issue_fabric_reglogin(vport); | ||
510 | return 0; | 587 | return 0; |
511 | } | 588 | } |
512 | |||
513 | /** | 589 | /** |
514 | * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port | 590 | * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port |
515 | * @vport: pointer to a host virtual N_Port data structure. | 591 | * @vport: pointer to a host virtual N_Port data structure. |
@@ -817,9 +893,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
817 | if (sp->cmn.fcphHigh < FC_PH3) | 893 | if (sp->cmn.fcphHigh < FC_PH3) |
818 | sp->cmn.fcphHigh = FC_PH3; | 894 | sp->cmn.fcphHigh = FC_PH3; |
819 | 895 | ||
820 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 896 | if (phba->sli_rev == LPFC_SLI_REV4) { |
897 | elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1); | ||
898 | elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1); | ||
899 | /* FLOGI needs to be 3 for WQE FCFI */ | ||
900 | /* Set the fcfi to the fcfi we registered with */ | ||
901 | elsiocb->iocb.ulpContext = phba->fcf.fcfi; | ||
902 | } else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | ||
821 | sp->cmn.request_multiple_Nport = 1; | 903 | sp->cmn.request_multiple_Nport = 1; |
822 | |||
823 | /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */ | 904 | /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */ |
824 | icmd->ulpCt_h = 1; | 905 | icmd->ulpCt_h = 1; |
825 | icmd->ulpCt_l = 0; | 906 | icmd->ulpCt_l = 0; |
@@ -932,6 +1013,8 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
932 | if (!ndlp) | 1013 | if (!ndlp) |
933 | return 0; | 1014 | return 0; |
934 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | 1015 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
1016 | /* Set the node type */ | ||
1017 | ndlp->nlp_type |= NLP_FABRIC; | ||
935 | /* Put ndlp onto node list */ | 1018 | /* Put ndlp onto node list */ |
936 | lpfc_enqueue_node(vport, ndlp); | 1019 | lpfc_enqueue_node(vport, ndlp); |
937 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | 1020 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { |
@@ -1604,7 +1687,8 @@ lpfc_adisc_done(struct lpfc_vport *vport) | |||
1604 | * and continue discovery. | 1687 | * and continue discovery. |
1605 | */ | 1688 | */ |
1606 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 1689 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
1607 | !(vport->fc_flag & FC_RSCN_MODE)) { | 1690 | !(vport->fc_flag & FC_RSCN_MODE) && |
1691 | (phba->sli_rev < LPFC_SLI_REV4)) { | ||
1608 | lpfc_issue_reg_vpi(phba, vport); | 1692 | lpfc_issue_reg_vpi(phba, vport); |
1609 | return; | 1693 | return; |
1610 | } | 1694 | } |
@@ -2937,6 +3021,14 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2937 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); | 3021 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); |
2938 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; | 3022 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
2939 | 3023 | ||
3024 | /* | ||
3025 | * This routine is used to register and unregister in previous SLI | ||
3026 | * modes. | ||
3027 | */ | ||
3028 | if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && | ||
3029 | (phba->sli_rev == LPFC_SLI_REV4)) | ||
3030 | lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); | ||
3031 | |||
2940 | pmb->context1 = NULL; | 3032 | pmb->context1 = NULL; |
2941 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 3033 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
2942 | kfree(mp); | 3034 | kfree(mp); |
@@ -3816,7 +3908,9 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) | |||
3816 | payload_len -= sizeof(uint32_t); | 3908 | payload_len -= sizeof(uint32_t); |
3817 | switch (rscn_did.un.b.resv & RSCN_ADDRESS_FORMAT_MASK) { | 3909 | switch (rscn_did.un.b.resv & RSCN_ADDRESS_FORMAT_MASK) { |
3818 | case RSCN_ADDRESS_FORMAT_PORT: | 3910 | case RSCN_ADDRESS_FORMAT_PORT: |
3819 | if (ns_did.un.word == rscn_did.un.word) | 3911 | if ((ns_did.un.b.domain == rscn_did.un.b.domain) |
3912 | && (ns_did.un.b.area == rscn_did.un.b.area) | ||
3913 | && (ns_did.un.b.id == rscn_did.un.b.id)) | ||
3820 | goto return_did_out; | 3914 | goto return_did_out; |
3821 | break; | 3915 | break; |
3822 | case RSCN_ADDRESS_FORMAT_AREA: | 3916 | case RSCN_ADDRESS_FORMAT_AREA: |
@@ -4857,7 +4951,10 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4857 | } else { | 4951 | } else { |
4858 | /* FAN verified - skip FLOGI */ | 4952 | /* FAN verified - skip FLOGI */ |
4859 | vport->fc_myDID = vport->fc_prevDID; | 4953 | vport->fc_myDID = vport->fc_prevDID; |
4860 | lpfc_issue_fabric_reglogin(vport); | 4954 | if (phba->sli_rev < LPFC_SLI_REV4) |
4955 | lpfc_issue_fabric_reglogin(vport); | ||
4956 | else | ||
4957 | lpfc_issue_reg_vfi(vport); | ||
4861 | } | 4958 | } |
4862 | } | 4959 | } |
4863 | return 0; | 4960 | return 0; |
@@ -5540,11 +5637,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
5540 | 5637 | ||
5541 | dropit: | 5638 | dropit: |
5542 | if (vport && !(vport->load_flag & FC_UNLOADING)) | 5639 | if (vport && !(vport->load_flag & FC_UNLOADING)) |
5543 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 5640 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
5544 | "(%d):0111 Dropping received ELS cmd " | 5641 | "0111 Dropping received ELS cmd " |
5545 | "Data: x%x x%x x%x\n", | 5642 | "Data: x%x x%x x%x\n", |
5546 | vport->vpi, icmd->ulpStatus, | 5643 | icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout); |
5547 | icmd->un.ulpWord[4], icmd->ulpTimeout); | ||
5548 | phba->fc_stat.elsRcvDrop++; | 5644 | phba->fc_stat.elsRcvDrop++; |
5549 | } | 5645 | } |
5550 | 5646 | ||
@@ -5620,10 +5716,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
5620 | icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { | 5716 | icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { |
5621 | if (icmd->unsli3.rcvsli3.vpi == 0xffff) | 5717 | if (icmd->unsli3.rcvsli3.vpi == 0xffff) |
5622 | vport = phba->pport; | 5718 | vport = phba->pport; |
5623 | else { | 5719 | else |
5624 | uint16_t vpi = icmd->unsli3.rcvsli3.vpi; | 5720 | vport = lpfc_find_vport_by_vpid(phba, |
5625 | vport = lpfc_find_vport_by_vpid(phba, vpi); | 5721 | icmd->unsli3.rcvsli3.vpi - phba->vpi_base); |
5626 | } | ||
5627 | } | 5722 | } |
5628 | /* If there are no BDEs associated | 5723 | /* If there are no BDEs associated |
5629 | * with this IOCB, there is nothing to do. | 5724 | * with this IOCB, there is nothing to do. |
@@ -5792,7 +5887,10 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5792 | 5887 | ||
5793 | } else { | 5888 | } else { |
5794 | if (vport == phba->pport) | 5889 | if (vport == phba->pport) |
5795 | lpfc_issue_fabric_reglogin(vport); | 5890 | if (phba->sli_rev < LPFC_SLI_REV4) |
5891 | lpfc_issue_fabric_reglogin(vport); | ||
5892 | else | ||
5893 | lpfc_issue_reg_vfi(vport); | ||
5796 | else | 5894 | else |
5797 | lpfc_do_scr_ns_plogi(phba, vport); | 5895 | lpfc_do_scr_ns_plogi(phba, vport); |
5798 | } | 5896 | } |
@@ -5824,7 +5922,7 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, | |||
5824 | 5922 | ||
5825 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 5923 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
5826 | if (mbox) { | 5924 | if (mbox) { |
5827 | lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox); | 5925 | lpfc_reg_vpi(vport, mbox); |
5828 | mbox->vport = vport; | 5926 | mbox->vport = vport; |
5829 | mbox->context2 = lpfc_nlp_get(ndlp); | 5927 | mbox->context2 = lpfc_nlp_get(ndlp); |
5830 | mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; | 5928 | mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; |
@@ -6496,3 +6594,38 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba) | |||
6496 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | 6594 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, |
6497 | IOERR_SLI_ABORTED); | 6595 | IOERR_SLI_ABORTED); |
6498 | } | 6596 | } |
6597 | |||
6598 | /** | ||
6599 | * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort | ||
6600 | * @phba: pointer to lpfc hba data structure. | ||
6601 | * @axri: pointer to the els xri abort wcqe structure. | ||
6602 | * | ||
6603 | * This routine is invoked by the worker thread to process a SLI4 slow-path | ||
6604 | * ELS aborted xri. | ||
6605 | **/ | ||
6606 | void | ||
6607 | lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, | ||
6608 | struct sli4_wcqe_xri_aborted *axri) | ||
6609 | { | ||
6610 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); | ||
6611 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; | ||
6612 | unsigned long iflag = 0; | ||
6613 | |||
6614 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, iflag); | ||
6615 | list_for_each_entry_safe(sglq_entry, sglq_next, | ||
6616 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { | ||
6617 | if (sglq_entry->sli4_xritag == xri) { | ||
6618 | list_del(&sglq_entry->list); | ||
6619 | spin_unlock_irqrestore( | ||
6620 | &phba->sli4_hba.abts_sgl_list_lock, | ||
6621 | iflag); | ||
6622 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
6623 | |||
6624 | list_add_tail(&sglq_entry->list, | ||
6625 | &phba->sli4_hba.lpfc_sgl_list); | ||
6626 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
6627 | return; | ||
6628 | } | ||
6629 | } | ||
6630 | spin_unlock_irqrestore(&phba->sli4_hba.abts_sgl_list_lock, iflag); | ||
6631 | } | ||