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

Commit 50738420 authored by James Smart's avatar James Smart Committed by Christoph Hellwig
Browse files

lpfc: support nvmet_fc defer_rcv callback



Currently, calls to nvmet_fc_rcv_fcp_req() always copied the
FC-NVME cmd iu to a temporary buffer before returning, allowing
the driver to immediately repost the buffer to the hardware.

To address timing conditions on queue element structures vs async
command reception, the nvmet_fc transport occasionally may need to
hold on to the command iu buffer for a short period. In these cases,
the nvmet_fc_rcv_fcp_req() will return a special return code
(-EOVERFLOW). In these cases, the LLDD must delay until the new
defer_rcv lldd callback is called before recycling the buffer back
to the hw.

This patch adds support for the new nvmet_fc transport defer_rcv
callback and recognition of the new error code when passing commands
to the transport.

Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 0fb228d3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -205,8 +205,10 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
				atomic_read(&tgtp->xmt_ls_rsp_error));

		len += snprintf(buf+len, PAGE_SIZE-len,
				"FCP: Rcv %08x Release %08x Drop %08x\n",
				"FCP: Rcv %08x Defer %08x Release %08x "
				"Drop %08x\n",
				atomic_read(&tgtp->rcv_fcp_cmd_in),
				atomic_read(&tgtp->rcv_fcp_cmd_defer),
				atomic_read(&tgtp->xmt_fcp_release),
				atomic_read(&tgtp->rcv_fcp_cmd_drop));

+4 −1
Original line number Diff line number Diff line
@@ -782,8 +782,11 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
				atomic_read(&tgtp->xmt_ls_rsp_error));

		len += snprintf(buf + len, size - len,
				"FCP: Rcv %08x Drop %08x\n",
				"FCP: Rcv %08x Defer %08x Release %08x "
				"Drop %08x\n",
				atomic_read(&tgtp->rcv_fcp_cmd_in),
				atomic_read(&tgtp->rcv_fcp_cmd_defer),
				atomic_read(&tgtp->xmt_fcp_release),
				atomic_read(&tgtp->rcv_fcp_cmd_drop));

		if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
+30 −0
Original line number Diff line number Diff line
@@ -841,12 +841,31 @@ lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
	lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
}

static void
lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
		     struct nvmefc_tgt_fcp_req *rsp)
{
	struct lpfc_nvmet_tgtport *tgtp;
	struct lpfc_nvmet_rcv_ctx *ctxp =
		container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
	struct rqb_dmabuf *nvmebuf = ctxp->rqb_buffer;
	struct lpfc_hba *phba = ctxp->phba;

	lpfc_nvmeio_data(phba, "NVMET DEFERRCV: xri x%x sz %d CPU %02x\n",
			 ctxp->oxid, ctxp->size, smp_processor_id());

	tgtp = phba->targetport->private;
	atomic_inc(&tgtp->rcv_fcp_cmd_defer);
	lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
}

static struct nvmet_fc_target_template lpfc_tgttemplate = {
	.targetport_delete = lpfc_nvmet_targetport_delete,
	.xmt_ls_rsp     = lpfc_nvmet_xmt_ls_rsp,
	.fcp_op         = lpfc_nvmet_xmt_fcp_op,
	.fcp_abort      = lpfc_nvmet_xmt_fcp_abort,
	.fcp_req_release = lpfc_nvmet_xmt_fcp_release,
	.defer_rcv	= lpfc_nvmet_defer_rcv,

	.max_hw_queues  = 1,
	.max_sgl_segments = LPFC_NVMET_DEFAULT_SEGS,
@@ -1504,6 +1523,17 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
		return;
	}

	/* Processing of FCP command is deferred */
	if (rc == -EOVERFLOW) {
		lpfc_nvmeio_data(phba,
				 "NVMET RCV BUSY: xri x%x sz %d from %06x\n",
				 oxid, size, sid);
		/* defer reposting rcv buffer till .defer_rcv callback */
		ctxp->rqb_buffer = nvmebuf;
		atomic_inc(&tgtp->rcv_fcp_cmd_out);
		return;
	}

	atomic_inc(&tgtp->rcv_fcp_cmd_drop);
	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
			"6159 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct lpfc_nvmet_tgtport {
	atomic_t rcv_fcp_cmd_in;
	atomic_t rcv_fcp_cmd_out;
	atomic_t rcv_fcp_cmd_drop;
	atomic_t rcv_fcp_cmd_defer;
	atomic_t xmt_fcp_release;

	/* Stats counters - lpfc_nvmet_xmt_fcp_op */