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.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 8dfb55130b..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 },
@@ -133,7 +136,9 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
 
     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);
 
@@ -373,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) {
@@ -593,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),