From 1264a2b909a096430afef28a7d5e9d0f8829fc24 Mon Sep 17 00:00:00 2001 From: Chuck Tuffli Date: Fri, 27 Mar 2020 15:28:27 +0000 Subject: [PATCH] bhyve: fix NVMe emulation update of SQHD The SQHD field of a Completion Queue entry indicates the current Submission Queue head pointer value. The head pointer represents the next entry to be consumed and is updated after consuming the current entry. In the Admin queue processing, the current code updates the head pointer after reporting the value to the host via the SQHD. This gives the impression that the Controller is perpetually one command behind in its processing of the Admin SQ. And while this doesn't appear to bother some initiators, it is wrong. Fix is to update the SQ head pointer prior to writing the SQHD value in the completion. While here, fix missed update of dword 0 (cdw0) in the completion message. Reported by: khng300 Reviewed by: jhb, imp Approved by: jhb (maintainer) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D24083 --- usr.sbin/bhyve/pci_nvme.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c index 1a8ae8df7782..65e543510e14 100644 --- a/usr.sbin/bhyve/pci_nvme.c +++ b/usr.sbin/bhyve/pci_nvme.c @@ -1153,7 +1153,8 @@ pci_nvme_handle_admin_cmd(struct pci_nvme_softc* sc, uint64_t value) cmd->opc)); pci_nvme_status_genc(&compl.status, NVME_SC_INVALID_OPCODE); } - + sqhead = (sqhead + 1) % sq->size; + if (NVME_COMPLETION_VALID(compl)) { struct nvme_completion *cp; int phase; @@ -1170,7 +1171,6 @@ pci_nvme_handle_admin_cmd(struct pci_nvme_softc* sc, uint64_t value) cq->tail = (cq->tail + 1) % cq->size; } - sqhead = (sqhead + 1) % sq->size; } DPRINTF(("setting sqhead %u", sqhead)); @@ -1285,8 +1285,9 @@ pci_nvme_set_completion(struct pci_nvme_softc *sc, compl = &cq->qbase[cq->tail]; - compl->sqhd = atomic_load_acq_short(&sq->head); + compl->cdw0 = cdw0; compl->sqid = sqid; + compl->sqhd = atomic_load_acq_short(&sq->head); compl->cid = cid; // toggle phase