From: Daniel Gomez <[email protected]>

Commit 53493c1f83 ("hw/nvme: cap MDTS value for internal limitation")
capped MDTS so the worst-case PRP count would fit in IOV_MAX, leaving
transfers limited to 2 MiB.

Now that dma_blk_cb() can batch IOs up to IOV_MAX instead of limiting
to IOV_MAX, raise the limit via a new NVME_MDTS_MAX = 11 (i.e. 8 MiB) to
match Linux's NVME_MAX_BYTES.

Per spec, MDTS=0 means "that there is no maximum data transfer
size". With the dma_blk_cb() changes, we can potentionally honor
that literally, however Linux host driver will clamp requests at
NVME_MAX_BYTES regardless of the advertised MDTS. Coerce mdts=0 to
NVME_MDTS_MAX so the value the guest sees matches the current Linux
ceiling and document it.

Signed-off-by: Daniel Gomez <[email protected]>
---
 hw/nvme/ctrl.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 00995d9808f..123f969cc03 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -104,6 +104,9 @@
  *   as a power of two (2^n) and is in units of the minimum memory page size
  *   (CAP.MPSMIN). The default value is 7 (i.e. 512 KiB).
  *
+ *   NOTE: A value of 0 means "that there is no maximum data transfer size" per
+ *   spec, but here it is coerced to 11 (i.e. 8 MiB).
+ *
  * - `vsl`
  *   Indicates the maximum data size limit for the Verify command. Like `mdts`,
  *   this value is specified as a power of two (2^n) and is in units of the
@@ -226,6 +229,7 @@
 #define NVME_VF_RES_GRANULARITY 1
 #define NVME_VF_OFFSET 0x1
 #define NVME_VF_STRIDE 1
+#define NVME_MDTS_MAX 11
 
 #define NVME_GUEST_ERR(trace, fmt, ...) \
     do { \
@@ -8624,10 +8628,13 @@ static bool nvme_check_params(NvmeCtrl *n, Error **errp)
         host_memory_backend_set_mapped(n->pmr.dev, true);
     }
 
-    if (!n->params.mdts || ((1 << n->params.mdts) + 1) > IOV_MAX) {
-        error_setg(errp, "mdts exceeds IOV_MAX");
+    if (n->params.mdts > NVME_MDTS_MAX) {
+        error_setg(errp, "mdts must be in [0, %u]", NVME_MDTS_MAX);
         return false;
     }
+    if (n->params.mdts == 0) {
+        n->params.mdts = NVME_MDTS_MAX;
+    }
 
     if (n->params.zasl > n->params.mdts) {
         error_setg(errp, "zoned.zasl (Zone Append Size Limit) must be less "

-- 
2.53.0


Reply via email to