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
This commit is contained in:
Chuck Tuffli 2020-03-27 15:28:27 +00:00
parent 961be12f6a
commit 1264a2b909
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359367

View File

@ -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