Commit 939723a4 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.31: Correct point-to-point mode discovery errors on LPe16xxx

Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 27aa1b73
...@@ -230,27 +230,43 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, ...@@ -230,27 +230,43 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
INIT_LIST_HEAD(&pbuflist->list); INIT_LIST_HEAD(&pbuflist->list);
icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.elsreq64.remoteID = did; /* DID */
if (expectRsp) { if (expectRsp) {
icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
icmd->un.elsreq64.remoteID = did; /* DID */
icmd->ulpCommand = CMD_ELS_REQUEST64_CR; icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
icmd->ulpTimeout = phba->fc_ratov * 2; icmd->ulpTimeout = phba->fc_ratov * 2;
} else { } else {
icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64); icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.xseq64.bdl.bdeSize = sizeof(struct ulp_bde64);
icmd->un.xseq64.xmit_els_remoteID = did; /* DID */
icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
} }
icmd->ulpBdeCount = 1; icmd->ulpBdeCount = 1;
icmd->ulpLe = 1; icmd->ulpLe = 1;
icmd->ulpClass = CLASS3; icmd->ulpClass = CLASS3;
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { /*
icmd->un.elsreq64.myID = vport->fc_myDID; * If we have NPIV enabled, we want to send ELS traffic by VPI.
* For SLI4, since the driver controls VPIs we also want to include
* all ELS pt2pt protocol traffic as well.
*/
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) ||
((phba->sli_rev == LPFC_SLI_REV4) &&
(vport->fc_flag & FC_PT2PT))) {
if (expectRsp) {
icmd->un.elsreq64.myID = vport->fc_myDID;
/* For ELS_REQUEST64_CR, use the VPI by default */
icmd->ulpContext = phba->vpi_ids[vport->vpi];
}
/* For ELS_REQUEST64_CR, use the VPI by default */
icmd->ulpContext = phba->vpi_ids[vport->vpi];
icmd->ulpCt_h = 0; icmd->ulpCt_h = 0;
/* The CT field must be 0=INVALID_RPI for the ECHO cmd */ /* The CT field must be 0=INVALID_RPI for the ECHO cmd */
if (elscmd == ELS_CMD_ECHO) if (elscmd == ELS_CMD_ECHO)
...@@ -438,9 +454,10 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) ...@@ -438,9 +454,10 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
int rc = 0; int rc = 0;
sp = &phba->fc_fabparam; sp = &phba->fc_fabparam;
/* move forward in case of SLI4 FC port loopback test */ /* move forward in case of SLI4 FC port loopback test and pt2pt mode */
if ((phba->sli_rev == LPFC_SLI_REV4) && if ((phba->sli_rev == LPFC_SLI_REV4) &&
!(phba->link_flag & LS_LOOPBACK_MODE)) { !(phba->link_flag & LS_LOOPBACK_MODE) &&
!(vport->fc_flag & FC_PT2PT)) {
ndlp = lpfc_findnode_did(vport, Fabric_DID); ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
rc = -ENODEV; rc = -ENODEV;
...@@ -820,6 +837,17 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -820,6 +837,17 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
goto fail; goto fail;
} }
/*
* For SLI4, the VFI/VPI are registered AFTER the
* Nport with the higher WWPN sends the PLOGI with
* an assigned NPortId.
*/
/* not equal */
if ((phba->sli_rev == LPFC_SLI_REV4) && rc)
lpfc_issue_reg_vfi(vport);
/* Decrement ndlp reference count indicating that ndlp can be /* Decrement ndlp reference count indicating that ndlp can be
* safely released when other references to it are done. * safely released when other references to it are done.
*/ */
...@@ -4940,8 +4968,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -4940,8 +4968,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 1; return 1;
} }
did = Fabric_DID;
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) { if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
/* For a FLOGI we accept, then if our portname is greater /* For a FLOGI we accept, then if our portname is greater
* then the remote portname we initiate Nport login. * then the remote portname we initiate Nport login.
...@@ -4980,29 +5006,64 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -4980,29 +5006,64 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT_PLOGI; vport->fc_flag |= FC_PT2PT_PLOGI;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
/* If we have the high WWPN we can assign our own
* myDID; otherwise, we have to WAIT for a PLOGI
* from the remote NPort to find out what it
* will be.
*/
vport->fc_myDID = PT2PT_LocalID; vport->fc_myDID = PT2PT_LocalID;
} else }
vport->fc_myDID = PT2PT_RemoteID;
vport->port_state = LPFC_FLOGI; /*
* The vport state should go to LPFC_FLOGI only
* AFTER we issue a FLOGI, not receive one.
*/
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT; vport->fc_flag |= FC_PT2PT;
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
/*
* We temporarily set fc_myDID to make it look like we are
* a Fabric. This is done just so we end up with the right
* did / sid on the FLOGI ACC rsp.
*/
did = vport->fc_myDID;
vport->fc_myDID = Fabric_DID;
} else { } else {
/* Reject this request because invalid parameters */ /* Reject this request because invalid parameters */
stat.un.b.lsRjtRsvd0 = 0; stat.un.b.lsRjtRsvd0 = 0;
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
stat.un.b.vendorUnique = 0; stat.un.b.vendorUnique = 0;
/*
* We temporarily set fc_myDID to make it look like we are
* a Fabric. This is done just so we end up with the right
* did / sid on the FLOGI LS_RJT rsp.
*/
did = vport->fc_myDID;
vport->fc_myDID = Fabric_DID;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
NULL); NULL);
/* Now lets put fc_myDID back to what its supposed to be */
vport->fc_myDID = did;
return 1; return 1;
} }
/* Send back ACC */ /* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
/* Now lets put fc_myDID back to what its supposed to be */
vport->fc_myDID = did;
if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) if (!mbox)
goto fail; goto fail;
......
...@@ -2882,9 +2882,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) ...@@ -2882,9 +2882,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
} }
if (vport->port_state == LPFC_FABRIC_CFG_LINK) { if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
/* For private loop just start discovery and we are done. */ /*
if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && * For private loop or for NPort pt2pt,
!(vport->fc_flag & FC_PUBLIC_LOOP)) { * just start discovery and we are done.
*/
if ((vport->fc_flag & FC_PT2PT) ||
((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
!(vport->fc_flag & FC_PUBLIC_LOOP))) {
/* Use loop map to make discovery list */ /* Use loop map to make discovery list */
lpfc_disc_list_loopmap(vport); lpfc_disc_list_loopmap(vport);
/* Start discovery */ /* Start discovery */
...@@ -5491,9 +5496,9 @@ lpfc_nlp_release(struct kref *kref) ...@@ -5491,9 +5496,9 @@ lpfc_nlp_release(struct kref *kref)
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
"0279 lpfc_nlp_release: ndlp:x%p " "0279 lpfc_nlp_release: ndlp:x%p did %x "
"usgmap:x%x refcnt:%d\n", "usgmap:x%x refcnt:%d\n",
(void *)ndlp, ndlp->nlp_usg_map, (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map,
atomic_read(&ndlp->kref.refcount)); atomic_read(&ndlp->kref.refcount));
/* remove ndlp from action. */ /* remove ndlp from action. */
......
...@@ -3374,6 +3374,9 @@ typedef struct { ...@@ -3374,6 +3374,9 @@ typedef struct {
WORD5 w5; /* Header control/status word */ WORD5 w5; /* Header control/status word */
} XMT_SEQ_FIELDS64; } XMT_SEQ_FIELDS64;
/* This word is remote ports D_ID for XMIT_ELS_RSP64 */
#define xmit_els_remoteID xrsqRo
/* IOCB Command template for 64 bit RCV_SEQUENCE64 */ /* IOCB Command template for 64 bit RCV_SEQUENCE64 */
typedef struct { typedef struct {
struct ulp_bde64 rcvBde; struct ulp_bde64 rcvBde;
......
...@@ -3295,7 +3295,13 @@ struct els_request64_wqe { ...@@ -3295,7 +3295,13 @@ struct els_request64_wqe {
struct xmit_els_rsp64_wqe { struct xmit_els_rsp64_wqe {
struct ulp_bde64 bde; struct ulp_bde64 bde;
uint32_t response_payload_len; uint32_t response_payload_len;
uint32_t rsvd4; uint32_t word4;
#define els_rsp64_sid_SHIFT 0
#define els_rsp64_sid_MASK 0x00FFFFFF
#define els_rsp64_sid_WORD word4
#define els_rsp64_sp_SHIFT 24
#define els_rsp64_sp_MASK 0x00000001
#define els_rsp64_sp_WORD word4
struct wqe_did wqe_dest; struct wqe_did wqe_dest;
struct wqe_common wqe_com; /* words 6-11 */ struct wqe_common wqe_com; /* words 6-11 */
uint32_t word12; uint32_t word12;
......
...@@ -367,8 +367,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -367,8 +367,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 1; return 1;
} }
/* Check for Nport to NPort pt2pt protocol */
if ((vport->fc_flag & FC_PT2PT) && if ((vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_PT2PT_PLOGI)) { !(vport->fc_flag & FC_PT2PT_PLOGI)) {
/* rcv'ed PLOGI decides what our NPortId will be */ /* rcv'ed PLOGI decides what our NPortId will be */
vport->fc_myDID = icmd->un.rcvels.parmRo; vport->fc_myDID = icmd->un.rcvels.parmRo;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
...@@ -382,6 +384,13 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -382,6 +384,13 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
goto out; goto out;
} }
/*
* For SLI4, the VFI/VPI are registered AFTER the
* Nport with the higher WWPN sends us a PLOGI with
* our assigned NPortId.
*/
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_issue_reg_vfi(vport);
lpfc_can_disctmo(vport); lpfc_can_disctmo(vport);
} }
......
...@@ -7907,6 +7907,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ...@@ -7907,6 +7907,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(els_req64_sp, &wqe->els_req, 1); bf_set(els_req64_sp, &wqe->els_req, 1);
bf_set(els_req64_sid, &wqe->els_req, bf_set(els_req64_sid, &wqe->els_req,
iocbq->vport->fc_myDID); iocbq->vport->fc_myDID);
if ((*pcmd == ELS_CMD_FLOGI) &&
!(phba->fc_topology ==
LPFC_TOPOLOGY_LOOP))
bf_set(els_req64_sid, &wqe->els_req, 0);
bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
phba->vpi_ids[iocbq->vport->vpi]); phba->vpi_ids[iocbq->vport->vpi]);
...@@ -8064,11 +8068,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ...@@ -8064,11 +8068,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
/* words0-2 BDE memcpy */ /* words0-2 BDE memcpy */
/* word3 iocb=iotag32 wqe=response_payload_len */ /* word3 iocb=iotag32 wqe=response_payload_len */
wqe->xmit_els_rsp.response_payload_len = xmit_len; wqe->xmit_els_rsp.response_payload_len = xmit_len;
/* word4 iocb=did wge=rsvd. */ /* word4 */
wqe->xmit_els_rsp.rsvd4 = 0; wqe->xmit_els_rsp.word4 = 0;
/* word5 iocb=rsvd wge=did */ /* word5 iocb=rsvd wge=did */
bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest,
iocbq->iocb.un.elsreq64.remoteID); iocbq->iocb.un.xseq64.xmit_els_remoteID);
if_type = bf_get(lpfc_sli_intf_if_type,
&phba->sli4_hba.sli_intf);
if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
if (iocbq->vport->fc_flag & FC_PT2PT) {
bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
iocbq->vport->fc_myDID);
if (iocbq->vport->fc_myDID == Fabric_DID) {
bf_set(wqe_els_did,
&wqe->xmit_els_rsp.wqe_dest, 0);
}
}
}
bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com,
((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l));
bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU);
...@@ -8088,11 +8106,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ...@@ -8088,11 +8106,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
pcmd = (uint32_t *) (((struct lpfc_dmabuf *) pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
iocbq->context2)->virt); iocbq->context2)->virt);
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
bf_set(els_req64_sp, &wqe->els_req, 1); bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
bf_set(els_req64_sid, &wqe->els_req, bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
iocbq->vport->fc_myDID); iocbq->vport->fc_myDID);
bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1);
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com,
phba->vpi_ids[phba->pport->vpi]); phba->vpi_ids[phba->pport->vpi]);
} }
command_type = OTHER_COMMAND; command_type = OTHER_COMMAND;
...@@ -13636,8 +13654,13 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr, ...@@ -13636,8 +13654,13 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr,
uint32_t did = (fc_hdr->fh_d_id[0] << 16 | uint32_t did = (fc_hdr->fh_d_id[0] << 16 |
fc_hdr->fh_d_id[1] << 8 | fc_hdr->fh_d_id[1] << 8 |
fc_hdr->fh_d_id[2]); fc_hdr->fh_d_id[2]);
if (did == Fabric_DID) if (did == Fabric_DID)
return phba->pport; return phba->pport;
if ((phba->pport->fc_flag & FC_PT2PT) &&
!(phba->link_state == LPFC_HBA_READY))
return phba->pport;
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
...@@ -14174,7 +14197,15 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) ...@@ -14174,7 +14197,15 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
/* Initialize the first IOCB. */ /* Initialize the first IOCB. */
first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0; first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0;
first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS;
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
/* Check FC Header to see what TYPE of frame we are rcv'ing */
if (sli4_type_from_fc_hdr(fc_hdr) == FC_TYPE_ELS) {
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_ELS64_CX;
first_iocbq->iocb.un.rcvels.parmRo =
sli4_did_from_fc_hdr(fc_hdr);
first_iocbq->iocb.ulpPU = PARM_NPIV_DID;
} else
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
first_iocbq->iocb.ulpContext = NO_XRI; first_iocbq->iocb.ulpContext = NO_XRI;
first_iocbq->iocb.unsli3.rcvsli3.ox_id = first_iocbq->iocb.unsli3.rcvsli3.ox_id =
be16_to_cpu(fc_hdr->fh_ox_id); be16_to_cpu(fc_hdr->fh_ox_id);
...@@ -14304,6 +14335,7 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, ...@@ -14304,6 +14335,7 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
struct fc_frame_header *fc_hdr; struct fc_frame_header *fc_hdr;
struct lpfc_vport *vport; struct lpfc_vport *vport;
uint32_t fcfi; uint32_t fcfi;
uint32_t did;
/* Process each received buffer */ /* Process each received buffer */
fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
...@@ -14319,12 +14351,32 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, ...@@ -14319,12 +14351,32 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
else else
fcfi = bf_get(lpfc_rcqe_fcf_id, fcfi = bf_get(lpfc_rcqe_fcf_id,
&dmabuf->cq_event.cqe.rcqe_cmpl); &dmabuf->cq_event.cqe.rcqe_cmpl);
vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi); vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi);
if (!vport || !(vport->vpi_state & LPFC_VPI_REGISTERED)) { if (!vport) {
/* throw out the frame */ /* throw out the frame */
lpfc_in_buf_free(phba, &dmabuf->dbuf); lpfc_in_buf_free(phba, &dmabuf->dbuf);
return; return;
} }
/* d_id this frame is directed to */
did = sli4_did_from_fc_hdr(fc_hdr);
/* vport is registered unless we rcv a FLOGI directed to Fabric_DID */
if (!(vport->vpi_state & LPFC_VPI_REGISTERED) &&
(did != Fabric_DID)) {
/*
* Throw out the frame if we are not pt2pt.
* The pt2pt protocol allows for discovery frames
* to be received without a registered VPI.
*/
if (!(vport->fc_flag & FC_PT2PT) ||
(phba->link_state == LPFC_HBA_READY)) {
lpfc_in_buf_free(phba, &dmabuf->dbuf);
return;
}
}
/* Handle the basic abort sequence (BA_ABTS) event */ /* Handle the basic abort sequence (BA_ABTS) event */
if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) { if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) {
lpfc_sli4_handle_unsol_abort(vport, dmabuf); lpfc_sli4_handle_unsol_abort(vport, dmabuf);
......
...@@ -75,11 +75,19 @@ ...@@ -75,11 +75,19 @@
(fc_hdr)->fh_s_id[1] << 8 | \ (fc_hdr)->fh_s_id[1] << 8 | \
(fc_hdr)->fh_s_id[2]) (fc_hdr)->fh_s_id[2])
#define sli4_did_from_fc_hdr(fc_hdr) \
((fc_hdr)->fh_d_id[0] << 16 | \
(fc_hdr)->fh_d_id[1] << 8 | \
(fc_hdr)->fh_d_id[2])
#define sli4_fctl_from_fc_hdr(fc_hdr) \ #define sli4_fctl_from_fc_hdr(fc_hdr) \
((fc_hdr)->fh_f_ctl[0] << 16 | \ ((fc_hdr)->fh_f_ctl[0] << 16 | \
(fc_hdr)->fh_f_ctl[1] << 8 | \ (fc_hdr)->fh_f_ctl[1] << 8 | \
(fc_hdr)->fh_f_ctl[2]) (fc_hdr)->fh_f_ctl[2])
#define sli4_type_from_fc_hdr(fc_hdr) \
((fc_hdr)->fh_type)
#define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000 #define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
enum lpfc_sli4_queue_type { enum lpfc_sli4_queue_type {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment