qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-block] [PATCH 2/2] nvme: Check PSDT flag for admin and rw command


From: Qu Wenruo
Subject: [Qemu-block] [PATCH 2/2] nvme: Check PSDT flag for admin and rw command
Date: Tue, 6 Jun 2017 15:38:06 +0800

Check PRP or SGL for Data Transfer(PSDT) flag for admin and read/write
commands.

For NVMe-over-PCIE, admin sq entry should not set SGL bits.
and rw sq entry PSDT flag should not be set beyond controller support.

Although currently either linux kernel NVMe-over-PCIE host driver uses
SGL nor qemu nvme controller supports it, it's never a bad idea to
enhance the check.

Signed-off-by: Qu Wenruo <address@hidden>
---
 hw/block/nvme.c | 11 +++++++++++
 hw/block/nvme.h |  7 ++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index fa1069160e..b2579594d9 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -284,6 +284,10 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, 
NvmeCmd *cmd,
         block_acct_invalid(blk_get_stats(n->conf.blk), acct);
         return NVME_LBA_RANGE | NVME_DNR;
     }
+    if (!n->id_ctrl.sgls && NVME_CMD_FLAGS_PSDT(rw->flags)) {
+        block_acct_invalid(blk_get_stats(n->conf.blk), acct);
+        return NVME_INVALID_FIELD | NVME_DNR;
+    }
 
     if (nvme_map_prp(&req->qsg, prp1, prp2, data_size, n)) {
         block_acct_invalid(blk_get_stats(n->conf.blk), acct);
@@ -618,6 +622,11 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 
 static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
 {
+    /* Admin cmd for NVMe-over-PCIE should NOT use SGL */
+    if (NVME_CMD_FLAGS_PSDT(cmd->flags)) {
+        return NVME_INVALID_FIELD | NVME_DNR;
+    }
+
     switch (cmd->opcode) {
     case NVME_ADM_CMD_DELETE_SQ:
         return nvme_del_sq(n, cmd);
@@ -967,6 +976,8 @@ static int nvme_init(PCIDevice *pci_dev)
     if (blk_enable_write_cache(n->conf.blk)) {
         id->vwc = 1;
     }
+    /* TODO: Support SGL in NVMe-over-PCIE in both qemu and kernel */
+    id->sgls = 0;
 
     n->bar.cap = 0;
     NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 26be663d2d..caf21c5f94 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -229,9 +229,14 @@ typedef union NvmeDataPtr{
     NvmeKeyedSGLDesc    ksgl;
 } NvmeDataPtr;
 
+#define _NVME_CMD_FLAGS_FUSE_MASK    ((1 << 0)  + (1 << 1))
+#define _NVME_CMD_FLAGS_PSDT_MASK    ((1 << 15) + (1 << 14))
+#define NVME_CMD_FLAGS_FUSE(flags)  ((flags) & _NVME_CMD_FLAGS_FUSE_MASK)
+#define NVME_CMD_FLAGS_PSDT(flags)  ((flags) & _NVME_CMD_FLAGS_PSDT_MASK)
+
 typedef struct NvmeCmd {
     uint8_t     opcode;
-    uint8_t     fuse;
+    uint8_t     flags;
     uint16_t    cid;
     uint32_t    nsid;
     uint64_t    res1;
-- 
2.13.0






reply via email to

[Prev in Thread] Current Thread [Next in Thread]