scsi: qla2xxx: Add a new v2 dport diagnostic feature
authorBikash Hazarika <bhazarika@marvell.com>
Thu, 16 Jun 2022 05:34:59 +0000 (22:34 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 17 Jun 2022 01:59:52 +0000 (21:59 -0400)
FW requires minimum 72 bytes buffer size for D_port result. Buffer size
1024 is mentioned in the FW spec so buffer size is increased to 1024.
Rewrite the logic to handle START/RESTART command from SDMAPI.

Link: https://lore.kernel.org/r/20220616053508.27186-3-njavali@marvell.com
Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_bsg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c

index c2f00f0..606474a 100644 (file)
@@ -2425,6 +2425,89 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
 }
 
 static int
+qla2x00_do_dport_diagnostics_v2(struct bsg_job *bsg_job)
+{
+       struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+       struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
+       scsi_qla_host_t *vha = shost_priv(host);
+       int rval;
+       struct qla_dport_diag_v2 *dd;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       uint16_t options;
+
+       if (!IS_DPORT_CAPABLE(vha->hw))
+               return -EPERM;
+
+       dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+       if (!dd)
+               return -ENOMEM;
+
+       sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+                       bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
+
+       options  = dd->options;
+
+       /*  Check dport Test in progress */
+       if (options == QLA_GET_DPORT_RESULT_V2 &&
+           vha->dport_status & DPORT_DIAG_IN_PROGRESS) {
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
+                                       EXT_STATUS_DPORT_DIAG_IN_PROCESS;
+               goto dportcomplete;
+       }
+
+       /*  Check chip reset in progress and start/restart requests arrive */
+       if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
+           (options == QLA_START_DPORT_TEST_V2 ||
+            options == QLA_RESTART_DPORT_TEST_V2)) {
+               vha->dport_status &= ~DPORT_DIAG_CHIP_RESET_IN_PROGRESS;
+       }
+
+       /*  Check chip reset in progress and get result request arrive */
+       if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
+           options == QLA_GET_DPORT_RESULT_V2) {
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
+                                       EXT_STATUS_DPORT_DIAG_NOT_RUNNING;
+               goto dportcomplete;
+       }
+
+       rval = qla26xx_dport_diagnostics_v2(vha, dd, mcp);
+
+       if (rval == QLA_SUCCESS) {
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
+                                       EXT_STATUS_OK;
+               if (options == QLA_START_DPORT_TEST_V2 ||
+                   options == QLA_RESTART_DPORT_TEST_V2) {
+                       dd->mbx1 = mcp->mb[0];
+                       dd->mbx2 = mcp->mb[1];
+                       vha->dport_status |=  DPORT_DIAG_IN_PROGRESS;
+               } else if (options == QLA_GET_DPORT_RESULT_V2) {
+                       dd->mbx1 = vha->dport_data[1];
+                       dd->mbx2 = vha->dport_data[2];
+               }
+       } else {
+               dd->mbx1 = mcp->mb[0];
+               dd->mbx2 = mcp->mb[1];
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
+                               EXT_STATUS_DPORT_DIAG_ERR;
+       }
+
+dportcomplete:
+       sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                           bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
+
+       bsg_reply->reply_payload_rcv_len = sizeof(*dd);
+       bsg_job->reply_len = sizeof(*bsg_reply);
+       bsg_reply->result = DID_OK << 16;
+       bsg_job_done(bsg_job, bsg_reply->result,
+                    bsg_reply->reply_payload_rcv_len);
+
+       kfree(dd);
+
+       return 0;
+}
+
+static int
 qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
 {
        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
@@ -2860,6 +2943,9 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j
        case QL_VND_DPORT_DIAGNOSTICS:
                return qla2x00_do_dport_diagnostics(bsg_job);
 
+       case QL_VND_DPORT_DIAGNOSTICS_V2:
+               return qla2x00_do_dport_diagnostics_v2(bsg_job);
+
        case QL_VND_EDIF_MGMT:
                return qla_edif_app_mgmt(bsg_job);
 
index 6d2b0a7..bb64b9c 100644 (file)
@@ -37,6 +37,7 @@
 #define QL_VND_GET_TGT_STATS           0x25
 #define QL_VND_MANAGE_HOST_PORT                0x26
 #define QL_VND_MBX_PASSTHRU            0x2B
+#define QL_VND_DPORT_DIAGNOSTICS_V2    0x2C
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK                  0
@@ -60,6 +61,9 @@
 #define EXT_STATUS_TIMEOUT             30
 #define EXT_STATUS_THREAD_FAILED       31
 #define EXT_STATUS_DATA_CMP_FAILED     32
+#define EXT_STATUS_DPORT_DIAG_ERR      40
+#define EXT_STATUS_DPORT_DIAG_IN_PROCESS       41
+#define EXT_STATUS_DPORT_DIAG_NOT_RUNNING      42
 
 /* BSG definations for interpreting CommandSent field */
 #define INT_DEF_LB_LOOPBACK_CMD         0
@@ -288,6 +292,17 @@ struct qla_dport_diag {
        uint8_t  unused[62];
 } __packed;
 
+#define QLA_GET_DPORT_RESULT_V2                0  /* Get Result */
+#define QLA_RESTART_DPORT_TEST_V2      1  /* Restart test */
+#define QLA_START_DPORT_TEST_V2                2  /* Start test */
+struct qla_dport_diag_v2 {
+       uint16_t options;
+       uint16_t mbx1;
+       uint16_t mbx2;
+       uint8_t  unused[58];
+       uint8_t buf[1024]; /* Test Result */
+} __packed;
+
 /* D_Port options */
 #define QLA_DPORT_RESULT       0x0
 #define QLA_DPORT_START                0x2
index f064dcd..5888362 100644 (file)
@@ -1173,6 +1173,12 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
 
 /* ISP mailbox loopback echo diagnostic error code */
 #define MBS_LB_RESET   0x17
+
+/* AEN mailbox Port Diagnostics test */
+#define AEN_START_DIAG_TEST            0x0     /* start the diagnostics */
+#define AEN_DONE_DIAG_TEST_WITH_NOERR  0x1     /* Done with no errors */
+#define AEN_DONE_DIAG_TEST_WITH_ERR    0x2     /* Done with error.*/
+
 /*
  * Firmware options 1, 2, 3.
  */
@@ -5019,6 +5025,10 @@ typedef struct scsi_qla_host {
        u64 short_link_down_cnt;
        struct edif_dbell e_dbell;
        struct pur_core pur_cinfo;
+
+#define DPORT_DIAG_IN_PROGRESS                 BIT_0
+#define DPORT_DIAG_CHIP_RESET_IN_PROGRESS      BIT_1
+       uint16_t dport_status;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
index 08103ef..3674b35 100644 (file)
@@ -555,6 +555,10 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
 extern int
 qla26xx_dport_diagnostics(scsi_qla_host_t *, void *, uint, uint);
 
+extern int
+qla26xx_dport_diagnostics_v2(scsi_qla_host_t *,
+                            struct qla_dport_diag_v2 *,  mbx_cmd_t *);
+
 int qla24xx_send_mb_cmd(struct scsi_qla_host *, mbx_cmd_t *);
 int qla24xx_gpdb_wait(struct scsi_qla_host *, fc_port_t *, u8);
 int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
index 6070834..e4db1c1 100644 (file)
@@ -7208,6 +7208,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
        if (vha->flags.online) {
                qla2x00_abort_isp_cleanup(vha);
 
+               vha->dport_status |= DPORT_DIAG_CHIP_RESET_IN_PROGRESS;
+               vha->dport_status &= ~DPORT_DIAG_IN_PROGRESS;
+
                if (vha->hw->flags.port_isolated)
                        return status;
 
index 9ca20ea..9af9b35 100644 (file)
@@ -1761,6 +1761,9 @@ global_port_update:
                break;
 
        case MBA_DPORT_DIAGNOSTICS:
+               if ((mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_NOERR ||
+                   (mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_ERR)
+                       vha->dport_status &= ~DPORT_DIAG_IN_PROGRESS;
                ql_dbg(ql_dbg_async, vha, 0x5052,
                    "D-Port Diagnostics: %04x %04x %04x %04x\n",
                    mb[0], mb[1], mb[2], mb[3]);
index 892caf2..16a736a 100644 (file)
@@ -6471,6 +6471,54 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
        return rval;
 }
 
+int
+qla26xx_dport_diagnostics_v2(scsi_qla_host_t *vha,
+                            struct qla_dport_diag_v2 *dd,  mbx_cmd_t *mcp)
+{
+       int rval;
+       dma_addr_t dd_dma;
+       uint size = sizeof(dd->buf);
+       uint16_t options = dd->options;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
+              "Entered %s.\n", __func__);
+
+       dd_dma = dma_map_single(&vha->hw->pdev->dev,
+                               dd->buf, size, DMA_FROM_DEVICE);
+       if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) {
+               ql_log(ql_log_warn, vha, 0x1194,
+                      "Failed to map dma buffer.\n");
+               return QLA_MEMORY_ALLOC_FAILED;
+       }
+
+       memset(dd->buf, 0, size);
+
+       mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
+       mcp->mb[1] = options;
+       mcp->mb[2] = MSW(LSD(dd_dma));
+       mcp->mb[3] = LSW(LSD(dd_dma));
+       mcp->mb[6] = MSW(MSD(dd_dma));
+       mcp->mb[7] = LSW(MSD(dd_dma));
+       mcp->mb[8] = size;
+       mcp->out_mb = MBX_8 | MBX_7 | MBX_6 | MBX_3 | MBX_2 | MBX_1 | MBX_0;
+       mcp->in_mb = MBX_3 | MBX_2 | MBX_1 | MBX_0;
+       mcp->buf_size = size;
+       mcp->flags = MBX_DMA_IN;
+       mcp->tov = MBX_TOV_SECONDS * 4;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
+       } else {
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
+                      "Done %s.\n", __func__);
+       }
+
+       dma_unmap_single(&vha->hw->pdev->dev, dd_dma, size, DMA_FROM_DEVICE);
+
+       return rval;
+}
+
 static void qla2x00_async_mb_sp_done(srb_t *sp, int res)
 {
        sp->u.iocb_cmd.u.mbx.rc = res;