diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 93 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 15 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 70 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 8 |
7 files changed, 175 insertions, 31 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 95cff9909eff..379397d17aca 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -230,27 +230,43 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
230 | 230 | ||
231 | INIT_LIST_HEAD(&pbuflist->list); | 231 | INIT_LIST_HEAD(&pbuflist->list); |
232 | 232 | ||
233 | icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); | ||
234 | icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys); | ||
235 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; | ||
236 | icmd->un.elsreq64.remoteID = did; /* DID */ | ||
237 | if (expectRsp) { | 233 | if (expectRsp) { |
234 | icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); | ||
235 | icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys); | ||
236 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; | ||
238 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); | 237 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); |
238 | |||
239 | icmd->un.elsreq64.remoteID = did; /* DID */ | ||
239 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; | 240 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; |
240 | icmd->ulpTimeout = phba->fc_ratov * 2; | 241 | icmd->ulpTimeout = phba->fc_ratov * 2; |
241 | } else { | 242 | } else { |
242 | icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64); | 243 | icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); |
244 | icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys); | ||
245 | icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; | ||
246 | icmd->un.xseq64.bdl.bdeSize = sizeof(struct ulp_bde64); | ||
247 | icmd->un.xseq64.xmit_els_remoteID = did; /* DID */ | ||
243 | icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; | 248 | icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; |
244 | } | 249 | } |
245 | icmd->ulpBdeCount = 1; | 250 | icmd->ulpBdeCount = 1; |
246 | icmd->ulpLe = 1; | 251 | icmd->ulpLe = 1; |
247 | icmd->ulpClass = CLASS3; | 252 | icmd->ulpClass = CLASS3; |
248 | 253 | ||
249 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 254 | /* |
250 | icmd->un.elsreq64.myID = vport->fc_myDID; | 255 | * If we have NPIV enabled, we want to send ELS traffic by VPI. |
256 | * For SLI4, since the driver controls VPIs we also want to include | ||
257 | * all ELS pt2pt protocol traffic as well. | ||
258 | */ | ||
259 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) || | ||
260 | ((phba->sli_rev == LPFC_SLI_REV4) && | ||
261 | (vport->fc_flag & FC_PT2PT))) { | ||
262 | |||
263 | if (expectRsp) { | ||
264 | icmd->un.elsreq64.myID = vport->fc_myDID; | ||
265 | |||
266 | /* For ELS_REQUEST64_CR, use the VPI by default */ | ||
267 | icmd->ulpContext = phba->vpi_ids[vport->vpi]; | ||
268 | } | ||
251 | 269 | ||
252 | /* For ELS_REQUEST64_CR, use the VPI by default */ | ||
253 | icmd->ulpContext = phba->vpi_ids[vport->vpi]; | ||
254 | icmd->ulpCt_h = 0; | 270 | icmd->ulpCt_h = 0; |
255 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ | 271 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ |
256 | if (elscmd == ELS_CMD_ECHO) | 272 | if (elscmd == ELS_CMD_ECHO) |
@@ -438,9 +454,10 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) | |||
438 | int rc = 0; | 454 | int rc = 0; |
439 | 455 | ||
440 | sp = &phba->fc_fabparam; | 456 | sp = &phba->fc_fabparam; |
441 | /* move forward in case of SLI4 FC port loopback test */ | 457 | /* move forward in case of SLI4 FC port loopback test and pt2pt mode */ |
442 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 458 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
443 | !(phba->link_flag & LS_LOOPBACK_MODE)) { | 459 | !(phba->link_flag & LS_LOOPBACK_MODE) && |
460 | !(vport->fc_flag & FC_PT2PT)) { | ||
444 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 461 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
445 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { | 462 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
446 | rc = -ENODEV; | 463 | rc = -ENODEV; |
@@ -820,6 +837,17 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
820 | mempool_free(mbox, phba->mbox_mem_pool); | 837 | mempool_free(mbox, phba->mbox_mem_pool); |
821 | goto fail; | 838 | goto fail; |
822 | } | 839 | } |
840 | |||
841 | /* | ||
842 | * For SLI4, the VFI/VPI are registered AFTER the | ||
843 | * Nport with the higher WWPN sends the PLOGI with | ||
844 | * an assigned NPortId. | ||
845 | */ | ||
846 | |||
847 | /* not equal */ | ||
848 | if ((phba->sli_rev == LPFC_SLI_REV4) && rc) | ||
849 | lpfc_issue_reg_vfi(vport); | ||
850 | |||
823 | /* Decrement ndlp reference count indicating that ndlp can be | 851 | /* Decrement ndlp reference count indicating that ndlp can be |
824 | * safely released when other references to it are done. | 852 | * safely released when other references to it are done. |
825 | */ | 853 | */ |
@@ -4940,8 +4968,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4940 | return 1; | 4968 | return 1; |
4941 | } | 4969 | } |
4942 | 4970 | ||
4943 | did = Fabric_DID; | ||
4944 | |||
4945 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) { | 4971 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) { |
4946 | /* For a FLOGI we accept, then if our portname is greater | 4972 | /* For a FLOGI we accept, then if our portname is greater |
4947 | * then the remote portname we initiate Nport login. | 4973 | * 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 | spin_lock_irq(shost->host_lock); | 5006 | spin_lock_irq(shost->host_lock); |
4981 | vport->fc_flag |= FC_PT2PT_PLOGI; | 5007 | vport->fc_flag |= FC_PT2PT_PLOGI; |
4982 | spin_unlock_irq(shost->host_lock); | 5008 | spin_unlock_irq(shost->host_lock); |
5009 | |||
5010 | /* If we have the high WWPN we can assign our own | ||
5011 | * myDID; otherwise, we have to WAIT for a PLOGI | ||
5012 | * from the remote NPort to find out what it | ||
5013 | * will be. | ||
5014 | */ | ||
4983 | vport->fc_myDID = PT2PT_LocalID; | 5015 | vport->fc_myDID = PT2PT_LocalID; |
4984 | } else | 5016 | } |
4985 | vport->fc_myDID = PT2PT_RemoteID; | 5017 | |
4986 | vport->port_state = LPFC_FLOGI; | 5018 | /* |
5019 | * The vport state should go to LPFC_FLOGI only | ||
5020 | * AFTER we issue a FLOGI, not receive one. | ||
5021 | */ | ||
4987 | spin_lock_irq(shost->host_lock); | 5022 | spin_lock_irq(shost->host_lock); |
4988 | vport->fc_flag |= FC_PT2PT; | 5023 | vport->fc_flag |= FC_PT2PT; |
4989 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 5024 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
4990 | spin_unlock_irq(shost->host_lock); | 5025 | spin_unlock_irq(shost->host_lock); |
5026 | |||
5027 | /* | ||
5028 | * We temporarily set fc_myDID to make it look like we are | ||
5029 | * a Fabric. This is done just so we end up with the right | ||
5030 | * did / sid on the FLOGI ACC rsp. | ||
5031 | */ | ||
5032 | did = vport->fc_myDID; | ||
5033 | vport->fc_myDID = Fabric_DID; | ||
5034 | |||
4991 | } else { | 5035 | } else { |
4992 | /* Reject this request because invalid parameters */ | 5036 | /* Reject this request because invalid parameters */ |
4993 | stat.un.b.lsRjtRsvd0 = 0; | 5037 | stat.un.b.lsRjtRsvd0 = 0; |
4994 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 5038 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
4995 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 5039 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
4996 | stat.un.b.vendorUnique = 0; | 5040 | stat.un.b.vendorUnique = 0; |
5041 | |||
5042 | /* | ||
5043 | * We temporarily set fc_myDID to make it look like we are | ||
5044 | * a Fabric. This is done just so we end up with the right | ||
5045 | * did / sid on the FLOGI LS_RJT rsp. | ||
5046 | */ | ||
5047 | did = vport->fc_myDID; | ||
5048 | vport->fc_myDID = Fabric_DID; | ||
5049 | |||
4997 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, | 5050 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
4998 | NULL); | 5051 | NULL); |
5052 | |||
5053 | /* Now lets put fc_myDID back to what its supposed to be */ | ||
5054 | vport->fc_myDID = did; | ||
5055 | |||
4999 | return 1; | 5056 | return 1; |
5000 | } | 5057 | } |
5001 | 5058 | ||
5002 | /* Send back ACC */ | 5059 | /* Send back ACC */ |
5003 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); | 5060 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
5004 | 5061 | ||
5062 | /* Now lets put fc_myDID back to what its supposed to be */ | ||
5063 | vport->fc_myDID = did; | ||
5064 | |||
5005 | if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { | 5065 | if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { |
5066 | |||
5006 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 5067 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
5007 | if (!mbox) | 5068 | if (!mbox) |
5008 | goto fail; | 5069 | goto fail; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 3986165b0275..5bb269e224f6 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -2882,9 +2882,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
2882 | } | 2882 | } |
2883 | 2883 | ||
2884 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { | 2884 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { |
2885 | /* For private loop just start discovery and we are done. */ | 2885 | /* |
2886 | if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && | 2886 | * For private loop or for NPort pt2pt, |
2887 | !(vport->fc_flag & FC_PUBLIC_LOOP)) { | 2887 | * just start discovery and we are done. |
2888 | */ | ||
2889 | if ((vport->fc_flag & FC_PT2PT) || | ||
2890 | ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && | ||
2891 | !(vport->fc_flag & FC_PUBLIC_LOOP))) { | ||
2892 | |||
2888 | /* Use loop map to make discovery list */ | 2893 | /* Use loop map to make discovery list */ |
2889 | lpfc_disc_list_loopmap(vport); | 2894 | lpfc_disc_list_loopmap(vport); |
2890 | /* Start discovery */ | 2895 | /* Start discovery */ |
@@ -5491,9 +5496,9 @@ lpfc_nlp_release(struct kref *kref) | |||
5491 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | 5496 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); |
5492 | 5497 | ||
5493 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, | 5498 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, |
5494 | "0279 lpfc_nlp_release: ndlp:x%p " | 5499 | "0279 lpfc_nlp_release: ndlp:x%p did %x " |
5495 | "usgmap:x%x refcnt:%d\n", | 5500 | "usgmap:x%x refcnt:%d\n", |
5496 | (void *)ndlp, ndlp->nlp_usg_map, | 5501 | (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, |
5497 | atomic_read(&ndlp->kref.refcount)); | 5502 | atomic_read(&ndlp->kref.refcount)); |
5498 | 5503 | ||
5499 | /* remove ndlp from action. */ | 5504 | /* remove ndlp from action. */ |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 5f280b5ae3db..41bb1d2fb625 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -3374,6 +3374,9 @@ typedef struct { | |||
3374 | WORD5 w5; /* Header control/status word */ | 3374 | WORD5 w5; /* Header control/status word */ |
3375 | } XMT_SEQ_FIELDS64; | 3375 | } XMT_SEQ_FIELDS64; |
3376 | 3376 | ||
3377 | /* This word is remote ports D_ID for XMIT_ELS_RSP64 */ | ||
3378 | #define xmit_els_remoteID xrsqRo | ||
3379 | |||
3377 | /* IOCB Command template for 64 bit RCV_SEQUENCE64 */ | 3380 | /* IOCB Command template for 64 bit RCV_SEQUENCE64 */ |
3378 | typedef struct { | 3381 | typedef struct { |
3379 | struct ulp_bde64 rcvBde; | 3382 | struct ulp_bde64 rcvBde; |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 24344c1fab5a..f1946dfda5b4 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -3295,7 +3295,13 @@ struct els_request64_wqe { | |||
3295 | struct xmit_els_rsp64_wqe { | 3295 | struct xmit_els_rsp64_wqe { |
3296 | struct ulp_bde64 bde; | 3296 | struct ulp_bde64 bde; |
3297 | uint32_t response_payload_len; | 3297 | uint32_t response_payload_len; |
3298 | uint32_t rsvd4; | 3298 | uint32_t word4; |
3299 | #define els_rsp64_sid_SHIFT 0 | ||
3300 | #define els_rsp64_sid_MASK 0x00FFFFFF | ||
3301 | #define els_rsp64_sid_WORD word4 | ||
3302 | #define els_rsp64_sp_SHIFT 24 | ||
3303 | #define els_rsp64_sp_MASK 0x00000001 | ||
3304 | #define els_rsp64_sp_WORD word4 | ||
3299 | struct wqe_did wqe_dest; | 3305 | struct wqe_did wqe_dest; |
3300 | struct wqe_common wqe_com; /* words 6-11 */ | 3306 | struct wqe_common wqe_com; /* words 6-11 */ |
3301 | uint32_t word12; | 3307 | uint32_t word12; |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 15ca2a9a0cdd..9133a97f045f 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -367,8 +367,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
367 | return 1; | 367 | return 1; |
368 | } | 368 | } |
369 | 369 | ||
370 | /* Check for Nport to NPort pt2pt protocol */ | ||
370 | if ((vport->fc_flag & FC_PT2PT) && | 371 | if ((vport->fc_flag & FC_PT2PT) && |
371 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { | 372 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { |
373 | |||
372 | /* rcv'ed PLOGI decides what our NPortId will be */ | 374 | /* rcv'ed PLOGI decides what our NPortId will be */ |
373 | vport->fc_myDID = icmd->un.rcvels.parmRo; | 375 | vport->fc_myDID = icmd->un.rcvels.parmRo; |
374 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 376 | 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 | mempool_free(mbox, phba->mbox_mem_pool); | 384 | mempool_free(mbox, phba->mbox_mem_pool); |
383 | goto out; | 385 | goto out; |
384 | } | 386 | } |
387 | /* | ||
388 | * For SLI4, the VFI/VPI are registered AFTER the | ||
389 | * Nport with the higher WWPN sends us a PLOGI with | ||
390 | * our assigned NPortId. | ||
391 | */ | ||
392 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
393 | lpfc_issue_reg_vfi(vport); | ||
385 | 394 | ||
386 | lpfc_can_disctmo(vport); | 395 | lpfc_can_disctmo(vport); |
387 | } | 396 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b035e5badd52..e84dd32553bc 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -7907,6 +7907,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
7907 | bf_set(els_req64_sp, &wqe->els_req, 1); | 7907 | bf_set(els_req64_sp, &wqe->els_req, 1); |
7908 | bf_set(els_req64_sid, &wqe->els_req, | 7908 | bf_set(els_req64_sid, &wqe->els_req, |
7909 | iocbq->vport->fc_myDID); | 7909 | iocbq->vport->fc_myDID); |
7910 | if ((*pcmd == ELS_CMD_FLOGI) && | ||
7911 | !(phba->fc_topology == | ||
7912 | LPFC_TOPOLOGY_LOOP)) | ||
7913 | bf_set(els_req64_sid, &wqe->els_req, 0); | ||
7910 | bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); | 7914 | bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); |
7911 | bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, | 7915 | bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, |
7912 | phba->vpi_ids[iocbq->vport->vpi]); | 7916 | phba->vpi_ids[iocbq->vport->vpi]); |
@@ -8064,11 +8068,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8064 | /* words0-2 BDE memcpy */ | 8068 | /* words0-2 BDE memcpy */ |
8065 | /* word3 iocb=iotag32 wqe=response_payload_len */ | 8069 | /* word3 iocb=iotag32 wqe=response_payload_len */ |
8066 | wqe->xmit_els_rsp.response_payload_len = xmit_len; | 8070 | wqe->xmit_els_rsp.response_payload_len = xmit_len; |
8067 | /* word4 iocb=did wge=rsvd. */ | 8071 | /* word4 */ |
8068 | wqe->xmit_els_rsp.rsvd4 = 0; | 8072 | wqe->xmit_els_rsp.word4 = 0; |
8069 | /* word5 iocb=rsvd wge=did */ | 8073 | /* word5 iocb=rsvd wge=did */ |
8070 | bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, | 8074 | bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, |
8071 | iocbq->iocb.un.elsreq64.remoteID); | 8075 | iocbq->iocb.un.xseq64.xmit_els_remoteID); |
8076 | |||
8077 | if_type = bf_get(lpfc_sli_intf_if_type, | ||
8078 | &phba->sli4_hba.sli_intf); | ||
8079 | if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { | ||
8080 | if (iocbq->vport->fc_flag & FC_PT2PT) { | ||
8081 | bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); | ||
8082 | bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, | ||
8083 | iocbq->vport->fc_myDID); | ||
8084 | if (iocbq->vport->fc_myDID == Fabric_DID) { | ||
8085 | bf_set(wqe_els_did, | ||
8086 | &wqe->xmit_els_rsp.wqe_dest, 0); | ||
8087 | } | ||
8088 | } | ||
8089 | } | ||
8072 | bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, | 8090 | bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, |
8073 | ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); | 8091 | ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); |
8074 | bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU); | 8092 | 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 | pcmd = (uint32_t *) (((struct lpfc_dmabuf *) | 8106 | pcmd = (uint32_t *) (((struct lpfc_dmabuf *) |
8089 | iocbq->context2)->virt); | 8107 | iocbq->context2)->virt); |
8090 | if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { | 8108 | if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { |
8091 | bf_set(els_req64_sp, &wqe->els_req, 1); | 8109 | bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); |
8092 | bf_set(els_req64_sid, &wqe->els_req, | 8110 | bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, |
8093 | iocbq->vport->fc_myDID); | 8111 | iocbq->vport->fc_myDID); |
8094 | bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); | 8112 | bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1); |
8095 | bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, | 8113 | bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, |
8096 | phba->vpi_ids[phba->pport->vpi]); | 8114 | phba->vpi_ids[phba->pport->vpi]); |
8097 | } | 8115 | } |
8098 | command_type = OTHER_COMMAND; | 8116 | command_type = OTHER_COMMAND; |
@@ -13636,8 +13654,13 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr, | |||
13636 | uint32_t did = (fc_hdr->fh_d_id[0] << 16 | | 13654 | uint32_t did = (fc_hdr->fh_d_id[0] << 16 | |
13637 | fc_hdr->fh_d_id[1] << 8 | | 13655 | fc_hdr->fh_d_id[1] << 8 | |
13638 | fc_hdr->fh_d_id[2]); | 13656 | fc_hdr->fh_d_id[2]); |
13657 | |||
13639 | if (did == Fabric_DID) | 13658 | if (did == Fabric_DID) |
13640 | return phba->pport; | 13659 | return phba->pport; |
13660 | if ((phba->pport->fc_flag & FC_PT2PT) && | ||
13661 | !(phba->link_state == LPFC_HBA_READY)) | ||
13662 | return phba->pport; | ||
13663 | |||
13641 | vports = lpfc_create_vport_work_array(phba); | 13664 | vports = lpfc_create_vport_work_array(phba); |
13642 | if (vports != NULL) | 13665 | if (vports != NULL) |
13643 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 13666 | 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 | /* Initialize the first IOCB. */ | 14197 | /* Initialize the first IOCB. */ |
14175 | first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0; | 14198 | first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0; |
14176 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; | 14199 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; |
14177 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; | 14200 | |
14201 | /* Check FC Header to see what TYPE of frame we are rcv'ing */ | ||
14202 | if (sli4_type_from_fc_hdr(fc_hdr) == FC_TYPE_ELS) { | ||
14203 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_ELS64_CX; | ||
14204 | first_iocbq->iocb.un.rcvels.parmRo = | ||
14205 | sli4_did_from_fc_hdr(fc_hdr); | ||
14206 | first_iocbq->iocb.ulpPU = PARM_NPIV_DID; | ||
14207 | } else | ||
14208 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; | ||
14178 | first_iocbq->iocb.ulpContext = NO_XRI; | 14209 | first_iocbq->iocb.ulpContext = NO_XRI; |
14179 | first_iocbq->iocb.unsli3.rcvsli3.ox_id = | 14210 | first_iocbq->iocb.unsli3.rcvsli3.ox_id = |
14180 | be16_to_cpu(fc_hdr->fh_ox_id); | 14211 | be16_to_cpu(fc_hdr->fh_ox_id); |
@@ -14304,6 +14335,7 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, | |||
14304 | struct fc_frame_header *fc_hdr; | 14335 | struct fc_frame_header *fc_hdr; |
14305 | struct lpfc_vport *vport; | 14336 | struct lpfc_vport *vport; |
14306 | uint32_t fcfi; | 14337 | uint32_t fcfi; |
14338 | uint32_t did; | ||
14307 | 14339 | ||
14308 | /* Process each received buffer */ | 14340 | /* Process each received buffer */ |
14309 | fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; | 14341 | fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; |
@@ -14319,12 +14351,32 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, | |||
14319 | else | 14351 | else |
14320 | fcfi = bf_get(lpfc_rcqe_fcf_id, | 14352 | fcfi = bf_get(lpfc_rcqe_fcf_id, |
14321 | &dmabuf->cq_event.cqe.rcqe_cmpl); | 14353 | &dmabuf->cq_event.cqe.rcqe_cmpl); |
14354 | |||
14322 | vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi); | 14355 | vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi); |
14323 | if (!vport || !(vport->vpi_state & LPFC_VPI_REGISTERED)) { | 14356 | if (!vport) { |
14324 | /* throw out the frame */ | 14357 | /* throw out the frame */ |
14325 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | 14358 | lpfc_in_buf_free(phba, &dmabuf->dbuf); |
14326 | return; | 14359 | return; |
14327 | } | 14360 | } |
14361 | |||
14362 | /* d_id this frame is directed to */ | ||
14363 | did = sli4_did_from_fc_hdr(fc_hdr); | ||
14364 | |||
14365 | /* vport is registered unless we rcv a FLOGI directed to Fabric_DID */ | ||
14366 | if (!(vport->vpi_state & LPFC_VPI_REGISTERED) && | ||
14367 | (did != Fabric_DID)) { | ||
14368 | /* | ||
14369 | * Throw out the frame if we are not pt2pt. | ||
14370 | * The pt2pt protocol allows for discovery frames | ||
14371 | * to be received without a registered VPI. | ||
14372 | */ | ||
14373 | if (!(vport->fc_flag & FC_PT2PT) || | ||
14374 | (phba->link_state == LPFC_HBA_READY)) { | ||
14375 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | ||
14376 | return; | ||
14377 | } | ||
14378 | } | ||
14379 | |||
14328 | /* Handle the basic abort sequence (BA_ABTS) event */ | 14380 | /* Handle the basic abort sequence (BA_ABTS) event */ |
14329 | if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) { | 14381 | if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) { |
14330 | lpfc_sli4_handle_unsol_abort(vport, dmabuf); | 14382 | lpfc_sli4_handle_unsol_abort(vport, dmabuf); |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index f097382d7b91..a4a77080091b 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -75,11 +75,19 @@ | |||
75 | (fc_hdr)->fh_s_id[1] << 8 | \ | 75 | (fc_hdr)->fh_s_id[1] << 8 | \ |
76 | (fc_hdr)->fh_s_id[2]) | 76 | (fc_hdr)->fh_s_id[2]) |
77 | 77 | ||
78 | #define sli4_did_from_fc_hdr(fc_hdr) \ | ||
79 | ((fc_hdr)->fh_d_id[0] << 16 | \ | ||
80 | (fc_hdr)->fh_d_id[1] << 8 | \ | ||
81 | (fc_hdr)->fh_d_id[2]) | ||
82 | |||
78 | #define sli4_fctl_from_fc_hdr(fc_hdr) \ | 83 | #define sli4_fctl_from_fc_hdr(fc_hdr) \ |
79 | ((fc_hdr)->fh_f_ctl[0] << 16 | \ | 84 | ((fc_hdr)->fh_f_ctl[0] << 16 | \ |
80 | (fc_hdr)->fh_f_ctl[1] << 8 | \ | 85 | (fc_hdr)->fh_f_ctl[1] << 8 | \ |
81 | (fc_hdr)->fh_f_ctl[2]) | 86 | (fc_hdr)->fh_f_ctl[2]) |
82 | 87 | ||
88 | #define sli4_type_from_fc_hdr(fc_hdr) \ | ||
89 | ((fc_hdr)->fh_type) | ||
90 | |||
83 | #define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000 | 91 | #define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000 |
84 | 92 | ||
85 | enum lpfc_sli4_queue_type { | 93 | enum lpfc_sli4_queue_type { |