| File: | .build-ci/../plugins/ocp/ocp-telemetry-decode.c |
| Warning: | line 1100, column 3 Potential leak of memory pointed to by 'description' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | |||
| 2 | /* Copyright (c) 2024 Western Digital Corporation or its affiliates. | |||
| 3 | * | |||
| 4 | * Authors: Jeff Lien <jeff.lien@wdc.com>, | |||
| 5 | */ | |||
| 6 | #include <libnvme.h> | |||
| 7 | ||||
| 8 | #include "common.h" | |||
| 9 | #include "nvme.h" | |||
| 10 | #include "plugin.h" | |||
| 11 | #include "util/types.h" | |||
| 12 | #include "nvme-print.h" | |||
| 13 | ||||
| 14 | #include "ocp-telemetry-decode.h" | |||
| 15 | ||||
| 16 | ||||
| 17 | void print_vu_event_data(__u32 size, __u8 *data) | |||
| 18 | { | |||
| 19 | int j; | |||
| 20 | __u16 vu_event_id = *(__u16 *)data; | |||
| 21 | ||||
| 22 | printf(" VU Event ID : 0x%02x\n", le16_to_cpu(vu_event_id)); | |||
| 23 | printf(" VU Data : 0x"); | |||
| 24 | for (j = 2; j < size; j++) | |||
| 25 | printf("%x", data[j]); | |||
| 26 | printf("\n\n"); | |||
| 27 | } | |||
| 28 | ||||
| 29 | void print_stats_desc(struct telemetry_stats_desc *stat_desc) | |||
| 30 | { | |||
| 31 | int j; | |||
| 32 | /* Get the statistics Identifier string name and data size */ | |||
| 33 | __u16 stat_id = stat_desc->id; | |||
| 34 | __u32 stat_data_sz = ((stat_desc->size) * 4); | |||
| 35 | ||||
| 36 | printf("Statistics Identifier : 0x%x, %s\n", | |||
| 37 | stat_id, telemetry_stat_id_to_string(stat_id)); | |||
| 38 | printf("Statistics info : 0x%x\n", stat_desc->info); | |||
| 39 | printf("NS info : 0x%x\n", stat_desc->ns_info); | |||
| 40 | printf("Statistic Data Size : 0x%x\n", le16_to_cpu(stat_data_sz)); | |||
| 41 | printf("Namespace ID[15:0] : 0x%x\n", stat_desc->nsid); | |||
| 42 | ||||
| 43 | if (stat_data_sz > 0) { | |||
| 44 | printf("%s : 0x", | |||
| 45 | telemetry_stat_id_to_string(stat_id)); | |||
| 46 | for (j = 0; j < stat_data_sz; j++) | |||
| 47 | printf("%02x", stat_desc->data[j]); | |||
| 48 | printf("\n"); | |||
| 49 | } | |||
| 50 | printf("\n"); | |||
| 51 | } | |||
| 52 | ||||
| 53 | void print_telemetry_fifo_event(__u8 class_type, | |||
| 54 | __u16 id, __u8 size_dw, __u8 *data) | |||
| 55 | { | |||
| 56 | int j; | |||
| 57 | const char *class_str = NULL((void*)0); | |||
| 58 | __u32 size = size_dw * 4; | |||
| 59 | char time_str[40]; | |||
| 60 | uint64_t timestamp = 0; | |||
| 61 | ||||
| 62 | memset((void *)time_str, '\0', 40); | |||
| 63 | ||||
| 64 | if (class_type) { | |||
| 65 | class_str = telemetry_event_class_to_string(class_type); | |||
| 66 | printf("Event Class : %s\n", class_str); | |||
| 67 | printf(" Size : 0x%02x\n", size); | |||
| 68 | } | |||
| 69 | ||||
| 70 | switch (class_type) { | |||
| 71 | case TELEMETRY_TIMESTAMP_CLASS: | |||
| 72 | timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(*(uint64_t *)data)); | |||
| 73 | ||||
| 74 | memset((void *)time_str, 0, 9); | |||
| 75 | sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(timestamp)/3600), | |||
| 76 | (int)((le64_to_cpu(timestamp%3600)/60)), | |||
| 77 | (int)(le64_to_cpu(timestamp%60))); | |||
| 78 | ||||
| 79 | printf(" Event ID : 0x%04x %s\n", id, telemetry_ts_event_to_string(id)); | |||
| 80 | printf(" Timestamp : %s\n", time_str); | |||
| 81 | if (size > 8) { | |||
| 82 | printf(" VU Data : 0x"); | |||
| 83 | for (j = 8; j < size; j++) | |||
| 84 | printf("%02x", data[j]); | |||
| 85 | printf("\n\n"); | |||
| 86 | } | |||
| 87 | break; | |||
| 88 | ||||
| 89 | case TELEMETRY_PCIE_CLASS: | |||
| 90 | printf(" Event ID : 0x%04x %s\n", | |||
| 91 | id, telemetry_pcie_event_id_to_string(id)); | |||
| 92 | printf(" State : 0x%02x %s\n", | |||
| 93 | data[0], telemetry_pcie_state_data_to_string(data[0])); | |||
| 94 | printf(" Speed : 0x%02x %s\n", | |||
| 95 | data[1], telemetry_pcie_speed_data_to_string(data[1])); | |||
| 96 | printf(" Width : 0x%02x %s\n", | |||
| 97 | data[2], telemetry_pcie_width_data_to_string(data[2])); | |||
| 98 | if (size > 4) { | |||
| 99 | printf(" VU Data : "); | |||
| 100 | for (j = 4; j < size; j++) | |||
| 101 | printf("%x", data[j]); | |||
| 102 | printf("\n\n"); | |||
| 103 | } | |||
| 104 | break; | |||
| 105 | ||||
| 106 | case TELEMETRY_NVME_CLASS: | |||
| 107 | printf(" Event ID : 0x%04x %s\n", | |||
| 108 | id, telemetry_nvme_event_id_to_string(id)); | |||
| 109 | if ((id == ADMIN_QUEUE_NONZERO_STATUS) || | |||
| 110 | (id == IO_QUEUE_NONZERO_STATUS)) { | |||
| 111 | printf(" Cmd Op Code : 0x%02x\n", data[0]); | |||
| 112 | __u16 status; | |||
| 113 | __u16 cmd_id; | |||
| 114 | __u16 sq_id; | |||
| 115 | ||||
| 116 | memcpy(&status, &data[1], sizeof(status)); | |||
| 117 | memcpy(&cmd_id, &data[3], sizeof(cmd_id)); | |||
| 118 | memcpy(&sq_id, &data[5], sizeof(sq_id)); | |||
| 119 | ||||
| 120 | printf(" Status Code : 0x%04x\n", le16_to_cpu(status)); | |||
| 121 | printf(" Cmd ID : 0x%04x\n", le16_to_cpu(cmd_id)); | |||
| 122 | printf(" SQ ID : 0x%04x\n", le16_to_cpu(sq_id)); | |||
| 123 | printf(" LID,FID,Other Cmd Reserved : 0x%02x\n", data[7]); | |||
| 124 | } else if (id == CC_REGISTER_CHANGED) { | |||
| 125 | __u32 cc_reg_data = *(__u32 *)data; | |||
| 126 | ||||
| 127 | printf(" CC Reg Data : 0x%08x\n", | |||
| 128 | le32_to_cpu(cc_reg_data)); | |||
| 129 | } else if (id == CSTS_REGISTER_CHANGED) { | |||
| 130 | __u32 csts_reg_data = *(__u32 *)data; | |||
| 131 | ||||
| 132 | printf(" CSTS Reg Data : 0x%08x\n", | |||
| 133 | le32_to_cpu(csts_reg_data)); | |||
| 134 | } else if (id == OOB_COMMAND) { | |||
| 135 | printf(" Cmd Op Code : 0x%02x\n", data[0]); | |||
| 136 | __u16 status; | |||
| 137 | memcpy(&status, &data[1], sizeof(status)); | |||
| 138 | ||||
| 139 | printf(" Admin Cmd Status : 0x%04x\n", le16_to_cpu(status)); | |||
| 140 | printf(" NVMe MI SC : 0x%02x\n", data[3]); | |||
| 141 | printf(" Byte1 Req Msg : 0x%02x\n", data[4]); | |||
| 142 | printf(" Byte2 Req Msg : 0x%02x\n", data[5]); | |||
| 143 | } else if (id == OOB_AER_EVENT_MSG_TRANS) { | |||
| 144 | __u64 aem = *(__u64 *)data; | |||
| 145 | ||||
| 146 | printf(" AEM : 0x%016"PRIx64"l" "x""\n", | |||
| 147 | le64_to_cpu(aem)); | |||
| 148 | } | |||
| 149 | if (size > 8) | |||
| 150 | print_vu_event_data((size-8), (__u8 *)&data[8]); | |||
| 151 | break; | |||
| 152 | ||||
| 153 | case TELEMETRY_RESET_CLASS: | |||
| 154 | printf(" Event ID : 0x%04x %s\n", | |||
| 155 | id, telemetry_reset_event_id_to_string(id)); | |||
| 156 | if (size) | |||
| 157 | print_vu_event_data(size, data); | |||
| 158 | break; | |||
| 159 | ||||
| 160 | case TELEMETRY_BOOT_SEQ_CLASS: | |||
| 161 | printf(" Event ID : 0x%04x %s\n", | |||
| 162 | id, telemetry_boot_seq_event_id_to_string(id)); | |||
| 163 | if (size) | |||
| 164 | print_vu_event_data(size, data); | |||
| 165 | break; | |||
| 166 | ||||
| 167 | case TELEMETRY_FW_ASSERT_CLASS: | |||
| 168 | printf(" Event ID : 0x%04x %s\n", | |||
| 169 | id, telemetry_fw_assert_event_id_to_string(id)); | |||
| 170 | if (size) | |||
| 171 | print_vu_event_data(size, data); | |||
| 172 | break; | |||
| 173 | ||||
| 174 | case TELEMETRY_TEMPERATURE_CLASS: | |||
| 175 | printf(" Event ID : 0x%04x %s\n", | |||
| 176 | id, telemetry_temperature_event_id_to_string(id)); | |||
| 177 | if (size) | |||
| 178 | print_vu_event_data(size, data); | |||
| 179 | break; | |||
| 180 | ||||
| 181 | case TELEMETRY_MEDIA_DBG_CLASS: | |||
| 182 | printf(" Event ID : 0x%04x %s\n", | |||
| 183 | id, telemetry_media_debug_event_id_to_string(id)); | |||
| 184 | if (size) | |||
| 185 | print_vu_event_data(size, data); | |||
| 186 | break; | |||
| 187 | ||||
| 188 | case TELEMETRY_MEDIA_WEAR_CLASS: | |||
| 189 | printf(" Event ID : 0x%04x %s\n", | |||
| 190 | id, telemetry_media_wear_event_id_to_string(id)); | |||
| 191 | __u32 host_tb_written = *(__u32 *)&data[0]; | |||
| 192 | __u32 media_tb_written = *(__u32 *)&data[4]; | |||
| 193 | __u32 media_tb_erased = *(__u32 *)&data[8]; | |||
| 194 | ||||
| 195 | printf(" Host TB Written : 0x%04x\n", | |||
| 196 | le16_to_cpu(host_tb_written)); | |||
| 197 | printf(" Media TB Written : 0x%04x\n", | |||
| 198 | le16_to_cpu(media_tb_written)); | |||
| 199 | printf(" Media TB Erased : 0x%04x\n", | |||
| 200 | le16_to_cpu(media_tb_erased)); | |||
| 201 | ||||
| 202 | if (size > 12) | |||
| 203 | print_vu_event_data((size-12), (__u8 *)&data[12]); | |||
| 204 | break; | |||
| 205 | ||||
| 206 | case TELEMETRY_STAT_SNAPSHOT_CLASS: | |||
| 207 | printf(" Statistic ID : 0x%02x %s\n", | |||
| 208 | id, telemetry_stat_id_to_string(id)); | |||
| 209 | print_stats_desc((struct telemetry_stats_desc *)data); | |||
| 210 | break; | |||
| 211 | ||||
| 212 | case TELEMETRY_VIRTUAL_FIFO_EVENT_CLASS: | |||
| 213 | printf(" Event ID : 0x%04x %s\n", | |||
| 214 | id, telemetry_virtual_fifo_event_id_to_string(id)); | |||
| 215 | ||||
| 216 | __u16 vu_event_id = *(__u16 *)data; | |||
| 217 | ||||
| 218 | printf(" VU Virtual FIFO Event ID : 0x%02x\n", le16_to_cpu(vu_event_id)); | |||
| 219 | printf("\n"); | |||
| 220 | break; | |||
| 221 | ||||
| 222 | default: | |||
| 223 | /* | |||
| 224 | * printf("Unknown Event Class Type\n"); | |||
| 225 | * printf("Data : 0x"); | |||
| 226 | * for (j = 0; j < size; j++) | |||
| 227 | * printf("%x", data[j]); | |||
| 228 | * printf("\n\n"); | |||
| 229 | */ | |||
| 230 | break; | |||
| 231 | } | |||
| 232 | } | |||
| 233 | ||||
| 234 | struct statistic_entry statistic_identifiers_map[] = { | |||
| 235 | { 0x00, "Error, this entry does not exist." }, | |||
| 236 | { 0x01, "Outstanding Admin Commands" }, | |||
| 237 | { 0x02, "Host Write Bandwidth"}, | |||
| 238 | { 0x03, "GC Write Bandwidth"}, | |||
| 239 | { 0x04, "Active Namespaces"}, | |||
| 240 | { 0x05, "Internal Write Workload"}, | |||
| 241 | { 0x06, "Internal Read Workload"}, | |||
| 242 | { 0x07, "Internal Write Queue Depth"}, | |||
| 243 | { 0x08, "Internal Read Queue Depth"}, | |||
| 244 | { 0x09, "Pending Trim LBA Count"}, | |||
| 245 | { 0x0A, "Host Trim LBA Request Count"}, | |||
| 246 | { 0x0B, "Current NVMe Power State"}, | |||
| 247 | { 0x0C, "Current DSSD Power State"}, | |||
| 248 | { 0x0D, "Program Fail Count"}, | |||
| 249 | { 0x0E, "Erase Fail Count"}, | |||
| 250 | { 0x0F, "Read Disturb Writes"}, | |||
| 251 | { 0x10, "Retention Writes"}, | |||
| 252 | { 0x11, "Wear Leveling Writes"}, | |||
| 253 | { 0x12, "Read Recovery Writes"}, | |||
| 254 | { 0x13, "GC Writes"}, | |||
| 255 | { 0x14, "SRAM Correctable Count"}, | |||
| 256 | { 0x15, "DRAM Correctable Count"}, | |||
| 257 | { 0x16, "SRAM Uncorrectable Count"}, | |||
| 258 | { 0x17, "DRAM Uncorrectable Count"}, | |||
| 259 | { 0x18, "Data Integrity Error Count"}, | |||
| 260 | { 0x19, "Read Retry Error Count"}, | |||
| 261 | { 0x1A, "PERST Events Count"}, | |||
| 262 | { 0x1B, "Max Die Bad Block"}, | |||
| 263 | { 0x1C, "Max NAND Channel Bad Block"}, | |||
| 264 | { 0x1D, "Minimum NAND Channel Bad Block"}, | |||
| 265 | { 0x1E, "Physical Media Units Written"}, | |||
| 266 | { 0x1F, "Physical Media Units Read"}, | |||
| 267 | { 0x20, "Bad User NAND Blocks"}, | |||
| 268 | { 0x21, "Bad System NAND Blocks"}, | |||
| 269 | { 0x22, "XOR Recovery Count"}, | |||
| 270 | { 0x23, "Uncorrectable Read Error Count"}, | |||
| 271 | { 0x24, "Soft ECC Error Count"}, | |||
| 272 | { 0x25, "End to End Correction Counts"}, | |||
| 273 | { 0x26, "System Data % Used"}, | |||
| 274 | { 0x27, "Refresh Counts"}, | |||
| 275 | { 0x28, "User Data Erase Counts"}, | |||
| 276 | { 0x29, "Thermal Throttling Status and Count"}, | |||
| 277 | { 0x2A, "DSSD Specification Version"}, | |||
| 278 | { 0x2B, "PCIe Correctable Error Count"}, | |||
| 279 | { 0x2C, "Incomplete Shutdowns"}, | |||
| 280 | { 0x2D, "% Free Blocks"}, | |||
| 281 | { 0x2E, "Capacitor Health"}, | |||
| 282 | { 0x2F, "NVM Express Base Errata Version"}, | |||
| 283 | { 0x30, "NVM Command Set Errata Version"}, | |||
| 284 | { 0x31, "NVM Express Management Interface Errata Version"}, | |||
| 285 | { 0x32, "Unaligned I/O"}, | |||
| 286 | { 0x33, "Security Version Number"}, | |||
| 287 | { 0x34, "Total NUSE"}, | |||
| 288 | { 0x35, "PLP Start Count"}, | |||
| 289 | { 0x36, "Endurance Estimate"}, | |||
| 290 | { 0x37, "PCIe Link Retraining Count"}, | |||
| 291 | { 0x38, "Power State Change Count"}, | |||
| 292 | { 0x39, "Lowest Permitted Firmware Revision"}, | |||
| 293 | { 0x3A, "Log Page Version"}, | |||
| 294 | { 0x3B, "Media Dies Offline"}, | |||
| 295 | { 0x3C, "Max Temperature Recorded"}, | |||
| 296 | { 0x3D, "NAND Avg. Erase Count"}, | |||
| 297 | { 0x3E, "Command Timeouts"}, | |||
| 298 | { 0x3F, "System Area Program Fail Count"}, | |||
| 299 | { 0x40, "System Area Read Fail Count"}, | |||
| 300 | { 0x41, "System Area Erase Fail Count"}, | |||
| 301 | { 0x42, "Max Peak Power Capability"}, | |||
| 302 | { 0x43, "Current Average Power"}, | |||
| 303 | { 0x44, "Lifetime Power Consumed"}, | |||
| 304 | { 0x45, "Error / Assert Count"}, | |||
| 305 | { 0x46, "Device Busy Time"}, | |||
| 306 | { 0x47, "Critical Warning"}, | |||
| 307 | { 0x48, "Composite Temperature"}, | |||
| 308 | { 0x49, "Available Spare"}, | |||
| 309 | { 0x4A, "Available Spare Threshold"}, | |||
| 310 | { 0x4B, "Percentage Used"}, | |||
| 311 | { 0x4C, "Endurance Group Critical Warning Summary"}, | |||
| 312 | { 0x4D, "Data Units Read"}, | |||
| 313 | { 0x4E, "Data Units Written"}, | |||
| 314 | { 0x4F, "Host Read Commands"}, | |||
| 315 | { 0x50, "Host Write Commands"}, | |||
| 316 | { 0x51, "Controller Busy Time"}, | |||
| 317 | { 0x52, "Power Cycles"}, | |||
| 318 | { 0x53, "Power On Hours"}, | |||
| 319 | { 0x54, "Unsafe Shutdowns"}, | |||
| 320 | { 0x55, "Media and Data Integrity Errors"}, | |||
| 321 | { 0x56, "Number of Error Information Log Entries"}, | |||
| 322 | { 0x57, "Warning Composite Temperature Time"}, | |||
| 323 | { 0x58, "Critical Composite Temperature Time"}, | |||
| 324 | { 0x59, "Temperature Sensor 1"}, | |||
| 325 | { 0x5A, "Temperature Sensor 2"}, | |||
| 326 | { 0x5B, "Temperature Sensor 3"}, | |||
| 327 | { 0x5C, "Temperature Sensor 4"}, | |||
| 328 | { 0x5D, "Temperature Sensor 5"}, | |||
| 329 | { 0x5E, "Temperature Sensor 6"}, | |||
| 330 | { 0x5F, "Temperature Sensor 7"}, | |||
| 331 | { 0x60, "Temperature Sensor 8"}, | |||
| 332 | { 0x61, "Thermal Management Temperature 1 Transition Count"}, | |||
| 333 | { 0x62, "Thermal Management Temperature 2 Transition Count"}, | |||
| 334 | { 0x63, "Total Time For Thermal Management Temperature 1"}, | |||
| 335 | { 0x64, "Total Time For Thermal Management Temperature 2"}, | |||
| 336 | { 0x65, "Endurance Estimate"}, | |||
| 337 | { 0x66, "Data Units Read"}, | |||
| 338 | { 0x67, "Data Units Written"}, | |||
| 339 | { 0x68, "Media Units Written"}, | |||
| 340 | { 0x69, "Number of Error Information Log Entries"}, | |||
| 341 | { 0x6A, "Form Factor"}, | |||
| 342 | { 0x6B, "Dies In Use Bad NAND Blocks"}, | |||
| 343 | { 0x6C, "Proactive Bad Die Retirement"}, | |||
| 344 | { 0x6D, "Namespace ID Context Statistic Descriptor"}, | |||
| 345 | { 0x6E, "Controller ID Context Statistic Descriptor"}, | |||
| 346 | { 0x6F, "Queue ID Context Statistic Descriptor"} | |||
| 347 | }; | |||
| 348 | ||||
| 349 | struct request_data host_log_page_header[] = { | |||
| 350 | { "LogIdentifier", 1 }, | |||
| 351 | { "Reserved1", 4 }, | |||
| 352 | { "IEEE OUI Identifier", 3 }, | |||
| 353 | { "Telemetry Host-Initiated Data Area 1 Last Block", 2 }, | |||
| 354 | { "Telemetry Host-Initiated Data Area 2 Last Block", 2 }, | |||
| 355 | { "Telemetry Host-Initiated Data Area 3 Last Block", 2 }, | |||
| 356 | { "Reserved2", 2 }, | |||
| 357 | { "Telemetry Host-Initiated Data Area 4 Last Block", 4 }, | |||
| 358 | { "Reserved3", 360 }, | |||
| 359 | { "Telemetry Host-Initiated Scope", 1 }, | |||
| 360 | { "Telemetry Host Initiated Generation Number", 1 }, | |||
| 361 | { "Telemetry Host-Initiated Data Available", 1 }, | |||
| 362 | { "Telemetry Controller-Initiated Data Generation Number", 1 } | |||
| 363 | }; | |||
| 364 | ||||
| 365 | struct request_data controller_log_page_header[] = { | |||
| 366 | { "LogIdentifier", 1 }, | |||
| 367 | { "Reserved1", 4 }, | |||
| 368 | { "IEEE OUI Identifier", 3 }, | |||
| 369 | { "Telemetry Host-Initiated Data Area 1 Last Block", 2 }, | |||
| 370 | { "Telemetry Host-Initiated Data Area 2 Last Block", 2 }, | |||
| 371 | { "Telemetry Host-Initiated Data Area 3 Last Block", 2 }, | |||
| 372 | { "Reserved2", 2 }, | |||
| 373 | { "Telemetry Host-Initiated Data Area 4 Last Block", 4 }, | |||
| 374 | { "Reserved3", 361 }, | |||
| 375 | { "Telemetry Controller-Initiated Scope", 1 }, | |||
| 376 | { "Telemetry Controller-Initiated Data Available", 1 }, | |||
| 377 | { "Telemetry Controller-Initiated Data Generation Number", 1 } | |||
| 378 | }; | |||
| 379 | ||||
| 380 | struct request_data reason_identifier[] = { | |||
| 381 | { "Error ID", 64 }, | |||
| 382 | { "File ID", 8 }, | |||
| 383 | { "Line Number", 2 }, | |||
| 384 | { "Valid Flags", 1 }, | |||
| 385 | { "Reserved", 21 }, | |||
| 386 | { "VU Reason Extension", 32 } | |||
| 387 | }; | |||
| 388 | ||||
| 389 | struct request_data ocp_header_in_da1[] = { | |||
| 390 | { "Major Version", 2 }, | |||
| 391 | { "Minor Version", 2 }, | |||
| 392 | { "Reserved1", 4 }, | |||
| 393 | { "Timestamp", 8 }, | |||
| 394 | { "Log page GUID", GUID_LEN16 }, | |||
| 395 | { "Number Telemetry Profiles Supported", 1 }, | |||
| 396 | { "Telemetry Profile Selected", 1 }, | |||
| 397 | { "Reserved2", 6 }, | |||
| 398 | { "Telemetry String Log Size", 8 }, | |||
| 399 | { "Reserved3", 8 }, | |||
| 400 | { "Firmware Revision", 8 }, | |||
| 401 | { "Reserved4", 32 }, | |||
| 402 | { "Data Area 1 Statistic Start", 8 }, | |||
| 403 | { "Data Area 1 Statistic Size", 8 }, | |||
| 404 | { "Data Area 2 Statistic Start", 8 }, | |||
| 405 | { "Data Area 2 Statistic Size", 8 }, | |||
| 406 | { "Reserved5", 32 }, | |||
| 407 | { "Event FIFO 1 Data Area", 1 }, | |||
| 408 | { "Event FIFO 2 Data Area", 1 }, | |||
| 409 | { "Event FIFO 3 Data Area", 1 }, | |||
| 410 | { "Event FIFO 4 Data Area", 1 }, | |||
| 411 | { "Event FIFO 5 Data Area", 1 }, | |||
| 412 | { "Event FIFO 6 Data Area", 1 }, | |||
| 413 | { "Event FIFO 7 Data Area", 1 }, | |||
| 414 | { "Event FIFO 8 Data Area", 1 }, | |||
| 415 | { "Event FIFO 9 Data Area", 1 }, | |||
| 416 | { "Event FIFO 10 Data Area", 1 }, | |||
| 417 | { "Event FIFO 11 Data Area", 1 }, | |||
| 418 | { "Event FIFO 12 Data Area", 1 }, | |||
| 419 | { "Event FIFO 13 Data Area", 1 }, | |||
| 420 | { "Event FIFO 14 Data Area", 1 }, | |||
| 421 | { "Event FIFO 15 Data Area", 1 }, | |||
| 422 | { "Event FIFO 16 Data Area", 1 }, | |||
| 423 | { "Event FIFO 1 Start", 8 }, | |||
| 424 | { "Event FIFO 1 Size", 8 }, | |||
| 425 | { "Event FIFO 2 Start", 8 }, | |||
| 426 | { "Event FIFO 2 Size", 8 }, | |||
| 427 | { "Event FIFO 3 Start", 8 }, | |||
| 428 | { "Event FIFO 3 Size", 8 }, | |||
| 429 | { "Event FIFO 4 Start", 8 }, | |||
| 430 | { "Event FIFO 4 Size", 8 }, | |||
| 431 | { "Event FIFO 5 Start", 8 }, | |||
| 432 | { "Event FIFO 5 Size", 8 }, | |||
| 433 | { "Event FIFO 6 Start", 8 }, | |||
| 434 | { "Event FIFO 6 Size", 8 }, | |||
| 435 | { "Event FIFO 7 Start", 8 }, | |||
| 436 | { "Event FIFO 7 Size", 8 }, | |||
| 437 | { "Event FIFO 8 Start", 8 }, | |||
| 438 | { "Event FIFO 8 Size", 8 }, | |||
| 439 | { "Event FIFO 9 Start", 8 }, | |||
| 440 | { "Event FIFO 9 Size", 8 }, | |||
| 441 | { "Event FIFO 10 Start", 8 }, | |||
| 442 | { "Event FIFO 10 Size", 8 }, | |||
| 443 | { "Event FIFO 11 Start", 8 }, | |||
| 444 | { "Event FIFO 11 Size", 8 }, | |||
| 445 | { "Event FIFO 12 Start", 8 }, | |||
| 446 | { "Event FIFO 12 Size", 8 }, | |||
| 447 | { "Event FIFO 13 Start", 8 }, | |||
| 448 | { "Event FIFO 13 Size", 8 }, | |||
| 449 | { "Event FIFO 14 Start", 8 }, | |||
| 450 | { "Event FIFO 14 Size", 8 }, | |||
| 451 | { "Event FIFO 15 Start", 8 }, | |||
| 452 | { "Event FIFO 15 Size", 8 }, | |||
| 453 | { "Event FIFO 16 Start", 8 }, | |||
| 454 | { "Event FIFO 16 Size", 8 }, | |||
| 455 | { "Reserved6", 80 } | |||
| 456 | }; | |||
| 457 | ||||
| 458 | struct request_data smart[] = { | |||
| 459 | { "Critical Warning", 1 }, | |||
| 460 | { "Composite Temperature", 2 }, | |||
| 461 | { "Available Spare", 1 }, | |||
| 462 | { "Available Spare Threshold", 1 }, | |||
| 463 | { "Percentage Used", 1 }, | |||
| 464 | { "Reserved1", 26 }, | |||
| 465 | { "Data Units Read", 16 }, | |||
| 466 | { "Data Units Written", 16 }, | |||
| 467 | { "Host Read Commands", 16 }, | |||
| 468 | { "Host Write Commands", 16 }, | |||
| 469 | { "Controller Busy Time", 16 }, | |||
| 470 | { "Power Cycles", 16 }, | |||
| 471 | { "Power On Hours", 16 }, | |||
| 472 | { "Unsafe Shutdowns", 16 }, | |||
| 473 | { "Media and Data Integrity Errors", 16 }, | |||
| 474 | { "Number of Error Information Log Entries", 16 }, | |||
| 475 | { "Warning Composite Temperature Time", 4 }, | |||
| 476 | { "Critical Composite Temperature Time", 4 }, | |||
| 477 | { "Temperature Sensor 1", 2 }, | |||
| 478 | { "Temperature Sensor 2", 2 }, | |||
| 479 | { "Temperature Sensor 3", 2 }, | |||
| 480 | { "Temperature Sensor 4", 2 }, | |||
| 481 | { "Temperature Sensor 5", 2 }, | |||
| 482 | { "Temperature Sensor 6", 2 }, | |||
| 483 | { "Temperature Sensor 7", 2 }, | |||
| 484 | { "Temperature Sensor 8", 2 }, | |||
| 485 | { "Thermal Management Temperature 1 Transition Count", 4 }, | |||
| 486 | { "Thermal Management Temperature 2 Transition Count", 4 }, | |||
| 487 | { "Total Time for Thermal Management Temperature 1", 4 }, | |||
| 488 | { "Total Time for Thermal Management Temperature 2", 4 }, | |||
| 489 | { "Reserved2", 280 } | |||
| 490 | }; | |||
| 491 | ||||
| 492 | struct request_data smart_extended[] = { | |||
| 493 | { "Physical Media Units Written", 16 }, | |||
| 494 | { "Physical Media Units Read", 16 }, | |||
| 495 | { "Bad User NAND Blocks Raw Count", 6 }, | |||
| 496 | { "Bad User NAND Blocks Normalized Value", 2 }, | |||
| 497 | { "Bad System NAND Blocks Raw Count", 6 }, | |||
| 498 | { "Bad System NAND Blocks Normalized Value", 2 }, | |||
| 499 | { "XOR Recovery Count", 8 }, | |||
| 500 | { "Uncorrectable Read Error Count", 8 }, | |||
| 501 | { "Soft ECC Error Count", 8 }, | |||
| 502 | { "End to End Correction Counts Detected Errors", 4 }, | |||
| 503 | { "End to End Correction Counts Corrected Errors", 4 }, | |||
| 504 | { "System Data Percent Used", 1 }, | |||
| 505 | { "Refresh Counts", 7 }, | |||
| 506 | { "Maximum User Data Erase Count", 4 }, | |||
| 507 | { "Minimum User Data Erase Count", 4 }, | |||
| 508 | { "Number of thermal throttling events", 1 }, | |||
| 509 | { "Current Throttling Status", 1 }, | |||
| 510 | { "Errata Version Field", 1 }, | |||
| 511 | { "Point Version Field", 2 }, | |||
| 512 | { "Minor Version Field", 2 }, | |||
| 513 | { "Major Version Field", 1 }, | |||
| 514 | { "PCIe Correctable Error Count", 8 }, | |||
| 515 | { "Incomplete Shutdowns", 4 }, | |||
| 516 | { "Reserved1", 4 }, | |||
| 517 | { "Percent Free Blocks", 1 }, | |||
| 518 | { "Reserved2", 7 }, | |||
| 519 | { "Capacitor Health", 2 }, | |||
| 520 | { "NVMe Base Errata Version", 1 }, | |||
| 521 | { "NVMe Command Set Errata Version", 1 }, | |||
| 522 | { "Reserved3", 4 }, | |||
| 523 | { "Unaligned IO", 8 }, | |||
| 524 | { "Security Version Number", 8 }, | |||
| 525 | { "Total NUSE", 8 }, | |||
| 526 | { "PLP Start Count", 16 }, | |||
| 527 | { "Endurance Estimate", 16 }, | |||
| 528 | { "PCIe Link Retraining Count", 8 }, | |||
| 529 | { "Power State Change Count", 8 }, | |||
| 530 | { "Lowest Permitted Firmware Revision", 8 }, | |||
| 531 | { "Reserved4", 278 }, | |||
| 532 | { "Log Page Version", 2 }, | |||
| 533 | { "Log page GUID", GUID_LEN16 } | |||
| 534 | }; | |||
| 535 | ||||
| 536 | #ifdef CONFIG_JSONC | |||
| 537 | void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata) | |||
| 538 | { | |||
| 539 | char data_str[70] = { 0 }; | |||
| 540 | ||||
| 541 | sprintf(data_str, "0x%x", pdata); | |||
| 542 | json_object_add_value_string(pobject, msg, data_str); | |||
| 543 | } | |||
| 544 | ||||
| 545 | void json_add_formatted_var_size_str(struct json_object *pobject, const char *msg, __u8 *pdata, | |||
| 546 | unsigned int data_size) | |||
| 547 | { | |||
| 548 | char *description_str = NULL((void*)0); | |||
| 549 | char temp_buffer[3] = { 0 }; | |||
| 550 | ||||
| 551 | /* Allocate 2 chars for each value in the data + 2 bytes for the null terminator */ | |||
| 552 | description_str = (char *) calloc(1, data_size*2 + 2); | |||
| 553 | ||||
| 554 | for (size_t i = 0; i < data_size; ++i) { | |||
| 555 | sprintf(temp_buffer, "%02X", pdata[i]); | |||
| 556 | strcat(description_str, temp_buffer); | |||
| 557 | } | |||
| 558 | ||||
| 559 | json_object_add_value_string(pobject, msg, description_str); | |||
| 560 | free(description_str); | |||
| 561 | } | |||
| 562 | #endif /* CONFIG_JSONC */ | |||
| 563 | ||||
| 564 | int get_telemetry_das_offset_and_size( | |||
| 565 | struct nvme_ocp_telemetry_common_header *ptelemetry_common_header, | |||
| 566 | struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset) | |||
| 567 | { | |||
| 568 | if (NULL((void*)0) == ptelemetry_common_header || NULL((void*)0) == ptelemetry_das_offset) { | |||
| 569 | nvme_show_error("Invalid input arguments.")nvme_show_message(1, "Invalid input arguments."); | |||
| 570 | return -1; | |||
| 571 | } | |||
| 572 | ||||
| 573 | if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_HOST) | |||
| 574 | ptelemetry_das_offset->header_size = | |||
| 575 | sizeof(struct nvme_ocp_telemetry_host_initiated_header); | |||
| 576 | else if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_CTRL) | |||
| 577 | ptelemetry_das_offset->header_size = | |||
| 578 | sizeof(struct nvme_ocp_telemetry_controller_initiated_header); | |||
| 579 | else | |||
| 580 | return -1; | |||
| 581 | ||||
| 582 | ptelemetry_das_offset->da1_start_offset = ptelemetry_das_offset->header_size; | |||
| 583 | ptelemetry_das_offset->da1_size = ptelemetry_common_header->da1_last_block * | |||
| 584 | OCP_TELEMETRY_DATA_BLOCK_SIZE512; | |||
| 585 | ||||
| 586 | ptelemetry_das_offset->da2_start_offset = ptelemetry_das_offset->da1_start_offset + | |||
| 587 | ptelemetry_das_offset->da1_size; | |||
| 588 | ptelemetry_das_offset->da2_size = | |||
| 589 | (ptelemetry_common_header->da2_last_block - | |||
| 590 | ptelemetry_common_header->da1_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512; | |||
| 591 | ||||
| 592 | ptelemetry_das_offset->da3_start_offset = ptelemetry_das_offset->da2_start_offset + | |||
| 593 | ptelemetry_das_offset->da2_size; | |||
| 594 | ptelemetry_das_offset->da3_size = | |||
| 595 | (ptelemetry_common_header->da3_last_block - | |||
| 596 | ptelemetry_common_header->da2_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512; | |||
| 597 | ||||
| 598 | ptelemetry_das_offset->da4_start_offset = ptelemetry_das_offset->da3_start_offset + | |||
| 599 | ptelemetry_das_offset->da3_size; | |||
| 600 | ptelemetry_das_offset->da4_size = | |||
| 601 | (ptelemetry_common_header->da4_last_block - | |||
| 602 | ptelemetry_common_header->da3_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512; | |||
| 603 | ||||
| 604 | return 0; | |||
| 605 | } | |||
| 606 | ||||
| 607 | int get_statistic_id_ascii_string(int identifier, char *description) | |||
| 608 | { | |||
| 609 | if (!pstring_buffer || !description) | |||
| 610 | return -1; | |||
| 611 | ||||
| 612 | struct nvme_ocp_telemetry_string_header *pocp_ts_header = | |||
| 613 | (struct nvme_ocp_telemetry_string_header *)pstring_buffer; | |||
| 614 | ||||
| 615 | //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS, | |||
| 616 | //So multiplying with sizeof(DWORD) | |||
| 617 | unsigned long long sits_table_size = (pocp_ts_header->sitsz) * SIZE_OF_DWORD4; | |||
| 618 | ||||
| 619 | //Calculating number of entries present in all 3 tables | |||
| 620 | int sits_entries = (int)sits_table_size / | |||
| 621 | sizeof(struct nvme_ocp_statistics_identifier_string_table); | |||
| 622 | ||||
| 623 | for (int sits_entry = 0; sits_entry < sits_entries; sits_entry++) { | |||
| 624 | struct nvme_ocp_statistics_identifier_string_table | |||
| 625 | *peach_statistic_entry = | |||
| 626 | (struct nvme_ocp_statistics_identifier_string_table *) | |||
| 627 | (pstring_buffer + (pocp_ts_header->sits * SIZE_OF_DWORD4) + | |||
| 628 | (sits_entry * | |||
| 629 | sizeof(struct nvme_ocp_statistics_identifier_string_table))); | |||
| 630 | ||||
| 631 | if (identifier == (int)peach_statistic_entry->vs_statistic_identifier) { | |||
| 632 | char *pdescription = (char *)(pstring_buffer + | |||
| 633 | (pocp_ts_header->ascts * SIZE_OF_DWORD4) + | |||
| 634 | (peach_statistic_entry->ascii_id_offset * | |||
| 635 | SIZE_OF_DWORD4)); | |||
| 636 | ||||
| 637 | memcpy(description, pdescription, | |||
| 638 | peach_statistic_entry->ascii_id_length + 1); | |||
| 639 | ||||
| 640 | return 0; | |||
| 641 | } | |||
| 642 | } | |||
| 643 | ||||
| 644 | // If ASCII string isn't found, see in our internal Map | |||
| 645 | // for 2.5 Spec defined strings | |||
| 646 | if (identifier <= 0x6F) { | |||
| 647 | strcpy(description, statistic_identifiers_map[identifier].description); | |||
| 648 | return 0; | |||
| 649 | } | |||
| 650 | ||||
| 651 | return -1; | |||
| 652 | } | |||
| 653 | ||||
| 654 | int get_event_id_ascii_string(int identifier, int debug_event_class, char *description) | |||
| 655 | { | |||
| 656 | if (pstring_buffer == NULL((void*)0)) | |||
| 657 | return -1; | |||
| 658 | ||||
| 659 | struct nvme_ocp_telemetry_string_header *pocp_ts_header = | |||
| 660 | (struct nvme_ocp_telemetry_string_header *)pstring_buffer; | |||
| 661 | ||||
| 662 | //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS, | |||
| 663 | //So multiplying with sizeof(DWORD) | |||
| 664 | unsigned long long ests_table_size = (pocp_ts_header->estsz) * SIZE_OF_DWORD4; | |||
| 665 | ||||
| 666 | //Calculating number of entries present in all 3 tables | |||
| 667 | int ests_entries = (int)ests_table_size / sizeof(struct nvme_ocp_event_string_table); | |||
| 668 | ||||
| 669 | for (int ests_entry = 0; ests_entry < ests_entries; ests_entry++) { | |||
| 670 | struct nvme_ocp_event_string_table *peach_event_entry = | |||
| 671 | (struct nvme_ocp_event_string_table *) | |||
| 672 | (pstring_buffer + (pocp_ts_header->ests * SIZE_OF_DWORD4) + | |||
| 673 | (ests_entry * sizeof(struct nvme_ocp_event_string_table))); | |||
| 674 | ||||
| 675 | if (identifier == (int)peach_event_entry->event_identifier && | |||
| 676 | debug_event_class == (int)peach_event_entry->debug_event_class) { | |||
| 677 | char *pdescription = (char *)(pstring_buffer + | |||
| 678 | (pocp_ts_header->ascts * SIZE_OF_DWORD4) + | |||
| 679 | (peach_event_entry->ascii_id_offset * SIZE_OF_DWORD4)); | |||
| 680 | ||||
| 681 | memcpy(description, pdescription, | |||
| 682 | peach_event_entry->ascii_id_length + 1); | |||
| 683 | return 0; | |||
| 684 | } | |||
| 685 | } | |||
| 686 | ||||
| 687 | return -1; | |||
| 688 | } | |||
| 689 | ||||
| 690 | int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description) | |||
| 691 | { | |||
| 692 | if (pstring_buffer == NULL((void*)0)) | |||
| 693 | return -1; | |||
| 694 | ||||
| 695 | struct nvme_ocp_telemetry_string_header *pocp_ts_header = | |||
| 696 | (struct nvme_ocp_telemetry_string_header *)pstring_buffer; | |||
| 697 | ||||
| 698 | //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS, | |||
| 699 | //So multiplying with sizeof(DWORD) | |||
| 700 | unsigned long long vuests_table_size = (pocp_ts_header->vu_estsz) * SIZE_OF_DWORD4; | |||
| 701 | ||||
| 702 | //Calculating number of entries present in all 3 tables | |||
| 703 | int vu_ests_entries = (int)vuests_table_size / | |||
| 704 | sizeof(struct nvme_ocp_vu_event_string_table); | |||
| 705 | ||||
| 706 | for (int vu_ests_entry = 0; vu_ests_entry < vu_ests_entries; vu_ests_entry++) { | |||
| 707 | struct nvme_ocp_vu_event_string_table *peach_vu_event_entry = | |||
| 708 | (struct nvme_ocp_vu_event_string_table *) | |||
| 709 | (pstring_buffer + (pocp_ts_header->vu_ests * SIZE_OF_DWORD4) + | |||
| 710 | (vu_ests_entry * sizeof(struct nvme_ocp_vu_event_string_table))); | |||
| 711 | ||||
| 712 | if (identifier == (int)peach_vu_event_entry->vu_event_identifier && | |||
| 713 | debug_event_class == | |||
| 714 | (int)peach_vu_event_entry->debug_event_class) { | |||
| 715 | char *pdescription = (char *)(pstring_buffer + | |||
| 716 | (pocp_ts_header->ascts * SIZE_OF_DWORD4) + | |||
| 717 | (peach_vu_event_entry->ascii_id_offset * SIZE_OF_DWORD4)); | |||
| 718 | ||||
| 719 | memcpy(description, pdescription, | |||
| 720 | peach_vu_event_entry->ascii_id_length + 1); | |||
| 721 | return 0; | |||
| 722 | } | |||
| 723 | } | |||
| 724 | ||||
| 725 | return -1; | |||
| 726 | } | |||
| 727 | ||||
| 728 | int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class, | |||
| 729 | enum ocp_telemetry_string_tables string_table, char *description) | |||
| 730 | { | |||
| 731 | if (pstring_buffer == NULL((void*)0)) | |||
| 732 | return -1; | |||
| 733 | ||||
| 734 | if (event_fifo_num != 0) { | |||
| 735 | struct nvme_ocp_telemetry_string_header *pocp_ts_header = | |||
| 736 | (struct nvme_ocp_telemetry_string_header *)pstring_buffer; | |||
| 737 | ||||
| 738 | if (*pocp_ts_header->fifo_ascii_string[event_fifo_num-1] != '\0') | |||
| 739 | memcpy(description, pocp_ts_header->fifo_ascii_string[event_fifo_num-1], | |||
| 740 | 16); | |||
| 741 | else | |||
| 742 | description = ""; | |||
| 743 | ||||
| 744 | return 0; | |||
| 745 | } | |||
| 746 | ||||
| 747 | if (string_table == STATISTICS_IDENTIFIER_STRING) | |||
| 748 | get_statistic_id_ascii_string(identifier, description); | |||
| 749 | else if (string_table == EVENT_STRING && debug_event_class < 0x80) | |||
| 750 | get_event_id_ascii_string(identifier, debug_event_class, description); | |||
| 751 | else if (string_table == VU_EVENT_STRING || debug_event_class >= 0x80) | |||
| 752 | get_vu_event_id_ascii_string(identifier, debug_event_class, description); | |||
| 753 | ||||
| 754 | return 0; | |||
| 755 | } | |||
| 756 | ||||
| 757 | #ifdef CONFIG_JSONC | |||
| 758 | int parse_time_stamp_event( | |||
| 759 | struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor, | |||
| 760 | struct json_object *pevent_descriptor_obj, | |||
| 761 | __u8 *pevent_specific_data, | |||
| 762 | struct json_object *pevent_fifos_object, | |||
| 763 | FILE *fp) | |||
| 764 | { | |||
| 765 | struct nvme_ocp_time_stamp_dbg_evt_class_format *ptime_stamp_event = | |||
| 766 | (struct nvme_ocp_time_stamp_dbg_evt_class_format *) pevent_specific_data; | |||
| 767 | struct nvme_ocp_common_dbg_evt_class_vu_data *ptime_stamp_event_vu_data = NULL((void*)0); | |||
| 768 | __u16 vu_event_id = 0; | |||
| 769 | __u8 *pdata = NULL((void*)0); | |||
| 770 | char description_str[256] = ""; | |||
| 771 | unsigned int vu_data_size = 0; | |||
| 772 | bool_Bool vu_data_present = false0; | |||
| 773 | ||||
| 774 | if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) > | |||
| 775 | sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)) { | |||
| 776 | vu_data_present = true1; | |||
| 777 | vu_data_size = | |||
| 778 | ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) - | |||
| 779 | (sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format) + | |||
| 780 | SIZE_OF_VU_EVENT_ID2)); | |||
| 781 | ||||
| 782 | ptime_stamp_event_vu_data = | |||
| 783 | (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ptime_stamp_event + | |||
| 784 | sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)); | |||
| 785 | vu_event_id = le16_to_cpu(ptime_stamp_event_vu_data->vu_event_identifier); | |||
| 786 | pdata = (__u8 *)&(ptime_stamp_event_vu_data->data); | |||
| 787 | ||||
| 788 | parse_ocp_telemetry_string_log(0, vu_event_id, | |||
| 789 | pevent_descriptor->debug_event_class_type, | |||
| 790 | VU_EVENT_STRING, description_str); | |||
| 791 | } else if (pevent_descriptor->event_data_size < 2) | |||
| 792 | return -1; | |||
| 793 | ||||
| 794 | if (pevent_fifos_object != NULL((void*)0)) { | |||
| 795 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 796 | ptime_stamp_event->time_stamp, DATA_SIZE_88); | |||
| 797 | if (vu_data_present) { | |||
| 798 | json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier", | |||
| 799 | vu_event_id); | |||
| 800 | json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String", | |||
| 801 | description_str); | |||
| 802 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata, | |||
| 803 | vu_data_size); | |||
| 804 | } | |||
| 805 | } else { | |||
| 806 | if (fp) { | |||
| 807 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 808 | ptime_stamp_event->time_stamp, DATA_SIZE_88, fp); | |||
| 809 | if (vu_data_present) { | |||
| 810 | fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 811 | fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 812 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 813 | } | |||
| 814 | } else { | |||
| 815 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 816 | ptime_stamp_event->time_stamp, DATA_SIZE_88, fp); | |||
| 817 | if (vu_data_present) { | |||
| 818 | printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 819 | printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 820 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 821 | } | |||
| 822 | } | |||
| 823 | } | |||
| 824 | ||||
| 825 | return 0; | |||
| 826 | } | |||
| 827 | ||||
| 828 | int parse_pcie_event( | |||
| 829 | struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor, | |||
| 830 | struct json_object *pevent_descriptor_obj, | |||
| 831 | __u8 *pevent_specific_data, | |||
| 832 | struct json_object *pevent_fifos_object, | |||
| 833 | FILE *fp) | |||
| 834 | { | |||
| 835 | struct nvme_ocp_pcie_dbg_evt_class_format *ppcie_event = | |||
| 836 | (struct nvme_ocp_pcie_dbg_evt_class_format *) pevent_specific_data; | |||
| 837 | struct nvme_ocp_common_dbg_evt_class_vu_data *ppcie_event_vu_data = NULL((void*)0); | |||
| 838 | __u16 vu_event_id = 0; | |||
| 839 | __u8 *pdata = NULL((void*)0); | |||
| 840 | char description_str[256] = ""; | |||
| 841 | unsigned int vu_data_size = 0; | |||
| 842 | bool_Bool vu_data_present = false0; | |||
| 843 | ||||
| 844 | if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) > | |||
| 845 | sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)) { | |||
| 846 | vu_data_present = true1; | |||
| 847 | vu_data_size = | |||
| 848 | ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) - | |||
| 849 | (sizeof(struct nvme_ocp_pcie_dbg_evt_class_format) + | |||
| 850 | SIZE_OF_VU_EVENT_ID2)); | |||
| 851 | ||||
| 852 | ppcie_event_vu_data = | |||
| 853 | (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ppcie_event + | |||
| 854 | sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)); | |||
| 855 | vu_event_id = le16_to_cpu(ppcie_event_vu_data->vu_event_identifier); | |||
| 856 | pdata = (__u8 *)&(ppcie_event_vu_data->data); | |||
| 857 | ||||
| 858 | parse_ocp_telemetry_string_log(0, vu_event_id, | |||
| 859 | pevent_descriptor->debug_event_class_type, | |||
| 860 | VU_EVENT_STRING, description_str); | |||
| 861 | } else if (pevent_descriptor->event_data_size < 1) | |||
| 862 | return -1; | |||
| 863 | ||||
| 864 | if (pevent_fifos_object != NULL((void*)0)) { | |||
| 865 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 866 | ppcie_event->pCIeDebugEventData, DATA_SIZE_44); | |||
| 867 | if (vu_data_present) { | |||
| 868 | json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier", | |||
| 869 | vu_event_id); | |||
| 870 | json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String", | |||
| 871 | description_str); | |||
| 872 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata, | |||
| 873 | vu_data_size); | |||
| 874 | } | |||
| 875 | } else { | |||
| 876 | if (fp) { | |||
| 877 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 878 | ppcie_event->pCIeDebugEventData, DATA_SIZE_44, fp); | |||
| 879 | if (vu_data_present) { | |||
| 880 | fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 881 | fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 882 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 883 | } | |||
| 884 | } else { | |||
| 885 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 886 | ppcie_event->pCIeDebugEventData, DATA_SIZE_44, fp); | |||
| 887 | if (vu_data_present) { | |||
| 888 | printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 889 | printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 890 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 891 | } | |||
| 892 | } | |||
| 893 | } | |||
| 894 | ||||
| 895 | return 0; | |||
| 896 | } | |||
| 897 | ||||
| 898 | int parse_nvme_event( | |||
| 899 | struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor, | |||
| 900 | struct json_object *pevent_descriptor_obj, | |||
| 901 | __u8 *pevent_specific_data, | |||
| 902 | struct json_object *pevent_fifos_object, | |||
| 903 | FILE *fp) | |||
| 904 | { | |||
| 905 | struct nvme_ocp_nvme_dbg_evt_class_format *pnvme_event = | |||
| 906 | (struct nvme_ocp_nvme_dbg_evt_class_format *) pevent_specific_data; | |||
| 907 | struct nvme_ocp_common_dbg_evt_class_vu_data *pnvme_event_vu_data = NULL((void*)0); | |||
| 908 | __u16 vu_event_id = 0; | |||
| 909 | __u8 *pdata = NULL((void*)0); | |||
| 910 | char description_str[256] = ""; | |||
| 911 | unsigned int vu_data_size = 0; | |||
| 912 | bool_Bool vu_data_present = false0; | |||
| 913 | ||||
| 914 | if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) > | |||
| 915 | sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)) { | |||
| 916 | vu_data_present = true1; | |||
| 917 | vu_data_size = | |||
| 918 | ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) - | |||
| 919 | (sizeof(struct nvme_ocp_nvme_dbg_evt_class_format) + | |||
| 920 | SIZE_OF_VU_EVENT_ID2)); | |||
| 921 | pnvme_event_vu_data = | |||
| 922 | (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pnvme_event + | |||
| 923 | sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)); | |||
| 924 | ||||
| 925 | vu_event_id = le16_to_cpu(pnvme_event_vu_data->vu_event_identifier); | |||
| 926 | pdata = (__u8 *)&(pnvme_event_vu_data->data); | |||
| 927 | ||||
| 928 | parse_ocp_telemetry_string_log(0, vu_event_id, | |||
| 929 | pevent_descriptor->debug_event_class_type, | |||
| 930 | VU_EVENT_STRING, | |||
| 931 | description_str); | |||
| 932 | } else if (pevent_descriptor->event_data_size < 2) | |||
| 933 | return -1; | |||
| 934 | ||||
| 935 | if (pevent_fifos_object != NULL((void*)0)) { | |||
| 936 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 937 | pnvme_event->nvmeDebugEventData, DATA_SIZE_88); | |||
| 938 | if (vu_data_present) { | |||
| 939 | json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier", | |||
| 940 | vu_event_id); | |||
| 941 | json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String", | |||
| 942 | description_str); | |||
| 943 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata, | |||
| 944 | vu_data_size); | |||
| 945 | } | |||
| 946 | } else { | |||
| 947 | if (fp) { | |||
| 948 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 949 | pnvme_event->nvmeDebugEventData, DATA_SIZE_88, fp); | |||
| 950 | if (vu_data_present) { | |||
| 951 | fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 952 | fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 953 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 954 | } | |||
| 955 | } else { | |||
| 956 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 957 | pnvme_event->nvmeDebugEventData, DATA_SIZE_88, fp); | |||
| 958 | if (vu_data_present) { | |||
| 959 | printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 960 | printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 961 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 962 | } | |||
| 963 | } | |||
| 964 | } | |||
| 965 | ||||
| 966 | return 0; | |||
| 967 | } | |||
| 968 | ||||
| 969 | void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor, | |||
| 970 | struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data, | |||
| 971 | struct json_object *pevent_fifos_object, FILE *fp) | |||
| 972 | { | |||
| 973 | if (pevent_specific_data) { | |||
| 974 | struct nvme_ocp_common_dbg_evt_class_vu_data *pcommon_debug_event_vu_data = | |||
| 975 | (struct nvme_ocp_common_dbg_evt_class_vu_data *) pevent_specific_data; | |||
| 976 | ||||
| 977 | __u16 vu_event_id = le16_to_cpu(pcommon_debug_event_vu_data->vu_event_identifier); | |||
| 978 | char description_str[256] = ""; | |||
| 979 | __u8 *pdata = (__u8 *)&(pcommon_debug_event_vu_data->data); | |||
| 980 | ||||
| 981 | unsigned int vu_data_size = ((pevent_descriptor->event_data_size * | |||
| 982 | SIZE_OF_DWORD4) - SIZE_OF_VU_EVENT_ID2); | |||
| 983 | ||||
| 984 | parse_ocp_telemetry_string_log(0, vu_event_id, | |||
| 985 | pevent_descriptor->debug_event_class_type, | |||
| 986 | VU_EVENT_STRING, description_str); | |||
| 987 | ||||
| 988 | if (pevent_fifos_object != NULL((void*)0)) { | |||
| 989 | json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier", | |||
| 990 | vu_event_id); | |||
| 991 | json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String", | |||
| 992 | description_str); | |||
| 993 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata, | |||
| 994 | vu_data_size); | |||
| 995 | } else { | |||
| 996 | if (fp) { | |||
| 997 | fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 998 | fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 999 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 1000 | } else { | |||
| 1001 | printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 1002 | printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 1003 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 1004 | } | |||
| 1005 | } | |||
| 1006 | } | |||
| 1007 | } | |||
| 1008 | ||||
| 1009 | int parse_media_wear_event( | |||
| 1010 | struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor, | |||
| 1011 | struct json_object *pevent_descriptor_obj, | |||
| 1012 | __u8 *pevent_specific_data, | |||
| 1013 | struct json_object *pevent_fifos_object, | |||
| 1014 | FILE *fp) | |||
| 1015 | { | |||
| 1016 | struct nvme_ocp_media_wear_dbg_evt_class_format *pmedia_wear_event = | |||
| 1017 | (struct nvme_ocp_media_wear_dbg_evt_class_format *) pevent_specific_data; | |||
| 1018 | struct nvme_ocp_common_dbg_evt_class_vu_data *pmedia_wear_event_vu_data = NULL((void*)0); | |||
| 1019 | ||||
| 1020 | __u16 vu_event_id = 0; | |||
| 1021 | __u8 *pdata = NULL((void*)0); | |||
| 1022 | char description_str[256] = ""; | |||
| 1023 | unsigned int vu_data_size = 0; | |||
| 1024 | bool_Bool vu_data_present = false0; | |||
| 1025 | ||||
| 1026 | if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) > | |||
| 1027 | sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)) { | |||
| 1028 | vu_data_present = true1; | |||
| 1029 | vu_data_size = | |||
| 1030 | ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) - | |||
| 1031 | (sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format) + | |||
| 1032 | SIZE_OF_VU_EVENT_ID2)); | |||
| 1033 | ||||
| 1034 | pmedia_wear_event_vu_data = | |||
| 1035 | (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pmedia_wear_event + | |||
| 1036 | sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)); | |||
| 1037 | vu_event_id = le16_to_cpu(pmedia_wear_event_vu_data->vu_event_identifier); | |||
| 1038 | pdata = (__u8 *)&(pmedia_wear_event_vu_data->data); | |||
| 1039 | ||||
| 1040 | parse_ocp_telemetry_string_log(0, vu_event_id, | |||
| 1041 | pevent_descriptor->debug_event_class_type, | |||
| 1042 | VU_EVENT_STRING, | |||
| 1043 | description_str); | |||
| 1044 | } else if (pevent_descriptor->event_data_size < 3) | |||
| 1045 | return -1; | |||
| 1046 | ||||
| 1047 | if (pevent_fifos_object != NULL((void*)0)) { | |||
| 1048 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 1049 | pmedia_wear_event->currentMediaWear, DATA_SIZE_1212); | |||
| 1050 | if (vu_data_present) { | |||
| 1051 | json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier", | |||
| 1052 | vu_event_id); | |||
| 1053 | json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String", | |||
| 1054 | description_str); | |||
| 1055 | json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata, | |||
| 1056 | vu_data_size); | |||
| 1057 | } | |||
| 1058 | } else { | |||
| 1059 | if (fp) { | |||
| 1060 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 1061 | pmedia_wear_event->currentMediaWear, DATA_SIZE_1212, fp); | |||
| 1062 | if (vu_data_present) { | |||
| 1063 | fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 1064 | fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 1065 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 1066 | } | |||
| 1067 | } else { | |||
| 1068 | print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data", | |||
| 1069 | pmedia_wear_event->currentMediaWear, DATA_SIZE_1212, NULL((void*)0)); | |||
| 1070 | if (vu_data_present) { | |||
| 1071 | printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id); | |||
| 1072 | printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str); | |||
| 1073 | print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp); | |||
| 1074 | } | |||
| 1075 | } | |||
| 1076 | } | |||
| 1077 | ||||
| 1078 | return 0; | |||
| 1079 | } | |||
| 1080 | ||||
| 1081 | int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, | |||
| 1082 | struct json_object *pevent_fifos_object, unsigned char *pstring_buffer, | |||
| 1083 | struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp) | |||
| 1084 | { | |||
| 1085 | if (NULL((void*)0) == pfifo_start || NULL((void*)0) == poffsets) { | |||
| ||||
| 1086 | nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL"); | |||
| 1087 | return -1; | |||
| 1088 | } | |||
| 1089 | ||||
| 1090 | int status = 0, ret = 0; | |||
| 1091 | unsigned int event_fifo_number = fifo_num + 1; | |||
| 1092 | char *description = (char *)malloc((40 + 1) * sizeof(char)); | |||
| 1093 | ||||
| 1094 | memset(description, 0, sizeof(40)); | |||
| 1095 | ||||
| 1096 | status = | |||
| 1097 | parse_ocp_telemetry_string_log(event_fifo_number, 0, 0, EVENT_STRING, description); | |||
| 1098 | ||||
| 1099 | if (status
| |||
| 1100 | nvme_show_error("Failed to get C9 String. status: %d\n", status)nvme_show_message(1, "Failed to get C9 String. status: %d\n", status); | |||
| ||||
| 1101 | return -1; | |||
| 1102 | } | |||
| 1103 | ||||
| 1104 | char event_fifo_name[100] = {0}; | |||
| 1105 | ||||
| 1106 | snprintf(event_fifo_name, sizeof(event_fifo_name), "%s%d%s%s", "EVENT FIFO ", | |||
| 1107 | event_fifo_number, " - ", description); | |||
| 1108 | ||||
| 1109 | struct json_object *pevent_fifo_array = NULL((void*)0); | |||
| 1110 | ||||
| 1111 | if (pevent_fifos_object != NULL((void*)0)) | |||
| 1112 | pevent_fifo_array = json_create_array()json_object_new_array(); | |||
| 1113 | else { | |||
| 1114 | char buffer[1024] = {0}; | |||
| 1115 | ||||
| 1116 | sprintf(buffer, "%s%s\n%s", STR_LINE"==============================================================================\n", event_fifo_name, STR_LINE"==============================================================================\n"); | |||
| 1117 | if (fp) | |||
| 1118 | fprintf(fp, "%s", buffer); | |||
| 1119 | else | |||
| 1120 | printf("%s", buffer); | |||
| 1121 | } | |||
| 1122 | ||||
| 1123 | int offset_to_move = 0; | |||
| 1124 | unsigned int event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor); | |||
| 1125 | ||||
| 1126 | while ((fifo_size > 0) && (offset_to_move < fifo_size)) { | |||
| 1127 | struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor = | |||
| 1128 | (struct nvme_ocp_telemetry_event_descriptor *) | |||
| 1129 | (pfifo_start + offset_to_move); | |||
| 1130 | ||||
| 1131 | /* check if at the end of the list */ | |||
| 1132 | if (pevent_descriptor->debug_event_class_type == RESERVED_CLASS_TYPE) | |||
| 1133 | break; | |||
| 1134 | ||||
| 1135 | __u8 *pevent_specific_data = NULL((void*)0); | |||
| 1136 | __u16 event_id = 0; | |||
| 1137 | char description_str[256] = ""; | |||
| 1138 | unsigned int data_size = 0; | |||
| 1139 | ||||
| 1140 | if (pevent_descriptor != NULL((void*)0) && | |||
| 1141 | pevent_descriptor->event_data_size >= 0 && | |||
| 1142 | pevent_descriptor->debug_event_class_type != | |||
| 1143 | STATISTIC_SNAPSHOT_CLASS_TYPE) { | |||
| 1144 | event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor); | |||
| 1145 | /* Data is present in the form of DWORDS, | |||
| 1146 | * So multiplying with sizeof(DWORD) | |||
| 1147 | */ | |||
| 1148 | data_size = pevent_descriptor->event_data_size * | |||
| 1149 | SIZE_OF_DWORD4; | |||
| 1150 | ||||
| 1151 | if (pevent_descriptor != NULL((void*)0) && pevent_descriptor->event_data_size > 0) | |||
| 1152 | pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size; | |||
| 1153 | ||||
| 1154 | event_id = le16_to_cpu(pevent_descriptor->event_id); | |||
| 1155 | ||||
| 1156 | parse_ocp_telemetry_string_log(0, event_id, | |||
| 1157 | pevent_descriptor->debug_event_class_type, EVENT_STRING, | |||
| 1158 | description_str); | |||
| 1159 | ||||
| 1160 | struct json_object *pevent_descriptor_obj = | |||
| 1161 | ((pevent_fifos_object != NULL((void*)0))?json_create_object()json_object_new_object():NULL((void*)0)); | |||
| 1162 | ||||
| 1163 | if (pevent_descriptor_obj != NULL((void*)0)) { | |||
| 1164 | json_add_formatted_u32_str(pevent_descriptor_obj, | |||
| 1165 | STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1166 | pevent_descriptor->debug_event_class_type); | |||
| 1167 | json_add_formatted_u32_str(pevent_descriptor_obj, | |||
| 1168 | STR_EVENT_IDENTIFIER"Event Identifier", event_id); | |||
| 1169 | json_object_add_value_string(pevent_descriptor_obj, | |||
| 1170 | STR_EVENT_STRING"Event String", description_str); | |||
| 1171 | json_add_formatted_u32_str(pevent_descriptor_obj, | |||
| 1172 | STR_EVENT_DATA_SIZE"Event Data Size", pevent_descriptor->event_data_size); | |||
| 1173 | ||||
| 1174 | if (pevent_descriptor->debug_event_class_type >= 0x80) | |||
| 1175 | json_add_formatted_var_size_str(pevent_descriptor_obj, | |||
| 1176 | STR_VU_DATA"VU Data", pevent_specific_data, data_size); | |||
| 1177 | } else { | |||
| 1178 | if (fp) { | |||
| 1179 | fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1180 | pevent_descriptor->debug_event_class_type); | |||
| 1181 | fprintf(fp, "%s: 0x%x\n", STR_EVENT_IDENTIFIER"Event Identifier", | |||
| 1182 | event_id); | |||
| 1183 | fprintf(fp, "%s: %s\n", STR_EVENT_STRING"Event String", description_str); | |||
| 1184 | fprintf(fp, "%s: 0x%x\n", STR_EVENT_DATA_SIZE"Event Data Size", | |||
| 1185 | pevent_descriptor->event_data_size); | |||
| 1186 | } else { | |||
| 1187 | printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1188 | pevent_descriptor->debug_event_class_type); | |||
| 1189 | printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER"Event Identifier", | |||
| 1190 | event_id); | |||
| 1191 | printf("%s: %s\n", STR_EVENT_STRING"Event String", description_str); | |||
| 1192 | printf("%s: 0x%x\n", STR_EVENT_DATA_SIZE"Event Data Size", | |||
| 1193 | pevent_descriptor->event_data_size); | |||
| 1194 | } | |||
| 1195 | ||||
| 1196 | if (pevent_descriptor->debug_event_class_type >= 0x80) | |||
| 1197 | print_formatted_var_size_str(STR_VU_DATA"VU Data", | |||
| 1198 | pevent_specific_data, data_size, fp); | |||
| 1199 | } | |||
| 1200 | ||||
| 1201 | switch (pevent_descriptor->debug_event_class_type) { | |||
| 1202 | case TIME_STAMP_CLASS_TYPE: | |||
| 1203 | ret = parse_time_stamp_event(pevent_descriptor, | |||
| 1204 | pevent_descriptor_obj, | |||
| 1205 | pevent_specific_data, | |||
| 1206 | pevent_fifos_object, | |||
| 1207 | fp); | |||
| 1208 | break; | |||
| 1209 | case PCIE_CLASS_TYPE: | |||
| 1210 | ret = parse_pcie_event(pevent_descriptor, | |||
| 1211 | pevent_descriptor_obj, | |||
| 1212 | pevent_specific_data, | |||
| 1213 | pevent_fifos_object, | |||
| 1214 | fp); | |||
| 1215 | break; | |||
| 1216 | case NVME_CLASS_TYPE: | |||
| 1217 | ret = parse_nvme_event(pevent_descriptor, | |||
| 1218 | pevent_descriptor_obj, | |||
| 1219 | pevent_specific_data, | |||
| 1220 | pevent_fifos_object, | |||
| 1221 | fp); | |||
| 1222 | break; | |||
| 1223 | case RESET_CLASS_TYPE: | |||
| 1224 | case BOOT_SEQUENCE_CLASS_TYPE: | |||
| 1225 | case FIRMWARE_ASSERT_CLASS_TYPE: | |||
| 1226 | case TEMPERATURE_CLASS_TYPE: | |||
| 1227 | case MEDIA_CLASS_TYPE: | |||
| 1228 | parse_common_event(pevent_descriptor, | |||
| 1229 | pevent_descriptor_obj, | |||
| 1230 | pevent_specific_data, | |||
| 1231 | pevent_fifos_object, | |||
| 1232 | fp); | |||
| 1233 | ret = 0; | |||
| 1234 | break; | |||
| 1235 | case MEDIA_WEAR_CLASS_TYPE: | |||
| 1236 | ret = parse_media_wear_event(pevent_descriptor, | |||
| 1237 | pevent_descriptor_obj, | |||
| 1238 | pevent_specific_data, | |||
| 1239 | pevent_fifos_object, | |||
| 1240 | fp); | |||
| 1241 | break; | |||
| 1242 | case RESERVED_CLASS_TYPE: | |||
| 1243 | default: | |||
| 1244 | break; | |||
| 1245 | } | |||
| 1246 | ||||
| 1247 | if (ret) { | |||
| 1248 | fprintf(stderrstderr, | |||
| 1249 | "ERROR : OCP : Invalid NVMe Event FIFO entry\n"); | |||
| 1250 | fprintf(stderrstderr, | |||
| 1251 | "FIFO: %d, offset: 0x%x\n", | |||
| 1252 | fifo_num, offset_to_move); | |||
| 1253 | fprintf(stderrstderr, | |||
| 1254 | "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", | |||
| 1255 | pevent_descriptor->debug_event_class_type, | |||
| 1256 | pevent_descriptor->event_id, | |||
| 1257 | pevent_descriptor->event_data_size); | |||
| 1258 | goto free_desc; | |||
| 1259 | } | |||
| 1260 | ||||
| 1261 | if (pevent_descriptor_obj != NULL((void*)0) && pevent_fifo_array != NULL((void*)0)) | |||
| 1262 | json_array_add_value_object(pevent_fifo_array,json_object_array_add(pevent_fifo_array, pevent_descriptor_obj ) | |||
| 1263 | pevent_descriptor_obj)json_object_array_add(pevent_fifo_array, pevent_descriptor_obj ); | |||
| 1264 | else { | |||
| 1265 | if (fp) | |||
| 1266 | fprintf(fp, STR_LINE2"-----------------------------------------------------------------------------\n"); | |||
| 1267 | else | |||
| 1268 | printf(STR_LINE2"-----------------------------------------------------------------------------\n"); | |||
| 1269 | } | |||
| 1270 | } else if ((pevent_descriptor != NULL((void*)0)) && | |||
| 1271 | (pevent_descriptor->debug_event_class_type == | |||
| 1272 | STATISTIC_SNAPSHOT_CLASS_TYPE)) { | |||
| 1273 | parse_ocp_telemetry_string_log(0, event_id, | |||
| 1274 | pevent_descriptor->debug_event_class_type, EVENT_STRING, | |||
| 1275 | description_str); | |||
| 1276 | ||||
| 1277 | struct json_object *pevent_descriptor_obj = | |||
| 1278 | ((pevent_fifos_object != NULL((void*)0)) ? json_create_object()json_object_new_object() : NULL((void*)0)); | |||
| 1279 | ||||
| 1280 | if (pevent_descriptor_obj != NULL((void*)0)) { | |||
| 1281 | json_add_formatted_u32_str(pevent_descriptor_obj, | |||
| 1282 | STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1283 | pevent_descriptor->debug_event_class_type); | |||
| 1284 | json_object_add_value_string(pevent_descriptor_obj, | |||
| 1285 | STR_EVENT_STRING"Event String", description_str); | |||
| 1286 | } else { | |||
| 1287 | if (fp) { | |||
| 1288 | fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1289 | pevent_descriptor->debug_event_class_type); | |||
| 1290 | fprintf(fp, "%s: %s\n", STR_EVENT_STRING"Event String", description_str); | |||
| 1291 | } else { | |||
| 1292 | printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type", | |||
| 1293 | pevent_descriptor->debug_event_class_type); | |||
| 1294 | printf("%s: %s\n", STR_EVENT_STRING"Event String", description_str); | |||
| 1295 | } | |||
| 1296 | } | |||
| 1297 | ||||
| 1298 | struct nvme_ocp_statistic_snapshot_evt_class_format | |||
| 1299 | *pStaticSnapshotEvent = | |||
| 1300 | (struct nvme_ocp_statistic_snapshot_evt_class_format *) | |||
| 1301 | pevent_descriptor; | |||
| 1302 | ||||
| 1303 | event_des_size = | |||
| 1304 | sizeof(struct nvme_ocp_statistic_snapshot_evt_class_format); | |||
| 1305 | data_size = | |||
| 1306 | (le16_to_cpu((unsigned int)pStaticSnapshotEvent->stat_data_size) * | |||
| 1307 | SIZE_OF_DWORD4); | |||
| 1308 | ||||
| 1309 | struct json_object *pstats_array = | |||
| 1310 | ((pevent_fifos_object != NULL((void*)0)) ? json_create_array()json_object_new_array() : NULL((void*)0)); | |||
| 1311 | ||||
| 1312 | if (pStaticSnapshotEvent != NULL((void*)0) && | |||
| 1313 | pStaticSnapshotEvent->stat_data_size > 0) { | |||
| 1314 | __u8 *pstatistic_entry = | |||
| 1315 | (__u8 *)pStaticSnapshotEvent + | |||
| 1316 | sizeof(struct nvme_ocp_telemetry_event_descriptor); | |||
| 1317 | ||||
| 1318 | parse_statistic( | |||
| 1319 | (struct nvme_ocp_telemetry_statistic_descriptor *) | |||
| 1320 | pstatistic_entry, | |||
| 1321 | pstats_array, | |||
| 1322 | fp); | |||
| 1323 | } | |||
| 1324 | } else { | |||
| 1325 | if (fp) | |||
| 1326 | fprintf(fp, "Unknown or null event class %p\n", pevent_descriptor); | |||
| 1327 | else | |||
| 1328 | printf("Unknown or null event class %p\n", pevent_descriptor); | |||
| 1329 | ||||
| 1330 | break; | |||
| 1331 | } | |||
| 1332 | ||||
| 1333 | offset_to_move += (data_size + event_des_size); | |||
| 1334 | } | |||
| 1335 | ||||
| 1336 | if (pevent_fifos_object != NULL((void*)0) && pevent_fifo_array != NULL((void*)0)) | |||
| 1337 | json_object_add_value_array(pevent_fifos_object, event_fifo_name,json_object_object_add(pevent_fifos_object, event_fifo_name, pevent_fifo_array ) | |||
| 1338 | pevent_fifo_array)json_object_object_add(pevent_fifos_object, event_fifo_name, pevent_fifo_array ); | |||
| 1339 | ||||
| 1340 | free_desc: | |||
| 1341 | free(description); | |||
| 1342 | return ret; | |||
| 1343 | } | |||
| 1344 | ||||
| 1345 | int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets, | |||
| 1346 | FILE *fp) | |||
| 1347 | { | |||
| 1348 | if (poffsets == NULL((void*)0)) { | |||
| 1349 | nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL"); | |||
| 1350 | return -1; | |||
| 1351 | } | |||
| 1352 | ||||
| 1353 | struct json_object *pevent_fifos_object = NULL((void*)0); | |||
| 1354 | ||||
| 1355 | if (root != NULL((void*)0)) | |||
| 1356 | pevent_fifos_object = json_create_object()json_object_new_object(); | |||
| 1357 | ||||
| 1358 | __u8 *pda1_header_offset = ptelemetry_buffer + poffsets->da1_start_offset;//512 | |||
| 1359 | __u8 *pda2_offset = ptelemetry_buffer + poffsets->da2_start_offset; | |||
| 1360 | struct nvme_ocp_header_in_da1 *pda1_header = (struct nvme_ocp_header_in_da1 *) | |||
| 1361 | pda1_header_offset; | |||
| 1362 | struct nvme_ocp_event_fifo_data event_fifo[MAX_NUM_FIFOS16]; | |||
| 1363 | ||||
| 1364 | for (int fifo_num = 0; fifo_num < MAX_NUM_FIFOS16; fifo_num++) { | |||
| 1365 | event_fifo[fifo_num].event_fifo_num = fifo_num; | |||
| 1366 | event_fifo[fifo_num].event_fifo_da = pda1_header->event_fifo_da[fifo_num]; | |||
| 1367 | event_fifo[fifo_num].event_fifo_start = | |||
| 1368 | pda1_header->fifo_offsets[fifo_num].event_fifo_start; | |||
| 1369 | event_fifo[fifo_num].event_fifo_size = | |||
| 1370 | pda1_header->fifo_offsets[fifo_num].event_fifo_size; | |||
| 1371 | } | |||
| 1372 | ||||
| 1373 | //Parse all the FIFOs DA wise | |||
| 1374 | for (int fifo_no = 0; fifo_no < MAX_NUM_FIFOS16; fifo_no++) { | |||
| 1375 | if (event_fifo[fifo_no].event_fifo_da == poffsets->data_area) { | |||
| 1376 | __u64 fifo_offset = | |||
| 1377 | (event_fifo[fifo_no].event_fifo_start * SIZE_OF_DWORD4); | |||
| 1378 | __u64 fifo_size = | |||
| 1379 | (event_fifo[fifo_no].event_fifo_size * SIZE_OF_DWORD4); | |||
| 1380 | __u8 *pfifo_start = NULL((void*)0); | |||
| 1381 | ||||
| 1382 | if (event_fifo[fifo_no].event_fifo_da == 1) | |||
| 1383 | pfifo_start = pda1_header_offset + fifo_offset; | |||
| 1384 | else if (event_fifo[fifo_no].event_fifo_da == 2) | |||
| 1385 | pfifo_start = pda2_offset + fifo_offset; | |||
| 1386 | else { | |||
| 1387 | nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area)nvme_show_message(1, "Unsupported Data Area:[%d]", poffsets-> data_area); | |||
| 1388 | return -1; | |||
| 1389 | } | |||
| 1390 | ||||
| 1391 | int status = parse_event_fifo(fifo_no, pfifo_start, pevent_fifos_object, | |||
| 1392 | pstring_buffer, poffsets, fifo_size, fp); | |||
| 1393 | ||||
| 1394 | if (status != 0) { | |||
| 1395 | nvme_show_error("Failed to parse Event FIFO. status:%d\n", status)nvme_show_message(1, "Failed to parse Event FIFO. status:%d\n" , status); | |||
| 1396 | return -1; | |||
| 1397 | } | |||
| 1398 | } | |||
| 1399 | } | |||
| 1400 | ||||
| 1401 | if (pevent_fifos_object != NULL((void*)0) && root != NULL((void*)0)) { | |||
| 1402 | const char *data_area = (poffsets->data_area == 1 ? STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info" : | |||
| 1403 | STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info"); | |||
| 1404 | ||||
| 1405 | json_object_add_value_array(root, data_area, pevent_fifos_object)json_object_object_add(root, data_area, pevent_fifos_object); | |||
| 1406 | } | |||
| 1407 | ||||
| 1408 | return 0; | |||
| 1409 | } | |||
| 1410 | ||||
| 1411 | int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry, | |||
| 1412 | struct json_object *pstats_array, FILE *fp) | |||
| 1413 | { | |||
| 1414 | if (pstatistic_entry == NULL((void*)0)) { | |||
| 1415 | nvme_show_error("Statistics Input buffer was NULL")nvme_show_message(1, "Statistics Input buffer was NULL"); | |||
| 1416 | return -1; | |||
| 1417 | } | |||
| 1418 | ||||
| 1419 | if (le16_to_cpu(pstatistic_entry->statistic_id) == STATISTICS_RESERVED_ID) | |||
| 1420 | /* End of statistics entries, return -1 to stop processing the buffer */ | |||
| 1421 | return -1; | |||
| 1422 | ||||
| 1423 | unsigned int data_size = pstatistic_entry->statistic_data_size * SIZE_OF_DWORD4; | |||
| 1424 | __u8 *pdata = (__u8 *)pstatistic_entry + | |||
| 1425 | sizeof(struct nvme_ocp_telemetry_statistic_descriptor); | |||
| 1426 | char description_str[256] = ""; | |||
| 1427 | ||||
| 1428 | parse_ocp_telemetry_string_log(0, pstatistic_entry->statistic_id, 0, | |||
| 1429 | STATISTICS_IDENTIFIER_STRING, description_str); | |||
| 1430 | ||||
| 1431 | if (pstats_array != NULL((void*)0)) { | |||
| 1432 | struct json_object *pstatistics_object = json_create_object()json_object_new_object(); | |||
| 1433 | ||||
| 1434 | json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_IDENTIFIER"Statistics Identifier", | |||
| 1435 | pstatistic_entry->statistic_id); | |||
| 1436 | json_object_add_value_string(pstatistics_object, STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String", | |||
| 1437 | description_str); | |||
| 1438 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1439 | STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type", | |||
| 1440 | pstatistic_entry->statistic_info_behaviour_type); | |||
| 1441 | json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved", | |||
| 1442 | pstatistic_entry->statistic_info_reserved); | |||
| 1443 | json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_IDENTIFIER"Namespace Identifier", | |||
| 1444 | pstatistic_entry->ns_info_nsid); | |||
| 1445 | json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_INFO_VALID"Namespace Information Valid", | |||
| 1446 | pstatistic_entry->ns_info_ns_info_valid); | |||
| 1447 | json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_DATA_SIZE"Statistic Data Size", | |||
| 1448 | pstatistic_entry->statistic_data_size); | |||
| 1449 | json_add_formatted_u32_str(pstatistics_object, STR_RESERVED"Reserved", | |||
| 1450 | pstatistic_entry->reserved); | |||
| 1451 | if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) { | |||
| 1452 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1453 | STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks", | |||
| 1454 | pdata[0]); | |||
| 1455 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1456 | STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks", | |||
| 1457 | *(__u16 *)&pdata[2]); | |||
| 1458 | } else if (pstatistic_entry->statistic_id == MAX_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1459 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1460 | STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks", | |||
| 1461 | pdata[0]); | |||
| 1462 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1463 | STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks", | |||
| 1464 | *(__u16 *)&pdata[2]); | |||
| 1465 | } else if (pstatistic_entry->statistic_id == MIN_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1466 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1467 | STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks", | |||
| 1468 | pdata[0]); | |||
| 1469 | json_add_formatted_u32_str(pstatistics_object, | |||
| 1470 | STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks", | |||
| 1471 | *(__u16 *)&pdata[2]); | |||
| 1472 | } else { | |||
| 1473 | json_add_formatted_var_size_str(pstatistics_object, | |||
| 1474 | STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data", | |||
| 1475 | pdata, | |||
| 1476 | data_size); | |||
| 1477 | } | |||
| 1478 | ||||
| 1479 | if (pstatistics_object != NULL((void*)0)) | |||
| 1480 | json_array_add_value_object(pstats_array, pstatistics_object)json_object_array_add(pstats_array, pstatistics_object); | |||
| 1481 | } else { | |||
| 1482 | if (fp) { | |||
| 1483 | fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_IDENTIFIER"Statistics Identifier", | |||
| 1484 | pstatistic_entry->statistic_id); | |||
| 1485 | fprintf(fp, "%s: %s\n", STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String", description_str); | |||
| 1486 | fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type", | |||
| 1487 | pstatistic_entry->statistic_info_behaviour_type); | |||
| 1488 | fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved", | |||
| 1489 | pstatistic_entry->statistic_info_reserved); | |||
| 1490 | fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER"Namespace Identifier", | |||
| 1491 | pstatistic_entry->ns_info_nsid); | |||
| 1492 | fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_INFO_VALID"Namespace Information Valid", | |||
| 1493 | pstatistic_entry->ns_info_ns_info_valid); | |||
| 1494 | fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_DATA_SIZE"Statistic Data Size", | |||
| 1495 | pstatistic_entry->statistic_data_size); | |||
| 1496 | fprintf(fp, "%s: 0x%x\n", STR_RESERVED"Reserved", pstatistic_entry->reserved); | |||
| 1497 | if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) { | |||
| 1498 | fprintf(fp, "%s: 0x%02x\n", STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks", | |||
| 1499 | pdata[0]); | |||
| 1500 | fprintf(fp, "%s: 0x%04x\n", STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks", | |||
| 1501 | *(__u16 *)&pdata[2]); | |||
| 1502 | } else if (pstatistic_entry->statistic_id == | |||
| 1503 | MAX_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1504 | fprintf(fp, "%s: 0x%02x\n", | |||
| 1505 | STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks", | |||
| 1506 | pdata[0]); | |||
| 1507 | fprintf(fp, "%s: 0x%04x\n", | |||
| 1508 | STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks", | |||
| 1509 | *(__u16 *)&pdata[2]); | |||
| 1510 | } else if (pstatistic_entry->statistic_id == | |||
| 1511 | MIN_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1512 | fprintf(fp, "%s: 0x%02x\n", | |||
| 1513 | STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks", | |||
| 1514 | pdata[0]); | |||
| 1515 | fprintf(fp, "%s: 0x%04x\n", | |||
| 1516 | STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks", | |||
| 1517 | *(__u16 *)&pdata[2]); | |||
| 1518 | } else { | |||
| 1519 | print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data", | |||
| 1520 | pdata, | |||
| 1521 | data_size, | |||
| 1522 | fp); | |||
| 1523 | } | |||
| 1524 | fprintf(fp, STR_LINE2"-----------------------------------------------------------------------------\n"); | |||
| 1525 | } else { | |||
| 1526 | printf("%s: 0x%x\n", STR_STATISTICS_IDENTIFIER"Statistics Identifier", | |||
| 1527 | pstatistic_entry->statistic_id); | |||
| 1528 | printf("%s: %s\n", STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String", description_str); | |||
| 1529 | printf("%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type", | |||
| 1530 | pstatistic_entry->statistic_info_behaviour_type); | |||
| 1531 | printf("%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved", | |||
| 1532 | pstatistic_entry->statistic_info_reserved); | |||
| 1533 | printf("%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER"Namespace Identifier", | |||
| 1534 | pstatistic_entry->ns_info_nsid); | |||
| 1535 | printf("%s: 0x%x\n", STR_NAMESPACE_INFO_VALID"Namespace Information Valid", | |||
| 1536 | pstatistic_entry->ns_info_ns_info_valid); | |||
| 1537 | printf("%s: 0x%x\n", STR_STATISTICS_DATA_SIZE"Statistic Data Size", | |||
| 1538 | pstatistic_entry->statistic_data_size); | |||
| 1539 | printf("%s: 0x%x\n", STR_RESERVED"Reserved", pstatistic_entry->reserved); | |||
| 1540 | if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) { | |||
| 1541 | printf("%s: 0x%02x\n", STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks", | |||
| 1542 | pdata[0]); | |||
| 1543 | printf("%s: 0x%04x\n", STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks", | |||
| 1544 | *(__u16 *)&pdata[2]); | |||
| 1545 | } else if (pstatistic_entry->statistic_id == | |||
| 1546 | MAX_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1547 | printf("%s: 0x%02x\n", | |||
| 1548 | STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks", | |||
| 1549 | pdata[0]); | |||
| 1550 | printf("%s: 0x%04x\n", | |||
| 1551 | STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks", | |||
| 1552 | *(__u16 *)&pdata[2]); | |||
| 1553 | } else if (pstatistic_entry->statistic_id == | |||
| 1554 | MIN_NAND_CHANNEL_BAD_BLOCK_ID) { | |||
| 1555 | printf("%s: 0x%02x\n", | |||
| 1556 | STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks", | |||
| 1557 | pdata[0]); | |||
| 1558 | printf("%s: 0x%04x\n", | |||
| 1559 | STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks", | |||
| 1560 | *(__u16 *)&pdata[2]); | |||
| 1561 | } else { | |||
| 1562 | print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data", | |||
| 1563 | pdata, | |||
| 1564 | data_size, | |||
| 1565 | fp); | |||
| 1566 | } | |||
| 1567 | printf(STR_LINE2"-----------------------------------------------------------------------------\n"); | |||
| 1568 | } | |||
| 1569 | } | |||
| 1570 | ||||
| 1571 | return 0; | |||
| 1572 | } | |||
| 1573 | ||||
| 1574 | int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets, | |||
| 1575 | FILE *fp) | |||
| 1576 | { | |||
| 1577 | if (poffsets == NULL((void*)0)) { | |||
| 1578 | nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL"); | |||
| 1579 | return -1; | |||
| 1580 | } | |||
| 1581 | ||||
| 1582 | __u8 *pda1_ocp_header_offset = ptelemetry_buffer + poffsets->header_size;//512 | |||
| 1583 | __u32 statistics_size = 0; | |||
| 1584 | __u32 stats_da_1_start_dw = 0, stats_da_1_size_dw = 0; | |||
| 1585 | __u32 stats_da_2_start_dw = 0, stats_da_2_size_dw = 0; | |||
| 1586 | __u8 *pstats_offset = NULL((void*)0); | |||
| 1587 | int parse_rc = 0; | |||
| 1588 | ||||
| 1589 | if (poffsets->data_area == 1) { | |||
| 1590 | __u32 stats_da_1_start = *(__u32 *)(pda1_ocp_header_offset + | |||
| 1591 | offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start)__builtin_offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start )); | |||
| 1592 | __u32 stats_da_1_size = *(__u32 *)(pda1_ocp_header_offset + | |||
| 1593 | offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size)__builtin_offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size )); | |||
| 1594 | ||||
| 1595 | //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD) | |||
| 1596 | stats_da_1_start_dw = (stats_da_1_start * SIZE_OF_DWORD4); | |||
| 1597 | stats_da_1_size_dw = (stats_da_1_size * SIZE_OF_DWORD4); | |||
| 1598 | ||||
| 1599 | pstats_offset = pda1_ocp_header_offset + stats_da_1_start_dw; | |||
| 1600 | statistics_size = stats_da_1_size_dw; | |||
| 1601 | } else if (poffsets->data_area == 2) { | |||
| 1602 | __u32 stats_da_2_start = *(__u32 *)(pda1_ocp_header_offset + | |||
| 1603 | offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start)__builtin_offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start )); | |||
| 1604 | __u32 stats_da_2_size = *(__u32 *)(pda1_ocp_header_offset + | |||
| 1605 | offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size)__builtin_offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size )); | |||
| 1606 | ||||
| 1607 | stats_da_2_start_dw = (stats_da_2_start * SIZE_OF_DWORD4); | |||
| 1608 | stats_da_2_size_dw = (stats_da_2_size * SIZE_OF_DWORD4); | |||
| 1609 | ||||
| 1610 | pstats_offset = pda1_ocp_header_offset + poffsets->da1_size + stats_da_2_start_dw; | |||
| 1611 | statistics_size = stats_da_2_size_dw; | |||
| 1612 | } else { | |||
| 1613 | nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area)nvme_show_message(1, "Unsupported Data Area:[%d]", poffsets-> data_area); | |||
| 1614 | return -1; | |||
| 1615 | } | |||
| 1616 | ||||
| 1617 | struct json_object *pstats_array = ((root != NULL((void*)0)) ? json_create_array()json_object_new_array() : NULL((void*)0)); | |||
| 1618 | ||||
| 1619 | __u32 stat_des_size = sizeof(struct nvme_ocp_telemetry_statistic_descriptor);//8 | |||
| 1620 | __u32 offset_to_move = 0; | |||
| 1621 | ||||
| 1622 | while (((statistics_size > 0) && (offset_to_move < statistics_size))) { | |||
| 1623 | struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry = | |||
| 1624 | (struct nvme_ocp_telemetry_statistic_descriptor *) | |||
| 1625 | (pstats_offset + offset_to_move); | |||
| 1626 | ||||
| 1627 | parse_rc = parse_statistic(pstatistic_entry, pstats_array, fp); | |||
| 1628 | if (parse_rc < 0) | |||
| 1629 | /* end of stats entries or null pointer, so break */ | |||
| 1630 | break; | |||
| 1631 | ||||
| 1632 | offset_to_move += (pstatistic_entry->statistic_data_size * SIZE_OF_DWORD4 + | |||
| 1633 | stat_des_size); | |||
| 1634 | } | |||
| 1635 | ||||
| 1636 | if (root != NULL((void*)0) && pstats_array != NULL((void*)0)) { | |||
| 1637 | const char *pdata_area = | |||
| 1638 | (poffsets->data_area == 1 ? STR_DA_1_STATS"Data Area 1 Statistics" : STR_DA_2_STATS"Data Area 2 Statistics"); | |||
| 1639 | ||||
| 1640 | json_object_add_value_array(root, pdata_area, pstats_array)json_object_object_add(root, pdata_area, pstats_array); | |||
| 1641 | } | |||
| 1642 | ||||
| 1643 | return 0; | |||
| 1644 | } | |||
| 1645 | ||||
| 1646 | int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) | |||
| 1647 | { | |||
| 1648 | int status = 0; | |||
| 1649 | char file_path[PATH_MAX4096]; | |||
| 1650 | ||||
| 1651 | if (options->output_file != NULL((void*)0)) { | |||
| 1652 | sprintf(file_path, "%s.%s", options->output_file, "txt"); | |||
| 1653 | FILE *fp = fopen(file_path, "w"); | |||
| 1654 | ||||
| 1655 | if (fp) { | |||
| 1656 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1657 | fprintf(fp, "%s\n", STR_LOG_PAGE_HEADER"Log Page Header"); | |||
| 1658 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1659 | if (!strcmp(options->telemetry_type, "host")) { | |||
| 1660 | if ((ptelemetry_buffer == NULL((void*)0)) || | |||
| 1661 | (ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header) [0])) == 0)) | |||
| 1662 | printf("skip generic_structure_parser\n"); | |||
| 1663 | else | |||
| 1664 | generic_structure_parser(ptelemetry_buffer, | |||
| 1665 | host_log_page_header, | |||
| 1666 | ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header) [0])), | |||
| 1667 | NULL((void*)0), 0, fp); | |||
| 1668 | } | |||
| 1669 | else if (!strcmp(options->telemetry_type, "controller")) | |||
| 1670 | generic_structure_parser(ptelemetry_buffer, | |||
| 1671 | controller_log_page_header, | |||
| 1672 | ARRAY_SIZE(controller_log_page_header)(sizeof(controller_log_page_header) / sizeof((controller_log_page_header )[0])), NULL((void*)0), 0, fp); | |||
| 1673 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1674 | fprintf(fp, "%s\n", STR_REASON_IDENTIFIER"Reason Identifier"); | |||
| 1675 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1676 | __u8 *preason_identifier_offset = ptelemetry_buffer + | |||
| 1677 | offsetof(struct nvme_ocp_telemetry_host_initiated_header,__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header , reason_id) | |||
| 1678 | reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header , reason_id); | |||
| 1679 | ||||
| 1680 | generic_structure_parser(preason_identifier_offset, reason_identifier, | |||
| 1681 | ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), NULL((void*)0), 0, fp); | |||
| 1682 | ||||
| 1683 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1684 | fprintf(fp, "%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1"Telemetry Host-Initiated Data Block 1"); | |||
| 1685 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1686 | ||||
| 1687 | //Set DA to 1 and get offsets | |||
| 1688 | struct nvme_ocp_telemetry_offsets offsets = { 0 }; | |||
| 1689 | ||||
| 1690 | offsets.data_area = 1;// Default DA - DA1 | |||
| 1691 | ||||
| 1692 | struct nvme_ocp_telemetry_common_header *ptelemetry_common_header = | |||
| 1693 | (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer; | |||
| 1694 | ||||
| 1695 | get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets); | |||
| 1696 | ||||
| 1697 | __u8 *pda1_header_offset = ptelemetry_buffer + | |||
| 1698 | offsets.da1_start_offset;//512 | |||
| 1699 | ||||
| 1700 | generic_structure_parser(pda1_header_offset, ocp_header_in_da1, | |||
| 1701 | ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), NULL((void*)0), 0, fp); | |||
| 1702 | ||||
| 1703 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1704 | fprintf(fp, "%s\n", STR_SMART_HEALTH_INFO"SMART / Health Information Log(LID-02h)"); | |||
| 1705 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1706 | __u8 *pda1_smart_offset = pda1_header_offset + | |||
| 1707 | offsetof(struct nvme_ocp_header_in_da1, smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info ); | |||
| 1708 | //512+512 =1024 | |||
| 1709 | ||||
| 1710 | generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])), | |||
| 1711 | NULL((void*)0), 0, fp); | |||
| 1712 | ||||
| 1713 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1714 | fprintf(fp, "%s\n", STR_SMART_HEALTH_INTO_EXTENDED"SMART / Health Information Extended(LID-C0h)"); | |||
| 1715 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1716 | __u8 *pda1_smart_ext_offset = pda1_header_offset + | |||
| 1717 | offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended ) | |||
| 1718 | smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended ); | |||
| 1719 | ||||
| 1720 | generic_structure_parser(pda1_smart_ext_offset, smart_extended, | |||
| 1721 | ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])), NULL((void*)0), 0, fp); | |||
| 1722 | ||||
| 1723 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1724 | fprintf(fp, "%s\n", STR_DA_1_STATS"Data Area 1 Statistics"); | |||
| 1725 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1726 | ||||
| 1727 | status = parse_statistics(NULL((void*)0), &offsets, fp); | |||
| 1728 | if (status != 0) { | |||
| 1729 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1730 | return -1; | |||
| 1731 | } | |||
| 1732 | ||||
| 1733 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1734 | fprintf(fp, "%s\n", STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info"); | |||
| 1735 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1736 | status = parse_event_fifos(NULL((void*)0), &offsets, fp); | |||
| 1737 | if (status != 0) | |||
| 1738 | return -1; | |||
| 1739 | ||||
| 1740 | //Set the DA to 2 | |||
| 1741 | if (options->data_area == 2) { | |||
| 1742 | offsets.data_area = 2; | |||
| 1743 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1744 | fprintf(fp, "%s\n", STR_DA_2_STATS"Data Area 2 Statistics"); | |||
| 1745 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1746 | status = parse_statistics(NULL((void*)0), &offsets, fp); | |||
| 1747 | ||||
| 1748 | if (status != 0) { | |||
| 1749 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1750 | return -1; | |||
| 1751 | } | |||
| 1752 | ||||
| 1753 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1754 | fprintf(fp, "%s\n", STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info"); | |||
| 1755 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1756 | status = parse_event_fifos(NULL((void*)0), &offsets, fp); | |||
| 1757 | if (status != 0) | |||
| 1758 | return -1; | |||
| 1759 | } | |||
| 1760 | ||||
| 1761 | fprintf(fp, STR_LINE"==============================================================================\n"); | |||
| 1762 | fclose(fp); | |||
| 1763 | } else { | |||
| 1764 | nvme_show_error("Failed to open %s file.\n", file_path)nvme_show_message(1, "Failed to open %s file.\n", file_path); | |||
| 1765 | return -1; | |||
| 1766 | } | |||
| 1767 | } else { | |||
| 1768 | printf(STR_LINE"==============================================================================\n"); | |||
| 1769 | printf("%s\n", STR_LOG_PAGE_HEADER"Log Page Header"); | |||
| 1770 | printf(STR_LINE"==============================================================================\n"); | |||
| 1771 | if (!strcmp(options->telemetry_type, "host")) { | |||
| 1772 | if ((ptelemetry_buffer == NULL((void*)0)) || | |||
| 1773 | (ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header) [0])) == 0)) | |||
| 1774 | printf("skip generic_structure_parser\n"); | |||
| 1775 | else { | |||
| 1776 | generic_structure_parser(ptelemetry_buffer, host_log_page_header, | |||
| 1777 | ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header) [0])), NULL((void*)0), 0, NULL((void*)0)); | |||
| 1778 | } | |||
| 1779 | } | |||
| 1780 | else if (!strcmp(options->telemetry_type, "controller")) | |||
| 1781 | generic_structure_parser(ptelemetry_buffer, controller_log_page_header, | |||
| 1782 | ARRAY_SIZE(controller_log_page_header)(sizeof(controller_log_page_header) / sizeof((controller_log_page_header )[0])), NULL((void*)0), 0, NULL((void*)0)); | |||
| 1783 | ||||
| 1784 | printf(STR_LINE"==============================================================================\n"); | |||
| 1785 | printf("%s\n", STR_REASON_IDENTIFIER"Reason Identifier"); | |||
| 1786 | printf(STR_LINE"==============================================================================\n"); | |||
| 1787 | __u8 *preason_identifier_offset = ptelemetry_buffer + | |||
| 1788 | offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header , reason_id); | |||
| 1789 | generic_structure_parser(preason_identifier_offset, reason_identifier, | |||
| 1790 | ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), NULL((void*)0), 0, NULL((void*)0)); | |||
| 1791 | ||||
| 1792 | printf(STR_LINE"==============================================================================\n"); | |||
| 1793 | printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1"Telemetry Host-Initiated Data Block 1"); | |||
| 1794 | printf(STR_LINE"==============================================================================\n"); | |||
| 1795 | ||||
| 1796 | //Set DA to 1 and get offsets | |||
| 1797 | struct nvme_ocp_telemetry_offsets offsets = { 0 }; | |||
| 1798 | ||||
| 1799 | offsets.data_area = 1; | |||
| 1800 | ||||
| 1801 | struct nvme_ocp_telemetry_common_header *ptelemetry_common_header = | |||
| 1802 | (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer; | |||
| 1803 | ||||
| 1804 | get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets); | |||
| 1805 | ||||
| 1806 | __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512 | |||
| 1807 | ||||
| 1808 | generic_structure_parser(pda1_header_offset, ocp_header_in_da1, | |||
| 1809 | ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), NULL((void*)0), 0, NULL((void*)0)); | |||
| 1810 | ||||
| 1811 | printf(STR_LINE"==============================================================================\n"); | |||
| 1812 | printf("%s\n", STR_SMART_HEALTH_INFO"SMART / Health Information Log(LID-02h)"); | |||
| 1813 | printf(STR_LINE"==============================================================================\n"); | |||
| 1814 | __u8 *pda1_smart_offset = pda1_header_offset + | |||
| 1815 | offsetof(struct nvme_ocp_header_in_da1, smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info ); | |||
| 1816 | ||||
| 1817 | generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])), NULL((void*)0), 0, | |||
| 1818 | NULL((void*)0)); | |||
| 1819 | ||||
| 1820 | printf(STR_LINE"==============================================================================\n"); | |||
| 1821 | printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED"SMART / Health Information Extended(LID-C0h)"); | |||
| 1822 | printf(STR_LINE"==============================================================================\n"); | |||
| 1823 | __u8 *pda1_smart_ext_offset = pda1_header_offset + | |||
| 1824 | offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended ); | |||
| 1825 | ||||
| 1826 | generic_structure_parser(pda1_smart_ext_offset, smart_extended, | |||
| 1827 | ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])), NULL((void*)0), 0, NULL((void*)0)); | |||
| 1828 | ||||
| 1829 | printf(STR_LINE"==============================================================================\n"); | |||
| 1830 | printf("%s\n", STR_DA_1_STATS"Data Area 1 Statistics"); | |||
| 1831 | printf(STR_LINE"==============================================================================\n"); | |||
| 1832 | status = parse_statistics(NULL((void*)0), &offsets, NULL((void*)0)); | |||
| 1833 | if (status != 0) { | |||
| 1834 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1835 | return -1; | |||
| 1836 | } | |||
| 1837 | ||||
| 1838 | printf(STR_LINE"==============================================================================\n"); | |||
| 1839 | printf("%s\n", STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info"); | |||
| 1840 | printf(STR_LINE"==============================================================================\n"); | |||
| 1841 | status = parse_event_fifos(NULL((void*)0), &offsets, NULL((void*)0)); | |||
| 1842 | if (status != 0) | |||
| 1843 | return -1; | |||
| 1844 | ||||
| 1845 | //Set the DA to 2 | |||
| 1846 | if (options->data_area == 2) { | |||
| 1847 | offsets.data_area = 2; | |||
| 1848 | printf(STR_LINE"==============================================================================\n"); | |||
| 1849 | printf("%s\n", STR_DA_2_STATS"Data Area 2 Statistics"); | |||
| 1850 | printf(STR_LINE"==============================================================================\n"); | |||
| 1851 | status = parse_statistics(NULL((void*)0), &offsets, NULL((void*)0)); | |||
| 1852 | if (status != 0) { | |||
| 1853 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1854 | return -1; | |||
| 1855 | } | |||
| 1856 | ||||
| 1857 | printf(STR_LINE"==============================================================================\n"); | |||
| 1858 | printf("%s\n", STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info"); | |||
| 1859 | printf(STR_LINE"==============================================================================\n"); | |||
| 1860 | status = parse_event_fifos(NULL((void*)0), &offsets, NULL((void*)0)); | |||
| 1861 | if (status != 0) | |||
| 1862 | return -1; | |||
| 1863 | } | |||
| 1864 | ||||
| 1865 | printf(STR_LINE"==============================================================================\n"); | |||
| 1866 | } | |||
| 1867 | ||||
| 1868 | return status; | |||
| 1869 | } | |||
| 1870 | ||||
| 1871 | int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options) | |||
| 1872 | { | |||
| 1873 | int status = 0; | |||
| 1874 | char file_path[PATH_MAX4096]; | |||
| 1875 | ||||
| 1876 | //create json objects | |||
| 1877 | struct json_object *root, *pheader, *preason_identifier, *da1_header, *smart_obj, | |||
| 1878 | *ext_smart_obj; | |||
| 1879 | ||||
| 1880 | root = json_create_object()json_object_new_object(); | |||
| 1881 | ||||
| 1882 | //Add data to root json object | |||
| 1883 | ||||
| 1884 | //"Log Page Header" | |||
| 1885 | pheader = json_create_object()json_object_new_object(); | |||
| 1886 | ||||
| 1887 | generic_structure_parser(ptelemetry_buffer, host_log_page_header, | |||
| 1888 | ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header) [0])), pheader, 0, NULL((void*)0)); | |||
| 1889 | json_object_add_value_object(root, STR_LOG_PAGE_HEADER, pheader)json_object_object_add(root, "Log Page Header", pheader); | |||
| 1890 | ||||
| 1891 | //"Reason Identifier" | |||
| 1892 | preason_identifier = json_create_object()json_object_new_object(); | |||
| 1893 | ||||
| 1894 | __u8 *preason_identifier_offset = ptelemetry_buffer + | |||
| 1895 | offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header , reason_id); | |||
| 1896 | ||||
| 1897 | generic_structure_parser(preason_identifier_offset, reason_identifier, | |||
| 1898 | ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), preason_identifier, 0, NULL((void*)0)); | |||
| 1899 | json_object_add_value_object(pheader, STR_REASON_IDENTIFIER, preason_identifier)json_object_object_add(pheader, "Reason Identifier", preason_identifier ); | |||
| 1900 | ||||
| 1901 | struct nvme_ocp_telemetry_offsets offsets = { 0 }; | |||
| 1902 | ||||
| 1903 | //Set DA to 1 and get offsets | |||
| 1904 | offsets.data_area = 1; | |||
| 1905 | struct nvme_ocp_telemetry_common_header *ptelemetry_common_header = | |||
| 1906 | (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer; | |||
| 1907 | ||||
| 1908 | get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets); | |||
| 1909 | ||||
| 1910 | //"Telemetry Host-Initiated Data Block 1" | |||
| 1911 | __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512 | |||
| 1912 | ||||
| 1913 | da1_header = json_create_object()json_object_new_object(); | |||
| 1914 | ||||
| 1915 | generic_structure_parser(pda1_header_offset, ocp_header_in_da1, | |||
| 1916 | ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), da1_header, 0, NULL((void*)0)); | |||
| 1917 | json_object_add_value_object(root, STR_TELEMETRY_HOST_DATA_BLOCK_1, da1_header)json_object_object_add(root, "Telemetry Host-Initiated Data Block 1" , da1_header); | |||
| 1918 | ||||
| 1919 | //"SMART / Health Information Log(LID-02h)" | |||
| 1920 | __u8 *pda1_smart_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info ) | |||
| 1921 | smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info ); | |||
| 1922 | smart_obj = json_create_object()json_object_new_object(); | |||
| 1923 | ||||
| 1924 | generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])), smart_obj, 0, NULL((void*)0)); | |||
| 1925 | json_object_add_value_object(da1_header, STR_SMART_HEALTH_INFO, smart_obj)json_object_object_add(da1_header, "SMART / Health Information Log(LID-02h)" , smart_obj); | |||
| 1926 | ||||
| 1927 | //"SMART / Health Information Extended(LID-C0h)" | |||
| 1928 | __u8 *pda1_smart_ext_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended ) | |||
| 1929 | smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended ); | |||
| 1930 | ext_smart_obj = json_create_object()json_object_new_object(); | |||
| 1931 | ||||
| 1932 | generic_structure_parser(pda1_smart_ext_offset, smart_extended, ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])), | |||
| 1933 | ext_smart_obj, 0, NULL((void*)0)); | |||
| 1934 | json_object_add_value_object(da1_header, STR_SMART_HEALTH_INTO_EXTENDED, ext_smart_obj)json_object_object_add(da1_header, "SMART / Health Information Extended(LID-C0h)" , ext_smart_obj); | |||
| 1935 | ||||
| 1936 | //Data Area 1 Statistics | |||
| 1937 | status = parse_statistics(root, &offsets, NULL((void*)0)); | |||
| 1938 | if (status != 0) { | |||
| 1939 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1940 | return -1; | |||
| 1941 | } | |||
| 1942 | ||||
| 1943 | //Data Area 1 Event FIFOs | |||
| 1944 | status = parse_event_fifos(root, &offsets, NULL((void*)0)); | |||
| 1945 | if (status != 0) | |||
| 1946 | return -1; | |||
| 1947 | ||||
| 1948 | if (options->data_area == 2) { | |||
| 1949 | //Set the DA to 2 | |||
| 1950 | offsets.data_area = 2; | |||
| 1951 | //Data Area 2 Statistics | |||
| 1952 | status = parse_statistics(root, &offsets, NULL((void*)0)); | |||
| 1953 | if (status != 0) { | |||
| 1954 | nvme_show_error("status: %d\n", status)nvme_show_message(1, "status: %d\n", status); | |||
| 1955 | return -1; | |||
| 1956 | } | |||
| 1957 | ||||
| 1958 | //Data Area 2 Event FIFOs | |||
| 1959 | status = parse_event_fifos(root, &offsets, NULL((void*)0)); | |||
| 1960 | if (status != 0) | |||
| 1961 | return -1; | |||
| 1962 | } | |||
| 1963 | ||||
| 1964 | if (options->output_file != NULL((void*)0)) { | |||
| 1965 | const char *json_string = json_object_to_json_string(root); | |||
| 1966 | sprintf(file_path, "%s.%s", options->output_file, "json"); | |||
| 1967 | FILE *fp = fopen(file_path, "w"); | |||
| 1968 | ||||
| 1969 | if (fp) { | |||
| 1970 | fputs(json_string, fp); | |||
| 1971 | fclose(fp); | |||
| 1972 | } else { | |||
| 1973 | nvme_show_error("Failed to open %s file.\n", file_path)nvme_show_message(1, "Failed to open %s file.\n", file_path); | |||
| 1974 | return -1; | |||
| 1975 | } | |||
| 1976 | } else { | |||
| 1977 | //Print root json object | |||
| 1978 | json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 << 1) | (1 << 4))); | |||
| 1979 | nvme_show_result("\n")nvme_show_message(0, "\n"); | |||
| 1980 | json_free_object(root)json_object_put(root); | |||
| 1981 | } | |||
| 1982 | ||||
| 1983 | return status; | |||
| 1984 | } | |||
| 1985 | #endif /* CONFIG_JSONC */ |