@@ -74,6 +74,8 @@ static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *,
74
74
struct lpfc_iocbq *);
75
75
static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
76
76
struct hbq_dmabuf *);
77
+ static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
78
+ struct hbq_dmabuf *dmabuf);
77
79
static int lpfc_sli4_fp_handle_cqe(struct lpfc_hba *, struct lpfc_queue *,
78
80
struct lpfc_cqe *);
79
81
static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
@@ -5907,7 +5909,7 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
5907
5909
bf_set(lpfc_mbx_set_feature_mds,
5908
5910
&mbox->u.mqe.un.set_feature, 1);
5909
5911
bf_set(lpfc_mbx_set_feature_mds_deep_loopbk,
5910
- &mbox->u.mqe.un.set_feature, 0 );
5912
+ &mbox->u.mqe.un.set_feature, 1 );
5911
5913
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
5912
5914
mbox->u.mqe.un.set_feature.param_len = 8;
5913
5915
break;
@@ -8688,8 +8690,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
8688
8690
memset(wqe, 0, sizeof(union lpfc_wqe128));
8689
8691
/* Some of the fields are in the right position already */
8690
8692
memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
8691
- wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */
8692
- wqe->generic.wqe_com.word10 = 0;
8693
+ if (iocbq->iocb.ulpCommand != CMD_SEND_FRAME) {
8694
+ /* The ct field has moved so reset */
8695
+ wqe->generic.wqe_com.word7 = 0;
8696
+ wqe->generic.wqe_com.word10 = 0;
8697
+ }
8693
8698
8694
8699
abort_tag = (uint32_t) iocbq->iotag;
8695
8700
xritag = iocbq->sli4_xritag;
@@ -9183,6 +9188,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
9183
9188
}
9184
9189
9185
9190
break;
9191
+ case CMD_SEND_FRAME:
9192
+ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
9193
+ bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
9194
+ return 0;
9186
9195
case CMD_XRI_ABORTED_CX:
9187
9196
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
9188
9197
case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */
@@ -16137,6 +16146,8 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
16137
16146
struct fc_vft_header *fc_vft_hdr;
16138
16147
uint32_t *header = (uint32_t *) fc_hdr;
16139
16148
16149
+ #define FC_RCTL_MDS_DIAGS 0xF4
16150
+
16140
16151
switch (fc_hdr->fh_r_ctl) {
16141
16152
case FC_RCTL_DD_UNCAT: /* uncategorized information */
16142
16153
case FC_RCTL_DD_SOL_DATA: /* solicited data */
@@ -16164,6 +16175,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
16164
16175
case FC_RCTL_F_BSY: /* fabric busy to data frame */
16165
16176
case FC_RCTL_F_BSYL: /* fabric busy to link control frame */
16166
16177
case FC_RCTL_LCR: /* link credit reset */
16178
+ case FC_RCTL_MDS_DIAGS: /* MDS Diagnostics */
16167
16179
case FC_RCTL_END: /* end */
16168
16180
break;
16169
16181
case FC_RCTL_VFTH: /* Virtual Fabric tagging Header */
@@ -16173,12 +16185,16 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
16173
16185
default:
16174
16186
goto drop;
16175
16187
}
16188
+
16189
+ #define FC_TYPE_VENDOR_UNIQUE 0xFF
16190
+
16176
16191
switch (fc_hdr->fh_type) {
16177
16192
case FC_TYPE_BLS:
16178
16193
case FC_TYPE_ELS:
16179
16194
case FC_TYPE_FCP:
16180
16195
case FC_TYPE_CT:
16181
16196
case FC_TYPE_NVME:
16197
+ case FC_TYPE_VENDOR_UNIQUE:
16182
16198
break;
16183
16199
case FC_TYPE_IP:
16184
16200
case FC_TYPE_ILS:
@@ -16189,12 +16205,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
16189
16205
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
16190
16206
"2538 Received frame rctl:%s (x%x), type:%s (x%x), "
16191
16207
"frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
16208
+ (fc_hdr->fh_r_ctl == FC_RCTL_MDS_DIAGS) ? "MDS Diags" :
16192
16209
lpfc_rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl,
16193
- lpfc_type_names[fc_hdr->fh_type], fc_hdr->fh_type,
16194
- be32_to_cpu(header[0]), be32_to_cpu(header[1]),
16195
- be32_to_cpu(header[2]), be32_to_cpu(header[3]),
16196
- be32_to_cpu(header[4]), be32_to_cpu(header[5]),
16197
- be32_to_cpu(header[6]));
16210
+ (fc_hdr->fh_type == FC_TYPE_VENDOR_UNIQUE) ?
16211
+ "Vendor Unique" : lpfc_type_names[fc_hdr->fh_type],
16212
+ fc_hdr->fh_type, be32_to_cpu(header[0]),
16213
+ be32_to_cpu(header[1]), be32_to_cpu(header[2]),
16214
+ be32_to_cpu(header[3]), be32_to_cpu(header[4]),
16215
+ be32_to_cpu(header[5]), be32_to_cpu(header[6]));
16198
16216
return 0;
16199
16217
drop:
16200
16218
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -17000,6 +17018,96 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport,
17000
17018
lpfc_sli_release_iocbq(phba, iocbq);
17001
17019
}
17002
17020
17021
+ static void
17022
+ lpfc_sli4_mds_loopback_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
17023
+ struct lpfc_iocbq *rspiocb)
17024
+ {
17025
+ struct lpfc_dmabuf *pcmd = cmdiocb->context2;
17026
+
17027
+ if (pcmd && pcmd->virt)
17028
+ pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
17029
+ kfree(pcmd);
17030
+ lpfc_sli_release_iocbq(phba, cmdiocb);
17031
+ }
17032
+
17033
+ static void
17034
+ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
17035
+ struct hbq_dmabuf *dmabuf)
17036
+ {
17037
+ struct fc_frame_header *fc_hdr;
17038
+ struct lpfc_hba *phba = vport->phba;
17039
+ struct lpfc_iocbq *iocbq = NULL;
17040
+ union lpfc_wqe *wqe;
17041
+ struct lpfc_dmabuf *pcmd = NULL;
17042
+ uint32_t frame_len;
17043
+ int rc;
17044
+
17045
+ fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
17046
+ frame_len = bf_get(lpfc_rcqe_length, &dmabuf->cq_event.cqe.rcqe_cmpl);
17047
+
17048
+ /* Send the received frame back */
17049
+ iocbq = lpfc_sli_get_iocbq(phba);
17050
+ if (!iocbq)
17051
+ goto exit;
17052
+
17053
+ /* Allocate buffer for command payload */
17054
+ pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
17055
+ if (pcmd)
17056
+ pcmd->virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
17057
+ &pcmd->phys);
17058
+ if (!pcmd || !pcmd->virt)
17059
+ goto exit;
17060
+
17061
+ INIT_LIST_HEAD(&pcmd->list);
17062
+
17063
+ /* copyin the payload */
17064
+ memcpy(pcmd->virt, dmabuf->dbuf.virt, frame_len);
17065
+
17066
+ /* fill in BDE's for command */
17067
+ iocbq->iocb.un.xseq64.bdl.addrHigh = putPaddrHigh(pcmd->phys);
17068
+ iocbq->iocb.un.xseq64.bdl.addrLow = putPaddrLow(pcmd->phys);
17069
+ iocbq->iocb.un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDE_64;
17070
+ iocbq->iocb.un.xseq64.bdl.bdeSize = frame_len;
17071
+
17072
+ iocbq->context2 = pcmd;
17073
+ iocbq->vport = vport;
17074
+ iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
17075
+ iocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
17076
+
17077
+ /*
17078
+ * Setup rest of the iocb as though it were a WQE
17079
+ * Build the SEND_FRAME WQE
17080
+ */
17081
+ wqe = (union lpfc_wqe *)&iocbq->iocb;
17082
+
17083
+ wqe->send_frame.frame_len = frame_len;
17084
+ wqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((uint32_t *)fc_hdr));
17085
+ wqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((uint32_t *)fc_hdr + 1));
17086
+ wqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((uint32_t *)fc_hdr + 2));
17087
+ wqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((uint32_t *)fc_hdr + 3));
17088
+ wqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((uint32_t *)fc_hdr + 4));
17089
+ wqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((uint32_t *)fc_hdr + 5));
17090
+
17091
+ iocbq->iocb.ulpCommand = CMD_SEND_FRAME;
17092
+ iocbq->iocb.ulpLe = 1;
17093
+ iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl;
17094
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0);
17095
+ if (rc == IOCB_ERROR)
17096
+ goto exit;
17097
+
17098
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
17099
+ return;
17100
+
17101
+ exit:
17102
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
17103
+ "2023 Unable to process MDS loopback frame\n");
17104
+ if (pcmd && pcmd->virt)
17105
+ pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
17106
+ kfree(pcmd);
17107
+ lpfc_sli_release_iocbq(phba, iocbq);
17108
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
17109
+ }
17110
+
17003
17111
/**
17004
17112
* lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
17005
17113
* @phba: Pointer to HBA context object.
@@ -17038,6 +17146,13 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
17038
17146
fcfi = bf_get(lpfc_rcqe_fcf_id,
17039
17147
&dmabuf->cq_event.cqe.rcqe_cmpl);
17040
17148
17149
+ if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) {
17150
+ vport = phba->pport;
17151
+ /* Handle MDS Loopback frames */
17152
+ lpfc_sli4_handle_mds_loopback(vport, dmabuf);
17153
+ return;
17154
+ }
17155
+
17041
17156
/* d_id this frame is directed to */
17042
17157
did = sli4_did_from_fc_hdr(fc_hdr);
17043
17158
0 commit comments