Bug Summary

File:.build-ci/../plugins/ocp/ocp-telemetry-decode.c
Warning:line 742, column 4
Value stored to 'description' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ocp-telemetry-decode.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../plugins/ocp/ocp-telemetry-decode.c
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
17void 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
29void 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
53void 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
234struct 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
349struct 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
365struct 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
380struct 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
389struct 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
458struct 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
492struct 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
537void 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
545void 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
564int 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
607int 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
654int 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
690int 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
728int 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
758int 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
828int 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
898int 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
969void 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
1009int 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
1081int 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
1340free_desc:
1341 free(description);
1342 return ret;
1343}
1344
1345int 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
1411int 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
1574int 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
1646int 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
1871int 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 */