]> www.infradead.org Git - qemu-nvme.git/commitdiff
hw/nvme: suppress mmio when processing sq
authorKlaus Jensen <k.jensen@samsung.com>
Thu, 9 Feb 2023 09:09:19 +0000 (10:09 +0100)
committerKlaus Jensen <k.jensen@samsung.com>
Thu, 8 Jun 2023 19:15:39 +0000 (21:15 +0200)
When using shadow doorbells, while we are looping the SQ, do not update
the event index. Otherwise we risk forcing the host to do a redundant
mmio doorbell write.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
hw/nvme/ctrl.c

index beeef2aeb90ba1151a9b36efad892c6858005383..45d15224b1c2546eea9c896f94a243a0ace18c0e 100644 (file)
@@ -7056,35 +7056,37 @@ static void nvme_process_sq(void *opaque)
         nvme_update_sq_tail(sq);
     }
 
-    while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) {
-        addr = sq->dma_addr + sq->head * n->sqe_size;
-        if (nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd))) {
-            trace_pci_nvme_err_addr_read(addr);
-            trace_pci_nvme_err_cfs();
-            stl_le_p(&n->bar.csts, NVME_CSTS_FAILED);
-            break;
-        }
-        nvme_inc_sq_head(sq);
-
-        req = QTAILQ_FIRST(&sq->req_list);
-        QTAILQ_REMOVE(&sq->req_list, req, entry);
-        QTAILQ_INSERT_TAIL(&sq->out_req_list, req, entry);
-        nvme_req_clear(req);
-        req->cqe.cid = cmd.cid;
-        memcpy(&req->cmd, &cmd, sizeof(NvmeCmd));
-
-        status = sq->sqid ? nvme_io_cmd(n, req) :
-            nvme_admin_cmd(n, req);
-        if (status != NVME_NO_COMPLETE) {
-            req->status = status;
-            nvme_enqueue_req_completion(cq, req);
+    do {
+        while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) {
+            addr = sq->dma_addr + sq->head * n->sqe_size;
+            if (nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd))) {
+                trace_pci_nvme_err_addr_read(addr);
+                trace_pci_nvme_err_cfs();
+                stl_le_p(&n->bar.csts, NVME_CSTS_FAILED);
+                break;
+            }
+            nvme_inc_sq_head(sq);
+
+            req = QTAILQ_FIRST(&sq->req_list);
+            QTAILQ_REMOVE(&sq->req_list, req, entry);
+            QTAILQ_INSERT_TAIL(&sq->out_req_list, req, entry);
+            nvme_req_clear(req);
+            req->cqe.cid = cmd.cid;
+            memcpy(&req->cmd, &cmd, sizeof(NvmeCmd));
+
+            status = sq->sqid ? nvme_io_cmd(n, req) :
+                nvme_admin_cmd(n, req);
+            if (status != NVME_NO_COMPLETE) {
+                req->status = status;
+                nvme_enqueue_req_completion(cq, req);
+            }
         }
 
         if (n->dbbuf_enabled) {
             nvme_update_sq_eventidx(sq);
             nvme_update_sq_tail(sq);
         }
-    }
+    } while (!nvme_sq_empty(sq));
 }
 
 static void nvme_update_msixcap_ts(PCIDevice *pci_dev, uint32_t table_size)