Commit 476da8fa authored by Bikash Hazarika's avatar Bikash Hazarika Committed by Martin K. Petersen
Browse files

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: default avatarBikash Hazarika <bhazarika@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bff4873c
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
@@ -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);

+15 −0
Original line number Diff line number Diff line
@@ -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
+10 −0
Original line number Diff line number Diff line
@@ -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 {
+4 −0
Original line number Diff line number Diff line
@@ -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,
+3 −0
Original line number Diff line number Diff line
@@ -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;

Loading