Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7401bc18 authored by Duane Grigsby's avatar Duane Grigsby Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Add FC-NVMe command handling



This patch adds logic to handle the completion of FC-NVMe commands and
creates a sub-command in the SRB command structure to manage NVMe
commands.

Signed-off-by: default avatarDarren Trapp <darren.trapp@cavium.com>
Signed-off-by: default avatarDuane Grigsby <duane.grigsby@cavium.com>
Signed-off-by: default avatarAnil Gurumurthy <anil.gurumurhty@cavium.com>
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a5d42f4c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -412,6 +412,20 @@ struct srb_iocb {
		struct {
			struct imm_ntfy_from_isp *ntfy;
		} nack;
		struct {
			__le16 comp_status;
			uint16_t rsp_pyld_len;
			uint8_t	aen_op;
			void *desc;

			/* These are only used with ls4 requests */
			int cmd_len;
			int rsp_len;
			dma_addr_t cmd_dma;
			dma_addr_t rsp_dma;
			uint32_t dl;
			uint32_t timeout_sec;
		} nvme;
	} u;

	struct timer_list timer;
@@ -437,6 +451,7 @@ struct srb_iocb {
#define SRB_NACK_PLOGI	16
#define SRB_NACK_PRLI	17
#define SRB_NACK_LOGO	18
#define SRB_NVME_CMD	19
#define SRB_PRLI_CMD	21

enum {
@@ -4110,6 +4125,8 @@ typedef struct scsi_qla_host {
	struct		nvme_fc_local_port *nvme_local_port;
	atomic_t	nvme_ref_count;
	struct list_head nvme_rport_list;
	atomic_t 	nvme_active_aen_cnt;
	uint16_t	nvme_last_rptd_aen;

	uint16_t	fcoe_vlan_id;
	uint16_t	fcoe_fcf_idx;
+19 −3
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
#ifndef __QLA_FW_H
#define __QLA_FW_H

#include <linux/nvme.h>
#include <linux/nvme-fc.h>

#define MBS_CHECKSUM_ERROR	0x4010
#define MBS_INVALID_PRODUCT_KEY	0x4020

@@ -603,9 +606,14 @@ struct sts_entry_24xx {

	uint32_t residual_len;		/* FW calc residual transfer length. */

	union {
		uint16_t reserved_1;
		uint16_t nvme_rsp_pyld_len;
	};

	uint16_t state_flags;		/* State flags. */
#define SF_TRANSFERRED_DATA	BIT_11
#define SF_NVME_ERSP            BIT_6
#define SF_FCP_RSP_DMA		BIT_0

	uint16_t retry_delay;
@@ -615,8 +623,16 @@ struct sts_entry_24xx {
	uint32_t rsp_residual_count;	/* FCP RSP residual count. */

	uint32_t sense_len;		/* FCP SENSE length. */
	uint32_t rsp_data_len;		/* FCP response data length. */
	uint8_t data[28];		/* FCP response/sense information. */

	union {
		struct {
			uint32_t rsp_data_len;	/* FCP response data length  */
			uint8_t data[28];	/* FCP rsp/sense information */
		};
		struct nvme_fc_ersp_iu nvme_ersp;
		uint8_t nvme_ersp_data[32];
	};

	/*
	 * If DIF Error is set in comp_status, these additional fields are
	 * defined:
+79 −0
Original line number Diff line number Diff line
@@ -1799,6 +1799,79 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
	sp->done(sp, 0);
}

static void
qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
{
	const char func[] = "NVME-IOCB";
	fc_port_t *fcport;
	srb_t *sp;
	struct srb_iocb *iocb;
	struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
	uint16_t        state_flags;
	struct nvmefc_fcp_req *fd;
	uint16_t        ret = 0;
	struct srb_iocb *nvme;

	sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
	if (!sp)
		return;

	iocb = &sp->u.iocb_cmd;
	fcport = sp->fcport;
	iocb->u.nvme.comp_status = le16_to_cpu(sts->comp_status);
	state_flags  = le16_to_cpu(sts->state_flags);
	fd = iocb->u.nvme.desc;
	nvme = &sp->u.iocb_cmd;

	if (unlikely(nvme->u.nvme.aen_op))
		atomic_dec(&sp->vha->nvme_active_aen_cnt);

	/*
	 * State flags: Bit 6 and 0.
	 * If 0 is set, we don't care about 6.
	 * both cases resp was dma'd to host buffer
	 * if both are 0, that is good path case.
	 * if six is set and 0 is clear, we need to
	 * copy resp data from status iocb to resp buffer.
	 */
	if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) {
		iocb->u.nvme.rsp_pyld_len = 0;
	} else if ((state_flags & SF_FCP_RSP_DMA)) {
		iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
	} else if (state_flags & SF_NVME_ERSP) {
		uint32_t *inbuf, *outbuf;
		uint16_t iter;

		inbuf = (uint32_t *)&sts->nvme_ersp_data;
		outbuf = (uint32_t *)fd->rspaddr;
		iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
		iter = iocb->u.nvme.rsp_pyld_len >> 2;
		for (; iter; iter--)
			*outbuf++ = swab32(*inbuf++);
	} else { /* unhandled case */
	    ql_log(ql_log_warn, fcport->vha, 0x503a,
		"NVME-%s error. Unhandled state_flags of %x\n",
		sp->name, state_flags);
	}

	fd->transferred_length = fd->payload_length -
	    le32_to_cpu(sts->residual_len);

	if (sts->entry_status) {
		ql_log(ql_log_warn, fcport->vha, 0x5038,
		    "NVME-%s error - hdl=%x entry-status(%x).\n",
		    sp->name, sp->handle, sts->entry_status);
		ret = QLA_FUNCTION_FAILED;
	} else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
		ql_log(ql_log_warn, fcport->vha, 0x5039,
		    "NVME-%s error - hdl=%x completion status(%x) resid=%x  ox_id=%x\n",
		    sp->name, sp->handle, sts->comp_status,
		    le32_to_cpu(sts->residual_len), sts->ox_id);
		ret = QLA_FUNCTION_FAILED;
	}
	sp->done(sp, ret);
}

/**
 * qla2x00_process_response_queue() - Process response queue entries.
 * @ha: SCSI driver HA context
@@ -2289,6 +2362,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
		return;
	}

	/* NVME completion. */
	if (sp->type == SRB_NVME_CMD) {
		qla24xx_nvme_iocb_entry(vha, req, pkt);
		return;
	}

	if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) {
		qla25xx_process_bidir_status_iocb(vha, pkt, req, handle);
		return;
+16 −2
Original line number Diff line number Diff line
@@ -695,9 +695,11 @@ qla2x00_sp_free_dma(void *ptr)
	}

end:
	if (sp->type != SRB_NVME_CMD) {
		CMD_SP(cmd) = NULL;
		qla2x00_rel_sp(sp);
	}
}

void
qla2x00_sp_compl(void *ptr, int res)
@@ -5993,6 +5995,18 @@ qla2x00_timer(scsi_qla_host_t *vha)
	if (!list_empty(&vha->work_list))
		start_dpc++;

	/*
	 * FC-NVME
	 * see if the active AEN count has changed from what was last reported.
	 */
	if (atomic_read(&vha->nvme_active_aen_cnt) != vha->nvme_last_rptd_aen) {
		vha->nvme_last_rptd_aen =
		    atomic_read(&vha->nvme_active_aen_cnt);
		ql_log(ql_log_info, vha, 0x3002,
		    "reporting new aen count of %d to the fw\n",
		    vha->nvme_last_rptd_aen);
	}

	/* Schedule the DPC routine if needed */
	if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
	    test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||