summary refs log tree commit diff stats
path: root/hw/nvme/ns.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/nvme/ns.c')
-rw-r--r--hw/nvme/ns.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index ee673f1a5b..8a3613d9ab 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -58,6 +58,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
 {
     static uint64_t ns_count;
     NvmeIdNs *id_ns = &ns->id_ns;
+    NvmeIdNsNvm *id_ns_nvm = &ns->id_ns_nvm;
     uint8_t ds;
     uint16_t ms;
     int i;
@@ -101,6 +102,8 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
         id_ns->dps |= NVME_ID_NS_DPS_FIRST_EIGHT;
     }
 
+    ns->pif = ns->params.pif;
+
     static const NvmeLBAF lbaf[16] = {
         [0] = { .ds =  9           },
         [1] = { .ds =  9, .ms =  8 },
@@ -112,10 +115,11 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
         [7] = { .ds = 12, .ms = 64 },
     };
 
+    ns->nlbaf = 8;
+
     memcpy(&id_ns->lbaf, &lbaf, sizeof(lbaf));
-    id_ns->nlbaf = 7;
 
-    for (i = 0; i <= id_ns->nlbaf; i++) {
+    for (i = 0; i < ns->nlbaf; i++) {
         NvmeLBAF *lbaf = &id_ns->lbaf[i];
         if (lbaf->ds == ds) {
             if (lbaf->ms == ms) {
@@ -126,12 +130,16 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
     }
 
     /* add non-standard lba format */
-    id_ns->nlbaf++;
-    id_ns->lbaf[id_ns->nlbaf].ds = ds;
-    id_ns->lbaf[id_ns->nlbaf].ms = ms;
-    id_ns->flbas |= id_ns->nlbaf;
+    id_ns->lbaf[ns->nlbaf].ds = ds;
+    id_ns->lbaf[ns->nlbaf].ms = ms;
+    ns->nlbaf++;
+
+    id_ns->flbas |= i;
+
 
 lbaf_found:
+    id_ns_nvm->elbaf[i] = (ns->pif & 0x3) << 7;
+    id_ns->nlbaf = ns->nlbaf - 1;
     nvme_ns_init_format(ns);
 
     return 0;
@@ -370,15 +378,36 @@ static void nvme_zoned_ns_shutdown(NvmeNamespace *ns)
 
 static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp)
 {
+    unsigned int pi_size;
+
     if (!ns->blkconf.blk) {
         error_setg(errp, "block backend not configured");
         return -1;
     }
 
-    if (ns->params.pi && ns->params.ms < 8) {
-        error_setg(errp, "at least 8 bytes of metadata required to enable "
-                   "protection information");
-        return -1;
+    if (ns->params.pi) {
+        if (ns->params.pi > NVME_ID_NS_DPS_TYPE_3) {
+            error_setg(errp, "invalid 'pi' value");
+            return -1;
+        }
+
+        switch (ns->params.pif) {
+        case NVME_PI_GUARD_16:
+            pi_size = 8;
+            break;
+        case NVME_PI_GUARD_64:
+            pi_size = 16;
+            break;
+        default:
+            error_setg(errp, "invalid 'pif'");
+            return -1;
+        }
+
+        if (ns->params.ms < pi_size) {
+            error_setg(errp, "at least %u bytes of metadata required to "
+                       "enable protection information", pi_size);
+            return -1;
+        }
     }
 
     if (ns->params.nsid > NVME_MAX_NAMESPACES) {
@@ -590,6 +619,7 @@ static Property nvme_ns_props[] = {
     DEFINE_PROP_UINT8("mset", NvmeNamespace, params.mset, 0),
     DEFINE_PROP_UINT8("pi", NvmeNamespace, params.pi, 0),
     DEFINE_PROP_UINT8("pil", NvmeNamespace, params.pil, 0),
+    DEFINE_PROP_UINT8("pif", NvmeNamespace, params.pif, 0),
     DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
     DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128),
     DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127),