From 5dedf4987e3c9903516dc7b9349a30498948dd9d 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. Signed-off-by: Alex Michon Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12182 (master) (cherry picked from commit f89cf818c04cc709e0e240693ab675e8d4223cdf) Change-Id: Ia4ac9b3ce9c319ee4c7e42f86eadda93dac85fca Signed-off-by: Krzysztof Karas Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12490 Reviewed-by: Tomasz Zawadzki Reviewed-by: Jim Harris Reviewed-by: Konrad Sztyber Tested-by: SPDK CI Jenkins --- 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 4400ae302..7a27eaca3 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 e934bc789..a6b368164 100644 --- a/lib/nvme/nvme_pcie_common.c +++ b/lib/nvme/nvme_pcie_common.c @@ -650,9 +650,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 e3fb862fd..0a9959cad 100644 --- a/lib/nvme/nvme_pcie_internal.h +++ b/lib/nvme/nvme_pcie_internal.h @@ -281,9 +281,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; }