From f45b402840300e11d19c491d02d21242d1cbc5a0 Mon Sep 17 00:00:00 2001 From: Sivaprasad Gutha Date: Tue, 27 May 2025 11:45:17 +0530 Subject: [PATCH 1/6] nvme: plot eye chart data and hex dumping VS eye data - Fixed segmentation fault issue in JSON output format for VS Eye data. - Added support to hex dump VS Eye data in both normal and JSON formats. - This enables customers to decode the raw eye chart data if needed. - Ensured compatibility with existing d() and obj_d() hex dump utilities. Signed-off-by: Sivaprasad Gutha --- nvme-print-json.c | 68 +++++++++++++++++++++++++++++++++++++-------- nvme-print-stdout.c | 14 ++++++++++ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/nvme-print-json.c b/nvme-print-json.c index 1766cae882..f04db270eb 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -2121,25 +2121,47 @@ static void json_boot_part_log(void *bp_log, const char *devname, /* Printable Eye string is allocated and returned, caller must free */ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, - struct json_object *r) + struct json_object *r) { char *eye = (char *)lane->eye_desc; - char *printable = malloc(lane->nrows * lane->ncols + lane->ncols); + uint16_t nrows = lane->nrows; + uint16_t ncols = lane->ncols; + + if (nrows == 0 || ncols == 0) + return NULL; + + // Allocate buffer for full printable string (with newlines) + char *printable = malloc(nrows * ncols + nrows + 1); // +1 for null terminator char *printable_start = printable; - int i, j; if (!printable) - goto exit; + return NULL; + + struct json_object *eye_array = json_create_array(); + + for (int i = 0; i < nrows; i++) { + char *row = malloc(ncols + 1); + + if (!row) + continue; - for (i = 0; i < lane->nrows; i++) { - for (j = 0; j < lane->ncols; j++, printable++) - sprintf(printable, "%c", eye[i * lane->ncols + j]); - sprintf(printable++, "\n"); + for (int j = 0; j < ncols; j++) { + char ch = eye[i * ncols + j]; + *printable++ = ch; + row[j] = ch; + } + + *printable++ = '\n'; + row[ncols] = '\0'; + + array_add_str(eye_array, row); + free(row); } - obj_add_str(r, "printable_eye", printable_start); + *printable = '\0'; + + obj_add_array(r, "printable_eye_rows", eye_array); -exit: return printable_start; } @@ -2155,6 +2177,8 @@ static void json_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log, for (i = 0; i < num_descs; i++) { struct nvme_eom_lane_desc *desc = p; + unsigned char *vsdata = NULL; + unsigned int vsdataoffset = 0; struct json_object *jdesc = json_create_object(); obj_add_uint(jdesc, "lid", desc->mstatus); @@ -2169,10 +2193,30 @@ static void json_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log, obj_add_uint(jdesc, "edlen", le16_to_cpu(desc->edlen)); if (NVME_EOM_ODP_PEFP(log->odp)) - allocated_eyes[i] = json_eom_printable_eye(desc, r); + allocated_eyes[i] = json_eom_printable_eye(desc, jdesc); - /* Eye Data field is vendor specific, doesn't map to JSON */ + if (desc->edlen == 0) + continue; + else { + /* Hex dump Vendor Specific Eye Data*/ + vsdata = (unsigned char *)malloc(desc->edlen); + vsdataoffset = (desc->nrows * desc->ncols) + + sizeof(struct nvme_eom_lane_desc); + vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); + char *hexstr = malloc(desc->edlen * 3 + 1); // 2 hex chars + space per byte + if (!hexstr) + return; + + char *p = hexstr; + + for (int offset = 0; offset < desc->edlen; offset++) + p += sprintf(p, "%02X ", vsdata[offset]); + *(p - 1) = '\0'; // remove trailing space + + obj_add_str(jdesc, "vsdata_hex", hexstr); + free(hexstr); + } array_add_obj(descs, jdesc); p += log->dsize; diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 1852beaf0c..1105e3ba56 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -790,6 +790,8 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) for (i = 0; i < log->nd; i++) { struct nvme_eom_lane_desc *desc = p; + unsigned char *vsdata = NULL; + unsigned int vsdataoffset = 0; printf("Measurement Status: %s\n", desc->mstatus ? "Successful" : "Not Successful"); @@ -807,6 +809,18 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) stdout_eom_printable_eye(desc); /* Eye Data field is vendor specific */ + if (desc->edlen == 0) + continue; + else { + /* Hex dump Vendor Specific Eye Data */ + vsdata = (unsigned char *)malloc(desc->edlen); + vsdataoffset = (desc->nrows * desc->ncols) + + sizeof(struct nvme_eom_lane_desc); + vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); + printf("Eye Data:\n"); + d(vsdata, desc->edlen, 16, 1); + printf("\n"); + } p += log->dsize; } From d69c312f025ef36285f49a7f004c313872a3fd6d Mon Sep 17 00:00:00 2001 From: Sivaprasad Gutha Date: Tue, 27 May 2025 12:03:45 +0530 Subject: [PATCH 2/6] plugins/micron: update authors list - Added contributors list to the AUTHORS section of the Micron plugin. Signed-off-by: Sivaprasad Gutha --- plugins/micron/micron-nvme.c | 4 +++- plugins/micron/micron-nvme.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 371bc56d59..cc20a1cb52 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -4,7 +4,9 @@ * * @file: micron-nvme.c * @brief: This module contains all the constructs needed for micron nvme-cli plugin. - * @authors:Chaithanya Shoba , + * @authors:Hanumanthu H + * Chaithanya Shoba + * Sivaprasad Gutha */ #include diff --git a/plugins/micron/micron-nvme.h b/plugins/micron/micron-nvme.h index 967909ac4a..c6b3b37dda 100644 --- a/plugins/micron/micron-nvme.h +++ b/plugins/micron/micron-nvme.h @@ -3,7 +3,9 @@ * * @file: micron-nvme.h * @brief: This module contains all the constructs needed for micron nvme-cli plugin. - * @authors:Chaithanya Shoba , + * @authors:Hanumanthu H + * Chaithanya Shoba + * Sivaprasad Gutha */ #undef CMD_INC_FILE From a404eb3050156fd80d6b9606a711a77390bc15d8 Mon Sep 17 00:00:00 2001 From: Sivaprasad Gutha Date: Thu, 29 May 2025 18:42:37 +0530 Subject: [PATCH 3/6] nvme: plot eye chart and hex dumping VS eye data -Addressing review comments Signed-off-by: Sivaprasad Gutha --- nvme-print-json.c | 51 ++++++++++++++++++++++++++------------------- nvme-print-stdout.c | 19 ++++++++--------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/nvme-print-json.c b/nvme-print-json.c index f04db270eb..4f8abc316e 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -2121,11 +2121,11 @@ static void json_boot_part_log(void *bp_log, const char *devname, /* Printable Eye string is allocated and returned, caller must free */ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, - struct json_object *r) + struct json_object *r) { char *eye = (char *)lane->eye_desc; - uint16_t nrows = lane->nrows; - uint16_t ncols = lane->ncols; + uint16_t nrows = le16_to_cpu(lane->nrows); + uint16_t ncols = le16_to_cpu(lane->ncols); if (nrows == 0 || ncols == 0) return NULL; @@ -2139,11 +2139,19 @@ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, struct json_object *eye_array = json_create_array(); + if (!eye_array) { + free(printable); + return NULL; + } + for (int i = 0; i < nrows; i++) { char *row = malloc(ncols + 1); - if (!row) - continue; + if (!row) { + // Cleanup on failure + free(printable_start); + return NULL; + } for (int j = 0; j < ncols; j++) { char ch = eye[i * ncols + j]; @@ -2160,7 +2168,7 @@ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, *printable = '\0'; - obj_add_array(r, "printable_eye_rows", eye_array); + obj_add_array(r, "printable_eye", eye_array); return printable_start; } @@ -2197,26 +2205,25 @@ static void json_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log, if (desc->edlen == 0) continue; - else { - /* Hex dump Vendor Specific Eye Data*/ - vsdata = (unsigned char *)malloc(desc->edlen); - vsdataoffset = (desc->nrows * desc->ncols) + - sizeof(struct nvme_eom_lane_desc); - vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); - char *hexstr = malloc(desc->edlen * 3 + 1); // 2 hex chars + space per byte - if (!hexstr) - return; + /* Hex dump Vendor Specific Eye Data*/ + vsdataoffset = (le16_to_cpu(desc->nrows) * le16_to_cpu(desc->ncols)) + + sizeof(struct nvme_eom_lane_desc); + vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); + // 2 hex chars + space per byte + _cleanup_free_ char *hexstr = malloc(le16_to_cpu(desc->edlen) * 3 + 1); - char *p = hexstr; + if (!hexstr) + return; - for (int offset = 0; offset < desc->edlen; offset++) - p += sprintf(p, "%02X ", vsdata[offset]); - *(p - 1) = '\0'; // remove trailing space + char *hexdata = hexstr; + + for (int offset = 0; offset < le16_to_cpu(desc->edlen); offset++) + hexdata += sprintf(hexdata, "%02X ", vsdata[offset]); + *(hexdata - 1) = '\0'; // remove trailing space + + obj_add_str(jdesc, "vsdata_hex", hexstr); - obj_add_str(jdesc, "vsdata_hex", hexstr); - free(hexstr); - } array_add_obj(descs, jdesc); p += log->dsize; diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 1105e3ba56..4d028b6fda 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -811,16 +811,15 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) /* Eye Data field is vendor specific */ if (desc->edlen == 0) continue; - else { - /* Hex dump Vendor Specific Eye Data */ - vsdata = (unsigned char *)malloc(desc->edlen); - vsdataoffset = (desc->nrows * desc->ncols) + - sizeof(struct nvme_eom_lane_desc); - vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); - printf("Eye Data:\n"); - d(vsdata, desc->edlen, 16, 1); - printf("\n"); - } + + /* Hex dump Vendor Specific Eye Data */ + vsdata = malloc(desc->edlen); + vsdataoffset = (desc->nrows * desc->ncols) + + sizeof(struct nvme_eom_lane_desc); + vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); + printf("Eye Data:\n"); + d(vsdata, desc->edlen, 16, 1); + printf("\n"); p += log->dsize; } From 1b18547a35f7a802ca56c42cdeffd31c963c4bb1 Mon Sep 17 00:00:00 2001 From: Sivaprasad Gutha Date: Thu, 29 May 2025 22:40:18 +0530 Subject: [PATCH 4/6] nvme: eye chart plotting and dump VS eye data -Addressing review comments -Converting all the unsigned shorts into host-endianness Signed-off-by: Sivaprasad Gutha --- nvme-print-stdout.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 4d028b6fda..212dd8d7f6 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -776,9 +776,9 @@ static void stdout_eom_printable_eye(struct nvme_eom_lane_desc *lane) char *eye = (char *)lane->eye_desc; int i, j; - for (i = 0; i < lane->nrows; i++) { - for (j = 0; j < lane->ncols; j++) - printf("%c", eye[i * lane->ncols + j]); + for (i = 0; i < le16_to_cpu(lane->nrows); i++) { + for (j = 0; j < le16_to_cpu(lane->ncols); j++) + printf("%c", eye[i * le16_to_cpu(lane->ncols) + j]); printf("\n"); } } @@ -809,16 +809,16 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) stdout_eom_printable_eye(desc); /* Eye Data field is vendor specific */ - if (desc->edlen == 0) + if (le16_to_cpu(desc->edlen) == 0) continue; /* Hex dump Vendor Specific Eye Data */ - vsdata = malloc(desc->edlen); - vsdataoffset = (desc->nrows * desc->ncols) + + vsdata = malloc(le16_to_cpu(desc->edlen)); + vsdataoffset = (le16_to_cpu(desc->nrows) * le16_to_cpu(desc->ncols)) + sizeof(struct nvme_eom_lane_desc); vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); printf("Eye Data:\n"); - d(vsdata, desc->edlen, 16, 1); + d(vsdata, le16_to_cpu(desc->edlen), 16, 1); printf("\n"); p += log->dsize; From 43097adacafaba51f1135ae8d24dc0a1988cbf53 Mon Sep 17 00:00:00 2001 From: Sivaprasad Gutha Date: Wed, 4 Jun 2025 15:30:32 +0530 Subject: [PATCH 5/6] nvme: eye chart plotting and dump VS eye data - Addressing review comments Signed-off-by: Sivaprasad Gutha --- nvme-print-json.c | 44 ++++++++++++++++++++++++++------------------ nvme-print-stdout.c | 18 ++++++++++-------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/nvme-print-json.c b/nvme-print-json.c index 4f8abc316e..d134af96f2 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -2126,19 +2126,23 @@ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, char *eye = (char *)lane->eye_desc; uint16_t nrows = le16_to_cpu(lane->nrows); uint16_t ncols = le16_to_cpu(lane->ncols); + char *printable = NULL; + char *printable_start = NULL; + struct json_object *eye_array = json_create_array(); if (nrows == 0 || ncols == 0) return NULL; - // Allocate buffer for full printable string (with newlines) - char *printable = malloc(nrows * ncols + nrows + 1); // +1 for null terminator - char *printable_start = printable; + /* + * Allocate buffer for full printable string (with newlines) + * +1 for null terminator + */ + printable = malloc(nrows * ncols + nrows + 1); + printable_start = printable; if (!printable) return NULL; - struct json_object *eye_array = json_create_array(); - if (!eye_array) { free(printable); return NULL; @@ -2148,7 +2152,7 @@ static char *json_eom_printable_eye(struct nvme_eom_lane_desc *lane, char *row = malloc(ncols + 1); if (!row) { - // Cleanup on failure + /* Cleanup on failure */ free(printable_start); return NULL; } @@ -2188,6 +2192,9 @@ static void json_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log, unsigned char *vsdata = NULL; unsigned int vsdataoffset = 0; struct json_object *jdesc = json_create_object(); + uint16_t nrows = le16_to_cpu(desc->nrows); + uint16_t ncols = le16_to_cpu(desc->ncols); + uint16_t edlen = le16_to_cpu(desc->edlen); obj_add_uint(jdesc, "lid", desc->mstatus); obj_add_uint(jdesc, "lane", desc->lane); @@ -2196,31 +2203,32 @@ static void json_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log, obj_add_uint(jdesc, "bottom", le16_to_cpu(desc->bottom)); obj_add_uint(jdesc, "left", le16_to_cpu(desc->left)); obj_add_uint(jdesc, "right", le16_to_cpu(desc->right)); - obj_add_uint(jdesc, "nrows", le16_to_cpu(desc->nrows)); - obj_add_uint(jdesc, "ncols", le16_to_cpu(desc->ncols)); - obj_add_uint(jdesc, "edlen", le16_to_cpu(desc->edlen)); + obj_add_uint(jdesc, "nrows", nrows); + obj_add_uint(jdesc, "ncols", ncols); + obj_add_uint(jdesc, "edlen", edlen); if (NVME_EOM_ODP_PEFP(log->odp)) allocated_eyes[i] = json_eom_printable_eye(desc, jdesc); - if (desc->edlen == 0) + if (edlen == 0) continue; - /* Hex dump Vendor Specific Eye Data*/ - vsdataoffset = (le16_to_cpu(desc->nrows) * le16_to_cpu(desc->ncols)) + - sizeof(struct nvme_eom_lane_desc); - vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); - // 2 hex chars + space per byte - _cleanup_free_ char *hexstr = malloc(le16_to_cpu(desc->edlen) * 3 + 1); + /* 2 hex chars + space per byte */ + _cleanup_free_ char *hexstr = malloc(edlen * 3 + 1); if (!hexstr) return; + /* Hex dump Vendor Specific Eye Data */ + vsdataoffset = (nrows * ncols) + sizeof(struct nvme_eom_lane_desc); + vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); + char *hexdata = hexstr; - for (int offset = 0; offset < le16_to_cpu(desc->edlen); offset++) + for (int offset = 0; offset < edlen; offset++) hexdata += sprintf(hexdata, "%02X ", vsdata[offset]); - *(hexdata - 1) = '\0'; // remove trailing space + /* remove trailing space */ + *(hexdata - 1) = '\0'; obj_add_str(jdesc, "vsdata_hex", hexstr); diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 212dd8d7f6..dea8ea7e0d 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -792,6 +792,9 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) struct nvme_eom_lane_desc *desc = p; unsigned char *vsdata = NULL; unsigned int vsdataoffset = 0; + uint16_t nrows = le16_to_cpu(desc->nrows); + uint16_t ncols = le16_to_cpu(desc->ncols); + uint16_t edlen = le16_to_cpu(desc->edlen); printf("Measurement Status: %s\n", desc->mstatus ? "Successful" : "Not Successful"); @@ -801,24 +804,23 @@ static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log) printf("Bottom: %u\n", le16_to_cpu(desc->bottom)); printf("Left: %u\n", le16_to_cpu(desc->left)); printf("Right: %u\n", le16_to_cpu(desc->right)); - printf("Number of Rows: %u\n", le16_to_cpu(desc->nrows)); - printf("Number of Columns: %u\n", le16_to_cpu(desc->ncols)); - printf("Eye Data Length: %u\n", le16_to_cpu(desc->edlen)); + printf("Number of Rows: %u\n", nrows); + printf("Number of Columns: %u\n", ncols); + printf("Eye Data Length: %u\n", desc->edlen); if (NVME_EOM_ODP_PEFP(log->odp)) stdout_eom_printable_eye(desc); /* Eye Data field is vendor specific */ - if (le16_to_cpu(desc->edlen) == 0) + if (edlen == 0) continue; /* Hex dump Vendor Specific Eye Data */ - vsdata = malloc(le16_to_cpu(desc->edlen)); - vsdataoffset = (le16_to_cpu(desc->nrows) * le16_to_cpu(desc->ncols)) + - sizeof(struct nvme_eom_lane_desc); + vsdata = malloc(edlen); + vsdataoffset = (nrows * ncols) + sizeof(struct nvme_eom_lane_desc); vsdata = (unsigned char *)((unsigned char *)desc + vsdataoffset); printf("Eye Data:\n"); - d(vsdata, le16_to_cpu(desc->edlen), 16, 1); + d(vsdata, edlen, 16, 1); printf("\n"); p += log->dsize; From 1b88468622f07b329403ce515da5269cd0cc483c Mon Sep 17 00:00:00 2001 From: jeff-lien-wdc Date: Tue, 27 May 2025 15:52:53 -0500 Subject: [PATCH 6/6] wdc: Fix for vs-smart-add-log wdc plugin command Support for the 0xC0 log page needs to be added for the SNTMP device. Removed support for parsing the 0xCA log page for the SNTMP device. Update the wdc plugin version to 2.14.0 Remove vs-drive-info support for SNTMP Signed-off-by: jeff-lien-wdc --- plugins/wdc/wdc-nvme.c | 4 ++-- plugins/wdc/wdc-nvme.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 48c0442ed7..d080f937c6 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -1907,14 +1907,13 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) case WDC_NVME_SNTMP_DEV_ID: capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C3_LOG_PAGE | - WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_OCP_C4_LOG_PAGE | WDC_DRIVE_CAP_OCP_C5_LOG_PAGE | WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | - WDC_DRIVE_CAP_INFO | + /* WDC_DRIVE_CAP_INFO | Currently not supported by FW */ WDC_DRIVE_CAP_CLOUD_SSD_VERSION | WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_DRIVE_STATUS | @@ -7317,6 +7316,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format case WDC_NVME_SN650_DEV_ID_4: case WDC_NVME_SN655_DEV_ID: case WDC_NVME_SN655_DEV_ID_1: + case WDC_NVME_SNTMP_DEV_ID: if (uuid_index == 0) { ret = nvme_get_print_ocp_cloud_smart_log(dev, uuid_index, diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h index 01c4482012..bf1f2aac51 100644 --- a/plugins/wdc/wdc-nvme.h +++ b/plugins/wdc/wdc-nvme.h @@ -5,7 +5,7 @@ #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME -#define WDC_PLUGIN_VERSION "2.13.0" +#define WDC_PLUGIN_VERSION "2.14.0" #include "cmd.h" PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),