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 <[email protected]>
---
 drivers/scsi/ibmvscsi/ibmvfc-core.c | 31 +++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c 
b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index aa7ae81df41b..6558ed3c67c4 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -250,6 +250,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
        int index = atomic_inc_return(&vhost->trace_index) & 
IBMVFC_TRACE_INDEX_MASK;
 
        entry = &vhost->trace[index];
+       memset(entry, 0, sizeof(*entry));
        entry->evt = evt;
        entry->time = jiffies;
        entry->fmt = evt->crq.format;
@@ -257,11 +258,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 = evt->fcp_req->payload_length;
+               }
                break;
        case IBMVFC_MAD_FORMAT:
                entry->op_code = be32_to_cpu(mad->opcode);
@@ -287,6 +293,7 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
        int index = atomic_inc_return(&vhost->trace_index) & 
IBMVFC_TRACE_INDEX_MASK;
 
        entry = &vhost->trace[index];
+       memset(entry, 0, sizeof(*entry));
        entry->evt = evt;
        entry->time = jiffies;
        entry->fmt = evt->crq.format;
@@ -294,15 +301,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


Reply via email to