Bug Summary

File:.build-ci/../plugins/wdc/wdc-nvme.c
Warning:line 12432, column 8
Opened stream never closed. Potential resource leak

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 /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=gnu11 -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-09-23-073103-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 <errno(*__errno_location ()).h>
26#include <fcntl.h>
27#include <inttypes.h>
28#include <limits.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#include <libnvme.h>
35
36#include <ccan/array_size/array_size.h>
37#include <ccan/endian/endian.h>
38#include <ccan/minmax/minmax.h>
39#include <shared/compiler-attributes-util.h>
40#include <shared/crypto-util.h>
41#include <shared/fs-util.h>
42#include <shared/io-util.h>
43#include <shared/parse-util.h>
44#include <shared/time-util.h>
45#include <shared/uint128-util.h>
46
47#include "global-ctx.h"
48#include "nvme-cmds.h"
49#include "nvme-pci-ids.h"
50#include "nvme-print.h"
51#include "plugin.h"
52#include "src/cleanup.h"
53
54#define WDC_PLUGIN_VERSION"2.15.1" "2.15.1"
55
56#include "wdc-utils.h"
57
58#define WRITE_SIZE(sizeof(__u8) * 4096) (sizeof(__u8) * 4096)
59
60#define WDC_NVME_SUBCMD_SHIFT8 8
61
62#define WDC_NVME_LOG_SIZE_DATA_LEN0x08 0x08
63#define WDC_NVME_LOG_SIZE_HDR_LEN0x08 0x08
64
65/* Enclosure */
66#define WDC_OPENFLEX_MI_DEVICE_MODEL"OpenFlex" "OpenFlex"
67#define WDC_RESULT_MORE_DATA0x80000000 0x80000000
68#define WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF 0x7FFFFFFF
69
70/* Device Config */
71#define WDC_NVME_VID0x1c58 0x1c58
72#define WDC_NVME_VID_20x1b96 0x1b96
73#define WDC_NVME_SNDK_VID0x15b7 0x15b7
74
75#define WDC_NVME_SN100_DEV_ID0x0003 0x0003
76#define WDC_NVME_SN200_DEV_ID0x0023 0x0023
77#define WDC_NVME_SN630_DEV_ID0x2200 0x2200
78#define WDC_NVME_SN630_DEV_ID_10x2201 0x2201
79#define WDC_NVME_SN840_DEV_ID0x2300 0x2300
80#define WDC_NVME_SN840_DEV_ID_10x2500 0x2500
81#define WDC_NVME_SN640_DEV_ID0x2400 0x2400
82#define WDC_NVME_SN640_DEV_ID_10x2401 0x2401
83#define WDC_NVME_SN640_DEV_ID_20x2402 0x2402
84#define WDC_NVME_SN640_DEV_ID_30x2404 0x2404
85#define WDC_NVME_ZN540_DEV_ID0x2600 0x2600
86#define WDC_NVME_SN540_DEV_ID0x2610 0x2610
87#define WDC_NVME_SN650_DEV_ID0x2700 0x2700
88#define WDC_NVME_SN650_DEV_ID_10x2701 0x2701
89#define WDC_NVME_SN650_DEV_ID_20x2702 0x2702
90#define WDC_NVME_SN650_DEV_ID_30x2720 0x2720
91#define WDC_NVME_SN650_DEV_ID_40x2721 0x2721
92#define WDC_NVME_SN655_DEV_ID0x2722 0x2722
93#define WDC_NVME_SN655_DEV_ID_10x2723 0x2723
94#define WDC_NVME_SN860_DEV_ID0x2730 0x2730
95#define WDC_NVME_SN660_DEV_ID0x2704 0x2704
96#define WDC_NVME_SN560_DEV_ID_10x2712 0x2712
97#define WDC_NVME_SN560_DEV_ID_20x2713 0x2713
98#define WDC_NVME_SN560_DEV_ID_30x2714 0x2714
99#define WDC_NVME_SN861_DEV_ID0x2750 0x2750
100#define WDC_NVME_SN861_DEV_ID_10x2751 0x2751
101#define WDC_NVME_SN861_DEV_ID_20x2752 0x2752
102#define WDC_NVME_SNTMP_DEV_ID0x2761 0x2761
103#define WDC_NVME_SNTMP_DEV_ID_10x2763 0x2763
104
105#define WDC_NVME_SNESSD1_DEV_ID_E1L0x2765 0x2765
106#define WDC_NVME_SNESSD1_DEV_ID_E20x2766 0x2766
107#define WDC_NVME_SNESSD1_DEV_ID_E3S0x2767 0x2767
108#define WDC_NVME_SNESSD1_DEV_ID_E3L0x2768 0x2768
109#define WDC_NVME_SNESSD1_DEV_ID_U20x2769 0x2769
110
111/* This id's are no longer supported, delete ?? */
112#define WDC_NVME_SN550_DEV_ID0x2708 0x2708
113
114#define WDC_NVME_SXSLCL_DEV_ID0x2001 0x2001
115#define WDC_NVME_SN520_DEV_ID0x5003 0x5003
116#define WDC_NVME_SN520_DEV_ID_10x5004 0x5004
117#define WDC_NVME_SN520_DEV_ID_20x5005 0x5005
118
119#define WDC_NVME_SN530_DEV_ID_10x5007 0x5007
120#define WDC_NVME_SN530_DEV_ID_20x5008 0x5008
121#define WDC_NVME_SN530_DEV_ID_30x5009 0x5009
122#define WDC_NVME_SN530_DEV_ID_40x500b 0x500b
123#define WDC_NVME_SN530_DEV_ID_50x501d 0x501d
124
125#define WDC_NVME_SN350_DEV_ID0x5019 0x5019
126
127#define WDC_NVME_SN570_DEV_ID0x501A 0x501A
128
129#define WDC_NVME_SN850X_DEV_ID0x5030 0x5030
130
131#define WDC_NVME_SN5000_DEV_ID_10x5034 0x5034
132#define WDC_NVME_SN5000_DEV_ID_20x5035 0x5035
133#define WDC_NVME_SN5000_DEV_ID_30x5036 0x5036
134#define WDC_NVME_SN5000_DEV_ID_40x504A 0x504A
135
136#define WDC_NVME_SN7000S_DEV_ID_10x5039 0x5039
137
138#define WDC_NVME_SN7150_DEV_ID_10x503b 0x503b
139#define WDC_NVME_SN7150_DEV_ID_20x503c 0x503c
140#define WDC_NVME_SN7150_DEV_ID_30x503d 0x503d
141#define WDC_NVME_SN7150_DEV_ID_40x503e 0x503e
142#define WDC_NVME_SN7150_DEV_ID_50x503f 0x503f
143
144#define WDC_NVME_SN7100_DEV_ID_10x5043 0x5043
145#define WDC_NVME_SN7100_DEV_ID_20x5044 0x5044
146#define WDC_NVME_SN7100_DEV_ID_30x5045 0x5045
147
148#define WDC_NVME_SN8000S_DEV_ID0x5049 0x5049
149
150#define WDC_NVME_SN720_DEV_ID0x5002 0x5002
151#define WDC_NVME_SN730_DEV_ID0x5006 0x5006
152#define WDC_NVME_SN740_DEV_ID0x5015 0x5015
153#define WDC_NVME_SN740_DEV_ID_10x5016 0x5016
154#define WDC_NVME_SN740_DEV_ID_20x5017 0x5017
155#define WDC_NVME_SN740_DEV_ID_30x5025 0x5025
156#define WDC_NVME_SN340_DEV_ID0x500d 0x500d
157#define WDC_NVME_ZN350_DEV_ID0x5010 0x5010
158#define WDC_NVME_ZN350_DEV_ID_10x5018 0x5018
159#define WDC_NVME_SN810_DEV_ID0x5011 0x5011
160#define WDC_NVME_SN820CL_DEV_ID0x5037 0x5037
161
162#define WDC_NVME_SN5100S_DEV_ID_10x5061 0x5061
163#define WDC_NVME_SN5100S_DEV_ID_20x5062 0x5062
164#define WDC_NVME_SN5100S_DEV_ID_30x5063 0x5063
165
166/* Shared flag space with SNDK plugin, should be kept in sync */
167#define WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 0x0000000000000001
168#define WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 0x0000000000000002
169#define WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 0x0000000000000004
170#define WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 0x0000000000000008
171#define WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 0x0000000000000010
172#define WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 0x0000000000000020
173#define WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 0x0000000000000040
174#define WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 0x0000000000000080
175#define WDC_DRIVE_CAP_RESIZE0x0000000000000100 0x0000000000000100
176#define WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 0x0000000000000200
177#define WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 0x0000000000000400
178#define WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 0x0000000000000800
179#define WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 0x0000000000001000
180#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 0x0000000000002000
181#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 0x0000000000004000
182#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 0x0000000000008000
183#define WDC_DRIVE_CAP_REASON_ID0x0000000000010000 0x0000000000010000
184#define WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 0x0000000000020000
185#define WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 0x0000000000040000
186#define WDC_DRIVE_CAP_INFO0x0000000000080000 0x0000000000080000
187#define WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 0x0000000000100000
188#define WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 0x0000000000200000
189#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 0x0000000000400000
190#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 0x0000000000800000
191#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 0x0000000001000000
192#define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 0x0000000002000000
193#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 0x0000000004000000
194#define WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 0x0000000008000000
195#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 0x0000000010000000
196#define WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 0x0000000020000000
197#define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 0x0000000040000000
198#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 0x0000000080000000
199#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 0x0000000100000000
200#define WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 0x0000000200000000
201#define WDC_SN730B_CAP_VUC_LOG0x0000000400000000 0x0000000400000000
202#define WDC_DRIVE_CAP_DUI0x0000000800000000 0x0000000800000000
203#define WDC_DRIVE_CAP_PURGE0x0000001000000000 0x0000001000000000
204#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 0x0000002000000000
205#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 0x0000004000000000
206#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 0x0000008000000000
207#define WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 0x0000010000000000
208#define WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 0x0000020000000000
209#define WDC_DRIVE_CAP_UDUI0x0000040000000000 0x0000040000000000
210#define WDC_DRIVE_CAP_RESIZE_SN8610x0000080000000000 0x0000080000000000
211
212/* Any new capability flags should be added to the SNDK plugin */
213
214#define WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
(WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | \
215 WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 | \
216 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | \
217 WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010)
218#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
(WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 | \
219 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | \
220 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000)
221#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | \
222 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000)
223#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | \
224 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000)
225#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
(WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | \
226 WDC_DRIVE_CAP_DUI0x0000000800000000 | \
227 WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | \
228 WDC_SN730B_CAP_VUC_LOG0x0000000400000000)
229
230/* SN730 Get Log Capabilities */
231#define SN730_NVME_GET_LOG_OPCODE0xc2 0xc2
232#define SN730_GET_FULL_LOG_LENGTH0x00080009 0x00080009
233#define SN730_GET_KEY_LOG_LENGTH0x00090009 0x00090009
234#define SN730_GET_COREDUMP_LOG_LENGTH0x00120009 0x00120009
235#define SN730_GET_EXTENDED_LOG_LENGTH0x00420009 0x00420009
236
237#define SN730_GET_FULL_LOG_SUBOPCODE0x00010009 0x00010009
238#define SN730_GET_KEY_LOG_SUBOPCODE0x00020009 0x00020009
239#define SN730_GET_CORE_LOG_SUBOPCODE0x00030009 0x00030009
240#define SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009 0x00040009
241#define SN730_LOG_CHUNK_SIZE0x1000 0x1000
242
243/* Customer ID's */
244#define WDC_CUSTOMER_ID_GN0x0001 0x0001
245#define WDC_CUSTOMER_ID_GD0x0101 0x0101
246#define WDC_CUSTOMER_ID_BD0x1009 0x1009
247
248#define WDC_CUSTOMER_ID_0x00F00x00F0 0x00F0
249#define WDC_CUSTOMER_ID_0x10040x1004 0x1004
250#define WDC_CUSTOMER_ID_0x10050x1005 0x1005
251#define WDC_CUSTOMER_ID_0x10080x1008 0x1008
252#define WDC_CUSTOMER_ID_0x13040x1304 0x1304
253#define WDC_INVALID_CUSTOMER_ID-1 -1
254
255#define WDC_ALL_PAGE_MASK0xFFFF 0xFFFF
256#define WDC_C0_PAGE_MASK0x0001 0x0001
257#define WDC_C1_PAGE_MASK0x0002 0x0002
258#define WDC_CA_PAGE_MASK0x0004 0x0004
259#define WDC_D0_PAGE_MASK0x0008 0x0008
260
261/* Drive Resize */
262#define WDC_NVME_DRIVE_RESIZE_OPCODE0xCC 0xCC
263#define WDC_NVME_DRIVE_RESIZE_CMD0x03 0x03
264#define WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 0x01
265
266/* Namespace Resize */
267#define WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB 0xFB
268
269/* Drive Info */
270#define WDC_NVME_DRIVE_INFO_OPCODE0xC6 0xC6
271#define WDC_NVME_DRIVE_INFO_CMD0x22 0x22
272#define WDC_NVME_DRIVE_INFO_SUBCMD0x06 0x06
273
274/* VS PCIE Stats */
275#define WDC_NVME_PCIE_STATS_OPCODE0xD1 0xD1
276
277/* Capture Diagnostics */
278#define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
279#define WDC_NVME_CAP_DIAG_OPCODE0xE6 0xE6
280/* Sanity bound on the device-reported Capture Diagnostics log length. */
281#define WDC_NVME_CAP_DIAG_LENGTH_MAX(1U << 30) (1U << 30)
282#define WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6 0xC6
283#define WDC_NVME_CAP_DIAG_SUBCMD0x00 0x00
284#define WDC_NVME_CAP_DIAG_CMD0x00 0x00
285
286#define WDC_NVME_CRASH_DUMP_TYPE1 1
287#define WDC_NVME_PFAIL_DUMP_TYPE2 2
288
289/* Capture Device Unit Info */
290#define WDC_NVME_CAP_DUI_HEADER_SIZE0x400 0x400
291#define WDC_NVME_CAP_DUI_OPCODE0xFA 0xFA
292#define WDC_NVME_CAP_DUI_DISABLE_IO0x01 0x01
293#define WDC_NVME_DUI_MAX_SECTION0x3A 0x3A
294#define WDC_NVME_DUI_MAX_SECTION_V20x26 0x26
295#define WDC_NVME_DUI_MAX_SECTION_V30x23 0x23
296#define WDC_NVME_DUI_MAX_DATA_AREA0x05 0x05
297#define WDC_NVME_SN730_SECTOR_SIZE512 512
298
299/* Telemtery types for vs-internal-log command */
300#define WDC_TELEMETRY_TYPE_NONE0x0 0x0
301#define WDC_TELEMETRY_TYPE_HOST0x1 0x1
302#define WDC_TELEMETRY_TYPE_CONTROLLER0x2 0x2
303#define WDC_TELEMETRY_HEADER_LENGTH512 512
304#define WDC_TELEMETRY_BLOCK_SIZE512 512
305
306/* Crash dump */
307#define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
308#define WDC_NVME_CRASH_DUMP_SIZE_NDT0x02 0x02
309#define WDC_NVME_CRASH_DUMP_SIZE_CMD0x20 0x20
310#define WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 0x03
311
312#define WDC_NVME_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
313#define WDC_NVME_CRASH_DUMP_CMD0x20 0x20
314#define WDC_NVME_CRASH_DUMP_SUBCMD0x04 0x04
315
316/* PFail Crash dump */
317#define WDC_NVME_PF_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_HDR_LEN0x08
318#define WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02 0x02
319#define WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20 0x20
320#define WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 0x05
321
322#define WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
323#define WDC_NVME_PF_CRASH_DUMP_CMD0x20 0x20
324#define WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 0x06
325
326/* Drive Log */
327#define WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
328#define WDC_NVME_DRIVE_LOG_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
329#define WDC_NVME_DRIVE_LOG_SIZE_NDT0x02 0x02
330#define WDC_NVME_DRIVE_LOG_SIZE_CMD0x20 0x20
331#define WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 0x01
332
333#define WDC_NVME_DRIVE_LOG_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
334#define WDC_NVME_DRIVE_LOG_CMD0x20 0x20
335#define WDC_NVME_DRIVE_LOG_SUBCMD0x00 0x00
336
337/* Purge and Purge Monitor */
338#define WDC_NVME_PURGE_CMD_OPCODE0xDD 0xDD
339#define WDC_NVME_PURGE_MONITOR_OPCODE0xDE 0xDE
340#define WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F 0x2F
341#define WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C 0x0000000C
342#define WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530 0x7530
343#define WDC_NVME_PURGE_CMD_SEQ_ERR0x0C 0x0C
344#define WDC_NVME_PURGE_INT_DEV_ERR0x06 0x06
345
346#define WDC_NVME_PURGE_STATE_IDLE0x00 0x00
347#define WDC_NVME_PURGE_STATE_DONE0x01 0x01
348#define WDC_NVME_PURGE_STATE_BUSY0x02 0x02
349#define WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03 0x03
350#define WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04 0x04
351
352/* Clear dumps */
353#define WDC_NVME_CLEAR_DUMP_OPCODE0xFF 0xFF
354#define WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03 0x03
355#define WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 0x05
356#define WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 0x06
357
358/* Clear FW Activate History */
359#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6 0xC6
360#define WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23 0x23
361#define WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 0x05
362#define WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1 0xC1
363
364/* Additional Smart Log */
365#define WDC_ADD_LOG_BUF_LEN0x4000 0x4000
366#define WDC_NVME_ADD_LOG_OPCODE0xC1 0xC1
367#define WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37 0x37
368#define WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F 0x0F
369
370/* C2 Log Page */
371#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2 0xC2
372#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 0xC8
373#define WDC_C2_LOG_BUF_LEN0x1000 0x1000
374#define WDC_C2_MARKETING_NAME_ID0x07 0x07
375#define WDC_C2_LOG_PAGES_SUPPORTED_ID0x08 0x08
376#define WDC_C2_CUSTOMER_ID_ID0x15 0x15
377#define WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18 0x18
378#define WDC_C2_ASSERT_DUMP_PRESENT_ID0x19 0x19
379#define WDC_C2_USER_EOL_STATUS_ID0x1A 0x1A
380#define WDC_C2_USER_EOL_STATE_ID0x1C 0x1C
381#define WDC_C2_SYSTEM_EOL_STATE_ID0x1D 0x1D
382#define WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E 0x1E
383#define WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
384#define WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
385#define WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
386#define WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
387#define WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
388#define WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
389#define WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
390#define WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
391#define WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
392#define WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
393#define WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF) cpu_to_le32(0x000000FF)
394#define WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861" "Ultrastar DC SN861"
395#define WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861" "ULTRASTAR DC SN861"
396#define WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655" "Ultrastar DC SN655"
397#define WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655" "ULTRASTAR DC SN655"
398#define WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655" "SanDisk DC SN655"
399#define WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655" "SANDISK DC SN655"
400
401/* CA Log Page */
402#define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA 0xCA
403#define WDC_FB_CA_LOG_BUF_LEN0x80 0x80
404/* Added 4 padding bytes to resolve build warning messages */
405#define WDC_BD_CA_LOG_BUF_LEN0xA0 0xA0
406
407/* C0 EOL Status Log Page */
408#define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0 0xC0
409#define WDC_NVME_EOL_STATUS_LOG_LEN0x200 0x200
410#define WDC_NVME_SMART_CLOUD_ATTR_LEN0x200 0x200
411
412/* C0 SMART Cloud Attributes Log Page*/
413#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0 0xC0
414
415/* CB - FW Activate History Log Page */
416#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB 0xCB
417#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0 0x3d0
418
419/* C2 - FW Activation History Log Page */
420#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2 0xC2
421#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000 0x1000
422#define WDC_MAX_NUM_ACT_HIST_ENTRIES20 20
423#define WDC_C2_GUID_LENGTH16 16
424
425/* C3 Latency Monitor Log Page */
426#define WDC_LATENCY_MON_LOG_BUF_LEN0x200 0x200
427#define WDC_LATENCY_MON_LOG_ID0xC3 0xC3
428#define WDC_LATENCY_MON_VERSION0x0001 0x0001
429
430#define WDC_C3_GUID_LENGTH16 16
431static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH16] = {
432 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c,
433 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85
434};
435
436/* D0 Smart Log Page */
437#define WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0 0xD0
438#define WDC_NVME_VU_SMART_LOG_LEN0x200 0x200
439
440/* Log Page Directory defines */
441#define NVME_LOG_PERSISTENT_EVENT0x0D 0x0D
442#define WDC_LOG_ID_C00xC0 0xC0
443#define WDC_LOG_ID_C10xC1 0xC1
444#define WDC_LOG_ID_C20xC2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2
445#define WDC_LOG_ID_C30xC3 0xC3
446#define WDC_LOG_ID_C40xC4 0xC4
447#define WDC_LOG_ID_C50xC5 0xC5
448#define WDC_LOG_ID_C60xC6 0xC6
449#define WDC_LOG_ID_C80xC8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8
450#define WDC_LOG_ID_CA0xCA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA
451#define WDC_LOG_ID_CB0xCB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB
452#define WDC_LOG_ID_D00xD0 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0
453#define WDC_LOG_ID_D10xD1 0xD1
454#define WDC_LOG_ID_D60xD6 0xD6
455#define WDC_LOG_ID_D70xD7 0xD7
456#define WDC_LOG_ID_D80xD8 0xD8
457#define WDC_LOG_ID_DE0xDE 0xDE
458#define WDC_LOG_ID_F00xF0 0xF0
459#define WDC_LOG_ID_F10xF1 0xF1
460#define WDC_LOG_ID_F20xF2 0xF2
461#define WDC_LOG_ID_FA0xFA 0xFA
462
463/* Clear PCIe Correctable Errors */
464#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
465#define WDC_NVME_CLEAR_PCIE_CORR_CMD0x22 0x22
466#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 0x04
467#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2 0xD2
468#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3 0xC3
469/* Clear Assert Dump Status */
470#define WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8 0xD8
471#define WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03 0x03
472#define WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 0x05
473
474#define WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2 0xD2
475
476/* Drive Essentials */
477#define WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64 64
478#define WDC_DE_GENERIC_BUFFER_SIZE80 80
479#define WDC_DE_GLOBAL_NSID0xFFFFFFFF 0xFFFFFFFF
480#define WDC_DE_DEFAULT_NAMESPACE_ID0x01 0x01
481#define WDC_DE_PATH_SEPARATOR"/" "/"
482#define WDC_DE_TAR_FILES"*.bin" "*.bin"
483#define WDC_DE_TAR_FILE_EXTN".tar.gz" ".tar.gz"
484#define WDC_DE_TAR_CMD"tar -czf" "tar -czf"
485
486/* VS NAND Stats */
487#define WDC_NVME_NAND_STATS_LOG_ID0xFB 0xFB
488#define WDC_NVME_NAND_STATS_SIZE0x200 0x200
489
490/* VU Opcodes */
491#define WDC_DE_VU_READ_SIZE_OPCODE0xC0 0xC0
492#define WDC_DE_VU_READ_BUFFER_OPCODE0xC2 0xC2
493#define WDC_NVME_ADMIN_ENC_MGMT_SND0xC9 0xC9
494#define WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA 0xCA
495
496#define WDC_DE_FILE_HEADER_SIZE4 4
497#define WDC_DE_FILE_OFFSET_SIZE2 2
498#define WDC_DE_FILE_NAME_SIZE32 32
499#define WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000 0x8000
500#define WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 0x8000
501
502#define WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info" "manufacturing_info" /* Unique log entry page name. */
503#define WDC_DE_CORE_DUMP_FILE_NAME"core_dump" "core_dump"
504#define WDC_DE_EVENT_LOG_FILE_NAME"event_log" "event_log"
505#define WDC_DE_DESTN_SPI1 1
506#define WDC_DE_DUMPTRACE_DESTINATION6 6
507
508#define NVME_ID_CTRL_MODEL_NUMBER_SIZE40 40
509#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE20 20
510
511/* Enclosure log */
512#define WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000 0x1000
513#define WDC_NVME_ENC_NIC_LOG_SIZE0x400000 0x400000
514
515/* Enclosure nic crash dump get-log id */
516#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 0xD1
517#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 0xD2
518#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 0xD3
519#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4 0xD4
520#define WDC_ENC_CRASH_DUMP_ID0xE4 0xE4
521#define WDC_ENC_LOG_DUMP_ID0xE2 0xE2
522
523/* OCP Log Page Directory Data Structure */
524#define BYTE_TO_BIT(byte)((byte) * 8) ((byte) * 8)
525
526/* Set latency monitor feature */
527#define NVME_FEAT_OCP_LATENCY_MONITOR0xC5 0xC5
528
529enum _NVME_FEATURES_SELECT {
530 FS_CURRENT = 0,
531 FS_DEFAULT = 1,
532 FS_SAVED = 2,
533 FS_SUPPORTED_CAPBILITIES = 3
534};
535
536enum NVME_FEATURE_IDENTIFIERS {
537 FID_ARBITRATION = 0x01,
538 FID_POWER_MANAGEMENT = 0x02,
539 FID_LBA_RANGE_TYPE = 0x03,
540 FID_TEMPERATURE_THRESHOLD = 0x04,
541 FID_ERROR_RECOVERY = 0x05,
542 FID_VOLATILE_WRITE_CACHE = 0x06,
543 FID_NUMBER_OF_QUEUES = 0x07,
544 FID_INTERRUPT_COALESCING = 0x08,
545 FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
546 FID_WRITE_ATOMICITY = 0x0A,
547 FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B,
548 FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C,
549 /*Below FID's are NVM Command Set Specific*/
550 FID_SOFTWARE_PROGRESS_MARKER = 0x80,
551 FID_HOST_IDENTIFIER = 0x81,
552 FID_RESERVATION_NOTIFICATION_MASK = 0x82,
553 FID_RESERVATION_PERSISTENCE = 0x83
554};
555
556/* WDC UUID value */
557static const __u8 WDC_UUID[NVME_UUID_LEN16] = {
558 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15,
559 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
560};
561
562/* WDC_UUID value for SN640_3 devices */
563static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN16] = {
564 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
565 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
566};
567
568/* Sandisk UUID value */
569static const __u8 SNDK_UUID[NVME_UUID_LEN16] = {
570 0xde, 0x87, 0xd1, 0xeb, 0x72, 0xc5, 0x58, 0x0b,
571 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70
572};
573
574enum WDC_DRIVE_ESSENTIAL_TYPE {
575 WDC_DE_TYPE_IDENTIFY = 0x1,
576 WDC_DE_TYPE_SMARTATTRIBUTEDUMP = 0x2,
577 WDC_DE_TYPE_EVENTLOG = 0x4,
578 WDC_DE_TYPE_DUMPTRACE = 0x8,
579 WDC_DE_TYPE_DUMPSNAPSHOT = 0x10,
580 WDC_DE_TYPE_ATA_LOGS = 0x20,
581 WDC_DE_TYPE_SMART_LOGS = 0x40,
582 WDC_DE_TYPE_SCSI_LOGS = 0x80,
583 WDC_DE_TYPE_SCSI_MODE_PAGES = 0x100,
584 WDC_DE_TYPE_NVMe_FEATURES = 0x200,
585 WDC_DE_TYPE_DUMPSMARTERRORLOG3 = 0x400,
586 WDC_DE_TYPE_DUMPLOG3E = 0x800,
587 WDC_DE_TYPE_DUMPSCRAM = 0x1000,
588 WDC_DE_TYPE_PCU_LOG = 0x2000,
589 WDC_DE_TYPE_DUMP_ERROR_LOGS = 0x4000,
590 WDC_DE_TYPE_FW_SLOT_LOGS = 0x8000,
591 WDC_DE_TYPE_MEDIA_SETTINGS = 0x10000,
592 WDC_DE_TYPE_SMART_DATA = 0x20000,
593 WDC_DE_TYPE_NVME_SETTINGS = 0x40000,
594 WDC_DE_TYPE_NVME_ERROR_LOGS = 0x80000,
595 WDC_DE_TYPE_NVME_LOGS = 0x100000,
596 WDC_DE_TYPE_UART_LOGS = 0x200000,
597 WDC_DE_TYPE_DLOGS_SPI = 0x400000,
598 WDC_DE_TYPE_DLOGS_RAM = 0x800000,
599 WDC_DE_TYPE_NVME_MANF_INFO = 0x2000000,
600 WDC_DE_TYPE_NONE = 0x1000000,
601 WDC_DE_TYPE_ALL = 0xFFFFFFF,
602};
603
604#define WDC_C0_GUID_LENGTH16 16
605#define WDC_SCA_V1_NAND_STATS0x1 0x1
606#define WDC_SCA_V1_ALL0xF 0xF
607enum {
608 SCAO_V1_PMUWT = 0, /* Physical media units written TLC */
609 SCAO_V1_PMUWS = 16, /* Physical media units written SLC */
610 SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */
611 SCAO_V1_BUNBR = 34, /* Bad user nand blocks raw */
612 SCAO_V1_XRC = 40, /* XOR recovery count */
613 SCAO_V1_UREC = 48, /* Uncorrectable read error count */
614 SCAO_V1_EECE = 56, /* End to end corrected errors */
615 SCAO_V1_EEDE = 64, /* End to end detected errors */
616 SCAO_V1_EEUE = 72, /* End to end uncorrected errors */
617 SCAO_V1_SDPU = 80, /* System data percent used */
618 SCAO_V1_MNUDEC = 84, /* Min User data erase counts (TLC) */
619 SCAO_V1_MXUDEC = 92, /* Max User data erase counts (TLC) */
620 SCAO_V1_AVUDEC = 100, /* Average User data erase counts (TLC) */
621 SCAO_V1_MNEC = 108, /* Min Erase counts (SLC) */
622 SCAO_V1_MXEC = 116, /* Max Erase counts (SLC) */
623 SCAO_V1_AVEC = 124, /* Average Erase counts (SLC) */
624 SCAO_V1_PFCN = 132, /* Program fail count normalized */
625 SCAO_V1_PFCR = 134, /* Program fail count raw */
626 SCAO_V1_EFCN = 140, /* Erase fail count normalized */
627 SCAO_V1_EFCR = 142, /* Erase fail count raw */
628 SCAO_V1_PCEC = 148, /* PCIe correctable error count */
629 SCAO_V1_PFBU = 156, /* Percent free blocks (User) */
630 SCAO_V1_SVN = 160, /* Security Version Number */
631 SCAO_V1_PFBS = 168, /* Percent free blocks (System) */
632 SCAO_V1_DCC = 172, /* Deallocate Commands Completed */
633 SCAO_V1_TNU = 188, /* Total Namespace Utilization */
634 SCAO_V1_FCC = 196, /* Format NVM Commands Completed */
635 SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */
636 SCAO_V1_SEEC = 202, /* Soft ECC error count */
637 SCAO_V1_RFSC = 210, /* Refresh count */
638 SCAO_V1_BSNBN = 218, /* Bad system nand blocks normalized */
639 SCAO_V1_BSNBR = 220, /* Bad system nand blocks raw */
640 SCAO_V1_EEST = 226, /* Endurance estimate */
641 SCAO_V1_TTC = 242, /* Thermal throttling count */
642 SCAO_V1_UIO = 244, /* Unaligned I/O */
643 SCAO_V1_PMUR = 252, /* Physical media units read */
644 SCAO_V1_RTOC = 268, /* Read command timeout count */
645 SCAO_V1_WTOC = 272, /* Write command timeout count */
646 SCAO_V1_TTOC = 276, /* Trim command timeout count */
647 SCAO_V1_PLRC = 284, /* PCIe Link Retraining Count */
648 SCAO_V1_PSCC = 292, /* Power State Change Count */
649 SCAO_V1_MAVF = 300, /* Boot SSD major version field */
650 SCAO_V1_MIVF = 302, /* Boot SSD minor version field */
651 SCAO_V1_PVF = 304, /* Boot SSD point version field */
652 SCAO_V1_EVF = 306, /* Boot SSD errata version field */
653 SCAO_V1_FTLUS = 308, /* FTL Unit Size */
654 SCAO_V1_TCGOS = 312, /* TCG Ownership Status */
655
656 SCAO_V1_LPV = 494, /* Log page version - 0x0001 */
657 SCAO_V1_LPG = 496, /* Log page GUID */
658};
659
660static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH16] = {
661 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1,
662 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4
663};
664
665struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log {
666 __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */
667 __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */
668 __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */
669 __u64 ext_smart_xrc; /* 040 XOR recovery count */
670 __u64 ext_smart_urec; /* 048 Uncorrectable read error count */
671 __u64 ext_smart_eece; /* 056 End to end corrected errors */
672 __u64 ext_smart_eede; /* 064 End to end detected errors */
673 __u64 ext_smart_eeue; /* 072 End to end uncorrected errors */
674 __u8 ext_smart_sdpu; /* 080 System data percent used */
675 __u8 ext_smart_rsvd1[3]; /* 081 reserved */
676 __u64 ext_smart_mnudec; /* 084 Min User data erase counts (TLC) */
677 __u64 ext_smart_mxudec; /* 092 Max User data erase counts (TLC) */
678 __u64 ext_smart_avudec; /* 100 Average User data erase counts (TLC) */
679 __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */
680 __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */
681 __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */
682 __u8 ext_smart_pfc[8]; /* 132 Program fail count */
683 __u8 ext_smart_efc[8]; /* 140 Erase fail count */
684 __u64 ext_smart_pcec; /* 148 PCIe correctable error count */
685 __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */
686 __u8 ext_smart_rsvd2[3]; /* 157 reserved */
687 __u64 ext_smart_svn; /* 160 Security Version Number */
688 __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */
689 __u8 ext_smart_rsvd3[3]; /* 169 reserved */
690 __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */
691 __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */
692 __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */
693 __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */
694 __u8 ext_smart_rsvd4[3]; /* 199 reserved */
695 __u64 ext_smart_seec; /* 202 Soft ECC error count */
696 __u64 ext_smart_rfsc; /* 210 Refresh count */
697 __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */
698 __u8 ext_smart_eest[16]; /* 226 Endurance estimate */
699 __u16 ext_smart_ttc; /* 242 Thermal throttling count */
700 __u64 ext_smart_uio; /* 244 Unaligned I/O */
701 __u8 ext_smart_pmur[16]; /* 252 Physical media units read */
702 __u32 ext_smart_rtoc; /* 268 Read command timeout count */
703 __u32 ext_smart_wtoc; /* 272 Write command timeout count */
704 __u32 ext_smart_ttoc; /* 276 Trim command timeout count */
705 __u8 ext_smart_rsvd5[4]; /* 280 reserved */
706 __u64 ext_smart_plrc; /* 284 PCIe Link Retraining Count */
707 __u64 ext_smart_pscc; /* 292 Power State Change Count */
708 __u16 ext_smart_maj; /* 300 Boot SSD major version field */
709 __u16 ext_smart_min; /* 302 Boot SSD minor version field */
710 __u16 ext_smart_pt; /* 304 Boot SSD point version field */
711 __u16 ext_smart_err; /* 306 Boot SSD errata version field */
712 __u32 ext_smart_ftlus; /* 308 FTL Unit Size */
713 __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */
714 __u8 ext_smart_rsvd6[178]; /* 316 reserved */
715 __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */
716 __u8 ext_smart_lpg[16]; /* 496 Log page GUID */
717};
718
719struct ocp_bad_nand_block_count {
720 __u64 raw : 48;
721 __u16 normalized : 16;
722};
723
724struct ocp_e2e_correction_count {
725 __u32 detected;
726 __u32 corrected;
727};
728
729struct ocp_user_data_erase_count {
730 __u32 maximum;
731 __u32 minimum;
732};
733
734struct ocp_thermal_status {
735 __u8 num_events;
736 __u8 current_status;
737};
738
739struct __packed__attribute__((__packed__)) ocp_dssd_specific_ver {
740 __u8 errata_ver;
741 __u16 point_ver;
742 __u16 minor_ver;
743 __u8 major_ver;
744};
745
746struct ocp_cloud_smart_log {
747 __u8 physical_media_units_written[16];
748 __u8 physical_media_units_read[16];
749 struct ocp_bad_nand_block_count bad_user_nand_blocks;
750 struct ocp_bad_nand_block_count bad_system_nand_blocks;
751 __u64 xor_recovery_count;
752 __u64 uncorrectable_read_error_count;
753 __u64 soft_ecc_error_count;
754 struct ocp_e2e_correction_count e2e_correction_counts;
755 __u8 system_data_percent_used;
756 __u64 refresh_counts : 56;
757 struct ocp_user_data_erase_count user_data_erase_counts;
758 struct ocp_thermal_status thermal_status;
759 struct ocp_dssd_specific_ver dssd_specific_ver;
760 __u64 pcie_correctable_error_count;
761 __u32 incomplete_shutdowns;
762 __u8 rsvd116[4];
763 __u8 percent_free_blocks;
764 __u8 rsvd121[7];
765 __u16 capacitor_health;
766 __u8 nvme_base_errata_ver;
767 __u8 nvme_cmd_set_errata_ver;
768 __u8 rsvd132[4];
769 __u64 unaligned_io;
770 __u64 security_version_number;
771 __u64 total_nuse;
772 __u8 plp_start_count[16];
773 __u8 endurance_estimate[16];
774 __u64 pcie_link_retraining_cnt;
775 __u64 power_state_change_cnt;
776 union {
777 char lowest_permitted_fw_rev[8]; /* log_page_version >= 4 */
778 __u8 hardware_revision[16]; /* log_page_version == 3 */
779 };
780 __u8 rsvd224[270];
781 __u16 log_page_version;
782 __u8 log_page_guid[16];
783};
784
785static __u8 scao_guid[WDC_C0_GUID_LENGTH16] = {
786 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
787 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF
788};
789
790struct __packed__attribute__((__packed__)) wdc_nvme_c0_eol_log_page {
791 __u8 rsvd1[76];
792 __u32 eol_rbc;
793 __u32 eol_rsvd2;
794 __u32 eol_wra;
795 __u32 eol_plr;
796 __u32 eol_rsvd3;
797 __u32 eol_pfc;
798 __u32 eol_efc;
799 __u32 eol_rsvd4;
800 __u32 eol_rrer;
801 __u16 eol_cp_status;
802 __u16 eol_ip_status;
803 __u8 eol_cp_state;
804 __u8 eol_ip_state;
805};
806
807#define WDC_NVME_C6_GUID_LENGTH16 16
808#define WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6 0xc6
809#define WDC_NVME_HW_REV_LOG_PAGE_LEN512 512
810
811struct __packed__attribute__((__packed__)) wdc_nvme_hw_rev_log {
812 __u8 hw_rev_gdr; /* 0 Global Device HW Revision */
813 __u8 hw_rev_ar; /* 1 ASIC HW Revision */
814 __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */
815 __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */
816 __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */
817 __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */
818 __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */
819 __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */
820 __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */
821 __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */
822 __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */
823 __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */
824 __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */
825 __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */
826 __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */
827 __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */
828 __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */
829 __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */
830 __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */
831 __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */
832 __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */
833 __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */
834 __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */
835 __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */
836 __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */
837 __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */
838 __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */
839 __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */
840 __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */
841 __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */
842 __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */
843 __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */
844 __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */
845 __u8 hw_rev_sn[32]; /* 320 Serial Number */
846 __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */
847 __u16 hw_rev_version; /* 494 Log Page Version */
848 __u8 hw_rev_guid[16]; /* 496 Log Page GUID */
849};
850
851static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH16] = {
852 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15,
853 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C
854};
855
856struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA {
857 __u8 fileName[WDC_DE_FILE_NAME_SIZE32];
858 __u16 fileID;
859 __u64 fileSize;
860};
861
862struct WDC_DRIVE_ESSENTIALS {
863 struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA metaData;
864 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType;
865};
866
867struct WDC_DE_VU_LOG_DIRECTORY {
868 struct WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */
869 __u32 maxNumLogEntries; /* Caller to input memory allocated */
870 __u32 numOfValidLogEntries; /* API will output this value */
871};
872
873struct WDC_DE_CSA_FEATURE_ID_LIST {
874 enum NVME_FEATURE_IDENTIFIERS featureId;
875 __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE80];
876};
877
878struct tarfile_metadata {
879 char fileName[MAX_PATH_LEN256];
880 int8_t bufferFolderPath[MAX_PATH_LEN256];
881 char bufferFolderName[MAX_PATH_LEN256];
882 char tarFileName[MAX_PATH_LEN256];
883 char tarFiles[MAX_PATH_LEN256];
884 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
885 char currDir[MAX_PATH_LEN256];
886 UtilsTimeInfo timeInfo;
887 uint8_t *timeString[MAX_PATH_LEN256];
888};
889
890static struct WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = {
891 {0x00, "Dummy Placeholder"},
892 {FID_ARBITRATION, "Arbitration"},
893 {FID_POWER_MANAGEMENT, "PowerMgmnt"},
894 {FID_LBA_RANGE_TYPE, "LbaRangeType"},
895 {FID_TEMPERATURE_THRESHOLD, "TempThreshold"},
896 {FID_ERROR_RECOVERY, "ErrorRecovery"},
897 {FID_VOLATILE_WRITE_CACHE, "VolatileWriteCache"},
898 {FID_NUMBER_OF_QUEUES, "NumOfQueues"},
899 {FID_INTERRUPT_COALESCING, "InterruptCoalesing"},
900 {FID_INTERRUPT_VECTOR_CONFIGURATION, "InterruptVectorConfig"},
901 {FID_WRITE_ATOMICITY, "WriteAtomicity"},
902 {FID_ASYNCHRONOUS_EVENT_CONFIGURATION, "AsynEventConfig"},
903 {FID_AUTONOMOUS_POWER_STATE_TRANSITION, "AutonomousPowerState"},
904};
905
906enum NVME_VU_DE_LOGPAGE_NAMES {
907 NVME_DE_LOGPAGE_E3 = 0x01,
908 NVME_DE_LOGPAGE_C0 = 0x02
909};
910
911struct NVME_VU_DE_LOGPAGE_LIST {
912 enum NVME_VU_DE_LOGPAGE_NAMES logPageName;
913 __u32 logPageId;
914 __u32 logPageLen;
915 char logPageIdStr[5];
916};
917
918struct WDC_NVME_DE_VU_LOGPAGES {
919 enum NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd;
920 __u32 numOfVULogPages;
921};
922
923static struct NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = {
924 { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"},
925 { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"}
926};
927
928enum {
929 WDC_NVME_ADMIN_VUC_OPCODE_D2 = 0xD2,
930 WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2 = 0x0000010A,
931 WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2 = 0x00000105,
932};
933
934enum {
935 NVME_LOG_NS_BASE = 0x80,
936 NVME_LOG_VS_BASE = 0xC0,
937};
938
939/*drive_info struct*/
940struct ocp_drive_info {
941 __u32 hw_revision;
942 __u32 ftl_unit_size;
943};
944
945/*get log page directory struct*/
946struct log_page_directory {
947 __u64 supported_lid_bitmap;
948 __u64 rsvd;
949 __u64 supported_ns_lid_bitmap;
950 __u64 supported_vs_lid_bitmap;
951};
952
953/*set latency monitor feature */
954struct __packed__attribute__((__packed__)) feature_latency_monitor {
955 __u16 active_bucket_timer_threshold;
956 __u8 active_threshold_a;
957 __u8 active_threshold_b;
958 __u8 active_threshold_c;
959 __u8 active_threshold_d;
960 __u16 active_latency_config;
961 __u8 active_latency_minimum_window;
962 __u16 debug_log_trigger_enable;
963 __u8 discard_debug_log;
964 __u8 latency_monitor_feature_enable;
965 __u8 reserved[4083];
966};
967
968static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len, const char *suffix);
969static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
970 __u32 drive_log_length);
971static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12);
972static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12,
973 const char *file, __u32 xfer_size);
974static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type);
975static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type);
976static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
977 struct plugin *plugin);
978static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file);
979static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin);
980static const char *wdc_purge_mon_status_to_string(__u32 status);
981static int wdc_purge(int argc, char **argv, struct command *acmd, struct plugin *plugin);
982static int wdc_purge_monitor(int argc, char **argv, struct command *acmd, struct plugin *plugin);
983static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
984 struct libnvme_transport_handle *hdl,
985 __u8 log_id,
986 __u8 uuid_index);
987static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
988 struct plugin *plugin);
989static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *dir, char *key);
990static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
991 struct plugin *plugin);
992static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin);
993static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
994 struct plugin *plugin);
995static int wdc_drive_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin);
996static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size);
997static int wdc_namespace_resize(int argc, char **argv, struct command *acmd,
998 struct plugin *plugin);
999static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option);
1000static int wdc_reason_identifier(int argc, char **argv, struct command *acmd,
1001 struct plugin *plugin);
1002static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id);
1003static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size);
1004static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl);
1005static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
1006 struct plugin *plugin);
1007static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result);
1008static int wdc_vs_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin);
1009static int wdc_vs_temperature_stats(int argc, char **argv, struct command *acmd,
1010 struct plugin *plugin);
1011static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1012static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len,
1013 FILE *out);
1014static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len, int xfer_size,
1015 FILE *out, int data_id, int cdw14, int cdw15);
1016static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __u8 log_id,
1017 void **cbs_data);
1018static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1019static int wdc_print_c0_cloud_attr_log(void *data,
1020 int fmt,
1021 struct libnvme_transport_handle *hdl);
1022static int wdc_print_c0_eol_log(void *data, int fmt);
1023static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
1024 struct libnvme_transport_handle *hdl);
1025static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log);
1026static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx,
1027 struct libnvme_transport_handle *hdl,
1028 void **data);
1029static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data,
1030 __u32 *ret_data,
1031 __u32 entry_id);
1032static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
1033 __u32 entry_id,
1034 char *ret_data,
1035 __u32 *ret_data_len);
1036
1037/* Drive log data size */
1038struct wdc_log_size {
1039 __le32 log_size;
1040};
1041
1042/* E6 log header */
1043struct wdc_e6_log_hdr {
1044 __le32 eye_catcher;
1045 __u8 log_size[4];
1046};
1047
1048/* DUI log header */
1049struct wdc_dui_log_section {
1050 __le16 section_type;
1051 __le16 reserved;
1052 __le32 section_size;
1053};
1054
1055/* DUI log header V2 */
1056struct __packed__attribute__((__packed__)) wdc_dui_log_section_v2 {
1057 __le16 section_type;
1058 __le16 data_area_id;
1059 __le64 section_size;
1060};
1061
1062/* DUI log header V4 */
1063struct wdc_dui_log_section_v4 {
1064 __le16 section_type;
1065 __u8 data_area_id;
1066 __u8 reserved;
1067 __le32 section_size_sectors;
1068};
1069
1070struct wdc_dui_log_hdr {
1071 __u8 telemetry_hdr[512];
1072 __le16 hdr_version;
1073 __le16 section_count;
1074 __le32 log_size;
1075 struct wdc_dui_log_section log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1076 __u8 log_data[40];
1077};
1078
1079struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v2 {
1080 __u8 telemetry_hdr[512];
1081 __u8 hdr_version;
1082 __u8 product_id;
1083 __le16 section_count;
1084 __le64 log_size;
1085 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V20x26];
1086 __u8 log_data[40];
1087};
1088
1089struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v3 {
1090 __u8 telemetry_hdr[512];
1091 __u8 hdr_version;
1092 __u8 product_id;
1093 __le16 section_count;
1094 __le64 log_size;
1095 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V30x23];
1096 __u8 securityNonce[36];
1097 __u8 log_data[40];
1098};
1099
1100struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v4 {
1101 __u8 telemetry_hdr[512];
1102 __u8 hdr_version;
1103 __u8 product_id;
1104 __le16 section_count;
1105 __le32 log_size_sectors;
1106 struct wdc_dui_log_section_v4 log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1107 __u8 log_data[40];
1108};
1109
1110/* Purge monitor response */
1111struct wdc_nvme_purge_monitor_data {
1112 __le16 rsvd1;
1113 __le16 rsvd2;
1114 __le16 first_erase_failure_cnt;
1115 __le16 second_erase_failure_cnt;
1116 __le16 rsvd3;
1117 __le16 programm_failure_cnt;
1118 __le32 rsvd4;
1119 __le32 rsvd5;
1120 __le32 entire_progress_total;
1121 __le32 entire_progress_current;
1122 __u8 rsvd6[14];
1123};
1124
1125/* Additional Smart Log */
1126struct wdc_log_page_header {
1127 uint8_t num_subpages;
1128 uint8_t reserved;
1129 __le16 total_log_size;
1130};
1131
1132struct wdc_log_page_subpage_header {
1133 uint8_t spcode;
1134 uint8_t pcset;
1135 __le16 subpage_length;
1136};
1137
1138struct wdc_ssd_perf_stats {
1139 __le64 hr_cmds; /* Host Read Commands */
1140 __le64 hr_blks; /* Host Read Blocks */
1141 __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */
1142 __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */
1143 __le64 hr_st_cmds; /* Host Read Stalled Commands */
1144 __le64 hw_cmds; /* Host Write Commands */
1145 __le64 hw_blks; /* Host Write Blocks */
1146 __le64 hw_os_cmds; /* Host Write Odd Start Commands */
1147 __le64 hw_oe_cmds; /* Host Write Odd End Commands */
1148 __le64 hw_st_cmds; /* Host Write Commands Stalled */
1149 __le64 nr_cmds; /* NAND Read Commands */
1150 __le64 nr_blks; /* NAND Read Blocks */
1151 __le64 nw_cmds; /* NAND Write Commands */
1152 __le64 nw_blks; /* NAND Write Blocks */
1153 __le64 nrbw; /* NAND Read Before Write */
1154};
1155
1156/* Additional C2 Log Page */
1157struct wdc_c2_log_page_header {
1158 __le32 length;
1159 __le32 version;
1160};
1161
1162struct wdc_c2_log_subpage_header {
1163 __le32 length;
1164 __le32 entry_id;
1165 __le32 data;
1166};
1167
1168struct wdc_c2_cbs_data {
1169 __le32 length;
1170 __u8 data[];
1171};
1172
1173struct __packed__attribute__((__packed__)) wdc_bd_ca_log_format {
1174 __u8 field_id;
1175 __u8 reserved1[2];
1176 __u8 normalized_value;
1177 __u8 raw_value[8];
1178};
1179
1180#define WDC_LATENCY_LOG_BUCKET_READ3 3
1181#define WDC_LATENCY_LOG_BUCKET_WRITE2 2
1182#define WDC_LATENCY_LOG_BUCKET_TRIM1 1
1183#define WDC_LATENCY_LOG_BUCKET_RESERVED0 0
1184
1185#define WDC_LATENCY_LOG_MEASURED_LAT_READ2 2
1186#define WDC_LATENCY_LOG_MEASURED_LAT_WRITE1 1
1187#define WDC_LATENCY_LOG_MEASURED_LAT_TRIM0 0
1188
1189struct __packed__attribute__((__packed__)) wdc_ssd_latency_monitor_log {
1190 __u8 feature_status; /* 0x00 */
1191 __u8 rsvd1; /* 0x01 */
1192 __le16 active_bucket_timer; /* 0x02 */
1193 __le16 active_bucket_timer_threshold; /* 0x04 */
1194 __u8 active_threshold_a; /* 0x06 */
1195 __u8 active_threshold_b; /* 0x07 */
1196 __u8 active_threshold_c; /* 0x08 */
1197 __u8 active_threshold_d; /* 0x09 */
1198 __le16 active_latency_config; /* 0x0A */
1199 __u8 active_latency_min_window; /* 0x0C */
1200 __u8 rsvd2[0x13]; /* 0x0D */
1201
1202 __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */
1203 __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
1204 __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
1205 __le16 active_latency_stamp_units; /* 0xD8 */
1206 __u8 rsvd3[0x16]; /* 0xDA */
1207
1208 __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
1209 __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
1210 __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
1211 __le16 static_latency_stamp_units; /* 0x1A8 */
1212 __u8 rsvd4[10]; /* 0x1AA */
1213
1214 __u8 debug_telemetry_log_size[12]; /* 0x1B4 */
1215 __le16 debug_log_trigger_enable; /* 0x1C0 */
1216 __le16 debug_log_measured_latency; /* 0x1C2 */
1217 __le64 debug_log_latency_stamp; /* 0x1C4 */
1218 __le16 debug_log_ptr; /* 0x1CC */
1219 __le16 debug_log_counter_trigger; /* 0x1CE */
1220 __u8 debug_log_stamp_units; /* 0x1D0 */
1221 __u8 rsvd5[0x1D]; /* 0x1D1 */
1222
1223 __le16 log_page_version; /* 0x1EE */
1224 __u8 log_page_guid[0x10]; /* 0x1F0 */
1225};
1226
1227struct __packed__attribute__((__packed__)) wdc_ssd_ca_perf_stats {
1228 __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */
1229 __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */
1230 __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */
1231 __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */
1232 __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */
1233 __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */
1234 __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */
1235 __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */
1236 __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */
1237 __u8 data_percent_used; /* 0x40 - System Data Percent Used */
1238 __le32 data_erase_max; /* 0x41 - User Data Erase Counts */
1239 __le32 data_erase_min; /* 0x45 - User Data Erase Counts */
1240 __le64 refresh_count; /* 0x49 - Refresh Count */
1241 __le64 program_fail; /* 0x51 - Program Fail Count */
1242 __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */
1243 __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */
1244 __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */
1245 __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */
1246 __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */
1247 __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */
1248 __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */
1249 __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */
1250};
1251
1252struct __packed__attribute__((__packed__)) wdc_ssd_d0_smart_log {
1253 __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */
1254 __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */
1255 __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */
1256 __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */
1257 __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */
1258 __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */
1259 __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */
1260 __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */
1261 __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */
1262 __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */
1263 __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */
1264 __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */
1265 __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */
1266 __le32 current_temp; /* 0x34 - Current temperature */
1267 __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */
1268 __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */
1269 __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */
1270 __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */
1271 __le32 capacitor_health; /* 0x4C - Capacitor health */
1272 __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */
1273 __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */
1274 __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */
1275 __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */
1276 __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */
1277};
1278
1279#define WDC_OCP_C1_GUID_LENGTH16 16
1280#define WDC_ERROR_REC_LOG_BUF_LEN512 512
1281#define WDC_ERROR_REC_LOG_ID0xC1 0xC1
1282
1283struct __packed__attribute__((__packed__)) wdc_ocp_c1_error_recovery_log {
1284 __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */
1285 __u8 panic_reset_action; /* 002 - Panic Reset Action */
1286 __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */
1287 __le64 panic_id; /* 004 - Panic ID */
1288 __le32 dev_capabilities; /* 012 - Device Capabilities */
1289 __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */
1290 __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */
1291 __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */
1292 __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */
1293 __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */
1294 __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */
1295 __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2 */
1296 __u8 panic_count; /* 031 - Number of panics encountered */
1297 __le64 prev_panic_ids[4]; /* 032 - 063 Previous Panic ID's */
1298 __u8 rsvd2[430]; /* 064 - 493 Reserved Bytes */
1299 /* 430 reserved bytes aligns with the rest */
1300 /* of the data structure. The size of 463 */
1301 /* bytes mentioned in the OCP spec */
1302 /* (version 2.5) would not fit here. */
1303 __le16 log_page_version; /* 494 - Log Page Version */
1304 __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH16]; /* 496 - Log Page GUID */
1305};
1306
1307static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH16] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE,
1308 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A };
1309
1310/* NAND Stats */
1311struct __packed__attribute__((__packed__)) wdc_nand_stats {
1312 __u8 nand_write_tlc[16];
1313 __u8 nand_write_slc[16];
1314 __le32 nand_prog_failure;
1315 __le32 nand_erase_failure;
1316 __le32 bad_block_count;
1317 __le64 nand_rec_trigger_event;
1318 __le64 e2e_error_counter;
1319 __le64 successful_ns_resize_event;
1320 __u8 rsvd[442];
1321 __u16 log_page_version;
1322};
1323
1324struct __packed__attribute__((__packed__)) wdc_nand_stats_V3 {
1325 __u8 nand_write_tlc[16];
1326 __u8 nand_write_slc[16];
1327 __u8 bad_nand_block_count[8];
1328 __le64 xor_recovery_count;
1329 __le64 uecc_read_error_count;
1330 __u8 ssd_correction_counts[16];
1331 __u8 percent_life_used;
1332 __le64 user_data_erase_counts[4];
1333 __u8 program_fail_count[8];
1334 __u8 erase_fail_count[8];
1335 __le64 correctable_error_count;
1336 __u8 percent_free_blocks_user;
1337 __le64 security_version_number;
1338 __u8 percent_free_blocks_system;
1339 __u8 trim_completions[25];
1340 __u8 back_pressure_guage;
1341 __le64 soft_ecc_error_count;
1342 __le64 refresh_count;
1343 __u8 bad_sys_nand_block_count[8];
1344 __u8 endurance_estimate[16];
1345 __u8 thermal_throttling_st_ct[2];
1346 __le64 unaligned_IO;
1347 __u8 physical_media_units[16];
1348 __u8 reserved[279];
1349 __u16 log_page_version;
1350};
1351
1352struct wdc_vs_pcie_stats {
1353 __le64 unsupportedRequestErrorCount;
1354 __le64 ecrcErrorStatusCount;
1355 __le64 malformedTlpStatusCount;
1356 __le64 receiverOverflowStatusCount;
1357 __le64 unexpectedCmpltnStatusCount;
1358 __le64 completeAbortStatusCount;
1359 __le64 cmpltnTimoutStatusCount;
1360 __le64 flowControlErrorStatusCount;
1361 __le64 poisonedTlpStatusCount;
1362 __le64 dLinkPrtclErrorStatusCount;
1363 __le64 advsryNFatalErrStatusCount;
1364 __le64 replayTimerToStatusCount;
1365 __le64 replayNumRolloverStCount;
1366 __le64 badDllpStatusCount;
1367 __le64 badTlpStatusCount;
1368 __le64 receiverErrStatusCount;
1369 __u8 reserved1[384];
1370};
1371
1372struct wdc_fw_act_history_log_hdr {
1373 __le32 eye_catcher;
1374 __u8 version;
1375 __u8 reserved1;
1376 __u8 num_entries;
1377 __u8 reserved2;
1378 __le32 entry_size;
1379 __le32 reserved3;
1380};
1381
1382struct wdc_fw_act_history_log_entry {
1383 __le32 entry_num;
1384 __le32 power_cycle_count;
1385 __le64 power_on_seconds;
1386 __le64 previous_fw_version;
1387 __le64 new_fw_version;
1388 __u8 slot_number;
1389 __u8 commit_action_type;
1390 __le16 result;
1391 __u8 reserved[12];
1392};
1393
1394struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 {
1395 __u8 entry_version_num;
1396 __u8 entry_len;
1397 __le16 reserved;
1398 __le16 fw_act_hist_entries;
1399 __le64 timestamp;
1400 __u8 reserved2[8];
1401 __le64 power_cycle_count;
1402 __le64 previous_fw_version;
1403 __le64 current_fw_version;
1404 __u8 slot_number;
1405 __u8 commit_action_type;
1406 __le16 result;
1407 __u8 reserved3[14];
1408};
1409
1410struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_format_c2 {
1411 __u8 log_identifier;
1412 __u8 reserved[3];
1413 __le32 num_entries;
1414 struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES20];
1415 __u8 reserved2[2790];
1416 __le16 log_page_version;
1417 __u8 log_page_guid[WDC_C2_GUID_LENGTH16];
1418};
1419
1420static __u8 ocp_C2_guid[WDC_C2_GUID_LENGTH16] = {
1421 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
1422 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
1423};
1424
1425#define WDC_OCP_C4_GUID_LENGTH16 16
1426#define WDC_DEV_CAP_LOG_BUF_LEN4096 4096
1427#define WDC_DEV_CAP_LOG_ID0xC4 0xC4
1428#define WDC_DEV_CAP_LOG_VERSION0001 0001
1429#define WDC_OCP_C4_NUM_PS_DESCR127 127
1430
1431struct __packed__attribute__((__packed__)) wdc_ocp_C4_dev_cap_log {
1432 __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */
1433 __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */
1434 __le16 wrt_zeros_support; /* 0004 - Write Zeros Command Support */
1435 __le16 sanitize_support; /* 0006 - Sanitize Command Support */
1436 __le16 dsm_support; /* 0008 - Dataset Management Command Support */
1437 __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */
1438 __le16 fused_support; /* 0012 - Fused Operation Support */
1439 __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */
1440 __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */
1441 __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR127];/* 0017 - DSSD Power State Descriptors */
1442 __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */
1443 __le16 log_page_version; /* 4078 - Log Page Version */
1444 __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1445};
1446
1447static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH16] = {
1448 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98,
1449 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7
1450};
1451
1452#define WDC_OCP_C5_GUID_LENGTH16 16
1453#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096 4096
1454#define WDC_UNSUPPORTED_REQS_LOG_ID0xC5 0xC5
1455#define WDC_UNSUPPORTED_REQS_LOG_VERSION0001 0001
1456#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES253 253
1457
1458struct __packed__attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs {
1459 __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */
1460 __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */
1461 __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES253][16]; /* 0016 - Unsupported Requirements List */
1462 __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */
1463 __le16 log_page_version; /* 4078 - Log Page Version */
1464 __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1465};
1466
1467static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH16] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB,
1468 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 };
1469
1470#define WDC_REASON_INDEX_MAX16 16
1471#define WDC_REASON_ID_ENTRY_LEN128 128
1472#define WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli" "/usr/local/nvmecli"
1473
1474const char *log_page_name[256] = {
1475 [NVME_LOG_LID_ERROR] = "Error Information",
1476 [NVME_LOG_LID_SMART] = "SMART / Health Information",
1477 [NVME_LOG_LID_FW_SLOT] = "Firmware Slot Information",
1478 [NVME_LOG_LID_CHANGED_ATTACHED_NS] = "Changed Attached Namespace List",
1479 [NVME_LOG_LID_CMD_EFFECTS] = "Command Supported and Effects",
1480 [NVME_LOG_LID_TELEMETRY_HOST] = "Telemetry Host-Initiated",
1481 [NVME_LOG_LID_TELEMETRY_CTRL] = "Telemetry Controller-Initiated",
1482 [NVME_LOG_LID_SANITIZE] = "Sanitize Status",
1483 [WDC_LOG_ID_C00xC0] = "Extended SMART Information",
1484 [WDC_LOG_ID_C20xC2] = "Firmware Activation History",
1485 [WDC_LOG_ID_C30xC3] = "Latency Monitor",
1486 [WDC_LOG_ID_C40xC4] = "Device Capabilities",
1487 [WDC_LOG_ID_C50xC5] = "Unsupported Requirements",
1488};
1489
1490static double safe_div_fp(double numerator, double denominator)
1491{
1492 return denominator ? numerator / denominator : 0;
1493}
1494
1495static double calc_percent(uint64_t numerator, uint64_t denominator)
1496{
1497 return denominator ?
1498 (uint64_t)(((double)numerator / (double)denominator) * 100) : 0;
1499}
1500
1501static int wdc_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id)
1502{
1503 struct libnvme_passthru_cmd cmd;
1504 struct nvme_id_ctrl ctrl;
1505 int ret;
1506
1507 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1508 nvme_init_identify_ctrl(&cmd, &ctrl);
1509 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1510 if (ret) {
1511 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)
;
1512 return -1;
1513 }
1514
1515 *vendor_id = (uint32_t) ctrl.vid;
1516
1517 return ret;
1518}
1519
1520static bool_Bool wdc_is_sn861(__u32 device_id)
1521{
1522 if ((device_id == WDC_NVME_SN861_DEV_ID0x2750) ||
1523 (device_id == WDC_NVME_SN861_DEV_ID_10x2751) ||
1524 (device_id == WDC_NVME_SN861_DEV_ID_20x2752))
1525 return true1;
1526 else
1527 return false0;
1528}
1529
1530
1531static bool_Bool wdc_is_sn640(__u32 device_id)
1532{
1533 if ((device_id == WDC_NVME_SN640_DEV_ID0x2400) ||
1534 (device_id == WDC_NVME_SN640_DEV_ID_10x2401) ||
1535 (device_id == WDC_NVME_SN640_DEV_ID_20x2402))
1536 return true1;
1537 else
1538 return false0;
1539}
1540
1541static bool_Bool wdc_is_sn650_u2(__u32 device_id)
1542{
1543 if (device_id == WDC_NVME_SN650_DEV_ID_30x2720)
1544 return true1;
1545 else
1546 return false0;
1547}
1548
1549static bool_Bool wdc_is_sn650_e1l(__u32 device_id)
1550{
1551 if (device_id == WDC_NVME_SN650_DEV_ID_40x2721)
1552 return true1;
1553 else
1554 return false0;
1555}
1556
1557static bool_Bool wdc_is_zn350(__u32 device_id)
1558{
1559 return (device_id == WDC_NVME_ZN350_DEV_ID0x5010 ||
1560 device_id == WDC_NVME_ZN350_DEV_ID_10x5018);
1561}
1562static bool_Bool needs_c2_log_page_check(__u32 device_id)
1563{
1564 if ((wdc_is_sn640(device_id)) ||
1565 (wdc_is_sn650_u2(device_id)) ||
1566 (wdc_is_sn650_e1l(device_id)))
1567 return true1;
1568 else
1569 return false0;
1570}
1571
1572static bool_Bool wdc_check_power_of_2(int num)
1573{
1574 return num && (!(num & (num-1)));
1575}
1576
1577static int wdc_get_model_number(struct libnvme_transport_handle *hdl, char *model)
1578{
1579 struct libnvme_passthru_cmd cmd;
1580 struct nvme_id_ctrl ctrl;
1581 int ret, i;
1582
1583 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1584 nvme_init_identify_ctrl(&cmd, &ctrl);
1585 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1586 if (ret) {
1587 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)
;
1588 return -1;
1589 }
1590
1591 memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE40);
1592 /* get rid of the padded spaces */
1593 i = NVME_ID_CTRL_MODEL_NUMBER_SIZE40-1;
1594 while (model[i] == ' ')
1595 i--;
1596 model[i+1] = 0;
1597
1598 return ret;
1599}
1600
1601static bool_Bool wdc_check_device(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1602{
1603 int ret;
1604 bool_Bool supported;
1605 uint32_t read_device_id = -1, read_vendor_id = -1;
1606
1607 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1608 if (ret < 0) {
1609 /* Use the identify nvme command to get vendor id due to NVMeOF device. */
1610 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1611 return false0;
1612 }
1613
1614 supported = false0;
1615
1616 if (read_vendor_id == WDC_NVME_VID0x1c58 ||
1617 read_vendor_id == WDC_NVME_VID_20x1b96 ||
1618 read_vendor_id == WDC_NVME_SNDK_VID0x15b7)
1619 supported = true1;
1620 else
1621 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)
1622 "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)
1623 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)
;
1624
1625 return supported;
1626}
1627
1628static bool_Bool wdc_enc_check_model(struct libnvme_transport_handle *hdl)
1629{
1630 int ret;
1631 bool_Bool supported;
1632 char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40+1];
1633
1634 ret = wdc_get_model_number(hdl, model);
1635 if (ret < 0)
1636 return false0;
1637
1638 supported = false0;
1639 model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40] = 0; /* forced termination */
1640 if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL)_Generic (0 ? (model) : (void *) 1, const void *: (const char
*) (strstr (model, "OpenFlex")), default: strstr (model, "OpenFlex"
))
)
1641 supported = true1;
1642 else
1643 nvme_show_error("ERROR: WDC: unsupported WDC enclosure, Model = %s", model)nvme_show_message(1, "ERROR: WDC: unsupported WDC enclosure, Model = %s"
, model)
;
1644
1645 return supported;
1646}
1647
1648static __u64 wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1649{
1650 int ret;
1651 uint32_t read_device_id = -1, read_vendor_id = -1;
1652 __u64 capabilities = 0;
1653 __u32 cust_id;
1654
1655 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1656 if (ret < 0) {
1657 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1658 return capabilities;
1659 }
1660
1661 /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
1662 if (read_device_id == -1 && read_vendor_id != -1) {
1663 capabilities = wdc_get_enc_drive_capabilities(ctx, hdl);
1664 return capabilities;
1665 }
1666
1667 switch (read_vendor_id) {
1668 case WDC_NVME_VID0x1c58:
1669 switch (read_device_id) {
1670 case WDC_NVME_SN100_DEV_ID0x0003:
1671 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 |
1672 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1673 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1674 break;
1675
1676 case WDC_NVME_SN200_DEV_ID0x0023:
1677 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1678 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1679 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1680
1681 /* verify the 0xCA log page is supported */
1682 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1683 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1684 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1685
1686 /* verify the 0xC1 log page is supported */
1687 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1688 WDC_NVME_ADD_LOG_OPCODE0xC1, 0))
1689 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
1690 break;
1691
1692 default:
1693 capabilities = 0;
1694 }
1695 break;
1696
1697 case WDC_NVME_VID_20x1b96:
1698 switch (read_device_id) {
1699 case WDC_NVME_SN630_DEV_ID0x2200:
1700 case WDC_NVME_SN630_DEV_ID_10x2201:
1701 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1702 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1703 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1704 /* verify the 0xCA log page is supported */
1705 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1706 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1707 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1708
1709 /* verify the 0xD0 log page is supported */
1710 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1711 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1712 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1713 break;
1714
1715 case WDC_NVME_SN640_DEV_ID0x2400:
1716 case WDC_NVME_SN640_DEV_ID_10x2401:
1717 case WDC_NVME_SN640_DEV_ID_20x2402:
1718 case WDC_NVME_SN640_DEV_ID_30x2404:
1719 case WDC_NVME_SN560_DEV_ID_10x2712:
1720 case WDC_NVME_SN560_DEV_ID_20x2713:
1721 case WDC_NVME_SN560_DEV_ID_30x2714:
1722 case WDC_NVME_SN660_DEV_ID0x2704:
1723 /* verify the 0xC0 log page is supported */
1724 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1725 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)
1726 == true1) {
1727 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1728 }
1729
1730 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1731 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1732 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1733 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1734 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1735
1736 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1737 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1738 WDC_ERROR_REC_LOG_ID0xC1, 0))
1739 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1740
1741 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1742 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1743 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1744 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1745
1746 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1747 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1748 WDC_DEV_CAP_LOG_ID0xC4, 0))
1749 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1750
1751 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1752 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1753 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1754 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1755
1756 /* verify the 0xCA log page is supported */
1757 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1758 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1759 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1760
1761 /* verify the 0xD0 log page is supported */
1762 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1763 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1764 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1765
1766 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1767 /* Can still determine some capabilities in this case, but log an error */
1768 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1769 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1770 "%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)
1771 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1772
1773 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1774 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) || (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1775 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1776 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1777 else
1778 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1779
1780 break;
1781
1782 case WDC_NVME_SN840_DEV_ID0x2300:
1783 case WDC_NVME_SN840_DEV_ID_10x2500:
1784 case WDC_NVME_SN860_DEV_ID0x2730:
1785 /* verify the 0xC0 log page is supported */
1786 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1787 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, 0))
1788 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1789 fallthrough__attribute__((fallthrough));
1790 case WDC_NVME_ZN540_DEV_ID0x2600:
1791 case WDC_NVME_SN540_DEV_ID0x2610:
1792 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1793 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1794 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1795 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1796 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1797 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1798
1799 /* verify the 0xCA log page is supported */
1800 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1801 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1802 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1803
1804 /* verify the 0xD0 log page is supported */
1805 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1806 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1807 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1808 break;
1809
1810 case WDC_NVME_SN650_DEV_ID0x2700:
1811 case WDC_NVME_SN650_DEV_ID_10x2701:
1812 case WDC_NVME_SN650_DEV_ID_20x2702:
1813 case WDC_NVME_SN650_DEV_ID_30x2720:
1814 case WDC_NVME_SN650_DEV_ID_40x2721:
1815 case WDC_NVME_SN655_DEV_ID0x2722:
1816 case WDC_NVME_SN655_DEV_ID_10x2723:
1817 case WDC_NVME_SN550_DEV_ID0x2708:
1818 /* verify the 0xC0 log page is supported */
1819 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1820 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
1821 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1822
1823 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1824 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1825 WDC_ERROR_REC_LOG_ID0xC1, 0))
1826 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1827
1828 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1829 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1830 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1831 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1832
1833 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1834 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1835 WDC_DEV_CAP_LOG_ID0xC4, 0))
1836 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1837
1838 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1839 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1840 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1841 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1842
1843 /* verify the 0xCA log page is supported */
1844 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1845 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
1846 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1847
1848 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1849 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1850 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1851 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 |
1852 WDC_DRIVE_CAP_REASON_ID0x0000000000010000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1853
1854 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1855 /* Can still determine some capabilities in this case, but log an error */
1856 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1857 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1858 "%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)
1859 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1860
1861 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
1862 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1863 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
1864 (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1865 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1866 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1867 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1868 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1869 else
1870 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1871 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1872
1873 break;
1874
1875 case WDC_NVME_SN861_DEV_ID0x2750:
1876 case WDC_NVME_SN861_DEV_ID_10x2751:
1877 case WDC_NVME_SN861_DEV_ID_20x2752:
1878 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1879 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1880 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1881 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1882 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1883 WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1884 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
1885 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1886 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1887 WDC_DRIVE_CAP_INFO0x0000000000080000 |
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 case WDC_NVME_SNTMP_DEV_ID0x2761:
1895 case WDC_NVME_SNTMP_DEV_ID_10x2763:
1896 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1897 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1898 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1899 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1900 WDC_DRIVE_CAP_DUI0x0000000800000000 |
1901 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1902 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1903 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1904 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1905 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1906 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1907 break;
1908
1909 default:
1910 capabilities = 0;
1911 }
1912 break;
1913
1914 case WDC_NVME_SNDK_VID0x15b7:
1915 switch (read_device_id) {
1916 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
1917 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
1918 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
1919 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
1920 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
1921 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1922 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1923 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1924 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1925 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1926 WDC_DRIVE_CAP_UDUI0x0000040000000000 |
1927 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1928 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1929 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1930 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1931 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1932 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1933 break;
1934
1935 case WDC_NVME_SXSLCL_DEV_ID0x2001:
1936 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
1937 break;
1938
1939 case WDC_NVME_SN520_DEV_ID0x5003:
1940 case WDC_NVME_SN520_DEV_ID_10x5004:
1941 case WDC_NVME_SN520_DEV_ID_20x5005:
1942 case WDC_NVME_SN810_DEV_ID0x5011:
1943 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000;
1944 break;
1945
1946 case WDC_NVME_SN820CL_DEV_ID0x5037:
1947 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 |
1948 WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 |
1949 WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 | WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1950 WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
1951 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1952 WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000;
1953 break;
1954
1955 case WDC_NVME_SN720_DEV_ID0x5002:
1956 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1957 WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000;
1958 break;
1959
1960 case WDC_NVME_SN730_DEV_ID0x5006:
1961 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1962 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 |
1963 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000;
1964 break;
1965
1966 case WDC_NVME_SN530_DEV_ID_10x5007:
1967 fallthrough__attribute__((fallthrough));
1968 case WDC_NVME_SN530_DEV_ID_20x5008:
1969 fallthrough__attribute__((fallthrough));
1970 case WDC_NVME_SN530_DEV_ID_30x5009:
1971 fallthrough__attribute__((fallthrough));
1972 case WDC_NVME_SN530_DEV_ID_40x500b:
1973 fallthrough__attribute__((fallthrough));
1974 case WDC_NVME_SN530_DEV_ID_50x501d:
1975 fallthrough__attribute__((fallthrough));
1976 case WDC_NVME_SN350_DEV_ID0x5019:
1977 fallthrough__attribute__((fallthrough));
1978 case WDC_NVME_SN570_DEV_ID0x501A:
1979 fallthrough__attribute__((fallthrough));
1980 case WDC_NVME_SN850X_DEV_ID0x5030:
1981 fallthrough__attribute__((fallthrough));
1982 case WDC_NVME_SN5000_DEV_ID_10x5034:
1983 fallthrough__attribute__((fallthrough));
1984 case WDC_NVME_SN5000_DEV_ID_20x5035:
1985 fallthrough__attribute__((fallthrough));
1986 case WDC_NVME_SN5000_DEV_ID_30x5036:
1987 fallthrough__attribute__((fallthrough));
1988 case WDC_NVME_SN5000_DEV_ID_40x504A:
1989 fallthrough__attribute__((fallthrough));
1990 case WDC_NVME_SN7000S_DEV_ID_10x5039:
1991 fallthrough__attribute__((fallthrough));
1992 case WDC_NVME_SN7150_DEV_ID_10x503b:
1993 fallthrough__attribute__((fallthrough));
1994 case WDC_NVME_SN7150_DEV_ID_20x503c:
1995 fallthrough__attribute__((fallthrough));
1996 case WDC_NVME_SN7150_DEV_ID_30x503d:
1997 fallthrough__attribute__((fallthrough));
1998 case WDC_NVME_SN7150_DEV_ID_40x503e:
1999 fallthrough__attribute__((fallthrough));
2000 case WDC_NVME_SN7150_DEV_ID_50x503f:
2001 fallthrough__attribute__((fallthrough));
2002 case WDC_NVME_SN7100_DEV_ID_10x5043:
2003 fallthrough__attribute__((fallthrough));
2004 case WDC_NVME_SN7100_DEV_ID_20x5044:
2005 fallthrough__attribute__((fallthrough));
2006 case WDC_NVME_SN7100_DEV_ID_30x5045:
2007 fallthrough__attribute__((fallthrough));
2008 case WDC_NVME_SN8000S_DEV_ID0x5049:
2009 fallthrough__attribute__((fallthrough));
2010 case WDC_NVME_SN5100S_DEV_ID_10x5061:
2011 fallthrough__attribute__((fallthrough));
2012 case WDC_NVME_SN5100S_DEV_ID_20x5062:
2013 fallthrough__attribute__((fallthrough));
2014 case WDC_NVME_SN5100S_DEV_ID_30x5063:
2015 fallthrough__attribute__((fallthrough));
2016 case WDC_NVME_SN740_DEV_ID0x5015:
2017 case WDC_NVME_SN740_DEV_ID_10x5016:
2018 case WDC_NVME_SN740_DEV_ID_20x5017:
2019 case WDC_NVME_SN740_DEV_ID_30x5025:
2020 case WDC_NVME_SN340_DEV_ID0x500d:
2021 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000;
2022 break;
2023
2024 case WDC_NVME_ZN350_DEV_ID0x5010:
2025 case WDC_NVME_ZN350_DEV_ID_10x5018:
2026 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
2027 WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
2028 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2029 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
2030 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000;
2031 break;
2032
2033 default:
2034 capabilities = 0;
2035 }
2036 break;
2037 default:
2038 capabilities = 0;
2039 }
2040
2041 return capabilities;
2042}
2043
2044static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx,
2045 struct libnvme_transport_handle *hdl)
2046{
2047 int ret;
2048 uint32_t read_vendor_id;
2049 __u64 capabilities = 0;
2050 __u32 cust_id, market_name_len;
2051 char marketing_name[64];
2052 void *dev_mng_log = NULL((void*)0);
2053 int uuid_index = 0;
2054 struct nvme_id_uuid_list uuid_list;
2055
2056 memset(marketing_name, 0, 64);
2057
2058 ret = wdc_get_vendor_id(hdl, &read_vendor_id);
2059 if (ret < 0)
2060 return capabilities;
2061
2062 switch (read_vendor_id) {
2063 case WDC_NVME_VID0x1c58:
2064 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
2065 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000);
2066
2067 /* verify the 0xCA log page is supported */
2068 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2069 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2070 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2071
2072 /* verify the 0xC1 log page is supported */
2073 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2074 WDC_NVME_ADD_LOG_OPCODE0xC1, 0) == true1)
2075 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
2076 break;
2077 case WDC_NVME_VID_20x1b96:
2078 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
2079 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
2080 WDC_DRIVE_CAP_RESIZE0x0000000000000100);
2081
2082 /* Find the WDC UUID index */
2083 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2084 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2085 /* check for the Sandisk UUID first */
2086 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2087
2088 if (uuid_index < 0)
2089 /* The Sandisk UUID is not found;
2090 * check for the WDC UUID second.
2091 */
2092 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2093 }
2094
2095 /* WD UUID not found, use default uuid index - 0 */
2096 if (uuid_index < 0)
2097 uuid_index = 0;
2098
2099 /* verify the 0xC2 Device Manageability log page is supported */
2100 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2101 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
2102 uuid_index) == false0) {
2103 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)
2104 uuid_index)nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
;
2105 goto out;
2106 }
2107
2108 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
2109 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
2110 goto out;
2111 }
2112
2113 /* Get the customer ID and marketing name from WD C2 log page */
2114 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log,
2115 &cust_id,
2116 WDC_C2_CUSTOMER_ID_ID0x15))
2117 nvme_show_error("ERROR: SNDK: Get Customer FW ID Failed")nvme_show_message(1, "ERROR: SNDK: Get Customer FW ID Failed"
)
;
2118
2119 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
2120 WDC_C2_MARKETING_NAME_ID0x07,
2121 (char *)marketing_name,
2122 &market_name_len))
2123 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
2124
2125 /* verify the 0xC0 log page is supported */
2126 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2127 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
2128 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
2129
2130 /* verify the 0xC3 log page is supported */
2131 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2132 WDC_LATENCY_MON_LOG_ID0xC3, 0) == true1)
2133 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
2134
2135 /* verify the 0xCA log page is supported */
2136 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2137 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2138 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2139
2140 /* verify the 0xD0 log page is supported */
2141 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2142 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == true1)
2143 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
2144
2145 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
2146 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
2147 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
2148 (cust_id == WDC_CUSTOMER_ID_0x13040x1304) ||
2149 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) ||
2150 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len)))
2151 /* Set capabilities for OCP compliant drives */
2152 capabilities |= (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
2153 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2154 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000);
2155 else {
2156 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
2157 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
2158
2159 /* if the 0xCB log page is supported */
2160 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2161 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0) == true1)
2162 capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000;
2163 }
2164
2165 break;
2166 case WDC_NVME_SNDK_VID0x15b7:
2167 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
2168 break;
2169 default:
2170 capabilities = 0;
2171 }
2172
2173out:
2174 return capabilities;
2175}
2176
2177static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len,
2178 const char *suffix)
2179{
2180 int i;
2181 int ret;
2182 int res_len = 0;
2183 char orig[PATH_MAX4096] = {0};
2184 struct libnvme_passthru_cmd cmd;
2185 struct nvme_id_ctrl ctrl;
2186 int ctrl_sn_len = sizeof(ctrl.sn);
2187
2188 i = sizeof(ctrl.sn) - 1;
2189 strncpy(orig, file, PATH_MAX4096 - 1);
2190 memset(file, 0, len);
2191 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
2192 nvme_init_identify_ctrl(&cmd, &ctrl);
2193 ret = libnvme_exec_admin_passthru(hdl, &cmd);
2194 if (ret) {
2195 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)
;
2196 return -1;
2197 }
2198 /* Remove trailing spaces from the name */
2199 while (i && ctrl.sn[i] == ' ') {
2200 ctrl.sn[i] = '\0';
2201 i--;
2202 }
2203 if (ctrl.sn[sizeof(ctrl.sn) - 1] == '\0')
2204 ctrl_sn_len = strlen(ctrl.sn);
2205
2206 res_len = snprintf(file, len, "%s%.*s%s", orig, ctrl_sn_len, ctrl.sn, suffix);
2207 if (len <= res_len) {
2208 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
2209 "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"
)
;
2210 return -1;
2211 }
2212
2213 return 0;
2214}
2215
2216static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
2217 __u32 drive_log_length)
2218{
2219 int fd;
2220 int ret;
2221
2222 if (!drive_log_length) {
2223 nvme_show_error("ERROR: WDC: invalid log file length")nvme_show_message(1, "ERROR: WDC: invalid log file length");
2224 return -1;
2225 }
2226
2227 fd = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
2228 if (fd < 0) {
2229 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
2230 return -1;
2231 }
2232
2233 while (drive_log_length > WRITE_SIZE(sizeof(__u8) * 4096)) {
2234 ret = write(fd, drive_log_data, WRITE_SIZE(sizeof(__u8) * 4096));
2235 if (ret < 0) {
2236 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2237 close(fd);
2238 return -1;
2239 }
2240 drive_log_data += WRITE_SIZE(sizeof(__u8) * 4096);
2241 drive_log_length -= WRITE_SIZE(sizeof(__u8) * 4096);
2242 }
2243
2244 ret = write(fd, drive_log_data, drive_log_length);
2245 if (ret < 0) {
2246 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2247 close(fd);
2248 return -1;
2249 }
2250
2251 if (shr_fsync(fd) < 0) {
2252 nvme_show_error("ERROR: WDC: fsync: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: fsync: %s", libnvme_strerror
((*__errno_location ())))
;
2253 close(fd);
2254 return -1;
2255 }
2256 close(fd);
2257 return 0;
2258}
2259
2260bool_Bool wdc_validate_dev_mng_log(void *data)
2261{
2262 __u32 remaining_len = 0;
2263 __u32 log_length = 0;
2264 __u32 log_entry_size = 0;
2265 __u32 log_entry_id = 0;
2266 __u32 offset = 0;
2267 bool_Bool valid_log = false0;
2268 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2269 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2270
2271 log_length = le32_to_cpu(hdr_ptr->length);
2272 /* Ensure log data is large enough for common header */
2273 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2274 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
))
2275 "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
))
2276 __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
))
;
2277 return valid_log;
2278 }
2279
2280 /* Get pointer to first log Entry */
2281 offset = sizeof(struct wdc_c2_log_page_header);
2282 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2283 remaining_len = log_length - offset;
2284
2285 /* Proceed only if there is at least enough data to read an entry header */
2286 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2287 /* Get size of the next entry */
2288 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2289 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2290 /*
2291 * If log entry size is 0 or the log entry goes past the end
2292 * of the data, we must be at the end of the data
2293 */
2294 if (!log_entry_size || log_entry_size > remaining_len) {
2295 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__)
2296 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2297 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)
2298 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2299 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)
2300 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2301
2302 /* Force the loop to end */
2303 remaining_len = 0;
2304 } else if (!log_entry_id || log_entry_id > 200) {
2305 /* Invalid entry - fail the search */
2306 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)
2307 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2308 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)
2309 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2310 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2311
2312 /* Force the loop to end */
2313 remaining_len = 0;
2314 valid_log = false0;
2315 } else {
2316 /* A valid log has at least one entry and no invalid entries */
2317 valid_log = true1;
2318 remaining_len -= log_entry_size;
2319 if (remaining_len > 0) {
2320 /* Increment the offset counter */
2321 offset += log_entry_size;
2322 /* Get the next entry */
2323 p_next_log_entry =
2324 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2325 }
2326 }
2327 }
2328
2329 return valid_log;
2330}
2331
2332bool_Bool wdc_parse_dev_mng_log_entry(void *data, __u32 entry_id,
2333 struct wdc_c2_log_subpage_header **log_entry)
2334{
2335 __u32 remaining_len = 0;
2336 __u32 log_length = 0;
2337 __u32 log_entry_size = 0;
2338 __u32 log_entry_id = 0;
2339 __u32 offset = 0;
2340 bool_Bool found = false0;
2341 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2342 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2343
2344 log_length = le32_to_cpu(hdr_ptr->length);
2345 /* Ensure log data is large enough for common header */
2346 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2347 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
))
2348 "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
))
2349 __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
))
;
2350 return found;
2351 }
2352
2353 /* Get pointer to first log Entry */
2354 offset = sizeof(struct wdc_c2_log_page_header);
2355 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2356 remaining_len = log_length - offset;
2357
2358 if (!log_entry) {
2359 nvme_show_error("ERROR: WDC - %s: No log entry pointer.", __func__)nvme_show_message(1, "ERROR: WDC - %s: No log entry pointer."
, __func__)
;
2360 return found;
2361 }
2362 *log_entry = NULL((void*)0);
2363
2364 /* Proceed only if there is at least enough data to read an entry header */
2365 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2366 /* Get size of the next entry */
2367 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2368 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2369
2370 /*
2371 * If log entry size is 0 or the log entry goes past the end
2372 * of the data, we must be at the end of the data
2373 */
2374 if (!log_entry_size || log_entry_size > remaining_len) {
2375 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__)
2376 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2377 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)
2378 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2379 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)
2380 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2381
2382 /* Force the loop to end */
2383 remaining_len = 0;
2384 } else if (!log_entry_id || log_entry_id > 200) {
2385 /* Invalid entry - fail the search */
2386 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)
2387 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2388 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)
2389 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2390 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2391
2392 /* Force the loop to end */
2393 remaining_len = 0;
2394 } else {
2395 if (log_entry_id == entry_id) {
2396 found = true1;
2397 *log_entry = p_next_log_entry;
2398 remaining_len = 0;
2399 } else {
2400 remaining_len -= log_entry_size;
2401 }
2402
2403 if (remaining_len > 0) {
2404 /* Increment the offset counter */
2405 offset += log_entry_size;
2406
2407 /* Get the next entry */
2408 p_next_log_entry =
2409 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2410 }
2411 }
2412 }
2413
2414 return found;
2415}
2416
2417bool_Bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id,
2418 struct wdc_c2_log_page_header *p_log_hdr,
2419 struct wdc_c2_log_subpage_header **p_p_found_log_entry)
2420{
2421 __u32 remaining_len = 0;
2422 __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1;
2423 __u32 log_entry_size = 0;
2424 __u32 log_entry_id = 0;
2425 __u32 size = 0;
2426 bool_Bool valid_log;
2427 __u32 offset = 0;
2428 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2429
2430 *p_p_found_log_entry = NULL((void*)0);
2431
2432 /* Ensure log data is large enough for common header */
2433 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2434 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
))
2435 "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
))
2436 __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
))
;
2437 return false0;
2438 }
2439
2440 /* Get pointer to first log Entry */
2441 size = sizeof(struct wdc_c2_log_page_header);
2442 offset = size;
2443 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2444 remaining_len = log_length - size;
2445 valid_log = false0;
2446
2447 /*
2448 * Walk the entire structure. Perform a sanity check to make sure this is a
2449 * standard version of the structure. This means making sure each entry looks
2450 * valid. But allow for the data to overflow the allocated
2451 * buffer (we don't want a false negative because of a FW formatting error)
2452 */
2453
2454 /* Proceed only if there is at least enough data to read an entry header */
2455 while (remaining_len >= log_entry_hdr_size) {
2456 /* Get size of the next entry */
2457 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2458 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2459
2460 /*
2461 * If log entry size is 0 or the log entry goes past the end
2462 * of the data, we must be at the end of the data
2463 */
2464 if (!log_entry_size || log_entry_size > remaining_len) {
2465 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__)
2466 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2467 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)
2468 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2469 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)
2470 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2471
2472 /* Force the loop to end */
2473 remaining_len = 0;
2474 } else if (!log_entry_id || log_entry_id > 200) {
2475 /* Invalid entry - fail the search */
2476 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)
2477 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2478 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)
2479 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2480 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2481
2482 /* Force the loop to end */
2483 remaining_len = 0;
2484 valid_log = false0;
2485
2486 /* The structure is invalid, so any match that was found is invalid. */
2487 *p_p_found_log_entry = NULL((void*)0);
2488 } else {
2489 /* Structure must have at least one valid entry to be considered valid */
2490 valid_log = true1;
2491 if (log_entry_id == entry_id)
2492 /* A potential match. */
2493 *p_p_found_log_entry = p_next_log_entry;
2494
2495 remaining_len -= log_entry_size;
2496
2497 if (remaining_len > 0) {
2498 /* Increment the offset counter */
2499 offset += log_entry_size;
2500
2501 /* Get the next entry */
2502 p_next_log_entry =
2503 (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2504 }
2505 }
2506 }
2507
2508 return valid_log;
2509}
2510
2511static bool_Bool get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, void **log_data,
2512 __u8 uuid_ix)
2513{
2514 struct wdc_c2_log_page_header *hdr_ptr;
2515 struct libnvme_passthru_cmd cmd;
2516 bool_Bool valid = false0;
2517 __u32 length = 0;
2518 void *data;
2519 int ret = 0;
2520
2521 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2522 if (!data) {
2523 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2524 return false0;
2525 }
2526
2527 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2528
2529 /* get the log page length */
2530 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2531 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2532 WDC_C2_LOG_BUF_LEN0x1000);
2533 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2534 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2535 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2536 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2537 if (ret) {
2538 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)
2539 "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)
2540 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)
;
2541 goto end;
2542 }
2543
2544 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2545 length = le32_to_cpu(hdr_ptr->length);
2546
2547 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2548 /* Log page buffer too small for actual data */
2549 free(data);
2550 data = calloc(length, sizeof(__u8));
2551 if (!data) {
2552 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2553 goto end;
2554 }
2555
2556 /* get the log page data with the increased length */
2557 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2558 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2559 length);
2560 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2561 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2562 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2563 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2564 if (ret) {
2565 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)
2566 "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)
2567 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)
;
2568 goto end;
2569 }
2570 }
2571
2572 valid = wdc_validate_dev_mng_log(data);
2573 if (valid) {
2574 /* Ensure size of log data matches length in log header */
2575 *log_data = calloc(length, sizeof(__u8));
2576 if (!*log_data) {
2577 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2578 valid = false0;
2579 goto end;
2580 }
2581 memcpy((void *)*log_data, data, length);
2582 } else {
2583 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)
2584 uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
;
2585 }
2586
2587end:
2588 free(data);
2589 return valid;
2590}
2591
2592static bool_Bool get_dev_mgmt_log_page_lid_data(struct libnvme_transport_handle *hdl,
2593 void **cbs_data,
2594 __u8 lid,
2595 __u8 log_id,
2596 __u8 uuid_ix)
2597{
2598 void *data;
2599 struct wdc_c2_log_page_header *hdr_ptr;
2600 struct wdc_c2_log_subpage_header *sph;
2601 struct libnvme_passthru_cmd cmd;
2602 __u32 length = 0;
2603 int ret = 0;
2604 bool_Bool found = false0;
2605
2606 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2607 if (!data) {
2608 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2609 return false0;
2610 }
2611
2612 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2613
2614 /* get the log page length */
2615 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2616 WDC_C2_LOG_BUF_LEN0x1000);
2617 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2618 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2619 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2620 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2621 if (ret) {
2622 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)
2623 "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)
2624 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)
;
2625 goto end;
2626 }
2627
2628 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2629 length = le32_to_cpu(hdr_ptr->length);
2630
2631 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2632 /* Log Page buffer too small, free and reallocate the necessary size */
2633 free(data);
2634 data = calloc(length, sizeof(__u8));
2635 if (!data) {
2636 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2637 goto end;
2638 }
2639
2640 /* get the log page data with the increased length */
2641 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2642 length);
2643 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2644 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2645 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2646 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2647 if (ret) {
2648 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)
2649 "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)
2650 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)
;
2651 goto end;
2652 }
2653 }
2654
2655 /* Check the log data to see if the WD version of log page ID's is found */
2656 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2657 sph = NULL((void*)0);
2658 found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
2659 if (found && sph) {
2660 *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
2661 if (!*cbs_data) {
2662 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2663 found = false0;
2664 goto end;
2665 }
2666 memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
2667 } else if(found && !sph) {
2668 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)
;
2669 found = false0;
2670 } else {
2671 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)
2672 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)
;
2673 }
2674
2675end:
2676 free(data);
2677 return found;
2678}
2679
2680static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2681 void **data)
2682{
2683 bool_Bool found = false0;
2684 __u32 device_id = 0, vendor_id = 0;
2685 int uuid_index = 0;
2686 struct nvme_id_uuid_list uuid_list;
2687
2688 *data = NULL((void*)0);
2689
2690 /* The nvme_get_pci_ids() function could fail when drives are connected
2691 * via a PCIe switch. Therefore, the return code is intentionally
2692 * being ignored. The device_id and vendor_id variables have been
2693 * initialized to 0 so the code can continue on without issue for
2694 * both cases: successful or failed.
2695 */
2696 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2697
2698 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2699 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2700 /* check for the Sandisk UUID first */
2701 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2702
2703 if (uuid_index < 0) {
2704 /* The Sandisk UUID is not found;
2705 * check for the WDC UUID second.
2706 */
2707 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2708 if (uuid_index < 0)
2709 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2710 }
2711
2712 if (uuid_index >= 0)
2713 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2714 else {
2715 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2716 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2717 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2718 }
2719 } else if (needs_c2_log_page_check(device_id)) {
2720 /* In certain devices that don't support UUID lists, there are multiple
2721 * definitions of the C2 logpage. In those cases, the code
2722 * needs to try two UUID indexes and use an identification algorithm
2723 * to determine which is returning the correct log page data.
2724 */
2725
2726 uuid_index = 1;
2727 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2728
2729 if (!found) {
2730 /* not found with uuid = 1 try with uuid = 0 */
2731 uuid_index = 0;
2732 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)
2733 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2734
2735 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2736 }
2737 } else {
2738 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2739 uuid_index = 0;
2740 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2741 }
2742
2743 return found;
2744}
2745
2746static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2747 __u8 log_id, void **cbs_data)
2748{
2749 bool_Bool found = false0;
2750 __u8 lid = 0;
2751 __u32 device_id = 0, vendor_id = 0;
2752 int uuid_index = 0;
2753 struct nvme_id_uuid_list uuid_list;
2754
2755 *cbs_data = NULL((void*)0);
2756
2757 /* The nvme_get_pci_ids function could fail when drives are connected
2758 * via a PCIe switch. Therefore, the return code is intentionally
2759 * being ignored. The device_id and vendor_id variables have been
2760 * initialized to 0 so the code can continue on without issue for
2761 * both cases: successful or failed.
2762 */
2763 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2764
2765 lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
2766
2767 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2768 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2769 /* check for the Sandisk UUID first */
2770 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2771
2772 if (uuid_index < 0) {
2773 /* The Sandisk UUID is not found;
2774 * check for the WDC UUID second.
2775 */
2776 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2777 if (uuid_index < 0)
2778 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2779 }
2780
2781 if (uuid_index >= 0)
2782 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid,
2783 log_id, uuid_index);
2784 else {
2785 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2786 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2787 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2788 }
2789 } else if (needs_c2_log_page_check(device_id)) {
2790 /* In certain devices that don't support UUID lists, there are multiple
2791 * definitions of the C2 logpage. In those cases, the code
2792 * needs to try two UUID indexes and use an identification algorithm
2793 * to determine which is returning the correct log page data.
2794 */
2795 uuid_index = 1;
2796 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2797 if (!found) {
2798 /* not found with uuid = 1 try with uuid = 0 */
2799 uuid_index = 0;
2800 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)
2801 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2802
2803 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id,
2804 uuid_index);
2805 }
2806 } else {
2807 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2808 uuid_index = 0;
2809 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2810 }
2811
2812 return found;
2813}
2814
2815static int wdc_get_supported_log_pages(struct libnvme_transport_handle *hdl,
2816 struct nvme_supported_log_pages *supported,
2817 int uuid_index)
2818{
2819 struct libnvme_passthru_cmd cmd;
2820
2821 memset(supported, 0, sizeof(*supported));
2822 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
2823 NVME_CSI_NVM, supported, sizeof(*supported));
2824 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2825 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2826 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2827 return libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2828}
2829
2830static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
2831 struct libnvme_transport_handle *hdl,
2832 __u8 log_id,
2833 __u8 uuid_index)
2834{
2835 int i;
2836 bool_Bool found = false0;
2837 int err = -1;
2838 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
2839
2840 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_supported_log_pages *supports = NULL((void*)0);
2841
2842 /* Check log page id 0 (supported log pages) first */
2843 supports = libnvme_alloc(sizeof(*supports));
2844 if (!supports)
2845 return -ENOMEM12;
2846
2847 err = wdc_get_supported_log_pages(hdl,
2848 supports,
2849 uuid_index);
2850
2851 if (!err) {
2852 /* Check support log page list for support */
2853 if (supports->lid_support[log_id])
2854 /* Support for Log Page found in supported log pages */
2855 found = true1;
2856 }
2857
2858 /* if not found in the supported log pages (log id 0),
2859 * check the WDC C2 log page
2860 */
2861 if (!found) {
2862 if (get_dev_mgment_cbs_data(ctx, hdl,
2863 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
2864 (void *)&cbs_data)) {
2865 if (cbs_data) {
2866 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
2867 if (log_id == cbs_data->data[i]) {
2868 found = true1;
2869 break;
2870 }
2871 }
2872
2873#ifdef WDC_NVME_CLI_DEBUG
2874 if (!found) {
2875 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)
2876 log_id)nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
;
2877 nvme_show_error("WDC: Supported Log Pages:")nvme_show_message(1, "WDC: Supported Log Pages:");
2878 /* print the supported pages */
2879 d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length),
2880 16, 1);
2881 }
2882#endif
2883 free(cbs_data);
2884 } else {
2885 nvme_show_error("ERROR: WDC: cbs_data ptr = NULL")nvme_show_message(1, "ERROR: WDC: cbs_data ptr = NULL");
2886 }
2887 } else {
2888 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)
2889 WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
;
2890 }
2891 }
2892
2893 return found;
2894}
2895
2896static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data,
2897 __u32 entry_id)
2898{
2899 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2900
2901 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2902 if (entry_data) {
2903 *ret_data = le32_to_cpu(entry_data->data);
2904 return true1;
2905 }
2906 }
2907
2908 *ret_data = 0;
2909 return false0;
2910}
2911
2912static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
2913 __u32 entry_id,
2914 char *ret_data,
2915 __u32 *ret_data_len)
2916{
2917 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2918 struct wdc_c2_cbs_data *entry_str_data = NULL((void*)0);
2919
2920 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2921 if (entry_data) {
2922 entry_str_data = (struct wdc_c2_cbs_data *)&entry_data->data;
2923 memcpy(ret_data,
2924 (void *)&entry_str_data->data,
2925 le32_to_cpu(entry_str_data->length));
2926 *ret_data_len = le32_to_cpu(entry_str_data->length);
2927 return true1;
2928 }
2929 }
2930
2931 *ret_data = 0;
2932 *ret_data_len = 0;
2933 return false0;
2934}
2935
2936static bool_Bool wdc_nvme_get_dev_status_log_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __le32 *ret_data,
2937 __u8 log_id)
2938{
2939 __u32 *cbs_data = NULL((void*)0);
2940
2941 if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data)) {
2942 if (cbs_data) {
2943 memcpy((void *)ret_data, (void *)cbs_data, 4);
2944 free(cbs_data);
2945
2946 return true1;
2947 }
2948 }
2949
2950 *ret_data = 0;
2951 return false0;
2952}
2953
2954static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12)
2955{
2956 int ret;
2957 struct libnvme_passthru_cmd admin_cmd;
2958
2959 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2960 admin_cmd.opcode = opcode;
2961 admin_cmd.cdw12 = cdw12;
2962 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
2963 if (ret)
2964 fprintf(stdoutstdout, "ERROR: WDC: Crash dump erase failed\n");
2965 nvme_show_status(ret);
2966 return ret;
2967}
2968
2969static __u32 wdc_dump_length(struct libnvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length)
2970{
2971 int ret;
2972 __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN0x08] = {0};
2973 struct wdc_log_size *l;
2974 struct libnvme_passthru_cmd admin_cmd;
2975
2976 l = (struct wdc_log_size *) buf;
2977 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2978 admin_cmd.opcode = opcode;
2979 admin_cmd.addr = (__u64)(uintptr_t)buf;
2980 admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN0x08;
2981 admin_cmd.cdw10 = cdw10;
2982 admin_cmd.cdw12 = cdw12;
2983
2984 ret = libnvme_exec_admin_passthru(link, &admin_cmd);
2985 if (ret) {
2986 l->log_size = 0;
2987 ret = -1;
2988 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
2989 nvme_show_status(ret);
2990 return ret;
2991 }
2992
2993 if (opcode == WDC_NVME_CAP_DIAG_OPCODE0xE6)
2994 *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07];
2995 else
2996 *dump_length = le32_to_cpu(l->log_size);
2997 return ret;
2998}
2999
3000static __u32 wdc_dump_length_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
3001{
3002 int ret;
3003 struct libnvme_passthru_cmd admin_cmd;
3004
3005 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3006 admin_cmd.opcode = opcode;
3007 admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
3008 admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3009 admin_cmd.cdw10 = cdw10;
3010 admin_cmd.cdw12 = cdw12;
3011
3012 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3013 if (ret) {
3014 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3015 nvme_show_status(ret);
3016 }
3017
3018 return ret;
3019}
3020
3021static __u32 wdc_dump_dui_data(struct libnvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool_Bool last_xfer)
3022{
3023 int ret;
3024 struct libnvme_passthru_cmd admin_cmd;
3025
3026 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3027 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3028 admin_cmd.nsid = 0xFFFFFFFF;
3029 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3030 admin_cmd.data_len = dataLen;
3031 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3032 admin_cmd.cdw12 = offset;
3033 if (last_xfer)
3034 admin_cmd.cdw14 = 0;
3035 else
3036 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3037
3038
3039 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3040 if (ret) {
3041 nvme_show_error("ERROR: WDC: reading DUI data failed")nvme_show_message(1, "ERROR: WDC: reading DUI data failed");
3042 nvme_show_status(ret);
3043 }
3044
3045 return ret;
3046}
3047
3048static __u32 wdc_dump_dui_data_v2(struct libnvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool_Bool last_xfer)
3049{
3050 int ret;
3051 struct libnvme_passthru_cmd admin_cmd;
3052 __u64 offset_lo, offset_hi;
3053
3054 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3055 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3056 admin_cmd.nsid = 0xFFFFFFFF;
3057 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3058 admin_cmd.data_len = dataLen;
3059 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3060 offset_lo = offset & 0x00000000FFFFFFFF;
3061 offset_hi = ((offset & 0xFFFFFFFF00000000) >> 32);
3062 admin_cmd.cdw12 = (__u32)offset_lo;
3063 admin_cmd.cdw13 = (__u32)offset_hi;
3064
3065 if (last_xfer)
3066 admin_cmd.cdw14 = 0;
3067 else
3068 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3069
3070 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3071 if (ret) {
3072 nvme_show_error("ERROR: WDC: reading DUI data V2 failed")nvme_show_message(1, "ERROR: WDC: reading DUI data V2 failed"
)
;
3073 nvme_show_status(ret);
3074 }
3075
3076 return ret;
3077}
3078
3079static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3080 __u32 cdw12, const char *file, __u32 xfer_size)
3081{
3082 int ret = 0;
3083 __u8 *dump_data;
3084 __u32 curr_data_offset, curr_data_len;
3085 int i;
3086 struct libnvme_passthru_cmd admin_cmd;
3087 __u32 dump_length = data_len;
3088
3089 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
3090 if (!dump_data) {
3091 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3092 return -1;
3093 }
3094 memset(dump_data, 0, sizeof(__u8) * dump_length);
3095 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3096 curr_data_offset = 0;
3097 curr_data_len = xfer_size;
3098 i = 0;
3099
3100 admin_cmd.opcode = opcode;
3101 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3102 admin_cmd.data_len = curr_data_len;
3103 admin_cmd.cdw10 = curr_data_len >> 2;
3104 admin_cmd.cdw12 = cdw12;
3105 admin_cmd.cdw13 = curr_data_offset;
3106
3107 while (curr_data_offset < data_len) {
3108 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3109 if (ret) {
3110 nvme_show_status(ret);
3111 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)
3112 __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)
;
3113 break;
3114 }
3115
3116 if ((curr_data_offset + xfer_size) <= data_len)
3117 curr_data_len = xfer_size;
3118 else
3119 curr_data_len = data_len - curr_data_offset; /* last transfer */
3120
3121 curr_data_offset += curr_data_len;
3122 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3123 admin_cmd.data_len = curr_data_len;
3124 admin_cmd.cdw10 = curr_data_len >> 2;
3125 admin_cmd.cdw13 = curr_data_offset >> 2;
3126 i++;
3127 }
3128
3129 if (!ret) {
3130 nvme_show_status(ret);
3131 ret = wdc_create_log_file(file, dump_data, dump_length);
3132 }
3133 free(dump_data);
3134 return ret;
3135}
3136
3137static int wdc_do_dump_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3138 __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
3139{
3140 int ret = 0;
3141 __u8 *dump_data;
3142 __u32 curr_data_offset, log_size;
3143 int i;
3144 struct libnvme_passthru_cmd admin_cmd;
3145
3146 /* if data_len is not 4 byte aligned */
3147 if (data_len & 0x00000003) {
3148 /* Round down to the next 4 byte aligned value */
3149 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)
3150 __func__, data_len)nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
;
3151 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))
3152 __func__, (data_len &= 0xFFFFFFFC))nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, (data_len &= 0xFFFFFFFC))
;
3153 data_len &= 0xFFFFFFFC;
3154 }
3155
3156 dump_data = (__u8 *)malloc(sizeof(__u8) * data_len);
3157
3158 if (!dump_data) {
3159 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3160 return -1;
3161 }
3162 memset(dump_data, 0, sizeof(__u8) * data_len);
3163 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3164 curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3165 i = 0;
3166
3167 /* copy the 8 byte header into the dump_data buffer */
3168 memcpy(dump_data, log_hdr, WDC_NVME_LOG_SIZE_HDR_LEN0x08);
3169
3170 admin_cmd.opcode = opcode;
3171 admin_cmd.cdw12 = cdw12;
3172
3173 /* subtract off the header size since that was already copied into the buffer */
3174 log_size = (data_len - curr_data_offset);
3175 while (log_size > 0) {
3176 xfer_size = min(xfer_size, log_size)({ typeof(xfer_size) _a = (xfer_size); typeof(log_size) _b = (
log_size); do { } while (0); _a < _b ? _a : _b; })
;
3177
3178 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3179 admin_cmd.data_len = xfer_size;
3180 admin_cmd.cdw10 = xfer_size >> 2;
3181 admin_cmd.cdw13 = curr_data_offset >> 2;
3182
3183 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3184 if (ret) {
3185 nvme_show_status(ret);
3186 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)
3187 __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)
;
3188 break;
3189 }
3190
3191 log_size -= xfer_size;
3192 curr_data_offset += xfer_size;
3193 i++;
3194 }
3195
3196 if (!ret) {
3197 nvme_show_error("%s: INFO: ", __func__)nvme_show_message(1, "%s: INFO: ", __func__);
3198 nvme_show_status(ret);
3199 } else {
3200 nvme_show_error("%s: FAILURE: ", __func__)nvme_show_message(1, "%s: FAILURE: ", __func__);
3201 nvme_show_status(ret);
3202 nvme_show_error("%s: Partial data may have been captured", __func__)nvme_show_message(1, "%s: Partial data may have been captured"
, __func__)
;
3203 snprintf(file + strlen(file), PATH_MAX4096, "%s", "-PARTIAL");
3204 }
3205
3206 ret = wdc_create_log_file(file, dump_data, data_len);
3207
3208 free(dump_data);
3209 return ret;
3210}
3211
3212static int wdc_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
3213 struct libnvme_transport_handle *hdl, const char *file,
3214 __u32 bs, int type, int data_area)
3215{
3216 struct nvme_telemetry_log *log;
3217 size_t full_size = 0;
3218 int err = 0, output;
3219 int ctrl_init = 0;
3220 __u64 result;
3221 void *buf = NULL((void*)0);
3222 struct libnvme_passthru_cmd cmd;
3223 struct nvme_id_ctrl ctrl;
3224 __u64 capabilities = 0;
3225
3226 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
3227 nvme_init_identify_ctrl(&cmd, &ctrl);
3228 err = libnvme_exec_admin_passthru(hdl, &cmd);
3229 if (err) {
3230 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)
;
3231 return err;
3232 }
3233
3234 if (!(ctrl.lpa & 0x8)) {
3235 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"
)
;
3236 return -EINVAL22;
3237 }
3238
3239 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3240 if (err) {
3241 nvme_show_error("Failed to scan nvme subsystems")nvme_show_message(1, "Failed to scan nvme subsystems");
3242 return err;
3243 }
3244
3245 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3246
3247 if (type == WDC_TELEMETRY_TYPE_HOST0x1) {
3248 ctrl_init = 0;
3249 } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2) {
3250 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
3251 /* Verify the Controller Initiated Option is enabled */
3252 err = nvme_get_features(hdl, 0,
3253 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
3254 NVME_GET_FEATURES_SEL_CURRENT, 0, 0,
3255 buf, 4, &result);
3256 if (!err) {
3257 if (!result) {
3258 /* enabled */
3259 ctrl_init = 1;
3260 } else {
3261 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__)
;
3262 return -EINVAL22;
3263 }
3264 } else {
3265 nvme_show_error("ERROR: WDC: Get telemetry option feature failed.")nvme_show_message(1, "ERROR: WDC: Get telemetry option feature failed."
)
;
3266 nvme_show_status(err);
3267 return -EPERM1;
3268 }
3269 } else {
3270 ctrl_init = 1;
3271 }
3272 } else {
3273 nvme_show_error("%s: Invalid type parameter; type = %d", __func__, type)nvme_show_message(1, "%s: Invalid type parameter; type = %d",
__func__, type)
;
3274 return -EINVAL22;
3275 }
3276
3277 if (!file) {
3278 nvme_show_error("%s: Please provide an output file!", __func__)nvme_show_message(1, "%s: Please provide an output file!", __func__
)
;
3279 return -EINVAL22;
3280 }
3281
3282 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3283 if (output < 0) {
3284 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 ())))
3285 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3286 return output;
3287 }
3288
3289 if (ctrl_init)
3290 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
3291 data_area, &full_size);
3292 else
3293 err = libnvme_get_new_host_telemetry(hdl, &log,
3294 data_area, &full_size);
3295
3296 if (err < 0) {
3297 nvme_show_err(err, "get-telemetry-log");
3298 goto close_output;
3299 } else if (err > 0) {
3300 nvme_show_status(err);
3301 nvme_show_error("%s: Failed to acquire telemetry header!", __func__)nvme_show_message(1, "%s: Failed to acquire telemetry header!"
, __func__)
;
3302 goto close_output;
3303 }
3304
3305 /*
3306 * Continuously pull data until the offset hits the end of the last
3307 * block.
3308 */
3309 err = shr_write_all(output, log, full_size);
3310 if (err)
3311 nvme_show_error("ERROR: %s: write: %s", __func__, libnvme_strerror(-err))nvme_show_message(1, "ERROR: %s: write: %s", __func__, libnvme_strerror
(-err))
;
3312 else if (shr_fsync(output) < 0) {
3313 nvme_show_error("ERROR: %s: fsync: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "ERROR: %s: fsync: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3314 err = -1;
3315 }
3316
3317 free(log);
3318close_output:
3319 close(output);
3320 return err;
3321}
3322
3323static int wdc_do_cap_diag(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *file,
3324 __u32 xfer_size, int type, int data_area)
3325{
3326 int ret = -1;
3327 __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08;
3328 struct wdc_e6_log_hdr *log_hdr;
3329 __u32 cap_diag_length;
3330
3331 log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size);
3332 if (!log_hdr) {
3333 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3334 ret = -1;
3335 goto out;
3336 }
3337 memset(log_hdr, 0, e6_log_hdr_size);
3338
3339 if (type == WDC_TELEMETRY_TYPE_NONE0x0) {
3340 if (data_area) {
3341 nvme_show_error(nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3342 "%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__)
3343 __func__)nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
;
3344 ret = -1;
3345 goto out;
3346 }
3347 ret = wdc_dump_length_e6(hdl,
3348 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3349 WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08>>2,
3350 0x00,
3351 log_hdr);
3352 if (ret == -1) {
3353 ret = -1;
3354 goto out;
3355 }
3356
3357 cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 |
3358 log_hdr->log_size[2] << 8 | log_hdr->log_size[3]);
3359
3360 if (!cap_diag_length) {
3361 nvme_show_error("INFO: WDC: Capture Diagnostics log is empty")nvme_show_message(1, "INFO: WDC: Capture Diagnostics log is empty"
)
;
3362 } else if (cap_diag_length < WDC_NVME_LOG_SIZE_HDR_LEN0x08) {
3363 nvme_show_error("%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)",nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)"
, __func__, cap_diag_length, 0x08)
3364 __func__, cap_diag_length, WDC_NVME_LOG_SIZE_HDR_LEN)nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)"
, __func__, cap_diag_length, 0x08)
;
3365 ret = -1;
3366 } else if (cap_diag_length > WDC_NVME_CAP_DIAG_LENGTH_MAX(1U << 30)) {
3367 nvme_show_error("%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x",nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x"
, __func__, cap_diag_length, (1U << 30))
3368 __func__, cap_diag_length, WDC_NVME_CAP_DIAG_LENGTH_MAX)nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x"
, __func__, cap_diag_length, (1U << 30))
;
3369 ret = -1;
3370 } else {
3371 ret = wdc_do_dump_e6(hdl,
3372 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3373 cap_diag_length,
3374 (WDC_NVME_CAP_DIAG_SUBCMD0x00 << WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_CAP_DIAG_CMD0x00,
3375 file, xfer_size, (__u8 *)log_hdr);
3376
3377 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)
;
3378 }
3379 } else if ((type == WDC_TELEMETRY_TYPE_HOST0x1) ||
3380 (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
3381 /* Get the desired telemetry log page */
3382 ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size,
3383 type, data_area);
3384 } else {
3385 nvme_show_error("%s: ERROR: Invalid type : %d", __func__, type)nvme_show_message(1, "%s: ERROR: Invalid type : %d", __func__
, type)
;
3386 }
3387
3388out:
3389 free(log_hdr);
3390 return ret;
3391}
3392
3393static int wdc_do_cap_dui_v1(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3394 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size)
3395{
3396 __s32 log_size = 0;
3397 __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size);
3398 __u32 curr_data_offset = 0;
3399 __u8 *buffer_addr;
3400 __u8 *dump_data = NULL((void*)0);
3401 bool_Bool last_xfer = false0;
3402 int err;
3403 int i;
3404 int j;
3405 int output;
3406 int ret = 0;
3407
3408 if (verbose) {
3409 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)
3410 data_area)nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
;
3411 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)
;
3412 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)
;
3413 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)
;
3414 }
3415
3416 if (!cap_dui_length) {
3417 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"
)
;
3418 return 0;
3419 }
3420
3421 /* parse log header for all sections up to specified data area inclusively */
3422 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3423 for (j = 0; j < log_hdr->section_count; j++) {
3424 log_size += log_hdr->log_section[j].section_size;
3425 if (verbose)
3426 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)
3427 "%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)
3428 __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)
3429 (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)
3430 (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)
;
3431
3432 }
3433 } else {
3434 log_size = cap_dui_length;
3435 }
3436
3437 *total_size = log_size;
3438
3439 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size);
3440 if (!dump_data) {
3441 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)
3442 __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)
;
3443 return -1;
3444 }
3445 memset(dump_data, 0, sizeof(__u8) * xfer_size);
3446
3447 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3448 if (output < 0) {
3449 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 ())))
3450 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3451 free(dump_data);
3452 return output;
3453 }
3454
3455 /* write the telemetry and log headers into the dump_file */
3456 err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE0x400);
3457 if (err != WDC_NVME_CAP_DUI_HEADER_SIZE0x400) {
3458 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__)
;
3459 goto free_mem;
3460 }
3461
3462 log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3463 curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3464 i = 0;
3465 buffer_addr = dump_data;
3466
3467 for (; log_size > 0; log_size -= xfer_size) {
3468 xfer_size = min(xfer_size, log_size)({ typeof(xfer_size) _a = (xfer_size); typeof(log_size) _b = (
log_size); do { } while (0); _a < _b ? _a : _b; })
;
3469
3470 if (log_size <= xfer_size)
3471 last_xfer = true1;
3472
3473 ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer);
3474 if (ret) {
3475 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)
3476 "%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)
3477 __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)
;
3478 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3479 nvme_show_status(ret);
3480 break;
3481 }
3482
3483 /* write the dump data into the file */
3484 err = write(output, (void *)buffer_addr, xfer_size);
3485 if (err != xfer_size) {
3486 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)
3487 "%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)
3488 __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)
;
3489 ret = -1;
3490 goto free_mem;
3491 }
3492
3493 curr_data_offset += xfer_size;
3494 i++;
3495 }
3496
3497free_mem:
3498 close(output);
3499 free(dump_data);
3500 return ret;
3501}
3502
3503static int wdc_do_cap_dui_v2_v3(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3504 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3505 __u64 offset)
3506{
3507 __u64 cap_dui_length_v3;
3508 __u64 curr_data_offset = 0;
3509 __s64 log_size = 0;
3510 __u64 xfer_size_long = (__u64)xfer_size;
3511 __u8 *buffer_addr;
3512 __u8 *dump_data = NULL((void*)0);
3513 bool_Bool last_xfer = false0;
3514 int err;
3515 int i;
3516 int j;
3517 int output;
3518 int ret = 0;
3519 struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr;
3520
3521 cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size);
3522
3523 if (verbose) {
3524 nvme_show_error(nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3525 "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)
3526 data_area)nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
;
3527
3528 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)
3529 log_hdr_v3->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
;
3530 if ((log_hdr->hdr_version & 0xFF) == 0x03)
3531 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)
3532 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)
;
3533 }
3534
3535 if (!cap_dui_length_v3) {
3536 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"
)
;
3537 return 0;
3538 }
3539
3540 /* parse log header for all sections up to specified data area inclusively */
3541 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3542 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V30x23; j++) {
3543 if (log_hdr_v3->log_section[j].data_area_id <= data_area &&
3544 log_hdr_v3->log_section[j].data_area_id) {
3545 log_size += log_hdr_v3->log_section[j].section_size;
3546 if (verbose)
3547 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)
3548 "%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)
3549 __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)
3550 (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)
3551 (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)
;
3552 } else {
3553 if (verbose)
3554 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)
3555 __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3556 break;
3557 }
3558 }
3559 } else {
3560 log_size = cap_dui_length_v3;
3561 }
3562
3563 *total_size = log_size;
3564
3565 if (offset >= *total_size) {
3566 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)
3567 "%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)
3568 __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)
;
3569 return -1;
3570 }
3571
3572 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3573 if (!dump_data) {
3574 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)
3575 "%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)
3576 __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)
;
3577 return -1;
3578 }
3579 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3580
3581 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3582 if (output < 0) {
3583 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 ())))
3584 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3585 free(dump_data);
3586 return output;
3587 }
3588
3589 curr_data_offset = 0;
3590
3591 if (file_size) {
3592 /* Write the DUI data based on the passed in file size */
3593 if ((offset + file_size) > *total_size)
3594 log_size = min((*total_size - offset), file_size)({ typeof((*total_size - offset)) _a = ((*total_size - offset
)); typeof(file_size) _b = (file_size); do { } while (0); _a <
_b ? _a : _b; })
;
3595 else
3596 log_size = min(*total_size, file_size)({ typeof(*total_size) _a = (*total_size); typeof(file_size) _b
= (file_size); do { } while (0); _a < _b ? _a : _b; })
;
3597
3598 if (verbose)
3599 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)
3600 "%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)
3601 __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)
3602 (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)
;
3603
3604 curr_data_offset = offset;
3605 }
3606
3607 i = 0;
3608 buffer_addr = dump_data;
3609
3610 for (; log_size > 0; log_size -= xfer_size_long) {
3611 xfer_size_long = min(xfer_size_long, log_size)({ typeof(xfer_size_long) _a = (xfer_size_long); typeof(log_size
) _b = (log_size); do { } while (0); _a < _b ? _a : _b; })
;
3612
3613 if (log_size <= xfer_size_long)
3614 last_xfer = true1;
3615
3616 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr,
3617 last_xfer);
3618 if (ret) {
3619 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
)
3620 "%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
)
3621 __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
)
3622 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
)
;
3623 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3624 nvme_show_status(ret);
3625 break;
3626 }
3627
3628 /* write the dump data into the file */
3629 err = write(output, (void *)buffer_addr, xfer_size_long);
3630 if (err != xfer_size_long) {
3631 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)
3632 "%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)
3633 __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)
;
3634 ret = -1;
3635 goto free_mem;
3636 }
3637
3638 curr_data_offset += xfer_size_long;
3639 i++;
3640 }
3641
3642free_mem:
3643 close(output);
3644 free(dump_data);
3645 return ret;
3646}
3647
3648static int wdc_do_cap_dui_v4(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3649 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3650 __u64 offset)
3651{
3652 __s64 log_size = 0;
3653 __s64 section_size_bytes = 0;
3654 __s64 xfer_size_long = (__s64)xfer_size;
3655 __u64 cap_dui_length_v4;
3656 __u64 curr_data_offset = 0;
3657 __u8 *buffer_addr;
3658 __u8 *dump_data = NULL((void*)0);
3659 int err;
3660 int i;
3661 int j;
3662 int output;
3663 int ret = 0;
3664 bool_Bool last_xfer = false0;
3665 struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr;
3666
3667 cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE512;
3668
3669 if (verbose) {
3670 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)
;
3671 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)
;
3672 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)
;
3673 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)
;
3674 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)
;
3675 }
3676
3677 if (!cap_dui_length_v4) {
3678 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"
)
;
3679 return 0;
3680 }
3681
3682 /* parse log header for all sections up to specified data area inclusively */
3683 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3684 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION0x3A; j++) {
3685 if (log_hdr_v4->log_section[j].data_area_id <= data_area &&
3686 log_hdr_v4->log_section[j].data_area_id) {
3687 section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE512);
3688 log_size += section_size_bytes;
3689 if (verbose)
3690 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)
3691 "%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)
3692 __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)
3693 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)
3694 (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)
;
3695 } else {
3696 if (verbose)
3697 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)
;
3698 break;
3699 }
3700 }
3701 } else {
3702 log_size = cap_dui_length_v4;
3703 }
3704
3705 *total_size = log_size;
3706
3707 if (offset >= *total_size) {
3708 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)
3709 "%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)
3710 __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)
;
3711 return -1;
3712 }
3713
3714 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3715 if (!dump_data) {
3716 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)
3717 __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)
;
3718 return -1;
3719 }
3720 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3721
3722 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3723 if (output < 0) {
3724 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 ())))
3725 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3726 free(dump_data);
3727 return output;
3728 }
3729
3730 curr_data_offset = 0;
3731
3732 if (file_size) {
3733 /* Write the DUI data based on the passed in file size */
3734 if ((offset + file_size) > *total_size)
3735 log_size = min((*total_size - offset), file_size)({ typeof((*total_size - offset)) _a = ((*total_size - offset
)); typeof(file_size) _b = (file_size); do { } while (0); _a <
_b ? _a : _b; })
;
3736 else
3737 log_size = min(*total_size, file_size)({ typeof(*total_size) _a = (*total_size); typeof(file_size) _b
= (file_size); do { } while (0); _a < _b ? _a : _b; })
;
3738
3739 if (verbose)
3740 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)
3741 "%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)
3742 __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)
3743 (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)
;
3744
3745 curr_data_offset = offset;
3746 }
3747
3748 i = 0;
3749 buffer_addr = dump_data;
3750
3751 for (; log_size > 0; log_size -= xfer_size_long) {
3752 xfer_size_long = min(xfer_size_long, log_size)({ typeof(xfer_size_long) _a = (xfer_size_long); typeof(log_size
) _b = (log_size); do { } while (0); _a < _b ? _a : _b; })
;
3753
3754 if (log_size <= xfer_size_long)
3755 last_xfer = true1;
3756
3757 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer);
3758 if (ret) {
3759 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)
3760 "%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)
3761 __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)
3762 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)
;
3763 nvme_show_error("%s: ERROR: WDC:", __func__)nvme_show_message(1, "%s: ERROR: WDC:", __func__);
3764 nvme_show_status(ret);
3765 break;
3766 }
3767
3768 /* write the dump data into the file */
3769 err = write(output, (void *)buffer_addr, xfer_size_long);
3770 if (err != xfer_size_long) {
3771 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)
3772 "%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)
3773 __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)
;
3774 ret = -1;
3775 goto free_mem;
3776 }
3777
3778 curr_data_offset += xfer_size_long;
3779 i++;
3780 }
3781
3782free_mem:
3783 close(output);
3784 free(dump_data);
3785 return ret;
3786}
3787
3788static int wdc_do_cap_dui(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3789 __u64 file_size, __u64 offset)
3790{
3791 int ret = 0;
3792 __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3793 struct wdc_dui_log_hdr *log_hdr;
3794 __s64 total_size = 0;
3795 bool_Bool last_xfer = false0;
3796
3797 log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size);
3798 if (!log_hdr) {
3799 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
)
3800 __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
)
;
3801 return -1;
3802 }
3803 memset(log_hdr, 0, dui_log_hdr_size);
3804
3805 /* get the dui telemetry and log headers */
3806 ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE0x400, 0x00, (__u8 *)log_hdr, last_xfer);
3807 if (ret) {
3808 nvme_show_error("%s: ERROR: WDC: Get DUI headers failed", __func__)nvme_show_message(1, "%s: ERROR: WDC: Get DUI headers failed"
, __func__)
;
3809 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3810 nvme_show_status(ret);
3811 goto out;
3812 }
3813
3814 /* Check the Log Header version */
3815 if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) {
3816 ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr,
3817 &total_size);
3818 if (ret)
3819 goto out;
3820 } else if ((log_hdr->hdr_version & 0xFF) == 0x02 ||
3821 (log_hdr->hdr_version & 0xFF) == 0x03) {
3822 /* Process Version 2 or 3 header */
3823 ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr,
3824 &total_size, file_size, offset);
3825 if (ret)
3826 goto out;
3827 } else if ((log_hdr->hdr_version & 0xFF) == 0x04) {
3828 ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr,
3829 &total_size, file_size, offset);
3830 if (ret)
3831 goto out;
3832 } else {
3833 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)
3834 log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
;
3835 goto out;
3836 }
3837
3838 nvme_show_status(ret);
3839 if (verbose)
3840 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)
3841 (uint64_t)total_size)nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
;
3842
3843out:
3844 free(log_hdr);
3845 return ret;
3846}
3847
3848static int wdc_cap_diag(int argc, char **argv, struct command *acmd,
3849 struct plugin *plugin)
3850{
3851 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
3852 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
3853 const char *desc = "Capture Diagnostics Log.";
3854 const char *file = "Output file pathname.";
3855 const char *size = "Data retrieval transfer size.";
3856 __u64 capabilities = 0;
3857 char f[PATH_MAX4096] = {0};
3858 __u32 xfer_size = 0;
3859 int ret = 0;
3860
3861 struct config {
3862 char *file;
3863 __u32 xfer_size;
3864 };
3865
3866 struct config cfg = {
3867 .file = NULL((void*)0),
3868 .xfer_size = 0x10000
3869 };
3870
3871 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 informational output", 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) } }
3872 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 informational output", 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) } }
3873 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 informational output", 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) } }
;
3874
3875 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3876 if (ret)
3877 return ret;
3878
3879 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3880 if (ret)
3881 return ret;
3882
3883 if (cfg.file)
3884 strncpy(f, cfg.file, PATH_MAX4096 - 1);
3885 if (cfg.xfer_size)
3886 xfer_size = cfg.xfer_size;
3887 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "cap_diag");
3888 if (ret) {
3889 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
3890 return ret;
3891 }
3892 if (!cfg.file) {
3893 if (strlen(f) > PATH_MAX4096 - 5) {
3894 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
3895 return -1;
3896 }
3897 strcat(f, ".bin");
3898 }
3899
3900 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3901 if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001) == WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001)
3902 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0);
3903 else
3904 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
3905 return ret;
3906}
3907
3908static int wdc_do_get_sn730_log_len(struct libnvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode)
3909{
3910 int ret;
3911 uint32_t *output = NULL((void*)0);
3912 struct libnvme_passthru_cmd admin_cmd;
3913
3914 output = (uint32_t *)malloc(sizeof(uint32_t));
3915 if (!output) {
3916 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3917 return -1;
3918 }
3919 memset(output, 0, sizeof(uint32_t));
3920 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3921
3922 admin_cmd.data_len = 8;
3923 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3924 admin_cmd.addr = (uintptr_t)output;
3925 admin_cmd.cdw12 = subopcode;
3926 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3927
3928 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3929 if (!ret)
3930 *len_buf = *output;
3931 free(output);
3932 return ret;
3933}
3934
3935static int wdc_do_get_sn730_log(struct libnvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode)
3936{
3937 int ret;
3938 uint8_t *output = NULL((void*)0);
3939 struct libnvme_passthru_cmd admin_cmd;
3940
3941 output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE0x1000, sizeof(uint8_t));
3942 if (!output) {
3943 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
3944 return -1;
3945 }
3946 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3947 admin_cmd.data_len = SN730_LOG_CHUNK_SIZE0x1000;
3948 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3949 admin_cmd.addr = (uintptr_t)output;
3950 admin_cmd.cdw12 = subopcode;
3951 admin_cmd.cdw13 = offset;
3952 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3953
3954 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3955 if (!ret)
3956 memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE0x1000);
3957 return ret;
3958}
3959
3960static int get_sn730_log_chunks(struct libnvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode)
3961{
3962 int ret = 0;
3963 uint8_t *chunk_buf = NULL((void*)0);
3964 int remaining = log_len;
3965 int curr_offset = 0;
3966
3967 chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE0x1000);
3968 if (!chunk_buf) {
3969 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3970 ret = -1;
3971 goto out;
3972 }
3973
3974 while (remaining > 0) {
3975 memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE0x1000);
3976 ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode);
3977 if (!ret) {
3978 if (remaining >= SN730_LOG_CHUNK_SIZE0x1000) {
3979 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
3980 chunk_buf, SN730_LOG_CHUNK_SIZE0x1000);
3981 } else {
3982 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
3983 chunk_buf, remaining);
3984 }
3985 remaining -= SN730_LOG_CHUNK_SIZE0x1000;
3986 curr_offset += 1;
3987 } else {
3988 goto out;
3989 }
3990 }
3991out:
3992 free(chunk_buf);
3993 return ret;
3994}
3995
3996static int wdc_do_sn730_get_and_tar(struct libnvme_transport_handle *hdl, char *outputName)
3997{
3998 int ret = 0;
3999 void *retPtr;
4000 uint8_t *full_log_buf = NULL((void*)0);
4001 uint8_t *key_log_buf = NULL((void*)0);
4002 uint8_t *core_dump_log_buf = NULL((void*)0);
4003 uint8_t *extended_log_buf = NULL((void*)0);
4004 uint32_t full_log_len = 0;
4005 uint32_t key_log_len = 0;
4006 uint32_t core_dump_log_len = 0;
4007 uint32_t extended_log_len = 0;
4008 struct tarfile_metadata *tarInfo = NULL((void*)0);
4009
4010 tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata));
4011 if (!tarInfo) {
4012 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4013 ret = -1;
4014 goto free_buf;
4015 }
4016 memset(tarInfo, 0, sizeof(struct tarfile_metadata));
4017
4018 /* Create Logs directory */
4019 wdc_UtilsGetTime(&tarInfo->timeInfo);
4020 memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString));
4021 wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
4022 tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth,
4023 tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second);
4024
4025 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN256, "%s",
4026 (char *)outputName);
4027
4028 retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN256);
4029 if (retPtr) {
4030 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
4031 (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR"/", (char *)tarInfo->bufferFolderName);
4032 } else {
4033 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
4034 goto free_buf;
4035 }
4036
4037 ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath);
4038 if (ret) {
4039 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)
;
4040 goto free_buf;
4041 } else {
4042 nvme_show_error("Stored log files in directory: %s", tarInfo->bufferFolderPath)nvme_show_message(1, "Stored log files in directory: %s", tarInfo
->bufferFolderPath)
;
4043 }
4044
4045 ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH0x00080009);
4046 if (ret) {
4047 nvme_show_status(ret);
4048 goto free_buf;
4049 }
4050 ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH0x00090009);
4051 if (ret) {
4052 nvme_show_status(ret);
4053 goto free_buf;
4054 }
4055 ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH0x00120009);
4056 if (ret) {
4057 nvme_show_status(ret);
4058 goto free_buf;
4059 }
4060 ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH0x00420009);
4061 if (ret) {
4062 nvme_show_status(ret);
4063 goto free_buf;
4064 }
4065
4066 full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t));
4067 key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t));
4068 core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t));
4069 extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t));
4070
4071 if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) {
4072 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4073 ret = -1;
4074 goto free_buf;
4075 }
4076
4077 /* Get the full log */
4078 ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE0x00010009);
4079 if (ret) {
4080 nvme_show_status(ret);
4081 goto free_buf;
4082 }
4083
4084 /* Get the key log */
4085 ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE0x00020009);
4086 if (ret) {
4087 nvme_show_status(ret);
4088 goto free_buf;
4089 }
4090
4091 /* Get the core dump log */
4092 ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE0x00030009);
4093 if (ret) {
4094 nvme_show_status(ret);
4095 goto free_buf;
4096 }
4097
4098 /* Get the extended log */
4099 ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009);
4100 if (ret) {
4101 nvme_show_status(ret);
4102 goto free_buf;
4103 }
4104
4105 /* Write log files */
4106 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4107 "full_log", (char *)tarInfo->timeString);
4108 wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len);
4109
4110 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4111 "key_log", (char *)tarInfo->timeString);
4112 wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len);
4113
4114 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4115 "core_dump_log", (char *)tarInfo->timeString);
4116 wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len);
4117
4118 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4119 "extended_log", (char *)tarInfo->timeString);
4120 wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len);
4121
4122 /* Tar the log directory */
4123 wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
4124 wdc_UtilsSnprintf(tarInfo->tarFiles, sizeof(tarInfo->tarFiles), "%s%s%s", (char *)tarInfo->bufferFolderName, WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
4125 wdc_UtilsSnprintf(tarInfo->tarCmd, sizeof(tarInfo->tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarInfo->tarFileName, (char *)tarInfo->tarFiles);
4126
4127 ret = system(tarInfo->tarCmd);
4128
4129 if (ret)
4130 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)
;
4131
4132free_buf:
4133 free(tarInfo);
4134 free(full_log_buf);
4135 free(core_dump_log_buf);
4136 free(key_log_buf);
4137 free(extended_log_buf);
4138 return ret;
4139}
4140
4141static int dump_internal_logs(struct libnvme_transport_handle *hdl, const char *dir_name, int verbose)
4142{
4143 char file_path[PATH_MAX4096];
4144 void *telemetry_log;
4145 const size_t bs = 512;
4146 struct nvme_telemetry_log *hdr;
4147 struct libnvme_passthru_cmd cmd;
4148 size_t full_size, offset = bs;
4149 int err, output;
4150
4151 if (verbose)
4152 printf("NVMe Telemetry log...\n");
4153
4154 hdr = malloc(bs);
4155 telemetry_log = malloc(bs);
4156 if (!hdr || !telemetry_log) {
4157 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 ())))
;
4158 err = -ENOMEM12;
4159 goto free_mem;
4160 }
4161 memset(hdr, 0, bs);
4162
4163 sprintf(file_path, "%s/telemetry.bin", dir_name);
4164 output = shr_open_rawdata(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file_path), (01 | 0100 | 01000), 0666);
4165 if (output < 0) {
4166 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 ())))
;
4167 err = output;
4168 goto free_mem;
4169 }
4170
4171 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4172 NVME_CSI_NVM, hdr, bs);
4173 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))
4174 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4175 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
4176 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4177 if (err < 0)
4178 nvme_show_err(err, "get-telemetry-log");
4179 else if (err > 0) {
4180 nvme_show_status(err);
4181 nvme_show_error("Failed to acquire telemetry header %d!", err)nvme_show_message(1, "Failed to acquire telemetry header %d!"
, err)
;
4182 goto close_output;
4183 }
4184
4185 err = write(output, (void *)hdr, bs);
4186 if (err != bs) {
4187 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4188 goto close_output;
4189 }
4190
4191 full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
4192
4193 while (offset != full_size) {
4194 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4195 NVME_CSI_NVM, telemetry_log, bs);
4196 nvme_init_get_log_lpo(&cmd, offset);
4197 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4198 if (err < 0) {
4199 nvme_show_err(err, "get-telemetry-log");
4200 break;
4201 } else if (err > 0) {
4202 nvme_show_error("Failed to acquire full telemetry log!")nvme_show_message(1, "Failed to acquire full telemetry log!");
4203 nvme_show_status(err);
4204 break;
4205 }
4206
4207 err = write(output, (void *)telemetry_log, bs);
4208 if (err != bs) {
4209 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4210 break;
4211 }
4212 err = 0;
4213 offset += bs;
4214 }
4215
4216close_output:
4217 close(output);
4218free_mem:
4219 free(hdr);
4220 free(telemetry_log);
4221
4222 return err;
4223}
4224
4225static int wdc_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
4226 int *data_area)
4227{
4228 struct libnvme_passthru_cmd cmd;
4229 struct nvme_id_ctrl ctrl;
4230 int err;
4231
4232 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
4233 nvme_init_identify_ctrl(&cmd, &ctrl);
4234 err = libnvme_exec_admin_passthru(hdl, &cmd);
4235 if (err) {
4236 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)
;
4237 return err;
4238 }
4239
4240 if (ctrl.lpa & 0x40)
4241 *data_area = 4;
4242 else
4243 *data_area = 3;
4244
4245 return 0;
4246}
4247
4248static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd,
4249 struct plugin *plugin)
4250{
4251 const char *desc = "Internal Firmware Log.";
4252 const char *file = "Output file pathname.";
4253 const char *size = "Data retrieval transfer size.";
4254 const char *data_area =
4255 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
4256 const char *type =
4257 "Telemetry type - NONE, HOST, or CONTROLLER:\n" \
4258 " NONE - Default, capture without using NVMe telemetry.\n" \
4259 " HOST - Host-initiated telemetry.\n" \
4260 " CONTROLLER - Controller-initiated telemetry.";
4261 const char *verbose = "Display more debug messages.";
4262 const char *file_size =
4263 "Output file size. Deprecated, see man page for supported devices.";
4264 const char *offset =
4265 "Output file data offset. Deprecated, see man page for supported devices.";
4266 char f[PATH_MAX4096] = {0};
4267 char fb[PATH_MAX4096/2] = {0};
4268 char fileSuffix[PATH_MAX4096] = {0};
4269 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4270 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4271 __u32 xfer_size = 0;
4272 int telemetry_type = 0, telemetry_data_area = 0;
4273 UtilsTimeInfo timeInfo;
4274 __u8 timeStamp[MAX_PATH_LEN256];
4275 __u64 capabilities = 0;
4276 __u32 device_id, read_vendor_id;
4277 char file_path[PATH_MAX4096/2] = {0};
4278 char cmd_buf[PATH_MAX4096] = {0};
4279 int ret = -1;
4280
4281 struct config {
4282 char *file;
4283 __u32 xfer_size;
4284 int data_area;
4285 __u64 file_size;
4286 __u64 offset;
4287 char *type;
4288 bool_Bool verbose;
4289 };
4290
4291 struct config cfg = {
4292 .file = NULL((void*)0),
4293 .xfer_size = 0x10000,
4294 .data_area = 0,
4295 .file_size = 0,
4296 .offset = 0,
4297 .type = NULL((void*)0),
4298 .verbose = false0,
4299 };
4300
4301 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 informational output", 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) } }
4302 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 informational output", 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_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 informational output", 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("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 informational output", 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_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 informational output", 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_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 informational output", 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_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 informational output", 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("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 informational output", 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_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 informational output", 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
4311 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4312 if (ret)
4313 return ret;
4314
4315 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4316 if (ret || !wdc_check_device(ctx, hdl))
4317 goto out;
4318
4319 if (cfg.xfer_size) {
4320 xfer_size = cfg.xfer_size;
4321 } else {
4322 nvme_show_error("ERROR: WDC: Invalid length")nvme_show_message(1, "ERROR: WDC: Invalid length");
4323 goto out;
4324 }
4325
4326 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4327
4328 if (!wdc_is_sn861(device_id)) {
4329 if (cfg.file) {
4330 int verify_file;
4331
4332 /* verify file name and path is valid before getting dump data */
4333 verify_file = shr_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
4334 if (verify_file < 0) {
4335 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
4336 goto out;
4337 }
4338 close(verify_file);
4339 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4340 } else {
4341 wdc_UtilsGetTime(&timeInfo);
4342 memset(timeStamp, 0, sizeof(timeStamp));
4343 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4344 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4345 timeInfo.month, timeInfo.dayOfMonth,
4346 timeInfo.hour, timeInfo.minute,
4347 timeInfo.second);
4348 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4349
4350 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix);
4351 if (ret) {
4352 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4353 goto out;
4354 }
4355 }
4356
4357 if (!cfg.file) {
4358 if (strlen(f) > PATH_MAX4096 - 5) {
4359 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4360 ret = -1;
4361 goto out;
4362 }
4363 strcat(f, ".bin");
4364 }
4365 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
4366
4367 if (cfg.data_area) {
4368 if (cfg.data_area > 5 || cfg.data_area < 1) {
4369 nvme_show_error("ERROR: WDC: Data area must be 1-5")nvme_show_message(1, "ERROR: WDC: Data area must be 1-5");
4370 ret = -1;
4371 goto out;
4372 }
4373 }
4374
4375 if (!cfg.type || !strcmp(cfg.type, "NONE") || !strcmp(cfg.type, "none")) {
4376 telemetry_type = WDC_TELEMETRY_TYPE_NONE0x0;
4377 data_area = 0;
4378 } else if (!strcmp(cfg.type, "HOST") || !strcmp(cfg.type, "host")) {
4379 telemetry_type = WDC_TELEMETRY_TYPE_HOST0x1;
4380 telemetry_data_area = cfg.data_area;
4381 } else if (!strcmp(cfg.type, "CONTROLLER") || !strcmp(cfg.type, "controller")) {
4382 telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER0x2;
4383 telemetry_data_area = cfg.data_area;
4384 } else {
4385 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"
)
4386 "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"
)
;
4387 ret = -1;
4388 goto out;
4389 }
4390 } else {
4391 if (cfg.file) {
4392 strncpy(fb, cfg.file, PATH_MAX4096/2 - 8);
4393 } else {
4394 wdc_UtilsGetTime(&timeInfo);
4395 memset(timeStamp, 0, sizeof(timeStamp));
4396 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4397 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4398 timeInfo.month, timeInfo.dayOfMonth,
4399 timeInfo.hour, timeInfo.minute,
4400 timeInfo.second);
4401 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4402
4403 ret = wdc_get_serial_name(hdl, fb, PATH_MAX4096/2 - 7, fileSuffix);
4404 if (ret) {
4405 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4406 goto out;
4407 }
4408
4409 if (strlen(fb) > PATH_MAX4096/2 - 7) {
4410 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4411 ret = -1;
4412 goto out;
4413 }
4414 }
4415 nvme_show_error("%s: filename = %s.tar.gz", __func__, fb)nvme_show_message(1, "%s: filename = %s.tar.gz", __func__, fb
)
;
4416
4417
4418 memset(file_path, 0, sizeof(file_path));
4419 if (snprintf(file_path, PATH_MAX4096/2 - 8, "%s.tar.gz", fb) >= PATH_MAX4096/2 - 8) {
4420 nvme_show_error("File path is too long!")nvme_show_message(1, "File path is too long!");
4421 ret = -1;
4422 goto out;
4423 }
4424 if (access(file_path, F_OK0) != -1) {
4425 nvme_show_error("Output file already exists!")nvme_show_message(1, "Output file already exists!");
4426 ret = -EEXIST17;
4427 goto out;
4428 }
4429 }
4430
4431 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4432 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
4433 if (!wdc_is_sn861(device_id)) {
4434 if (telemetry_type != WDC_TELEMETRY_TYPE_NONE0x0 &&
4435 wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4436 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4437 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4438 return -EINVAL22;
4439 }
4440
4441 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size,
4442 telemetry_type, telemetry_data_area);
4443 } else {
4444 if (nvme_args.verbose)
4445 printf("Creating temp directory...\n");
4446
4447 ret = shr_mkdir(fb, 0666);
4448 if (ret) {
4449 nvme_show_error("Failed to create directory!")nvme_show_message(1, "Failed to create directory!");
4450 goto out;
4451 }
4452
4453 ret = dump_internal_logs(hdl, fb, nvme_args.verbose);
4454 if (ret < 0)
4455 nvme_show_err(ret, "vs-internal-log");
4456
4457 if (nvme_args.verbose)
4458 printf("Archiving...\n");
4459
4460 if (snprintf(cmd_buf, PATH_MAX4096,
4461 "tar --remove-files -czf %s %s",
4462 file_path, fb) >= PATH_MAX4096) {
4463 nvme_show_error("Command buffer is too long!")nvme_show_message(1, "Command buffer is too long!");
4464 ret = -1;
4465 goto out;
4466 }
4467
4468 ret = system(cmd_buf);
4469 if (ret)
4470 nvme_show_error("Failed to create an archive file!")nvme_show_message(1, "Failed to create an archive file!");
4471 }
4472 goto out;
4473 }
4474 if ((capabilities & WDC_DRIVE_CAP_DUI0x0000000800000000) == WDC_DRIVE_CAP_DUI0x0000000800000000) {
4475 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4476 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4477 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4478 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4479 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4480 return -EINVAL22;
4481 }
4482 /* Get the desired telemetry log page */
4483 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4484 telemetry_type, telemetry_data_area);
4485 goto out;
4486 } else {
4487 if (!cfg.data_area)
4488 cfg.data_area = 1;
4489
4490 /* FW requirement - xfer size must be 256k for data area 4 */
4491 if (cfg.data_area >= 4)
4492 xfer_size = 0x40000;
4493 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4494 cfg.data_area,
4495 nvme_args.verbose, cfg.file_size,
4496 cfg.offset);
4497 goto out;
4498 }
4499 }
4500 if ((capabilities & WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) == WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) {
4501 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4502 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4503 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4504 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4505 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4506 return -EINVAL22;
4507 }
4508 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4509 telemetry_type, telemetry_data_area);
4510 goto out;
4511 } else {
4512 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4513 WDC_NVME_DUI_MAX_DATA_AREA0x05,
4514 nvme_args.verbose, 0, 0);
4515 goto out;
4516 }
4517 }
4518 if ((capabilities & WDC_SN730B_CAP_VUC_LOG0x0000000400000000) == WDC_SN730B_CAP_VUC_LOG0x0000000400000000) {
4519 ret = wdc_do_sn730_get_and_tar(hdl, f);
4520 } else {
4521 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4522 ret = -1;
4523 }
4524out:
4525 return ret;
4526}
4527
4528static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type)
4529{
4530 int ret;
4531 __u32 crash_dump_length;
4532 __u32 opcode;
4533 __u32 cdw12;
4534 __u32 cdw10_size;
4535 __u32 cdw12_size;
4536 __u32 cdw12_clear;
4537
4538 if (type == WDC_NVME_PFAIL_DUMP_TYPE2) {
4539 /* set parms to get the PFAIL Crash Dump */
4540 opcode = WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6;
4541 cdw10_size = WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02;
4542 cdw12_size = ((WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4543 WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20);
4544
4545 cdw12 = (WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4546 WDC_NVME_PF_CRASH_DUMP_CMD0x20;
4547
4548 cdw12_clear = ((WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4549 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4550
4551 } else {
4552 /* set parms to get the Crash Dump */
4553 opcode = WDC_NVME_CRASH_DUMP_OPCODE0xC6;
4554 cdw10_size = WDC_NVME_CRASH_DUMP_SIZE_NDT0x02;
4555 cdw12_size = ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 << WDC_NVME_SUBCMD_SHIFT8) |
4556 WDC_NVME_CRASH_DUMP_SIZE_CMD0x20);
4557
4558 cdw12 = (WDC_NVME_CRASH_DUMP_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
4559 WDC_NVME_CRASH_DUMP_CMD0x20;
4560
4561 cdw12_clear = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4562 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4563 }
4564
4565 ret = wdc_dump_length(hdl,
4566 opcode,
4567 cdw10_size,
4568 cdw12_size,
4569 &crash_dump_length);
4570
4571 if (ret == -1) {
4572 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4573 nvme_show_error("INFO: WDC: Pfail dump get size failed")nvme_show_message(1, "INFO: WDC: Pfail dump get size failed");
4574 else
4575 nvme_show_error("INFO: WDC: Crash dump get size failed")nvme_show_message(1, "INFO: WDC: Crash dump get size failed");
4576
4577 return -1;
4578 }
4579
4580 if (!crash_dump_length) {
4581 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4582 nvme_show_error("INFO: WDC: Pfail dump is empty")nvme_show_message(1, "INFO: WDC: Pfail dump is empty");
4583 else
4584 nvme_show_error("INFO: WDC: Crash dump is empty")nvme_show_message(1, "INFO: WDC: Crash dump is empty");
4585 } else {
4586 ret = wdc_do_dump(hdl,
4587 opcode,
4588 crash_dump_length,
4589 cdw12,
4590 file,
4591 crash_dump_length);
4592
4593 if (!ret)
4594 ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE0xFF,
4595 cdw12_clear);
4596 }
4597 return ret;
4598}
4599
4600static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type)
4601{
4602 char f[PATH_MAX4096] = {0};
4603 const char *dump_type;
4604 int ret;
4605
4606 if (file)
4607 strncpy(f, file, PATH_MAX4096 - 1);
4608
4609 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4610 dump_type = "_pfail_dump";
4611 else
4612 dump_type = "_crash_dump";
4613
4614 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, dump_type);
4615 if (ret)
4616 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4617 else
4618 ret = wdc_do_crash_dump(hdl, f, type);
4619 return ret;
4620}
4621
4622static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file)
4623{
4624 int ret;
4625 __u8 *drive_log_data;
4626 __u32 drive_log_length;
4627 struct libnvme_passthru_cmd admin_cmd;
4628
4629 ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6,
4630 WDC_NVME_DRIVE_LOG_SIZE_NDT0x02,
4631 (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 <<
4632 WDC_NVME_SUBCMD_SHIFT8 | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20),
4633 &drive_log_length);
4634 if (ret == -1)
4635 return -1;
4636
4637 drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length);
4638 if (!drive_log_data) {
4639 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4640 return -1;
4641 }
4642
4643 memset(drive_log_data, 0, sizeof(__u8) * drive_log_length);
4644 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4645 admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE0xC6;
4646 admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
4647 admin_cmd.data_len = drive_log_length;
4648 admin_cmd.cdw10 = drive_log_length;
4649 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD0x00 <<
4650 WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20);
4651
4652 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4653 nvme_show_status(ret);
4654 if (!ret)
4655 ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
4656 free(drive_log_data);
4657 return ret;
4658}
4659
4660static int wdc_drive_log(int argc, char **argv, struct command *acmd,
4661 struct plugin *plugin)
4662{
4663 const char *desc = "Capture Drive Log.";
4664 const char *file = "Output file pathname.";
4665 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4666 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4667 char f[PATH_MAX4096] = {0};
4668 int ret;
4669 __u64 capabilities = 0;
4670 struct config {
4671 char *file;
4672 };
4673
4674 struct config cfg = {
4675 .file = NULL((void*)0)
4676 };
4677
4678 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 informational output", 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) } }
4679 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 informational output", 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
4681 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4682 if (ret)
4683 return ret;
4684
4685 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4686 if (ret || !wdc_check_device(ctx, hdl))
4687 return ret;
4688
4689 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4690
4691 if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400)) {
4692 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4693 ret = -1;
4694 } else {
4695 if (cfg.file)
4696 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4697 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "drive_log");
4698 if (ret)
4699 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4700 else
4701 ret = wdc_do_drive_log(hdl, f);
4702 }
4703 return ret;
4704}
4705
4706static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
4707 struct plugin *plugin)
4708{
4709 const char *desc = "Get Crash Dump.";
4710 const char *file = "Output file pathname.";
4711 __u64 capabilities = 0;
4712 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4713 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4714 int ret;
4715
4716 struct config {
4717 char *file;
4718 };
4719
4720 struct config cfg = {
4721 .file = NULL((void*)0),
4722 };
4723
4724 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 informational output", 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) } }
4725 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 informational output", 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
4727 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4728 if (ret)
4729 return ret;
4730
4731 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4732 if (ret || !wdc_check_device(ctx, hdl))
4733 return ret;
4734
4735 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4736
4737 if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800)) {
4738 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4739 ret = -1;
4740 } else {
4741 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE1);
4742 if (ret)
4743 nvme_show_error("ERROR: WDC: failed to read crash dump")nvme_show_message(1, "ERROR: WDC: failed to read crash dump");
4744 }
4745 return ret;
4746}
4747
4748static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd,
4749 struct plugin *plugin)
4750{
4751 const char *desc = "Get Pfail Crash Dump.";
4752 const char *file = "Output file pathname.";
4753 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4754 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4755 __u64 capabilities = 0;
4756 struct config {
4757 char *file;
4758 };
4759 int ret;
4760
4761 struct config cfg = {
4762 .file = NULL((void*)0),
4763 };
4764
4765 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 informational output", 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) } }
4766 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 informational output", 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
4768 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4769 if (ret)
4770 return ret;
4771
4772 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4773 if (ret || !wdc_check_device(ctx, hdl))
4774 return ret;
4775
4776 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4777 if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000)) {
4778 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4779 ret = -1;
4780 } else {
4781 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE2);
4782 if (ret)
4783 nvme_show_error("ERROR: WDC: failed to read pfail crash dump")nvme_show_message(1, "ERROR: WDC: failed to read pfail crash dump"
)
;
4784 }
4785 return ret;
4786}
4787
4788static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root)
4789{
4790 char vsn[24] = {0};
4791 int base = 3072;
4792 int vsn_start = 3081;
4793
4794 memcpy(vsn, &vs[vsn_start - base], sizeof(vsn));
4795 if (root)
4796 json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL");
4797 else
4798 printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL");
4799}
4800
4801static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
4802{
4803 return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl);
4804}
4805
4806static const char *wdc_purge_mon_status_to_string(__u32 status)
4807{
4808 const char *str;
4809
4810 switch (status) {
4811 case WDC_NVME_PURGE_STATE_IDLE0x00:
4812 str = "Purge State Idle.";
4813 break;
4814 case WDC_NVME_PURGE_STATE_DONE0x01:
4815 str = "Purge State Done.";
4816 break;
4817 case WDC_NVME_PURGE_STATE_BUSY0x02:
4818 str = "Purge State Busy.";
4819 break;
4820 case WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03:
4821 str = "Purge Operation resulted in an error that requires power cycle.";
4822 break;
4823 case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04:
4824 str = "The previous purge operation was interrupted by a power cycle\n"
4825 "or reset interruption. Other commands may be rejected until\n"
4826 "Purge Execute is issued and completed.";
4827 break;
4828 default:
4829 str = "Unknown.";
4830 }
4831 return str;
4832}
4833
4834static int wdc_purge(int argc, char **argv,
4835 struct command *command, struct plugin *plugin)
4836{
4837 const char *desc = "Send a Purge command.";
4838 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4839 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4840 struct libnvme_passthru_cmd admin_cmd;
4841 __u64 capabilities = 0;
4842 char *err_str;
4843 int ret;
4844
4845 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 informational output", 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) } }
;
4846
4847 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4848 if (ret)
4849 return ret;
4850
4851 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4852 if (ret || !wdc_check_device(ctx, hdl))
4853 return ret;
4854
4855 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4856 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4857 ret = -1;
4858 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4859 } else {
4860 err_str = "";
4861 memset(&admin_cmd, 0, sizeof(admin_cmd));
4862 admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE0xDD;
4863
4864 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4865 if (ret > 0) {
4866 switch (ret) {
4867 case WDC_NVME_PURGE_CMD_SEQ_ERR0x0C:
4868 err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n";
4869 break;
4870 case WDC_NVME_PURGE_INT_DEV_ERR0x06:
4871 err_str = "ERROR: WDC: Internal Device Error.\n";
4872 break;
4873 default:
4874 err_str = "ERROR: WDC\n";
4875 }
4876 }
4877
4878 nvme_show_error("%s", err_str)nvme_show_message(1, "%s", err_str);
4879 nvme_show_status(ret);
4880 }
4881 return ret;
4882}
4883
4884static int wdc_purge_monitor(int argc, char **argv,
4885 struct command *command, struct plugin *plugin)
4886{
4887 const char *desc = "Send a Purge Monitor command.";
4888 __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F];
4889 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4890 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4891 double progress_percent;
4892 struct libnvme_passthru_cmd admin_cmd;
4893 struct wdc_nvme_purge_monitor_data *mon;
4894 __u64 capabilities;
4895 int ret;
4896
4897 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 informational output", 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) } }
;
4898
4899 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4900 if (ret)
4901 return ret;
4902
4903 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4904 if (ret || !wdc_check_device(ctx, hdl))
4905 return ret;
4906
4907 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4908 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4909 ret = -1;
4910 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4911 } else {
4912 memset(output, 0, sizeof(output));
4913 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4914 admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE0xDE;
4915 admin_cmd.addr = (__u64)(uintptr_t)output;
4916 admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F;
4917 admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C;
4918 admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530;
4919
4920 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4921 if (!ret) {
4922 mon = (struct wdc_nvme_purge_monitor_data *) output;
4923 printf("Purge state = 0x%0"PRIx64"l" "x""\n",
4924 (uint64_t)admin_cmd.result);
4925 printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result));
4926 if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY0x02) {
4927 progress_percent =
4928 ((double)le32_to_cpu(mon->entire_progress_current) * 100) /
4929 le32_to_cpu(mon->entire_progress_total);
4930 printf("Purge Progress = %f%%\n", progress_percent);
4931 }
4932 }
4933
4934 nvme_show_status(ret);
4935 }
4936 return ret;
4937}
4938
4939static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf)
4940{
4941 printf(" C1 Log Page Performance Statistics :-\n");
4942 printf(" Host Read Commands %20"PRIu64"l" "u""\n",
4943 le64_to_cpu(perf->hr_cmds));
4944 printf(" Host Read Blocks %20"PRIu64"l" "u""\n",
4945 le64_to_cpu(perf->hr_blks));
4946 printf(" Average Read Size %20lf\n",
4947 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))));
4948 printf(" Host Read Cache Hit Commands %20"PRIu64"l" "u""\n",
4949 le64_to_cpu(perf->hr_ch_cmds));
4950 printf(" Host Read Cache Hit_Percentage %20"PRIu64"l" "u""%%\n",
4951 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)));
4952 printf(" Host Read Cache Hit Blocks %20"PRIu64"l" "u""\n",
4953 le64_to_cpu(perf->hr_ch_blks));
4954 printf(" Average Read Cache Hit Size %20f\n",
4955 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))));
4956 printf(" Host Read Commands Stalled %20"PRIu64"l" "u""\n",
4957 le64_to_cpu(perf->hr_st_cmds));
4958 printf(" Host Read Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
4959 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)));
4960 printf(" Host Write Commands %20"PRIu64"l" "u""\n",
4961 le64_to_cpu(perf->hw_cmds));
4962 printf(" Host Write Blocks %20"PRIu64"l" "u""\n",
4963 le64_to_cpu(perf->hw_blks));
4964 printf(" Average Write Size %20f\n",
4965 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))));
4966 printf(" Host Write Odd Start Commands %20"PRIu64"l" "u""\n",
4967 le64_to_cpu(perf->hw_os_cmds));
4968 printf(" Host Write Odd Start Commands Percentage %20"PRIu64"l" "u""%%\n",
4969 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))));
4970 printf(" Host Write Odd End Commands %20"PRIu64"l" "u""\n",
4971 le64_to_cpu(perf->hw_oe_cmds));
4972 printf(" Host Write Odd End Commands Percentage %20"PRIu64"l" "u""%%\n",
4973 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))));
4974 printf(" Host Write Commands Stalled %20"PRIu64"l" "u""\n",
4975 le64_to_cpu(perf->hw_st_cmds));
4976 printf(" Host Write Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
4977 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))));
4978 printf(" NAND Read Commands %20"PRIu64"l" "u""\n",
4979 le64_to_cpu(perf->nr_cmds));
4980 printf(" NAND Read Blocks Commands %20"PRIu64"l" "u""\n",
4981 le64_to_cpu(perf->nr_blks));
4982 printf(" Average NAND Read Size %20f\n",
4983 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))));
4984 printf(" Nand Write Commands %20"PRIu64"l" "u""\n",
4985 le64_to_cpu(perf->nw_cmds));
4986 printf(" NAND Write Blocks %20"PRIu64"l" "u""\n",
4987 le64_to_cpu(perf->nw_blks));
4988 printf(" Average NAND Write Size %20f\n",
4989 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))));
4990 printf(" NAND Read Before Write %20"PRIu64"l" "u""\n",
4991 le64_to_cpu(perf->nrbw));
4992}
4993
4994static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf)
4995{
4996 struct json_object *root = json_create_object()json_object_new_object();
4997
4998 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)))
;
4999 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)))
;
5000 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)))))
5001 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)))))
;
5002 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)))
5003 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)))
;
5004 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))))
5005 (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))))
;
5006 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)))
5007 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)))
;
5008 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)))))
5009 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)))))
;
5010 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)))
5011 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)))
;
5012 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))))
5013 (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))))
;
5014 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)))
5015 le64_to_cpu(perf->hw_cmds))json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
;
5016 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)))
5017 le64_to_cpu(perf->hw_blks))json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
;
5018 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)))))
5019 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)))))
;
5020 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)))
5021 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)))
;
5022 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)))))
5023 (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)))))
;
5024 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)))
5025 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)))
;
5026 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))))))
5027 (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))))))
;
5028 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)))
5029 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)))
;
5030 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)))))
5031 (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)))))
;
5032 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)))
5033 le64_to_cpu(perf->nr_cmds))json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
;
5034 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)))
5035 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)))
;
5036 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))))))
5037 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))))))
;
5038 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)))
5039 le64_to_cpu(perf->nw_cmds))json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
;
5040 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)))
5041 le64_to_cpu(perf->nw_blks))json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
;
5042 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)))))
5043 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)))))
;
5044 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)))
5045 le64_to_cpu(perf->nrbw))json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
;
5046 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5047 printf("\n");
5048 json_free_object(root)json_object_put(root);
5049}
5050
5051static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt)
5052{
5053 if (!perf) {
5054 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
5055 return -1;
5056 }
5057 switch (fmt) {
5058 case NORMAL:
5059 wdc_print_log_normal(perf);
5060 break;
5061 case JSON:
5062 wdc_print_log_json(perf);
5063 break;
5064 }
5065 return 0;
5066}
5067
5068static int wdc_print_latency_monitor_log_normal(struct libnvme_transport_handle *hdl,
5069 struct wdc_ssd_latency_monitor_log *log_data)
5070{
5071 printf("Latency Monitor/C3 Log Page Data\n");
5072 printf(" Controller : %s\n", libnvme_transport_handle_get_name(hdl));
5073 int err = -1, i, j;
5074 struct libnvme_passthru_cmd cmd;
5075 struct nvme_id_ctrl ctrl;
5076 char ts_buf[128];
5077
5078 nvme_init_identify_ctrl(&cmd, &ctrl);
5079 err = libnvme_exec_admin_passthru(hdl, &cmd);
5080 if (!err) {
5081 printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn);
5082 } else {
5083 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)
;
5084 return err;
5085 }
5086
5087 printf(" Feature Status 0x%x\n", log_data->feature_status);
5088 printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer));
5089 printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold));
5090 printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1)));
5091 printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1)));
5092 printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1)));
5093 printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1)));
5094 printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config));
5095 printf(" Active Latency Minimum Window %d ms\n", 100*log_data->active_latency_min_window);
5096 printf(" Active Latency Stamp Units %d\n", le16_to_cpu(log_data->active_latency_stamp_units));
5097 printf(" Static Latency Stamp Units %d\n", le16_to_cpu(log_data->static_latency_stamp_units));
5098 if (le16_to_cpu(log_data->log_page_version) >= 4)
5099 printf(" Debug Telemetry Log Size %"PRIu64"l" "u""\n",
5100 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size));
5101 printf(" Debug Log Trigger Enable %d\n",
5102 le16_to_cpu(log_data->debug_log_trigger_enable));
5103 printf(" Log Page Version %d\n",
5104 le16_to_cpu(log_data->log_page_version));
5105 printf(" Log page GUID 0x");
5106 for (j = 0; j < WDC_C3_GUID_LENGTH16; j++)
5107 printf("%x", log_data->log_page_guid[j]);
5108 printf("\n");
5109
5110 printf(" Read Write Deallocate/Trim\n");
5111 for (i = 0; i <= 3; i++)
5112 printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
5113 i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5114 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5115 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5116
5117 for (i = 3; i >= 0; i--)
5118 printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5119 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5120 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5121 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5122
5123 for (i = 3; i >= 0; i--) {
5124 printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
5125 for (j = 2; j >= 0; j--) {
5126 if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) {
5127 printf(" N/A ");
5128 } else {
5129 shr_format_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
5130 printf("%s ", ts_buf);
5131 }
5132 }
5133 printf("\n");
5134 }
5135
5136 for (i = 0; i <= 3; i++)
5137 printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
5138 i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5139 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5140 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5141
5142 for (i = 3; i >= 0; i--)
5143 printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5144 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5145 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5146 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5147
5148 for (i = 3; i >= 0; i--) {
5149 printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
5150 for (j = 2; j >= 0; j--) {
5151 if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) {
5152 printf(" N/A ");
5153 } else {
5154 shr_format_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
5155 printf("%s ", ts_buf);
5156 }
5157 }
5158 printf("\n");
5159 }
5160
5161 return 0;
5162}
5163
5164static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data)
5165{
5166 int i, j;
5167 char buf[128];
5168 const char *operation[3] = {"Read", "Write", "Trim"};
5169 struct json_object *root = json_create_object()json_object_new_object();
5170
5171 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))
;
5172 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)))
;
5173 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
)))
;
5174 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)))
;
5175 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)))
;
5176 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)))
;
5177 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)))
;
5178 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)))
;
5179 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
))
;
5180 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)))
;
5181 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)))
;
5182 if (le16_to_cpu(log_data->log_page_version) >= 4) {
5183 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
)))
5184 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
)))
;
5185 }
5186 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)))
5187 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)))
;
5188 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)))
5189 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)))
;
5190
5191 char guid[40];
5192
5193 memset((void *)guid, 0, 40);
5194 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5195 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5196 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5197 json_object_add_value_string(root, "Log page GUID", guid);
5198
5199 for (i = 0; i <= 3; i++) {
5200 for (j = 2; j >= 0; j--) {
5201 sprintf(buf, "Active Bucket Counter: Bucket %d %s", i, operation[2-j]);
5202 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])))
;
5203 }
5204 }
5205 for (i = 3; i >= 0; i--) {
5206 for (j = 2; j >= 0; j--) {
5207 sprintf(buf, "Active Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5208 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])))
;
5209 }
5210 }
5211 for (i = 3; i >= 0; i--) {
5212 for (j = 2; j >= 0; j--) {
5213 sprintf(buf, "Active Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5214 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])))
;
5215 }
5216 }
5217 for (i = 0; i <= 3; i++) {
5218 for (j = 2; j >= 0; j--) {
5219 sprintf(buf, "Static Bucket Counter: Bucket %d %s", i, operation[2-j]);
5220 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])))
;
5221 }
5222 }
5223 for (i = 3; i >= 0; i--) {
5224 for (j = 2; j >= 0; j--) {
5225 sprintf(buf, "Static Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5226 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])))
;
5227 }
5228 }
5229 for (i = 3; i >= 0; i--) {
5230 for (j = 2; j >= 0; j--) {
5231 sprintf(buf, "Static Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5232 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])))
;
5233 }
5234 }
5235
5236 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5237 printf("\n");
5238
5239 json_free_object(root)json_object_put(root);
5240}
5241
5242static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data)
5243{
5244 int j;
5245
5246 printf("Error Recovery/C1 Log Page Data\n");
5247
5248 printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time));
5249 printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
5250 printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1);
5251 printf(" Panic ID : 0x%" PRIu64"l" "u" "\n", le64_to_cpu(log_data->panic_id));
5252 printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities));
5253 printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc);
5254 printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12));
5255 printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13));
5256 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5257 printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to);
5258 printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2);
5259 printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to);
5260 }
5261 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5262 printf(" Panic Count : 0x%x\n", log_data->panic_count);
5263 for (j = 0; j < 4; j++)
5264 printf(" Previous Panic ID N-%d : 0x%"PRIx64"l" "x""\n",
5265 j+1, le64_to_cpu(log_data->prev_panic_ids[j]));
5266 }
5267 printf(" Log Page Version : 0x%x\n",
5268 le16_to_cpu(log_data->log_page_version));
5269 printf(" Log page GUID : 0x");
5270 for (j = 0; j < WDC_OCP_C1_GUID_LENGTH16; j++)
5271 printf("%x", log_data->log_page_guid[j]);
5272 printf("\n");
5273}
5274
5275static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
5276{
5277 int j;
5278 char buf[128];
5279 struct json_object *root = json_create_object()json_object_new_object();
5280
5281 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)))
;
5282 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))
;
5283 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))
;
5284 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)))
;
5285 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)))
;
5286 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))
;
5287 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)))
;
5288 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)))
;
5289 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5290 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))
;
5291 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))
;
5292 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))
;
5293 }
5294 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5295 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))
;
5296 for (j = 0; j < 4; j++) {
5297 sprintf(buf, "Previous Panic ID N-%d", j+1);
5298 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])))
5299 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])))
;
5300 }
5301 }
5302 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)))
5303 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)))
;
5304
5305 char guid[40];
5306
5307 memset((void *)guid, 0, 40);
5308 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5309 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5310 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5311 json_object_add_value_string(root, "Log page GUID", guid);
5312
5313 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5314 printf("\n");
5315
5316 json_free_object(root)json_object_put(root);
5317}
5318
5319static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data)
5320{
5321 int j;
5322
5323 printf("Device Capabilities/C4 Log Page Data\n");
5324
5325 printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports));
5326 printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support));
5327 printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support));
5328 printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support));
5329 printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support));
5330 printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support));
5331 printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support));
5332 printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps));
5333
5334 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++)
5335 printf(" DSSD Power State %d Descriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]);
5336
5337 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5338 printf(" Log page GUID : 0x");
5339 for (j = 0; j < WDC_OCP_C4_GUID_LENGTH16; j++)
5340 printf("%x", log_data->log_page_guid[j]);
5341 printf("\n");
5342}
5343
5344static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
5345{
5346 int j;
5347 struct json_object *root = json_create_object()json_object_new_object();
5348
5349 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)))
;
5350 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
)))
;
5351 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)))
;
5352 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)))
;
5353 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)))
;
5354 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)))
;
5355 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)))
;
5356 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)))
;
5357
5358 char dssd_descr_str[40];
5359
5360 memset((void *)dssd_descr_str, 0, 40);
5361 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++) {
5362 sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j);
5363 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]))
;
5364 }
5365
5366 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)))
;
5367 char guid[40];
5368
5369 memset((void *)guid, 0, 40);
5370 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5371 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5372 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5373 json_object_add_value_string(root, "Log page GUID", guid);
5374
5375 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5376 printf("\n");
5377
5378 json_free_object(root)json_object_put(root);
5379}
5380
5381static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data)
5382{
5383 int j;
5384
5385 printf("Unsupported Requirements/C5 Log Page Data\n");
5386
5387 printf(" Number Unsupported Req IDs : 0x%x\n",
5388 le16_to_cpu(log_data->unsupported_count));
5389
5390 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++)
5391 printf(" Unsupported Requirement List %d : %s\n", j,
5392 log_data->unsupported_req_list[j]);
5393
5394 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5395 printf(" Log page GUID : 0x");
5396 for (j = 0; j < WDC_OCP_C5_GUID_LENGTH16; j++)
5397 printf("%x", log_data->log_page_guid[j]);
5398 printf("\n");
5399}
5400
5401static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
5402{
5403 int j;
5404 struct json_object *root = json_create_object()json_object_new_object();
5405
5406 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)))
;
5407
5408 char unsup_req_list_str[41];
5409
5410 memset((void *)unsup_req_list_str, 0, 41);
5411 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
5412 sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j);
5413 json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]);
5414 }
5415
5416 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)))
5417 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)))
;
5418 char guid[40];
5419
5420 memset((void *)guid, 0, 40);
5421 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5422 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5423 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5424 json_object_add_value_string(root, "Log page GUID", guid);
5425
5426 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5427 printf("\n");
5428
5429 json_free_object(root)json_object_put(root);
5430}
5431
5432static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
5433{
5434 uint64_t converted = 0;
5435
5436 printf(" CA Log Page Performance Statistics :-\n");
5437 printf(" NAND Bytes Written %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5438 le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo));
5439 printf(" NAND Bytes Read %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5440 le64_to_cpu(perf->nand_bytes_rd_hi), le64_to_cpu(perf->nand_bytes_rd_lo));
5441
5442 converted = le64_to_cpu(perf->nand_bad_block);
5443 printf(" NAND Bad Block Count (Normalized) %20"PRIu64"l" "u""\n",
5444 converted & 0xFFFF);
5445 printf(" NAND Bad Block Count (Raw) %20"PRIu64"l" "u""\n",
5446 converted >> 16);
5447
5448 printf(" Uncorrectable Read Count %20"PRIu64"l" "u""\n",
5449 le64_to_cpu(perf->uncorr_read_count));
5450 printf(" Soft ECC Error Count %20"PRIu64"l" "u""\n",
5451 le64_to_cpu(perf->ecc_error_count));
5452 printf(" SSD End to End Detected Correction Count %20"PRIu32"u""\n",
5453 (uint32_t)le32_to_cpu(perf->ssd_detect_count));
5454 printf(" SSD End to End Corrected Correction Count %20"PRIu32"u""\n",
5455 (uint32_t)le32_to_cpu(perf->ssd_correct_count));
5456 printf(" System Data Percent Used %20"PRIu32"u""%%\n",
5457 perf->data_percent_used);
5458 printf(" User Data Erase Counts Max %20"PRIu32"u""\n",
5459 (uint32_t)le32_to_cpu(perf->data_erase_max));
5460 printf(" User Data Erase Counts Min %20"PRIu32"u""\n",
5461 (uint32_t)le32_to_cpu(perf->data_erase_min));
5462 printf(" Refresh Count %20"PRIu64"l" "u""\n",
5463 le64_to_cpu(perf->refresh_count));
5464
5465 converted = le64_to_cpu(perf->program_fail);
5466 printf(" Program Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5467 converted & 0xFFFF);
5468 printf(" Program Fail Count (Raw) %20"PRIu64"l" "u""\n",
5469 converted >> 16);
5470
5471 converted = le64_to_cpu(perf->user_erase_fail);
5472 printf(" User Data Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5473 converted & 0xFFFF);
5474 printf(" User Data Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5475 converted >> 16);
5476
5477 converted = le64_to_cpu(perf->system_erase_fail);
5478 printf(" System Area Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5479 converted & 0xFFFF);
5480 printf(" System Area Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5481 converted >> 16);
5482
5483 printf(" Thermal Throttling Status %20"PRIu8"hhu""\n",
5484 perf->thermal_throttle_status);
5485 printf(" Thermal Throttling Count %20"PRIu8"hhu""\n",
5486 perf->thermal_throttle_count);
5487 printf(" PCIe Correctable Error Count %20"PRIu64"l" "u""\n",
5488 le64_to_cpu(perf->pcie_corr_error));
5489 printf(" Incomplete Shutdown Count %20"PRIu32"u""\n",
5490 (uint32_t)le32_to_cpu(perf->incomplete_shutdown_count));
5491 printf(" Percent Free Blocks %20"PRIu32"u""%%\n",
5492 perf->percent_free_blocks);
5493}
5494
5495static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf)
5496{
5497 struct json_object *root = json_create_object()json_object_new_object();
5498 uint64_t converted = 0;
5499
5500 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)))
;
5501 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)))
;
5502 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)))
;
5503 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)))
;
5504
5505 converted = le64_to_cpu(perf->nand_bad_block);
5506 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))
5507 converted & 0xFFFF)json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5508 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))
5509 converted >> 16)json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
;
5510
5511 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)))
;
5512 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)))
;
5513 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))
)
5514 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))
)
;
5515 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)
))
5516 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)
))
;
5517 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))
5518 perf->data_percent_used)json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
;
5519 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)))
5520 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)))
;
5521 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)))
5522 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)))
;
5523 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)))
;
5524
5525 converted = le64_to_cpu(perf->program_fail);
5526 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))
5527 converted & 0xFFFF)json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5528 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))
5529 converted >> 16)json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
;
5530
5531 converted = le64_to_cpu(perf->user_erase_fail);
5532 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))
5533 converted & 0xFFFF)json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5534 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))
5535 converted >> 16)json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5536
5537 converted = le64_to_cpu(perf->system_erase_fail);
5538 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))
5539 converted & 0xFFFF)json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5540 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))
5541 converted >> 16)json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5542
5543 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))
5544 perf->thermal_throttle_status)json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
;
5545 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))
5546 perf->thermal_throttle_count)json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
;
5547 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)))
;
5548 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)))
;
5549 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))
;
5550 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5551 printf("\n");
5552 json_free_object(root)json_object_put(root);
5553}
5554
5555static void wdc_print_bd_ca_log_normal(struct libnvme_transport_handle *hdl, void *data)
5556{
5557 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5558 __u64 *raw;
5559 __u64 rawSwapped;
5560 __u16 *word_raw1 = NULL((void*)0),
5561 *word_raw2 = NULL((void*)0),
5562 *word_raw3 = NULL((void*)0);
5563 __u32 *dword_raw = NULL((void*)0);
5564 __u8 *byte_raw = NULL((void*)0);
5565 bool_Bool valid_id = true1;
5566
5567 while (valid_id) {
5568 raw = (__u64 *)&bd_data->raw_value[0];
5569 rawSwapped = (le64_to_cpu(*raw)>>8);
5570
5571 switch (bd_data->field_id) {
5572 case 0x0:
5573 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
5574 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
5575 printf("key normalized raw\n");
5576 printf("program_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5577 bd_data->normalized_value, (uint64_t)rawSwapped);
5578 break;
5579 case 0x1:
5580 printf("erase_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5581 bd_data->normalized_value, (uint64_t)rawSwapped);
5582 break;
5583 case 0x2:
5584 word_raw1 = (__u16 *)&bd_data->raw_value[1];
5585 word_raw2 = (__u16 *)&bd_data->raw_value[3];
5586 word_raw3 = (__u16 *)&bd_data->raw_value[5];
5587 printf("wear_leveling : %3"PRIu8"hhu",
5588 bd_data->normalized_value);
5589 printf("%% min: %"PRIu16"hu"", max: %"PRIu16"hu"", avg: %"PRIu16"hu""\n",
5590 le16_to_cpu(*word_raw1),
5591 le16_to_cpu(*word_raw2),
5592 le16_to_cpu(*word_raw3));
5593 break;
5594 case 0x3:
5595 printf("end_to_end_error_detection_count: %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5596 bd_data->normalized_value, (uint64_t)rawSwapped);
5597 break;
5598 case 0x4:
5599 printf("crc_error_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5600 bd_data->normalized_value, (uint64_t)rawSwapped);
5601 break;
5602 case 0x5:
5603 printf("timed_workload_media_wear : %3"PRIu8"hhu""%% %-.3f%%\n",
5604 bd_data->normalized_value,
5605 safe_div_fp((rawSwapped), 1024.0));
5606 break;
5607 case 0x6:
5608 printf("timed_workload_host_reads : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5609 bd_data->normalized_value, (uint64_t)rawSwapped);
5610 break;
5611 case 0x7:
5612 printf("timed_workload_timer : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5613 bd_data->normalized_value, (uint64_t)rawSwapped);
5614 break;
5615 case 0x8:
5616 byte_raw = (__u8 *)&bd_data->raw_value[1];
5617 dword_raw = (__u32 *)&bd_data->raw_value[2];
5618 printf("thermal_throttle_status : %3"PRIu8"hhu""%% %"PRIu16"hu",
5619 bd_data->normalized_value, *byte_raw);
5620 printf("%%, cnt: %"PRIu16"hu""\n", le32_to_cpu(*dword_raw));
5621 break;
5622 case 0x9:
5623 printf("retry_buffer_overflow_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5624 bd_data->normalized_value, (uint64_t)rawSwapped);
5625 break;
5626 case 0xA:
5627 printf("pll_lock_loss_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5628 bd_data->normalized_value, (uint64_t)rawSwapped);
5629 break;
5630 case 0xB:
5631 printf("nand_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5632 bd_data->normalized_value, (uint64_t)rawSwapped);
5633 break;
5634 case 0xC:
5635 printf("host_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5636 bd_data->normalized_value, (uint64_t)rawSwapped);
5637 /* last entry, break from while loop */
5638 valid_id = false0;
5639 break;
5640 default:
5641 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5642 break;
5643 }
5644
5645 bd_data++;
5646 }
5647
5648 return;
5649}
5650
5651static void wdc_print_bd_ca_log_json(void *data)
5652{
5653 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5654 __u64 *raw, rawSwapped;
5655 __u16 *word_raw;
5656 __u32 *dword_raw;
5657 __u8 *byte_raw;
5658 bool_Bool valid_id = true1;
5659 struct json_object *root = json_create_object()json_object_new_object();
5660
5661 while (valid_id) {
5662 raw = (__u64 *)&bd_data->raw_value[0];
5663 rawSwapped = (le64_to_cpu(*raw)>>8);
5664
5665 switch (bd_data->field_id) {
5666 case 0x0:
5667 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))
5668 bd_data->normalized_value)json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
;
5669 json_object_add_value_uint64(root, "program_fail_count raw",json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
5670 rawSwapped)json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5671 break;
5672 case 0x1:
5673 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))
5674 bd_data->normalized_value)json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5675 json_object_add_value_uint64(root, "erase_fail_count raw",json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
5676 rawSwapped)json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5677 break;
5678 case 0x2:
5679 word_raw = (__u16 *)&bd_data->raw_value[1];
5680 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))
5681 bd_data->normalized_value)json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
;
5682 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)))
5683 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling min", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5684 word_raw = (__u16 *)&bd_data->raw_value[3];
5685 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)))
5686 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling max", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5687 word_raw = (__u16 *)&bd_data->raw_value[5];
5688 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)))
5689 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling avg", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5690 break;
5691 case 0x3:
5692 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))
5693 "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))
5694 bd_data->normalized_value)json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5695 json_object_add_value_uint64(root,json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5696 "end_to_end_error_detection_count raw",json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5697 rawSwapped)json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
;
5698 break;
5699 case 0x4:
5700 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))
5701 bd_data->normalized_value)json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5702 json_object_add_value_uint64(root, "crc_error_count raw",json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
5703 rawSwapped)json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
;
5704 break;
5705 case 0x5:
5706 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))
5707 bd_data->normalized_value)json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
;
5708 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)))
5709 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)))
;
5710 break;
5711 case 0x6:
5712 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))
5713 bd_data->normalized_value)json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
;
5714 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))
5715 rawSwapped)json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
;
5716 break;
5717 case 0x7:
5718 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))
5719 bd_data->normalized_value)json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
;
5720 json_object_add_value_uint64(root, "timed_workload_timer",json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
5721 rawSwapped)json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
;
5722 break;
5723 case 0x8:
5724 byte_raw = (__u8 *)&bd_data->raw_value[1];
5725 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))
5726 bd_data->normalized_value)json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
;
5727 json_object_add_value_int(root, "thermal_throttle_status",json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
5728 *byte_raw)json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
;
5729 dword_raw = (__u32 *)&bd_data->raw_value[2];
5730 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)))
5731 le32_to_cpu(*dword_raw))json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(le32_to_cpu(*dword_raw)))
;
5732 break;
5733 case 0x9:
5734 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))
5735 bd_data->normalized_value)json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5736 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))
5737 rawSwapped)json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
;
5738 break;
5739 case 0xA:
5740 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))
5741 bd_data->normalized_value)json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5742 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))
5743 rawSwapped)json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
;
5744 break;
5745 case 0xB:
5746 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))
5747 bd_data->normalized_value)json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5748 json_object_add_value_uint64(root, "nand_bytes_written raw",json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
5749 rawSwapped)json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5750 break;
5751 case 0xC:
5752 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))
5753 bd_data->normalized_value)json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5754 json_object_add_value_uint64(root, "host_bytes_written raw",json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
5755 rawSwapped)json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5756
5757 /* last entry, break from while loop */
5758 valid_id = false0;
5759 break;
5760 default:
5761 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5762 break;
5763 }
5764
5765 bd_data++;
5766 }
5767
5768 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5769 printf("\n");
5770 json_free_object(root)json_object_put(root);
5771
5772 return;
5773}
5774
5775static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf)
5776{
5777 printf(" D0 Smart Log Page Statistics :-\n");
5778 printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"u""\n",
5779 (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count));
5780 printf(" Lifetime Power on Hours %20"PRIu32"u""\n",
5781 (uint32_t)le32_to_cpu(perf->lifetime_power_on_hours));
5782 printf(" Lifetime UECC Count %20"PRIu32"u""\n",
5783 (uint32_t)le32_to_cpu(perf->lifetime_uecc_count));
5784 printf(" Lifetime Write Amplification Factor %20"PRIu32"u""\n",
5785 (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor));
5786 printf(" Trailing Hour Write Amplification Factor %20"PRIu32"u""\n",
5787 (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor));
5788 printf(" Reserve Erase Block Count %20"PRIu32"u""\n",
5789 (uint32_t)le32_to_cpu(perf->reserve_erase_block_count));
5790 printf(" Lifetime Program Fail Count %20"PRIu32"u""\n",
5791 (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count));
5792 printf(" Lifetime Block Erase Fail Count %20"PRIu32"u""\n",
5793 (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count));
5794 printf(" Lifetime Die Failure Count %20"PRIu32"u""\n",
5795 (uint32_t)le32_to_cpu(perf->lifetime_die_failure_count));
5796 printf(" Lifetime Link Rate Downgrade Count %20"PRIu32"u""\n",
5797 (uint32_t)le32_to_cpu(perf->lifetime_link_rate_downgrade_count));
5798 printf(" Lifetime Clean Shutdown Count on Power Loss %20"PRIu32"u""\n",
5799 (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count));
5800 printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"u""\n",
5801 (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count));
5802 printf(" Current Temperature %20"PRIu32"u""\n",
5803 (uint32_t)le32_to_cpu(perf->current_temp));
5804 printf(" Max Recorded Temperature %20"PRIu32"u""\n",
5805 (uint32_t)le32_to_cpu(perf->max_recorded_temp));
5806 printf(" Lifetime Retired Block Count %20"PRIu32"u""\n",
5807 (uint32_t)le32_to_cpu(perf->lifetime_retired_block_count));
5808 printf(" Lifetime Read Disturb Reallocation Events %20"PRIu32"u""\n",
5809 (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events));
5810 printf(" Lifetime NAND Writes %20"PRIu64"l" "u""\n",
5811 le64_to_cpu(perf->lifetime_nand_writes));
5812 printf(" Capacitor Health %20"PRIu32"u""%%\n",
5813 (uint32_t)le32_to_cpu(perf->capacitor_health));
5814 printf(" Lifetime User Writes %20"PRIu64"l" "u""\n",
5815 le64_to_cpu(perf->lifetime_user_writes));
5816 printf(" Lifetime User Reads %20"PRIu64"l" "u""\n",
5817 le64_to_cpu(perf->lifetime_user_reads));
5818 printf(" Lifetime Thermal Throttle Activations %20"PRIu32"u""\n",
5819 (uint32_t)le32_to_cpu(perf->lifetime_thermal_throttle_act));
5820 printf(" Percentage of P/E Cycles Remaining %20"PRIu32"u""%%\n",
5821 (uint32_t)le32_to_cpu(perf->percentage_pe_cycles_remaining));
5822}
5823
5824static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf)
5825{
5826 struct json_object *root = json_create_object()json_object_new_object();
5827
5828 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
)))
5829 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
)))
;
5830 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)))
5831 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)))
;
5832 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)))
5833 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)))
;
5834 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
)))
5835 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
)))
;
5836 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
)))
5837 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
)))
;
5838 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)))
5839 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)))
;
5840 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)))
5841 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)))
;
5842 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
)))
5843 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
)))
;
5844 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)))
5845 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)))
;
5846 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
)))
5847 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
)))
;
5848 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
)))
5849 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
)))
;
5850 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
)))
5851 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
)))
;
5852 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)))
5853 le32_to_cpu(perf->current_temp))json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
;
5854 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)))
5855 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)))
;
5856 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)))
5857 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)))
;
5858 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
)))
5859 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
)))
;
5860 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)))
5861 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)))
;
5862 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)))
5863 le32_to_cpu(perf->capacitor_health))json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
;
5864 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)))
5865 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)))
;
5866 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)))
5867 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)))
;
5868 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
)))
5869 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
)))
;
5870 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
)))
5871 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
)))
;
5872
5873 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5874 printf("\n");
5875 json_free_object(root)json_object_put(root);
5876}
5877
5878static void wdc_get_commit_action_bin(__u8 commit_action_type, char *action_bin)
5879{
5880
5881 switch (commit_action_type) {
5882 case 0:
5883 strcpy(action_bin, "000b");
5884 break;
5885 case 1:
5886 strcpy(action_bin, "001b");
5887 break;
5888 case 2:
5889 strcpy(action_bin, "010b");
5890 break;
5891 case 3:
5892 strcpy(action_bin, "011b");
5893 break;
5894 case 4:
5895 strcpy(action_bin, "100b");
5896 break;
5897 case 5:
5898 strcpy(action_bin, "101b");
5899 break;
5900 case 6:
5901 strcpy(action_bin, "110b");
5902 break;
5903 case 7:
5904 strcpy(action_bin, "111b");
5905 break;
5906 default:
5907 strcpy(action_bin, "INVALID");
5908 }
5909
5910}
5911
5912static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
5913 __u32 cust_id, __u32 vendor_id,
5914 __u32 device_id)
5915{
5916 int i, j;
5917 char previous_fw[9];
5918 char new_fw[9];
5919 char commit_action_bin[8];
5920 char time_str[100];
5921 __u16 oldestEntryIdx = 0, entryIdx = 0;
5922 uint64_t timestamp;
5923 __u64 timestamp_sec;
5924 const char *null_fw = "--------";
5925
5926 memset((void *)time_str, '\0', 100);
5927
5928 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
5929 printf(" Firmware Activate History Log\n");
5930 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005 ||
5931 vendor_id == WDC_NVME_SNDK_VID0x15b7) {
5932 printf(" Power on Hour Power Cycle Previous New\n");
5933 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
5934 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5935 } else {
5936 printf(" Power Cycle Previous New\n");
5937 printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n");
5938 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5939 }
5940
5941 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
5942
5943 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
5944 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
5945 /* find lowest/oldest entry */
5946 for (i = 0; i < num_entries; i++) {
5947 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
5948 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
5949 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
5950 oldestEntryIdx = j;
5951 break;
5952 }
5953 }
5954 }
5955 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
5956 entryIdx = 0;
5957 else
5958 entryIdx = oldestEntryIdx;
5959
5960 for (i = 0; i < num_entries; i++) {
5961 memset((void *)previous_fw, 0, 9);
5962 memset((void *)new_fw, 0, 9);
5963 memset((void *)commit_action_bin, 0, 8);
5964
5965 memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8);
5966 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
5967 memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8);
5968 else
5969 memcpy(new_fw, null_fw, 8);
5970
5971 printf("%5"PRIu16"hu""", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
5972
5973 timestamp = (0x0000FFFFFFFFFFFF &
5974 le64_to_cpu(
5975 fw_act_history_entry->entry[entryIdx].timestamp));
5976 timestamp_sec = timestamp / 1000;
5977 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
5978 printf(" ");
5979 memset((void *)time_str, 0, 9);
5980 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
5981 (__u32)(timestamp_sec/3600),
5982 (__u8)(timestamp_sec%3600/60),
5983 (__u8)(timestamp_sec%60));
5984
5985 printf("%s", time_str);
5986 printf(" ");
5987 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
5988 printf(" ");
5989
5990 memset((void *)time_str, 0, 9);
5991 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
5992 (__u32)((timestamp_sec/3600)%24),
5993 (__u8)((timestamp_sec/60)%60),
5994 (__u8)(timestamp_sec%60));
5995 printf("%s", time_str);
5996 printf(" ");
5997 } else {
5998 printf(" ");
5999 printf("%16"PRIu64"l" "u""", timestamp);
6000 printf(" ");
6001 }
6002
6003 printf("%16"PRIu64"l" "u""", (uint64_t)le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count));
6004 printf(" ");
6005 printf("%s", (char *)previous_fw);
6006 printf(" ");
6007 printf("%s", (char *)new_fw);
6008 printf(" ");
6009 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number);
6010 printf(" ");
6011 wdc_get_commit_action_bin(
6012 fw_act_history_entry->entry[entryIdx].commit_action_type,
6013 (char *)&commit_action_bin);
6014 printf(" %s", (char *)commit_action_bin);
6015 printf(" ");
6016 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))
6017 printf("pass");
6018 else
6019 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result));
6020 printf("\n");
6021
6022 entryIdx++;
6023 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6024 entryIdx = 0;
6025 }
6026 } else {
6027 printf(" Firmware Activate History Log\n");
6028 printf(" Power on Hour Power Cycle Previous New\n");
6029 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6030 printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n");
6031
6032 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));
6033
6034 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6035 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6036 /* find lowest/oldest entry */
6037 for (i = 0; i < num_entries; i++) {
6038 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6039 oldestEntryIdx = i+1;
6040 break;
6041 }
6042 }
6043 }
6044
6045 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6046 entryIdx = 0;
6047 else
6048 entryIdx = oldestEntryIdx;
6049
6050 for (i = 0; i < num_entries; i++) {
6051 memset((void *)previous_fw, 0, 9);
6052 memset((void *)new_fw, 0, 9);
6053 memset((void *)commit_action_bin, 0, 8);
6054
6055 memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6056 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6057 memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6058 else
6059 memcpy(new_fw, null_fw, 8);
6060
6061 printf("%5"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].entry_num));
6062 printf(" ");
6063 printf("%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6064 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6065 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6066 printf(" ");
6067 printf("%16"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count));
6068 printf(" ");
6069 printf("%s", (char *)previous_fw);
6070 printf(" ");
6071 printf("%s", (char *)new_fw);
6072 printf(" ");
6073 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry[entryIdx].slot_number);
6074 printf(" ");
6075 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6076 (char *)&commit_action_bin);
6077 printf(" %s", (char *)commit_action_bin);
6078 printf(" ");
6079 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result))
6080 printf("pass");
6081 else
6082 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result));
6083
6084 printf("\n");
6085
6086 entryIdx++;
6087 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6088 entryIdx = 0;
6089 }
6090 }
6091}
6092
6093static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
6094 __u32 cust_id, __u32 vendor_id,
6095 __u32 device_id)
6096{
6097 struct json_object *root = json_create_object()json_object_new_object();
6098 int i, j;
6099 char previous_fw[9];
6100 char new_fw[9];
6101 char commit_action_bin[8];
6102 char fail_str[32];
6103 char time_str[100];
6104 char ext_time_str[20];
6105 uint64_t timestamp;
6106 __u64 timestamp_sec;
6107
6108 memset((void *)previous_fw, 0, 9);
6109 memset((void *)new_fw, 0, 9);
6110 memset((void *)commit_action_bin, 0, 8);
6111 memset((void *)time_str, '\0', 100);
6112 memset((void *)ext_time_str, 0, 20);
6113 memset((void *)fail_str, 0, 11);
6114 char *null_fw = "--------";
6115 __u16 oldestEntryIdx = 0, entryIdx = 0;
6116
6117 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6118 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6119
6120 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6121 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6122 /* find lowest/oldest entry */
6123 for (i = 0; i < num_entries; i++) {
6124 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6125 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6126 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6127 oldestEntryIdx = j;
6128 break;
6129 }
6130 }
6131 }
6132 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6133 entryIdx = 0;
6134 else
6135 entryIdx = oldestEntryIdx;
6136
6137 for (i = 0; i < num_entries; i++) {
6138 memcpy(previous_fw,
6139 (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version),
6140 8);
6141 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6142 memcpy(new_fw,
6143 (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version),
6144 8);
6145 else
6146 memcpy(new_fw, null_fw, 8);
6147
6148 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
)))
6149 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
)))
;
6150
6151 timestamp = (0x0000FFFFFFFFFFFF &
6152 le64_to_cpu(
6153 fw_act_history_entry->entry[entryIdx].timestamp));
6154 timestamp_sec = timestamp / 1000;
6155 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6156 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6157 (__u32)(timestamp_sec/3600),
6158 (__u8)(timestamp_sec%3600/60),
6159 (__u8)(timestamp_sec%60));
6160
6161 json_object_add_value_string(root, "Power on Hour", time_str);
6162
6163 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6164 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6165 (__u32)((timestamp_sec/3600)%24),
6166 (__u8)((timestamp_sec/60)%60),
6167 (__u8)(timestamp_sec%60));
6168 json_object_add_value_string(root, "Power on Hour", time_str);
6169 } else {
6170 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
6171 }
6172
6173 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
)))
6174 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
)))
;
6175 json_object_add_value_string(root, "Previous Firmware",
6176 previous_fw);
6177 json_object_add_value_string(root, "New Firmware",
6178 new_fw);
6179 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))
6180 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))
;
6181
6182 wdc_get_commit_action_bin(
6183 fw_act_history_entry->entry[entryIdx].commit_action_type,
6184 (char *)&commit_action_bin);
6185 json_object_add_value_string(root, "Action", commit_action_bin);
6186
6187 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) {
6188 json_object_add_value_string(root, "Result", "pass");
6189 } else {
6190 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)));
6191 json_object_add_value_string(root, "Result", fail_str);
6192 }
6193
6194 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6195 printf("\n");
6196
6197 entryIdx++;
6198 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6199 entryIdx = 0;
6200 }
6201 } else {
6202 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));
6203
6204 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6205 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6206 /* find lowest/oldest entry */
6207 for (i = 0; i < num_entries; i++) {
6208 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6209 oldestEntryIdx = i+1;
6210 break;
6211 }
6212 }
6213 }
6214 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6215 entryIdx = 0;
6216 else
6217 entryIdx = oldestEntryIdx;
6218
6219 for (i = 0; i < num_entries; i++) {
6220 memcpy(previous_fw,
6221 (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6222 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6223 memcpy(new_fw,
6224 (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6225 else
6226 memcpy(new_fw, null_fw, 8);
6227
6228 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)))
6229 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)))
;
6230
6231 sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6232 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6233 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6234 json_object_add_value_string(root, "Power on Hour", time_str);
6235
6236 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
)))
6237 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
)))
;
6238 json_object_add_value_string(root, "Previous Firmware",
6239 previous_fw);
6240 json_object_add_value_string(root, "New Firmware",
6241 new_fw);
6242 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
6243 fw_act_history_entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
;
6244
6245 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6246 (char *)&commit_action_bin);
6247 json_object_add_value_string(root, "Action", commit_action_bin);
6248
6249 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) {
6250 json_object_add_value_string(root, "Result", "pass");
6251 } else {
6252 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry[entryIdx].result)));
6253 json_object_add_value_string(root, "Result", fail_str);
6254 }
6255
6256 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6257 printf("\n");
6258
6259 entryIdx++;
6260 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6261 entryIdx = 0;
6262 }
6263 }
6264
6265 json_free_object(root)json_object_put(root);
6266}
6267
6268static int nvme_get_print_ocp_cloud_smart_log(struct libnvme_transport_handle *hdl,
6269 int uuid_index,
6270 __u32 namespace_id,
6271 int fmt)
6272{
6273 struct ocp_cloud_smart_log *log_ptr = NULL((void*)0);
6274 struct libnvme_passthru_cmd cmd;
6275 int ret, i;
6276
6277 log_ptr = malloc(sizeof(*log_ptr));
6278 if (!log_ptr) {
6279 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6280 return -1;
6281 }
6282
6283 if (namespace_id == NVME_NSID_ALL) {
6284 ret = libnvme_get_nsid(hdl, &namespace_id);
6285 if (ret < 0)
6286 namespace_id = NVME_NSID_ALL;
6287 }
6288
6289 /* Get the 0xC0 log data */
6290 nvme_init_get_log(&cmd, namespace_id,
6291 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6292 log_ptr, sizeof(*log_ptr));
6293 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6294 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6295 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6296 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6297 if (fmt == JSON)
6298 nvme_show_status(ret);
6299
6300 if (!ret) {
6301 /* Verify GUID matches */
6302 for (i = 0; i < 16; i++) {
6303 if (scao_guid[i] != log_ptr->log_page_guid[i]) {
6304 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"
)
;
6305 int j;
6306
6307 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6308 for (j = 0; j < 16; j++)
6309 nvme_show_error("%x", scao_guid[j])nvme_show_message(1, "%x", scao_guid[j]);
6310 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6311 for (j = 0; j < 16; j++)
6312 nvme_show_error("%x", log_ptr->log_page_guid[j])nvme_show_message(1, "%x", log_ptr->log_page_guid[j]);
6313 nvme_show_error("")nvme_show_message(1, "");
6314
6315 ret = -1;
6316 break;
6317 }
6318 }
6319
6320 if (!ret)
6321 /* parse the data */
6322 wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl);
6323 } else {
6324 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"
)
;
6325 ret = -1;
6326 }
6327
6328 free(log_ptr);
6329 return ret;
6330}
6331
6332static int nvme_get_print_c0_eol_log(struct libnvme_transport_handle *hdl,
6333 int uuid_index,
6334 __u32 namespace_id,
6335 int fmt)
6336{
6337 __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN0x200;
6338 struct libnvme_passthru_cmd cmd;
6339 void *log_ptr = NULL((void*)0);
6340 int ret;
6341
6342 log_ptr = (void *)malloc(sizeof(__u8) * length);
6343 if (!log_ptr) {
6344 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6345 return -1;
6346 }
6347
6348 if (namespace_id == NVME_NSID_ALL) {
6349 ret = libnvme_get_nsid(hdl, &namespace_id);
6350 if (ret < 0)
6351 namespace_id = NVME_NSID_ALL;
6352 }
6353
6354 /* Get the 0xC0 log data */
6355 nvme_init_get_log(&cmd, namespace_id,
6356 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, NVME_CSI_NVM,
6357 log_ptr, length);
6358 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6359 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6360 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6361 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6362 if (fmt == JSON)
6363 nvme_show_status(ret);
6364
6365 if (!ret) {
6366 /* parse the data */
6367 wdc_print_c0_eol_log(log_ptr, fmt);
6368 } else {
6369 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 "
)
;
6370 nvme_show_error("with uuid index %d", uuid_index)nvme_show_message(1, "with uuid index %d", uuid_index);
6371 ret = -1;
6372 }
6373
6374 free(log_ptr);
6375 return ret;
6376}
6377
6378static int nvme_get_ext_smart_cloud_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6379{
6380 struct libnvme_passthru_cmd cmd;
6381 __u8 *log_ptr = NULL((void*)0);
6382 int ret, i;
6383
6384 log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6385 if (!log_ptr) {
6386 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6387 return -1;
6388 }
6389
6390 /* Get the 0xC0 log data */
6391 nvme_init_get_log(&cmd, namespace_id,
6392 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6393 log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6394 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6395 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6396 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6397 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6398 if (!ret) {
6399 /* Verify GUID matches */
6400 for (i = 0; i < WDC_C0_GUID_LENGTH16; i++) {
6401 if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
6402 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"
)
;
6403 int j;
6404
6405 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6406 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6407 nvme_show_error("%x", ext_smart_guid[j])nvme_show_message(1, "%x", ext_smart_guid[j]);
6408 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6409 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6410 nvme_show_error("%x", *&log_ptr[SCAO_V1_LPG + j])nvme_show_message(1, "%x", *&log_ptr[SCAO_V1_LPG + j]);
6411 nvme_show_error("")nvme_show_message(1, "");
6412
6413 ret = -1;
6414 break;
6415 }
6416 }
6417 }
6418
6419 *data = log_ptr;
6420
6421 return ret;
6422}
6423
6424
6425static int nvme_get_hw_rev_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6426{
6427 struct wdc_nvme_hw_rev_log *log_ptr = NULL((void*)0);
6428 struct libnvme_passthru_cmd cmd;
6429 int ret, i;
6430
6431 log_ptr = malloc(sizeof(*log_ptr));
6432 if (!log_ptr) {
6433 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6434 return -1;
6435 }
6436
6437 /* Get the 0xC0 log data */
6438 nvme_init_get_log(&cmd, namespace_id,
6439 WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6, NVME_CSI_NVM,
6440 log_ptr, sizeof(*log_ptr));
6441 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6442 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6443 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6444 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6445 if (!ret) {
6446 /* Verify GUID matches */
6447 for (i = 0; i < WDC_NVME_C6_GUID_LENGTH16; i++) {
6448 if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
6449 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"
)
;
6450 int j;
6451
6452 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6453 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6454 nvme_show_error("%x", hw_rev_log_guid[j])nvme_show_message(1, "%x", hw_rev_log_guid[j]);
6455 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6456 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6457 nvme_show_error("%x", log_ptr->hw_rev_guid[j])nvme_show_message(1, "%x", log_ptr->hw_rev_guid[j]);
6458 nvme_show_error("")nvme_show_message(1, "");
6459
6460 ret = -1;
6461 break;
6462 }
6463 }
6464 }
6465
6466 *data = (__u8 *)log_ptr;
6467
6468 return ret;
6469}
6470
6471
6472static void wdc_print_hw_rev_log_normal(void *data)
6473{
6474 int i;
6475 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6476
6477 printf(" Hardware Revision Log:-\n");
6478
6479 printf(" Global Device HW Revision : %d\n",
6480 log_data->hw_rev_gdr);
6481 printf(" ASIC HW Revision : %d\n",
6482 log_data->hw_rev_ar);
6483 printf(" PCB Manufacturer Code : %d\n",
6484 log_data->hw_rev_pbc_mc);
6485 printf(" DRAM Manufacturer Code : %d\n",
6486 log_data->hw_rev_dram_mc);
6487 printf(" NAND Manufacturer Code : %d\n",
6488 log_data->hw_rev_nand_mc);
6489 printf(" PMIC 1 Manufacturer Code : %d\n",
6490 log_data->hw_rev_pmic1_mc);
6491 printf(" PMIC 2 Manufacturer Code : %d\n",
6492 log_data->hw_rev_pmic2_mc);
6493 printf(" Other Component 1 Manf Code : %d\n",
6494 log_data->hw_rev_c1_mc);
6495 printf(" Other Component 2 Manf Code : %d\n",
6496 log_data->hw_rev_c2_mc);
6497 printf(" Other Component 3 Manf Code : %d\n",
6498 log_data->hw_rev_c3_mc);
6499 printf(" Other Component 4 Manf Code : %d\n",
6500 log_data->hw_rev_c4_mc);
6501 printf(" Other Component 5 Manf Code : %d\n",
6502 log_data->hw_rev_c5_mc);
6503 printf(" Other Component 6 Manf Code : %d\n",
6504 log_data->hw_rev_c6_mc);
6505 printf(" Other Component 7 Manf Code : %d\n",
6506 log_data->hw_rev_c7_mc);
6507 printf(" Other Component 8 Manf Code : %d\n",
6508 log_data->hw_rev_c8_mc);
6509 printf(" Other Component 9 Manf Code : %d\n",
6510 log_data->hw_rev_c9_mc);
6511
6512 printf(" Device Manf Detailed Info : 0x");
6513 for (i = 0; i < 16; i++) {
6514 printf("%02x", log_data->hw_rev_dev_mdi[i]);
6515 if (i == 7)
6516 printf(" 0x");
6517 }
6518 printf("\n");
6519 printf(" ASIC Detailed Info : 0x");
6520 for (i = 0; i < 16; i++) {
6521 printf("%02x", log_data->hw_rev_asic_di[i]);
6522 if (i == 7)
6523 printf(" 0x");
6524 }
6525 printf("\n");
6526 printf(" PCB Detailed Info : 0x");
6527 for (i = 0; i < 16; i++) {
6528 printf("%02x", log_data->hw_rev_pcb_di[i]);
6529 if (i == 7)
6530 printf(" 0x");
6531 }
6532 printf("\n");
6533 printf(" DRAM Detailed Info : 0x");
6534 for (i = 0; i < 16; i++) {
6535 printf("%02x", log_data->hw_rev_dram_di[i]);
6536 if (i == 7)
6537 printf(" 0x");
6538 }
6539 printf("\n");
6540 printf(" NAND Detailed Info : 0x");
6541 for (i = 0; i < 16; i++) {
6542 printf("%02x", log_data->hw_rev_nand_di[i]);
6543 if (i == 7)
6544 printf(" 0x");
6545 }
6546 printf("\n");
6547 printf(" PMIC 1 Detailed Info : 0x");
6548 for (i = 0; i < 16; i++) {
6549 printf("%02x", log_data->hw_rev_pmic1_di[i]);
6550 if (i == 7)
6551 printf(" 0x");
6552 }
6553 printf("\n");
6554 printf(" PMIC 2 Detailed Info : 0x");
6555 for (i = 0; i < 16; i++) {
6556 printf("%02x", log_data->hw_rev_pmic2_di[i]);
6557 if (i == 7)
6558 printf(" 0x");
6559 }
6560 printf("\n");
6561 printf(" Component 1 Detailed Info : 0x");
6562 for (i = 0; i < 16; i++) {
6563 printf("%02x", log_data->hw_rev_c1_di[i]);
6564 if (i == 7)
6565 printf(" 0x");
6566 }
6567 printf("\n");
6568 printf(" Component 2 Detailed Info : 0x");
6569 for (i = 0; i < 16; i++) {
6570 printf("%02x", log_data->hw_rev_c2_di[i]);
6571 if (i == 7)
6572 printf(" 0x");
6573 }
6574 printf("\n");
6575 printf(" Component 3 Detailed Info : 0x");
6576 for (i = 0; i < 16; i++) {
6577 printf("%02x", log_data->hw_rev_c3_di[i]);
6578 if (i == 7)
6579 printf(" 0x");
6580 }
6581 printf("\n");
6582 printf(" Component 4 Detailed Info : 0x");
6583 for (i = 0; i < 16; i++) {
6584 printf("%02x", log_data->hw_rev_c4_di[i]);
6585 if (i == 7)
6586 printf(" 0x");
6587 }
6588 printf("\n");
6589 printf(" Component 5 Detailed Info : 0x");
6590 for (i = 0; i < 16; i++) {
6591 printf("%02x", log_data->hw_rev_c5_di[i]);
6592 if (i == 7)
6593 printf(" 0x");
6594 }
6595 printf("\n");
6596 printf(" Component 6 Detailed Info : 0x");
6597 for (i = 0; i < 16; i++) {
6598 printf("%02x", log_data->hw_rev_c6_di[i]);
6599 if (i == 7)
6600 printf(" 0x");
6601 }
6602 printf("\n");
6603 printf(" Component 7 Detailed Info : 0x");
6604 for (i = 0; i < 16; i++) {
6605 printf("%02x", log_data->hw_rev_c7_di[i]);
6606 if (i == 7)
6607 printf(" 0x");
6608 }
6609 printf("\n");
6610 printf(" Component 8 Detailed Info : 0x");
6611 for (i = 0; i < 16; i++) {
6612 printf("%02x", log_data->hw_rev_c8_di[i]);
6613 if (i == 7)
6614 printf(" 0x");
6615 }
6616 printf("\n");
6617 printf(" Component 9 Detailed Info : 0x");
6618 for (i = 0; i < 16; i++) {
6619 printf("%02x", log_data->hw_rev_c9_di[i]);
6620 if (i == 7)
6621 printf(" 0x");
6622 }
6623 printf("\n");
6624 printf(" Serial Number : 0x");
6625 for (i = 0; i < 32; i++) {
6626 if ((i > 1) & !(i % 8))
6627 printf(" 0x");
6628 printf("%02x", log_data->hw_rev_sn[i]);
6629 }
6630 printf("\n");
6631
6632 printf(" Log Page Version : %d\n", log_data->hw_rev_version);
6633 printf(" Log page GUID : 0x");
6634 printf("%"PRIx64"l" "x""%"PRIx64"l" "x""\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6635 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6636 printf("\n");
6637}
6638
6639static void wdc_print_hw_rev_log_json(void *data)
6640{
6641 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6642 struct json_object *root = json_create_object()json_object_new_object();
6643 char json_data[80];
6644
6645 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))
6646 log_data->hw_rev_gdr)json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
;
6647 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))
6648 log_data->hw_rev_ar)json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
;
6649 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))
6650 log_data->hw_rev_pbc_mc)json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
;
6651 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))
6652 log_data->hw_rev_dram_mc)json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
;
6653 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))
6654 log_data->hw_rev_nand_mc)json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
;
6655 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))
6656 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))
;
6657 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))
6658 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))
;
6659 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))
6660 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))
;
6661 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))
6662 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))
;
6663 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))
6664 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))
;
6665 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))
6666 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))
;
6667 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))
6668 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))
;
6669 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))
6670 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))
;
6671 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))
6672 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))
;
6673 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))
6674 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))
;
6675 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))
6676 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))
;
6677
6678 memset((void *)json_data, 0, 40);
6679 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]),
6680 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
6681 json_object_add_value_string(root, "Device Manf Detailed Info", json_data);
6682
6683 memset((void *)json_data, 0, 40);
6684 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]),
6685 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
6686 json_object_add_value_string(root, "ASIC Detailed Info", json_data);
6687
6688 memset((void *)json_data, 0, 40);
6689 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]),
6690 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
6691 json_object_add_value_string(root, "PCB Detailed Info", json_data);
6692
6693 memset((void *)json_data, 0, 40);
6694 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]),
6695 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
6696 json_object_add_value_string(root, "DRAM Detailed Info", json_data);
6697
6698 memset((void *)json_data, 0, 40);
6699 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]),
6700 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
6701 json_object_add_value_string(root, "NAND Detailed Info", json_data);
6702
6703 memset((void *)json_data, 0, 40);
6704 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]),
6705 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
6706 json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
6707
6708 memset((void *)json_data, 0, 40);
6709 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
6710 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
6711 json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
6712
6713 memset((void *)json_data, 0, 40);
6714 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
6715 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
6716 json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
6717
6718 memset((void *)json_data, 0, 40);
6719 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
6720 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
6721 json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
6722
6723 memset((void *)json_data, 0, 40);
6724 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
6725 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
6726 json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
6727
6728 memset((void *)json_data, 0, 40);
6729 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
6730 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
6731 json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
6732
6733 memset((void *)json_data, 0, 40);
6734 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
6735 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
6736 json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
6737
6738 memset((void *)json_data, 0, 40);
6739 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
6740 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
6741 json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
6742
6743 memset((void *)json_data, 0, 40);
6744 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
6745 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
6746 json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
6747
6748 memset((void *)json_data, 0, 40);
6749 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
6750 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
6751 json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
6752
6753 memset((void *)json_data, 0, 40);
6754 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
6755 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
6756 json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
6757
6758 memset((void *)json_data, 0, 80);
6759 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""",
6760 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
6761 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
6762 json_object_add_value_string(root, "Serial Number", json_data);
6763
6764 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)))
6765 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)))
;
6766
6767 memset((void *)json_data, 0, 40);
6768 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6769 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6770 json_object_add_value_string(root, "Log Page GUID", json_data);
6771
6772 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6773 printf("\n");
6774 json_free_object(root)json_object_put(root);
6775}
6776
6777static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
6778{
6779 int i;
6780 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6781
6782 if (mask == WDC_SCA_V1_NAND_STATS0x1)
6783 printf(" NAND Statistics :-\n");
6784 else
6785 printf(" SMART Cloud Attributes :-\n");
6786
6787 printf(" Physical Media Units Written TLC (Bytes): %s\n",
6788 uint128_t_to_string(le128_to_cpu(
6789 ext_smart_log_ptr->ext_smart_pmuwt)));
6790 printf(" Physical Media Units Written SLC (Bytes): %s\n",
6791 uint128_t_to_string(le128_to_cpu(
6792 ext_smart_log_ptr->ext_smart_pmuws)));
6793 printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
6794 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
6795 printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6796 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
6797 printf(" XOR Recovery Count (Int) : %"PRIu64"l" "u""\n",
6798 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
6799 printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"l" "u""\n",
6800 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
6801 if (mask == WDC_SCA_V1_ALL0xF) {
6802 printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"l" "u""\n",
6803 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
6804 printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"l" "u""\n",
6805 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
6806 printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"l" "u""\n",
6807 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
6808 printf(" System Data %% life-used : %d %%\n",
6809 ext_smart_log_ptr->ext_smart_sdpu);
6810 }
6811 printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"l" "u""\n",
6812 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
6813 printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"l" "u""\n",
6814 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
6815 printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"l" "u""\n",
6816 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
6817 printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"l" "u""\n",
6818 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
6819 printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"l" "u""\n",
6820 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
6821 printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"l" "u""\n",
6822 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
6823 printf(" Program Fail Count (Normalized) (Int) : %d\n",
6824 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
6825 printf(" Program Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6826 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
6827 printf(" Erase Fail Count (Normalized) (Int) : %d\n",
6828 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
6829 printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6830 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
6831 if (mask == WDC_SCA_V1_ALL0xF) {
6832 printf(" PCIe Correctable Error Count (Int) : %"PRIu64"l" "u""\n",
6833 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
6834 printf(" %% Free Blocks (User) (Int) : %d %%\n",
6835 ext_smart_log_ptr->ext_smart_pfbu);
6836 printf(" Security Version Number (Int) : %"PRIu64"l" "u""\n",
6837 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
6838 printf(" %% Free Blocks (System) (Int) : %d %%\n",
6839 ext_smart_log_ptr->ext_smart_pfbs);
6840 printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n",
6841 uint128_t_to_string(le128_to_cpu(
6842 ext_smart_log_ptr->ext_smart_dcc)));
6843 printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"l" "u""\n",
6844 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
6845 printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
6846 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
6847 printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
6848 ext_smart_log_ptr->ext_smart_bbpg);
6849 }
6850 printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"l" "u""\n",
6851 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
6852 if (mask == WDC_SCA_V1_ALL0xF) {
6853 printf(" Total # of Read Refresh Count (Int) : %"PRIu64"l" "u""\n",
6854 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
6855 }
6856 printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
6857 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
6858 printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6859 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
6860 printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n",
6861 uint128_t_to_string(
6862 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)));
6863 if (mask == WDC_SCA_V1_ALL0xF) {
6864 printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
6865 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
6866 printf(" Total # Unaligned I/O (Int) : %"PRIu64"l" "u""\n",
6867 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
6868 }
6869 printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n",
6870 uint128_t_to_string(
6871 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)));
6872 if (mask == WDC_SCA_V1_ALL0xF) {
6873 printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6874 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
6875 printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6876 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
6877 printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6878 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
6879 printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"l" "u""\n",
6880 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
6881 printf(" Active Power State Change Count (Int) : %"PRIu64"l" "u""\n",
6882 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
6883 }
6884 printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
6885 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
6886 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
6887 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
6888 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
6889 printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
6890 0, 0, 0, 0);
6891 if (mask == WDC_SCA_V1_ALL0xF) {
6892 printf(" FTL Unit Size : %"PRIu32"u""\n",
6893 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
6894 printf(" TCG Ownership Status : %"PRIu32"u""\n",
6895 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
6896 printf(" Log Page Version (Int) : %d\n",
6897 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
6898 printf(" Log page GUID (Hex) : 0x");
6899 for (i = WDC_C0_GUID_LENGTH16; i > 0; i--)
6900 printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
6901 printf("\n");
6902 }
6903 printf("\n");
6904}
6905
6906static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
6907{
6908 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr =
6909 (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6910 struct json_object *root = json_create_object()json_object_new_object();
6911
6912 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)))
6913 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)))
;
6914 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)))
6915 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)))
;
6916 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
)))
6917 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
)))
;
6918 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)))
6919 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)))
;
6920 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)))
6921 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)))
;
6922 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)))
6923 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)))
;
6924 if (mask == WDC_SCA_V1_ALL0xF) {
6925 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)))
6926 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)))
;
6927 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)))
6928 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)))
;
6929 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)))
6930 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)))
;
6931 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))
6932 (__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))
;
6933 }
6934 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
)))
6935 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
)))
;
6936 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
)))
6937 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
)))
;
6938 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
)))
6939 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
)))
;
6940 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
)))
6941 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
)))
;
6942 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
)))
6943 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
)))
;
6944 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
)))
6945 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
)))
;
6946 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)))
6947 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)))
;
6948 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)))
6949 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)))
;
6950 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
)))
6951 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
)))
;
6952 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)))
6953 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)))
;
6954 if (mask == WDC_SCA_V1_ALL0xF) {
6955 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)))
6956 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)))
;
6957 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))
6958 (__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))
;
6959 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)))
6960 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)))
;
6961 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))
6962 (__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))
;
6963 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)))
6964 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)))
;
6965 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)))
6966 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)))
;
6967 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)))
6968 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)))
;
6969 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))
6970 (__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))
;
6971 }
6972 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)))
6973 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)))
;
6974 if (mask == WDC_SCA_V1_ALL0xF)
6975 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)))
6976 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)))
;
6977 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
)))
6978 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
)))
;
6979 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)))
6980 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)))
;
6981 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)))
6982 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)))
;
6983 if (mask == WDC_SCA_V1_ALL0xF) {
6984 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)))
6985 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)))
;
6986 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)))
6987 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)))
;
6988 }
6989 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)))
6990 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)))
;
6991 if (mask == WDC_SCA_V1_ALL0xF) {
6992 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)))
6993 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)))
;
6994 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)))
6995 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)))
;
6996 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)))
6997 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)))
;
6998 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)))
6999 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)))
;
7000 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
)))
7001 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
)))
;
7002 }
7003 char vers_str[40];
7004
7005 memset((void *)vers_str, 0, 40);
7006 sprintf((char *)vers_str, "%d.%d.%d.%d",
7007 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7008 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7009 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7010 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7011 json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
7012 memset((void *)vers_str, 0, 40);
7013 sprintf((char *)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0);
7014 json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
7015
7016 if (mask == WDC_SCA_V1_ALL0xF) {
7017 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)))
7018 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)))
;
7019 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)))
7020 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)))
;
7021 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)))
7022 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)))
;
7023 char guid[40];
7024
7025 memset((void *)guid, 0, 40);
7026 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7027 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]),
7028 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0]));
7029 json_object_add_value_string(root, "log_page_guid", guid);
7030 }
7031
7032 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7033 printf("\n");
7034 json_free_object(root)json_object_put(root);
7035}
7036
7037static void wdc_print_eol_c0_normal(void *data)
7038{
7039 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7040 (struct wdc_nvme_c0_eol_log_page *)data;
7041
7042 printf(" End of Life Log Page 0xC0 :-\n");
7043 printf(" Realloc Block Count %"PRIu32"u""\n",
7044 le32_to_cpu(eol_log_page_ptr->eol_rbc));
7045 printf(" Write Amp %"PRIu32"u""\n",
7046 le32_to_cpu(eol_log_page_ptr->eol_wra));
7047 printf(" Percent Life Remaining %"PRIu32"u""\n",
7048 le32_to_cpu(eol_log_page_ptr->eol_plr));
7049 printf(" Program Fail Count %"PRIu32"u""\n",
7050 le32_to_cpu(eol_log_page_ptr->eol_pfc));
7051 printf(" Erase Fail Count %"PRIu32"u""\n",
7052 le32_to_cpu(eol_log_page_ptr->eol_efc));
7053 printf(" Raw Read Error Rate %"PRIu32"u""\n",
7054 le32_to_cpu(eol_log_page_ptr->eol_rrer));
7055}
7056
7057static void wdc_print_eol_c0_json(void *data)
7058{
7059 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7060 (struct wdc_nvme_c0_eol_log_page *)data;
7061 struct json_object *root = json_create_object()json_object_new_object();
7062
7063 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)))
7064 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)))
;
7065 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)))
7066 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)))
;
7067 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)))
7068 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)))
;
7069 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)))
7070 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)))
;
7071 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)))
7072 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)))
;
7073 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)))
7074 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)))
;
7075
7076 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7077 printf("\n");
7078 json_free_object(root)json_object_put(root);
7079}
7080
7081static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
7082{
7083 if (!data) {
7084 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"
)
;
7085 return -1;
7086 }
7087 switch (fmt) {
7088 case NORMAL:
7089 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL0xF);
7090 break;
7091 case JSON:
7092 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL0xF);
7093 break;
7094 }
7095 return 0;
7096}
7097
7098static int wdc_print_c0_cloud_attr_log(void *data,
7099 int fmt,
7100 struct libnvme_transport_handle *hdl)
7101{
7102 struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data;
7103
7104 if (!data) {
7105 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7106 return -1;
7107 }
7108
7109 switch (fmt) {
7110 case BINARY:
7111 d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log));
7112 break;
7113 case NORMAL:
7114 wdc_show_cloud_smart_log_normal(log, hdl);
7115 break;
7116 case JSON:
7117 wdc_show_cloud_smart_log_json(log);
7118 break;
7119 }
7120 return 0;
7121}
7122
7123static int wdc_print_c0_eol_log(void *data, int fmt)
7124{
7125 if (!data) {
7126 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7127 return -1;
7128 }
7129 switch (fmt) {
7130 case BINARY:
7131 d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN0x200);
7132 break;
7133 case NORMAL:
7134 wdc_print_eol_c0_normal(data);
7135 break;
7136 case JSON:
7137 wdc_print_eol_c0_json(data);
7138 break;
7139 }
7140 return 0;
7141}
7142
7143static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct libnvme_transport_handle *hdl, int uuid_index,
7144 char *format, __u32 namespace_id, int fmt)
7145{
7146 int ret;
7147
7148 if (!uuid_index) {
7149 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7150 uuid_index,
7151 namespace_id,
7152 fmt);
7153 } else if (uuid_index == 1) {
7154 ret = nvme_get_print_c0_eol_log(hdl,
7155 uuid_index,
7156 namespace_id,
7157 fmt);
7158 } else {
7159 nvme_show_error("ERROR: WDC: Unknown uuid index")nvme_show_message(1, "ERROR: WDC: Unknown uuid index");
7160 ret = -1;
7161 }
7162
7163 return ret;
7164}
7165
7166static int wdc_get_c0_log_page_sn(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, int uuid_index, char *format,
7167 __u32 namespace_id, int fmt)
7168{
7169 int ret = 0;
7170 __u32 cust_id;
7171
7172 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7173 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7174 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7175 return -1;
7176 }
7177
7178 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
7179 (cust_id == WDC_CUSTOMER_ID_0x10050x1005)) {
7180 ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format,
7181 namespace_id, fmt);
7182 } else {
7183 ret = nvme_get_print_c0_eol_log(hdl,
7184 0,
7185 namespace_id,
7186 fmt);
7187 }
7188
7189 return ret;
7190}
7191
7192static int wdc_get_c0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format, int uuid_index,
7193 __u32 namespace_id)
7194{
7195 uint32_t device_id = 0, read_vendor_id;
7196 nvme_print_flags_t fmt;
7197 int ret;
7198 __u8 *data;
7199 void *dev_mng_log = NULL((void*)0);
7200 __u32 market_name_len = 0;
7201 char marketing_name[64];
7202
7203 memset(marketing_name, 0, 64);
7204
7205 if (!wdc_check_device(ctx, hdl))
7206 return -1;
7207 ret = validate_output_format(format, &fmt);
7208 if (ret < 0) {
7209 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7210 return ret;
7211 }
7212
7213 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7214 if (ret) {
7215 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
7216 return ret;
7217 }
7218
7219 switch (device_id) {
7220 case WDC_NVME_SN640_DEV_ID0x2400:
7221 case WDC_NVME_SN640_DEV_ID_10x2401:
7222 case WDC_NVME_SN640_DEV_ID_20x2402:
7223 case WDC_NVME_SN640_DEV_ID_30x2404:
7224 case WDC_NVME_SN840_DEV_ID0x2300:
7225 case WDC_NVME_SN840_DEV_ID_10x2500:
7226 case WDC_NVME_SN860_DEV_ID0x2730:
7227 case WDC_NVME_SN560_DEV_ID_10x2712:
7228 case WDC_NVME_SN560_DEV_ID_20x2713:
7229 case WDC_NVME_SN560_DEV_ID_30x2714:
7230 case WDC_NVME_SN550_DEV_ID0x2708:
7231 ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt);
7232 break;
7233 case WDC_NVME_SN650_DEV_ID0x2700:
7234 case WDC_NVME_SN650_DEV_ID_10x2701:
7235 case WDC_NVME_SN650_DEV_ID_20x2702:
7236 case WDC_NVME_SN650_DEV_ID_30x2720:
7237 case WDC_NVME_SN650_DEV_ID_40x2721:
7238 case WDC_NVME_SN655_DEV_ID0x2722:
7239 case WDC_NVME_SN655_DEV_ID_10x2723:
7240 case WDC_NVME_SNTMP_DEV_ID0x2761:
7241 case WDC_NVME_SNTMP_DEV_ID_10x2763:
7242 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
7243 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
7244 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
7245 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
7246 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
7247 if (uuid_index == 0) {
7248 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7249 uuid_index,
7250 namespace_id,
7251 fmt);
7252 } else {
7253 ret = nvme_get_print_c0_eol_log(hdl,
7254 uuid_index,
7255 namespace_id,
7256 fmt);
7257 }
7258 break;
7259 case WDC_NVME_ZN350_DEV_ID0x5010:
7260 case WDC_NVME_ZN350_DEV_ID_10x5018:
7261 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7262 0,
7263 NVME_NSID_ALL,
7264 fmt);
7265 break;
7266 case WDC_NVME_SN820CL_DEV_ID0x5037:
7267 /* Get the 0xC0 Extended Smart Cloud Attribute log data */
7268 data = NULL((void*)0);
7269 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
7270 uuid_index, namespace_id);
7271
7272 if (strcmp(format, "json"))
7273 nvme_show_status(ret);
7274
7275 if (!ret) {
7276 /* parse the data */
7277 wdc_print_ext_smart_cloud_log(data, fmt);
7278 } else {
7279 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"
)
;
7280 ret = -1;
7281 }
7282
7283 free(data);
7284 break;
7285 default:
7286 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
7287 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
7288 ret = -1;
7289 goto out;
7290 }
7291
7292 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
7293 WDC_C2_MARKETING_NAME_ID0x07,
7294 (char *)marketing_name,
7295 &market_name_len)) {
7296 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
7297 ret = -1;
7298 goto out;
7299 }
7300
7301 if ((!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655", market_name_len)) ||
7302 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655", market_name_len)) ||
7303 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655", market_name_len)) ||
7304 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655", market_name_len))) {
7305 if (uuid_index == 0) {
7306 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7307 uuid_index,
7308 namespace_id,
7309 fmt);
7310 } else {
7311 ret = nvme_get_print_c0_eol_log(hdl,
7312 uuid_index,
7313 namespace_id,
7314 fmt);
7315 }
7316 } else {
7317 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)
7318 device_id, marketing_name)nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
;
7319 ret = -1;
7320 }
7321 break;
7322 }
7323
7324out:
7325 return ret;
7326}
7327
7328static int wdc_print_latency_monitor_log(struct libnvme_transport_handle *hdl,
7329 struct wdc_ssd_latency_monitor_log *log_data,
7330 int fmt)
7331{
7332 if (!log_data) {
7333 nvme_show_error("ERROR: WDC: Invalid C3 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C3 log data buffer"
)
;
7334 return -1;
7335 }
7336 switch (fmt) {
7337 case NORMAL:
7338 wdc_print_latency_monitor_log_normal(hdl, log_data);
7339 break;
7340 case JSON:
7341 wdc_print_latency_monitor_log_json(log_data);
7342 break;
7343 }
7344 return 0;
7345}
7346
7347static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
7348{
7349 if (!log_data) {
7350 nvme_show_error("ERROR: WDC: Invalid C1 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C1 log data buffer"
)
;
7351 return -1;
7352 }
7353 switch (fmt) {
7354 case NORMAL:
7355 wdc_print_error_rec_log_normal(log_data);
7356 break;
7357 case JSON:
7358 wdc_print_error_rec_log_json(log_data);
7359 break;
7360 }
7361 return 0;
7362}
7363
7364static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
7365{
7366 if (!log_data) {
7367 nvme_show_error("ERROR: WDC: Invalid C4 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C4 log data buffer"
)
;
7368 return -1;
7369 }
7370 switch (fmt) {
7371 case NORMAL:
7372 wdc_print_dev_cap_log_normal(log_data);
7373 break;
7374 case JSON:
7375 wdc_print_dev_cap_log_json(log_data);
7376 break;
7377 }
7378 return 0;
7379}
7380
7381static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
7382{
7383 if (!log_data) {
7384 nvme_show_error("ERROR: WDC: Invalid C5 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C5 log data buffer"
)
;
7385 return -1;
7386 }
7387 switch (fmt) {
7388 case NORMAL:
7389 wdc_print_unsupported_reqs_log_normal(log_data);
7390 break;
7391 case JSON:
7392 wdc_print_unsupported_reqs_log_json(log_data);
7393 break;
7394 }
7395 return 0;
7396}
7397
7398static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
7399{
7400 if (!perf) {
7401 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7402 return -1;
7403 }
7404 switch (fmt) {
7405 case NORMAL:
7406 wdc_print_fb_ca_log_normal(perf);
7407 break;
7408 case JSON:
7409 wdc_print_fb_ca_log_json(perf);
7410 break;
7411 }
7412 return 0;
7413}
7414
7415static int wdc_print_bd_ca_log(struct libnvme_transport_handle *hdl, void *bd_data, int fmt)
7416{
7417 if (!bd_data) {
7418 nvme_show_error("ERROR: WDC: Invalid buffer to read data")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read data"
)
;
7419 return -1;
7420 }
7421 switch (fmt) {
7422 case NORMAL:
7423 wdc_print_bd_ca_log_normal(hdl, bd_data);
7424 break;
7425 case JSON:
7426 wdc_print_bd_ca_log_json(bd_data);
7427 break;
7428 default:
7429 nvme_show_error("ERROR: WDC: Unknown format - %d", fmt)nvme_show_message(1, "ERROR: WDC: Unknown format - %d", fmt);
7430 return -1;
7431 }
7432 return 0;
7433}
7434
7435static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt)
7436{
7437 if (!perf) {
7438 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7439 return -1;
7440 }
7441 switch (fmt) {
7442 case NORMAL:
7443 wdc_print_d0_log_normal(perf);
7444 break;
7445 case JSON:
7446 wdc_print_d0_log_json(perf);
7447 break;
7448 }
7449 return 0;
7450}
7451
7452static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt,
7453 __u32 cust_id, __u32 vendor_id,
7454 __u32 device_id)
7455{
7456 if (!data) {
7457 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"
)
;
7458 return -1;
7459 }
7460
7461 switch (fmt) {
7462 case NORMAL:
7463 wdc_print_fw_act_history_log_normal(data, num_entries, cust_id,
7464 vendor_id, device_id);
7465 break;
7466 case JSON:
7467 wdc_print_fw_act_history_log_json(data, num_entries, cust_id,
7468 vendor_id, device_id);
7469 break;
7470 }
7471 return 0;
7472}
7473
7474static int wdc_get_ca_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7475{
7476 uint32_t read_device_id = 0, read_vendor_id;
7477 struct wdc_ssd_ca_perf_stats *perf;
7478 nvme_print_flags_t fmt;
7479 __u32 cust_id;
7480 __u8 *data;
7481 int ret;
7482
7483 if (!wdc_check_device(ctx, hdl))
7484 return -1;
7485 ret = validate_output_format(format, &fmt);
7486 if (ret < 0) {
7487 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7488 return ret;
7489 }
7490
7491 /* verify the 0xCA log page is supported */
7492 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7493 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
7494 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
7495 return -1;
7496 }
7497
7498 /* get the FW customer id */
7499 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7500 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7501 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7502 return -1;
7503 }
7504
7505 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7506 if (ret) {
7507 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
7508 return ret;
7509 }
7510
7511 switch (read_device_id) {
7512 case WDC_NVME_SN200_DEV_ID0x0023:
7513 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7514 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7515 if (!data) {
7516 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7517 return -1;
7518 }
7519
7520 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7521
7522 ret = nvme_get_log_simple(hdl,
7523 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7524 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7525 if (strcmp(format, "json"))
7526 nvme_show_status(ret);
7527
7528 if (!ret) {
7529 /* parse the data */
7530 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7531 ret = wdc_print_fb_ca_log(perf, fmt);
7532 } else {
7533 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"
)
;
7534 ret = -1;
7535 }
7536 } else {
7537
7538 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)
;
7539 return -1;
7540 }
7541 break;
7542 case WDC_NVME_SN640_DEV_ID0x2400:
7543 case WDC_NVME_SN640_DEV_ID_10x2401:
7544 case WDC_NVME_SN640_DEV_ID_20x2402:
7545 case WDC_NVME_SN640_DEV_ID_30x2404:
7546 case WDC_NVME_SN840_DEV_ID0x2300:
7547 case WDC_NVME_SN840_DEV_ID_10x2500:
7548 case WDC_NVME_SN860_DEV_ID0x2730:
7549 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7550 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7551 if (!data) {
7552 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7553 return -1;
7554 }
7555
7556 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7557
7558 ret = nvme_get_log_simple(hdl,
7559 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7560 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7561 if (strcmp(format, "json"))
7562 nvme_show_status(ret);
7563
7564 if (!ret) {
7565 /* parse the data */
7566 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7567 ret = wdc_print_fb_ca_log(perf, fmt);
7568 } else {
7569 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"
)
;
7570 ret = -1;
7571 }
7572 } else if ((cust_id == WDC_CUSTOMER_ID_GN0x0001) || (cust_id == WDC_CUSTOMER_ID_GD0x0101) ||
7573 (cust_id == WDC_CUSTOMER_ID_BD0x1009)) {
7574 data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7575 if (!data) {
7576 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7577 return -1;
7578 }
7579
7580 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7581 ret = nvme_get_log_simple(hdl,
7582 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7583 data, WDC_BD_CA_LOG_BUF_LEN0xA0);
7584 if (strcmp(format, "json"))
7585 nvme_show_status(ret);
7586
7587 if (!ret) {
7588 /* parse the data */
7589 ret = wdc_print_bd_ca_log(hdl, data, fmt);
7590 } else {
7591 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"
)
;
7592 ret = -1;
7593 }
7594 } else {
7595 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)
;
7596 return -1;
7597 }
7598 break;
7599 default:
7600 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"
)
;
7601 return -1;
7602 }
7603
7604 free(data);
7605 return ret;
7606}
7607
7608static int wdc_get_c1_log_page(struct libnvme_global_ctx *ctx,
7609 struct libnvme_transport_handle *hdl, char *format,
7610 uint8_t interval)
7611{
7612 struct wdc_log_page_subpage_header *sph;
7613 struct wdc_ssd_perf_stats *perf;
7614 struct wdc_log_page_header *l;
7615 nvme_print_flags_t fmt;
7616 int total_subpages;
7617 int skip_cnt = 4;
7618 __u8 *data;
7619 __u8 *p;
7620 int i;
7621 int ret;
7622
7623 if (!wdc_check_device(ctx, hdl))
7624 return -1;
7625
7626 ret = validate_output_format(format, &fmt);
7627 if (ret < 0) {
7628 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7629 return ret;
7630 }
7631
7632 if (interval < 1 || interval > 15) {
7633 nvme_show_error("ERROR: WDC: interval out of range [1-15]")nvme_show_message(1, "ERROR: WDC: interval out of range [1-15]"
)
;
7634 return -1;
7635 }
7636
7637 data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7638 if (!data) {
7639 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7640 return -1;
7641 }
7642 memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7643
7644 ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE0xC1,
7645 data, WDC_ADD_LOG_BUF_LEN0x4000);
7646 if (strcmp(format, "json"))
7647 nvme_show_status(ret);
7648 if (!ret) {
7649 l = (struct wdc_log_page_header *)data;
7650 total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F - 1;
7651 for (i = 0, p = data + skip_cnt; i < total_subpages; i++, p += skip_cnt) {
7652 sph = (struct wdc_log_page_subpage_header *)p;
7653 if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37) {
7654 if (sph->pcset == interval) {
7655 perf = (struct wdc_ssd_perf_stats *)(p + 4);
7656 ret = wdc_print_log(perf, fmt);
7657 break;
7658 }
7659 }
7660 skip_cnt = le16_to_cpu(sph->subpage_length) + 4;
7661 }
7662 if (ret)
7663 nvme_show_error("ERROR: WDC: Unable to read data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read data from buffer"
)
;
7664 }
7665 free(data);
7666 return ret;
7667}
7668
7669static int wdc_get_c3_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7670{
7671 struct wdc_ssd_latency_monitor_log *log_data;
7672 nvme_print_flags_t fmt;
7673 __u8 *data;
7674 int ret;
7675 int i;
7676
7677 if (!wdc_check_device(ctx, hdl))
7678 return -1;
7679
7680 ret = validate_output_format(format, &fmt);
7681 if (ret < 0) {
7682 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7683 return ret;
7684 }
7685
7686 data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7687 if (!data) {
7688 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7689 return -1;
7690 }
7691 memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7692
7693 ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID0xC3,
7694 data, WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7695
7696 if (strcmp(format, "json"))
7697 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)
;
7698
7699 if (!ret) {
7700 log_data = (struct wdc_ssd_latency_monitor_log *)data;
7701
7702 /* check log page version */
7703 if (log_data->log_page_version != WDC_LATENCY_MON_VERSION0x0001) {
7704 nvme_show_error("ERROR: WDC: invalid latency monitor version")nvme_show_message(1, "ERROR: WDC: invalid latency monitor version"
)
;
7705 ret = -1;
7706 goto out;
7707 }
7708
7709 /* check log page guid */
7710 /* Verify GUID matches */
7711 for (i = 0; i < 16; i++) {
7712 if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) {
7713 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"
)
;
7714 int j;
7715
7716 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7717 for (j = 0; j < 16; j++)
7718 nvme_show_error("%x", wdc_lat_mon_guid[j])nvme_show_message(1, "%x", wdc_lat_mon_guid[j]);
7719 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7720 for (j = 0; j < 16; j++)
7721 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7722 nvme_show_error("")nvme_show_message(1, "");
7723
7724 ret = -1;
7725 goto out;
7726 }
7727 }
7728
7729 /* parse the data */
7730 wdc_print_latency_monitor_log(hdl, log_data, fmt);
7731 } else {
7732 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"
)
;
7733 }
7734
7735out:
7736 free(data);
7737 return ret;
7738
7739}
7740
7741static int wdc_get_ocp_c1_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7742{
7743 struct wdc_ocp_c1_error_recovery_log *log_data;
7744 nvme_print_flags_t fmt;
7745 __u8 *data;
7746 int ret;
7747 int i;
7748
7749 if (!wdc_check_device(ctx, hdl))
7750 return -1;
7751
7752 ret = validate_output_format(format, &fmt);
7753 if (ret < 0) {
7754 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7755 return ret;
7756 }
7757
7758 data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7759 if (!data) {
7760 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7761 return -1;
7762 }
7763 memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7764
7765 ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID0xC1,
7766 data, WDC_ERROR_REC_LOG_BUF_LEN512);
7767
7768 if (strcmp(format, "json"))
7769 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)
;
7770
7771 if (!ret) {
7772 log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
7773
7774 /* check log page version */
7775 if ((log_data->log_page_version < 1) ||
7776 (log_data->log_page_version > 3)) {
7777 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)
7778 log_data->log_page_version)nvme_show_message(1, "ERROR: WDC: invalid error recovery log version - %d"
, log_data->log_page_version)
;
7779 ret = -1;
7780 goto out;
7781 }
7782
7783 /* Verify GUID matches */
7784 for (i = 0; i < WDC_OCP_C1_GUID_LENGTH16; i++) {
7785 if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
7786 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"
)
;
7787 int j;
7788
7789 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7790 for (j = 0; j < 16; j++)
7791 nvme_show_error("%x", wdc_ocp_c1_guid[j])nvme_show_message(1, "%x", wdc_ocp_c1_guid[j]);
7792 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7793 for (j = 0; j < 16; j++)
7794 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7795 nvme_show_error("")nvme_show_message(1, "");
7796
7797 ret = -1;
7798 goto out;
7799 }
7800 }
7801
7802 /* parse the data */
7803 wdc_print_error_rec_log(log_data, fmt);
7804 } else {
7805 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"
)
;
7806 }
7807
7808out:
7809 free(data);
7810 return ret;
7811}
7812
7813static int wdc_get_ocp_c4_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7814{
7815 struct wdc_ocp_C4_dev_cap_log *log_data;
7816 nvme_print_flags_t fmt;
7817 __u8 *data;
7818 int ret;
7819 int i;
7820
7821 if (!wdc_check_device(ctx, hdl))
7822 return -1;
7823
7824 ret = validate_output_format(format, &fmt);
7825 if (ret < 0) {
7826 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7827 return ret;
7828 }
7829
7830 data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7831 if (!data) {
7832 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7833 return -1;
7834 }
7835 memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7836
7837 ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID0xC4,
7838 data, WDC_DEV_CAP_LOG_BUF_LEN4096);
7839
7840 if (strcmp(format, "json"))
7841 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)
;
7842
7843 if (!ret) {
7844 log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
7845
7846 /* check log page version */
7847 if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION0001) {
7848 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)
;
7849 ret = -1;
7850 goto out;
7851 }
7852
7853 /* Verify GUID matches */
7854 for (i = 0; i < WDC_OCP_C4_GUID_LENGTH16; i++) {
7855 if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
7856 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"
)
;
7857 int j;
7858
7859 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7860 for (j = 0; j < 16; j++)
7861 nvme_show_error("%x", wdc_ocp_c4_guid[j])nvme_show_message(1, "%x", wdc_ocp_c4_guid[j]);
7862 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7863 for (j = 0; j < 16; j++)
7864 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7865 nvme_show_error("")nvme_show_message(1, "");
7866
7867 ret = -1;
7868 goto out;
7869 }
7870 }
7871
7872 /* parse the data */
7873 wdc_print_dev_cap_log(log_data, fmt);
7874 } else {
7875 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"
)
;
7876 }
7877
7878out:
7879 free(data);
7880 return ret;
7881}
7882
7883static int wdc_get_ocp_c5_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7884{
7885 struct wdc_ocp_C5_unsupported_reqs *log_data;
7886 nvme_print_flags_t fmt;
7887 int ret;
7888 __u8 *data;
7889 int i;
7890
7891 if (!wdc_check_device(ctx, hdl))
7892 return -1;
7893
7894 ret = validate_output_format(format, &fmt);
7895 if (ret < 0) {
7896 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7897 return ret;
7898 }
7899
7900 data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7901 if (!data) {
7902 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7903 return -1;
7904 }
7905 memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7906
7907 ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID0xC5,
7908 data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7909
7910 if (strcmp(format, "json"))
7911 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)
;
7912
7913 if (!ret) {
7914 log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
7915
7916 /* check log page version */
7917 if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION0001) {
7918 nvme_show_error("ERROR: WDC: invalid 0xC5 log page version")nvme_show_message(1, "ERROR: WDC: invalid 0xC5 log page version"
)
;
7919 nvme_show_error("ERROR: WDC: log page version: %d",nvme_show_message(1, "ERROR: WDC: log page version: %d", log_data
->log_page_version)
7920 log_data->log_page_version)nvme_show_message(1, "ERROR: WDC: log page version: %d", log_data
->log_page_version)
;
7921 ret = -1;
7922 goto out;
7923 }
7924
7925 /* Verify GUID matches */
7926 for (i = 0; i < WDC_OCP_C5_GUID_LENGTH16; i++) {
7927 if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
7928 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"
)
;
7929 int j;
7930
7931 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7932 for (j = 0; j < 16; j++)
7933 nvme_show_error("%x", wdc_ocp_c5_guid[j])nvme_show_message(1, "%x", wdc_ocp_c5_guid[j]);
7934 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7935 for (j = 0; j < 16; j++)
7936 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7937 nvme_show_error("")nvme_show_message(1, "");
7938
7939 ret = -1;
7940 goto out;
7941 }
7942 }
7943
7944 /* parse the data */
7945 wdc_print_unsupported_reqs_log(log_data, fmt);
7946 } else {
7947 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"
)
;
7948 }
7949
7950out:
7951 free(data);
7952 return ret;
7953}
7954
7955static int wdc_get_d0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7956{
7957 struct wdc_ssd_d0_smart_log *perf;
7958 nvme_print_flags_t fmt;
7959 int ret = 0;
7960 __u8 *data;
7961
7962 if (!wdc_check_device(ctx, hdl))
7963 return -1;
7964
7965 ret = validate_output_format(format, &fmt);
7966 if (ret < 0) {
7967 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7968 return ret;
7969 }
7970
7971 /* verify the 0xD0 log page is supported */
7972 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7973 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == false0) {
7974 nvme_show_error("ERROR: WDC: 0xD0 Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xD0 Log Page not supported"
)
;
7975 return -1;
7976 }
7977
7978 data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7979 if (!data) {
7980 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7981 return -1;
7982 }
7983 memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7984
7985 ret = nvme_get_log_simple(hdl,
7986 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0,
7987 data, WDC_NVME_VU_SMART_LOG_LEN0x200);
7988 if (strcmp(format, "json"))
7989 nvme_show_status(ret);
7990
7991 if (!ret) {
7992 /* parse the data */
7993 perf = (struct wdc_ssd_d0_smart_log *)(data);
7994 ret = wdc_print_d0_log(perf, fmt);
7995 } else {
7996 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"
)
;
7997 ret = -1;
7998 }
7999
8000 free(data);
8001 return ret;
8002}
8003
8004static long double le_to_float(__u8 *data, int byte_len)
8005{
8006 long double result = 0;
8007 int i;
8008
8009 for (i = 0; i < byte_len; i++) {
8010 result *= 256;
8011 result += data[15 - i];
8012 }
8013
8014 return result;
8015}
8016
8017static void stringify_log_page_guid(__u8 *guid, char *buf)
8018{
8019 char *ptr = buf;
8020 int i;
8021
8022 memset(buf, 0, sizeof(char) * (2 * 16 + 1));
8023
8024 ptr += sprintf(ptr, "0x");
8025 for (i = 0; i < 16; i++)
8026 ptr += sprintf(ptr, "%x", guid[15 - i]);
8027}
8028
8029static const char *const cloud_smart_log_thermal_status[] = {
8030 [0x00] = "unthrottled",
8031 [0x01] = "first_level",
8032 [0x02] = "second_level",
8033 [0x03] = "third_level",
8034};
8035
8036static const char *stringify_cloud_smart_log_thermal_status(__u8 status)
8037{
8038 if (status < ARRAY_SIZE(cloud_smart_log_thermal_status)(sizeof(cloud_smart_log_thermal_status) / sizeof((cloud_smart_log_thermal_status
)[0]) + 0)
&&
8039 cloud_smart_log_thermal_status[status])
8040 return cloud_smart_log_thermal_status[status];
8041 return "unrecognized";
8042}
8043
8044static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log)
8045{
8046 struct json_object *root;
8047 struct json_object *bad_user_nand_blocks;
8048 struct json_object *bad_system_nand_blocks;
8049 struct json_object *e2e_correction_counts;
8050 struct json_object *user_data_erase_counts;
8051 struct json_object *thermal_status;
8052 struct json_object *dssd_specific_ver;
8053 char buf[2 * sizeof(log->log_page_guid) + 3];
8054 char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1];
8055 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8056
8057 bad_user_nand_blocks = json_create_object()json_object_new_object();
8058 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)))
8059 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)))
;
8060 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)))
8061 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)))
;
8062
8063 bad_system_nand_blocks = json_create_object()json_object_new_object();
8064 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)))
8065 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)))
;
8066 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)))
8067 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)))
;
8068
8069 e2e_correction_counts = json_create_object()json_object_new_object();
8070 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)))
8071 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)))
;
8072 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)))
8073 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)))
;
8074
8075 user_data_erase_counts = json_create_object()json_object_new_object();
8076 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)))
8077 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)))
;
8078 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)))
8079 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)))
;
8080
8081 thermal_status = json_create_object()json_object_new_object();
8082 json_object_add_value_string(thermal_status, "current_status",
8083 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8084 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))
8085 log->thermal_status.num_events)json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
;
8086
8087 dssd_specific_ver = json_create_object()json_object_new_object();
8088 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))
8089 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))
;
8090 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)))
8091 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)))
;
8092 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)))
8093 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)))
;
8094 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))
8095 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))
;
8096
8097 root = json_create_object()json_object_new_object();
8098 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)))
8099 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)))
;
8100 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)))
8101 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)))
;
8102 json_object_add_value_object(root, "bad_user_nand_blocks",json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
8103 bad_user_nand_blocks)json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
;
8104 json_object_add_value_object(root, "bad_system_nand_blocks",json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
8105 bad_system_nand_blocks)json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
;
8106 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)))
8107 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)))
;
8108 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
)))
8109 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
)))
;
8110 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)))
8111 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)))
;
8112 json_object_add_value_object(root, "e2e_correction_counts",json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
8113 e2e_correction_counts)json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
;
8114 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))
8115 log->system_data_percent_used)json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
;
8116 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)))
8117 le64_to_cpu(log->refresh_counts))json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
;
8118 json_object_add_value_object(root, "user_data_erase_counts",json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
8119 user_data_erase_counts)json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
;
8120 json_object_add_value_object(root, "thermal_status", thermal_status)json_object_object_add(root, "thermal_status", thermal_status
)
;
8121 if (smart_log_ver >= 3)
8122 json_object_add_value_object(root, "dssd_specific_ver",json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
8123 dssd_specific_ver)json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
;
8124 else
8125 json_free_object(dssd_specific_ver)json_object_put(dssd_specific_ver);
8126 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)))
8127 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)))
;
8128 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)))
8129 le32_to_cpu(log->incomplete_shutdowns))json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
;
8130 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))
8131 log->percent_free_blocks)json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
;
8132 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)))
8133 le16_to_cpu(log->capacitor_health))json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
;
8134 if (smart_log_ver >= 3) {
8135 if (smart_log_ver >= 4) {
8136 sprintf(buf, "%c", log->nvme_base_errata_ver);
8137 json_object_add_value_string(root, "nvme_base_errata_version", buf);
8138 sprintf(buf, "%c", log->nvme_cmd_set_errata_ver);
8139 json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf);
8140 } else {
8141 sprintf(buf, "%c", log->nvme_base_errata_ver);
8142 json_object_add_value_string(root, "nvme_errata_version", buf);
8143 }
8144 }
8145
8146 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)))
8147 le64_to_cpu(log->unaligned_io))json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
;
8148 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)))
8149 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)))
;
8150 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)))
8151 le64_to_cpu(log->total_nuse))json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
;
8152 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)))
8153 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)))
;
8154 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)))
8155 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)))
;
8156 if (smart_log_ver >= 3) {
8157 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)))
8158 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)))
;
8159 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)))
8160 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)))
;
8161 if (smart_log_ver >= 4) {
8162 snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s",
8163 (int)sizeof(log->lowest_permitted_fw_rev),
8164 log->lowest_permitted_fw_rev);
8165 json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr);
8166 } else
8167 json_object_add_value_uint128(root, "hardware_revision",json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu(log->hardware_revision)))
8168 le128_to_cpu(log->hardware_revision))json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu(log->hardware_revision)))
;
8169 }
8170 json_object_add_value_uint(root, "log_page_version",json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
8171 smart_log_ver)json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
;
8172 stringify_log_page_guid(log->log_page_guid, buf);
8173 json_object_add_value_string(root, "log_page_guid", buf);
8174
8175 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8176 printf("\n");
8177 json_free_object(root)json_object_put(root);
8178}
8179
8180static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
8181 struct libnvme_transport_handle *hdl)
8182{
8183 char buf[2 * sizeof(log->log_page_guid) + 3];
8184 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8185
8186 printf("SMART Cloud Attributes for NVMe device : %s\n",
8187 libnvme_transport_handle_get_name(hdl));
8188 printf("Physical Media Units Written : %'.0Lf\n",
8189 le_to_float(log->physical_media_units_written, 16));
8190 printf("Physical Media Units Read : %'.0Lf\n",
8191 le_to_float(log->physical_media_units_read, 16));
8192 printf("Bad User NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8193 le16_to_cpu(log->bad_user_nand_blocks.normalized));
8194 printf("Bad User NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8195 le64_to_cpu(log->bad_user_nand_blocks.raw));
8196 printf("Bad System NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8197 le16_to_cpu(log->bad_system_nand_blocks.normalized));
8198 printf("Bad System NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8199 le64_to_cpu(log->bad_system_nand_blocks.raw));
8200 printf("XOR Recovery Count : %" PRIu64"l" "u" "\n",
8201 le64_to_cpu(log->xor_recovery_count));
8202 printf("Uncorrectable Read Error Count : %" PRIu64"l" "u" "\n",
8203 le64_to_cpu(log->uncorrectable_read_error_count));
8204 printf("Soft ECC Error Count : %" PRIu64"l" "u" "\n",
8205 le64_to_cpu(log->soft_ecc_error_count));
8206 printf("End to End Correction Counts (Corrected) : %" PRIu32"u" "\n",
8207 le32_to_cpu(log->e2e_correction_counts.corrected));
8208 printf("End to End Correction Counts (Detected) : %" PRIu32"u" "\n",
8209 le32_to_cpu(log->e2e_correction_counts.detected));
8210 printf("System Data %% Used : %" PRIu8"hhu" "%%\n",
8211 log->system_data_percent_used);
8212 printf("Refresh Counts : %" PRIu64"l" "u" "\n",
8213 le64_to_cpu(log->refresh_counts));
8214 printf("User Data Erase Counts (Minimum) : %" PRIu32"u" "\n",
8215 le32_to_cpu(log->user_data_erase_counts.minimum));
8216 printf("User Data Erase Counts (Maximum) : %" PRIu32"u" "\n",
8217 le32_to_cpu(log->user_data_erase_counts.maximum));
8218 printf("Thermal Throttling Status (Current Status) : %s\n",
8219 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8220 printf("Thermal Throttling Status (Number of Events) : %" PRIu8"hhu" "\n",
8221 log->thermal_status.num_events);
8222 if (smart_log_ver >= 3) {
8223 printf("NVMe Major Version : %" PRIu8"hhu" "\n",
8224 log->dssd_specific_ver.major_ver);
8225 printf(" Minor Version : %" PRIu16"hu" "\n",
8226 le16_to_cpu(log->dssd_specific_ver.minor_ver));
8227 printf(" Point Version : %" PRIu16"hu" "\n",
8228 le16_to_cpu(log->dssd_specific_ver.point_ver));
8229 printf(" Errata Version : %" PRIu8"hhu" "\n",
8230 log->dssd_specific_ver.errata_ver);
8231 }
8232 printf("PCIe Correctable Error Count : %" PRIu64"l" "u" "\n",
8233 le64_to_cpu(log->pcie_correctable_error_count));
8234 printf("Incomplete Shutdowns : %" PRIu32"u" "\n",
8235 le32_to_cpu(log->incomplete_shutdowns));
8236 printf("%% Free Blocks : %" PRIu8"hhu" "%%\n",
8237 log->percent_free_blocks);
8238 printf("Capacitor Health : %" PRIu16"hu" "%%\n",
8239 le16_to_cpu(log->capacitor_health));
8240 if (smart_log_ver >= 3) {
8241 if (smart_log_ver >= 4) {
8242 printf("NVMe Base Errata Version : %c\n",
8243 log->nvme_base_errata_ver);
8244 printf("NVMe Command Set Errata Version : %c\n",
8245 log->nvme_cmd_set_errata_ver);
8246 } else {
8247 printf("NVMe Errata Version : %c\n",
8248 log->nvme_base_errata_ver);
8249 }
8250 }
8251 printf("Unaligned IO : %" PRIu64"l" "u" "\n",
8252 le64_to_cpu(log->unaligned_io));
8253 printf("Security Version Number : %" PRIu64"l" "u" "\n",
8254 le64_to_cpu(log->security_version_number));
8255 printf("Total NUSE : %" PRIu64"l" "u" "\n",
8256 le64_to_cpu(log->total_nuse));
8257 printf("PLP Start Count : %'.0Lf\n",
8258 le_to_float(log->plp_start_count, 16));
8259 printf("Endurance Estimate : %'.0Lf\n",
8260 le_to_float(log->endurance_estimate, 16));
8261 if (smart_log_ver >= 3) {
8262 printf("PCIe Link Retraining Count : %" PRIu64"l" "u" "\n",
8263 le64_to_cpu(log->pcie_link_retraining_cnt));
8264 printf("Power State Change Count : %" PRIu64"l" "u" "\n",
8265 le64_to_cpu(log->power_state_change_cnt));
8266 if (smart_log_ver >= 4)
8267 printf("Lowest Permitted FW Revision : %-.*s\n",
8268 (int)sizeof(log->lowest_permitted_fw_rev),
8269 log->lowest_permitted_fw_rev);
8270 else
8271 printf("Hardware Revision : %s\n",
8272 uint128_t_to_string(le128_to_cpu(log->hardware_revision)));
8273 }
8274 printf("Log Page Version : %" PRIu16"hu" "\n",
8275 smart_log_ver);
8276 stringify_log_page_guid(log->log_page_guid, buf);
8277 printf("Log Page GUID : %s\n", buf);
8278 printf("\n\n");
8279}
8280
8281static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd,
8282 struct plugin *plugin)
8283{
8284 const char *desc = "Retrieve additional performance statistics.";
8285 const char *interval = "Interval to read the statistics from [1, 15].";
8286 const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
8287 const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
8288 const char *namespace_id = "desired namespace id";
8289 nvme_print_flags_t fmt;
8290 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8291 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8292 int ret = 0;
8293 int uuid_index = 0;
8294 int page_mask = 0, num, i;
8295 int log_page_list[16];
8296 __u64 capabilities = 0;
8297 __u32 device_id, read_vendor_id;
8298
8299 struct config {
8300 uint8_t interval;
8301 __u8 log_page_version;
8302 char *log_page_mask;
8303 __u32 namespace_id;
8304 };
8305
8306 struct config cfg = {
8307 .interval = 14,
8308 .log_page_version = 0,
8309 .log_page_mask = "",
8310 .namespace_id = NVME_NSID_ALL,
8311 };
8312
8313 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 informational output", 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) } }
8314 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 informational output", 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) } }
8315 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 informational output", 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) } }
8316 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 informational output", 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) } }
8317 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 informational output", 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) } }
;
8318
8319 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8320 if (ret)
8321 return ret;
8322
8323 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8324 if (ret)
8325 return ret;
8326
8327 if (!cfg.log_page_version) {
8328 uuid_index = 0;
8329 } else if (cfg.log_page_version == 1) {
8330 uuid_index = 1;
8331 } else {
8332 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"
)
;
8333 ret = -1;
8334 goto out;
8335 }
8336
8337 num = shr_parse_csv_int(cfg.log_page_mask, log_page_list, 16);
8338
8339 if (num == -1) {
8340 nvme_show_error("ERROR: WDC: log page list is malformed")nvme_show_message(1, "ERROR: WDC: log page list is malformed"
)
;
8341 ret = -1;
8342 goto out;
8343 }
8344
8345 if (!num) {
8346 page_mask |= WDC_ALL_PAGE_MASK0xFFFF;
8347 } else {
8348 for (i = 0; i < num; i++) {
8349 if (log_page_list[i] == 0xc0)
8350 page_mask |= WDC_C0_PAGE_MASK0x0001;
8351 if (log_page_list[i] == 0xc1)
8352 page_mask |= WDC_C1_PAGE_MASK0x0002;
8353 if (log_page_list[i] == 0xca)
8354 page_mask |= WDC_CA_PAGE_MASK0x0004;
8355 if (log_page_list[i] == 0xd0)
8356 page_mask |= WDC_D0_PAGE_MASK0x0008;
8357 }
8358 }
8359
8360 if (!page_mask)
8361 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)
;
8362
8363 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8364
8365 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8366 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8367 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8368 ret = -1;
8369 goto out;
8370 }
8371
8372 if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) == WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) &&
8373 (page_mask & WDC_C0_PAGE_MASK0x0001)) {
8374 /* Get 0xC0 log page if possible. */
8375 if (!wdc_is_sn861(device_id)) {
8376 ret = wdc_get_c0_log_page(ctx, hdl,
8377 nvme_args.output_format,
8378 uuid_index, cfg.namespace_id);
8379 if (ret)
8380 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8381 "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)
8382 ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
;
8383 } else {
8384 ret = validate_output_format(nvme_args.output_format,
8385 &fmt);
8386 if (ret < 0) {
8387 nvme_show_error("Invalid output format: %s",nvme_show_message(1, "Invalid output format: %s", nvme_args.output_format
)
8388 nvme_args.output_format)nvme_show_message(1, "Invalid output format: %s", nvme_args.output_format
)
;
8389 goto out;
8390 }
8391
8392 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
8393 0,
8394 NVME_NSID_ALL,
8395 fmt);
8396 }
8397 }
8398 if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) == (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) &&
8399 (page_mask & WDC_CA_PAGE_MASK0x0004) &&
8400 (!wdc_is_sn861(device_id))) {
8401 /* Get the CA Log Page */
8402 ret = wdc_get_ca_log_page(ctx, hdl, nvme_args.output_format);
8403 if (ret)
8404 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)
;
8405 }
8406 if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) == WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) &&
8407 (page_mask & WDC_C1_PAGE_MASK0x0002)) {
8408 /* Get the C1 Log Page */
8409 ret = wdc_get_c1_log_page(ctx, hdl, nvme_args.output_format,
8410 cfg.interval);
8411 if (ret)
8412 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)
;
8413 }
8414 if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) == WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) &&
8415 (page_mask & WDC_D0_PAGE_MASK0x0008)) {
8416 /* Get the D0 Log Page */
8417 ret = wdc_get_d0_log_page(ctx, hdl, nvme_args.output_format);
8418 if (ret)
8419 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)
;
8420 }
8421
8422out:
8423 return ret;
8424}
8425
8426static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd,
8427 struct plugin *plugin)
8428{
8429 const char *desc = "Retrieve customer unique smart log statistics.";
8430 const char *uuid_index = "The uuid index to select the correct log page implementation.";
8431 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8432 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8433 struct libnvme_passthru_cmd cmd;
8434 int ret = 0;
8435 __u64 capabilities = 0;
8436 uint32_t read_device_id = 0, read_vendor_id;
8437 nvme_print_flags_t fmt;
8438 __u8 *data;
8439
8440 struct config {
8441 int uuid_index;
8442 };
8443
8444 struct config cfg = {
8445 .uuid_index = 0,
8446 };
8447
8448 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 informational output", 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) } }
8449 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 informational output", 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) } }
;
8450
8451 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8452 if (ret)
8453 return ret;
8454
8455 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8456 if (ret)
8457 return ret;
8458
8459 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8460 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8461 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8462 ret = -1;
8463 goto out;
8464 }
8465
8466 if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) == WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) {
8467 if (!wdc_check_device(ctx, hdl))
8468 return -1;
8469
8470 ret = validate_output_format(nvme_args.output_format, &fmt);
8471
8472 if (ret < 0) {
8473 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8474 return ret;
8475 }
8476
8477 /* verify the 0xCA log page is supported */
8478 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8479 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
8480 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
8481 return -1;
8482 }
8483
8484 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8485 if (ret) {
8486 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
8487 return ret;
8488 }
8489
8490 switch (read_device_id) {
8491 case WDC_NVME_SN861_DEV_ID0x2750:
8492 case WDC_NVME_SN861_DEV_ID_10x2751:
8493 data = (__u8 *)malloc(WDC_BD_CA_LOG_BUF_LEN0xA0);
8494 if (!data) {
8495 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8496 ret = -1;
8497 break;
8498 }
8499
8500 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
8501
8502 /* Get the CA Log Page */
8503 nvme_init_get_log(&cmd, NVME_NSID_ALL,
8504 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0,
8505 NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN0xA0);
8506 cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8507 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8508 NVME_LOG_CDW14_UUID_MASK)(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
8509 ret = libnvme_get_log(hdl, &cmd, false0,
8510 NVME_LOG_PAGE_PDU_SIZE4096);
8511
8512 if (strcmp(nvme_args.output_format, "json"))
8513 nvme_show_status(ret);
8514
8515 if (!ret) {
8516 /* parse the data */
8517 ret = wdc_print_bd_ca_log(hdl, data, fmt);
8518 } else {
8519 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"
)
;
8520 ret = -1;
8521 }
8522
8523 free(data);
8524 break;
8525 default:
8526 nvme_show_error("ERROR: WDC: Command not supported on this device")nvme_show_message(1, "ERROR: WDC: Command not supported on this device"
)
;
8527 ret = -1;
8528 }
8529 } else {
8530 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"
)
;
8531 ret = -1;
8532 }
8533
8534out:
8535 return ret;
8536}
8537
8538static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd,
8539 struct plugin *plugin)
8540{
8541 const char *desc = "Retrieve Cloud Log Smart/Health Information";
8542 const char *namespace_id = "desired namespace id";
8543 nvme_print_flags_t fmt;
8544 __u64 capabilities = 0;
8545 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8546 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8547 int ret;
8548 __u8 *data;
8549
8550 struct config {
8551 char *output_format;
8552 __u32 namespace_id;
8553 };
8554
8555 struct config cfg = {
8556 .output_format = "normal",
8557 .namespace_id = NVME_NSID_ALL,
8558 };
8559
8560 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 informational output", 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) } }
8561 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 informational output", 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) } }
;
8562
8563 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8564 if (ret)
8565 return ret;
8566
8567 cfg.output_format = nvme_args.output_format;
8568
8569 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8570 if (ret)
8571 return ret;
8572
8573 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8574
8575 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
8576 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8577 ret = -1;
8578 goto out;
8579 }
8580
8581 data = NULL((void*)0);
8582 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8583 cfg.namespace_id);
8584
8585 if (strcmp(cfg.output_format, "json"))
8586 nvme_show_status(ret);
8587
8588 if (!ret) {
8589 ret = validate_output_format(cfg.output_format, &fmt);
8590 if (ret < 0) {
8591 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8592 } else {
8593 /* parse the data */
8594 wdc_print_ext_smart_cloud_log(data, fmt);
8595 }
8596 } else {
8597 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"
)
;
8598 ret = -1;
8599 }
8600
8601 free(data);
8602
8603out:
8604 return ret;
8605}
8606
8607static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd,
8608 struct plugin *plugin)
8609{
8610 const char *desc = "Retrieve Hardware Revision Log Information";
8611 const char *namespace_id = "desired namespace id";
8612 nvme_print_flags_t fmt;
8613 __u64 capabilities = 0;
8614 struct libnvme_transport_handle *hdl;
8615 int ret;
8616 __u8 *data = NULL((void*)0);
8617 struct libnvme_global_ctx *ctx;
8618
8619 struct config {
8620 char *output_format;
8621 __u32 namespace_id;
8622 };
8623
8624 struct config cfg = {
8625 .output_format = "normal",
8626 .namespace_id = NVME_NSID_ALL,
8627 };
8628
8629 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 informational output", 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) } }
8630 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 informational output", 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) } }
;
8631
8632 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8633 if (ret)
8634 return ret;
8635
8636 cfg.output_format = nvme_args.output_format;
8637
8638 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8639 if (ret)
8640 return ret;
8641
8642 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8643
8644 if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000)) {
8645 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8646 ret = -1;
8647 goto out;
8648 }
8649
8650 ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id);
8651
8652 if (strcmp(cfg.output_format, "json"))
8653 nvme_show_status(ret);
8654
8655 if (!ret) {
8656 ret = validate_output_format(cfg.output_format, &fmt);
8657 if (ret < 0) {
8658 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8659 goto free_buf;
8660 }
8661
8662 if (!data) {
8663 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"
)
;
8664 ret = -1;
8665 goto out;
8666 }
8667 switch (fmt) {
8668 case NORMAL:
8669 wdc_print_hw_rev_log_normal(data);
8670 break;
8671 case JSON:
8672 wdc_print_hw_rev_log_json(data);
8673 break;
8674 default:
8675 break;
8676 }
8677 } else {
8678 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"
)
;
8679 ret = -1;
8680 }
8681
8682free_buf:
8683 free(data);
8684
8685out:
8686 return ret;
8687}
8688
8689static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd,
8690 struct plugin *plugin)
8691{
8692 const char *desc = "Retrieve Device Write Amplication Factor";
8693 const char *namespace_id = "desired namespace id";
8694 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8695 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8696 struct nvme_smart_log smart_log;
8697 nvme_print_flags_t fmt;
8698 __u8 *data;
8699 int ret = 0;
8700 __u64 capabilities = 0;
8701 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr;
8702 long double data_units_written = 0,
8703 phys_media_units_written_tlc = 0,
8704 phys_media_units_written_slc = 0;
8705 struct json_object *root = NULL((void*)0);
8706 char tlc_waf_str[32] = { 0 },
8707 slc_waf_str[32] = { 0 };
8708
8709 struct config {
8710 char *output_format;
8711 __u32 namespace_id;
8712 };
8713
8714 struct config cfg = {
8715 .output_format = "normal",
8716 .namespace_id = NVME_NSID_ALL,
8717 };
8718
8719 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 informational output", 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) } }
8720 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 informational output", 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) } }
;
8721
8722 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8723 if (ret)
8724 return ret;
8725
8726 cfg.output_format = nvme_args.output_format;
8727
8728 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8729 if (ret)
8730 return ret;
8731
8732 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8733
8734 if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000)) {
8735 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8736 ret = -1;
8737 goto out;
8738 }
8739
8740 /* get data units written from the smart log page */
8741 ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log);
8742 if (!ret) {
8743 data_units_written = int128_to_double(smart_log.data_units_written);
8744 } else if (ret > 0) {
8745 nvme_show_status(ret);
8746 ret = -1;
8747 goto out;
8748 } else {
8749 nvme_show_error("smart log: %s", libnvme_strerror(errno))nvme_show_message(1, "smart log: %s", libnvme_strerror((*__errno_location
())))
;
8750 ret = -1;
8751 goto out;
8752 }
8753
8754 /* get Physical Media Units Written from extended smart/C0 log page */
8755 data = NULL((void*)0);
8756 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8757 cfg.namespace_id);
8758
8759 if (!ret) {
8760 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
8761 phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
8762 phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
8763
8764 free(data);
8765 } else {
8766 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__)
;
8767 ret = -1;
8768 goto out;
8769 }
8770
8771 if (strcmp(cfg.output_format, "json"))
8772 nvme_show_status(ret);
8773
8774 ret = validate_output_format(cfg.output_format, &fmt);
8775 if (ret < 0) {
8776 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8777 goto out;
8778 }
8779
8780 if (!data_units_written) {
8781 nvme_show_error("ERROR: WDC %s: 0 data units written", __func__)nvme_show_message(1, "ERROR: WDC %s: 0 data units written", __func__
)
;
8782 ret = -1;
8783 goto out;
8784 }
8785
8786 if (fmt == NORMAL) {
8787 printf("Device Write Amplification Factor TLC : %4.2Lf\n",
8788 (phys_media_units_written_tlc/data_units_written));
8789 printf("Device Write Amplification Factor SLC : %4.2Lf\n",
8790 (phys_media_units_written_slc/data_units_written));
8791 } else if (fmt == JSON) {
8792 root = json_create_object()json_object_new_object();
8793 sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written));
8794 sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written));
8795
8796 json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
8797 json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
8798
8799 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8800 printf("\n");
8801
8802 json_free_object(root)json_object_put(root);
8803 }
8804
8805out:
8806 return ret;
8807}
8808
8809static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd,
8810 struct plugin *plugin)
8811{
8812 const char *desc = "Retrieve latency monitor log data.";
8813 __u64 capabilities = 0;
8814 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8815 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8816 int ret = 0;
8817
8818 struct config {
8819 char *output_format;
8820 };
8821
8822 struct config cfg = {
8823 .output_format = "normal",
8824 };
8825
8826 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 informational output", 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) } }
;
8827
8828 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8829 if (ret)
8830 return ret;
8831
8832 cfg.output_format = nvme_args.output_format;
8833
8834 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8835 if (ret)
8836 return ret;
8837 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8838
8839 if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000)) {
8840 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8841 ret = -1;
8842 goto out;
8843 }
8844
8845 ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format);
8846 if (ret)
8847 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)
;
8848
8849out:
8850 return ret;
8851}
8852
8853static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd,
8854 struct plugin *plugin)
8855{
8856 const char *desc = "Retrieve error recovery log data.";
8857 __u64 capabilities = 0;
8858 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8859 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8860 int ret = 0;
8861
8862 struct config {
8863 char *output_format;
8864 };
8865
8866 struct config cfg = {
8867 .output_format = "normal",
8868 };
8869
8870 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 informational output", 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) } }
;
8871
8872 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8873 if (ret)
8874 return ret;
8875
8876 cfg.output_format = nvme_args.output_format;
8877
8878 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8879 if (ret)
8880 return ret;
8881
8882 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8883
8884 if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000)) {
8885 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8886 ret = -1;
8887 goto out;
8888 }
8889
8890 ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format);
8891 if (ret)
8892 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)
;
8893
8894out:
8895 return ret;
8896}
8897
8898static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd,
8899 struct plugin *plugin)
8900{
8901 const char *desc = "Retrieve device capabilities log data.";
8902 __u64 capabilities = 0;
8903 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8904 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8905 int ret = 0;
8906
8907 struct config {
8908 char *output_format;
8909 };
8910
8911 struct config cfg = {
8912 .output_format = "normal",
8913 };
8914
8915 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 informational output", 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) } }
;
8916
8917 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8918 if (ret)
8919 return ret;
8920
8921 cfg.output_format = nvme_args.output_format;
8922
8923 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8924 if (ret)
8925 return ret;
8926
8927 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8928
8929 if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000)) {
8930 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8931 ret = -1;
8932 goto out;
8933 }
8934
8935 ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format);
8936 if (ret)
8937 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)
;
8938
8939out:
8940 return ret;
8941}
8942
8943static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd,
8944 struct plugin *plugin)
8945{
8946 const char *desc = "Retrieve unsupported requirements log data.";
8947 __u64 capabilities = 0;
8948 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8949 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8950 int ret = 0;
8951
8952 struct config {
8953 char *output_format;
8954 };
8955
8956 struct config cfg = {
8957 .output_format = "normal",
8958 };
8959
8960 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 informational output", 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) } }
;
8961
8962 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8963 if (ret)
8964 return ret;
8965
8966 cfg.output_format = nvme_args.output_format;
8967
8968 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8969 if (ret)
8970 return ret;
8971
8972 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8973
8974 if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000)) {
8975 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8976 ret = -1;
8977 goto out;
8978 }
8979
8980 ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format);
8981 if (ret)
8982 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)
;
8983
8984out:
8985 return ret;
8986}
8987
8988static int wdc_do_clear_pcie_correctable_errors(struct libnvme_transport_handle *hdl)
8989{
8990 int ret;
8991 struct libnvme_passthru_cmd admin_cmd;
8992
8993 memset(&admin_cmd, 0, sizeof(admin_cmd));
8994 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6;
8995 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
8996 WDC_NVME_CLEAR_PCIE_CORR_CMD0x22);
8997
8998 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
8999 nvme_show_status(ret);
9000 return ret;
9001}
9002
9003static int wdc_do_clear_pcie_correctable_errors_vuc(struct libnvme_transport_handle *hdl)
9004{
9005 int ret;
9006 struct libnvme_passthru_cmd admin_cmd;
9007
9008 memset(&admin_cmd, 0, sizeof(admin_cmd));
9009 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2;
9010
9011 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9012 nvme_show_status(ret);
9013 return ret;
9014}
9015
9016static int wdc_do_clear_pcie_correctable_errors_fid(struct libnvme_transport_handle *hdl)
9017{
9018 int ret;
9019 __u64 result;
9020 __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
9021
9022 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3, false0,
9023 value, &result);
9024
9025 nvme_show_status(ret);
9026 return ret;
9027}
9028
9029static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
9030 struct plugin *plugin)
9031{
9032 const char *desc = "Clear PCIE Correctable Errors.";
9033 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9034 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9035 __u64 capabilities = 0;
9036 int ret;
9037
9038 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 informational output", 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) } }
;
9039
9040 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9041 if (ret)
9042 return ret;
9043
9044 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9045 if (ret || !wdc_check_device(ctx, hdl))
9046 return -1;
9047
9048 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9049 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
)) {
9050 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9051 ret = -1;
9052 goto out;
9053 }
9054
9055 if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080)
9056 ret = wdc_do_clear_pcie_correctable_errors(hdl);
9057 else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000)
9058 ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl);
9059 else
9060 ret = wdc_do_clear_pcie_correctable_errors_fid(hdl);
9061
9062out:
9063 return ret;
9064}
9065
9066static int wdc_drive_status(int argc, char **argv, struct command *acmd,
9067 struct plugin *plugin)
9068{
9069 const char *desc = "Get Drive Status.";
9070 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9071 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9072 int ret = 0;
9073 int uuid_index;
9074 void *dev_mng_log = NULL((void*)0);
9075 __u32 system_eol_state;
9076 __u32 user_eol_state;
9077 __u32 format_corrupt_reason = 0xFFFFFFFF;
9078 __u32 eol_status;
9079 __u32 assert_status = 0xFFFFFFFF;
9080 __u32 thermal_status = 0xFFFFFFFF;
9081 __u64 capabilities = 0;
9082 struct nvme_id_uuid_list uuid_list;
9083
9084 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 informational output", 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) } }
;
9085
9086 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9087 if (ret)
9088 return ret;
9089
9090 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9091 if (ret)
9092 return ret;
9093
9094 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9095
9096 if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) != WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) {
9097 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9098 ret = -1;
9099 goto out;
9100 }
9101
9102 uuid_index = 0;
9103
9104 /* Find the WDC UUID index */
9105 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
9106 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
9107 /* check for the Sandisk UUID first */
9108 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
9109
9110 if (uuid_index < 0)
9111 /* The Sandisk UUID is not found;
9112 * check for the WDC UUID second.
9113 */
9114 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
9115 }
9116
9117 /* WD UUID not found, use default uuid index - 0 */
9118 if (uuid_index < 0)
9119 uuid_index = 0;
9120
9121 /* verify the 0xC2 Device Manageability log page is supported */
9122 if (wdc_nvme_check_supported_log_page(ctx, hdl,
9123 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
9124 uuid_index) == false0) {
9125 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)
9126 uuid_index)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
;
9127 ret = -1;
9128 goto out;
9129 }
9130
9131 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
9132 nvme_show_error("ERROR: WDC: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not found");
9133 ret = -1;
9134 goto out;
9135 }
9136
9137 /* Get the assert dump present status */
9138 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &assert_status,
9139 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19))
9140 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9141
9142 /* Get the thermal throttling status */
9143 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &thermal_status,
9144 WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18))
9145 nvme_show_error("ERROR: WDC: Get Thermal Throttling Status Failed")nvme_show_message(1, "ERROR: WDC: Get Thermal Throttling Status Failed"
)
;
9146
9147 /* Get EOL status */
9148 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &eol_status,
9149 WDC_C2_USER_EOL_STATUS_ID0x1A)) {
9150 nvme_show_error("ERROR: WDC: Get User EOL Status Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL Status Failed"
)
;
9151 eol_status = cpu_to_le32(-1);
9152 }
9153
9154 /* Get Customer EOL state */
9155 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &user_eol_state,
9156 WDC_C2_USER_EOL_STATE_ID0x1C))
9157 nvme_show_error("ERROR: WDC: Get User EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL State Failed");
9158
9159 /* Get System EOL state*/
9160 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &system_eol_state,
9161 WDC_C2_SYSTEM_EOL_STATE_ID0x1D))
9162 nvme_show_error("ERROR: WDC: Get System EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get System EOL State Failed"
)
;
9163
9164 /* Get format corrupt reason*/
9165 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &format_corrupt_reason,
9166 WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E))
9167 nvme_show_error("ERROR: WDC: Get Format Corrupt Reason Failed")nvme_show_message(1, "ERROR: WDC: Get Format Corrupt Reason Failed"
)
;
9168
9169 printf(" Drive Status :-\n");
9170 if ((int)le32_to_cpu(eol_status) >= 0)
9171 printf(" Percent Used: %"PRIu32"u""%%\n",
9172 le32_to_cpu(eol_status));
9173 else
9174 printf(" Percent Used: Unknown\n");
9175 if (system_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) && user_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000))
9176 printf(" Drive Life Status: Normal\n");
9177 else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) ||
9178 user_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001))
9179 printf(" Drive Life Status: End Of Life\n");
9180 else if (system_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) ||
9181 user_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002))
9182 printf(" Drive Life Status: Read Only\n");
9183 else
9184 printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n",
9185 le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state));
9186
9187 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001))
9188 printf(" Assert Dump Status: Present\n");
9189 else if (assert_status == WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000))
9190 printf(" Assert Dump Status: Not Present\n");
9191 else
9192 printf(" Assert Dump Status: Unknown : 0x%08x\n", le32_to_cpu(assert_status));
9193
9194 if (thermal_status == WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000))
9195 printf(" Thermal Throttling Status: Off\n");
9196 else if (thermal_status == WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001))
9197 printf(" Thermal Throttling Status: On\n");
9198 else if (thermal_status == WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002))
9199 printf(" Thermal Throttling Status: Unavailable\n");
9200 else
9201 printf(" Thermal Throttling Status: Unknown : 0x%08x\n", le32_to_cpu(thermal_status));
9202
9203 if (format_corrupt_reason == WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000))
9204 printf(" Format Corrupt Reason: Format Not Corrupted\n");
9205 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001))
9206 printf(" Format Corrupt Reason: Format Corrupt due to FW Assert\n");
9207 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF))
9208 printf(" Format Corrupt Reason: Format Corrupt for Unknown Reason\n");
9209 else
9210 printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
9211
9212 free(dev_mng_log);
9213out:
9214 return ret;
9215}
9216
9217static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
9218 struct plugin *plugin)
9219{
9220 const char *desc = "Clear Assert Dump Present Status.";
9221 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9222 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9223 int ret = -1;
9224 __le32 assert_status = cpu_to_le32(0xFFFFFFFF);
9225 __u64 capabilities = 0;
9226 struct libnvme_passthru_cmd admin_cmd;
9227
9228 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 informational output", 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) } }
;
9229
9230 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9231 if (ret)
9232 return ret;
9233
9234 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9235 if (ret)
9236 return ret;
9237
9238 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9239
9240 if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) != WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) {
9241 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9242 ret = -1;
9243 goto out;
9244 }
9245 if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status,
9246 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19)) {
9247 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9248 ret = -1;
9249 goto out;
9250 }
9251
9252 /* Get the assert dump present status */
9253 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001)) {
9254 memset(&admin_cmd, 0, sizeof(admin_cmd));
9255 admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8;
9256 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9257 WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03);
9258
9259 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9260 nvme_show_status(ret);
9261 } else
9262 nvme_show_error("INFO: WDC: No Assert Dump Present")nvme_show_message(1, "INFO: WDC: No Assert Dump Present");
9263
9264out:
9265 return ret;
9266}
9267
9268static int wdc_get_fw_act_history(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9269 char *format)
9270{
9271 struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
9272 nvme_print_flags_t fmt;
9273 int ret;
9274 __u8 *data;
9275
9276 if (!wdc_check_device(ctx, hdl))
9277 return -1;
9278
9279 ret = validate_output_format(format, &fmt);
9280 if (ret < 0) {
9281 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9282 return ret;
9283 }
9284
9285 /* verify the FW Activate History log page is supported */
9286 if (!wdc_nvme_check_supported_log_page(ctx, hdl,
9287 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) {
9288 nvme_show_error("ERROR: WDC: %d Log Page not supported",nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
9289 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
;
9290 return -1;
9291 }
9292
9293 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9294 if (!data) {
9295 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9296 return -1;
9297 }
9298
9299 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9300
9301 ret = nvme_get_log_simple(hdl,
9302 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB,
9303 data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9304
9305 if (strcmp(format, "json"))
9306 nvme_show_status(ret);
9307
9308 if (!ret) {
9309 /* parse the data */
9310 fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data);
9311
9312 if ((fw_act_history_hdr->num_entries > 0) &&
9313 (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES20)) {
9314 ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries,
9315 fmt, 0, 0, 0);
9316 } else if (!fw_act_history_hdr->num_entries) {
9317 nvme_show_error("INFO: WDC: No FW Activate History entries found.")nvme_show_message(1, "INFO: WDC: No FW Activate History entries found."
)
;
9318 ret = 0;
9319 } else {
9320 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)
9321 "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)
9322 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)
;
9323 ret = -1;
9324 }
9325 } else {
9326 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"
)
;
9327 ret = -1;
9328 }
9329
9330 free(data);
9331 return ret;
9332}
9333
9334static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
9335{
9336
9337 __u32 cust_id = WDC_INVALID_CUSTOMER_ID-1;
9338 __u32 *cust_id_ptr = NULL((void*)0);
9339
9340 if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID0x15, (void *)&cust_id_ptr))
9341 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)
9342 __func__, WDC_C2_CUSTOMER_ID_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
;
9343 else
9344 cust_id = *cust_id_ptr;
9345
9346 free(cust_id_ptr);
9347 return cust_id;
9348}
9349
9350static int wdc_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9351 char *format)
9352{
9353 struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
9354 __u32 tot_entries = 0, num_entries = 0;
9355 __u32 vendor_id = 0, device_id = 0;
9356 __u32 cust_id = 0;
9357 nvme_print_flags_t fmt;
9358 __u8 *data;
9359 int ret;
9360 bool_Bool c2GuidMatch = false0;
9361
9362 if (!wdc_check_device(ctx, hdl))
9363 return -1;
9364
9365 ret = validate_output_format(format, &fmt);
9366 if (ret < 0) {
9367 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9368 return ret;
9369 }
9370
9371 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
9372
9373 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9374 if (!data) {
9375 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9376 return -1;
9377 }
9378
9379 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9380
9381 ret = nvme_get_log_simple(hdl,
9382 WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
9383 data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9384
9385 if (strcmp(format, "json"))
9386 nvme_show_status(ret);
9387
9388 if (!ret) {
9389 /* Get the log page data and verify the GUID */
9390 fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data);
9391
9392 c2GuidMatch = !memcmp(ocp_C2_guid,
9393 fw_act_history_log->log_page_guid,
9394 WDC_C2_GUID_LENGTH16);
9395
9396 if (c2GuidMatch) {
9397 /* parse the data */
9398 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
9399
9400 if (tot_entries > 0) {
9401 /* get the FW customer id */
9402 if (!wdc_is_sn861(device_id)) {
9403 cust_id = wdc_get_fw_cust_id(ctx, hdl);
9404 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
9405 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9406 "%s: ERROR: WDC: invalid customer id\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9407 __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
;
9408 ret = -1;
9409 goto freeData;
9410 }
9411 }
9412 num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES20) ?
9413 tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES20;
9414 ret = wdc_print_fw_act_history_log(data, num_entries,
9415 fmt, cust_id, vendor_id, device_id);
9416 } else {
9417 nvme_show_error("INFO: WDC: No entries found.")nvme_show_message(1, "INFO: WDC: No entries found.");
9418 ret = 0;
9419 }
9420 } else {
9421 nvme_show_error("ERROR: WDC: Invalid C2 log page GUID")nvme_show_message(1, "ERROR: WDC: Invalid C2 log page GUID");
9422 ret = -1;
9423 }
9424 } else {
9425 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"
)
;
9426 ret = -1;
9427 }
9428
9429freeData:
9430 free(data);
9431 return ret;
9432}
9433
9434static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd,
9435 struct plugin *plugin)
9436{
9437 const char *desc = "Retrieve FW activate history table.";
9438 __u64 capabilities = 0;
9439 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9440 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9441 int ret = -1;
9442
9443 struct config {
9444 char *output_format;
9445 };
9446
9447 struct config cfg = {
9448 .output_format = "normal",
9449 };
9450
9451 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 informational output", 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) } }
;
9452
9453 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9454 if (ret)
9455 return ret;
9456
9457 cfg.output_format = nvme_args.output_format;
9458
9459 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9460 if (ret)
9461 return ret;
9462
9463 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9464
9465 if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000))) {
9466 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9467 ret = -1;
9468 goto out;
9469 }
9470
9471 if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000) {
9472 __u32 cust_fw_id = 0;
9473 /* get the FW customer id */
9474 cust_fw_id = wdc_get_fw_cust_id(ctx, hdl);
9475 if (cust_fw_id == WDC_INVALID_CUSTOMER_ID-1) {
9476 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
9477 ret = -1;
9478 goto out;
9479 }
9480
9481 if ((cust_fw_id == WDC_CUSTOMER_ID_0x10040x1004) ||
9482 (cust_fw_id == WDC_CUSTOMER_ID_0x10080x1008) ||
9483 (cust_fw_id == WDC_CUSTOMER_ID_0x10050x1005) ||
9484 (cust_fw_id == WDC_CUSTOMER_ID_0x13040x1304))
9485 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9486 else
9487 ret = wdc_get_fw_act_history(ctx, hdl, cfg.output_format);
9488 } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
9489 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9490 }
9491
9492 if (ret)
9493 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)
;
9494out:
9495 return ret;
9496}
9497
9498static int wdc_do_clear_fw_activate_history_vuc(struct libnvme_transport_handle *hdl)
9499{
9500 int ret = -1;
9501 struct libnvme_passthru_cmd admin_cmd;
9502
9503 memset(&admin_cmd, 0, sizeof(admin_cmd));
9504 admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6;
9505 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9506 WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23);
9507
9508 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9509 nvme_show_status(ret);
9510
9511 return ret;
9512}
9513
9514static int wdc_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
9515{
9516 int ret = -1;
9517 __u64 result;
9518 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
9519
9520 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, false0,
9521 value, &result);
9522
9523 nvme_show_status(ret);
9524 return ret;
9525}
9526
9527static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd,
9528 struct plugin *plugin)
9529{
9530 const char *desc = "Clear FW activate history table.";
9531 __u64 capabilities = 0;
9532 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9533 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9534 int ret;
9535
9536 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 informational output", 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) } }
;
9537
9538 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9539 if (ret)
9540 return ret;
9541
9542 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9543 if (ret)
9544 return ret;
9545
9546 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9547
9548 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000))) {
9549 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9550 ret = -1;
9551 goto out;
9552 }
9553
9554 if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000)
9555 ret = wdc_do_clear_fw_activate_history_vuc(hdl);
9556 else
9557 ret = wdc_do_clear_fw_activate_history_fid(hdl);
9558
9559out:
9560 return ret;
9561}
9562
9563static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd,
9564 struct plugin *plugin)
9565{
9566 const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
9567 const char *disable = "Disable controller option of the telemetry log page.";
9568 const char *enable = "Enable controller option of the telemetry log page.";
9569 const char *status = "Displays the current state of the controller initiated log page.";
9570 __u64 capabilities = 0;
9571 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9572 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9573 struct libnvme_passthru_cmd cmd;
9574 __u64 result;
9575 int ret = -1;
9576
9577
9578 struct config {
9579 bool_Bool disable;
9580 bool_Bool enable;
9581 bool_Bool status;
9582 };
9583
9584 struct config cfg = {
9585 .disable = false0,
9586 .enable = false0,
9587 .status = false0,
9588 };
9589
9590 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 informational output", 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) } }
9591 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 informational output", 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) } }
9592 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 informational output", 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) } }
9593 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 informational output", 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) } }
;
9594
9595 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9596 if (ret)
9597 return ret;
9598
9599 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9600 if (ret)
9601 return ret;
9602
9603 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9604
9605 if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) {
9606 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9607 ret = -1;
9608 goto out;
9609 }
9610
9611 /* allow only one option at a time */
9612 if ((cfg.disable + cfg.enable + cfg.status) > 1) {
9613
9614 nvme_show_error("ERROR: WDC: Invalid option")nvme_show_message(1, "ERROR: WDC: Invalid option");
9615 ret = -1;
9616 goto out;
9617 }
9618
9619 if (cfg.disable) {
9620 ret = nvme_set_features_simple(hdl, 0,
9621 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9622 false0, 1, &result);
9623
9624 wdc_clear_reason_id(hdl);
9625 } else {
9626 if (cfg.enable) {
9627 ret = nvme_set_features_simple(hdl, 0,
9628 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9629 false0, 0, &result);
9630 } else if (cfg.status) {
9631 nvme_init_get_features(&cmd,
9632 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9633 NVME_GET_FEATURES_SEL_CURRENT);
9634 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9635 result = cmd.result;
9636 if (!ret) {
9637 if (result)
9638 nvme_show_error("Controller Option Telemetry Log Page State: Disabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Disabled"
)
;
9639 else
9640 nvme_show_error("Controller Option Telemetry Log Page State: Enabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Enabled"
)
;
9641 } else {
9642 nvme_show_status(ret);
9643 }
9644 } else {
9645 nvme_show_error("ERROR: WDC: unsupported option for this command")nvme_show_message(1, "ERROR: WDC: unsupported option for this command"
)
;
9646 nvme_show_error("Please provide an option, -d, -e or -s")nvme_show_message(1, "Please provide an option, -d, -e or -s"
)
;
9647 ret = -1;
9648 goto out;
9649 }
9650 }
9651
9652out:
9653 return ret;
9654}
9655
9656
9657static int wdc_get_serial_and_fw_rev(struct libnvme_transport_handle *hdl, char *sn, char *fw_rev)
9658{
9659 struct libnvme_passthru_cmd cmd;
9660 struct nvme_id_ctrl ctrl;
9661 int ret;
9662 int i;
9663
9664 i = sizeof(ctrl.sn) - 1;
9665 memset(sn, 0, WDC_SERIAL_NO_LEN20);
9666 memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN9);
9667 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9668 nvme_init_identify_ctrl(&cmd, &ctrl);
9669 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9670 if (ret) {
9671 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)
;
9672 return -1;
9673 }
9674 /* Remove trailing spaces from the name */
9675 while (i && ctrl.sn[i] == ' ') {
9676 ctrl.sn[i] = '\0';
9677 i--;
9678 }
9679 snprintf(sn, WDC_SERIAL_NO_LEN20, "%s", ctrl.sn);
9680 snprintf(fw_rev, WDC_NVME_FIRMWARE_REV_LEN9, "%s", ctrl.fr);
9681
9682 return 0;
9683}
9684
9685static int wdc_get_max_transfer_len(struct libnvme_transport_handle *hdl, __u32 *maxTransferLen)
9686{
9687 struct libnvme_passthru_cmd cmd;
9688 struct nvme_id_ctrl ctrl;
9689 int ret = 0;
9690
9691 __u32 maxTransferLenDevice = 0;
9692
9693 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9694 nvme_init_identify_ctrl(&cmd, &ctrl);
9695 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9696 if (ret) {
9697 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)
;
9698 return -1;
9699 }
9700
9701 maxTransferLenDevice = (1 << ctrl.mdts) * shr_getpagesize();
9702 *maxTransferLen = maxTransferLenDevice;
9703
9704 return ret;
9705}
9706
9707static int wdc_de_VU_read_size(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize)
9708{
9709 int ret = WDC_STATUS_FAILURE-1;
9710 struct libnvme_passthru_cmd cmd;
9711
9712 if (!logSize) {
9713 ret = WDC_STATUS_INVALID_PARAMETER-3;
9714 goto end;
9715 }
9716
9717 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9718 cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE0xC0;
9719 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9720 cmd.cdw13 = fileId << 16;
9721 cmd.cdw14 = spiDestn;
9722
9723 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9724
9725 if (!ret && logSize)
9726 *logSize = cmd.result;
9727 if (ret != WDC_STATUS_SUCCESS0) {
9728 nvme_show_error("ERROR: WDC: VUReadSize() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadSize() failed, ");
9729 nvme_show_status(ret);
9730 }
9731
9732end:
9733 return ret;
9734}
9735
9736static int wdc_de_VU_read_buffer(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn,
9737 __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize)
9738{
9739 int ret = WDC_STATUS_FAILURE-1;
9740 struct libnvme_passthru_cmd cmd;
9741 __u32 noOfDwordExpected = 0;
9742
9743 if (!dataBuffer || !bufferSize) {
9744 ret = WDC_STATUS_INVALID_PARAMETER-3;
9745 goto end;
9746 }
9747
9748 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9749 noOfDwordExpected = *bufferSize / sizeof(__u32);
9750 cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE0xC2;
9751 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9752 cmd.cdw10 = noOfDwordExpected;
9753 cmd.cdw13 = fileId << 16;
9754 cmd.cdw14 = spiDestn;
9755 cmd.cdw15 = offsetInDwords;
9756
9757 cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
9758 cmd.data_len = *bufferSize;
9759
9760 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9761
9762 if (ret != WDC_STATUS_SUCCESS0) {
9763 nvme_show_error("ERROR: WDC: VUReadBuffer() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadBuffer() failed, ");
9764 nvme_show_status(ret);
9765 }
9766
9767end:
9768 return ret;
9769}
9770
9771static int wdc_get_log_dir_max_entries(struct libnvme_transport_handle *hdl, __u32 *maxNumOfEntries)
9772{
9773 int ret = WDC_STATUS_FAILURE-1;
9774 __u32 headerPayloadSize = 0;
9775 __u8 *fileIdOffsetsBuffer = NULL((void*)0);
9776 __u32 fileIdOffsetsBufferSize = 0;
9777 __u32 fileNum = 0;
9778 __u16 fileOffset = 0;
9779
9780
9781 if (!maxNumOfEntries) {
9782 ret = WDC_STATUS_INVALID_PARAMETER-3;
9783 return ret;
9784 }
9785 /* 1.Get log directory first four bytes */
9786 ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize);
9787 if (ret != WDC_STATUS_SUCCESS0) {
9788 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
9789 "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)
9790 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
;
9791 return ret;
9792 }
9793
9794 fileIdOffsetsBufferSize =
9795 WDC_DE_FILE_HEADER_SIZE4 + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE2);
9796 fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize);
9797
9798 /* 2.Read to get file offsets */
9799 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize);
9800 if (ret != WDC_STATUS_SUCCESS0) {
9801 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
9802 "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)
9803 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
;
9804 goto end;
9805 }
9806 /* 3.Determine valid entries */
9807 for (fileNum = 0;
9808 fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9809 fileNum++) {
9810 fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9811 (fileNum * WDC_DE_FILE_OFFSET_SIZE2)] << 8) +
9812 fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9813 (fileNum * WDC_DE_FILE_OFFSET_SIZE2) + 1];
9814 if (!fileOffset)
9815 continue;
9816 (*maxNumOfEntries)++;
9817 }
9818
9819end:
9820 free(fileIdOffsetsBuffer);
9821 return ret;
9822}
9823
9824static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[])
9825{
9826 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE;
9827
9828 if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME"core_dump"))
9829 essentialType = WDC_DE_TYPE_DUMPSNAPSHOT;
9830 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME"event_log"))
9831 essentialType = WDC_DE_TYPE_EVENTLOG;
9832 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info"))
9833 essentialType = WDC_DE_TYPE_NVME_MANF_INFO;
9834
9835 return essentialType;
9836}
9837
9838static int wdc_fetch_log_directory(struct libnvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory)
9839{
9840 int ret = WDC_STATUS_FAILURE-1;
9841 __u8 *fileOffset = NULL((void*)0);
9842 __u8 *fileDirectory = NULL((void*)0);
9843 __u32 headerSize = 0;
9844 __u32 fileNum = 0, startIdx = 0;
9845 __u16 fileOffsetTemp = 0;
9846 __u32 entryId = 0;
9847 __u32 fileDirectorySize = 0;
9848
9849 if (!directory) {
9850 ret = WDC_STATUS_INVALID_PARAMETER-3;
9851 goto end;
9852 }
9853
9854 ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize);
9855 if (ret != WDC_STATUS_SUCCESS0) {
9856 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
9857 "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)
9858 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
;
9859 goto end;
9860 }
9861
9862 fileDirectory = (__u8 *)calloc(1, fileDirectorySize);
9863 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize);
9864 if (ret != WDC_STATUS_SUCCESS0) {
9865 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)
9866 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
;
9867 goto end;
9868 }
9869
9870 /* First four bytes of header directory is headerSize */
9871 memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE4);
9872
9873 /* headerSize describes the offset table inside fileDirectory */
9874 if (headerSize < WDC_DE_FILE_HEADER_SIZE4 || headerSize > fileDirectorySize) {
9875 nvme_show_error("ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n",nvme_show_message(1, "ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n"
, __func__, headerSize, fileDirectorySize)
9876 __func__, headerSize, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n"
, __func__, headerSize, fileDirectorySize)
;
9877 ret = WDC_STATUS_FAILURE-1;
9878 goto end;
9879 }
9880
9881 /* minimum buffer for 1 entry is required */
9882 if (!directory->maxNumLogEntries) {
9883 ret = WDC_STATUS_INVALID_PARAMETER-3;
9884 goto end;
9885 }
9886
9887 for (fileNum = 0;
9888 fileNum < (headerSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9889 fileNum++) {
9890 if (entryId >= directory->maxNumLogEntries)
9891 break;
9892
9893 startIdx = WDC_DE_FILE_HEADER_SIZE4 + (fileNum * WDC_DE_FILE_OFFSET_SIZE2);
9894 memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp));
9895 fileOffset = fileDirectory + fileOffsetTemp;
9896
9897 if (!fileOffsetTemp)
9898 continue;
9899
9900 if (fileOffsetTemp + sizeof(struct WDC_DE_VU_FILE_META_DATA) > fileDirectorySize) {
9901 nvme_show_error("ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n",nvme_show_message(1, "ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n"
, __func__, fileOffsetTemp, fileDirectorySize)
9902 __func__, fileOffsetTemp, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n"
, __func__, fileOffsetTemp, fileDirectorySize)
;
9903 ret = WDC_STATUS_FAILURE-1;
9904 goto end;
9905 }
9906
9907 memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS));
9908 memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA));
9909 directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE32 - 1] = '\0';
9910 wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName,
9911 WDC_DE_FILE_NAME_SIZE32, ' ');
9912 if (!directory->logEntry[entryId].metaData.fileID)
9913 continue;
9914
9915 directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName);
9916 entryId++;
9917 }
9918
9919 directory->numOfValidLogEntries = entryId;
9920
9921end:
9922 free(fileDirectory);
9923 return ret;
9924}
9925
9926static int wdc_fetch_log_file_from_device(struct libnvme_transport_handle *hdl, __u32 fileId,
9927 __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
9928{
9929 int ret = WDC_STATUS_FAILURE-1;
9930 __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9931 __u32 maximumTransferLength = 0;
9932 __u32 buffSize = 0;
9933 __u64 offsetIdx = 0;
9934
9935 if (!dataBuffer || !fileSize) {
9936 ret = WDC_STATUS_INVALID_PARAMETER-3;
9937 goto end;
9938 }
9939
9940 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) {
9941 ret = WDC_STATUS_FAILURE-1;
9942 goto end;
9943 }
9944
9945 /* Fetch Log File Data */
9946 if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) {
9947 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9948 if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000)
9949 chunckSize = maximumTransferLength;
9950
9951 buffSize = chunckSize;
9952 for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) {
9953 if (((offsetIdx * chunckSize) + buffSize) > fileSize)
9954 buffSize = (__u32)(fileSize - (offsetIdx * chunckSize));
9955 /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */
9956 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9957 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize);
9958 if (ret != WDC_STATUS_SUCCESS0) {
9959 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)
9960 __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)
;
9961 break;
9962 }
9963 }
9964 } else {
9965 buffSize = (__u32)fileSize;
9966 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9967 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)),
9968 dataBuffer, &buffSize);
9969 if (ret != WDC_STATUS_SUCCESS0) {
9970 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)
9971 __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)
;
9972 }
9973 }
9974
9975end:
9976 return ret;
9977}
9978
9979static int wdc_de_get_dump_trace(struct libnvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen,
9980 const char *binFileName)
9981{
9982 int ret = WDC_STATUS_FAILURE-1;
9983 __u8 *readBuffer = NULL((void*)0);
9984 __u32 readBufferLen = 0;
9985 __u32 lastPktReadBufferLen = 0;
9986 __u32 maxTransferLen = 0;
9987 __u32 dumptraceSize = 0;
9988 __u32 chunkSize;
9989 __u32 chunks;
9990 __u32 offset;
9991 __u32 i;
9992 __u32 maximumTransferLength = 0;
9993
9994 if (!binFileName || !filePath) {
9995 ret = WDC_STATUS_INVALID_PARAMETER-3;
9996 return ret;
9997 }
9998
9999 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0)
10000 return WDC_STATUS_FAILURE-1;
10001
10002 do {
10003 /* Get dumptrace size */
10004 ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, &dumptraceSize);
10005 if (ret != WDC_STATUS_SUCCESS0) {
10006 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)
10007 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
;
10008 break;
10009 }
10010
10011 /* Make sure the size requested is greater than dword */
10012 if (dumptraceSize < 4) {
10013 ret = WDC_STATUS_FAILURE-1;
10014 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)
10015 __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)
;
10016 break;
10017 }
10018
10019 /* Choose the least max transfer length */
10020 maxTransferLen = maximumTransferLength < WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 ? maximumTransferLength : WDC_DE_READ_MAX_TRANSFER_SIZE0x8000;
10021
10022 /* Comment from FW Team:
10023 * The max non - block transfer size is 0xFFFF (16 bits allowed as the block size).Use 0x8000
10024 * to keep it on a word - boundary.
10025 * max_xfer = int(pow(2, id_data['MDTS'])) * 4096 # 4k page size as reported in pcie capabiltiies
10026 */
10027 chunkSize = dumptraceSize < maxTransferLen ? dumptraceSize : maxTransferLen;
10028 chunks = (dumptraceSize / maxTransferLen) + ((dumptraceSize % maxTransferLen) ? 1 : 0);
10029
10030 readBuffer = (unsigned char *)calloc(dumptraceSize, sizeof(unsigned char));
10031 readBufferLen = chunkSize;
10032 lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize;
10033
10034 if (!readBuffer) {
10035 nvme_show_error("ERROR: WDC: %s: readBuffer calloc failed", __func__)nvme_show_message(1, "ERROR: WDC: %s: readBuffer calloc failed"
, __func__)
;
10036 ret = WDC_STATUS_INSUFFICIENT_MEMORY-2;
10037 break;
10038 }
10039
10040 for (i = 0; i < chunks; i++) {
10041 offset = (i * chunkSize) / 4;
10042
10043 /* Last loop call, Assign readBufferLen to read only left over bytes */
10044 if (i == (chunks - 1))
10045 readBufferLen = lastPktReadBufferLen;
10046
10047 ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, 0,
10048 readBuffer + offset, &readBufferLen);
10049 if (ret != WDC_STATUS_SUCCESS0) {
10050 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)
10051 "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)
10052 __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)
;
10053 break;
10054 }
10055 }
10056 } while (0);
10057
10058 if (ret == WDC_STATUS_SUCCESS0) {
10059 ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
10060 if (ret != WDC_STATUS_SUCCESS0)
10061 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)
10062 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
;
10063 } else {
10064 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)
10065 ret)nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
;
10066 }
10067
10068 free(readBuffer);
10069
10070 return ret;
10071}
10072
10073int wdc_fetch_vu_file_directory(struct libnvme_transport_handle *hdl,
10074 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList,
10075 __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString)
10076{
10077 int ret = wdc_fetch_log_directory(hdl, &deEssentialsList);
10078 __u32 listIdx;
10079 char *dataBuffer;
10080 char fileName[MAX_PATH_LEN256];
10081
10082 if (ret != WDC_STATUS_SUCCESS0) {
10083 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)
;
10084 return ret;
10085 }
10086
10087 /* Get Debug Data Files */
10088 for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) {
10089 if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) {
10090 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)
10091 deEssentialsList.logEntry[listIdx].metaData.fileName)nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
;
10092 ret = WDC_STATUS_FILE_SIZE_ZERO-27;
10093 } else {
10094 /* Fetch Log File Data */
10095 dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10096 ret = wdc_fetch_log_file_from_device(hdl,
10097 deEssentialsList.logEntry[listIdx].metaData.fileID,
10098 WDC_DE_DESTN_SPI1,
10099 deEssentialsList.logEntry[listIdx].metaData.fileSize,
10100 (__u8 *)dataBuffer);
10101
10102 /* Write databuffer to file */
10103 if (ret == WDC_STATUS_SUCCESS0) {
10104 memset(fileName, 0, sizeof(fileName));
10105 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10106 deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString);
10107 if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) {
10108 wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF);
10109 wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF));
10110 } else {
10111 wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10112 }
10113 } else {
10114 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)
10115 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)
;
10116 }
10117 free(dataBuffer);
10118 }
10119 }
10120
10121 return ret;
10122}
10123
10124int wdc_read_debug_directory(struct libnvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo,
10125 __u8 *timeString)
10126{
10127 __u32 maxNumOfVUFiles = 0;
10128 int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles);
10129 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
10130
10131 if (ret != WDC_STATUS_SUCCESS0) {
10132 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)
;
10133 return ret;
10134 }
10135
10136 memset(&deEssentialsList, 0, sizeof(deEssentialsList));
10137 deEssentialsList.logEntry =
10138 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles);
10139 deEssentialsList.maxNumLogEntries = maxNumOfVUFiles;
10140
10141 ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo,
10142 timeString);
10143
10144 free(deEssentialsList.logEntry);
10145 deEssentialsList.logEntry = NULL((void*)0);
10146
10147 return ret;
10148}
10149
10150static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
10151 char *dir, char *key)
10152{
10153 int ret = 0;
10154 void *retPtr;
10155 char fileName[MAX_PATH_LEN256];
10156 __s8 bufferFolderPath[MAX_PATH_LEN256];
10157 char bufferFolderName[MAX_PATH_LEN256];
10158 char tarFileName[MAX_PATH_LEN256];
10159 char tarFiles[MAX_PATH_LEN256];
10160 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
10161 UtilsTimeInfo timeInfo;
10162 __u8 timeString[MAX_PATH_LEN256];
10163 __u8 serialNo[WDC_SERIAL_NO_LEN20];
10164 __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN9];
10165 __u8 idSerialNo[WDC_SERIAL_NO_LEN20];
10166 __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN9];
10167 __u8 featureIdBuff[4];
10168 char currDir[MAX_PATH_LEN256];
10169 char *dataBuffer = NULL((void*)0);
10170 __u32 elogNumEntries, elogBufferSize;
10171 __u32 dataBufferSize;
10172 __u32 listIdx = 0;
10173 __u32 vuLogIdx = 0;
10174 __u64 result;
10175 struct nvme_id_ctrl ctrl;
10176 struct nvme_id_ns ns;
10177 struct nvme_error_log_page *elogBuffer;
10178 struct nvme_smart_log smart_log;
10179 struct nvme_firmware_slot fw_log;
10180 struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL((void*)0);
10181 struct libnvme_passthru_cmd cmd;
10182
10183 memset(bufferFolderPath, 0, sizeof(bufferFolderPath));
10184 memset(bufferFolderName, 0, sizeof(bufferFolderName));
10185 memset(tarFileName, 0, sizeof(tarFileName));
10186 memset(tarFiles, 0, sizeof(tarFiles));
10187 memset(tarCmd, 0, sizeof(tarCmd));
10188 memset(&timeInfo, 0, sizeof(timeInfo));
10189
10190 if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) {
10191 nvme_show_error("ERROR: WDC: get serial # and fw revision failed")nvme_show_message(1, "ERROR: WDC: get serial # and fw revision failed"
)
;
10192 return -1;
10193 }
10194
10195 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)
10196 idSerialNo, idFwRev)nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
;
10197
10198 /* Create Drive Essentials directory */
10199 wdc_UtilsGetTime(&timeInfo);
10200 memset(timeString, 0, sizeof(timeString));
10201 wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10202 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10203 timeInfo.hour, timeInfo.minute, timeInfo.second);
10204
10205 wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN20, (char *)idSerialNo);
10206 /* Remove any space form serialNo */
10207 wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN20, ' ');
10208
10209 memset(firmwareRevision, 0, sizeof(firmwareRevision));
10210 wdc_UtilsSnprintf((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, (char *)idFwRev);
10211 /* Remove any space form FirmwareRevision */
10212 wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, ' ');
10213
10214 wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN256, "%s_%s_%s_%s",
10215 "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString);
10216
10217 if (dir) {
10218 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10219 (char *)dir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10220 } else {
10221 retPtr = getcwd((char *)currDir, MAX_PATH_LEN256);
10222 if (retPtr) {
10223 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10224 (char *)currDir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10225 } else {
10226 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
10227 return -1;
10228 }
10229 }
10230
10231 ret = wdc_UtilsCreateDir((char *)bufferFolderPath);
10232 if (ret) {
10233 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)
;
10234 return -1;
10235 }
10236
10237 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)
;
10238
10239 /* Get Identify Controller Data */
10240 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10241 nvme_init_identify_ctrl(&cmd, &ctrl);
10242 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10243 if (ret) {
10244 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)
;
10245 return -1;
10246 }
10247
10248 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath,
10249 WDC_DE_PATH_SEPARATOR"/", "IdentifyController", (char *)serialNo,
10250 (char *)timeString);
10251 wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl));
10252
10253 memset(&ns, 0, sizeof(struct nvme_id_ns));
10254 nvme_init_identify_ns(&cmd, 1, &ns);
10255 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10256 if (ret) {
10257 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)
;
10258 } else {
10259 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10260 "IdentifyNamespace", (char *)serialNo, (char *)timeString);
10261 wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns));
10262 }
10263
10264 /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */
10265 elogNumEntries = WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64;
10266 elogBufferSize = elogNumEntries*sizeof(struct nvme_error_log_page);
10267 dataBuffer = calloc(1, elogBufferSize);
10268 elogBuffer = (struct nvme_error_log_page *)dataBuffer;
10269
10270 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR,
10271 NVME_CSI_NVM, elogBuffer, elogBufferSize);
10272
10273 ret = libnvme_get_log(hdl, &cmd, false0, elogBufferSize);
10274 if (ret) {
10275 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)
;
10276 } else {
10277 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10278 "ErrorLog", (char *)serialNo, (char *)timeString);
10279 wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize);
10280 }
10281
10282 free(dataBuffer);
10283 dataBuffer = NULL((void*)0);
10284
10285 /* Get Smart log page */
10286 memset(&smart_log, 0, sizeof(struct nvme_smart_log));
10287 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
10288 if (ret) {
10289 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)
;
10290 } else {
10291 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10292 "SmartLog", (char *)serialNo, (char *)timeString);
10293 wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log));
10294 }
10295
10296 /* Get FW Slot log page */
10297 memset(&fw_log, 0, sizeof(struct nvme_firmware_slot));
10298 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT,
10299 NVME_CSI_NVM, &fw_log, sizeof(fw_log));
10300
10301 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(fw_log));
10302 if (ret) {
10303 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)
;
10304 } else {
10305 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10306 "FwSLotLog", (char *)serialNo, (char *)timeString);
10307 wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot));
10308 }
10309
10310 /* Get VU log pages */
10311 /* define inputs for vendor unique log pages */
10312 vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES));
10313 vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList)(sizeof(deVULogPagesList) / sizeof((deVULogPagesList)[0]) + 0
)
;
10314
10315 for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) {
10316 dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen;
10317 dataBuffer = calloc(1, dataBufferSize);
10318 memset(dataBuffer, 0, dataBufferSize);
10319
10320 ret = nvme_get_log_simple(hdl,
10321 deVULogPagesList[vuLogIdx].logPageId,
10322 dataBuffer, dataBufferSize);
10323 if (ret) {
10324 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)
10325 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)
;
10326 } else {
10327 wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' ');
10328 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10329 "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString);
10330 wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize);
10331 }
10332
10333 free(dataBuffer);
10334 }
10335
10336 free(vuLogInput);
10337
10338 /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */
10339 for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList)(sizeof(deFeatureIdList) / sizeof((deFeatureIdList)[0]) + 0); listIdx++) {
10340 memset(featureIdBuff, 0, sizeof(featureIdBuff));
10341 /* skipping LbaRangeType as it is an optional nvme command and not supported */
10342 if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
10343 continue;
10344 ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID0xFFFFFFFF,
10345 (enum nvme_features_id)deFeatureIdList[listIdx].featureId,
10346 NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff,
10347 sizeof(featureIdBuff), &result);
10348 if (ret) {
10349 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)
10350 deFeatureIdList[listIdx].featureId, ret)nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
;
10351 } else {
10352 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10353 "FEATURE_ID_", deFeatureIdList[listIdx].featureId,
10354 deFeatureIdList[listIdx].featureName, serialNo, timeString);
10355 wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff));
10356 }
10357 }
10358
10359 wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString);
10360
10361 /* Get Dump Trace Data */
10362 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/", "dumptrace", serialNo, timeString);
10363 ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName);
10364 if (ret != WDC_STATUS_SUCCESS0)
10365 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)
;
10366
10367 /* Tar the Drive Essentials directory */
10368 wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
10369 if (dir)
10370 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s%s%s", (char *)dir,
10371 WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName,
10372 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10373 else
10374 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s", (char *)bufferFolderName,
10375 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10376 wdc_UtilsSnprintf(tarCmd, sizeof(tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarFileName, (char *)tarFiles);
10377
10378 ret = system(tarCmd);
10379
10380 if (ret)
10381 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)
10382 ret)nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
;
10383
10384 nvme_show_verbose_result("Get of Drive Essentials data successful")nvme_show_verbose_message("Get of Drive Essentials data successful"
)
;
10385 return 0;
10386}
10387
10388static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
10389 struct plugin *plugin)
10390{
10391 const char *desc = "Capture Drive Essentials.";
10392 const char *dirName = "Output directory pathname.";
10393 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10394 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10395 char d[PATH_MAX4096] = {0};
10396 char k[PATH_MAX4096] = {0};
10397 __u64 capabilities = 0;
10398 char *d_ptr;
10399 int ret;
10400
10401 struct config {
10402 char *dirName;
10403 };
10404
10405 struct config cfg = {
10406 .dirName = NULL((void*)0),
10407 };
10408
10409 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 informational output", 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) } }
10410 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 informational output", 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) } }
;
10411
10412
10413 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10414 if (ret)
10415 return ret;
10416
10417 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10418 if (ret)
10419 return ret;
10420
10421 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10422
10423 if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) {
10424 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10425 ret = -1;
10426 goto out;
10427 }
10428
10429 if (cfg.dirName) {
10430 strncpy(d, cfg.dirName, PATH_MAX4096 - 1);
10431 d_ptr = d;
10432 } else {
10433 d_ptr = NULL((void*)0);
10434 }
10435
10436 ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k);
10437out:
10438 return ret;
10439}
10440
10441static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size)
10442{
10443 int ret;
10444 struct libnvme_passthru_cmd admin_cmd;
10445
10446 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10447 admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE0xCC;
10448 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 << WDC_NVME_SUBCMD_SHIFT8) |
10449 WDC_NVME_DRIVE_RESIZE_CMD0x03);
10450 admin_cmd.cdw13 = new_size;
10451
10452 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10453 return ret;
10454}
10455
10456static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option)
10457{
10458 int ret;
10459 struct libnvme_passthru_cmd admin_cmd;
10460
10461 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10462 admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB;
10463 admin_cmd.nsid = nsid;
10464 admin_cmd.cdw10 = op_option;
10465
10466 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10467 return ret;
10468}
10469
10470static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result)
10471{
10472 int ret;
10473 struct libnvme_passthru_cmd admin_cmd;
10474
10475 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10476 admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE0xC6;
10477 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
10478 WDC_NVME_DRIVE_INFO_CMD0x22);
10479
10480 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10481
10482 if (!ret && result)
10483 *result = admin_cmd.result;
10484
10485 return ret;
10486}
10487
10488static int wdc_drive_resize(int argc, char **argv,
10489 struct command *command, struct plugin *plugin)
10490{
10491 const char *desc = "Send a Resize command.";
10492 const char *size = "The new size (in GB) to resize the drive to.";
10493 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10494 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10495 uint64_t capabilities = 0;
10496 int ret;
10497
10498 struct config {
10499 uint64_t size;
10500 };
10501
10502 struct config cfg = {
10503 .size = 0,
10504 };
10505
10506 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 informational output", 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) } }
10507 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 informational output", 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) } }
;
10508
10509 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10510 if (ret)
10511 return ret;
10512
10513 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10514 if (ret || !wdc_check_device(ctx, hdl))
10515 return -1;
10516
10517 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10518
10519 if ((capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100) == WDC_DRIVE_CAP_RESIZE0x0000000000000100) {
10520 ret = wdc_do_drive_resize(hdl, cfg.size);
10521 } else {
10522 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10523 ret = -1;
10524 }
10525
10526 if (!ret)
10527 printf("New size: %" PRIu64"l" "u" " GB\n", cfg.size);
10528
10529 nvme_show_status(ret);
10530 return ret;
10531}
10532
10533static int wdc_namespace_resize(int argc, char **argv,
10534 struct command *command, struct plugin *plugin)
10535{
10536 const char *desc = "Send a Namespace Resize command.";
10537 const char *namespace_id = "The namespace id to resize.";
10538 const char *op_option = "The over provisioning option to set for namespace.";
10539 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10540 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10541 uint64_t capabilities = 0;
10542 int ret;
10543
10544 struct config {
10545 __u32 namespace_id;
10546 __u32 op_option;
10547 };
10548
10549 struct config cfg = {
10550 .namespace_id = 0x1,
10551 .op_option = 0xF,
10552 };
10553
10554 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 informational output"
, 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) } }
10555 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 informational output"
, 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) } }
10556 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 informational output"
, 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) } }
;
10557
10558 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10559 if (ret)
10560 return ret;
10561
10562 if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) &&
10563 (cfg.op_option != 0xF)) {
10564 nvme_show_error("ERROR: WDC: unsupported OP option parameter")nvme_show_message(1, "ERROR: WDC: unsupported OP option parameter"
)
;
10565 return -1;
10566 }
10567
10568 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10569 if (ret || !wdc_check_device(ctx, hdl))
10570 return -1;
10571
10572 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10573
10574 if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) == WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) {
10575 ret = wdc_do_namespace_resize(hdl, cfg.namespace_id,
10576 cfg.op_option);
10577
10578 if (ret)
10579 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)
;
10580 } else {
10581 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10582 ret = -1;
10583 }
10584
10585 nvme_show_status(ret);
10586 return ret;
10587}
10588
10589static int wdc_reason_identifier(int argc, char **argv,
10590 struct command *command, struct plugin *plugin)
10591{
10592 const char *desc = "Retrieve telemetry log reason identifier.";
10593 const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
10594 const char *fname = "File name to save raw binary identifier";
10595 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10596 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10597 int ret;
10598 uint64_t capabilities = 0;
10599 char f[PATH_MAX4096] = {0};
10600 char fileSuffix[PATH_MAX4096] = {0};
10601 UtilsTimeInfo timeInfo;
10602 __u8 timeStamp[MAX_PATH_LEN256];
10603
10604
10605 struct config {
10606 int log_id;
10607 char *file;
10608 };
10609 struct config cfg = {
10610 .log_id = 7,
10611 .file = NULL((void*)0),
10612 };
10613
10614 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 informational output", 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) } }
10615 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 informational output", 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) } }
10616 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 informational output", 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) } }
;
10617
10618 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10619
10620 if (ret)
10621 return ret;
10622
10623 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10624 if (ret)
10625 return ret;
10626
10627 if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST &&
10628 cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
10629 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)"
)
;
10630 return -1;
10631 }
10632
10633 if (cfg.file) {
10634 int verify_file;
10635
10636 /* verify the passed in file name and path is valid before getting the dump data */
10637 verify_file = shr_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
10638 if (verify_file < 0) {
10639 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
10640 return -1;
10641 }
10642 close(verify_file);
10643 strncpy(f, cfg.file, PATH_MAX4096 - 1);
10644 } else {
10645 wdc_UtilsGetTime(&timeInfo);
10646 memset(timeStamp, 0, sizeof(timeStamp));
10647 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10648 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10649 timeInfo.hour, timeInfo.minute, timeInfo.second);
10650 if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
10651 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_ctlr_%s", (char *)timeStamp);
10652 else
10653 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_host_%s", (char *)timeStamp);
10654
10655 if (wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix) == -1) {
10656 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
10657 return -1;
10658 }
10659 if (strlen(f) > PATH_MAX4096 - 5) {
10660 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
10661 return -1;
10662 }
10663 strcat(f, ".bin");
10664 }
10665
10666 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
10667
10668 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10669 if ((capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000) == WDC_DRIVE_CAP_REASON_ID0x0000000000010000) {
10670 ret = wdc_do_get_reason_id(hdl, f, cfg.log_id);
10671 } else {
10672 nvme_show_error("ERROR: WDC:unsupported device for this command")nvme_show_message(1, "ERROR: WDC:unsupported device for this command"
)
;
10673 ret = -1;
10674 }
10675
10676 nvme_show_status(ret);
10677
10678 return ret;
10679}
10680
10681static const char *nvme_log_id_to_string(__u8 log_id)
10682{
10683 switch (log_id) {
10684 case NVME_LOG_LID_ERROR:
10685 return "Error Information Log ID";
10686 case NVME_LOG_LID_SMART:
10687 return "Smart/Health Information Log ID";
10688 case NVME_LOG_LID_FW_SLOT:
10689 return "Firmware Slot Information Log ID";
10690 case NVME_LOG_LID_CHANGED_ATTACHED_NS:
10691 return "Attached Namespace Changed Log ID";
10692 case NVME_LOG_LID_CMD_EFFECTS:
10693 return "Commamds Supported and Effects Log ID";
10694 case NVME_LOG_LID_DEVICE_SELF_TEST:
10695 return "Device Self Test Log ID";
10696 case NVME_LOG_LID_TELEMETRY_HOST:
10697 return "Telemetry Host Initiated Log ID";
10698 case NVME_LOG_LID_TELEMETRY_CTRL:
10699 return "Telemetry Controller Generated Log ID";
10700 case NVME_LOG_LID_ENDURANCE_GROUP:
10701 return "Endurance Group Log ID";
10702 case NVME_LOG_LID_ANA:
10703 return "ANA Log ID";
10704 case NVME_LOG_LID_PERSISTENT_EVENT:
10705 return "Persistent Event Log ID";
10706 case NVME_LOG_LID_DISCOVERY:
10707 return "Discovery Log ID";
10708 case NVME_LOG_LID_RESERVATION:
10709 return "Reservation Notification Log ID";
10710 case NVME_LOG_LID_SANITIZE:
10711 return "Sanitize Status Log ID";
10712 case WDC_LOG_ID_C00xC0:
10713 return "WDC Vendor Unique Log ID C0";
10714 case WDC_LOG_ID_C10xC1:
10715 return "WDC Vendor Unique Log ID C1";
10716 case WDC_LOG_ID_C20xC2:
10717 return "WDC Vendor Unique Log ID C2";
10718 case WDC_LOG_ID_C30xC3:
10719 return "WDC Vendor Unique Log ID C3";
10720 case WDC_LOG_ID_C40xC4:
10721 return "WDC Vendor Unique Log ID C4";
10722 case WDC_LOG_ID_C50xC5:
10723 return "WDC Vendor Unique Log ID C5";
10724 case WDC_LOG_ID_C60xC6:
10725 return "WDC Vendor Unique Log ID C6";
10726 case WDC_LOG_ID_C80xC8:
10727 return "WDC Vendor Unique Log ID C8";
10728 case WDC_LOG_ID_CA0xCA:
10729 return "WDC Vendor Unique Log ID CA";
10730 case WDC_LOG_ID_CB0xCB:
10731 return "WDC Vendor Unique Log ID CB";
10732 case WDC_LOG_ID_D00xD0:
10733 return "WDC Vendor Unique Log ID D0";
10734 case WDC_LOG_ID_D10xD1:
10735 return "WDC Vendor Unique Log ID D1";
10736 case WDC_LOG_ID_D60xD6:
10737 return "WDC Vendor Unique Log ID D6";
10738 case WDC_LOG_ID_D70xD7:
10739 return "WDC Vendor Unique Log ID D7";
10740 case WDC_LOG_ID_D80xD8:
10741 return "WDC Vendor Unique Log ID D8";
10742 case WDC_LOG_ID_DE0xDE:
10743 return "WDC Vendor Unique Log ID DE";
10744 case WDC_LOG_ID_F00xF0:
10745 return "WDC Vendor Unique Log ID F0";
10746 case WDC_LOG_ID_F10xF1:
10747 return "WDC Vendor Unique Log ID F1";
10748 case WDC_LOG_ID_F20xF2:
10749 return "WDC Vendor Unique Log ID F2";
10750 case WDC_LOG_ID_FA0xFA:
10751 return "WDC Vendor Unique Log ID FA";
10752 default:
10753 return "Unknown Log ID";
10754 }
10755}
10756
10757static void __json_log_page_directory(struct log_page_directory *directory)
10758{
10759 __u32 bitmap_idx;
10760 __u8 log_id;
10761 struct json_object *root;
10762 struct json_object *entries;
10763
10764 root = json_create_object()json_object_new_object();
10765
10766 entries = json_create_array()json_object_new_array();
10767 json_object_add_value_array(root, "Entries", entries)json_object_object_add(root, "Entries", entries);
10768
10769 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10770 log_id = bitmap_idx;
10771 if (!log_page_name[log_id])
10772 continue;
10773 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10774 struct json_object *json_entry = json_create_object()json_object_new_object();
10775
10776 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))
;
10777 json_object_add_value_string(json_entry, "Log Page Name",
10778 log_page_name[log_id]);
10779
10780 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10781 }
10782 }
10783
10784 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10785 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10786 if (!log_page_name[log_id])
10787 continue;
10788 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10789 struct json_object *json_entry = json_create_object()json_object_new_object();
10790
10791 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))
;
10792 json_object_add_value_string(json_entry, "Log Page Name",
10793 log_page_name[log_id]);
10794
10795 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10796 }
10797 }
10798
10799 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10800 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10801 if (!log_page_name[log_id])
10802 continue;
10803 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10804 struct json_object *json_entry = json_create_object()json_object_new_object();
10805
10806 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))
;
10807 json_object_add_value_string(json_entry, "Log Page Name",
10808 log_page_name[log_id]);
10809
10810 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10811 }
10812 }
10813
10814 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10815 printf("\n");
10816 json_free_object(root)json_object_put(root);
10817}
10818
10819
10820static void __show_log_page_directory(struct log_page_directory *directory)
10821{
10822 __u32 bitmap_idx;
10823 __u8 log_id;
10824
10825 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10826 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10827 log_id = bitmap_idx;
10828 if (log_page_name[log_id])
10829 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10830 }
10831 }
10832
10833 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10834 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10835 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10836 if (log_page_name[log_id])
10837 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10838 }
10839 }
10840
10841 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10842 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10843 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10844 if (log_page_name[log_id])
10845 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10846 }
10847 }
10848}
10849
10850static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
10851 struct plugin *plugin)
10852{
10853 const char *desc = "Retrieve Log Page Directory.";
10854 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10855 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10856 nvme_print_flags_t fmt;
10857 int ret = 0;
10858 __u64 capabilities = 0;
10859 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
10860 int i, uuid_index = 0;
10861 __u8 log_id = 0;
10862 __u32 device_id, read_vendor_id;
10863 bool_Bool uuid_supported = false0;
10864 struct nvme_id_uuid_list uuid_list;
10865
10866 struct config {
10867 char *output_format;
10868 };
10869
10870 struct config cfg = {
10871 .output_format = "normal",
10872 };
10873
10874 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 informational output", 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) } }
;
10875
10876 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10877 if (ret)
10878 return ret;
10879
10880 cfg.output_format = nvme_args.output_format;
10881
10882 ret = validate_output_format(cfg.output_format, &fmt);
10883 if (ret < 0) {
10884 nvme_show_error("%s: ERROR: WDC: invalid output format", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid output format",
__func__)
;
10885 return ret;
10886 }
10887
10888 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10889 if (ret)
10890 return ret;
10891
10892 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10893
10894 if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000)) {
10895 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10896 ret = -1;
10897 } else {
10898 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
10899 if (wdc_CheckUuidListSupport(hdl, &uuid_list))
10900 uuid_supported = true1;
10901
10902 if (uuid_supported)
10903 nvme_show_error("WDC: UUID lists supported")nvme_show_message(1, "WDC: UUID lists supported");
10904 else
10905 nvme_show_error("WDC: UUID lists NOT supported")nvme_show_message(1, "WDC: UUID lists NOT supported");
10906
10907
10908 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
10909 if (ret)
10910 return ret;
10911
10912 log_id = wdc_is_zn350(device_id) ?
10913 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 :
10914 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
10915
10916 if (!wdc_is_sn861(device_id)) {
10917 if (uuid_supported) {
10918 /* check for the Sandisk UUID first */
10919 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
10920
10921 if (uuid_index < 0)
10922 /* The Sandisk UUID is not found;
10923 * check for the WDC UUID second.
10924 */
10925 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
10926 }
10927
10928 /* WD UUID not found, use default uuid index - 0 */
10929 if (uuid_index < 0)
10930 uuid_index = 0;
10931
10932 /* verify the 0xC2 Device Manageability log page is supported */
10933 if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) {
10934 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)
10935 __func__, log_id)nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
;
10936 ret = -1;
10937 goto out;
10938 }
10939
10940 if (!get_dev_mgment_cbs_data(ctx, hdl,
10941 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
10942 (void *)&cbs_data)) {
10943 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
10944 "%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)
10945 __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)
;
10946 ret = -1;
10947 goto out;
10948 }
10949 if (!cbs_data) {
10950 nvme_show_error("%s: ERROR: WDC: NULL_data ptr", __func__)nvme_show_message(1, "%s: ERROR: WDC: NULL_data ptr", __func__
)
;
10951 ret = -1;
10952 goto out;
10953 }
10954 printf("Log Page Directory\n");
10955 /* print the supported pages */
10956 if (!strcmp(cfg.output_format, "normal")) {
10957 for (i = 0; i < le32_to_cpu(cbs_data->length); i++)
10958 printf("0x%x - %s\n", cbs_data->data[i],
10959 nvme_log_id_to_string(cbs_data->data[i]));
10960 } else if (!strcmp(cfg.output_format, "binary")) {
10961 d((__u8 *)cbs_data->data,
10962 le32_to_cpu(cbs_data->length), 16, 1);
10963 } else if (!strcmp(cfg.output_format, "json")) {
10964 struct json_object *root = json_create_object()json_object_new_object();
10965
10966 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
10967 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]))
10968 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]))
10969 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]))
;
10970 }
10971
10972 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10973 printf("\n");
10974 json_free_object(root)json_object_put(root);
10975 } else {
10976 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
10977 "%s: ERROR: WDC: Invalid format, format = %s\n",nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
10978 __func__, cfg.output_format)nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
;
10979 }
10980
10981 free(cbs_data);
10982 } else {
10983 struct log_page_directory *dir;
10984 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *data = NULL((void*)0);
10985
10986 data = libnvme_alloc(512);
10987 if (!data) {
10988 nvme_show_error(nvme_show_message(1, "can not allocate log page directory payload\n"
)
10989 "can not allocate log page directory payload\n")nvme_show_message(1, "can not allocate log page directory payload\n"
)
;
10990 return -ENOMEM12;
10991 }
10992
10993 dir = (struct log_page_directory *)data;
10994 struct libnvme_passthru_cmd cmd = {
10995 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
10996 .cdw10 = 8,
10997 .cdw12 = WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2,
10998 .addr = (__u64)(uintptr_t)data,
10999 .data_len = 32,
11000 };
11001
11002 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11003 if (!ret) {
11004 switch (fmt) {
11005 case BINARY:
11006 d_raw((unsigned char *)data, 32);
11007 break;
11008 case JSON:
11009 __json_log_page_directory(dir);
11010 break;
11011 default:
11012 __show_log_page_directory(dir);
11013 }
11014 } else {
11015 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
11016 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
11017 }
11018 }
11019 }
11020
11021out:
11022 return ret;
11023}
11024
11025static int wdc_get_drive_reason_id(struct libnvme_transport_handle *hdl, char *drive_reason_id, size_t len)
11026{
11027 const char *reason_id_str = "reason_id";
11028 struct libnvme_passthru_cmd cmd;
11029 struct nvme_id_ctrl ctrl;
11030 int res_len = 0;
11031 int i, j;
11032 int ret;
11033
11034 i = sizeof(ctrl.sn) - 1;
11035 j = sizeof(ctrl.mn) - 1;
11036 memset(drive_reason_id, 0, len);
11037 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
11038 nvme_init_identify_ctrl(&cmd, &ctrl);
11039 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11040 if (ret) {
11041 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)
;
11042 return -1;
11043 }
11044 /* Remove trailing spaces from the sn and mn */
11045 while (i && ctrl.sn[i] == ' ') {
11046 ctrl.sn[i] = '\0';
11047 i--;
11048 }
11049
11050 while (j && ctrl.mn[j] == ' ') {
11051 ctrl.mn[j] = '\0';
11052 j--;
11053 }
11054
11055 res_len = snprintf(drive_reason_id, len, "%s_%s_%s", ctrl.sn, ctrl.mn, reason_id_str);
11056 if (len <= res_len) {
11057 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
11058 "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"
)
;
11059 return -1;
11060 }
11061
11062 return 0;
11063}
11064
11065static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size)
11066{
11067 int ret = 0;
11068 char *reason_id_file;
11069 char drive_reason_id[PATH_MAX4096] = {0};
11070 char reason_id_path[PATH_MAX4096] = WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli";
11071 struct stat st = {0};
11072
11073 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11074 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__)
;
11075 return -1;
11076 }
11077
11078 /* make the nvmecli dir in /usr/local if it doesn't already exist */
11079 if (stat(reason_id_path, &st) == -1) {
11080 if (shr_mkdir(reason_id_path, 0700) < 0) {
11081 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 ())))
11082 __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 ())))
;
11083 return -1;
11084 }
11085 }
11086
11087 if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
11088 drive_reason_id, ".bin") < 0)
11089 return -ENOMEM12;
11090
11091 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
)
;
11092
11093 /* save off the error reason identifier to a file in /usr/local/nvmecli */
11094 ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN128);
11095 free(reason_id_file);
11096
11097 return ret;
11098}
11099
11100static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl)
11101{
11102 int ret = -1;
11103 int verify_file;
11104 char *reason_id_file;
11105 char drive_reason_id[PATH_MAX4096] = {0};
11106
11107 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11108 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__)
;
11109 return -1;
11110 }
11111
11112 if (asprintf(&reason_id_file, "%s/%s%s", WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli",
11113 drive_reason_id, ".bin") < 0)
11114 return -ENOMEM12;
11115
11116 /* verify the drive reason id file name and path is valid */
11117 verify_file = shr_open_rawdata(reason_id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((reason_id_file), (01 | 0100 | 01000), 0666);
11118 if (verify_file < 0) {
11119 ret = -1;
11120 goto free;
11121 }
11122 close(verify_file);
11123
11124 /* remove the reason id file */
11125 ret = remove(reason_id_file);
11126
11127free:
11128 free(reason_id_file);
11129
11130 return ret;
11131}
11132
11133static int wdc_dump_telemetry_hdr(struct libnvme_transport_handle *hdl, int log_id, struct nvme_telemetry_log *log_hdr)
11134{
11135 int ret = 0;
11136
11137 if (log_id == NVME_LOG_LID_TELEMETRY_HOST) {
11138 struct libnvme_passthru_cmd cmd;
11139
11140 nvme_init_get_log_create_telemetry_host(&cmd, log_hdr);
11141
11142 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(*log_hdr));
11143 } else {
11144 struct libnvme_passthru_cmd cmd;
11145
11146 nvme_init_get_log_telemetry_ctrl(&cmd, 0, (void *)log_hdr, 512);
11147
11148 ret = libnvme_get_log_dynamic_chunk(hdl, &cmd, false0, 512);
11149 }
11150
11151 if (ret < 0) {
11152 nvme_show_err(ret, "get-telemetry-log");
11153 } else if (ret > 0) {
11154 nvme_show_status(ret);
11155 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)
;
11156 }
11157
11158 return ret;
11159}
11160
11161static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id)
11162{
11163 int ret;
11164 struct nvme_telemetry_log *log_hdr;
11165 __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
11166 __u32 reason_id_size = 0;
11167
11168 log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size);
11169 if (!log_hdr) {
11170 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
())))
;
11171 ret = -1;
11172 goto out;
11173 }
11174 memset(log_hdr, 0, log_hdr_size);
11175
11176 ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr);
11177 if (ret) {
11178 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)
;
11179 ret = -1;
11180 goto out;
11181 }
11182
11183 reason_id_size = sizeof(log_hdr->rsnident);
11184
11185 if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11186 wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size);
11187
11188 ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
11189
11190out:
11191 free(log_hdr);
11192 return ret;
11193}
11194
11195static void wdc_print_nand_stats_normal(__u16 version, void *data)
11196{
11197 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11198 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11199 __u64 temp_raw;
11200 __u16 temp_norm;
11201 __u64 *temp_ptr = NULL((void*)0);
11202
11203 switch (version) {
11204 case 0:
11205 printf(" NAND Statistics :-\n");
11206 printf(" NAND Writes TLC (Bytes) %s\n",
11207 uint128_t_to_string(
11208 le128_to_cpu(nand_stats->nand_write_tlc)));
11209 printf(" NAND Writes SLC (Bytes) %s\n",
11210 uint128_t_to_string(
11211 le128_to_cpu(nand_stats->nand_write_slc)));
11212 printf(" NAND Program Failures %"PRIu32"u""\n",
11213 (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure));
11214 printf(" NAND Erase Failures %"PRIu32"u""\n",
11215 (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure));
11216 printf(" Bad Block Count %"PRIu32"u""\n",
11217 (uint32_t)le32_to_cpu(nand_stats->bad_block_count));
11218 printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"l" "u""\n",
11219 le64_to_cpu(nand_stats->nand_rec_trigger_event));
11220 printf(" E2E Error Counter %"PRIu64"l" "u""\n",
11221 le64_to_cpu(nand_stats->e2e_error_counter));
11222 printf(" Number Successful NS Resizing Events %"PRIu64"l" "u""\n",
11223 le64_to_cpu(nand_stats->successful_ns_resize_event));
11224 printf(" log page version %"PRIu16"hu""\n",
11225 le16_to_cpu(nand_stats->log_page_version));
11226 break;
11227 case 3:
11228 printf(" NAND Statistics V3:-\n");
11229 printf(" TLC Units Written %s\n",
11230 uint128_t_to_string(
11231 le128_to_cpu(nand_stats_v3->nand_write_tlc)));
11232 printf(" SLC Units Written %s\n",
11233 uint128_t_to_string(
11234 le128_to_cpu(nand_stats_v3->nand_write_slc)));
11235 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11236 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11237 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11238 printf(" Bad NAND Blocks Count - Normalized %"PRIu16"hu""\n",
11239 le16_to_cpu(temp_norm));
11240 printf(" Bad NAND Blocks Count - Raw %"PRIu64"l" "u""\n",
11241 le64_to_cpu(temp_raw));
11242 printf(" NAND XOR Recovery count %"PRIu64"l" "u""\n",
11243 le64_to_cpu(nand_stats_v3->xor_recovery_count));
11244 printf(" UECC Read Error count %"PRIu64"l" "u""\n",
11245 le64_to_cpu(nand_stats_v3->uecc_read_error_count));
11246 printf(" SSD End to End corrected errors %"PRIu64"l" "u""\n",
11247 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
11248 printf(" SSD End to End detected errors %"PRIu32"u""\n",
11249 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
11250 printf(" SSD End to End uncorrected E2E errors %"PRIu32"u""\n",
11251 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
11252 printf(" System data %% life-used %u\n",
11253 nand_stats_v3->percent_life_used);
11254 printf(" User Data Erase Counts - TLC Min %"PRIu64"l" "u""\n",
11255 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
11256 printf(" User Data Erase Counts - TLC Max %"PRIu64"l" "u""\n",
11257 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
11258 printf(" User Data Erase Counts - SLC Min %"PRIu64"l" "u""\n",
11259 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
11260 printf(" User Data Erase Counts - SLC Max %"PRIu64"l" "u""\n",
11261 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
11262 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11263 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11264 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11265 printf(" Program Fail Count - Normalized %"PRIu16"hu""\n",
11266 le16_to_cpu(temp_norm));
11267 printf(" Program Fail Count - Raw %"PRIu64"l" "u""\n",
11268 le64_to_cpu(temp_raw));
11269 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11270 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11271 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11272 printf(" Erase Fail Count - Normalized %"PRIu16"hu""\n",
11273 le16_to_cpu(temp_norm));
11274 printf(" Erase Fail Count - Raw %"PRIu64"l" "u""\n",
11275 le64_to_cpu(temp_raw));
11276 printf(" PCIe Correctable Error Count %"PRIu16"hu""\n",
11277 le16_to_cpu(nand_stats_v3->correctable_error_count));
11278 printf(" %% Free Blocks (User) %u\n",
11279 nand_stats_v3->percent_free_blocks_user);
11280 printf(" Security Version Number %"PRIu64"l" "u""\n",
11281 le64_to_cpu(nand_stats_v3->security_version_number));
11282 printf(" %% Free Blocks (System) %u\n",
11283 nand_stats_v3->percent_free_blocks_system);
11284 printf(" Data Set Management Commands %s\n",
11285 uint128_t_to_string(
11286 le128_to_cpu(nand_stats_v3->trim_completions)));
11287 printf(" Estimate of Incomplete Trim Data %"PRIu64"l" "u""\n",
11288 le64_to_cpu(nand_stats_v3->trim_completions[16]));
11289 printf(" %% of completed trim %u\n",
11290 nand_stats_v3->trim_completions[24]);
11291 printf(" Background Back-Pressure-Guage %u\n",
11292 nand_stats_v3->back_pressure_guage);
11293 printf(" Soft ECC Error Count %"PRIu64"l" "u""\n",
11294 le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
11295 printf(" Refresh Count %"PRIu64"l" "u""\n",
11296 le64_to_cpu(nand_stats_v3->refresh_count));
11297 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11298 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11299 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11300 printf(" Bad System Nand Block Count - Normalized %"PRIu16"hu""\n",
11301 le16_to_cpu(temp_norm));
11302 printf(" Bad System Nand Block Count - Raw %"PRIu64"l" "u""\n",
11303 le64_to_cpu(temp_raw));
11304 printf(" Endurance Estimate %s\n",
11305 uint128_t_to_string(
11306 le128_to_cpu(nand_stats_v3->endurance_estimate)));
11307 printf(" Thermal Throttling Count %u\n",
11308 nand_stats_v3->thermal_throttling_st_ct[0]);
11309 printf(" Thermal Throttling Status %u\n",
11310 nand_stats_v3->thermal_throttling_st_ct[1]);
11311 printf(" Unaligned I/O %"PRIu64"l" "u""\n",
11312 le64_to_cpu(nand_stats_v3->unaligned_IO));
11313 printf(" Physical Media Units Read %s\n",
11314 uint128_t_to_string(
11315 le128_to_cpu(nand_stats_v3->physical_media_units)));
11316 printf(" log page version %"PRIu16"hu""\n",
11317 le16_to_cpu(nand_stats_v3->log_page_version));
11318 break;
11319
11320 default:
11321 nvme_show_error("WDC: Nand Stats ERROR: Invalid version")nvme_show_message(1, "WDC: Nand Stats ERROR: Invalid version"
)
;
11322 break;
11323
11324 }
11325}
11326
11327static void wdc_print_nand_stats_json(__u16 version, void *data)
11328{
11329 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11330 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11331 struct json_object *root = json_create_object()json_object_new_object();
11332 __u64 temp_raw;
11333 __u16 temp_norm;
11334 __u64 *temp_ptr = NULL((void*)0);
11335
11336 switch (version) {
11337 case 0:
11338 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)))
11339 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)))
;
11340 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)))
11341 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)))
;
11342 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)))
11343 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)))
;
11344 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)))
11345 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)))
;
11346 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)))
11347 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)))
;
11348 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
)))
11349 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
)))
;
11350 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)))
11351 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)))
;
11352 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
)))
11353 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
)))
;
11354
11355 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11356 printf("\n");
11357 break;
11358 case 3:
11359 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)))
11360 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)))
;
11361 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)))
11362 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)))
;
11363 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11364 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11365 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11366 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)))
11367 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11368 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)))
11369 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11370 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)))
11371 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)))
;
11372 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)))
11373 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)))
;
11374 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])))
11375 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])))
;
11376 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])))
11377 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])))
;
11378 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])))
11379 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])))
;
11380 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))
11381 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))
;
11382 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])))
11383 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])))
;
11384 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])))
11385 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])))
;
11386 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])))
11387 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])))
;
11388 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])))
11389 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])))
;
11390 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11391 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11392 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11393 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)))
11394 le16_to_cpu(temp_norm))json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11395 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)))
11396 le64_to_cpu(temp_raw))json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11397 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11398 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11399 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11400 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)))
11401 le16_to_cpu(temp_norm))json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11402 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)))
11403 le64_to_cpu(temp_raw))json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11404 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)))
11405 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)))
;
11406 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))
11407 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))
;
11408 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)))
11409 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)))
;
11410 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))
11411 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))
;
11412 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)))
11413 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)))
;
11414 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])))
11415 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])))
;
11416 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]))
11417 nand_stats_v3->trim_completions[24])json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
;
11418 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
))
11419 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
))
;
11420 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)))
11421 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)))
;
11422 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)))
11423 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)))
;
11424 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11425 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11426 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11427 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)))
11428 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)))
;
11429 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)))
11430 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)))
;
11431 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)))
11432 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)))
;
11433 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]))
11434 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]))
;
11435 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]))
11436 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]))
;
11437 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)))
11438 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)))
;
11439 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)))
11440 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)))
;
11441 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)))
11442 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)))
;
11443
11444 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11445 printf("\n");
11446 break;
11447 default:
11448 nvme_show_error("%s: Invalid Stats Version = %d", __func__, version)nvme_show_message(1, "%s: Invalid Stats Version = %d", __func__
, version)
;
11449 break;
11450 }
11451
11452 json_free_object(root)json_object_put(root);
11453
11454}
11455
11456static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats)
11457{
11458 printf(" PCIE Statistics :-\n");
11459 printf(" Unsupported Request Error Counter %20"PRIu64"l" "u""\n",
11460 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
11461 printf(" ECRC Error Status Counter %20"PRIu64"l" "u""\n",
11462 le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
11463 printf(" Malformed TLP Status Counter %20"PRIu64"l" "u""\n",
11464 le64_to_cpu(pcie_stats->malformedTlpStatusCount));
11465 printf(" Receiver Overflow Status Counter %20"PRIu64"l" "u""\n",
11466 le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
11467 printf(" Unexpected Completion Status Counter %20"PRIu64"l" "u""\n",
11468 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
11469 printf(" Complete Abort Status Counter %20"PRIu64"l" "u""\n",
11470 le64_to_cpu(pcie_stats->completeAbortStatusCount));
11471 printf(" Completion Timeout Status Counter %20"PRIu64"l" "u""\n",
11472 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
11473 printf(" Flow Control Error Status Counter %20"PRIu64"l" "u""\n",
11474 le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
11475 printf(" Poisoned TLP Status Counter %20"PRIu64"l" "u""\n",
11476 le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
11477 printf(" Dlink Protocol Error Status Counter %20"PRIu64"l" "u""\n",
11478 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
11479 printf(" Advisory Non Fatal Error Status Counter %20"PRIu64"l" "u""\n",
11480 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
11481 printf(" Replay Timer TO Status Counter %20"PRIu64"l" "u""\n",
11482 le64_to_cpu(pcie_stats->replayTimerToStatusCount));
11483 printf(" Replay Number Rollover Status Counter %20"PRIu64"l" "u""\n",
11484 le64_to_cpu(pcie_stats->replayNumRolloverStCount));
11485 printf(" Bad DLLP Status Counter %20"PRIu64"l" "u""\n",
11486 le64_to_cpu(pcie_stats->badDllpStatusCount));
11487 printf(" Bad TLP Status Counter %20"PRIu64"l" "u""\n",
11488 le64_to_cpu(pcie_stats->badTlpStatusCount));
11489 printf(" Receiver Error Status Counter %20"PRIu64"l" "u""\n",
11490 le64_to_cpu(pcie_stats->receiverErrStatusCount));
11491
11492}
11493
11494static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
11495{
11496 struct json_object *root = json_create_object()json_object_new_object();
11497
11498 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
)))
11499 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
)))
;
11500 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)))
11501 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)))
;
11502 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)))
11503 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)))
;
11504
11505 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
)))
11506 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
)))
;
11507 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
)))
11508 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
)))
;
11509 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
)))
11510 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
)))
;
11511 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
)))
11512 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
)))
;
11513 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
)))
11514 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
)))
;
11515 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)))
11516 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)))
;
11517 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
)))
11518 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
)))
;
11519 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
)))
11520 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
)))
;
11521 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
)))
11522 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
)))
;
11523 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
)))
11524 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
)))
;
11525 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)))
11526 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)))
;
11527 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)))
11528 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)))
;
11529 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
)))
11530 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
)))
;
11531
11532 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11533 printf("\n");
11534
11535 json_free_object(root)json_object_put(root);
11536}
11537
11538static int wdc_do_vs_nand_stats_sn810_2(struct libnvme_transport_handle *hdl, char *format)
11539{
11540 nvme_print_flags_t fmt;
11541 uint8_t *data = NULL((void*)0);
11542 int ret;
11543
11544 data = NULL((void*)0);
11545 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
11546 NVME_NSID_ALL);
11547
11548 if (ret) {
11549 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__)
;
11550 goto out;
11551 } else {
11552 ret = validate_output_format(format, &fmt);
11553 if (ret < 0) {
11554 nvme_show_error("ERROR: WDC: %s : invalid output format", __func__)nvme_show_message(1, "ERROR: WDC: %s : invalid output format"
, __func__)
;
11555 goto out;
11556 }
11557
11558 /* parse the data */
11559 switch (fmt) {
11560 case NORMAL:
11561 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS0x1);
11562 break;
11563 case JSON:
11564 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS0x1);
11565 break;
11566 default:
11567 break;
11568 }
11569 }
11570
11571out:
11572 free(data);
11573 return ret;
11574}
11575
11576static int wdc_do_vs_nand_stats(struct libnvme_transport_handle *hdl, char *format)
11577{
11578 nvme_print_flags_t fmt;
11579 uint8_t *output = NULL((void*)0);
11580 __u16 version = 0;
11581 int ret;
11582
11583 output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE0x200, sizeof(uint8_t));
11584 if (!output) {
11585 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
11586 ret = -1;
11587 goto out;
11588 }
11589
11590 ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID0xFB,
11591 (void *)output, WDC_NVME_NAND_STATS_SIZE0x200);
11592 if (ret) {
11593 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__)
;
11594 goto out;
11595 } else {
11596 ret = validate_output_format(format, &fmt);
11597 if (ret < 0) {
11598 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11599 goto out;
11600 }
11601
11602 version = output[WDC_NVME_NAND_STATS_SIZE0x200 - 2];
11603
11604 /* parse the data */
11605 switch (fmt) {
11606 case NORMAL:
11607 wdc_print_nand_stats_normal(version, output);
11608 break;
11609 case JSON:
11610 wdc_print_nand_stats_json(version, output);
11611 break;
11612 default:
11613 break;
11614 }
11615 }
11616
11617out:
11618 free(output);
11619 return ret;
11620}
11621
11622static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd,
11623 struct plugin *plugin)
11624{
11625 const char *desc = "Retrieve NAND statistics.";
11626 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11627 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11628 __u64 capabilities = 0;
11629 uint32_t read_device_id = 0, read_vendor_id = 0;
11630 int ret;
11631
11632 struct config {
11633 char *output_format;
11634 };
11635
11636 struct config cfg = {
11637 .output_format = "normal",
11638 };
11639
11640 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 informational output", 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) } }
;
11641
11642 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11643 if (ret)
11644 return ret;
11645
11646 cfg.output_format = nvme_args.output_format;
11647
11648 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11649 if (ret)
11650 return ret;
11651
11652 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11653
11654 if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200)) {
11655 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11656 ret = -1;
11657 } else {
11658 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11659 if (ret < 0) {
11660 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)
;
11661 return -1;
11662 }
11663
11664 switch (read_device_id) {
11665 case WDC_NVME_SN820CL_DEV_ID0x5037:
11666 ret = wdc_do_vs_nand_stats_sn810_2(hdl,
11667 cfg.output_format);
11668 break;
11669 default:
11670 ret = wdc_do_vs_nand_stats(hdl, cfg.output_format);
11671 break;
11672 }
11673 }
11674
11675 if (ret)
11676 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)
;
11677
11678 return ret;
11679}
11680
11681static int wdc_do_vs_pcie_stats(struct libnvme_transport_handle *hdl,
11682 struct wdc_vs_pcie_stats *pcieStatsPtr)
11683{
11684 int ret;
11685 struct libnvme_passthru_cmd admin_cmd;
11686 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11687
11688 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
11689 admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE0xD1;
11690 admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
11691 admin_cmd.data_len = pcie_stats_size;
11692
11693 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
11694
11695 return ret;
11696}
11697
11698static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd,
11699 struct plugin *plugin)
11700{
11701 const char *desc = "Retrieve PCIE statistics.";
11702 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11703 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11704 nvme_print_flags_t fmt;
11705 int ret;
11706 __u64 capabilities = 0;
11707 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
11708 struct wdc_vs_pcie_stats *pcieStatsPtr = NULL((void*)0);
11709 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11710
11711 struct config {
11712 char *output_format;
11713 };
11714
11715 struct config cfg = {
11716 .output_format = "normal",
11717 };
11718
11719 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 informational output", 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) } }
;
11720
11721 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11722 if (ret)
11723 return ret;
11724
11725 cfg.output_format = nvme_args.output_format;
11726
11727 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11728 if (ret)
11729 return ret;
11730
11731 ret = validate_output_format(cfg.output_format, &fmt);
11732 if (ret < 0) {
11733 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11734 goto out;
11735 }
11736
11737 pcieStatsPtr = libnvme_alloc_huge(pcie_stats_size, &mh);
11738 if (!pcieStatsPtr) {
11739 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 ())))
;
11740 ret = -1;
11741 goto out;
11742 }
11743
11744 memset((void *)pcieStatsPtr, 0, pcie_stats_size);
11745
11746 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11747
11748 if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000)) {
11749 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11750 ret = -1;
11751 } else {
11752 ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr);
11753 if (ret) {
11754 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)
;
11755 } else {
11756 /* parse the data */
11757 switch (fmt) {
11758 case NORMAL:
11759 wdc_print_pcie_stats_normal(pcieStatsPtr);
11760 break;
11761 case JSON:
11762 wdc_print_pcie_stats_json(pcieStatsPtr);
11763 break;
11764 default:
11765 break;
11766 }
11767 }
11768 }
11769out:
11770 return ret;
11771}
11772
11773static int wdc_vs_drive_info(int argc, char **argv,
11774 struct command *command, struct plugin *plugin)
11775{
11776 const char *desc = "Send a vs-drive-info command.";
11777 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11778 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11779 nvme_print_flags_t fmt;
11780 uint64_t capabilities = 0;
11781 int ret;
11782 __le32 result;
11783 __u16 size;
11784 double rev;
11785 struct libnvme_passthru_cmd cmd;
11786 struct nvme_id_ctrl ctrl;
11787 char vsData[32] = {0};
11788 char major_rev = 0, minor_rev = 0;
11789 __u8 *data = NULL((void*)0);
11790 __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
11791 __u16 boot_spec_major = 0, boot_spec_minor = 0;
11792 struct json_object *root = NULL((void*)0);
11793 char formatter[41] = { 0 };
11794 char rev_str[16] = { 0 };
11795 uint32_t read_device_id = -1, read_vendor_id = -1;
11796 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
11797 struct ocp_drive_info info;
11798 __u32 data_len = 0;
11799 unsigned int num_dwords = 0;
11800
11801 struct config {
11802 char *output_format;
11803 };
11804
11805 struct config cfg = {
11806 .output_format = "normal",
11807 };
11808
11809 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 informational output", 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) } }
;
11810
11811 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11812 if (ret)
11813 return ret;
11814
11815 cfg.output_format = nvme_args.output_format;
11816
11817 ret = validate_output_format(cfg.output_format, &fmt);
11818 if (ret < 0) {
11819 nvme_show_error("ERROR: WDC %s invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s invalid output format", __func__
)
;
11820 return ret;
11821 }
11822
11823 /* get the id ctrl data used to fill in drive info below */
11824 nvme_init_identify_ctrl(&cmd, &ctrl);
11825 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11826 if (ret) {
11827 nvme_show_error("ERROR: WDC %s: Identify Controller failed", __func__)nvme_show_message(1, "ERROR: WDC %s: Identify Controller failed"
, __func__)
;
11828 return ret;
11829 }
11830
11831 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11832 if (ret || !wdc_check_device(ctx, hdl))
11833 return -1;
11834
11835 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11836
11837 if ((capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000) == WDC_DRIVE_CAP_INFO0x0000000000080000) {
11838 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11839 if (ret < 0) {
11840 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)
;
11841 goto out;
11842 }
11843
11844 switch (read_device_id) {
11845 case WDC_NVME_SN640_DEV_ID0x2400:
11846 case WDC_NVME_SN640_DEV_ID_10x2401:
11847 case WDC_NVME_SN640_DEV_ID_20x2402:
11848 case WDC_NVME_SN640_DEV_ID_30x2404:
11849 case WDC_NVME_SN650_DEV_ID0x2700:
11850 case WDC_NVME_SN650_DEV_ID_10x2701:
11851 case WDC_NVME_SN650_DEV_ID_20x2702:
11852 case WDC_NVME_SN650_DEV_ID_30x2720:
11853 case WDC_NVME_SN650_DEV_ID_40x2721:
11854 case WDC_NVME_SN655_DEV_ID0x2722:
11855 case WDC_NVME_SN655_DEV_ID_10x2723:
11856 case WDC_NVME_SN560_DEV_ID_10x2712:
11857 case WDC_NVME_SN560_DEV_ID_20x2713:
11858 case WDC_NVME_SN560_DEV_ID_30x2714:
11859 case WDC_NVME_SN550_DEV_ID0x2708:
11860 case WDC_NVME_ZN350_DEV_ID0x5010:
11861 case WDC_NVME_ZN350_DEV_ID_10x5018:
11862 ret = wdc_do_drive_info(hdl, &result);
11863
11864 if (!ret) {
11865 size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
11866 rev = (double)(cpu_to_le32(result) & 0x0000ffff);
11867
11868 if (fmt == NORMAL) {
11869 printf("Drive HW Revision: %4.1f\n", (.1 * rev));
11870 printf("FTL Unit Size: 0x%x KB\n", size);
11871 printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
11872 } else if (fmt == JSON) {
11873 root = json_create_object()json_object_new_object();
11874 sprintf(rev_str, "%4.1f", (.1 * rev));
11875 json_object_add_value_string(root, "Drive HW Revision", rev_str);
11876
11877 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)))
;
11878 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
11879 json_object_add_value_string(root, "Customer SN", formatter);
11880
11881 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11882 printf("\n");
11883
11884 json_free_object(root)json_object_put(root);
11885 }
11886 }
11887 break;
11888 case WDC_NVME_SN730_DEV_ID0x5006:
11889 memcpy(vsData, &ctrl.vs[0], 32);
11890
11891 major_rev = ctrl.sn[12];
11892 minor_rev = ctrl.sn[13];
11893
11894 if (fmt == NORMAL) {
11895 printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev);
11896 printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
11897 } else if (fmt == JSON) {
11898 root = json_create_object()json_object_new_object();
11899 sprintf(rev_str, "%c.%c", major_rev, minor_rev);
11900 json_object_add_value_string(root, "Drive HW Revison", rev_str);
11901 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
11902 json_object_add_value_string(root, "Customer SN", formatter);
11903
11904 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11905 printf("\n");
11906
11907 json_free_object(root)json_object_put(root);
11908 }
11909 break;
11910 case WDC_NVME_SN820CL_DEV_ID0x5037:
11911 /* Get the Drive HW Rev from the C6 Log page */
11912 ret = nvme_get_hw_rev_log(hdl, &data, 0,
11913 NVME_NSID_ALL);
11914 if (!ret) {
11915 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
11916
11917 major_rev = log_data->hw_rev_gdr;
11918
11919 free(data);
11920 data = NULL((void*)0);
11921 } else {
11922 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__)
;
11923 ret = -1;
11924 goto out;
11925 }
11926
11927 /* Get the Smart C0 log page */
11928 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
11929 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11930 ret = -1;
11931 goto out;
11932 }
11933
11934 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
11935 0, NVME_NSID_ALL);
11936
11937 if (!ret) {
11938 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
11939
11940 /* Set the FTL Unit size */
11941 ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
11942
11943 /* Set the Boot Spec Version */
11944 boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
11945 boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
11946
11947 /* Set the Drive Ownership Status */
11948 tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
11949 free(data);
11950 } else {
11951 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__)
;
11952 ret = -1;
11953 goto out;
11954 }
11955
11956 if (fmt == NORMAL) {
11957 printf("Drive HW Revision: %2d\n", major_rev);
11958 printf("FTL Unit Size: %d\n", ftl_unit_size);
11959 printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
11960 printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
11961
11962 } else if (fmt == JSON) {
11963 root = json_create_object()json_object_new_object();
11964
11965 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))
;
11966 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))
;
11967 sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor);
11968 json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
11969 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))
;
11970
11971 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11972 printf("\n");
11973
11974 json_free_object(root)json_object_put(root);
11975 }
11976
11977 break;
11978 case WDC_NVME_SN861_DEV_ID0x2750:
11979 case WDC_NVME_SN861_DEV_ID_10x2751:
11980 case WDC_NVME_SN861_DEV_ID_20x2752:
11981 data_len = sizeof(info);
11982 num_dwords = data_len / 4;
11983 if (data_len % 4 != 0)
11984 num_dwords += 1;
11985
11986 struct libnvme_passthru_cmd cmd = {
11987 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
11988 .cdw10 = num_dwords,
11989 .cdw12 = WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2,
11990 .addr = (__u64)(uintptr_t)&info,
11991 .data_len = data_len,
11992 };
11993 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11994 if (!ret) {
11995 __u16 hw_rev_major, hw_rev_minor;
11996
11997 hw_rev_major = le32_to_cpu(info.hw_revision) / 10;
11998 hw_rev_minor = le32_to_cpu(info.hw_revision) % 10;
11999 if (fmt == NORMAL) {
12000 printf("HW Revision : %" PRIu32"u" ".%" PRIu32"u" "\n",
12001 hw_rev_major, hw_rev_minor);
12002 printf("FTL Unit Size : %" PRIu32"u" "\n",
12003 le32_to_cpu(info.ftl_unit_size));
12004 } else if (fmt == JSON) {
12005 char buf[20];
12006
12007 root = json_create_object()json_object_new_object();
12008
12009 memset((void *)buf, 0, 20);
12010 sprintf(buf, "%" PRIu32"u" ".%" PRIu32"u",
12011 hw_rev_major, hw_rev_minor);
12012
12013 json_object_add_value_string(root,
12014 "hw_revision", buf);
12015 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)))
12016 "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
12017 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)))
;
12018
12019 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12020 printf("\n");
12021 json_free_object(root)json_object_put(root);
12022 }
12023 }
12024 break;
12025 default:
12026 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12027 ret = -1;
12028 break;
12029 }
12030 } else {
12031 nvme_show_error("ERROR: WDC: capability not supported by this device")nvme_show_message(1, "ERROR: WDC: capability not supported by this device"
)
;
12032 ret = -1;
12033 }
12034
12035out:
12036 nvme_show_status(ret);
12037 return ret;
12038}
12039
12040static int wdc_vs_temperature_stats(int argc, char **argv,
12041 struct command *command, struct plugin *plugin)
12042{
12043 const char *desc = "Send a vs-temperature-stats command.";
12044 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12045 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12046 struct libnvme_passthru_cmd cmd;
12047 struct nvme_smart_log smart_log;
12048 struct nvme_id_ctrl id_ctrl;
12049 nvme_print_flags_t fmt;
12050 uint64_t capabilities = 0;
12051 __u64 hctm_tmt;
12052 int temperature, temp_tmt1, temp_tmt2;
12053 int ret;
12054
12055 struct config {
12056 char *output_format;
12057 };
12058
12059 struct config cfg = {
12060 .output_format = "normal",
12061 };
12062
12063 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 informational output", 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) } }
;
12064
12065 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12066 if (ret)
12067 return ret;
12068
12069 cfg.output_format = nvme_args.output_format;
12070
12071 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12072 if (ret)
12073 return ret;
12074
12075 ret = validate_output_format(cfg.output_format, &fmt);
12076 if (ret < 0) {
12077 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12078 goto out;
12079 }
12080
12081 /* check if command is supported */
12082 wdc_check_device(ctx, hdl);
12083 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12084 if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) != WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) {
12085 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12086 ret = -1;
12087 goto out;
12088 }
12089
12090 /* get the temperature stats or report errors */
12091 nvme_init_identify_ctrl(&cmd, &id_ctrl);
12092 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12093 if (ret)
12094 goto out;
12095 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
12096 if (ret)
12097 goto out;
12098
12099 /* convert from kelvins to degrees Celsius */
12100 temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
12101
12102 /* retrieve HCTM Thermal Management Temperatures */
12103 nvme_init_get_features(&cmd, 0x10, NVME_GET_FEATURES_SEL_CURRENT);
12104 libnvme_exec_admin_passthru(hdl, &cmd);
12105 hctm_tmt = cmd.result;
12106 temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
12107 temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
12108
12109 if (fmt == NORMAL) {
12110 /* print the temperature stats */
12111 printf("Temperature Stats for NVME device:%s namespace-id:%x\n",
12112 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
12113
12114 printf("Current Composite Temperature : %d °C\n", temperature);
12115 printf("WCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.wctemp - 273);
12116 printf("CCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.cctemp - 273);
12117 printf("DITT support : 0\n");
12118 printf("HCTM support : %"PRIu16"hu""\n", id_ctrl.hctma);
12119
12120 printf("HCTM Light (TMT1) : %"PRIu16"hu"" °C\n", temp_tmt1);
12121 printf("TMT1 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp1_trans_count);
12122 printf("TMT1 Total Time : %"PRIu32"u""\n", smart_log.thm_temp1_total_time);
12123
12124 printf("HCTM Heavy (TMT2) : %"PRIu16"hu"" °C\n", temp_tmt2);
12125 printf("TMT2 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp2_trans_count);
12126 printf("TMT2 Total Time : %"PRIu32"u""\n", smart_log.thm_temp2_total_time);
12127 printf("Thermal Shutdown Threshold : 95 °C\n");
12128 } else if (fmt == JSON) {
12129 struct json_object *root;
12130
12131 root = json_create_object()json_object_new_object();
12132
12133 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)))
;
12134 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)))
;
12135 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)))
;
12136 json_object_add_value_int(root, "DITT support", 0)json_object_object_add(root, "DITT support", json_object_new_int
(0))
;
12137 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)))
;
12138
12139 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)))
;
12140 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)))
;
12141 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)))
;
12142
12143 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)))
;
12144 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)))
;
12145 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)))
;
12146 json_object_add_value_int(root, "Thermal Shutdown Threshold", 95)json_object_object_add(root, "Thermal Shutdown Threshold", json_object_new_int
(95))
;
12147
12148 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12149 printf("\n");
12150
12151 json_free_object(root)json_object_put(root);
12152 } else {
12153 nvme_show_error("%s: Invalid format", __func__)nvme_show_message(1, "%s: Invalid format", __func__);
12154 }
12155
12156out:
12157 nvme_show_status(ret);
12158 return ret;
12159}
12160
12161static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12162{
12163 const char *desc = "Send a capabilities command.";
12164 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12165 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12166 uint64_t capabilities = 0;
12167 int ret;
12168
12169 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 informational output", 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) } }
;
12170
12171 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12172 if (ret)
12173 return ret;
12174
12175 /* get capabilities */
12176 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12177 if (ret || !wdc_check_device(ctx, hdl))
12178 return -1;
12179
12180 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12181
12182 /* print command and supported status */
12183 printf("WDC Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
12184 printf("cap-diag : %s\n",
12185 capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 ? "Supported" : "Not Supported");
12186 printf("drive-log : %s\n",
12187 capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 ? "Supported" : "Not Supported");
12188 printf("get-crash-dump : %s\n",
12189 capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 ? "Supported" : "Not Supported");
12190 printf("get-pfail-dump : %s\n",
12191 capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 ? "Supported" : "Not Supported");
12192 printf("id-ctrl : Supported\n");
12193 printf("purge : %s\n",
12194 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12195 printf("purge-monitor : %s\n",
12196 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12197 printf("vs-internal-log : %s\n",
12198 capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
? "Supported" : "Not Supported");
12199 printf("vs-nand-stats : %s\n",
12200 capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
12201 printf("vs-smart-add-log : %s\n",
12202 capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
12203 printf("--C0 Log Page : %s\n",
12204 capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
12205 printf("--C1 Log Page : %s\n",
12206 capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
12207 printf("--C3 Log Page : %s\n",
12208 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12209 printf("--CA Log Page : %s\n",
12210 capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
12211 printf("--D0 Log Page : %s\n",
12212 capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
12213 printf("clear-pcie-correctable-errors : %s\n",
12214 capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
12215 printf("drive-essentials : %s\n",
12216 capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 ? "Supported" : "Not Supported");
12217 printf("get-drive-status : %s\n",
12218 capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
12219 printf("clear-assert-dump : %s\n",
12220 capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
12221 printf("drive-resize : %s\n",
12222 capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100 ? "Supported" : "Not Supported");
12223 printf("vs-fw-activate-history : %s\n",
12224 capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" : "Not Supported");
12225 printf("clear-fw-activate-history : %s\n",
12226 capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" : "Not Supported");
12227 printf("vs-telemetry-controller-option: %s\n",
12228 capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
12229 printf("vs-error-reason-identifier : %s\n",
12230 capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
12231 printf("log-page-directory : %s\n",
12232 capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
12233 printf("namespace-resize : %s\n",
12234 capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
12235 printf("vs-drive-info : %s\n",
12236 capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
12237 printf("vs-temperature-stats : %s\n",
12238 capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
12239 printf("cloud-SSD-plugin-version : %s\n",
12240 capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
12241 printf("vs-pcie-stats : %s\n",
12242 capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
12243 printf("get-error-recovery-log : %s\n",
12244 capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
12245 printf("get-dev-capabilities-log : %s\n",
12246 capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
12247 printf("get-unsupported-reqs-log : %s\n",
12248 capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
12249 printf("get-latency-monitor-log : %s\n",
12250 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12251 printf("cloud-boot-SSD-version : %s\n",
12252 capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" : "Not Supported");
12253 printf("vs-cloud-log : %s\n",
12254 capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
12255 printf("vs-hw-rev-log : %s\n",
12256 capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
12257 printf("vs-device_waf : %s\n",
12258 capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
12259 printf("set-latency-monitor-feature : %s\n",
12260 capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
12261 printf("capabilities : Supported\n");
12262 return 0;
12263}
12264
12265static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd,
12266 struct plugin *plugin)
12267{
12268 const char *desc = "Get Cloud SSD Plugin Version command.";
12269 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12270 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12271 uint64_t capabilities = 0;
12272 int ret;
12273
12274 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 informational output", 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) } }
;
12275
12276 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12277 if (ret)
12278 return ret;
12279
12280 /* get capabilities */
12281 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12282 if (ret || !wdc_check_device(ctx, hdl))
12283 return -1;
12284
12285 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12286
12287 if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) {
12288 /* print command and supported status */
12289 printf("WDC Cloud SSD Plugin Version: 1.0\n");
12290 } else {
12291 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12292 }
12293
12294 return 0;
12295}
12296
12297static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd,
12298 struct plugin *plugin)
12299{
12300 const char *desc = "Get Cloud Boot SSD Version command.";
12301 const char *namespace_id = "desired namespace id";
12302 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12303 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12304 uint64_t capabilities = 0;
12305 int ret;
12306 int major = 0, minor = 0;
12307 __u8 *data = NULL((void*)0);
12308 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12309
12310 struct config {
12311 __u32 namespace_id;
12312 };
12313
12314 struct config cfg = {
12315 .namespace_id = NVME_NSID_ALL,
12316 };
12317
12318 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 informational output", 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) } }
12319 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 informational output", 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) } }
;
12320
12321 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12322 if (ret)
12323 return ret;
12324
12325 /* get capabilities */
12326 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12327 if (ret || !wdc_check_device(ctx, hdl))
12328 return -1;
12329
12330 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12331
12332 if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) {
12333 /* Get the 0xC0 Smart Cloud Attribute V1 log data */
12334 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
12335 cfg.namespace_id);
12336
12337 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12338 if (!ret) {
12339 major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12340 minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12341
12342 /* print the version returned from the log page */
12343 printf("HyperScale Boot Version: %d.%d\n", major, minor);
12344 } else {
12345 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"
)
;
12346 ret = -1;
12347 }
12348
12349 free(data);
12350 } else {
12351 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12352 }
12353
12354 return ret;
12355}
12356
12357static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12358{
12359 const char *desc = "Get Enclosure Log.";
12360 const char *file = "Output file pathname.";
12361 const char *size = "Data retrieval transfer size.";
12362 const char *log = "Enclosure Log Page ID.";
12363 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12364 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12365 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *output_file = NULL((void*)0);
12366 FILE *output_fd;
12367 int xfer_size = 0;
12368 int len;
12369 int err = 0;
12370
12371 struct config {
12372 char *file;
12373 __u32 xfer_size;
12374 __u32 log_id;
12375 };
12376
12377 struct config cfg = {
12378 .file = NULL((void*)0),
12379 .xfer_size = 0,
12380 .log_id = 0xffffffff,
12381 };
12382
12383 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 informational output", 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) } }
12384 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 informational output", 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) } }
12385 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 informational output", 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) } }
12386 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 informational output", 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) } }
;
12387
12388 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12389 if (err)
1
Assuming 'err' is 0
2
Taking false branch
12390 return err;
12391
12392 if (!wdc_enc_check_model(hdl))
3
Taking false branch
12393 return -EINVAL22;
12394
12395 if (cfg.log_id > 0xff) {
4
Assuming field 'log_id' is <= 255
5
Taking false branch
12396 nvme_show_error(nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12397 "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)
12398 cfg.log_id)nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
;
12399 return -EINVAL22;
12400 }
12401
12402 if (cfg.xfer_size) {
6
Assuming field 'xfer_size' is 0
7
Taking false branch
12403 xfer_size = cfg.xfer_size;
12404 if (!wdc_check_power_of_2(cfg.xfer_size)) {
12405 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)
12406 __func__, cfg.xfer_size)nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
;
12407 return -EINVAL22;
12408 }
12409 }
12410
12411 /* Log IDs are only for specific enclosures */
12412 if (cfg.log_id) {
8
Assuming field 'log_id' is not equal to 0
12413 xfer_size = (xfer_size
9.1
'xfer_size' is 0
) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000;
9
Taking true branch
10
'?' condition is false
12414 len = !cfg.file ? 0 : strlen(cfg.file);
11
Assuming field 'file' is non-null
12
'?' condition is false
12415 if (len > 0) {
13
Assuming 'len' is > 0
14
Taking true branch
12416 output_file = fopen(cfg.file, "wb");
15
Stream opened here
16
Assuming that 'fopen' is successful
12417 if (!output_file
16.1
'output_file' is non-null
) {
17
Taking false branch
12418 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 ())))
12419 libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
;
12420 return -EINVAL22;
12421 }
12422 output_fd = output_file;
12423 } else {
12424 output_fd = stdoutstdout;
12425 }
12426 if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 ||
18
Assuming field 'log_id' is equal to WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1
12427 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 ||
12428 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 ||
12429 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4) {
12430 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)
12431 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12432 err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size,
19
Opened stream never closed. Potential resource leak
12433 WDC_NVME_ENC_NIC_LOG_SIZE0x400000, output_fd);
12434 } else {
12435 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)
12436 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12437 err = wdc_enc_submit_move_data(hdl, NULL((void*)0), 0, xfer_size, output_fd,
12438 cfg.log_id, 0, 0);
12439 }
12440
12441 if (err == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12442 nvme_show_error("No Log/Crashdump available")nvme_show_message(1, "No Log/Crashdump available");
12443 err = 0;
12444 } else if (err) {
12445 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)
12446 cfg.log_id)nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
;
12447 }
12448 }
12449 return err;
12450}
12451
12452static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len,
12453 int xfer_size, FILE *out, int log_id,
12454 int cdw14, int cdw15)
12455{
12456 uint32_t response_size, more;
12457 int err;
12458 int handle;
12459 uint32_t offset = 0;
12460 char *buf;
12461
12462 buf = malloc(xfer_size);
12463 if (!buf) {
12464 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12465 return -1;
12466 }
12467 /* send something no matter what */
12468 cmd = (len) ? cmd : buf;
12469 len = (len) ? len : 0x20;
12470
12471 struct libnvme_passthru_cmd nvme_cmd = {
12472 .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND0xC9,
12473 .nsid = 0,
12474 .addr = (__u64)(uintptr_t) cmd,
12475 .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t),
12476 .cdw10 = len,
12477 .cdw12 = log_id,
12478 .cdw13 = 0,
12479 .cdw14 = cdw14,
12480 .cdw15 = cdw15,
12481 };
12482
12483 /* Handle to associate send request with receive request */
12484 if (shr_getrandom(&handle, sizeof(handle)) != 0) {
12485 nvme_show_error("%s: ERROR: failed to generate a random handle", __func__)nvme_show_message(1, "%s: ERROR: failed to generate a random handle"
, __func__)
;
12486 free(buf);
12487 return -1;
12488 }
12489 nvme_cmd.cdw11 = handle;
12490
12491#ifdef WDC_NVME_CLI_DEBUG
12492 unsigned char *d = (unsigned char *)nvme_cmd.addr;
12493 unsigned char *md = (unsigned char *)nvme_cmd.metadata;
12494
12495 printf("NVME_ADMIN_COMMAND:\n");
12496 printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ",
12497 nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2);
12498 printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, "
12499 nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10);
12500 printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, "
12501 nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15);
12502 printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n",
12503 nvme_cmd.timeout_ms, nvme_cmd.result, md, d);
12504#endif
12505 nvme_cmd.result = 0;
12506 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12507 if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) {
12508 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)
;
12509 } else if (err) {
12510 nvme_show_error("%s: ERROR: WDC: NVMe Snd Mgmt", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Snd Mgmt", __func__
)
;
12511 nvme_show_status(err);
12512 } else {
12513 if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12514 free(buf);
12515 return WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF;
12516 }
12517
12518 do {
12519 /* Sent request, now go retrieve response */
12520 nvme_cmd.flags = 0;
12521 nvme_cmd.opcode = WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA;
12522 nvme_cmd.addr = (__u64)(uintptr_t) buf;
12523 nvme_cmd.data_len = xfer_size;
12524 nvme_cmd.cdw10 = xfer_size / sizeof(uint32_t);
12525 nvme_cmd.cdw11 = handle;
12526 nvme_cmd.cdw12 = log_id;
12527 nvme_cmd.cdw13 = offset / sizeof(uint32_t);
12528 nvme_cmd.cdw14 = cdw14;
12529 nvme_cmd.cdw15 = cdw15;
12530 nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
12531 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12532 if (err) {
12533 more = 0;
12534 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__
)
;
12535 nvme_show_status(err);
12536 } else {
12537 more = nvme_cmd.result & WDC_RESULT_MORE_DATA0x80000000;
12538 response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA0x80000000;
12539 fwrite(buf, response_size, 1, out);
12540 offset += response_size;
12541 if (more && (response_size & (sizeof(uint32_t)-1))) {
12542 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)
12543 __func__, response_size)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
;
12544 }
12545 }
12546 } while (more);
12547 }
12548
12549 free(buf);
12550 return err;
12551}
12552
12553static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out)
12554{
12555 __u8 *dump_data;
12556 __u32 curr_data_offset, curr_data_len;
12557 int i, ret = -1;
12558 struct libnvme_passthru_cmd admin_cmd;
12559 __u32 dump_length = data_len;
12560 __u32 numd;
12561 __u16 numdu, numdl;
12562
12563 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
12564 if (!dump_data) {
12565 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12566 return -1;
12567 }
12568 memset(dump_data, 0, sizeof(__u8) * dump_length);
12569 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12570 curr_data_offset = 0;
12571 curr_data_len = xfer_size;
12572 i = 0;
12573
12574 numd = (curr_data_len >> 2) - 1;
12575 numdu = numd >> 16;
12576 numdl = numd & 0xffff;
12577 admin_cmd.opcode = nvme_admin_get_log_page;
12578 admin_cmd.nsid = curr_data_offset;
12579 admin_cmd.addr = (__u64)(uintptr_t) dump_data;
12580 admin_cmd.data_len = curr_data_len;
12581 admin_cmd.cdw10 = log_id | (numdl << 16);
12582 admin_cmd.cdw11 = numdu;
12583
12584 while (curr_data_offset < data_len) {
12585#ifdef WDC_NVME_CLI_DEBUG
12586 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)
12587 "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)
12588 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)
12589 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)
;
12590#endif
12591 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
12592 if (ret) {
12593 nvme_show_status(ret);
12594 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)
12595 __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)
;
12596 break;
12597 }
12598
12599 if ((curr_data_offset + xfer_size) <= data_len)
12600 curr_data_len = xfer_size;
12601 else
12602 curr_data_len = data_len - curr_data_offset; /* last transfer */
12603
12604 curr_data_offset += curr_data_len;
12605 numd = (curr_data_len >> 2) - 1;
12606 numdu = numd >> 16;
12607 numdl = numd & 0xffff;
12608 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
12609 admin_cmd.nsid = curr_data_offset;
12610 admin_cmd.data_len = curr_data_len;
12611 admin_cmd.cdw10 = log_id | (numdl << 16);
12612 admin_cmd.cdw11 = numdu;
12613 i++;
12614 }
12615 fwrite(dump_data, data_len, 1, out);
12616 free(dump_data);
12617 return ret;
12618}
12619
12620//------------------------------------------------------------------------------------
12621// Description: set latency monitor feature
12622//
12623int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd,
12624 struct plugin *plugin)
12625{
12626 const char *desc = "Set Latency Monitor feature.";
12627
12628 struct feature_latency_monitor buf = {0,};
12629 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12630 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12631 uint64_t capabilities = 0;
12632 __u64 result;
12633 int ret;
12634
12635 const char *active_bucket_timer_threshold =
12636 "This is the value that loads the Active Bucket Timer Threshold.";
12637 const char *active_threshold_a =
12638 "This is the value that loads into the Active Threshold A.";
12639 const char *active_threshold_b =
12640 "This is the value that loads into the Active Threshold B.";
12641 const char *active_threshold_c =
12642 "This is the value that loads into the Active Threshold C.";
12643 const char *active_threshold_d =
12644 "This is the value that loads into the Active Threshold D.";
12645 const char *active_latency_config =
12646 "This is the value that loads into the Active Latency Configuration.";
12647 const char *active_latency_minimum_window =
12648 "This is the value that loads into the Active Latency Minimum Window.";
12649 const char *debug_log_trigger_enable =
12650 "This is the value that loads into the Debug Log Trigger Enable.";
12651 const char *discard_debug_log = "Discard Debug Log.";
12652 const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable.";
12653
12654 struct config {
12655 __u16 active_bucket_timer_threshold;
12656 __u8 active_threshold_a;
12657 __u8 active_threshold_b;
12658 __u8 active_threshold_c;
12659 __u8 active_threshold_d;
12660 __u16 active_latency_config;
12661 __u8 active_latency_minimum_window;
12662 __u16 debug_log_trigger_enable;
12663 __u8 discard_debug_log;
12664 __u8 latency_monitor_feature_enable;
12665 };
12666
12667 struct config cfg = {
12668 .active_bucket_timer_threshold = 0x7E0,
12669 .active_threshold_a = 0x5,
12670 .active_threshold_b = 0x13,
12671 .active_threshold_c = 0x1E,
12672 .active_threshold_d = 0x2E,
12673 .active_latency_config = 0xFFF,
12674 .active_latency_minimum_window = 0xA,
12675 .debug_log_trigger_enable = 0,
12676 .discard_debug_log = 0,
12677 .latency_monitor_feature_enable = 0x7,
12678 };
12679
12680 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 informational output", 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) } }
12681 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 informational output", 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) } }
12682 &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 informational output", 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) } }
12683 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 informational output", 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) } }
12684 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 informational output", 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) } }
12685 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 informational output", 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) } }
12686 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 informational output", 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) } }
12687 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 informational output", 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) } }
12688 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 informational output", 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) } }
12689 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 informational output", 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) } }
12690 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 informational output", 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) } }
12691 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 informational output", 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) } }
12692 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 informational output", 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) } }
12693 &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 informational output", 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) } }
12694 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 informational output", 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) } }
12695 &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 informational output", 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) } }
12696 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 informational output", 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) } }
12697 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 informational output", 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) } }
12698 &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 informational output", 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) } }
12699 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 informational output", 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) } }
12700 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 informational output", 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) } }
12701 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 informational output", 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) } }
12702 &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 informational output", 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) } }
12703 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 informational output", 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) } }
;
12704
12705 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12706
12707 if (ret < 0)
12708 return ret;
12709
12710 /* get capabilities */
12711 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12712 if (ret || !wdc_check_device(ctx, hdl))
12713 return -1;
12714
12715 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12716
12717 if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000)) {
12718 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12719 return -1;
12720 }
12721
12722 memset(&buf, 0, sizeof(struct feature_latency_monitor));
12723
12724 buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold;
12725 buf.active_threshold_a = cfg.active_threshold_a;
12726 buf.active_threshold_b = cfg.active_threshold_b;
12727 buf.active_threshold_c = cfg.active_threshold_c;
12728 buf.active_threshold_d = cfg.active_threshold_d;
12729 buf.active_latency_config = cfg.active_latency_config;
12730 buf.active_latency_minimum_window = cfg.active_latency_minimum_window;
12731 buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable;
12732 buf.discard_debug_log = cfg.discard_debug_log;
12733 buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable;
12734
12735 ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR0xC5, 1, 0, 0, 0,
12736 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result);
12737
12738 if (ret < 0) {
12739 nvme_show_err(ret, "set-feature");
12740 } else if (!ret) {
12741 printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n",
12742 NVME_FEAT_OCP_LATENCY_MONITOR0xC5);
12743 printf("active bucket timer threshold: 0x%x\n",
12744 buf.active_bucket_timer_threshold);
12745 printf("active threshold a: 0x%x\n", buf.active_threshold_a);
12746 printf("active threshold b: 0x%x\n", buf.active_threshold_b);
12747 printf("active threshold c: 0x%x\n", buf.active_threshold_c);
12748 printf("active threshold d: 0x%x\n", buf.active_threshold_d);
12749 printf("active latency config: 0x%x\n", buf.active_latency_config);
12750 printf("active latency minimum window: 0x%x\n",
12751 buf.active_latency_minimum_window);
12752 printf("debug log trigger enable: 0x%x\n",
12753 buf.debug_log_trigger_enable);
12754 printf("discard debug log: 0x%x\n", buf.discard_debug_log);
12755 printf("latency monitor feature enable: 0x%x\n",
12756 buf.latency_monitor_feature_enable);
12757 } else if (ret > 0)
12758 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
12759 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
12760
12761 return ret;
12762}
12763
12764/*
12765 * Externally available functions used to call the WDC Plugin commands
12766 */
12767int run_wdc_cloud_ssd_plugin_version(int argc, char **argv,
12768 struct command *command,
12769 struct plugin *plugin)
12770{
12771 return wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
12772}
12773
12774int run_wdc_vs_internal_fw_log(int argc, char **argv,
12775 struct command *command,
12776 struct plugin *plugin)
12777{
12778 return wdc_vs_internal_fw_log(argc, argv, command, plugin);
12779}
12780
12781int run_wdc_vs_nand_stats(int argc, char **argv,
12782 struct command *command,
12783 struct plugin *plugin)
12784{
12785 return wdc_vs_nand_stats(argc, argv, command, plugin);
12786}
12787
12788int run_wdc_vs_smart_add_log(int argc, char **argv,
12789 struct command *command,
12790 struct plugin *plugin)
12791{
12792 return wdc_vs_smart_add_log(argc, argv, command, plugin);
12793}
12794
12795int run_wdc_clear_pcie_correctable_errors(int argc, char **argv,
12796 struct command *command,
12797 struct plugin *plugin)
12798{
12799 return wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
12800}
12801
12802int run_wdc_drive_status(int argc, char **argv,
12803 struct command *command,
12804 struct plugin *plugin)
12805{
12806 return wdc_drive_status(argc, argv, command, plugin);
12807}
12808
12809int run_wdc_clear_assert_dump(int argc, char **argv,
12810 struct command *command,
12811 struct plugin *plugin)
12812{
12813 return wdc_clear_assert_dump(argc, argv, command, plugin);
12814}
12815
12816int run_wdc_drive_resize(int argc, char **argv,
12817 struct command *command,
12818 struct plugin *plugin)
12819{
12820 return wdc_drive_resize(argc, argv, command, plugin);
12821}
12822
12823int run_wdc_vs_fw_activate_history(int argc, char **argv,
12824 struct command *command,
12825 struct plugin *plugin)
12826{
12827 return wdc_vs_fw_activate_history(argc, argv, command, plugin);
12828}
12829
12830int run_wdc_clear_fw_activate_history(int argc, char **argv,
12831 struct command *command,
12832 struct plugin *plugin)
12833{
12834 return wdc_clear_fw_activate_history(argc, argv, command, plugin);
12835}
12836
12837int run_wdc_vs_telemetry_controller_option(int argc, char **argv,
12838 struct command *command,
12839 struct plugin *plugin)
12840{
12841 return wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
12842}
12843
12844int run_wdc_reason_identifier(int argc, char **argv,
12845 struct command *command,
12846 struct plugin *plugin)
12847{
12848 return wdc_reason_identifier(argc, argv, command, plugin);
12849}
12850
12851int run_wdc_log_page_directory(int argc, char **argv,
12852 struct command *command,
12853 struct plugin *plugin)
12854{
12855 return wdc_log_page_directory(argc, argv, command, plugin);
12856}
12857
12858int run_wdc_namespace_resize(int argc, char **argv,
12859 struct command *command,
12860 struct plugin *plugin)
12861{
12862 return wdc_namespace_resize(argc, argv, command, plugin);
12863}
12864
12865int run_wdc_vs_drive_info(int argc, char **argv,
12866 struct command *command,
12867 struct plugin *plugin)
12868{
12869 return wdc_vs_drive_info(argc, argv, command, plugin);
12870}
12871
12872int run_wdc_vs_pcie_stats(int argc, char **argv,
12873 struct command *command,
12874 struct plugin *plugin)
12875{
12876 return wdc_vs_pcie_stats(argc, argv, command, plugin);
12877}
12878
12879int run_wdc_get_latency_monitor_log(int argc, char **argv,
12880 struct command *command,
12881 struct plugin *plugin)
12882{
12883 return wdc_get_latency_monitor_log(argc, argv, command, plugin);
12884}
12885
12886int run_wdc_get_error_recovery_log(int argc, char **argv,
12887 struct command *command,
12888 struct plugin *plugin)
12889{
12890 return wdc_get_error_recovery_log(argc, argv, command, plugin);
12891}
12892
12893int run_wdc_get_dev_capabilities_log(int argc, char **argv,
12894 struct command *command,
12895 struct plugin *plugin)
12896{
12897 return wdc_get_dev_capabilities_log(argc, argv, command, plugin);
12898}
12899
12900int run_wdc_get_unsupported_reqs_log(int argc, char **argv,
12901 struct command *command,
12902 struct plugin *plugin)
12903{
12904 return wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
12905}
12906
12907int run_wdc_cloud_boot_SSD_version(int argc, char **argv,
12908 struct command *command,
12909 struct plugin *plugin)
12910{
12911 return wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
12912}
12913
12914int run_wdc_vs_cloud_log(int argc, char **argv,
12915 struct command *command,
12916 struct plugin *plugin)
12917{
12918 return wdc_vs_cloud_log(argc, argv, command, plugin);
12919}
12920
12921int run_wdc_vs_hw_rev_log(int argc, char **argv,
12922 struct command *command,
12923 struct plugin *plugin)
12924{
12925 return wdc_vs_hw_rev_log(argc, argv, command, plugin);
12926}
12927
12928int run_wdc_vs_device_waf(int argc, char **argv,
12929 struct command *command,
12930 struct plugin *plugin)
12931{
12932 return wdc_vs_device_waf(argc, argv, command, plugin);
12933}
12934
12935int run_wdc_set_latency_monitor_feature(int argc, char **argv,
12936 struct command *command,
12937 struct plugin *plugin)
12938{
12939 return wdc_set_latency_monitor_feature(argc, argv, command, plugin);
12940}
12941
12942int run_wdc_vs_temperature_stats(int argc, char **argv,
12943 struct command *command,
12944 struct plugin *plugin)
12945{
12946 return wdc_vs_temperature_stats(argc, argv, command, plugin);
12947}
12948
12949int run_wdc_cu_smart_log(int argc, char **argv,
12950 struct command *command,
12951 struct plugin *plugin)
12952{
12953 return wdc_cu_smart_log(argc, argv, command, plugin);
12954}
12955
12956
12957__u32 run_wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx,
12958 struct libnvme_transport_handle *hdl)
12959{
12960 return wdc_get_fw_cust_id(ctx, hdl);
12961}
12962
12963bool_Bool run_wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
12964 struct libnvme_transport_handle *hdl,
12965 __u8 log_id,
12966 __u8 uuid_index)
12967{
12968 return wdc_nvme_check_supported_log_page(ctx,
12969 hdl,
12970 log_id,
12971 uuid_index);
12972}
12973
12974__u64 run_wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx,
12975 struct libnvme_transport_handle *hdl)
12976{
12977 return wdc_get_drive_capabilities(ctx, hdl);
12978}
12979
12980static struct command wdc_cap_diag_cmd = {
12981 .name = "cap-diag",
12982 .help = "WDC Capture-Diagnostics",
12983 .fn = wdc_cap_diag,
12984};
12985
12986static struct command wdc_drive_log_cmd = {
12987 .name = "drive-log",
12988 .help = "WDC Drive Log",
12989 .fn = wdc_drive_log,
12990};
12991
12992static struct command wdc_get_crash_dump_cmd = {
12993 .name = "get-crash-dump",
12994 .help = "WDC Crash Dump",
12995 .fn = wdc_get_crash_dump,
12996};
12997
12998static struct command wdc_get_pfail_dump_cmd = {
12999 .name = "get-pfail-dump",
13000 .help = "WDC Pfail Dump",
13001 .fn = wdc_get_pfail_dump,
13002};
13003
13004static struct command wdc_id_ctrl_cmd = {
13005 .name = "id-ctrl",
13006 .help = "WDC identify controller",
13007 .fn = wdc_id_ctrl,
13008};
13009
13010static struct command wdc_purge_cmd = {
13011 .name = "purge",
13012 .help = "WDC Purge",
13013 .fn = wdc_purge,
13014};
13015
13016static struct command wdc_purge_monitor_cmd = {
13017 .name = "purge-monitor",
13018 .help = "WDC Purge Monitor",
13019 .fn = wdc_purge_monitor,
13020};
13021
13022static struct command wdc_vs_internal_fw_log_cmd = {
13023 .name = "vs-internal-log",
13024 .help = "WDC Internal Firmware Log",
13025 .fn = wdc_vs_internal_fw_log,
13026};
13027
13028static struct command wdc_vs_nand_stats_cmd = {
13029 .name = "vs-nand-stats",
13030 .help = "WDC NAND Statistics",
13031 .fn = wdc_vs_nand_stats,
13032};
13033
13034static struct command wdc_vs_smart_add_log_cmd = {
13035 .name = "vs-smart-add-log",
13036 .help = "WDC Additional Smart Log",
13037 .fn = wdc_vs_smart_add_log,
13038};
13039
13040static struct command wdc_clear_pcie_correctable_errors_cmd = {
13041 .name = "clear-pcie-correctable-errors",
13042 .help = "WDC Clear PCIe Correctable Error Count",
13043 .fn = wdc_clear_pcie_correctable_errors,
13044};
13045
13046static struct command wdc_drive_essentials_cmd = {
13047 .name = "drive-essentials",
13048 .help = "WDC Drive Essentials",
13049 .fn = wdc_drive_essentials,
13050};
13051
13052static struct command wdc_drive_status_cmd = {
13053 .name = "get-drive-status",
13054 .help = "WDC Get Drive Status",
13055 .fn = wdc_drive_status,
13056};
13057
13058static struct command wdc_clear_assert_dump_cmd = {
13059 .name = "clear-assert-dump",
13060 .help = "WDC Clear Assert Dump",
13061 .fn = wdc_clear_assert_dump,
13062};
13063
13064static struct command wdc_drive_resize_cmd = {
13065 .name = "drive-resize",
13066 .help = "WDC Drive Resize",
13067 .fn = wdc_drive_resize,
13068};
13069
13070static struct command wdc_vs_fw_activate_history_cmd = {
13071 .name = "vs-fw-activate-history",
13072 .help = "WDC Get FW Activate History",
13073 .fn = wdc_vs_fw_activate_history,
13074};
13075
13076static struct command wdc_clear_fw_activate_history_cmd = {
13077 .name = "clear-fw-activate-history",
13078 .help = "WDC Clear FW Activate History",
13079 .fn = wdc_clear_fw_activate_history,
13080};
13081
13082static struct command wdc_enc_get_log_cmd = {
13083 .name = "enc-get-log",
13084 .help = "WDC Get Enclosure Log",
13085 .fn = wdc_enc_get_log,
13086};
13087
13088static struct command wdc_vs_telemetry_controller_option_cmd = {
13089 .name = "vs-telemetry-controller-option",
13090 .help = "WDC Enable/Disable Controller Initiated Telemetry Log",
13091 .fn = wdc_vs_telemetry_controller_option,
13092};
13093
13094static struct command wdc_reason_identifier_cmd = {
13095 .name = "vs-error-reason-identifier",
13096 .help = "WDC Telemetry Reason Identifier",
13097 .fn = wdc_reason_identifier,
13098};
13099
13100static struct command wdc_log_page_directory_cmd = {
13101 .name = "log-page-directory",
13102 .help = "WDC Get Log Page Directory",
13103 .fn = wdc_log_page_directory,
13104};
13105
13106static struct command wdc_namespace_resize_cmd = {
13107 .name = "namespace-resize",
13108 .help = "WDC NamespaceDrive Resize",
13109 .fn = wdc_namespace_resize,
13110};
13111
13112static struct command wdc_vs_drive_info_cmd = {
13113 .name = "vs-drive-info",
13114 .help = "WDC Get Drive Info",
13115 .fn = wdc_vs_drive_info,
13116};
13117
13118static struct command wdc_vs_temperature_stats_cmd = {
13119 .name = "vs-temperature-stats",
13120 .help = "WDC Get Temperature Stats",
13121 .fn = wdc_vs_temperature_stats,
13122};
13123
13124static struct command wdc_capabilities_cmd = {
13125 .name = "capabilities",
13126 .help = "WDC Device Capabilities",
13127 .fn = wdc_capabilities,
13128};
13129
13130static struct command wdc_cloud_ssd_plugin_version_cmd = {
13131 .name = "cloud-SSD-plugin-version",
13132 .help = "WDC Cloud SSD Plugin Version",
13133 .fn = wdc_cloud_ssd_plugin_version,
13134};
13135
13136static struct command wdc_vs_pcie_stats_cmd = {
13137 .name = "vs-pcie-stats",
13138 .help = "WDC VS PCIE Statistics",
13139 .fn = wdc_vs_pcie_stats,
13140};
13141
13142static struct command wdc_get_latency_monitor_log_cmd = {
13143 .name = "get-latency-monitor-log",
13144 .help = "WDC Get Latency Monitor Log Page",
13145 .fn = wdc_get_latency_monitor_log,
13146};
13147
13148static struct command wdc_get_error_recovery_log_cmd = {
13149 .name = "get-error-recovery-log",
13150 .help = "WDC Get Error Recovery Log Page",
13151 .fn = wdc_get_error_recovery_log,
13152};
13153
13154static struct command wdc_get_dev_capabilities_log_cmd = {
13155 .name = "get-dev-capabilities-log",
13156 .help = "WDC Get Device Capabilities Log Page",
13157 .fn = wdc_get_dev_capabilities_log,
13158};
13159
13160static struct command wdc_get_unsupported_reqs_log_cmd = {
13161 .name = "get-unsupported-reqs-log",
13162 .help = "WDC Get Unsupported Requirements Log Page",
13163 .fn = wdc_get_unsupported_reqs_log,
13164};
13165
13166static struct command wdc_cloud_boot_SSD_version_cmd = {
13167 .name = "cloud-boot-SSD-version",
13168 .help = "WDC Get the Cloud Boot SSD Version",
13169 .fn = wdc_cloud_boot_SSD_version,
13170};
13171
13172static struct command wdc_vs_cloud_log_cmd = {
13173 .name = "vs-cloud-log",
13174 .help = "WDC Get the Cloud Log Page",
13175 .fn = wdc_vs_cloud_log,
13176};
13177
13178static struct command wdc_vs_hw_rev_log_cmd = {
13179 .name = "vs-hw-rev-log",
13180 .help = "WDC Get the Hardware Revision Log Page",
13181 .fn = wdc_vs_hw_rev_log,
13182};
13183
13184static struct command wdc_vs_device_waf_cmd = {
13185 .name = "vs-device-waf",
13186 .help = "WDC Calculate Device Write Amplication Factor",
13187 .fn = wdc_vs_device_waf,
13188};
13189
13190static struct command wdc_set_latency_monitor_feature_cmd = {
13191 .name = "set-latency-monitor-feature",
13192 .help = "WDC set Latency Monitor feature",
13193 .fn = wdc_set_latency_monitor_feature,
13194};
13195
13196static struct command wdc_cu_smart_log_cmd = {
13197 .name = "cu-smart-log",
13198 .help = "WDC Get Customer Unique Smart Log",
13199 .fn = wdc_cu_smart_log,
13200};
13201
13202static struct command *commands[] = {
13203 &wdc_cap_diag_cmd,
13204 &wdc_drive_log_cmd,
13205 &wdc_get_crash_dump_cmd,
13206 &wdc_get_pfail_dump_cmd,
13207 &wdc_id_ctrl_cmd,
13208 &wdc_purge_cmd,
13209 &wdc_purge_monitor_cmd,
13210 &wdc_vs_internal_fw_log_cmd,
13211 &wdc_vs_nand_stats_cmd,
13212 &wdc_vs_smart_add_log_cmd,
13213 &wdc_clear_pcie_correctable_errors_cmd,
13214 &wdc_drive_essentials_cmd,
13215 &wdc_drive_status_cmd,
13216 &wdc_clear_assert_dump_cmd,
13217 &wdc_drive_resize_cmd,
13218 &wdc_vs_fw_activate_history_cmd,
13219 &wdc_clear_fw_activate_history_cmd,
13220 &wdc_enc_get_log_cmd,
13221 &wdc_vs_telemetry_controller_option_cmd,
13222 &wdc_reason_identifier_cmd,
13223 &wdc_log_page_directory_cmd,
13224 &wdc_namespace_resize_cmd,
13225 &wdc_vs_drive_info_cmd,
13226 &wdc_vs_temperature_stats_cmd,
13227 &wdc_capabilities_cmd,
13228 &wdc_cloud_ssd_plugin_version_cmd,
13229 &wdc_vs_pcie_stats_cmd,
13230 &wdc_get_latency_monitor_log_cmd,
13231 &wdc_get_error_recovery_log_cmd,
13232 &wdc_get_dev_capabilities_log_cmd,
13233 &wdc_get_unsupported_reqs_log_cmd,
13234 &wdc_cloud_boot_SSD_version_cmd,
13235 &wdc_vs_cloud_log_cmd,
13236 &wdc_vs_hw_rev_log_cmd,
13237 &wdc_vs_device_waf_cmd,
13238 &wdc_set_latency_monitor_feature_cmd,
13239 &wdc_cu_smart_log_cmd,
13240 NULL((void*)0),
13241};
13242
13243static struct plugin plugin = {
13244 .name = "wdc",
13245 .desc = "Western Digital vendor specific extensions",
13246 .version = WDC_PLUGIN_VERSION"2.15.1",
13247};
13248
13249static void __shr_constructor__attribute__((constructor)) register_plugin(void)
13250{
13251 plugin_add_group(&plugin, NULL((void*)0), commands);
13252 register_extension(&plugin);
13253}