scsi: qla2xxx: Add a new v2 dport diagnostic feature

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>
This commit is contained in:
Bikash Hazarika 2022-06-15 22:34:59 -07:00 committed by Martin K. Petersen
parent bff4873c70
commit 476da8faa3
7 changed files with 169 additions and 0 deletions

View File

@ -2424,6 +2424,89 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
return 0;
}
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)
{
@ -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);

View 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

View 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 {

View 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,

View 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;

View 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]);

View 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;