| File: | .build-ci/../plugins/ocp/ocp-telemetry-decode.c |
| Warning: | line 742, column 4 Value stored to 'description' is never read |
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 = ""; |
Value stored to 'description' is never read | |
| 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 != 0) { |
| 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 */ |