Added code to support driver loopback with MDS Diagnostics.
This style of diagnostics passes frames from the fabric to
the driver who then echo them back out the link.  SEND_FRAME
WQEs are used to transmit the frames.  Added the SOF and EOF
field location definitions for use by SEND_FRAME.

Also ensure that enable_mds_diags is a RW parameter.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <jsmart2...@gmail.com>
---
 drivers/scsi/lpfc/lpfc_attr.c |  2 +-
 drivers/scsi/lpfc/lpfc_els.c  | 11 ++++++-----
 drivers/scsi/lpfc/lpfc_hw4.h  |  6 ++++++
 drivers/scsi/lpfc/lpfc_sli.c  | 30 +++++++++++++++++++++++++-----
 4 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index f4f1291ec1ba..491a999056aa 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5925,7 +5925,7 @@ lpfc_sg_seg_cnt_init(struct lpfc_hba *phba, int val)
  *       1  = MDS Diagnostics enabled
  * Value range is [0,1]. Default value is 0.
  */
-LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
+LPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
 
 /*
  * lpfc_ras_fwlog_buffsize: Firmware logging host buffer size
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index aaad1c74bb98..30bbfa3f6086 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1052,17 +1052,18 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
                if (lpfc_els_retry(phba, cmdiocb, rspiocb))
                        goto out;
 
+               lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+                                "0150 FLOGI failure Status:x%x/x%x "
+                                "xri x%x TMO:x%x\n",
+                                irsp->ulpStatus, irsp->un.ulpWord[4],
+                                cmdiocb->sli4_xritag, irsp->ulpTimeout);
+
                /* If this is not a loop open failure, bail out */
                if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
                      ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
                                        IOERR_LOOP_OPEN_FAILURE)))
                        goto flogifail;
 
-               lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
-                                "0150 FLOGI failure Status:x%x/x%x xri x%x 
TMO:x%x\n",
-                                irsp->ulpStatus, irsp->un.ulpWord[4],
-                                cmdiocb->sli4_xritag, irsp->ulpTimeout);
-
                /* FLOGI failed, so there is no fabric */
                spin_lock_irq(shost->host_lock);
                vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 77f9a55a3f54..d89480b9eade 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -4314,6 +4314,12 @@ struct wqe_common {
 #define wqe_rcvoxid_SHIFT     16
 #define wqe_rcvoxid_MASK      0x0000FFFF
 #define wqe_rcvoxid_WORD      word9
+#define wqe_sof_SHIFT         24
+#define wqe_sof_MASK          0x000000FF
+#define wqe_sof_WORD          word9
+#define wqe_eof_SHIFT         16
+#define wqe_eof_MASK          0x000000FF
+#define wqe_eof_WORD          word9
        uint32_t word10;
 #define wqe_ebde_cnt_SHIFT    0
 #define wqe_ebde_cnt_MASK     0x0000000f
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index efa602592728..6e8b03f38fac 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -9352,11 +9352,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct 
lpfc_iocbq *iocbq,
                memset(wqe, 0, sizeof(union lpfc_wqe128));
        /* Some of the fields are in the right position already */
        memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
-       if (iocbq->iocb.ulpCommand != CMD_SEND_FRAME) {
-               /* The ct field has moved so reset */
-               wqe->generic.wqe_com.word7 = 0;
-               wqe->generic.wqe_com.word10 = 0;
-       }
+       /* The ct field has moved so reset */
+       wqe->generic.wqe_com.word7 = 0;
+       wqe->generic.wqe_com.word10 = 0;
 
        abort_tag = (uint32_t) iocbq->iotag;
        xritag = iocbq->sli4_xritag;
@@ -9862,6 +9860,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct 
lpfc_iocbq *iocbq,
 
                break;
        case CMD_SEND_FRAME:
+               bf_set(wqe_cmnd, &wqe->generic.wqe_com, CMD_SEND_FRAME);
+               bf_set(wqe_sof, &wqe->generic.wqe_com, 0x2E); /* SOF byte */
+               bf_set(wqe_eof, &wqe->generic.wqe_com, 0x41); /* EOF byte */
+               bf_set(wqe_lenloc, &wqe->generic.wqe_com, 1);
+               bf_set(wqe_xbl, &wqe->generic.wqe_com, 1);
+               bf_set(wqe_dbde, &wqe->generic.wqe_com, 1);
+               bf_set(wqe_xc, &wqe->generic.wqe_com, 1);
+               bf_set(wqe_cmd_type, &wqe->generic.wqe_com, 0xA);
+               bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
                bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
                bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
                return 0;
@@ -16940,6 +16947,8 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct 
fc_frame_header *fc_hdr)
        struct fc_vft_header *fc_vft_hdr;
        uint32_t *header = (uint32_t *) fc_hdr;
 
+#define FC_RCTL_MDS_DIAGS      0xF4
+
        switch (fc_hdr->fh_r_ctl) {
        case FC_RCTL_DD_UNCAT:          /* uncategorized information */
        case FC_RCTL_DD_SOL_DATA:       /* solicited data */
@@ -17950,6 +17959,17 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                fcfi = bf_get(lpfc_rcqe_fcf_id,
                              &dmabuf->cq_event.cqe.rcqe_cmpl);
 
+       if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) {
+               vport = phba->pport;
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "2023 MDS Loopback %d bytes\n",
+                               bf_get(lpfc_rcqe_length,
+                                      &dmabuf->cq_event.cqe.rcqe_cmpl));
+               /* Handle MDS Loopback frames */
+               lpfc_sli4_handle_mds_loopback(vport, dmabuf);
+               return;
+       }
+
        /* d_id this frame is directed to */
        did = sli4_did_from_fc_hdr(fc_hdr);
 
-- 
2.13.7

Reply via email to