From: Klaus Jensen Date: Tue, 7 Feb 2023 13:37:25 +0000 (+0100) Subject: hw/nvme: also start sqs on notify X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b564af1c7bd9978ff58a6a07ddb465cafda0147c;p=qemu-nvme.git hw/nvme: also start sqs on notify When using ioeventfd for mmio, if the updated completion queue was previously full, make sure associated submission queues are queued up for precessing. Signed-off-by: Klaus Jensen --- diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 920f7087d3..42955a081e 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -4466,26 +4466,43 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) return NVME_INVALID_OPCODE | NVME_DNR; } -static void nvme_cq_notifier(EventNotifier *e) +static void nvme_cq_update(NvmeCQueue *cq, bool start_sqs) { - NvmeCQueue *cq = container_of(e, NvmeCQueue, notifier); - NvmeCtrl *n = cq->ctrl; + if (start_sqs) { + NvmeSQueue *sq; - if (!event_notifier_test_and_clear(e)) { - return; + /* cq was full; start processing sqes on affected sqs again */ + QTAILQ_FOREACH(sq, &cq->sq_list, entry) { + qemu_bh_schedule(sq->bh); + } + + /* if no sq has pending sqes, make sure any pending cqes are posted */ + qemu_bh_schedule(cq->bh); } - nvme_update_cq_head(cq); if (nvme_cq_empty(cq)) { + NvmeCtrl *n = cq->ctrl; + if (cq->irq_enabled) { n->cq_pending--; } nvme_irq_deassert(n, cq); } +} - qemu_bh_schedule(cq->bh); +static void nvme_cq_notifier(EventNotifier *e) +{ + NvmeCQueue *cq = container_of(e, NvmeCQueue, notifier); + bool start_sqs = nvme_cq_full(cq); + + if (!event_notifier_test_and_clear(e)) { + return; + } + + nvme_update_cq_head(cq); + nvme_cq_update(cq, start_sqs); } static int nvme_init_cq_ioeventfd(NvmeCQueue *cq) @@ -7636,21 +7653,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) if (!qid && n->dbbuf_enabled) { pci_dma_write(pci, cq->db_addr, &cq->head, sizeof(cq->head)); } - if (start_sqs) { - NvmeSQueue *sq; - QTAILQ_FOREACH(sq, &cq->sq_list, entry) { - qemu_bh_schedule(sq->bh); - } - qemu_bh_schedule(cq->bh); - } - if (nvme_cq_empty(cq)) { - if (cq->irq_enabled) { - n->cq_pending--; - } - - nvme_irq_deassert(n, cq); - } + nvme_cq_update(cq, start_sqs); } else { /* Submission queue doorbell write */