[PATCH v2 13/20] scsi: ibmvfc: make NVMe FCP abort callback asynchronous
From: Tyrel Datwyler <tyreld@linux.ibm.com>
Date: 2026-09-19 01:33:29
Also in:
linux-scsi, lkml
Subsystem:
ibm power virtual fc device drivers, linux for powerpc (32-bit and 64-bit), scsi subsystem, the rest · Maintainers:
Tyrel Datwyler, Madhavan Srinivasan, "James E.J. Bottomley", "Martin K. Petersen", Linus Torvalds
The nvme_fc_port_template fcp_abort callback is called by the NVMe-FC
transport from the block layer timeout workqueue. The current
implementation submits a cancel MAD and then blocks on
wait_for_completion() until the VIOS response arrives. This stalls the
timeout workqueue for the full MAD round-trip, preventing any other I/O
timeout from being processed in the meantime.
The nvme-fc-driver.h API contract is explicit: the LLDD must initiate
the abort and return immediately; the ABTS does not need to be complete
on return. The transport waits for the original exchange to complete
independently via fcp_req->done().
Replace the synchronous ibmvfc_sync_nvme_completion callback with a
dedicated ibmvfc_nvme_fcp_abort_done() that runs asynchronously when
the cancel MAD response arrives. The new callback logs any non-zero MAD
status, drops the target kref, and frees the event. ibmvfc_send_event()
guarantees the done callback is invoked on both success and failure
paths, so event ownership is fully transferred and ibmvfc_nvme_fcp_abort()
returns immediately after ibmvfc_send_event().
Drop the now-unnecessary init_completion() from ibmvfc_init_fcp_abort()
and the sync_iu / wait_for_completion / second lock-cycle from the abort
function itself.
Fixes: 4e70b8795ee3 ("scsi: ibmvfc: implement nvme-fc FCP abort callback")
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc-nvme.c | 34 ++++++++++++-----------------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc-nvme.c b/drivers/scsi/ibmvscsi/ibmvfc-nvme.c
index a6fc9e8a35f6..d23e5f31f8b5 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-nvme.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-nvme.c@@ -400,8 +400,18 @@ static void ibmvfc_init_fcp_abort(struct ibmvfc_event *evt, tmf->target_wwpn = cpu_to_be64(tgt->wwpn); tmf->assoc_id = cpu_to_be64(tgt->assoc_id); tmf->task_tag = cpu_to_be64((u64)abt_evt); +} - init_completion(&evt->comp); +static void ibmvfc_nvme_fcp_abort_done(struct ibmvfc_event *evt) +{ + u16 status = be16_to_cpu(evt->xfer_iu->mad_common.status); + + if (status) + ibmvfc_dbg(evt->vhost, "fcp_abort: cancel MAD failed with rc=%x\n", + status); + + kref_put(&evt->tgt->kref, ibmvfc_release_tgt); + ibmvfc_free_event(evt); } static void ibmvfc_nvme_fcp_abort(struct nvme_fc_local_port *lport,
@@ -413,9 +423,7 @@ static void ibmvfc_nvme_fcp_abort(struct nvme_fc_local_port *lport, struct ibmvfc_target *tgt = rport->private; struct ibmvfc_event *evt, *abt_evt = abort_req->private; struct ibmvfc_queue *queue; - union ibmvfc_iu rsp; unsigned long flags; - u16 status = 0; if (!abt_evt) return;
@@ -430,27 +438,13 @@ static void ibmvfc_nvme_fcp_abort(struct nvme_fc_local_port *lport, spin_lock_irqsave(queue->q_lock, flags); kref_get(&tgt->kref); - ibmvfc_init_event(evt, ibmvfc_sync_nvme_completion, IBMVFC_MAD_FORMAT); + ibmvfc_init_event(evt, ibmvfc_nvme_fcp_abort_done, IBMVFC_MAD_FORMAT); ibmvfc_init_fcp_abort(evt, abort_req); - evt->sync_iu = &rsp; + evt->tgt = tgt; if (ibmvfc_send_event(evt, vhost, default_timeout)) - goto out; - - spin_unlock_irqrestore(queue->q_lock, flags); - - wait_for_completion(&evt->comp); - status = be16_to_cpu(rsp.mad_common.status); - - spin_lock_irqsave(queue->q_lock, flags); - ibmvfc_free_event(evt); -out: + kref_put(&tgt->kref, ibmvfc_release_tgt); spin_unlock_irqrestore(queue->q_lock, flags); - - if (status) - ibmvfc_dbg(vhost, "fcp_abort: cancel failed with rc=%x\n", status); - - kref_put(&tgt->kref, ibmvfc_release_tgt); } static struct nvme_fc_port_template ibmvfc_nvme_fc_transport = {
--
2.55.0