]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
nvme: add Persistent Memory Region (PMR) registers
authorRevanth Rajashekar <revanth.rajashekar@intel.com>
Tue, 6 Aug 2019 21:36:45 +0000 (15:36 -0600)
committerRevanth Rajashekar <revanth.rajashekar@intel.com>
Mon, 12 Aug 2019 22:52:04 +0000 (16:52 -0600)
*update 'show-regs' to display the new PMR registers (PMRCAP, PMRCTL, PMRSTS)
*update 'show-regs' to display the PMRS bit of the Controller Capabilities Register
*add support for error status NVME_SC_SANITIZE_PROHIBITED_PMR

Change-Id: Iec44c4c6cb6518dd6aacd870bd339668892d2525
Signed-off-by: Revanth Rajashekar <revanth.rajashekar@intel.com>
Documentation/nvme-sanitize-log.1
linux/nvme.h
nvme-print.c
nvme-status.c
nvme.h

index ef3b47c730678e3d32632ba1999b75ac704ee6d9..825ce5aa533946662345d2f39fa892b1ccb3d3dd 100644 (file)
@@ -90,7 +90,7 @@ T{
 0x0100
 T}:T{
 .sp
-Global Data Erased bit If set to 1 then non\-volatile storage in the NVM subsystem has not been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation\&. If cleared to 0, then non\-volatile storage in the NVM subsystem has been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem\&.
+Global Data Erased bit If set to 1 then no namespace logical block in the NVM subsystem has been written to and no Persistent Memory Region in the NVM subsystem has been enabled: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation\&. If cleared to 0, then a namespace logical block in the NVM subsystem has been written to or a Persistent Memory Region in the NVM subsystem has been enabled: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem\&.
 T}
 .TE
 .sp 1
index 3a5dc7e78f4d1dca29bf0b700feed3141e8cc140..51ee14f54e27bc1693686b611a6678863e610eca 100644 (file)
@@ -124,6 +124,9 @@ enum {
        NVME_REG_BPINFO = 0x0040,       /* Boot Partition Information */
        NVME_REG_BPRSEL = 0x0044,       /* Boot Partition Read Select */
        NVME_REG_BPMBL  = 0x0048,       /* Boot Partition Memory Buffer Location */
+       NVME_REG_PMRCAP = 0x0e00,       /* Persistent Memory Capabilities */
+       NVME_REG_PMRCTL = 0x0e04,       /* Persistent Memory Region Control */
+       NVME_REG_PMRSTS = 0x0e08,       /* Persistent Memory Region Status */
        NVME_REG_DBS    = 0x1000,       /* SQ 0 Tail Doorbell */
 };
 
@@ -1441,6 +1444,7 @@ enum {
        NVME_SC_THIN_PROV_NOT_SUPP      = 0x11b,
        NVME_SC_CTRL_LIST_INVALID       = 0x11c,
        NVME_SC_BP_WRITE_PROHIBITED     = 0x11e,
+       NVME_SC_PMR_SAN_PROHIBITED      = 0x123,
 
        /*
         * I/O Command Set Specific - NVM commands:
index 16dd05f59dde2fda6682530a5b1600eb6433cfe4..7142b45dd7496cec117dc282421b36ae95187e58 100644 (file)
@@ -1769,9 +1769,11 @@ static void show_sanitize_log_sstat(__u16 status)
 
        printf("\t  [8]\t");
        if (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED)
-               str = "Global Data Erased set: NVM storage has not been written";
+               str = "Global Data Erased set: no NS LB in the NVM subsystem has been written to "\
+                     "and no PMR in the NVM subsystem has been enabled";
        else
-               str = "Global Data Erased cleared: NVM storage has been written";
+               str = "Global Data Erased cleared: a NS LB in the NVM subsystem has been written to "\
+                     "or  a PMR in the NVM subsystem has been enabled";
        printf("%s\n", str);
 }
 
@@ -1947,6 +1949,7 @@ const char *nvme_status_to_string(__u32 status)
        case NVME_SC_ANA_INACCESSIBLE:          return "ASYMMETRIC_NAMESPACE_ACCESS_INACCESSIBLE: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Inaccessible state";
        case NVME_SC_ANA_TRANSITION:            return "ASYMMETRIC_NAMESPACE_ACCESS_TRANSITION: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace transitioning between Asymmetric Namespace Access states";
        case NVME_SC_CMD_INTERRUPTED:           return "CMD_INTERRUPTED: Command processing was interrupted and the controller is unable to successfully complete the command. The host should retry the command.";
+       case NVME_SC_PMR_SAN_PROHIBITED:        return "Sanitize Prohibited While Persistent Memory Region is Enabled: A sanitize operation is prohibited while the Persistent Memory Region is enabled.";
        default:                                return "Unknown";
        }
 }
@@ -3105,18 +3108,20 @@ void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n)
 
 static void show_registers_cap(struct nvme_bar_cap *cap)
 {
-       printf("\tMemory Page Size Maximum      (MPSMAX): %u bytes\n", 1 <<  (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4)));
-       printf("\tMemory Page Size Minimum      (MPSMIN): %u bytes\n", 1 <<  (12 + (cap->mpsmax_mpsmin & 0x0f)));
-       printf("\tBoot Partition Support           (BPS): %s\n", (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No");
-       printf("\tCommand Sets Supported           (CSS): NVM command set is %s\n",
+       printf("\tPersistent Memory Region Supported (PMRS): The Persistent Memory Region is %s\n",
+                       (cap->rsvd_pmrs & 0x01) ? "supported":"not supported");
+       printf("\tMemory Page Size Maximum         (MPSMAX): %u bytes\n", 1 <<  (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4)));
+       printf("\tMemory Page Size Minimum         (MPSMIN): %u bytes\n", 1 <<  (12 + (cap->mpsmax_mpsmin & 0x0f)));
+       printf("\tBoot Partition Support              (BPS): %s\n", (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No");
+       printf("\tCommand Sets Supported              (CSS): NVM command set is %s\n",
                        (cap->bps_css_nssrs_dstrd & 0x0020) ? "supported":"not supported");
-       printf("\tNVM Subsystem Reset Supported  (NSSRS): %s\n", (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
-       printf("\tDoorbell Stride                (DSTRD): %u bytes\n", 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f)));
-       printf("\tTimeout                           (TO): %u ms\n", cap->to * 500);
-       printf("\tArbitration Mechanism Supported  (AMS): Weighted Round Robin with Urgent Priority Class is %s\n",
+       printf("\tNVM Subsystem Reset Supported     (NSSRS): %s\n", (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
+       printf("\tDoorbell Stride                   (DSTRD): %u bytes\n", 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f)));
+       printf("\tTimeout                              (TO): %u ms\n", cap->to * 500);
+       printf("\tArbitration Mechanism Supported     (AMS): Weighted Round Robin with Urgent Priority Class is %s\n",
                        (cap->ams_cqr & 0x02) ? "supported":"not supported");
-       printf("\tContiguous Queues Required       (CQR): %s\n", (cap->ams_cqr & 0x01) ? "Yes":"No");
-       printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", cap->mqes + 1);
+       printf("\tContiguous Queues Required          (CQR): %s\n", (cap->ams_cqr & 0x01) ? "Yes":"No");
+       printf("\tMaximum Queue Entries Supported    (MQES): %u\n\n", cap->mqes + 1);
 }
 
 static void show_registers_version(__u32 vs)
@@ -3329,6 +3334,44 @@ static void show_registers_bpmbl(uint64_t bpmbl)
        printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n", bpmbl);
 }
 
+static void show_registers_pmrcap(__u32 pmrcap)
+{
+       printf("\tPersistent Memory Region Timeout                  (PMRTO): %x\n", (pmrcap & 0x00ff0000) >> 16);
+       printf("\tPersistent Memory Region Write Barrier Mechanisms(PMRWBM): %x\n", (pmrcap & 0x00003c00) >> 10);
+       printf("\tPersistent Memory Region Time Units               (PMRTU): PMR time unit is %s\n",
+                       (pmrcap & 0x00000300) >> 8 ? "minutes":"500 milliseconds");
+       printf("\tBase Indicator Register                             (BIR): %x\n", (pmrcap & 0x000000e0) >> 5);
+       printf("\tWrite Data Support                                  (WDS): Write data to the PMR is %s\n",
+                       (pmrcap & 0x00000010) ? "supported":"not supported");
+       printf("\tRead Data Support                                   (RDS): Read data from the PMR is %s\n",
+                       (pmrcap & 0x00000008) ? "supported":"not supported");
+}
+
+static void show_registers_pmrctl(__u32 pmrctl)
+{
+       printf("\tEnable (EN): PMR is %s\n", (pmrctl & 0x00000001) ? "READY":"Disabled");
+}
+
+static const char *nvme_register_pmr_hsts_to_string(__u8 hsts)
+{
+        switch (hsts) {
+        case 0: return "Normal Operation";
+        case 1: return "Restore Error";
+        case 2: return "Read Only";
+        case 3: return "Unreliable";
+        default: return "Reserved";
+        }
+}
+
+static void show_registers_pmrsts(__u32 pmrsts, __u32 pmrctl)
+{
+       printf("\tHealth Status (HSTS): %s\n", nvme_register_pmr_hsts_to_string((pmrsts & 0x00000e00) >> 9));
+       printf("\tNot Ready     (NRDY): The Persistent Memory Region is %s to process "\
+              "PCI Express memory read and write requests\n",
+              (pmrsts & 0x00000100) == 0 && (pmrctl & 0x00000001) ? "READY":"Not Ready");
+       printf("\tError          (ERR): %x\n", (pmrsts & 0x000000ff));
+}
+
 static inline uint32_t mmio_read32(void *addr)
 {
        __le32 *p = addr;
@@ -3348,7 +3391,7 @@ void json_ctrl_registers(void *bar)
 {
        uint64_t cap, asq, acq, bpmbl;
        uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc,
-                       bpinfo, bprsel;
+                       bpinfo, bprsel, pmrcap, pmrctl, pmrsts;
        struct json_object *root;
 
        cap = mmio_read64(bar + NVME_REG_CAP);
@@ -3366,6 +3409,9 @@ void json_ctrl_registers(void *bar)
        bpinfo = mmio_read32(bar + NVME_REG_BPINFO);
        bprsel = mmio_read32(bar + NVME_REG_BPRSEL);
        bpmbl = mmio_read64(bar + NVME_REG_BPMBL);
+       pmrcap = mmio_read32(bar + NVME_REG_PMRCAP);
+       pmrctl = mmio_read32(bar + NVME_REG_PMRCTL);
+       pmrsts = mmio_read32(bar + NVME_REG_PMRSTS);
 
        root = json_create_object();
        json_object_add_value_uint(root, "cap", cap);
@@ -3383,6 +3429,9 @@ void json_ctrl_registers(void *bar)
        json_object_add_value_int(root, "bpinfo", bpinfo);
        json_object_add_value_int(root, "bprsel", bprsel);
        json_object_add_value_uint(root, "bpmbl", bpmbl);
+       json_object_add_value_int(root, "pmrcap", pmrcap);
+       json_object_add_value_int(root, "pmrctl", pmrctl);
+       json_object_add_value_int(root, "pmrsts", pmrsts);
        json_print_object(root, NULL);
        printf("\n");
        json_free_object(root);
@@ -3391,7 +3440,8 @@ void json_ctrl_registers(void *bar)
 void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
 {
        uint64_t cap, asq, acq, bpmbl;
-       uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, bpinfo, bprsel;
+       uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, bpinfo,
+                bprsel, pmrcap, pmrctl, pmrsts;
 
        int human = mode & HUMAN;
 
@@ -3410,6 +3460,9 @@ void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
        bpinfo = mmio_read32(bar + NVME_REG_BPINFO);
        bprsel = mmio_read32(bar + NVME_REG_BPRSEL);
        bpmbl = mmio_read64(bar + NVME_REG_BPMBL);
+       pmrcap = mmio_read32(bar + NVME_REG_PMRCAP);
+       pmrctl = mmio_read32(bar + NVME_REG_PMRCTL);
+       pmrsts = mmio_read32(bar + NVME_REG_PMRSTS);
 
        if (human) {
                if (cap != 0xffffffff) {
@@ -3465,6 +3518,15 @@ void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
 
                        printf("bpmbl   : %"PRIx64"\n", bpmbl);
                        show_registers_bpmbl(bpmbl);
+
+                       printf("pmrcap  : %x\n", pmrcap);
+                       show_registers_pmrcap(pmrcap);
+
+                       printf("pmrctl  : %x\n", pmrctl);
+                       show_registers_pmrctl(pmrctl);
+
+                       printf("pmrsts  : %x\n", pmrsts);
+                       show_registers_pmrsts(pmrsts, pmrctl);
                }
        } else {
                if (cap != 0xffffffff)
index c69ff3f9a115fd1ec8a0e268bee973732ee81bca..47c241b4aa1667d1f8efb1ff3e9d20e69b18dea8 100644 (file)
@@ -80,6 +80,7 @@ static inline __u8 nvme_cmd_specific_status_to_errno(__u16 status)
        case NVME_SC_NS_IS_PRIVATE:
        case NVME_SC_BP_WRITE_PROHIBITED:
        case NVME_SC_READ_ONLY:
+       case NVME_SC_PMR_SAN_PROHIBITED:
                return EPERM;
        case NVME_SC_OVERLAPPING_RANGE:
        case NVME_SC_NS_NOT_ATTACHED:
diff --git a/nvme.h b/nvme.h
index e630b1036c2c6dd647eb72e6e8446cbfeb42feaa..7e0278b5b5c1b0b23d009241b81c16520134f90e 100644 (file)
--- a/nvme.h
+++ b/nvme.h
@@ -110,7 +110,7 @@ struct nvme_bar_cap {
        __u8    to;
        __u16   bps_css_nssrs_dstrd;
        __u8    mpsmax_mpsmin;
-       __u8    reserved;
+       __u8    rsvd_pmrs;
 };
 
 #ifdef __CHECKER__