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 <[email protected]>
---
 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


Reply via email to