]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
[Memblaze] modify SMART info
author丁剑 <jian.ding@memblaze.com>
Tue, 10 Mar 2020 07:16:32 +0000 (15:16 +0800)
committerKeith Busch <kbusch@kernel.org>
Thu, 23 Apr 2020 20:13:34 +0000 (14:13 -0600)
1. Modify SMART info fellow Intel format;
2. Add Memblaze private SMART info;
3. Compatible with both new and old formats;

Signed-off-by: 丁剑 <jian.ding@memblaze.com>
plugins/memblaze/memblaze-nvme.c
plugins/memblaze/memblaze-utils.h [new file with mode: 0644]

index 387548f072fba9035cb21db4d2ba8f39f6e8abca..b54941437f2d36ea3b808a1a8f991c777a0ddf57 100644 (file)
 
 #define CREATE_CMD
 #include "memblaze-nvme.h"
+#include "memblaze-utils.h"
 
 enum {
-       TOTAL_WRITE,
-       TOTAL_READ,
-       THERMAL_THROTTLE,
-       TEMPT_SINCE_RESET,
-       POWER_CONSUMPTION,
-       TEMPT_SINCE_BOOTUP,
-       POWER_LOSS_PROTECTION,
-       WEARLEVELING_COUNT,
-       HOST_WRITE,
-       THERMAL_THROTTLE_CNT,
-       CORRECT_PCIE_PORT0,
-       CORRECT_PCIE_PORT1,
-       REBUILD_FAIL,
-       ERASE_FAIL,
-       PROGRAM_FAIL,
-       READ_FAIL,
-       NR_SMART_ITEMS,
-};
-
-enum {
-       MB_FEAT_POWER_MGMT = 0Xc6,
-};
-
-#pragma pack(push, 1)
-struct nvme_memblaze_smart_log_item {
-       __u8 id[3];
-       union {
-               __u8    __nmval[2];
-               __le16  nmval;
-       };
-       union {
-               __u8 rawval[6];
-               struct temperature {
-                       __le16 max;
-                       __le16 min;
-                       __le16 curr;
-               } temperature;
-               struct power {
-                       __le16 max;
-                       __le16 min;
-                       __le16 curr;
-               } power;
-               struct thermal_throttle_mb {
-                       __u8 on;
-                       __u32 count;
-               } thermal_throttle;
-               struct temperature_p {
-                       __le16 max;
-                       __le16 min;
-               } temperature_p;
-               struct power_loss_protection {
-                       __u8 curr;
-               } power_loss_protection;
-               struct wearleveling_count {
-                       __le16 min;
-                       __le16 max;
-                       __le16 avg;
-               } wearleveling_count;
-               struct thermal_throttle_cnt {
-                       __u8 active;
-                       __le32 cnt;
-               } thermal_throttle_cnt;
-       };
-       __u8 resv;
-};
-#pragma pack(pop)
-
-struct nvme_memblaze_smart_log {
-       struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS];
-       __u8 resv[512 - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS];
+    MB_FEAT_POWER_MGMT = 0xc6,
 };
 
 /*
@@ -97,138 +29,317 @@ struct nvme_memblaze_smart_log {
  */
 static int compare_fw_version(const char *fw1, const char *fw2)
 {
-       while (*fw1 != '\0') {
-               if (*fw2 == '\0' || *fw1 > *fw2)
-                       return 1;
-               if (*fw1 < *fw2)
-                       return -1;
-               fw1++;
-               fw2++;
-       }
+    while (*fw1 != '\0') {
+        if (*fw2 == '\0' || *fw1 > *fw2)
+            return 1;
+        if (*fw1 < *fw2)
+            return -1;
+        fw1++;
+        fw2++;
+    }
+
+    if (*fw2 != '\0')
+        return -1;
+
+    return 0;
+}
+
+/**********************************************************
+ * input: firmware version string
+ * output:
+ *     1: new intel format
+ *     0: old memblaze format
+ * *******************************************************/
+#define MEMBLAZE_FORMAT         (0)
+#define INTEL_FORMAT            (1)
 
-       if (*fw2 != '\0')
-               return -1;
+// 2.83 = raisin
+#define IS_RAISIN(str)          (!strcmp(str, "2.83"))
+#define STR_VER_SIZE            5
 
-       return 0;
+int getlogpage_format_type(char *fw_ver)
+{
+    char fw_ver_local[STR_VER_SIZE];
+    strncpy(fw_ver_local, fw_ver, STR_VER_SIZE);
+    *(fw_ver_local + STR_VER_SIZE - 1) = '\0';
+    if ( IS_RAISIN(fw_ver_local) )
+    {
+        return INTEL_FORMAT;
+    }
+    else
+    {
+        return MEMBLAZE_FORMAT;
+    }
 }
 
 static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item)
 {
-       __le32  __id = 0;
-       memcpy(&__id, item->id, 3);
-       return le32_to_cpu(__id);
+    __le32  __id = 0;
+    memcpy(&__id, item->id, 3);
+    return le32_to_cpu(__id);
 }
 
 static __u64 raw_2_u64(const __u8 *buf, size_t len)
 {
-       __le64  val = 0;
-       memcpy(&val, buf, len);
-       return le64_to_cpu(val);
+    __le64  val = 0;
+    memcpy(&val, buf, len);
+    return le64_to_cpu(val);
 }
 
-static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname,
-               struct nvme_memblaze_smart_log *smart)
+#define STRN2_01    "Additional Smart Log for NVME device"
+#define STRN2_02    "namespace-id"
+#define STRN1_01    "key"
+#define STRN1_02    "normalized"
+#define STRN1_03    "raw"
+#define STR00_01    "program_fail_count"
+#define STR01_01    "erase_fail_count"
+#define STR02_01    "wear_leveling"
+#define STR02_03    "min: "
+#define STR02_04    ", max: "
+#define STR02_05    ", avg: "
+#define STR03_01    "end_to_end_error_detection_count"
+#define STR04_01    "crc_error_count"
+#define STR05_01    "timed_workload_media_wear"
+#define STR06_01    "timed_workload_host_reads"
+#define STR07_01    "timed_workload_timer"
+#define STR07_02    " min"
+#define STR08_01    "thermal_throttle_status"
+#define STR08_02    ", cnt: "
+#define STR09_01    "retry_buffer_overflow_count"
+#define STR10_01    "pll_lock_loss_count"
+#define STR11_01    "nand_bytes_written"
+#define STR11_03    "sectors: "
+#define STR12_01    "host_bytes_written"
+#define STR12_03    "sectors: "
+#define STR13_01    "system_area_life_left"
+#define STR14_01    "total_read"
+#define STR15_01    "tempt_since_born"
+#define STR15_03    "max: "
+#define STR15_04    ", min: "
+#define STR15_05    ", curr: "
+#define STR16_01    "power_consumption"
+#define STR16_03    "max: "
+#define STR16_04    ", min: "
+#define STR16_05    ", curr: "
+#define STR17_01    "tempt_since_bootup"
+#define STR17_03    "max: "
+#define STR17_04    ", min: "
+#define STR17_05    ", curr: "
+#define STR18_01    "power_loss_protection"
+#define STR19_01    "read_fail"
+#define STR20_01    "thermal_throttle_time"
+#define STR21_01    "flash_media_error"
+
+static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart, int index, u8 *nm_val, u8 *raw_val)
 {
-       struct nvme_id_ctrl ctrl;
-       char fw_ver[10];
-       int err = 0;
-       struct nvme_memblaze_smart_log_item *item;
-
-       err = nvme_identify_ctrl(fd, &ctrl);
-       if (err)
-               return err;
-       snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
-               ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
-               ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
-
-       printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid);
-
-       printf("Total write in GB since last factory reset                      : %"PRIu64"\n",
-               int48_to_long(smart->items[TOTAL_WRITE].rawval));
-       printf("Total read in GB since last factory reset                       : %"PRIu64"\n",
-               int48_to_long(smart->items[TOTAL_READ].rawval));
-
-       printf("Thermal throttling status[1:HTP in progress]                    : %u\n",
-               smart->items[THERMAL_THROTTLE].thermal_throttle.on);
-       printf("Total thermal throttling minutes since power on                 : %u\n",
-               smart->items[THERMAL_THROTTLE].thermal_throttle.count);
-
-       printf("Maximum temperature in Kelvin since last factory reset          : %u\n",
-               le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.max));
-       printf("Minimum temperature in Kelvin since last factory reset          : %u\n",
-               le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.min));
-       if (compare_fw_version(fw_ver, "0.09.0300") != 0) {
-               printf("Maximum temperature in Kelvin since power on                    : %u\n",
-                       le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max));
-               printf("Minimum temperature in Kelvin since power on                    : %u\n",
-                       le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min));
-       }
-       printf("Current temperature in Kelvin                                   : %u\n",
-               le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr));
-
-       printf("Maximum power in watt since power on                            : %u\n",
-               le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max));
-       printf("Minimum power in watt since power on                            : %u\n",
-               le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min));
-       printf("Current power in watt                                           : %u\n",
-               le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr));
-
-       item = &smart->items[POWER_LOSS_PROTECTION];
-       if (item_id_2_u32(item) == 0xEC)
-               printf("Power loss protection normalized value                          : %u\n",
-                       item->power_loss_protection.curr);
-
-       item = &smart->items[WEARLEVELING_COUNT];
-       if (item_id_2_u32(item) == 0xAD) {
-               printf("Percentage of wearleveling count left                           : %u\n",
-                               le16_to_cpu(item->nmval));
-               printf("Wearleveling count min erase cycle                              : %u\n",
-                               le16_to_cpu(item->wearleveling_count.min));
-               printf("Wearleveling count max erase cycle                              : %u\n",
-                               le16_to_cpu(item->wearleveling_count.max));
-               printf("Wearleveling count avg erase cycle                              : %u\n",
-                               le16_to_cpu(item->wearleveling_count.avg));
-       }
+    memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE);
+    memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE);
+}
 
-       item = &smart->items[HOST_WRITE];
-       if (item_id_2_u32(item) == 0xF5)
-               printf("Total host write in GiB since device born                       : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
-               
-       item = &smart->items[THERMAL_THROTTLE_CNT];
-       if (item_id_2_u32(item) == 0xEB)
-               printf("Thermal throttling count since device born                      : %u\n",
-                               item->thermal_throttle_cnt.cnt);
-
-       item = &smart->items[CORRECT_PCIE_PORT0];
-       if (item_id_2_u32(item) == 0xED)
-               printf("PCIE Correctable Error Count of Port0                           : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
-
-       item = &smart->items[CORRECT_PCIE_PORT1];
-       if (item_id_2_u32(item) == 0xEE)
-               printf("PCIE Correctable Error Count of Port1                           : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
-
-       item = &smart->items[REBUILD_FAIL];
-       if (item_id_2_u32(item) == 0xEF)
-               printf("End-to-End Error Detection Count                                : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
-
-       item = &smart->items[ERASE_FAIL];
-       if (item_id_2_u32(item) == 0xF0)
-               printf("Erase Fail Count                                                : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s,
+    unsigned int nsid, const char *devname)
+{
+    struct nvme_p4_smart_log *smart = (struct nvme_p4_smart_log *)s;
+    u8 *nm = malloc(NM_SIZE * sizeof(u8));
+    u8 *raw = malloc(RAW_SIZE * sizeof(u8));
+
+    /* Table Title */
+    printf("%s:%s %s:%x\n", STRN2_01, devname, STRN2_02, nsid);
+    /* Clumn Name*/
+    printf("%-34s%-11s%s\n", STRN1_01, STRN1_02, STRN1_03);
+    /* 00 RAISIN_SI_VD_PROGRAM_FAIL */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PROGRAM_FAIL, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR00_01, *nm, int48_to_long(raw));
+    /* 01 RAISIN_SI_VD_ERASE_FAIL */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_ERASE_FAIL, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR01_01, *nm, int48_to_long(raw));
+    /* 02 RAISIN_SI_VD_WEARLEVELING_COUNT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_WEARLEVELING_COUNT, nm, raw);
+    printf("%-31s : %3d%%       %s%u%s%u%s%u\n", STR02_01, *nm,
+        STR02_03, *raw, STR02_04, *(raw+2), STR02_05, *(raw+4));
+    /* 03 RAISIN_SI_VD_E2E_DECTECTION_COUNT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_E2E_DECTECTION_COUNT, nm, raw);
+    printf("%-31s: %3d%%       %"PRIu64"\n", STR03_01, *nm, int48_to_long(raw));
+    /* 04 RAISIN_SI_VD_PCIE_CRC_ERR_COUNT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PCIE_CRC_ERR_COUNT, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR04_01, *nm, int48_to_long(raw));
+    /* 05 RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR, nm, raw);
+    printf("%-32s: %3d%%       %.3f%%\n", STR05_01, *nm, ((float)int48_to_long(raw))/1000);
+    /* 06 RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"%%\n", STR06_01, *nm, int48_to_long(raw));
+    /* 07 RAISIN_SI_VD_TIMED_WORKLOAD_TIMER */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_TIMER, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"%s\n", STR07_01, *nm, int48_to_long(raw), STR07_02);
+    /* 08 RAISIN_SI_VD_THERMAL_THROTTLE_STATUS */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_STATUS, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"%%%s%"PRIu64"\n", STR08_01, *nm,
+        int48_to_long(raw), STR08_02, int48_to_long(raw+1));
+    /* 09 RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR09_01, *nm, int48_to_long(raw));
+    /* 10 RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR10_01, *nm, int48_to_long(raw));
+    /* 11 RAISIN_SI_VD_TOTAL_WRITE */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_WRITE, nm, raw);
+    printf("%-32s: %3d%%       %s%"PRIu64"\n", STR11_01, *nm, STR11_03, int48_to_long(raw));
+    /* 12 RAISIN_SI_VD_HOST_WRITE */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_HOST_WRITE, nm, raw);
+    printf("%-32s: %3d%%       %s%"PRIu64"\n", STR12_01, *nm, STR12_03, int48_to_long(raw));
+    /* 13 RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR13_01, *nm, int48_to_long(raw));
+    /* 14 RAISIN_SI_VD_TOTAL_READ */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_READ, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR14_01, *nm, int48_to_long(raw));
+    /* 15 RAISIN_SI_VD_TEMPT_SINCE_BORN */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BORN, nm, raw);
+    printf("%-32s: %3d%%       %s%u%s%u%s%u\n", STR15_01,  *nm,
+        STR15_03, *raw, STR15_04, *(raw+2), STR15_05, *(raw+4));
+    /* 16 RAISIN_SI_VD_POWER_CONSUMPTION */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_CONSUMPTION, nm, raw);
+    printf("%-32s: %3d%%       %s%u%s%u%s%u\n", STR16_01,  *nm,
+        STR16_03, *raw, STR16_04, *(raw+2), STR16_05, *(raw+4));
+    /* 17 RAISIN_SI_VD_TEMPT_SINCE_BOOTUP */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BOOTUP, nm, raw);
+    printf("%-32s: %3d%%       %s%u%s%u%s%u\n", STR17_01,  *nm, STR17_03, *raw,
+        STR17_04, *(raw+2), STR17_05, *(raw+4));
+    /* 18 RAISIN_SI_VD_POWER_LOSS_PROTECTION */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_LOSS_PROTECTION, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR18_01, *nm, int48_to_long(raw));
+    /* 19 RAISIN_SI_VD_READ_FAIL */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR19_01, *nm, int48_to_long(raw));
+    /* 20 RAISIN_SI_VD_THERMAL_THROTTLE_TIME */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_TIME, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR20_01, *nm, int48_to_long(raw));
+    /* 21 RAISIN_SI_VD_FLASH_MEDIA_ERROR */
+    get_memblaze_new_smart_info(smart, RAISIN_SI_VD_FLASH_MEDIA_ERROR, nm, raw);
+    printf("%-32s: %3d%%       %"PRIu64"\n", STR21_01, *nm, int48_to_long(raw));
+
+    free(nm);
+    free(raw);
+}
+
+static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart,
+    unsigned int nsid, const char *devname, const char *fw_ver)
+{
+    struct nvme_memblaze_smart_log_item *item;
+
+    printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid);
+
+    printf("Total write in GB since last factory reset                 : %"PRIu64"\n",
+        int48_to_long(smart->items[TOTAL_WRITE].rawval));
+    printf("Total read in GB since last factory reset                  : %"PRIu64"\n",
+        int48_to_long(smart->items[TOTAL_READ].rawval));
+
+    printf("Thermal throttling status[1:HTP in progress]                       : %u\n",
+        smart->items[THERMAL_THROTTLE].thermal_throttle.on);
+    printf("Total thermal throttling minutes since power on                    : %u\n",
+        smart->items[THERMAL_THROTTLE].thermal_throttle.count);
+
+    printf("Maximum temperature in Kelvin since last factory reset             : %u\n",
+        le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.max));
+    printf("Minimum temperature in Kelvin since last factory reset             : %u\n",
+        le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.min));
+    if (compare_fw_version(fw_ver, "0.09.0300") != 0) {
+        printf("Maximum temperature in Kelvin since power on                   : %u\n",
+            le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max));
+        printf("Minimum temperature in Kelvin since power on                   : %u\n",
+            le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min));
+    }
+    printf("Current temperature in Kelvin                                      : %u\n",
+        le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr));
+
+    printf("Maximum power in watt since power on                               : %u\n",
+        le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max));
+    printf("Minimum power in watt since power on                               : %u\n",
+        le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min));
+    printf("Current power in watt                                              : %u\n",
+        le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr));
+
+    item = &smart->items[POWER_LOSS_PROTECTION];
+    if (item_id_2_u32(item) == 0xEC)
+        printf("Power loss protection normalized value                         : %u\n",
+            item->power_loss_protection.curr);
+
+    item = &smart->items[WEARLEVELING_COUNT];
+    if (item_id_2_u32(item) == 0xAD) {
+        printf("Percentage of wearleveling count left                          : %u\n",
+            le16_to_cpu(item->nmval));
+        printf("Wearleveling count min erase cycle                             : %u\n",
+            le16_to_cpu(item->wearleveling_count.min));
+        printf("Wearleveling count max erase cycle                             : %u\n",
+            le16_to_cpu(item->wearleveling_count.max));
+        printf("Wearleveling count avg erase cycle                             : %u\n",
+            le16_to_cpu(item->wearleveling_count.avg));
+    }
+
+    item = &smart->items[HOST_WRITE];
+    if (item_id_2_u32(item) == 0xF5)
+        printf("Total host write in GiB since device born                      : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+
+    item = &smart->items[THERMAL_THROTTLE_CNT];
+    if (item_id_2_u32(item) == 0xEB)
+        printf("Thermal throttling count since device born                     : %u\n",
+            item->thermal_throttle_cnt.cnt);
+
+    item = &smart->items[CORRECT_PCIE_PORT0];
+    if (item_id_2_u32(item) == 0xED)
+        printf("PCIE Correctable Error Count of Port0                          : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+
+    item = &smart->items[CORRECT_PCIE_PORT1];
+    if (item_id_2_u32(item) == 0xEE)
+        printf("PCIE Correctable Error Count of Port1                          : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+
+    item = &smart->items[REBUILD_FAIL];
+    if (item_id_2_u32(item) == 0xEF)
+        printf("End-to-End Error Detection Count                               : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+
+    item = &smart->items[ERASE_FAIL];
+    if (item_id_2_u32(item) == 0xF0)
+        printf("Erase Fail Count                                               : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
 
     item = &smart->items[PROGRAM_FAIL];
-       if (item_id_2_u32(item) == 0xF1)
-               printf("Program Fail Count                                              : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
-
-       item = &smart->items[READ_FAIL];
-       if (item_id_2_u32(item) == 0xF2)
-               printf("Read Fail Count                                                 : %llu\n",
-                               (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+    if (item_id_2_u32(item) == 0xF1)
+        printf("Program Fail Count                                             : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+
+    item = &smart->items[READ_FAIL];
+    if (item_id_2_u32(item) == 0xF2)
+        printf("Read Fail Count                                                        : %llu\n",
+            (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
+}
+
+static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname,
+    struct nvme_memblaze_smart_log *smart)
+{
+    struct nvme_id_ctrl ctrl;
+    char fw_ver[10];
+    int err = 0;
+
+    err = nvme_identify_ctrl(fd, &ctrl);
+    if (err)
+        return err;
+    snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
+        ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
+        ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
+
+    if (getlogpage_format_type(fw_ver)) // Intel Format & new format
+    {
+        show_memblaze_smart_log_new(smart, nsid, devname);
+    }
+    else  // Memblaze Format & old format
+    {
+        show_memblaze_smart_log_old(smart, nsid, devname, fw_ver);
+    }
        return err;
 }
 
@@ -481,3 +592,4 @@ free:
                free(buf);
        return err;
 }
+
diff --git a/plugins/memblaze/memblaze-utils.h b/plugins/memblaze/memblaze-utils.h
new file mode 100644 (file)
index 0000000..f5bec94
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef __MEMBLAZE_UTILS_H__
+#define __MEMBLAZE_UTILS_H__
+
+#define SMART_INFO_OLD_SIZE     512
+#define SMART_INFO_NEW_SIZE     4096
+
+#define ID_SIZE                 3
+#define NM_SIZE                 2
+#define RAW_SIZE                7
+
+typedef unsigned char           u8;
+
+// Intel Format & new format
+/* Raisin Additional smart external ID */
+#define RAISIN_SI_VD_PROGRAM_FAIL_ID                        0xAB
+#define RAISIN_SI_VD_ERASE_FAIL_ID                          0xAC
+#define RAISIN_SI_VD_WEARLEVELING_COUNT_ID                  0xAD
+#define RAISIN_SI_VD_E2E_DECTECTION_COUNT_ID                0xB8
+#define RAISIN_SI_VD_PCIE_CRC_ERR_COUNT_ID                  0xC7
+#define RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR_ID           0xE2
+#define RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ_ID            0xE3
+#define RAISIN_SI_VD_TIMED_WORKLOAD_TIMER_ID                0xE4
+#define RAISIN_SI_VD_THERMAL_THROTTLE_STATUS_ID             0xEA
+#define RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT_ID           0xF0
+#define RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT_ID                 0xF3
+#define RAISIN_SI_VD_TOTAL_WRITE_ID                         0xF4
+#define RAISIN_SI_VD_HOST_WRITE_ID                          0xF5
+#define RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT_ID               0xF6
+#define RAISIN_SI_VD_TOTAL_READ_ID                          0xFA
+#define RAISIN_SI_VD_TEMPT_SINCE_BORN_ID                    0xE7
+#define RAISIN_SI_VD_POWER_CONSUMPTION_ID                   0xE8
+#define RAISIN_SI_VD_TEMPT_SINCE_BOOTUP_ID                  0xAF
+#define RAISIN_SI_VD_POWER_LOSS_PROTECTION_ID               0xEC
+#define RAISIN_SI_VD_READ_FAIL_ID                           0xF2
+#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID               0xEB
+#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID                   0xED
+
+/* Raisin Addtional smart internal ID */
+typedef enum
+{
+    /* smart attr following intel */
+    RAISIN_SI_VD_PROGRAM_FAIL = 0, /* 0xAB */
+    RAISIN_SI_VD_ERASE_FAIL = 1,   /* 0xAC */
+    RAISIN_SI_VD_WEARLEVELING_COUNT = 2,/* 0xAD */
+    RAISIN_SI_VD_E2E_DECTECTION_COUNT = 3, /* 0xB8 */
+    RAISIN_SI_VD_PCIE_CRC_ERR_COUNT = 4, /* 0xC7, 2 port data in one attribute */
+    RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR = 5, /* 0xE2 , unknown definition*/
+    RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ = 6, /* 0xE3 , unknown definition */
+    RAISIN_SI_VD_TIMED_WORKLOAD_TIMER = 7, /* 0xE4 , unknown definition */
+    RAISIN_SI_VD_THERMAL_THROTTLE_STATUS = 8, /* 0xEA */
+    RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT = 9, /* 0xF0, unknown definition*/
+    RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT = 10, /* 0xF3, unknown definition*/
+    RAISIN_SI_VD_TOTAL_WRITE = 11, /* 0xF4, unit is 32MiB */
+    RAISIN_SI_VD_HOST_WRITE = 12, /* 0xF5, unit is 32MiB */
+    RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT = 13, /* 0xF6, unknown definition*/
+    RAISIN_SI_VD_TOTAL_READ = 14, /* 0xFA, unit is 32MiB */
+
+    /* smart attr self defined */
+    RAISIN_SI_VD_TEMPT_SINCE_BORN = 15, /* 0xE7 */
+    RAISIN_SI_VD_POWER_CONSUMPTION = 16, /* 0xE8 */
+    RAISIN_SI_VD_TEMPT_SINCE_BOOTUP = 17, /* 0xAF */
+    RAISIN_SI_VD_POWER_LOSS_PROTECTION = 18, /* 0xEC */
+    RAISIN_SI_VD_READ_FAIL = 19, /* 0xF2 */
+    RAISIN_SI_VD_THERMAL_THROTTLE_TIME = 20, /* 0xEB */
+    RAISIN_SI_VD_FLASH_MEDIA_ERROR = 21, /* 0xED */
+    RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
+} RAISIN_si_vendor_smart_item_e;
+
+// Memblaze Format & old format
+enum {
+    TOTAL_WRITE = 0,
+    TOTAL_READ,
+    THERMAL_THROTTLE,
+    TEMPT_SINCE_RESET,
+    POWER_CONSUMPTION,
+    TEMPT_SINCE_BOOTUP,
+    POWER_LOSS_PROTECTION,
+    WEARLEVELING_COUNT,
+    HOST_WRITE,
+    THERMAL_THROTTLE_CNT,
+    CORRECT_PCIE_PORT0,
+    CORRECT_PCIE_PORT1,
+    REBUILD_FAIL,
+    ERASE_FAIL,
+    PROGRAM_FAIL,
+    READ_FAIL,
+    NR_SMART_ITEMS = RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
+};
+
+// Memblaze Format & old format
+#pragma pack(push, 1)
+struct nvme_memblaze_smart_log_item {
+        __u8 id[3];
+        union {
+            __u8    __nmval[2];
+            __le16  nmval;
+        };
+        union {
+        __u8 rawval[6];
+        struct temperature {
+        __le16 max;
+        __le16 min;
+        __le16 curr;
+        } temperature;
+        struct power {
+            __le16 max;
+            __le16 min;
+            __le16 curr;
+        } power;
+        struct thermal_throttle_mb {
+            __u8 on;
+            __u32 count;
+        } thermal_throttle;
+        struct temperature_p {
+            __le16 max;
+            __le16 min;
+        } temperature_p;
+        struct power_loss_protection {
+            __u8 curr;
+        } power_loss_protection;
+        struct wearleveling_count {
+            __le16 min;
+            __le16 max;
+            __le16 avg;
+        } wearleveling_count;
+        struct thermal_throttle_cnt {
+            __u8 active;
+            __le32 cnt;
+        } thermal_throttle_cnt;
+    };
+    __u8 resv;
+};
+#pragma pack(pop)
+
+struct nvme_memblaze_smart_log {
+    struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS];
+    u8 resv[SMART_INFO_OLD_SIZE - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS];
+};
+
+// Intel Format & new format
+struct nvme_p4_smart_log_item
+{
+    /* Item identifier */
+    u8 id[ID_SIZE];
+    /* Normalized value or percentage. In the range from 0 to 100. */
+    u8 nmVal[NM_SIZE];
+    /* raw value */
+    u8 rawVal[RAW_SIZE];
+};
+
+struct nvme_p4_smart_log
+{
+    struct nvme_p4_smart_log_item itemArr[NR_SMART_ITEMS];
+
+    /**
+     * change 512 to 4096.
+     * because micron's getlogpage request,the size of many commands have changed to 4k.
+     * request size > user malloc size,casuing parameters that are closed in momery are dirty.
+     */
+    u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS];
+};
+
+#endif // __MEMBLAZE_UTILS_H__
+