From 4e70b8795ee3ac9aa24d55bff6c11674af2e7fcf Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Wed, 22 Jul 2026 17:01:48 -0700 Subject: [PATCH] scsi: ibmvfc: implement nvme-fc FCP abort callback Implement the NVMe-FC FCP abort callback by issuing an NVMF cancel MAD on the same submission queue used by the original FCP request. Use the original request event stored in abort_req->private to recover the associated ibmvfc queue, then allocate a new event from that queue so the cancel is sent on the matching nvme_scrq. Factor the TMF setup into a dedicated helper, mirroring the LS abort path, and populate the cancel key, task tag, target WWPN, and association ID needed for the VIOS NVMF abort request. The abort path sends the cancel synchronously, waits for completion, frees the temporary event, and logs non-zero MAD status values for debugging. Signed-off-by: Tyrel Datwyler Link: https://patch.msgid.link/20260723000149.969416-33-tyreld@linux.ibm.com Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc-nvme.c | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-nvme.c b/drivers/scsi/ibmvscsi/ibmvfc-nvme.c index 390410e44f0d..54f80b6265d4 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-nvme.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-nvme.c @@ -374,11 +374,75 @@ static int ibmvfc_nvme_fcp_io(struct nvme_fc_local_port *lport, return rc; } +static void ibmvfc_init_fcp_abort(struct ibmvfc_event *evt, + struct nvmefc_fcp_req *abort_req) +{ + struct ibmvfc_tmf *tmf; + struct ibmvfc_event *abt_evt = abort_req->private; + struct ibmvfc_target *tgt = abt_evt->tgt; + + tmf = &evt->iu.tmf; + memset(tmf, 0, sizeof(*tmf)); + tmf->common.version = cpu_to_be32(2); + tmf->common.opcode = cpu_to_be32(IBMVFC_NVMF_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->flags = cpu_to_be32(IBMVFC_TMF_ABORT_TASK | IBMVFC_TMF_NVMF_ASSOC); + tmf->cancel_key = cpu_to_be32((u64)abt_evt); + tmf->my_cancel_key = cpu_to_be32((u64)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(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, void *hw_queue_handle, struct nvmefc_fcp_req *abort_req) { + struct ibmvfc_host *vhost = lport->private; + 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; + + queue = abt_evt->queue; + if (!vhost->logged_in || !queue) + return; + + evt = ibmvfc_get_event(queue); + if (!evt) + return; + + spin_lock_irqsave(queue->q_lock, flags); + kref_get(&tgt->kref); + ibmvfc_init_event(evt, ibmvfc_sync_nvme_completion, IBMVFC_MAD_FORMAT); + ibmvfc_init_fcp_abort(evt, abort_req); + evt->sync_iu = &rsp; + + 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: + 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 = {