[PATCH 02/20] scsi: ibmvfc: fix trace logging for NVMe FCP commands

From: Tyrel Datwyler

Date: Wed Sep 16 2026 - 19:10:48 EST


ibmvfc_trc_start() and ibmvfc_trc_end() handle IBMVFC_CMD_FORMAT events
by reading SCSI-specific fields via ibmvfc_get_fcp_iu() and
ibmvfc_get_fcp_rsp(). These helpers return a pointer into the v3scsi
union member of struct ibmvfc_cmd, but NVMe FCP commands store their
command IU in the v3nvme union member. Reading SCSI FCP fields out of an
NVMe IU produces garbage trace entries (wrong opcode, lun, tmf_flags,
xfer_len, rsp_code, and scsi_status).

Fix this by gating the SCSI-specific field reads on evt->cmnd within the
IBMVFC_CMD_FORMAT branch. For NVMe FCP events (evt->fcp_req set) record
the NVMe SQE opcode from v3nvme.iu.sqe.common.opcode and the payload
length from vfc_cmd->payload_len. The common fields that are valid for
both protocols (tgt_scsi_id, vfc_cmd->status, vfc_cmd->error) are
logged unconditionally.

Fixes: 73c13e30c56f ("scsi: ibmvfc: implement nvme-fc IO command submission callback")
Signed-off-by: Tyrel Datwyler <tyreld@xxxxxxxxxxxxx>
---
drivers/scsi/ibmvscsi/ibmvfc-core.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index aa7ae81df41b..6c243b2a84d7 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -257,11 +257,16 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)

switch (entry->fmt) {
case IBMVFC_CMD_FORMAT:
- entry->op_code = iu->cdb[0];
entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
- entry->lun = scsilun_to_int(&iu->lun);
- entry->tmf_flags = iu->tmf_flags;
- entry->u.start.xfer_len = be32_to_cpu(iu->xfer_len);
+ if (evt->cmnd) {
+ entry->op_code = iu->cdb[0];
+ entry->lun = scsilun_to_int(&iu->lun);
+ entry->tmf_flags = iu->tmf_flags;
+ entry->u.start.xfer_len = be32_to_cpu(iu->xfer_len);
+ } else if (evt->fcp_req) {
+ entry->op_code = vfc_cmd->v3nvme.iu.sqe.common.opcode;
+ entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->payload_len);
+ }
break;
case IBMVFC_MAD_FORMAT:
entry->op_code = be32_to_cpu(mad->opcode);
@@ -294,15 +299,19 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)

switch (entry->fmt) {
case IBMVFC_CMD_FORMAT:
- entry->op_code = iu->cdb[0];
entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
- entry->lun = scsilun_to_int(&iu->lun);
- entry->tmf_flags = iu->tmf_flags;
entry->u.end.status = be16_to_cpu(vfc_cmd->status);
entry->u.end.error = be16_to_cpu(vfc_cmd->error);
- entry->u.end.fcp_rsp_flags = rsp->flags;
- entry->u.end.rsp_code = rsp->data.info.rsp_code;
- entry->u.end.scsi_status = rsp->scsi_status;
+ if (evt->cmnd) {
+ entry->op_code = iu->cdb[0];
+ entry->lun = scsilun_to_int(&iu->lun);
+ entry->tmf_flags = iu->tmf_flags;
+ entry->u.end.fcp_rsp_flags = rsp->flags;
+ entry->u.end.rsp_code = rsp->data.info.rsp_code;
+ entry->u.end.scsi_status = rsp->scsi_status;
+ } else if (evt->fcp_req) {
+ entry->op_code = vfc_cmd->v3nvme.iu.sqe.common.opcode;
+ }
break;
case IBMVFC_MAD_FORMAT:
entry->op_code = be32_to_cpu(mad->opcode);
--
2.55.0