Bug Summary

File:.build-ci/../plugins/wdc/wdc-nvme.c
Warning:line 7500, column 2
Value stored to 'ret' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name wdc-nvme.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 static -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/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I shared -I ../shared -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -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 -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-08-08-045408-589-1 -x c ../plugins/wdc/wdc-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2015-2018 Western Digital Corporation or its affiliates.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 *
20 * Author: Chaitanya Kulkarni <chaitanya.kulkarni@hgst.com>,
21 * Dong Ho <dong.ho@hgst.com>,
22 * Jeff Lien <jeff.lien@wdc.com>
23 * Brandon Paupore <brandon.paupore@wdc.com>
24 */
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28#include <inttypes.h>
29#include <errno(*__errno_location ()).h>
30#include <limits.h>
31#include <fcntl.h>
32#include <unistd.h>
33
34#include <libnvme.h>
35
36#include "common.h"
37#include "nvme-cmds.h"
38#include "nvme-print.h"
39#include "nvme.h"
40#include "plugin.h"
41#include "src/cleanup.h"
42#include "uint128-util.h"
43#include "time-util.h"
44#include "parse-util.h"
45#include "nvme-pci-ids.h"
46
47#define CREATE_CMD
48#include "wdc-nvme.h"
49#include "wdc-utils.h"
50#include "wdc-nvme-cmds.h"
51
52#define WRITE_SIZE(sizeof(__u8) * 4096) (sizeof(__u8) * 4096)
53
54#define WDC_NVME_SUBCMD_SHIFT8 8
55
56#define WDC_NVME_LOG_SIZE_DATA_LEN0x08 0x08
57#define WDC_NVME_LOG_SIZE_HDR_LEN0x08 0x08
58
59/* Enclosure */
60#define WDC_OPENFLEX_MI_DEVICE_MODEL"OpenFlex" "OpenFlex"
61#define WDC_RESULT_MORE_DATA0x80000000 0x80000000
62#define WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF 0x7FFFFFFF
63
64/* Device Config */
65#define WDC_NVME_VID0x1c58 0x1c58
66#define WDC_NVME_VID_20x1b96 0x1b96
67#define WDC_NVME_SNDK_VID0x15b7 0x15b7
68
69#define WDC_NVME_SN100_DEV_ID0x0003 0x0003
70#define WDC_NVME_SN200_DEV_ID0x0023 0x0023
71#define WDC_NVME_SN630_DEV_ID0x2200 0x2200
72#define WDC_NVME_SN630_DEV_ID_10x2201 0x2201
73#define WDC_NVME_SN840_DEV_ID0x2300 0x2300
74#define WDC_NVME_SN840_DEV_ID_10x2500 0x2500
75#define WDC_NVME_SN640_DEV_ID0x2400 0x2400
76#define WDC_NVME_SN640_DEV_ID_10x2401 0x2401
77#define WDC_NVME_SN640_DEV_ID_20x2402 0x2402
78#define WDC_NVME_SN640_DEV_ID_30x2404 0x2404
79#define WDC_NVME_ZN540_DEV_ID0x2600 0x2600
80#define WDC_NVME_SN540_DEV_ID0x2610 0x2610
81#define WDC_NVME_SN650_DEV_ID0x2700 0x2700
82#define WDC_NVME_SN650_DEV_ID_10x2701 0x2701
83#define WDC_NVME_SN650_DEV_ID_20x2702 0x2702
84#define WDC_NVME_SN650_DEV_ID_30x2720 0x2720
85#define WDC_NVME_SN650_DEV_ID_40x2721 0x2721
86#define WDC_NVME_SN655_DEV_ID0x2722 0x2722
87#define WDC_NVME_SN655_DEV_ID_10x2723 0x2723
88#define WDC_NVME_SN860_DEV_ID0x2730 0x2730
89#define WDC_NVME_SN660_DEV_ID0x2704 0x2704
90#define WDC_NVME_SN560_DEV_ID_10x2712 0x2712
91#define WDC_NVME_SN560_DEV_ID_20x2713 0x2713
92#define WDC_NVME_SN560_DEV_ID_30x2714 0x2714
93#define WDC_NVME_SN861_DEV_ID0x2750 0x2750
94#define WDC_NVME_SN861_DEV_ID_10x2751 0x2751
95#define WDC_NVME_SN861_DEV_ID_20x2752 0x2752
96#define WDC_NVME_SNTMP_DEV_ID0x2761 0x2761
97#define WDC_NVME_SNTMP_DEV_ID_10x2763 0x2763
98
99#define WDC_NVME_SNESSD1_DEV_ID_E1L0x2765 0x2765
100#define WDC_NVME_SNESSD1_DEV_ID_E20x2766 0x2766
101#define WDC_NVME_SNESSD1_DEV_ID_E3S0x2767 0x2767
102#define WDC_NVME_SNESSD1_DEV_ID_E3L0x2768 0x2768
103#define WDC_NVME_SNESSD1_DEV_ID_U20x2769 0x2769
104
105/* This id's are no longer supported, delete ?? */
106#define WDC_NVME_SN550_DEV_ID0x2708 0x2708
107
108#define WDC_NVME_SXSLCL_DEV_ID0x2001 0x2001
109#define WDC_NVME_SN520_DEV_ID0x5003 0x5003
110#define WDC_NVME_SN520_DEV_ID_10x5004 0x5004
111#define WDC_NVME_SN520_DEV_ID_20x5005 0x5005
112
113#define WDC_NVME_SN530_DEV_ID_10x5007 0x5007
114#define WDC_NVME_SN530_DEV_ID_20x5008 0x5008
115#define WDC_NVME_SN530_DEV_ID_30x5009 0x5009
116#define WDC_NVME_SN530_DEV_ID_40x500b 0x500b
117#define WDC_NVME_SN530_DEV_ID_50x501d 0x501d
118
119#define WDC_NVME_SN350_DEV_ID0x5019 0x5019
120
121#define WDC_NVME_SN570_DEV_ID0x501A 0x501A
122
123#define WDC_NVME_SN850X_DEV_ID0x5030 0x5030
124
125#define WDC_NVME_SN5000_DEV_ID_10x5034 0x5034
126#define WDC_NVME_SN5000_DEV_ID_20x5035 0x5035
127#define WDC_NVME_SN5000_DEV_ID_30x5036 0x5036
128#define WDC_NVME_SN5000_DEV_ID_40x504A 0x504A
129
130#define WDC_NVME_SN7000S_DEV_ID_10x5039 0x5039
131
132#define WDC_NVME_SN7150_DEV_ID_10x503b 0x503b
133#define WDC_NVME_SN7150_DEV_ID_20x503c 0x503c
134#define WDC_NVME_SN7150_DEV_ID_30x503d 0x503d
135#define WDC_NVME_SN7150_DEV_ID_40x503e 0x503e
136#define WDC_NVME_SN7150_DEV_ID_50x503f 0x503f
137
138#define WDC_NVME_SN7100_DEV_ID_10x5043 0x5043
139#define WDC_NVME_SN7100_DEV_ID_20x5044 0x5044
140#define WDC_NVME_SN7100_DEV_ID_30x5045 0x5045
141
142#define WDC_NVME_SN8000S_DEV_ID0x5049 0x5049
143
144#define WDC_NVME_SN720_DEV_ID0x5002 0x5002
145#define WDC_NVME_SN730_DEV_ID0x5006 0x5006
146#define WDC_NVME_SN740_DEV_ID0x5015 0x5015
147#define WDC_NVME_SN740_DEV_ID_10x5016 0x5016
148#define WDC_NVME_SN740_DEV_ID_20x5017 0x5017
149#define WDC_NVME_SN740_DEV_ID_30x5025 0x5025
150#define WDC_NVME_SN340_DEV_ID0x500d 0x500d
151#define WDC_NVME_ZN350_DEV_ID0x5010 0x5010
152#define WDC_NVME_ZN350_DEV_ID_10x5018 0x5018
153#define WDC_NVME_SN810_DEV_ID0x5011 0x5011
154#define WDC_NVME_SN820CL_DEV_ID0x5037 0x5037
155
156#define WDC_NVME_SN5100S_DEV_ID_10x5061 0x5061
157#define WDC_NVME_SN5100S_DEV_ID_20x5062 0x5062
158#define WDC_NVME_SN5100S_DEV_ID_30x5063 0x5063
159
160/* Shared flag space with SNDK plugin, should be kept in sync */
161#define WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 0x0000000000000001
162#define WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 0x0000000000000002
163#define WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 0x0000000000000004
164#define WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 0x0000000000000008
165#define WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 0x0000000000000010
166#define WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 0x0000000000000020
167#define WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 0x0000000000000040
168#define WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 0x0000000000000080
169#define WDC_DRIVE_CAP_RESIZE0x0000000000000100 0x0000000000000100
170#define WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 0x0000000000000200
171#define WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 0x0000000000000400
172#define WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 0x0000000000000800
173#define WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 0x0000000000001000
174#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 0x0000000000002000
175#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 0x0000000000004000
176#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 0x0000000000008000
177#define WDC_DRIVE_CAP_REASON_ID0x0000000000010000 0x0000000000010000
178#define WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 0x0000000000020000
179#define WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 0x0000000000040000
180#define WDC_DRIVE_CAP_INFO0x0000000000080000 0x0000000000080000
181#define WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 0x0000000000100000
182#define WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 0x0000000000200000
183#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 0x0000000000400000
184#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 0x0000000000800000
185#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 0x0000000001000000
186#define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 0x0000000002000000
187#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 0x0000000004000000
188#define WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 0x0000000008000000
189#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 0x0000000010000000
190#define WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 0x0000000020000000
191#define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 0x0000000040000000
192#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 0x0000000080000000
193#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 0x0000000100000000
194#define WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 0x0000000200000000
195#define WDC_SN730B_CAP_VUC_LOG0x0000000400000000 0x0000000400000000
196#define WDC_DRIVE_CAP_DUI0x0000000800000000 0x0000000800000000
197#define WDC_DRIVE_CAP_PURGE0x0000001000000000 0x0000001000000000
198#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 0x0000002000000000
199#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 0x0000004000000000
200#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 0x0000008000000000
201#define WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 0x0000010000000000
202#define WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 0x0000020000000000
203#define WDC_DRIVE_CAP_UDUI0x0000040000000000 0x0000040000000000
204#define WDC_DRIVE_CAP_RESIZE_SN8610x0000080000000000 0x0000080000000000
205
206/* Any new capability flags should be added to the SNDK plugin */
207
208#define WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
(WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | \
209 WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 | \
210 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | \
211 WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010)
212#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
(WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 | \
213 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | \
214 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000)
215#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | \
216 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000)
217#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | \
218 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000)
219#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
(WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | \
220 WDC_DRIVE_CAP_DUI0x0000000800000000 | \
221 WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | \
222 WDC_SN730B_CAP_VUC_LOG0x0000000400000000)
223
224/* SN730 Get Log Capabilities */
225#define SN730_NVME_GET_LOG_OPCODE0xc2 0xc2
226#define SN730_GET_FULL_LOG_LENGTH0x00080009 0x00080009
227#define SN730_GET_KEY_LOG_LENGTH0x00090009 0x00090009
228#define SN730_GET_COREDUMP_LOG_LENGTH0x00120009 0x00120009
229#define SN730_GET_EXTENDED_LOG_LENGTH0x00420009 0x00420009
230
231#define SN730_GET_FULL_LOG_SUBOPCODE0x00010009 0x00010009
232#define SN730_GET_KEY_LOG_SUBOPCODE0x00020009 0x00020009
233#define SN730_GET_CORE_LOG_SUBOPCODE0x00030009 0x00030009
234#define SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009 0x00040009
235#define SN730_LOG_CHUNK_SIZE0x1000 0x1000
236
237/* Customer ID's */
238#define WDC_CUSTOMER_ID_GN0x0001 0x0001
239#define WDC_CUSTOMER_ID_GD0x0101 0x0101
240#define WDC_CUSTOMER_ID_BD0x1009 0x1009
241
242#define WDC_CUSTOMER_ID_0x00F00x00F0 0x00F0
243#define WDC_CUSTOMER_ID_0x10040x1004 0x1004
244#define WDC_CUSTOMER_ID_0x10050x1005 0x1005
245#define WDC_CUSTOMER_ID_0x10080x1008 0x1008
246#define WDC_CUSTOMER_ID_0x13040x1304 0x1304
247#define WDC_INVALID_CUSTOMER_ID-1 -1
248
249#define WDC_ALL_PAGE_MASK0xFFFF 0xFFFF
250#define WDC_C0_PAGE_MASK0x0001 0x0001
251#define WDC_C1_PAGE_MASK0x0002 0x0002
252#define WDC_CA_PAGE_MASK0x0004 0x0004
253#define WDC_D0_PAGE_MASK0x0008 0x0008
254
255/* Drive Resize */
256#define WDC_NVME_DRIVE_RESIZE_OPCODE0xCC 0xCC
257#define WDC_NVME_DRIVE_RESIZE_CMD0x03 0x03
258#define WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 0x01
259
260/* Namespace Resize */
261#define WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB 0xFB
262
263/* Drive Info */
264#define WDC_NVME_DRIVE_INFO_OPCODE0xC6 0xC6
265#define WDC_NVME_DRIVE_INFO_CMD0x22 0x22
266#define WDC_NVME_DRIVE_INFO_SUBCMD0x06 0x06
267
268/* VS PCIE Stats */
269#define WDC_NVME_PCIE_STATS_OPCODE0xD1 0xD1
270
271/* Capture Diagnostics */
272#define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
273#define WDC_NVME_CAP_DIAG_OPCODE0xE6 0xE6
274#define WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6 0xC6
275#define WDC_NVME_CAP_DIAG_SUBCMD0x00 0x00
276#define WDC_NVME_CAP_DIAG_CMD0x00 0x00
277
278#define WDC_NVME_CRASH_DUMP_TYPE1 1
279#define WDC_NVME_PFAIL_DUMP_TYPE2 2
280
281/* Capture Device Unit Info */
282#define WDC_NVME_CAP_DUI_HEADER_SIZE0x400 0x400
283#define WDC_NVME_CAP_DUI_OPCODE0xFA 0xFA
284#define WDC_NVME_CAP_DUI_DISABLE_IO0x01 0x01
285#define WDC_NVME_DUI_MAX_SECTION0x3A 0x3A
286#define WDC_NVME_DUI_MAX_SECTION_V20x26 0x26
287#define WDC_NVME_DUI_MAX_SECTION_V30x23 0x23
288#define WDC_NVME_DUI_MAX_DATA_AREA0x05 0x05
289#define WDC_NVME_SN730_SECTOR_SIZE512 512
290
291/* Telemtery types for vs-internal-log command */
292#define WDC_TELEMETRY_TYPE_NONE0x0 0x0
293#define WDC_TELEMETRY_TYPE_HOST0x1 0x1
294#define WDC_TELEMETRY_TYPE_CONTROLLER0x2 0x2
295#define WDC_TELEMETRY_HEADER_LENGTH512 512
296#define WDC_TELEMETRY_BLOCK_SIZE512 512
297
298/* Crash dump */
299#define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
300#define WDC_NVME_CRASH_DUMP_SIZE_NDT0x02 0x02
301#define WDC_NVME_CRASH_DUMP_SIZE_CMD0x20 0x20
302#define WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 0x03
303
304#define WDC_NVME_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
305#define WDC_NVME_CRASH_DUMP_CMD0x20 0x20
306#define WDC_NVME_CRASH_DUMP_SUBCMD0x04 0x04
307
308/* PFail Crash dump */
309#define WDC_NVME_PF_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_HDR_LEN0x08
310#define WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02 0x02
311#define WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20 0x20
312#define WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 0x05
313
314#define WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
315#define WDC_NVME_PF_CRASH_DUMP_CMD0x20 0x20
316#define WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 0x06
317
318/* Drive Log */
319#define WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
320#define WDC_NVME_DRIVE_LOG_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
321#define WDC_NVME_DRIVE_LOG_SIZE_NDT0x02 0x02
322#define WDC_NVME_DRIVE_LOG_SIZE_CMD0x20 0x20
323#define WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 0x01
324
325#define WDC_NVME_DRIVE_LOG_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
326#define WDC_NVME_DRIVE_LOG_CMD0x20 0x20
327#define WDC_NVME_DRIVE_LOG_SUBCMD0x00 0x00
328
329/* Purge and Purge Monitor */
330#define WDC_NVME_PURGE_CMD_OPCODE0xDD 0xDD
331#define WDC_NVME_PURGE_MONITOR_OPCODE0xDE 0xDE
332#define WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F 0x2F
333#define WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C 0x0000000C
334#define WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530 0x7530
335#define WDC_NVME_PURGE_CMD_SEQ_ERR0x0C 0x0C
336#define WDC_NVME_PURGE_INT_DEV_ERR0x06 0x06
337
338#define WDC_NVME_PURGE_STATE_IDLE0x00 0x00
339#define WDC_NVME_PURGE_STATE_DONE0x01 0x01
340#define WDC_NVME_PURGE_STATE_BUSY0x02 0x02
341#define WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03 0x03
342#define WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04 0x04
343
344/* Clear dumps */
345#define WDC_NVME_CLEAR_DUMP_OPCODE0xFF 0xFF
346#define WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03 0x03
347#define WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 0x05
348#define WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 0x06
349
350/* Clear FW Activate History */
351#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6 0xC6
352#define WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23 0x23
353#define WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 0x05
354#define WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1 0xC1
355
356/* Additional Smart Log */
357#define WDC_ADD_LOG_BUF_LEN0x4000 0x4000
358#define WDC_NVME_ADD_LOG_OPCODE0xC1 0xC1
359#define WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37 0x37
360#define WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F 0x0F
361
362/* C2 Log Page */
363#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2 0xC2
364#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 0xC8
365#define WDC_C2_LOG_BUF_LEN0x1000 0x1000
366#define WDC_C2_MARKETING_NAME_ID0x07 0x07
367#define WDC_C2_LOG_PAGES_SUPPORTED_ID0x08 0x08
368#define WDC_C2_CUSTOMER_ID_ID0x15 0x15
369#define WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18 0x18
370#define WDC_C2_ASSERT_DUMP_PRESENT_ID0x19 0x19
371#define WDC_C2_USER_EOL_STATUS_ID0x1A 0x1A
372#define WDC_C2_USER_EOL_STATE_ID0x1C 0x1C
373#define WDC_C2_SYSTEM_EOL_STATE_ID0x1D 0x1D
374#define WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E 0x1E
375#define WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
376#define WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
377#define WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
378#define WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
379#define WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
380#define WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
381#define WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
382#define WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
383#define WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
384#define WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
385#define WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF) cpu_to_le32(0x000000FF)
386#define WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861" "Ultrastar DC SN861"
387#define WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861" "ULTRASTAR DC SN861"
388#define WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655" "Ultrastar DC SN655"
389#define WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655" "ULTRASTAR DC SN655"
390#define WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655" "SanDisk DC SN655"
391#define WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655" "SANDISK DC SN655"
392
393/* CA Log Page */
394#define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA 0xCA
395#define WDC_FB_CA_LOG_BUF_LEN0x80 0x80
396/* Added 4 padding bytes to resolve build warning messages */
397#define WDC_BD_CA_LOG_BUF_LEN0xA0 0xA0
398
399/* C0 EOL Status Log Page */
400#define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0 0xC0
401#define WDC_NVME_EOL_STATUS_LOG_LEN0x200 0x200
402#define WDC_NVME_SMART_CLOUD_ATTR_LEN0x200 0x200
403
404/* C0 SMART Cloud Attributes Log Page*/
405#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0 0xC0
406
407/* CB - FW Activate History Log Page */
408#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB 0xCB
409#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0 0x3d0
410
411/* C2 - FW Activation History Log Page */
412#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2 0xC2
413#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000 0x1000
414#define WDC_MAX_NUM_ACT_HIST_ENTRIES20 20
415#define WDC_C2_GUID_LENGTH16 16
416
417/* C3 Latency Monitor Log Page */
418#define WDC_LATENCY_MON_LOG_BUF_LEN0x200 0x200
419#define WDC_LATENCY_MON_LOG_ID0xC3 0xC3
420#define WDC_LATENCY_MON_VERSION0x0001 0x0001
421
422#define WDC_C3_GUID_LENGTH16 16
423static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH16] = {
424 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c,
425 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85
426};
427
428/* D0 Smart Log Page */
429#define WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0 0xD0
430#define WDC_NVME_VU_SMART_LOG_LEN0x200 0x200
431
432/* Log Page Directory defines */
433#define NVME_LOG_PERSISTENT_EVENT0x0D 0x0D
434#define WDC_LOG_ID_C00xC0 0xC0
435#define WDC_LOG_ID_C10xC1 0xC1
436#define WDC_LOG_ID_C20xC2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2
437#define WDC_LOG_ID_C30xC3 0xC3
438#define WDC_LOG_ID_C40xC4 0xC4
439#define WDC_LOG_ID_C50xC5 0xC5
440#define WDC_LOG_ID_C60xC6 0xC6
441#define WDC_LOG_ID_C80xC8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8
442#define WDC_LOG_ID_CA0xCA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA
443#define WDC_LOG_ID_CB0xCB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB
444#define WDC_LOG_ID_D00xD0 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0
445#define WDC_LOG_ID_D10xD1 0xD1
446#define WDC_LOG_ID_D60xD6 0xD6
447#define WDC_LOG_ID_D70xD7 0xD7
448#define WDC_LOG_ID_D80xD8 0xD8
449#define WDC_LOG_ID_DE0xDE 0xDE
450#define WDC_LOG_ID_F00xF0 0xF0
451#define WDC_LOG_ID_F10xF1 0xF1
452#define WDC_LOG_ID_F20xF2 0xF2
453#define WDC_LOG_ID_FA0xFA 0xFA
454
455/* Clear PCIe Correctable Errors */
456#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
457#define WDC_NVME_CLEAR_PCIE_CORR_CMD0x22 0x22
458#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 0x04
459#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2 0xD2
460#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3 0xC3
461/* Clear Assert Dump Status */
462#define WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8 0xD8
463#define WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03 0x03
464#define WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 0x05
465
466#define WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2 0xD2
467
468/* Drive Essentials */
469#define WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64 64
470#define WDC_DE_GENERIC_BUFFER_SIZE80 80
471#define WDC_DE_GLOBAL_NSID0xFFFFFFFF 0xFFFFFFFF
472#define WDC_DE_DEFAULT_NAMESPACE_ID0x01 0x01
473#define WDC_DE_PATH_SEPARATOR"/" "/"
474#define WDC_DE_TAR_FILES"*.bin" "*.bin"
475#define WDC_DE_TAR_FILE_EXTN".tar.gz" ".tar.gz"
476#define WDC_DE_TAR_CMD"tar -czf" "tar -czf"
477
478/* VS NAND Stats */
479#define WDC_NVME_NAND_STATS_LOG_ID0xFB 0xFB
480#define WDC_NVME_NAND_STATS_SIZE0x200 0x200
481
482/* VU Opcodes */
483#define WDC_DE_VU_READ_SIZE_OPCODE0xC0 0xC0
484#define WDC_DE_VU_READ_BUFFER_OPCODE0xC2 0xC2
485#define WDC_NVME_ADMIN_ENC_MGMT_SND0xC9 0xC9
486#define WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA 0xCA
487
488#define WDC_DE_FILE_HEADER_SIZE4 4
489#define WDC_DE_FILE_OFFSET_SIZE2 2
490#define WDC_DE_FILE_NAME_SIZE32 32
491#define WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000 0x8000
492#define WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 0x8000
493
494#define WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info" "manufacturing_info" /* Unique log entry page name. */
495#define WDC_DE_CORE_DUMP_FILE_NAME"core_dump" "core_dump"
496#define WDC_DE_EVENT_LOG_FILE_NAME"event_log" "event_log"
497#define WDC_DE_DESTN_SPI1 1
498#define WDC_DE_DUMPTRACE_DESTINATION6 6
499
500#define NVME_ID_CTRL_MODEL_NUMBER_SIZE40 40
501#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE20 20
502
503/* Enclosure log */
504#define WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000 0x1000
505#define WDC_NVME_ENC_NIC_LOG_SIZE0x400000 0x400000
506
507/* Enclosure nic crash dump get-log id */
508#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 0xD1
509#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 0xD2
510#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 0xD3
511#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4 0xD4
512#define WDC_ENC_CRASH_DUMP_ID0xE4 0xE4
513#define WDC_ENC_LOG_DUMP_ID0xE2 0xE2
514
515/* OCP Log Page Directory Data Structure */
516#define BYTE_TO_BIT(byte)((byte) * 8) ((byte) * 8)
517
518/* Set latency monitor feature */
519#define NVME_FEAT_OCP_LATENCY_MONITOR0xC5 0xC5
520
521enum _NVME_FEATURES_SELECT {
522 FS_CURRENT = 0,
523 FS_DEFAULT = 1,
524 FS_SAVED = 2,
525 FS_SUPPORTED_CAPBILITIES = 3
526};
527
528enum NVME_FEATURE_IDENTIFIERS {
529 FID_ARBITRATION = 0x01,
530 FID_POWER_MANAGEMENT = 0x02,
531 FID_LBA_RANGE_TYPE = 0x03,
532 FID_TEMPERATURE_THRESHOLD = 0x04,
533 FID_ERROR_RECOVERY = 0x05,
534 FID_VOLATILE_WRITE_CACHE = 0x06,
535 FID_NUMBER_OF_QUEUES = 0x07,
536 FID_INTERRUPT_COALESCING = 0x08,
537 FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
538 FID_WRITE_ATOMICITY = 0x0A,
539 FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B,
540 FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C,
541 /*Below FID's are NVM Command Set Specific*/
542 FID_SOFTWARE_PROGRESS_MARKER = 0x80,
543 FID_HOST_IDENTIFIER = 0x81,
544 FID_RESERVATION_NOTIFICATION_MASK = 0x82,
545 FID_RESERVATION_PERSISTENCE = 0x83
546};
547
548/* WDC UUID value */
549static const __u8 WDC_UUID[NVME_UUID_LEN16] = {
550 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15,
551 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
552};
553
554/* WDC_UUID value for SN640_3 devices */
555static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN16] = {
556 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
557 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
558};
559
560/* Sandisk UUID value */
561static const __u8 SNDK_UUID[NVME_UUID_LEN16] = {
562 0xde, 0x87, 0xd1, 0xeb, 0x72, 0xc5, 0x58, 0x0b,
563 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70
564};
565
566enum WDC_DRIVE_ESSENTIAL_TYPE {
567 WDC_DE_TYPE_IDENTIFY = 0x1,
568 WDC_DE_TYPE_SMARTATTRIBUTEDUMP = 0x2,
569 WDC_DE_TYPE_EVENTLOG = 0x4,
570 WDC_DE_TYPE_DUMPTRACE = 0x8,
571 WDC_DE_TYPE_DUMPSNAPSHOT = 0x10,
572 WDC_DE_TYPE_ATA_LOGS = 0x20,
573 WDC_DE_TYPE_SMART_LOGS = 0x40,
574 WDC_DE_TYPE_SCSI_LOGS = 0x80,
575 WDC_DE_TYPE_SCSI_MODE_PAGES = 0x100,
576 WDC_DE_TYPE_NVMe_FEATURES = 0x200,
577 WDC_DE_TYPE_DUMPSMARTERRORLOG3 = 0x400,
578 WDC_DE_TYPE_DUMPLOG3E = 0x800,
579 WDC_DE_TYPE_DUMPSCRAM = 0x1000,
580 WDC_DE_TYPE_PCU_LOG = 0x2000,
581 WDC_DE_TYPE_DUMP_ERROR_LOGS = 0x4000,
582 WDC_DE_TYPE_FW_SLOT_LOGS = 0x8000,
583 WDC_DE_TYPE_MEDIA_SETTINGS = 0x10000,
584 WDC_DE_TYPE_SMART_DATA = 0x20000,
585 WDC_DE_TYPE_NVME_SETTINGS = 0x40000,
586 WDC_DE_TYPE_NVME_ERROR_LOGS = 0x80000,
587 WDC_DE_TYPE_NVME_LOGS = 0x100000,
588 WDC_DE_TYPE_UART_LOGS = 0x200000,
589 WDC_DE_TYPE_DLOGS_SPI = 0x400000,
590 WDC_DE_TYPE_DLOGS_RAM = 0x800000,
591 WDC_DE_TYPE_NVME_MANF_INFO = 0x2000000,
592 WDC_DE_TYPE_NONE = 0x1000000,
593 WDC_DE_TYPE_ALL = 0xFFFFFFF,
594};
595
596#define WDC_C0_GUID_LENGTH16 16
597#define WDC_SCA_V1_NAND_STATS0x1 0x1
598#define WDC_SCA_V1_ALL0xF 0xF
599enum {
600 SCAO_V1_PMUWT = 0, /* Physical media units written TLC */
601 SCAO_V1_PMUWS = 16, /* Physical media units written SLC */
602 SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */
603 SCAO_V1_BUNBR = 34, /* Bad user nand blocks raw */
604 SCAO_V1_XRC = 40, /* XOR recovery count */
605 SCAO_V1_UREC = 48, /* Uncorrectable read error count */
606 SCAO_V1_EECE = 56, /* End to end corrected errors */
607 SCAO_V1_EEDE = 64, /* End to end detected errors */
608 SCAO_V1_EEUE = 72, /* End to end uncorrected errors */
609 SCAO_V1_SDPU = 80, /* System data percent used */
610 SCAO_V1_MNUDEC = 84, /* Min User data erase counts (TLC) */
611 SCAO_V1_MXUDEC = 92, /* Max User data erase counts (TLC) */
612 SCAO_V1_AVUDEC = 100, /* Average User data erase counts (TLC) */
613 SCAO_V1_MNEC = 108, /* Min Erase counts (SLC) */
614 SCAO_V1_MXEC = 116, /* Max Erase counts (SLC) */
615 SCAO_V1_AVEC = 124, /* Average Erase counts (SLC) */
616 SCAO_V1_PFCN = 132, /* Program fail count normalized */
617 SCAO_V1_PFCR = 134, /* Program fail count raw */
618 SCAO_V1_EFCN = 140, /* Erase fail count normalized */
619 SCAO_V1_EFCR = 142, /* Erase fail count raw */
620 SCAO_V1_PCEC = 148, /* PCIe correctable error count */
621 SCAO_V1_PFBU = 156, /* Percent free blocks (User) */
622 SCAO_V1_SVN = 160, /* Security Version Number */
623 SCAO_V1_PFBS = 168, /* Percent free blocks (System) */
624 SCAO_V1_DCC = 172, /* Deallocate Commands Completed */
625 SCAO_V1_TNU = 188, /* Total Namespace Utilization */
626 SCAO_V1_FCC = 196, /* Format NVM Commands Completed */
627 SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */
628 SCAO_V1_SEEC = 202, /* Soft ECC error count */
629 SCAO_V1_RFSC = 210, /* Refresh count */
630 SCAO_V1_BSNBN = 218, /* Bad system nand blocks normalized */
631 SCAO_V1_BSNBR = 220, /* Bad system nand blocks raw */
632 SCAO_V1_EEST = 226, /* Endurance estimate */
633 SCAO_V1_TTC = 242, /* Thermal throttling count */
634 SCAO_V1_UIO = 244, /* Unaligned I/O */
635 SCAO_V1_PMUR = 252, /* Physical media units read */
636 SCAO_V1_RTOC = 268, /* Read command timeout count */
637 SCAO_V1_WTOC = 272, /* Write command timeout count */
638 SCAO_V1_TTOC = 276, /* Trim command timeout count */
639 SCAO_V1_PLRC = 284, /* PCIe Link Retraining Count */
640 SCAO_V1_PSCC = 292, /* Power State Change Count */
641 SCAO_V1_MAVF = 300, /* Boot SSD major version field */
642 SCAO_V1_MIVF = 302, /* Boot SSD minor version field */
643 SCAO_V1_PVF = 304, /* Boot SSD point version field */
644 SCAO_V1_EVF = 306, /* Boot SSD errata version field */
645 SCAO_V1_FTLUS = 308, /* FTL Unit Size */
646 SCAO_V1_TCGOS = 312, /* TCG Ownership Status */
647
648 SCAO_V1_LPV = 494, /* Log page version - 0x0001 */
649 SCAO_V1_LPG = 496, /* Log page GUID */
650};
651
652static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH16] = {
653 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1,
654 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4
655};
656
657struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log {
658 __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */
659 __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */
660 __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */
661 __u64 ext_smart_xrc; /* 040 XOR recovery count */
662 __u64 ext_smart_urec; /* 048 Uncorrectable read error count */
663 __u64 ext_smart_eece; /* 056 End to end corrected errors */
664 __u64 ext_smart_eede; /* 064 End to end detected errors */
665 __u64 ext_smart_eeue; /* 072 End to end uncorrected errors */
666 __u8 ext_smart_sdpu; /* 080 System data percent used */
667 __u8 ext_smart_rsvd1[3]; /* 081 reserved */
668 __u64 ext_smart_mnudec; /* 084 Min User data erase counts (TLC) */
669 __u64 ext_smart_mxudec; /* 092 Max User data erase counts (TLC) */
670 __u64 ext_smart_avudec; /* 100 Average User data erase counts (TLC) */
671 __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */
672 __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */
673 __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */
674 __u8 ext_smart_pfc[8]; /* 132 Program fail count */
675 __u8 ext_smart_efc[8]; /* 140 Erase fail count */
676 __u64 ext_smart_pcec; /* 148 PCIe correctable error count */
677 __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */
678 __u8 ext_smart_rsvd2[3]; /* 157 reserved */
679 __u64 ext_smart_svn; /* 160 Security Version Number */
680 __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */
681 __u8 ext_smart_rsvd3[3]; /* 169 reserved */
682 __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */
683 __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */
684 __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */
685 __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */
686 __u8 ext_smart_rsvd4[3]; /* 199 reserved */
687 __u64 ext_smart_seec; /* 202 Soft ECC error count */
688 __u64 ext_smart_rfsc; /* 210 Refresh count */
689 __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */
690 __u8 ext_smart_eest[16]; /* 226 Endurance estimate */
691 __u16 ext_smart_ttc; /* 242 Thermal throttling count */
692 __u64 ext_smart_uio; /* 244 Unaligned I/O */
693 __u8 ext_smart_pmur[16]; /* 252 Physical media units read */
694 __u32 ext_smart_rtoc; /* 268 Read command timeout count */
695 __u32 ext_smart_wtoc; /* 272 Write command timeout count */
696 __u32 ext_smart_ttoc; /* 276 Trim command timeout count */
697 __u8 ext_smart_rsvd5[4]; /* 280 reserved */
698 __u64 ext_smart_plrc; /* 284 PCIe Link Retraining Count */
699 __u64 ext_smart_pscc; /* 292 Power State Change Count */
700 __u16 ext_smart_maj; /* 300 Boot SSD major version field */
701 __u16 ext_smart_min; /* 302 Boot SSD minor version field */
702 __u16 ext_smart_pt; /* 304 Boot SSD point version field */
703 __u16 ext_smart_err; /* 306 Boot SSD errata version field */
704 __u32 ext_smart_ftlus; /* 308 FTL Unit Size */
705 __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */
706 __u8 ext_smart_rsvd6[178]; /* 316 reserved */
707 __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */
708 __u8 ext_smart_lpg[16]; /* 496 Log page GUID */
709};
710
711struct ocp_bad_nand_block_count {
712 __u64 raw : 48;
713 __u16 normalized : 16;
714};
715
716struct ocp_e2e_correction_count {
717 __u32 detected;
718 __u32 corrected;
719};
720
721struct ocp_user_data_erase_count {
722 __u32 maximum;
723 __u32 minimum;
724};
725
726struct ocp_thermal_status {
727 __u8 num_events;
728 __u8 current_status;
729};
730
731struct __packed__attribute__((__packed__)) ocp_dssd_specific_ver {
732 __u8 errata_ver;
733 __u16 point_ver;
734 __u16 minor_ver;
735 __u8 major_ver;
736};
737
738struct ocp_cloud_smart_log {
739 __u8 physical_media_units_written[16];
740 __u8 physical_media_units_read[16];
741 struct ocp_bad_nand_block_count bad_user_nand_blocks;
742 struct ocp_bad_nand_block_count bad_system_nand_blocks;
743 __u64 xor_recovery_count;
744 __u64 uncorrectable_read_error_count;
745 __u64 soft_ecc_error_count;
746 struct ocp_e2e_correction_count e2e_correction_counts;
747 __u8 system_data_percent_used;
748 __u64 refresh_counts : 56;
749 struct ocp_user_data_erase_count user_data_erase_counts;
750 struct ocp_thermal_status thermal_status;
751 struct ocp_dssd_specific_ver dssd_specific_ver;
752 __u64 pcie_correctable_error_count;
753 __u32 incomplete_shutdowns;
754 __u8 rsvd116[4];
755 __u8 percent_free_blocks;
756 __u8 rsvd121[7];
757 __u16 capacitor_health;
758 __u8 nvme_base_errata_ver;
759 __u8 nvme_cmd_set_errata_ver;
760 __u8 rsvd132[4];
761 __u64 unaligned_io;
762 __u64 security_version_number;
763 __u64 total_nuse;
764 __u8 plp_start_count[16];
765 __u8 endurance_estimate[16];
766 __u64 pcie_link_retraining_cnt;
767 __u64 power_state_change_cnt;
768 char lowest_permitted_fw_rev[8];
769 __u8 rsvd216[278];
770 __u16 log_page_version;
771 __u8 log_page_guid[16];
772};
773
774static __u8 scao_guid[WDC_C0_GUID_LENGTH16] = {
775 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
776 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF
777};
778
779struct __packed__attribute__((__packed__)) wdc_nvme_c0_eol_log_page {
780 __u8 rsvd1[76];
781 __u32 eol_rbc;
782 __u32 eol_rsvd2;
783 __u32 eol_wra;
784 __u32 eol_plr;
785 __u32 eol_rsvd3;
786 __u32 eol_pfc;
787 __u32 eol_efc;
788 __u32 eol_rsvd4;
789 __u32 eol_rrer;
790 __u16 eol_cp_status;
791 __u16 eol_ip_status;
792 __u8 eol_cp_state;
793 __u8 eol_ip_state;
794};
795
796#define WDC_NVME_C6_GUID_LENGTH16 16
797#define WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6 0xc6
798#define WDC_NVME_HW_REV_LOG_PAGE_LEN512 512
799
800struct __packed__attribute__((__packed__)) wdc_nvme_hw_rev_log {
801 __u8 hw_rev_gdr; /* 0 Global Device HW Revision */
802 __u8 hw_rev_ar; /* 1 ASIC HW Revision */
803 __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */
804 __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */
805 __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */
806 __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */
807 __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */
808 __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */
809 __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */
810 __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */
811 __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */
812 __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */
813 __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */
814 __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */
815 __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */
816 __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */
817 __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */
818 __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */
819 __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */
820 __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */
821 __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */
822 __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */
823 __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */
824 __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */
825 __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */
826 __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */
827 __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */
828 __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */
829 __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */
830 __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */
831 __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */
832 __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */
833 __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */
834 __u8 hw_rev_sn[32]; /* 320 Serial Number */
835 __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */
836 __u16 hw_rev_version; /* 494 Log Page Version */
837 __u8 hw_rev_guid[16]; /* 496 Log Page GUID */
838};
839
840static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH16] = {
841 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15,
842 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C
843};
844
845struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA {
846 __u8 fileName[WDC_DE_FILE_NAME_SIZE32];
847 __u16 fileID;
848 __u64 fileSize;
849};
850
851struct WDC_DRIVE_ESSENTIALS {
852 struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA metaData;
853 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType;
854};
855
856struct WDC_DE_VU_LOG_DIRECTORY {
857 struct WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */
858 __u32 maxNumLogEntries; /* Caller to input memory allocated */
859 __u32 numOfValidLogEntries; /* API will output this value */
860};
861
862struct WDC_DE_CSA_FEATURE_ID_LIST {
863 enum NVME_FEATURE_IDENTIFIERS featureId;
864 __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE80];
865};
866
867struct tarfile_metadata {
868 char fileName[MAX_PATH_LEN256];
869 int8_t bufferFolderPath[MAX_PATH_LEN256];
870 char bufferFolderName[MAX_PATH_LEN256];
871 char tarFileName[MAX_PATH_LEN256];
872 char tarFiles[MAX_PATH_LEN256];
873 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
874 char currDir[MAX_PATH_LEN256];
875 UtilsTimeInfo timeInfo;
876 uint8_t *timeString[MAX_PATH_LEN256];
877};
878
879static struct WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = {
880 {0x00, "Dummy Placeholder"},
881 {FID_ARBITRATION, "Arbitration"},
882 {FID_POWER_MANAGEMENT, "PowerMgmnt"},
883 {FID_LBA_RANGE_TYPE, "LbaRangeType"},
884 {FID_TEMPERATURE_THRESHOLD, "TempThreshold"},
885 {FID_ERROR_RECOVERY, "ErrorRecovery"},
886 {FID_VOLATILE_WRITE_CACHE, "VolatileWriteCache"},
887 {FID_NUMBER_OF_QUEUES, "NumOfQueues"},
888 {FID_INTERRUPT_COALESCING, "InterruptCoalesing"},
889 {FID_INTERRUPT_VECTOR_CONFIGURATION, "InterruptVectorConfig"},
890 {FID_WRITE_ATOMICITY, "WriteAtomicity"},
891 {FID_ASYNCHRONOUS_EVENT_CONFIGURATION, "AsynEventConfig"},
892 {FID_AUTONOMOUS_POWER_STATE_TRANSITION, "AutonomousPowerState"},
893};
894
895enum NVME_VU_DE_LOGPAGE_NAMES {
896 NVME_DE_LOGPAGE_E3 = 0x01,
897 NVME_DE_LOGPAGE_C0 = 0x02
898};
899
900struct NVME_VU_DE_LOGPAGE_LIST {
901 enum NVME_VU_DE_LOGPAGE_NAMES logPageName;
902 __u32 logPageId;
903 __u32 logPageLen;
904 char logPageIdStr[5];
905};
906
907struct WDC_NVME_DE_VU_LOGPAGES {
908 enum NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd;
909 __u32 numOfVULogPages;
910};
911
912static struct NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = {
913 { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"},
914 { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"}
915};
916
917enum {
918 WDC_NVME_ADMIN_VUC_OPCODE_D2 = 0xD2,
919 WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2 = 0x0000010A,
920 WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2 = 0x00000105,
921};
922
923enum {
924 NVME_LOG_NS_BASE = 0x80,
925 NVME_LOG_VS_BASE = 0xC0,
926};
927
928/*drive_info struct*/
929struct ocp_drive_info {
930 __u32 hw_revision;
931 __u32 ftl_unit_size;
932};
933
934/*get log page directory struct*/
935struct log_page_directory {
936 __u64 supported_lid_bitmap;
937 __u64 rsvd;
938 __u64 supported_ns_lid_bitmap;
939 __u64 supported_vs_lid_bitmap;
940};
941
942/*set latency monitor feature */
943struct __packed__attribute__((__packed__)) feature_latency_monitor {
944 __u16 active_bucket_timer_threshold;
945 __u8 active_threshold_a;
946 __u8 active_threshold_b;
947 __u8 active_threshold_c;
948 __u8 active_threshold_d;
949 __u16 active_latency_config;
950 __u8 active_latency_minimum_window;
951 __u16 debug_log_trigger_enable;
952 __u8 discard_debug_log;
953 __u8 latency_monitor_feature_enable;
954 __u8 reserved[4083];
955};
956
957static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len, const char *suffix);
958static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
959 __u32 drive_log_length);
960static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12);
961static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12,
962 const char *file, __u32 xfer_size);
963static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type);
964static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type);
965static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
966 struct plugin *plugin);
967static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file);
968static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin);
969static const char *wdc_purge_mon_status_to_string(__u32 status);
970static int wdc_purge(int argc, char **argv, struct command *acmd, struct plugin *plugin);
971static int wdc_purge_monitor(int argc, char **argv, struct command *acmd, struct plugin *plugin);
972static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
973 struct libnvme_transport_handle *hdl,
974 __u8 log_id,
975 __u8 uuid_index);
976static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
977 struct plugin *plugin);
978static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *dir, char *key);
979static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
980 struct plugin *plugin);
981static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin);
982static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
983 struct plugin *plugin);
984static int wdc_drive_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin);
985static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size);
986static int wdc_namespace_resize(int argc, char **argv, struct command *acmd,
987 struct plugin *plugin);
988static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option);
989static int wdc_reason_identifier(int argc, char **argv, struct command *acmd,
990 struct plugin *plugin);
991static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id);
992static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size);
993static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl);
994static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
995 struct plugin *plugin);
996static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result);
997static int wdc_vs_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin);
998static int wdc_vs_temperature_stats(int argc, char **argv, struct command *acmd,
999 struct plugin *plugin);
1000static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1001static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len,
1002 FILE *out);
1003static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len, int xfer_size,
1004 FILE *out, int data_id, int cdw14, int cdw15);
1005static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __u8 log_id,
1006 void **cbs_data);
1007static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1008static int wdc_print_c0_cloud_attr_log(void *data,
1009 int fmt,
1010 struct libnvme_transport_handle *hdl);
1011static int wdc_print_c0_eol_log(void *data, int fmt);
1012static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
1013 struct libnvme_transport_handle *hdl);
1014static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log);
1015static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx,
1016 struct libnvme_transport_handle *hdl,
1017 void **data);
1018static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data,
1019 __u32 *ret_data,
1020 __u32 entry_id);
1021static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
1022 __u32 entry_id,
1023 char *ret_data,
1024 __u32 *ret_data_len);
1025
1026/* Drive log data size */
1027struct wdc_log_size {
1028 __le32 log_size;
1029};
1030
1031/* E6 log header */
1032struct wdc_e6_log_hdr {
1033 __le32 eye_catcher;
1034 __u8 log_size[4];
1035};
1036
1037/* DUI log header */
1038struct wdc_dui_log_section {
1039 __le16 section_type;
1040 __le16 reserved;
1041 __le32 section_size;
1042};
1043
1044/* DUI log header V2 */
1045struct __packed__attribute__((__packed__)) wdc_dui_log_section_v2 {
1046 __le16 section_type;
1047 __le16 data_area_id;
1048 __le64 section_size;
1049};
1050
1051/* DUI log header V4 */
1052struct wdc_dui_log_section_v4 {
1053 __le16 section_type;
1054 __u8 data_area_id;
1055 __u8 reserved;
1056 __le32 section_size_sectors;
1057};
1058
1059struct wdc_dui_log_hdr {
1060 __u8 telemetry_hdr[512];
1061 __le16 hdr_version;
1062 __le16 section_count;
1063 __le32 log_size;
1064 struct wdc_dui_log_section log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1065 __u8 log_data[40];
1066};
1067
1068struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v2 {
1069 __u8 telemetry_hdr[512];
1070 __u8 hdr_version;
1071 __u8 product_id;
1072 __le16 section_count;
1073 __le64 log_size;
1074 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V20x26];
1075 __u8 log_data[40];
1076};
1077
1078struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v3 {
1079 __u8 telemetry_hdr[512];
1080 __u8 hdr_version;
1081 __u8 product_id;
1082 __le16 section_count;
1083 __le64 log_size;
1084 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V30x23];
1085 __u8 securityNonce[36];
1086 __u8 log_data[40];
1087};
1088
1089struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v4 {
1090 __u8 telemetry_hdr[512];
1091 __u8 hdr_version;
1092 __u8 product_id;
1093 __le16 section_count;
1094 __le32 log_size_sectors;
1095 struct wdc_dui_log_section_v4 log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1096 __u8 log_data[40];
1097};
1098
1099/* Purge monitor response */
1100struct wdc_nvme_purge_monitor_data {
1101 __le16 rsvd1;
1102 __le16 rsvd2;
1103 __le16 first_erase_failure_cnt;
1104 __le16 second_erase_failure_cnt;
1105 __le16 rsvd3;
1106 __le16 programm_failure_cnt;
1107 __le32 rsvd4;
1108 __le32 rsvd5;
1109 __le32 entire_progress_total;
1110 __le32 entire_progress_current;
1111 __u8 rsvd6[14];
1112};
1113
1114/* Additional Smart Log */
1115struct wdc_log_page_header {
1116 uint8_t num_subpages;
1117 uint8_t reserved;
1118 __le16 total_log_size;
1119};
1120
1121struct wdc_log_page_subpage_header {
1122 uint8_t spcode;
1123 uint8_t pcset;
1124 __le16 subpage_length;
1125};
1126
1127struct wdc_ssd_perf_stats {
1128 __le64 hr_cmds; /* Host Read Commands */
1129 __le64 hr_blks; /* Host Read Blocks */
1130 __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */
1131 __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */
1132 __le64 hr_st_cmds; /* Host Read Stalled Commands */
1133 __le64 hw_cmds; /* Host Write Commands */
1134 __le64 hw_blks; /* Host Write Blocks */
1135 __le64 hw_os_cmds; /* Host Write Odd Start Commands */
1136 __le64 hw_oe_cmds; /* Host Write Odd End Commands */
1137 __le64 hw_st_cmds; /* Host Write Commands Stalled */
1138 __le64 nr_cmds; /* NAND Read Commands */
1139 __le64 nr_blks; /* NAND Read Blocks */
1140 __le64 nw_cmds; /* NAND Write Commands */
1141 __le64 nw_blks; /* NAND Write Blocks */
1142 __le64 nrbw; /* NAND Read Before Write */
1143};
1144
1145/* Additional C2 Log Page */
1146struct wdc_c2_log_page_header {
1147 __le32 length;
1148 __le32 version;
1149};
1150
1151struct wdc_c2_log_subpage_header {
1152 __le32 length;
1153 __le32 entry_id;
1154 __le32 data;
1155};
1156
1157struct wdc_c2_cbs_data {
1158 __le32 length;
1159 __u8 data[];
1160};
1161
1162struct __packed__attribute__((__packed__)) wdc_bd_ca_log_format {
1163 __u8 field_id;
1164 __u8 reserved1[2];
1165 __u8 normalized_value;
1166 __u8 raw_value[8];
1167};
1168
1169#define WDC_LATENCY_LOG_BUCKET_READ3 3
1170#define WDC_LATENCY_LOG_BUCKET_WRITE2 2
1171#define WDC_LATENCY_LOG_BUCKET_TRIM1 1
1172#define WDC_LATENCY_LOG_BUCKET_RESERVED0 0
1173
1174#define WDC_LATENCY_LOG_MEASURED_LAT_READ2 2
1175#define WDC_LATENCY_LOG_MEASURED_LAT_WRITE1 1
1176#define WDC_LATENCY_LOG_MEASURED_LAT_TRIM0 0
1177
1178struct __packed__attribute__((__packed__)) wdc_ssd_latency_monitor_log {
1179 __u8 feature_status; /* 0x00 */
1180 __u8 rsvd1; /* 0x01 */
1181 __le16 active_bucket_timer; /* 0x02 */
1182 __le16 active_bucket_timer_threshold; /* 0x04 */
1183 __u8 active_threshold_a; /* 0x06 */
1184 __u8 active_threshold_b; /* 0x07 */
1185 __u8 active_threshold_c; /* 0x08 */
1186 __u8 active_threshold_d; /* 0x09 */
1187 __le16 active_latency_config; /* 0x0A */
1188 __u8 active_latency_min_window; /* 0x0C */
1189 __u8 rsvd2[0x13]; /* 0x0D */
1190
1191 __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */
1192 __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
1193 __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
1194 __le16 active_latency_stamp_units; /* 0xD8 */
1195 __u8 rsvd3[0x16]; /* 0xDA */
1196
1197 __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
1198 __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
1199 __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
1200 __le16 static_latency_stamp_units; /* 0x1A8 */
1201 __u8 rsvd4[10]; /* 0x1AA */
1202
1203 __u8 debug_telemetry_log_size[12]; /* 0x1B4 */
1204 __le16 debug_log_trigger_enable; /* 0x1C0 */
1205 __le16 debug_log_measured_latency; /* 0x1C2 */
1206 __le64 debug_log_latency_stamp; /* 0x1C4 */
1207 __le16 debug_log_ptr; /* 0x1CC */
1208 __le16 debug_log_counter_trigger; /* 0x1CE */
1209 __u8 debug_log_stamp_units; /* 0x1D0 */
1210 __u8 rsvd5[0x1D]; /* 0x1D1 */
1211
1212 __le16 log_page_version; /* 0x1EE */
1213 __u8 log_page_guid[0x10]; /* 0x1F0 */
1214};
1215
1216struct __packed__attribute__((__packed__)) wdc_ssd_ca_perf_stats {
1217 __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */
1218 __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */
1219 __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */
1220 __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */
1221 __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */
1222 __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */
1223 __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */
1224 __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */
1225 __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */
1226 __u8 data_percent_used; /* 0x40 - System Data Percent Used */
1227 __le32 data_erase_max; /* 0x41 - User Data Erase Counts */
1228 __le32 data_erase_min; /* 0x45 - User Data Erase Counts */
1229 __le64 refresh_count; /* 0x49 - Refresh Count */
1230 __le64 program_fail; /* 0x51 - Program Fail Count */
1231 __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */
1232 __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */
1233 __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */
1234 __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */
1235 __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */
1236 __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */
1237 __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */
1238 __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */
1239};
1240
1241struct __packed__attribute__((__packed__)) wdc_ssd_d0_smart_log {
1242 __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */
1243 __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */
1244 __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */
1245 __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */
1246 __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */
1247 __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */
1248 __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */
1249 __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */
1250 __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */
1251 __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */
1252 __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */
1253 __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */
1254 __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */
1255 __le32 current_temp; /* 0x34 - Current temperature */
1256 __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */
1257 __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */
1258 __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */
1259 __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */
1260 __le32 capacitor_health; /* 0x4C - Capacitor health */
1261 __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */
1262 __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */
1263 __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */
1264 __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */
1265 __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */
1266};
1267
1268#define WDC_OCP_C1_GUID_LENGTH16 16
1269#define WDC_ERROR_REC_LOG_BUF_LEN512 512
1270#define WDC_ERROR_REC_LOG_ID0xC1 0xC1
1271
1272struct __packed__attribute__((__packed__)) wdc_ocp_c1_error_recovery_log {
1273 __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */
1274 __u8 panic_reset_action; /* 002 - Panic Reset Action */
1275 __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */
1276 __le64 panic_id; /* 004 - Panic ID */
1277 __le32 dev_capabilities; /* 012 - Device Capabilities */
1278 __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */
1279 __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */
1280 __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */
1281 __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */
1282 __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */
1283 __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */
1284 __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2 */
1285 __u8 panic_count; /* 031 - Number of panics encountered */
1286 __le64 prev_panic_ids[4]; /* 032 - 063 Previous Panic ID's */
1287 __u8 rsvd2[430]; /* 064 - 493 Reserved Bytes */
1288 /* 430 reserved bytes aligns with the rest */
1289 /* of the data structure. The size of 463 */
1290 /* bytes mentioned in the OCP spec */
1291 /* (version 2.5) would not fit here. */
1292 __le16 log_page_version; /* 494 - Log Page Version */
1293 __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH16]; /* 496 - Log Page GUID */
1294};
1295
1296static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH16] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE,
1297 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A };
1298
1299/* NAND Stats */
1300struct __packed__attribute__((__packed__)) wdc_nand_stats {
1301 __u8 nand_write_tlc[16];
1302 __u8 nand_write_slc[16];
1303 __le32 nand_prog_failure;
1304 __le32 nand_erase_failure;
1305 __le32 bad_block_count;
1306 __le64 nand_rec_trigger_event;
1307 __le64 e2e_error_counter;
1308 __le64 successful_ns_resize_event;
1309 __u8 rsvd[442];
1310 __u16 log_page_version;
1311};
1312
1313struct __packed__attribute__((__packed__)) wdc_nand_stats_V3 {
1314 __u8 nand_write_tlc[16];
1315 __u8 nand_write_slc[16];
1316 __u8 bad_nand_block_count[8];
1317 __le64 xor_recovery_count;
1318 __le64 uecc_read_error_count;
1319 __u8 ssd_correction_counts[16];
1320 __u8 percent_life_used;
1321 __le64 user_data_erase_counts[4];
1322 __u8 program_fail_count[8];
1323 __u8 erase_fail_count[8];
1324 __le64 correctable_error_count;
1325 __u8 percent_free_blocks_user;
1326 __le64 security_version_number;
1327 __u8 percent_free_blocks_system;
1328 __u8 trim_completions[25];
1329 __u8 back_pressure_guage;
1330 __le64 soft_ecc_error_count;
1331 __le64 refresh_count;
1332 __u8 bad_sys_nand_block_count[8];
1333 __u8 endurance_estimate[16];
1334 __u8 thermal_throttling_st_ct[2];
1335 __le64 unaligned_IO;
1336 __u8 physical_media_units[16];
1337 __u8 reserved[279];
1338 __u16 log_page_version;
1339};
1340
1341struct wdc_vs_pcie_stats {
1342 __le64 unsupportedRequestErrorCount;
1343 __le64 ecrcErrorStatusCount;
1344 __le64 malformedTlpStatusCount;
1345 __le64 receiverOverflowStatusCount;
1346 __le64 unexpectedCmpltnStatusCount;
1347 __le64 completeAbortStatusCount;
1348 __le64 cmpltnTimoutStatusCount;
1349 __le64 flowControlErrorStatusCount;
1350 __le64 poisonedTlpStatusCount;
1351 __le64 dLinkPrtclErrorStatusCount;
1352 __le64 advsryNFatalErrStatusCount;
1353 __le64 replayTimerToStatusCount;
1354 __le64 replayNumRolloverStCount;
1355 __le64 badDllpStatusCount;
1356 __le64 badTlpStatusCount;
1357 __le64 receiverErrStatusCount;
1358 __u8 reserved1[384];
1359};
1360
1361struct wdc_fw_act_history_log_hdr {
1362 __le32 eye_catcher;
1363 __u8 version;
1364 __u8 reserved1;
1365 __u8 num_entries;
1366 __u8 reserved2;
1367 __le32 entry_size;
1368 __le32 reserved3;
1369};
1370
1371struct wdc_fw_act_history_log_entry {
1372 __le32 entry_num;
1373 __le32 power_cycle_count;
1374 __le64 power_on_seconds;
1375 __le64 previous_fw_version;
1376 __le64 new_fw_version;
1377 __u8 slot_number;
1378 __u8 commit_action_type;
1379 __le16 result;
1380 __u8 reserved[12];
1381};
1382
1383struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 {
1384 __u8 entry_version_num;
1385 __u8 entry_len;
1386 __le16 reserved;
1387 __le16 fw_act_hist_entries;
1388 __le64 timestamp;
1389 __u8 reserved2[8];
1390 __le64 power_cycle_count;
1391 __le64 previous_fw_version;
1392 __le64 current_fw_version;
1393 __u8 slot_number;
1394 __u8 commit_action_type;
1395 __le16 result;
1396 __u8 reserved3[14];
1397};
1398
1399struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_format_c2 {
1400 __u8 log_identifier;
1401 __u8 reserved[3];
1402 __le32 num_entries;
1403 struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES20];
1404 __u8 reserved2[2790];
1405 __le16 log_page_version;
1406 __u8 log_page_guid[WDC_C2_GUID_LENGTH16];
1407};
1408
1409static __u8 ocp_C2_guid[WDC_C2_GUID_LENGTH16] = {
1410 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
1411 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
1412};
1413
1414#define WDC_OCP_C4_GUID_LENGTH16 16
1415#define WDC_DEV_CAP_LOG_BUF_LEN4096 4096
1416#define WDC_DEV_CAP_LOG_ID0xC4 0xC4
1417#define WDC_DEV_CAP_LOG_VERSION0001 0001
1418#define WDC_OCP_C4_NUM_PS_DESCR127 127
1419
1420struct __packed__attribute__((__packed__)) wdc_ocp_C4_dev_cap_log {
1421 __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */
1422 __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */
1423 __le16 wrt_zeros_support; /* 0004 - Write Zeros Command Support */
1424 __le16 sanitize_support; /* 0006 - Sanitize Command Support */
1425 __le16 dsm_support; /* 0008 - Dataset Management Command Support */
1426 __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */
1427 __le16 fused_support; /* 0012 - Fused Operation Support */
1428 __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */
1429 __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */
1430 __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR127];/* 0017 - DSSD Power State Descriptors */
1431 __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */
1432 __le16 log_page_version; /* 4078 - Log Page Version */
1433 __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1434};
1435
1436static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH16] = {
1437 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98,
1438 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7
1439};
1440
1441#define WDC_OCP_C5_GUID_LENGTH16 16
1442#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096 4096
1443#define WDC_UNSUPPORTED_REQS_LOG_ID0xC5 0xC5
1444#define WDC_UNSUPPORTED_REQS_LOG_VERSION0001 0001
1445#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES253 253
1446
1447struct __packed__attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs {
1448 __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */
1449 __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */
1450 __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES253][16]; /* 0016 - Unsupported Requirements List */
1451 __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */
1452 __le16 log_page_version; /* 4078 - Log Page Version */
1453 __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1454};
1455
1456static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH16] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB,
1457 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 };
1458
1459#define WDC_REASON_INDEX_MAX16 16
1460#define WDC_REASON_ID_ENTRY_LEN128 128
1461#define WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli" "/usr/local/nvmecli"
1462
1463const char *log_page_name[256] = {
1464 [NVME_LOG_LID_ERROR] = "Error Information",
1465 [NVME_LOG_LID_SMART] = "SMART / Health Information",
1466 [NVME_LOG_LID_FW_SLOT] = "Firmware Slot Information",
1467 [NVME_LOG_LID_CHANGED_NS] = "Changed Namespace List",
1468 [NVME_LOG_LID_CMD_EFFECTS] = "Command Supported and Effects",
1469 [NVME_LOG_LID_TELEMETRY_HOST] = "Telemetry Host-Initiated",
1470 [NVME_LOG_LID_TELEMETRY_CTRL] = "Telemetry Controller-Initiated",
1471 [NVME_LOG_LID_SANITIZE] = "Sanitize Status",
1472 [WDC_LOG_ID_C00xC0] = "Extended SMART Information",
1473 [WDC_LOG_ID_C20xC2] = "Firmware Activation History",
1474 [WDC_LOG_ID_C30xC3] = "Latency Monitor",
1475 [WDC_LOG_ID_C40xC4] = "Device Capabilities",
1476 [WDC_LOG_ID_C50xC5] = "Unsupported Requirements",
1477};
1478
1479static double safe_div_fp(double numerator, double denominator)
1480{
1481 return denominator ? numerator / denominator : 0;
1482}
1483
1484static double calc_percent(uint64_t numerator, uint64_t denominator)
1485{
1486 return denominator ?
1487 (uint64_t)(((double)numerator / (double)denominator) * 100) : 0;
1488}
1489
1490static int wdc_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id)
1491{
1492 struct nvme_id_ctrl ctrl;
1493 int ret;
1494
1495 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1496 ret = nvme_identify_ctrl(hdl, &ctrl);
1497 if (ret) {
1498 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
1499 return -1;
1500 }
1501
1502 *vendor_id = (uint32_t) ctrl.vid;
1503
1504 return ret;
1505}
1506
1507static bool_Bool wdc_is_sn861(__u32 device_id)
1508{
1509 if ((device_id == WDC_NVME_SN861_DEV_ID0x2750) ||
1510 (device_id == WDC_NVME_SN861_DEV_ID_10x2751) ||
1511 (device_id == WDC_NVME_SN861_DEV_ID_20x2752))
1512 return true1;
1513 else
1514 return false0;
1515}
1516
1517
1518static bool_Bool wdc_is_sn640(__u32 device_id)
1519{
1520 if ((device_id == WDC_NVME_SN640_DEV_ID0x2400) ||
1521 (device_id == WDC_NVME_SN640_DEV_ID_10x2401) ||
1522 (device_id == WDC_NVME_SN640_DEV_ID_20x2402))
1523 return true1;
1524 else
1525 return false0;
1526}
1527
1528static bool_Bool wdc_is_sn650_u2(__u32 device_id)
1529{
1530 if (device_id == WDC_NVME_SN650_DEV_ID_30x2720)
1531 return true1;
1532 else
1533 return false0;
1534}
1535
1536static bool_Bool wdc_is_sn650_e1l(__u32 device_id)
1537{
1538 if (device_id == WDC_NVME_SN650_DEV_ID_40x2721)
1539 return true1;
1540 else
1541 return false0;
1542}
1543
1544static bool_Bool wdc_is_zn350(__u32 device_id)
1545{
1546 return (device_id == WDC_NVME_ZN350_DEV_ID0x5010 ||
1547 device_id == WDC_NVME_ZN350_DEV_ID_10x5018);
1548}
1549static bool_Bool needs_c2_log_page_check(__u32 device_id)
1550{
1551 if ((wdc_is_sn640(device_id)) ||
1552 (wdc_is_sn650_u2(device_id)) ||
1553 (wdc_is_sn650_e1l(device_id)))
1554 return true1;
1555 else
1556 return false0;
1557}
1558
1559static bool_Bool wdc_check_power_of_2(int num)
1560{
1561 return num && (!(num & (num-1)));
1562}
1563
1564static int wdc_get_model_number(struct libnvme_transport_handle *hdl, char *model)
1565{
1566 struct nvme_id_ctrl ctrl;
1567 int ret, i;
1568
1569 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1570 ret = nvme_identify_ctrl(hdl, &ctrl);
1571 if (ret) {
1572 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
1573 return -1;
1574 }
1575
1576 memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE40);
1577 /* get rid of the padded spaces */
1578 i = NVME_ID_CTRL_MODEL_NUMBER_SIZE40-1;
1579 while (model[i] == ' ')
1580 i--;
1581 model[i+1] = 0;
1582
1583 return ret;
1584}
1585
1586static bool_Bool wdc_check_device(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1587{
1588 int ret;
1589 bool_Bool supported;
1590 uint32_t read_device_id = -1, read_vendor_id = -1;
1591
1592 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1593 if (ret < 0) {
1594 /* Use the identify nvme command to get vendor id due to NVMeOF device. */
1595 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1596 return false0;
1597 }
1598
1599 supported = false0;
1600
1601 if (read_vendor_id == WDC_NVME_VID0x1c58 ||
1602 read_vendor_id == WDC_NVME_VID_20x1b96 ||
1603 read_vendor_id == WDC_NVME_SNDK_VID0x15b7)
1604 supported = true1;
1605 else
1606 nvme_show_error(nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
1607 "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n",nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
1608 read_vendor_id, read_device_id)nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
;
1609
1610 return supported;
1611}
1612
1613static bool_Bool wdc_enc_check_model(struct libnvme_transport_handle *hdl)
1614{
1615 int ret;
1616 bool_Bool supported;
1617 char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40+1];
1618
1619 ret = wdc_get_model_number(hdl, model);
1620 if (ret < 0)
1621 return false0;
1622
1623 supported = false0;
1624 model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40] = 0; /* forced termination */
1625 if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL)_Generic (0 ? (model) : (void *) 1, const void *: (const char
*) (strstr (model, "OpenFlex")), default: strstr (model, "OpenFlex"
))
)
1626 supported = true1;
1627 else
1628 nvme_show_error("ERROR: WDC: unsupported WDC enclosure, Model = %s", model)nvme_show_message(1, "ERROR: WDC: unsupported WDC enclosure, Model = %s"
, model)
;
1629
1630 return supported;
1631}
1632
1633static __u64 wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1634{
1635 int ret;
1636 uint32_t read_device_id = -1, read_vendor_id = -1;
1637 __u64 capabilities = 0;
1638 __u32 cust_id;
1639
1640 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1641 if (ret < 0) {
1642 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1643 return capabilities;
1644 }
1645
1646 /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
1647 if (read_device_id == -1 && read_vendor_id != -1) {
1648 capabilities = wdc_get_enc_drive_capabilities(ctx, hdl);
1649 return capabilities;
1650 }
1651
1652 switch (read_vendor_id) {
1653 case WDC_NVME_VID0x1c58:
1654 switch (read_device_id) {
1655 case WDC_NVME_SN100_DEV_ID0x0003:
1656 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 |
1657 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1658 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1659 break;
1660
1661 case WDC_NVME_SN200_DEV_ID0x0023:
1662 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1663 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1664 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1665
1666 /* verify the 0xCA log page is supported */
1667 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1668 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1669 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1670
1671 /* verify the 0xC1 log page is supported */
1672 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1673 WDC_NVME_ADD_LOG_OPCODE0xC1, 0))
1674 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
1675 break;
1676
1677 default:
1678 capabilities = 0;
1679 }
1680 break;
1681
1682 case WDC_NVME_VID_20x1b96:
1683 switch (read_device_id) {
1684 case WDC_NVME_SN630_DEV_ID0x2200:
1685 case WDC_NVME_SN630_DEV_ID_10x2201:
1686 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1687 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1688 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1689 /* verify the 0xCA log page is supported */
1690 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1691 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1692 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1693
1694 /* verify the 0xD0 log page is supported */
1695 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1696 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1697 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1698 break;
1699
1700 case WDC_NVME_SN640_DEV_ID0x2400:
1701 case WDC_NVME_SN640_DEV_ID_10x2401:
1702 case WDC_NVME_SN640_DEV_ID_20x2402:
1703 case WDC_NVME_SN640_DEV_ID_30x2404:
1704 case WDC_NVME_SN560_DEV_ID_10x2712:
1705 case WDC_NVME_SN560_DEV_ID_20x2713:
1706 case WDC_NVME_SN560_DEV_ID_30x2714:
1707 case WDC_NVME_SN660_DEV_ID0x2704:
1708 /* verify the 0xC0 log page is supported */
1709 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1710 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)
1711 == true1) {
1712 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1713 }
1714
1715 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1716 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1717 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1718 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1719 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1720
1721 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1722 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1723 WDC_ERROR_REC_LOG_ID0xC1, 0))
1724 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1725
1726 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1727 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1728 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1729 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1730
1731 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1732 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1733 WDC_DEV_CAP_LOG_ID0xC4, 0))
1734 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1735
1736 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1737 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1738 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1739 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1740
1741 /* verify the 0xCA log page is supported */
1742 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1743 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1744 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1745
1746 /* verify the 0xD0 log page is supported */
1747 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1748 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1749 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1750
1751 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1752 /* Can still determine some capabilities in this case, but log an error */
1753 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1754 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1755 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1756 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1757
1758 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1759 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) || (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1760 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1761 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1762 else
1763 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1764
1765 break;
1766
1767 case WDC_NVME_SN840_DEV_ID0x2300:
1768 case WDC_NVME_SN840_DEV_ID_10x2500:
1769 case WDC_NVME_SN860_DEV_ID0x2730:
1770 /* verify the 0xC0 log page is supported */
1771 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1772 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, 0))
1773 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1774 fallthrough__attribute__((fallthrough));
1775 case WDC_NVME_ZN540_DEV_ID0x2600:
1776 case WDC_NVME_SN540_DEV_ID0x2610:
1777 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1778 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1779 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1780 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1781 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1782 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1783
1784 /* verify the 0xCA log page is supported */
1785 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1786 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1787 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1788
1789 /* verify the 0xD0 log page is supported */
1790 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1791 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1792 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1793 break;
1794
1795 case WDC_NVME_SN650_DEV_ID0x2700:
1796 case WDC_NVME_SN650_DEV_ID_10x2701:
1797 case WDC_NVME_SN650_DEV_ID_20x2702:
1798 case WDC_NVME_SN650_DEV_ID_30x2720:
1799 case WDC_NVME_SN650_DEV_ID_40x2721:
1800 case WDC_NVME_SN655_DEV_ID0x2722:
1801 case WDC_NVME_SN655_DEV_ID_10x2723:
1802 case WDC_NVME_SN550_DEV_ID0x2708:
1803 /* verify the 0xC0 log page is supported */
1804 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1805 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
1806 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1807
1808 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1809 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1810 WDC_ERROR_REC_LOG_ID0xC1, 0))
1811 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1812
1813 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1814 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1815 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1816 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1817
1818 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1819 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1820 WDC_DEV_CAP_LOG_ID0xC4, 0))
1821 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1822
1823 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1824 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1825 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1826 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1827
1828 /* verify the 0xCA log page is supported */
1829 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1830 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
1831 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1832
1833 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1834 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1835 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1836 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 |
1837 WDC_DRIVE_CAP_REASON_ID0x0000000000010000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1838
1839 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1840 /* Can still determine some capabilities in this case, but log an error */
1841 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1842 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1843 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1844 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1845
1846 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
1847 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1848 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
1849 (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1850 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1851 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1852 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1853 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1854 else
1855 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1856 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1857
1858 break;
1859
1860 case WDC_NVME_SN861_DEV_ID0x2750:
1861 case WDC_NVME_SN861_DEV_ID_10x2751:
1862 case WDC_NVME_SN861_DEV_ID_20x2752:
1863 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1864 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1865 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1866 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1867 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1868 WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1869 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
1870 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1871 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1872 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1873 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1874 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1875 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1876 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1877 break;
1878
1879 case WDC_NVME_SNTMP_DEV_ID0x2761:
1880 case WDC_NVME_SNTMP_DEV_ID_10x2763:
1881 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1882 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1883 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1884 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1885 WDC_DRIVE_CAP_DUI0x0000000800000000 |
1886 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1887 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1888 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1889 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1890 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1891 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1892 break;
1893
1894 default:
1895 capabilities = 0;
1896 }
1897 break;
1898
1899 case WDC_NVME_SNDK_VID0x15b7:
1900 switch (read_device_id) {
1901 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
1902 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
1903 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
1904 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
1905 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
1906 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1907 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1908 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1909 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1910 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1911 WDC_DRIVE_CAP_UDUI0x0000040000000000 |
1912 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1913 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1914 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1915 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1916 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1917 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1918 break;
1919
1920 case WDC_NVME_SXSLCL_DEV_ID0x2001:
1921 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
1922 break;
1923
1924 case WDC_NVME_SN520_DEV_ID0x5003:
1925 case WDC_NVME_SN520_DEV_ID_10x5004:
1926 case WDC_NVME_SN520_DEV_ID_20x5005:
1927 case WDC_NVME_SN810_DEV_ID0x5011:
1928 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000;
1929 break;
1930
1931 case WDC_NVME_SN820CL_DEV_ID0x5037:
1932 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 |
1933 WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 |
1934 WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 | WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1935 WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
1936 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1937 WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000;
1938 break;
1939
1940 case WDC_NVME_SN720_DEV_ID0x5002:
1941 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1942 WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000;
1943 break;
1944
1945 case WDC_NVME_SN730_DEV_ID0x5006:
1946 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1947 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 |
1948 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000;
1949 break;
1950
1951 case WDC_NVME_SN530_DEV_ID_10x5007:
1952 fallthrough__attribute__((fallthrough));
1953 case WDC_NVME_SN530_DEV_ID_20x5008:
1954 fallthrough__attribute__((fallthrough));
1955 case WDC_NVME_SN530_DEV_ID_30x5009:
1956 fallthrough__attribute__((fallthrough));
1957 case WDC_NVME_SN530_DEV_ID_40x500b:
1958 fallthrough__attribute__((fallthrough));
1959 case WDC_NVME_SN530_DEV_ID_50x501d:
1960 fallthrough__attribute__((fallthrough));
1961 case WDC_NVME_SN350_DEV_ID0x5019:
1962 fallthrough__attribute__((fallthrough));
1963 case WDC_NVME_SN570_DEV_ID0x501A:
1964 fallthrough__attribute__((fallthrough));
1965 case WDC_NVME_SN850X_DEV_ID0x5030:
1966 fallthrough__attribute__((fallthrough));
1967 case WDC_NVME_SN5000_DEV_ID_10x5034:
1968 fallthrough__attribute__((fallthrough));
1969 case WDC_NVME_SN5000_DEV_ID_20x5035:
1970 fallthrough__attribute__((fallthrough));
1971 case WDC_NVME_SN5000_DEV_ID_30x5036:
1972 fallthrough__attribute__((fallthrough));
1973 case WDC_NVME_SN5000_DEV_ID_40x504A:
1974 fallthrough__attribute__((fallthrough));
1975 case WDC_NVME_SN7000S_DEV_ID_10x5039:
1976 fallthrough__attribute__((fallthrough));
1977 case WDC_NVME_SN7150_DEV_ID_10x503b:
1978 fallthrough__attribute__((fallthrough));
1979 case WDC_NVME_SN7150_DEV_ID_20x503c:
1980 fallthrough__attribute__((fallthrough));
1981 case WDC_NVME_SN7150_DEV_ID_30x503d:
1982 fallthrough__attribute__((fallthrough));
1983 case WDC_NVME_SN7150_DEV_ID_40x503e:
1984 fallthrough__attribute__((fallthrough));
1985 case WDC_NVME_SN7150_DEV_ID_50x503f:
1986 fallthrough__attribute__((fallthrough));
1987 case WDC_NVME_SN7100_DEV_ID_10x5043:
1988 fallthrough__attribute__((fallthrough));
1989 case WDC_NVME_SN7100_DEV_ID_20x5044:
1990 fallthrough__attribute__((fallthrough));
1991 case WDC_NVME_SN7100_DEV_ID_30x5045:
1992 fallthrough__attribute__((fallthrough));
1993 case WDC_NVME_SN8000S_DEV_ID0x5049:
1994 fallthrough__attribute__((fallthrough));
1995 case WDC_NVME_SN5100S_DEV_ID_10x5061:
1996 fallthrough__attribute__((fallthrough));
1997 case WDC_NVME_SN5100S_DEV_ID_20x5062:
1998 fallthrough__attribute__((fallthrough));
1999 case WDC_NVME_SN5100S_DEV_ID_30x5063:
2000 fallthrough__attribute__((fallthrough));
2001 case WDC_NVME_SN740_DEV_ID0x5015:
2002 case WDC_NVME_SN740_DEV_ID_10x5016:
2003 case WDC_NVME_SN740_DEV_ID_20x5017:
2004 case WDC_NVME_SN740_DEV_ID_30x5025:
2005 case WDC_NVME_SN340_DEV_ID0x500d:
2006 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000;
2007 break;
2008
2009 case WDC_NVME_ZN350_DEV_ID0x5010:
2010 case WDC_NVME_ZN350_DEV_ID_10x5018:
2011 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
2012 WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
2013 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2014 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
2015 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000;
2016 break;
2017
2018 default:
2019 capabilities = 0;
2020 }
2021 break;
2022 default:
2023 capabilities = 0;
2024 }
2025
2026 return capabilities;
2027}
2028
2029static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx,
2030 struct libnvme_transport_handle *hdl)
2031{
2032 int ret;
2033 uint32_t read_vendor_id;
2034 __u64 capabilities = 0;
2035 __u32 cust_id, market_name_len;
2036 char marketing_name[64];
2037 void *dev_mng_log = NULL((void*)0);
2038 int uuid_index = 0;
2039 struct nvme_id_uuid_list uuid_list;
2040
2041 memset(marketing_name, 0, 64);
2042
2043 ret = wdc_get_vendor_id(hdl, &read_vendor_id);
2044 if (ret < 0)
2045 return capabilities;
2046
2047 switch (read_vendor_id) {
2048 case WDC_NVME_VID0x1c58:
2049 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
2050 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000);
2051
2052 /* verify the 0xCA log page is supported */
2053 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2054 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2055 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2056
2057 /* verify the 0xC1 log page is supported */
2058 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2059 WDC_NVME_ADD_LOG_OPCODE0xC1, 0) == true1)
2060 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
2061 break;
2062 case WDC_NVME_VID_20x1b96:
2063 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
2064 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
2065 WDC_DRIVE_CAP_RESIZE0x0000000000000100);
2066
2067 /* Find the WDC UUID index */
2068 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2069 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2070 /* check for the Sandisk UUID first */
2071 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2072
2073 if (uuid_index < 0)
2074 /* The Sandisk UUID is not found;
2075 * check for the WDC UUID second.
2076 */
2077 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2078 }
2079
2080 /* WD UUID not found, use default uuid index - 0 */
2081 if (uuid_index < 0)
2082 uuid_index = 0;
2083
2084 /* verify the 0xC2 Device Manageability log page is supported */
2085 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2086 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
2087 uuid_index) == false0) {
2088 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not supported, index: %d",nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
2089 uuid_index)nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
;
2090 ret = -1;
2091 goto out;
2092 }
2093
2094 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
2095 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
2096 ret = -1;
2097 goto out;
2098 }
2099
2100 /* Get the customer ID and marketing name from WD C2 log page */
2101 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log,
2102 &cust_id,
2103 WDC_C2_CUSTOMER_ID_ID0x15))
2104 nvme_show_error("ERROR: SNDK: Get Customer FW ID Failed")nvme_show_message(1, "ERROR: SNDK: Get Customer FW ID Failed"
)
;
2105
2106 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
2107 WDC_C2_MARKETING_NAME_ID0x07,
2108 (char *)marketing_name,
2109 &market_name_len))
2110 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
2111
2112 /* verify the 0xC0 log page is supported */
2113 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2114 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
2115 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
2116
2117 /* verify the 0xC3 log page is supported */
2118 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2119 WDC_LATENCY_MON_LOG_ID0xC3, 0) == true1)
2120 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
2121
2122 /* verify the 0xCA log page is supported */
2123 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2124 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2125 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2126
2127 /* verify the 0xD0 log page is supported */
2128 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2129 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == true1)
2130 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
2131
2132 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
2133 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
2134 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
2135 (cust_id == WDC_CUSTOMER_ID_0x13040x1304) ||
2136 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) ||
2137 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len)))
2138 /* Set capabilities for OCP compliant drives */
2139 capabilities |= (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
2140 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2141 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000);
2142 else {
2143 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
2144 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
2145
2146 /* if the 0xCB log page is supported */
2147 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2148 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0) == true1)
2149 capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000;
2150 }
2151
2152 break;
2153 case WDC_NVME_SNDK_VID0x15b7:
2154 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
2155 break;
2156 default:
2157 capabilities = 0;
2158 }
2159
2160out:
2161 return capabilities;
2162}
2163
2164static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len,
2165 const char *suffix)
2166{
2167 int i;
2168 int ret;
2169 int res_len = 0;
2170 char orig[PATH_MAX4096] = {0};
2171 struct nvme_id_ctrl ctrl;
2172 int ctrl_sn_len = sizeof(ctrl.sn);
2173
2174 i = sizeof(ctrl.sn) - 1;
2175 strncpy(orig, file, PATH_MAX4096 - 1);
2176 memset(file, 0, len);
2177 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
2178 ret = nvme_identify_ctrl(hdl, &ctrl);
2179 if (ret) {
2180 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
2181 return -1;
2182 }
2183 /* Remove trailing spaces from the name */
2184 while (i && ctrl.sn[i] == ' ') {
2185 ctrl.sn[i] = '\0';
2186 i--;
2187 }
2188 if (ctrl.sn[sizeof(ctrl.sn) - 1] == '\0')
2189 ctrl_sn_len = strlen(ctrl.sn);
2190
2191 res_len = snprintf(file, len, "%s%.*s%s", orig, ctrl_sn_len, ctrl.sn, suffix);
2192 if (len <= res_len) {
2193 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
2194 "ERROR: WDC: cannot format serial number due to data of unexpected length\n")nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
;
2195 return -1;
2196 }
2197
2198 return 0;
2199}
2200
2201static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
2202 __u32 drive_log_length)
2203{
2204 int fd;
2205 int ret;
2206
2207 if (!drive_log_length) {
2208 nvme_show_error("ERROR: WDC: invalid log file length")nvme_show_message(1, "ERROR: WDC: invalid log file length");
2209 return -1;
2210 }
2211
2212 fd = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
2213 if (fd < 0) {
2214 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
2215 return -1;
2216 }
2217
2218 while (drive_log_length > WRITE_SIZE(sizeof(__u8) * 4096)) {
2219 ret = write(fd, drive_log_data, WRITE_SIZE(sizeof(__u8) * 4096));
2220 if (ret < 0) {
2221 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2222 close(fd);
2223 return -1;
2224 }
2225 drive_log_data += WRITE_SIZE(sizeof(__u8) * 4096);
2226 drive_log_length -= WRITE_SIZE(sizeof(__u8) * 4096);
2227 }
2228
2229 ret = write(fd, drive_log_data, drive_log_length);
2230 if (ret < 0) {
2231 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2232 close(fd);
2233 return -1;
2234 }
2235
2236 if (fsync(fd) < 0) {
2237 nvme_show_error("ERROR: WDC: fsync: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: fsync: %s", libnvme_strerror
((*__errno_location ())))
;
2238 close(fd);
2239 return -1;
2240 }
2241 close(fd);
2242 return 0;
2243}
2244
2245bool_Bool wdc_validate_dev_mng_log(void *data)
2246{
2247 __u32 remaining_len = 0;
2248 __u32 log_length = 0;
2249 __u32 log_entry_size = 0;
2250 __u32 log_entry_id = 0;
2251 __u32 offset = 0;
2252 bool_Bool valid_log = false0;
2253 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2254 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2255
2256 log_length = le32_to_cpu(hdr_ptr->length);
2257 /* Ensure log data is large enough for common header */
2258 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2259 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2260 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2261 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2262 return valid_log;
2263 }
2264
2265 /* Get pointer to first log Entry */
2266 offset = sizeof(struct wdc_c2_log_page_header);
2267 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2268 remaining_len = log_length - offset;
2269
2270 /* Proceed only if there is at least enough data to read an entry header */
2271 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2272 /* Get size of the next entry */
2273 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2274 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2275 /*
2276 * If log entry size is 0 or the log entry goes past the end
2277 * of the data, we must be at the end of the data
2278 */
2279 if (!log_entry_size || log_entry_size > remaining_len) {
2280 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2281 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2282 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2283 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2284 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2285 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2286
2287 /* Force the loop to end */
2288 remaining_len = 0;
2289 } else if (!log_entry_id || log_entry_id > 200) {
2290 /* Invalid entry - fail the search */
2291 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2292 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2293 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2294 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2295 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2296
2297 /* Force the loop to end */
2298 remaining_len = 0;
2299 valid_log = false0;
2300 } else {
2301 /* A valid log has at least one entry and no invalid entries */
2302 valid_log = true1;
2303 remaining_len -= log_entry_size;
2304 if (remaining_len > 0) {
2305 /* Increment the offset counter */
2306 offset += log_entry_size;
2307 /* Get the next entry */
2308 p_next_log_entry =
2309 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2310 }
2311 }
2312 }
2313
2314 return valid_log;
2315}
2316
2317bool_Bool wdc_parse_dev_mng_log_entry(void *data, __u32 entry_id,
2318 struct wdc_c2_log_subpage_header **log_entry)
2319{
2320 __u32 remaining_len = 0;
2321 __u32 log_length = 0;
2322 __u32 log_entry_size = 0;
2323 __u32 log_entry_id = 0;
2324 __u32 offset = 0;
2325 bool_Bool found = false0;
2326 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2327 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2328
2329 log_length = le32_to_cpu(hdr_ptr->length);
2330 /* Ensure log data is large enough for common header */
2331 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2332 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2333 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2334 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2335 return found;
2336 }
2337
2338 /* Get pointer to first log Entry */
2339 offset = sizeof(struct wdc_c2_log_page_header);
2340 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2341 remaining_len = log_length - offset;
2342
2343 if (!log_entry) {
2344 nvme_show_error("ERROR: WDC - %s: No log entry pointer.", __func__)nvme_show_message(1, "ERROR: WDC - %s: No log entry pointer."
, __func__)
;
2345 return found;
2346 }
2347 *log_entry = NULL((void*)0);
2348
2349 /* Proceed only if there is at least enough data to read an entry header */
2350 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2351 /* Get size of the next entry */
2352 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2353 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2354
2355 /*
2356 * If log entry size is 0 or the log entry goes past the end
2357 * of the data, we must be at the end of the data
2358 */
2359 if (!log_entry_size || log_entry_size > remaining_len) {
2360 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2361 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2362 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2363 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2364 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2365 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2366
2367 /* Force the loop to end */
2368 remaining_len = 0;
2369 } else if (!log_entry_id || log_entry_id > 200) {
2370 /* Invalid entry - fail the search */
2371 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2372 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2373 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2374 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2375 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2376
2377 /* Force the loop to end */
2378 remaining_len = 0;
2379 } else {
2380 if (log_entry_id == entry_id) {
2381 found = true1;
2382 *log_entry = p_next_log_entry;
2383 remaining_len = 0;
2384 } else {
2385 remaining_len -= log_entry_size;
2386 }
2387
2388 if (remaining_len > 0) {
2389 /* Increment the offset counter */
2390 offset += log_entry_size;
2391
2392 /* Get the next entry */
2393 p_next_log_entry =
2394 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2395 }
2396 }
2397 }
2398
2399 return found;
2400}
2401
2402bool_Bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id,
2403 struct wdc_c2_log_page_header *p_log_hdr,
2404 struct wdc_c2_log_subpage_header **p_p_found_log_entry)
2405{
2406 __u32 remaining_len = 0;
2407 __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1;
2408 __u32 log_entry_size = 0;
2409 __u32 log_entry_id = 0;
2410 __u32 size = 0;
2411 bool_Bool valid_log;
2412 __u32 offset = 0;
2413 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2414
2415 *p_p_found_log_entry = NULL((void*)0);
2416
2417 /* Ensure log data is large enough for common header */
2418 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2419 nvme_show_error(nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2420 "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2421 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2422 return false0;
2423 }
2424
2425 /* Get pointer to first log Entry */
2426 size = sizeof(struct wdc_c2_log_page_header);
2427 offset = size;
2428 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2429 remaining_len = log_length - size;
2430 valid_log = false0;
2431
2432 /*
2433 * Walk the entire structure. Perform a sanity check to make sure this is a
2434 * standard version of the structure. This means making sure each entry looks
2435 * valid. But allow for the data to overflow the allocated
2436 * buffer (we don't want a false negative because of a FW formatting error)
2437 */
2438
2439 /* Proceed only if there is at least enough data to read an entry header */
2440 while (remaining_len >= log_entry_hdr_size) {
2441 /* Get size of the next entry */
2442 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2443 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2444
2445 /*
2446 * If log entry size is 0 or the log entry goes past the end
2447 * of the data, we must be at the end of the data
2448 */
2449 if (!log_entry_size || log_entry_size > remaining_len) {
2450 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2451 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2452 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2453 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2454 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2455 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2456
2457 /* Force the loop to end */
2458 remaining_len = 0;
2459 } else if (!log_entry_id || log_entry_id > 200) {
2460 /* Invalid entry - fail the search */
2461 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2462 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2463 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2464 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2465 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2466
2467 /* Force the loop to end */
2468 remaining_len = 0;
2469 valid_log = false0;
2470
2471 /* The structure is invalid, so any match that was found is invalid. */
2472 *p_p_found_log_entry = NULL((void*)0);
2473 } else {
2474 /* Structure must have at least one valid entry to be considered valid */
2475 valid_log = true1;
2476 if (log_entry_id == entry_id)
2477 /* A potential match. */
2478 *p_p_found_log_entry = p_next_log_entry;
2479
2480 remaining_len -= log_entry_size;
2481
2482 if (remaining_len > 0) {
2483 /* Increment the offset counter */
2484 offset += log_entry_size;
2485
2486 /* Get the next entry */
2487 p_next_log_entry =
2488 (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2489 }
2490 }
2491 }
2492
2493 return valid_log;
2494}
2495
2496static bool_Bool get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, void **log_data,
2497 __u8 uuid_ix)
2498{
2499 struct wdc_c2_log_page_header *hdr_ptr;
2500 struct libnvme_passthru_cmd cmd;
2501 bool_Bool valid = false0;
2502 __u32 length = 0;
2503 void *data;
2504 int ret = 0;
2505
2506 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2507 if (!data) {
2508 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2509 return false0;
2510 }
2511
2512 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2513
2514 /* get the log page length */
2515 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2516 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2517 WDC_C2_LOG_BUF_LEN0x1000);
2518 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2519 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2520 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2521 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2522 if (ret) {
2523 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2524 "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2525 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2526 goto end;
2527 }
2528
2529 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2530 length = le32_to_cpu(hdr_ptr->length);
2531
2532 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2533 /* Log page buffer too small for actual data */
2534 free(data);
2535 data = calloc(length, sizeof(__u8));
2536 if (!data) {
2537 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2538 goto end;
2539 }
2540
2541 /* get the log page data with the increased length */
2542 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2543 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2544 length);
2545 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2546 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2547 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2548 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2549 if (ret) {
2550 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2551 "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2552 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2553 goto end;
2554 }
2555 }
2556
2557 valid = wdc_validate_dev_mng_log(data);
2558 if (valid) {
2559 /* Ensure size of log data matches length in log header */
2560 *log_data = calloc(length, sizeof(__u8));
2561 if (!*log_data) {
2562 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2563 valid = false0;
2564 goto end;
2565 }
2566 memcpy((void *)*log_data, data, length);
2567 } else {
2568 nvme_show_error("ERROR: WDC: C2 log page not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
2569 uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
;
2570 }
2571
2572end:
2573 free(data);
2574 return valid;
2575}
2576
2577static bool_Bool get_dev_mgmt_log_page_lid_data(struct libnvme_transport_handle *hdl,
2578 void **cbs_data,
2579 __u8 lid,
2580 __u8 log_id,
2581 __u8 uuid_ix)
2582{
2583 void *data;
2584 struct wdc_c2_log_page_header *hdr_ptr;
2585 struct wdc_c2_log_subpage_header *sph;
2586 struct libnvme_passthru_cmd cmd;
2587 __u32 length = 0;
2588 int ret = 0;
2589 bool_Bool found = false0;
2590
2591 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2592 if (!data) {
2593 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2594 return false0;
2595 }
2596
2597 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2598
2599 /* get the log page length */
2600 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2601 WDC_C2_LOG_BUF_LEN0x1000);
2602 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2603 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2604 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2605 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2606 if (ret) {
2607 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2608 "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2609 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2610 goto end;
2611 }
2612
2613 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2614 length = le32_to_cpu(hdr_ptr->length);
2615
2616 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2617 /* Log Page buffer too small, free and reallocate the necessary size */
2618 free(data);
2619 data = calloc(length, sizeof(__u8));
2620 if (!data) {
2621 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2622 goto end;
2623 }
2624
2625 /* get the log page data with the increased length */
2626 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2627 length);
2628 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2629 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2630 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2631 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2632 if (ret) {
2633 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2634 "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2635 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2636 goto end;
2637 }
2638 }
2639
2640 /* Check the log data to see if the WD version of log page ID's is found */
2641 length = sizeof(struct wdc_c2_log_page_header);
2642 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2643 sph = NULL((void*)0);
2644 found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
2645 if (found && sph) {
2646 *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
2647 if (!*cbs_data) {
2648 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2649 found = false0;
2650 goto end;
2651 }
2652 memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
2653 } else if(found && !sph) {
2654 nvme_show_error("ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d",log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d"
,log_id, uuid_ix)
;
2655 found = false0;
2656 } else {
2657 nvme_show_error("ERROR: WDC: C2 log id 0x%x not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
2658 log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
;
2659 }
2660
2661end:
2662 free(data);
2663 return found;
2664}
2665
2666static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2667 void **data)
2668{
2669 bool_Bool found = false0;
2670 __u32 device_id = 0, vendor_id = 0;
2671 int uuid_index = 0;
2672 struct nvme_id_uuid_list uuid_list;
2673
2674 *data = NULL((void*)0);
2675
2676 /* The nvme_get_pci_ids() function could fail when drives are connected
2677 * via a PCIe switch. Therefore, the return code is intentionally
2678 * being ignored. The device_id and vendor_id variables have been
2679 * initialized to 0 so the code can continue on without issue for
2680 * both cases: successful or failed.
2681 */
2682 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2683
2684 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2685 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2686 /* check for the Sandisk UUID first */
2687 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2688
2689 if (uuid_index < 0) {
2690 /* The Sandisk UUID is not found;
2691 * check for the WDC UUID second.
2692 */
2693 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2694 if (uuid_index < 0)
2695 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2696 }
2697
2698 if (uuid_index >= 0)
2699 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2700 else {
2701 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2702 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2703 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2704 }
2705 } else if (needs_c2_log_page_check(device_id)) {
2706 /* In certain devices that don't support UUID lists, there are multiple
2707 * definitions of the C2 logpage. In those cases, the code
2708 * needs to try two UUID indexes and use an identification algorithm
2709 * to determine which is returning the correct log page data.
2710 */
2711
2712 uuid_index = 1;
2713 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2714
2715 if (!found) {
2716 /* not found with uuid = 1 try with uuid = 0 */
2717 uuid_index = 0;
2718 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2719 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2720
2721 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2722 }
2723 } else {
2724 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2725 uuid_index = 0;
2726 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2727 }
2728
2729 return found;
2730}
2731
2732static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2733 __u8 log_id, void **cbs_data)
2734{
2735 bool_Bool found = false0;
2736 __u8 lid = 0;
2737 __u32 device_id = 0, vendor_id = 0;
2738 int uuid_index = 0;
2739 struct nvme_id_uuid_list uuid_list;
2740
2741 *cbs_data = NULL((void*)0);
2742
2743 /* The nvme_get_pci_ids function could fail when drives are connected
2744 * via a PCIe switch. Therefore, the return code is intentionally
2745 * being ignored. The device_id and vendor_id variables have been
2746 * initialized to 0 so the code can continue on without issue for
2747 * both cases: successful or failed.
2748 */
2749 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2750
2751 lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
2752
2753 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2754 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2755 /* check for the Sandisk UUID first */
2756 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2757
2758 if (uuid_index < 0) {
2759 /* The Sandisk UUID is not found;
2760 * check for the WDC UUID second.
2761 */
2762 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2763 if (uuid_index < 0)
2764 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2765 }
2766
2767 if (uuid_index >= 0)
2768 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid,
2769 log_id, uuid_index);
2770 else {
2771 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2772 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2773 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2774 }
2775 } else if (needs_c2_log_page_check(device_id)) {
2776 /* In certain devices that don't support UUID lists, there are multiple
2777 * definitions of the C2 logpage. In those cases, the code
2778 * needs to try two UUID indexes and use an identification algorithm
2779 * to determine which is returning the correct log page data.
2780 */
2781 uuid_index = 1;
2782 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2783 if (!found) {
2784 /* not found with uuid = 1 try with uuid = 0 */
2785 uuid_index = 0;
2786 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2787 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2788
2789 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id,
2790 uuid_index);
2791 }
2792 } else {
2793 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2794 uuid_index = 0;
2795 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2796 }
2797
2798 return found;
2799}
2800
2801static int wdc_get_supported_log_pages(struct libnvme_transport_handle *hdl,
2802 struct nvme_supported_log_pages *supported,
2803 int uuid_index)
2804{
2805 struct libnvme_passthru_cmd cmd;
2806
2807 memset(supported, 0, sizeof(*supported));
2808 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
2809 NVME_CSI_NVM, supported, sizeof(*supported));
2810 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2811 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2812 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2813 return libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2814}
2815
2816static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
2817 struct libnvme_transport_handle *hdl,
2818 __u8 log_id,
2819 __u8 uuid_index)
2820{
2821 int i;
2822 bool_Bool found = false0;
2823 int err = -1;
2824 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
2825
2826 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_supported_log_pages *supports = NULL((void*)0);
2827
2828 /* Check log page id 0 (supported log pages) first */
2829 supports = libnvme_alloc(sizeof(*supports));
2830 if (!supports)
2831 return -ENOMEM12;
2832
2833 err = wdc_get_supported_log_pages(hdl,
2834 supports,
2835 uuid_index);
2836
2837 if (!err) {
2838 /* Check support log page list for support */
2839 if (supports->lid_support[log_id])
2840 /* Support for Log Page found in supported log pages */
2841 found = true1;
2842 }
2843
2844 /* if not found in the supported log pages (log id 0),
2845 * check the WDC C2 log page
2846 */
2847 if (!found) {
2848 if (get_dev_mgment_cbs_data(ctx, hdl,
2849 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
2850 (void *)&cbs_data)) {
2851 if (cbs_data) {
2852 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
2853 if (log_id == cbs_data->data[i]) {
2854 found = true1;
2855 break;
2856 }
2857 }
2858
2859#ifdef WDC_NVME_CLI_DEBUG
2860 if (!found) {
2861 nvme_show_error("ERROR: WDC: Log Page 0x%x not supported",nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
2862 log_id)nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
;
2863 nvme_show_error("WDC: Supported Log Pages:")nvme_show_message(1, "WDC: Supported Log Pages:");
2864 /* print the supported pages */
2865 d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length),
2866 16, 1);
2867 }
2868#endif
2869 free(cbs_data);
2870 } else {
2871 nvme_show_error("ERROR: WDC: cbs_data ptr = NULL")nvme_show_message(1, "ERROR: WDC: cbs_data ptr = NULL");
2872 }
2873 } else {
2874 nvme_show_error("ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found",nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
2875 WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
;
2876 }
2877 }
2878
2879 return found;
2880}
2881
2882static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data,
2883 __u32 entry_id)
2884{
2885 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2886
2887 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2888 if (entry_data) {
2889 *ret_data = le32_to_cpu(entry_data->data);
2890 return true1;
2891 }
2892 }
2893
2894 *ret_data = 0;
2895 return false0;
2896}
2897
2898static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
2899 __u32 entry_id,
2900 char *ret_data,
2901 __u32 *ret_data_len)
2902{
2903 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2904 struct wdc_c2_cbs_data *entry_str_data = NULL((void*)0);
2905
2906 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2907 if (entry_data) {
2908 entry_str_data = (struct wdc_c2_cbs_data *)&entry_data->data;
2909 memcpy(ret_data,
2910 (void *)&entry_str_data->data,
2911 le32_to_cpu(entry_str_data->length));
2912 *ret_data_len = le32_to_cpu(entry_str_data->length);
2913 return true1;
2914 }
2915 }
2916
2917 *ret_data = 0;
2918 *ret_data_len = 0;
2919 return false0;
2920}
2921
2922static bool_Bool wdc_nvme_get_dev_status_log_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __le32 *ret_data,
2923 __u8 log_id)
2924{
2925 __u32 *cbs_data = NULL((void*)0);
2926
2927 if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data)) {
2928 if (cbs_data) {
2929 memcpy((void *)ret_data, (void *)cbs_data, 4);
2930 free(cbs_data);
2931
2932 return true1;
2933 }
2934 }
2935
2936 *ret_data = 0;
2937 return false0;
2938}
2939
2940static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12)
2941{
2942 int ret;
2943 struct libnvme_passthru_cmd admin_cmd;
2944
2945 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2946 admin_cmd.opcode = opcode;
2947 admin_cmd.cdw12 = cdw12;
2948 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
2949 if (ret)
2950 fprintf(stdoutstdout, "ERROR: WDC: Crash dump erase failed\n");
2951 nvme_show_status(ret);
2952 return ret;
2953}
2954
2955static __u32 wdc_dump_length(struct libnvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length)
2956{
2957 int ret;
2958 __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN0x08] = {0};
2959 struct wdc_log_size *l;
2960 struct libnvme_passthru_cmd admin_cmd;
2961
2962 l = (struct wdc_log_size *) buf;
2963 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2964 admin_cmd.opcode = opcode;
2965 admin_cmd.addr = (__u64)(uintptr_t)buf;
2966 admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN0x08;
2967 admin_cmd.cdw10 = cdw10;
2968 admin_cmd.cdw12 = cdw12;
2969
2970 ret = libnvme_exec_admin_passthru(link, &admin_cmd);
2971 if (ret) {
2972 l->log_size = 0;
2973 ret = -1;
2974 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
2975 nvme_show_status(ret);
2976 return ret;
2977 }
2978
2979 if (opcode == WDC_NVME_CAP_DIAG_OPCODE0xE6)
2980 *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07];
2981 else
2982 *dump_length = le32_to_cpu(l->log_size);
2983 return ret;
2984}
2985
2986static __u32 wdc_dump_length_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
2987{
2988 int ret;
2989 struct libnvme_passthru_cmd admin_cmd;
2990
2991 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2992 admin_cmd.opcode = opcode;
2993 admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
2994 admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
2995 admin_cmd.cdw10 = cdw10;
2996 admin_cmd.cdw12 = cdw12;
2997
2998 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
2999 if (ret) {
3000 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3001 nvme_show_status(ret);
3002 }
3003
3004 return ret;
3005}
3006
3007static __u32 wdc_dump_dui_data(struct libnvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool_Bool last_xfer)
3008{
3009 int ret;
3010 struct libnvme_passthru_cmd admin_cmd;
3011
3012 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3013 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3014 admin_cmd.nsid = 0xFFFFFFFF;
3015 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3016 admin_cmd.data_len = dataLen;
3017 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3018 admin_cmd.cdw12 = offset;
3019 if (last_xfer)
3020 admin_cmd.cdw14 = 0;
3021 else
3022 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3023
3024
3025 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3026 if (ret) {
3027 nvme_show_error("ERROR: WDC: reading DUI data failed")nvme_show_message(1, "ERROR: WDC: reading DUI data failed");
3028 nvme_show_status(ret);
3029 }
3030
3031 return ret;
3032}
3033
3034static __u32 wdc_dump_dui_data_v2(struct libnvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool_Bool last_xfer)
3035{
3036 int ret;
3037 struct libnvme_passthru_cmd admin_cmd;
3038 __u64 offset_lo, offset_hi;
3039
3040 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3041 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3042 admin_cmd.nsid = 0xFFFFFFFF;
3043 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3044 admin_cmd.data_len = dataLen;
3045 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3046 offset_lo = offset & 0x00000000FFFFFFFF;
3047 offset_hi = ((offset & 0xFFFFFFFF00000000) >> 32);
3048 admin_cmd.cdw12 = (__u32)offset_lo;
3049 admin_cmd.cdw13 = (__u32)offset_hi;
3050
3051 if (last_xfer)
3052 admin_cmd.cdw14 = 0;
3053 else
3054 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3055
3056 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3057 if (ret) {
3058 nvme_show_error("ERROR: WDC: reading DUI data V2 failed")nvme_show_message(1, "ERROR: WDC: reading DUI data V2 failed"
)
;
3059 nvme_show_status(ret);
3060 }
3061
3062 return ret;
3063}
3064
3065static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3066 __u32 cdw12, const char *file, __u32 xfer_size)
3067{
3068 int ret = 0;
3069 __u8 *dump_data;
3070 __u32 curr_data_offset, curr_data_len;
3071 int i;
3072 struct libnvme_passthru_cmd admin_cmd;
3073 __u32 dump_length = data_len;
3074
3075 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
3076 if (!dump_data) {
3077 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3078 return -1;
3079 }
3080 memset(dump_data, 0, sizeof(__u8) * dump_length);
3081 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3082 curr_data_offset = 0;
3083 curr_data_len = xfer_size;
3084 i = 0;
3085
3086 admin_cmd.opcode = opcode;
3087 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3088 admin_cmd.data_len = curr_data_len;
3089 admin_cmd.cdw10 = curr_data_len >> 2;
3090 admin_cmd.cdw12 = cdw12;
3091 admin_cmd.cdw13 = curr_data_offset;
3092
3093 while (curr_data_offset < data_len) {
3094 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3095 if (ret) {
3096 nvme_show_status(ret);
3097 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
3098 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
3099 break;
3100 }
3101
3102 if ((curr_data_offset + xfer_size) <= data_len)
3103 curr_data_len = xfer_size;
3104 else
3105 curr_data_len = data_len - curr_data_offset; /* last transfer */
3106
3107 curr_data_offset += curr_data_len;
3108 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3109 admin_cmd.data_len = curr_data_len;
3110 admin_cmd.cdw10 = curr_data_len >> 2;
3111 admin_cmd.cdw13 = curr_data_offset >> 2;
3112 i++;
3113 }
3114
3115 if (!ret) {
3116 nvme_show_status(ret);
3117 ret = wdc_create_log_file(file, dump_data, dump_length);
3118 }
3119 free(dump_data);
3120 return ret;
3121}
3122
3123static int wdc_do_dump_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3124 __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
3125{
3126 int ret = 0;
3127 __u8 *dump_data;
3128 __u32 curr_data_offset, log_size;
3129 int i;
3130 struct libnvme_passthru_cmd admin_cmd;
3131
3132 /* if data_len is not 4 byte aligned */
3133 if (data_len & 0x00000003) {
3134 /* Round down to the next 4 byte aligned value */
3135 nvme_show_error("%s: INFO: data_len 0x%x not 4 byte aligned.",nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
3136 __func__, data_len)nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
;
3137 nvme_show_error("%s: INFO: Round down to 0x%x.",nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, (data_len &= 0xFFFFFFFC))
3138 __func__, (data_len &= 0xFFFFFFFC))nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, (data_len &= 0xFFFFFFFC))
;
3139 data_len &= 0xFFFFFFFC;
3140 }
3141
3142 dump_data = (__u8 *)malloc(sizeof(__u8) * data_len);
3143
3144 if (!dump_data) {
3145 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3146 return -1;
3147 }
3148 memset(dump_data, 0, sizeof(__u8) * data_len);
3149 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3150 curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3151 i = 0;
3152
3153 /* copy the 8 byte header into the dump_data buffer */
3154 memcpy(dump_data, log_hdr, WDC_NVME_LOG_SIZE_HDR_LEN0x08);
3155
3156 admin_cmd.opcode = opcode;
3157 admin_cmd.cdw12 = cdw12;
3158
3159 /* subtract off the header size since that was already copied into the buffer */
3160 log_size = (data_len - curr_data_offset);
3161 while (log_size > 0) {
3162 xfer_size = min(xfer_size, log_size)((xfer_size) > (log_size) ? (log_size) : (xfer_size));
3163
3164 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3165 admin_cmd.data_len = xfer_size;
3166 admin_cmd.cdw10 = xfer_size >> 2;
3167 admin_cmd.cdw13 = curr_data_offset >> 2;
3168
3169 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3170 if (ret) {
3171 nvme_show_status(ret);
3172 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
3173 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
3174 break;
3175 }
3176
3177 log_size -= xfer_size;
3178 curr_data_offset += xfer_size;
3179 i++;
3180 }
3181
3182 if (!ret) {
3183 nvme_show_error("%s: INFO: ", __func__)nvme_show_message(1, "%s: INFO: ", __func__);
3184 nvme_show_status(ret);
3185 } else {
3186 nvme_show_error("%s: FAILURE: ", __func__)nvme_show_message(1, "%s: FAILURE: ", __func__);
3187 nvme_show_status(ret);
3188 nvme_show_error("%s: Partial data may have been captured", __func__)nvme_show_message(1, "%s: Partial data may have been captured"
, __func__)
;
3189 snprintf(file + strlen(file), PATH_MAX4096, "%s", "-PARTIAL");
3190 }
3191
3192 ret = wdc_create_log_file(file, dump_data, data_len);
3193
3194 free(dump_data);
3195 return ret;
3196}
3197
3198static int wdc_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
3199 struct libnvme_transport_handle *hdl, const char *file,
3200 __u32 bs, int type, int data_area)
3201{
3202 struct nvme_telemetry_log *log;
3203 size_t full_size = 0;
3204 int err = 0, output;
3205 __u32 host_gen = 1;
3206 int ctrl_init = 0;
3207 __u64 result;
3208 void *buf = NULL((void*)0);
3209 __u8 *data_ptr = NULL((void*)0);
3210 int data_written = 0, data_remaining = 0;
3211 struct nvme_id_ctrl ctrl;
3212 __u64 capabilities = 0;
3213
3214 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
3215 err = nvme_identify_ctrl(hdl, &ctrl);
3216 if (err) {
3217 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", err)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, err)
;
3218 return err;
3219 }
3220
3221 if (!(ctrl.lpa & 0x8)) {
3222 nvme_show_error("Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported")nvme_show_message(1, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported"
)
;
3223 return -EINVAL22;
3224 }
3225
3226 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3227 if (err) {
3228 nvme_show_error("Failed to scan nvme subsystems")nvme_show_message(1, "Failed to scan nvme subsystems");
3229 return err;
3230 }
3231
3232 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3233
3234 if (type == WDC_TELEMETRY_TYPE_HOST0x1) {
3235 host_gen = 1;
3236 ctrl_init = 0;
3237 } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2) {
3238 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
3239 /* Verify the Controller Initiated Option is enabled */
3240 err = nvme_get_features(hdl, 0,
3241 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
3242 NVME_GET_FEATURES_SEL_CURRENT, 0, 0,
3243 buf, 4, &result);
3244 if (!err) {
3245 if (!result) {
3246 /* enabled */
3247 host_gen = 0;
3248 ctrl_init = 1;
3249 } else {
3250 nvme_show_error("%s: Controller initiated option telemetry log page disabled", __func__)nvme_show_message(1, "%s: Controller initiated option telemetry log page disabled"
, __func__)
;
3251 return -EINVAL22;
3252 }
3253 } else {
3254 nvme_show_error("ERROR: WDC: Get telemetry option feature failed.")nvme_show_message(1, "ERROR: WDC: Get telemetry option feature failed."
)
;
3255 nvme_show_status(err);
3256 return -EPERM1;
3257 }
3258 } else {
3259 host_gen = 0;
3260 ctrl_init = 1;
3261 }
3262 } else {
3263 nvme_show_error("%s: Invalid type parameter; type = %d", __func__, type)nvme_show_message(1, "%s: Invalid type parameter; type = %d",
__func__, type)
;
3264 return -EINVAL22;
3265 }
3266
3267 if (!file) {
3268 nvme_show_error("%s: Please provide an output file!", __func__)nvme_show_message(1, "%s: Please provide an output file!", __func__
)
;
3269 return -EINVAL22;
3270 }
3271
3272 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3273 if (output < 0) {
3274 nvme_show_error("%s: Failed to open output file %s: %s!",nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3275 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3276 return output;
3277 }
3278
3279 if (ctrl_init)
3280 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
3281 data_area, &full_size);
3282 else if (host_gen)
3283 err = libnvme_get_new_host_telemetry(hdl, &log,
3284 data_area, &full_size);
3285 else
3286 err = libnvme_get_host_telemetry(hdl, &log, data_area,
3287 &full_size);
3288
3289 if (err < 0) {
3290 nvme_show_err(err, "get-telemetry-log");
3291 goto close_output;
3292 } else if (err > 0) {
3293 nvme_show_status(err);
3294 nvme_show_error("%s: Failed to acquire telemetry header!", __func__)nvme_show_message(1, "%s: Failed to acquire telemetry header!"
, __func__)
;
3295 goto close_output;
3296 }
3297
3298 /*
3299 *Continuously pull data until the offset hits the end of the last
3300 *block.
3301 */
3302 data_written = 0;
3303 data_remaining = full_size;
3304 data_ptr = (__u8 *)log;
3305
3306 while (data_remaining) {
3307 data_written = write(output, data_ptr, data_remaining);
3308
3309 if (data_written < 0) {
3310 data_remaining = data_written;
3311 break;
3312 } else if (data_written <= data_remaining) {
3313 data_remaining -= data_written;
3314 data_ptr += data_written;
3315 } else {
3316 /* Unexpected overwrite */
3317 nvme_show_error("Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x",nvme_show_message(1, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x"
, data_remaining, data_written)
3318 data_remaining, data_written)nvme_show_message(1, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x"
, data_remaining, data_written)
;
3319 break;
3320 }
3321 }
3322
3323 if (fsync(output) < 0) {
3324 nvme_show_error("ERROR: %s: fsync: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "ERROR: %s: fsync: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3325 err = -1;
3326 }
3327
3328 free(log);
3329close_output:
3330 close(output);
3331 return err;
3332}
3333
3334static int wdc_do_cap_diag(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *file,
3335 __u32 xfer_size, int type, int data_area)
3336{
3337 int ret = -1;
3338 __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08;
3339 struct wdc_e6_log_hdr *log_hdr;
3340 __u32 cap_diag_length;
3341
3342 log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size);
3343 if (!log_hdr) {
3344 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3345 ret = -1;
3346 goto out;
3347 }
3348 memset(log_hdr, 0, e6_log_hdr_size);
3349
3350 if (type == WDC_TELEMETRY_TYPE_NONE0x0) {
3351 if (data_area) {
3352 nvme_show_error(nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3353 "%s: ERROR: Data area parameter is not supported when type is NONE\n",nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3354 __func__)nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
;
3355 ret = -1;
3356 goto out;
3357 }
3358 ret = wdc_dump_length_e6(hdl,
3359 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3360 WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08>>2,
3361 0x00,
3362 log_hdr);
3363 if (ret == -1) {
3364 ret = -1;
3365 goto out;
3366 }
3367
3368 cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 |
3369 log_hdr->log_size[2] << 8 | log_hdr->log_size[3]);
3370
3371 if (!cap_diag_length) {
3372 nvme_show_error("INFO: WDC: Capture Diagnostics log is empty")nvme_show_message(1, "INFO: WDC: Capture Diagnostics log is empty"
)
;
3373 } else {
3374 ret = wdc_do_dump_e6(hdl,
3375 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3376 cap_diag_length,
3377 (WDC_NVME_CAP_DIAG_SUBCMD0x00 << WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_CAP_DIAG_CMD0x00,
3378 file, xfer_size, (__u8 *)log_hdr);
3379
3380 nvme_show_error("INFO: WDC: Capture Diagnostics log, length = 0x%x", cap_diag_length)nvme_show_message(1, "INFO: WDC: Capture Diagnostics log, length = 0x%x"
, cap_diag_length)
;
3381 }
3382 } else if ((type == WDC_TELEMETRY_TYPE_HOST0x1) ||
3383 (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
3384 /* Get the desired telemetry log page */
3385 ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size,
3386 type, data_area);
3387 } else {
3388 nvme_show_error("%s: ERROR: Invalid type : %d", __func__, type)nvme_show_message(1, "%s: ERROR: Invalid type : %d", __func__
, type)
;
3389 }
3390
3391out:
3392 free(log_hdr);
3393 return ret;
3394}
3395
3396static int wdc_do_cap_dui_v1(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3397 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size)
3398{
3399 __s32 log_size = 0;
3400 __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size);
3401 __u32 curr_data_offset = 0;
3402 __u8 *buffer_addr;
3403 __u8 *dump_data = NULL((void*)0);
3404 bool_Bool last_xfer = false0;
3405 int err;
3406 int i;
3407 int j;
3408 int output;
3409 int ret = 0;
3410
3411 if (verbose) {
3412 nvme_show_error("INFO: WDC: Capture V1 Device Unit Info log, data area = %d",nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
3413 data_area)nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
;
3414 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x", log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr
->hdr_version)
;
3415 nvme_show_error("INFO: WDC: DUI section count = 0x%x", log_hdr->section_count)nvme_show_message(1, "INFO: WDC: DUI section count = 0x%x", log_hdr
->section_count)
;
3416 nvme_show_error("INFO: WDC: DUI log size = 0x%x", log_hdr->log_size)nvme_show_message(1, "INFO: WDC: DUI log size = 0x%x", log_hdr
->log_size)
;
3417 }
3418
3419 if (!cap_dui_length) {
3420 nvme_show_error("INFO: WDC: Capture V1 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log is empty"
)
;
3421 return 0;
3422 }
3423
3424 /* parse log header for all sections up to specified data area inclusively */
3425 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3426 for (j = 0; j < log_hdr->section_count; j++) {
3427 log_size += log_hdr->log_section[j].section_size;
3428 if (verbose)
3429 nvme_show_error(nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3430 "%s: section size 0x%x, total size = 0x%x\n",nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3431 __func__,nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3432 (unsigned int)log_hdr->log_section[j].section_size,nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3433 (unsigned int)log_size)nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
;
3434
3435 }
3436 } else {
3437 log_size = cap_dui_length;
3438 }
3439
3440 *total_size = log_size;
3441
3442 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size);
3443 if (!dump_data) {
3444 nvme_show_error("%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x",nvme_show_message(1, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size)
3445 __func__, libnvme_strerror(errno), (unsigned int)xfer_size)nvme_show_message(1, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size)
;
3446 return -1;
3447 }
3448 memset(dump_data, 0, sizeof(__u8) * xfer_size);
3449
3450 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3451 if (output < 0) {
3452 nvme_show_error("%s: Failed to open output file %s: %s!", __func__, file,nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3453 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3454 free(dump_data);
3455 return output;
3456 }
3457
3458 /* write the telemetry and log headers into the dump_file */
3459 err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE0x400);
3460 if (err != WDC_NVME_CAP_DUI_HEADER_SIZE0x400) {
3461 nvme_show_error("%s: Failed to flush header data to file!", __func__)nvme_show_message(1, "%s: Failed to flush header data to file!"
, __func__)
;
3462 goto free_mem;
3463 }
3464
3465 log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3466 curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3467 i = 0;
3468 buffer_addr = dump_data;
3469
3470 for (; log_size > 0; log_size -= xfer_size) {
3471 xfer_size = min(xfer_size, log_size)((xfer_size) > (log_size) ? (log_size) : (xfer_size));
3472
3473 if (log_size <= xfer_size)
3474 last_xfer = true1;
3475
3476 ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer);
3477 if (ret) {
3478 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
3479 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
3480 __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
;
3481 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3482 nvme_show_status(ret);
3483 break;
3484 }
3485
3486 /* write the dump data into the file */
3487 err = write(output, (void *)buffer_addr, xfer_size);
3488 if (err != xfer_size) {
3489 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
3490 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
3491 __func__, i, err, xfer_size)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
;
3492 ret = -1;
3493 goto free_mem;
3494 }
3495
3496 curr_data_offset += xfer_size;
3497 i++;
3498 }
3499
3500free_mem:
3501 close(output);
3502 free(dump_data);
3503 return ret;
3504}
3505
3506static int wdc_do_cap_dui_v2_v3(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3507 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3508 __u64 offset)
3509{
3510 __u64 cap_dui_length_v3;
3511 __u64 curr_data_offset = 0;
3512 __s64 log_size = 0;
3513 __u64 xfer_size_long = (__u64)xfer_size;
3514 __u8 *buffer_addr;
3515 __u8 *dump_data = NULL((void*)0);
3516 bool_Bool last_xfer = false0;
3517 int err;
3518 int i;
3519 int j;
3520 int output;
3521 int ret = 0;
3522 struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr;
3523
3524 cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size);
3525
3526 if (verbose) {
3527 nvme_show_error(nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3528 "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n",nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3529 data_area)nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
;
3530
3531 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x",nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
3532 log_hdr_v3->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
;
3533 if ((log_hdr->hdr_version & 0xFF) == 0x03)
3534 nvme_show_error("INFO: WDC: DUI Product ID = 0x%x/%c",nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v3
->product_id, log_hdr_v3->product_id)
3535 log_hdr_v3->product_id, log_hdr_v3->product_id)nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v3
->product_id, log_hdr_v3->product_id)
;
3536 }
3537
3538 if (!cap_dui_length_v3) {
3539 nvme_show_error("INFO: WDC: Capture V2 or V3 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log is empty"
)
;
3540 return 0;
3541 }
3542
3543 /* parse log header for all sections up to specified data area inclusively */
3544 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3545 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V30x23; j++) {
3546 if (log_hdr_v3->log_section[j].data_area_id <= data_area &&
3547 log_hdr_v3->log_section[j].data_area_id) {
3548 log_size += log_hdr_v3->log_section[j].section_size;
3549 if (verbose)
3550 nvme_show_error(nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3551 "%s: Data area ID %d : section size 0x%x, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3552 __func__, log_hdr_v3->log_section[j].data_area_id,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3553 (unsigned int)log_hdr_v3->log_section[j].section_size,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3554 (uint64_t)log_size)nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
;
3555 } else {
3556 if (verbose)
3557 nvme_show_error("%s: break, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
3558 __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3559 break;
3560 }
3561 }
3562 } else {
3563 log_size = cap_dui_length_v3;
3564 }
3565
3566 *total_size = log_size;
3567
3568 if (offset >= *total_size) {
3569 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3570 "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3571 __func__, (uint64_t)offset, (uint64_t)*total_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
;
3572 return -1;
3573 }
3574
3575 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3576 if (!dump_data) {
3577 nvme_show_error(nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
3578 "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
3579 __func__, libnvme_strerror(errno), (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
;
3580 return -1;
3581 }
3582 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3583
3584 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3585 if (output < 0) {
3586 nvme_show_error("%s: Failed to open output file %s: %s!",nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3587 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3588 free(dump_data);
3589 return output;
3590 }
3591
3592 curr_data_offset = 0;
3593
3594 if (file_size) {
3595 /* Write the DUI data based on the passed in file size */
3596 if ((offset + file_size) > *total_size)
3597 log_size = min((*total_size - offset), file_size)(((*total_size - offset)) > (file_size) ? (file_size) : ((
*total_size - offset)))
;
3598 else
3599 log_size = min(*total_size, file_size)((*total_size) > (file_size) ? (file_size) : (*total_size)
)
;
3600
3601 if (verbose)
3602 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3603 "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3604 __func__, (uint64_t)offset,nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3605 (uint64_t)file_size, (uint64_t)*total_size, (uint64_t)log_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
;
3606
3607 curr_data_offset = offset;
3608 }
3609
3610 i = 0;
3611 buffer_addr = dump_data;
3612
3613 for (; log_size > 0; log_size -= xfer_size_long) {
3614 xfer_size_long = min(xfer_size_long, log_size)((xfer_size_long) > (log_size) ? (log_size) : (xfer_size_long
))
;
3615
3616 if (log_size <= xfer_size_long)
3617 last_xfer = true1;
3618
3619 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr,
3620 last_xfer);
3621 if (ret) {
3622 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3623 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3624 __func__, i, (uint64_t)*total_size, (uint64_t)curr_data_offset,nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3625 buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
;
3626 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3627 nvme_show_status(ret);
3628 break;
3629 }
3630
3631 /* write the dump data into the file */
3632 err = write(output, (void *)buffer_addr, xfer_size_long);
3633 if (err != xfer_size_long) {
3634 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3635 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3636 __func__, i, err, (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
;
3637 ret = -1;
3638 goto free_mem;
3639 }
3640
3641 curr_data_offset += xfer_size_long;
3642 i++;
3643 }
3644
3645free_mem:
3646 close(output);
3647 free(dump_data);
3648 return ret;
3649}
3650
3651static int wdc_do_cap_dui_v4(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3652 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3653 __u64 offset)
3654{
3655 __s64 log_size = 0;
3656 __s64 section_size_bytes = 0;
3657 __s64 xfer_size_long = (__s64)xfer_size;
3658 __u64 cap_dui_length_v4;
3659 __u64 curr_data_offset = 0;
3660 __u8 *buffer_addr;
3661 __u8 *dump_data = NULL((void*)0);
3662 int err;
3663 int i;
3664 int j;
3665 int output;
3666 int ret = 0;
3667 bool_Bool last_xfer = false0;
3668 struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr;
3669
3670 cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE512;
3671
3672 if (verbose) {
3673 nvme_show_error("INFO: WDC: Capture V4 Device Unit Info log, data area = %d", data_area)nvme_show_message(1, "INFO: WDC: Capture V4 Device Unit Info log, data area = %d"
, data_area)
;
3674 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x", log_hdr_v4->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v4
->hdr_version)
;
3675 nvme_show_error("INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v4->product_id, log_hdr_v4->product_id)nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v4
->product_id, log_hdr_v4->product_id)
;
3676 nvme_show_error("INFO: WDC: DUI log size sectors = 0x%x", log_hdr_v4->log_size_sectors)nvme_show_message(1, "INFO: WDC: DUI log size sectors = 0x%x"
, log_hdr_v4->log_size_sectors)
;
3677 nvme_show_error("INFO: WDC: DUI cap_dui_length = 0x%"PRIx64"\n", (uint64_t)cap_dui_length_v4)nvme_show_message(1, "INFO: WDC: DUI cap_dui_length = 0x%""l"
"x""\n", (uint64_t)cap_dui_length_v4)
;
3678 }
3679
3680 if (!cap_dui_length_v4) {
3681 nvme_show_error("INFO: WDC: Capture V4 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V4 Device Unit Info log is empty"
)
;
3682 return 0;
3683 }
3684
3685 /* parse log header for all sections up to specified data area inclusively */
3686 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3687 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION0x3A; j++) {
3688 if (log_hdr_v4->log_section[j].data_area_id <= data_area &&
3689 log_hdr_v4->log_section[j].data_area_id) {
3690 section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE512);
3691 log_size += section_size_bytes;
3692 if (verbose)
3693 nvme_show_error(nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3694 "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"PRIx64" bytes, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3695 __func__, log_hdr_v4->log_section[j].data_area_id,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3696 log_hdr_v4->log_section[j].section_size_sectors,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3697 (uint64_t)section_size_bytes, (uint64_t)log_size)nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
;
3698 } else {
3699 if (verbose)
3700 nvme_show_error("%s: break, total size = 0x%"PRIx64"\n", __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3701 break;
3702 }
3703 }
3704 } else {
3705 log_size = cap_dui_length_v4;
3706 }
3707
3708 *total_size = log_size;
3709
3710 if (offset >= *total_size) {
3711 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3712 "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3713 __func__, (uint64_t)offset, (uint64_t)*total_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
;
3714 return -1;
3715 }
3716
3717 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3718 if (!dump_data) {
3719 nvme_show_error("%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x",nvme_show_message(1, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size_long)
3720 __func__, libnvme_strerror(errno), (unsigned int)xfer_size_long)nvme_show_message(1, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size_long)
;
3721 return -1;
3722 }
3723 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3724
3725 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3726 if (output < 0) {
3727 nvme_show_error("%s: Failed to open output file %s: %s!", __func__, file,nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3728 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3729 free(dump_data);
3730 return output;
3731 }
3732
3733 curr_data_offset = 0;
3734
3735 if (file_size) {
3736 /* Write the DUI data based on the passed in file size */
3737 if ((offset + file_size) > *total_size)
3738 log_size = min((*total_size - offset), file_size)(((*total_size - offset)) > (file_size) ? (file_size) : ((
*total_size - offset)))
;
3739 else
3740 log_size = min(*total_size, file_size)((*total_size) > (file_size) ? (file_size) : (*total_size)
)
;
3741
3742 if (verbose)
3743 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3744 "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3745 __func__, (uint64_t)offset, (uint64_t)file_size,nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3746 (uint64_t)*total_size, (uint64_t)log_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
;
3747
3748 curr_data_offset = offset;
3749 }
3750
3751 i = 0;
3752 buffer_addr = dump_data;
3753
3754 for (; log_size > 0; log_size -= xfer_size_long) {
3755 xfer_size_long = min(xfer_size_long, log_size)((xfer_size_long) > (log_size) ? (log_size) : (xfer_size_long
))
;
3756
3757 if (log_size <= xfer_size_long)
3758 last_xfer = true1;
3759
3760 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer);
3761 if (ret) {
3762 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3763 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3764 __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset,nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3765 buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
;
3766 nvme_show_error("%s: ERROR: WDC:", __func__)nvme_show_message(1, "%s: ERROR: WDC:", __func__);
3767 nvme_show_status(ret);
3768 break;
3769 }
3770
3771 /* write the dump data into the file */
3772 err = write(output, (void *)buffer_addr, xfer_size_long);
3773 if (err != xfer_size_long) {
3774 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3775 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3776 __func__, i, err, (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
;
3777 ret = -1;
3778 goto free_mem;
3779 }
3780
3781 curr_data_offset += xfer_size_long;
3782 i++;
3783 }
3784
3785free_mem:
3786 close(output);
3787 free(dump_data);
3788 return ret;
3789}
3790
3791static int wdc_do_cap_dui(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3792 __u64 file_size, __u64 offset)
3793{
3794 int ret = 0;
3795 __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3796 struct wdc_dui_log_hdr *log_hdr;
3797 __s64 total_size = 0;
3798 bool_Bool last_xfer = false0;
3799
3800 log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size);
3801 if (!log_hdr) {
3802 nvme_show_error("%s: ERROR: log header malloc failed : status %s, size 0x%x",nvme_show_message(1, "%s: ERROR: log header malloc failed : status %s, size 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), dui_log_hdr_size
)
3803 __func__, libnvme_strerror(errno), dui_log_hdr_size)nvme_show_message(1, "%s: ERROR: log header malloc failed : status %s, size 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), dui_log_hdr_size
)
;
3804 return -1;
3805 }
3806 memset(log_hdr, 0, dui_log_hdr_size);
3807
3808 /* get the dui telemetry and log headers */
3809 ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE0x400, 0x00, (__u8 *)log_hdr, last_xfer);
3810 if (ret) {
3811 nvme_show_error("%s: ERROR: WDC: Get DUI headers failed", __func__)nvme_show_message(1, "%s: ERROR: WDC: Get DUI headers failed"
, __func__)
;
3812 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3813 nvme_show_status(ret);
3814 goto out;
3815 }
3816
3817 /* Check the Log Header version */
3818 if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) {
3819 ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr,
3820 &total_size);
3821 if (ret)
3822 goto out;
3823 } else if ((log_hdr->hdr_version & 0xFF) == 0x02 ||
3824 (log_hdr->hdr_version & 0xFF) == 0x03) {
3825 /* Process Version 2 or 3 header */
3826 ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr,
3827 &total_size, file_size, offset);
3828 if (ret)
3829 goto out;
3830 } else if ((log_hdr->hdr_version & 0xFF) == 0x04) {
3831 ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr,
3832 &total_size, file_size, offset);
3833 if (ret)
3834 goto out;
3835 } else {
3836 nvme_show_error("INFO: WDC: Unsupported header version = 0x%x",nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
3837 log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
;
3838 goto out;
3839 }
3840
3841 nvme_show_status(ret);
3842 if (verbose)
3843 nvme_show_error("INFO: WDC: Capture Device Unit Info log, length = 0x%"PRIx64"\n",nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
3844 (uint64_t)total_size)nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
;
3845
3846out:
3847 free(log_hdr);
3848 return ret;
3849}
3850
3851static int wdc_cap_diag(int argc, char **argv, struct command *acmd,
3852 struct plugin *plugin)
3853{
3854 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
3855 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
3856 const char *desc = "Capture Diagnostics Log.";
3857 const char *file = "Output file pathname.";
3858 const char *size = "Data retrieval transfer size.";
3859 __u64 capabilities = 0;
3860 char f[PATH_MAX4096] = {0};
3861 __u32 xfer_size = 0;
3862 int ret = 0;
3863
3864 struct config {
3865 char *file;
3866 __u32 xfer_size;
3867 };
3868
3869 struct config cfg = {
3870 .file = NULL((void*)0),
3871 .xfer_size = 0x10000
3872 };
3873
3874 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
3875 OPT_FILE("output-file", 'O', &cfg.file, file),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
3876 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
3877
3878 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3879 if (ret)
3880 return ret;
3881
3882 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3883 if (ret)
3884 return ret;
3885
3886 if (cfg.file)
3887 strncpy(f, cfg.file, PATH_MAX4096 - 1);
3888 if (cfg.xfer_size)
3889 xfer_size = cfg.xfer_size;
3890 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "cap_diag");
3891 if (ret) {
3892 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
3893 return ret;
3894 }
3895 if (!cfg.file) {
3896 if (strlen(f) > PATH_MAX4096 - 5) {
3897 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
3898 return -1;
3899 }
3900 strcat(f, ".bin");
3901 }
3902
3903 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3904 if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001) == WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001)
3905 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0);
3906 else
3907 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
3908 return ret;
3909}
3910
3911static int wdc_do_get_sn730_log_len(struct libnvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode)
3912{
3913 int ret;
3914 uint32_t *output = NULL((void*)0);
3915 struct libnvme_passthru_cmd admin_cmd;
3916
3917 output = (uint32_t *)malloc(sizeof(uint32_t));
3918 if (!output) {
3919 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3920 return -1;
3921 }
3922 memset(output, 0, sizeof(uint32_t));
3923 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3924
3925 admin_cmd.data_len = 8;
3926 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3927 admin_cmd.addr = (uintptr_t)output;
3928 admin_cmd.cdw12 = subopcode;
3929 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3930
3931 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3932 if (!ret)
3933 *len_buf = *output;
3934 free(output);
3935 return ret;
3936}
3937
3938static int wdc_do_get_sn730_log(struct libnvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode)
3939{
3940 int ret;
3941 uint8_t *output = NULL((void*)0);
3942 struct libnvme_passthru_cmd admin_cmd;
3943
3944 output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE0x1000, sizeof(uint8_t));
3945 if (!output) {
3946 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
3947 return -1;
3948 }
3949 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3950 admin_cmd.data_len = SN730_LOG_CHUNK_SIZE0x1000;
3951 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3952 admin_cmd.addr = (uintptr_t)output;
3953 admin_cmd.cdw12 = subopcode;
3954 admin_cmd.cdw13 = offset;
3955 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3956
3957 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3958 if (!ret)
3959 memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE0x1000);
3960 return ret;
3961}
3962
3963static int get_sn730_log_chunks(struct libnvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode)
3964{
3965 int ret = 0;
3966 uint8_t *chunk_buf = NULL((void*)0);
3967 int remaining = log_len;
3968 int curr_offset = 0;
3969
3970 chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE0x1000);
3971 if (!chunk_buf) {
3972 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3973 ret = -1;
3974 goto out;
3975 }
3976
3977 while (remaining > 0) {
3978 memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE0x1000);
3979 ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode);
3980 if (!ret) {
3981 if (remaining >= SN730_LOG_CHUNK_SIZE0x1000) {
3982 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
3983 chunk_buf, SN730_LOG_CHUNK_SIZE0x1000);
3984 } else {
3985 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
3986 chunk_buf, remaining);
3987 }
3988 remaining -= SN730_LOG_CHUNK_SIZE0x1000;
3989 curr_offset += 1;
3990 } else {
3991 goto out;
3992 }
3993 }
3994out:
3995 free(chunk_buf);
3996 return ret;
3997}
3998
3999static int wdc_do_sn730_get_and_tar(struct libnvme_transport_handle *hdl, char *outputName)
4000{
4001 int ret = 0;
4002 void *retPtr;
4003 uint8_t *full_log_buf = NULL((void*)0);
4004 uint8_t *key_log_buf = NULL((void*)0);
4005 uint8_t *core_dump_log_buf = NULL((void*)0);
4006 uint8_t *extended_log_buf = NULL((void*)0);
4007 uint32_t full_log_len = 0;
4008 uint32_t key_log_len = 0;
4009 uint32_t core_dump_log_len = 0;
4010 uint32_t extended_log_len = 0;
4011 struct tarfile_metadata *tarInfo = NULL((void*)0);
4012
4013 tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata));
4014 if (!tarInfo) {
4015 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4016 ret = -1;
4017 goto free_buf;
4018 }
4019 memset(tarInfo, 0, sizeof(struct tarfile_metadata));
4020
4021 /* Create Logs directory */
4022 wdc_UtilsGetTime(&tarInfo->timeInfo);
4023 memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString));
4024 wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
4025 tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth,
4026 tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second);
4027
4028 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN256, "%s",
4029 (char *)outputName);
4030
4031 retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN256);
4032 if (retPtr) {
4033 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
4034 (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR"/", (char *)tarInfo->bufferFolderName);
4035 } else {
4036 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
4037 goto free_buf;
4038 }
4039
4040 ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath);
4041 if (ret) {
4042 nvme_show_error("ERROR: WDC: create directory failed, ret = %d, dir = %s", ret, tarInfo->bufferFolderPath)nvme_show_message(1, "ERROR: WDC: create directory failed, ret = %d, dir = %s"
, ret, tarInfo->bufferFolderPath)
;
4043 goto free_buf;
4044 } else {
4045 nvme_show_error("Stored log files in directory: %s", tarInfo->bufferFolderPath)nvme_show_message(1, "Stored log files in directory: %s", tarInfo
->bufferFolderPath)
;
4046 }
4047
4048 ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH0x00080009);
4049 if (ret) {
4050 nvme_show_status(ret);
4051 goto free_buf;
4052 }
4053 ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH0x00090009);
4054 if (ret) {
4055 nvme_show_status(ret);
4056 goto free_buf;
4057 }
4058 ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH0x00120009);
4059 if (ret) {
4060 nvme_show_status(ret);
4061 goto free_buf;
4062 }
4063 ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH0x00420009);
4064 if (ret) {
4065 nvme_show_status(ret);
4066 goto free_buf;
4067 }
4068
4069 full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t));
4070 key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t));
4071 core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t));
4072 extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t));
4073
4074 if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) {
4075 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4076 ret = -1;
4077 goto free_buf;
4078 }
4079
4080 /* Get the full log */
4081 ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE0x00010009);
4082 if (ret) {
4083 nvme_show_status(ret);
4084 goto free_buf;
4085 }
4086
4087 /* Get the key log */
4088 ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE0x00020009);
4089 if (ret) {
4090 nvme_show_status(ret);
4091 goto free_buf;
4092 }
4093
4094 /* Get the core dump log */
4095 ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE0x00030009);
4096 if (ret) {
4097 nvme_show_status(ret);
4098 goto free_buf;
4099 }
4100
4101 /* Get the extended log */
4102 ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009);
4103 if (ret) {
4104 nvme_show_status(ret);
4105 goto free_buf;
4106 }
4107
4108 /* Write log files */
4109 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4110 "full_log", (char *)tarInfo->timeString);
4111 wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len);
4112
4113 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4114 "key_log", (char *)tarInfo->timeString);
4115 wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len);
4116
4117 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4118 "core_dump_log", (char *)tarInfo->timeString);
4119 wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len);
4120
4121 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4122 "extended_log", (char *)tarInfo->timeString);
4123 wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len);
4124
4125 /* Tar the log directory */
4126 wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
4127 wdc_UtilsSnprintf(tarInfo->tarFiles, sizeof(tarInfo->tarFiles), "%s%s%s", (char *)tarInfo->bufferFolderName, WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
4128 wdc_UtilsSnprintf(tarInfo->tarCmd, sizeof(tarInfo->tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarInfo->tarFileName, (char *)tarInfo->tarFiles);
4129
4130 ret = system(tarInfo->tarCmd);
4131
4132 if (ret)
4133 nvme_show_error("ERROR: WDC: Tar of log data failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Tar of log data failed, ret = %d"
, ret)
;
4134
4135free_buf:
4136 free(tarInfo);
4137 free(full_log_buf);
4138 free(core_dump_log_buf);
4139 free(key_log_buf);
4140 free(extended_log_buf);
4141 return ret;
4142}
4143
4144static int dump_internal_logs(struct libnvme_transport_handle *hdl, const char *dir_name, int verbose)
4145{
4146 char file_path[PATH_MAX4096];
4147 void *telemetry_log;
4148 const size_t bs = 512;
4149 struct nvme_telemetry_log *hdr;
4150 struct libnvme_passthru_cmd cmd;
4151 size_t full_size, offset = bs;
4152 int err, output;
4153
4154 if (verbose)
4155 printf("NVMe Telemetry log...\n");
4156
4157 hdr = malloc(bs);
4158 telemetry_log = malloc(bs);
4159 if (!hdr || !telemetry_log) {
4160 nvme_show_error("Failed to allocate %zu bytes for log: %s", bs, libnvme_strerror(errno))nvme_show_message(1, "Failed to allocate %zu bytes for log: %s"
, bs, libnvme_strerror((*__errno_location ())))
;
4161 err = -ENOMEM12;
4162 goto free_mem;
4163 }
4164 memset(hdr, 0, bs);
4165
4166 sprintf(file_path, "%s/telemetry.bin", dir_name);
4167 output = nvme_open_rawdata(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file_path), (01 | 0100 | 01000), 0666);
4168 if (output < 0) {
4169 nvme_show_error("Failed to open output file %s: %s!", file_path, libnvme_strerror(errno))nvme_show_message(1, "Failed to open output file %s: %s!", file_path
, libnvme_strerror((*__errno_location ())))
;
4170 err = output;
4171 goto free_mem;
4172 }
4173
4174 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4175 NVME_CSI_NVM, hdr, bs);
4176 cmd.cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_CREATE,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4177 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4178 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
4179 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4180 if (err < 0)
4181 nvme_show_err(err, "get-telemetry-log");
4182 else if (err > 0) {
4183 nvme_show_status(err);
4184 nvme_show_error("Failed to acquire telemetry header %d!", err)nvme_show_message(1, "Failed to acquire telemetry header %d!"
, err)
;
4185 goto close_output;
4186 }
4187
4188 err = write(output, (void *)hdr, bs);
4189 if (err != bs) {
4190 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4191 goto close_output;
4192 }
4193
4194 full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
4195
4196 while (offset != full_size) {
4197 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4198 NVME_CSI_NVM, telemetry_log, bs);
4199 nvme_init_get_log_lpo(&cmd, offset);
4200 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4201 if (err < 0) {
4202 nvme_show_err(err, "get-telemetry-log");
4203 break;
4204 } else if (err > 0) {
4205 nvme_show_error("Failed to acquire full telemetry log!")nvme_show_message(1, "Failed to acquire full telemetry log!");
4206 nvme_show_status(err);
4207 break;
4208 }
4209
4210 err = write(output, (void *)telemetry_log, bs);
4211 if (err != bs) {
4212 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4213 break;
4214 }
4215 err = 0;
4216 offset += bs;
4217 }
4218
4219close_output:
4220 close(output);
4221free_mem:
4222 free(hdr);
4223 free(telemetry_log);
4224
4225 return err;
4226}
4227
4228static int wdc_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
4229 int *data_area)
4230{
4231 struct nvme_id_ctrl ctrl;
4232 int err;
4233
4234 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
4235 err = nvme_identify_ctrl(hdl, &ctrl);
4236 if (err) {
4237 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", err)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, err)
;
4238 return err;
4239 }
4240
4241 if (ctrl.lpa & 0x40)
4242 *data_area = 4;
4243 else
4244 *data_area = 3;
4245
4246 return 0;
4247}
4248
4249static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd,
4250 struct plugin *plugin)
4251{
4252 const char *desc = "Internal Firmware Log.";
4253 const char *file = "Output file pathname.";
4254 const char *size = "Data retrieval transfer size.";
4255 const char *data_area =
4256 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
4257 const char *type =
4258 "Telemetry type - NONE, HOST, or CONTROLLER:\n" \
4259 " NONE - Default, capture without using NVMe telemetry.\n" \
4260 " HOST - Host-initiated telemetry.\n" \
4261 " CONTROLLER - Controller-initiated telemetry.";
4262 const char *verbose = "Display more debug messages.";
4263 const char *file_size =
4264 "Output file size. Deprecated, see man page for supported devices.";
4265 const char *offset =
4266 "Output file data offset. Deprecated, see man page for supported devices.";
4267 char f[PATH_MAX4096] = {0};
4268 char fb[PATH_MAX4096/2] = {0};
4269 char fileSuffix[PATH_MAX4096] = {0};
4270 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4271 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4272 __u32 xfer_size = 0;
4273 int telemetry_type = 0, telemetry_data_area = 0;
4274 UtilsTimeInfo timeInfo;
4275 __u8 timeStamp[MAX_PATH_LEN256];
4276 __u64 capabilities = 0;
4277 __u32 device_id, read_vendor_id;
4278 char file_path[PATH_MAX4096/2] = {0};
4279 char cmd_buf[PATH_MAX4096] = {0};
4280 int ret = -1;
4281
4282 struct config {
4283 char *file;
4284 __u32 xfer_size;
4285 int data_area;
4286 __u64 file_size;
4287 __u64 offset;
4288 char *type;
4289 bool_Bool verbose;
4290 };
4291
4292 struct config cfg = {
4293 .file = NULL((void*)0),
4294 .xfer_size = 0x10000,
4295 .data_area = 0,
4296 .file_size = 0,
4297 .offset = 0,
4298 .type = NULL((void*)0),
4299 .verbose = false0,
4300 };
4301
4302 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4303 OPT_FILE("output-file", 'O', &cfg.file, file),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4304 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4305 OPT_UINT("data-area", 'd', &cfg.data_area, data_area),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4306 OPT_FILE("type", 't', &cfg.type, type),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4307 OPT_FLAG("verbose", 'V', &cfg.verbose, verbose),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4308 OPT_LONG("file-size", 'f', &cfg.file_size, file_size),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4309 OPT_LONG("offset", 'e', &cfg.offset, offset),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4310 OPT_END())nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4311
4312 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4313 if (ret)
4314 return ret;
4315
4316 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4317 if (ret || !wdc_check_device(ctx, hdl))
4318 goto out;
4319
4320 if (cfg.xfer_size) {
4321 xfer_size = cfg.xfer_size;
4322 } else {
4323 nvme_show_error("ERROR: WDC: Invalid length")nvme_show_message(1, "ERROR: WDC: Invalid length");
4324 goto out;
4325 }
4326
4327 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4328
4329 if (!wdc_is_sn861(device_id)) {
4330 if (cfg.file) {
4331 int verify_file;
4332
4333 /* verify file name and path is valid before getting dump data */
4334 verify_file = nvme_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
4335 if (verify_file < 0) {
4336 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
4337 goto out;
4338 }
4339 close(verify_file);
4340 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4341 } else {
4342 wdc_UtilsGetTime(&timeInfo);
4343 memset(timeStamp, 0, sizeof(timeStamp));
4344 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4345 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4346 timeInfo.month, timeInfo.dayOfMonth,
4347 timeInfo.hour, timeInfo.minute,
4348 timeInfo.second);
4349 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4350
4351 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix);
4352 if (ret) {
4353 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4354 goto out;
4355 }
4356 }
4357
4358 if (!cfg.file) {
4359 if (strlen(f) > PATH_MAX4096 - 5) {
4360 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4361 ret = -1;
4362 goto out;
4363 }
4364 strcat(f, ".bin");
4365 }
4366 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
4367
4368 if (cfg.data_area) {
4369 if (cfg.data_area > 5 || cfg.data_area < 1) {
4370 nvme_show_error("ERROR: WDC: Data area must be 1-5")nvme_show_message(1, "ERROR: WDC: Data area must be 1-5");
4371 ret = -1;
4372 goto out;
4373 }
4374 }
4375
4376 if (!cfg.type || !strcmp(cfg.type, "NONE") || !strcmp(cfg.type, "none")) {
4377 telemetry_type = WDC_TELEMETRY_TYPE_NONE0x0;
4378 data_area = 0;
4379 } else if (!strcmp(cfg.type, "HOST") || !strcmp(cfg.type, "host")) {
4380 telemetry_type = WDC_TELEMETRY_TYPE_HOST0x1;
4381 telemetry_data_area = cfg.data_area;
4382 } else if (!strcmp(cfg.type, "CONTROLLER") || !strcmp(cfg.type, "controller")) {
4383 telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER0x2;
4384 telemetry_data_area = cfg.data_area;
4385 } else {
4386 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"
)
4387 "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n")nvme_show_message(1, "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"
)
;
4388 ret = -1;
4389 goto out;
4390 }
4391 } else {
4392 if (cfg.file) {
4393 strncpy(fb, cfg.file, PATH_MAX4096/2 - 8);
4394 } else {
4395 wdc_UtilsGetTime(&timeInfo);
4396 memset(timeStamp, 0, sizeof(timeStamp));
4397 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4398 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4399 timeInfo.month, timeInfo.dayOfMonth,
4400 timeInfo.hour, timeInfo.minute,
4401 timeInfo.second);
4402 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4403
4404 ret = wdc_get_serial_name(hdl, fb, PATH_MAX4096/2 - 7, fileSuffix);
4405 if (ret) {
4406 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4407 goto out;
4408 }
4409
4410 if (strlen(fb) > PATH_MAX4096/2 - 7) {
4411 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4412 ret = -1;
4413 goto out;
4414 }
4415 }
4416 nvme_show_error("%s: filename = %s.tar.gz", __func__, fb)nvme_show_message(1, "%s: filename = %s.tar.gz", __func__, fb
)
;
4417
4418
4419 memset(file_path, 0, sizeof(file_path));
4420 if (snprintf(file_path, PATH_MAX4096/2 - 8, "%s.tar.gz", fb) >= PATH_MAX4096/2 - 8) {
4421 nvme_show_error("File path is too long!")nvme_show_message(1, "File path is too long!");
4422 ret = -1;
4423 goto out;
4424 }
4425 if (access(file_path, F_OK0) != -1) {
4426 nvme_show_error("Output file already exists!")nvme_show_message(1, "Output file already exists!");
4427 ret = -EEXIST17;
4428 goto out;
4429 }
4430 }
4431
4432 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4433 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
4434 if (!wdc_is_sn861(device_id)) {
4435 if (telemetry_type != WDC_TELEMETRY_TYPE_NONE0x0 &&
4436 wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4437 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4438 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4439 return -EINVAL22;
4440 }
4441
4442 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size,
4443 telemetry_type, telemetry_data_area);
4444 } else {
4445 if (nvme_args.verbose)
4446 printf("Creating temp directory...\n");
4447
4448 ret = mkdir(fb, 0666);
4449 if (ret) {
4450 nvme_show_error("Failed to create directory!")nvme_show_message(1, "Failed to create directory!");
4451 goto out;
4452 }
4453
4454 ret = dump_internal_logs(hdl, fb, nvme_args.verbose);
4455 if (ret < 0)
4456 nvme_show_err(ret, "vs-internal-log");
4457
4458 if (nvme_args.verbose)
4459 printf("Archiving...\n");
4460
4461 if (snprintf(cmd_buf, PATH_MAX4096,
4462 "tar --remove-files -czf %s %s",
4463 file_path, fb) >= PATH_MAX4096) {
4464 nvme_show_error("Command buffer is too long!")nvme_show_message(1, "Command buffer is too long!");
4465 ret = -1;
4466 goto out;
4467 }
4468
4469 ret = system(cmd_buf);
4470 if (ret)
4471 nvme_show_error("Failed to create an archive file!")nvme_show_message(1, "Failed to create an archive file!");
4472 }
4473 goto out;
4474 }
4475 if ((capabilities & WDC_DRIVE_CAP_DUI0x0000000800000000) == WDC_DRIVE_CAP_DUI0x0000000800000000) {
4476 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4477 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4478 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4479 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4480 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4481 return -EINVAL22;
4482 }
4483 /* Get the desired telemetry log page */
4484 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4485 telemetry_type, telemetry_data_area);
4486 goto out;
4487 } else {
4488 if (!cfg.data_area)
4489 cfg.data_area = 1;
4490
4491 /* FW requirement - xfer size must be 256k for data area 4 */
4492 if (cfg.data_area >= 4)
4493 xfer_size = 0x40000;
4494 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4495 cfg.data_area,
4496 nvme_args.verbose, cfg.file_size,
4497 cfg.offset);
4498 goto out;
4499 }
4500 }
4501 if ((capabilities & WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) == WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) {
4502 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4503 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4504 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4505 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4506 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4507 return -EINVAL22;
4508 }
4509 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4510 telemetry_type, telemetry_data_area);
4511 goto out;
4512 } else {
4513 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4514 WDC_NVME_DUI_MAX_DATA_AREA0x05,
4515 nvme_args.verbose, 0, 0);
4516 goto out;
4517 }
4518 }
4519 if ((capabilities & WDC_SN730B_CAP_VUC_LOG0x0000000400000000) == WDC_SN730B_CAP_VUC_LOG0x0000000400000000) {
4520 ret = wdc_do_sn730_get_and_tar(hdl, f);
4521 } else {
4522 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4523 ret = -1;
4524 }
4525out:
4526 return ret;
4527}
4528
4529static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type)
4530{
4531 int ret;
4532 __u32 crash_dump_length;
4533 __u32 opcode;
4534 __u32 cdw12;
4535 __u32 cdw10_size;
4536 __u32 cdw12_size;
4537 __u32 cdw12_clear;
4538
4539 if (type == WDC_NVME_PFAIL_DUMP_TYPE2) {
4540 /* set parms to get the PFAIL Crash Dump */
4541 opcode = WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6;
4542 cdw10_size = WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02;
4543 cdw12_size = ((WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4544 WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20);
4545
4546 cdw12 = (WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4547 WDC_NVME_PF_CRASH_DUMP_CMD0x20;
4548
4549 cdw12_clear = ((WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4550 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4551
4552 } else {
4553 /* set parms to get the Crash Dump */
4554 opcode = WDC_NVME_CRASH_DUMP_OPCODE0xC6;
4555 cdw10_size = WDC_NVME_CRASH_DUMP_SIZE_NDT0x02;
4556 cdw12_size = ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 << WDC_NVME_SUBCMD_SHIFT8) |
4557 WDC_NVME_CRASH_DUMP_SIZE_CMD0x20);
4558
4559 cdw12 = (WDC_NVME_CRASH_DUMP_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
4560 WDC_NVME_CRASH_DUMP_CMD0x20;
4561
4562 cdw12_clear = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4563 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4564 }
4565
4566 ret = wdc_dump_length(hdl,
4567 opcode,
4568 cdw10_size,
4569 cdw12_size,
4570 &crash_dump_length);
4571
4572 if (ret == -1) {
4573 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4574 nvme_show_error("INFO: WDC: Pfail dump get size failed")nvme_show_message(1, "INFO: WDC: Pfail dump get size failed");
4575 else
4576 nvme_show_error("INFO: WDC: Crash dump get size failed")nvme_show_message(1, "INFO: WDC: Crash dump get size failed");
4577
4578 return -1;
4579 }
4580
4581 if (!crash_dump_length) {
4582 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4583 nvme_show_error("INFO: WDC: Pfail dump is empty")nvme_show_message(1, "INFO: WDC: Pfail dump is empty");
4584 else
4585 nvme_show_error("INFO: WDC: Crash dump is empty")nvme_show_message(1, "INFO: WDC: Crash dump is empty");
4586 } else {
4587 ret = wdc_do_dump(hdl,
4588 opcode,
4589 crash_dump_length,
4590 cdw12,
4591 file,
4592 crash_dump_length);
4593
4594 if (!ret)
4595 ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE0xFF,
4596 cdw12_clear);
4597 }
4598 return ret;
4599}
4600
4601static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type)
4602{
4603 char f[PATH_MAX4096] = {0};
4604 const char *dump_type;
4605 int ret;
4606
4607 if (file)
4608 strncpy(f, file, PATH_MAX4096 - 1);
4609
4610 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4611 dump_type = "_pfail_dump";
4612 else
4613 dump_type = "_crash_dump";
4614
4615 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, dump_type);
4616 if (ret)
4617 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4618 else
4619 ret = wdc_do_crash_dump(hdl, f, type);
4620 return ret;
4621}
4622
4623static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file)
4624{
4625 int ret;
4626 __u8 *drive_log_data;
4627 __u32 drive_log_length;
4628 struct libnvme_passthru_cmd admin_cmd;
4629
4630 ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6,
4631 WDC_NVME_DRIVE_LOG_SIZE_NDT0x02,
4632 (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 <<
4633 WDC_NVME_SUBCMD_SHIFT8 | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20),
4634 &drive_log_length);
4635 if (ret == -1)
4636 return -1;
4637
4638 drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length);
4639 if (!drive_log_data) {
4640 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4641 return -1;
4642 }
4643
4644 memset(drive_log_data, 0, sizeof(__u8) * drive_log_length);
4645 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4646 admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE0xC6;
4647 admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
4648 admin_cmd.data_len = drive_log_length;
4649 admin_cmd.cdw10 = drive_log_length;
4650 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD0x00 <<
4651 WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20);
4652
4653 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4654 nvme_show_status(ret);
4655 if (!ret)
4656 ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
4657 free(drive_log_data);
4658 return ret;
4659}
4660
4661static int wdc_drive_log(int argc, char **argv, struct command *acmd,
4662 struct plugin *plugin)
4663{
4664 const char *desc = "Capture Drive Log.";
4665 const char *file = "Output file pathname.";
4666 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4667 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4668 char f[PATH_MAX4096] = {0};
4669 int ret;
4670 __u64 capabilities = 0;
4671 struct config {
4672 char *file;
4673 };
4674
4675 struct config cfg = {
4676 .file = NULL((void*)0)
4677 };
4678
4679 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4680 OPT_FILE("output-file", 'O', &cfg.file, file))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4681
4682 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4683 if (ret)
4684 return ret;
4685
4686 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4687 if (ret || !wdc_check_device(ctx, hdl))
4688 return ret;
4689
4690 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4691
4692 if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400)) {
4693 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4694 ret = -1;
4695 } else {
4696 if (cfg.file)
4697 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4698 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "drive_log");
4699 if (ret)
4700 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4701 else
4702 ret = wdc_do_drive_log(hdl, f);
4703 }
4704 return ret;
4705}
4706
4707static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
4708 struct plugin *plugin)
4709{
4710 const char *desc = "Get Crash Dump.";
4711 const char *file = "Output file pathname.";
4712 __u64 capabilities = 0;
4713 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4714 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4715 int ret;
4716
4717 struct config {
4718 char *file;
4719 };
4720
4721 struct config cfg = {
4722 .file = NULL((void*)0),
4723 };
4724
4725 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4726 OPT_FILE("output-file", 'O', &cfg.file, file))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4727
4728 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4729 if (ret)
4730 return ret;
4731
4732 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4733 if (ret || !wdc_check_device(ctx, hdl))
4734 return ret;
4735
4736 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4737
4738 if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800)) {
4739 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4740 ret = -1;
4741 } else {
4742 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE1);
4743 if (ret)
4744 nvme_show_error("ERROR: WDC: failed to read crash dump")nvme_show_message(1, "ERROR: WDC: failed to read crash dump");
4745 }
4746 return ret;
4747}
4748
4749static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd,
4750 struct plugin *plugin)
4751{
4752 const char *desc = "Get Pfail Crash Dump.";
4753 const char *file = "Output file pathname.";
4754 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4755 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4756 __u64 capabilities = 0;
4757 struct config {
4758 char *file;
4759 };
4760 int ret;
4761
4762 struct config cfg = {
4763 .file = NULL((void*)0),
4764 };
4765
4766 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
4767 OPT_FILE("output-file", 'O', &cfg.file, file))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4768
4769 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4770 if (ret)
4771 return ret;
4772
4773 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4774 if (ret || !wdc_check_device(ctx, hdl))
4775 return ret;
4776
4777 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4778 if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000)) {
4779 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4780 ret = -1;
4781 } else {
4782 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE2);
4783 if (ret)
4784 nvme_show_error("ERROR: WDC: failed to read pfail crash dump")nvme_show_message(1, "ERROR: WDC: failed to read pfail crash dump"
)
;
4785 }
4786 return ret;
4787}
4788
4789static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root)
4790{
4791 char vsn[24] = {0};
4792 int base = 3072;
4793 int vsn_start = 3081;
4794
4795 memcpy(vsn, &vs[vsn_start - base], sizeof(vsn));
4796 if (root)
4797 json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL");
4798 else
4799 printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL");
4800}
4801
4802static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
4803{
4804 return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl);
4805}
4806
4807static const char *wdc_purge_mon_status_to_string(__u32 status)
4808{
4809 const char *str;
4810
4811 switch (status) {
4812 case WDC_NVME_PURGE_STATE_IDLE0x00:
4813 str = "Purge State Idle.";
4814 break;
4815 case WDC_NVME_PURGE_STATE_DONE0x01:
4816 str = "Purge State Done.";
4817 break;
4818 case WDC_NVME_PURGE_STATE_BUSY0x02:
4819 str = "Purge State Busy.";
4820 break;
4821 case WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03:
4822 str = "Purge Operation resulted in an error that requires power cycle.";
4823 break;
4824 case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04:
4825 str = "The previous purge operation was interrupted by a power cycle\n"
4826 "or reset interruption. Other commands may be rejected until\n"
4827 "Purge Execute is issued and completed.";
4828 break;
4829 default:
4830 str = "Unknown.";
4831 }
4832 return str;
4833}
4834
4835static int wdc_purge(int argc, char **argv,
4836 struct command *command, struct plugin *plugin)
4837{
4838 const char *desc = "Send a Purge command.";
4839 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4840 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4841 struct libnvme_passthru_cmd admin_cmd;
4842 __u64 capabilities = 0;
4843 char *err_str;
4844 int ret;
4845
4846 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4847
4848 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4849 if (ret)
4850 return ret;
4851
4852 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4853 if (ret || !wdc_check_device(ctx, hdl))
4854 return ret;
4855
4856 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4857 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4858 ret = -1;
4859 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4860 } else {
4861 err_str = "";
4862 memset(&admin_cmd, 0, sizeof(admin_cmd));
4863 admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE0xDD;
4864
4865 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4866 if (ret > 0) {
4867 switch (ret) {
4868 case WDC_NVME_PURGE_CMD_SEQ_ERR0x0C:
4869 err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n";
4870 break;
4871 case WDC_NVME_PURGE_INT_DEV_ERR0x06:
4872 err_str = "ERROR: WDC: Internal Device Error.\n";
4873 break;
4874 default:
4875 err_str = "ERROR: WDC\n";
4876 }
4877 }
4878
4879 nvme_show_error("%s", err_str)nvme_show_message(1, "%s", err_str);
4880 nvme_show_status(ret);
4881 }
4882 return ret;
4883}
4884
4885static int wdc_purge_monitor(int argc, char **argv,
4886 struct command *command, struct plugin *plugin)
4887{
4888 const char *desc = "Send a Purge Monitor command.";
4889 __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F];
4890 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4891 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4892 double progress_percent;
4893 struct libnvme_passthru_cmd admin_cmd;
4894 struct wdc_nvme_purge_monitor_data *mon;
4895 __u64 capabilities;
4896 int ret;
4897
4898 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
4899
4900 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4901 if (ret)
4902 return ret;
4903
4904 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4905 if (ret || !wdc_check_device(ctx, hdl))
4906 return ret;
4907
4908 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4909 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4910 ret = -1;
4911 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4912 } else {
4913 memset(output, 0, sizeof(output));
4914 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4915 admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE0xDE;
4916 admin_cmd.addr = (__u64)(uintptr_t)output;
4917 admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F;
4918 admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C;
4919 admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530;
4920
4921 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4922 if (!ret) {
4923 mon = (struct wdc_nvme_purge_monitor_data *) output;
4924 printf("Purge state = 0x%0"PRIx64"l" "x""\n",
4925 (uint64_t)admin_cmd.result);
4926 printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result));
4927 if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY0x02) {
4928 progress_percent =
4929 ((double)le32_to_cpu(mon->entire_progress_current) * 100) /
4930 le32_to_cpu(mon->entire_progress_total);
4931 printf("Purge Progress = %f%%\n", progress_percent);
4932 }
4933 }
4934
4935 nvme_show_status(ret);
4936 }
4937 return ret;
4938}
4939
4940static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf)
4941{
4942 printf(" C1 Log Page Performance Statistics :-\n");
4943 printf(" Host Read Commands %20"PRIu64"l" "u""\n",
4944 le64_to_cpu(perf->hr_cmds));
4945 printf(" Host Read Blocks %20"PRIu64"l" "u""\n",
4946 le64_to_cpu(perf->hr_blks));
4947 printf(" Average Read Size %20lf\n",
4948 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))));
4949 printf(" Host Read Cache Hit Commands %20"PRIu64"l" "u""\n",
4950 le64_to_cpu(perf->hr_ch_cmds));
4951 printf(" Host Read Cache Hit_Percentage %20"PRIu64"l" "u""%%\n",
4952 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)));
4953 printf(" Host Read Cache Hit Blocks %20"PRIu64"l" "u""\n",
4954 le64_to_cpu(perf->hr_ch_blks));
4955 printf(" Average Read Cache Hit Size %20f\n",
4956 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))));
4957 printf(" Host Read Commands Stalled %20"PRIu64"l" "u""\n",
4958 le64_to_cpu(perf->hr_st_cmds));
4959 printf(" Host Read Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
4960 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)));
4961 printf(" Host Write Commands %20"PRIu64"l" "u""\n",
4962 le64_to_cpu(perf->hw_cmds));
4963 printf(" Host Write Blocks %20"PRIu64"l" "u""\n",
4964 le64_to_cpu(perf->hw_blks));
4965 printf(" Average Write Size %20f\n",
4966 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))));
4967 printf(" Host Write Odd Start Commands %20"PRIu64"l" "u""\n",
4968 le64_to_cpu(perf->hw_os_cmds));
4969 printf(" Host Write Odd Start Commands Percentage %20"PRIu64"l" "u""%%\n",
4970 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))));
4971 printf(" Host Write Odd End Commands %20"PRIu64"l" "u""\n",
4972 le64_to_cpu(perf->hw_oe_cmds));
4973 printf(" Host Write Odd End Commands Percentage %20"PRIu64"l" "u""%%\n",
4974 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))));
4975 printf(" Host Write Commands Stalled %20"PRIu64"l" "u""\n",
4976 le64_to_cpu(perf->hw_st_cmds));
4977 printf(" Host Write Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
4978 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))));
4979 printf(" NAND Read Commands %20"PRIu64"l" "u""\n",
4980 le64_to_cpu(perf->nr_cmds));
4981 printf(" NAND Read Blocks Commands %20"PRIu64"l" "u""\n",
4982 le64_to_cpu(perf->nr_blks));
4983 printf(" Average NAND Read Size %20f\n",
4984 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))));
4985 printf(" Nand Write Commands %20"PRIu64"l" "u""\n",
4986 le64_to_cpu(perf->nw_cmds));
4987 printf(" NAND Write Blocks %20"PRIu64"l" "u""\n",
4988 le64_to_cpu(perf->nw_blks));
4989 printf(" Average NAND Write Size %20f\n",
4990 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))));
4991 printf(" NAND Read Before Write %20"PRIu64"l" "u""\n",
4992 le64_to_cpu(perf->nrbw));
4993}
4994
4995static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf)
4996{
4997 struct json_object *root = json_create_object()json_object_new_object();
4998
4999 json_object_add_value_int(root, "Host Read Commands", le64_to_cpu(perf->hr_cmds))json_object_object_add(root, "Host Read Commands", json_object_new_int
(le64_to_cpu(perf->hr_cmds)))
;
5000 json_object_add_value_int(root, "Host Read Blocks", le64_to_cpu(perf->hr_blks))json_object_object_add(root, "Host Read Blocks", json_object_new_int
(le64_to_cpu(perf->hr_blks)))
;
5001 json_object_add_value_int(root, "Average Read Size",json_object_object_add(root, "Average Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf
->hr_cmds)))))
5002 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))))json_object_object_add(root, "Average Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf
->hr_cmds)))))
;
5003 json_object_add_value_int(root, "Host Read Cache Hit Commands",json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_int
(le64_to_cpu(perf->hr_ch_cmds)))
5004 le64_to_cpu(perf->hr_ch_cmds))json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_int
(le64_to_cpu(perf->hr_ch_cmds)))
;
5005 json_object_add_value_int(root, "Host Read Cache Hit Percentage",json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_int((uint64_t) calc_percent(le64_to_cpu(perf
->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))))
5006 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_int((uint64_t) calc_percent(le64_to_cpu(perf
->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))))
;
5007 json_object_add_value_int(root, "Host Read Cache Hit Blocks",json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_int
(le64_to_cpu(perf->hr_ch_blks)))
5008 le64_to_cpu(perf->hr_ch_blks))json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_int
(le64_to_cpu(perf->hr_ch_blks)))
;
5009 json_object_add_value_int(root, "Average Read Cache Hit Size",json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu
(perf->hr_ch_cmds)))))
5010 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))))json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu
(perf->hr_ch_cmds)))))
;
5011 json_object_add_value_int(root, "Host Read Commands Stalled",json_object_object_add(root, "Host Read Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hr_st_cmds)))
5012 le64_to_cpu(perf->hr_st_cmds))json_object_object_add(root, "Host Read Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hr_st_cmds)))
;
5013 json_object_add_value_int(root, "Host Read Commands Stalled Percentage",json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))))
5014 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))))
;
5015 json_object_add_value_int(root, "Host Write Commands",json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
5016 le64_to_cpu(perf->hw_cmds))json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
;
5017 json_object_add_value_int(root, "Host Write Blocks",json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
5018 le64_to_cpu(perf->hw_blks))json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
;
5019 json_object_add_value_int(root, "Average Write Size",json_object_object_add(root, "Average Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf
->hw_cmds)))))
5020 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Average Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf
->hw_cmds)))))
;
5021 json_object_add_value_int(root, "Host Write Odd Start Commands",json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_int(le64_to_cpu(perf->hw_os_cmds)))
5022 le64_to_cpu(perf->hw_os_cmds))json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_int(le64_to_cpu(perf->hw_os_cmds)))
;
5023 json_object_add_value_int(root, "Host Write Odd Start Commands Percentage",json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))))
5024 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))))
;
5025 json_object_add_value_int(root, "Host Write Odd End Commands",json_object_object_add(root, "Host Write Odd End Commands", json_object_new_int
(le64_to_cpu(perf->hw_oe_cmds)))
5026 le64_to_cpu(perf->hw_oe_cmds))json_object_object_add(root, "Host Write Odd End Commands", json_object_new_int
(le64_to_cpu(perf->hw_oe_cmds)))
;
5027 json_object_add_value_int(root, "Host Write Odd End Commands Percentage",json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))))
5028 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))))json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))))
;
5029 json_object_add_value_int(root, "Host Write Commands Stalled",json_object_object_add(root, "Host Write Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hw_st_cmds)))
5030 le64_to_cpu(perf->hw_st_cmds))json_object_object_add(root, "Host Write Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hw_st_cmds)))
;
5031 json_object_add_value_int(root, "Host Write Commands Stalled Percentage",json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))))
5032 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))))
;
5033 json_object_add_value_int(root, "NAND Read Commands",json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
5034 le64_to_cpu(perf->nr_cmds))json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
;
5035 json_object_add_value_int(root, "NAND Read Blocks Commands",json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_int
(le64_to_cpu(perf->nr_blks)))
5036 le64_to_cpu(perf->nr_blks))json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_int
(le64_to_cpu(perf->nr_blks)))
;
5037 json_object_add_value_int(root, "Average NAND Read Size",json_object_object_add(root, "Average NAND Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf
->nr_cmds))))))
5038 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))))json_object_object_add(root, "Average NAND Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf
->nr_cmds))))))
;
5039 json_object_add_value_int(root, "Nand Write Commands",json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
5040 le64_to_cpu(perf->nw_cmds))json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
;
5041 json_object_add_value_int(root, "NAND Write Blocks",json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
5042 le64_to_cpu(perf->nw_blks))json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
;
5043 json_object_add_value_int(root, "Average NAND Write Size",json_object_object_add(root, "Average NAND Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf
->nw_cmds)))))
5044 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))))json_object_object_add(root, "Average NAND Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf
->nw_cmds)))))
;
5045 json_object_add_value_int(root, "NAND Read Before Written",json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
5046 le64_to_cpu(perf->nrbw))json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
;
5047 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5048 printf("\n");
5049 json_free_object(root)json_object_put(root);
5050}
5051
5052static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt)
5053{
5054 if (!perf) {
5055 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
5056 return -1;
5057 }
5058 switch (fmt) {
5059 case NORMAL:
5060 wdc_print_log_normal(perf);
5061 break;
5062 case JSON:
5063 wdc_print_log_json(perf);
5064 break;
5065 }
5066 return 0;
5067}
5068
5069static int wdc_print_latency_monitor_log_normal(struct libnvme_transport_handle *hdl,
5070 struct wdc_ssd_latency_monitor_log *log_data)
5071{
5072 printf("Latency Monitor/C3 Log Page Data\n");
5073 printf(" Controller : %s\n", libnvme_transport_handle_get_name(hdl));
5074 int err = -1, i, j;
5075 struct nvme_id_ctrl ctrl;
5076 char ts_buf[128];
5077
5078 err = nvme_identify_ctrl(hdl, &ctrl);
5079 if (!err) {
5080 printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn);
5081 } else {
5082 nvme_show_error("ERROR: WDC: latency monitor read id ctrl failure, err = %d", err)nvme_show_message(1, "ERROR: WDC: latency monitor read id ctrl failure, err = %d"
, err)
;
5083 return err;
5084 }
5085
5086 printf(" Feature Status 0x%x\n", log_data->feature_status);
5087 printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer));
5088 printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold));
5089 printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1)));
5090 printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1)));
5091 printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1)));
5092 printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1)));
5093 printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config));
5094 printf(" Active Latency Minimum Window %d ms\n", 100*log_data->active_latency_min_window);
5095 printf(" Active Latency Stamp Units %d\n", le16_to_cpu(log_data->active_latency_stamp_units));
5096 printf(" Static Latency Stamp Units %d\n", le16_to_cpu(log_data->static_latency_stamp_units));
5097 if (le16_to_cpu(log_data->log_page_version) >= 4)
5098 printf(" Debug Telemetry Log Size %"PRIu64"l" "u""\n",
5099 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size));
5100 printf(" Debug Log Trigger Enable %d\n",
5101 le16_to_cpu(log_data->debug_log_trigger_enable));
5102 printf(" Log Page Version %d\n",
5103 le16_to_cpu(log_data->log_page_version));
5104 printf(" Log page GUID 0x");
5105 for (j = 0; j < WDC_C3_GUID_LENGTH16; j++)
5106 printf("%x", log_data->log_page_guid[j]);
5107 printf("\n");
5108
5109 printf(" Read Write Deallocate/Trim\n");
5110 for (i = 0; i <= 3; i++)
5111 printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
5112 i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5113 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5114 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5115
5116 for (i = 3; i >= 0; i--)
5117 printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5118 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5119 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5120 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5121
5122 for (i = 3; i >= 0; i--) {
5123 printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
5124 for (j = 2; j >= 0; j--) {
5125 if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) {
5126 printf(" N/A ");
5127 } else {
5128 shr_format_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
5129 printf("%s ", ts_buf);
5130 }
5131 }
5132 printf("\n");
5133 }
5134
5135 for (i = 0; i <= 3; i++)
5136 printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
5137 i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5138 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5139 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5140
5141 for (i = 3; i >= 0; i--)
5142 printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5143 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5144 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5145 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5146
5147 for (i = 3; i >= 0; i--) {
5148 printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
5149 for (j = 2; j >= 0; j--) {
5150 if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) {
5151 printf(" N/A ");
5152 } else {
5153 shr_format_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
5154 printf("%s ", ts_buf);
5155 }
5156 }
5157 printf("\n");
5158 }
5159
5160 return 0;
5161}
5162
5163static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data)
5164{
5165 int i, j;
5166 char buf[128];
5167 const char *operation[3] = {"Read", "Write", "Trim"};
5168 struct json_object *root = json_create_object()json_object_new_object();
5169
5170 json_object_add_value_int(root, "Feature Status", log_data->feature_status)json_object_object_add(root, "Feature Status", json_object_new_int
(log_data->feature_status))
;
5171 json_object_add_value_int(root, "Active Bucket Timer", 5*le16_to_cpu(log_data->active_bucket_timer))json_object_object_add(root, "Active Bucket Timer", json_object_new_int
(5*le16_to_cpu(log_data->active_bucket_timer)))
;
5172 json_object_add_value_int(root, "Active Bucket Timer Threshold", 5*le16_to_cpu(log_data->active_bucket_timer_threshold))json_object_object_add(root, "Active Bucket Timer Threshold",
json_object_new_int(5*le16_to_cpu(log_data->active_bucket_timer_threshold
)))
;
5173 json_object_add_value_int(root, "Active Threshold A", 5*le16_to_cpu(log_data->active_threshold_a+1))json_object_object_add(root, "Active Threshold A", json_object_new_int
(5*le16_to_cpu(log_data->active_threshold_a+1)))
;
5174 json_object_add_value_int(root, "Active Threshold B", 5*le16_to_cpu(log_data->active_threshold_b+1))json_object_object_add(root, "Active Threshold B", json_object_new_int
(5*le16_to_cpu(log_data->active_threshold_b+1)))
;
5175 json_object_add_value_int(root, "Active Threshold C", 5*le16_to_cpu(log_data->active_threshold_c+1))json_object_object_add(root, "Active Threshold C", json_object_new_int
(5*le16_to_cpu(log_data->active_threshold_c+1)))
;
5176 json_object_add_value_int(root, "Active Threshold D", 5*le16_to_cpu(log_data->active_threshold_d+1))json_object_object_add(root, "Active Threshold D", json_object_new_int
(5*le16_to_cpu(log_data->active_threshold_d+1)))
;
5177 json_object_add_value_int(root, "Active Latency Config", le16_to_cpu(log_data->active_latency_config))json_object_object_add(root, "Active Latency Config", json_object_new_int
(le16_to_cpu(log_data->active_latency_config)))
;
5178 json_object_add_value_int(root, "Active Lantency Minimum Window", 100*log_data->active_latency_min_window)json_object_object_add(root, "Active Lantency Minimum Window"
, json_object_new_int(100*log_data->active_latency_min_window
))
;
5179 json_object_add_value_int(root, "Active Latency Stamp Units", le16_to_cpu(log_data->active_latency_stamp_units))json_object_object_add(root, "Active Latency Stamp Units", json_object_new_int
(le16_to_cpu(log_data->active_latency_stamp_units)))
;
5180 json_object_add_value_int(root, "Static Latency Stamp Units", le16_to_cpu(log_data->static_latency_stamp_units))json_object_object_add(root, "Static Latency Stamp Units", json_object_new_int
(le16_to_cpu(log_data->static_latency_stamp_units)))
;
5181 if (le16_to_cpu(log_data->log_page_version) >= 4) {
5182 json_object_add_value_int(root, "Debug Telemetry Log Size",json_object_object_add(root, "Debug Telemetry Log Size", json_object_new_int
(le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size
)))
5183 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size))json_object_object_add(root, "Debug Telemetry Log Size", json_object_new_int
(le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size
)))
;
5184 }
5185 json_object_add_value_int(root, "Debug Log Trigger Enable",json_object_object_add(root, "Debug Log Trigger Enable", json_object_new_int
(le16_to_cpu(log_data->debug_log_trigger_enable)))
5186 le16_to_cpu(log_data->debug_log_trigger_enable))json_object_object_add(root, "Debug Log Trigger Enable", json_object_new_int
(le16_to_cpu(log_data->debug_log_trigger_enable)))
;
5187 json_object_add_value_int(root, "Log Page Version",json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
5188 le16_to_cpu(log_data->log_page_version))json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
;
5189
5190 char guid[40];
5191
5192 memset((void *)guid, 0, 40);
5193 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5194 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5195 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5196 json_object_add_value_string(root, "Log page GUID", guid);
5197
5198 for (i = 0; i <= 3; i++) {
5199 for (j = 2; j >= 0; j--) {
5200 sprintf(buf, "Active Bucket Counter: Bucket %d %s", i, operation[2-j]);
5201 json_object_add_value_int(root, buf, le32_to_cpu(log_data->active_bucket_counter[i][j+1]))json_object_object_add(root, buf, json_object_new_int(le32_to_cpu
(log_data->active_bucket_counter[i][j+1])))
;
5202 }
5203 }
5204 for (i = 3; i >= 0; i--) {
5205 for (j = 2; j >= 0; j--) {
5206 sprintf(buf, "Active Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5207 json_object_add_value_int(root, buf, le16_to_cpu(log_data->active_measured_latency[i][j]))json_object_object_add(root, buf, json_object_new_int(le16_to_cpu
(log_data->active_measured_latency[i][j])))
;
5208 }
5209 }
5210 for (i = 3; i >= 0; i--) {
5211 for (j = 2; j >= 0; j--) {
5212 sprintf(buf, "Active Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5213 json_object_add_value_int(root, buf, le64_to_cpu(log_data->active_latency_timestamp[i][j]))json_object_object_add(root, buf, json_object_new_int(le64_to_cpu
(log_data->active_latency_timestamp[i][j])))
;
5214 }
5215 }
5216 for (i = 0; i <= 3; i++) {
5217 for (j = 2; j >= 0; j--) {
5218 sprintf(buf, "Static Bucket Counter: Bucket %d %s", i, operation[2-j]);
5219 json_object_add_value_int(root, buf, le32_to_cpu(log_data->static_bucket_counter[i][j+1]))json_object_object_add(root, buf, json_object_new_int(le32_to_cpu
(log_data->static_bucket_counter[i][j+1])))
;
5220 }
5221 }
5222 for (i = 3; i >= 0; i--) {
5223 for (j = 2; j >= 0; j--) {
5224 sprintf(buf, "Static Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5225 json_object_add_value_int(root, buf, le16_to_cpu(log_data->static_measured_latency[i][j]))json_object_object_add(root, buf, json_object_new_int(le16_to_cpu
(log_data->static_measured_latency[i][j])))
;
5226 }
5227 }
5228 for (i = 3; i >= 0; i--) {
5229 for (j = 2; j >= 0; j--) {
5230 sprintf(buf, "Static Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5231 json_object_add_value_int(root, buf, le64_to_cpu(log_data->static_latency_timestamp[i][j]))json_object_object_add(root, buf, json_object_new_int(le64_to_cpu
(log_data->static_latency_timestamp[i][j])))
;
5232 }
5233 }
5234
5235 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5236 printf("\n");
5237
5238 json_free_object(root)json_object_put(root);
5239}
5240
5241static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data)
5242{
5243 int j;
5244
5245 printf("Error Recovery/C1 Log Page Data\n");
5246
5247 printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time));
5248 printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
5249 printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1);
5250 printf(" Panic ID : 0x%" PRIu64"l" "u" "\n", le64_to_cpu(log_data->panic_id));
5251 printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities));
5252 printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc);
5253 printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12));
5254 printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13));
5255 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5256 printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to);
5257 printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2);
5258 printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to);
5259 }
5260 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5261 printf(" Panic Count : 0x%x\n", log_data->panic_count);
5262 for (j = 0; j < 4; j++)
5263 printf(" Previous Panic ID N-%d : 0x%"PRIx64"l" "x""\n",
5264 j+1, le64_to_cpu(log_data->prev_panic_ids[j]));
5265 }
5266 printf(" Log Page Version : 0x%x\n",
5267 le16_to_cpu(log_data->log_page_version));
5268 printf(" Log page GUID : 0x");
5269 for (j = 0; j < WDC_OCP_C1_GUID_LENGTH16; j++)
5270 printf("%x", log_data->log_page_guid[j]);
5271 printf("\n");
5272}
5273
5274static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
5275{
5276 int j;
5277 char buf[128];
5278 struct json_object *root = json_create_object()json_object_new_object();
5279
5280 json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time))json_object_object_add(root, "Panic Reset Wait Time", json_object_new_int
(le16_to_cpu(log_data->panic_reset_wait_time)))
;
5281 json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_wait_time)json_object_object_add(root, "Panic Reset Action", json_object_new_int
(log_data->panic_reset_wait_time))
;
5282 json_object_add_value_int(root, "Device Recovery Action 1", log_data->dev_recovery_action1)json_object_object_add(root, "Device Recovery Action 1", json_object_new_int
(log_data->dev_recovery_action1))
;
5283 json_object_add_value_int(root, "Panic ID", le64_to_cpu(log_data->panic_id))json_object_object_add(root, "Panic ID", json_object_new_int(
le64_to_cpu(log_data->panic_id)))
;
5284 json_object_add_value_int(root, "Device Capabilities", le32_to_cpu(log_data->dev_capabilities))json_object_object_add(root, "Device Capabilities", json_object_new_int
(le32_to_cpu(log_data->dev_capabilities)))
;
5285 json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vs_recovery_opc)json_object_object_add(root, "Vendor Specific Recovery Opcode"
, json_object_new_int(log_data->vs_recovery_opc))
;
5286 json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vs_cmd_cdw12))json_object_object_add(root, "Vendor Specific Command CDW12",
json_object_new_int(le32_to_cpu(log_data->vs_cmd_cdw12)))
;
5287 json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vs_cmd_cdw13))json_object_object_add(root, "Vendor Specific Command CDW13",
json_object_new_int(le32_to_cpu(log_data->vs_cmd_cdw13)))
;
5288 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5289 json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to)json_object_object_add(root, "Vendor Specific Command Timeout"
, json_object_new_int(log_data->vs_cmd_to))
;
5290 json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2)json_object_object_add(root, "Device Recovery Action 2", json_object_new_int
(log_data->dev_recovery_action2))
;
5291 json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to)json_object_object_add(root, "Device Recovery Action 2 Timeout"
, json_object_new_int(log_data->dev_recovery_action2_to))
;
5292 }
5293 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5294 json_object_add_value_int(root, "Panic Count", log_data->panic_count)json_object_object_add(root, "Panic Count", json_object_new_int
(log_data->panic_count))
;
5295 for (j = 0; j < 4; j++) {
5296 sprintf(buf, "Previous Panic ID N-%d", j+1);
5297 json_object_add_value_int(root, buf,json_object_object_add(root, buf, json_object_new_int(le64_to_cpu
(log_data->prev_panic_ids[j])))
5298 le64_to_cpu(log_data->prev_panic_ids[j]))json_object_object_add(root, buf, json_object_new_int(le64_to_cpu
(log_data->prev_panic_ids[j])))
;
5299 }
5300 }
5301 json_object_add_value_int(root, "Log Page Version",json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
5302 le16_to_cpu(log_data->log_page_version))json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
;
5303
5304 char guid[40];
5305
5306 memset((void *)guid, 0, 40);
5307 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5308 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5309 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5310 json_object_add_value_string(root, "Log page GUID", guid);
5311
5312 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5313 printf("\n");
5314
5315 json_free_object(root)json_object_put(root);
5316}
5317
5318static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data)
5319{
5320 int j;
5321
5322 printf("Device Capabilities/C4 Log Page Data\n");
5323
5324 printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports));
5325 printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support));
5326 printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support));
5327 printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support));
5328 printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support));
5329 printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support));
5330 printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support));
5331 printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps));
5332
5333 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++)
5334 printf(" DSSD Power State %d Descriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]);
5335
5336 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5337 printf(" Log page GUID : 0x");
5338 for (j = 0; j < WDC_OCP_C4_GUID_LENGTH16; j++)
5339 printf("%x", log_data->log_page_guid[j]);
5340 printf("\n");
5341}
5342
5343static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
5344{
5345 int j;
5346 struct json_object *root = json_create_object()json_object_new_object();
5347
5348 json_object_add_value_int(root, "Number PCIE Ports", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Number PCIE Ports", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5349 json_object_add_value_int(root, "Number OOB Management Interfaces", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Number OOB Management Interfaces"
, json_object_new_int(le16_to_cpu(log_data->num_pcie_ports
)))
;
5350 json_object_add_value_int(root, "Write Zeros Command Support", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Write Zeros Command Support", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5351 json_object_add_value_int(root, "Sanitize Command Support", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Sanitize Command Support", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5352 json_object_add_value_int(root, "DSM Command Support", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "DSM Command Support", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5353 json_object_add_value_int(root, "Write Uncorr Command Support", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Write Uncorr Command Support", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5354 json_object_add_value_int(root, "Fused Command Support", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Fused Command Support", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5355 json_object_add_value_int(root, "Minimum DSSD Power State", le16_to_cpu(log_data->num_pcie_ports))json_object_object_add(root, "Minimum DSSD Power State", json_object_new_int
(le16_to_cpu(log_data->num_pcie_ports)))
;
5356
5357 char dssd_descr_str[40];
5358
5359 memset((void *)dssd_descr_str, 0, 40);
5360 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++) {
5361 sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j);
5362 json_object_add_value_int(root, dssd_descr_str, log_data->dssd_ps_descr[j])json_object_object_add(root, dssd_descr_str, json_object_new_int
(log_data->dssd_ps_descr[j]))
;
5363 }
5364
5365 json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version))json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
;
5366 char guid[40];
5367
5368 memset((void *)guid, 0, 40);
5369 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5370 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5371 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5372 json_object_add_value_string(root, "Log page GUID", guid);
5373
5374 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5375 printf("\n");
5376
5377 json_free_object(root)json_object_put(root);
5378}
5379
5380static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data)
5381{
5382 int j;
5383
5384 printf("Unsupported Requirements/C5 Log Page Data\n");
5385
5386 printf(" Number Unsupported Req IDs : 0x%x\n",
5387 le16_to_cpu(log_data->unsupported_count));
5388
5389 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++)
5390 printf(" Unsupported Requirement List %d : %s\n", j,
5391 log_data->unsupported_req_list[j]);
5392
5393 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5394 printf(" Log page GUID : 0x");
5395 for (j = 0; j < WDC_OCP_C5_GUID_LENGTH16; j++)
5396 printf("%x", log_data->log_page_guid[j]);
5397 printf("\n");
5398}
5399
5400static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
5401{
5402 int j;
5403 struct json_object *root = json_create_object()json_object_new_object();
5404
5405 json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count))json_object_object_add(root, "Number Unsupported Req IDs", json_object_new_int
(le16_to_cpu(log_data->unsupported_count)))
;
5406
5407 char unsup_req_list_str[41];
5408
5409 memset((void *)unsup_req_list_str, 0, 41);
5410 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
5411 sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j);
5412 json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]);
5413 }
5414
5415 json_object_add_value_int(root, "Log Page Version",json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
5416 le16_to_cpu(log_data->log_page_version))json_object_object_add(root, "Log Page Version", json_object_new_int
(le16_to_cpu(log_data->log_page_version)))
;
5417 char guid[40];
5418
5419 memset((void *)guid, 0, 40);
5420 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5421 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5422 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5423 json_object_add_value_string(root, "Log page GUID", guid);
5424
5425 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5426 printf("\n");
5427
5428 json_free_object(root)json_object_put(root);
5429}
5430
5431static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
5432{
5433 uint64_t converted = 0;
5434
5435 printf(" CA Log Page Performance Statistics :-\n");
5436 printf(" NAND Bytes Written %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5437 le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo));
5438 printf(" NAND Bytes Read %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5439 le64_to_cpu(perf->nand_bytes_rd_hi), le64_to_cpu(perf->nand_bytes_rd_lo));
5440
5441 converted = le64_to_cpu(perf->nand_bad_block);
5442 printf(" NAND Bad Block Count (Normalized) %20"PRIu64"l" "u""\n",
5443 converted & 0xFFFF);
5444 printf(" NAND Bad Block Count (Raw) %20"PRIu64"l" "u""\n",
5445 converted >> 16);
5446
5447 printf(" Uncorrectable Read Count %20"PRIu64"l" "u""\n",
5448 le64_to_cpu(perf->uncorr_read_count));
5449 printf(" Soft ECC Error Count %20"PRIu64"l" "u""\n",
5450 le64_to_cpu(perf->ecc_error_count));
5451 printf(" SSD End to End Detected Correction Count %20"PRIu32"u""\n",
5452 (uint32_t)le32_to_cpu(perf->ssd_detect_count));
5453 printf(" SSD End to End Corrected Correction Count %20"PRIu32"u""\n",
5454 (uint32_t)le32_to_cpu(perf->ssd_correct_count));
5455 printf(" System Data Percent Used %20"PRIu32"u""%%\n",
5456 perf->data_percent_used);
5457 printf(" User Data Erase Counts Max %20"PRIu32"u""\n",
5458 (uint32_t)le32_to_cpu(perf->data_erase_max));
5459 printf(" User Data Erase Counts Min %20"PRIu32"u""\n",
5460 (uint32_t)le32_to_cpu(perf->data_erase_min));
5461 printf(" Refresh Count %20"PRIu64"l" "u""\n",
5462 le64_to_cpu(perf->refresh_count));
5463
5464 converted = le64_to_cpu(perf->program_fail);
5465 printf(" Program Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5466 converted & 0xFFFF);
5467 printf(" Program Fail Count (Raw) %20"PRIu64"l" "u""\n",
5468 converted >> 16);
5469
5470 converted = le64_to_cpu(perf->user_erase_fail);
5471 printf(" User Data Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5472 converted & 0xFFFF);
5473 printf(" User Data Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5474 converted >> 16);
5475
5476 converted = le64_to_cpu(perf->system_erase_fail);
5477 printf(" System Area Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5478 converted & 0xFFFF);
5479 printf(" System Area Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5480 converted >> 16);
5481
5482 printf(" Thermal Throttling Status %20"PRIu8"hhu""\n",
5483 perf->thermal_throttle_status);
5484 printf(" Thermal Throttling Count %20"PRIu8"hhu""\n",
5485 perf->thermal_throttle_count);
5486 printf(" PCIe Correctable Error Count %20"PRIu64"l" "u""\n",
5487 le64_to_cpu(perf->pcie_corr_error));
5488 printf(" Incomplete Shutdown Count %20"PRIu32"u""\n",
5489 (uint32_t)le32_to_cpu(perf->incomplete_shutdown_count));
5490 printf(" Percent Free Blocks %20"PRIu32"u""%%\n",
5491 perf->percent_free_blocks);
5492}
5493
5494static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf)
5495{
5496 struct json_object *root = json_create_object()json_object_new_object();
5497 uint64_t converted = 0;
5498
5499 json_object_add_value_int(root, "NAND Bytes Written Hi", le64_to_cpu(perf->nand_bytes_wr_hi))json_object_object_add(root, "NAND Bytes Written Hi", json_object_new_int
(le64_to_cpu(perf->nand_bytes_wr_hi)))
;
5500 json_object_add_value_int(root, "NAND Bytes Written Lo", le64_to_cpu(perf->nand_bytes_wr_lo))json_object_object_add(root, "NAND Bytes Written Lo", json_object_new_int
(le64_to_cpu(perf->nand_bytes_wr_lo)))
;
5501 json_object_add_value_int(root, "NAND Bytes Read Hi", le64_to_cpu(perf->nand_bytes_rd_hi))json_object_object_add(root, "NAND Bytes Read Hi", json_object_new_int
(le64_to_cpu(perf->nand_bytes_rd_hi)))
;
5502 json_object_add_value_int(root, "NAND Bytes Read Lo", le64_to_cpu(perf->nand_bytes_rd_lo))json_object_object_add(root, "NAND Bytes Read Lo", json_object_new_int
(le64_to_cpu(perf->nand_bytes_rd_lo)))
;
5503
5504 converted = le64_to_cpu(perf->nand_bad_block);
5505 json_object_add_value_int(root, "NAND Bad Block Count (Normalized)",json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
5506 converted & 0xFFFF)json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5507 json_object_add_value_int(root, "NAND Bad Block Count (Raw)",json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
5508 converted >> 16)json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
;
5509
5510 json_object_add_value_int(root, "Uncorrectable Read Count", le64_to_cpu(perf->uncorr_read_count))json_object_object_add(root, "Uncorrectable Read Count", json_object_new_int
(le64_to_cpu(perf->uncorr_read_count)))
;
5511 json_object_add_value_int(root, "Soft ECC Error Count", le64_to_cpu(perf->ecc_error_count))json_object_object_add(root, "Soft ECC Error Count", json_object_new_int
(le64_to_cpu(perf->ecc_error_count)))
;
5512 json_object_add_value_int(root, "SSD End to End Detected Correction Count",json_object_object_add(root, "SSD End to End Detected Correction Count"
, json_object_new_int(le32_to_cpu(perf->ssd_detect_count))
)
5513 le32_to_cpu(perf->ssd_detect_count))json_object_object_add(root, "SSD End to End Detected Correction Count"
, json_object_new_int(le32_to_cpu(perf->ssd_detect_count))
)
;
5514 json_object_add_value_int(root, "SSD End to End Corrected Correction Count",json_object_object_add(root, "SSD End to End Corrected Correction Count"
, json_object_new_int(le32_to_cpu(perf->ssd_correct_count)
))
5515 le32_to_cpu(perf->ssd_correct_count))json_object_object_add(root, "SSD End to End Corrected Correction Count"
, json_object_new_int(le32_to_cpu(perf->ssd_correct_count)
))
;
5516 json_object_add_value_int(root, "System Data Percent Used",json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
5517 perf->data_percent_used)json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
;
5518 json_object_add_value_int(root, "User Data Erase Counts Max",json_object_object_add(root, "User Data Erase Counts Max", json_object_new_int
(le32_to_cpu(perf->data_erase_max)))
5519 le32_to_cpu(perf->data_erase_max))json_object_object_add(root, "User Data Erase Counts Max", json_object_new_int
(le32_to_cpu(perf->data_erase_max)))
;
5520 json_object_add_value_int(root, "User Data Erase Counts Min",json_object_object_add(root, "User Data Erase Counts Min", json_object_new_int
(le32_to_cpu(perf->data_erase_min)))
5521 le32_to_cpu(perf->data_erase_min))json_object_object_add(root, "User Data Erase Counts Min", json_object_new_int
(le32_to_cpu(perf->data_erase_min)))
;
5522 json_object_add_value_int(root, "Refresh Count", le64_to_cpu(perf->refresh_count))json_object_object_add(root, "Refresh Count", json_object_new_int
(le64_to_cpu(perf->refresh_count)))
;
5523
5524 converted = le64_to_cpu(perf->program_fail);
5525 json_object_add_value_int(root, "Program Fail Count (Normalized)",json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
5526 converted & 0xFFFF)json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5527 json_object_add_value_int(root, "Program Fail Count (Raw)",json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
5528 converted >> 16)json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
;
5529
5530 converted = le64_to_cpu(perf->user_erase_fail);
5531 json_object_add_value_int(root, "User Data Erase Fail Count (Normalized)",json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
5532 converted & 0xFFFF)json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5533 json_object_add_value_int(root, "User Data Erase Fail Count (Raw)",json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
5534 converted >> 16)json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5535
5536 converted = le64_to_cpu(perf->system_erase_fail);
5537 json_object_add_value_int(root, "System Area Erase Fail Count (Normalized)",json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
5538 converted & 0xFFFF)json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5539 json_object_add_value_int(root, "System Area Erase Fail Count (Raw)",json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
5540 converted >> 16)json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5541
5542 json_object_add_value_int(root, "Thermal Throttling Status",json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
5543 perf->thermal_throttle_status)json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
;
5544 json_object_add_value_int(root, "Thermal Throttling Count",json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
5545 perf->thermal_throttle_count)json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
;
5546 json_object_add_value_int(root, "PCIe Correctable Error", le64_to_cpu(perf->pcie_corr_error))json_object_object_add(root, "PCIe Correctable Error", json_object_new_int
(le64_to_cpu(perf->pcie_corr_error)))
;
5547 json_object_add_value_int(root, "Incomplete Shutdown Counte", le32_to_cpu(perf->incomplete_shutdown_count))json_object_object_add(root, "Incomplete Shutdown Counte", json_object_new_int
(le32_to_cpu(perf->incomplete_shutdown_count)))
;
5548 json_object_add_value_int(root, "Percent Free Blocks", perf->percent_free_blocks)json_object_object_add(root, "Percent Free Blocks", json_object_new_int
(perf->percent_free_blocks))
;
5549 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5550 printf("\n");
5551 json_free_object(root)json_object_put(root);
5552}
5553
5554static void wdc_print_bd_ca_log_normal(struct libnvme_transport_handle *hdl, void *data)
5555{
5556 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5557 __u64 *raw;
5558 __u64 rawSwapped;
5559 __u16 *word_raw1 = NULL((void*)0),
5560 *word_raw2 = NULL((void*)0),
5561 *word_raw3 = NULL((void*)0);
5562 __u32 *dword_raw = NULL((void*)0);
5563 __u8 *byte_raw = NULL((void*)0);
5564 bool_Bool valid_id = true1;
5565
5566 while (valid_id) {
5567 raw = (__u64 *)&bd_data->raw_value[0];
5568 rawSwapped = (le64_to_cpu(*raw)>>8);
5569
5570 switch (bd_data->field_id) {
5571 case 0x0:
5572 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
5573 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
5574 printf("key normalized raw\n");
5575 printf("program_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5576 bd_data->normalized_value, (uint64_t)rawSwapped);
5577 break;
5578 case 0x1:
5579 printf("erase_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5580 bd_data->normalized_value, (uint64_t)rawSwapped);
5581 break;
5582 case 0x2:
5583 word_raw1 = (__u16 *)&bd_data->raw_value[1];
5584 word_raw2 = (__u16 *)&bd_data->raw_value[3];
5585 word_raw3 = (__u16 *)&bd_data->raw_value[5];
5586 printf("wear_leveling : %3"PRIu8"hhu",
5587 bd_data->normalized_value);
5588 printf("%% min: %"PRIu16"hu"", max: %"PRIu16"hu"", avg: %"PRIu16"hu""\n",
5589 le16_to_cpu(*word_raw1),
5590 le16_to_cpu(*word_raw2),
5591 le16_to_cpu(*word_raw3));
5592 break;
5593 case 0x3:
5594 printf("end_to_end_error_detection_count: %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5595 bd_data->normalized_value, (uint64_t)rawSwapped);
5596 break;
5597 case 0x4:
5598 printf("crc_error_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5599 bd_data->normalized_value, (uint64_t)rawSwapped);
5600 break;
5601 case 0x5:
5602 printf("timed_workload_media_wear : %3"PRIu8"hhu""%% %-.3f%%\n",
5603 bd_data->normalized_value,
5604 safe_div_fp((rawSwapped), 1024.0));
5605 break;
5606 case 0x6:
5607 printf("timed_workload_host_reads : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5608 bd_data->normalized_value, (uint64_t)rawSwapped);
5609 break;
5610 case 0x7:
5611 printf("timed_workload_timer : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5612 bd_data->normalized_value, (uint64_t)rawSwapped);
5613 break;
5614 case 0x8:
5615 byte_raw = (__u8 *)&bd_data->raw_value[1];
5616 dword_raw = (__u32 *)&bd_data->raw_value[2];
5617 printf("thermal_throttle_status : %3"PRIu8"hhu""%% %"PRIu16"hu",
5618 bd_data->normalized_value, *byte_raw);
5619 printf("%%, cnt: %"PRIu16"hu""\n", le32_to_cpu(*dword_raw));
5620 break;
5621 case 0x9:
5622 printf("retry_buffer_overflow_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5623 bd_data->normalized_value, (uint64_t)rawSwapped);
5624 break;
5625 case 0xA:
5626 printf("pll_lock_loss_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5627 bd_data->normalized_value, (uint64_t)rawSwapped);
5628 break;
5629 case 0xB:
5630 printf("nand_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5631 bd_data->normalized_value, (uint64_t)rawSwapped);
5632 break;
5633 case 0xC:
5634 printf("host_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5635 bd_data->normalized_value, (uint64_t)rawSwapped);
5636 /* last entry, break from while loop */
5637 valid_id = false0;
5638 break;
5639 default:
5640 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5641 break;
5642 }
5643
5644 bd_data++;
5645 }
5646
5647 return;
5648}
5649
5650static void wdc_print_bd_ca_log_json(void *data)
5651{
5652 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5653 __u64 *raw, rawSwapped;
5654 __u16 *word_raw;
5655 __u32 *dword_raw;
5656 __u8 *byte_raw;
5657 bool_Bool valid_id = true1;
5658 struct json_object *root = json_create_object()json_object_new_object();
5659
5660 while (valid_id) {
5661 raw = (__u64 *)&bd_data->raw_value[0];
5662 rawSwapped = (le64_to_cpu(*raw)>>8);
5663
5664 switch (bd_data->field_id) {
5665 case 0x0:
5666 json_object_add_value_int(root, "program_fail_count normalized",json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
5667 bd_data->normalized_value)json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
;
5668 json_object_add_value_uint64(root, "program_fail_count raw",json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
5669 rawSwapped)json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5670 break;
5671 case 0x1:
5672 json_object_add_value_int(root, "erase_fail_count normalized",json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
5673 bd_data->normalized_value)json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5674 json_object_add_value_uint64(root, "erase_fail_count raw",json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
5675 rawSwapped)json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5676 break;
5677 case 0x2:
5678 word_raw = (__u16 *)&bd_data->raw_value[1];
5679 json_object_add_value_int(root, "wear_leveling normalized",json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
5680 bd_data->normalized_value)json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
;
5681 json_object_add_value_int(root, "wear_leveling min",json_object_object_add(root, "wear_leveling min", json_object_new_int
(le16_to_cpu(*word_raw)))
5682 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling min", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5683 word_raw = (__u16 *)&bd_data->raw_value[3];
5684 json_object_add_value_int(root, "wear_leveling max",json_object_object_add(root, "wear_leveling max", json_object_new_int
(le16_to_cpu(*word_raw)))
5685 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling max", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5686 word_raw = (__u16 *)&bd_data->raw_value[5];
5687 json_object_add_value_int(root, "wear_leveling avg",json_object_object_add(root, "wear_leveling avg", json_object_new_int
(le16_to_cpu(*word_raw)))
5688 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling avg", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5689 break;
5690 case 0x3:
5691 json_object_add_value_int(root,json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
5692 "end_to_end_error_detection_count normalized",json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
5693 bd_data->normalized_value)json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5694 json_object_add_value_uint64(root,json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5695 "end_to_end_error_detection_count raw",json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5696 rawSwapped)json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
;
5697 break;
5698 case 0x4:
5699 json_object_add_value_int(root, "crc_error_count normalized",json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
5700 bd_data->normalized_value)json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5701 json_object_add_value_uint64(root, "crc_error_count raw",json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
5702 rawSwapped)json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
;
5703 break;
5704 case 0x5:
5705 json_object_add_value_int(root, "timed_workload_media_wear normalized",json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
5706 bd_data->normalized_value)json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
;
5707 json_object_add_value_double(root, "timed_workload_media_wear raw",json_object_object_add(root, "timed_workload_media_wear raw",
util_json_object_new_double(safe_div_fp(((uint64_t)rawSwapped
), 1024.0)))
5708 safe_div_fp(((uint64_t)rawSwapped), 1024.0))json_object_object_add(root, "timed_workload_media_wear raw",
util_json_object_new_double(safe_div_fp(((uint64_t)rawSwapped
), 1024.0)))
;
5709 break;
5710 case 0x6:
5711 json_object_add_value_int(root, "timed_workload_host_reads normalized",json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
5712 bd_data->normalized_value)json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
;
5713 json_object_add_value_uint64(root, "timed_workload_host_reads raw",json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
5714 rawSwapped)json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
;
5715 break;
5716 case 0x7:
5717 json_object_add_value_int(root, "timed_workload_timer normalized",json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
5718 bd_data->normalized_value)json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
;
5719 json_object_add_value_uint64(root, "timed_workload_timer",json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
5720 rawSwapped)json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
;
5721 break;
5722 case 0x8:
5723 byte_raw = (__u8 *)&bd_data->raw_value[1];
5724 json_object_add_value_int(root, "thermal_throttle_status normalized",json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
5725 bd_data->normalized_value)json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
;
5726 json_object_add_value_int(root, "thermal_throttle_status",json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
5727 *byte_raw)json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
;
5728 dword_raw = (__u32 *)&bd_data->raw_value[2];
5729 json_object_add_value_int(root, "thermal_throttle_cnt",json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(le32_to_cpu(*dword_raw)))
5730 le32_to_cpu(*dword_raw))json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(le32_to_cpu(*dword_raw)))
;
5731 break;
5732 case 0x9:
5733 json_object_add_value_int(root, "retry_buffer_overflow_count normalized",json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
5734 bd_data->normalized_value)json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5735 json_object_add_value_uint64(root, "retry_buffer_overflow_count raw",json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
5736 rawSwapped)json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
;
5737 break;
5738 case 0xA:
5739 json_object_add_value_int(root, "pll_lock_loss_count normalized",json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
5740 bd_data->normalized_value)json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5741 json_object_add_value_uint64(root, "pll_lock_loss_count raw",json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
5742 rawSwapped)json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
;
5743 break;
5744 case 0xB:
5745 json_object_add_value_int(root, "nand_bytes_written normalized",json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
5746 bd_data->normalized_value)json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5747 json_object_add_value_uint64(root, "nand_bytes_written raw",json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
5748 rawSwapped)json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5749 break;
5750 case 0xC:
5751 json_object_add_value_int(root, "host_bytes_written normalized",json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
5752 bd_data->normalized_value)json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5753 json_object_add_value_uint64(root, "host_bytes_written raw",json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
5754 rawSwapped)json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5755
5756 /* last entry, break from while loop */
5757 valid_id = false0;
5758 break;
5759 default:
5760 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5761 break;
5762 }
5763
5764 bd_data++;
5765 }
5766
5767 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5768 printf("\n");
5769 json_free_object(root)json_object_put(root);
5770
5771 return;
5772}
5773
5774static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf)
5775{
5776 printf(" D0 Smart Log Page Statistics :-\n");
5777 printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"u""\n",
5778 (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count));
5779 printf(" Lifetime Power on Hours %20"PRIu32"u""\n",
5780 (uint32_t)le32_to_cpu(perf->lifetime_power_on_hours));
5781 printf(" Lifetime UECC Count %20"PRIu32"u""\n",
5782 (uint32_t)le32_to_cpu(perf->lifetime_uecc_count));
5783 printf(" Lifetime Write Amplification Factor %20"PRIu32"u""\n",
5784 (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor));
5785 printf(" Trailing Hour Write Amplification Factor %20"PRIu32"u""\n",
5786 (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor));
5787 printf(" Reserve Erase Block Count %20"PRIu32"u""\n",
5788 (uint32_t)le32_to_cpu(perf->reserve_erase_block_count));
5789 printf(" Lifetime Program Fail Count %20"PRIu32"u""\n",
5790 (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count));
5791 printf(" Lifetime Block Erase Fail Count %20"PRIu32"u""\n",
5792 (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count));
5793 printf(" Lifetime Die Failure Count %20"PRIu32"u""\n",
5794 (uint32_t)le32_to_cpu(perf->lifetime_die_failure_count));
5795 printf(" Lifetime Link Rate Downgrade Count %20"PRIu32"u""\n",
5796 (uint32_t)le32_to_cpu(perf->lifetime_link_rate_downgrade_count));
5797 printf(" Lifetime Clean Shutdown Count on Power Loss %20"PRIu32"u""\n",
5798 (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count));
5799 printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"u""\n",
5800 (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count));
5801 printf(" Current Temperature %20"PRIu32"u""\n",
5802 (uint32_t)le32_to_cpu(perf->current_temp));
5803 printf(" Max Recorded Temperature %20"PRIu32"u""\n",
5804 (uint32_t)le32_to_cpu(perf->max_recorded_temp));
5805 printf(" Lifetime Retired Block Count %20"PRIu32"u""\n",
5806 (uint32_t)le32_to_cpu(perf->lifetime_retired_block_count));
5807 printf(" Lifetime Read Disturb Reallocation Events %20"PRIu32"u""\n",
5808 (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events));
5809 printf(" Lifetime NAND Writes %20"PRIu64"l" "u""\n",
5810 le64_to_cpu(perf->lifetime_nand_writes));
5811 printf(" Capacitor Health %20"PRIu32"u""%%\n",
5812 (uint32_t)le32_to_cpu(perf->capacitor_health));
5813 printf(" Lifetime User Writes %20"PRIu64"l" "u""\n",
5814 le64_to_cpu(perf->lifetime_user_writes));
5815 printf(" Lifetime User Reads %20"PRIu64"l" "u""\n",
5816 le64_to_cpu(perf->lifetime_user_reads));
5817 printf(" Lifetime Thermal Throttle Activations %20"PRIu32"u""\n",
5818 (uint32_t)le32_to_cpu(perf->lifetime_thermal_throttle_act));
5819 printf(" Percentage of P/E Cycles Remaining %20"PRIu32"u""%%\n",
5820 (uint32_t)le32_to_cpu(perf->percentage_pe_cycles_remaining));
5821}
5822
5823static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf)
5824{
5825 struct json_object *root = json_create_object()json_object_new_object();
5826
5827 json_object_add_value_int(root, "Lifetime Reallocated Erase Block Count",json_object_object_add(root, "Lifetime Reallocated Erase Block Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_realloc_erase_block_count
)))
5828 le32_to_cpu(perf->lifetime_realloc_erase_block_count))json_object_object_add(root, "Lifetime Reallocated Erase Block Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_realloc_erase_block_count
)))
;
5829 json_object_add_value_int(root, "Lifetime Power on Hours",json_object_object_add(root, "Lifetime Power on Hours", json_object_new_int
(le32_to_cpu(perf->lifetime_power_on_hours)))
5830 le32_to_cpu(perf->lifetime_power_on_hours))json_object_object_add(root, "Lifetime Power on Hours", json_object_new_int
(le32_to_cpu(perf->lifetime_power_on_hours)))
;
5831 json_object_add_value_int(root, "Lifetime UECC Count",json_object_object_add(root, "Lifetime UECC Count", json_object_new_int
(le32_to_cpu(perf->lifetime_uecc_count)))
5832 le32_to_cpu(perf->lifetime_uecc_count))json_object_object_add(root, "Lifetime UECC Count", json_object_new_int
(le32_to_cpu(perf->lifetime_uecc_count)))
;
5833 json_object_add_value_int(root, "Lifetime Write Amplification Factor",json_object_object_add(root, "Lifetime Write Amplification Factor"
, json_object_new_int(le32_to_cpu(perf->lifetime_wrt_amp_factor
)))
5834 le32_to_cpu(perf->lifetime_wrt_amp_factor))json_object_object_add(root, "Lifetime Write Amplification Factor"
, json_object_new_int(le32_to_cpu(perf->lifetime_wrt_amp_factor
)))
;
5835 json_object_add_value_int(root, "Trailing Hour Write Amplification Factor",json_object_object_add(root, "Trailing Hour Write Amplification Factor"
, json_object_new_int(le32_to_cpu(perf->trailing_hr_wrt_amp_factor
)))
5836 le32_to_cpu(perf->trailing_hr_wrt_amp_factor))json_object_object_add(root, "Trailing Hour Write Amplification Factor"
, json_object_new_int(le32_to_cpu(perf->trailing_hr_wrt_amp_factor
)))
;
5837 json_object_add_value_int(root, "Reserve Erase Block Count",json_object_object_add(root, "Reserve Erase Block Count", json_object_new_int
(le32_to_cpu(perf->reserve_erase_block_count)))
5838 le32_to_cpu(perf->reserve_erase_block_count))json_object_object_add(root, "Reserve Erase Block Count", json_object_new_int
(le32_to_cpu(perf->reserve_erase_block_count)))
;
5839 json_object_add_value_int(root, "Lifetime Program Fail Count",json_object_object_add(root, "Lifetime Program Fail Count", json_object_new_int
(le32_to_cpu(perf->lifetime_program_fail_count)))
5840 le32_to_cpu(perf->lifetime_program_fail_count))json_object_object_add(root, "Lifetime Program Fail Count", json_object_new_int
(le32_to_cpu(perf->lifetime_program_fail_count)))
;
5841 json_object_add_value_int(root, "Lifetime Block Erase Fail Count",json_object_object_add(root, "Lifetime Block Erase Fail Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_block_erase_fail_count
)))
5842 le32_to_cpu(perf->lifetime_block_erase_fail_count))json_object_object_add(root, "Lifetime Block Erase Fail Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_block_erase_fail_count
)))
;
5843 json_object_add_value_int(root, "Lifetime Die Failure Count",json_object_object_add(root, "Lifetime Die Failure Count", json_object_new_int
(le32_to_cpu(perf->lifetime_die_failure_count)))
5844 le32_to_cpu(perf->lifetime_die_failure_count))json_object_object_add(root, "Lifetime Die Failure Count", json_object_new_int
(le32_to_cpu(perf->lifetime_die_failure_count)))
;
5845 json_object_add_value_int(root, "Lifetime Link Rate Downgrade Count",json_object_object_add(root, "Lifetime Link Rate Downgrade Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_link_rate_downgrade_count
)))
5846 le32_to_cpu(perf->lifetime_link_rate_downgrade_count))json_object_object_add(root, "Lifetime Link Rate Downgrade Count"
, json_object_new_int(le32_to_cpu(perf->lifetime_link_rate_downgrade_count
)))
;
5847 json_object_add_value_int(root, "Lifetime Clean Shutdown Count on Power Loss",json_object_object_add(root, "Lifetime Clean Shutdown Count on Power Loss"
, json_object_new_int(le32_to_cpu(perf->lifetime_clean_shutdown_count
)))
5848 le32_to_cpu(perf->lifetime_clean_shutdown_count))json_object_object_add(root, "Lifetime Clean Shutdown Count on Power Loss"
, json_object_new_int(le32_to_cpu(perf->lifetime_clean_shutdown_count
)))
;
5849 json_object_add_value_int(root, "Lifetime Unclean Shutdowns on Power Loss",json_object_object_add(root, "Lifetime Unclean Shutdowns on Power Loss"
, json_object_new_int(le32_to_cpu(perf->lifetime_unclean_shutdown_count
)))
5850 le32_to_cpu(perf->lifetime_unclean_shutdown_count))json_object_object_add(root, "Lifetime Unclean Shutdowns on Power Loss"
, json_object_new_int(le32_to_cpu(perf->lifetime_unclean_shutdown_count
)))
;
5851 json_object_add_value_int(root, "Current Temperature",json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
5852 le32_to_cpu(perf->current_temp))json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
;
5853 json_object_add_value_int(root, "Max Recorded Temperature",json_object_object_add(root, "Max Recorded Temperature", json_object_new_int
(le32_to_cpu(perf->max_recorded_temp)))
5854 le32_to_cpu(perf->max_recorded_temp))json_object_object_add(root, "Max Recorded Temperature", json_object_new_int
(le32_to_cpu(perf->max_recorded_temp)))
;
5855 json_object_add_value_int(root, "Lifetime Retired Block Count",json_object_object_add(root, "Lifetime Retired Block Count", json_object_new_int
(le32_to_cpu(perf->lifetime_retired_block_count)))
5856 le32_to_cpu(perf->lifetime_retired_block_count))json_object_object_add(root, "Lifetime Retired Block Count", json_object_new_int
(le32_to_cpu(perf->lifetime_retired_block_count)))
;
5857 json_object_add_value_int(root, "Lifetime Read Disturb Reallocation Events",json_object_object_add(root, "Lifetime Read Disturb Reallocation Events"
, json_object_new_int(le32_to_cpu(perf->lifetime_read_disturb_realloc_events
)))
5858 le32_to_cpu(perf->lifetime_read_disturb_realloc_events))json_object_object_add(root, "Lifetime Read Disturb Reallocation Events"
, json_object_new_int(le32_to_cpu(perf->lifetime_read_disturb_realloc_events
)))
;
5859 json_object_add_value_int(root, "Lifetime NAND Writes",json_object_object_add(root, "Lifetime NAND Writes", json_object_new_int
(le64_to_cpu(perf->lifetime_nand_writes)))
5860 le64_to_cpu(perf->lifetime_nand_writes))json_object_object_add(root, "Lifetime NAND Writes", json_object_new_int
(le64_to_cpu(perf->lifetime_nand_writes)))
;
5861 json_object_add_value_int(root, "Capacitor Health",json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
5862 le32_to_cpu(perf->capacitor_health))json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
;
5863 json_object_add_value_int(root, "Lifetime User Writes",json_object_object_add(root, "Lifetime User Writes", json_object_new_int
(le64_to_cpu(perf->lifetime_user_writes)))
5864 le64_to_cpu(perf->lifetime_user_writes))json_object_object_add(root, "Lifetime User Writes", json_object_new_int
(le64_to_cpu(perf->lifetime_user_writes)))
;
5865 json_object_add_value_int(root, "Lifetime User Reads",json_object_object_add(root, "Lifetime User Reads", json_object_new_int
(le64_to_cpu(perf->lifetime_user_reads)))
5866 le64_to_cpu(perf->lifetime_user_reads))json_object_object_add(root, "Lifetime User Reads", json_object_new_int
(le64_to_cpu(perf->lifetime_user_reads)))
;
5867 json_object_add_value_int(root, "Lifetime Thermal Throttle Activations",json_object_object_add(root, "Lifetime Thermal Throttle Activations"
, json_object_new_int(le32_to_cpu(perf->lifetime_thermal_throttle_act
)))
5868 le32_to_cpu(perf->lifetime_thermal_throttle_act))json_object_object_add(root, "Lifetime Thermal Throttle Activations"
, json_object_new_int(le32_to_cpu(perf->lifetime_thermal_throttle_act
)))
;
5869 json_object_add_value_int(root, "Percentage of P/E Cycles Remaining",json_object_object_add(root, "Percentage of P/E Cycles Remaining"
, json_object_new_int(le32_to_cpu(perf->percentage_pe_cycles_remaining
)))
5870 le32_to_cpu(perf->percentage_pe_cycles_remaining))json_object_object_add(root, "Percentage of P/E Cycles Remaining"
, json_object_new_int(le32_to_cpu(perf->percentage_pe_cycles_remaining
)))
;
5871
5872 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5873 printf("\n");
5874 json_free_object(root)json_object_put(root);
5875}
5876
5877static void wdc_get_commit_action_bin(__u8 commit_action_type, char *action_bin)
5878{
5879
5880 switch (commit_action_type) {
5881 case 0:
5882 strcpy(action_bin, "000b");
5883 break;
5884 case 1:
5885 strcpy(action_bin, "001b");
5886 break;
5887 case 2:
5888 strcpy(action_bin, "010b");
5889 break;
5890 case 3:
5891 strcpy(action_bin, "011b");
5892 break;
5893 case 4:
5894 strcpy(action_bin, "100b");
5895 break;
5896 case 5:
5897 strcpy(action_bin, "101b");
5898 break;
5899 case 6:
5900 strcpy(action_bin, "110b");
5901 break;
5902 case 7:
5903 strcpy(action_bin, "111b");
5904 break;
5905 default:
5906 strcpy(action_bin, "INVALID");
5907 }
5908
5909}
5910
5911static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
5912 __u32 cust_id, __u32 vendor_id,
5913 __u32 device_id)
5914{
5915 int i, j;
5916 char previous_fw[9];
5917 char new_fw[9];
5918 char commit_action_bin[8];
5919 char time_str[100];
5920 __u16 oldestEntryIdx = 0, entryIdx = 0;
5921 uint64_t timestamp;
5922 __u64 timestamp_sec;
5923 const char *null_fw = "--------";
5924
5925 memset((void *)time_str, '\0', 100);
5926
5927 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
5928 printf(" Firmware Activate History Log\n");
5929 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005 ||
5930 vendor_id == WDC_NVME_SNDK_VID0x15b7) {
5931 printf(" Power on Hour Power Cycle Previous New\n");
5932 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
5933 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5934 } else {
5935 printf(" Power Cycle Previous New\n");
5936 printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n");
5937 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5938 }
5939
5940 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
5941
5942 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
5943 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
5944 /* find lowest/oldest entry */
5945 for (i = 0; i < num_entries; i++) {
5946 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
5947 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
5948 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
5949 oldestEntryIdx = j;
5950 break;
5951 }
5952 }
5953 }
5954 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
5955 entryIdx = 0;
5956 else
5957 entryIdx = oldestEntryIdx;
5958
5959 for (i = 0; i < num_entries; i++) {
5960 memset((void *)previous_fw, 0, 9);
5961 memset((void *)new_fw, 0, 9);
5962 memset((void *)commit_action_bin, 0, 8);
5963
5964 memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8);
5965 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
5966 memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8);
5967 else
5968 memcpy(new_fw, null_fw, 8);
5969
5970 printf("%5"PRIu16"hu""", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
5971
5972 timestamp = (0x0000FFFFFFFFFFFF &
5973 le64_to_cpu(
5974 fw_act_history_entry->entry[entryIdx].timestamp));
5975 timestamp_sec = timestamp / 1000;
5976 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
5977 printf(" ");
5978 memset((void *)time_str, 0, 9);
5979 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
5980 (__u32)(timestamp_sec/3600),
5981 (__u8)(timestamp_sec%3600/60),
5982 (__u8)(timestamp_sec%60));
5983
5984 printf("%s", time_str);
5985 printf(" ");
5986 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
5987 printf(" ");
5988
5989 memset((void *)time_str, 0, 9);
5990 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
5991 (__u32)((timestamp_sec/3600)%24),
5992 (__u8)((timestamp_sec/60)%60),
5993 (__u8)(timestamp_sec%60));
5994 printf("%s", time_str);
5995 printf(" ");
5996 } else {
5997 printf(" ");
5998 printf("%16"PRIu64"l" "u""", timestamp);
5999 printf(" ");
6000 }
6001
6002 printf("%16"PRIu64"l" "u""", (uint64_t)le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count));
6003 printf(" ");
6004 printf("%s", (char *)previous_fw);
6005 printf(" ");
6006 printf("%s", (char *)new_fw);
6007 printf(" ");
6008 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number);
6009 printf(" ");
6010 wdc_get_commit_action_bin(
6011 fw_act_history_entry->entry[entryIdx].commit_action_type,
6012 (char *)&commit_action_bin);
6013 printf(" %s", (char *)commit_action_bin);
6014 printf(" ");
6015 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))
6016 printf("pass");
6017 else
6018 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result));
6019 printf("\n");
6020
6021 entryIdx++;
6022 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6023 entryIdx = 0;
6024 }
6025 } else {
6026 printf(" Firmware Activate History Log\n");
6027 printf(" Power on Hour Power Cycle Previous New\n");
6028 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6029 printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n");
6030
6031 struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr));
6032
6033 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6034 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6035 /* find lowest/oldest entry */
6036 for (i = 0; i < num_entries; i++) {
6037 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6038 oldestEntryIdx = i+1;
6039 break;
6040 }
6041 }
6042 }
6043
6044 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6045 entryIdx = 0;
6046 else
6047 entryIdx = oldestEntryIdx;
6048
6049 for (i = 0; i < num_entries; i++) {
6050 memset((void *)previous_fw, 0, 9);
6051 memset((void *)new_fw, 0, 9);
6052 memset((void *)commit_action_bin, 0, 8);
6053
6054 memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6055 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6056 memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6057 else
6058 memcpy(new_fw, null_fw, 8);
6059
6060 printf("%5"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].entry_num));
6061 printf(" ");
6062 printf("%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6063 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6064 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6065 printf(" ");
6066 printf("%16"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count));
6067 printf(" ");
6068 printf("%s", (char *)previous_fw);
6069 printf(" ");
6070 printf("%s", (char *)new_fw);
6071 printf(" ");
6072 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry[entryIdx].slot_number);
6073 printf(" ");
6074 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6075 (char *)&commit_action_bin);
6076 printf(" %s", (char *)commit_action_bin);
6077 printf(" ");
6078 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result))
6079 printf("pass");
6080 else
6081 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result));
6082
6083 printf("\n");
6084
6085 entryIdx++;
6086 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6087 entryIdx = 0;
6088 }
6089 }
6090}
6091
6092static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
6093 __u32 cust_id, __u32 vendor_id,
6094 __u32 device_id)
6095{
6096 struct json_object *root = json_create_object()json_object_new_object();
6097 int i, j;
6098 char previous_fw[9];
6099 char new_fw[9];
6100 char commit_action_bin[8];
6101 char fail_str[32];
6102 char time_str[100];
6103 char ext_time_str[20];
6104 uint64_t timestamp;
6105 __u64 timestamp_sec;
6106
6107 memset((void *)previous_fw, 0, 9);
6108 memset((void *)new_fw, 0, 9);
6109 memset((void *)commit_action_bin, 0, 8);
6110 memset((void *)time_str, '\0', 100);
6111 memset((void *)ext_time_str, 0, 20);
6112 memset((void *)fail_str, 0, 11);
6113 char *null_fw = "--------";
6114 __u16 oldestEntryIdx = 0, entryIdx = 0;
6115
6116 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6117 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6118
6119 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6120 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6121 /* find lowest/oldest entry */
6122 for (i = 0; i < num_entries; i++) {
6123 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6124 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6125 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6126 oldestEntryIdx = j;
6127 break;
6128 }
6129 }
6130 }
6131 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6132 entryIdx = 0;
6133 else
6134 entryIdx = oldestEntryIdx;
6135
6136 for (i = 0; i < num_entries; i++) {
6137 memcpy(previous_fw,
6138 (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version),
6139 8);
6140 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6141 memcpy(new_fw,
6142 (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version),
6143 8);
6144 else
6145 memcpy(new_fw, null_fw, 8);
6146
6147 json_object_add_value_int(root, "Entry",json_object_object_add(root, "Entry", json_object_new_int(le16_to_cpu
(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries
)))
6148 le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries))json_object_object_add(root, "Entry", json_object_new_int(le16_to_cpu
(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries
)))
;
6149
6150 timestamp = (0x0000FFFFFFFFFFFF &
6151 le64_to_cpu(
6152 fw_act_history_entry->entry[entryIdx].timestamp));
6153 timestamp_sec = timestamp / 1000;
6154 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6155 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6156 (__u32)(timestamp_sec/3600),
6157 (__u8)(timestamp_sec%3600/60),
6158 (__u8)(timestamp_sec%60));
6159
6160 json_object_add_value_string(root, "Power on Hour", time_str);
6161
6162 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6163 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6164 (__u32)((timestamp_sec/3600)%24),
6165 (__u8)((timestamp_sec/60)%60),
6166 (__u8)(timestamp_sec%60));
6167 json_object_add_value_string(root, "Power on Hour", time_str);
6168 } else {
6169 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
6170 }
6171
6172 json_object_add_value_int(root, "Power Cycle Count",json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count
)))
6173 le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count))json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count
)))
;
6174 json_object_add_value_string(root, "Previous Firmware",
6175 previous_fw);
6176 json_object_add_value_string(root, "New Firmware",
6177 new_fw);
6178 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
->entry[entryIdx].slot_number))
6179 fw_act_history_entry->entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
->entry[entryIdx].slot_number))
;
6180
6181 wdc_get_commit_action_bin(
6182 fw_act_history_entry->entry[entryIdx].commit_action_type,
6183 (char *)&commit_action_bin);
6184 json_object_add_value_string(root, "Action", commit_action_bin);
6185
6186 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) {
6187 json_object_add_value_string(root, "Result", "pass");
6188 } else {
6189 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)));
6190 json_object_add_value_string(root, "Result", fail_str);
6191 }
6192
6193 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6194 printf("\n");
6195
6196 entryIdx++;
6197 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6198 entryIdx = 0;
6199 }
6200 } else {
6201 struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr));
6202
6203 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6204 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6205 /* find lowest/oldest entry */
6206 for (i = 0; i < num_entries; i++) {
6207 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6208 oldestEntryIdx = i+1;
6209 break;
6210 }
6211 }
6212 }
6213 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6214 entryIdx = 0;
6215 else
6216 entryIdx = oldestEntryIdx;
6217
6218 for (i = 0; i < num_entries; i++) {
6219 memcpy(previous_fw,
6220 (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6221 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6222 memcpy(new_fw,
6223 (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6224 else
6225 memcpy(new_fw, null_fw, 8);
6226
6227 json_object_add_value_int(root, "Entry",json_object_object_add(root, "Entry", json_object_new_int(le32_to_cpu
(fw_act_history_entry[entryIdx].entry_num)))
6228 le32_to_cpu(fw_act_history_entry[entryIdx].entry_num))json_object_object_add(root, "Entry", json_object_new_int(le32_to_cpu
(fw_act_history_entry[entryIdx].entry_num)))
;
6229
6230 sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6231 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6232 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6233 json_object_add_value_string(root, "Power on Hour", time_str);
6234
6235 json_object_add_value_int(root, "Power Cycle Count",json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count
)))
6236 le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count))json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count
)))
;
6237 json_object_add_value_string(root, "Previous Firmware",
6238 previous_fw);
6239 json_object_add_value_string(root, "New Firmware",
6240 new_fw);
6241 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
6242 fw_act_history_entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
;
6243
6244 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6245 (char *)&commit_action_bin);
6246 json_object_add_value_string(root, "Action", commit_action_bin);
6247
6248 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) {
6249 json_object_add_value_string(root, "Result", "pass");
6250 } else {
6251 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry[entryIdx].result)));
6252 json_object_add_value_string(root, "Result", fail_str);
6253 }
6254
6255 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6256 printf("\n");
6257
6258 entryIdx++;
6259 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6260 entryIdx = 0;
6261 }
6262 }
6263
6264 json_free_object(root)json_object_put(root);
6265}
6266
6267static int nvme_get_print_ocp_cloud_smart_log(struct libnvme_transport_handle *hdl,
6268 int uuid_index,
6269 __u32 namespace_id,
6270 int fmt)
6271{
6272 struct ocp_cloud_smart_log *log_ptr = NULL((void*)0);
6273 struct libnvme_passthru_cmd cmd;
6274 int ret, i;
6275
6276 log_ptr = malloc(sizeof(*log_ptr));
6277 if (!log_ptr) {
6278 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6279 return -1;
6280 }
6281
6282 if (namespace_id == NVME_NSID_ALL) {
6283 ret = libnvme_get_nsid(hdl, &namespace_id);
6284 if (ret < 0)
6285 namespace_id = NVME_NSID_ALL;
6286 }
6287
6288 /* Get the 0xC0 log data */
6289 nvme_init_get_log(&cmd, namespace_id,
6290 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6291 log_ptr, sizeof(*log_ptr));
6292 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6293 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6294 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6295 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6296 if (fmt == JSON)
6297 nvme_show_status(ret);
6298
6299 if (!ret) {
6300 /* Verify GUID matches */
6301 for (i = 0; i < 16; i++) {
6302 if (scao_guid[i] != log_ptr->log_page_guid[i]) {
6303 nvme_show_error("ERROR: WDC: Unknown GUID in C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C0 Log Page data"
)
;
6304 int j;
6305
6306 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6307 for (j = 0; j < 16; j++)
6308 nvme_show_error("%x", scao_guid[j])nvme_show_message(1, "%x", scao_guid[j]);
6309 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6310 for (j = 0; j < 16; j++)
6311 nvme_show_error("%x", log_ptr->log_page_guid[j])nvme_show_message(1, "%x", log_ptr->log_page_guid[j]);
6312 nvme_show_error("")nvme_show_message(1, "");
6313
6314 ret = -1;
6315 break;
6316 }
6317 }
6318
6319 if (!ret)
6320 /* parse the data */
6321 wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl);
6322 } else {
6323 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page data"
)
;
6324 ret = -1;
6325 }
6326
6327 free(log_ptr);
6328 return ret;
6329}
6330
6331static int nvme_get_print_c0_eol_log(struct libnvme_transport_handle *hdl,
6332 int uuid_index,
6333 __u32 namespace_id,
6334 int fmt)
6335{
6336 __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN0x200;
6337 struct libnvme_passthru_cmd cmd;
6338 void *log_ptr = NULL((void*)0);
6339 int ret;
6340
6341 log_ptr = (void *)malloc(sizeof(__u8) * length);
6342 if (!log_ptr) {
6343 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6344 return -1;
6345 }
6346
6347 if (namespace_id == NVME_NSID_ALL) {
6348 ret = libnvme_get_nsid(hdl, &namespace_id);
6349 if (ret < 0)
6350 namespace_id = NVME_NSID_ALL;
6351 }
6352
6353 /* Get the 0xC0 log data */
6354 nvme_init_get_log(&cmd, namespace_id,
6355 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, NVME_CSI_NVM,
6356 log_ptr, length);
6357 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6358 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6359 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6360 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6361 if (fmt == JSON)
6362 nvme_show_status(ret);
6363
6364 if (!ret) {
6365 /* parse the data */
6366 wdc_print_c0_eol_log(log_ptr, fmt);
6367 } else {
6368 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page data ")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page data "
)
;
6369 nvme_show_error("with uuid index %d", uuid_index)nvme_show_message(1, "with uuid index %d", uuid_index);
6370 ret = -1;
6371 }
6372
6373 free(log_ptr);
6374 return ret;
6375}
6376
6377static int nvme_get_ext_smart_cloud_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6378{
6379 struct libnvme_passthru_cmd cmd;
6380 __u8 *log_ptr = NULL((void*)0);
6381 int ret, i;
6382
6383 log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6384 if (!log_ptr) {
6385 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6386 return -1;
6387 }
6388
6389 /* Get the 0xC0 log data */
6390 nvme_init_get_log(&cmd, namespace_id,
6391 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6392 log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6393 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6394 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6395 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6396 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6397 if (!ret) {
6398 /* Verify GUID matches */
6399 for (i = 0; i < WDC_C0_GUID_LENGTH16; i++) {
6400 if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
6401 nvme_show_error("ERROR: WDC: Unknown GUID in C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C0 Log Page V1 data"
)
;
6402 int j;
6403
6404 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6405 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6406 nvme_show_error("%x", ext_smart_guid[j])nvme_show_message(1, "%x", ext_smart_guid[j]);
6407 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6408 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6409 nvme_show_error("%x", *&log_ptr[SCAO_V1_LPG + j])nvme_show_message(1, "%x", *&log_ptr[SCAO_V1_LPG + j]);
6410 nvme_show_error("")nvme_show_message(1, "");
6411
6412 ret = -1;
6413 break;
6414 }
6415 }
6416 }
6417
6418 *data = log_ptr;
6419
6420 return ret;
6421}
6422
6423
6424static int nvme_get_hw_rev_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6425{
6426 struct wdc_nvme_hw_rev_log *log_ptr = NULL((void*)0);
6427 struct libnvme_passthru_cmd cmd;
6428 int ret, i;
6429
6430 log_ptr = malloc(sizeof(*log_ptr));
6431 if (!log_ptr) {
6432 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6433 return -1;
6434 }
6435
6436 /* Get the 0xC0 log data */
6437 nvme_init_get_log(&cmd, namespace_id,
6438 WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6, NVME_CSI_NVM,
6439 log_ptr, sizeof(*log_ptr));
6440 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6441 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6442 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6443 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6444 if (!ret) {
6445 /* Verify GUID matches */
6446 for (i = 0; i < WDC_NVME_C6_GUID_LENGTH16; i++) {
6447 if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
6448 nvme_show_error("ERROR: WDC: Unknown GUID in HW Revision Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in HW Revision Log Page data"
)
;
6449 int j;
6450
6451 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6452 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6453 nvme_show_error("%x", hw_rev_log_guid[j])nvme_show_message(1, "%x", hw_rev_log_guid[j]);
6454 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6455 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6456 nvme_show_error("%x", log_ptr->hw_rev_guid[j])nvme_show_message(1, "%x", log_ptr->hw_rev_guid[j]);
6457 nvme_show_error("")nvme_show_message(1, "");
6458
6459 ret = -1;
6460 break;
6461 }
6462 }
6463 }
6464
6465 *data = (__u8 *)log_ptr;
6466
6467 return ret;
6468}
6469
6470
6471static void wdc_print_hw_rev_log_normal(void *data)
6472{
6473 int i;
6474 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6475
6476 printf(" Hardware Revision Log:-\n");
6477
6478 printf(" Global Device HW Revision : %d\n",
6479 log_data->hw_rev_gdr);
6480 printf(" ASIC HW Revision : %d\n",
6481 log_data->hw_rev_ar);
6482 printf(" PCB Manufacturer Code : %d\n",
6483 log_data->hw_rev_pbc_mc);
6484 printf(" DRAM Manufacturer Code : %d\n",
6485 log_data->hw_rev_dram_mc);
6486 printf(" NAND Manufacturer Code : %d\n",
6487 log_data->hw_rev_nand_mc);
6488 printf(" PMIC 1 Manufacturer Code : %d\n",
6489 log_data->hw_rev_pmic1_mc);
6490 printf(" PMIC 2 Manufacturer Code : %d\n",
6491 log_data->hw_rev_pmic2_mc);
6492 printf(" Other Component 1 Manf Code : %d\n",
6493 log_data->hw_rev_c1_mc);
6494 printf(" Other Component 2 Manf Code : %d\n",
6495 log_data->hw_rev_c2_mc);
6496 printf(" Other Component 3 Manf Code : %d\n",
6497 log_data->hw_rev_c3_mc);
6498 printf(" Other Component 4 Manf Code : %d\n",
6499 log_data->hw_rev_c4_mc);
6500 printf(" Other Component 5 Manf Code : %d\n",
6501 log_data->hw_rev_c5_mc);
6502 printf(" Other Component 6 Manf Code : %d\n",
6503 log_data->hw_rev_c6_mc);
6504 printf(" Other Component 7 Manf Code : %d\n",
6505 log_data->hw_rev_c7_mc);
6506 printf(" Other Component 8 Manf Code : %d\n",
6507 log_data->hw_rev_c8_mc);
6508 printf(" Other Component 9 Manf Code : %d\n",
6509 log_data->hw_rev_c9_mc);
6510
6511 printf(" Device Manf Detailed Info : 0x");
6512 for (i = 0; i < 16; i++) {
6513 printf("%02x", log_data->hw_rev_dev_mdi[i]);
6514 if (i == 7)
6515 printf(" 0x");
6516 }
6517 printf("\n");
6518 printf(" ASIC Detailed Info : 0x");
6519 for (i = 0; i < 16; i++) {
6520 printf("%02x", log_data->hw_rev_asic_di[i]);
6521 if (i == 7)
6522 printf(" 0x");
6523 }
6524 printf("\n");
6525 printf(" PCB Detailed Info : 0x");
6526 for (i = 0; i < 16; i++) {
6527 printf("%02x", log_data->hw_rev_pcb_di[i]);
6528 if (i == 7)
6529 printf(" 0x");
6530 }
6531 printf("\n");
6532 printf(" DRAM Detailed Info : 0x");
6533 for (i = 0; i < 16; i++) {
6534 printf("%02x", log_data->hw_rev_dram_di[i]);
6535 if (i == 7)
6536 printf(" 0x");
6537 }
6538 printf("\n");
6539 printf(" NAND Detailed Info : 0x");
6540 for (i = 0; i < 16; i++) {
6541 printf("%02x", log_data->hw_rev_nand_di[i]);
6542 if (i == 7)
6543 printf(" 0x");
6544 }
6545 printf("\n");
6546 printf(" PMIC 1 Detailed Info : 0x");
6547 for (i = 0; i < 16; i++) {
6548 printf("%02x", log_data->hw_rev_pmic1_di[i]);
6549 if (i == 7)
6550 printf(" 0x");
6551 }
6552 printf("\n");
6553 printf(" PMIC 2 Detailed Info : 0x");
6554 for (i = 0; i < 16; i++) {
6555 printf("%02x", log_data->hw_rev_pmic2_di[i]);
6556 if (i == 7)
6557 printf(" 0x");
6558 }
6559 printf("\n");
6560 printf(" Component 1 Detailed Info : 0x");
6561 for (i = 0; i < 16; i++) {
6562 printf("%02x", log_data->hw_rev_c1_di[i]);
6563 if (i == 7)
6564 printf(" 0x");
6565 }
6566 printf("\n");
6567 printf(" Component 2 Detailed Info : 0x");
6568 for (i = 0; i < 16; i++) {
6569 printf("%02x", log_data->hw_rev_c2_di[i]);
6570 if (i == 7)
6571 printf(" 0x");
6572 }
6573 printf("\n");
6574 printf(" Component 3 Detailed Info : 0x");
6575 for (i = 0; i < 16; i++) {
6576 printf("%02x", log_data->hw_rev_c3_di[i]);
6577 if (i == 7)
6578 printf(" 0x");
6579 }
6580 printf("\n");
6581 printf(" Component 4 Detailed Info : 0x");
6582 for (i = 0; i < 16; i++) {
6583 printf("%02x", log_data->hw_rev_c4_di[i]);
6584 if (i == 7)
6585 printf(" 0x");
6586 }
6587 printf("\n");
6588 printf(" Component 5 Detailed Info : 0x");
6589 for (i = 0; i < 16; i++) {
6590 printf("%02x", log_data->hw_rev_c5_di[i]);
6591 if (i == 7)
6592 printf(" 0x");
6593 }
6594 printf("\n");
6595 printf(" Component 6 Detailed Info : 0x");
6596 for (i = 0; i < 16; i++) {
6597 printf("%02x", log_data->hw_rev_c6_di[i]);
6598 if (i == 7)
6599 printf(" 0x");
6600 }
6601 printf("\n");
6602 printf(" Component 7 Detailed Info : 0x");
6603 for (i = 0; i < 16; i++) {
6604 printf("%02x", log_data->hw_rev_c7_di[i]);
6605 if (i == 7)
6606 printf(" 0x");
6607 }
6608 printf("\n");
6609 printf(" Component 8 Detailed Info : 0x");
6610 for (i = 0; i < 16; i++) {
6611 printf("%02x", log_data->hw_rev_c8_di[i]);
6612 if (i == 7)
6613 printf(" 0x");
6614 }
6615 printf("\n");
6616 printf(" Component 9 Detailed Info : 0x");
6617 for (i = 0; i < 16; i++) {
6618 printf("%02x", log_data->hw_rev_c9_di[i]);
6619 if (i == 7)
6620 printf(" 0x");
6621 }
6622 printf("\n");
6623 printf(" Serial Number : 0x");
6624 for (i = 0; i < 32; i++) {
6625 if ((i > 1) & !(i % 8))
6626 printf(" 0x");
6627 printf("%02x", log_data->hw_rev_sn[i]);
6628 }
6629 printf("\n");
6630
6631 printf(" Log Page Version : %d\n", log_data->hw_rev_version);
6632 printf(" Log page GUID : 0x");
6633 printf("%"PRIx64"l" "x""%"PRIx64"l" "x""\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6634 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6635 printf("\n");
6636}
6637
6638static void wdc_print_hw_rev_log_json(void *data)
6639{
6640 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6641 struct json_object *root = json_create_object()json_object_new_object();
6642 char json_data[80];
6643
6644 json_object_add_value_uint(root, "Global Device HW Revision",json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
6645 log_data->hw_rev_gdr)json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
;
6646 json_object_add_value_uint(root, "ASIC HW Revision",json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
6647 log_data->hw_rev_ar)json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
;
6648 json_object_add_value_uint(root, "PCB Manufacturer Code",json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
6649 log_data->hw_rev_pbc_mc)json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
;
6650 json_object_add_value_uint(root, "DRAM Manufacturer Code",json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
6651 log_data->hw_rev_dram_mc)json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
;
6652 json_object_add_value_uint(root, "NAND Manufacturer Code",json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
6653 log_data->hw_rev_nand_mc)json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
;
6654 json_object_add_value_uint(root, "PMIC 1 Manufacturer Code",json_object_object_add(root, "PMIC 1 Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pmic1_mc))
6655 log_data->hw_rev_pmic1_mc)json_object_object_add(root, "PMIC 1 Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pmic1_mc))
;
6656 json_object_add_value_uint(root, "PMIC 2 Manufacturer Code",json_object_object_add(root, "PMIC 2 Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pmic2_mc))
6657 log_data->hw_rev_pmic2_mc)json_object_object_add(root, "PMIC 2 Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pmic2_mc))
;
6658 json_object_add_value_uint(root, "Other Component 1 Manf Code",json_object_object_add(root, "Other Component 1 Manf Code", json_object_new_uint64
(log_data->hw_rev_c1_mc))
6659 log_data->hw_rev_c1_mc)json_object_object_add(root, "Other Component 1 Manf Code", json_object_new_uint64
(log_data->hw_rev_c1_mc))
;
6660 json_object_add_value_uint(root, "Other Component 2 Manf Code",json_object_object_add(root, "Other Component 2 Manf Code", json_object_new_uint64
(log_data->hw_rev_c2_mc))
6661 log_data->hw_rev_c2_mc)json_object_object_add(root, "Other Component 2 Manf Code", json_object_new_uint64
(log_data->hw_rev_c2_mc))
;
6662 json_object_add_value_uint(root, "Other Component 3 Manf Code",json_object_object_add(root, "Other Component 3 Manf Code", json_object_new_uint64
(log_data->hw_rev_c3_mc))
6663 log_data->hw_rev_c3_mc)json_object_object_add(root, "Other Component 3 Manf Code", json_object_new_uint64
(log_data->hw_rev_c3_mc))
;
6664 json_object_add_value_uint(root, "Other Component 4 Manf Code",json_object_object_add(root, "Other Component 4 Manf Code", json_object_new_uint64
(log_data->hw_rev_c4_mc))
6665 log_data->hw_rev_c4_mc)json_object_object_add(root, "Other Component 4 Manf Code", json_object_new_uint64
(log_data->hw_rev_c4_mc))
;
6666 json_object_add_value_uint(root, "Other Component 5 Manf Code",json_object_object_add(root, "Other Component 5 Manf Code", json_object_new_uint64
(log_data->hw_rev_c5_mc))
6667 log_data->hw_rev_c5_mc)json_object_object_add(root, "Other Component 5 Manf Code", json_object_new_uint64
(log_data->hw_rev_c5_mc))
;
6668 json_object_add_value_uint(root, "Other Component 6 Manf Code",json_object_object_add(root, "Other Component 6 Manf Code", json_object_new_uint64
(log_data->hw_rev_c6_mc))
6669 log_data->hw_rev_c6_mc)json_object_object_add(root, "Other Component 6 Manf Code", json_object_new_uint64
(log_data->hw_rev_c6_mc))
;
6670 json_object_add_value_uint(root, "Other Component 7 Manf Code",json_object_object_add(root, "Other Component 7 Manf Code", json_object_new_uint64
(log_data->hw_rev_c7_mc))
6671 log_data->hw_rev_c7_mc)json_object_object_add(root, "Other Component 7 Manf Code", json_object_new_uint64
(log_data->hw_rev_c7_mc))
;
6672 json_object_add_value_uint(root, "Other Component 8 Manf Code",json_object_object_add(root, "Other Component 8 Manf Code", json_object_new_uint64
(log_data->hw_rev_c8_mc))
6673 log_data->hw_rev_c8_mc)json_object_object_add(root, "Other Component 8 Manf Code", json_object_new_uint64
(log_data->hw_rev_c8_mc))
;
6674 json_object_add_value_uint(root, "Other Component 9 Manf Code",json_object_object_add(root, "Other Component 9 Manf Code", json_object_new_uint64
(log_data->hw_rev_c9_mc))
6675 log_data->hw_rev_c9_mc)json_object_object_add(root, "Other Component 9 Manf Code", json_object_new_uint64
(log_data->hw_rev_c9_mc))
;
6676
6677 memset((void *)json_data, 0, 40);
6678 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]),
6679 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
6680 json_object_add_value_string(root, "Device Manf Detailed Info", json_data);
6681
6682 memset((void *)json_data, 0, 40);
6683 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]),
6684 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
6685 json_object_add_value_string(root, "ASIC Detailed Info", json_data);
6686
6687 memset((void *)json_data, 0, 40);
6688 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]),
6689 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
6690 json_object_add_value_string(root, "PCB Detailed Info", json_data);
6691
6692 memset((void *)json_data, 0, 40);
6693 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]),
6694 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
6695 json_object_add_value_string(root, "DRAM Detailed Info", json_data);
6696
6697 memset((void *)json_data, 0, 40);
6698 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]),
6699 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
6700 json_object_add_value_string(root, "NAND Detailed Info", json_data);
6701
6702 memset((void *)json_data, 0, 40);
6703 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]),
6704 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
6705 json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
6706
6707 memset((void *)json_data, 0, 40);
6708 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
6709 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
6710 json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
6711
6712 memset((void *)json_data, 0, 40);
6713 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
6714 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
6715 json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
6716
6717 memset((void *)json_data, 0, 40);
6718 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
6719 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
6720 json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
6721
6722 memset((void *)json_data, 0, 40);
6723 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
6724 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
6725 json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
6726
6727 memset((void *)json_data, 0, 40);
6728 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
6729 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
6730 json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
6731
6732 memset((void *)json_data, 0, 40);
6733 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
6734 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
6735 json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
6736
6737 memset((void *)json_data, 0, 40);
6738 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
6739 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
6740 json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
6741
6742 memset((void *)json_data, 0, 40);
6743 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
6744 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
6745 json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
6746
6747 memset((void *)json_data, 0, 40);
6748 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
6749 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
6750 json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
6751
6752 memset((void *)json_data, 0, 40);
6753 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
6754 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
6755 json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
6756
6757 memset((void *)json_data, 0, 80);
6758 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""",
6759 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
6760 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
6761 json_object_add_value_string(root, "Serial Number", json_data);
6762
6763 json_object_add_value_uint(root, "Log Page Version",json_object_object_add(root, "Log Page Version", json_object_new_uint64
(le16_to_cpu(log_data->hw_rev_version)))
6764 le16_to_cpu(log_data->hw_rev_version))json_object_object_add(root, "Log Page Version", json_object_new_uint64
(le16_to_cpu(log_data->hw_rev_version)))
;
6765
6766 memset((void *)json_data, 0, 40);
6767 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6768 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6769 json_object_add_value_string(root, "Log Page GUID", json_data);
6770
6771 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6772 printf("\n");
6773 json_free_object(root)json_object_put(root);
6774}
6775
6776static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
6777{
6778 int i;
6779 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6780
6781 if (mask == WDC_SCA_V1_NAND_STATS0x1)
6782 printf(" NAND Statistics :-\n");
6783 else
6784 printf(" SMART Cloud Attributes :-\n");
6785
6786 printf(" Physical Media Units Written TLC (Bytes): %s\n",
6787 uint128_t_to_string(le128_to_cpu(
6788 ext_smart_log_ptr->ext_smart_pmuwt)));
6789 printf(" Physical Media Units Written SLC (Bytes): %s\n",
6790 uint128_t_to_string(le128_to_cpu(
6791 ext_smart_log_ptr->ext_smart_pmuws)));
6792 printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
6793 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
6794 printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6795 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
6796 printf(" XOR Recovery Count (Int) : %"PRIu64"l" "u""\n",
6797 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
6798 printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"l" "u""\n",
6799 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
6800 if (mask == WDC_SCA_V1_ALL0xF) {
6801 printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"l" "u""\n",
6802 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
6803 printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"l" "u""\n",
6804 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
6805 printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"l" "u""\n",
6806 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
6807 printf(" System Data %% life-used : %d %%\n",
6808 ext_smart_log_ptr->ext_smart_sdpu);
6809 }
6810 printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"l" "u""\n",
6811 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
6812 printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"l" "u""\n",
6813 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
6814 printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"l" "u""\n",
6815 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
6816 printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"l" "u""\n",
6817 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
6818 printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"l" "u""\n",
6819 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
6820 printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"l" "u""\n",
6821 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
6822 printf(" Program Fail Count (Normalized) (Int) : %d\n",
6823 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
6824 printf(" Program Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6825 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
6826 printf(" Erase Fail Count (Normalized) (Int) : %d\n",
6827 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
6828 printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6829 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
6830 if (mask == WDC_SCA_V1_ALL0xF) {
6831 printf(" PCIe Correctable Error Count (Int) : %"PRIu64"l" "u""\n",
6832 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
6833 printf(" %% Free Blocks (User) (Int) : %d %%\n",
6834 ext_smart_log_ptr->ext_smart_pfbu);
6835 printf(" Security Version Number (Int) : %"PRIu64"l" "u""\n",
6836 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
6837 printf(" %% Free Blocks (System) (Int) : %d %%\n",
6838 ext_smart_log_ptr->ext_smart_pfbs);
6839 printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n",
6840 uint128_t_to_string(le128_to_cpu(
6841 ext_smart_log_ptr->ext_smart_dcc)));
6842 printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"l" "u""\n",
6843 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
6844 printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
6845 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
6846 printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
6847 ext_smart_log_ptr->ext_smart_bbpg);
6848 }
6849 printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"l" "u""\n",
6850 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
6851 if (mask == WDC_SCA_V1_ALL0xF) {
6852 printf(" Total # of Read Refresh Count (Int) : %"PRIu64"l" "u""\n",
6853 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
6854 }
6855 printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
6856 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
6857 printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6858 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
6859 printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n",
6860 uint128_t_to_string(
6861 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)));
6862 if (mask == WDC_SCA_V1_ALL0xF) {
6863 printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
6864 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
6865 printf(" Total # Unaligned I/O (Int) : %"PRIu64"l" "u""\n",
6866 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
6867 }
6868 printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n",
6869 uint128_t_to_string(
6870 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)));
6871 if (mask == WDC_SCA_V1_ALL0xF) {
6872 printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6873 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
6874 printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6875 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
6876 printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6877 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
6878 printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"l" "u""\n",
6879 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
6880 printf(" Active Power State Change Count (Int) : %"PRIu64"l" "u""\n",
6881 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
6882 }
6883 printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
6884 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
6885 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
6886 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
6887 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
6888 printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
6889 0, 0, 0, 0);
6890 if (mask == WDC_SCA_V1_ALL0xF) {
6891 printf(" FTL Unit Size : %"PRIu32"u""\n",
6892 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
6893 printf(" TCG Ownership Status : %"PRIu32"u""\n",
6894 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
6895 printf(" Log Page Version (Int) : %d\n",
6896 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
6897 printf(" Log page GUID (Hex) : 0x");
6898 for (i = WDC_C0_GUID_LENGTH16; i > 0; i--)
6899 printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
6900 printf("\n");
6901 }
6902 printf("\n");
6903}
6904
6905static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
6906{
6907 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr =
6908 (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6909 struct json_object *root = json_create_object()json_object_new_object();
6910
6911 json_object_add_value_uint128(root, "physical_media_units_bytes_tlc",json_object_object_add(root, "physical_media_units_bytes_tlc"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmuwt)))
6912 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuwt))json_object_object_add(root, "physical_media_units_bytes_tlc"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmuwt)))
;
6913 json_object_add_value_uint128(root, "physical_media_units_bytes_slc",json_object_object_add(root, "physical_media_units_bytes_slc"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmuws)))
6914 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuws))json_object_object_add(root, "physical_media_units_bytes_slc"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmuws)))
;
6915 json_object_add_value_uint(root, "bad_user_blocks_normalized",json_object_object_add(root, "bad_user_blocks_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc
)))
6916 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc))json_object_object_add(root, "bad_user_blocks_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc
)))
;
6917 json_object_add_value_uint64(root, "bad_user_blocks_raw",json_object_object_add(root, "bad_user_blocks_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc
& 0xFFFFFFFFFFFF0000)))
6918 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000))json_object_object_add(root, "bad_user_blocks_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc
& 0xFFFFFFFFFFFF0000)))
;
6919 json_object_add_value_uint64(root, "xor_recovery_count",json_object_object_add(root, "xor_recovery_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc)))
6920 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc))json_object_object_add(root, "xor_recovery_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc)))
;
6921 json_object_add_value_uint64(root, "uncorrectable_read_errors",json_object_object_add(root, "uncorrectable_read_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_urec)))
6922 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec))json_object_object_add(root, "uncorrectable_read_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_urec)))
;
6923 if (mask == WDC_SCA_V1_ALL0xF) {
6924 json_object_add_value_uint64(root, "corrected_e2e_errors",json_object_object_add(root, "corrected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eece)))
6925 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece))json_object_object_add(root, "corrected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eece)))
;
6926 json_object_add_value_uint64(root, "detected_e2e_errors",json_object_object_add(root, "detected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eede)))
6927 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede))json_object_object_add(root, "detected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eede)))
;
6928 json_object_add_value_uint64(root, "uncorrected_e2e_errors",json_object_object_add(root, "uncorrected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue)))
6929 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue))json_object_object_add(root, "uncorrected_e2e_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue)))
;
6930 json_object_add_value_uint(root, "system_data_life_used_pct",json_object_object_add(root, "system_data_life_used_pct", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_sdpu))
6931 (__u8)ext_smart_log_ptr->ext_smart_sdpu)json_object_object_add(root, "system_data_life_used_pct", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_sdpu))
;
6932 }
6933 json_object_add_value_uint64(root, "min_slc_user_data_erase_count",json_object_object_add(root, "min_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec
)))
6934 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec))json_object_object_add(root, "min_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec
)))
;
6935 json_object_add_value_uint64(root, "min_tlc_user_data_erase_count",json_object_object_add(root, "min_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec
)))
6936 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec))json_object_object_add(root, "min_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec
)))
;
6937 json_object_add_value_uint64(root, "max_slc_user_data_erase_count",json_object_object_add(root, "max_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec
)))
6938 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec))json_object_object_add(root, "max_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec
)))
;
6939 json_object_add_value_uint64(root, "max_tlc_user_data_erase_count",json_object_object_add(root, "max_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec
)))
6940 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec))json_object_object_add(root, "max_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec
)))
;
6941 json_object_add_value_uint64(root, "avg_slc_user_data_erase_count",json_object_object_add(root, "avg_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_avec
)))
6942 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec))json_object_object_add(root, "avg_slc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_avec
)))
;
6943 json_object_add_value_uint64(root, "avg_tlc_user_data_erase_count",json_object_object_add(root, "avg_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec
)))
6944 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec))json_object_object_add(root, "avg_tlc_user_data_erase_count",
json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec
)))
;
6945 json_object_add_value_uint(root, "program_fail_count_normalized",json_object_object_add(root, "program_fail_count_normalized",
json_object_new_uint64(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr
->ext_smart_pfc)))
6946 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc))json_object_object_add(root, "program_fail_count_normalized",
json_object_new_uint64(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr
->ext_smart_pfc)))
;
6947 json_object_add_value_uint64(root, "program_fail_count_raw",json_object_object_add(root, "program_fail_count_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc
& 0xFFFFFFFFFFFF0000)))
6948 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000))json_object_object_add(root, "program_fail_count_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc
& 0xFFFFFFFFFFFF0000)))
;
6949 json_object_add_value_uint(root, "erase_fail_count_normalized",json_object_object_add(root, "erase_fail_count_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc
)))
6950 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc))json_object_object_add(root, "erase_fail_count_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc
)))
;
6951 json_object_add_value_uint64(root, "erase_fail_count_raw",json_object_object_add(root, "erase_fail_count_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc
& 0xFFFFFFFFFFFF0000)))
6952 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000))json_object_object_add(root, "erase_fail_count_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc
& 0xFFFFFFFFFFFF0000)))
;
6953 if (mask == WDC_SCA_V1_ALL0xF) {
6954 json_object_add_value_uint64(root, "pcie_correctable_errors",json_object_object_add(root, "pcie_correctable_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec)))
6955 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec))json_object_object_add(root, "pcie_correctable_errors", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec)))
;
6956 json_object_add_value_uint(root, "pct_free_blocks_user",json_object_object_add(root, "pct_free_blocks_user", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_pfbu))
6957 (__u8)ext_smart_log_ptr->ext_smart_pfbu)json_object_object_add(root, "pct_free_blocks_user", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_pfbu))
;
6958 json_object_add_value_uint64(root, "security_version",json_object_object_add(root, "security_version", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)))
6959 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn))json_object_object_add(root, "security_version", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)))
;
6960 json_object_add_value_uint(root, "pct_free_blocks_system",json_object_object_add(root, "pct_free_blocks_system", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_pfbs))
6961 (__u8)ext_smart_log_ptr->ext_smart_pfbs)json_object_object_add(root, "pct_free_blocks_system", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_pfbs))
;
6962 json_object_add_value_uint128(root, "num_of_trim_commands",json_object_object_add(root, "num_of_trim_commands", util_json_object_new_uint128
(le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc)))
6963 le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc))json_object_object_add(root, "num_of_trim_commands", util_json_object_new_uint128
(le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc)))
;
6964 json_object_add_value_uint64(root, "total_nuse_bytes",json_object_object_add(root, "total_nuse_bytes", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)))
6965 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu))json_object_object_add(root, "total_nuse_bytes", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)))
;
6966 json_object_add_value_uint(root, "num_of_format_commands",json_object_object_add(root, "num_of_format_commands", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc)))
6967 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc))json_object_object_add(root, "num_of_format_commands", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc)))
;
6968 json_object_add_value_uint(root, "background_pressure_gauge",json_object_object_add(root, "background_pressure_gauge", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_bbpg))
6969 (__u8)ext_smart_log_ptr->ext_smart_bbpg)json_object_object_add(root, "background_pressure_gauge", json_object_new_uint64
((__u8)ext_smart_log_ptr->ext_smart_bbpg))
;
6970 }
6971 json_object_add_value_uint64(root, "soft_ecc_error_count",json_object_object_add(root, "soft_ecc_error_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_seec)))
6972 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec))json_object_object_add(root, "soft_ecc_error_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_seec)))
;
6973 if (mask == WDC_SCA_V1_ALL0xF)
6974 json_object_add_value_uint64(root, "read_refresh_count",json_object_object_add(root, "read_refresh_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc)))
6975 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc))json_object_object_add(root, "read_refresh_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc)))
;
6976 json_object_add_value_uint(root, "bad_system_block_normalized",json_object_object_add(root, "bad_system_block_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc
)))
6977 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc))json_object_object_add(root, "bad_system_block_normalized", json_object_new_uint64
(le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc
)))
;
6978 json_object_add_value_uint64(root, "bad_system_block_raw",json_object_object_add(root, "bad_system_block_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc
& 0xFFFFFFFFFFFF0000)))
6979 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000))json_object_object_add(root, "bad_system_block_raw", json_object_new_uint64
(le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc
& 0xFFFFFFFFFFFF0000)))
;
6980 json_object_add_value_uint128(root, "endurance_est_bytes",json_object_object_add(root, "endurance_est_bytes", util_json_object_new_uint128
(le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)))
6981 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest))json_object_object_add(root, "endurance_est_bytes", util_json_object_new_uint128
(le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)))
;
6982 if (mask == WDC_SCA_V1_ALL0xF) {
6983 json_object_add_value_uint(root, "num_throttling_events",json_object_object_add(root, "num_throttling_events", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)))
6984 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc))json_object_object_add(root, "num_throttling_events", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)))
;
6985 json_object_add_value_uint64(root, "total_unaligned_io",json_object_object_add(root, "total_unaligned_io", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)))
6986 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio))json_object_object_add(root, "total_unaligned_io", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)))
;
6987 }
6988 json_object_add_value_uint128(root, "physical_media_units_read_bytes",json_object_object_add(root, "physical_media_units_read_bytes"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmur)))
6989 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur))json_object_object_add(root, "physical_media_units_read_bytes"
, util_json_object_new_uint128(le128_to_cpu(ext_smart_log_ptr
->ext_smart_pmur)))
;
6990 if (mask == WDC_SCA_V1_ALL0xF) {
6991 json_object_add_value_uint(root, "num_read_timeouts",json_object_object_add(root, "num_read_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)))
6992 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc))json_object_object_add(root, "num_read_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)))
;
6993 json_object_add_value_uint(root, "num_write_timeouts",json_object_object_add(root, "num_write_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc)))
6994 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc))json_object_object_add(root, "num_write_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc)))
;
6995 json_object_add_value_uint(root, "num_trim_timeouts",json_object_object_add(root, "num_trim_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc)))
6996 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc))json_object_object_add(root, "num_trim_timeouts", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc)))
;
6997 json_object_add_value_uint64(root, "pcie_link_retrain_count",json_object_object_add(root, "pcie_link_retrain_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc)))
6998 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc))json_object_object_add(root, "pcie_link_retrain_count", json_object_new_uint64
(le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc)))
;
6999 json_object_add_value_uint64(root, "active_power_state_change_count",json_object_object_add(root, "active_power_state_change_count"
, json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc
)))
7000 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc))json_object_object_add(root, "active_power_state_change_count"
, json_object_new_uint64(le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc
)))
;
7001 }
7002 char vers_str[40];
7003
7004 memset((void *)vers_str, 0, 40);
7005 sprintf((char *)vers_str, "%d.%d.%d.%d",
7006 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7007 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7008 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7009 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7010 json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
7011 memset((void *)vers_str, 0, 40);
7012 sprintf((char *)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0);
7013 json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
7014
7015 if (mask == WDC_SCA_V1_ALL0xF) {
7016 json_object_add_value_uint(root, "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus)))
7017 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus))json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus)))
;
7018 json_object_add_value_uint(root, "tcg_ownership_status",json_object_object_add(root, "tcg_ownership_status", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos)))
7019 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos))json_object_object_add(root, "tcg_ownership_status", json_object_new_uint64
(le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos)))
;
7020 json_object_add_value_uint(root, "log_page_ver",json_object_object_add(root, "log_page_ver", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv)))
7021 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv))json_object_object_add(root, "log_page_ver", json_object_new_uint64
(le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv)))
;
7022 char guid[40];
7023
7024 memset((void *)guid, 0, 40);
7025 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7026 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]),
7027 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0]));
7028 json_object_add_value_string(root, "log_page_guid", guid);
7029 }
7030
7031 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7032 printf("\n");
7033 json_free_object(root)json_object_put(root);
7034}
7035
7036static void wdc_print_eol_c0_normal(void *data)
7037{
7038 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7039 (struct wdc_nvme_c0_eol_log_page *)data;
7040
7041 printf(" End of Life Log Page 0xC0 :-\n");
7042 printf(" Realloc Block Count %"PRIu32"u""\n",
7043 le32_to_cpu(eol_log_page_ptr->eol_rbc));
7044 printf(" Write Amp %"PRIu32"u""\n",
7045 le32_to_cpu(eol_log_page_ptr->eol_wra));
7046 printf(" Percent Life Remaining %"PRIu32"u""\n",
7047 le32_to_cpu(eol_log_page_ptr->eol_plr));
7048 printf(" Program Fail Count %"PRIu32"u""\n",
7049 le32_to_cpu(eol_log_page_ptr->eol_pfc));
7050 printf(" Erase Fail Count %"PRIu32"u""\n",
7051 le32_to_cpu(eol_log_page_ptr->eol_efc));
7052 printf(" Raw Read Error Rate %"PRIu32"u""\n",
7053 le32_to_cpu(eol_log_page_ptr->eol_rrer));
7054}
7055
7056static void wdc_print_eol_c0_json(void *data)
7057{
7058 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7059 (struct wdc_nvme_c0_eol_log_page *)data;
7060 struct json_object *root = json_create_object()json_object_new_object();
7061
7062 json_object_add_value_uint(root, "Realloc Block Count",json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rbc)))
7063 le32_to_cpu(eol_log_page_ptr->eol_rbc))json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rbc)))
;
7064 json_object_add_value_uint(root, "Write Amp",json_object_object_add(root, "Write Amp", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_wra)))
7065 le32_to_cpu(eol_log_page_ptr->eol_wra))json_object_object_add(root, "Write Amp", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_wra)))
;
7066 json_object_add_value_uint(root, "Percent Life Remaining",json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_plr)))
7067 le32_to_cpu(eol_log_page_ptr->eol_plr))json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_plr)))
;
7068 json_object_add_value_uint(root, "Program Fail Count",json_object_object_add(root, "Program Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_pfc)))
7069 le32_to_cpu(eol_log_page_ptr->eol_pfc))json_object_object_add(root, "Program Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_pfc)))
;
7070 json_object_add_value_uint(root, "Erase Fail Count",json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_efc)))
7071 le32_to_cpu(eol_log_page_ptr->eol_efc))json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_efc)))
;
7072 json_object_add_value_uint(root, "Raw Read Error Rate",json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rrer)))
7073 le32_to_cpu(eol_log_page_ptr->eol_rrer))json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rrer)))
;
7074
7075 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7076 printf("\n");
7077 json_free_object(root)json_object_put(root);
7078}
7079
7080static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
7081{
7082 if (!data) {
7083 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 V1 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 V1 log"
)
;
7084 return -1;
7085 }
7086 switch (fmt) {
7087 case NORMAL:
7088 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL0xF);
7089 break;
7090 case JSON:
7091 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL0xF);
7092 break;
7093 }
7094 return 0;
7095}
7096
7097static int wdc_print_c0_cloud_attr_log(void *data,
7098 int fmt,
7099 struct libnvme_transport_handle *hdl)
7100{
7101 struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data;
7102
7103 if (!data) {
7104 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7105 return -1;
7106 }
7107
7108 switch (fmt) {
7109 case BINARY:
7110 d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log));
7111 break;
7112 case NORMAL:
7113 wdc_show_cloud_smart_log_normal(log, hdl);
7114 break;
7115 case JSON:
7116 wdc_show_cloud_smart_log_json(log);
7117 break;
7118 }
7119 return 0;
7120}
7121
7122static int wdc_print_c0_eol_log(void *data, int fmt)
7123{
7124 if (!data) {
7125 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7126 return -1;
7127 }
7128 switch (fmt) {
7129 case BINARY:
7130 d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN0x200);
7131 break;
7132 case NORMAL:
7133 wdc_print_eol_c0_normal(data);
7134 break;
7135 case JSON:
7136 wdc_print_eol_c0_json(data);
7137 break;
7138 }
7139 return 0;
7140}
7141
7142static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct libnvme_transport_handle *hdl, int uuid_index,
7143 char *format, __u32 namespace_id, int fmt)
7144{
7145 int ret;
7146
7147 if (!uuid_index) {
7148 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7149 uuid_index,
7150 namespace_id,
7151 fmt);
7152 } else if (uuid_index == 1) {
7153 ret = nvme_get_print_c0_eol_log(hdl,
7154 uuid_index,
7155 namespace_id,
7156 fmt);
7157 } else {
7158 nvme_show_error("ERROR: WDC: Unknown uuid index")nvme_show_message(1, "ERROR: WDC: Unknown uuid index");
7159 ret = -1;
7160 }
7161
7162 return ret;
7163}
7164
7165static int wdc_get_c0_log_page_sn(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, int uuid_index, char *format,
7166 __u32 namespace_id, int fmt)
7167{
7168 int ret = 0;
7169 __u32 cust_id;
7170
7171 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7172 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7173 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7174 return -1;
7175 }
7176
7177 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
7178 (cust_id == WDC_CUSTOMER_ID_0x10050x1005)) {
7179 ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format,
7180 namespace_id, fmt);
7181 } else {
7182 ret = nvme_get_print_c0_eol_log(hdl,
7183 0,
7184 namespace_id,
7185 fmt);
7186 }
7187
7188 return ret;
7189}
7190
7191static int wdc_get_c0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format, int uuid_index,
7192 __u32 namespace_id)
7193{
7194 uint32_t device_id, read_vendor_id;
7195 nvme_print_flags_t fmt;
7196 int ret;
7197 __u8 *data;
7198 void *dev_mng_log = NULL((void*)0);
7199 __u32 market_name_len = 0;
7200 char marketing_name[64];
7201
7202 memset(marketing_name, 0, 64);
7203
7204 if (!wdc_check_device(ctx, hdl))
7205 return -1;
7206 ret = validate_output_format(format, &fmt);
7207 if (ret < 0) {
7208 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7209 return ret;
7210 }
7211
7212 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7213
7214 switch (device_id) {
7215 case WDC_NVME_SN640_DEV_ID0x2400:
7216 case WDC_NVME_SN640_DEV_ID_10x2401:
7217 case WDC_NVME_SN640_DEV_ID_20x2402:
7218 case WDC_NVME_SN640_DEV_ID_30x2404:
7219 case WDC_NVME_SN840_DEV_ID0x2300:
7220 case WDC_NVME_SN840_DEV_ID_10x2500:
7221 case WDC_NVME_SN860_DEV_ID0x2730:
7222 case WDC_NVME_SN560_DEV_ID_10x2712:
7223 case WDC_NVME_SN560_DEV_ID_20x2713:
7224 case WDC_NVME_SN560_DEV_ID_30x2714:
7225 case WDC_NVME_SN550_DEV_ID0x2708:
7226 ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt);
7227 break;
7228 case WDC_NVME_SN650_DEV_ID0x2700:
7229 case WDC_NVME_SN650_DEV_ID_10x2701:
7230 case WDC_NVME_SN650_DEV_ID_20x2702:
7231 case WDC_NVME_SN650_DEV_ID_30x2720:
7232 case WDC_NVME_SN650_DEV_ID_40x2721:
7233 case WDC_NVME_SN655_DEV_ID0x2722:
7234 case WDC_NVME_SN655_DEV_ID_10x2723:
7235 case WDC_NVME_SNTMP_DEV_ID0x2761:
7236 case WDC_NVME_SNTMP_DEV_ID_10x2763:
7237 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
7238 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
7239 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
7240 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
7241 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
7242 if (uuid_index == 0) {
7243 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7244 uuid_index,
7245 namespace_id,
7246 fmt);
7247 } else {
7248 ret = nvme_get_print_c0_eol_log(hdl,
7249 uuid_index,
7250 namespace_id,
7251 fmt);
7252 }
7253 break;
7254 case WDC_NVME_ZN350_DEV_ID0x5010:
7255 case WDC_NVME_ZN350_DEV_ID_10x5018:
7256 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7257 0,
7258 NVME_NSID_ALL,
7259 fmt);
7260 break;
7261 case WDC_NVME_SN820CL_DEV_ID0x5037:
7262 /* Get the 0xC0 Extended Smart Cloud Attribute log data */
7263 data = NULL((void*)0);
7264 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
7265 uuid_index, namespace_id);
7266
7267 if (strcmp(format, "json"))
7268 nvme_show_status(ret);
7269
7270 if (!ret) {
7271 /* parse the data */
7272 wdc_print_ext_smart_cloud_log(data, fmt);
7273 } else {
7274 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page V1 data"
)
;
7275 ret = -1;
7276 }
7277
7278 free(data);
7279 break;
7280 default:
7281 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
7282 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
7283 ret = -1;
7284 goto out;
7285 }
7286
7287 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
7288 WDC_C2_MARKETING_NAME_ID0x07,
7289 (char *)marketing_name,
7290 &market_name_len)) {
7291 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
7292 ret = -1;
7293 goto out;
7294 }
7295
7296 if ((!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655", market_name_len)) ||
7297 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655", market_name_len)) ||
7298 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655", market_name_len)) ||
7299 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655", market_name_len))) {
7300 if (uuid_index == 0) {
7301 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7302 uuid_index,
7303 namespace_id,
7304 fmt);
7305 } else {
7306 ret = nvme_get_print_c0_eol_log(hdl,
7307 uuid_index,
7308 namespace_id,
7309 fmt);
7310 }
7311 } else {
7312 nvme_show_error("ERROR: WDC: Unknown device id: 0x%x or marketing name: %s",nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
7313 device_id, marketing_name)nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
;
7314 ret = -1;
7315 }
7316 break;
7317 }
7318
7319out:
7320 return ret;
7321}
7322
7323static int wdc_print_latency_monitor_log(struct libnvme_transport_handle *hdl,
7324 struct wdc_ssd_latency_monitor_log *log_data,
7325 int fmt)
7326{
7327 if (!log_data) {
7328 nvme_show_error("ERROR: WDC: Invalid C3 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C3 log data buffer"
)
;
7329 return -1;
7330 }
7331 switch (fmt) {
7332 case NORMAL:
7333 wdc_print_latency_monitor_log_normal(hdl, log_data);
7334 break;
7335 case JSON:
7336 wdc_print_latency_monitor_log_json(log_data);
7337 break;
7338 }
7339 return 0;
7340}
7341
7342static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
7343{
7344 if (!log_data) {
7345 nvme_show_error("ERROR: WDC: Invalid C1 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C1 log data buffer"
)
;
7346 return -1;
7347 }
7348 switch (fmt) {
7349 case NORMAL:
7350 wdc_print_error_rec_log_normal(log_data);
7351 break;
7352 case JSON:
7353 wdc_print_error_rec_log_json(log_data);
7354 break;
7355 }
7356 return 0;
7357}
7358
7359static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
7360{
7361 if (!log_data) {
7362 nvme_show_error("ERROR: WDC: Invalid C4 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C4 log data buffer"
)
;
7363 return -1;
7364 }
7365 switch (fmt) {
7366 case NORMAL:
7367 wdc_print_dev_cap_log_normal(log_data);
7368 break;
7369 case JSON:
7370 wdc_print_dev_cap_log_json(log_data);
7371 break;
7372 }
7373 return 0;
7374}
7375
7376static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
7377{
7378 if (!log_data) {
7379 nvme_show_error("ERROR: WDC: Invalid C5 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C5 log data buffer"
)
;
7380 return -1;
7381 }
7382 switch (fmt) {
7383 case NORMAL:
7384 wdc_print_unsupported_reqs_log_normal(log_data);
7385 break;
7386 case JSON:
7387 wdc_print_unsupported_reqs_log_json(log_data);
7388 break;
7389 }
7390 return 0;
7391}
7392
7393static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
7394{
7395 if (!perf) {
7396 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7397 return -1;
7398 }
7399 switch (fmt) {
7400 case NORMAL:
7401 wdc_print_fb_ca_log_normal(perf);
7402 break;
7403 case JSON:
7404 wdc_print_fb_ca_log_json(perf);
7405 break;
7406 }
7407 return 0;
7408}
7409
7410static int wdc_print_bd_ca_log(struct libnvme_transport_handle *hdl, void *bd_data, int fmt)
7411{
7412 if (!bd_data) {
7413 nvme_show_error("ERROR: WDC: Invalid buffer to read data")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read data"
)
;
7414 return -1;
7415 }
7416 switch (fmt) {
7417 case NORMAL:
7418 wdc_print_bd_ca_log_normal(hdl, bd_data);
7419 break;
7420 case JSON:
7421 wdc_print_bd_ca_log_json(bd_data);
7422 break;
7423 default:
7424 nvme_show_error("ERROR: WDC: Unknown format - %d", fmt)nvme_show_message(1, "ERROR: WDC: Unknown format - %d", fmt);
7425 return -1;
7426 }
7427 return 0;
7428}
7429
7430static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt)
7431{
7432 if (!perf) {
7433 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7434 return -1;
7435 }
7436 switch (fmt) {
7437 case NORMAL:
7438 wdc_print_d0_log_normal(perf);
7439 break;
7440 case JSON:
7441 wdc_print_d0_log_json(perf);
7442 break;
7443 }
7444 return 0;
7445}
7446
7447static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt,
7448 __u32 cust_id, __u32 vendor_id,
7449 __u32 device_id)
7450{
7451 if (!data) {
7452 nvme_show_error("ERROR: WDC: Invalid buffer to read fw activate history entries")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read fw activate history entries"
)
;
7453 return -1;
7454 }
7455
7456 switch (fmt) {
7457 case NORMAL:
7458 wdc_print_fw_act_history_log_normal(data, num_entries, cust_id,
7459 vendor_id, device_id);
7460 break;
7461 case JSON:
7462 wdc_print_fw_act_history_log_json(data, num_entries, cust_id,
7463 vendor_id, device_id);
7464 break;
7465 }
7466 return 0;
7467}
7468
7469static int wdc_get_ca_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7470{
7471 uint32_t read_device_id, read_vendor_id;
7472 struct wdc_ssd_ca_perf_stats *perf;
7473 nvme_print_flags_t fmt;
7474 __u32 cust_id;
7475 __u8 *data;
7476 int ret;
7477
7478 if (!wdc_check_device(ctx, hdl))
7479 return -1;
7480 ret = validate_output_format(format, &fmt);
7481 if (ret < 0) {
7482 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7483 return ret;
7484 }
7485
7486 /* verify the 0xCA log page is supported */
7487 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7488 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
7489 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
7490 return -1;
7491 }
7492
7493 /* get the FW customer id */
7494 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7495 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7496 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7497 return -1;
7498 }
7499
7500 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
Value stored to 'ret' is never read
7501
7502 switch (read_device_id) {
7503 case WDC_NVME_SN200_DEV_ID0x0023:
7504 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7505 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7506 if (!data) {
7507 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7508 return -1;
7509 }
7510
7511 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7512
7513 ret = nvme_get_log_simple(hdl,
7514 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7515 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7516 if (strcmp(format, "json"))
7517 nvme_show_status(ret);
7518
7519 if (!ret) {
7520 /* parse the data */
7521 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7522 ret = wdc_print_fb_ca_log(perf, fmt);
7523 } else {
7524 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7525 ret = -1;
7526 }
7527 } else {
7528
7529 nvme_show_error("ERROR: WDC: Unsupported Customer id, id = 0x%x", cust_id)nvme_show_message(1, "ERROR: WDC: Unsupported Customer id, id = 0x%x"
, cust_id)
;
7530 return -1;
7531 }
7532 break;
7533 case WDC_NVME_SN640_DEV_ID0x2400:
7534 case WDC_NVME_SN640_DEV_ID_10x2401:
7535 case WDC_NVME_SN640_DEV_ID_20x2402:
7536 case WDC_NVME_SN640_DEV_ID_30x2404:
7537 case WDC_NVME_SN840_DEV_ID0x2300:
7538 case WDC_NVME_SN840_DEV_ID_10x2500:
7539 case WDC_NVME_SN860_DEV_ID0x2730:
7540 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7541 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7542 if (!data) {
7543 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7544 return -1;
7545 }
7546
7547 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7548
7549 ret = nvme_get_log_simple(hdl,
7550 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7551 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7552 if (strcmp(format, "json"))
7553 nvme_show_status(ret);
7554
7555 if (!ret) {
7556 /* parse the data */
7557 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7558 ret = wdc_print_fb_ca_log(perf, fmt);
7559 } else {
7560 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7561 ret = -1;
7562 }
7563 } else if ((cust_id == WDC_CUSTOMER_ID_GN0x0001) || (cust_id == WDC_CUSTOMER_ID_GD0x0101) ||
7564 (cust_id == WDC_CUSTOMER_ID_BD0x1009)) {
7565 data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7566 if (!data) {
7567 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7568 return -1;
7569 }
7570
7571 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7572 ret = nvme_get_log_simple(hdl,
7573 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7574 data, WDC_BD_CA_LOG_BUF_LEN0xA0);
7575 if (strcmp(format, "json"))
7576 nvme_show_status(ret);
7577
7578 if (!ret) {
7579 /* parse the data */
7580 ret = wdc_print_bd_ca_log(hdl, data, fmt);
7581 } else {
7582 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7583 ret = -1;
7584 }
7585 } else {
7586 nvme_show_error("ERROR: WDC: Unsupported Customer id, id = 0x%x", cust_id)nvme_show_message(1, "ERROR: WDC: Unsupported Customer id, id = 0x%x"
, cust_id)
;
7587 return -1;
7588 }
7589 break;
7590 default:
7591 nvme_show_error("ERROR: WDC: Log page 0xCA not supported for this device")nvme_show_message(1, "ERROR: WDC: Log page 0xCA not supported for this device"
)
;
7592 return -1;
7593 }
7594
7595 free(data);
7596 return ret;
7597}
7598
7599static int wdc_get_c1_log_page(struct libnvme_global_ctx *ctx,
7600 struct libnvme_transport_handle *hdl, char *format,
7601 uint8_t interval)
7602{
7603 struct wdc_log_page_subpage_header *sph;
7604 struct wdc_ssd_perf_stats *perf;
7605 struct wdc_log_page_header *l;
7606 nvme_print_flags_t fmt;
7607 int total_subpages;
7608 int skip_cnt = 4;
7609 __u8 *data;
7610 __u8 *p;
7611 int i;
7612 int ret;
7613
7614 if (!wdc_check_device(ctx, hdl))
7615 return -1;
7616
7617 ret = validate_output_format(format, &fmt);
7618 if (ret < 0) {
7619 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7620 return ret;
7621 }
7622
7623 if (interval < 1 || interval > 15) {
7624 nvme_show_error("ERROR: WDC: interval out of range [1-15]")nvme_show_message(1, "ERROR: WDC: interval out of range [1-15]"
)
;
7625 return -1;
7626 }
7627
7628 data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7629 if (!data) {
7630 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7631 return -1;
7632 }
7633 memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7634
7635 ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE0xC1,
7636 data, WDC_ADD_LOG_BUF_LEN0x4000);
7637 if (strcmp(format, "json"))
7638 nvme_show_status(ret);
7639 if (!ret) {
7640 l = (struct wdc_log_page_header *)data;
7641 total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F - 1;
7642 for (i = 0, p = data + skip_cnt; i < total_subpages; i++, p += skip_cnt) {
7643 sph = (struct wdc_log_page_subpage_header *)p;
7644 if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37) {
7645 if (sph->pcset == interval) {
7646 perf = (struct wdc_ssd_perf_stats *)(p + 4);
7647 ret = wdc_print_log(perf, fmt);
7648 break;
7649 }
7650 }
7651 skip_cnt = le16_to_cpu(sph->subpage_length) + 4;
7652 }
7653 if (ret)
7654 nvme_show_error("ERROR: WDC: Unable to read data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read data from buffer"
)
;
7655 }
7656 free(data);
7657 return ret;
7658}
7659
7660static int wdc_get_c3_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7661{
7662 struct wdc_ssd_latency_monitor_log *log_data;
7663 nvme_print_flags_t fmt;
7664 __u8 *data;
7665 int ret;
7666 int i;
7667
7668 if (!wdc_check_device(ctx, hdl))
7669 return -1;
7670
7671 ret = validate_output_format(format, &fmt);
7672 if (ret < 0) {
7673 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7674 return ret;
7675 }
7676
7677 data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7678 if (!data) {
7679 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7680 return -1;
7681 }
7682 memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7683
7684 ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID0xC3,
7685 data, WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7686
7687 if (strcmp(format, "json"))
7688 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
7689
7690 if (!ret) {
7691 log_data = (struct wdc_ssd_latency_monitor_log *)data;
7692
7693 /* check log page version */
7694 if (log_data->log_page_version != WDC_LATENCY_MON_VERSION0x0001) {
7695 nvme_show_error("ERROR: WDC: invalid latency monitor version")nvme_show_message(1, "ERROR: WDC: invalid latency monitor version"
)
;
7696 ret = -1;
7697 goto out;
7698 }
7699
7700 /* check log page guid */
7701 /* Verify GUID matches */
7702 for (i = 0; i < 16; i++) {
7703 if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) {
7704 nvme_show_error("ERROR: WDC: Unknown GUID in C3 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C3 Log Page data"
)
;
7705 int j;
7706
7707 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7708 for (j = 0; j < 16; j++)
7709 nvme_show_error("%x", wdc_lat_mon_guid[j])nvme_show_message(1, "%x", wdc_lat_mon_guid[j]);
7710 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7711 for (j = 0; j < 16; j++)
7712 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7713 nvme_show_error("")nvme_show_message(1, "");
7714
7715 ret = -1;
7716 goto out;
7717 }
7718 }
7719
7720 /* parse the data */
7721 wdc_print_latency_monitor_log(hdl, log_data, fmt);
7722 } else {
7723 nvme_show_error("ERROR: WDC: Unable to read C3 data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read C3 data from buffer"
)
;
7724 }
7725
7726out:
7727 free(data);
7728 return ret;
7729
7730}
7731
7732static int wdc_get_ocp_c1_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7733{
7734 struct wdc_ocp_c1_error_recovery_log *log_data;
7735 nvme_print_flags_t fmt;
7736 __u8 *data;
7737 int ret;
7738 int i;
7739
7740 if (!wdc_check_device(ctx, hdl))
7741 return -1;
7742
7743 ret = validate_output_format(format, &fmt);
7744 if (ret < 0) {
7745 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7746 return ret;
7747 }
7748
7749 data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7750 if (!data) {
7751 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7752 return -1;
7753 }
7754 memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7755
7756 ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID0xC1,
7757 data, WDC_ERROR_REC_LOG_BUF_LEN512);
7758
7759 if (strcmp(format, "json"))
7760 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
7761
7762 if (!ret) {
7763 log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
7764
7765 /* check log page version */
7766 if ((log_data->log_page_version < 1) ||
7767 (log_data->log_page_version > 3)) {
7768 nvme_show_error("ERROR: WDC: invalid error recovery log version - %d",nvme_show_message(1, "ERROR: WDC: invalid error recovery log version - %d"
, log_data->log_page_version)
7769 log_data->log_page_version)nvme_show_message(1, "ERROR: WDC: invalid error recovery log version - %d"
, log_data->log_page_version)
;
7770 ret = -1;
7771 goto out;
7772 }
7773
7774 /* Verify GUID matches */
7775 for (i = 0; i < WDC_OCP_C1_GUID_LENGTH16; i++) {
7776 if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
7777 nvme_show_error("ERROR: WDC: Unknown GUID in C1 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C1 Log Page data"
)
;
7778 int j;
7779
7780 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7781 for (j = 0; j < 16; j++)
7782 nvme_show_error("%x", wdc_ocp_c1_guid[j])nvme_show_message(1, "%x", wdc_ocp_c1_guid[j]);
7783 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7784 for (j = 0; j < 16; j++)
7785 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7786 nvme_show_error("")nvme_show_message(1, "");
7787
7788 ret = -1;
7789 goto out;
7790 }
7791 }
7792
7793 /* parse the data */
7794 wdc_print_error_rec_log(log_data, fmt);
7795 } else {
7796 nvme_show_error("ERROR: WDC: Unable to read error recovery (C1) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read error recovery (C1) data from buffer"
)
;
7797 }
7798
7799out:
7800 free(data);
7801 return ret;
7802}
7803
7804static int wdc_get_ocp_c4_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7805{
7806 struct wdc_ocp_C4_dev_cap_log *log_data;
7807 nvme_print_flags_t fmt;
7808 __u8 *data;
7809 int ret;
7810 int i;
7811
7812 if (!wdc_check_device(ctx, hdl))
7813 return -1;
7814
7815 ret = validate_output_format(format, &fmt);
7816 if (ret < 0) {
7817 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7818 return ret;
7819 }
7820
7821 data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7822 if (!data) {
7823 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7824 return -1;
7825 }
7826 memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7827
7828 ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID0xC4,
7829 data, WDC_DEV_CAP_LOG_BUF_LEN4096);
7830
7831 if (strcmp(format, "json"))
7832 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
7833
7834 if (!ret) {
7835 log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
7836
7837 /* check log page version */
7838 if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION0001) {
7839 nvme_show_error("ERROR: WDC: invalid device capabilities log version - %d", log_data->log_page_version)nvme_show_message(1, "ERROR: WDC: invalid device capabilities log version - %d"
, log_data->log_page_version)
;
7840 ret = -1;
7841 goto out;
7842 }
7843
7844 /* Verify GUID matches */
7845 for (i = 0; i < WDC_OCP_C4_GUID_LENGTH16; i++) {
7846 if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
7847 nvme_show_error("ERROR: WDC: Unknown GUID in C4 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C4 Log Page data"
)
;
7848 int j;
7849
7850 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7851 for (j = 0; j < 16; j++)
7852 nvme_show_error("%x", wdc_ocp_c4_guid[j])nvme_show_message(1, "%x", wdc_ocp_c4_guid[j]);
7853 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7854 for (j = 0; j < 16; j++)
7855 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7856 nvme_show_error("")nvme_show_message(1, "");
7857
7858 ret = -1;
7859 goto out;
7860 }
7861 }
7862
7863 /* parse the data */
7864 wdc_print_dev_cap_log(log_data, fmt);
7865 } else {
7866 nvme_show_error("ERROR: WDC: Unable to read device capabilities (C4) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read device capabilities (C4) data from buffer"
)
;
7867 }
7868
7869out:
7870 free(data);
7871 return ret;
7872}
7873
7874static int wdc_get_ocp_c5_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7875{
7876 struct wdc_ocp_C5_unsupported_reqs *log_data;
7877 nvme_print_flags_t fmt;
7878 int ret;
7879 __u8 *data;
7880 int i;
7881
7882 if (!wdc_check_device(ctx, hdl))
7883 return -1;
7884
7885 ret = validate_output_format(format, &fmt);
7886 if (ret < 0) {
7887 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7888 return ret;
7889 }
7890
7891 data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7892 if (!data) {
7893 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7894 return -1;
7895 }
7896 memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7897
7898 ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID0xC5,
7899 data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7900
7901 if (strcmp(format, "json"))
7902 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
7903
7904 if (!ret) {
7905 log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
7906
7907 /* check log page version */
7908 if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION0001) {
7909 nvme_show_error("ERROR: WDC: invalid 0xC5 log page version")nvme_show_message(1, "ERROR: WDC: invalid 0xC5 log page version"
)
;
7910 nvme_show_error("ERROR: WDC: log page version: %d",nvme_show_message(1, "ERROR: WDC: log page version: %d", log_data
->log_page_version)
7911 log_data->log_page_version)nvme_show_message(1, "ERROR: WDC: log page version: %d", log_data
->log_page_version)
;
7912 ret = -1;
7913 goto out;
7914 }
7915
7916 /* Verify GUID matches */
7917 for (i = 0; i < WDC_OCP_C5_GUID_LENGTH16; i++) {
7918 if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
7919 nvme_show_error("ERROR: WDC: Unknown GUID in C5 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C5 Log Page data"
)
;
7920 int j;
7921
7922 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7923 for (j = 0; j < 16; j++)
7924 nvme_show_error("%x", wdc_ocp_c5_guid[j])nvme_show_message(1, "%x", wdc_ocp_c5_guid[j]);
7925 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7926 for (j = 0; j < 16; j++)
7927 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7928 nvme_show_error("")nvme_show_message(1, "");
7929
7930 ret = -1;
7931 goto out;
7932 }
7933 }
7934
7935 /* parse the data */
7936 wdc_print_unsupported_reqs_log(log_data, fmt);
7937 } else {
7938 nvme_show_error("ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer"
)
;
7939 }
7940
7941out:
7942 free(data);
7943 return ret;
7944}
7945
7946static int wdc_get_d0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7947{
7948 struct wdc_ssd_d0_smart_log *perf;
7949 nvme_print_flags_t fmt;
7950 int ret = 0;
7951 __u8 *data;
7952
7953 if (!wdc_check_device(ctx, hdl))
7954 return -1;
7955
7956 ret = validate_output_format(format, &fmt);
7957 if (ret < 0) {
7958 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7959 return ret;
7960 }
7961
7962 /* verify the 0xD0 log page is supported */
7963 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7964 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == false0) {
7965 nvme_show_error("ERROR: WDC: 0xD0 Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xD0 Log Page not supported"
)
;
7966 return -1;
7967 }
7968
7969 data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7970 if (!data) {
7971 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7972 return -1;
7973 }
7974 memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7975
7976 ret = nvme_get_log_simple(hdl,
7977 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0,
7978 data, WDC_NVME_VU_SMART_LOG_LEN0x200);
7979 if (strcmp(format, "json"))
7980 nvme_show_status(ret);
7981
7982 if (!ret) {
7983 /* parse the data */
7984 perf = (struct wdc_ssd_d0_smart_log *)(data);
7985 ret = wdc_print_d0_log(perf, fmt);
7986 } else {
7987 nvme_show_error("ERROR: WDC: Unable to read D0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read D0 Log Page data"
)
;
7988 ret = -1;
7989 }
7990
7991 free(data);
7992 return ret;
7993}
7994
7995static long double le_to_float(__u8 *data, int byte_len)
7996{
7997 long double result = 0;
7998 int i;
7999
8000 for (i = 0; i < byte_len; i++) {
8001 result *= 256;
8002 result += data[15 - i];
8003 }
8004
8005 return result;
8006}
8007
8008static void stringify_log_page_guid(__u8 *guid, char *buf)
8009{
8010 char *ptr = buf;
8011 int i;
8012
8013 memset(buf, 0, sizeof(char) * (2 * 16 + 1));
8014
8015 ptr += sprintf(ptr, "0x");
8016 for (i = 0; i < 16; i++)
8017 ptr += sprintf(ptr, "%x", guid[15 - i]);
8018}
8019
8020static const char *const cloud_smart_log_thermal_status[] = {
8021 [0x00] = "unthrottled",
8022 [0x01] = "first_level",
8023 [0x02] = "second_level",
8024 [0x03] = "third_level",
8025};
8026
8027static const char *stringify_cloud_smart_log_thermal_status(__u8 status)
8028{
8029 if (status < ARRAY_SIZE(cloud_smart_log_thermal_status)(sizeof(cloud_smart_log_thermal_status) / sizeof((cloud_smart_log_thermal_status
)[0]))
&&
8030 cloud_smart_log_thermal_status[status])
8031 return cloud_smart_log_thermal_status[status];
8032 return "unrecognized";
8033}
8034
8035static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log)
8036{
8037 struct json_object *root;
8038 struct json_object *bad_user_nand_blocks;
8039 struct json_object *bad_system_nand_blocks;
8040 struct json_object *e2e_correction_counts;
8041 struct json_object *user_data_erase_counts;
8042 struct json_object *thermal_status;
8043 struct json_object *dssd_specific_ver;
8044 char buf[2 * sizeof(log->log_page_guid) + 3];
8045 char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1];
8046 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8047
8048 bad_user_nand_blocks = json_create_object()json_object_new_object();
8049 json_object_add_value_uint(bad_user_nand_blocks, "normalized",json_object_object_add(bad_user_nand_blocks, "normalized", json_object_new_uint64
(le16_to_cpu(log->bad_user_nand_blocks.normalized)))
8050 le16_to_cpu(log->bad_user_nand_blocks.normalized))json_object_object_add(bad_user_nand_blocks, "normalized", json_object_new_uint64
(le16_to_cpu(log->bad_user_nand_blocks.normalized)))
;
8051 json_object_add_value_uint(bad_user_nand_blocks, "raw",json_object_object_add(bad_user_nand_blocks, "raw", json_object_new_uint64
(le64_to_cpu(log->bad_user_nand_blocks.raw)))
8052 le64_to_cpu(log->bad_user_nand_blocks.raw))json_object_object_add(bad_user_nand_blocks, "raw", json_object_new_uint64
(le64_to_cpu(log->bad_user_nand_blocks.raw)))
;
8053
8054 bad_system_nand_blocks = json_create_object()json_object_new_object();
8055 json_object_add_value_uint(bad_system_nand_blocks, "normalized",json_object_object_add(bad_system_nand_blocks, "normalized", json_object_new_uint64
(le16_to_cpu(log->bad_system_nand_blocks.normalized)))
8056 le16_to_cpu(log->bad_system_nand_blocks.normalized))json_object_object_add(bad_system_nand_blocks, "normalized", json_object_new_uint64
(le16_to_cpu(log->bad_system_nand_blocks.normalized)))
;
8057 json_object_add_value_uint(bad_system_nand_blocks, "raw",json_object_object_add(bad_system_nand_blocks, "raw", json_object_new_uint64
(le64_to_cpu(log->bad_system_nand_blocks.raw)))
8058 le64_to_cpu(log->bad_system_nand_blocks.raw))json_object_object_add(bad_system_nand_blocks, "raw", json_object_new_uint64
(le64_to_cpu(log->bad_system_nand_blocks.raw)))
;
8059
8060 e2e_correction_counts = json_create_object()json_object_new_object();
8061 json_object_add_value_uint(e2e_correction_counts, "corrected",json_object_object_add(e2e_correction_counts, "corrected", json_object_new_uint64
(le32_to_cpu(log->e2e_correction_counts.corrected)))
8062 le32_to_cpu(log->e2e_correction_counts.corrected))json_object_object_add(e2e_correction_counts, "corrected", json_object_new_uint64
(le32_to_cpu(log->e2e_correction_counts.corrected)))
;
8063 json_object_add_value_uint(e2e_correction_counts, "detected",json_object_object_add(e2e_correction_counts, "detected", json_object_new_uint64
(le32_to_cpu(log->e2e_correction_counts.detected)))
8064 le32_to_cpu(log->e2e_correction_counts.detected))json_object_object_add(e2e_correction_counts, "detected", json_object_new_uint64
(le32_to_cpu(log->e2e_correction_counts.detected)))
;
8065
8066 user_data_erase_counts = json_create_object()json_object_new_object();
8067 json_object_add_value_uint(user_data_erase_counts, "minimum",json_object_object_add(user_data_erase_counts, "minimum", json_object_new_uint64
(le32_to_cpu(log->user_data_erase_counts.minimum)))
8068 le32_to_cpu(log->user_data_erase_counts.minimum))json_object_object_add(user_data_erase_counts, "minimum", json_object_new_uint64
(le32_to_cpu(log->user_data_erase_counts.minimum)))
;
8069 json_object_add_value_uint(user_data_erase_counts, "maximum",json_object_object_add(user_data_erase_counts, "maximum", json_object_new_uint64
(le32_to_cpu(log->user_data_erase_counts.maximum)))
8070 le32_to_cpu(log->user_data_erase_counts.maximum))json_object_object_add(user_data_erase_counts, "maximum", json_object_new_uint64
(le32_to_cpu(log->user_data_erase_counts.maximum)))
;
8071
8072 thermal_status = json_create_object()json_object_new_object();
8073 json_object_add_value_string(thermal_status, "current_status",
8074 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8075 json_object_add_value_uint(thermal_status, "num_events",json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
8076 log->thermal_status.num_events)json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
;
8077
8078 dssd_specific_ver = json_create_object()json_object_new_object();
8079 json_object_add_value_uint(dssd_specific_ver, "major_ver",json_object_object_add(dssd_specific_ver, "major_ver", json_object_new_uint64
(log->dssd_specific_ver.major_ver))
8080 log->dssd_specific_ver.major_ver)json_object_object_add(dssd_specific_ver, "major_ver", json_object_new_uint64
(log->dssd_specific_ver.major_ver))
;
8081 json_object_add_value_uint(dssd_specific_ver, "minor_ver",json_object_object_add(dssd_specific_ver, "minor_ver", json_object_new_uint64
(le16_to_cpu(log->dssd_specific_ver.minor_ver)))
8082 le16_to_cpu(log->dssd_specific_ver.minor_ver))json_object_object_add(dssd_specific_ver, "minor_ver", json_object_new_uint64
(le16_to_cpu(log->dssd_specific_ver.minor_ver)))
;
8083 json_object_add_value_uint(dssd_specific_ver, "point_ver",json_object_object_add(dssd_specific_ver, "point_ver", json_object_new_uint64
(le16_to_cpu(log->dssd_specific_ver.point_ver)))
8084 le16_to_cpu(log->dssd_specific_ver.point_ver))json_object_object_add(dssd_specific_ver, "point_ver", json_object_new_uint64
(le16_to_cpu(log->dssd_specific_ver.point_ver)))
;
8085 json_object_add_value_uint(dssd_specific_ver, "errata_ver",json_object_object_add(dssd_specific_ver, "errata_ver", json_object_new_uint64
(log->dssd_specific_ver.errata_ver))
8086 log->dssd_specific_ver.errata_ver)json_object_object_add(dssd_specific_ver, "errata_ver", json_object_new_uint64
(log->dssd_specific_ver.errata_ver))
;
8087
8088 root = json_create_object()json_object_new_object();
8089 json_object_add_value_uint64(root, "physical_media_units_written",json_object_object_add(root, "physical_media_units_written", json_object_new_uint64
(le_to_float(log->physical_media_units_written, 16)))
8090 le_to_float(log->physical_media_units_written, 16))json_object_object_add(root, "physical_media_units_written", json_object_new_uint64
(le_to_float(log->physical_media_units_written, 16)))
;
8091 json_object_add_value_uint64(root, "physical_media_units_read",json_object_object_add(root, "physical_media_units_read", json_object_new_uint64
(le_to_float(log->physical_media_units_read, 16)))
8092 le_to_float(log->physical_media_units_read, 16))json_object_object_add(root, "physical_media_units_read", json_object_new_uint64
(le_to_float(log->physical_media_units_read, 16)))
;
8093 json_object_add_value_object(root, "bad_user_nand_blocks",json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
8094 bad_user_nand_blocks)json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
;
8095 json_object_add_value_object(root, "bad_system_nand_blocks",json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
8096 bad_system_nand_blocks)json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
;
8097 json_object_add_value_uint(root, "xor_recovery_count",json_object_object_add(root, "xor_recovery_count", json_object_new_uint64
(le64_to_cpu(log->xor_recovery_count)))
8098 le64_to_cpu(log->xor_recovery_count))json_object_object_add(root, "xor_recovery_count", json_object_new_uint64
(le64_to_cpu(log->xor_recovery_count)))
;
8099 json_object_add_value_uint(root, "uncorrectable_read_error_count",json_object_object_add(root, "uncorrectable_read_error_count"
, json_object_new_uint64(le64_to_cpu(log->uncorrectable_read_error_count
)))
8100 le64_to_cpu(log->uncorrectable_read_error_count))json_object_object_add(root, "uncorrectable_read_error_count"
, json_object_new_uint64(le64_to_cpu(log->uncorrectable_read_error_count
)))
;
8101 json_object_add_value_uint(root, "soft_ecc_error_count",json_object_object_add(root, "soft_ecc_error_count", json_object_new_uint64
(le64_to_cpu(log->soft_ecc_error_count)))
8102 le64_to_cpu(log->soft_ecc_error_count))json_object_object_add(root, "soft_ecc_error_count", json_object_new_uint64
(le64_to_cpu(log->soft_ecc_error_count)))
;
8103 json_object_add_value_object(root, "e2e_correction_counts",json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
8104 e2e_correction_counts)json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
;
8105 json_object_add_value_uint(root, "system_data_percent_used",json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
8106 log->system_data_percent_used)json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
;
8107 json_object_add_value_uint(root, "refresh_counts",json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
8108 le64_to_cpu(log->refresh_counts))json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
;
8109 json_object_add_value_object(root, "user_data_erase_counts",json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
8110 user_data_erase_counts)json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
;
8111 json_object_add_value_object(root, "thermal_status", thermal_status)json_object_object_add(root, "thermal_status", thermal_status
)
;
8112 if (smart_log_ver >= 3)
8113 json_object_add_value_object(root, "dssd_specific_ver",json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
8114 dssd_specific_ver)json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
;
8115 else
8116 json_free_object(dssd_specific_ver)json_object_put(dssd_specific_ver);
8117 json_object_add_value_uint(root, "pcie_correctable_error_count",json_object_object_add(root, "pcie_correctable_error_count", json_object_new_uint64
(le64_to_cpu(log->pcie_correctable_error_count)))
8118 le64_to_cpu(log->pcie_correctable_error_count))json_object_object_add(root, "pcie_correctable_error_count", json_object_new_uint64
(le64_to_cpu(log->pcie_correctable_error_count)))
;
8119 json_object_add_value_uint(root, "incomplete_shutdowns",json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
8120 le32_to_cpu(log->incomplete_shutdowns))json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
;
8121 json_object_add_value_uint(root, "percent_free_blocks",json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
8122 log->percent_free_blocks)json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
;
8123 json_object_add_value_uint(root, "capacitor_health",json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
8124 le16_to_cpu(log->capacitor_health))json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
;
8125 if (smart_log_ver >= 3) {
8126 if (smart_log_ver >= 4) {
8127 sprintf(buf, "%c", log->nvme_base_errata_ver);
8128 json_object_add_value_string(root, "nvme_base_errata_version", buf);
8129 sprintf(buf, "%c", log->nvme_cmd_set_errata_ver);
8130 json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf);
8131 } else {
8132 sprintf(buf, "%c", log->nvme_base_errata_ver);
8133 json_object_add_value_string(root, "nvme_errata_version", buf);
8134 }
8135 }
8136
8137 json_object_add_value_uint(root, "unaligned_io",json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
8138 le64_to_cpu(log->unaligned_io))json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
;
8139 json_object_add_value_uint(root, "security_version_number",json_object_object_add(root, "security_version_number", json_object_new_uint64
(le64_to_cpu(log->security_version_number)))
8140 le64_to_cpu(log->security_version_number))json_object_object_add(root, "security_version_number", json_object_new_uint64
(le64_to_cpu(log->security_version_number)))
;
8141 json_object_add_value_uint(root, "total_nuse",json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
8142 le64_to_cpu(log->total_nuse))json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
;
8143 json_object_add_value_uint64(root, "plp_start_count",json_object_object_add(root, "plp_start_count", json_object_new_uint64
(le_to_float(log->plp_start_count, 16)))
8144 le_to_float(log->plp_start_count, 16))json_object_object_add(root, "plp_start_count", json_object_new_uint64
(le_to_float(log->plp_start_count, 16)))
;
8145 json_object_add_value_uint64(root, "endurance_estimate",json_object_object_add(root, "endurance_estimate", json_object_new_uint64
(le_to_float(log->endurance_estimate, 16)))
8146 le_to_float(log->endurance_estimate, 16))json_object_object_add(root, "endurance_estimate", json_object_new_uint64
(le_to_float(log->endurance_estimate, 16)))
;
8147 if (smart_log_ver >= 3) {
8148 json_object_add_value_uint(root, "pcie_link_retraining_count",json_object_object_add(root, "pcie_link_retraining_count", json_object_new_uint64
(le64_to_cpu(log->pcie_link_retraining_cnt)))
8149 le64_to_cpu(log->pcie_link_retraining_cnt))json_object_object_add(root, "pcie_link_retraining_count", json_object_new_uint64
(le64_to_cpu(log->pcie_link_retraining_cnt)))
;
8150 json_object_add_value_uint(root, "power_state_change_count",json_object_object_add(root, "power_state_change_count", json_object_new_uint64
(le64_to_cpu(log->power_state_change_cnt)))
8151 le64_to_cpu(log->power_state_change_cnt))json_object_object_add(root, "power_state_change_count", json_object_new_uint64
(le64_to_cpu(log->power_state_change_cnt)))
;
8152 if (smart_log_ver >= 4) {
8153 snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s",
8154 (int)sizeof(log->lowest_permitted_fw_rev),
8155 log->lowest_permitted_fw_rev);
8156 json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr);
8157 } else
8158 json_object_add_value_uint128(root, "hardware_revision",json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]
)))
8159 le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]))json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]
)))
;
8160 }
8161 json_object_add_value_uint(root, "log_page_version",json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
8162 smart_log_ver)json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
;
8163 stringify_log_page_guid(log->log_page_guid, buf);
8164 json_object_add_value_string(root, "log_page_guid", buf);
8165
8166 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8167 printf("\n");
8168 json_free_object(root)json_object_put(root);
8169}
8170
8171static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
8172 struct libnvme_transport_handle *hdl)
8173{
8174 char buf[2 * sizeof(log->log_page_guid) + 3];
8175 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8176
8177 printf("SMART Cloud Attributes for NVMe device : %s\n",
8178 libnvme_transport_handle_get_name(hdl));
8179 printf("Physical Media Units Written : %'.0Lf\n",
8180 le_to_float(log->physical_media_units_written, 16));
8181 printf("Physical Media Units Read : %'.0Lf\n",
8182 le_to_float(log->physical_media_units_read, 16));
8183 printf("Bad User NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8184 le16_to_cpu(log->bad_user_nand_blocks.normalized));
8185 printf("Bad User NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8186 le64_to_cpu(log->bad_user_nand_blocks.raw));
8187 printf("Bad System NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8188 le16_to_cpu(log->bad_system_nand_blocks.normalized));
8189 printf("Bad System NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8190 le64_to_cpu(log->bad_system_nand_blocks.raw));
8191 printf("XOR Recovery Count : %" PRIu64"l" "u" "\n",
8192 le64_to_cpu(log->xor_recovery_count));
8193 printf("Uncorrectable Read Error Count : %" PRIu64"l" "u" "\n",
8194 le64_to_cpu(log->uncorrectable_read_error_count));
8195 printf("Soft ECC Error Count : %" PRIu64"l" "u" "\n",
8196 le64_to_cpu(log->soft_ecc_error_count));
8197 printf("End to End Correction Counts (Corrected) : %" PRIu32"u" "\n",
8198 le32_to_cpu(log->e2e_correction_counts.corrected));
8199 printf("End to End Correction Counts (Detected) : %" PRIu32"u" "\n",
8200 le32_to_cpu(log->e2e_correction_counts.detected));
8201 printf("System Data %% Used : %" PRIu8"hhu" "%%\n",
8202 log->system_data_percent_used);
8203 printf("Refresh Counts : %" PRIu64"l" "u" "\n",
8204 le64_to_cpu(log->refresh_counts));
8205 printf("User Data Erase Counts (Minimum) : %" PRIu32"u" "\n",
8206 le32_to_cpu(log->user_data_erase_counts.minimum));
8207 printf("User Data Erase Counts (Maximum) : %" PRIu32"u" "\n",
8208 le32_to_cpu(log->user_data_erase_counts.maximum));
8209 printf("Thermal Throttling Status (Current Status) : %s\n",
8210 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8211 printf("Thermal Throttling Status (Number of Events) : %" PRIu8"hhu" "\n",
8212 log->thermal_status.num_events);
8213 if (smart_log_ver >= 3) {
8214 printf("NVMe Major Version : %" PRIu8"hhu" "\n",
8215 log->dssd_specific_ver.major_ver);
8216 printf(" Minor Version : %" PRIu16"hu" "\n",
8217 le16_to_cpu(log->dssd_specific_ver.minor_ver));
8218 printf(" Point Version : %" PRIu16"hu" "\n",
8219 le16_to_cpu(log->dssd_specific_ver.point_ver));
8220 printf(" Errata Version : %" PRIu8"hhu" "\n",
8221 log->dssd_specific_ver.errata_ver);
8222 }
8223 printf("PCIe Correctable Error Count : %" PRIu64"l" "u" "\n",
8224 le64_to_cpu(log->pcie_correctable_error_count));
8225 printf("Incomplete Shutdowns : %" PRIu32"u" "\n",
8226 le32_to_cpu(log->incomplete_shutdowns));
8227 printf("%% Free Blocks : %" PRIu8"hhu" "%%\n",
8228 log->percent_free_blocks);
8229 printf("Capacitor Health : %" PRIu16"hu" "%%\n",
8230 le16_to_cpu(log->capacitor_health));
8231 if (smart_log_ver >= 3) {
8232 if (smart_log_ver >= 4) {
8233 printf("NVMe Base Errata Version : %c\n",
8234 log->nvme_base_errata_ver);
8235 printf("NVMe Command Set Errata Version : %c\n",
8236 log->nvme_cmd_set_errata_ver);
8237 } else {
8238 printf("NVMe Errata Version : %c\n",
8239 log->nvme_base_errata_ver);
8240 }
8241 }
8242 printf("Unaligned IO : %" PRIu64"l" "u" "\n",
8243 le64_to_cpu(log->unaligned_io));
8244 printf("Security Version Number : %" PRIu64"l" "u" "\n",
8245 le64_to_cpu(log->security_version_number));
8246 printf("Total NUSE : %" PRIu64"l" "u" "\n",
8247 le64_to_cpu(log->total_nuse));
8248 printf("PLP Start Count : %'.0Lf\n",
8249 le_to_float(log->plp_start_count, 16));
8250 printf("Endurance Estimate : %'.0Lf\n",
8251 le_to_float(log->endurance_estimate, 16));
8252 if (smart_log_ver >= 3) {
8253 printf("PCIe Link Retraining Count : %" PRIu64"l" "u" "\n",
8254 le64_to_cpu(log->pcie_link_retraining_cnt));
8255 printf("Power State Change Count : %" PRIu64"l" "u" "\n",
8256 le64_to_cpu(log->power_state_change_cnt));
8257 if (smart_log_ver >= 4)
8258 printf("Lowest Permitted FW Revision : %-.*s\n",
8259 (int)sizeof(log->lowest_permitted_fw_rev),
8260 log->lowest_permitted_fw_rev);
8261 else
8262 printf("Hardware Revision : %s\n",
8263 uint128_t_to_string(le128_to_cpu(
8264 (__u8 *)&log->lowest_permitted_fw_rev[0])));
8265 }
8266 printf("Log Page Version : %" PRIu16"hu" "\n",
8267 smart_log_ver);
8268 stringify_log_page_guid(log->log_page_guid, buf);
8269 printf("Log Page GUID : %s\n", buf);
8270 printf("\n\n");
8271}
8272
8273static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd,
8274 struct plugin *plugin)
8275{
8276 const char *desc = "Retrieve additional performance statistics.";
8277 const char *interval = "Interval to read the statistics from [1, 15].";
8278 const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
8279 const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
8280 const char *namespace_id = "desired namespace id";
8281 nvme_print_flags_t fmt;
8282 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8283 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8284 int ret = 0;
8285 int uuid_index = 0;
8286 int page_mask = 0, num, i;
8287 int log_page_list[16];
8288 __u64 capabilities = 0;
8289 __u32 device_id, read_vendor_id;
8290
8291 struct config {
8292 uint8_t interval;
8293 __u8 log_page_version;
8294 char *log_page_mask;
8295 __u32 namespace_id;
8296 };
8297
8298 struct config cfg = {
8299 .interval = 14,
8300 .log_page_version = 0,
8301 .log_page_mask = "",
8302 .namespace_id = NVME_NSID_ALL,
8303 };
8304
8305 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval
, 1, interval, 0, }, {"log-page-version", 'l', "NUM", CFG_BYTE
, &cfg.log_page_version, 1, log_page_version, 0, }, {"log-page-mask"
, 'p', "LIST", CFG_STRING, &cfg.log_page_mask, 1, log_page_mask
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8306 OPT_UINT("interval", 'i', &cfg.interval, interval),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval
, 1, interval, 0, }, {"log-page-version", 'l', "NUM", CFG_BYTE
, &cfg.log_page_version, 1, log_page_version, 0, }, {"log-page-mask"
, 'p', "LIST", CFG_STRING, &cfg.log_page_mask, 1, log_page_mask
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8307 OPT_BYTE("log-page-version", 'l', &cfg.log_page_version, log_page_version),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval
, 1, interval, 0, }, {"log-page-version", 'l', "NUM", CFG_BYTE
, &cfg.log_page_version, 1, log_page_version, 0, }, {"log-page-mask"
, 'p', "LIST", CFG_STRING, &cfg.log_page_mask, 1, log_page_mask
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8308 OPT_LIST("log-page-mask", 'p', &cfg.log_page_mask, log_page_mask),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval
, 1, interval, 0, }, {"log-page-version", 'l', "NUM", CFG_BYTE
, &cfg.log_page_version, 1, log_page_version, 0, }, {"log-page-mask"
, 'p', "LIST", CFG_STRING, &cfg.log_page_mask, 1, log_page_mask
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8309 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval
, 1, interval, 0, }, {"log-page-version", 'l', "NUM", CFG_BYTE
, &cfg.log_page_version, 1, log_page_version, 0, }, {"log-page-mask"
, 'p', "LIST", CFG_STRING, &cfg.log_page_mask, 1, log_page_mask
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8310
8311 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8312 if (ret)
8313 return ret;
8314
8315 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8316 if (ret)
8317 return ret;
8318
8319 if (!cfg.log_page_version) {
8320 uuid_index = 0;
8321 } else if (cfg.log_page_version == 1) {
8322 uuid_index = 1;
8323 } else {
8324 nvme_show_error("ERROR: WDC: unsupported log page version for this command")nvme_show_message(1, "ERROR: WDC: unsupported log page version for this command"
)
;
8325 ret = -1;
8326 goto out;
8327 }
8328
8329 num = shr_parse_csv_int(cfg.log_page_mask, log_page_list, 16);
8330
8331 if (num == -1) {
8332 nvme_show_error("ERROR: WDC: log page list is malformed")nvme_show_message(1, "ERROR: WDC: log page list is malformed"
)
;
8333 ret = -1;
8334 goto out;
8335 }
8336
8337 if (!num) {
8338 page_mask |= WDC_ALL_PAGE_MASK0xFFFF;
8339 } else {
8340 for (i = 0; i < num; i++) {
8341 if (log_page_list[i] == 0xc0)
8342 page_mask |= WDC_C0_PAGE_MASK0x0001;
8343 if (log_page_list[i] == 0xc1)
8344 page_mask |= WDC_C1_PAGE_MASK0x0002;
8345 if (log_page_list[i] == 0xca)
8346 page_mask |= WDC_CA_PAGE_MASK0x0004;
8347 if (log_page_list[i] == 0xd0)
8348 page_mask |= WDC_D0_PAGE_MASK0x0008;
8349 }
8350 }
8351
8352 if (!page_mask)
8353 nvme_show_error("ERROR: WDC: Unknown log page mask - %s", cfg.log_page_mask)nvme_show_message(1, "ERROR: WDC: Unknown log page mask - %s"
, cfg.log_page_mask)
;
8354
8355 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8356
8357 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8358 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8359 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8360 ret = -1;
8361 goto out;
8362 }
8363
8364 if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) == WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) &&
8365 (page_mask & WDC_C0_PAGE_MASK0x0001)) {
8366 /* Get 0xC0 log page if possible. */
8367 if (!wdc_is_sn861(device_id)) {
8368 ret = wdc_get_c0_log_page(ctx, hdl,
8369 nvme_args.output_format,
8370 uuid_index, cfg.namespace_id);
8371 if (ret)
8372 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8373 "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n",nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8374 ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
;
8375 } else {
8376 ret = validate_output_format(nvme_args.output_format,
8377 &fmt);
8378 if (ret < 0) {
8379 nvme_show_error("Invalid output format: %s",nvme_show_message(1, "Invalid output format: %s", nvme_args.output_format
)
8380 nvme_args.output_format)nvme_show_message(1, "Invalid output format: %s", nvme_args.output_format
)
;
8381 goto out;
8382 }
8383
8384 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
8385 0,
8386 NVME_NSID_ALL,
8387 fmt);
8388 }
8389 }
8390 if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) == (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) &&
8391 (page_mask & WDC_CA_PAGE_MASK0x0004) &&
8392 (!wdc_is_sn861(device_id))) {
8393 /* Get the CA Log Page */
8394 ret = wdc_get_ca_log_page(ctx, hdl, nvme_args.output_format);
8395 if (ret)
8396 nvme_show_error("ERROR: WDC: Failure reading the CA Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the CA Log Page, ret = %d"
, ret)
;
8397 }
8398 if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) == WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) &&
8399 (page_mask & WDC_C1_PAGE_MASK0x0002)) {
8400 /* Get the C1 Log Page */
8401 ret = wdc_get_c1_log_page(ctx, hdl, nvme_args.output_format,
8402 cfg.interval);
8403 if (ret)
8404 nvme_show_error("ERROR: WDC: Failure reading the C1 Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C1 Log Page, ret = %d"
, ret)
;
8405 }
8406 if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) == WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) &&
8407 (page_mask & WDC_D0_PAGE_MASK0x0008)) {
8408 /* Get the D0 Log Page */
8409 ret = wdc_get_d0_log_page(ctx, hdl, nvme_args.output_format);
8410 if (ret)
8411 nvme_show_error("ERROR: WDC: Failure reading the D0 Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the D0 Log Page, ret = %d"
, ret)
;
8412 }
8413
8414out:
8415 return ret;
8416}
8417
8418static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd,
8419 struct plugin *plugin)
8420{
8421 const char *desc = "Retrieve customer unique smart log statistics.";
8422 const char *uuid_index = "The uuid index to select the correct log page implementation.";
8423 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8424 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8425 struct libnvme_passthru_cmd cmd;
8426 int ret = 0;
8427 __u64 capabilities = 0;
8428 uint32_t read_device_id, read_vendor_id;
8429 nvme_print_flags_t fmt;
8430 __u8 *data;
8431
8432 struct config {
8433 int uuid_index;
8434 };
8435
8436 struct config cfg = {
8437 .uuid_index = 0,
8438 };
8439
8440 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"uuid-index", 'u', "NUM", CFG_POSITIVE, &cfg.uuid_index
, 1, uuid_index, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8441 OPT_UINT("uuid-index", 'u', &cfg.uuid_index, uuid_index))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"uuid-index", 'u', "NUM", CFG_POSITIVE, &cfg.uuid_index
, 1, uuid_index, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8442
8443 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8444 if (ret)
8445 return ret;
8446
8447 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8448 if (ret)
8449 return ret;
8450
8451 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8452 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8453 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8454 ret = -1;
8455 goto out;
8456 }
8457
8458 if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) == WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) {
8459 if (!wdc_check_device(ctx, hdl))
8460 return -1;
8461
8462 ret = validate_output_format(nvme_args.output_format, &fmt);
8463
8464 if (ret < 0) {
8465 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8466 return ret;
8467 }
8468
8469 /* verify the 0xCA log page is supported */
8470 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8471 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
8472 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
8473 return -1;
8474 }
8475
8476 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8477
8478 switch (read_device_id) {
8479 case WDC_NVME_SN861_DEV_ID0x2750:
8480 case WDC_NVME_SN861_DEV_ID_10x2751:
8481 data = (__u8 *)malloc(WDC_BD_CA_LOG_BUF_LEN0xA0);
8482 if (!data) {
8483 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8484 ret = -1;
8485 break;
8486 }
8487
8488 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
8489
8490 /* Get the CA Log Page */
8491 nvme_init_get_log(&cmd, NVME_NSID_ALL,
8492 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0,
8493 NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN0xA0);
8494 cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8495 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8496 NVME_LOG_CDW14_UUID_MASK)(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
8497 ret = libnvme_get_log(hdl, &cmd, false0,
8498 NVME_LOG_PAGE_PDU_SIZE4096);
8499
8500 if (strcmp(nvme_args.output_format, "json"))
8501 nvme_show_status(ret);
8502
8503 if (!ret) {
8504 /* parse the data */
8505 ret = wdc_print_bd_ca_log(hdl, data, fmt);
8506 } else {
8507 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
8508 ret = -1;
8509 }
8510
8511 free(data);
8512 break;
8513 default:
8514 nvme_show_error("ERROR: WDC: Command not supported on this device")nvme_show_message(1, "ERROR: WDC: Command not supported on this device"
)
;
8515 ret = -1;
8516 }
8517 } else {
8518 nvme_show_error("ERROR: WDC: CA log page supported on this device")nvme_show_message(1, "ERROR: WDC: CA log page supported on this device"
)
;
8519 ret = -1;
8520 }
8521
8522out:
8523 return ret;
8524}
8525
8526static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd,
8527 struct plugin *plugin)
8528{
8529 const char *desc = "Retrieve Cloud Log Smart/Health Information";
8530 const char *namespace_id = "desired namespace id";
8531 nvme_print_flags_t fmt;
8532 __u64 capabilities = 0;
8533 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8534 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8535 int ret;
8536 __u8 *data;
8537
8538 struct config {
8539 char *output_format;
8540 __u32 namespace_id;
8541 };
8542
8543 struct config cfg = {
8544 .output_format = "normal",
8545 .namespace_id = NVME_NSID_ALL,
8546 };
8547
8548 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8549 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8550
8551 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8552 if (ret)
8553 return ret;
8554
8555 cfg.output_format = nvme_args.output_format;
8556
8557 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8558 if (ret)
8559 return ret;
8560
8561 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8562
8563 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
8564 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8565 ret = -1;
8566 goto out;
8567 }
8568
8569 data = NULL((void*)0);
8570 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8571 cfg.namespace_id);
8572
8573 if (strcmp(cfg.output_format, "json"))
8574 nvme_show_status(ret);
8575
8576 if (!ret) {
8577 ret = validate_output_format(cfg.output_format, &fmt);
8578 if (ret < 0) {
8579 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8580 } else {
8581 /* parse the data */
8582 wdc_print_ext_smart_cloud_log(data, fmt);
8583 }
8584 } else {
8585 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page V1 data"
)
;
8586 ret = -1;
8587 }
8588
8589 free(data);
8590
8591out:
8592 return ret;
8593}
8594
8595static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd,
8596 struct plugin *plugin)
8597{
8598 const char *desc = "Retrieve Hardware Revision Log Information";
8599 const char *namespace_id = "desired namespace id";
8600 nvme_print_flags_t fmt;
8601 __u64 capabilities = 0;
8602 struct libnvme_transport_handle *hdl;
8603 int ret;
8604 __u8 *data = NULL((void*)0);
8605 struct libnvme_global_ctx *ctx;
8606
8607 struct config {
8608 char *output_format;
8609 __u32 namespace_id;
8610 };
8611
8612 struct config cfg = {
8613 .output_format = "normal",
8614 .namespace_id = NVME_NSID_ALL,
8615 };
8616
8617 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8618 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8619
8620 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8621 if (ret)
8622 return ret;
8623
8624 cfg.output_format = nvme_args.output_format;
8625
8626 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8627 if (ret)
8628 return ret;
8629
8630 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8631
8632 if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000)) {
8633 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8634 ret = -1;
8635 goto out;
8636 }
8637
8638 ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id);
8639
8640 if (strcmp(cfg.output_format, "json"))
8641 nvme_show_status(ret);
8642
8643 if (!ret) {
8644 ret = validate_output_format(cfg.output_format, &fmt);
8645 if (ret < 0) {
8646 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8647 goto free_buf;
8648 }
8649
8650 if (!data) {
8651 nvme_show_error("ERROR: WDC: Invalid buffer to read Hardware Revision log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read Hardware Revision log"
)
;
8652 ret = -1;
8653 goto out;
8654 }
8655 switch (fmt) {
8656 case NORMAL:
8657 wdc_print_hw_rev_log_normal(data);
8658 break;
8659 case JSON:
8660 wdc_print_hw_rev_log_json(data);
8661 break;
8662 default:
8663 break;
8664 }
8665 } else {
8666 nvme_show_error("ERROR: WDC: Unable to read Hardware Revision Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read Hardware Revision Log Page data"
)
;
8667 ret = -1;
8668 }
8669
8670free_buf:
8671 free(data);
8672
8673out:
8674 return ret;
8675}
8676
8677static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd,
8678 struct plugin *plugin)
8679{
8680 const char *desc = "Retrieve Device Write Amplication Factor";
8681 const char *namespace_id = "desired namespace id";
8682 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8683 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8684 struct nvme_smart_log smart_log;
8685 nvme_print_flags_t fmt;
8686 __u8 *data;
8687 int ret = 0;
8688 __u64 capabilities = 0;
8689 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr;
8690 long double data_units_written = 0,
8691 phys_media_units_written_tlc = 0,
8692 phys_media_units_written_slc = 0;
8693 struct json_object *root = NULL((void*)0);
8694 char tlc_waf_str[32] = { 0 },
8695 slc_waf_str[32] = { 0 };
8696
8697 struct config {
8698 char *output_format;
8699 __u32 namespace_id;
8700 };
8701
8702 struct config cfg = {
8703 .output_format = "normal",
8704 .namespace_id = NVME_NSID_ALL,
8705 };
8706
8707 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
8708 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8709
8710 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8711 if (ret)
8712 return ret;
8713
8714 cfg.output_format = nvme_args.output_format;
8715
8716 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8717 if (ret)
8718 return ret;
8719
8720 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8721
8722 if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000)) {
8723 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8724 ret = -1;
8725 goto out;
8726 }
8727
8728 /* get data units written from the smart log page */
8729 ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log);
8730 if (!ret) {
8731 data_units_written = int128_to_double(smart_log.data_units_written);
8732 } else if (ret > 0) {
8733 nvme_show_status(ret);
8734 ret = -1;
8735 goto out;
8736 } else {
8737 nvme_show_error("smart log: %s", libnvme_strerror(errno))nvme_show_message(1, "smart log: %s", libnvme_strerror((*__errno_location
())))
;
8738 ret = -1;
8739 goto out;
8740 }
8741
8742 /* get Physical Media Units Written from extended smart/C0 log page */
8743 data = NULL((void*)0);
8744 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8745 cfg.namespace_id);
8746
8747 if (!ret) {
8748 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
8749 phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
8750 phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
8751
8752 free(data);
8753 } else {
8754 nvme_show_error("ERROR: WDC %s: get smart cloud log failure", __func__)nvme_show_message(1, "ERROR: WDC %s: get smart cloud log failure"
, __func__)
;
8755 ret = -1;
8756 goto out;
8757 }
8758
8759 if (strcmp(cfg.output_format, "json"))
8760 nvme_show_status(ret);
8761
8762 ret = validate_output_format(cfg.output_format, &fmt);
8763 if (ret < 0) {
8764 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8765 goto out;
8766 }
8767
8768 if (!data_units_written) {
8769 nvme_show_error("ERROR: WDC %s: 0 data units written", __func__)nvme_show_message(1, "ERROR: WDC %s: 0 data units written", __func__
)
;
8770 ret = -1;
8771 goto out;
8772 }
8773
8774 if (fmt == NORMAL) {
8775 printf("Device Write Amplification Factor TLC : %4.2Lf\n",
8776 (phys_media_units_written_tlc/data_units_written));
8777 printf("Device Write Amplification Factor SLC : %4.2Lf\n",
8778 (phys_media_units_written_slc/data_units_written));
8779 } else if (fmt == JSON) {
8780 root = json_create_object()json_object_new_object();
8781 sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written));
8782 sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written));
8783
8784 json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
8785 json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
8786
8787 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8788 printf("\n");
8789
8790 json_free_object(root)json_object_put(root);
8791 }
8792
8793out:
8794 return ret;
8795}
8796
8797static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd,
8798 struct plugin *plugin)
8799{
8800 const char *desc = "Retrieve latency monitor log data.";
8801 __u64 capabilities = 0;
8802 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8803 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8804 int ret = 0;
8805
8806 struct config {
8807 char *output_format;
8808 };
8809
8810 struct config cfg = {
8811 .output_format = "normal",
8812 };
8813
8814 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8815
8816 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8817 if (ret)
8818 return ret;
8819
8820 cfg.output_format = nvme_args.output_format;
8821
8822 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8823 if (ret)
8824 return ret;
8825 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8826
8827 if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000)) {
8828 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8829 ret = -1;
8830 goto out;
8831 }
8832
8833 ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format);
8834 if (ret)
8835 nvme_show_error("ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d"
, ret)
;
8836
8837out:
8838 return ret;
8839}
8840
8841static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd,
8842 struct plugin *plugin)
8843{
8844 const char *desc = "Retrieve error recovery log data.";
8845 __u64 capabilities = 0;
8846 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8847 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8848 int ret = 0;
8849
8850 struct config {
8851 char *output_format;
8852 };
8853
8854 struct config cfg = {
8855 .output_format = "normal",
8856 };
8857
8858 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8859
8860 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8861 if (ret)
8862 return ret;
8863
8864 cfg.output_format = nvme_args.output_format;
8865
8866 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8867 if (ret)
8868 return ret;
8869
8870 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8871
8872 if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000)) {
8873 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8874 ret = -1;
8875 goto out;
8876 }
8877
8878 ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format);
8879 if (ret)
8880 nvme_show_error("ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x"
, ret)
;
8881
8882out:
8883 return ret;
8884}
8885
8886static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd,
8887 struct plugin *plugin)
8888{
8889 const char *desc = "Retrieve device capabilities log data.";
8890 __u64 capabilities = 0;
8891 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8892 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8893 int ret = 0;
8894
8895 struct config {
8896 char *output_format;
8897 };
8898
8899 struct config cfg = {
8900 .output_format = "normal",
8901 };
8902
8903 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8904
8905 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8906 if (ret)
8907 return ret;
8908
8909 cfg.output_format = nvme_args.output_format;
8910
8911 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8912 if (ret)
8913 return ret;
8914
8915 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8916
8917 if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000)) {
8918 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8919 ret = -1;
8920 goto out;
8921 }
8922
8923 ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format);
8924 if (ret)
8925 nvme_show_error("ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x"
, ret)
;
8926
8927out:
8928 return ret;
8929}
8930
8931static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd,
8932 struct plugin *plugin)
8933{
8934 const char *desc = "Retrieve unsupported requirements log data.";
8935 __u64 capabilities = 0;
8936 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8937 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8938 int ret = 0;
8939
8940 struct config {
8941 char *output_format;
8942 };
8943
8944 struct config cfg = {
8945 .output_format = "normal",
8946 };
8947
8948 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
8949
8950 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8951 if (ret)
8952 return ret;
8953
8954 cfg.output_format = nvme_args.output_format;
8955
8956 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8957 if (ret)
8958 return ret;
8959
8960 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8961
8962 if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000)) {
8963 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8964 ret = -1;
8965 goto out;
8966 }
8967
8968 ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format);
8969 if (ret)
8970 nvme_show_error("ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x"
, ret)
;
8971
8972out:
8973 return ret;
8974}
8975
8976static int wdc_do_clear_pcie_correctable_errors(struct libnvme_transport_handle *hdl)
8977{
8978 int ret;
8979 struct libnvme_passthru_cmd admin_cmd;
8980
8981 memset(&admin_cmd, 0, sizeof(admin_cmd));
8982 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6;
8983 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
8984 WDC_NVME_CLEAR_PCIE_CORR_CMD0x22);
8985
8986 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
8987 nvme_show_status(ret);
8988 return ret;
8989}
8990
8991static int wdc_do_clear_pcie_correctable_errors_vuc(struct libnvme_transport_handle *hdl)
8992{
8993 int ret;
8994 struct libnvme_passthru_cmd admin_cmd;
8995
8996 memset(&admin_cmd, 0, sizeof(admin_cmd));
8997 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2;
8998
8999 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9000 nvme_show_status(ret);
9001 return ret;
9002}
9003
9004static int wdc_do_clear_pcie_correctable_errors_fid(struct libnvme_transport_handle *hdl)
9005{
9006 int ret;
9007 __u64 result;
9008 __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
9009
9010 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3, false0,
9011 value, &result);
9012
9013 nvme_show_status(ret);
9014 return ret;
9015}
9016
9017static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
9018 struct plugin *plugin)
9019{
9020 const char *desc = "Clear PCIE Correctable Errors.";
9021 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9022 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9023 __u64 capabilities = 0;
9024 int ret;
9025
9026 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9027
9028 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9029 if (ret)
9030 return ret;
9031
9032 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9033 if (ret || !wdc_check_device(ctx, hdl))
9034 return -1;
9035
9036 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9037 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
)) {
9038 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9039 ret = -1;
9040 goto out;
9041 }
9042
9043 if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080)
9044 ret = wdc_do_clear_pcie_correctable_errors(hdl);
9045 else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000)
9046 ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl);
9047 else
9048 ret = wdc_do_clear_pcie_correctable_errors_fid(hdl);
9049
9050out:
9051 return ret;
9052}
9053
9054static int wdc_drive_status(int argc, char **argv, struct command *acmd,
9055 struct plugin *plugin)
9056{
9057 const char *desc = "Get Drive Status.";
9058 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9059 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9060 int ret = 0;
9061 int uuid_index;
9062 void *dev_mng_log = NULL((void*)0);
9063 __u32 system_eol_state;
9064 __u32 user_eol_state;
9065 __u32 format_corrupt_reason = 0xFFFFFFFF;
9066 __u32 eol_status;
9067 __u32 assert_status = 0xFFFFFFFF;
9068 __u32 thermal_status = 0xFFFFFFFF;
9069 __u64 capabilities = 0;
9070 struct nvme_id_uuid_list uuid_list;
9071
9072 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9073
9074 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9075 if (ret)
9076 return ret;
9077
9078 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9079 if (ret)
9080 return ret;
9081
9082 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9083
9084 if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) != WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) {
9085 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9086 ret = -1;
9087 goto out;
9088 }
9089
9090 uuid_index = 0;
9091
9092 /* Find the WDC UUID index */
9093 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
9094 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
9095 /* check for the Sandisk UUID first */
9096 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
9097
9098 if (uuid_index < 0)
9099 /* The Sandisk UUID is not found;
9100 * check for the WDC UUID second.
9101 */
9102 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
9103 }
9104
9105 /* WD UUID not found, use default uuid index - 0 */
9106 if (uuid_index < 0)
9107 uuid_index = 0;
9108
9109 /* verify the 0xC2 Device Manageability log page is supported */
9110 if (wdc_nvme_check_supported_log_page(ctx, hdl,
9111 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
9112 uuid_index) == false0) {
9113 nvme_show_error("ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d",nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
9114 uuid_index)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
;
9115 ret = -1;
9116 goto out;
9117 }
9118
9119 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
9120 nvme_show_error("ERROR: WDC: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not found");
9121 ret = -1;
9122 goto out;
9123 }
9124
9125 /* Get the assert dump present status */
9126 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &assert_status,
9127 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19))
9128 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9129
9130 /* Get the thermal throttling status */
9131 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &thermal_status,
9132 WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18))
9133 nvme_show_error("ERROR: WDC: Get Thermal Throttling Status Failed")nvme_show_message(1, "ERROR: WDC: Get Thermal Throttling Status Failed"
)
;
9134
9135 /* Get EOL status */
9136 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &eol_status,
9137 WDC_C2_USER_EOL_STATUS_ID0x1A)) {
9138 nvme_show_error("ERROR: WDC: Get User EOL Status Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL Status Failed"
)
;
9139 eol_status = cpu_to_le32(-1);
9140 }
9141
9142 /* Get Customer EOL state */
9143 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &user_eol_state,
9144 WDC_C2_USER_EOL_STATE_ID0x1C))
9145 nvme_show_error("ERROR: WDC: Get User EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL State Failed");
9146
9147 /* Get System EOL state*/
9148 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &system_eol_state,
9149 WDC_C2_SYSTEM_EOL_STATE_ID0x1D))
9150 nvme_show_error("ERROR: WDC: Get System EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get System EOL State Failed"
)
;
9151
9152 /* Get format corrupt reason*/
9153 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &format_corrupt_reason,
9154 WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E))
9155 nvme_show_error("ERROR: WDC: Get Format Corrupt Reason Failed")nvme_show_message(1, "ERROR: WDC: Get Format Corrupt Reason Failed"
)
;
9156
9157 printf(" Drive Status :-\n");
9158 if ((int)le32_to_cpu(eol_status) >= 0)
9159 printf(" Percent Used: %"PRIu32"u""%%\n",
9160 le32_to_cpu(eol_status));
9161 else
9162 printf(" Percent Used: Unknown\n");
9163 if (system_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) && user_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000))
9164 printf(" Drive Life Status: Normal\n");
9165 else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) ||
9166 user_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001))
9167 printf(" Drive Life Status: End Of Life\n");
9168 else if (system_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) ||
9169 user_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002))
9170 printf(" Drive Life Status: Read Only\n");
9171 else
9172 printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n",
9173 le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state));
9174
9175 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001))
9176 printf(" Assert Dump Status: Present\n");
9177 else if (assert_status == WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000))
9178 printf(" Assert Dump Status: Not Present\n");
9179 else
9180 printf(" Assert Dump Status: Unknown : 0x%08x\n", le32_to_cpu(assert_status));
9181
9182 if (thermal_status == WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000))
9183 printf(" Thermal Throttling Status: Off\n");
9184 else if (thermal_status == WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001))
9185 printf(" Thermal Throttling Status: On\n");
9186 else if (thermal_status == WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002))
9187 printf(" Thermal Throttling Status: Unavailable\n");
9188 else
9189 printf(" Thermal Throttling Status: Unknown : 0x%08x\n", le32_to_cpu(thermal_status));
9190
9191 if (format_corrupt_reason == WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000))
9192 printf(" Format Corrupt Reason: Format Not Corrupted\n");
9193 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001))
9194 printf(" Format Corrupt Reason: Format Corrupt due to FW Assert\n");
9195 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF))
9196 printf(" Format Corrupt Reason: Format Corrupt for Unknown Reason\n");
9197 else
9198 printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
9199
9200 free(dev_mng_log);
9201out:
9202 return ret;
9203}
9204
9205static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
9206 struct plugin *plugin)
9207{
9208 const char *desc = "Clear Assert Dump Present Status.";
9209 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9210 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9211 int ret = -1;
9212 __le32 assert_status = cpu_to_le32(0xFFFFFFFF);
9213 __u64 capabilities = 0;
9214 struct libnvme_passthru_cmd admin_cmd;
9215
9216 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9217
9218 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9219 if (ret)
9220 return ret;
9221
9222 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9223 if (ret)
9224 return ret;
9225
9226 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9227
9228 if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) != WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) {
9229 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9230 ret = -1;
9231 goto out;
9232 }
9233 if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status,
9234 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19)) {
9235 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9236 ret = -1;
9237 goto out;
9238 }
9239
9240 /* Get the assert dump present status */
9241 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001)) {
9242 memset(&admin_cmd, 0, sizeof(admin_cmd));
9243 admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8;
9244 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9245 WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03);
9246
9247 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9248 nvme_show_status(ret);
9249 } else
9250 nvme_show_error("INFO: WDC: No Assert Dump Present")nvme_show_message(1, "INFO: WDC: No Assert Dump Present");
9251
9252out:
9253 return ret;
9254}
9255
9256static int wdc_get_fw_act_history(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9257 char *format)
9258{
9259 struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
9260 nvme_print_flags_t fmt;
9261 int ret;
9262 __u8 *data;
9263
9264 if (!wdc_check_device(ctx, hdl))
9265 return -1;
9266
9267 ret = validate_output_format(format, &fmt);
9268 if (ret < 0) {
9269 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9270 return ret;
9271 }
9272
9273 /* verify the FW Activate History log page is supported */
9274 if (!wdc_nvme_check_supported_log_page(ctx, hdl,
9275 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) {
9276 nvme_show_error("ERROR: WDC: %d Log Page not supported",nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
9277 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
;
9278 return -1;
9279 }
9280
9281 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9282 if (!data) {
9283 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9284 return -1;
9285 }
9286
9287 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9288
9289 ret = nvme_get_log_simple(hdl,
9290 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB,
9291 data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9292
9293 if (strcmp(format, "json"))
9294 nvme_show_status(ret);
9295
9296 if (!ret) {
9297 /* parse the data */
9298 fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data);
9299
9300 if ((fw_act_history_hdr->num_entries > 0) &&
9301 (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES20)) {
9302 ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries,
9303 fmt, 0, 0, 0);
9304 } else if (!fw_act_history_hdr->num_entries) {
9305 nvme_show_error("INFO: WDC: No FW Activate History entries found.")nvme_show_message(1, "INFO: WDC: No FW Activate History entries found."
)
;
9306 ret = 0;
9307 } else {
9308 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
9309 "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n",nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
9310 fw_act_history_hdr->num_entries)nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
;
9311 ret = -1;
9312 }
9313 } else {
9314 nvme_show_error("ERROR: WDC: Unable to read FW Activate History Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read FW Activate History Log Page data"
)
;
9315 ret = -1;
9316 }
9317
9318 free(data);
9319 return ret;
9320}
9321
9322static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
9323{
9324
9325 __u32 cust_id = WDC_INVALID_CUSTOMER_ID-1;
9326 __u32 *cust_id_ptr = NULL((void*)0);
9327
9328 if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID0x15, (void *)&cust_id_ptr))
9329 nvme_show_error("%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found",nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
9330 __func__, WDC_C2_CUSTOMER_ID_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
;
9331 else
9332 cust_id = *cust_id_ptr;
9333
9334 free(cust_id_ptr);
9335 return cust_id;
9336}
9337
9338static int wdc_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9339 char *format)
9340{
9341 struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
9342 __u32 tot_entries = 0, num_entries = 0;
9343 __u32 vendor_id = 0, device_id = 0;
9344 __u32 cust_id = 0;
9345 nvme_print_flags_t fmt;
9346 __u8 *data;
9347 int ret;
9348 bool_Bool c2GuidMatch = false0;
9349
9350 if (!wdc_check_device(ctx, hdl))
9351 return -1;
9352
9353 ret = validate_output_format(format, &fmt);
9354 if (ret < 0) {
9355 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9356 return ret;
9357 }
9358
9359 ret = nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
9360
9361 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9362 if (!data) {
9363 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9364 return -1;
9365 }
9366
9367 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9368
9369 ret = nvme_get_log_simple(hdl,
9370 WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
9371 data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9372
9373 if (strcmp(format, "json"))
9374 nvme_show_status(ret);
9375
9376 if (!ret) {
9377 /* Get the log page data and verify the GUID */
9378 fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data);
9379
9380 c2GuidMatch = !memcmp(ocp_C2_guid,
9381 fw_act_history_log->log_page_guid,
9382 WDC_C2_GUID_LENGTH16);
9383
9384 if (c2GuidMatch) {
9385 /* parse the data */
9386 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
9387
9388 if (tot_entries > 0) {
9389 /* get the FW customer id */
9390 if (!wdc_is_sn861(device_id)) {
9391 cust_id = wdc_get_fw_cust_id(ctx, hdl);
9392 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
9393 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9394 "%s: ERROR: WDC: invalid customer id\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9395 __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
;
9396 ret = -1;
9397 goto freeData;
9398 }
9399 }
9400 num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES20) ?
9401 tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES20;
9402 ret = wdc_print_fw_act_history_log(data, num_entries,
9403 fmt, cust_id, vendor_id, device_id);
9404 } else {
9405 nvme_show_error("INFO: WDC: No entries found.")nvme_show_message(1, "INFO: WDC: No entries found.");
9406 ret = 0;
9407 }
9408 } else {
9409 nvme_show_error("ERROR: WDC: Invalid C2 log page GUID")nvme_show_message(1, "ERROR: WDC: Invalid C2 log page GUID");
9410 ret = -1;
9411 }
9412 } else {
9413 nvme_show_error("ERROR: WDC: Unable to read FW Activate History Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read FW Activate History Log Page data"
)
;
9414 ret = -1;
9415 }
9416
9417freeData:
9418 free(data);
9419 return ret;
9420}
9421
9422static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd,
9423 struct plugin *plugin)
9424{
9425 const char *desc = "Retrieve FW activate history table.";
9426 __u64 capabilities = 0;
9427 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9428 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9429 int ret = -1;
9430
9431 struct config {
9432 char *output_format;
9433 };
9434
9435 struct config cfg = {
9436 .output_format = "normal",
9437 };
9438
9439 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9440
9441 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9442 if (ret)
9443 return ret;
9444
9445 cfg.output_format = nvme_args.output_format;
9446
9447 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9448 if (ret)
9449 return ret;
9450
9451 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9452
9453 if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000))) {
9454 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9455 ret = -1;
9456 goto out;
9457 }
9458
9459 if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000) {
9460 __u32 cust_fw_id = 0;
9461 /* get the FW customer id */
9462 cust_fw_id = wdc_get_fw_cust_id(ctx, hdl);
9463 if (cust_fw_id == WDC_INVALID_CUSTOMER_ID-1) {
9464 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
9465 ret = -1;
9466 goto out;
9467 }
9468
9469 if ((cust_fw_id == WDC_CUSTOMER_ID_0x10040x1004) ||
9470 (cust_fw_id == WDC_CUSTOMER_ID_0x10080x1008) ||
9471 (cust_fw_id == WDC_CUSTOMER_ID_0x10050x1005) ||
9472 (cust_fw_id == WDC_CUSTOMER_ID_0x13040x1304))
9473 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9474 else
9475 ret = wdc_get_fw_act_history(ctx, hdl, cfg.output_format);
9476 } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
9477 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9478 }
9479
9480 if (ret)
9481 nvme_show_error("ERROR: WDC: Failure reading the FW Activate History, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the FW Activate History, ret = %d"
, ret)
;
9482out:
9483 return ret;
9484}
9485
9486static int wdc_do_clear_fw_activate_history_vuc(struct libnvme_transport_handle *hdl)
9487{
9488 int ret = -1;
9489 struct libnvme_passthru_cmd admin_cmd;
9490
9491 memset(&admin_cmd, 0, sizeof(admin_cmd));
9492 admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6;
9493 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9494 WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23);
9495
9496 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9497 nvme_show_status(ret);
9498
9499 return ret;
9500}
9501
9502static int wdc_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
9503{
9504 int ret = -1;
9505 __u64 result;
9506 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
9507
9508 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, false0,
9509 value, &result);
9510
9511 nvme_show_status(ret);
9512 return ret;
9513}
9514
9515static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd,
9516 struct plugin *plugin)
9517{
9518 const char *desc = "Clear FW activate history table.";
9519 __u64 capabilities = 0;
9520 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9521 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9522 int ret;
9523
9524 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9525
9526 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9527 if (ret)
9528 return ret;
9529
9530 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9531 if (ret)
9532 return ret;
9533
9534 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9535
9536 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000))) {
9537 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9538 ret = -1;
9539 goto out;
9540 }
9541
9542 if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000)
9543 ret = wdc_do_clear_fw_activate_history_vuc(hdl);
9544 else
9545 ret = wdc_do_clear_fw_activate_history_fid(hdl);
9546
9547out:
9548 return ret;
9549}
9550
9551static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd,
9552 struct plugin *plugin)
9553{
9554 const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
9555 const char *disable = "Disable controller option of the telemetry log page.";
9556 const char *enable = "Enable controller option of the telemetry log page.";
9557 const char *status = "Displays the current state of the controller initiated log page.";
9558 __u64 capabilities = 0;
9559 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9560 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9561 __u64 result;
9562 int ret = -1;
9563
9564
9565 struct config {
9566 bool_Bool disable;
9567 bool_Bool enable;
9568 bool_Bool status;
9569 };
9570
9571 struct config cfg = {
9572 .disable = false0,
9573 .enable = false0,
9574 .status = false0,
9575 };
9576
9577 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"disable", 'd', ((void*)0), CFG_FLAG, &cfg.disable
, 0, disable, 0, }, {"enable", 'e', ((void*)0), CFG_FLAG, &
cfg.enable, 0, enable, 0, }, {"status", 's', ((void*)0), CFG_FLAG
, &cfg.status, 0, status, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
9578 OPT_FLAG("disable", 'd', &cfg.disable, disable),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"disable", 'd', ((void*)0), CFG_FLAG, &cfg.disable
, 0, disable, 0, }, {"enable", 'e', ((void*)0), CFG_FLAG, &
cfg.enable, 0, enable, 0, }, {"status", 's', ((void*)0), CFG_FLAG
, &cfg.status, 0, status, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
9579 OPT_FLAG("enable", 'e', &cfg.enable, enable),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"disable", 'd', ((void*)0), CFG_FLAG, &cfg.disable
, 0, disable, 0, }, {"enable", 'e', ((void*)0), CFG_FLAG, &
cfg.enable, 0, enable, 0, }, {"status", 's', ((void*)0), CFG_FLAG
, &cfg.status, 0, status, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
9580 OPT_FLAG("status", 's', &cfg.status, status))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"disable", 'd', ((void*)0), CFG_FLAG, &cfg.disable
, 0, disable, 0, }, {"enable", 'e', ((void*)0), CFG_FLAG, &
cfg.enable, 0, enable, 0, }, {"status", 's', ((void*)0), CFG_FLAG
, &cfg.status, 0, status, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
9581
9582 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9583 if (ret)
9584 return ret;
9585
9586 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9587 if (ret)
9588 return ret;
9589
9590 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9591
9592 if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) {
9593 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9594 ret = -1;
9595 goto out;
9596 }
9597
9598 /* allow only one option at a time */
9599 if ((cfg.disable + cfg.enable + cfg.status) > 1) {
9600
9601 nvme_show_error("ERROR: WDC: Invalid option")nvme_show_message(1, "ERROR: WDC: Invalid option");
9602 ret = -1;
9603 goto out;
9604 }
9605
9606 if (cfg.disable) {
9607 ret = nvme_set_features_simple(hdl, 0,
9608 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9609 false0, 1, &result);
9610
9611 wdc_clear_reason_id(hdl);
9612 } else {
9613 if (cfg.enable) {
9614 ret = nvme_set_features_simple(hdl, 0,
9615 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9616 false0, 0, &result);
9617 } else if (cfg.status) {
9618 ret = nvme_get_features_simple(hdl,
9619 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9620 NVME_GET_FEATURES_SEL_CURRENT,
9621 &result);
9622 if (!ret) {
9623 if (result)
9624 nvme_show_error("Controller Option Telemetry Log Page State: Disabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Disabled"
)
;
9625 else
9626 nvme_show_error("Controller Option Telemetry Log Page State: Enabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Enabled"
)
;
9627 } else {
9628 nvme_show_status(ret);
9629 }
9630 } else {
9631 nvme_show_error("ERROR: WDC: unsupported option for this command")nvme_show_message(1, "ERROR: WDC: unsupported option for this command"
)
;
9632 nvme_show_error("Please provide an option, -d, -e or -s")nvme_show_message(1, "Please provide an option, -d, -e or -s"
)
;
9633 ret = -1;
9634 goto out;
9635 }
9636 }
9637
9638out:
9639 return ret;
9640}
9641
9642
9643static int wdc_get_serial_and_fw_rev(struct libnvme_transport_handle *hdl, char *sn, char *fw_rev)
9644{
9645 struct nvme_id_ctrl ctrl;
9646 int ret;
9647 int i;
9648
9649 i = sizeof(ctrl.sn) - 1;
9650 memset(sn, 0, WDC_SERIAL_NO_LEN20);
9651 memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN9);
9652 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9653 ret = nvme_identify_ctrl(hdl, &ctrl);
9654 if (ret) {
9655 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
9656 return -1;
9657 }
9658 /* Remove trailing spaces from the name */
9659 while (i && ctrl.sn[i] == ' ') {
9660 ctrl.sn[i] = '\0';
9661 i--;
9662 }
9663 snprintf(sn, WDC_SERIAL_NO_LEN20, "%s", ctrl.sn);
9664 snprintf(fw_rev, WDC_NVME_FIRMWARE_REV_LEN9, "%s", ctrl.fr);
9665
9666 return 0;
9667}
9668
9669static int wdc_get_max_transfer_len(struct libnvme_transport_handle *hdl, __u32 *maxTransferLen)
9670{
9671 struct nvme_id_ctrl ctrl;
9672 int ret = 0;
9673
9674 __u32 maxTransferLenDevice = 0;
9675
9676 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9677 ret = nvme_identify_ctrl(hdl, &ctrl);
9678 if (ret) {
9679 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
9680 return -1;
9681 }
9682
9683 maxTransferLenDevice = (1 << ctrl.mdts) * getpagesize();
9684 *maxTransferLen = maxTransferLenDevice;
9685
9686 return ret;
9687}
9688
9689static int wdc_de_VU_read_size(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize)
9690{
9691 int ret = WDC_STATUS_FAILURE-1;
9692 struct libnvme_passthru_cmd cmd;
9693
9694 if (!logSize) {
9695 ret = WDC_STATUS_INVALID_PARAMETER-3;
9696 goto end;
9697 }
9698
9699 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9700 cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE0xC0;
9701 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9702 cmd.cdw13 = fileId << 16;
9703 cmd.cdw14 = spiDestn;
9704
9705 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9706
9707 if (!ret && logSize)
9708 *logSize = cmd.result;
9709 if (ret != WDC_STATUS_SUCCESS0) {
9710 nvme_show_error("ERROR: WDC: VUReadSize() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadSize() failed, ");
9711 nvme_show_status(ret);
9712 }
9713
9714end:
9715 return ret;
9716}
9717
9718static int wdc_de_VU_read_buffer(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn,
9719 __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize)
9720{
9721 int ret = WDC_STATUS_FAILURE-1;
9722 struct libnvme_passthru_cmd cmd;
9723 __u32 noOfDwordExpected = 0;
9724
9725 if (!dataBuffer || !bufferSize) {
9726 ret = WDC_STATUS_INVALID_PARAMETER-3;
9727 goto end;
9728 }
9729
9730 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9731 noOfDwordExpected = *bufferSize / sizeof(__u32);
9732 cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE0xC2;
9733 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9734 cmd.cdw10 = noOfDwordExpected;
9735 cmd.cdw13 = fileId << 16;
9736 cmd.cdw14 = spiDestn;
9737 cmd.cdw15 = offsetInDwords;
9738
9739 cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
9740 cmd.data_len = *bufferSize;
9741
9742 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9743
9744 if (ret != WDC_STATUS_SUCCESS0) {
9745 nvme_show_error("ERROR: WDC: VUReadBuffer() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadBuffer() failed, ");
9746 nvme_show_status(ret);
9747 }
9748
9749end:
9750 return ret;
9751}
9752
9753static int wdc_get_log_dir_max_entries(struct libnvme_transport_handle *hdl, __u32 *maxNumOfEntries)
9754{
9755 int ret = WDC_STATUS_FAILURE-1;
9756 __u32 headerPayloadSize = 0;
9757 __u8 *fileIdOffsetsBuffer = NULL((void*)0);
9758 __u32 fileIdOffsetsBufferSize = 0;
9759 __u32 fileNum = 0;
9760 __u16 fileOffset = 0;
9761
9762
9763 if (!maxNumOfEntries) {
9764 ret = WDC_STATUS_INVALID_PARAMETER-3;
9765 return ret;
9766 }
9767 /* 1.Get log directory first four bytes */
9768 ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize);
9769 if (ret != WDC_STATUS_SUCCESS0) {
9770 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
9771 "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
9772 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
;
9773 return ret;
9774 }
9775
9776 fileIdOffsetsBufferSize =
9777 WDC_DE_FILE_HEADER_SIZE4 + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE2);
9778 fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize);
9779
9780 /* 2.Read to get file offsets */
9781 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize);
9782 if (ret != WDC_STATUS_SUCCESS0) {
9783 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
9784 "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
9785 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
;
9786 goto end;
9787 }
9788 /* 3.Determine valid entries */
9789 for (fileNum = 0;
9790 fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9791 fileNum++) {
9792 fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9793 (fileNum * WDC_DE_FILE_OFFSET_SIZE2)] << 8) +
9794 fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9795 (fileNum * WDC_DE_FILE_OFFSET_SIZE2) + 1];
9796 if (!fileOffset)
9797 continue;
9798 (*maxNumOfEntries)++;
9799 }
9800
9801end:
9802 free(fileIdOffsetsBuffer);
9803 return ret;
9804}
9805
9806static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[])
9807{
9808 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE;
9809
9810 if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME"core_dump"))
9811 essentialType = WDC_DE_TYPE_DUMPSNAPSHOT;
9812 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME"event_log"))
9813 essentialType = WDC_DE_TYPE_EVENTLOG;
9814 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info"))
9815 essentialType = WDC_DE_TYPE_NVME_MANF_INFO;
9816
9817 return essentialType;
9818}
9819
9820static int wdc_fetch_log_directory(struct libnvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory)
9821{
9822 int ret = WDC_STATUS_FAILURE-1;
9823 __u8 *fileOffset = NULL((void*)0);
9824 __u8 *fileDirectory = NULL((void*)0);
9825 __u32 headerSize = 0;
9826 __u32 fileNum = 0, startIdx = 0;
9827 __u16 fileOffsetTemp = 0;
9828 __u32 entryId = 0;
9829 __u32 fileDirectorySize = 0;
9830
9831 if (!directory) {
9832 ret = WDC_STATUS_INVALID_PARAMETER-3;
9833 goto end;
9834 }
9835
9836 ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize);
9837 if (ret != WDC_STATUS_SUCCESS0) {
9838 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
9839 "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
9840 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
;
9841 goto end;
9842 }
9843
9844 fileDirectory = (__u8 *)calloc(1, fileDirectorySize);
9845 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize);
9846 if (ret != WDC_STATUS_SUCCESS0) {
9847 nvme_show_error("ERROR: WDC: %s: Failed to get filesystem directory, ret = %d",nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
9848 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
;
9849 goto end;
9850 }
9851
9852 /* First four bytes of header directory is headerSize */
9853 memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE4);
9854
9855 /* minimum buffer for 1 entry is required */
9856 if (!directory->maxNumLogEntries) {
9857 ret = WDC_STATUS_INVALID_PARAMETER-3;
9858 goto end;
9859 }
9860
9861 for (fileNum = 0;
9862 fileNum < (headerSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9863 fileNum++) {
9864 if (entryId >= directory->maxNumLogEntries)
9865 break;
9866
9867 startIdx = WDC_DE_FILE_HEADER_SIZE4 + (fileNum * WDC_DE_FILE_OFFSET_SIZE2);
9868 memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp));
9869 fileOffset = fileDirectory + fileOffsetTemp;
9870
9871 if (!fileOffsetTemp)
9872 continue;
9873
9874 memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS));
9875 memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA));
9876 directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE32 - 1] = '\0';
9877 wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName,
9878 WDC_DE_FILE_NAME_SIZE32, ' ');
9879 if (!directory->logEntry[entryId].metaData.fileID)
9880 continue;
9881
9882 directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName);
9883 entryId++;
9884 }
9885
9886 directory->numOfValidLogEntries = entryId;
9887
9888end:
9889 free(fileDirectory);
9890 return ret;
9891}
9892
9893static int wdc_fetch_log_file_from_device(struct libnvme_transport_handle *hdl, __u32 fileId,
9894 __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
9895{
9896 int ret = WDC_STATUS_FAILURE-1;
9897 __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9898 __u32 maximumTransferLength = 0;
9899 __u32 buffSize = 0;
9900 __u64 offsetIdx = 0;
9901
9902 if (!dataBuffer || !fileSize) {
9903 ret = WDC_STATUS_INVALID_PARAMETER-3;
9904 goto end;
9905 }
9906
9907 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) {
9908 ret = WDC_STATUS_FAILURE-1;
9909 goto end;
9910 }
9911
9912 /* Fetch Log File Data */
9913 if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) {
9914 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9915 if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000)
9916 chunckSize = maximumTransferLength;
9917
9918 buffSize = chunckSize;
9919 for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) {
9920 if (((offsetIdx * chunckSize) + buffSize) > fileSize)
9921 buffSize = (__u32)(fileSize - (offsetIdx * chunckSize));
9922 /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */
9923 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9924 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize);
9925 if (ret != WDC_STATUS_SUCCESS0) {
9926 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
9927 __func__, ret, fileId, (unsigned long)fileSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
;
9928 break;
9929 }
9930 }
9931 } else {
9932 buffSize = (__u32)fileSize;
9933 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9934 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)),
9935 dataBuffer, &buffSize);
9936 if (ret != WDC_STATUS_SUCCESS0) {
9937 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
9938 __func__, ret, fileId, (unsigned long)fileSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
;
9939 }
9940 }
9941
9942end:
9943 return ret;
9944}
9945
9946static int wdc_de_get_dump_trace(struct libnvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen,
9947 const char *binFileName)
9948{
9949 int ret = WDC_STATUS_FAILURE-1;
9950 __u8 *readBuffer = NULL((void*)0);
9951 __u32 readBufferLen = 0;
9952 __u32 lastPktReadBufferLen = 0;
9953 __u32 maxTransferLen = 0;
9954 __u32 dumptraceSize = 0;
9955 __u32 chunkSize;
9956 __u32 chunks;
9957 __u32 offset;
9958 __u32 i;
9959 __u32 maximumTransferLength = 0;
9960
9961 if (!binFileName || !filePath) {
9962 ret = WDC_STATUS_INVALID_PARAMETER-3;
9963 return ret;
9964 }
9965
9966 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0)
9967 return WDC_STATUS_FAILURE-1;
9968
9969 do {
9970 /* Get dumptrace size */
9971 ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, &dumptraceSize);
9972 if (ret != WDC_STATUS_SUCCESS0) {
9973 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
9974 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
;
9975 break;
9976 }
9977
9978 /* Make sure the size requested is greater than dword */
9979 if (dumptraceSize < 4) {
9980 ret = WDC_STATUS_FAILURE-1;
9981 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x"
, __func__, dumptraceSize)
9982 __func__, dumptraceSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x"
, __func__, dumptraceSize)
;
9983 break;
9984 }
9985
9986 /* Choose the least max transfer length */
9987 maxTransferLen = maximumTransferLength < WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 ? maximumTransferLength : WDC_DE_READ_MAX_TRANSFER_SIZE0x8000;
9988
9989 /* Comment from FW Team:
9990 * The max non - block transfer size is 0xFFFF (16 bits allowed as the block size).Use 0x8000
9991 * to keep it on a word - boundary.
9992 * max_xfer = int(pow(2, id_data['MDTS'])) * 4096 # 4k page size as reported in pcie capabiltiies
9993 */
9994 chunkSize = dumptraceSize < maxTransferLen ? dumptraceSize : maxTransferLen;
9995 chunks = (dumptraceSize / maxTransferLen) + ((dumptraceSize % maxTransferLen) ? 1 : 0);
9996
9997 readBuffer = (unsigned char *)calloc(dumptraceSize, sizeof(unsigned char));
9998 readBufferLen = chunkSize;
9999 lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize;
10000
10001 if (!readBuffer) {
10002 nvme_show_error("ERROR: WDC: %s: readBuffer calloc failed", __func__)nvme_show_message(1, "ERROR: WDC: %s: readBuffer calloc failed"
, __func__)
;
10003 ret = WDC_STATUS_INSUFFICIENT_MEMORY-2;
10004 break;
10005 }
10006
10007 for (i = 0; i < chunks; i++) {
10008 offset = (i * chunkSize) / 4;
10009
10010 /* Last loop call, Assign readBufferLen to read only left over bytes */
10011 if (i == (chunks - 1))
10012 readBufferLen = lastPktReadBufferLen;
10013
10014 ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, 0,
10015 readBuffer + offset, &readBufferLen);
10016 if (ret != WDC_STATUS_SUCCESS0) {
10017 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
10018 "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
10019 __func__, ret, offset)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
;
10020 break;
10021 }
10022 }
10023 } while (0);
10024
10025 if (ret == WDC_STATUS_SUCCESS0) {
10026 ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
10027 if (ret != WDC_STATUS_SUCCESS0)
10028 nvme_show_error("ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d",nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
10029 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
;
10030 } else {
10031 nvme_show_error("ERROR: WDC: %s: Read Buffer Loop failed, ret = %d", __func__,nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
10032 ret)nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
;
10033 }
10034
10035 free(readBuffer);
10036
10037 return ret;
10038}
10039
10040int wdc_fetch_vu_file_directory(struct libnvme_transport_handle *hdl,
10041 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList,
10042 __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString)
10043{
10044 int ret = wdc_fetch_log_directory(hdl, &deEssentialsList);
10045 __u32 listIdx;
10046 char *dataBuffer;
10047 char fileName[MAX_PATH_LEN256];
10048
10049 if (ret != WDC_STATUS_SUCCESS0) {
10050 nvme_show_error("WDC: wdc_fetch_log_directory failed, ret = %d", ret)nvme_show_message(1, "WDC: wdc_fetch_log_directory failed, ret = %d"
, ret)
;
10051 return ret;
10052 }
10053
10054 /* Get Debug Data Files */
10055 for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) {
10056 if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) {
10057 nvme_show_error("ERROR: WDC: File Size for %s is 0",nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
10058 deEssentialsList.logEntry[listIdx].metaData.fileName)nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
;
10059 ret = WDC_STATUS_FILE_SIZE_ZERO-27;
10060 } else {
10061 /* Fetch Log File Data */
10062 dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10063 ret = wdc_fetch_log_file_from_device(hdl,
10064 deEssentialsList.logEntry[listIdx].metaData.fileID,
10065 WDC_DE_DESTN_SPI1,
10066 deEssentialsList.logEntry[listIdx].metaData.fileSize,
10067 (__u8 *)dataBuffer);
10068
10069 /* Write databuffer to file */
10070 if (ret == WDC_STATUS_SUCCESS0) {
10071 memset(fileName, 0, sizeof(fileName));
10072 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10073 deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString);
10074 if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) {
10075 wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF);
10076 wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF));
10077 } else {
10078 wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10079 }
10080 } else {
10081 nvme_show_error("ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d",nvme_show_message(1, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d"
, deEssentialsList.logEntry[listIdx].metaData.fileName, ret)
10082 deEssentialsList.logEntry[listIdx].metaData.fileName, ret)nvme_show_message(1, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d"
, deEssentialsList.logEntry[listIdx].metaData.fileName, ret)
;
10083 }
10084 free(dataBuffer);
10085 }
10086 }
10087
10088 return ret;
10089}
10090
10091int wdc_read_debug_directory(struct libnvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo,
10092 __u8 *timeString)
10093{
10094 __u32 maxNumOfVUFiles = 0;
10095 int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles);
10096 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
10097
10098 if (ret != WDC_STATUS_SUCCESS0) {
10099 nvme_show_error("WDC: wdc_get_log_dir_max_entries failed, ret = %d", ret)nvme_show_message(1, "WDC: wdc_get_log_dir_max_entries failed, ret = %d"
, ret)
;
10100 return ret;
10101 }
10102
10103 memset(&deEssentialsList, 0, sizeof(deEssentialsList));
10104 deEssentialsList.logEntry =
10105 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles);
10106 deEssentialsList.maxNumLogEntries = maxNumOfVUFiles;
10107
10108 ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo,
10109 timeString);
10110
10111 free(deEssentialsList.logEntry);
10112 deEssentialsList.logEntry = NULL((void*)0);
10113
10114 return ret;
10115}
10116
10117static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
10118 char *dir, char *key)
10119{
10120 int ret = 0;
10121 void *retPtr;
10122 char fileName[MAX_PATH_LEN256];
10123 __s8 bufferFolderPath[MAX_PATH_LEN256];
10124 char bufferFolderName[MAX_PATH_LEN256];
10125 char tarFileName[MAX_PATH_LEN256];
10126 char tarFiles[MAX_PATH_LEN256];
10127 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
10128 UtilsTimeInfo timeInfo;
10129 __u8 timeString[MAX_PATH_LEN256];
10130 __u8 serialNo[WDC_SERIAL_NO_LEN20];
10131 __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN9];
10132 __u8 idSerialNo[WDC_SERIAL_NO_LEN20];
10133 __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN9];
10134 __u8 featureIdBuff[4];
10135 char currDir[MAX_PATH_LEN256];
10136 char *dataBuffer = NULL((void*)0);
10137 __u32 elogNumEntries, elogBufferSize;
10138 __u32 dataBufferSize;
10139 __u32 listIdx = 0;
10140 __u32 vuLogIdx = 0;
10141 __u64 result;
10142 struct nvme_id_ctrl ctrl;
10143 struct nvme_id_ns ns;
10144 struct nvme_error_log_page *elogBuffer;
10145 struct nvme_smart_log smart_log;
10146 struct nvme_firmware_slot fw_log;
10147 struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL((void*)0);
10148
10149 memset(bufferFolderPath, 0, sizeof(bufferFolderPath));
10150 memset(bufferFolderName, 0, sizeof(bufferFolderName));
10151 memset(tarFileName, 0, sizeof(tarFileName));
10152 memset(tarFiles, 0, sizeof(tarFiles));
10153 memset(tarCmd, 0, sizeof(tarCmd));
10154 memset(&timeInfo, 0, sizeof(timeInfo));
10155
10156 if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) {
10157 nvme_show_error("ERROR: WDC: get serial # and fw revision failed")nvme_show_message(1, "ERROR: WDC: get serial # and fw revision failed"
)
;
10158 return -1;
10159 }
10160
10161 nvme_show_error("Get Drive Essentials Data for device serial #: %s and fw revision: %s",nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
10162 idSerialNo, idFwRev)nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
;
10163
10164 /* Create Drive Essentials directory */
10165 wdc_UtilsGetTime(&timeInfo);
10166 memset(timeString, 0, sizeof(timeString));
10167 wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10168 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10169 timeInfo.hour, timeInfo.minute, timeInfo.second);
10170
10171 wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN20, (char *)idSerialNo);
10172 /* Remove any space form serialNo */
10173 wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN20, ' ');
10174
10175 memset(firmwareRevision, 0, sizeof(firmwareRevision));
10176 wdc_UtilsSnprintf((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, (char *)idFwRev);
10177 /* Remove any space form FirmwareRevision */
10178 wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, ' ');
10179
10180 wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN256, "%s_%s_%s_%s",
10181 "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString);
10182
10183 if (dir) {
10184 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10185 (char *)dir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10186 } else {
10187 retPtr = getcwd((char *)currDir, MAX_PATH_LEN256);
10188 if (retPtr) {
10189 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10190 (char *)currDir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10191 } else {
10192 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
10193 return -1;
10194 }
10195 }
10196
10197 ret = wdc_UtilsCreateDir((char *)bufferFolderPath);
10198 if (ret) {
10199 nvme_show_error("ERROR: WDC: create directory failed, ret = %d, dir = %s", ret, bufferFolderPath)nvme_show_message(1, "ERROR: WDC: create directory failed, ret = %d, dir = %s"
, ret, bufferFolderPath)
;
10200 return -1;
10201 }
10202
10203 nvme_show_error("Store Drive Essentials bin files in directory: %s", bufferFolderPath)nvme_show_message(1, "Store Drive Essentials bin files in directory: %s"
, bufferFolderPath)
;
10204
10205 /* Get Identify Controller Data */
10206 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10207 ret = nvme_identify_ctrl(hdl, &ctrl);
10208 if (ret) {
10209 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed, ret = %d"
, ret)
;
10210 return -1;
10211 }
10212
10213 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath,
10214 WDC_DE_PATH_SEPARATOR"/", "IdentifyController", (char *)serialNo,
10215 (char *)timeString);
10216 wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl));
10217
10218 memset(&ns, 0, sizeof(struct nvme_id_ns));
10219 ret = nvme_identify_ns(hdl, 1, &ns);
10220 if (ret) {
10221 nvme_show_error("ERROR: WDC: nvme_identify_ns() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ns() failed, ret = %d"
, ret)
;
10222 } else {
10223 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10224 "IdentifyNamespace", (char *)serialNo, (char *)timeString);
10225 wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns));
10226 }
10227
10228 /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */
10229 elogNumEntries = WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64;
10230 elogBufferSize = elogNumEntries*sizeof(struct nvme_error_log_page);
10231 dataBuffer = calloc(1, elogBufferSize);
10232 elogBuffer = (struct nvme_error_log_page *)dataBuffer;
10233
10234 ret = nvme_get_log_error(hdl, NVME_NSID_ALL, elogNumEntries, elogBuffer);
10235 if (ret) {
10236 nvme_show_error("ERROR: WDC: nvme_error_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_error_log() failed, ret = %d"
, ret)
;
10237 } else {
10238 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10239 "ErrorLog", (char *)serialNo, (char *)timeString);
10240 wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize);
10241 }
10242
10243 free(dataBuffer);
10244 dataBuffer = NULL((void*)0);
10245
10246 /* Get Smart log page */
10247 memset(&smart_log, 0, sizeof(struct nvme_smart_log));
10248 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
10249 if (ret) {
10250 nvme_show_error("ERROR: WDC: nvme_smart_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_smart_log() failed, ret = %d"
, ret)
;
10251 } else {
10252 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10253 "SmartLog", (char *)serialNo, (char *)timeString);
10254 wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log));
10255 }
10256
10257 /* Get FW Slot log page */
10258 memset(&fw_log, 0, sizeof(struct nvme_firmware_slot));
10259 ret = nvme_get_log_fw_slot(hdl, false0, &fw_log);
10260 if (ret) {
10261 nvme_show_error("ERROR: WDC: nvme_fw_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_fw_log() failed, ret = %d"
, ret)
;
10262 } else {
10263 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10264 "FwSLotLog", (char *)serialNo, (char *)timeString);
10265 wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot));
10266 }
10267
10268 /* Get VU log pages */
10269 /* define inputs for vendor unique log pages */
10270 vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES));
10271 vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList)(sizeof(deVULogPagesList) / sizeof((deVULogPagesList)[0]));
10272
10273 for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) {
10274 dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen;
10275 dataBuffer = calloc(1, dataBufferSize);
10276 memset(dataBuffer, 0, dataBufferSize);
10277
10278 ret = nvme_get_log_simple(hdl,
10279 deVULogPagesList[vuLogIdx].logPageId,
10280 dataBuffer, dataBufferSize);
10281 if (ret) {
10282 nvme_show_error("ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d",nvme_show_message(1, "ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d"
, deVULogPagesList[vuLogIdx].logPageId, ret)
10283 deVULogPagesList[vuLogIdx].logPageId, ret)nvme_show_message(1, "ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d"
, deVULogPagesList[vuLogIdx].logPageId, ret)
;
10284 } else {
10285 wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' ');
10286 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10287 "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString);
10288 wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize);
10289 }
10290
10291 free(dataBuffer);
10292 dataBuffer = NULL((void*)0);
10293 }
10294
10295 free(vuLogInput);
10296
10297 /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */
10298 for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList)(sizeof(deFeatureIdList) / sizeof((deFeatureIdList)[0])); listIdx++) {
10299 memset(featureIdBuff, 0, sizeof(featureIdBuff));
10300 /* skipping LbaRangeType as it is an optional nvme command and not supported */
10301 if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
10302 continue;
10303 ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID0xFFFFFFFF,
10304 (enum nvme_features_id)deFeatureIdList[listIdx].featureId,
10305 NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff,
10306 sizeof(featureIdBuff), &result);
10307 if (ret) {
10308 nvme_show_error("ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d",nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
10309 deFeatureIdList[listIdx].featureId, ret)nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
;
10310 } else {
10311 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10312 "FEATURE_ID_", deFeatureIdList[listIdx].featureId,
10313 deFeatureIdList[listIdx].featureName, serialNo, timeString);
10314 wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff));
10315 }
10316 }
10317
10318 ret = wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString);
10319
10320 /* Get Dump Trace Data */
10321 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/", "dumptrace", serialNo, timeString);
10322 ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName);
10323 if (ret != WDC_STATUS_SUCCESS0)
10324 nvme_show_error("ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d"
, ret)
;
10325
10326 /* Tar the Drive Essentials directory */
10327 wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
10328 if (dir)
10329 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s%s%s", (char *)dir,
10330 WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName,
10331 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10332 else
10333 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s", (char *)bufferFolderName,
10334 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10335 wdc_UtilsSnprintf(tarCmd, sizeof(tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarFileName, (char *)tarFiles);
10336
10337 ret = system(tarCmd);
10338
10339 if (ret)
10340 nvme_show_error("ERROR: WDC: Tar of Drive Essentials data failed, ret = %d",nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
10341 ret)nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
;
10342
10343 nvme_show_verbose_result("Get of Drive Essentials data successful")nvme_show_verbose_message("Get of Drive Essentials data successful"
)
;
10344 return 0;
10345}
10346
10347static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
10348 struct plugin *plugin)
10349{
10350 const char *desc = "Capture Drive Essentials.";
10351 const char *dirName = "Output directory pathname.";
10352 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10353 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10354 char d[PATH_MAX4096] = {0};
10355 char k[PATH_MAX4096] = {0};
10356 __u64 capabilities = 0;
10357 char *d_ptr;
10358 int ret;
10359
10360 struct config {
10361 char *dirName;
10362 };
10363
10364 struct config cfg = {
10365 .dirName = NULL((void*)0),
10366 };
10367
10368 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"dir-name", 'd', "DIRECTORY", CFG_STRING, &cfg.dirName
, 1, dirName, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10369 OPT_STRING("dir-name", 'd', "DIRECTORY", &cfg.dirName, dirName))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"dir-name", 'd', "DIRECTORY", CFG_STRING, &cfg.dirName
, 1, dirName, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
10370
10371
10372 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10373 if (ret)
10374 return ret;
10375
10376 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10377 if (ret)
10378 return ret;
10379
10380 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10381
10382 if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) {
10383 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10384 ret = -1;
10385 goto out;
10386 }
10387
10388 if (cfg.dirName) {
10389 strncpy(d, cfg.dirName, PATH_MAX4096 - 1);
10390 d_ptr = d;
10391 } else {
10392 d_ptr = NULL((void*)0);
10393 }
10394
10395 ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k);
10396out:
10397 return ret;
10398}
10399
10400static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size)
10401{
10402 int ret;
10403 struct libnvme_passthru_cmd admin_cmd;
10404
10405 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10406 admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE0xCC;
10407 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 << WDC_NVME_SUBCMD_SHIFT8) |
10408 WDC_NVME_DRIVE_RESIZE_CMD0x03);
10409 admin_cmd.cdw13 = new_size;
10410
10411 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10412 return ret;
10413}
10414
10415static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option)
10416{
10417 int ret;
10418 struct libnvme_passthru_cmd admin_cmd;
10419
10420 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10421 admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB;
10422 admin_cmd.nsid = nsid;
10423 admin_cmd.cdw10 = op_option;
10424
10425 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10426 return ret;
10427}
10428
10429static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result)
10430{
10431 int ret;
10432 struct libnvme_passthru_cmd admin_cmd;
10433
10434 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10435 admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE0xC6;
10436 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
10437 WDC_NVME_DRIVE_INFO_CMD0x22);
10438
10439 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10440
10441 if (!ret && result)
10442 *result = admin_cmd.result;
10443
10444 return ret;
10445}
10446
10447static int wdc_drive_resize(int argc, char **argv,
10448 struct command *command, struct plugin *plugin)
10449{
10450 const char *desc = "Send a Resize command.";
10451 const char *size = "The new size (in GB) to resize the drive to.";
10452 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10453 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10454 uint64_t capabilities = 0;
10455 int ret;
10456
10457 struct config {
10458 uint64_t size;
10459 };
10460
10461 struct config cfg = {
10462 .size = 0,
10463 };
10464
10465 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"size", 's', "NUM", CFG_POSITIVE, &cfg.size, 1, size
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10466 OPT_UINT("size", 's', &cfg.size, size))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"size", 's', "NUM", CFG_POSITIVE, &cfg.size, 1, size
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
10467
10468 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10469 if (ret)
10470 return ret;
10471
10472 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10473 if (ret || !wdc_check_device(ctx, hdl))
10474 return -1;
10475
10476 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10477
10478 if ((capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100) == WDC_DRIVE_CAP_RESIZE0x0000000000000100) {
10479 ret = wdc_do_drive_resize(hdl, cfg.size);
10480 } else {
10481 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10482 ret = -1;
10483 }
10484
10485 if (!ret)
10486 printf("New size: %" PRIu64"l" "u" " GB\n", cfg.size);
10487
10488 nvme_show_status(ret);
10489 return ret;
10490}
10491
10492static int wdc_namespace_resize(int argc, char **argv,
10493 struct command *command, struct plugin *plugin)
10494{
10495 const char *desc = "Send a Namespace Resize command.";
10496 const char *namespace_id = "The namespace id to resize.";
10497 const char *op_option = "The over provisioning option to set for namespace.";
10498 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10499 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10500 uint64_t capabilities = 0;
10501 int ret;
10502
10503 struct config {
10504 __u32 namespace_id;
10505 __u32 op_option;
10506 };
10507
10508 struct config cfg = {
10509 .namespace_id = 0x1,
10510 .op_option = 0xF,
10511 };
10512
10513 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"op-option", 'O', "NUM", CFG_POSITIVE
, &cfg.op_option, 1, op_option, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10514 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"op-option", 'O', "NUM", CFG_POSITIVE
, &cfg.op_option, 1, op_option, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10515 OPT_UINT("op-option", 'O', &cfg.op_option, op_option))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"op-option", 'O', "NUM", CFG_POSITIVE
, &cfg.op_option, 1, op_option, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
10516
10517 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10518 if (ret)
10519 return ret;
10520
10521 if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) &&
10522 (cfg.op_option != 0xF)) {
10523 nvme_show_error("ERROR: WDC: unsupported OP option parameter")nvme_show_message(1, "ERROR: WDC: unsupported OP option parameter"
)
;
10524 return -1;
10525 }
10526
10527 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10528 if (ret || !wdc_check_device(ctx, hdl))
10529 return -1;
10530
10531 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10532
10533 if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) == WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) {
10534 ret = wdc_do_namespace_resize(hdl, cfg.namespace_id,
10535 cfg.op_option);
10536
10537 if (ret)
10538 nvme_show_error("ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed", cfg.namespace_id, cfg.op_option)nvme_show_message(1, "ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed"
, cfg.namespace_id, cfg.op_option)
;
10539 } else {
10540 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10541 ret = -1;
10542 }
10543
10544 nvme_show_status(ret);
10545 return ret;
10546}
10547
10548static int wdc_reason_identifier(int argc, char **argv,
10549 struct command *command, struct plugin *plugin)
10550{
10551 const char *desc = "Retrieve telemetry log reason identifier.";
10552 const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
10553 const char *fname = "File name to save raw binary identifier";
10554 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10555 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10556 int ret;
10557 uint64_t capabilities = 0;
10558 char f[PATH_MAX4096] = {0};
10559 char fileSuffix[PATH_MAX4096] = {0};
10560 UtilsTimeInfo timeInfo;
10561 __u8 timeStamp[MAX_PATH_LEN256];
10562
10563
10564 struct config {
10565 int log_id;
10566 char *file;
10567 };
10568 struct config cfg = {
10569 .log_id = 7,
10570 .file = NULL((void*)0),
10571 };
10572
10573 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log-id", 'i', "NUM", CFG_POSITIVE, &cfg.log_id, 1
, log_id, 0, }, {"file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, fname, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((
void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10574 OPT_UINT("log-id", 'i', &cfg.log_id, log_id),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log-id", 'i', "NUM", CFG_POSITIVE, &cfg.log_id, 1
, log_id, 0, }, {"file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, fname, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((
void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
10575 OPT_FILE("file", 'O', &cfg.file, fname))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log-id", 'i', "NUM", CFG_POSITIVE, &cfg.log_id, 1
, log_id, 0, }, {"file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, fname, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((
void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
10576
10577 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10578
10579 if (ret)
10580 return ret;
10581
10582 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10583 if (ret)
10584 return ret;
10585
10586 if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST &&
10587 cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
10588 nvme_show_error("ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)")nvme_show_message(1, "ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)"
)
;
10589 return -1;
10590 }
10591
10592 if (cfg.file) {
10593 int verify_file;
10594
10595 /* verify the passed in file name and path is valid before getting the dump data */
10596 verify_file = nvme_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
10597 if (verify_file < 0) {
10598 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
10599 return -1;
10600 }
10601 close(verify_file);
10602 strncpy(f, cfg.file, PATH_MAX4096 - 1);
10603 } else {
10604 wdc_UtilsGetTime(&timeInfo);
10605 memset(timeStamp, 0, sizeof(timeStamp));
10606 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10607 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10608 timeInfo.hour, timeInfo.minute, timeInfo.second);
10609 if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
10610 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_ctlr_%s", (char *)timeStamp);
10611 else
10612 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_host_%s", (char *)timeStamp);
10613
10614 if (wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix) == -1) {
10615 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
10616 return -1;
10617 }
10618 if (strlen(f) > PATH_MAX4096 - 5) {
10619 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
10620 return -1;
10621 }
10622 strcat(f, ".bin");
10623 }
10624
10625 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
10626
10627 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10628 if ((capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000) == WDC_DRIVE_CAP_REASON_ID0x0000000000010000) {
10629 ret = wdc_do_get_reason_id(hdl, f, cfg.log_id);
10630 } else {
10631 nvme_show_error("ERROR: WDC:unsupported device for this command")nvme_show_message(1, "ERROR: WDC:unsupported device for this command"
)
;
10632 ret = -1;
10633 }
10634
10635 nvme_show_status(ret);
10636
10637 return ret;
10638}
10639
10640static const char *nvme_log_id_to_string(__u8 log_id)
10641{
10642 switch (log_id) {
10643 case NVME_LOG_LID_ERROR:
10644 return "Error Information Log ID";
10645 case NVME_LOG_LID_SMART:
10646 return "Smart/Health Information Log ID";
10647 case NVME_LOG_LID_FW_SLOT:
10648 return "Firmware Slot Information Log ID";
10649 case NVME_LOG_LID_CHANGED_NS:
10650 return "Namespace Changed Log ID";
10651 case NVME_LOG_LID_CMD_EFFECTS:
10652 return "Commamds Supported and Effects Log ID";
10653 case NVME_LOG_LID_DEVICE_SELF_TEST:
10654 return "Device Self Test Log ID";
10655 case NVME_LOG_LID_TELEMETRY_HOST:
10656 return "Telemetry Host Initiated Log ID";
10657 case NVME_LOG_LID_TELEMETRY_CTRL:
10658 return "Telemetry Controller Generated Log ID";
10659 case NVME_LOG_LID_ENDURANCE_GROUP:
10660 return "Endurance Group Log ID";
10661 case NVME_LOG_LID_ANA:
10662 return "ANA Log ID";
10663 case NVME_LOG_LID_PERSISTENT_EVENT:
10664 return "Persistent Event Log ID";
10665 case NVME_LOG_LID_DISCOVERY:
10666 return "Discovery Log ID";
10667 case NVME_LOG_LID_RESERVATION:
10668 return "Reservation Notification Log ID";
10669 case NVME_LOG_LID_SANITIZE:
10670 return "Sanitize Status Log ID";
10671 case WDC_LOG_ID_C00xC0:
10672 return "WDC Vendor Unique Log ID C0";
10673 case WDC_LOG_ID_C10xC1:
10674 return "WDC Vendor Unique Log ID C1";
10675 case WDC_LOG_ID_C20xC2:
10676 return "WDC Vendor Unique Log ID C2";
10677 case WDC_LOG_ID_C30xC3:
10678 return "WDC Vendor Unique Log ID C3";
10679 case WDC_LOG_ID_C40xC4:
10680 return "WDC Vendor Unique Log ID C4";
10681 case WDC_LOG_ID_C50xC5:
10682 return "WDC Vendor Unique Log ID C5";
10683 case WDC_LOG_ID_C60xC6:
10684 return "WDC Vendor Unique Log ID C6";
10685 case WDC_LOG_ID_C80xC8:
10686 return "WDC Vendor Unique Log ID C8";
10687 case WDC_LOG_ID_CA0xCA:
10688 return "WDC Vendor Unique Log ID CA";
10689 case WDC_LOG_ID_CB0xCB:
10690 return "WDC Vendor Unique Log ID CB";
10691 case WDC_LOG_ID_D00xD0:
10692 return "WDC Vendor Unique Log ID D0";
10693 case WDC_LOG_ID_D10xD1:
10694 return "WDC Vendor Unique Log ID D1";
10695 case WDC_LOG_ID_D60xD6:
10696 return "WDC Vendor Unique Log ID D6";
10697 case WDC_LOG_ID_D70xD7:
10698 return "WDC Vendor Unique Log ID D7";
10699 case WDC_LOG_ID_D80xD8:
10700 return "WDC Vendor Unique Log ID D8";
10701 case WDC_LOG_ID_DE0xDE:
10702 return "WDC Vendor Unique Log ID DE";
10703 case WDC_LOG_ID_F00xF0:
10704 return "WDC Vendor Unique Log ID F0";
10705 case WDC_LOG_ID_F10xF1:
10706 return "WDC Vendor Unique Log ID F1";
10707 case WDC_LOG_ID_F20xF2:
10708 return "WDC Vendor Unique Log ID F2";
10709 case WDC_LOG_ID_FA0xFA:
10710 return "WDC Vendor Unique Log ID FA";
10711 default:
10712 return "Unknown Log ID";
10713 }
10714}
10715
10716static void __json_log_page_directory(struct log_page_directory *directory)
10717{
10718 __u32 bitmap_idx;
10719 __u8 log_id;
10720 struct json_object *root;
10721 struct json_object *entries;
10722
10723 root = json_create_object()json_object_new_object();
10724
10725 entries = json_create_array()json_object_new_array();
10726 json_object_add_value_array(root, "Entries", entries)json_object_object_add(root, "Entries", entries);
10727
10728 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10729 log_id = bitmap_idx;
10730 if (!log_page_name[log_id])
10731 continue;
10732 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10733 struct json_object *json_entry = json_create_object()json_object_new_object();
10734
10735 json_object_add_value_uint(json_entry, "Log ID", log_id)json_object_object_add(json_entry, "Log ID", json_object_new_uint64
(log_id))
;
10736 json_object_add_value_string(json_entry, "Log Page Name",
10737 log_page_name[log_id]);
10738
10739 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10740 }
10741 }
10742
10743 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10744 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10745 if (!log_page_name[log_id])
10746 continue;
10747 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10748 struct json_object *json_entry = json_create_object()json_object_new_object();
10749
10750 json_object_add_value_uint(json_entry, "Log ID", log_id)json_object_object_add(json_entry, "Log ID", json_object_new_uint64
(log_id))
;
10751 json_object_add_value_string(json_entry, "Log Page Name",
10752 log_page_name[log_id]);
10753
10754 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10755 }
10756 }
10757
10758 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10759 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10760 if (!log_page_name[log_id])
10761 continue;
10762 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10763 struct json_object *json_entry = json_create_object()json_object_new_object();
10764
10765 json_object_add_value_uint(json_entry, "Log ID", log_id)json_object_object_add(json_entry, "Log ID", json_object_new_uint64
(log_id))
;
10766 json_object_add_value_string(json_entry, "Log Page Name",
10767 log_page_name[log_id]);
10768
10769 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10770 }
10771 }
10772
10773 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10774 printf("\n");
10775 json_free_object(root)json_object_put(root);
10776}
10777
10778
10779static void __show_log_page_directory(struct log_page_directory *directory)
10780{
10781 __u32 bitmap_idx;
10782 __u8 log_id;
10783
10784 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10785 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10786 log_id = bitmap_idx;
10787 if (log_page_name[log_id])
10788 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10789 }
10790 }
10791
10792 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10793 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10794 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10795 if (log_page_name[log_id])
10796 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10797 }
10798 }
10799
10800 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10801 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10802 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10803 if (log_page_name[log_id])
10804 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10805 }
10806 }
10807}
10808
10809static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
10810 struct plugin *plugin)
10811{
10812 const char *desc = "Retrieve Log Page Directory.";
10813 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10814 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10815 nvme_print_flags_t fmt;
10816 int ret = 0;
10817 __u64 capabilities = 0;
10818 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
10819 int i, uuid_index = 0;
10820 __u8 log_id = 0;
10821 __u32 device_id, read_vendor_id;
10822 bool_Bool uuid_supported = false0;
10823 struct nvme_id_uuid_list uuid_list;
10824
10825 struct config {
10826 char *output_format;
10827 };
10828
10829 struct config cfg = {
10830 .output_format = "normal",
10831 };
10832
10833 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
10834
10835 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10836 if (ret)
10837 return ret;
10838
10839 cfg.output_format = nvme_args.output_format;
10840
10841 ret = validate_output_format(cfg.output_format, &fmt);
10842 if (ret < 0) {
10843 nvme_show_error("%s: ERROR: WDC: invalid output format", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid output format",
__func__)
;
10844 return ret;
10845 }
10846
10847 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10848 if (ret)
10849 return ret;
10850
10851 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10852
10853 if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000)) {
10854 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10855 ret = -1;
10856 } else {
10857 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
10858 if (wdc_CheckUuidListSupport(hdl, &uuid_list))
10859 uuid_supported = true1;
10860
10861 if (uuid_supported)
10862 nvme_show_error("WDC: UUID lists supported")nvme_show_message(1, "WDC: UUID lists supported");
10863 else
10864 nvme_show_error("WDC: UUID lists NOT supported")nvme_show_message(1, "WDC: UUID lists NOT supported");
10865
10866
10867 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
10868 if (ret)
10869 return ret;
10870
10871 log_id = wdc_is_zn350(device_id) ?
10872 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 :
10873 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
10874
10875 if (!wdc_is_sn861(device_id)) {
10876 if (uuid_supported) {
10877 /* check for the Sandisk UUID first */
10878 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
10879
10880 if (uuid_index < 0)
10881 /* The Sandisk UUID is not found;
10882 * check for the WDC UUID second.
10883 */
10884 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
10885 }
10886
10887 /* WD UUID not found, use default uuid index - 0 */
10888 if (uuid_index < 0)
10889 uuid_index = 0;
10890
10891 /* verify the 0xC2 Device Manageability log page is supported */
10892 if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) {
10893 nvme_show_error("%s: ERROR: WDC: 0x%x Log Page not supported",nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
10894 __func__, log_id)nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
;
10895 ret = -1;
10896 goto out;
10897 }
10898
10899 if (!get_dev_mgment_cbs_data(ctx, hdl,
10900 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
10901 (void *)&cbs_data)) {
10902 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
10903 "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
10904 __func__, WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
;
10905 ret = -1;
10906 goto out;
10907 }
10908 if (!cbs_data) {
10909 nvme_show_error("%s: ERROR: WDC: NULL_data ptr", __func__)nvme_show_message(1, "%s: ERROR: WDC: NULL_data ptr", __func__
)
;
10910 ret = -1;
10911 goto out;
10912 }
10913 printf("Log Page Directory\n");
10914 /* print the supported pages */
10915 if (!strcmp(cfg.output_format, "normal")) {
10916 for (i = 0; i < le32_to_cpu(cbs_data->length); i++)
10917 printf("0x%x - %s\n", cbs_data->data[i],
10918 nvme_log_id_to_string(cbs_data->data[i]));
10919 } else if (!strcmp(cfg.output_format, "binary")) {
10920 d((__u8 *)cbs_data->data,
10921 le32_to_cpu(cbs_data->length), 16, 1);
10922 } else if (!strcmp(cfg.output_format, "json")) {
10923 struct json_object *root = json_create_object()json_object_new_object();
10924
10925 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
10926 json_object_add_value_int(root,json_object_object_add(root, nvme_log_id_to_string(cbs_data->
data[i]), json_object_new_int(cbs_data->data[i]))
10927 nvme_log_id_to_string(cbs_data->data[i]),json_object_object_add(root, nvme_log_id_to_string(cbs_data->
data[i]), json_object_new_int(cbs_data->data[i]))
10928 cbs_data->data[i])json_object_object_add(root, nvme_log_id_to_string(cbs_data->
data[i]), json_object_new_int(cbs_data->data[i]))
;
10929 }
10930
10931 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10932 printf("\n");
10933 json_free_object(root)json_object_put(root);
10934 } else {
10935 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
10936 "%s: ERROR: WDC: Invalid format, format = %s\n",nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
10937 __func__, cfg.output_format)nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
;
10938 }
10939
10940 free(cbs_data);
10941 } else {
10942 struct log_page_directory *dir;
10943 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *data = NULL((void*)0);
10944
10945 data = libnvme_alloc(512);
10946 if (!data) {
10947 nvme_show_error(nvme_show_message(1, "can not allocate log page directory payload\n"
)
10948 "can not allocate log page directory payload\n")nvme_show_message(1, "can not allocate log page directory payload\n"
)
;
10949 return -ENOMEM12;
10950 }
10951
10952 dir = (struct log_page_directory *)data;
10953 struct libnvme_passthru_cmd cmd = {
10954 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
10955 .cdw10 = 8,
10956 .cdw12 = WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2,
10957 .addr = (__u64)(uintptr_t)data,
10958 .data_len = 32,
10959 };
10960
10961 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10962 if (!ret) {
10963 switch (fmt) {
10964 case BINARY:
10965 d_raw((unsigned char *)data, 32);
10966 break;
10967 case JSON:
10968 __json_log_page_directory(dir);
10969 break;
10970 default:
10971 __show_log_page_directory(dir);
10972 }
10973 } else {
10974 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
10975 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
10976 }
10977 }
10978 }
10979
10980out:
10981 return ret;
10982}
10983
10984static int wdc_get_drive_reason_id(struct libnvme_transport_handle *hdl, char *drive_reason_id, size_t len)
10985{
10986 const char *reason_id_str = "reason_id";
10987 struct nvme_id_ctrl ctrl;
10988 int res_len = 0;
10989 int i, j;
10990 int ret;
10991
10992 i = sizeof(ctrl.sn) - 1;
10993 j = sizeof(ctrl.mn) - 1;
10994 memset(drive_reason_id, 0, len);
10995 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10996 ret = nvme_identify_ctrl(hdl, &ctrl);
10997 if (ret) {
10998 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
10999 return -1;
11000 }
11001 /* Remove trailing spaces from the sn and mn */
11002 while (i && ctrl.sn[i] == ' ') {
11003 ctrl.sn[i] = '\0';
11004 i--;
11005 }
11006
11007 while (j && ctrl.mn[j] == ' ') {
11008 ctrl.mn[j] = '\0';
11009 j--;
11010 }
11011
11012 res_len = snprintf(drive_reason_id, len, "%s_%s_%s", ctrl.sn, ctrl.mn, reason_id_str);
11013 if (len <= res_len) {
11014 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
11015 "ERROR: WDC: cannot format serial number due to data of unexpected length\n")nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
;
11016 return -1;
11017 }
11018
11019 return 0;
11020}
11021
11022static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size)
11023{
11024 int ret = 0;
11025 char *reason_id_file;
11026 char drive_reason_id[PATH_MAX4096] = {0};
11027 char reason_id_path[PATH_MAX4096] = WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli";
11028 struct stat st = {0};
11029
11030 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11031 nvme_show_error("%s: ERROR: failed to get drive reason id", __func__)nvme_show_message(1, "%s: ERROR: failed to get drive reason id"
, __func__)
;
11032 return -1;
11033 }
11034
11035 /* make the nvmecli dir in /usr/local if it doesn't already exist */
11036 if (stat(reason_id_path, &st) == -1) {
11037 if (mkdir(reason_id_path, 0700) < 0) {
11038 nvme_show_error("%s: ERROR: failed to mkdir %s: %s",nvme_show_message(1, "%s: ERROR: failed to mkdir %s: %s", __func__
, reason_id_path, libnvme_strerror((*__errno_location ())))
11039 __func__, reason_id_path, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: failed to mkdir %s: %s", __func__
, reason_id_path, libnvme_strerror((*__errno_location ())))
;
11040 return -1;
11041 }
11042 }
11043
11044 if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
11045 drive_reason_id, ".bin") < 0)
11046 return -ENOMEM12;
11047
11048 nvme_show_error("%s: reason id file = %s", __func__, reason_id_file)nvme_show_message(1, "%s: reason id file = %s", __func__, reason_id_file
)
;
11049
11050 /* save off the error reason identifier to a file in /usr/local/nvmecli */
11051 ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN128);
11052 free(reason_id_file);
11053
11054 return ret;
11055}
11056
11057static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl)
11058{
11059 int ret = -1;
11060 int verify_file;
11061 char *reason_id_file;
11062 char drive_reason_id[PATH_MAX4096] = {0};
11063
11064 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11065 nvme_show_error("%s: ERROR: failed to get drive reason id", __func__)nvme_show_message(1, "%s: ERROR: failed to get drive reason id"
, __func__)
;
11066 return -1;
11067 }
11068
11069 if (asprintf(&reason_id_file, "%s/%s%s", WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli",
11070 drive_reason_id, ".bin") < 0)
11071 return -ENOMEM12;
11072
11073 /* verify the drive reason id file name and path is valid */
11074 verify_file = nvme_open_rawdata(reason_id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((reason_id_file), (01 | 0100 | 01000), 0666);
11075 if (verify_file < 0) {
11076 ret = -1;
11077 goto free;
11078 }
11079 close(verify_file);
11080
11081 /* remove the reason id file */
11082 ret = remove(reason_id_file);
11083
11084free:
11085 free(reason_id_file);
11086
11087 return ret;
11088}
11089
11090static int wdc_dump_telemetry_hdr(struct libnvme_transport_handle *hdl, int log_id, struct nvme_telemetry_log *log_hdr)
11091{
11092 int ret = 0;
11093
11094 if (log_id == NVME_LOG_LID_TELEMETRY_HOST)
11095 ret = nvme_get_log_create_telemetry_host(hdl, log_hdr);
11096 else
11097 ret = nvme_get_log_telemetry_ctrl(hdl, false0, 0, (void *)log_hdr, 512);
11098
11099 if (ret < 0) {
11100 nvme_show_err(ret, "get-telemetry-log");
11101 } else if (ret > 0) {
11102 nvme_show_status(ret);
11103 nvme_show_error("%s: ERROR: Failed to acquire telemetry header, ret = %d!", __func__, ret)nvme_show_message(1, "%s: ERROR: Failed to acquire telemetry header, ret = %d!"
, __func__, ret)
;
11104 }
11105
11106 return ret;
11107}
11108
11109static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id)
11110{
11111 int ret;
11112 struct nvme_telemetry_log *log_hdr;
11113 __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
11114 __u32 reason_id_size = 0;
11115
11116 log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size);
11117 if (!log_hdr) {
11118 nvme_show_error("%s: ERROR: malloc failed, size : 0x%x, status: %s", __func__, log_hdr_size, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc failed, size : 0x%x, status: %s"
, __func__, log_hdr_size, libnvme_strerror((*__errno_location
())))
;
11119 ret = -1;
11120 goto out;
11121 }
11122 memset(log_hdr, 0, log_hdr_size);
11123
11124 ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr);
11125 if (ret) {
11126 nvme_show_error("%s: ERROR: get telemetry header failed, ret : %d", __func__, ret)nvme_show_message(1, "%s: ERROR: get telemetry header failed, ret : %d"
, __func__, ret)
;
11127 ret = -1;
11128 goto out;
11129 }
11130
11131 reason_id_size = sizeof(log_hdr->rsnident);
11132
11133 if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11134 wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size);
11135
11136 ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
11137
11138out:
11139 free(log_hdr);
11140 return ret;
11141}
11142
11143static void wdc_print_nand_stats_normal(__u16 version, void *data)
11144{
11145 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11146 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11147 __u64 temp_raw;
11148 __u16 temp_norm;
11149 __u64 *temp_ptr = NULL((void*)0);
11150
11151 switch (version) {
11152 case 0:
11153 printf(" NAND Statistics :-\n");
11154 printf(" NAND Writes TLC (Bytes) %s\n",
11155 uint128_t_to_string(
11156 le128_to_cpu(nand_stats->nand_write_tlc)));
11157 printf(" NAND Writes SLC (Bytes) %s\n",
11158 uint128_t_to_string(
11159 le128_to_cpu(nand_stats->nand_write_slc)));
11160 printf(" NAND Program Failures %"PRIu32"u""\n",
11161 (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure));
11162 printf(" NAND Erase Failures %"PRIu32"u""\n",
11163 (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure));
11164 printf(" Bad Block Count %"PRIu32"u""\n",
11165 (uint32_t)le32_to_cpu(nand_stats->bad_block_count));
11166 printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"l" "u""\n",
11167 le64_to_cpu(nand_stats->nand_rec_trigger_event));
11168 printf(" E2E Error Counter %"PRIu64"l" "u""\n",
11169 le64_to_cpu(nand_stats->e2e_error_counter));
11170 printf(" Number Successful NS Resizing Events %"PRIu64"l" "u""\n",
11171 le64_to_cpu(nand_stats->successful_ns_resize_event));
11172 printf(" log page version %"PRIu16"hu""\n",
11173 le16_to_cpu(nand_stats->log_page_version));
11174 break;
11175 case 3:
11176 printf(" NAND Statistics V3:-\n");
11177 printf(" TLC Units Written %s\n",
11178 uint128_t_to_string(
11179 le128_to_cpu(nand_stats_v3->nand_write_tlc)));
11180 printf(" SLC Units Written %s\n",
11181 uint128_t_to_string(
11182 le128_to_cpu(nand_stats_v3->nand_write_slc)));
11183 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11184 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11185 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11186 printf(" Bad NAND Blocks Count - Normalized %"PRIu16"hu""\n",
11187 le16_to_cpu(temp_norm));
11188 printf(" Bad NAND Blocks Count - Raw %"PRIu64"l" "u""\n",
11189 le64_to_cpu(temp_raw));
11190 printf(" NAND XOR Recovery count %"PRIu64"l" "u""\n",
11191 le64_to_cpu(nand_stats_v3->xor_recovery_count));
11192 printf(" UECC Read Error count %"PRIu64"l" "u""\n",
11193 le64_to_cpu(nand_stats_v3->uecc_read_error_count));
11194 printf(" SSD End to End corrected errors %"PRIu64"l" "u""\n",
11195 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
11196 printf(" SSD End to End detected errors %"PRIu32"u""\n",
11197 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
11198 printf(" SSD End to End uncorrected E2E errors %"PRIu32"u""\n",
11199 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
11200 printf(" System data %% life-used %u\n",
11201 nand_stats_v3->percent_life_used);
11202 printf(" User Data Erase Counts - TLC Min %"PRIu64"l" "u""\n",
11203 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
11204 printf(" User Data Erase Counts - TLC Max %"PRIu64"l" "u""\n",
11205 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
11206 printf(" User Data Erase Counts - SLC Min %"PRIu64"l" "u""\n",
11207 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
11208 printf(" User Data Erase Counts - SLC Max %"PRIu64"l" "u""\n",
11209 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
11210 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11211 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11212 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11213 printf(" Program Fail Count - Normalized %"PRIu16"hu""\n",
11214 le16_to_cpu(temp_norm));
11215 printf(" Program Fail Count - Raw %"PRIu64"l" "u""\n",
11216 le64_to_cpu(temp_raw));
11217 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11218 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11219 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11220 printf(" Erase Fail Count - Normalized %"PRIu16"hu""\n",
11221 le16_to_cpu(temp_norm));
11222 printf(" Erase Fail Count - Raw %"PRIu64"l" "u""\n",
11223 le64_to_cpu(temp_raw));
11224 printf(" PCIe Correctable Error Count %"PRIu16"hu""\n",
11225 le16_to_cpu(nand_stats_v3->correctable_error_count));
11226 printf(" %% Free Blocks (User) %u\n",
11227 nand_stats_v3->percent_free_blocks_user);
11228 printf(" Security Version Number %"PRIu64"l" "u""\n",
11229 le64_to_cpu(nand_stats_v3->security_version_number));
11230 printf(" %% Free Blocks (System) %u\n",
11231 nand_stats_v3->percent_free_blocks_system);
11232 printf(" Data Set Management Commands %s\n",
11233 uint128_t_to_string(
11234 le128_to_cpu(nand_stats_v3->trim_completions)));
11235 printf(" Estimate of Incomplete Trim Data %"PRIu64"l" "u""\n",
11236 le64_to_cpu(nand_stats_v3->trim_completions[16]));
11237 printf(" %% of completed trim %u\n",
11238 nand_stats_v3->trim_completions[24]);
11239 printf(" Background Back-Pressure-Guage %u\n",
11240 nand_stats_v3->back_pressure_guage);
11241 printf(" Soft ECC Error Count %"PRIu64"l" "u""\n",
11242 le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
11243 printf(" Refresh Count %"PRIu64"l" "u""\n",
11244 le64_to_cpu(nand_stats_v3->refresh_count));
11245 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11246 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11247 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11248 printf(" Bad System Nand Block Count - Normalized %"PRIu16"hu""\n",
11249 le16_to_cpu(temp_norm));
11250 printf(" Bad System Nand Block Count - Raw %"PRIu64"l" "u""\n",
11251 le64_to_cpu(temp_raw));
11252 printf(" Endurance Estimate %s\n",
11253 uint128_t_to_string(
11254 le128_to_cpu(nand_stats_v3->endurance_estimate)));
11255 printf(" Thermal Throttling Count %u\n",
11256 nand_stats_v3->thermal_throttling_st_ct[0]);
11257 printf(" Thermal Throttling Status %u\n",
11258 nand_stats_v3->thermal_throttling_st_ct[1]);
11259 printf(" Unaligned I/O %"PRIu64"l" "u""\n",
11260 le64_to_cpu(nand_stats_v3->unaligned_IO));
11261 printf(" Physical Media Units Read %s\n",
11262 uint128_t_to_string(
11263 le128_to_cpu(nand_stats_v3->physical_media_units)));
11264 printf(" log page version %"PRIu16"hu""\n",
11265 le16_to_cpu(nand_stats_v3->log_page_version));
11266 break;
11267
11268 default:
11269 nvme_show_error("WDC: Nand Stats ERROR: Invalid version")nvme_show_message(1, "WDC: Nand Stats ERROR: Invalid version"
)
;
11270 break;
11271
11272 }
11273}
11274
11275static void wdc_print_nand_stats_json(__u16 version, void *data)
11276{
11277 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11278 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11279 struct json_object *root = json_create_object()json_object_new_object();
11280 __u64 temp_raw;
11281 __u16 temp_norm;
11282 __u64 *temp_ptr = NULL((void*)0);
11283
11284 switch (version) {
11285 case 0:
11286 json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)",json_object_object_add(root, "NAND Writes TLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats->nand_write_tlc)))
11287 le128_to_cpu(nand_stats->nand_write_tlc))json_object_object_add(root, "NAND Writes TLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats->nand_write_tlc)))
;
11288 json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)",json_object_object_add(root, "NAND Writes SLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats->nand_write_slc)))
11289 le128_to_cpu(nand_stats->nand_write_slc))json_object_object_add(root, "NAND Writes SLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats->nand_write_slc)))
;
11290 json_object_add_value_uint(root, "NAND Program Failures",json_object_object_add(root, "NAND Program Failures", json_object_new_uint64
(le32_to_cpu(nand_stats->nand_prog_failure)))
11291 le32_to_cpu(nand_stats->nand_prog_failure))json_object_object_add(root, "NAND Program Failures", json_object_new_uint64
(le32_to_cpu(nand_stats->nand_prog_failure)))
;
11292 json_object_add_value_uint(root, "NAND Erase Failures",json_object_object_add(root, "NAND Erase Failures", json_object_new_uint64
(le32_to_cpu(nand_stats->nand_erase_failure)))
11293 le32_to_cpu(nand_stats->nand_erase_failure))json_object_object_add(root, "NAND Erase Failures", json_object_new_uint64
(le32_to_cpu(nand_stats->nand_erase_failure)))
;
11294 json_object_add_value_uint(root, "Bad Block Count",json_object_object_add(root, "Bad Block Count", json_object_new_uint64
(le32_to_cpu(nand_stats->bad_block_count)))
11295 le32_to_cpu(nand_stats->bad_block_count))json_object_object_add(root, "Bad Block Count", json_object_new_uint64
(le32_to_cpu(nand_stats->bad_block_count)))
;
11296 json_object_add_value_uint64(root, "NAND XOR/RAID Recovery Trigger Events",json_object_object_add(root, "NAND XOR/RAID Recovery Trigger Events"
, json_object_new_uint64(le64_to_cpu(nand_stats->nand_rec_trigger_event
)))
11297 le64_to_cpu(nand_stats->nand_rec_trigger_event))json_object_object_add(root, "NAND XOR/RAID Recovery Trigger Events"
, json_object_new_uint64(le64_to_cpu(nand_stats->nand_rec_trigger_event
)))
;
11298 json_object_add_value_uint64(root, "E2E Error Counter",json_object_object_add(root, "E2E Error Counter", json_object_new_uint64
(le64_to_cpu(nand_stats->e2e_error_counter)))
11299 le64_to_cpu(nand_stats->e2e_error_counter))json_object_object_add(root, "E2E Error Counter", json_object_new_uint64
(le64_to_cpu(nand_stats->e2e_error_counter)))
;
11300 json_object_add_value_uint64(root, "Number Successful NS Resizing Events",json_object_object_add(root, "Number Successful NS Resizing Events"
, json_object_new_uint64(le64_to_cpu(nand_stats->successful_ns_resize_event
)))
11301 le64_to_cpu(nand_stats->successful_ns_resize_event))json_object_object_add(root, "Number Successful NS Resizing Events"
, json_object_new_uint64(le64_to_cpu(nand_stats->successful_ns_resize_event
)))
;
11302
11303 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11304 printf("\n");
11305 break;
11306 case 3:
11307 json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)",json_object_object_add(root, "NAND Writes TLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->nand_write_tlc)))
11308 le128_to_cpu(nand_stats_v3->nand_write_tlc))json_object_object_add(root, "NAND Writes TLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->nand_write_tlc)))
;
11309 json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)",json_object_object_add(root, "NAND Writes SLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->nand_write_slc)))
11310 le128_to_cpu(nand_stats_v3->nand_write_slc))json_object_object_add(root, "NAND Writes SLC (Bytes)", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->nand_write_slc)))
;
11311 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11312 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11313 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11314 json_object_add_value_uint(root, "Bad NAND Blocks Count - Normalized",json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11315 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11316 json_object_add_value_uint64(root, "Bad NAND Blocks Count - Raw",json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11317 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11318 json_object_add_value_uint64(root, "NAND XOR Recovery count",json_object_object_add(root, "NAND XOR Recovery count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->xor_recovery_count)))
11319 le64_to_cpu(nand_stats_v3->xor_recovery_count))json_object_object_add(root, "NAND XOR Recovery count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->xor_recovery_count)))
;
11320 json_object_add_value_uint64(root, "UECC Read Error count",json_object_object_add(root, "UECC Read Error count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->uecc_read_error_count)))
11321 le64_to_cpu(nand_stats_v3->uecc_read_error_count))json_object_object_add(root, "UECC Read Error count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->uecc_read_error_count)))
;
11322 json_object_add_value_uint64(root, "SSD End to End corrected errors",json_object_object_add(root, "SSD End to End corrected errors"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->ssd_correction_counts
[0])))
11323 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]))json_object_object_add(root, "SSD End to End corrected errors"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->ssd_correction_counts
[0])))
;
11324 json_object_add_value_uint(root, "SSD End to End detected errors",json_object_object_add(root, "SSD End to End detected errors"
, json_object_new_uint64(le32_to_cpu(nand_stats_v3->ssd_correction_counts
[8])))
11325 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]))json_object_object_add(root, "SSD End to End detected errors"
, json_object_new_uint64(le32_to_cpu(nand_stats_v3->ssd_correction_counts
[8])))
;
11326 json_object_add_value_uint(root, "SSD End to End uncorrected E2E errors",json_object_object_add(root, "SSD End to End uncorrected E2E errors"
, json_object_new_uint64(le32_to_cpu(nand_stats_v3->ssd_correction_counts
[12])))
11327 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]))json_object_object_add(root, "SSD End to End uncorrected E2E errors"
, json_object_new_uint64(le32_to_cpu(nand_stats_v3->ssd_correction_counts
[12])))
;
11328 json_object_add_value_uint(root, "System data % life-used",json_object_object_add(root, "System data % life-used", json_object_new_uint64
(nand_stats_v3->percent_life_used))
11329 nand_stats_v3->percent_life_used)json_object_object_add(root, "System data % life-used", json_object_new_uint64
(nand_stats_v3->percent_life_used))
;
11330 json_object_add_value_uint64(root, "User Data Erase Counts - TLC Min",json_object_object_add(root, "User Data Erase Counts - TLC Min"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[0])))
11331 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]))json_object_object_add(root, "User Data Erase Counts - TLC Min"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[0])))
;
11332 json_object_add_value_uint64(root, "User Data Erase Counts - TLC Max",json_object_object_add(root, "User Data Erase Counts - TLC Max"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[1])))
11333 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]))json_object_object_add(root, "User Data Erase Counts - TLC Max"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[1])))
;
11334 json_object_add_value_uint64(root, "User Data Erase Counts - SLC Min",json_object_object_add(root, "User Data Erase Counts - SLC Min"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[2])))
11335 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]))json_object_object_add(root, "User Data Erase Counts - SLC Min"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[2])))
;
11336 json_object_add_value_uint64(root, "User Data Erase Counts - SLC Max",json_object_object_add(root, "User Data Erase Counts - SLC Max"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[3])))
11337 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]))json_object_object_add(root, "User Data Erase Counts - SLC Max"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->user_data_erase_counts
[3])))
;
11338 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11339 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11340 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11341 json_object_add_value_uint(root, "Program Fail Count - Normalized",json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11342 le16_to_cpu(temp_norm))json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11343 json_object_add_value_uint64(root, "Program Fail Count - Raw",json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11344 le64_to_cpu(temp_raw))json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11345 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11346 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11347 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11348 json_object_add_value_uint(root, "Erase Fail Count - Normalized",json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
11349 le16_to_cpu(temp_norm))json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11350 json_object_add_value_uint64(root, "Erase Fail Count - Raw",json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11351 le64_to_cpu(temp_raw))json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11352 json_object_add_value_uint(root, "PCIe Correctable Error Count",json_object_object_add(root, "PCIe Correctable Error Count", json_object_new_uint64
(le16_to_cpu(nand_stats_v3->correctable_error_count)))
11353 le16_to_cpu(nand_stats_v3->correctable_error_count))json_object_object_add(root, "PCIe Correctable Error Count", json_object_new_uint64
(le16_to_cpu(nand_stats_v3->correctable_error_count)))
;
11354 json_object_add_value_uint(root, "% Free Blocks (User)",json_object_object_add(root, "% Free Blocks (User)", json_object_new_uint64
(nand_stats_v3->percent_free_blocks_user))
11355 nand_stats_v3->percent_free_blocks_user)json_object_object_add(root, "% Free Blocks (User)", json_object_new_uint64
(nand_stats_v3->percent_free_blocks_user))
;
11356 json_object_add_value_uint64(root, "Security Version Number",json_object_object_add(root, "Security Version Number", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->security_version_number)))
11357 le64_to_cpu(nand_stats_v3->security_version_number))json_object_object_add(root, "Security Version Number", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->security_version_number)))
;
11358 json_object_add_value_uint(root, "% Free Blocks (System)",json_object_object_add(root, "% Free Blocks (System)", json_object_new_uint64
(nand_stats_v3->percent_free_blocks_system))
11359 nand_stats_v3->percent_free_blocks_system)json_object_object_add(root, "% Free Blocks (System)", json_object_new_uint64
(nand_stats_v3->percent_free_blocks_system))
;
11360 json_object_add_value_uint128(root, "Data Set Management Commands",json_object_object_add(root, "Data Set Management Commands", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->trim_completions)))
11361 le128_to_cpu(nand_stats_v3->trim_completions))json_object_object_add(root, "Data Set Management Commands", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->trim_completions)))
;
11362 json_object_add_value_uint64(root, "Estimate of Incomplete Trim Data",json_object_object_add(root, "Estimate of Incomplete Trim Data"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->trim_completions
[16])))
11363 le64_to_cpu(nand_stats_v3->trim_completions[16]))json_object_object_add(root, "Estimate of Incomplete Trim Data"
, json_object_new_uint64(le64_to_cpu(nand_stats_v3->trim_completions
[16])))
;
11364 json_object_add_value_uint(root, "%% of completed trim",json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
11365 nand_stats_v3->trim_completions[24])json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
;
11366 json_object_add_value_uint(root, "Background Back-Pressure-Guage",json_object_object_add(root, "Background Back-Pressure-Guage"
, json_object_new_uint64(nand_stats_v3->back_pressure_guage
))
11367 nand_stats_v3->back_pressure_guage)json_object_object_add(root, "Background Back-Pressure-Guage"
, json_object_new_uint64(nand_stats_v3->back_pressure_guage
))
;
11368 json_object_add_value_uint64(root, "Soft ECC Error Count",json_object_object_add(root, "Soft ECC Error Count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->soft_ecc_error_count)))
11369 le64_to_cpu(nand_stats_v3->soft_ecc_error_count))json_object_object_add(root, "Soft ECC Error Count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->soft_ecc_error_count)))
;
11370 json_object_add_value_uint64(root, "Refresh Count",json_object_object_add(root, "Refresh Count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->refresh_count)))
11371 le64_to_cpu(nand_stats_v3->refresh_count))json_object_object_add(root, "Refresh Count", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->refresh_count)))
;
11372 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11373 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11374 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11375 json_object_add_value_uint(root, "Bad System Nand Block Count - Normalized",json_object_object_add(root, "Bad System Nand Block Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11376 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad System Nand Block Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11377 json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw",json_object_object_add(root, "Bad System Nand Block Count - Raw"
, json_object_new_uint64(le64_to_cpu(temp_raw)))
11378 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad System Nand Block Count - Raw"
, json_object_new_uint64(le64_to_cpu(temp_raw)))
;
11379 json_object_add_value_uint128(root, "Endurance Estimate",json_object_object_add(root, "Endurance Estimate", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->endurance_estimate)))
11380 le128_to_cpu(nand_stats_v3->endurance_estimate))json_object_object_add(root, "Endurance Estimate", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->endurance_estimate)))
;
11381 json_object_add_value_uint(root, "Thermal Throttling Status",json_object_object_add(root, "Thermal Throttling Status", json_object_new_uint64
(nand_stats_v3->thermal_throttling_st_ct[0]))
11382 nand_stats_v3->thermal_throttling_st_ct[0])json_object_object_add(root, "Thermal Throttling Status", json_object_new_uint64
(nand_stats_v3->thermal_throttling_st_ct[0]))
;
11383 json_object_add_value_uint(root, "Thermal Throttling Count",json_object_object_add(root, "Thermal Throttling Count", json_object_new_uint64
(nand_stats_v3->thermal_throttling_st_ct[1]))
11384 nand_stats_v3->thermal_throttling_st_ct[1])json_object_object_add(root, "Thermal Throttling Count", json_object_new_uint64
(nand_stats_v3->thermal_throttling_st_ct[1]))
;
11385 json_object_add_value_uint64(root, "Unaligned I/O",json_object_object_add(root, "Unaligned I/O", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->unaligned_IO)))
11386 le64_to_cpu(nand_stats_v3->unaligned_IO))json_object_object_add(root, "Unaligned I/O", json_object_new_uint64
(le64_to_cpu(nand_stats_v3->unaligned_IO)))
;
11387 json_object_add_value_uint128(root, "Physical Media Units Read",json_object_object_add(root, "Physical Media Units Read", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->physical_media_units)))
11388 le128_to_cpu(nand_stats_v3->physical_media_units))json_object_object_add(root, "Physical Media Units Read", util_json_object_new_uint128
(le128_to_cpu(nand_stats_v3->physical_media_units)))
;
11389 json_object_add_value_uint(root, "log page version",json_object_object_add(root, "log page version", json_object_new_uint64
(le16_to_cpu(nand_stats_v3->log_page_version)))
11390 le16_to_cpu(nand_stats_v3->log_page_version))json_object_object_add(root, "log page version", json_object_new_uint64
(le16_to_cpu(nand_stats_v3->log_page_version)))
;
11391
11392 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11393 printf("\n");
11394 break;
11395 default:
11396 nvme_show_error("%s: Invalid Stats Version = %d", __func__, version)nvme_show_message(1, "%s: Invalid Stats Version = %d", __func__
, version)
;
11397 break;
11398 }
11399
11400 json_free_object(root)json_object_put(root);
11401
11402}
11403
11404static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats)
11405{
11406 printf(" PCIE Statistics :-\n");
11407 printf(" Unsupported Request Error Counter %20"PRIu64"l" "u""\n",
11408 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
11409 printf(" ECRC Error Status Counter %20"PRIu64"l" "u""\n",
11410 le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
11411 printf(" Malformed TLP Status Counter %20"PRIu64"l" "u""\n",
11412 le64_to_cpu(pcie_stats->malformedTlpStatusCount));
11413 printf(" Receiver Overflow Status Counter %20"PRIu64"l" "u""\n",
11414 le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
11415 printf(" Unexpected Completion Status Counter %20"PRIu64"l" "u""\n",
11416 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
11417 printf(" Complete Abort Status Counter %20"PRIu64"l" "u""\n",
11418 le64_to_cpu(pcie_stats->completeAbortStatusCount));
11419 printf(" Completion Timeout Status Counter %20"PRIu64"l" "u""\n",
11420 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
11421 printf(" Flow Control Error Status Counter %20"PRIu64"l" "u""\n",
11422 le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
11423 printf(" Poisoned TLP Status Counter %20"PRIu64"l" "u""\n",
11424 le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
11425 printf(" Dlink Protocol Error Status Counter %20"PRIu64"l" "u""\n",
11426 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
11427 printf(" Advisory Non Fatal Error Status Counter %20"PRIu64"l" "u""\n",
11428 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
11429 printf(" Replay Timer TO Status Counter %20"PRIu64"l" "u""\n",
11430 le64_to_cpu(pcie_stats->replayTimerToStatusCount));
11431 printf(" Replay Number Rollover Status Counter %20"PRIu64"l" "u""\n",
11432 le64_to_cpu(pcie_stats->replayNumRolloverStCount));
11433 printf(" Bad DLLP Status Counter %20"PRIu64"l" "u""\n",
11434 le64_to_cpu(pcie_stats->badDllpStatusCount));
11435 printf(" Bad TLP Status Counter %20"PRIu64"l" "u""\n",
11436 le64_to_cpu(pcie_stats->badTlpStatusCount));
11437 printf(" Receiver Error Status Counter %20"PRIu64"l" "u""\n",
11438 le64_to_cpu(pcie_stats->receiverErrStatusCount));
11439
11440}
11441
11442static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
11443{
11444 struct json_object *root = json_create_object()json_object_new_object();
11445
11446 json_object_add_value_uint64(root, "Unsupported Request Error Counter",json_object_object_add(root, "Unsupported Request Error Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->unsupportedRequestErrorCount
)))
11447 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount))json_object_object_add(root, "Unsupported Request Error Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->unsupportedRequestErrorCount
)))
;
11448 json_object_add_value_uint64(root, "ECRC Error Status Counter",json_object_object_add(root, "ECRC Error Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->ecrcErrorStatusCount)))
11449 le64_to_cpu(pcie_stats->ecrcErrorStatusCount))json_object_object_add(root, "ECRC Error Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->ecrcErrorStatusCount)))
;
11450 json_object_add_value_uint64(root, "Malformed TLP Status Counter",json_object_object_add(root, "Malformed TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->malformedTlpStatusCount)))
11451 le64_to_cpu(pcie_stats->malformedTlpStatusCount))json_object_object_add(root, "Malformed TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->malformedTlpStatusCount)))
;
11452
11453 json_object_add_value_uint64(root, "Receiver Overflow Status Counter",json_object_object_add(root, "Receiver Overflow Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->receiverOverflowStatusCount
)))
11454 le64_to_cpu(pcie_stats->receiverOverflowStatusCount))json_object_object_add(root, "Receiver Overflow Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->receiverOverflowStatusCount
)))
;
11455 json_object_add_value_uint64(root, "Unexpected Completion Status Counter",json_object_object_add(root, "Unexpected Completion Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount
)))
11456 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount))json_object_object_add(root, "Unexpected Completion Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount
)))
;
11457 json_object_add_value_uint64(root, "Complete Abort Status Counter",json_object_object_add(root, "Complete Abort Status Counter",
json_object_new_uint64(le64_to_cpu(pcie_stats->completeAbortStatusCount
)))
11458 le64_to_cpu(pcie_stats->completeAbortStatusCount))json_object_object_add(root, "Complete Abort Status Counter",
json_object_new_uint64(le64_to_cpu(pcie_stats->completeAbortStatusCount
)))
;
11459 json_object_add_value_uint64(root, "Completion Timeout Status Counter",json_object_object_add(root, "Completion Timeout Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount
)))
11460 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount))json_object_object_add(root, "Completion Timeout Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount
)))
;
11461 json_object_add_value_uint64(root, "Flow Control Error Status Counter",json_object_object_add(root, "Flow Control Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->flowControlErrorStatusCount
)))
11462 le64_to_cpu(pcie_stats->flowControlErrorStatusCount))json_object_object_add(root, "Flow Control Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->flowControlErrorStatusCount
)))
;
11463 json_object_add_value_uint64(root, "Poisoned TLP Status Counter",json_object_object_add(root, "Poisoned TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->poisonedTlpStatusCount)))
11464 le64_to_cpu(pcie_stats->poisonedTlpStatusCount))json_object_object_add(root, "Poisoned TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->poisonedTlpStatusCount)))
;
11465 json_object_add_value_uint64(root, "Dlink Protocol Error Status Counter",json_object_object_add(root, "Dlink Protocol Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount
)))
11466 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount))json_object_object_add(root, "Dlink Protocol Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount
)))
;
11467 json_object_add_value_uint64(root, "Advisory Non Fatal Error Status Counter",json_object_object_add(root, "Advisory Non Fatal Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount
)))
11468 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount))json_object_object_add(root, "Advisory Non Fatal Error Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount
)))
;
11469 json_object_add_value_uint64(root, "Replay Timer TO Status Counter",json_object_object_add(root, "Replay Timer TO Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->replayTimerToStatusCount
)))
11470 le64_to_cpu(pcie_stats->replayTimerToStatusCount))json_object_object_add(root, "Replay Timer TO Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->replayTimerToStatusCount
)))
;
11471 json_object_add_value_uint64(root, "Replay Number Rollover Status Counter",json_object_object_add(root, "Replay Number Rollover Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->replayNumRolloverStCount
)))
11472 le64_to_cpu(pcie_stats->replayNumRolloverStCount))json_object_object_add(root, "Replay Number Rollover Status Counter"
, json_object_new_uint64(le64_to_cpu(pcie_stats->replayNumRolloverStCount
)))
;
11473 json_object_add_value_uint64(root, "Bad DLLP Status Counter",json_object_object_add(root, "Bad DLLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->badDllpStatusCount)))
11474 le64_to_cpu(pcie_stats->badDllpStatusCount))json_object_object_add(root, "Bad DLLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->badDllpStatusCount)))
;
11475 json_object_add_value_uint64(root, "Bad TLP Status Counter",json_object_object_add(root, "Bad TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->badTlpStatusCount)))
11476 le64_to_cpu(pcie_stats->badTlpStatusCount))json_object_object_add(root, "Bad TLP Status Counter", json_object_new_uint64
(le64_to_cpu(pcie_stats->badTlpStatusCount)))
;
11477 json_object_add_value_uint64(root, "Receiver Error Status Counter",json_object_object_add(root, "Receiver Error Status Counter",
json_object_new_uint64(le64_to_cpu(pcie_stats->receiverErrStatusCount
)))
11478 le64_to_cpu(pcie_stats->receiverErrStatusCount))json_object_object_add(root, "Receiver Error Status Counter",
json_object_new_uint64(le64_to_cpu(pcie_stats->receiverErrStatusCount
)))
;
11479
11480 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11481 printf("\n");
11482
11483 json_free_object(root)json_object_put(root);
11484}
11485
11486static int wdc_do_vs_nand_stats_sn810_2(struct libnvme_transport_handle *hdl, char *format)
11487{
11488 nvme_print_flags_t fmt;
11489 uint8_t *data = NULL((void*)0);
11490 int ret;
11491
11492 data = NULL((void*)0);
11493 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
11494 NVME_NSID_ALL);
11495
11496 if (ret) {
11497 nvme_show_error("ERROR: WDC: %s : Failed to retrieve NAND stats", __func__)nvme_show_message(1, "ERROR: WDC: %s : Failed to retrieve NAND stats"
, __func__)
;
11498 goto out;
11499 } else {
11500 ret = validate_output_format(format, &fmt);
11501 if (ret < 0) {
11502 nvme_show_error("ERROR: WDC: %s : invalid output format", __func__)nvme_show_message(1, "ERROR: WDC: %s : invalid output format"
, __func__)
;
11503 goto out;
11504 }
11505
11506 /* parse the data */
11507 switch (fmt) {
11508 case NORMAL:
11509 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS0x1);
11510 break;
11511 case JSON:
11512 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS0x1);
11513 break;
11514 default:
11515 break;
11516 }
11517 }
11518
11519out:
11520 free(data);
11521 return ret;
11522}
11523
11524static int wdc_do_vs_nand_stats(struct libnvme_transport_handle *hdl, char *format)
11525{
11526 nvme_print_flags_t fmt;
11527 uint8_t *output = NULL((void*)0);
11528 __u16 version = 0;
11529 int ret;
11530
11531 output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE0x200, sizeof(uint8_t));
11532 if (!output) {
11533 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
11534 ret = -1;
11535 goto out;
11536 }
11537
11538 ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID0xFB,
11539 (void *)output, WDC_NVME_NAND_STATS_SIZE0x200);
11540 if (ret) {
11541 nvme_show_error("ERROR: WDC: %s : Failed to retrieve NAND stats", __func__)nvme_show_message(1, "ERROR: WDC: %s : Failed to retrieve NAND stats"
, __func__)
;
11542 goto out;
11543 } else {
11544 ret = validate_output_format(format, &fmt);
11545 if (ret < 0) {
11546 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11547 goto out;
11548 }
11549
11550 version = output[WDC_NVME_NAND_STATS_SIZE0x200 - 2];
11551
11552 /* parse the data */
11553 switch (fmt) {
11554 case NORMAL:
11555 wdc_print_nand_stats_normal(version, output);
11556 break;
11557 case JSON:
11558 wdc_print_nand_stats_json(version, output);
11559 break;
11560 default:
11561 break;
11562 }
11563 }
11564
11565out:
11566 free(output);
11567 return ret;
11568}
11569
11570static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd,
11571 struct plugin *plugin)
11572{
11573 const char *desc = "Retrieve NAND statistics.";
11574 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11575 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11576 __u64 capabilities = 0;
11577 uint32_t read_device_id = 0, read_vendor_id = 0;
11578 int ret;
11579
11580 struct config {
11581 char *output_format;
11582 };
11583
11584 struct config cfg = {
11585 .output_format = "normal",
11586 };
11587
11588 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
11589
11590 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11591 if (ret)
11592 return ret;
11593
11594 cfg.output_format = nvme_args.output_format;
11595
11596 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11597 if (ret)
11598 return ret;
11599
11600 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11601
11602 if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200)) {
11603 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11604 ret = -1;
11605 } else {
11606 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11607 if (ret < 0) {
11608 nvme_show_error("ERROR: WDC: %s: failure to get pci ids, ret = %d", __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: failure to get pci ids, ret = %d"
, __func__, ret)
;
11609 return -1;
11610 }
11611
11612 switch (read_device_id) {
11613 case WDC_NVME_SN820CL_DEV_ID0x5037:
11614 ret = wdc_do_vs_nand_stats_sn810_2(hdl,
11615 cfg.output_format);
11616 break;
11617 default:
11618 ret = wdc_do_vs_nand_stats(hdl, cfg.output_format);
11619 break;
11620 }
11621 }
11622
11623 if (ret)
11624 nvme_show_error("ERROR: WDC: Failure reading NAND statistics, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading NAND statistics, ret = %d"
, ret)
;
11625
11626 return ret;
11627}
11628
11629static int wdc_do_vs_pcie_stats(struct libnvme_transport_handle *hdl,
11630 struct wdc_vs_pcie_stats *pcieStatsPtr)
11631{
11632 int ret;
11633 struct libnvme_passthru_cmd admin_cmd;
11634 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11635
11636 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
11637 admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE0xD1;
11638 admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
11639 admin_cmd.data_len = pcie_stats_size;
11640
11641 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
11642
11643 return ret;
11644}
11645
11646static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd,
11647 struct plugin *plugin)
11648{
11649 const char *desc = "Retrieve PCIE statistics.";
11650 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11651 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11652 nvme_print_flags_t fmt;
11653 int ret;
11654 __u64 capabilities = 0;
11655 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
11656 struct wdc_vs_pcie_stats *pcieStatsPtr = NULL((void*)0);
11657 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11658
11659 struct config {
11660 char *output_format;
11661 };
11662
11663 struct config cfg = {
11664 .output_format = "normal",
11665 };
11666
11667 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
11668
11669 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11670 if (ret)
11671 return ret;
11672
11673 cfg.output_format = nvme_args.output_format;
11674
11675 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11676 if (ret)
11677 return ret;
11678
11679 ret = validate_output_format(cfg.output_format, &fmt);
11680 if (ret < 0) {
11681 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11682 goto out;
11683 }
11684
11685 pcieStatsPtr = libnvme_alloc_huge(pcie_stats_size, &mh);
11686 if (!pcieStatsPtr) {
11687 nvme_show_error("ERROR: WDC: PCIE Stats alloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: PCIE Stats alloc: %s", libnvme_strerror
((*__errno_location ())))
;
11688 ret = -1;
11689 goto out;
11690 }
11691
11692 memset((void *)pcieStatsPtr, 0, pcie_stats_size);
11693
11694 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11695
11696 if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000)) {
11697 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11698 ret = -1;
11699 } else {
11700 ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr);
11701 if (ret) {
11702 nvme_show_error("ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x"
, ret)
;
11703 } else {
11704 /* parse the data */
11705 switch (fmt) {
11706 case NORMAL:
11707 wdc_print_pcie_stats_normal(pcieStatsPtr);
11708 break;
11709 case JSON:
11710 wdc_print_pcie_stats_json(pcieStatsPtr);
11711 break;
11712 default:
11713 break;
11714 }
11715 }
11716 }
11717out:
11718 return ret;
11719}
11720
11721static int wdc_vs_drive_info(int argc, char **argv,
11722 struct command *command, struct plugin *plugin)
11723{
11724 const char *desc = "Send a vs-drive-info command.";
11725 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11726 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11727 nvme_print_flags_t fmt;
11728 uint64_t capabilities = 0;
11729 int ret;
11730 __le32 result;
11731 __u16 size;
11732 double rev;
11733 struct nvme_id_ctrl ctrl;
11734 char vsData[32] = {0};
11735 char major_rev = 0, minor_rev = 0;
11736 __u8 *data = NULL((void*)0);
11737 __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
11738 __u16 boot_spec_major = 0, boot_spec_minor = 0;
11739 struct json_object *root = NULL((void*)0);
11740 char formatter[41] = { 0 };
11741 char rev_str[16] = { 0 };
11742 uint32_t read_device_id = -1, read_vendor_id = -1;
11743 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
11744 struct ocp_drive_info info;
11745 __u32 data_len = 0;
11746 unsigned int num_dwords = 0;
11747
11748 struct config {
11749 char *output_format;
11750 };
11751
11752 struct config cfg = {
11753 .output_format = "normal",
11754 };
11755
11756 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
11757
11758 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11759 if (ret)
11760 return ret;
11761
11762 cfg.output_format = nvme_args.output_format;
11763
11764 ret = validate_output_format(cfg.output_format, &fmt);
11765 if (ret < 0) {
11766 nvme_show_error("ERROR: WDC %s invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s invalid output format", __func__
)
;
11767 return ret;
11768 }
11769
11770 /* get the id ctrl data used to fill in drive info below */
11771 ret = nvme_identify_ctrl(hdl, &ctrl);
11772 if (ret) {
11773 nvme_show_error("ERROR: WDC %s: Identify Controller failed", __func__)nvme_show_message(1, "ERROR: WDC %s: Identify Controller failed"
, __func__)
;
11774 return ret;
11775 }
11776
11777 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11778 if (ret || !wdc_check_device(ctx, hdl))
11779 return -1;
11780
11781 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11782
11783 if ((capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000) == WDC_DRIVE_CAP_INFO0x0000000000080000) {
11784 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11785 if (ret < 0) {
11786 nvme_show_error("ERROR: WDC: %s: failure to get pci ids, ret = %d", __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: failure to get pci ids, ret = %d"
, __func__, ret)
;
11787 goto out;
11788 }
11789
11790 switch (read_device_id) {
11791 case WDC_NVME_SN640_DEV_ID0x2400:
11792 case WDC_NVME_SN640_DEV_ID_10x2401:
11793 case WDC_NVME_SN640_DEV_ID_20x2402:
11794 case WDC_NVME_SN640_DEV_ID_30x2404:
11795 case WDC_NVME_SN650_DEV_ID0x2700:
11796 case WDC_NVME_SN650_DEV_ID_10x2701:
11797 case WDC_NVME_SN650_DEV_ID_20x2702:
11798 case WDC_NVME_SN650_DEV_ID_30x2720:
11799 case WDC_NVME_SN650_DEV_ID_40x2721:
11800 case WDC_NVME_SN655_DEV_ID0x2722:
11801 case WDC_NVME_SN655_DEV_ID_10x2723:
11802 case WDC_NVME_SN560_DEV_ID_10x2712:
11803 case WDC_NVME_SN560_DEV_ID_20x2713:
11804 case WDC_NVME_SN560_DEV_ID_30x2714:
11805 case WDC_NVME_SN550_DEV_ID0x2708:
11806 case WDC_NVME_ZN350_DEV_ID0x5010:
11807 case WDC_NVME_ZN350_DEV_ID_10x5018:
11808 ret = wdc_do_drive_info(hdl, &result);
11809
11810 if (!ret) {
11811 size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
11812 rev = (double)(cpu_to_le32(result) & 0x0000ffff);
11813
11814 if (fmt == NORMAL) {
11815 printf("Drive HW Revision: %4.1f\n", (.1 * rev));
11816 printf("FTL Unit Size: 0x%x KB\n", size);
11817 printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
11818 } else if (fmt == JSON) {
11819 root = json_create_object()json_object_new_object();
11820 sprintf(rev_str, "%4.1f", (.1 * rev));
11821 json_object_add_value_string(root, "Drive HW Revision", rev_str);
11822
11823 json_object_add_value_int(root, "FTL Unit Size", le16_to_cpu(size))json_object_object_add(root, "FTL Unit Size", json_object_new_int
(le16_to_cpu(size)))
;
11824 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
11825 json_object_add_value_string(root, "Customer SN", formatter);
11826
11827 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11828 printf("\n");
11829
11830 json_free_object(root)json_object_put(root);
11831 }
11832 }
11833 break;
11834 case WDC_NVME_SN730_DEV_ID0x5006:
11835 memcpy(vsData, &ctrl.vs[0], 32);
11836
11837 major_rev = ctrl.sn[12];
11838 minor_rev = ctrl.sn[13];
11839
11840 if (fmt == NORMAL) {
11841 printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev);
11842 printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
11843 } else if (fmt == JSON) {
11844 root = json_create_object()json_object_new_object();
11845 sprintf(rev_str, "%c.%c", major_rev, minor_rev);
11846 json_object_add_value_string(root, "Drive HW Revison", rev_str);
11847 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
11848 json_object_add_value_string(root, "Customer SN", formatter);
11849
11850 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11851 printf("\n");
11852
11853 json_free_object(root)json_object_put(root);
11854 }
11855 break;
11856 case WDC_NVME_SN820CL_DEV_ID0x5037:
11857 /* Get the Drive HW Rev from the C6 Log page */
11858 ret = nvme_get_hw_rev_log(hdl, &data, 0,
11859 NVME_NSID_ALL);
11860 if (!ret) {
11861 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
11862
11863 major_rev = log_data->hw_rev_gdr;
11864
11865 free(data);
11866 data = NULL((void*)0);
11867 } else {
11868 nvme_show_error("ERROR: WDC: %s: failure to get hw revision log", __func__)nvme_show_message(1, "ERROR: WDC: %s: failure to get hw revision log"
, __func__)
;
11869 ret = -1;
11870 goto out;
11871 }
11872
11873 /* Get the Smart C0 log page */
11874 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
11875 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11876 ret = -1;
11877 goto out;
11878 }
11879
11880 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
11881 0, NVME_NSID_ALL);
11882
11883 if (!ret) {
11884 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
11885
11886 /* Set the FTL Unit size */
11887 ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
11888
11889 /* Set the Boot Spec Version */
11890 boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
11891 boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
11892
11893 /* Set the Drive Ownership Status */
11894 tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
11895 free(data);
11896 } else {
11897 nvme_show_error("ERROR: WDC: %s: failure to get extended smart cloud log", __func__)nvme_show_message(1, "ERROR: WDC: %s: failure to get extended smart cloud log"
, __func__)
;
11898 ret = -1;
11899 goto out;
11900 }
11901
11902 if (fmt == NORMAL) {
11903 printf("Drive HW Revision: %2d\n", major_rev);
11904 printf("FTL Unit Size: %d\n", ftl_unit_size);
11905 printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
11906 printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
11907
11908 } else if (fmt == JSON) {
11909 root = json_create_object()json_object_new_object();
11910
11911 json_object_add_value_int(root, "Drive HW Revison", major_rev)json_object_object_add(root, "Drive HW Revison", json_object_new_int
(major_rev))
;
11912 json_object_add_value_int(root, "FTL Unit Size", ftl_unit_size)json_object_object_add(root, "FTL Unit Size", json_object_new_int
(ftl_unit_size))
;
11913 sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor);
11914 json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
11915 json_object_add_value_int(root, "TCG Device Ownership Status", tcg_dev_ownership)json_object_object_add(root, "TCG Device Ownership Status", json_object_new_int
(tcg_dev_ownership))
;
11916
11917 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11918 printf("\n");
11919
11920 json_free_object(root)json_object_put(root);
11921 }
11922
11923 break;
11924 case WDC_NVME_SN861_DEV_ID0x2750:
11925 case WDC_NVME_SN861_DEV_ID_10x2751:
11926 case WDC_NVME_SN861_DEV_ID_20x2752:
11927 data_len = sizeof(info);
11928 num_dwords = data_len / 4;
11929 if (data_len % 4 != 0)
11930 num_dwords += 1;
11931
11932 struct libnvme_passthru_cmd cmd = {
11933 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
11934 .cdw10 = num_dwords,
11935 .cdw12 = WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2,
11936 .addr = (__u64)(uintptr_t)&info,
11937 .data_len = data_len,
11938 };
11939 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11940 if (!ret) {
11941 __u16 hw_rev_major, hw_rev_minor;
11942
11943 hw_rev_major = le32_to_cpu(info.hw_revision) / 10;
11944 hw_rev_minor = le32_to_cpu(info.hw_revision) % 10;
11945 if (fmt == NORMAL) {
11946 printf("HW Revision : %" PRIu32"u" ".%" PRIu32"u" "\n",
11947 hw_rev_major, hw_rev_minor);
11948 printf("FTL Unit Size : %" PRIu32"u" "\n",
11949 le32_to_cpu(info.ftl_unit_size));
11950 } else if (fmt == JSON) {
11951 char buf[20];
11952
11953 root = json_create_object()json_object_new_object();
11954
11955 memset((void *)buf, 0, 20);
11956 sprintf(buf, "%" PRIu32"u" ".%" PRIu32"u",
11957 hw_rev_major, hw_rev_minor);
11958
11959 json_object_add_value_string(root,
11960 "hw_revision", buf);
11961 json_object_add_value_uint(root,json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
11962 "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
11963 le32_to_cpu(info.ftl_unit_size))json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
;
11964
11965 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11966 printf("\n");
11967 json_free_object(root)json_object_put(root);
11968 }
11969 }
11970 break;
11971 default:
11972 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11973 ret = -1;
11974 break;
11975 }
11976 } else {
11977 nvme_show_error("ERROR: WDC: capability not supported by this device")nvme_show_message(1, "ERROR: WDC: capability not supported by this device"
)
;
11978 ret = -1;
11979 }
11980
11981out:
11982 nvme_show_status(ret);
11983 return ret;
11984}
11985
11986static int wdc_vs_temperature_stats(int argc, char **argv,
11987 struct command *command, struct plugin *plugin)
11988{
11989 const char *desc = "Send a vs-temperature-stats command.";
11990 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11991 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11992 struct nvme_smart_log smart_log;
11993 struct nvme_id_ctrl id_ctrl;
11994 nvme_print_flags_t fmt;
11995 uint64_t capabilities = 0;
11996 __u64 hctm_tmt;
11997 int temperature, temp_tmt1, temp_tmt2;
11998 int ret;
11999
12000 struct config {
12001 char *output_format;
12002 };
12003
12004 struct config cfg = {
12005 .output_format = "normal",
12006 };
12007
12008 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12009
12010 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12011 if (ret)
12012 return ret;
12013
12014 cfg.output_format = nvme_args.output_format;
12015
12016 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12017 if (ret)
12018 return ret;
12019
12020 ret = validate_output_format(cfg.output_format, &fmt);
12021 if (ret < 0) {
12022 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12023 goto out;
12024 }
12025
12026 /* check if command is supported */
12027 wdc_check_device(ctx, hdl);
12028 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12029 if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) != WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) {
12030 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12031 ret = -1;
12032 goto out;
12033 }
12034
12035 /* get the temperature stats or report errors */
12036 ret = nvme_identify_ctrl(hdl, &id_ctrl);
12037 if (ret)
12038 goto out;
12039 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
12040 if (ret)
12041 goto out;
12042
12043 /* convert from kelvins to degrees Celsius */
12044 temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
12045
12046 /* retrieve HCTM Thermal Management Temperatures */
12047 nvme_get_features_simple(hdl, 0x10,
12048 NVME_GET_FEATURES_SEL_CURRENT, &hctm_tmt);
12049 temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
12050 temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
12051
12052 if (fmt == NORMAL) {
12053 /* print the temperature stats */
12054 printf("Temperature Stats for NVME device:%s namespace-id:%x\n",
12055 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
12056
12057 printf("Current Composite Temperature : %d °C\n", temperature);
12058 printf("WCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.wctemp - 273);
12059 printf("CCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.cctemp - 273);
12060 printf("DITT support : 0\n");
12061 printf("HCTM support : %"PRIu16"hu""\n", id_ctrl.hctma);
12062
12063 printf("HCTM Light (TMT1) : %"PRIu16"hu"" °C\n", temp_tmt1);
12064 printf("TMT1 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp1_trans_count);
12065 printf("TMT1 Total Time : %"PRIu32"u""\n", smart_log.thm_temp1_total_time);
12066
12067 printf("HCTM Heavy (TMT2) : %"PRIu16"hu"" °C\n", temp_tmt2);
12068 printf("TMT2 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp2_trans_count);
12069 printf("TMT2 Total Time : %"PRIu32"u""\n", smart_log.thm_temp2_total_time);
12070 printf("Thermal Shutdown Threshold : 95 °C\n");
12071 } else if (fmt == JSON) {
12072 struct json_object *root;
12073
12074 root = json_create_object()json_object_new_object();
12075
12076 json_object_add_value_int(root, "Current Composite Temperature", le32_to_cpu(temperature))json_object_object_add(root, "Current Composite Temperature",
json_object_new_int(le32_to_cpu(temperature)))
;
12077 json_object_add_value_int(root, "WCTEMP", le16_to_cpu(id_ctrl.wctemp - 273))json_object_object_add(root, "WCTEMP", json_object_new_int(le16_to_cpu
(id_ctrl.wctemp - 273)))
;
12078 json_object_add_value_int(root, "CCTEMP", le16_to_cpu(id_ctrl.cctemp - 273))json_object_object_add(root, "CCTEMP", json_object_new_int(le16_to_cpu
(id_ctrl.cctemp - 273)))
;
12079 json_object_add_value_int(root, "DITT support", 0)json_object_object_add(root, "DITT support", json_object_new_int
(0))
;
12080 json_object_add_value_int(root, "HCTM support", le16_to_cpu(id_ctrl.hctma))json_object_object_add(root, "HCTM support", json_object_new_int
(le16_to_cpu(id_ctrl.hctma)))
;
12081
12082 json_object_add_value_int(root, "HCTM Light (TMT1)", le16_to_cpu(temp_tmt1))json_object_object_add(root, "HCTM Light (TMT1)", json_object_new_int
(le16_to_cpu(temp_tmt1)))
;
12083 json_object_add_value_int(root, "TMT1 Transition Counter", le32_to_cpu(smart_log.thm_temp1_trans_count))json_object_object_add(root, "TMT1 Transition Counter", json_object_new_int
(le32_to_cpu(smart_log.thm_temp1_trans_count)))
;
12084 json_object_add_value_int(root, "TMT1 Total Time", le32_to_cpu(smart_log.thm_temp1_total_time))json_object_object_add(root, "TMT1 Total Time", json_object_new_int
(le32_to_cpu(smart_log.thm_temp1_total_time)))
;
12085
12086 json_object_add_value_int(root, "HCTM Light (TMT2)", le16_to_cpu(temp_tmt2))json_object_object_add(root, "HCTM Light (TMT2)", json_object_new_int
(le16_to_cpu(temp_tmt2)))
;
12087 json_object_add_value_int(root, "TMT2 Transition Counter", le32_to_cpu(smart_log.thm_temp2_trans_count))json_object_object_add(root, "TMT2 Transition Counter", json_object_new_int
(le32_to_cpu(smart_log.thm_temp2_trans_count)))
;
12088 json_object_add_value_int(root, "TMT2 Total Time", le32_to_cpu(smart_log.thm_temp2_total_time))json_object_object_add(root, "TMT2 Total Time", json_object_new_int
(le32_to_cpu(smart_log.thm_temp2_total_time)))
;
12089 json_object_add_value_int(root, "Thermal Shutdown Threshold", 95)json_object_object_add(root, "Thermal Shutdown Threshold", json_object_new_int
(95))
;
12090
12091 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12092 printf("\n");
12093
12094 json_free_object(root)json_object_put(root);
12095 } else {
12096 nvme_show_error("%s: Invalid format", __func__)nvme_show_message(1, "%s: Invalid format", __func__);
12097 }
12098
12099out:
12100 nvme_show_status(ret);
12101 return ret;
12102}
12103
12104static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12105{
12106 const char *desc = "Send a capabilities command.";
12107 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12108 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12109 uint64_t capabilities = 0;
12110 int ret;
12111
12112 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12113
12114 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12115 if (ret)
12116 return ret;
12117
12118 /* get capabilities */
12119 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12120 if (ret || !wdc_check_device(ctx, hdl))
12121 return -1;
12122
12123 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12124
12125 /* print command and supported status */
12126 printf("WDC Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
12127 printf("cap-diag : %s\n",
12128 capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 ? "Supported" : "Not Supported");
12129 printf("drive-log : %s\n",
12130 capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 ? "Supported" : "Not Supported");
12131 printf("get-crash-dump : %s\n",
12132 capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 ? "Supported" : "Not Supported");
12133 printf("get-pfail-dump : %s\n",
12134 capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 ? "Supported" : "Not Supported");
12135 printf("id-ctrl : Supported\n");
12136 printf("purge : %s\n",
12137 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12138 printf("purge-monitor : %s\n",
12139 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12140 printf("vs-internal-log : %s\n",
12141 capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
? "Supported" : "Not Supported");
12142 printf("vs-nand-stats : %s\n",
12143 capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
12144 printf("vs-smart-add-log : %s\n",
12145 capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
12146 printf("--C0 Log Page : %s\n",
12147 capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
12148 printf("--C1 Log Page : %s\n",
12149 capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
12150 printf("--C3 Log Page : %s\n",
12151 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12152 printf("--CA Log Page : %s\n",
12153 capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
12154 printf("--D0 Log Page : %s\n",
12155 capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
12156 printf("clear-pcie-correctable-errors : %s\n",
12157 capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
12158 printf("drive-essentials : %s\n",
12159 capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 ? "Supported" : "Not Supported");
12160 printf("get-drive-status : %s\n",
12161 capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
12162 printf("clear-assert-dump : %s\n",
12163 capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
12164 printf("drive-resize : %s\n",
12165 capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100 ? "Supported" : "Not Supported");
12166 printf("vs-fw-activate-history : %s\n",
12167 capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" : "Not Supported");
12168 printf("clear-fw-activate-history : %s\n",
12169 capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" : "Not Supported");
12170 printf("vs-telemetry-controller-option: %s\n",
12171 capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
12172 printf("vs-error-reason-identifier : %s\n",
12173 capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
12174 printf("log-page-directory : %s\n",
12175 capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
12176 printf("namespace-resize : %s\n",
12177 capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
12178 printf("vs-drive-info : %s\n",
12179 capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
12180 printf("vs-temperature-stats : %s\n",
12181 capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
12182 printf("cloud-SSD-plugin-version : %s\n",
12183 capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
12184 printf("vs-pcie-stats : %s\n",
12185 capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
12186 printf("get-error-recovery-log : %s\n",
12187 capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
12188 printf("get-dev-capabilities-log : %s\n",
12189 capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
12190 printf("get-unsupported-reqs-log : %s\n",
12191 capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
12192 printf("get-latency-monitor-log : %s\n",
12193 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12194 printf("cloud-boot-SSD-version : %s\n",
12195 capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" : "Not Supported");
12196 printf("vs-cloud-log : %s\n",
12197 capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
12198 printf("vs-hw-rev-log : %s\n",
12199 capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
12200 printf("vs-device_waf : %s\n",
12201 capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
12202 printf("set-latency-monitor-feature : %s\n",
12203 capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
12204 printf("capabilities : Supported\n");
12205 return 0;
12206}
12207
12208static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd,
12209 struct plugin *plugin)
12210{
12211 const char *desc = "Get Cloud SSD Plugin Version command.";
12212 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12213 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12214 uint64_t capabilities = 0;
12215 int ret;
12216
12217 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12218
12219 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12220 if (ret)
12221 return ret;
12222
12223 /* get capabilities */
12224 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12225 if (ret || !wdc_check_device(ctx, hdl))
12226 return -1;
12227
12228 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12229
12230 if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) {
12231 /* print command and supported status */
12232 printf("WDC Cloud SSD Plugin Version: 1.0\n");
12233 } else {
12234 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12235 }
12236
12237 return 0;
12238}
12239
12240static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd,
12241 struct plugin *plugin)
12242{
12243 const char *desc = "Get Cloud Boot SSD Version command.";
12244 const char *namespace_id = "desired namespace id";
12245 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12246 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12247 uint64_t capabilities = 0;
12248 int ret;
12249 int major = 0, minor = 0;
12250 __u8 *data = NULL((void*)0);
12251 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12252
12253 struct config {
12254 __u32 namespace_id;
12255 };
12256
12257 struct config cfg = {
12258 .namespace_id = NVME_NSID_ALL,
12259 };
12260
12261 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12262 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12263
12264 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12265 if (ret)
12266 return ret;
12267
12268 /* get capabilities */
12269 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12270 if (ret || !wdc_check_device(ctx, hdl))
12271 return -1;
12272
12273 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12274
12275 if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) {
12276 /* Get the 0xC0 Smart Cloud Attribute V1 log data */
12277 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
12278 cfg.namespace_id);
12279
12280 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12281 if (!ret) {
12282 major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12283 minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12284
12285 /* print the version returned from the log page */
12286 printf("HyperScale Boot Version: %d.%d\n", major, minor);
12287 } else {
12288 nvme_show_error("ERROR: WDC: Unable to read Extended Smart/C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read Extended Smart/C0 Log Page data"
)
;
12289 ret = -1;
12290 }
12291
12292 free(data);
12293 } else {
12294 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12295 }
12296
12297 return ret;
12298}
12299
12300static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12301{
12302 const char *desc = "Get Enclosure Log.";
12303 const char *file = "Output file pathname.";
12304 const char *size = "Data retrieval transfer size.";
12305 const char *log = "Enclosure Log Page ID.";
12306 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12307 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12308 FILE *output_fd;
12309 int xfer_size = 0;
12310 int len;
12311 int err = 0;
12312
12313 struct config {
12314 char *file;
12315 __u32 xfer_size;
12316 __u32 log_id;
12317 };
12318
12319 struct config cfg = {
12320 .file = NULL((void*)0),
12321 .xfer_size = 0,
12322 .log_id = 0xffffffff,
12323 };
12324
12325 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"log-id", 'l', "NUM", CFG_POSITIVE
, &cfg.log_id, 1, log, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12326 OPT_FILE("output-file", 'O', &cfg.file, file),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"log-id", 'l', "NUM", CFG_POSITIVE
, &cfg.log_id, 1, log, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12327 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"log-id", 'l', "NUM", CFG_POSITIVE
, &cfg.log_id, 1, log, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12328 OPT_UINT("log-id", 'l', &cfg.log_id, log))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"log-id", 'l', "NUM", CFG_POSITIVE
, &cfg.log_id, 1, log, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12329
12330 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12331 if (err)
12332 return err;
12333
12334 if (!wdc_enc_check_model(hdl))
12335 return -EINVAL22;
12336
12337 if (cfg.log_id > 0xff) {
12338 nvme_show_error(nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12339 "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n",nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12340 cfg.log_id)nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
;
12341 return -EINVAL22;
12342 }
12343
12344 if (cfg.xfer_size) {
12345 xfer_size = cfg.xfer_size;
12346 if (!wdc_check_power_of_2(cfg.xfer_size)) {
12347 nvme_show_error("%s: ERROR: xfer-size (%d) must be a power of 2",nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
12348 __func__, cfg.xfer_size)nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
;
12349 return -EINVAL22;
12350 }
12351 }
12352
12353 /* Log IDs are only for specific enclosures */
12354 if (cfg.log_id) {
12355 xfer_size = (xfer_size) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000;
12356 len = !cfg.file ? 0 : strlen(cfg.file);
12357 if (len > 0) {
12358 output_fd = fopen(cfg.file, "wb");
12359 if (!output_fd) {
12360 nvme_show_error("%s: ERROR: opening:%s: %s", __func__, cfg.file,nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
12361 libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
;
12362 return -EINVAL22;
12363 }
12364 } else {
12365 output_fd = stdoutstdout;
12366 }
12367 if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 ||
12368 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 ||
12369 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 ||
12370 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4) {
12371 nvme_show_error("args - sz:%x logid:%x of:%s", xfer_size, cfg.log_id,nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
12372 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12373 err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size,
12374 WDC_NVME_ENC_NIC_LOG_SIZE0x400000, output_fd);
12375 } else {
12376 nvme_show_error("args - sz:%x logid:%x of:%s", xfer_size, cfg.log_id,nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
12377 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12378 err = wdc_enc_submit_move_data(hdl, NULL((void*)0), 0, xfer_size, output_fd,
12379 cfg.log_id, 0, 0);
12380 }
12381
12382 if (err == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12383 nvme_show_error("No Log/Crashdump available")nvme_show_message(1, "No Log/Crashdump available");
12384 err = 0;
12385 } else if (err) {
12386 nvme_show_error("ERROR: 0x%x Failed to collect log-id:%x", err,nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
12387 cfg.log_id)nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
;
12388 }
12389 }
12390 return err;
12391}
12392
12393static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len,
12394 int xfer_size, FILE *out, int log_id,
12395 int cdw14, int cdw15)
12396{
12397 struct timespec time;
12398 uint32_t response_size, more;
12399 int err;
12400 int handle;
12401 uint32_t offset = 0;
12402 char *buf;
12403
12404 buf = malloc(xfer_size);
12405 if (!buf) {
12406 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12407 return -1;
12408 }
12409 /* send something no matter what */
12410 cmd = (len) ? cmd : buf;
12411 len = (len) ? len : 0x20;
12412
12413 struct libnvme_passthru_cmd nvme_cmd = {
12414 .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND0xC9,
12415 .nsid = 0,
12416 .addr = (__u64)(uintptr_t) cmd,
12417 .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t),
12418 .cdw10 = len,
12419 .cdw12 = log_id,
12420 .cdw13 = 0,
12421 .cdw14 = cdw14,
12422 .cdw15 = cdw15,
12423 };
12424
12425 clock_gettime(CLOCK_REALTIME0, &time);
12426 srand(time.tv_nsec);
12427 handle = random(); /* Handle to associate send request with receive request */
12428 nvme_cmd.cdw11 = handle;
12429
12430#ifdef WDC_NVME_CLI_DEBUG
12431 unsigned char *d = (unsigned char *)nvme_cmd.addr;
12432 unsigned char *md = (unsigned char *)nvme_cmd.metadata;
12433
12434 printf("NVME_ADMIN_COMMAND:\n");
12435 printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ",
12436 nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2);
12437 printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, "
12438 nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10);
12439 printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, "
12440 nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15);
12441 printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n",
12442 nvme_cmd.timeout_ms, nvme_cmd.result, md, d);
12443#endif
12444 nvme_cmd.result = 0;
12445 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12446 if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) {
12447 nvme_show_error("%s: WARNING : WDC: No log ID:x%x available", __func__, log_id)nvme_show_message(1, "%s: WARNING : WDC: No log ID:x%x available"
, __func__, log_id)
;
12448 } else if (err) {
12449 nvme_show_error("%s: ERROR: WDC: NVMe Snd Mgmt", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Snd Mgmt", __func__
)
;
12450 nvme_show_status(err);
12451 } else {
12452 if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12453 free(buf);
12454 return WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF;
12455 }
12456
12457 do {
12458 /* Sent request, now go retrieve response */
12459 nvme_cmd.flags = 0;
12460 nvme_cmd.opcode = WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA;
12461 nvme_cmd.addr = (__u64)(uintptr_t) buf;
12462 nvme_cmd.data_len = xfer_size;
12463 nvme_cmd.cdw10 = xfer_size / sizeof(uint32_t);
12464 nvme_cmd.cdw11 = handle;
12465 nvme_cmd.cdw12 = log_id;
12466 nvme_cmd.cdw13 = offset / sizeof(uint32_t);
12467 nvme_cmd.cdw14 = cdw14;
12468 nvme_cmd.cdw15 = cdw15;
12469 nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
12470 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12471 if (err) {
12472 more = 0;
12473 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__
)
;
12474 nvme_show_status(err);
12475 } else {
12476 more = nvme_cmd.result & WDC_RESULT_MORE_DATA0x80000000;
12477 response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA0x80000000;
12478 fwrite(buf, response_size, 1, out);
12479 offset += response_size;
12480 if (more && (response_size & (sizeof(uint32_t)-1))) {
12481 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned",nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
12482 __func__, response_size)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
;
12483 }
12484 }
12485 } while (more);
12486 }
12487
12488 free(buf);
12489 return err;
12490}
12491
12492static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out)
12493{
12494 __u8 *dump_data;
12495 __u32 curr_data_offset, curr_data_len;
12496 int i, ret = -1;
12497 struct libnvme_passthru_cmd admin_cmd;
12498 __u32 dump_length = data_len;
12499 __u32 numd;
12500 __u16 numdu, numdl;
12501
12502 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
12503 if (!dump_data) {
12504 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12505 return -1;
12506 }
12507 memset(dump_data, 0, sizeof(__u8) * dump_length);
12508 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12509 curr_data_offset = 0;
12510 curr_data_len = xfer_size;
12511 i = 0;
12512
12513 numd = (curr_data_len >> 2) - 1;
12514 numdu = numd >> 16;
12515 numdl = numd & 0xffff;
12516 admin_cmd.opcode = nvme_admin_get_log_page;
12517 admin_cmd.nsid = curr_data_offset;
12518 admin_cmd.addr = (__u64)(uintptr_t) dump_data;
12519 admin_cmd.data_len = curr_data_len;
12520 admin_cmd.cdw10 = log_id | (numdl << 16);
12521 admin_cmd.cdw11 = numdu;
12522
12523 while (curr_data_offset < data_len) {
12524#ifdef WDC_NVME_CLI_DEBUG
12525 nvme_show_error(nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
12526 "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n",nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
12527 admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10,nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
12528 admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14)nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
;
12529#endif
12530 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
12531 if (ret) {
12532 nvme_show_status(ret);
12533 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
12534 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
12535 break;
12536 }
12537
12538 if ((curr_data_offset + xfer_size) <= data_len)
12539 curr_data_len = xfer_size;
12540 else
12541 curr_data_len = data_len - curr_data_offset; /* last transfer */
12542
12543 curr_data_offset += curr_data_len;
12544 numd = (curr_data_len >> 2) - 1;
12545 numdu = numd >> 16;
12546 numdl = numd & 0xffff;
12547 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
12548 admin_cmd.nsid = curr_data_offset;
12549 admin_cmd.data_len = curr_data_len;
12550 admin_cmd.cdw10 = log_id | (numdl << 16);
12551 admin_cmd.cdw11 = numdu;
12552 i++;
12553 }
12554 fwrite(dump_data, data_len, 1, out);
12555 free(dump_data);
12556 return ret;
12557}
12558
12559//------------------------------------------------------------------------------------
12560// Description: set latency monitor feature
12561//
12562int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd,
12563 struct plugin *plugin)
12564{
12565 const char *desc = "Set Latency Monitor feature.";
12566
12567 struct feature_latency_monitor buf = {0,};
12568 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12569 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12570 uint64_t capabilities = 0;
12571 __u64 result;
12572 int ret;
12573
12574 const char *active_bucket_timer_threshold =
12575 "This is the value that loads the Active Bucket Timer Threshold.";
12576 const char *active_threshold_a =
12577 "This is the value that loads into the Active Threshold A.";
12578 const char *active_threshold_b =
12579 "This is the value that loads into the Active Threshold B.";
12580 const char *active_threshold_c =
12581 "This is the value that loads into the Active Threshold C.";
12582 const char *active_threshold_d =
12583 "This is the value that loads into the Active Threshold D.";
12584 const char *active_latency_config =
12585 "This is the value that loads into the Active Latency Configuration.";
12586 const char *active_latency_minimum_window =
12587 "This is the value that loads into the Active Latency Minimum Window.";
12588 const char *debug_log_trigger_enable =
12589 "This is the value that loads into the Debug Log Trigger Enable.";
12590 const char *discard_debug_log = "Discard Debug Log.";
12591 const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable.";
12592
12593 struct config {
12594 __u16 active_bucket_timer_threshold;
12595 __u8 active_threshold_a;
12596 __u8 active_threshold_b;
12597 __u8 active_threshold_c;
12598 __u8 active_threshold_d;
12599 __u16 active_latency_config;
12600 __u8 active_latency_minimum_window;
12601 __u16 debug_log_trigger_enable;
12602 __u8 discard_debug_log;
12603 __u8 latency_monitor_feature_enable;
12604 };
12605
12606 struct config cfg = {
12607 .active_bucket_timer_threshold = 0x7E0,
12608 .active_threshold_a = 0x5,
12609 .active_threshold_b = 0x13,
12610 .active_threshold_c = 0x1E,
12611 .active_threshold_d = 0x2E,
12612 .active_latency_config = 0xFFF,
12613 .active_latency_minimum_window = 0xA,
12614 .debug_log_trigger_enable = 0,
12615 .discard_debug_log = 0,
12616 .latency_monitor_feature_enable = 0x7,
12617 };
12618
12619 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12620 OPT_UINT("active_bucket_timer_threshold", 't',nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12621 &cfg.active_bucket_timer_threshold,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12622 active_bucket_timer_threshold),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12623 OPT_UINT("active_threshold_a", 'a', &cfg.active_threshold_a,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12624 active_threshold_a),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12625 OPT_UINT("active_threshold_b", 'b', &cfg.active_threshold_b,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12626 active_threshold_b),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12627 OPT_UINT("active_threshold_c", 'c', &cfg.active_threshold_c,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12628 active_threshold_c),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12629 OPT_UINT("active_threshold_d", 'd', &cfg.active_threshold_d,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12630 active_threshold_d),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12631 OPT_UINT("active_latency_config", 'f',nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12632 &cfg.active_latency_config, active_latency_config),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12633 OPT_UINT("active_latency_minimum_window", 'w',nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12634 &cfg.active_latency_minimum_window,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12635 active_latency_minimum_window),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12636 OPT_UINT("debug_log_trigger_enable", 'r',nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12637 &cfg.debug_log_trigger_enable, debug_log_trigger_enable),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12638 OPT_UINT("discard_debug_log", 'l', &cfg.discard_debug_log,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12639 discard_debug_log),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12640 OPT_UINT("latency_monitor_feature_enable", 'e',nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12641 &cfg.latency_monitor_feature_enable,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
12642 latency_monitor_feature_enable))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"active_bucket_timer_threshold", 't', "NUM", CFG_POSITIVE
, &cfg.active_bucket_timer_threshold, 1, active_bucket_timer_threshold
, 0, }, {"active_threshold_a", 'a', "NUM", CFG_POSITIVE, &
cfg.active_threshold_a, 1, active_threshold_a, 0, }, {"active_threshold_b"
, 'b', "NUM", CFG_POSITIVE, &cfg.active_threshold_b, 1, active_threshold_b
, 0, }, {"active_threshold_c", 'c', "NUM", CFG_POSITIVE, &
cfg.active_threshold_c, 1, active_threshold_c, 0, }, {"active_threshold_d"
, 'd', "NUM", CFG_POSITIVE, &cfg.active_threshold_d, 1, active_threshold_d
, 0, }, {"active_latency_config", 'f', "NUM", CFG_POSITIVE, &
cfg.active_latency_config, 1, active_latency_config, 0, }, {"active_latency_minimum_window"
, 'w', "NUM", CFG_POSITIVE, &cfg.active_latency_minimum_window
, 1, active_latency_minimum_window, 0, }, {"debug_log_trigger_enable"
, 'r', "NUM", CFG_POSITIVE, &cfg.debug_log_trigger_enable
, 1, debug_log_trigger_enable, 0, }, {"discard_debug_log", 'l'
, "NUM", CFG_POSITIVE, &cfg.discard_debug_log, 1, discard_debug_log
, 0, }, {"latency_monitor_feature_enable", 'e', "NUM", CFG_POSITIVE
, &cfg.latency_monitor_feature_enable, 1, latency_monitor_feature_enable
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
12643
12644 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12645
12646 if (ret < 0)
12647 return ret;
12648
12649 /* get capabilities */
12650 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12651 if (ret || !wdc_check_device(ctx, hdl))
12652 return -1;
12653
12654 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12655
12656 if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000)) {
12657 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12658 return -1;
12659 }
12660
12661 memset(&buf, 0, sizeof(struct feature_latency_monitor));
12662
12663 buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold;
12664 buf.active_threshold_a = cfg.active_threshold_a;
12665 buf.active_threshold_b = cfg.active_threshold_b;
12666 buf.active_threshold_c = cfg.active_threshold_c;
12667 buf.active_threshold_d = cfg.active_threshold_d;
12668 buf.active_latency_config = cfg.active_latency_config;
12669 buf.active_latency_minimum_window = cfg.active_latency_minimum_window;
12670 buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable;
12671 buf.discard_debug_log = cfg.discard_debug_log;
12672 buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable;
12673
12674 ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR0xC5, 1, 0, 0, 0,
12675 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result);
12676
12677 if (ret < 0) {
12678 nvme_show_err(ret, "set-feature");
12679 } else if (!ret) {
12680 printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n",
12681 NVME_FEAT_OCP_LATENCY_MONITOR0xC5);
12682 printf("active bucket timer threshold: 0x%x\n",
12683 buf.active_bucket_timer_threshold);
12684 printf("active threshold a: 0x%x\n", buf.active_threshold_a);
12685 printf("active threshold b: 0x%x\n", buf.active_threshold_b);
12686 printf("active threshold c: 0x%x\n", buf.active_threshold_c);
12687 printf("active threshold d: 0x%x\n", buf.active_threshold_d);
12688 printf("active latency config: 0x%x\n", buf.active_latency_config);
12689 printf("active latency minimum window: 0x%x\n",
12690 buf.active_latency_minimum_window);
12691 printf("debug log trigger enable: 0x%x\n",
12692 buf.debug_log_trigger_enable);
12693 printf("discard debug log: 0x%x\n", buf.discard_debug_log);
12694 printf("latency monitor feature enable: 0x%x\n",
12695 buf.latency_monitor_feature_enable);
12696 } else if (ret > 0)
12697 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
12698 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
12699
12700 return ret;
12701}
12702
12703/*
12704 * Externally available functions used to call the WDC Plugin commands
12705 */
12706int run_wdc_cloud_ssd_plugin_version(int argc, char **argv,
12707 struct command *command,
12708 struct plugin *plugin)
12709{
12710 return wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
12711}
12712
12713int run_wdc_vs_internal_fw_log(int argc, char **argv,
12714 struct command *command,
12715 struct plugin *plugin)
12716{
12717 return wdc_vs_internal_fw_log(argc, argv, command, plugin);
12718}
12719
12720int run_wdc_vs_nand_stats(int argc, char **argv,
12721 struct command *command,
12722 struct plugin *plugin)
12723{
12724 return wdc_vs_nand_stats(argc, argv, command, plugin);
12725}
12726
12727int run_wdc_vs_smart_add_log(int argc, char **argv,
12728 struct command *command,
12729 struct plugin *plugin)
12730{
12731 return wdc_vs_smart_add_log(argc, argv, command, plugin);
12732}
12733
12734int run_wdc_clear_pcie_correctable_errors(int argc, char **argv,
12735 struct command *command,
12736 struct plugin *plugin)
12737{
12738 return wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
12739}
12740
12741int run_wdc_drive_status(int argc, char **argv,
12742 struct command *command,
12743 struct plugin *plugin)
12744{
12745 return wdc_drive_status(argc, argv, command, plugin);
12746}
12747
12748int run_wdc_clear_assert_dump(int argc, char **argv,
12749 struct command *command,
12750 struct plugin *plugin)
12751{
12752 return wdc_clear_assert_dump(argc, argv, command, plugin);
12753}
12754
12755int run_wdc_drive_resize(int argc, char **argv,
12756 struct command *command,
12757 struct plugin *plugin)
12758{
12759 return wdc_drive_resize(argc, argv, command, plugin);
12760}
12761
12762int run_wdc_vs_fw_activate_history(int argc, char **argv,
12763 struct command *command,
12764 struct plugin *plugin)
12765{
12766 return wdc_vs_fw_activate_history(argc, argv, command, plugin);
12767}
12768
12769int run_wdc_clear_fw_activate_history(int argc, char **argv,
12770 struct command *command,
12771 struct plugin *plugin)
12772{
12773 return wdc_clear_fw_activate_history(argc, argv, command, plugin);
12774}
12775
12776int run_wdc_vs_telemetry_controller_option(int argc, char **argv,
12777 struct command *command,
12778 struct plugin *plugin)
12779{
12780 return wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
12781}
12782
12783int run_wdc_reason_identifier(int argc, char **argv,
12784 struct command *command,
12785 struct plugin *plugin)
12786{
12787 return wdc_reason_identifier(argc, argv, command, plugin);
12788}
12789
12790int run_wdc_log_page_directory(int argc, char **argv,
12791 struct command *command,
12792 struct plugin *plugin)
12793{
12794 return wdc_log_page_directory(argc, argv, command, plugin);
12795}
12796
12797int run_wdc_namespace_resize(int argc, char **argv,
12798 struct command *command,
12799 struct plugin *plugin)
12800{
12801 return wdc_namespace_resize(argc, argv, command, plugin);
12802}
12803
12804int run_wdc_vs_drive_info(int argc, char **argv,
12805 struct command *command,
12806 struct plugin *plugin)
12807{
12808 return wdc_vs_drive_info(argc, argv, command, plugin);
12809}
12810
12811int run_wdc_vs_pcie_stats(int argc, char **argv,
12812 struct command *command,
12813 struct plugin *plugin)
12814{
12815 return wdc_vs_pcie_stats(argc, argv, command, plugin);
12816}
12817
12818int run_wdc_get_latency_monitor_log(int argc, char **argv,
12819 struct command *command,
12820 struct plugin *plugin)
12821{
12822 return wdc_get_latency_monitor_log(argc, argv, command, plugin);
12823}
12824
12825int run_wdc_get_error_recovery_log(int argc, char **argv,
12826 struct command *command,
12827 struct plugin *plugin)
12828{
12829 return wdc_get_error_recovery_log(argc, argv, command, plugin);
12830}
12831
12832int run_wdc_get_dev_capabilities_log(int argc, char **argv,
12833 struct command *command,
12834 struct plugin *plugin)
12835{
12836 return wdc_get_dev_capabilities_log(argc, argv, command, plugin);
12837}
12838
12839int run_wdc_get_unsupported_reqs_log(int argc, char **argv,
12840 struct command *command,
12841 struct plugin *plugin)
12842{
12843 return wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
12844}
12845
12846int run_wdc_cloud_boot_SSD_version(int argc, char **argv,
12847 struct command *command,
12848 struct plugin *plugin)
12849{
12850 return wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
12851}
12852
12853int run_wdc_vs_cloud_log(int argc, char **argv,
12854 struct command *command,
12855 struct plugin *plugin)
12856{
12857 return wdc_vs_cloud_log(argc, argv, command, plugin);
12858}
12859
12860int run_wdc_vs_hw_rev_log(int argc, char **argv,
12861 struct command *command,
12862 struct plugin *plugin)
12863{
12864 return wdc_vs_hw_rev_log(argc, argv, command, plugin);
12865}
12866
12867int run_wdc_vs_device_waf(int argc, char **argv,
12868 struct command *command,
12869 struct plugin *plugin)
12870{
12871 return wdc_vs_device_waf(argc, argv, command, plugin);
12872}
12873
12874int run_wdc_set_latency_monitor_feature(int argc, char **argv,
12875 struct command *command,
12876 struct plugin *plugin)
12877{
12878 return wdc_set_latency_monitor_feature(argc, argv, command, plugin);
12879}
12880
12881int run_wdc_vs_temperature_stats(int argc, char **argv,
12882 struct command *command,
12883 struct plugin *plugin)
12884{
12885 return wdc_vs_temperature_stats(argc, argv, command, plugin);
12886}
12887
12888int run_wdc_cu_smart_log(int argc, char **argv,
12889 struct command *command,
12890 struct plugin *plugin)
12891{
12892 return wdc_cu_smart_log(argc, argv, command, plugin);
12893}
12894
12895
12896__u32 run_wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx,
12897 struct libnvme_transport_handle *hdl)
12898{
12899 return wdc_get_fw_cust_id(ctx, hdl);
12900}
12901
12902bool_Bool run_wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
12903 struct libnvme_transport_handle *hdl,
12904 __u8 log_id,
12905 __u8 uuid_index)
12906{
12907 return wdc_nvme_check_supported_log_page(ctx,
12908 hdl,
12909 log_id,
12910 uuid_index);
12911}
12912
12913__u64 run_wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx,
12914 struct libnvme_transport_handle *hdl)
12915{
12916 return wdc_get_drive_capabilities(ctx, hdl);
12917}