From f89cf818c04cc709e0e240693ab675e8d4223cdf Mon Sep 17 00:00:00 2001 From: Alex Michon Date: Wed, 6 Apr 2022 16:10:48 +0200 Subject: [PATCH] nvme/pcie: Fix doorbell delay with fuse operations When sending the first part of a fuse command, we set the first_fused_submitted flag so that we don't ring the doorbell immediately. When the second part is sent, we ring the doorbell for both commands. However, this doesn't work well when we use the option to delay ringing the doorbell. We send both parts, then later when we try to ring the doorbell, we don't because of the first_fused_submitted flag from the first command. Replace this mechanism by keeping track of the last submitted fuse. Change-Id: Ia4ac9b3ce9c319ee4c7e42f86eadda93dac85fca Signed-off-by: Alex Michon Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12182 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker Reviewed-by: Konrad Sztyber --- lib/nvme/nvme_internal.h | 2 +- lib/nvme/nvme_pcie_common.c | 9 ++++++--- lib/nvme/nvme_pcie_internal.h | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index fbf9b8614..9da6bde37 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -446,7 +446,7 @@ struct spdk_nvme_qpair { */ uint8_t no_deletion_notification_needed: 1; - uint8_t first_fused_submitted: 1; + uint8_t last_fuse: 2; uint8_t transport_failure_reason: 2; uint8_t last_transport_failure_reason: 2; diff --git a/lib/nvme/nvme_pcie_common.c b/lib/nvme/nvme_pcie_common.c index a74388afd..8009e6e12 100644 --- a/lib/nvme/nvme_pcie_common.c +++ b/lib/nvme/nvme_pcie_common.c @@ -651,9 +651,12 @@ nvme_pcie_qpair_submit_tracker(struct spdk_nvme_qpair *qpair, struct nvme_tracke spdk_trace_record(TRACE_NVME_PCIE_SUBMIT, qpair->id, 0, (uintptr_t)req, req->cmd.cid, req->cmd.opc, req->cmd.cdw10, req->cmd.cdw11, req->cmd.cdw12); - if (req->cmd.fuse == SPDK_NVME_IO_FLAGS_FUSE_FIRST) { - /* This is first cmd of two fused commands - don't ring doorbell */ - qpair->first_fused_submitted = 1; + if (req->cmd.fuse) { + /* + * Keep track of the fuse operation sequence so that we ring the doorbell only + * after the second fuse is submitted. + */ + qpair->last_fuse = req->cmd.fuse; } /* Don't use wide instructions to copy NVMe command, this is limited by QEMU diff --git a/lib/nvme/nvme_pcie_internal.h b/lib/nvme/nvme_pcie_internal.h index c7aaeaf67..0849aaae9 100644 --- a/lib/nvme/nvme_pcie_internal.h +++ b/lib/nvme/nvme_pcie_internal.h @@ -277,9 +277,8 @@ nvme_pcie_qpair_ring_sq_doorbell(struct spdk_nvme_qpair *qpair) struct nvme_pcie_ctrlr *pctrlr = nvme_pcie_ctrlr(qpair->ctrlr); bool need_mmio = true; - if (qpair->first_fused_submitted) { + if (qpair->last_fuse == SPDK_NVME_IO_FLAGS_FUSE_FIRST) { /* This is first cmd of two fused commands - don't ring doorbell */ - qpair->first_fused_submitted = 0; return; }