Commit 9aa09e98 authored by James Smart's avatar James Smart Committed by Jens Axboe

lpfc: nvme: Add Receive LS Request and Send LS Response support to nvme

Now that common helpers exist, add the ability to receive NVME LS requests
to the driver. New requests will be delivered to the transport by
nvme_fc_rcv_ls_req().

In order to complete the LS, add support for Send LS Response and send
LS response completion handling to the driver.
Signed-off-by: default avatarPaul Ely <paul.ely@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent fe1bedec
......@@ -402,6 +402,10 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)
* request. Any remaining validation is done and the LS is then forwarded
* to the nvme-fc transport via nvme_fc_rcv_ls_req().
*
* The calling sequence should be: nvme_fc_rcv_ls_req() -> (processing)
* -> lpfc_nvme_xmt_ls_rsp/cmp -> req->done.
* __lpfc_nvme_xmt_ls_rsp_cmp should free the allocated axchg.
*
* Returns 0 if LS was handled and delivered to the transport
* Returns 1 if LS failed to be handled and should be dropped
*/
......@@ -409,6 +413,40 @@ int
lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
struct lpfc_async_xchg_ctx *axchg)
{
#if (IS_ENABLED(CONFIG_NVME_FC))
struct lpfc_vport *vport;
struct lpfc_nvme_rport *lpfc_rport;
struct nvme_fc_remote_port *remoteport;
struct lpfc_nvme_lport *lport;
uint32_t *payload = axchg->payload;
int rc;
vport = axchg->ndlp->vport;
lpfc_rport = axchg->ndlp->nrport;
if (!lpfc_rport)
return -EINVAL;
remoteport = lpfc_rport->remoteport;
if (!vport->localport)
return -EINVAL;
lport = vport->localport->private;
if (!lport)
return -EINVAL;
rc = nvme_fc_rcv_ls_req(remoteport, &axchg->ls_rsp, axchg->payload,
axchg->size);
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
"6205 NVME Unsol rcv: sz %d rc %d: %08x %08x %08x "
"%08x %08x %08x\n",
axchg->size, rc,
*payload, *(payload+1), *(payload+2),
*(payload+3), *(payload+4), *(payload+5));
if (!rc)
return 0;
#endif
return 1;
}
......@@ -860,6 +898,37 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 1;
}
static int
lpfc_nvme_xmt_ls_rsp(struct nvme_fc_local_port *localport,
struct nvme_fc_remote_port *remoteport,
struct nvmefc_ls_rsp *ls_rsp)
{
struct lpfc_async_xchg_ctx *axchg =
container_of(ls_rsp, struct lpfc_async_xchg_ctx, ls_rsp);
struct lpfc_nvme_lport *lport;
int rc;
if (axchg->phba->pport->load_flag & FC_UNLOADING)
return -ENODEV;
lport = (struct lpfc_nvme_lport *)localport->private;
rc = __lpfc_nvme_xmt_ls_rsp(axchg, ls_rsp, __lpfc_nvme_xmt_ls_rsp_cmp);
if (rc) {
/*
* unless the failure is due to having already sent
* the response, an abort will be generated for the
* exchange if the rsp can't be sent.
*/
if (rc != -EALREADY)
atomic_inc(&lport->xmt_ls_abort);
return rc;
}
return 0;
}
/**
* lpfc_nvme_ls_abort - Abort a prior NVME LS request
* @lpfc_nvme_lport: Transport localport that LS is to be issued from.
......@@ -2005,6 +2074,7 @@ static struct nvme_fc_port_template lpfc_nvme_template = {
.fcp_io = lpfc_nvme_fcp_io_submit,
.ls_abort = lpfc_nvme_ls_abort,
.fcp_abort = lpfc_nvme_fcp_abort,
.xmt_ls_rsp = lpfc_nvme_xmt_ls_rsp,
.max_hw_queues = 1,
.max_sgl_segments = LPFC_NVME_DEFAULT_SEGS,
......@@ -2200,6 +2270,7 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
atomic_set(&lport->cmpl_fcp_err, 0);
atomic_set(&lport->cmpl_ls_xb, 0);
atomic_set(&lport->cmpl_ls_err, 0);
atomic_set(&lport->fc4NvmeLsRequests, 0);
atomic_set(&lport->fc4NvmeLsCmpls, 0);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment