Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name 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 pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../plugins/wdc/wdc-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2015-2018 Western Digital Corporation or its affiliates.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 *
20 * Author: Chaitanya Kulkarni <chaitanya.kulkarni@hgst.com>,
21 * Dong Ho <dong.ho@hgst.com>,
22 * Jeff Lien <jeff.lien@wdc.com>
23 * Brandon Paupore <brandon.paupore@wdc.com>
24 */
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28#include <inttypes.h>
29#include <errno(*__errno_location ()).h>
30#include <limits.h>
31#include <fcntl.h>
32#include <unistd.h>
33
34#include <libnvme.h>
35
36#include "common.h"
37#include "nvme-cmds.h"
38#include "nvme-print.h"
39#include "nvme.h"
40#include "plugin.h"
41#include "util/cleanup.h"
42#include "util/types.h"
43
44#define CREATE_CMD
45#include "wdc-nvme.h"
46#include "wdc-utils.h"
47#include "wdc-nvme-cmds.h"
48
49#define WRITE_SIZE(sizeof(__u8) * 4096) (sizeof(__u8) * 4096)
50
51#define WDC_NVME_SUBCMD_SHIFT8 8
52
53#define WDC_NVME_LOG_SIZE_DATA_LEN0x08 0x08
54#define WDC_NVME_LOG_SIZE_HDR_LEN0x08 0x08
55
56/* Enclosure */
57#define WDC_OPENFLEX_MI_DEVICE_MODEL"OpenFlex" "OpenFlex"
58#define WDC_RESULT_MORE_DATA0x80000000 0x80000000
59#define WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF 0x7FFFFFFF
60
61/* Device Config */
62#define WDC_NVME_VID0x1c58 0x1c58
63#define WDC_NVME_VID_20x1b96 0x1b96
64#define WDC_NVME_SNDK_VID0x15b7 0x15b7
65
66#define WDC_NVME_SN100_DEV_ID0x0003 0x0003
67#define WDC_NVME_SN200_DEV_ID0x0023 0x0023
68#define WDC_NVME_SN630_DEV_ID0x2200 0x2200
69#define WDC_NVME_SN630_DEV_ID_10x2201 0x2201
70#define WDC_NVME_SN840_DEV_ID0x2300 0x2300
71#define WDC_NVME_SN840_DEV_ID_10x2500 0x2500
72#define WDC_NVME_SN640_DEV_ID0x2400 0x2400
73#define WDC_NVME_SN640_DEV_ID_10x2401 0x2401
74#define WDC_NVME_SN640_DEV_ID_20x2402 0x2402
75#define WDC_NVME_SN640_DEV_ID_30x2404 0x2404
76#define WDC_NVME_ZN540_DEV_ID0x2600 0x2600
77#define WDC_NVME_SN540_DEV_ID0x2610 0x2610
78#define WDC_NVME_SN650_DEV_ID0x2700 0x2700
79#define WDC_NVME_SN650_DEV_ID_10x2701 0x2701
80#define WDC_NVME_SN650_DEV_ID_20x2702 0x2702
81#define WDC_NVME_SN650_DEV_ID_30x2720 0x2720
82#define WDC_NVME_SN650_DEV_ID_40x2721 0x2721
83#define WDC_NVME_SN655_DEV_ID0x2722 0x2722
84#define WDC_NVME_SN655_DEV_ID_10x2723 0x2723
85#define WDC_NVME_SN860_DEV_ID0x2730 0x2730
86#define WDC_NVME_SN660_DEV_ID0x2704 0x2704
87#define WDC_NVME_SN560_DEV_ID_10x2712 0x2712
88#define WDC_NVME_SN560_DEV_ID_20x2713 0x2713
89#define WDC_NVME_SN560_DEV_ID_30x2714 0x2714
90#define WDC_NVME_SN861_DEV_ID0x2750 0x2750
91#define WDC_NVME_SN861_DEV_ID_10x2751 0x2751
92#define WDC_NVME_SN861_DEV_ID_20x2752 0x2752
93#define WDC_NVME_SNTMP_DEV_ID0x2761 0x2761
94#define WDC_NVME_SNTMP_DEV_ID_10x2763 0x2763
95
96#define WDC_NVME_SNESSD1_DEV_ID_E1L0x2765 0x2765
97#define WDC_NVME_SNESSD1_DEV_ID_E20x2766 0x2766
98#define WDC_NVME_SNESSD1_DEV_ID_E3S0x2767 0x2767
99#define WDC_NVME_SNESSD1_DEV_ID_E3L0x2768 0x2768
100#define WDC_NVME_SNESSD1_DEV_ID_U20x2769 0x2769
101
102/* This id's are no longer supported, delete ?? */
103#define WDC_NVME_SN550_DEV_ID0x2708 0x2708
104
105#define WDC_NVME_SXSLCL_DEV_ID0x2001 0x2001
106#define WDC_NVME_SN520_DEV_ID0x5003 0x5003
107#define WDC_NVME_SN520_DEV_ID_10x5004 0x5004
108#define WDC_NVME_SN520_DEV_ID_20x5005 0x5005
109
110#define WDC_NVME_SN530_DEV_ID_10x5007 0x5007
111#define WDC_NVME_SN530_DEV_ID_20x5008 0x5008
112#define WDC_NVME_SN530_DEV_ID_30x5009 0x5009
113#define WDC_NVME_SN530_DEV_ID_40x500b 0x500b
114#define WDC_NVME_SN530_DEV_ID_50x501d 0x501d
115
116#define WDC_NVME_SN350_DEV_ID0x5019 0x5019
117
118#define WDC_NVME_SN570_DEV_ID0x501A 0x501A
119
120#define WDC_NVME_SN850X_DEV_ID0x5030 0x5030
121
122#define WDC_NVME_SN5000_DEV_ID_10x5034 0x5034
123#define WDC_NVME_SN5000_DEV_ID_20x5035 0x5035
124#define WDC_NVME_SN5000_DEV_ID_30x5036 0x5036
125#define WDC_NVME_SN5000_DEV_ID_40x504A 0x504A
126
127#define WDC_NVME_SN7000S_DEV_ID_10x5039 0x5039
128
129#define WDC_NVME_SN7150_DEV_ID_10x503b 0x503b
130#define WDC_NVME_SN7150_DEV_ID_20x503c 0x503c
131#define WDC_NVME_SN7150_DEV_ID_30x503d 0x503d
132#define WDC_NVME_SN7150_DEV_ID_40x503e 0x503e
133#define WDC_NVME_SN7150_DEV_ID_50x503f 0x503f
134
135#define WDC_NVME_SN7100_DEV_ID_10x5043 0x5043
136#define WDC_NVME_SN7100_DEV_ID_20x5044 0x5044
137#define WDC_NVME_SN7100_DEV_ID_30x5045 0x5045
138
139#define WDC_NVME_SN8000S_DEV_ID0x5049 0x5049
140
141#define WDC_NVME_SN720_DEV_ID0x5002 0x5002
142#define WDC_NVME_SN730_DEV_ID0x5006 0x5006
143#define WDC_NVME_SN740_DEV_ID0x5015 0x5015
144#define WDC_NVME_SN740_DEV_ID_10x5016 0x5016
145#define WDC_NVME_SN740_DEV_ID_20x5017 0x5017
146#define WDC_NVME_SN740_DEV_ID_30x5025 0x5025
147#define WDC_NVME_SN340_DEV_ID0x500d 0x500d
148#define WDC_NVME_ZN350_DEV_ID0x5010 0x5010
149#define WDC_NVME_ZN350_DEV_ID_10x5018 0x5018
150#define WDC_NVME_SN810_DEV_ID0x5011 0x5011
151#define WDC_NVME_SN820CL_DEV_ID0x5037 0x5037
152
153#define WDC_NVME_SN5100S_DEV_ID_10x5061 0x5061
154#define WDC_NVME_SN5100S_DEV_ID_20x5062 0x5062
155#define WDC_NVME_SN5100S_DEV_ID_30x5063 0x5063
156
157/* Shared flag space with SNDK plugin, should be kept in sync */
158#define WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 0x0000000000000001
159#define WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 0x0000000000000002
160#define WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 0x0000000000000004
161#define WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 0x0000000000000008
162#define WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 0x0000000000000010
163#define WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 0x0000000000000020
164#define WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 0x0000000000000040
165#define WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 0x0000000000000080
166#define WDC_DRIVE_CAP_RESIZE0x0000000000000100 0x0000000000000100
167#define WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 0x0000000000000200
168#define WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 0x0000000000000400
169#define WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 0x0000000000000800
170#define WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 0x0000000000001000
171#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 0x0000000000002000
172#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 0x0000000000004000
173#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 0x0000000000008000
174#define WDC_DRIVE_CAP_REASON_ID0x0000000000010000 0x0000000000010000
175#define WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 0x0000000000020000
176#define WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 0x0000000000040000
177#define WDC_DRIVE_CAP_INFO0x0000000000080000 0x0000000000080000
178#define WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 0x0000000000100000
179#define WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 0x0000000000200000
180#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 0x0000000000400000
181#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 0x0000000000800000
182#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 0x0000000001000000
183#define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 0x0000000002000000
184#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 0x0000000004000000
185#define WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 0x0000000008000000
186#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 0x0000000010000000
187#define WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 0x0000000020000000
188#define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 0x0000000040000000
189#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 0x0000000080000000
190#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 0x0000000100000000
191#define WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 0x0000000200000000
192#define WDC_SN730B_CAP_VUC_LOG0x0000000400000000 0x0000000400000000
193#define WDC_DRIVE_CAP_DUI0x0000000800000000 0x0000000800000000
194#define WDC_DRIVE_CAP_PURGE0x0000001000000000 0x0000001000000000
195#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 0x0000002000000000
196#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 0x0000004000000000
197#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 0x0000008000000000
198#define WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 0x0000010000000000
199#define WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 0x0000020000000000
200#define WDC_DRIVE_CAP_UDUI0x0000040000000000 0x0000040000000000
201#define WDC_DRIVE_CAP_RESIZE_SN8610x0000080000000000 0x0000080000000000
202
203/* Any new capability flags should be added to the SNDK plugin */
204
205#define WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
(WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | \
206 WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 | \
207 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | \
208 WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010)
209#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
(WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 | \
210 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | \
211 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000)
212#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | \
213 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000)
214#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | \
215 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000)
216#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
(WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | \
217 WDC_DRIVE_CAP_DUI0x0000000800000000 | \
218 WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | \
219 WDC_SN730B_CAP_VUC_LOG0x0000000400000000)
220
221/* SN730 Get Log Capabilities */
222#define SN730_NVME_GET_LOG_OPCODE0xc2 0xc2
223#define SN730_GET_FULL_LOG_LENGTH0x00080009 0x00080009
224#define SN730_GET_KEY_LOG_LENGTH0x00090009 0x00090009
225#define SN730_GET_COREDUMP_LOG_LENGTH0x00120009 0x00120009
226#define SN730_GET_EXTENDED_LOG_LENGTH0x00420009 0x00420009
227
228#define SN730_GET_FULL_LOG_SUBOPCODE0x00010009 0x00010009
229#define SN730_GET_KEY_LOG_SUBOPCODE0x00020009 0x00020009
230#define SN730_GET_CORE_LOG_SUBOPCODE0x00030009 0x00030009
231#define SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009 0x00040009
232#define SN730_LOG_CHUNK_SIZE0x1000 0x1000
233
234/* Customer ID's */
235#define WDC_CUSTOMER_ID_GN0x0001 0x0001
236#define WDC_CUSTOMER_ID_GD0x0101 0x0101
237#define WDC_CUSTOMER_ID_BD0x1009 0x1009
238
239#define WDC_CUSTOMER_ID_0x00F00x00F0 0x00F0
240#define WDC_CUSTOMER_ID_0x10040x1004 0x1004
241#define WDC_CUSTOMER_ID_0x10050x1005 0x1005
242#define WDC_CUSTOMER_ID_0x10080x1008 0x1008
243#define WDC_CUSTOMER_ID_0x13040x1304 0x1304
244#define WDC_INVALID_CUSTOMER_ID-1 -1
245
246#define WDC_ALL_PAGE_MASK0xFFFF 0xFFFF
247#define WDC_C0_PAGE_MASK0x0001 0x0001
248#define WDC_C1_PAGE_MASK0x0002 0x0002
249#define WDC_CA_PAGE_MASK0x0004 0x0004
250#define WDC_D0_PAGE_MASK0x0008 0x0008
251
252/* Drive Resize */
253#define WDC_NVME_DRIVE_RESIZE_OPCODE0xCC 0xCC
254#define WDC_NVME_DRIVE_RESIZE_CMD0x03 0x03
255#define WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 0x01
256
257/* Namespace Resize */
258#define WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB 0xFB
259
260/* Drive Info */
261#define WDC_NVME_DRIVE_INFO_OPCODE0xC6 0xC6
262#define WDC_NVME_DRIVE_INFO_CMD0x22 0x22
263#define WDC_NVME_DRIVE_INFO_SUBCMD0x06 0x06
264
265/* VS PCIE Stats */
266#define WDC_NVME_PCIE_STATS_OPCODE0xD1 0xD1
267
268/* Capture Diagnostics */
269#define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
270#define WDC_NVME_CAP_DIAG_OPCODE0xE6 0xE6
271#define WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6 0xC6
272#define WDC_NVME_CAP_DIAG_SUBCMD0x00 0x00
273#define WDC_NVME_CAP_DIAG_CMD0x00 0x00
274
275#define WDC_NVME_CRASH_DUMP_TYPE1 1
276#define WDC_NVME_PFAIL_DUMP_TYPE2 2
277
278/* Capture Device Unit Info */
279#define WDC_NVME_CAP_DUI_HEADER_SIZE0x400 0x400
280#define WDC_NVME_CAP_DUI_OPCODE0xFA 0xFA
281#define WDC_NVME_CAP_DUI_DISABLE_IO0x01 0x01
282#define WDC_NVME_DUI_MAX_SECTION0x3A 0x3A
283#define WDC_NVME_DUI_MAX_SECTION_V20x26 0x26
284#define WDC_NVME_DUI_MAX_SECTION_V30x23 0x23
285#define WDC_NVME_DUI_MAX_DATA_AREA0x05 0x05
286#define WDC_NVME_SN730_SECTOR_SIZE512 512
287
288/* Telemtery types for vs-internal-log command */
289#define WDC_TELEMETRY_TYPE_NONE0x0 0x0
290#define WDC_TELEMETRY_TYPE_HOST0x1 0x1
291#define WDC_TELEMETRY_TYPE_CONTROLLER0x2 0x2
292#define WDC_TELEMETRY_HEADER_LENGTH512 512
293#define WDC_TELEMETRY_BLOCK_SIZE512 512
294
295/* Crash dump */
296#define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
297#define WDC_NVME_CRASH_DUMP_SIZE_NDT0x02 0x02
298#define WDC_NVME_CRASH_DUMP_SIZE_CMD0x20 0x20
299#define WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 0x03
300
301#define WDC_NVME_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
302#define WDC_NVME_CRASH_DUMP_CMD0x20 0x20
303#define WDC_NVME_CRASH_DUMP_SUBCMD0x04 0x04
304
305/* PFail Crash dump */
306#define WDC_NVME_PF_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_HDR_LEN0x08
307#define WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02 0x02
308#define WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20 0x20
309#define WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 0x05
310
311#define WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
312#define WDC_NVME_PF_CRASH_DUMP_CMD0x20 0x20
313#define WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 0x06
314
315/* Drive Log */
316#define WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
317#define WDC_NVME_DRIVE_LOG_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
318#define WDC_NVME_DRIVE_LOG_SIZE_NDT0x02 0x02
319#define WDC_NVME_DRIVE_LOG_SIZE_CMD0x20 0x20
320#define WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 0x01
321
322#define WDC_NVME_DRIVE_LOG_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
323#define WDC_NVME_DRIVE_LOG_CMD0x20 0x20
324#define WDC_NVME_DRIVE_LOG_SUBCMD0x00 0x00
325
326/* Purge and Purge Monitor */
327#define WDC_NVME_PURGE_CMD_OPCODE0xDD 0xDD
328#define WDC_NVME_PURGE_MONITOR_OPCODE0xDE 0xDE
329#define WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F 0x2F
330#define WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C 0x0000000C
331#define WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530 0x7530
332#define WDC_NVME_PURGE_CMD_SEQ_ERR0x0C 0x0C
333#define WDC_NVME_PURGE_INT_DEV_ERR0x06 0x06
334
335#define WDC_NVME_PURGE_STATE_IDLE0x00 0x00
336#define WDC_NVME_PURGE_STATE_DONE0x01 0x01
337#define WDC_NVME_PURGE_STATE_BUSY0x02 0x02
338#define WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03 0x03
339#define WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04 0x04
340
341/* Clear dumps */
342#define WDC_NVME_CLEAR_DUMP_OPCODE0xFF 0xFF
343#define WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03 0x03
344#define WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 0x05
345#define WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 0x06
346
347/* Clear FW Activate History */
348#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6 0xC6
349#define WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23 0x23
350#define WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 0x05
351#define WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1 0xC1
352
353/* Additional Smart Log */
354#define WDC_ADD_LOG_BUF_LEN0x4000 0x4000
355#define WDC_NVME_ADD_LOG_OPCODE0xC1 0xC1
356#define WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37 0x37
357#define WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F 0x0F
358
359/* C2 Log Page */
360#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2 0xC2
361#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 0xC8
362#define WDC_C2_LOG_BUF_LEN0x1000 0x1000
363#define WDC_C2_MARKETING_NAME_ID0x07 0x07
364#define WDC_C2_LOG_PAGES_SUPPORTED_ID0x08 0x08
365#define WDC_C2_CUSTOMER_ID_ID0x15 0x15
366#define WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18 0x18
367#define WDC_C2_ASSERT_DUMP_PRESENT_ID0x19 0x19
368#define WDC_C2_USER_EOL_STATUS_ID0x1A 0x1A
369#define WDC_C2_USER_EOL_STATE_ID0x1C 0x1C
370#define WDC_C2_SYSTEM_EOL_STATE_ID0x1D 0x1D
371#define WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E 0x1E
372#define WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
373#define WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
374#define WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
375#define WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
376#define WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
377#define WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
378#define WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
379#define WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
380#define WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
381#define WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
382#define WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF) cpu_to_le32(0x000000FF)
383#define WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861" "Ultrastar DC SN861"
384#define WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861" "ULTRASTAR DC SN861"
385
386/* CA Log Page */
387#define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA 0xCA
388#define WDC_FB_CA_LOG_BUF_LEN0x80 0x80
389/* Added 4 padding bytes to resolve build warning messages */
390#define WDC_BD_CA_LOG_BUF_LEN0xA0 0xA0
391
392/* C0 EOL Status Log Page */
393#define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0 0xC0
394#define WDC_NVME_EOL_STATUS_LOG_LEN0x200 0x200
395#define WDC_NVME_SMART_CLOUD_ATTR_LEN0x200 0x200
396
397/* C0 SMART Cloud Attributes Log Page*/
398#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0 0xC0
399
400/* CB - FW Activate History Log Page */
401#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB 0xCB
402#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0 0x3d0
403
404/* C2 - FW Activation History Log Page */
405#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2 0xC2
406#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000 0x1000
407#define WDC_MAX_NUM_ACT_HIST_ENTRIES20 20
408#define WDC_C2_GUID_LENGTH16 16
409
410/* C3 Latency Monitor Log Page */
411#define WDC_LATENCY_MON_LOG_BUF_LEN0x200 0x200
412#define WDC_LATENCY_MON_LOG_ID0xC3 0xC3
413#define WDC_LATENCY_MON_VERSION0x0001 0x0001
414
415#define WDC_C3_GUID_LENGTH16 16
416static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH16] = {
417 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c,
418 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85
419};
420
421/* D0 Smart Log Page */
422#define WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0 0xD0
423#define WDC_NVME_VU_SMART_LOG_LEN0x200 0x200
424
425/* Log Page Directory defines */
426#define NVME_LOG_PERSISTENT_EVENT0x0D 0x0D
427#define WDC_LOG_ID_C00xC0 0xC0
428#define WDC_LOG_ID_C10xC1 0xC1
429#define WDC_LOG_ID_C20xC2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2
430#define WDC_LOG_ID_C30xC3 0xC3
431#define WDC_LOG_ID_C40xC4 0xC4
432#define WDC_LOG_ID_C50xC5 0xC5
433#define WDC_LOG_ID_C60xC6 0xC6
434#define WDC_LOG_ID_C80xC8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8
435#define WDC_LOG_ID_CA0xCA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA
436#define WDC_LOG_ID_CB0xCB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB
437#define WDC_LOG_ID_D00xD0 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0
438#define WDC_LOG_ID_D10xD1 0xD1
439#define WDC_LOG_ID_D60xD6 0xD6
440#define WDC_LOG_ID_D70xD7 0xD7
441#define WDC_LOG_ID_D80xD8 0xD8
442#define WDC_LOG_ID_DE0xDE 0xDE
443#define WDC_LOG_ID_F00xF0 0xF0
444#define WDC_LOG_ID_F10xF1 0xF1
445#define WDC_LOG_ID_F20xF2 0xF2
446#define WDC_LOG_ID_FA0xFA 0xFA
447
448/* Clear PCIe Correctable Errors */
449#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
450#define WDC_NVME_CLEAR_PCIE_CORR_CMD0x22 0x22
451#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 0x04
452#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2 0xD2
453#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3 0xC3
454/* Clear Assert Dump Status */
455#define WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8 0xD8
456#define WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03 0x03
457#define WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 0x05
458
459#define WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2 0xD2
460
461/* Drive Essentials */
462#define WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64 64
463#define WDC_DE_GENERIC_BUFFER_SIZE80 80
464#define WDC_DE_GLOBAL_NSID0xFFFFFFFF 0xFFFFFFFF
465#define WDC_DE_DEFAULT_NAMESPACE_ID0x01 0x01
466#define WDC_DE_PATH_SEPARATOR"/" "/"
467#define WDC_DE_TAR_FILES"*.bin" "*.bin"
468#define WDC_DE_TAR_FILE_EXTN".tar.gz" ".tar.gz"
469#define WDC_DE_TAR_CMD"tar -czf" "tar -czf"
470
471/* VS NAND Stats */
472#define WDC_NVME_NAND_STATS_LOG_ID0xFB 0xFB
473#define WDC_NVME_NAND_STATS_SIZE0x200 0x200
474
475/* VU Opcodes */
476#define WDC_DE_VU_READ_SIZE_OPCODE0xC0 0xC0
477#define WDC_DE_VU_READ_BUFFER_OPCODE0xC2 0xC2
478#define WDC_NVME_ADMIN_ENC_MGMT_SND0xC9 0xC9
479#define WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA 0xCA
480
481#define WDC_DE_FILE_HEADER_SIZE4 4
482#define WDC_DE_FILE_OFFSET_SIZE2 2
483#define WDC_DE_FILE_NAME_SIZE32 32
484#define WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000 0x8000
485#define WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 0x8000
486
487#define WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info" "manufacturing_info" /* Unique log entry page name. */
488#define WDC_DE_CORE_DUMP_FILE_NAME"core_dump" "core_dump"
489#define WDC_DE_EVENT_LOG_FILE_NAME"event_log" "event_log"
490#define WDC_DE_DESTN_SPI1 1
491#define WDC_DE_DUMPTRACE_DESTINATION6 6
492
493#define NVME_ID_CTRL_MODEL_NUMBER_SIZE40 40
494#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE20 20
495
496/* Enclosure log */
497#define WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000 0x1000
498#define WDC_NVME_ENC_NIC_LOG_SIZE0x400000 0x400000
499
500/* Enclosure nic crash dump get-log id */
501#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 0xD1
502#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 0xD2
503#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 0xD3
504#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4 0xD4
505#define WDC_ENC_CRASH_DUMP_ID0xE4 0xE4
506#define WDC_ENC_LOG_DUMP_ID0xE2 0xE2
507
508/* OCP Log Page Directory Data Structure */
509#define BYTE_TO_BIT(byte)((byte) * 8) ((byte) * 8)
510
511/* Set latency monitor feature */
512#define NVME_FEAT_OCP_LATENCY_MONITOR0xC5 0xC5
513
514enum _NVME_FEATURES_SELECT {
515 FS_CURRENT = 0,
516 FS_DEFAULT = 1,
517 FS_SAVED = 2,
518 FS_SUPPORTED_CAPBILITIES = 3
519};
520
521enum NVME_FEATURE_IDENTIFIERS {
522 FID_ARBITRATION = 0x01,
523 FID_POWER_MANAGEMENT = 0x02,
524 FID_LBA_RANGE_TYPE = 0x03,
525 FID_TEMPERATURE_THRESHOLD = 0x04,
526 FID_ERROR_RECOVERY = 0x05,
527 FID_VOLATILE_WRITE_CACHE = 0x06,
528 FID_NUMBER_OF_QUEUES = 0x07,
529 FID_INTERRUPT_COALESCING = 0x08,
530 FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
531 FID_WRITE_ATOMICITY = 0x0A,
532 FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B,
533 FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C,
534 /*Below FID's are NVM Command Set Specific*/
535 FID_SOFTWARE_PROGRESS_MARKER = 0x80,
536 FID_HOST_IDENTIFIER = 0x81,
537 FID_RESERVATION_NOTIFICATION_MASK = 0x82,
538 FID_RESERVATION_PERSISTENCE = 0x83
539};
540
541/* WDC UUID value */
542static const __u8 WDC_UUID[NVME_UUID_LEN16] = {
543 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15,
544 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
545};
546
547/* WDC_UUID value for SN640_3 devices */
548static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN16] = {
549 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
550 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
551};
552
553/* Sandisk UUID value */
554static const __u8 SNDK_UUID[NVME_UUID_LEN16] = {
555 0xde, 0x87, 0xd1, 0xeb, 0x72, 0xc5, 0x58, 0x0b,
556 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70
557};
558
559enum WDC_DRIVE_ESSENTIAL_TYPE {
560 WDC_DE_TYPE_IDENTIFY = 0x1,
561 WDC_DE_TYPE_SMARTATTRIBUTEDUMP = 0x2,
562 WDC_DE_TYPE_EVENTLOG = 0x4,
563 WDC_DE_TYPE_DUMPTRACE = 0x8,
564 WDC_DE_TYPE_DUMPSNAPSHOT = 0x10,
565 WDC_DE_TYPE_ATA_LOGS = 0x20,
566 WDC_DE_TYPE_SMART_LOGS = 0x40,
567 WDC_DE_TYPE_SCSI_LOGS = 0x80,
568 WDC_DE_TYPE_SCSI_MODE_PAGES = 0x100,
569 WDC_DE_TYPE_NVMe_FEATURES = 0x200,
570 WDC_DE_TYPE_DUMPSMARTERRORLOG3 = 0x400,
571 WDC_DE_TYPE_DUMPLOG3E = 0x800,
572 WDC_DE_TYPE_DUMPSCRAM = 0x1000,
573 WDC_DE_TYPE_PCU_LOG = 0x2000,
574 WDC_DE_TYPE_DUMP_ERROR_LOGS = 0x4000,
575 WDC_DE_TYPE_FW_SLOT_LOGS = 0x8000,
576 WDC_DE_TYPE_MEDIA_SETTINGS = 0x10000,
577 WDC_DE_TYPE_SMART_DATA = 0x20000,
578 WDC_DE_TYPE_NVME_SETTINGS = 0x40000,
579 WDC_DE_TYPE_NVME_ERROR_LOGS = 0x80000,
580 WDC_DE_TYPE_NVME_LOGS = 0x100000,
581 WDC_DE_TYPE_UART_LOGS = 0x200000,
582 WDC_DE_TYPE_DLOGS_SPI = 0x400000,
583 WDC_DE_TYPE_DLOGS_RAM = 0x800000,
584 WDC_DE_TYPE_NVME_MANF_INFO = 0x2000000,
585 WDC_DE_TYPE_NONE = 0x1000000,
586 WDC_DE_TYPE_ALL = 0xFFFFFFF,
587};
588
589#define WDC_C0_GUID_LENGTH16 16
590#define WDC_SCA_V1_NAND_STATS0x1 0x1
591#define WDC_SCA_V1_ALL0xF 0xF
592enum {
593 SCAO_V1_PMUWT = 0, /* Physical media units written TLC */
594 SCAO_V1_PMUWS = 16, /* Physical media units written SLC */
595 SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */
596 SCAO_V1_BUNBR = 34, /* Bad user nand blocks raw */
597 SCAO_V1_XRC = 40, /* XOR recovery count */
598 SCAO_V1_UREC = 48, /* Uncorrectable read error count */
599 SCAO_V1_EECE = 56, /* End to end corrected errors */
600 SCAO_V1_EEDE = 64, /* End to end detected errors */
601 SCAO_V1_EEUE = 72, /* End to end uncorrected errors */
602 SCAO_V1_SDPU = 80, /* System data percent used */
603 SCAO_V1_MNUDEC = 84, /* Min User data erase counts (TLC) */
604 SCAO_V1_MXUDEC = 92, /* Max User data erase counts (TLC) */
605 SCAO_V1_AVUDEC = 100, /* Average User data erase counts (TLC) */
606 SCAO_V1_MNEC = 108, /* Min Erase counts (SLC) */
607 SCAO_V1_MXEC = 116, /* Max Erase counts (SLC) */
608 SCAO_V1_AVEC = 124, /* Average Erase counts (SLC) */
609 SCAO_V1_PFCN = 132, /* Program fail count normalized */
610 SCAO_V1_PFCR = 134, /* Program fail count raw */
611 SCAO_V1_EFCN = 140, /* Erase fail count normalized */
612 SCAO_V1_EFCR = 142, /* Erase fail count raw */
613 SCAO_V1_PCEC = 148, /* PCIe correctable error count */
614 SCAO_V1_PFBU = 156, /* Percent free blocks (User) */
615 SCAO_V1_SVN = 160, /* Security Version Number */
616 SCAO_V1_PFBS = 168, /* Percent free blocks (System) */
617 SCAO_V1_DCC = 172, /* Deallocate Commands Completed */
618 SCAO_V1_TNU = 188, /* Total Namespace Utilization */
619 SCAO_V1_FCC = 196, /* Format NVM Commands Completed */
620 SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */
621 SCAO_V1_SEEC = 202, /* Soft ECC error count */
622 SCAO_V1_RFSC = 210, /* Refresh count */
623 SCAO_V1_BSNBN = 218, /* Bad system nand blocks normalized */
624 SCAO_V1_BSNBR = 220, /* Bad system nand blocks raw */
625 SCAO_V1_EEST = 226, /* Endurance estimate */
626 SCAO_V1_TTC = 242, /* Thermal throttling count */
627 SCAO_V1_UIO = 244, /* Unaligned I/O */
628 SCAO_V1_PMUR = 252, /* Physical media units read */
629 SCAO_V1_RTOC = 268, /* Read command timeout count */
630 SCAO_V1_WTOC = 272, /* Write command timeout count */
631 SCAO_V1_TTOC = 276, /* Trim command timeout count */
632 SCAO_V1_PLRC = 284, /* PCIe Link Retraining Count */
633 SCAO_V1_PSCC = 292, /* Power State Change Count */
634 SCAO_V1_MAVF = 300, /* Boot SSD major version field */
635 SCAO_V1_MIVF = 302, /* Boot SSD minor version field */
636 SCAO_V1_PVF = 304, /* Boot SSD point version field */
637 SCAO_V1_EVF = 306, /* Boot SSD errata version field */
638 SCAO_V1_FTLUS = 308, /* FTL Unit Size */
639 SCAO_V1_TCGOS = 312, /* TCG Ownership Status */
640
641 SCAO_V1_LPV = 494, /* Log page version - 0x0001 */
642 SCAO_V1_LPG = 496, /* Log page GUID */
643};
644
645static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH16] = {
646 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1,
647 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4
648};
649
650struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log {
651 __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */
652 __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */
653 __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */
654 __u64 ext_smart_xrc; /* 040 XOR recovery count */
655 __u64 ext_smart_urec; /* 048 Uncorrectable read error count */
656 __u64 ext_smart_eece; /* 056 End to end corrected errors */
657 __u64 ext_smart_eede; /* 064 End to end detected errors */
658 __u64 ext_smart_eeue; /* 072 End to end uncorrected errors */
659 __u8 ext_smart_sdpu; /* 080 System data percent used */
660 __u8 ext_smart_rsvd1[3]; /* 081 reserved */
661 __u64 ext_smart_mnudec; /* 084 Min User data erase counts (TLC) */
662 __u64 ext_smart_mxudec; /* 092 Max User data erase counts (TLC) */
663 __u64 ext_smart_avudec; /* 100 Average User data erase counts (TLC) */
664 __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */
665 __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */
666 __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */
667 __u8 ext_smart_pfc[8]; /* 132 Program fail count */
668 __u8 ext_smart_efc[8]; /* 140 Erase fail count */
669 __u64 ext_smart_pcec; /* 148 PCIe correctable error count */
670 __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */
671 __u8 ext_smart_rsvd2[3]; /* 157 reserved */
672 __u64 ext_smart_svn; /* 160 Security Version Number */
673 __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */
674 __u8 ext_smart_rsvd3[3]; /* 169 reserved */
675 __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */
676 __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */
677 __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */
678 __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */
679 __u8 ext_smart_rsvd4[3]; /* 199 reserved */
680 __u64 ext_smart_seec; /* 202 Soft ECC error count */
681 __u64 ext_smart_rfsc; /* 210 Refresh count */
682 __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */
683 __u8 ext_smart_eest[16]; /* 226 Endurance estimate */
684 __u16 ext_smart_ttc; /* 242 Thermal throttling count */
685 __u64 ext_smart_uio; /* 244 Unaligned I/O */
686 __u8 ext_smart_pmur[16]; /* 252 Physical media units read */
687 __u32 ext_smart_rtoc; /* 268 Read command timeout count */
688 __u32 ext_smart_wtoc; /* 272 Write command timeout count */
689 __u32 ext_smart_ttoc; /* 276 Trim command timeout count */
690 __u8 ext_smart_rsvd5[4]; /* 280 reserved */
691 __u64 ext_smart_plrc; /* 284 PCIe Link Retraining Count */
692 __u64 ext_smart_pscc; /* 292 Power State Change Count */
693 __u16 ext_smart_maj; /* 300 Boot SSD major version field */
694 __u16 ext_smart_min; /* 302 Boot SSD minor version field */
695 __u16 ext_smart_pt; /* 304 Boot SSD point version field */
696 __u16 ext_smart_err; /* 306 Boot SSD errata version field */
697 __u32 ext_smart_ftlus; /* 308 FTL Unit Size */
698 __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */
699 __u8 ext_smart_rsvd6[178]; /* 316 reserved */
700 __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */
701 __u8 ext_smart_lpg[16]; /* 496 Log page GUID */
702};
703
704struct ocp_bad_nand_block_count {
705 __u64 raw : 48;
706 __u16 normalized : 16;
707};
708
709struct ocp_e2e_correction_count {
710 __u32 detected;
711 __u32 corrected;
712};
713
714struct ocp_user_data_erase_count {
715 __u32 maximum;
716 __u32 minimum;
717};
718
719struct ocp_thermal_status {
720 __u8 num_events;
721 __u8 current_status;
722};
723
724struct __packed__attribute__((__packed__)) ocp_dssd_specific_ver {
725 __u8 errata_ver;
726 __u16 point_ver;
727 __u16 minor_ver;
728 __u8 major_ver;
729};
730
731struct ocp_cloud_smart_log {
732 __u8 physical_media_units_written[16];
733 __u8 physical_media_units_read[16];
734 struct ocp_bad_nand_block_count bad_user_nand_blocks;
735 struct ocp_bad_nand_block_count bad_system_nand_blocks;
736 __u64 xor_recovery_count;
737 __u64 uncorrectable_read_error_count;
738 __u64 soft_ecc_error_count;
739 struct ocp_e2e_correction_count e2e_correction_counts;
740 __u8 system_data_percent_used;
741 __u64 refresh_counts : 56;
742 struct ocp_user_data_erase_count user_data_erase_counts;
743 struct ocp_thermal_status thermal_status;
744 struct ocp_dssd_specific_ver dssd_specific_ver;
745 __u64 pcie_correctable_error_count;
746 __u32 incomplete_shutdowns;
747 __u8 rsvd116[4];
748 __u8 percent_free_blocks;
749 __u8 rsvd121[7];
750 __u16 capacitor_health;
751 __u8 nvme_base_errata_ver;
752 __u8 nvme_cmd_set_errata_ver;
753 __u8 rsvd132[4];
754 __u64 unaligned_io;
755 __u64 security_version_number;
756 __u64 total_nuse;
757 __u8 plp_start_count[16];
758 __u8 endurance_estimate[16];
759 __u64 pcie_link_retraining_cnt;
760 __u64 power_state_change_cnt;
761 char lowest_permitted_fw_rev[8];
762 __u8 rsvd216[278];
763 __u16 log_page_version;
764 __u8 log_page_guid[16];
765};
766
767static __u8 scao_guid[WDC_C0_GUID_LENGTH16] = {
768 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
769 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF
770};
771
772enum {
773 EOL_RBC = 76, /* Realloc Block Count */
774 EOL_ECCR = 80, /* ECC Rate */
775 EOL_WRA = 84, /* Write Amp */
776 EOL_PLR = 88, /* Percent Life Remaining */
777 EOL_RSVBC = 92, /* Reserved Block Count */
778 EOL_PFC = 96, /* Program Fail Count */
779 EOL_EFC = 100, /* Erase Fail Count */
780 EOL_RRER = 108, /* Raw Read Error Rate */
781};
782
783#define WDC_NVME_C6_GUID_LENGTH16 16
784#define WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6 0xc6
785#define WDC_NVME_HW_REV_LOG_PAGE_LEN512 512
786
787struct __packed__attribute__((__packed__)) wdc_nvme_hw_rev_log {
788 __u8 hw_rev_gdr; /* 0 Global Device HW Revision */
789 __u8 hw_rev_ar; /* 1 ASIC HW Revision */
790 __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */
791 __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */
792 __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */
793 __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */
794 __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */
795 __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */
796 __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */
797 __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */
798 __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */
799 __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */
800 __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */
801 __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */
802 __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */
803 __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */
804 __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */
805 __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */
806 __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */
807 __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */
808 __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */
809 __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */
810 __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */
811 __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */
812 __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */
813 __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */
814 __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */
815 __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */
816 __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */
817 __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */
818 __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */
819 __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */
820 __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */
821 __u8 hw_rev_sn[32]; /* 320 Serial Number */
822 __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */
823 __u16 hw_rev_version; /* 494 Log Page Version */
824 __u8 hw_rev_guid[16]; /* 496 Log Page GUID */
825};
826
827static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH16] = {
828 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15,
829 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C
830};
831
832struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA {
833 __u8 fileName[WDC_DE_FILE_NAME_SIZE32];
834 __u16 fileID;
835 __u64 fileSize;
836};
837
838struct WDC_DRIVE_ESSENTIALS {
839 struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA metaData;
840 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType;
841};
842
843struct WDC_DE_VU_LOG_DIRECTORY {
844 struct WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */
845 __u32 maxNumLogEntries; /* Caller to input memory allocated */
846 __u32 numOfValidLogEntries; /* API will output this value */
847};
848
849struct WDC_DE_CSA_FEATURE_ID_LIST {
850 enum NVME_FEATURE_IDENTIFIERS featureId;
851 __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE80];
852};
853
854struct tarfile_metadata {
855 char fileName[MAX_PATH_LEN256];
856 int8_t bufferFolderPath[MAX_PATH_LEN256];
857 char bufferFolderName[MAX_PATH_LEN256];
858 char tarFileName[MAX_PATH_LEN256];
859 char tarFiles[MAX_PATH_LEN256];
860 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
861 char currDir[MAX_PATH_LEN256];
862 UtilsTimeInfo timeInfo;
863 uint8_t *timeString[MAX_PATH_LEN256];
864};
865
866static struct WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = {
867 {0x00, "Dummy Placeholder"},
868 {FID_ARBITRATION, "Arbitration"},
869 {FID_POWER_MANAGEMENT, "PowerMgmnt"},
870 {FID_LBA_RANGE_TYPE, "LbaRangeType"},
871 {FID_TEMPERATURE_THRESHOLD, "TempThreshold"},
872 {FID_ERROR_RECOVERY, "ErrorRecovery"},
873 {FID_VOLATILE_WRITE_CACHE, "VolatileWriteCache"},
874 {FID_NUMBER_OF_QUEUES, "NumOfQueues"},
875 {FID_INTERRUPT_COALESCING, "InterruptCoalesing"},
876 {FID_INTERRUPT_VECTOR_CONFIGURATION, "InterruptVectorConfig"},
877 {FID_WRITE_ATOMICITY, "WriteAtomicity"},
878 {FID_ASYNCHRONOUS_EVENT_CONFIGURATION, "AsynEventConfig"},
879 {FID_AUTONOMOUS_POWER_STATE_TRANSITION, "AutonomousPowerState"},
880};
881
882enum NVME_VU_DE_LOGPAGE_NAMES {
883 NVME_DE_LOGPAGE_E3 = 0x01,
884 NVME_DE_LOGPAGE_C0 = 0x02
885};
886
887struct NVME_VU_DE_LOGPAGE_LIST {
888 enum NVME_VU_DE_LOGPAGE_NAMES logPageName;
889 __u32 logPageId;
890 __u32 logPageLen;
891 char logPageIdStr[5];
892};
893
894struct WDC_NVME_DE_VU_LOGPAGES {
895 enum NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd;
896 __u32 numOfVULogPages;
897};
898
899static struct NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = {
900 { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"},
901 { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"}
902};
903
904enum {
905 WDC_NVME_ADMIN_VUC_OPCODE_D2 = 0xD2,
906 WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2 = 0x0000010A,
907 WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2 = 0x00000105,
908};
909
910enum {
911 NVME_LOG_NS_BASE = 0x80,
912 NVME_LOG_VS_BASE = 0xC0,
913};
914
915/*drive_info struct*/
916struct ocp_drive_info {
917 __u32 hw_revision;
918 __u32 ftl_unit_size;
919};
920
921/*get log page directory struct*/
922struct log_page_directory {
923 __u64 supported_lid_bitmap;
924 __u64 rsvd;
925 __u64 supported_ns_lid_bitmap;
926 __u64 supported_vs_lid_bitmap;
927};
928
929/*set latency monitor feature */
930struct __packed__attribute__((__packed__)) feature_latency_monitor {
931 __u16 active_bucket_timer_threshold;
932 __u8 active_threshold_a;
933 __u8 active_threshold_b;
934 __u8 active_threshold_c;
935 __u8 active_threshold_d;
936 __u16 active_latency_config;
937 __u8 active_latency_minimum_window;
938 __u16 debug_log_trigger_enable;
939 __u8 discard_debug_log;
940 __u8 latency_monitor_feature_enable;
941 __u8 reserved[4083];
942};
943
944static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len, const char *suffix);
945static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
946 __u32 drive_log_length);
947static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12);
948static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12,
949 const char *file, __u32 xfer_size);
950static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type);
951static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type);
952static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
953 struct plugin *plugin);
954static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file);
955static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin);
956static const char *wdc_purge_mon_status_to_string(__u32 status);
957static int wdc_purge(int argc, char **argv, struct command *acmd, struct plugin *plugin);
958static int wdc_purge_monitor(int argc, char **argv, struct command *acmd, struct plugin *plugin);
959static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
960 struct libnvme_transport_handle *hdl,
961 __u8 log_id,
962 __u8 uuid_index);
963static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
964 struct plugin *plugin);
965static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *dir, char *key);
966static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
967 struct plugin *plugin);
968static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin);
969static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
970 struct plugin *plugin);
971static int wdc_drive_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin);
972static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size);
973static int wdc_namespace_resize(int argc, char **argv, struct command *acmd,
974 struct plugin *plugin);
975static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option);
976static int wdc_reason_identifier(int argc, char **argv, struct command *acmd,
977 struct plugin *plugin);
978static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id);
979static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size);
980static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl);
981static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
982 struct plugin *plugin);
983static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result);
984static int wdc_vs_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin);
985static int wdc_vs_temperature_stats(int argc, char **argv, struct command *acmd,
986 struct plugin *plugin);
987static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
988static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len,
989 FILE *out);
990static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len, int xfer_size,
991 FILE *out, int data_id, int cdw14, int cdw15);
992static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __u8 log_id,
993 void **cbs_data);
994static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
995static int wdc_print_c0_cloud_attr_log(void *data,
996 int fmt,
997 struct libnvme_transport_handle *hdl);
998static int wdc_print_c0_eol_log(void *data, int fmt);
999static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
1000 struct libnvme_transport_handle *hdl);
1001static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log);
1002static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx,
1003 struct libnvme_transport_handle *hdl,
1004 void **data);
1005static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data,
1006 __u32 *ret_data,
1007 __u32 entry_id);
1008static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
1009 __u32 entry_id,
1010 char *ret_data,
1011 __u32 *ret_data_len);
1012
1013/* Drive log data size */
1014struct wdc_log_size {
1015 __le32 log_size;
1016};
1017
1018/* E6 log header */
1019struct wdc_e6_log_hdr {
1020 __le32 eye_catcher;
1021 __u8 log_size[4];
1022};
1023
1024/* DUI log header */
1025struct wdc_dui_log_section {
1026 __le16 section_type;
1027 __le16 reserved;
1028 __le32 section_size;
1029};
1030
1031/* DUI log header V2 */
1032struct __packed__attribute__((__packed__)) wdc_dui_log_section_v2 {
1033 __le16 section_type;
1034 __le16 data_area_id;
1035 __le64 section_size;
1036};
1037
1038/* DUI log header V4 */
1039struct wdc_dui_log_section_v4 {
1040 __le16 section_type;
1041 __u8 data_area_id;
1042 __u8 reserved;
1043 __le32 section_size_sectors;
1044};
1045
1046struct wdc_dui_log_hdr {
1047 __u8 telemetry_hdr[512];
1048 __le16 hdr_version;
1049 __le16 section_count;
1050 __le32 log_size;
1051 struct wdc_dui_log_section log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1052 __u8 log_data[40];
1053};
1054
1055struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v2 {
1056 __u8 telemetry_hdr[512];
1057 __u8 hdr_version;
1058 __u8 product_id;
1059 __le16 section_count;
1060 __le64 log_size;
1061 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V20x26];
1062 __u8 log_data[40];
1063};
1064
1065struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v3 {
1066 __u8 telemetry_hdr[512];
1067 __u8 hdr_version;
1068 __u8 product_id;
1069 __le16 section_count;
1070 __le64 log_size;
1071 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V30x23];
1072 __u8 securityNonce[36];
1073 __u8 log_data[40];
1074};
1075
1076struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v4 {
1077 __u8 telemetry_hdr[512];
1078 __u8 hdr_version;
1079 __u8 product_id;
1080 __le16 section_count;
1081 __le32 log_size_sectors;
1082 struct wdc_dui_log_section_v4 log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1083 __u8 log_data[40];
1084};
1085
1086/* Purge monitor response */
1087struct wdc_nvme_purge_monitor_data {
1088 __le16 rsvd1;
1089 __le16 rsvd2;
1090 __le16 first_erase_failure_cnt;
1091 __le16 second_erase_failure_cnt;
1092 __le16 rsvd3;
1093 __le16 programm_failure_cnt;
1094 __le32 rsvd4;
1095 __le32 rsvd5;
1096 __le32 entire_progress_total;
1097 __le32 entire_progress_current;
1098 __u8 rsvd6[14];
1099};
1100
1101/* Additional Smart Log */
1102struct wdc_log_page_header {
1103 uint8_t num_subpages;
1104 uint8_t reserved;
1105 __le16 total_log_size;
1106};
1107
1108struct wdc_log_page_subpage_header {
1109 uint8_t spcode;
1110 uint8_t pcset;
1111 __le16 subpage_length;
1112};
1113
1114struct wdc_ssd_perf_stats {
1115 __le64 hr_cmds; /* Host Read Commands */
1116 __le64 hr_blks; /* Host Read Blocks */
1117 __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */
1118 __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */
1119 __le64 hr_st_cmds; /* Host Read Stalled Commands */
1120 __le64 hw_cmds; /* Host Write Commands */
1121 __le64 hw_blks; /* Host Write Blocks */
1122 __le64 hw_os_cmds; /* Host Write Odd Start Commands */
1123 __le64 hw_oe_cmds; /* Host Write Odd End Commands */
1124 __le64 hw_st_cmds; /* Host Write Commands Stalled */
1125 __le64 nr_cmds; /* NAND Read Commands */
1126 __le64 nr_blks; /* NAND Read Blocks */
1127 __le64 nw_cmds; /* NAND Write Commands */
1128 __le64 nw_blks; /* NAND Write Blocks */
1129 __le64 nrbw; /* NAND Read Before Write */
1130};
1131
1132/* Additional C2 Log Page */
1133struct wdc_c2_log_page_header {
1134 __le32 length;
1135 __le32 version;
1136};
1137
1138struct wdc_c2_log_subpage_header {
1139 __le32 length;
1140 __le32 entry_id;
1141 __le32 data;
1142};
1143
1144struct wdc_c2_cbs_data {
1145 __le32 length;
1146 __u8 data[];
1147};
1148
1149struct __packed__attribute__((__packed__)) wdc_bd_ca_log_format {
1150 __u8 field_id;
1151 __u8 reserved1[2];
1152 __u8 normalized_value;
1153 __u8 raw_value[8];
1154};
1155
1156#define WDC_LATENCY_LOG_BUCKET_READ3 3
1157#define WDC_LATENCY_LOG_BUCKET_WRITE2 2
1158#define WDC_LATENCY_LOG_BUCKET_TRIM1 1
1159#define WDC_LATENCY_LOG_BUCKET_RESERVED0 0
1160
1161#define WDC_LATENCY_LOG_MEASURED_LAT_READ2 2
1162#define WDC_LATENCY_LOG_MEASURED_LAT_WRITE1 1
1163#define WDC_LATENCY_LOG_MEASURED_LAT_TRIM0 0
1164
1165struct __packed__attribute__((__packed__)) wdc_ssd_latency_monitor_log {
1166 __u8 feature_status; /* 0x00 */
1167 __u8 rsvd1; /* 0x01 */
1168 __le16 active_bucket_timer; /* 0x02 */
1169 __le16 active_bucket_timer_threshold; /* 0x04 */
1170 __u8 active_threshold_a; /* 0x06 */
1171 __u8 active_threshold_b; /* 0x07 */
1172 __u8 active_threshold_c; /* 0x08 */
1173 __u8 active_threshold_d; /* 0x09 */
1174 __le16 active_latency_config; /* 0x0A */
1175 __u8 active_latency_min_window; /* 0x0C */
1176 __u8 rsvd2[0x13]; /* 0x0D */
1177
1178 __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */
1179 __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
1180 __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
1181 __le16 active_latency_stamp_units; /* 0xD8 */
1182 __u8 rsvd3[0x16]; /* 0xDA */
1183
1184 __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
1185 __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
1186 __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
1187 __le16 static_latency_stamp_units; /* 0x1A8 */
1188 __u8 rsvd4[10]; /* 0x1AA */
1189
1190 __u8 debug_telemetry_log_size[12]; /* 0x1B4 */
1191 __le16 debug_log_trigger_enable; /* 0x1C0 */
1192 __le16 debug_log_measured_latency; /* 0x1C2 */
1193 __le64 debug_log_latency_stamp; /* 0x1C4 */
1194 __le16 debug_log_ptr; /* 0x1CC */
1195 __le16 debug_log_counter_trigger; /* 0x1CE */
1196 __u8 debug_log_stamp_units; /* 0x1D0 */
1197 __u8 rsvd5[0x1D]; /* 0x1D1 */
1198
1199 __le16 log_page_version; /* 0x1EE */
1200 __u8 log_page_guid[0x10]; /* 0x1F0 */
1201};
1202
1203struct __packed__attribute__((__packed__)) wdc_ssd_ca_perf_stats {
1204 __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */
1205 __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */
1206 __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */
1207 __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */
1208 __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */
1209 __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */
1210 __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */
1211 __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */
1212 __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */
1213 __u8 data_percent_used; /* 0x40 - System Data Percent Used */
1214 __le32 data_erase_max; /* 0x41 - User Data Erase Counts */
1215 __le32 data_erase_min; /* 0x45 - User Data Erase Counts */
1216 __le64 refresh_count; /* 0x49 - Refresh Count */
1217 __le64 program_fail; /* 0x51 - Program Fail Count */
1218 __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */
1219 __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */
1220 __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */
1221 __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */
1222 __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */
1223 __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */
1224 __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */
1225 __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */
1226};
1227
1228struct __packed__attribute__((__packed__)) wdc_ssd_d0_smart_log {
1229 __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */
1230 __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */
1231 __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */
1232 __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */
1233 __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */
1234 __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */
1235 __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */
1236 __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */
1237 __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */
1238 __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */
1239 __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */
1240 __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */
1241 __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */
1242 __le32 current_temp; /* 0x34 - Current temperature */
1243 __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */
1244 __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */
1245 __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */
1246 __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */
1247 __le32 capacitor_health; /* 0x4C - Capacitor health */
1248 __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */
1249 __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */
1250 __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */
1251 __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */
1252 __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */
1253};
1254
1255#define WDC_OCP_C1_GUID_LENGTH16 16
1256#define WDC_ERROR_REC_LOG_BUF_LEN512 512
1257#define WDC_ERROR_REC_LOG_ID0xC1 0xC1
1258
1259struct __packed__attribute__((__packed__)) wdc_ocp_c1_error_recovery_log {
1260 __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */
1261 __u8 panic_reset_action; /* 002 - Panic Reset Action */
1262 __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */
1263 __le64 panic_id; /* 004 - Panic ID */
1264 __le32 dev_capabilities; /* 012 - Device Capabilities */
1265 __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */
1266 __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */
1267 __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */
1268 __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */
1269 __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */
1270 __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */
1271 __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2 */
1272 __u8 panic_count; /* 031 - Number of panics encountered */
1273 __le64 prev_panic_ids[4]; /* 032 - 063 Previous Panic ID's */
1274 __u8 rsvd2[430]; /* 064 - 493 Reserved Bytes */
1275 /* 430 reserved bytes aligns with the rest */
1276 /* of the data structure. The size of 463 */
1277 /* bytes mentioned in the OCP spec */
1278 /* (version 2.5) would not fit here. */
1279 __le16 log_page_version; /* 494 - Log Page Version */
1280 __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH16]; /* 496 - Log Page GUID */
1281};
1282
1283static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH16] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE,
1284 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A };
1285
1286/* NAND Stats */
1287struct __packed__attribute__((__packed__)) wdc_nand_stats {
1288 __u8 nand_write_tlc[16];
1289 __u8 nand_write_slc[16];
1290 __le32 nand_prog_failure;
1291 __le32 nand_erase_failure;
1292 __le32 bad_block_count;
1293 __le64 nand_rec_trigger_event;
1294 __le64 e2e_error_counter;
1295 __le64 successful_ns_resize_event;
1296 __u8 rsvd[442];
1297 __u16 log_page_version;
1298};
1299
1300struct __packed__attribute__((__packed__)) wdc_nand_stats_V3 {
1301 __u8 nand_write_tlc[16];
1302 __u8 nand_write_slc[16];
1303 __u8 bad_nand_block_count[8];
1304 __le64 xor_recovery_count;
1305 __le64 uecc_read_error_count;
1306 __u8 ssd_correction_counts[16];
1307 __u8 percent_life_used;
1308 __le64 user_data_erase_counts[4];
1309 __u8 program_fail_count[8];
1310 __u8 erase_fail_count[8];
1311 __le64 correctable_error_count;
1312 __u8 percent_free_blocks_user;
1313 __le64 security_version_number;
1314 __u8 percent_free_blocks_system;
1315 __u8 trim_completions[25];
1316 __u8 back_pressure_guage;
1317 __le64 soft_ecc_error_count;
1318 __le64 refresh_count;
1319 __u8 bad_sys_nand_block_count[8];
1320 __u8 endurance_estimate[16];
1321 __u8 thermal_throttling_st_ct[2];
1322 __le64 unaligned_IO;
1323 __u8 physical_media_units[16];
1324 __u8 reserved[279];
1325 __u16 log_page_version;
1326};
1327
1328struct wdc_vs_pcie_stats {
1329 __le64 unsupportedRequestErrorCount;
1330 __le64 ecrcErrorStatusCount;
1331 __le64 malformedTlpStatusCount;
1332 __le64 receiverOverflowStatusCount;
1333 __le64 unexpectedCmpltnStatusCount;
1334 __le64 completeAbortStatusCount;
1335 __le64 cmpltnTimoutStatusCount;
1336 __le64 flowControlErrorStatusCount;
1337 __le64 poisonedTlpStatusCount;
1338 __le64 dLinkPrtclErrorStatusCount;
1339 __le64 advsryNFatalErrStatusCount;
1340 __le64 replayTimerToStatusCount;
1341 __le64 replayNumRolloverStCount;
1342 __le64 badDllpStatusCount;
1343 __le64 badTlpStatusCount;
1344 __le64 receiverErrStatusCount;
1345 __u8 reserved1[384];
1346};
1347
1348struct wdc_fw_act_history_log_hdr {
1349 __le32 eye_catcher;
1350 __u8 version;
1351 __u8 reserved1;
1352 __u8 num_entries;
1353 __u8 reserved2;
1354 __le32 entry_size;
1355 __le32 reserved3;
1356};
1357
1358struct wdc_fw_act_history_log_entry {
1359 __le32 entry_num;
1360 __le32 power_cycle_count;
1361 __le64 power_on_seconds;
1362 __le64 previous_fw_version;
1363 __le64 new_fw_version;
1364 __u8 slot_number;
1365 __u8 commit_action_type;
1366 __le16 result;
1367 __u8 reserved[12];
1368};
1369
1370struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 {
1371 __u8 entry_version_num;
1372 __u8 entry_len;
1373 __le16 reserved;
1374 __le16 fw_act_hist_entries;
1375 __le64 timestamp;
1376 __u8 reserved2[8];
1377 __le64 power_cycle_count;
1378 __le64 previous_fw_version;
1379 __le64 current_fw_version;
1380 __u8 slot_number;
1381 __u8 commit_action_type;
1382 __le16 result;
1383 __u8 reserved3[14];
1384};
1385
1386struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_format_c2 {
1387 __u8 log_identifier;
1388 __u8 reserved[3];
1389 __le32 num_entries;
1390 struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES20];
1391 __u8 reserved2[2790];
1392 __le16 log_page_version;
1393 __u8 log_page_guid[WDC_C2_GUID_LENGTH16];
1394};
1395
1396static __u8 ocp_C2_guid[WDC_C2_GUID_LENGTH16] = {
1397 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
1398 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
1399};
1400
1401#define WDC_OCP_C4_GUID_LENGTH16 16
1402#define WDC_DEV_CAP_LOG_BUF_LEN4096 4096
1403#define WDC_DEV_CAP_LOG_ID0xC4 0xC4
1404#define WDC_DEV_CAP_LOG_VERSION0001 0001
1405#define WDC_OCP_C4_NUM_PS_DESCR127 127
1406
1407struct __packed__attribute__((__packed__)) wdc_ocp_C4_dev_cap_log {
1408 __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */
1409 __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */
1410 __le16 wrt_zeros_support; /* 0004 - Write Zeros Command Support */
1411 __le16 sanitize_support; /* 0006 - Sanitize Command Support */
1412 __le16 dsm_support; /* 0008 - Dataset Management Command Support */
1413 __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */
1414 __le16 fused_support; /* 0012 - Fused Operation Support */
1415 __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */
1416 __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */
1417 __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR127];/* 0017 - DSSD Power State Descriptors */
1418 __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */
1419 __le16 log_page_version; /* 4078 - Log Page Version */
1420 __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1421};
1422
1423static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH16] = {
1424 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98,
1425 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7
1426};
1427
1428#define WDC_OCP_C5_GUID_LENGTH16 16
1429#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096 4096
1430#define WDC_UNSUPPORTED_REQS_LOG_ID0xC5 0xC5
1431#define WDC_UNSUPPORTED_REQS_LOG_VERSION0001 0001
1432#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES253 253
1433
1434struct __packed__attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs {
1435 __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */
1436 __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */
1437 __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES253][16]; /* 0016 - Unsupported Requirements List */
1438 __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */
1439 __le16 log_page_version; /* 4078 - Log Page Version */
1440 __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1441};
1442
1443static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH16] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB,
1444 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 };
1445
1446#define WDC_REASON_INDEX_MAX16 16
1447#define WDC_REASON_ID_ENTRY_LEN128 128
1448#define WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli" "/usr/local/nvmecli"
1449
1450const char *log_page_name[256] = {
1451 [NVME_LOG_LID_ERROR] = "Error Information",
1452 [NVME_LOG_LID_SMART] = "SMART / Health Information",
1453 [NVME_LOG_LID_FW_SLOT] = "Firmware Slot Information",
1454 [NVME_LOG_LID_CHANGED_NS] = "Changed Namespace List",
1455 [NVME_LOG_LID_CMD_EFFECTS] = "Command Supported and Effects",
1456 [NVME_LOG_LID_TELEMETRY_HOST] = "Telemetry Host-Initiated",
1457 [NVME_LOG_LID_TELEMETRY_CTRL] = "Telemetry Controller-Initiated",
1458 [NVME_LOG_LID_SANITIZE] = "Sanitize Status",
1459 [WDC_LOG_ID_C00xC0] = "Extended SMART Information",
1460 [WDC_LOG_ID_C20xC2] = "Firmware Activation History",
1461 [WDC_LOG_ID_C30xC3] = "Latency Monitor",
1462 [WDC_LOG_ID_C40xC4] = "Device Capabilities",
1463 [WDC_LOG_ID_C50xC5] = "Unsupported Requirements",
1464};
1465
1466static double safe_div_fp(double numerator, double denominator)
1467{
1468 return denominator ? numerator / denominator : 0;
1469}
1470
1471static double calc_percent(uint64_t numerator, uint64_t denominator)
1472{
1473 return denominator ?
1474 (uint64_t)(((double)numerator / (double)denominator) * 100) : 0;
1475}
1476
1477static int wdc_get_pci_ids(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
1478 uint32_t *device_id, uint32_t *vendor_id)
1479{
1480 const char *name = libnvme_transport_handle_get_name(hdl);
1481 char vid[256], did[256], id[32];
1482 libnvme_ctrl_t c = NULL((void*)0);
1483 libnvme_ns_t n = NULL((void*)0);
1484 int fd, ret;
1485
1486 ret = libnvme_scan_ctrl(ctx, name, &c);
1487 if (!ret) {
1488 snprintf(vid, sizeof(vid), "%s/device/vendor",
1489 libnvme_ctrl_get_sysfs_dir(c));
1490 snprintf(did, sizeof(did), "%s/device/device",
1491 libnvme_ctrl_get_sysfs_dir(c));
1492 libnvme_free_ctrl(c);
1493 } else {
1494 ret = libnvme_scan_namespace(ctx, name, &n);
1495 if (ret) {
1496 fprintf(stderrstderr, "Unable to find %s\n", name);
1497 return ret;
1498 }
1499
1500 snprintf(vid, sizeof(vid), "%s/device/device/vendor",
1501 libnvme_ns_get_sysfs_dir(n));
1502 snprintf(did, sizeof(did), "%s/device/device/device",
1503 libnvme_ns_get_sysfs_dir(n));
1504 libnvme_free_ns(n);
1505 }
1506
1507 fd = open(vid, O_RDONLY00);
1508 if (fd < 0) {
1509 fprintf(stderrstderr, "ERROR: WDC: %s : Open vendor file failed\n", __func__);
1510 return -1;
1511 }
1512
1513 ret = read(fd, id, 32);
1514 close(fd);
1515
1516 if (ret < 0) {
1517 fprintf(stderrstderr, "%s: Read of pci vendor id failed\n", __func__);
1518 return -1;
1519 }
1520 id[ret < 32 ? ret : 31] = '\0';
1521 if (id[strlen(id) - 1] == '\n')
1522 id[strlen(id) - 1] = '\0';
1523
1524 *vendor_id = strtol(id, NULL((void*)0), 0);
1525 ret = 0;
Value stored to 'ret' is never read
1526
1527 fd = open(did, O_RDONLY00);
1528 if (fd < 0) {
1529 fprintf(stderrstderr, "ERROR: WDC: %s : Open device file failed\n", __func__);
1530 return -1;
1531 }
1532
1533 ret = read(fd, id, 32);
1534 close(fd);
1535
1536 if (ret < 0) {
1537 fprintf(stderrstderr, "%s: Read of pci device id failed\n", __func__);
1538 return -1;
1539 }
1540 id[ret < 32 ? ret : 31] = '\0';
1541 if (id[strlen(id) - 1] == '\n')
1542 id[strlen(id) - 1] = '\0';
1543
1544 *device_id = strtol(id, NULL((void*)0), 0);
1545 return 0;
1546}
1547
1548static int wdc_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id)
1549{
1550 struct nvme_id_ctrl ctrl;
1551 int ret;
1552
1553 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1554 ret = nvme_identify_ctrl(hdl, &ctrl);
1555 if (ret) {
1556 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
1557 return -1;
1558 }
1559
1560 *vendor_id = (uint32_t) ctrl.vid;
1561
1562 return ret;
1563}
1564
1565static bool_Bool wdc_is_sn861(__u32 device_id)
1566{
1567 if ((device_id == WDC_NVME_SN861_DEV_ID0x2750) ||
1568 (device_id == WDC_NVME_SN861_DEV_ID_10x2751) ||
1569 (device_id == WDC_NVME_SN861_DEV_ID_20x2752))
1570 return true1;
1571 else
1572 return false0;
1573}
1574
1575
1576static bool_Bool wdc_is_sn640(__u32 device_id)
1577{
1578 if ((device_id == WDC_NVME_SN640_DEV_ID0x2400) ||
1579 (device_id == WDC_NVME_SN640_DEV_ID_10x2401) ||
1580 (device_id == WDC_NVME_SN640_DEV_ID_20x2402))
1581 return true1;
1582 else
1583 return false0;
1584}
1585
1586static bool_Bool wdc_is_sn650_u2(__u32 device_id)
1587{
1588 if (device_id == WDC_NVME_SN650_DEV_ID_30x2720)
1589 return true1;
1590 else
1591 return false0;
1592}
1593
1594static bool_Bool wdc_is_sn650_e1l(__u32 device_id)
1595{
1596 if (device_id == WDC_NVME_SN650_DEV_ID_40x2721)
1597 return true1;
1598 else
1599 return false0;
1600}
1601
1602static bool_Bool wdc_is_zn350(__u32 device_id)
1603{
1604 return (device_id == WDC_NVME_ZN350_DEV_ID0x5010 ||
1605 device_id == WDC_NVME_ZN350_DEV_ID_10x5018);
1606}
1607static bool_Bool needs_c2_log_page_check(__u32 device_id)
1608{
1609 if ((wdc_is_sn640(device_id)) ||
1610 (wdc_is_sn650_u2(device_id)) ||
1611 (wdc_is_sn650_e1l(device_id)))
1612 return true1;
1613 else
1614 return false0;
1615}
1616
1617static bool_Bool wdc_check_power_of_2(int num)
1618{
1619 return num && (!(num & (num-1)));
1620}
1621
1622static int wdc_get_model_number(struct libnvme_transport_handle *hdl, char *model)
1623{
1624 struct nvme_id_ctrl ctrl;
1625 int ret, i;
1626
1627 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1628 ret = nvme_identify_ctrl(hdl, &ctrl);
1629 if (ret) {
1630 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
1631 return -1;
1632 }
1633
1634 memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE40);
1635 /* get rid of the padded spaces */
1636 i = NVME_ID_CTRL_MODEL_NUMBER_SIZE40-1;
1637 while (model[i] == ' ')
1638 i--;
1639 model[i+1] = 0;
1640
1641 return ret;
1642}
1643
1644static bool_Bool wdc_check_device(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1645{
1646 int ret;
1647 bool_Bool supported;
1648 uint32_t read_device_id = -1, read_vendor_id = -1;
1649
1650 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
1651 if (ret < 0) {
1652 /* Use the identify nvme command to get vendor id due to NVMeOF device. */
1653 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1654 return false0;
1655 }
1656
1657 supported = false0;
1658
1659 if (read_vendor_id == WDC_NVME_VID0x1c58 ||
1660 read_vendor_id == WDC_NVME_VID_20x1b96 ||
1661 read_vendor_id == WDC_NVME_SNDK_VID0x15b7)
1662 supported = true1;
1663 else
1664 fprintf(stderrstderr,
1665 "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n",
1666 read_vendor_id, read_device_id);
1667
1668 return supported;
1669}
1670
1671static bool_Bool wdc_enc_check_model(struct libnvme_transport_handle *hdl)
1672{
1673 int ret;
1674 bool_Bool supported;
1675 char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40+1];
1676
1677 ret = wdc_get_model_number(hdl, model);
1678 if (ret < 0)
1679 return false0;
1680
1681 supported = false0;
1682 model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40] = 0; /* forced termination */
1683 if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL"OpenFlex"))
1684 supported = true1;
1685 else
1686 fprintf(stderrstderr, "ERROR: WDC: unsupported WDC enclosure, Model = %s\n", model);
1687
1688 return supported;
1689}
1690
1691static __u64 wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1692{
1693 int ret;
1694 uint32_t read_device_id = -1, read_vendor_id = -1;
1695 __u64 capabilities = 0;
1696 __u32 cust_id;
1697
1698 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
1699 if (ret < 0) {
1700 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1701 return capabilities;
1702 }
1703
1704 /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
1705 if (read_device_id == -1 && read_vendor_id != -1) {
1706 capabilities = wdc_get_enc_drive_capabilities(ctx, hdl);
1707 return capabilities;
1708 }
1709
1710 switch (read_vendor_id) {
1711 case WDC_NVME_VID0x1c58:
1712 switch (read_device_id) {
1713 case WDC_NVME_SN100_DEV_ID0x0003:
1714 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 |
1715 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1716 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1717 break;
1718
1719 case WDC_NVME_SN200_DEV_ID0x0023:
1720 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1721 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1722 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1723
1724 /* verify the 0xCA log page is supported */
1725 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1726 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1727 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1728
1729 /* verify the 0xC1 log page is supported */
1730 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1731 WDC_NVME_ADD_LOG_OPCODE0xC1, 0))
1732 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
1733 break;
1734
1735 default:
1736 capabilities = 0;
1737 }
1738 break;
1739
1740 case WDC_NVME_VID_20x1b96:
1741 switch (read_device_id) {
1742 case WDC_NVME_SN630_DEV_ID0x2200:
1743 case WDC_NVME_SN630_DEV_ID_10x2201:
1744 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1745 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1746 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1747 /* verify the 0xCA log page is supported */
1748 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1749 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1750 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1751
1752 /* verify the 0xD0 log page is supported */
1753 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1754 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1755 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1756 break;
1757
1758 case WDC_NVME_SN640_DEV_ID0x2400:
1759 case WDC_NVME_SN640_DEV_ID_10x2401:
1760 case WDC_NVME_SN640_DEV_ID_20x2402:
1761 case WDC_NVME_SN640_DEV_ID_30x2404:
1762 case WDC_NVME_SN560_DEV_ID_10x2712:
1763 case WDC_NVME_SN560_DEV_ID_20x2713:
1764 case WDC_NVME_SN560_DEV_ID_30x2714:
1765 case WDC_NVME_SN660_DEV_ID0x2704:
1766 /* verify the 0xC0 log page is supported */
1767 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1768 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)
1769 == true1) {
1770 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1771 }
1772
1773 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1774 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1775 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1776 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1777 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1778
1779 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1780 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1781 WDC_ERROR_REC_LOG_ID0xC1, 0))
1782 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1783
1784 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1785 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1786 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1787 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1788
1789 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1790 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1791 WDC_DEV_CAP_LOG_ID0xC4, 0))
1792 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1793
1794 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1795 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1796 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1797 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
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
1809 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1810 /* Can still determine some capabilities in this case, but log an error */
1811 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1812 fprintf(stderrstderr,
1813 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",
1814 __func__, read_device_id);
1815
1816 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1817 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) || (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1818 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1819 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1820 else
1821 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1822
1823 break;
1824
1825 case WDC_NVME_SN840_DEV_ID0x2300:
1826 case WDC_NVME_SN840_DEV_ID_10x2500:
1827 case WDC_NVME_SN860_DEV_ID0x2730:
1828 /* verify the 0xC0 log page is supported */
1829 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1830 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, 0))
1831 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1832 fallthrough__attribute__((fallthrough));
1833 case WDC_NVME_ZN540_DEV_ID0x2600:
1834 case WDC_NVME_SN540_DEV_ID0x2610:
1835 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1836 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1837 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1838 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1839 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1840 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1841
1842 /* verify the 0xCA log page is supported */
1843 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1844 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1845 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1846
1847 /* verify the 0xD0 log page is supported */
1848 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1849 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1850 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1851 break;
1852
1853 case WDC_NVME_SN650_DEV_ID0x2700:
1854 case WDC_NVME_SN650_DEV_ID_10x2701:
1855 case WDC_NVME_SN650_DEV_ID_20x2702:
1856 case WDC_NVME_SN650_DEV_ID_30x2720:
1857 case WDC_NVME_SN650_DEV_ID_40x2721:
1858 case WDC_NVME_SN655_DEV_ID0x2722:
1859 case WDC_NVME_SN655_DEV_ID_10x2723:
1860 case WDC_NVME_SN550_DEV_ID0x2708:
1861 /* verify the 0xC0 log page is supported */
1862 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1863 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
1864 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1865
1866 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1867 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1868 WDC_ERROR_REC_LOG_ID0xC1, 0))
1869 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1870
1871 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1872 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1873 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1874 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1875
1876 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1877 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1878 WDC_DEV_CAP_LOG_ID0xC4, 0))
1879 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1880
1881 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1882 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1883 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1884 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1885
1886 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1887 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1888 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1889 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 |
1890 WDC_DRIVE_CAP_REASON_ID0x0000000000010000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1891
1892 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1893 /* Can still determine some capabilities in this case, but log an error */
1894 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1895 fprintf(stderrstderr,
1896 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",
1897 __func__, read_device_id);
1898
1899 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
1900 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1901 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
1902 (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1903 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1904 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1905 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1906 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1907 else
1908 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1909 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1910
1911 break;
1912
1913 case WDC_NVME_SN861_DEV_ID0x2750:
1914 case WDC_NVME_SN861_DEV_ID_10x2751:
1915 case WDC_NVME_SN861_DEV_ID_20x2752:
1916 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1917 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1918 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1919 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1920 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1921 WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1922 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
1923 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1924 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1925 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1926 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1927 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1928 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1929 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1930 break;
1931
1932 case WDC_NVME_SNTMP_DEV_ID0x2761:
1933 case WDC_NVME_SNTMP_DEV_ID_10x2763:
1934 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1935 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1936 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1937 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1938 WDC_DRIVE_CAP_DUI0x0000000800000000 |
1939 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1940 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1941 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1942 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1943 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1944 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1945 break;
1946
1947 default:
1948 capabilities = 0;
1949 }
1950 break;
1951
1952 case WDC_NVME_SNDK_VID0x15b7:
1953 switch (read_device_id) {
1954 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
1955 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
1956 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
1957 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
1958 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
1959 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1960 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1961 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1962 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1963 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1964 WDC_DRIVE_CAP_UDUI0x0000040000000000 |
1965 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1966 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1967 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1968 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1969 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1970 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1971 break;
1972
1973 case WDC_NVME_SXSLCL_DEV_ID0x2001:
1974 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
1975 break;
1976
1977 case WDC_NVME_SN520_DEV_ID0x5003:
1978 case WDC_NVME_SN520_DEV_ID_10x5004:
1979 case WDC_NVME_SN520_DEV_ID_20x5005:
1980 case WDC_NVME_SN810_DEV_ID0x5011:
1981 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000;
1982 break;
1983
1984 case WDC_NVME_SN820CL_DEV_ID0x5037:
1985 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 |
1986 WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 |
1987 WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 | WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1988 WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
1989 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1990 WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000;
1991 break;
1992
1993 case WDC_NVME_SN720_DEV_ID0x5002:
1994 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1995 WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000;
1996 break;
1997
1998 case WDC_NVME_SN730_DEV_ID0x5006:
1999 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
2000 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 |
2001 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000;
2002 break;
2003
2004 case WDC_NVME_SN530_DEV_ID_10x5007:
2005 fallthrough__attribute__((fallthrough));
2006 case WDC_NVME_SN530_DEV_ID_20x5008:
2007 fallthrough__attribute__((fallthrough));
2008 case WDC_NVME_SN530_DEV_ID_30x5009:
2009 fallthrough__attribute__((fallthrough));
2010 case WDC_NVME_SN530_DEV_ID_40x500b:
2011 fallthrough__attribute__((fallthrough));
2012 case WDC_NVME_SN530_DEV_ID_50x501d:
2013 fallthrough__attribute__((fallthrough));
2014 case WDC_NVME_SN350_DEV_ID0x5019:
2015 fallthrough__attribute__((fallthrough));
2016 case WDC_NVME_SN570_DEV_ID0x501A:
2017 fallthrough__attribute__((fallthrough));
2018 case WDC_NVME_SN850X_DEV_ID0x5030:
2019 fallthrough__attribute__((fallthrough));
2020 case WDC_NVME_SN5000_DEV_ID_10x5034:
2021 fallthrough__attribute__((fallthrough));
2022 case WDC_NVME_SN5000_DEV_ID_20x5035:
2023 fallthrough__attribute__((fallthrough));
2024 case WDC_NVME_SN5000_DEV_ID_30x5036:
2025 fallthrough__attribute__((fallthrough));
2026 case WDC_NVME_SN5000_DEV_ID_40x504A:
2027 fallthrough__attribute__((fallthrough));
2028 case WDC_NVME_SN7000S_DEV_ID_10x5039:
2029 fallthrough__attribute__((fallthrough));
2030 case WDC_NVME_SN7150_DEV_ID_10x503b:
2031 fallthrough__attribute__((fallthrough));
2032 case WDC_NVME_SN7150_DEV_ID_20x503c:
2033 fallthrough__attribute__((fallthrough));
2034 case WDC_NVME_SN7150_DEV_ID_30x503d:
2035 fallthrough__attribute__((fallthrough));
2036 case WDC_NVME_SN7150_DEV_ID_40x503e:
2037 fallthrough__attribute__((fallthrough));
2038 case WDC_NVME_SN7150_DEV_ID_50x503f:
2039 fallthrough__attribute__((fallthrough));
2040 case WDC_NVME_SN7100_DEV_ID_10x5043:
2041 fallthrough__attribute__((fallthrough));
2042 case WDC_NVME_SN7100_DEV_ID_20x5044:
2043 fallthrough__attribute__((fallthrough));
2044 case WDC_NVME_SN7100_DEV_ID_30x5045:
2045 fallthrough__attribute__((fallthrough));
2046 case WDC_NVME_SN8000S_DEV_ID0x5049:
2047 fallthrough__attribute__((fallthrough));
2048 case WDC_NVME_SN5100S_DEV_ID_10x5061:
2049 fallthrough__attribute__((fallthrough));
2050 case WDC_NVME_SN5100S_DEV_ID_20x5062:
2051 fallthrough__attribute__((fallthrough));
2052 case WDC_NVME_SN5100S_DEV_ID_30x5063:
2053 fallthrough__attribute__((fallthrough));
2054 case WDC_NVME_SN740_DEV_ID0x5015:
2055 case WDC_NVME_SN740_DEV_ID_10x5016:
2056 case WDC_NVME_SN740_DEV_ID_20x5017:
2057 case WDC_NVME_SN740_DEV_ID_30x5025:
2058 case WDC_NVME_SN340_DEV_ID0x500d:
2059 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000;
2060 break;
2061
2062 case WDC_NVME_ZN350_DEV_ID0x5010:
2063 case WDC_NVME_ZN350_DEV_ID_10x5018:
2064 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
2065 WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
2066 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2067 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
2068 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000;
2069 break;
2070
2071 default:
2072 capabilities = 0;
2073 }
2074 break;
2075 default:
2076 capabilities = 0;
2077 }
2078
2079 return capabilities;
2080}
2081
2082static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx,
2083 struct libnvme_transport_handle *hdl)
2084{
2085 int ret;
2086 uint32_t read_vendor_id;
2087 __u64 capabilities = 0;
2088 __u32 cust_id, market_name_len;
2089 char marketing_name[64];
2090 void *dev_mng_log = NULL((void*)0);
2091 int uuid_index = 0;
2092 struct nvme_id_uuid_list uuid_list;
2093
2094 memset(marketing_name, 0, 64);
2095
2096 ret = wdc_get_vendor_id(hdl, &read_vendor_id);
2097 if (ret < 0)
2098 return capabilities;
2099
2100 switch (read_vendor_id) {
2101 case WDC_NVME_VID0x1c58:
2102 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
2103 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000);
2104
2105 /* verify the 0xCA log page is supported */
2106 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2107 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2108 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2109
2110 /* verify the 0xC1 log page is supported */
2111 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2112 WDC_NVME_ADD_LOG_OPCODE0xC1, 0) == true1)
2113 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
2114 break;
2115 case WDC_NVME_VID_20x1b96:
2116 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
2117 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
2118 WDC_DRIVE_CAP_RESIZE0x0000000000000100);
2119
2120 /* Find the WDC UUID index */
2121 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2122 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2123 /* check for the Sandisk UUID first */
2124 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2125
2126 if (uuid_index < 0)
2127 /* The Sandisk UUID is not found;
2128 * check for the WDC UUID second.
2129 */
2130 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2131 }
2132
2133 /* WD UUID not found, use default uuid index - 0 */
2134 if (uuid_index < 0)
2135 uuid_index = 0;
2136
2137 /* verify the 0xC2 Device Manageability log page is supported */
2138 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2139 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
2140 uuid_index) == false0) {
2141 fprintf(stderrstderr, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d\n",
2142 uuid_index);
2143 ret = -1;
2144 goto out;
2145 }
2146
2147 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
2148 fprintf(stderrstderr, "ERROR: SNDK: 0xC2 Log Page not found\n");
2149 ret = -1;
2150 goto out;
2151 }
2152
2153 /* Get the customer ID and marketing name from WD C2 log page */
2154 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log,
2155 &cust_id,
2156 WDC_C2_CUSTOMER_ID_ID0x15))
2157 fprintf(stderrstderr, "ERROR: SNDK: Get Customer FW ID Failed\n");
2158
2159 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
2160 WDC_C2_MARKETING_NAME_ID0x07,
2161 (char *)marketing_name,
2162 &market_name_len))
2163 fprintf(stderrstderr, "ERROR: SNDK: Get Marketing Name Failed\n");
2164
2165 /* verify the 0xC3 log page is supported */
2166 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2167 WDC_LATENCY_MON_LOG_ID0xC3, 0) == true1)
2168 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
2169
2170 /* verify the 0xCA log page is supported */
2171 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2172 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2173 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2174
2175 /* verify the 0xD0 log page is supported */
2176 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2177 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == true1)
2178 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
2179
2180 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
2181 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
2182 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
2183 (cust_id == WDC_CUSTOMER_ID_0x13040x1304) ||
2184 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) ||
2185 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len)))
2186 /* Set capabilities for OCP compliant drives */
2187 capabilities |= (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
2188 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2189 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000);
2190 else {
2191 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
2192 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
2193
2194 /* if the 0xCB log page is supported */
2195 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2196 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0) == true1)
2197 capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000;
2198 }
2199
2200 break;
2201 case WDC_NVME_SNDK_VID0x15b7:
2202 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
2203 break;
2204 default:
2205 capabilities = 0;
2206 }
2207
2208out:
2209 return capabilities;
2210}
2211
2212static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len,
2213 const char *suffix)
2214{
2215 int i;
2216 int ret;
2217 int res_len = 0;
2218 char orig[PATH_MAX4096] = {0};
2219 struct nvme_id_ctrl ctrl;
2220 int ctrl_sn_len = sizeof(ctrl.sn);
2221
2222 i = sizeof(ctrl.sn) - 1;
2223 strncpy(orig, file, PATH_MAX4096 - 1);
2224 memset(file, 0, len);
2225 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
2226 ret = nvme_identify_ctrl(hdl, &ctrl);
2227 if (ret) {
2228 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
2229 return -1;
2230 }
2231 /* Remove trailing spaces from the name */
2232 while (i && ctrl.sn[i] == ' ') {
2233 ctrl.sn[i] = '\0';
2234 i--;
2235 }
2236 if (ctrl.sn[sizeof(ctrl.sn) - 1] == '\0')
2237 ctrl_sn_len = strlen(ctrl.sn);
2238
2239 res_len = snprintf(file, len, "%s%.*s%s", orig, ctrl_sn_len, ctrl.sn, suffix);
2240 if (len <= res_len) {
2241 fprintf(stderrstderr,
2242 "ERROR: WDC: cannot format serial number due to data of unexpected length\n");
2243 return -1;
2244 }
2245
2246 return 0;
2247}
2248
2249static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
2250 __u32 drive_log_length)
2251{
2252 int fd;
2253 int ret;
2254
2255 if (!drive_log_length) {
2256 fprintf(stderrstderr, "ERROR: WDC: invalid log file length\n");
2257 return -1;
2258 }
2259
2260 fd = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
2261 if (fd < 0) {
2262 fprintf(stderrstderr, "ERROR: WDC: open: %s\n", libnvme_strerror(errno(*__errno_location ())));
2263 return -1;
2264 }
2265
2266 while (drive_log_length > WRITE_SIZE(sizeof(__u8) * 4096)) {
2267 ret = write(fd, drive_log_data, WRITE_SIZE(sizeof(__u8) * 4096));
2268 if (ret < 0) {
2269 fprintf(stderrstderr, "ERROR: WDC: write: %s\n", libnvme_strerror(errno(*__errno_location ())));
2270 close(fd);
2271 return -1;
2272 }
2273 drive_log_data += WRITE_SIZE(sizeof(__u8) * 4096);
2274 drive_log_length -= WRITE_SIZE(sizeof(__u8) * 4096);
2275 }
2276
2277 ret = write(fd, drive_log_data, drive_log_length);
2278 if (ret < 0) {
2279 fprintf(stderrstderr, "ERROR: WDC: write: %s\n", libnvme_strerror(errno(*__errno_location ())));
2280 close(fd);
2281 return -1;
2282 }
2283
2284 if (fsync(fd) < 0) {
2285 fprintf(stderrstderr, "ERROR: WDC: fsync: %s\n", libnvme_strerror(errno(*__errno_location ())));
2286 close(fd);
2287 return -1;
2288 }
2289 close(fd);
2290 return 0;
2291}
2292
2293bool_Bool wdc_validate_dev_mng_log(void *data)
2294{
2295 __u32 remaining_len = 0;
2296 __u32 log_length = 0;
2297 __u32 log_entry_size = 0;
2298 __u32 log_entry_id = 0;
2299 __u32 offset = 0;
2300 bool_Bool valid_log = false0;
2301 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2302 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2303
2304 log_length = le32_to_cpu(hdr_ptr->length);
2305 /* Ensure log data is large enough for common header */
2306 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2307 fprintf(stderrstderr,
2308 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"l" "x""\n",
2309 __func__, log_length, sizeof(struct wdc_c2_log_page_header));
2310 return valid_log;
2311 }
2312
2313 /* Get pointer to first log Entry */
2314 offset = sizeof(struct wdc_c2_log_page_header);
2315 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2316 remaining_len = log_length - offset;
2317
2318 /* Proceed only if there is at least enough data to read an entry header */
2319 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2320 /* Get size of the next entry */
2321 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2322 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2323 /*
2324 * If log entry size is 0 or the log entry goes past the end
2325 * of the data, we must be at the end of the data
2326 */
2327 if (!log_entry_size || log_entry_size > remaining_len) {
2328 fprintf(stderrstderr, "ERROR: WDC: %s: Detected unaligned end of the data. ",
2329 __func__);
2330 fprintf(stderrstderr, "Data Offset: 0x%x Entry Size: 0x%x, ",
2331 offset, log_entry_size);
2332 fprintf(stderrstderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n",
2333 remaining_len, log_entry_id);
2334
2335 /* Force the loop to end */
2336 remaining_len = 0;
2337 } else if (!log_entry_id || log_entry_id > 200) {
2338 /* Invalid entry - fail the search */
2339 fprintf(stderrstderr, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",
2340 __func__, offset);
2341 fprintf(stderrstderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ",
2342 log_entry_size, remaining_len);
2343 fprintf(stderrstderr, "Entry Id: 0x%x\n", log_entry_id);
2344
2345 /* Force the loop to end */
2346 remaining_len = 0;
2347 valid_log = false0;
2348 } else {
2349 /* A valid log has at least one entry and no invalid entries */
2350 valid_log = true1;
2351 remaining_len -= log_entry_size;
2352 if (remaining_len > 0) {
2353 /* Increment the offset counter */
2354 offset += log_entry_size;
2355 /* Get the next entry */
2356 p_next_log_entry =
2357 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2358 }
2359 }
2360 }
2361
2362 return valid_log;
2363}
2364
2365bool_Bool wdc_parse_dev_mng_log_entry(void *data, __u32 entry_id,
2366 struct wdc_c2_log_subpage_header **log_entry)
2367{
2368 __u32 remaining_len = 0;
2369 __u32 log_length = 0;
2370 __u32 log_entry_size = 0;
2371 __u32 log_entry_id = 0;
2372 __u32 offset = 0;
2373 bool_Bool found = false0;
2374 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2375 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2376
2377 log_length = le32_to_cpu(hdr_ptr->length);
2378 /* Ensure log data is large enough for common header */
2379 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2380 fprintf(stderrstderr,
2381 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"l" "x""\n",
2382 __func__, log_length, sizeof(struct wdc_c2_log_page_header));
2383 return found;
2384 }
2385
2386 /* Get pointer to first log Entry */
2387 offset = sizeof(struct wdc_c2_log_page_header);
2388 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2389 remaining_len = log_length - offset;
2390
2391 if (!log_entry) {
2392 fprintf(stderrstderr, "ERROR: WDC - %s: No log entry pointer.\n", __func__);
2393 return found;
2394 }
2395 *log_entry = NULL((void*)0);
2396
2397 /* Proceed only if there is at least enough data to read an entry header */
2398 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2399 /* Get size of the next entry */
2400 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2401 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2402
2403 /*
2404 * If log entry size is 0 or the log entry goes past the end
2405 * of the data, we must be at the end of the data
2406 */
2407 if (!log_entry_size || log_entry_size > remaining_len) {
2408 fprintf(stderrstderr, "ERROR: WDC: %s: Detected unaligned end of the data. ",
2409 __func__);
2410 fprintf(stderrstderr, "Data Offset: 0x%x Entry Size: 0x%x, ",
2411 offset, log_entry_size);
2412 fprintf(stderrstderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n",
2413 remaining_len, log_entry_id);
2414
2415 /* Force the loop to end */
2416 remaining_len = 0;
2417 } else if (!log_entry_id || log_entry_id > 200) {
2418 /* Invalid entry - fail the search */
2419 fprintf(stderrstderr, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",
2420 __func__, offset);
2421 fprintf(stderrstderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ",
2422 log_entry_size, remaining_len);
2423 fprintf(stderrstderr, "Entry Id: 0x%x\n", log_entry_id);
2424
2425 /* Force the loop to end */
2426 remaining_len = 0;
2427 } else {
2428 if (log_entry_id == entry_id) {
2429 found = true1;
2430 *log_entry = p_next_log_entry;
2431 remaining_len = 0;
2432 } else {
2433 remaining_len -= log_entry_size;
2434 }
2435
2436 if (remaining_len > 0) {
2437 /* Increment the offset counter */
2438 offset += log_entry_size;
2439
2440 /* Get the next entry */
2441 p_next_log_entry =
2442 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2443 }
2444 }
2445 }
2446
2447 return found;
2448}
2449
2450bool_Bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id,
2451 struct wdc_c2_log_page_header *p_log_hdr,
2452 struct wdc_c2_log_subpage_header **p_p_found_log_entry)
2453{
2454 __u32 remaining_len = 0;
2455 __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1;
2456 __u32 log_entry_size = 0;
2457 __u32 log_entry_id = 0;
2458 __u32 size = 0;
2459 bool_Bool valid_log;
2460 __u32 offset = 0;
2461 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2462
2463 if (!*p_p_found_log_entry) {
2464 fprintf(stderrstderr, "ERROR: WDC - %s: No ppLogEntry pointer.\n", __func__);
2465 return false0;
2466 }
2467
2468 *p_p_found_log_entry = NULL((void*)0);
2469
2470 /* Ensure log data is large enough for common header */
2471 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2472 fprintf(stderrstderr,
2473 "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"l" "x""\n",
2474 __func__, log_length, sizeof(struct wdc_c2_log_page_header));
2475 return false0;
2476 }
2477
2478 /* Get pointer to first log Entry */
2479 size = sizeof(struct wdc_c2_log_page_header);
2480 offset = size;
2481 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2482 remaining_len = log_length - size;
2483 valid_log = false0;
2484
2485 /*
2486 * Walk the entire structure. Perform a sanity check to make sure this is a
2487 * standard version of the structure. This means making sure each entry looks
2488 * valid. But allow for the data to overflow the allocated
2489 * buffer (we don't want a false negative because of a FW formatting error)
2490 */
2491
2492 /* Proceed only if there is at least enough data to read an entry header */
2493 while (remaining_len >= log_entry_hdr_size) {
2494 /* Get size of the next entry */
2495 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2496 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2497
2498 /*
2499 * If log entry size is 0 or the log entry goes past the end
2500 * of the data, we must be at the end of the data
2501 */
2502 if (!log_entry_size || log_entry_size > remaining_len) {
2503 fprintf(stderrstderr, "ERROR: WDC: %s: Detected unaligned end of the data. ",
2504 __func__);
2505 fprintf(stderrstderr, "Data Offset: 0x%x Entry Size: 0x%x, ",
2506 offset, log_entry_size);
2507 fprintf(stderrstderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n",
2508 remaining_len, log_entry_id);
2509
2510 /* Force the loop to end */
2511 remaining_len = 0;
2512 } else if (!log_entry_id || log_entry_id > 200) {
2513 /* Invalid entry - fail the search */
2514 fprintf(stderrstderr, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",
2515 __func__, offset);
2516 fprintf(stderrstderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ",
2517 log_entry_size, remaining_len);
2518 fprintf(stderrstderr, "Entry Id: 0x%x\n", log_entry_id);
2519
2520 /* Force the loop to end */
2521 remaining_len = 0;
2522 valid_log = false0;
2523
2524 /* The structure is invalid, so any match that was found is invalid. */
2525 *p_p_found_log_entry = NULL((void*)0);
2526 } else {
2527 /* Structure must have at least one valid entry to be considered valid */
2528 valid_log = true1;
2529 if (log_entry_id == entry_id)
2530 /* A potential match. */
2531 *p_p_found_log_entry = p_next_log_entry;
2532
2533 remaining_len -= log_entry_size;
2534
2535 if (remaining_len > 0) {
2536 /* Increment the offset counter */
2537 offset += log_entry_size;
2538
2539 /* Get the next entry */
2540 p_next_log_entry =
2541 (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2542 }
2543 }
2544 }
2545
2546 return valid_log;
2547}
2548
2549static bool_Bool get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, void **log_data,
2550 __u8 uuid_ix)
2551{
2552 struct wdc_c2_log_page_header *hdr_ptr;
2553 struct libnvme_passthru_cmd cmd;
2554 bool_Bool valid = false0;
2555 __u32 length = 0;
2556 void *data;
2557 int ret = 0;
2558
2559 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2560 if (!data) {
2561 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2562 return false0;
2563 }
2564
2565 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2566
2567 /* get the log page length */
2568 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2569 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2570 WDC_C2_LOG_BUF_LEN0x1000);
2571 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2572 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2573 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2574 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2575 if (ret) {
2576 fprintf(stderrstderr,
2577 "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n",
2578 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, uuid_ix, ret);
2579 goto end;
2580 }
2581
2582 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2583 length = le32_to_cpu(hdr_ptr->length);
2584
2585 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2586 /* Log page buffer too small for actual data */
2587 free(data);
2588 data = calloc(length, sizeof(__u8));
2589 if (!data) {
2590 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2591 goto end;
2592 }
2593
2594 /* get the log page data with the increased length */
2595 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2596 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2597 length);
2598 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2599 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2600 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2601 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2602 if (ret) {
2603 fprintf(stderrstderr,
2604 "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n",
2605 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, uuid_ix, ret);
2606 goto end;
2607 }
2608 }
2609
2610 valid = wdc_validate_dev_mng_log(data);
2611 if (valid) {
2612 /* Ensure size of log data matches length in log header */
2613 *log_data = calloc(length, sizeof(__u8));
2614 if (!*log_data) {
2615 fprintf(stderrstderr, "ERROR: WDC: calloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2616 valid = false0;
2617 goto end;
2618 }
2619 memcpy((void *)*log_data, data, length);
2620 } else {
2621 fprintf(stderrstderr, "ERROR: WDC: C2 log page not found with uuid index %d\n",
2622 uuid_ix);
2623 }
2624
2625end:
2626 free(data);
2627 return valid;
2628}
2629
2630static bool_Bool get_dev_mgmt_log_page_lid_data(struct libnvme_transport_handle *hdl,
2631 void **cbs_data,
2632 __u8 lid,
2633 __u8 log_id,
2634 __u8 uuid_ix)
2635{
2636 void *data;
2637 struct wdc_c2_log_page_header *hdr_ptr;
2638 struct wdc_c2_log_subpage_header *sph;
2639 struct libnvme_passthru_cmd cmd;
2640 __u32 length = 0;
2641 int ret = 0;
2642 bool_Bool found = false0;
2643
2644 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2645 if (!data) {
2646 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2647 return false0;
2648 }
2649
2650 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2651
2652 /* get the log page length */
2653 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2654 WDC_C2_LOG_BUF_LEN0x1000);
2655 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2656 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2657 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2658 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2659 if (ret) {
2660 fprintf(stderrstderr,
2661 "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n",
2662 lid, uuid_ix, ret);
2663 goto end;
2664 }
2665
2666 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2667 length = le32_to_cpu(hdr_ptr->length);
2668
2669 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2670 /* Log Page buffer too small, free and reallocate the necessary size */
2671 free(data);
2672 data = calloc(length, sizeof(__u8));
2673 if (!data) {
2674 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2675 goto end;
2676 }
2677
2678 /* get the log page data with the increased length */
2679 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2680 length);
2681 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2682 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2683 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2684 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2685 if (ret) {
2686 fprintf(stderrstderr,
2687 "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n",
2688 lid, uuid_ix, ret);
2689 goto end;
2690 }
2691 }
2692
2693 /* Check the log data to see if the WD version of log page ID's is found */
2694 length = sizeof(struct wdc_c2_log_page_header);
2695 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2696 sph = (struct wdc_c2_log_subpage_header *)(data + length);
2697 found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
2698 if (found) {
2699 *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
2700 if (!*cbs_data) {
2701 fprintf(stderrstderr, "ERROR: WDC: calloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
2702 found = false0;
2703 goto end;
2704 }
2705 memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
2706 } else {
2707 fprintf(stderrstderr, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d\n",
2708 log_id, uuid_ix);
2709 }
2710
2711end:
2712 free(data);
2713 return found;
2714}
2715
2716static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2717 void **data)
2718{
2719 bool_Bool found = false0;
2720 __u32 device_id = 0, vendor_id = 0;
2721 int uuid_index = 0;
2722 struct nvme_id_uuid_list uuid_list;
2723
2724 *data = NULL((void*)0);
2725
2726 /* The wdc_get_pci_ids function could fail when drives are connected
2727 * via a PCIe switch. Therefore, the return code is intentionally
2728 * being ignored. The device_id and vendor_id variables have been
2729 * initialized to 0 so the code can continue on without issue for
2730 * both cases: wdc_get_pci_ids successful or failed.
2731 */
2732 wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id);
2733
2734 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2735 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2736 /* check for the Sandisk UUID first */
2737 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2738
2739 if (uuid_index < 0) {
2740 /* The Sandisk UUID is not found;
2741 * check for the WDC UUID second.
2742 */
2743 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2744 if (uuid_index < 0)
2745 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2746 }
2747
2748 if (uuid_index >= 0)
2749 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2750 else {
2751 fprintf(stderrstderr, "%s: UUID lists are supported but a matching ",
2752 __func__);
2753 fprintf(stderrstderr, "uuid was not found\n");
2754 }
2755 } else if (needs_c2_log_page_check(device_id)) {
2756 /* In certain devices that don't support UUID lists, there are multiple
2757 * definitions of the C2 logpage. In those cases, the code
2758 * needs to try two UUID indexes and use an identification algorithm
2759 * to determine which is returning the correct log page data.
2760 */
2761
2762 uuid_index = 1;
2763 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2764
2765 if (!found) {
2766 /* not found with uuid = 1 try with uuid = 0 */
2767 uuid_index = 0;
2768 fprintf(stderrstderr, "Not found, requesting log page with uuid_index %d\n",
2769 uuid_index);
2770
2771 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2772 }
2773 } else {
2774 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2775 uuid_index = 0;
2776 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2777 }
2778
2779 return found;
2780}
2781
2782static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2783 __u8 log_id, void **cbs_data)
2784{
2785 bool_Bool found = false0;
2786 __u8 lid = 0;
2787 __u32 device_id = 0, vendor_id = 0;
2788 int uuid_index = 0;
2789 struct nvme_id_uuid_list uuid_list;
2790
2791 *cbs_data = NULL((void*)0);
2792
2793 /* The wdc_get_pci_ids function could fail when drives are connected
2794 * via a PCIe switch. Therefore, the return code is intentionally
2795 * being ignored. The device_id and vendor_id variables have been
2796 * initialized to 0 so the code can continue on without issue for
2797 * both cases: wdc_get_pci_ids successful or failed.
2798 */
2799 wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id);
2800
2801 lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
2802
2803 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2804 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2805 /* check for the Sandisk UUID first */
2806 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2807
2808 if (uuid_index < 0) {
2809 /* The Sandisk UUID is not found;
2810 * check for the WDC UUID second.
2811 */
2812 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2813 if (uuid_index < 0)
2814 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2815 }
2816
2817 if (uuid_index >= 0)
2818 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid,
2819 log_id, uuid_index);
2820 else {
2821 fprintf(stderrstderr, "%s: UUID lists are supported but a matching ",
2822 __func__);
2823 fprintf(stderrstderr, "uuid was not found\n");
2824 }
2825 } else if (needs_c2_log_page_check(device_id)) {
2826 /* In certain devices that don't support UUID lists, there are multiple
2827 * definitions of the C2 logpage. In those cases, the code
2828 * needs to try two UUID indexes and use an identification algorithm
2829 * to determine which is returning the correct log page data.
2830 */
2831 uuid_index = 1;
2832 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2833 if (!found) {
2834 /* not found with uuid = 1 try with uuid = 0 */
2835 uuid_index = 0;
2836 fprintf(stderrstderr, "Not found, requesting log page with uuid_index %d\n",
2837 uuid_index);
2838
2839 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id,
2840 uuid_index);
2841 }
2842 } else {
2843 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2844 uuid_index = 0;
2845 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2846 }
2847
2848 return found;
2849}
2850
2851static int wdc_get_supported_log_pages(struct libnvme_transport_handle *hdl,
2852 struct nvme_supported_log_pages *supported,
2853 int uuid_index)
2854{
2855 struct libnvme_passthru_cmd cmd;
2856
2857 memset(supported, 0, sizeof(*supported));
2858 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
2859 NVME_CSI_NVM, supported, sizeof(*supported));
2860 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2861 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2862 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2863 return libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2864}
2865
2866static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
2867 struct libnvme_transport_handle *hdl,
2868 __u8 log_id,
2869 __u8 uuid_index)
2870{
2871 int i;
2872 bool_Bool found = false0;
2873 int err = -1;
2874 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
2875
2876 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_supported_log_pages *supports = NULL((void*)0);
2877
2878 /* Check log page id 0 (supported log pages) first */
2879 supports = libnvme_alloc(sizeof(*supports));
2880 if (!supports)
2881 return -ENOMEM12;
2882
2883 err = wdc_get_supported_log_pages(hdl,
2884 supports,
2885 uuid_index);
2886
2887 if (!err) {
2888 /* Check support log page list for support */
2889 if (supports->lid_support[log_id])
2890 /* Support for Log Page found in supported log pages */
2891 found = true1;
2892 }
2893
2894 /* if not found in the supported log pages (log id 0),
2895 * check the WDC C2 log page
2896 */
2897 if (!found) {
2898 if (get_dev_mgment_cbs_data(ctx, hdl,
2899 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
2900 (void *)&cbs_data)) {
2901 if (cbs_data) {
2902 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
2903 if (log_id == cbs_data->data[i]) {
2904 found = true1;
2905 break;
2906 }
2907 }
2908
2909#ifdef WDC_NVME_CLI_DEBUG
2910 if (!found) {
2911 fprintf(stderrstderr, "ERROR: WDC: Log Page 0x%x not supported\n",
2912 log_id);
2913 fprintf(stderrstderr, "WDC: Supported Log Pages:\n");
2914 /* print the supported pages */
2915 d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length),
2916 16, 1);
2917 }
2918#endif
2919 free(cbs_data);
2920 } else {
2921 fprintf(stderrstderr, "ERROR: WDC: cbs_data ptr = NULL\n");
2922 }
2923 } else {
2924 fprintf(stderrstderr, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",
2925 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08);
2926 }
2927 }
2928
2929 return found;
2930}
2931
2932static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data,
2933 __u32 entry_id)
2934{
2935 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2936
2937 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2938 if (entry_data) {
2939 *ret_data = le32_to_cpu(entry_data->data);
2940 return true1;
2941 }
2942 }
2943
2944 *ret_data = 0;
2945 return false0;
2946}
2947
2948static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
2949 __u32 entry_id,
2950 char *ret_data,
2951 __u32 *ret_data_len)
2952{
2953 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2954 struct wdc_c2_cbs_data *entry_str_data = NULL((void*)0);
2955
2956 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2957 if (entry_data) {
2958 entry_str_data = (struct wdc_c2_cbs_data *)&entry_data->data;
2959 memcpy(ret_data,
2960 (void *)&entry_str_data->data,
2961 le32_to_cpu(entry_str_data->length));
2962 *ret_data_len = le32_to_cpu(entry_str_data->length);
2963 return true1;
2964 }
2965 }
2966
2967 *ret_data = 0;
2968 *ret_data_len = 0;
2969 return false0;
2970}
2971
2972static bool_Bool wdc_nvme_get_dev_status_log_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __le32 *ret_data,
2973 __u8 log_id)
2974{
2975 __u32 *cbs_data = NULL((void*)0);
2976
2977 if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data)) {
2978 if (cbs_data) {
2979 memcpy((void *)ret_data, (void *)cbs_data, 4);
2980 free(cbs_data);
2981
2982 return true1;
2983 }
2984 }
2985
2986 *ret_data = 0;
2987 return false0;
2988}
2989
2990static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12)
2991{
2992 int ret;
2993 struct libnvme_passthru_cmd admin_cmd;
2994
2995 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2996 admin_cmd.opcode = opcode;
2997 admin_cmd.cdw12 = cdw12;
2998 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
2999 if (ret)
3000 fprintf(stdoutstdout, "ERROR: WDC: Crash dump erase failed\n");
3001 nvme_show_status(ret);
3002 return ret;
3003}
3004
3005static __u32 wdc_dump_length(struct libnvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length)
3006{
3007 int ret;
3008 __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN0x08] = {0};
3009 struct wdc_log_size *l;
3010 struct libnvme_passthru_cmd admin_cmd;
3011
3012 l = (struct wdc_log_size *) buf;
3013 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3014 admin_cmd.opcode = opcode;
3015 admin_cmd.addr = (__u64)(uintptr_t)buf;
3016 admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN0x08;
3017 admin_cmd.cdw10 = cdw10;
3018 admin_cmd.cdw12 = cdw12;
3019
3020 ret = libnvme_exec_admin_passthru(link, &admin_cmd);
3021 if (ret) {
3022 l->log_size = 0;
3023 ret = -1;
3024 fprintf(stderrstderr, "ERROR: WDC: reading dump length failed\n");
3025 nvme_show_status(ret);
3026 return ret;
3027 }
3028
3029 if (opcode == WDC_NVME_CAP_DIAG_OPCODE0xE6)
3030 *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07];
3031 else
3032 *dump_length = le32_to_cpu(l->log_size);
3033 return ret;
3034}
3035
3036static __u32 wdc_dump_length_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
3037{
3038 int ret;
3039 struct libnvme_passthru_cmd admin_cmd;
3040
3041 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3042 admin_cmd.opcode = opcode;
3043 admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
3044 admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3045 admin_cmd.cdw10 = cdw10;
3046 admin_cmd.cdw12 = cdw12;
3047
3048 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3049 if (ret) {
3050 fprintf(stderrstderr, "ERROR: WDC: reading dump length failed\n");
3051 nvme_show_status(ret);
3052 }
3053
3054 return ret;
3055}
3056
3057static __u32 wdc_dump_dui_data(struct libnvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool_Bool last_xfer)
3058{
3059 int ret;
3060 struct libnvme_passthru_cmd admin_cmd;
3061
3062 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3063 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3064 admin_cmd.nsid = 0xFFFFFFFF;
3065 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3066 admin_cmd.data_len = dataLen;
3067 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3068 admin_cmd.cdw12 = offset;
3069 if (last_xfer)
3070 admin_cmd.cdw14 = 0;
3071 else
3072 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3073
3074
3075 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3076 if (ret) {
3077 fprintf(stderrstderr, "ERROR: WDC: reading DUI data failed\n");
3078 nvme_show_status(ret);
3079 }
3080
3081 return ret;
3082}
3083
3084static __u32 wdc_dump_dui_data_v2(struct libnvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool_Bool last_xfer)
3085{
3086 int ret;
3087 struct libnvme_passthru_cmd admin_cmd;
3088 __u64 offset_lo, offset_hi;
3089
3090 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3091 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3092 admin_cmd.nsid = 0xFFFFFFFF;
3093 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3094 admin_cmd.data_len = dataLen;
3095 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3096 offset_lo = offset & 0x00000000FFFFFFFF;
3097 offset_hi = ((offset & 0xFFFFFFFF00000000) >> 32);
3098 admin_cmd.cdw12 = (__u32)offset_lo;
3099 admin_cmd.cdw13 = (__u32)offset_hi;
3100
3101 if (last_xfer)
3102 admin_cmd.cdw14 = 0;
3103 else
3104 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3105
3106 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3107 if (ret) {
3108 fprintf(stderrstderr, "ERROR: WDC: reading DUI data V2 failed\n");
3109 nvme_show_status(ret);
3110 }
3111
3112 return ret;
3113}
3114
3115static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3116 __u32 cdw12, const char *file, __u32 xfer_size)
3117{
3118 int ret = 0;
3119 __u8 *dump_data;
3120 __u32 curr_data_offset, curr_data_len;
3121 int i;
3122 struct libnvme_passthru_cmd admin_cmd;
3123 __u32 dump_length = data_len;
3124
3125 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
3126 if (!dump_data) {
3127 fprintf(stderrstderr, "%s: ERROR: malloc: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
3128 return -1;
3129 }
3130 memset(dump_data, 0, sizeof(__u8) * dump_length);
3131 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3132 curr_data_offset = 0;
3133 curr_data_len = xfer_size;
3134 i = 0;
3135
3136 admin_cmd.opcode = opcode;
3137 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3138 admin_cmd.data_len = curr_data_len;
3139 admin_cmd.cdw10 = curr_data_len >> 2;
3140 admin_cmd.cdw12 = cdw12;
3141 admin_cmd.cdw13 = curr_data_offset;
3142
3143 while (curr_data_offset < data_len) {
3144 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3145 if (ret) {
3146 nvme_show_status(ret);
3147 fprintf(stderrstderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
3148 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr);
3149 break;
3150 }
3151
3152 if ((curr_data_offset + xfer_size) <= data_len)
3153 curr_data_len = xfer_size;
3154 else
3155 curr_data_len = data_len - curr_data_offset; /* last transfer */
3156
3157 curr_data_offset += curr_data_len;
3158 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3159 admin_cmd.data_len = curr_data_len;
3160 admin_cmd.cdw10 = curr_data_len >> 2;
3161 admin_cmd.cdw13 = curr_data_offset >> 2;
3162 i++;
3163 }
3164
3165 if (!ret) {
3166 nvme_show_status(ret);
3167 ret = wdc_create_log_file(file, dump_data, dump_length);
3168 }
3169 free(dump_data);
3170 return ret;
3171}
3172
3173static int wdc_do_dump_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3174 __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
3175{
3176 int ret = 0;
3177 __u8 *dump_data;
3178 __u32 curr_data_offset, log_size;
3179 int i;
3180 struct libnvme_passthru_cmd admin_cmd;
3181
3182 /* if data_len is not 4 byte aligned */
3183 if (data_len & 0x00000003) {
3184 /* Round down to the next 4 byte aligned value */
3185 fprintf(stderrstderr, "%s: INFO: data_len 0x%x not 4 byte aligned.\n",
3186 __func__, data_len);
3187 fprintf(stderrstderr, "%s: INFO: Round down to 0x%x.\n",
3188 __func__, (data_len &= 0xFFFFFFFC));
3189 data_len &= 0xFFFFFFFC;
3190 }
3191
3192 dump_data = (__u8 *)malloc(sizeof(__u8) * data_len);
3193
3194 if (!dump_data) {
3195 fprintf(stderrstderr, "%s: ERROR: malloc: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
3196 return -1;
3197 }
3198 memset(dump_data, 0, sizeof(__u8) * data_len);
3199 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3200 curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3201 i = 0;
3202
3203 /* copy the 8 byte header into the dump_data buffer */
3204 memcpy(dump_data, log_hdr, WDC_NVME_LOG_SIZE_HDR_LEN0x08);
3205
3206 admin_cmd.opcode = opcode;
3207 admin_cmd.cdw12 = cdw12;
3208
3209 /* subtract off the header size since that was already copied into the buffer */
3210 log_size = (data_len - curr_data_offset);
3211 while (log_size > 0) {
3212 xfer_size = min(xfer_size, log_size)((xfer_size) > (log_size) ? (log_size) : (xfer_size));
3213
3214 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3215 admin_cmd.data_len = xfer_size;
3216 admin_cmd.cdw10 = xfer_size >> 2;
3217 admin_cmd.cdw13 = curr_data_offset >> 2;
3218
3219 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3220 if (ret) {
3221 nvme_show_status(ret);
3222 fprintf(stderrstderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
3223 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr);
3224 break;
3225 }
3226
3227 log_size -= xfer_size;
3228 curr_data_offset += xfer_size;
3229 i++;
3230 }
3231
3232 if (!ret) {
3233 fprintf(stderrstderr, "%s: INFO: ", __func__);
3234 nvme_show_status(ret);
3235 } else {
3236 fprintf(stderrstderr, "%s: FAILURE: ", __func__);
3237 nvme_show_status(ret);
3238 fprintf(stderrstderr, "%s: Partial data may have been captured\n", __func__);
3239 snprintf(file + strlen(file), PATH_MAX4096, "%s", "-PARTIAL");
3240 }
3241
3242 ret = wdc_create_log_file(file, dump_data, data_len);
3243
3244 free(dump_data);
3245 return ret;
3246}
3247
3248static int wdc_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
3249 struct libnvme_transport_handle *hdl, const char *file,
3250 __u32 bs, int type, int data_area)
3251{
3252 struct nvme_telemetry_log *log;
3253 size_t full_size = 0;
3254 int err = 0, output;
3255 __u32 host_gen = 1;
3256 int ctrl_init = 0;
3257 __u64 result;
3258 void *buf = NULL((void*)0);
3259 __u8 *data_ptr = NULL((void*)0);
3260 int data_written = 0, data_remaining = 0;
3261 struct nvme_id_ctrl ctrl;
3262 __u64 capabilities = 0;
3263
3264 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
3265 err = nvme_identify_ctrl(hdl, &ctrl);
3266 if (err) {
3267 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err);
3268 return err;
3269 }
3270
3271 if (!(ctrl.lpa & 0x8)) {
3272 fprintf(stderrstderr, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported\n");
3273 return -EINVAL22;
3274 }
3275
3276 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3277 if (err) {
3278 fprintf(stderrstderr, "Failed to scan nvme subsystems\n");
3279 return err;
3280 }
3281
3282 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3283
3284 if (type == WDC_TELEMETRY_TYPE_HOST0x1) {
3285 host_gen = 1;
3286 ctrl_init = 0;
3287 } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2) {
3288 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
3289 /* Verify the Controller Initiated Option is enabled */
3290 err = nvme_get_features(hdl, 0,
3291 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
3292 NVME_GET_FEATURES_SEL_CURRENT, 0, 0,
3293 buf, 4, &result);
3294 if (!err) {
3295 if (!result) {
3296 /* enabled */
3297 host_gen = 0;
3298 ctrl_init = 1;
3299 } else {
3300 fprintf(stderrstderr, "%s: Controller initiated option telemetry log page disabled\n", __func__);
3301 return -EINVAL22;
3302 }
3303 } else {
3304 fprintf(stderrstderr, "ERROR: WDC: Get telemetry option feature failed.");
3305 nvme_show_status(err);
3306 return -EPERM1;
3307 }
3308 } else {
3309 host_gen = 0;
3310 ctrl_init = 1;
3311 }
3312 } else {
3313 fprintf(stderrstderr, "%s: Invalid type parameter; type = %d\n", __func__, type);
3314 return -EINVAL22;
3315 }
3316
3317 if (!file) {
3318 fprintf(stderrstderr, "%s: Please provide an output file!\n", __func__);
3319 return -EINVAL22;
3320 }
3321
3322 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3323 if (output < 0) {
3324 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n",
3325 __func__, file, libnvme_strerror(errno(*__errno_location ())));
3326 return output;
3327 }
3328
3329 if (ctrl_init)
3330 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
3331 data_area, &full_size);
3332 else if (host_gen)
3333 err = libnvme_get_new_host_telemetry(hdl, &log,
3334 data_area, &full_size);
3335 else
3336 err = libnvme_get_host_telemetry(hdl, &log, data_area,
3337 &full_size);
3338
3339 if (err < 0) {
3340 perror("get-telemetry-log");
3341 goto close_output;
3342 } else if (err > 0) {
3343 nvme_show_status(err);
3344 fprintf(stderrstderr, "%s: Failed to acquire telemetry header!\n", __func__);
3345 goto close_output;
3346 }
3347
3348 /*
3349 *Continuously pull data until the offset hits the end of the last
3350 *block.
3351 */
3352 data_written = 0;
3353 data_remaining = full_size;
3354 data_ptr = (__u8 *)log;
3355
3356 while (data_remaining) {
3357 data_written = write(output, data_ptr, data_remaining);
3358
3359 if (data_written < 0) {
3360 data_remaining = data_written;
3361 break;
3362 } else if (data_written <= data_remaining) {
3363 data_remaining -= data_written;
3364 data_ptr += data_written;
3365 } else {
3366 /* Unexpected overwrite */
3367 fprintf(stderrstderr, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x\n",
3368 data_remaining, data_written);
3369 break;
3370 }
3371 }
3372
3373 if (fsync(output) < 0) {
3374 fprintf(stderrstderr, "ERROR: %s: fsync: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
3375 err = -1;
3376 }
3377
3378 free(log);
3379close_output:
3380 close(output);
3381 return err;
3382}
3383
3384static int wdc_do_cap_diag(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *file,
3385 __u32 xfer_size, int type, int data_area)
3386{
3387 int ret = -1;
3388 __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08;
3389 struct wdc_e6_log_hdr *log_hdr;
3390 __u32 cap_diag_length;
3391
3392 log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size);
3393 if (!log_hdr) {
3394 fprintf(stderrstderr, "%s: ERROR: malloc: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
3395 ret = -1;
3396 goto out;
3397 }
3398 memset(log_hdr, 0, e6_log_hdr_size);
3399
3400 if (type == WDC_TELEMETRY_TYPE_NONE0x0) {
3401 if (data_area) {
3402 fprintf(stderrstderr,
3403 "%s: ERROR: Data area parameter is not supported when type is NONE\n",
3404 __func__);
3405 ret = -1;
3406 goto out;
3407 }
3408 ret = wdc_dump_length_e6(hdl,
3409 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3410 WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08>>2,
3411 0x00,
3412 log_hdr);
3413 if (ret == -1) {
3414 ret = -1;
3415 goto out;
3416 }
3417
3418 cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 |
3419 log_hdr->log_size[2] << 8 | log_hdr->log_size[3]);
3420
3421 if (!cap_diag_length) {
3422 fprintf(stderrstderr, "INFO: WDC: Capture Diagnostics log is empty\n");
3423 } else {
3424 ret = wdc_do_dump_e6(hdl,
3425 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3426 cap_diag_length,
3427 (WDC_NVME_CAP_DIAG_SUBCMD0x00 << WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_CAP_DIAG_CMD0x00,
3428 file, xfer_size, (__u8 *)log_hdr);
3429
3430 fprintf(stderrstderr, "INFO: WDC: Capture Diagnostics log, length = 0x%x\n", cap_diag_length);
3431 }
3432 } else if ((type == WDC_TELEMETRY_TYPE_HOST0x1) ||
3433 (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
3434 /* Get the desired telemetry log page */
3435 ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size,
3436 type, data_area);
3437 } else {
3438 fprintf(stderrstderr, "%s: ERROR: Invalid type : %d\n", __func__, type);
3439 }
3440
3441out:
3442 free(log_hdr);
3443 return ret;
3444}
3445
3446static int wdc_do_cap_dui_v1(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3447 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size)
3448{
3449 __s32 log_size = 0;
3450 __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size);
3451 __u32 curr_data_offset = 0;
3452 __u8 *buffer_addr;
3453 __u8 *dump_data = NULL((void*)0);
3454 bool_Bool last_xfer = false0;
3455 int err;
3456 int i;
3457 int j;
3458 int output;
3459 int ret = 0;
3460
3461 if (verbose) {
3462 fprintf(stderrstderr, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d\n",
3463 data_area);
3464 fprintf(stderrstderr, "INFO: WDC: DUI Header Version = 0x%x\n", log_hdr->hdr_version);
3465 fprintf(stderrstderr, "INFO: WDC: DUI section count = 0x%x\n", log_hdr->section_count);
3466 fprintf(stderrstderr, "INFO: WDC: DUI log size = 0x%x\n", log_hdr->log_size);
3467 }
3468
3469 if (!cap_dui_length) {
3470 fprintf(stderrstderr, "INFO: WDC: Capture V1 Device Unit Info log is empty\n");
3471 return 0;
3472 }
3473
3474 /* parse log header for all sections up to specified data area inclusively */
3475 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3476 for (j = 0; j < log_hdr->section_count; j++) {
3477 log_size += log_hdr->log_section[j].section_size;
3478 if (verbose)
3479 fprintf(stderrstderr,
3480 "%s: section size 0x%x, total size = 0x%x\n",
3481 __func__,
3482 (unsigned int)log_hdr->log_section[j].section_size,
3483 (unsigned int)log_size);
3484
3485 }
3486 } else {
3487 log_size = cap_dui_length;
3488 }
3489
3490 *total_size = log_size;
3491
3492 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size);
3493 if (!dump_data) {
3494 fprintf(stderrstderr, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x\n",
3495 __func__, libnvme_strerror(errno(*__errno_location ())), (unsigned int)xfer_size);
3496 return -1;
3497 }
3498 memset(dump_data, 0, sizeof(__u8) * xfer_size);
3499
3500 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3501 if (output < 0) {
3502 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n", __func__, file,
3503 libnvme_strerror(errno(*__errno_location ())));
3504 free(dump_data);
3505 return output;
3506 }
3507
3508 /* write the telemetry and log headers into the dump_file */
3509 err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE0x400);
3510 if (err != WDC_NVME_CAP_DUI_HEADER_SIZE0x400) {
3511 fprintf(stderrstderr, "%s: Failed to flush header data to file!\n", __func__);
3512 goto free_mem;
3513 }
3514
3515 log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3516 curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3517 i = 0;
3518 buffer_addr = dump_data;
3519
3520 for (; log_size > 0; log_size -= xfer_size) {
3521 xfer_size = min(xfer_size, log_size)((xfer_size) > (log_size) ? (log_size) : (xfer_size));
3522
3523 if (log_size <= xfer_size)
3524 last_xfer = true1;
3525
3526 ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer);
3527 if (ret) {
3528 fprintf(stderrstderr,
3529 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64"l" "x"", offset = 0x%x, addr = %p\n",
3530 __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr);
3531 fprintf(stderrstderr, "%s: ERROR: WDC: ", __func__);
3532 nvme_show_status(ret);
3533 break;
3534 }
3535
3536 /* write the dump data into the file */
3537 err = write(output, (void *)buffer_addr, xfer_size);
3538 if (err != xfer_size) {
3539 fprintf(stderrstderr,
3540 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n",
3541 __func__, i, err, xfer_size);
3542 ret = -1;
3543 goto free_mem;
3544 }
3545
3546 curr_data_offset += xfer_size;
3547 i++;
3548 }
3549
3550free_mem:
3551 close(output);
3552 free(dump_data);
3553 return ret;
3554}
3555
3556static int wdc_do_cap_dui_v2_v3(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3557 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3558 __u64 offset)
3559{
3560 __u64 cap_dui_length_v3;
3561 __u64 curr_data_offset = 0;
3562 __s64 log_size = 0;
3563 __u64 xfer_size_long = (__u64)xfer_size;
3564 __u8 *buffer_addr;
3565 __u8 *dump_data = NULL((void*)0);
3566 bool_Bool last_xfer = false0;
3567 int err;
3568 int i;
3569 int j;
3570 int output;
3571 int ret = 0;
3572 struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr;
3573
3574 cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size);
3575
3576 if (verbose) {
3577 fprintf(stderrstderr,
3578 "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n",
3579 data_area);
3580
3581 fprintf(stderrstderr, "INFO: WDC: DUI Header Version = 0x%x\n",
3582 log_hdr_v3->hdr_version);
3583 if ((log_hdr->hdr_version & 0xFF) == 0x03)
3584 fprintf(stderrstderr, "INFO: WDC: DUI Product ID = 0x%x/%c\n",
3585 log_hdr_v3->product_id, log_hdr_v3->product_id);
3586 }
3587
3588 if (!cap_dui_length_v3) {
3589 fprintf(stderrstderr, "INFO: WDC: Capture V2 or V3 Device Unit Info log is empty\n");
3590 return 0;
3591 }
3592
3593 /* parse log header for all sections up to specified data area inclusively */
3594 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3595 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V30x23; j++) {
3596 if (log_hdr_v3->log_section[j].data_area_id <= data_area &&
3597 log_hdr_v3->log_section[j].data_area_id) {
3598 log_size += log_hdr_v3->log_section[j].section_size;
3599 if (verbose)
3600 fprintf(stderrstderr,
3601 "%s: Data area ID %d : section size 0x%x, total size = 0x%"PRIx64"l" "x""\n",
3602 __func__, log_hdr_v3->log_section[j].data_area_id,
3603 (unsigned int)log_hdr_v3->log_section[j].section_size,
3604 (uint64_t)log_size);
3605 } else {
3606 if (verbose)
3607 fprintf(stderrstderr, "%s: break, total size = 0x%"PRIx64"l" "x""\n",
3608 __func__, (uint64_t)log_size);
3609 break;
3610 }
3611 }
3612 } else {
3613 log_size = cap_dui_length_v3;
3614 }
3615
3616 *total_size = log_size;
3617
3618 if (offset >= *total_size) {
3619 fprintf(stderrstderr,
3620 "%s: INFO: WDC: Offset 0x%"PRIx64"l" "x"" exceeds total size 0x%"PRIx64"l" "x"", no data retrieved\n",
3621 __func__, (uint64_t)offset, (uint64_t)*total_size);
3622 return -1;
3623 }
3624
3625 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3626 if (!dump_data) {
3627 fprintf(stderrstderr,
3628 "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"PRIx64"l" "x""\n",
3629 __func__, libnvme_strerror(errno(*__errno_location ())), (uint64_t)xfer_size_long);
3630 return -1;
3631 }
3632 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3633
3634 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3635 if (output < 0) {
3636 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n",
3637 __func__, file, libnvme_strerror(errno(*__errno_location ())));
3638 free(dump_data);
3639 return output;
3640 }
3641
3642 curr_data_offset = 0;
3643
3644 if (file_size) {
3645 /* Write the DUI data based on the passed in file size */
3646 if ((offset + file_size) > *total_size)
3647 log_size = min((*total_size - offset), file_size)(((*total_size - offset)) > (file_size) ? (file_size) : ((
*total_size - offset)))
;
3648 else
3649 log_size = min(*total_size, file_size)((*total_size) > (file_size) ? (file_size) : (*total_size)
)
;
3650
3651 if (verbose)
3652 fprintf(stderrstderr,
3653 "%s: INFO: WDC: Offset 0x%"PRIx64"l" "x"", file size 0x%"PRIx64"l" "x"", total size 0x%"PRIx64"l" "x"", log size 0x%"PRIx64"l" "x""\n",
3654 __func__, (uint64_t)offset,
3655 (uint64_t)file_size, (uint64_t)*total_size, (uint64_t)log_size);
3656
3657 curr_data_offset = offset;
3658 }
3659
3660 i = 0;
3661 buffer_addr = dump_data;
3662
3663 for (; log_size > 0; log_size -= xfer_size_long) {
3664 xfer_size_long = min(xfer_size_long, log_size)((xfer_size_long) > (log_size) ? (log_size) : (xfer_size_long
))
;
3665
3666 if (log_size <= xfer_size_long)
3667 last_xfer = true1;
3668
3669 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr,
3670 last_xfer);
3671 if (ret) {
3672 fprintf(stderrstderr,
3673 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64"l" "x"", offset = 0x%"PRIx64"l" "x"", addr = %p\n",
3674 __func__, i, (uint64_t)*total_size, (uint64_t)curr_data_offset,
3675 buffer_addr);
3676 fprintf(stderrstderr, "%s: ERROR: WDC: ", __func__);
3677 nvme_show_status(ret);
3678 break;
3679 }
3680
3681 /* write the dump data into the file */
3682 err = write(output, (void *)buffer_addr, xfer_size_long);
3683 if (err != xfer_size_long) {
3684 fprintf(stderrstderr,
3685 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"PRIx64"l" "x""\n",
3686 __func__, i, err, (uint64_t)xfer_size_long);
3687 ret = -1;
3688 goto free_mem;
3689 }
3690
3691 curr_data_offset += xfer_size_long;
3692 i++;
3693 }
3694
3695free_mem:
3696 close(output);
3697 free(dump_data);
3698 return ret;
3699}
3700
3701static int wdc_do_cap_dui_v4(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3702 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3703 __u64 offset)
3704{
3705 __s64 log_size = 0;
3706 __s64 section_size_bytes = 0;
3707 __s64 xfer_size_long = (__s64)xfer_size;
3708 __u64 cap_dui_length_v4;
3709 __u64 curr_data_offset = 0;
3710 __u8 *buffer_addr;
3711 __u8 *dump_data = NULL((void*)0);
3712 int err;
3713 int i;
3714 int j;
3715 int output;
3716 int ret = 0;
3717 bool_Bool last_xfer = false0;
3718 struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr;
3719
3720 cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE512;
3721
3722 if (verbose) {
3723 fprintf(stderrstderr, "INFO: WDC: Capture V4 Device Unit Info log, data area = %d\n", data_area);
3724 fprintf(stderrstderr, "INFO: WDC: DUI Header Version = 0x%x\n", log_hdr_v4->hdr_version);
3725 fprintf(stderrstderr, "INFO: WDC: DUI Product ID = 0x%x/%c\n", log_hdr_v4->product_id, log_hdr_v4->product_id);
3726 fprintf(stderrstderr, "INFO: WDC: DUI log size sectors = 0x%x\n", log_hdr_v4->log_size_sectors);
3727 fprintf(stderrstderr, "INFO: WDC: DUI cap_dui_length = 0x%"PRIx64"l" "x""\n", (uint64_t)cap_dui_length_v4);
3728 }
3729
3730 if (!cap_dui_length_v4) {
3731 fprintf(stderrstderr, "INFO: WDC: Capture V4 Device Unit Info log is empty\n");
3732 return 0;
3733 }
3734
3735 /* parse log header for all sections up to specified data area inclusively */
3736 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3737 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION0x3A; j++) {
3738 if (log_hdr_v4->log_section[j].data_area_id <= data_area &&
3739 log_hdr_v4->log_section[j].data_area_id) {
3740 section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE512);
3741 log_size += section_size_bytes;
3742 if (verbose)
3743 fprintf(stderrstderr,
3744 "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"PRIx64"l" "x"" bytes, total size = 0x%"PRIx64"l" "x""\n",
3745 __func__, log_hdr_v4->log_section[j].data_area_id,
3746 log_hdr_v4->log_section[j].section_size_sectors,
3747 (uint64_t)section_size_bytes, (uint64_t)log_size);
3748 } else {
3749 if (verbose)
3750 fprintf(stderrstderr, "%s: break, total size = 0x%"PRIx64"l" "x""\n", __func__, (uint64_t)log_size);
3751 break;
3752 }
3753 }
3754 } else {
3755 log_size = cap_dui_length_v4;
3756 }
3757
3758 *total_size = log_size;
3759
3760 if (offset >= *total_size) {
3761 fprintf(stderrstderr,
3762 "%s: INFO: WDC: Offset 0x%"PRIx64"l" "x"" exceeds total size 0x%"PRIx64"l" "x"", no data retrieved\n",
3763 __func__, (uint64_t)offset, (uint64_t)*total_size);
3764 return -1;
3765 }
3766
3767 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3768 if (!dump_data) {
3769 fprintf(stderrstderr, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x\n",
3770 __func__, libnvme_strerror(errno(*__errno_location ())), (unsigned int)xfer_size_long);
3771 return -1;
3772 }
3773 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3774
3775 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3776 if (output < 0) {
3777 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n", __func__, file,
3778 libnvme_strerror(errno(*__errno_location ())));
3779 free(dump_data);
3780 return output;
3781 }
3782
3783 curr_data_offset = 0;
3784
3785 if (file_size) {
3786 /* Write the DUI data based on the passed in file size */
3787 if ((offset + file_size) > *total_size)
3788 log_size = min((*total_size - offset), file_size)(((*total_size - offset)) > (file_size) ? (file_size) : ((
*total_size - offset)))
;
3789 else
3790 log_size = min(*total_size, file_size)((*total_size) > (file_size) ? (file_size) : (*total_size)
)
;
3791
3792 if (verbose)
3793 fprintf(stderrstderr,
3794 "%s: INFO: WDC: Offset 0x%"PRIx64"l" "x"", file size 0x%"PRIx64"l" "x"", total size 0x%"PRIx64"l" "x"", log size 0x%"PRIx64"l" "x""\n",
3795 __func__, (uint64_t)offset, (uint64_t)file_size,
3796 (uint64_t)*total_size, (uint64_t)log_size);
3797
3798 curr_data_offset = offset;
3799 }
3800
3801 i = 0;
3802 buffer_addr = dump_data;
3803
3804 for (; log_size > 0; log_size -= xfer_size_long) {
3805 xfer_size_long = min(xfer_size_long, log_size)((xfer_size_long) > (log_size) ? (log_size) : (xfer_size_long
))
;
3806
3807 if (log_size <= xfer_size_long)
3808 last_xfer = true1;
3809
3810 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer);
3811 if (ret) {
3812 fprintf(stderrstderr,
3813 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64"l" "x"", offset = 0x%"PRIx64"l" "x"", addr = %p\n",
3814 __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset,
3815 buffer_addr);
3816 fprintf(stderrstderr, "%s: ERROR: WDC:", __func__);
3817 nvme_show_status(ret);
3818 break;
3819 }
3820
3821 /* write the dump data into the file */
3822 err = write(output, (void *)buffer_addr, xfer_size_long);
3823 if (err != xfer_size_long) {
3824 fprintf(stderrstderr,
3825 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"PRIx64"l" "x""\n",
3826 __func__, i, err, (uint64_t)xfer_size_long);
3827 ret = -1;
3828 goto free_mem;
3829 }
3830
3831 curr_data_offset += xfer_size_long;
3832 i++;
3833 }
3834
3835free_mem:
3836 close(output);
3837 free(dump_data);
3838 return ret;
3839}
3840
3841static int wdc_do_cap_dui(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3842 __u64 file_size, __u64 offset)
3843{
3844 int ret = 0;
3845 __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3846 struct wdc_dui_log_hdr *log_hdr;
3847 __s64 total_size = 0;
3848 bool_Bool last_xfer = false0;
3849
3850 log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size);
3851 if (!log_hdr) {
3852 fprintf(stderrstderr, "%s: ERROR: log header malloc failed : status %s, size 0x%x\n",
3853 __func__, libnvme_strerror(errno(*__errno_location ())), dui_log_hdr_size);
3854 return -1;
3855 }
3856 memset(log_hdr, 0, dui_log_hdr_size);
3857
3858 /* get the dui telemetry and log headers */
3859 ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE0x400, 0x00, (__u8 *)log_hdr, last_xfer);
3860 if (ret) {
3861 fprintf(stderrstderr, "%s: ERROR: WDC: Get DUI headers failed\n", __func__);
3862 fprintf(stderrstderr, "%s: ERROR: WDC: ", __func__);
3863 nvme_show_status(ret);
3864 goto out;
3865 }
3866
3867 /* Check the Log Header version */
3868 if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) {
3869 ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr,
3870 &total_size);
3871 if (ret)
3872 goto out;
3873 } else if ((log_hdr->hdr_version & 0xFF) == 0x02 ||
3874 (log_hdr->hdr_version & 0xFF) == 0x03) {
3875 /* Process Version 2 or 3 header */
3876 ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr,
3877 &total_size, file_size, offset);
3878 if (ret)
3879 goto out;
3880 } else if ((log_hdr->hdr_version & 0xFF) == 0x04) {
3881 ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr,
3882 &total_size, file_size, offset);
3883 if (ret)
3884 goto out;
3885 } else {
3886 fprintf(stderrstderr, "INFO: WDC: Unsupported header version = 0x%x\n",
3887 log_hdr->hdr_version);
3888 goto out;
3889 }
3890
3891 nvme_show_status(ret);
3892 if (verbose)
3893 fprintf(stderrstderr, "INFO: WDC: Capture Device Unit Info log, length = 0x%"PRIx64"l" "x""\n",
3894 (uint64_t)total_size);
3895
3896out:
3897 free(log_hdr);
3898 return ret;
3899}
3900
3901static int wdc_cap_diag(int argc, char **argv, struct command *acmd,
3902 struct plugin *plugin)
3903{
3904 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
3905 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
3906 const char *desc = "Capture Diagnostics Log.";
3907 const char *file = "Output file pathname.";
3908 const char *size = "Data retrieval transfer size.";
3909 __u64 capabilities = 0;
3910 char f[PATH_MAX4096] = {0};
3911 __u32 xfer_size = 0;
3912 int ret = 0;
3913
3914 struct config {
3915 char *file;
3916 __u32 xfer_size;
3917 };
3918
3919 struct config cfg = {
3920 .file = NULL((void*)0),
3921 .xfer_size = 0x10000
3922 };
3923
3924 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
3925 OPT_FILE("output-file", 'O', &cfg.file, file),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
3926 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
3927
3928 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3929 if (ret)
3930 return ret;
3931
3932 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3933 if (ret)
3934 return ret;
3935
3936 if (cfg.file)
3937 strncpy(f, cfg.file, PATH_MAX4096 - 1);
3938 if (cfg.xfer_size)
3939 xfer_size = cfg.xfer_size;
3940 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "cap_diag");
3941 if (ret) {
3942 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
3943 return ret;
3944 }
3945 if (!cfg.file) {
3946 if (strlen(f) > PATH_MAX4096 - 5) {
3947 fprintf(stderrstderr, "ERROR: WDC: file name overflow\n");
3948 return -1;
3949 }
3950 strcat(f, ".bin");
3951 }
3952
3953 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3954 if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001) == WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001)
3955 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0);
3956 else
3957 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
3958 return ret;
3959}
3960
3961static int wdc_do_get_sn730_log_len(struct libnvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode)
3962{
3963 int ret;
3964 uint32_t *output = NULL((void*)0);
3965 struct libnvme_passthru_cmd admin_cmd;
3966
3967 output = (uint32_t *)malloc(sizeof(uint32_t));
3968 if (!output) {
3969 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
3970 return -1;
3971 }
3972 memset(output, 0, sizeof(uint32_t));
3973 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3974
3975 admin_cmd.data_len = 8;
3976 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3977 admin_cmd.addr = (uintptr_t)output;
3978 admin_cmd.cdw12 = subopcode;
3979 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3980
3981 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3982 if (!ret)
3983 *len_buf = *output;
3984 free(output);
3985 return ret;
3986}
3987
3988static int wdc_do_get_sn730_log(struct libnvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode)
3989{
3990 int ret;
3991 uint8_t *output = NULL((void*)0);
3992 struct libnvme_passthru_cmd admin_cmd;
3993
3994 output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE0x1000, sizeof(uint8_t));
3995 if (!output) {
3996 fprintf(stderrstderr, "ERROR: WDC: calloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
3997 return -1;
3998 }
3999 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4000 admin_cmd.data_len = SN730_LOG_CHUNK_SIZE0x1000;
4001 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
4002 admin_cmd.addr = (uintptr_t)output;
4003 admin_cmd.cdw12 = subopcode;
4004 admin_cmd.cdw13 = offset;
4005 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
4006
4007 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4008 if (!ret)
4009 memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE0x1000);
4010 return ret;
4011}
4012
4013static int get_sn730_log_chunks(struct libnvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode)
4014{
4015 int ret = 0;
4016 uint8_t *chunk_buf = NULL((void*)0);
4017 int remaining = log_len;
4018 int curr_offset = 0;
4019
4020 chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE0x1000);
4021 if (!chunk_buf) {
4022 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
4023 ret = -1;
4024 goto out;
4025 }
4026
4027 while (remaining > 0) {
4028 memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE0x1000);
4029 ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode);
4030 if (!ret) {
4031 if (remaining >= SN730_LOG_CHUNK_SIZE0x1000) {
4032 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4033 chunk_buf, SN730_LOG_CHUNK_SIZE0x1000);
4034 } else {
4035 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4036 chunk_buf, remaining);
4037 }
4038 remaining -= SN730_LOG_CHUNK_SIZE0x1000;
4039 curr_offset += 1;
4040 } else {
4041 goto out;
4042 }
4043 }
4044out:
4045 free(chunk_buf);
4046 return ret;
4047}
4048
4049static int wdc_do_sn730_get_and_tar(struct libnvme_transport_handle *hdl, char *outputName)
4050{
4051 int ret = 0;
4052 void *retPtr;
4053 uint8_t *full_log_buf = NULL((void*)0);
4054 uint8_t *key_log_buf = NULL((void*)0);
4055 uint8_t *core_dump_log_buf = NULL((void*)0);
4056 uint8_t *extended_log_buf = NULL((void*)0);
4057 uint32_t full_log_len = 0;
4058 uint32_t key_log_len = 0;
4059 uint32_t core_dump_log_len = 0;
4060 uint32_t extended_log_len = 0;
4061 struct tarfile_metadata *tarInfo = NULL((void*)0);
4062
4063 tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata));
4064 if (!tarInfo) {
4065 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
4066 ret = -1;
4067 goto free_buf;
4068 }
4069 memset(tarInfo, 0, sizeof(struct tarfile_metadata));
4070
4071 /* Create Logs directory */
4072 wdc_UtilsGetTime(&tarInfo->timeInfo);
4073 memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString));
4074 wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
4075 tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth,
4076 tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second);
4077
4078 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN256, "%s",
4079 (char *)outputName);
4080
4081 retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN256);
4082 if (retPtr) {
4083 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
4084 (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR"/", (char *)tarInfo->bufferFolderName);
4085 } else {
4086 fprintf(stderrstderr, "ERROR: WDC: get current working directory failed\n");
4087 goto free_buf;
4088 }
4089
4090 ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath);
4091 if (ret) {
4092 fprintf(stderrstderr, "ERROR: WDC: create directory failed, ret = %d, dir = %s\n", ret, tarInfo->bufferFolderPath);
4093 goto free_buf;
4094 } else {
4095 fprintf(stderrstderr, "Stored log files in directory: %s\n", tarInfo->bufferFolderPath);
4096 }
4097
4098 ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH0x00080009);
4099 if (ret) {
4100 nvme_show_status(ret);
4101 goto free_buf;
4102 }
4103 ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH0x00090009);
4104 if (ret) {
4105 nvme_show_status(ret);
4106 goto free_buf;
4107 }
4108 ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH0x00120009);
4109 if (ret) {
4110 nvme_show_status(ret);
4111 goto free_buf;
4112 }
4113 ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH0x00420009);
4114 if (ret) {
4115 nvme_show_status(ret);
4116 goto free_buf;
4117 }
4118
4119 full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t));
4120 key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t));
4121 core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t));
4122 extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t));
4123
4124 if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) {
4125 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
4126 ret = -1;
4127 goto free_buf;
4128 }
4129
4130 /* Get the full log */
4131 ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE0x00010009);
4132 if (ret) {
4133 nvme_show_status(ret);
4134 goto free_buf;
4135 }
4136
4137 /* Get the key log */
4138 ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE0x00020009);
4139 if (ret) {
4140 nvme_show_status(ret);
4141 goto free_buf;
4142 }
4143
4144 /* Get the core dump log */
4145 ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE0x00030009);
4146 if (ret) {
4147 nvme_show_status(ret);
4148 goto free_buf;
4149 }
4150
4151 /* Get the extended log */
4152 ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009);
4153 if (ret) {
4154 nvme_show_status(ret);
4155 goto free_buf;
4156 }
4157
4158 /* Write log files */
4159 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4160 "full_log", (char *)tarInfo->timeString);
4161 wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len);
4162
4163 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4164 "key_log", (char *)tarInfo->timeString);
4165 wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len);
4166
4167 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4168 "core_dump_log", (char *)tarInfo->timeString);
4169 wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len);
4170
4171 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4172 "extended_log", (char *)tarInfo->timeString);
4173 wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len);
4174
4175 /* Tar the log directory */
4176 wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
4177 wdc_UtilsSnprintf(tarInfo->tarFiles, sizeof(tarInfo->tarFiles), "%s%s%s", (char *)tarInfo->bufferFolderName, WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
4178 wdc_UtilsSnprintf(tarInfo->tarCmd, sizeof(tarInfo->tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarInfo->tarFileName, (char *)tarInfo->tarFiles);
4179
4180 ret = system(tarInfo->tarCmd);
4181
4182 if (ret)
4183 fprintf(stderrstderr, "ERROR: WDC: Tar of log data failed, ret = %d\n", ret);
4184
4185free_buf:
4186 free(tarInfo);
4187 free(full_log_buf);
4188 free(core_dump_log_buf);
4189 free(key_log_buf);
4190 free(extended_log_buf);
4191 return ret;
4192}
4193
4194static int dump_internal_logs(struct libnvme_transport_handle *hdl, const char *dir_name, int verbose)
4195{
4196 char file_path[PATH_MAX4096];
4197 void *telemetry_log;
4198 const size_t bs = 512;
4199 struct nvme_telemetry_log *hdr;
4200 struct libnvme_passthru_cmd cmd;
4201 size_t full_size, offset = bs;
4202 int err, output;
4203
4204 if (verbose)
4205 printf("NVMe Telemetry log...\n");
4206
4207 hdr = malloc(bs);
4208 telemetry_log = malloc(bs);
4209 if (!hdr || !telemetry_log) {
4210 fprintf(stderrstderr, "Failed to allocate %zu bytes for log: %s\n", bs, libnvme_strerror(errno(*__errno_location ())));
4211 err = -ENOMEM12;
4212 goto free_mem;
4213 }
4214 memset(hdr, 0, bs);
4215
4216 sprintf(file_path, "%s/telemetry.bin", dir_name);
4217 output = nvme_open_rawdata(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file_path), (01 | 0100 | 01000), 0666);
4218 if (output < 0) {
4219 fprintf(stderrstderr, "Failed to open output file %s: %s!\n", file_path, libnvme_strerror(errno(*__errno_location ())));
4220 err = output;
4221 goto free_mem;
4222 }
4223
4224 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4225 NVME_CSI_NVM, hdr, bs);
4226 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))
4227 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4228 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
4229 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4230 if (err < 0)
4231 perror("get-telemetry-log");
4232 else if (err > 0) {
4233 nvme_show_status(err);
4234 fprintf(stderrstderr, "Failed to acquire telemetry header %d!\n", err);
4235 goto close_output;
4236 }
4237
4238 err = write(output, (void *)hdr, bs);
4239 if (err != bs) {
4240 fprintf(stderrstderr, "Failed to flush all data to file!\n");
4241 goto close_output;
4242 }
4243
4244 full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
4245
4246 while (offset != full_size) {
4247 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4248 NVME_CSI_NVM, telemetry_log, bs);
4249 nvme_init_get_log_lpo(&cmd, offset);
4250 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4251 if (err < 0) {
4252 perror("get-telemetry-log");
4253 break;
4254 } else if (err > 0) {
4255 fprintf(stderrstderr, "Failed to acquire full telemetry log!\n");
4256 nvme_show_status(err);
4257 break;
4258 }
4259
4260 err = write(output, (void *)telemetry_log, bs);
4261 if (err != bs) {
4262 fprintf(stderrstderr, "Failed to flush all data to file!\n");
4263 break;
4264 }
4265 err = 0;
4266 offset += bs;
4267 }
4268
4269close_output:
4270 close(output);
4271free_mem:
4272 free(hdr);
4273 free(telemetry_log);
4274
4275 return err;
4276}
4277
4278static int wdc_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
4279 int *data_area)
4280{
4281 struct nvme_id_ctrl ctrl;
4282 int err;
4283
4284 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
4285 err = nvme_identify_ctrl(hdl, &ctrl);
4286 if (err) {
4287 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err);
4288 return err;
4289 }
4290
4291 if (ctrl.lpa & 0x40)
4292 *data_area = 4;
4293 else
4294 *data_area = 3;
4295
4296 return 0;
4297}
4298
4299static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd,
4300 struct plugin *plugin)
4301{
4302 const char *desc = "Internal Firmware Log.";
4303 const char *file = "Output file pathname.";
4304 const char *size = "Data retrieval transfer size.";
4305 const char *data_area =
4306 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
4307 const char *type =
4308 "Telemetry type - NONE, HOST, or CONTROLLER:\n" \
4309 " NONE - Default, capture without using NVMe telemetry.\n" \
4310 " HOST - Host-initiated telemetry.\n" \
4311 " CONTROLLER - Controller-initiated telemetry.";
4312 const char *verbose = "Display more debug messages.";
4313 const char *file_size =
4314 "Output file size. Deprecated, see man page for supported devices.";
4315 const char *offset =
4316 "Output file data offset. Deprecated, see man page for supported devices.";
4317 char f[PATH_MAX4096] = {0};
4318 char fb[PATH_MAX4096/2] = {0};
4319 char fileSuffix[PATH_MAX4096] = {0};
4320 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4321 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4322 __u32 xfer_size = 0;
4323 int telemetry_type = 0, telemetry_data_area = 0;
4324 UtilsTimeInfo timeInfo;
4325 __u8 timeStamp[MAX_PATH_LEN256];
4326 __u64 capabilities = 0;
4327 __u32 device_id, read_vendor_id;
4328 char file_path[PATH_MAX4096/2] = {0};
4329 char cmd_buf[PATH_MAX4096] = {0};
4330 int ret = -1;
4331
4332 struct config {
4333 char *file;
4334 __u32 xfer_size;
4335 int data_area;
4336 __u64 file_size;
4337 __u64 offset;
4338 char *type;
4339 bool_Bool verbose;
4340 };
4341
4342 struct config cfg = {
4343 .file = NULL((void*)0),
4344 .xfer_size = 0x10000,
4345 .data_area = 0,
4346 .file_size = 0,
4347 .offset = 0,
4348 .type = NULL((void*)0),
4349 .verbose = false0,
4350 };
4351
4352 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4353 OPT_FILE("output-file", 'O', &cfg.file, file),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4354 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4355 OPT_UINT("data-area", 'd', &cfg.data_area, data_area),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4356 OPT_FILE("type", 't', &cfg.type, type),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4357 OPT_FLAG("verbose", 'V', &cfg.verbose, verbose),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4358 OPT_LONG("file-size", 'f', &cfg.file_size, file_size),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4359 OPT_LONG("offset", 'e', &cfg.offset, offset),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4360 OPT_END())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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
4361
4362 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4363 if (ret)
4364 return ret;
4365
4366 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4367 if (ret || !wdc_check_device(ctx, hdl))
4368 goto out;
4369
4370 if (cfg.xfer_size) {
4371 xfer_size = cfg.xfer_size;
4372 } else {
4373 fprintf(stderrstderr, "ERROR: WDC: Invalid length\n");
4374 goto out;
4375 }
4376
4377 ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id);
4378
4379 if (!wdc_is_sn861(device_id)) {
4380 if (cfg.file) {
4381 int verify_file;
4382
4383 /* verify file name and path is valid before getting dump data */
4384 verify_file = nvme_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
4385 if (verify_file < 0) {
4386 fprintf(stderrstderr, "ERROR: WDC: open: %s\n", libnvme_strerror(errno(*__errno_location ())));
4387 goto out;
4388 }
4389 close(verify_file);
4390 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4391 } else {
4392 wdc_UtilsGetTime(&timeInfo);
4393 memset(timeStamp, 0, sizeof(timeStamp));
4394 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4395 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4396 timeInfo.month, timeInfo.dayOfMonth,
4397 timeInfo.hour, timeInfo.minute,
4398 timeInfo.second);
4399 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4400
4401 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix);
4402 if (ret) {
4403 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
4404 goto out;
4405 }
4406 }
4407
4408 if (!cfg.file) {
4409 if (strlen(f) > PATH_MAX4096 - 5) {
4410 fprintf(stderrstderr, "ERROR: WDC: file name overflow\n");
4411 ret = -1;
4412 goto out;
4413 }
4414 strcat(f, ".bin");
4415 }
4416 fprintf(stderrstderr, "%s: filename = %s\n", __func__, f);
4417
4418 if (cfg.data_area) {
4419 if (cfg.data_area > 5 || cfg.data_area < 1) {
4420 fprintf(stderrstderr, "ERROR: WDC: Data area must be 1-5\n");
4421 ret = -1;
4422 goto out;
4423 }
4424 }
4425
4426 if (!cfg.type || !strcmp(cfg.type, "NONE") || !strcmp(cfg.type, "none")) {
4427 telemetry_type = WDC_TELEMETRY_TYPE_NONE0x0;
4428 data_area = 0;
4429 } else if (!strcmp(cfg.type, "HOST") || !strcmp(cfg.type, "host")) {
4430 telemetry_type = WDC_TELEMETRY_TYPE_HOST0x1;
4431 telemetry_data_area = cfg.data_area;
4432 } else if (!strcmp(cfg.type, "CONTROLLER") || !strcmp(cfg.type, "controller")) {
4433 telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER0x2;
4434 telemetry_data_area = cfg.data_area;
4435 } else {
4436 fprintf(stderrstderr,
4437 "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n");
4438 ret = -1;
4439 goto out;
4440 }
4441 } else {
4442 if (cfg.file) {
4443 strncpy(fb, cfg.file, PATH_MAX4096/2 - 8);
4444 } else {
4445 wdc_UtilsGetTime(&timeInfo);
4446 memset(timeStamp, 0, sizeof(timeStamp));
4447 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4448 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4449 timeInfo.month, timeInfo.dayOfMonth,
4450 timeInfo.hour, timeInfo.minute,
4451 timeInfo.second);
4452 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4453
4454 ret = wdc_get_serial_name(hdl, fb, PATH_MAX4096/2 - 7, fileSuffix);
4455 if (ret) {
4456 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
4457 goto out;
4458 }
4459
4460 if (strlen(fb) > PATH_MAX4096/2 - 7) {
4461 fprintf(stderrstderr, "ERROR: WDC: file name overflow\n");
4462 ret = -1;
4463 goto out;
4464 }
4465 }
4466 fprintf(stderrstderr, "%s: filename = %s.tar.gz\n", __func__, fb);
4467
4468
4469 memset(file_path, 0, sizeof(file_path));
4470 if (snprintf(file_path, PATH_MAX4096/2 - 8, "%s.tar.gz", fb) >= PATH_MAX4096/2 - 8) {
4471 fprintf(stderrstderr, "File path is too long!\n");
4472 ret = -1;
4473 goto out;
4474 }
4475 if (access(file_path, F_OK0) != -1) {
4476 fprintf(stderrstderr, "Output file already exists!\n");
4477 ret = -EEXIST17;
4478 goto out;
4479 }
4480 }
4481
4482 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4483 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
4484 if (!wdc_is_sn861(device_id)) {
4485 if (telemetry_type != WDC_TELEMETRY_TYPE_NONE0x0 &&
4486 wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4487 fprintf(stderrstderr, "%s: Error determining default telemetry data area\n",
4488 __func__);
4489 return -EINVAL22;
4490 }
4491
4492 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size,
4493 telemetry_type, telemetry_data_area);
4494 } else {
4495 if (nvme_args.verbose)
4496 printf("Creating temp directory...\n");
4497
4498 ret = mkdir(fb, 0666);
4499 if (ret) {
4500 fprintf(stderrstderr, "Failed to create directory!\n");
4501 goto out;
4502 }
4503
4504 ret = dump_internal_logs(hdl, fb, nvme_args.verbose);
4505 if (ret < 0)
4506 perror("vs-internal-log");
4507
4508 if (nvme_args.verbose)
4509 printf("Archiving...\n");
4510
4511 if (snprintf(cmd_buf, PATH_MAX4096,
4512 "tar --remove-files -czf %s %s",
4513 file_path, fb) >= PATH_MAX4096) {
4514 fprintf(stderrstderr, "Command buffer is too long!\n");
4515 ret = -1;
4516 goto out;
4517 }
4518
4519 ret = system(cmd_buf);
4520 if (ret)
4521 fprintf(stderrstderr, "Failed to create an archive file!\n");
4522 }
4523 goto out;
4524 }
4525 if ((capabilities & WDC_DRIVE_CAP_DUI0x0000000800000000) == WDC_DRIVE_CAP_DUI0x0000000800000000) {
4526 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4527 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4528 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4529 fprintf(stderrstderr, "%s: Error determining default telemetry data area\n",
4530 __func__);
4531 return -EINVAL22;
4532 }
4533 /* Get the desired telemetry log page */
4534 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4535 telemetry_type, telemetry_data_area);
4536 goto out;
4537 } else {
4538 if (!cfg.data_area)
4539 cfg.data_area = 1;
4540
4541 /* FW requirement - xfer size must be 256k for data area 4 */
4542 if (cfg.data_area >= 4)
4543 xfer_size = 0x40000;
4544 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4545 cfg.data_area,
4546 nvme_args.verbose, cfg.file_size,
4547 cfg.offset);
4548 goto out;
4549 }
4550 }
4551 if ((capabilities & WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) == WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) {
4552 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4553 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4554 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4555 fprintf(stderrstderr, "%s: Error determining default telemetry data area\n",
4556 __func__);
4557 return -EINVAL22;
4558 }
4559 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4560 telemetry_type, telemetry_data_area);
4561 goto out;
4562 } else {
4563 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4564 WDC_NVME_DUI_MAX_DATA_AREA0x05,
4565 nvme_args.verbose, 0, 0);
4566 goto out;
4567 }
4568 }
4569 if ((capabilities & WDC_SN730B_CAP_VUC_LOG0x0000000400000000) == WDC_SN730B_CAP_VUC_LOG0x0000000400000000) {
4570 ret = wdc_do_sn730_get_and_tar(hdl, f);
4571 } else {
4572 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4573 ret = -1;
4574 }
4575out:
4576 return ret;
4577}
4578
4579static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type)
4580{
4581 int ret;
4582 __u32 crash_dump_length;
4583 __u32 opcode;
4584 __u32 cdw12;
4585 __u32 cdw10_size;
4586 __u32 cdw12_size;
4587 __u32 cdw12_clear;
4588
4589 if (type == WDC_NVME_PFAIL_DUMP_TYPE2) {
4590 /* set parms to get the PFAIL Crash Dump */
4591 opcode = WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6;
4592 cdw10_size = WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02;
4593 cdw12_size = ((WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4594 WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20);
4595
4596 cdw12 = (WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4597 WDC_NVME_PF_CRASH_DUMP_CMD0x20;
4598
4599 cdw12_clear = ((WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4600 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4601
4602 } else {
4603 /* set parms to get the Crash Dump */
4604 opcode = WDC_NVME_CRASH_DUMP_OPCODE0xC6;
4605 cdw10_size = WDC_NVME_CRASH_DUMP_SIZE_NDT0x02;
4606 cdw12_size = ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 << WDC_NVME_SUBCMD_SHIFT8) |
4607 WDC_NVME_CRASH_DUMP_SIZE_CMD0x20);
4608
4609 cdw12 = (WDC_NVME_CRASH_DUMP_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
4610 WDC_NVME_CRASH_DUMP_CMD0x20;
4611
4612 cdw12_clear = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4613 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4614 }
4615
4616 ret = wdc_dump_length(hdl,
4617 opcode,
4618 cdw10_size,
4619 cdw12_size,
4620 &crash_dump_length);
4621
4622 if (ret == -1) {
4623 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4624 fprintf(stderrstderr, "INFO: WDC: Pfail dump get size failed\n");
4625 else
4626 fprintf(stderrstderr, "INFO: WDC: Crash dump get size failed\n");
4627
4628 return -1;
4629 }
4630
4631 if (!crash_dump_length) {
4632 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4633 fprintf(stderrstderr, "INFO: WDC: Pfail dump is empty\n");
4634 else
4635 fprintf(stderrstderr, "INFO: WDC: Crash dump is empty\n");
4636 } else {
4637 ret = wdc_do_dump(hdl,
4638 opcode,
4639 crash_dump_length,
4640 cdw12,
4641 file,
4642 crash_dump_length);
4643
4644 if (!ret)
4645 ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE0xFF,
4646 cdw12_clear);
4647 }
4648 return ret;
4649}
4650
4651static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type)
4652{
4653 char f[PATH_MAX4096] = {0};
4654 const char *dump_type;
4655 int ret;
4656
4657 if (file)
4658 strncpy(f, file, PATH_MAX4096 - 1);
4659
4660 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4661 dump_type = "_pfail_dump";
4662 else
4663 dump_type = "_crash_dump";
4664
4665 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, dump_type);
4666 if (ret)
4667 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
4668 else
4669 ret = wdc_do_crash_dump(hdl, f, type);
4670 return ret;
4671}
4672
4673static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file)
4674{
4675 int ret;
4676 __u8 *drive_log_data;
4677 __u32 drive_log_length;
4678 struct libnvme_passthru_cmd admin_cmd;
4679
4680 ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6,
4681 WDC_NVME_DRIVE_LOG_SIZE_NDT0x02,
4682 (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 <<
4683 WDC_NVME_SUBCMD_SHIFT8 | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20),
4684 &drive_log_length);
4685 if (ret == -1)
4686 return -1;
4687
4688 drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length);
4689 if (!drive_log_data) {
4690 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
4691 return -1;
4692 }
4693
4694 memset(drive_log_data, 0, sizeof(__u8) * drive_log_length);
4695 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4696 admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE0xC6;
4697 admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
4698 admin_cmd.data_len = drive_log_length;
4699 admin_cmd.cdw10 = drive_log_length;
4700 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD0x00 <<
4701 WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20);
4702
4703 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4704 nvme_show_status(ret);
4705 if (!ret)
4706 ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
4707 free(drive_log_data);
4708 return ret;
4709}
4710
4711static int wdc_drive_log(int argc, char **argv, struct command *acmd,
4712 struct plugin *plugin)
4713{
4714 const char *desc = "Capture Drive Log.";
4715 const char *file = "Output file pathname.";
4716 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4717 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4718 char f[PATH_MAX4096] = {0};
4719 int ret;
4720 __u64 capabilities = 0;
4721 struct config {
4722 char *file;
4723 };
4724
4725 struct config cfg = {
4726 .file = NULL((void*)0)
4727 };
4728
4729 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4730 OPT_FILE("output-file", 'O', &cfg.file, file))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
4731
4732 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4733 if (ret)
4734 return ret;
4735
4736 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4737 if (ret || !wdc_check_device(ctx, hdl))
4738 return ret;
4739
4740 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4741
4742 if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400)) {
4743 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4744 ret = -1;
4745 } else {
4746 if (cfg.file)
4747 strncpy(f, cfg.file, PATH_MAX4096 - 1);
4748 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "drive_log");
4749 if (ret)
4750 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
4751 else
4752 ret = wdc_do_drive_log(hdl, f);
4753 }
4754 return ret;
4755}
4756
4757static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
4758 struct plugin *plugin)
4759{
4760 const char *desc = "Get Crash Dump.";
4761 const char *file = "Output file pathname.";
4762 __u64 capabilities = 0;
4763 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4764 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4765 int ret;
4766
4767 struct config {
4768 char *file;
4769 };
4770
4771 struct config cfg = {
4772 .file = NULL((void*)0),
4773 };
4774
4775 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4776 OPT_FILE("output-file", 'O', &cfg.file, file))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
4777
4778 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4779 if (ret)
4780 return ret;
4781
4782 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4783 if (ret || !wdc_check_device(ctx, hdl))
4784 return ret;
4785
4786 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4787
4788 if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800)) {
4789 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4790 ret = -1;
4791 } else {
4792 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE1);
4793 if (ret)
4794 fprintf(stderrstderr, "ERROR: WDC: failed to read crash dump\n");
4795 }
4796 return ret;
4797}
4798
4799static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd,
4800 struct plugin *plugin)
4801{
4802 const char *desc = "Get Pfail Crash Dump.";
4803 const char *file = "Output file pathname.";
4804 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4805 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4806 __u64 capabilities = 0;
4807 struct config {
4808 char *file;
4809 };
4810 int ret;
4811
4812 struct config cfg = {
4813 .file = NULL((void*)0),
4814 };
4815
4816 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
4817 OPT_FILE("output-file", 'O', &cfg.file, file))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
4818
4819 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4820 if (ret)
4821 return ret;
4822
4823 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4824 if (ret || !wdc_check_device(ctx, hdl))
4825 return ret;
4826
4827 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4828 if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000)) {
4829 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4830 ret = -1;
4831 } else {
4832 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE2);
4833 if (ret)
4834 fprintf(stderrstderr, "ERROR: WDC: failed to read pfail crash dump\n");
4835 }
4836 return ret;
4837}
4838
4839static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root)
4840{
4841 char vsn[24] = {0};
4842 int base = 3072;
4843 int vsn_start = 3081;
4844
4845 memcpy(vsn, &vs[vsn_start - base], sizeof(vsn));
4846 if (root)
4847 json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL");
4848 else
4849 printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL");
4850}
4851
4852static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
4853{
4854 return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl);
4855}
4856
4857static const char *wdc_purge_mon_status_to_string(__u32 status)
4858{
4859 const char *str;
4860
4861 switch (status) {
4862 case WDC_NVME_PURGE_STATE_IDLE0x00:
4863 str = "Purge State Idle.";
4864 break;
4865 case WDC_NVME_PURGE_STATE_DONE0x01:
4866 str = "Purge State Done.";
4867 break;
4868 case WDC_NVME_PURGE_STATE_BUSY0x02:
4869 str = "Purge State Busy.";
4870 break;
4871 case WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03:
4872 str = "Purge Operation resulted in an error that requires power cycle.";
4873 break;
4874 case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04:
4875 str = "The previous purge operation was interrupted by a power cycle\n"
4876 "or reset interruption. Other commands may be rejected until\n"
4877 "Purge Execute is issued and completed.";
4878 break;
4879 default:
4880 str = "Unknown.";
4881 }
4882 return str;
4883}
4884
4885static int wdc_purge(int argc, char **argv,
4886 struct command *command, struct plugin *plugin)
4887{
4888 const char *desc = "Send a Purge command.";
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 struct libnvme_passthru_cmd admin_cmd;
4892 __u64 capabilities = 0;
4893 char *err_str;
4894 int ret;
4895
4896 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
4897
4898 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4899 if (ret)
4900 return ret;
4901
4902 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4903 if (ret || !wdc_check_device(ctx, hdl))
4904 return ret;
4905
4906 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4907 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4908 ret = -1;
4909 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4910 } else {
4911 err_str = "";
4912 memset(&admin_cmd, 0, sizeof(admin_cmd));
4913 admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE0xDD;
4914
4915 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4916 if (ret > 0) {
4917 switch (ret) {
4918 case WDC_NVME_PURGE_CMD_SEQ_ERR0x0C:
4919 err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n";
4920 break;
4921 case WDC_NVME_PURGE_INT_DEV_ERR0x06:
4922 err_str = "ERROR: WDC: Internal Device Error.\n";
4923 break;
4924 default:
4925 err_str = "ERROR: WDC\n";
4926 }
4927 }
4928
4929 fprintf(stderrstderr, "%s", err_str);
4930 nvme_show_status(ret);
4931 }
4932 return ret;
4933}
4934
4935static int wdc_purge_monitor(int argc, char **argv,
4936 struct command *command, struct plugin *plugin)
4937{
4938 const char *desc = "Send a Purge Monitor command.";
4939 __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F];
4940 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4941 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4942 double progress_percent;
4943 struct libnvme_passthru_cmd admin_cmd;
4944 struct wdc_nvme_purge_monitor_data *mon;
4945 __u64 capabilities;
4946 int ret;
4947
4948 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
4949
4950 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4951 if (ret)
4952 return ret;
4953
4954 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4955 if (ret || !wdc_check_device(ctx, hdl))
4956 return ret;
4957
4958 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4959 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
4960 ret = -1;
4961 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
4962 } else {
4963 memset(output, 0, sizeof(output));
4964 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4965 admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE0xDE;
4966 admin_cmd.addr = (__u64)(uintptr_t)output;
4967 admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F;
4968 admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C;
4969 admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530;
4970
4971 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4972 if (!ret) {
4973 mon = (struct wdc_nvme_purge_monitor_data *) output;
4974 printf("Purge state = 0x%0"PRIx64"l" "x""\n",
4975 (uint64_t)admin_cmd.result);
4976 printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result));
4977 if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY0x02) {
4978 progress_percent =
4979 ((double)le32_to_cpu(mon->entire_progress_current) * 100) /
4980 le32_to_cpu(mon->entire_progress_total);
4981 printf("Purge Progress = %f%%\n", progress_percent);
4982 }
4983 }
4984
4985 nvme_show_status(ret);
4986 }
4987 return ret;
4988}
4989
4990static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf)
4991{
4992 printf(" C1 Log Page Performance Statistics :-\n");
4993 printf(" Host Read Commands %20"PRIu64"l" "u""\n",
4994 le64_to_cpu(perf->hr_cmds));
4995 printf(" Host Read Blocks %20"PRIu64"l" "u""\n",
4996 le64_to_cpu(perf->hr_blks));
4997 printf(" Average Read Size %20lf\n",
4998 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))));
4999 printf(" Host Read Cache Hit Commands %20"PRIu64"l" "u""\n",
5000 le64_to_cpu(perf->hr_ch_cmds));
5001 printf(" Host Read Cache Hit_Percentage %20"PRIu64"l" "u""%%\n",
5002 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)));
5003 printf(" Host Read Cache Hit Blocks %20"PRIu64"l" "u""\n",
5004 le64_to_cpu(perf->hr_ch_blks));
5005 printf(" Average Read Cache Hit Size %20f\n",
5006 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))));
5007 printf(" Host Read Commands Stalled %20"PRIu64"l" "u""\n",
5008 le64_to_cpu(perf->hr_st_cmds));
5009 printf(" Host Read Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5010 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)));
5011 printf(" Host Write Commands %20"PRIu64"l" "u""\n",
5012 le64_to_cpu(perf->hw_cmds));
5013 printf(" Host Write Blocks %20"PRIu64"l" "u""\n",
5014 le64_to_cpu(perf->hw_blks));
5015 printf(" Average Write Size %20f\n",
5016 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))));
5017 printf(" Host Write Odd Start Commands %20"PRIu64"l" "u""\n",
5018 le64_to_cpu(perf->hw_os_cmds));
5019 printf(" Host Write Odd Start Commands Percentage %20"PRIu64"l" "u""%%\n",
5020 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))));
5021 printf(" Host Write Odd End Commands %20"PRIu64"l" "u""\n",
5022 le64_to_cpu(perf->hw_oe_cmds));
5023 printf(" Host Write Odd End Commands Percentage %20"PRIu64"l" "u""%%\n",
5024 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))));
5025 printf(" Host Write Commands Stalled %20"PRIu64"l" "u""\n",
5026 le64_to_cpu(perf->hw_st_cmds));
5027 printf(" Host Write Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5028 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))));
5029 printf(" NAND Read Commands %20"PRIu64"l" "u""\n",
5030 le64_to_cpu(perf->nr_cmds));
5031 printf(" NAND Read Blocks Commands %20"PRIu64"l" "u""\n",
5032 le64_to_cpu(perf->nr_blks));
5033 printf(" Average NAND Read Size %20f\n",
5034 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))));
5035 printf(" Nand Write Commands %20"PRIu64"l" "u""\n",
5036 le64_to_cpu(perf->nw_cmds));
5037 printf(" NAND Write Blocks %20"PRIu64"l" "u""\n",
5038 le64_to_cpu(perf->nw_blks));
5039 printf(" Average NAND Write Size %20f\n",
5040 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))));
5041 printf(" NAND Read Before Write %20"PRIu64"l" "u""\n",
5042 le64_to_cpu(perf->nrbw));
5043}
5044
5045static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf)
5046{
5047 struct json_object *root = json_create_object()json_object_new_object();
5048
5049 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)))
;
5050 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)))
;
5051 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)))))
5052 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)))))
;
5053 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)))
5054 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)))
;
5055 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))))
5056 (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))))
;
5057 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)))
5058 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)))
;
5059 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)))))
5060 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)))))
;
5061 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)))
5062 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)))
;
5063 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))))
5064 (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))))
;
5065 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)))
5066 le64_to_cpu(perf->hw_cmds))json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
;
5067 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)))
5068 le64_to_cpu(perf->hw_blks))json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
;
5069 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)))))
5070 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)))))
;
5071 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)))
5072 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)))
;
5073 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)))))
5074 (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)))))
;
5075 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)))
5076 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)))
;
5077 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))))))
5078 (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))))))
;
5079 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)))
5080 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)))
;
5081 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)))))
5082 (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)))))
;
5083 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)))
5084 le64_to_cpu(perf->nr_cmds))json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
;
5085 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)))
5086 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)))
;
5087 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))))))
5088 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))))))
;
5089 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)))
5090 le64_to_cpu(perf->nw_cmds))json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
;
5091 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)))
5092 le64_to_cpu(perf->nw_blks))json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
;
5093 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)))))
5094 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)))))
;
5095 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)))
5096 le64_to_cpu(perf->nrbw))json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
;
5097 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5098 printf("\n");
5099 json_free_object(root)json_object_put(root);
5100}
5101
5102static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt)
5103{
5104 if (!perf) {
5105 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read perf stats\n");
5106 return -1;
5107 }
5108 switch (fmt) {
5109 case NORMAL:
5110 wdc_print_log_normal(perf);
5111 break;
5112 case JSON:
5113 wdc_print_log_json(perf);
5114 break;
5115 }
5116 return 0;
5117}
5118
5119static int wdc_print_latency_monitor_log_normal(struct libnvme_transport_handle *hdl,
5120 struct wdc_ssd_latency_monitor_log *log_data)
5121{
5122 printf("Latency Monitor/C3 Log Page Data\n");
5123 printf(" Controller : %s\n", libnvme_transport_handle_get_name(hdl));
5124 int err = -1, i, j;
5125 struct nvme_id_ctrl ctrl;
5126 char ts_buf[128];
5127
5128 err = nvme_identify_ctrl(hdl, &ctrl);
5129 if (!err) {
5130 printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn);
5131 } else {
5132 fprintf(stderrstderr, "ERROR: WDC: latency monitor read id ctrl failure, err = %d\n", err);
5133 return err;
5134 }
5135
5136 printf(" Feature Status 0x%x\n", log_data->feature_status);
5137 printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer));
5138 printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold));
5139 printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1)));
5140 printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1)));
5141 printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1)));
5142 printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1)));
5143 printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config));
5144 printf(" Active Latency Minimum Window %d ms\n", 100*log_data->active_latency_min_window);
5145 printf(" Active Latency Stamp Units %d\n", le16_to_cpu(log_data->active_latency_stamp_units));
5146 printf(" Static Latency Stamp Units %d\n", le16_to_cpu(log_data->static_latency_stamp_units));
5147 if (le16_to_cpu(log_data->log_page_version) >= 4)
5148 printf(" Debug Telemetry Log Size %"PRIu64"l" "u""\n",
5149 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size));
5150 printf(" Debug Log Trigger Enable %d\n",
5151 le16_to_cpu(log_data->debug_log_trigger_enable));
5152 printf(" Log Page Version %d\n",
5153 le16_to_cpu(log_data->log_page_version));
5154 printf(" Log page GUID 0x");
5155 for (j = 0; j < WDC_C3_GUID_LENGTH16; j++)
5156 printf("%x", log_data->log_page_guid[j]);
5157 printf("\n");
5158
5159 printf(" Read Write Deallocate/Trim\n");
5160 for (i = 0; i <= 3; i++)
5161 printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
5162 i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5163 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5164 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5165
5166 for (i = 3; i >= 0; i--)
5167 printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5168 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5169 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5170 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5171
5172 for (i = 3; i >= 0; i--) {
5173 printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
5174 for (j = 2; j >= 0; j--) {
5175 if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) {
5176 printf(" N/A ");
5177 } else {
5178 convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
5179 printf("%s ", ts_buf);
5180 }
5181 }
5182 printf("\n");
5183 }
5184
5185 for (i = 0; i <= 3; i++)
5186 printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
5187 i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5188 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5189 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5190
5191 for (i = 3; i >= 0; i--)
5192 printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5193 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5194 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5195 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5196
5197 for (i = 3; i >= 0; i--) {
5198 printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
5199 for (j = 2; j >= 0; j--) {
5200 if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) {
5201 printf(" N/A ");
5202 } else {
5203 convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
5204 printf("%s ", ts_buf);
5205 }
5206 }
5207 printf("\n");
5208 }
5209
5210 return 0;
5211}
5212
5213static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data)
5214{
5215 int i, j;
5216 char buf[128];
5217 const char *operation[3] = {"Read", "Write", "Trim"};
5218 struct json_object *root = json_create_object()json_object_new_object();
5219
5220 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))
;
5221 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)))
;
5222 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
)))
;
5223 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)))
;
5224 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)))
;
5225 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)))
;
5226 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)))
;
5227 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)))
;
5228 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
))
;
5229 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)))
;
5230 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)))
;
5231 if (le16_to_cpu(log_data->log_page_version) >= 4) {
5232 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
)))
5233 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
)))
;
5234 }
5235 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)))
5236 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)))
;
5237 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)))
5238 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)))
;
5239
5240 char guid[40];
5241
5242 memset((void *)guid, 0, 40);
5243 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5244 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5245 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5246 json_object_add_value_string(root, "Log page GUID", guid);
5247
5248 for (i = 0; i <= 3; i++) {
5249 for (j = 2; j >= 0; j--) {
5250 sprintf(buf, "Active Bucket Counter: Bucket %d %s", i, operation[2-j]);
5251 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])))
;
5252 }
5253 }
5254 for (i = 3; i >= 0; i--) {
5255 for (j = 2; j >= 0; j--) {
5256 sprintf(buf, "Active Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5257 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])))
;
5258 }
5259 }
5260 for (i = 3; i >= 0; i--) {
5261 for (j = 2; j >= 0; j--) {
5262 sprintf(buf, "Active Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5263 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])))
;
5264 }
5265 }
5266 for (i = 0; i <= 3; i++) {
5267 for (j = 2; j >= 0; j--) {
5268 sprintf(buf, "Static Bucket Counter: Bucket %d %s", i, operation[2-j]);
5269 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])))
;
5270 }
5271 }
5272 for (i = 3; i >= 0; i--) {
5273 for (j = 2; j >= 0; j--) {
5274 sprintf(buf, "Static Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
5275 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])))
;
5276 }
5277 }
5278 for (i = 3; i >= 0; i--) {
5279 for (j = 2; j >= 0; j--) {
5280 sprintf(buf, "Static Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
5281 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])))
;
5282 }
5283 }
5284
5285 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5286 printf("\n");
5287
5288 json_free_object(root)json_object_put(root);
5289}
5290
5291static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data)
5292{
5293 int j;
5294
5295 printf("Error Recovery/C1 Log Page Data\n");
5296
5297 printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time));
5298 printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
5299 printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1);
5300 printf(" Panic ID : 0x%" PRIu64"l" "u" "\n", le64_to_cpu(log_data->panic_id));
5301 printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities));
5302 printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc);
5303 printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12));
5304 printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13));
5305 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5306 printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to);
5307 printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2);
5308 printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to);
5309 }
5310 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5311 printf(" Panic Count : 0x%x\n", log_data->panic_count);
5312 for (j = 0; j < 4; j++)
5313 printf(" Previous Panic ID N-%d : 0x%"PRIx64"l" "x""\n",
5314 j+1, le64_to_cpu(log_data->prev_panic_ids[j]));
5315 }
5316 printf(" Log Page Version : 0x%x\n",
5317 le16_to_cpu(log_data->log_page_version));
5318 printf(" Log page GUID : 0x");
5319 for (j = 0; j < WDC_OCP_C1_GUID_LENGTH16; j++)
5320 printf("%x", log_data->log_page_guid[j]);
5321 printf("\n");
5322}
5323
5324static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
5325{
5326 int j;
5327 char buf[128];
5328 struct json_object *root = json_create_object()json_object_new_object();
5329
5330 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)))
;
5331 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))
;
5332 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))
;
5333 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)))
;
5334 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)))
;
5335 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))
;
5336 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)))
;
5337 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)))
;
5338 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5339 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))
;
5340 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))
;
5341 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))
;
5342 }
5343 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5344 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))
;
5345 for (j = 0; j < 4; j++) {
5346 sprintf(buf, "Previous Panic ID N-%d", j+1);
5347 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])))
5348 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])))
;
5349 }
5350 }
5351 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)))
5352 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)))
;
5353
5354 char guid[40];
5355
5356 memset((void *)guid, 0, 40);
5357 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5358 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5359 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5360 json_object_add_value_string(root, "Log page GUID", guid);
5361
5362 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5363 printf("\n");
5364
5365 json_free_object(root)json_object_put(root);
5366}
5367
5368static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data)
5369{
5370 int j;
5371
5372 printf("Device Capabilities/C4 Log Page Data\n");
5373
5374 printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports));
5375 printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support));
5376 printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support));
5377 printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support));
5378 printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support));
5379 printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support));
5380 printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support));
5381 printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps));
5382
5383 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++)
5384 printf(" DSSD Power State %d Descriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]);
5385
5386 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5387 printf(" Log page GUID : 0x");
5388 for (j = 0; j < WDC_OCP_C4_GUID_LENGTH16; j++)
5389 printf("%x", log_data->log_page_guid[j]);
5390 printf("\n");
5391}
5392
5393static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
5394{
5395 int j;
5396 struct json_object *root = json_create_object()json_object_new_object();
5397
5398 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)))
;
5399 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
)))
;
5400 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)))
;
5401 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)))
;
5402 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)))
;
5403 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)))
;
5404 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)))
;
5405 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)))
;
5406
5407 char dssd_descr_str[40];
5408
5409 memset((void *)dssd_descr_str, 0, 40);
5410 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++) {
5411 sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j);
5412 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]))
;
5413 }
5414
5415 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)))
;
5416 char guid[40];
5417
5418 memset((void *)guid, 0, 40);
5419 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5420 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5421 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5422 json_object_add_value_string(root, "Log page GUID", guid);
5423
5424 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5425 printf("\n");
5426
5427 json_free_object(root)json_object_put(root);
5428}
5429
5430static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data)
5431{
5432 int j;
5433
5434 printf("Unsupported Requirements/C5 Log Page Data\n");
5435
5436 printf(" Number Unsupported Req IDs : 0x%x\n",
5437 le16_to_cpu(log_data->unsupported_count));
5438
5439 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++)
5440 printf(" Unsupported Requirement List %d : %s\n", j,
5441 log_data->unsupported_req_list[j]);
5442
5443 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5444 printf(" Log page GUID : 0x");
5445 for (j = 0; j < WDC_OCP_C5_GUID_LENGTH16; j++)
5446 printf("%x", log_data->log_page_guid[j]);
5447 printf("\n");
5448}
5449
5450static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
5451{
5452 int j;
5453 struct json_object *root = json_create_object()json_object_new_object();
5454
5455 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)))
;
5456
5457 char unsup_req_list_str[41];
5458
5459 memset((void *)unsup_req_list_str, 0, 41);
5460 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
5461 sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j);
5462 json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]);
5463 }
5464
5465 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)))
5466 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)))
;
5467 char guid[40];
5468
5469 memset((void *)guid, 0, 40);
5470 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5471 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
5472 (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
5473 json_object_add_value_string(root, "Log page GUID", guid);
5474
5475 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5476 printf("\n");
5477
5478 json_free_object(root)json_object_put(root);
5479}
5480
5481static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
5482{
5483 uint64_t converted = 0;
5484
5485 printf(" CA Log Page Performance Statistics :-\n");
5486 printf(" NAND Bytes Written %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5487 le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo));
5488 printf(" NAND Bytes Read %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5489 le64_to_cpu(perf->nand_bytes_rd_hi), le64_to_cpu(perf->nand_bytes_rd_lo));
5490
5491 converted = le64_to_cpu(perf->nand_bad_block);
5492 printf(" NAND Bad Block Count (Normalized) %20"PRIu64"l" "u""\n",
5493 converted & 0xFFFF);
5494 printf(" NAND Bad Block Count (Raw) %20"PRIu64"l" "u""\n",
5495 converted >> 16);
5496
5497 printf(" Uncorrectable Read Count %20"PRIu64"l" "u""\n",
5498 le64_to_cpu(perf->uncorr_read_count));
5499 printf(" Soft ECC Error Count %20"PRIu64"l" "u""\n",
5500 le64_to_cpu(perf->ecc_error_count));
5501 printf(" SSD End to End Detected Correction Count %20"PRIu32"u""\n",
5502 (uint32_t)le32_to_cpu(perf->ssd_detect_count));
5503 printf(" SSD End to End Corrected Correction Count %20"PRIu32"u""\n",
5504 (uint32_t)le32_to_cpu(perf->ssd_correct_count));
5505 printf(" System Data Percent Used %20"PRIu32"u""%%\n",
5506 perf->data_percent_used);
5507 printf(" User Data Erase Counts Max %20"PRIu32"u""\n",
5508 (uint32_t)le32_to_cpu(perf->data_erase_max));
5509 printf(" User Data Erase Counts Min %20"PRIu32"u""\n",
5510 (uint32_t)le32_to_cpu(perf->data_erase_min));
5511 printf(" Refresh Count %20"PRIu64"l" "u""\n",
5512 le64_to_cpu(perf->refresh_count));
5513
5514 converted = le64_to_cpu(perf->program_fail);
5515 printf(" Program Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5516 converted & 0xFFFF);
5517 printf(" Program Fail Count (Raw) %20"PRIu64"l" "u""\n",
5518 converted >> 16);
5519
5520 converted = le64_to_cpu(perf->user_erase_fail);
5521 printf(" User Data Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5522 converted & 0xFFFF);
5523 printf(" User Data Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5524 converted >> 16);
5525
5526 converted = le64_to_cpu(perf->system_erase_fail);
5527 printf(" System Area Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5528 converted & 0xFFFF);
5529 printf(" System Area Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5530 converted >> 16);
5531
5532 printf(" Thermal Throttling Status %20"PRIu8"u""\n",
5533 perf->thermal_throttle_status);
5534 printf(" Thermal Throttling Count %20"PRIu8"u""\n",
5535 perf->thermal_throttle_count);
5536 printf(" PCIe Correctable Error Count %20"PRIu64"l" "u""\n",
5537 le64_to_cpu(perf->pcie_corr_error));
5538 printf(" Incomplete Shutdown Count %20"PRIu32"u""\n",
5539 (uint32_t)le32_to_cpu(perf->incomplete_shutdown_count));
5540 printf(" Percent Free Blocks %20"PRIu32"u""%%\n",
5541 perf->percent_free_blocks);
5542}
5543
5544static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf)
5545{
5546 struct json_object *root = json_create_object()json_object_new_object();
5547 uint64_t converted = 0;
5548
5549 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)))
;
5550 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)))
;
5551 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)))
;
5552 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)))
;
5553
5554 converted = le64_to_cpu(perf->nand_bad_block);
5555 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))
5556 converted & 0xFFFF)json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5557 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))
5558 converted >> 16)json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
;
5559
5560 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)))
;
5561 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)))
;
5562 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))
)
5563 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))
)
;
5564 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)
))
5565 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)
))
;
5566 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))
5567 perf->data_percent_used)json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
;
5568 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)))
5569 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)))
;
5570 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)))
5571 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)))
;
5572 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)))
;
5573
5574 converted = le64_to_cpu(perf->program_fail);
5575 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))
5576 converted & 0xFFFF)json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5577 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))
5578 converted >> 16)json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
;
5579
5580 converted = le64_to_cpu(perf->user_erase_fail);
5581 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))
5582 converted & 0xFFFF)json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5583 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))
5584 converted >> 16)json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5585
5586 converted = le64_to_cpu(perf->system_erase_fail);
5587 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))
5588 converted & 0xFFFF)json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5589 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))
5590 converted >> 16)json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5591
5592 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))
5593 perf->thermal_throttle_status)json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
;
5594 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))
5595 perf->thermal_throttle_count)json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
;
5596 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)))
;
5597 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)))
;
5598 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))
;
5599 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5600 printf("\n");
5601 json_free_object(root)json_object_put(root);
5602}
5603
5604static void wdc_print_bd_ca_log_normal(struct libnvme_transport_handle *hdl, void *data)
5605{
5606 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5607 __u64 *raw;
5608 __u64 rawSwapped;
5609 __u16 *word_raw1 = NULL((void*)0),
5610 *word_raw2 = NULL((void*)0),
5611 *word_raw3 = NULL((void*)0);
5612 __u32 *dword_raw = NULL((void*)0);
5613 __u8 *byte_raw = NULL((void*)0);
5614 bool_Bool valid_id = true1;
5615
5616 while (valid_id) {
5617 raw = (__u64 *)&bd_data->raw_value[0];
5618 rawSwapped = (le64_to_cpu(*raw)>>8);
5619
5620 switch (bd_data->field_id) {
5621 case 0x0:
5622 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
5623 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
5624 printf("key normalized raw\n");
5625 printf("program_fail_count : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5626 bd_data->normalized_value, (uint64_t)rawSwapped);
5627 break;
5628 case 0x1:
5629 printf("erase_fail_count : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5630 bd_data->normalized_value, (uint64_t)rawSwapped);
5631 break;
5632 case 0x2:
5633 word_raw1 = (__u16 *)&bd_data->raw_value[1];
5634 word_raw2 = (__u16 *)&bd_data->raw_value[3];
5635 word_raw3 = (__u16 *)&bd_data->raw_value[5];
5636 printf("wear_leveling : %3"PRIu8"u",
5637 bd_data->normalized_value);
5638 printf("%% min: %"PRIu16"u"", max: %"PRIu16"u"", avg: %"PRIu16"u""\n",
5639 le16_to_cpu(*word_raw1),
5640 le16_to_cpu(*word_raw2),
5641 le16_to_cpu(*word_raw3));
5642 break;
5643 case 0x3:
5644 printf("end_to_end_error_detection_count: %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5645 bd_data->normalized_value, (uint64_t)rawSwapped);
5646 break;
5647 case 0x4:
5648 printf("crc_error_count : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5649 bd_data->normalized_value, (uint64_t)rawSwapped);
5650 break;
5651 case 0x5:
5652 printf("timed_workload_media_wear : %3"PRIu8"u""%% %-.3f%%\n",
5653 bd_data->normalized_value,
5654 safe_div_fp((rawSwapped), 1024.0));
5655 break;
5656 case 0x6:
5657 printf("timed_workload_host_reads : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5658 bd_data->normalized_value, (uint64_t)rawSwapped);
5659 break;
5660 case 0x7:
5661 printf("timed_workload_timer : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5662 bd_data->normalized_value, (uint64_t)rawSwapped);
5663 break;
5664 case 0x8:
5665 byte_raw = (__u8 *)&bd_data->raw_value[1];
5666 dword_raw = (__u32 *)&bd_data->raw_value[2];
5667 printf("thermal_throttle_status : %3"PRIu8"u""%% %"PRIu16"u",
5668 bd_data->normalized_value, *byte_raw);
5669 printf("%%, cnt: %"PRIu16"u""\n", le32_to_cpu(*dword_raw));
5670 break;
5671 case 0x9:
5672 printf("retry_buffer_overflow_count : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5673 bd_data->normalized_value, (uint64_t)rawSwapped);
5674 break;
5675 case 0xA:
5676 printf("pll_lock_loss_count : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5677 bd_data->normalized_value, (uint64_t)rawSwapped);
5678 break;
5679 case 0xB:
5680 printf("nand_bytes_written : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5681 bd_data->normalized_value, (uint64_t)rawSwapped);
5682 break;
5683 case 0xC:
5684 printf("host_bytes_written : %3"PRIu8"u""%% %"PRIu64"l" "u""\n",
5685 bd_data->normalized_value, (uint64_t)rawSwapped);
5686 /* last entry, break from while loop */
5687 valid_id = false0;
5688 break;
5689 default:
5690 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5691 break;
5692 }
5693
5694 bd_data++;
5695 }
5696
5697 return;
5698}
5699
5700static void wdc_print_bd_ca_log_json(void *data)
5701{
5702 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5703 __u64 *raw, rawSwapped;
5704 __u16 *word_raw;
5705 __u32 *dword_raw;
5706 __u8 *byte_raw;
5707 bool_Bool valid_id = true1;
5708 struct json_object *root = json_create_object()json_object_new_object();
5709
5710 while (valid_id) {
5711 raw = (__u64 *)&bd_data->raw_value[0];
5712 rawSwapped = (le64_to_cpu(*raw)>>8);
5713
5714 switch (bd_data->field_id) {
5715 case 0x0:
5716 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))
5717 bd_data->normalized_value)json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
;
5718 json_object_add_value_uint64(root, "program_fail_count raw",json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
5719 rawSwapped)json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5720 break;
5721 case 0x1:
5722 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))
5723 bd_data->normalized_value)json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5724 json_object_add_value_uint64(root, "erase_fail_count raw",json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
5725 rawSwapped)json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5726 break;
5727 case 0x2:
5728 word_raw = (__u16 *)&bd_data->raw_value[1];
5729 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))
5730 bd_data->normalized_value)json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
;
5731 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)))
5732 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling min", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5733 word_raw = (__u16 *)&bd_data->raw_value[3];
5734 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)))
5735 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling max", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5736 word_raw = (__u16 *)&bd_data->raw_value[5];
5737 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)))
5738 le16_to_cpu(*word_raw))json_object_object_add(root, "wear_leveling avg", json_object_new_int
(le16_to_cpu(*word_raw)))
;
5739 break;
5740 case 0x3:
5741 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))
5742 "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))
5743 bd_data->normalized_value)json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5744 json_object_add_value_uint64(root,json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5745 "end_to_end_error_detection_count raw",json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5746 rawSwapped)json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
;
5747 break;
5748 case 0x4:
5749 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))
5750 bd_data->normalized_value)json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5751 json_object_add_value_uint64(root, "crc_error_count raw",json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
5752 rawSwapped)json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
;
5753 break;
5754 case 0x5:
5755 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))
5756 bd_data->normalized_value)json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
;
5757 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)))
5758 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)))
;
5759 break;
5760 case 0x6:
5761 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))
5762 bd_data->normalized_value)json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
;
5763 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))
5764 rawSwapped)json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
;
5765 break;
5766 case 0x7:
5767 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))
5768 bd_data->normalized_value)json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
;
5769 json_object_add_value_uint64(root, "timed_workload_timer",json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
5770 rawSwapped)json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
;
5771 break;
5772 case 0x8:
5773 byte_raw = (__u8 *)&bd_data->raw_value[1];
5774 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))
5775 bd_data->normalized_value)json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
;
5776 json_object_add_value_int(root, "thermal_throttle_status",json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
5777 *byte_raw)json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(*byte_raw))
;
5778 dword_raw = (__u32 *)&bd_data->raw_value[2];
5779 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)))
5780 le32_to_cpu(*dword_raw))json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(le32_to_cpu(*dword_raw)))
;
5781 break;
5782 case 0x9:
5783 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))
5784 bd_data->normalized_value)json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5785 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))
5786 rawSwapped)json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
;
5787 break;
5788 case 0xA:
5789 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))
5790 bd_data->normalized_value)json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5791 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))
5792 rawSwapped)json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
;
5793 break;
5794 case 0xB:
5795 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))
5796 bd_data->normalized_value)json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5797 json_object_add_value_uint64(root, "nand_bytes_written raw",json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
5798 rawSwapped)json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5799 break;
5800 case 0xC:
5801 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))
5802 bd_data->normalized_value)json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5803 json_object_add_value_uint64(root, "host_bytes_written raw",json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
5804 rawSwapped)json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5805
5806 /* last entry, break from while loop */
5807 valid_id = false0;
5808 break;
5809 default:
5810 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5811 break;
5812 }
5813
5814 bd_data++;
5815 }
5816
5817 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5818 printf("\n");
5819 json_free_object(root)json_object_put(root);
5820
5821 return;
5822}
5823
5824static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf)
5825{
5826 printf(" D0 Smart Log Page Statistics :-\n");
5827 printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"u""\n",
5828 (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count));
5829 printf(" Lifetime Power on Hours %20"PRIu32"u""\n",
5830 (uint32_t)le32_to_cpu(perf->lifetime_power_on_hours));
5831 printf(" Lifetime UECC Count %20"PRIu32"u""\n",
5832 (uint32_t)le32_to_cpu(perf->lifetime_uecc_count));
5833 printf(" Lifetime Write Amplification Factor %20"PRIu32"u""\n",
5834 (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor));
5835 printf(" Trailing Hour Write Amplification Factor %20"PRIu32"u""\n",
5836 (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor));
5837 printf(" Reserve Erase Block Count %20"PRIu32"u""\n",
5838 (uint32_t)le32_to_cpu(perf->reserve_erase_block_count));
5839 printf(" Lifetime Program Fail Count %20"PRIu32"u""\n",
5840 (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count));
5841 printf(" Lifetime Block Erase Fail Count %20"PRIu32"u""\n",
5842 (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count));
5843 printf(" Lifetime Die Failure Count %20"PRIu32"u""\n",
5844 (uint32_t)le32_to_cpu(perf->lifetime_die_failure_count));
5845 printf(" Lifetime Link Rate Downgrade Count %20"PRIu32"u""\n",
5846 (uint32_t)le32_to_cpu(perf->lifetime_link_rate_downgrade_count));
5847 printf(" Lifetime Clean Shutdown Count on Power Loss %20"PRIu32"u""\n",
5848 (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count));
5849 printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"u""\n",
5850 (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count));
5851 printf(" Current Temperature %20"PRIu32"u""\n",
5852 (uint32_t)le32_to_cpu(perf->current_temp));
5853 printf(" Max Recorded Temperature %20"PRIu32"u""\n",
5854 (uint32_t)le32_to_cpu(perf->max_recorded_temp));
5855 printf(" Lifetime Retired Block Count %20"PRIu32"u""\n",
5856 (uint32_t)le32_to_cpu(perf->lifetime_retired_block_count));
5857 printf(" Lifetime Read Disturb Reallocation Events %20"PRIu32"u""\n",
5858 (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events));
5859 printf(" Lifetime NAND Writes %20"PRIu64"l" "u""\n",
5860 le64_to_cpu(perf->lifetime_nand_writes));
5861 printf(" Capacitor Health %20"PRIu32"u""%%\n",
5862 (uint32_t)le32_to_cpu(perf->capacitor_health));
5863 printf(" Lifetime User Writes %20"PRIu64"l" "u""\n",
5864 le64_to_cpu(perf->lifetime_user_writes));
5865 printf(" Lifetime User Reads %20"PRIu64"l" "u""\n",
5866 le64_to_cpu(perf->lifetime_user_reads));
5867 printf(" Lifetime Thermal Throttle Activations %20"PRIu32"u""\n",
5868 (uint32_t)le32_to_cpu(perf->lifetime_thermal_throttle_act));
5869 printf(" Percentage of P/E Cycles Remaining %20"PRIu32"u""%%\n",
5870 (uint32_t)le32_to_cpu(perf->percentage_pe_cycles_remaining));
5871}
5872
5873static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf)
5874{
5875 struct json_object *root = json_create_object()json_object_new_object();
5876
5877 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
)))
5878 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
)))
;
5879 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)))
5880 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)))
;
5881 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)))
5882 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)))
;
5883 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
)))
5884 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
)))
;
5885 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
)))
5886 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
)))
;
5887 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)))
5888 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)))
;
5889 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)))
5890 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)))
;
5891 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
)))
5892 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
)))
;
5893 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)))
5894 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)))
;
5895 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
)))
5896 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
)))
;
5897 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
)))
5898 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
)))
;
5899 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
)))
5900 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
)))
;
5901 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)))
5902 le32_to_cpu(perf->current_temp))json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
;
5903 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)))
5904 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)))
;
5905 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)))
5906 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)))
;
5907 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
)))
5908 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
)))
;
5909 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)))
5910 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)))
;
5911 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)))
5912 le32_to_cpu(perf->capacitor_health))json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
;
5913 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)))
5914 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)))
;
5915 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)))
5916 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)))
;
5917 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
)))
5918 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
)))
;
5919 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
)))
5920 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
)))
;
5921
5922 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5923 printf("\n");
5924 json_free_object(root)json_object_put(root);
5925}
5926
5927static void wdc_get_commit_action_bin(__u8 commit_action_type, char *action_bin)
5928{
5929
5930 switch (commit_action_type) {
5931 case 0:
5932 strcpy(action_bin, "000b");
5933 break;
5934 case 1:
5935 strcpy(action_bin, "001b");
5936 break;
5937 case 2:
5938 strcpy(action_bin, "010b");
5939 break;
5940 case 3:
5941 strcpy(action_bin, "011b");
5942 break;
5943 case 4:
5944 strcpy(action_bin, "100b");
5945 break;
5946 case 5:
5947 strcpy(action_bin, "101b");
5948 break;
5949 case 6:
5950 strcpy(action_bin, "110b");
5951 break;
5952 case 7:
5953 strcpy(action_bin, "111b");
5954 break;
5955 default:
5956 strcpy(action_bin, "INVALID");
5957 }
5958
5959}
5960
5961static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
5962 __u32 cust_id, __u32 vendor_id,
5963 __u32 device_id)
5964{
5965 int i, j;
5966 char previous_fw[9];
5967 char new_fw[9];
5968 char commit_action_bin[8];
5969 char time_str[100];
5970 __u16 oldestEntryIdx = 0, entryIdx = 0;
5971 uint64_t timestamp;
5972 __u64 timestamp_sec;
5973 const char *null_fw = "--------";
5974
5975 memset((void *)time_str, '\0', 100);
5976
5977 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
5978 printf(" Firmware Activate History Log\n");
5979 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005 ||
5980 vendor_id == WDC_NVME_SNDK_VID0x15b7) {
5981 printf(" Power on Hour Power Cycle Previous New\n");
5982 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
5983 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5984 } else {
5985 printf(" Power Cycle Previous New\n");
5986 printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n");
5987 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
5988 }
5989
5990 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
5991
5992 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
5993 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
5994 /* find lowest/oldest entry */
5995 for (i = 0; i < num_entries; i++) {
5996 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
5997 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
5998 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
5999 oldestEntryIdx = j;
6000 break;
6001 }
6002 }
6003 }
6004 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6005 entryIdx = 0;
6006 else
6007 entryIdx = oldestEntryIdx;
6008
6009 for (i = 0; i < num_entries; i++) {
6010 memset((void *)previous_fw, 0, 9);
6011 memset((void *)new_fw, 0, 9);
6012 memset((void *)commit_action_bin, 0, 8);
6013
6014 memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8);
6015 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6016 memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8);
6017 else
6018 memcpy(new_fw, null_fw, 8);
6019
6020 printf("%5"PRIu16"u""", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
6021
6022 timestamp = (0x0000FFFFFFFFFFFF &
6023 le64_to_cpu(
6024 fw_act_history_entry->entry[entryIdx].timestamp));
6025 timestamp_sec = timestamp / 1000;
6026 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6027 printf(" ");
6028 memset((void *)time_str, 0, 9);
6029 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6030 (__u32)(timestamp_sec/3600),
6031 (__u8)(timestamp_sec%3600/60),
6032 (__u8)(timestamp_sec%60));
6033
6034 printf("%s", time_str);
6035 printf(" ");
6036 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6037 printf(" ");
6038
6039 memset((void *)time_str, 0, 9);
6040 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6041 (__u32)((timestamp_sec/3600)%24),
6042 (__u8)((timestamp_sec/60)%60),
6043 (__u8)(timestamp_sec%60));
6044 printf("%s", time_str);
6045 printf(" ");
6046 } else {
6047 printf(" ");
6048 printf("%16"PRIu64"l" "u""", timestamp);
6049 printf(" ");
6050 }
6051
6052 printf("%16"PRIu64"l" "u""", (uint64_t)le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count));
6053 printf(" ");
6054 printf("%s", (char *)previous_fw);
6055 printf(" ");
6056 printf("%s", (char *)new_fw);
6057 printf(" ");
6058 printf("%2"PRIu8"u""", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number);
6059 printf(" ");
6060 wdc_get_commit_action_bin(
6061 fw_act_history_entry->entry[entryIdx].commit_action_type,
6062 (char *)&commit_action_bin);
6063 printf(" %s", (char *)commit_action_bin);
6064 printf(" ");
6065 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))
6066 printf("pass");
6067 else
6068 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result));
6069 printf("\n");
6070
6071 entryIdx++;
6072 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6073 entryIdx = 0;
6074 }
6075 } else {
6076 printf(" Firmware Activate History Log\n");
6077 printf(" Power on Hour Power Cycle Previous New\n");
6078 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6079 printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n");
6080
6081 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));
6082
6083 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6084 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6085 /* find lowest/oldest entry */
6086 for (i = 0; i < num_entries; i++) {
6087 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6088 oldestEntryIdx = i+1;
6089 break;
6090 }
6091 }
6092 }
6093
6094 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6095 entryIdx = 0;
6096 else
6097 entryIdx = oldestEntryIdx;
6098
6099 for (i = 0; i < num_entries; i++) {
6100 memset((void *)previous_fw, 0, 9);
6101 memset((void *)new_fw, 0, 9);
6102 memset((void *)commit_action_bin, 0, 8);
6103
6104 memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6105 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6106 memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6107 else
6108 memcpy(new_fw, null_fw, 8);
6109
6110 printf("%5"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].entry_num));
6111 printf(" ");
6112 printf("%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6113 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6114 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6115 printf(" ");
6116 printf("%16"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count));
6117 printf(" ");
6118 printf("%s", (char *)previous_fw);
6119 printf(" ");
6120 printf("%s", (char *)new_fw);
6121 printf(" ");
6122 printf("%2"PRIu8"u""", (uint8_t)fw_act_history_entry[entryIdx].slot_number);
6123 printf(" ");
6124 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6125 (char *)&commit_action_bin);
6126 printf(" %s", (char *)commit_action_bin);
6127 printf(" ");
6128 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result))
6129 printf("pass");
6130 else
6131 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result));
6132
6133 printf("\n");
6134
6135 entryIdx++;
6136 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6137 entryIdx = 0;
6138 }
6139 }
6140}
6141
6142static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
6143 __u32 cust_id, __u32 vendor_id,
6144 __u32 device_id)
6145{
6146 struct json_object *root = json_create_object()json_object_new_object();
6147 int i, j;
6148 char previous_fw[9];
6149 char new_fw[9];
6150 char commit_action_bin[8];
6151 char fail_str[32];
6152 char time_str[100];
6153 char ext_time_str[20];
6154 uint64_t timestamp;
6155 __u64 timestamp_sec;
6156
6157 memset((void *)previous_fw, 0, 9);
6158 memset((void *)new_fw, 0, 9);
6159 memset((void *)commit_action_bin, 0, 8);
6160 memset((void *)time_str, '\0', 100);
6161 memset((void *)ext_time_str, 0, 20);
6162 memset((void *)fail_str, 0, 11);
6163 char *null_fw = "--------";
6164 __u16 oldestEntryIdx = 0, entryIdx = 0;
6165
6166 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6167 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6168
6169 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6170 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6171 /* find lowest/oldest entry */
6172 for (i = 0; i < num_entries; i++) {
6173 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6174 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6175 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6176 oldestEntryIdx = j;
6177 break;
6178 }
6179 }
6180 }
6181 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6182 entryIdx = 0;
6183 else
6184 entryIdx = oldestEntryIdx;
6185
6186 for (i = 0; i < num_entries; i++) {
6187 memcpy(previous_fw,
6188 (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version),
6189 8);
6190 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6191 memcpy(new_fw,
6192 (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version),
6193 8);
6194 else
6195 memcpy(new_fw, null_fw, 8);
6196
6197 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
)))
6198 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
)))
;
6199
6200 timestamp = (0x0000FFFFFFFFFFFF &
6201 le64_to_cpu(
6202 fw_act_history_entry->entry[entryIdx].timestamp));
6203 timestamp_sec = timestamp / 1000;
6204 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6205 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6206 (__u32)(timestamp_sec/3600),
6207 (__u8)(timestamp_sec%3600/60),
6208 (__u8)(timestamp_sec%60));
6209
6210 json_object_add_value_string(root, "Power on Hour", time_str);
6211
6212 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6213 sprintf((char *)time_str, "%"PRIu32"u"":%u:%u",
6214 (__u32)((timestamp_sec/3600)%24),
6215 (__u8)((timestamp_sec/60)%60),
6216 (__u8)(timestamp_sec%60));
6217 json_object_add_value_string(root, "Power on Hour", time_str);
6218 } else {
6219 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
6220 }
6221
6222 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
)))
6223 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
)))
;
6224 json_object_add_value_string(root, "Previous Firmware",
6225 previous_fw);
6226 json_object_add_value_string(root, "New Firmware",
6227 new_fw);
6228 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))
6229 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))
;
6230
6231 wdc_get_commit_action_bin(
6232 fw_act_history_entry->entry[entryIdx].commit_action_type,
6233 (char *)&commit_action_bin);
6234 json_object_add_value_string(root, "Action", commit_action_bin);
6235
6236 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) {
6237 json_object_add_value_string(root, "Result", "pass");
6238 } else {
6239 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)));
6240 json_object_add_value_string(root, "Result", fail_str);
6241 }
6242
6243 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6244 printf("\n");
6245
6246 entryIdx++;
6247 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6248 entryIdx = 0;
6249 }
6250 } else {
6251 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));
6252
6253 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6254 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6255 /* find lowest/oldest entry */
6256 for (i = 0; i < num_entries; i++) {
6257 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6258 oldestEntryIdx = i+1;
6259 break;
6260 }
6261 }
6262 }
6263 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6264 entryIdx = 0;
6265 else
6266 entryIdx = oldestEntryIdx;
6267
6268 for (i = 0; i < num_entries; i++) {
6269 memcpy(previous_fw,
6270 (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6271 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6272 memcpy(new_fw,
6273 (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6274 else
6275 memcpy(new_fw, null_fw, 8);
6276
6277 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)))
6278 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)))
;
6279
6280 sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6281 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6282 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6283 json_object_add_value_string(root, "Power on Hour", time_str);
6284
6285 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
)))
6286 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
)))
;
6287 json_object_add_value_string(root, "Previous Firmware",
6288 previous_fw);
6289 json_object_add_value_string(root, "New Firmware",
6290 new_fw);
6291 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
6292 fw_act_history_entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
;
6293
6294 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6295 (char *)&commit_action_bin);
6296 json_object_add_value_string(root, "Action", commit_action_bin);
6297
6298 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) {
6299 json_object_add_value_string(root, "Result", "pass");
6300 } else {
6301 sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry[entryIdx].result)));
6302 json_object_add_value_string(root, "Result", fail_str);
6303 }
6304
6305 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6306 printf("\n");
6307
6308 entryIdx++;
6309 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6310 entryIdx = 0;
6311 }
6312 }
6313
6314 json_free_object(root)json_object_put(root);
6315}
6316
6317static int nvme_get_print_ocp_cloud_smart_log(struct libnvme_transport_handle *hdl,
6318 int uuid_index,
6319 __u32 namespace_id,
6320 int fmt)
6321{
6322 __u32 length = WDC_NVME_SMART_CLOUD_ATTR_LEN0x200;
6323 struct ocp_cloud_smart_log *log_ptr = NULL((void*)0);
6324 struct libnvme_passthru_cmd cmd;
6325 int ret, i;
6326
6327 log_ptr = (struct ocp_cloud_smart_log *)malloc(sizeof(__u8) * length);
6328 if (!log_ptr) {
6329 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
6330 return -1;
6331 }
6332
6333 if (namespace_id == NVME_NSID_ALL) {
6334 ret = libnvme_get_nsid(hdl, &namespace_id);
6335 if (ret < 0)
6336 namespace_id = NVME_NSID_ALL;
6337 }
6338
6339 /* Get the 0xC0 log data */
6340 nvme_init_get_log(&cmd, namespace_id,
6341 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6342 log_ptr, length);
6343 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6344 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6345 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6346 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6347 if (fmt == JSON)
6348 nvme_show_status(ret);
6349
6350 if (!ret) {
6351 /* Verify GUID matches */
6352 for (i = 0; i < 16; i++) {
6353 if (scao_guid[i] != log_ptr->log_page_guid[i]) {
6354 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C0 Log Page data\n");
6355 int j;
6356
6357 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
6358 for (j = 0; j < 16; j++)
6359 fprintf(stderrstderr, "%x", scao_guid[j]);
6360 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
6361 for (j = 0; j < 16; j++)
6362 fprintf(stderrstderr, "%x", log_ptr->log_page_guid[j]);
6363 fprintf(stderrstderr, "\n");
6364
6365 ret = -1;
6366 break;
6367 }
6368 }
6369
6370 if (!ret)
6371 /* parse the data */
6372 wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl);
6373 } else {
6374 fprintf(stderrstderr, "ERROR: WDC: Unable to read C0 Log Page data\n");
6375 ret = -1;
6376 }
6377
6378 free(log_ptr);
6379 return ret;
6380}
6381
6382static int nvme_get_print_c0_eol_log(struct libnvme_transport_handle *hdl,
6383 int uuid_index,
6384 __u32 namespace_id,
6385 int fmt)
6386{
6387 __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN0x200;
6388 struct libnvme_passthru_cmd cmd;
6389 void *log_ptr = NULL((void*)0);
6390 int ret;
6391
6392 log_ptr = (void *)malloc(sizeof(__u8) * length);
6393 if (!log_ptr) {
6394 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
6395 return -1;
6396 }
6397
6398 if (namespace_id == NVME_NSID_ALL) {
6399 ret = libnvme_get_nsid(hdl, &namespace_id);
6400 if (ret < 0)
6401 namespace_id = NVME_NSID_ALL;
6402 }
6403
6404 /* Get the 0xC0 log data */
6405 nvme_init_get_log(&cmd, namespace_id,
6406 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, NVME_CSI_NVM,
6407 log_ptr, length);
6408 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6409 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6410 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6411 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6412 if (fmt == JSON)
6413 nvme_show_status(ret);
6414
6415 if (!ret) {
6416 /* parse the data */
6417 wdc_print_c0_eol_log(log_ptr, fmt);
6418 } else {
6419 fprintf(stderrstderr, "ERROR: WDC: Unable to read C0 Log Page data ");
6420 fprintf(stderrstderr, "with uuid index %d\n", uuid_index);
6421 ret = -1;
6422 }
6423
6424 free(log_ptr);
6425 return ret;
6426}
6427
6428static int nvme_get_ext_smart_cloud_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6429{
6430 struct libnvme_passthru_cmd cmd;
6431 __u8 *log_ptr = NULL((void*)0);
6432 int ret, i;
6433
6434 log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6435 if (!log_ptr) {
6436 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
6437 return -1;
6438 }
6439
6440 /* Get the 0xC0 log data */
6441 nvme_init_get_log(&cmd, namespace_id,
6442 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6443 log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6444 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6445 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6446 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6447 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6448 if (!ret) {
6449 /* Verify GUID matches */
6450 for (i = 0; i < WDC_C0_GUID_LENGTH16; i++) {
6451 if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
6452 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C0 Log Page V1 data\n");
6453 int j;
6454
6455 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
6456 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6457 fprintf(stderrstderr, "%x", ext_smart_guid[j]);
6458 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
6459 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6460 fprintf(stderrstderr, "%x", *&log_ptr[SCAO_V1_LPG + j]);
6461 fprintf(stderrstderr, "\n");
6462
6463 ret = -1;
6464 break;
6465 }
6466 }
6467 }
6468
6469 *data = log_ptr;
6470
6471 return ret;
6472}
6473
6474
6475static int nvme_get_hw_rev_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6476{
6477 struct wdc_nvme_hw_rev_log *log_ptr = NULL((void*)0);
6478 struct libnvme_passthru_cmd cmd;
6479 int ret, i;
6480
6481 log_ptr = (struct wdc_nvme_hw_rev_log *)malloc(sizeof(__u8) * WDC_NVME_HW_REV_LOG_PAGE_LEN512);
6482 if (!log_ptr) {
6483 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
6484 return -1;
6485 }
6486
6487 /* Get the 0xC0 log data */
6488 nvme_init_get_log(&cmd, namespace_id,
6489 WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6, NVME_CSI_NVM,
6490 log_ptr, WDC_NVME_HW_REV_LOG_PAGE_LEN512);
6491 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6492 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6493 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6494 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6495 if (!ret) {
6496 /* Verify GUID matches */
6497 for (i = 0; i < WDC_NVME_C6_GUID_LENGTH16; i++) {
6498 if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
6499 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in HW Revision Log Page data\n");
6500 int j;
6501
6502 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
6503 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6504 fprintf(stderrstderr, "%x", hw_rev_log_guid[j]);
6505 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
6506 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6507 fprintf(stderrstderr, "%x", log_ptr->hw_rev_guid[j]);
6508 fprintf(stderrstderr, "\n");
6509
6510 ret = -1;
6511 break;
6512 }
6513 }
6514 }
6515
6516 *data = (__u8 *)log_ptr;
6517
6518 return ret;
6519}
6520
6521
6522static void wdc_print_hw_rev_log_normal(void *data)
6523{
6524 int i;
6525 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6526
6527 printf(" Hardware Revision Log:-\n");
6528
6529 printf(" Global Device HW Revision : %d\n",
6530 log_data->hw_rev_gdr);
6531 printf(" ASIC HW Revision : %d\n",
6532 log_data->hw_rev_ar);
6533 printf(" PCB Manufacturer Code : %d\n",
6534 log_data->hw_rev_pbc_mc);
6535 printf(" DRAM Manufacturer Code : %d\n",
6536 log_data->hw_rev_dram_mc);
6537 printf(" NAND Manufacturer Code : %d\n",
6538 log_data->hw_rev_nand_mc);
6539 printf(" PMIC 1 Manufacturer Code : %d\n",
6540 log_data->hw_rev_pmic1_mc);
6541 printf(" PMIC 2 Manufacturer Code : %d\n",
6542 log_data->hw_rev_pmic2_mc);
6543 printf(" Other Component 1 Manf Code : %d\n",
6544 log_data->hw_rev_c1_mc);
6545 printf(" Other Component 2 Manf Code : %d\n",
6546 log_data->hw_rev_c2_mc);
6547 printf(" Other Component 3 Manf Code : %d\n",
6548 log_data->hw_rev_c3_mc);
6549 printf(" Other Component 4 Manf Code : %d\n",
6550 log_data->hw_rev_c4_mc);
6551 printf(" Other Component 5 Manf Code : %d\n",
6552 log_data->hw_rev_c5_mc);
6553 printf(" Other Component 6 Manf Code : %d\n",
6554 log_data->hw_rev_c6_mc);
6555 printf(" Other Component 7 Manf Code : %d\n",
6556 log_data->hw_rev_c7_mc);
6557 printf(" Other Component 8 Manf Code : %d\n",
6558 log_data->hw_rev_c8_mc);
6559 printf(" Other Component 9 Manf Code : %d\n",
6560 log_data->hw_rev_c9_mc);
6561
6562 printf(" Device Manf Detailed Info : 0x");
6563 for (i = 0; i < 16; i++) {
6564 printf("%02x", log_data->hw_rev_dev_mdi[i]);
6565 if (i == 7)
6566 printf(" 0x");
6567 }
6568 printf("\n");
6569 printf(" ASIC Detailed Info : 0x");
6570 for (i = 0; i < 16; i++) {
6571 printf("%02x", log_data->hw_rev_asic_di[i]);
6572 if (i == 7)
6573 printf(" 0x");
6574 }
6575 printf("\n");
6576 printf(" PCB Detailed Info : 0x");
6577 for (i = 0; i < 16; i++) {
6578 printf("%02x", log_data->hw_rev_pcb_di[i]);
6579 if (i == 7)
6580 printf(" 0x");
6581 }
6582 printf("\n");
6583 printf(" DRAM Detailed Info : 0x");
6584 for (i = 0; i < 16; i++) {
6585 printf("%02x", log_data->hw_rev_dram_di[i]);
6586 if (i == 7)
6587 printf(" 0x");
6588 }
6589 printf("\n");
6590 printf(" NAND Detailed Info : 0x");
6591 for (i = 0; i < 16; i++) {
6592 printf("%02x", log_data->hw_rev_nand_di[i]);
6593 if (i == 7)
6594 printf(" 0x");
6595 }
6596 printf("\n");
6597 printf(" PMIC 1 Detailed Info : 0x");
6598 for (i = 0; i < 16; i++) {
6599 printf("%02x", log_data->hw_rev_pmic1_di[i]);
6600 if (i == 7)
6601 printf(" 0x");
6602 }
6603 printf("\n");
6604 printf(" PMIC 2 Detailed Info : 0x");
6605 for (i = 0; i < 16; i++) {
6606 printf("%02x", log_data->hw_rev_pmic2_di[i]);
6607 if (i == 7)
6608 printf(" 0x");
6609 }
6610 printf("\n");
6611 printf(" Component 1 Detailed Info : 0x");
6612 for (i = 0; i < 16; i++) {
6613 printf("%02x", log_data->hw_rev_c1_di[i]);
6614 if (i == 7)
6615 printf(" 0x");
6616 }
6617 printf("\n");
6618 printf(" Component 2 Detailed Info : 0x");
6619 for (i = 0; i < 16; i++) {
6620 printf("%02x", log_data->hw_rev_c2_di[i]);
6621 if (i == 7)
6622 printf(" 0x");
6623 }
6624 printf("\n");
6625 printf(" Component 3 Detailed Info : 0x");
6626 for (i = 0; i < 16; i++) {
6627 printf("%02x", log_data->hw_rev_c3_di[i]);
6628 if (i == 7)
6629 printf(" 0x");
6630 }
6631 printf("\n");
6632 printf(" Component 4 Detailed Info : 0x");
6633 for (i = 0; i < 16; i++) {
6634 printf("%02x", log_data->hw_rev_c4_di[i]);
6635 if (i == 7)
6636 printf(" 0x");
6637 }
6638 printf("\n");
6639 printf(" Component 5 Detailed Info : 0x");
6640 for (i = 0; i < 16; i++) {
6641 printf("%02x", log_data->hw_rev_c5_di[i]);
6642 if (i == 7)
6643 printf(" 0x");
6644 }
6645 printf("\n");
6646 printf(" Component 6 Detailed Info : 0x");
6647 for (i = 0; i < 16; i++) {
6648 printf("%02x", log_data->hw_rev_c6_di[i]);
6649 if (i == 7)
6650 printf(" 0x");
6651 }
6652 printf("\n");
6653 printf(" Component 7 Detailed Info : 0x");
6654 for (i = 0; i < 16; i++) {
6655 printf("%02x", log_data->hw_rev_c7_di[i]);
6656 if (i == 7)
6657 printf(" 0x");
6658 }
6659 printf("\n");
6660 printf(" Component 8 Detailed Info : 0x");
6661 for (i = 0; i < 16; i++) {
6662 printf("%02x", log_data->hw_rev_c8_di[i]);
6663 if (i == 7)
6664 printf(" 0x");
6665 }
6666 printf("\n");
6667 printf(" Component 9 Detailed Info : 0x");
6668 for (i = 0; i < 16; i++) {
6669 printf("%02x", log_data->hw_rev_c9_di[i]);
6670 if (i == 7)
6671 printf(" 0x");
6672 }
6673 printf("\n");
6674 printf(" Serial Number : 0x");
6675 for (i = 0; i < 32; i++) {
6676 if ((i > 1) & !(i % 8))
6677 printf(" 0x");
6678 printf("%02x", log_data->hw_rev_sn[i]);
6679 }
6680 printf("\n");
6681
6682 printf(" Log Page Version : %d\n", log_data->hw_rev_version);
6683 printf(" Log page GUID : 0x");
6684 printf("%"PRIx64"l" "x""%"PRIx64"l" "x""\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6685 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6686 printf("\n");
6687}
6688
6689static void wdc_print_hw_rev_log_json(void *data)
6690{
6691 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6692 struct json_object *root = json_create_object()json_object_new_object();
6693 char json_data[80];
6694
6695 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))
6696 log_data->hw_rev_gdr)json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
;
6697 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))
6698 log_data->hw_rev_ar)json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
;
6699 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))
6700 log_data->hw_rev_pbc_mc)json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
;
6701 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))
6702 log_data->hw_rev_dram_mc)json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
;
6703 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))
6704 log_data->hw_rev_nand_mc)json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
;
6705 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))
6706 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))
;
6707 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))
6708 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))
;
6709 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))
6710 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))
;
6711 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))
6712 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))
;
6713 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))
6714 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))
;
6715 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))
6716 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))
;
6717 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))
6718 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))
;
6719 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))
6720 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))
;
6721 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))
6722 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))
;
6723 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))
6724 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))
;
6725 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))
6726 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))
;
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_dev_mdi[8]),
6730 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
6731 json_object_add_value_string(root, "Device Manf 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_asic_di[8]),
6735 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
6736 json_object_add_value_string(root, "ASIC 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_pcb_di[8]),
6740 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
6741 json_object_add_value_string(root, "PCB 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_dram_di[8]),
6745 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
6746 json_object_add_value_string(root, "DRAM 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_nand_di[8]),
6750 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
6751 json_object_add_value_string(root, "NAND 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_pmic1_di[8]),
6755 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
6756 json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
6757
6758 memset((void *)json_data, 0, 40);
6759 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
6760 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
6761 json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
6762
6763 memset((void *)json_data, 0, 40);
6764 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
6765 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
6766 json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
6767
6768 memset((void *)json_data, 0, 40);
6769 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
6770 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
6771 json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
6772
6773 memset((void *)json_data, 0, 40);
6774 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
6775 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
6776 json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
6777
6778 memset((void *)json_data, 0, 40);
6779 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
6780 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
6781 json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
6782
6783 memset((void *)json_data, 0, 40);
6784 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
6785 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
6786 json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
6787
6788 memset((void *)json_data, 0, 40);
6789 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
6790 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
6791 json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
6792
6793 memset((void *)json_data, 0, 40);
6794 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
6795 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
6796 json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
6797
6798 memset((void *)json_data, 0, 40);
6799 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
6800 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
6801 json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
6802
6803 memset((void *)json_data, 0, 40);
6804 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
6805 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
6806 json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
6807
6808 memset((void *)json_data, 0, 80);
6809 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""",
6810 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
6811 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
6812 json_object_add_value_string(root, "Serial Number", json_data);
6813
6814 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)))
6815 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)))
;
6816
6817 memset((void *)json_data, 0, 40);
6818 sprintf((char *)json_data, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6819 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6820 json_object_add_value_string(root, "Log Page GUID", json_data);
6821
6822 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6823 printf("\n");
6824 json_free_object(root)json_object_put(root);
6825}
6826
6827static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
6828{
6829 int i;
6830 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6831
6832 if (mask == WDC_SCA_V1_NAND_STATS0x1)
6833 printf(" NAND Statistics :-\n");
6834 else
6835 printf(" SMART Cloud Attributes :-\n");
6836
6837 printf(" Physical Media Units Written TLC (Bytes): %s\n",
6838 uint128_t_to_string(le128_to_cpu(
6839 ext_smart_log_ptr->ext_smart_pmuwt)));
6840 printf(" Physical Media Units Written SLC (Bytes): %s\n",
6841 uint128_t_to_string(le128_to_cpu(
6842 ext_smart_log_ptr->ext_smart_pmuws)));
6843 printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
6844 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
6845 printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6846 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
6847 printf(" XOR Recovery Count (Int) : %"PRIu64"l" "u""\n",
6848 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
6849 printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"l" "u""\n",
6850 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
6851 if (mask == WDC_SCA_V1_ALL0xF) {
6852 printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"l" "u""\n",
6853 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
6854 printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"l" "u""\n",
6855 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
6856 printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"l" "u""\n",
6857 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
6858 printf(" System Data %% life-used : %d %%\n",
6859 ext_smart_log_ptr->ext_smart_sdpu);
6860 }
6861 printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"l" "u""\n",
6862 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
6863 printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"l" "u""\n",
6864 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
6865 printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"l" "u""\n",
6866 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
6867 printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"l" "u""\n",
6868 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
6869 printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"l" "u""\n",
6870 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
6871 printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"l" "u""\n",
6872 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
6873 printf(" Program Fail Count (Normalized) (Int) : %d\n",
6874 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
6875 printf(" Program Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6876 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
6877 printf(" Erase Fail Count (Normalized) (Int) : %d\n",
6878 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
6879 printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6880 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
6881 if (mask == WDC_SCA_V1_ALL0xF) {
6882 printf(" PCIe Correctable Error Count (Int) : %"PRIu64"l" "u""\n",
6883 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
6884 printf(" %% Free Blocks (User) (Int) : %d %%\n",
6885 ext_smart_log_ptr->ext_smart_pfbu);
6886 printf(" Security Version Number (Int) : %"PRIu64"l" "u""\n",
6887 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
6888 printf(" %% Free Blocks (System) (Int) : %d %%\n",
6889 ext_smart_log_ptr->ext_smart_pfbs);
6890 printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n",
6891 uint128_t_to_string(le128_to_cpu(
6892 ext_smart_log_ptr->ext_smart_dcc)));
6893 printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"l" "u""\n",
6894 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
6895 printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
6896 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
6897 printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
6898 ext_smart_log_ptr->ext_smart_bbpg);
6899 }
6900 printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"l" "u""\n",
6901 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
6902 if (mask == WDC_SCA_V1_ALL0xF) {
6903 printf(" Total # of Read Refresh Count (Int) : %"PRIu64"l" "u""\n",
6904 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
6905 }
6906 printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
6907 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
6908 printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6909 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
6910 printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n",
6911 uint128_t_to_string(
6912 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)));
6913 if (mask == WDC_SCA_V1_ALL0xF) {
6914 printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
6915 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
6916 printf(" Total # Unaligned I/O (Int) : %"PRIu64"l" "u""\n",
6917 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
6918 }
6919 printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n",
6920 uint128_t_to_string(
6921 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)));
6922 if (mask == WDC_SCA_V1_ALL0xF) {
6923 printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6924 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
6925 printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6926 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
6927 printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
6928 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
6929 printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"l" "u""\n",
6930 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
6931 printf(" Active Power State Change Count (Int) : %"PRIu64"l" "u""\n",
6932 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
6933 }
6934 printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
6935 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
6936 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
6937 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
6938 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
6939 printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
6940 0, 0, 0, 0);
6941 if (mask == WDC_SCA_V1_ALL0xF) {
6942 printf(" FTL Unit Size : %"PRIu32"u""\n",
6943 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
6944 printf(" TCG Ownership Status : %"PRIu32"u""\n",
6945 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
6946 printf(" Log Page Version (Int) : %d\n",
6947 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
6948 printf(" Log page GUID (Hex) : 0x");
6949 for (i = WDC_C0_GUID_LENGTH16; i > 0; i--)
6950 printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
6951 printf("\n");
6952 }
6953 printf("\n");
6954}
6955
6956static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
6957{
6958 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr =
6959 (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6960 struct json_object *root = json_create_object()json_object_new_object();
6961
6962 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)))
6963 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)))
;
6964 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)))
6965 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)))
;
6966 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
)))
6967 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
)))
;
6968 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)))
6969 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)))
;
6970 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)))
6971 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)))
;
6972 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)))
6973 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)))
;
6974 if (mask == WDC_SCA_V1_ALL0xF) {
6975 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)))
6976 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)))
;
6977 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)))
6978 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)))
;
6979 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)))
6980 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)))
;
6981 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))
6982 (__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))
;
6983 }
6984 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
)))
6985 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
)))
;
6986 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
)))
6987 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
)))
;
6988 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
)))
6989 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
)))
;
6990 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
)))
6991 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
)))
;
6992 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
)))
6993 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
)))
;
6994 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
)))
6995 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
)))
;
6996 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)))
6997 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)))
;
6998 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)))
6999 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)))
;
7000 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
)))
7001 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
)))
;
7002 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)))
7003 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)))
;
7004 if (mask == WDC_SCA_V1_ALL0xF) {
7005 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)))
7006 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)))
;
7007 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))
7008 (__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))
;
7009 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)))
7010 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)))
;
7011 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))
7012 (__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))
;
7013 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)))
7014 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)))
;
7015 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)))
7016 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)))
;
7017 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)))
7018 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)))
;
7019 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))
7020 (__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))
;
7021 }
7022 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)))
7023 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)))
;
7024 if (mask == WDC_SCA_V1_ALL0xF)
7025 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)))
7026 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)))
;
7027 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
)))
7028 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
)))
;
7029 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)))
7030 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)))
;
7031 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)))
7032 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)))
;
7033 if (mask == WDC_SCA_V1_ALL0xF) {
7034 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)))
7035 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)))
;
7036 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)))
7037 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)))
;
7038 }
7039 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)))
7040 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)))
;
7041 if (mask == WDC_SCA_V1_ALL0xF) {
7042 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)))
7043 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)))
;
7044 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)))
7045 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)))
;
7046 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)))
7047 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)))
;
7048 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)))
7049 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)))
;
7050 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
)))
7051 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
)))
;
7052 }
7053 char vers_str[40];
7054
7055 memset((void *)vers_str, 0, 40);
7056 sprintf((char *)vers_str, "%d.%d.%d.%d",
7057 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7058 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7059 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7060 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7061 json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
7062 memset((void *)vers_str, 0, 40);
7063 sprintf((char *)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0);
7064 json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
7065
7066 if (mask == WDC_SCA_V1_ALL0xF) {
7067 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)))
7068 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)))
;
7069 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)))
7070 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)))
;
7071 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)))
7072 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)))
;
7073 char guid[40];
7074
7075 memset((void *)guid, 0, 40);
7076 sprintf((char *)guid, "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7077 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]),
7078 le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0]));
7079 json_object_add_value_string(root, "log_page_guid", guid);
7080 }
7081
7082 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7083 printf("\n");
7084 json_free_object(root)json_object_put(root);
7085}
7086
7087
7088static void wdc_print_eol_c0_normal(void *data)
7089{
7090
7091 __u8 *log_data = (__u8 *)data;
7092
7093 printf(" End of Life Log Page 0xC0 :-\n");
7094
7095 printf(" Realloc Block Count %"PRIu32"u""\n",
7096 (uint32_t)le32_to_cpu(log_data[EOL_RBC]));
7097 printf(" ECC Rate %"PRIu32"u""\n",
7098 (uint32_t)le32_to_cpu(log_data[EOL_ECCR]));
7099 printf(" Write Amp %"PRIu32"u""\n",
7100 (uint32_t)le32_to_cpu(log_data[EOL_WRA]));
7101 printf(" Percent Life Remaining %"PRIu32"u""\n",
7102 (uint32_t)le32_to_cpu(log_data[EOL_PLR]));
7103 printf(" Program Fail Count %"PRIu32"u""\n",
7104 (uint32_t)le32_to_cpu(log_data[EOL_PFC]));
7105 printf(" Erase Fail Count %"PRIu32"u""\n",
7106 (uint32_t)le32_to_cpu(log_data[EOL_EFC]));
7107 printf(" Raw Read Error Rate %"PRIu32"u""\n",
7108 (uint32_t)le32_to_cpu(log_data[EOL_RRER]));
7109
7110}
7111
7112static void wdc_print_eol_c0_json(void *data)
7113{
7114 __u8 *log_data = (__u8 *)data;
7115 struct json_object *root = json_create_object()json_object_new_object();
7116
7117 json_object_add_value_uint(root, "Realloc Block Count",json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_RBC])))
7118 (uint32_t)le32_to_cpu(log_data[EOL_RBC]))json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_RBC])))
;
7119 json_object_add_value_uint(root, "ECC Rate",json_object_object_add(root, "ECC Rate", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_ECCR])))
7120 (uint32_t)le32_to_cpu(log_data[EOL_ECCR]))json_object_object_add(root, "ECC Rate", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_ECCR])))
;
7121 json_object_add_value_uint(root, "Write Amp",json_object_object_add(root, "Write Amp", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_WRA])))
7122 (uint32_t)le32_to_cpu(log_data[EOL_WRA]))json_object_object_add(root, "Write Amp", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_WRA])))
;
7123 json_object_add_value_uint(root, "Percent Life Remaining",json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_PLR])))
7124 (uint32_t)le32_to_cpu(log_data[EOL_PLR]))json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_PLR])))
;
7125 json_object_add_value_uint(root, "Program Fail Count",json_object_object_add(root, "Program Fail Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_PFC])))
7126 (uint32_t)le32_to_cpu(log_data[EOL_PFC]))json_object_object_add(root, "Program Fail Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_PFC])))
;
7127 json_object_add_value_uint(root, "Erase Fail Count",json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_EFC])))
7128 (uint32_t)le32_to_cpu(log_data[EOL_EFC]))json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_EFC])))
;
7129 json_object_add_value_uint(root, "Raw Read Error Rate",json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_RRER])))
7130 (uint32_t)le32_to_cpu(log_data[EOL_RRER]))json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
((uint32_t)le32_to_cpu(log_data[EOL_RRER])))
;
7131
7132 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7133 printf("\n");
7134 json_free_object(root)json_object_put(root);
7135}
7136
7137static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
7138{
7139 if (!data) {
7140 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read 0xC0 V1 log\n");
7141 return -1;
7142 }
7143 switch (fmt) {
7144 case NORMAL:
7145 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL0xF);
7146 break;
7147 case JSON:
7148 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL0xF);
7149 break;
7150 }
7151 return 0;
7152}
7153
7154static int wdc_print_c0_cloud_attr_log(void *data,
7155 int fmt,
7156 struct libnvme_transport_handle *hdl)
7157{
7158 struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data;
7159
7160 if (!data) {
7161 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read 0xC0 log\n");
7162 return -1;
7163 }
7164
7165 switch (fmt) {
7166 case BINARY:
7167 d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log));
7168 break;
7169 case NORMAL:
7170 wdc_show_cloud_smart_log_normal(log, hdl);
7171 break;
7172 case JSON:
7173 wdc_show_cloud_smart_log_json(log);
7174 break;
7175 }
7176 return 0;
7177}
7178
7179static int wdc_print_c0_eol_log(void *data, int fmt)
7180{
7181 if (!data) {
7182 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read 0xC0 log\n");
7183 return -1;
7184 }
7185 switch (fmt) {
7186 case BINARY:
7187 d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN0x200);
7188 break;
7189 case NORMAL:
7190 wdc_print_eol_c0_normal(data);
7191 break;
7192 case JSON:
7193 wdc_print_eol_c0_json(data);
7194 break;
7195 }
7196 return 0;
7197}
7198
7199static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct libnvme_transport_handle *hdl, int uuid_index,
7200 char *format, __u32 namespace_id, int fmt)
7201{
7202 int ret;
7203
7204 if (!uuid_index) {
7205 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7206 uuid_index,
7207 namespace_id,
7208 fmt);
7209 } else if (uuid_index == 1) {
7210 ret = nvme_get_print_c0_eol_log(hdl,
7211 uuid_index,
7212 namespace_id,
7213 fmt);
7214 } else {
7215 fprintf(stderrstderr, "ERROR: WDC: Unknown uuid index\n");
7216 ret = -1;
7217 }
7218
7219 return ret;
7220}
7221
7222static int wdc_get_c0_log_page_sn(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, int uuid_index, char *format,
7223 __u32 namespace_id, int fmt)
7224{
7225 int ret = 0;
7226 __u32 cust_id;
7227
7228 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7229 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7230 fprintf(stderrstderr, "%s: ERROR: WDC: invalid customer id\n", __func__);
7231 return -1;
7232 }
7233
7234 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
7235 (cust_id == WDC_CUSTOMER_ID_0x10050x1005)) {
7236 ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format,
7237 namespace_id, fmt);
7238 } else {
7239 ret = nvme_get_print_c0_eol_log(hdl,
7240 0,
7241 namespace_id,
7242 fmt);
7243 }
7244
7245 return ret;
7246}
7247
7248static int wdc_get_c0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format, int uuid_index,
7249 __u32 namespace_id)
7250{
7251 uint32_t device_id, read_vendor_id;
7252 nvme_print_flags_t fmt;
7253 int ret;
7254 __u8 *data;
7255
7256 if (!wdc_check_device(ctx, hdl))
7257 return -1;
7258 ret = validate_output_format(format, &fmt);
7259 if (ret < 0) {
7260 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7261 return ret;
7262 }
7263
7264 ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id);
7265
7266 switch (device_id) {
7267 case WDC_NVME_SN640_DEV_ID0x2400:
7268 case WDC_NVME_SN640_DEV_ID_10x2401:
7269 case WDC_NVME_SN640_DEV_ID_20x2402:
7270 case WDC_NVME_SN640_DEV_ID_30x2404:
7271 case WDC_NVME_SN840_DEV_ID0x2300:
7272 case WDC_NVME_SN840_DEV_ID_10x2500:
7273 case WDC_NVME_SN860_DEV_ID0x2730:
7274 case WDC_NVME_SN560_DEV_ID_10x2712:
7275 case WDC_NVME_SN560_DEV_ID_20x2713:
7276 case WDC_NVME_SN560_DEV_ID_30x2714:
7277 case WDC_NVME_SN550_DEV_ID0x2708:
7278 ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt);
7279 break;
7280 case WDC_NVME_SN650_DEV_ID0x2700:
7281 case WDC_NVME_SN650_DEV_ID_10x2701:
7282 case WDC_NVME_SN650_DEV_ID_20x2702:
7283 case WDC_NVME_SN650_DEV_ID_30x2720:
7284 case WDC_NVME_SN650_DEV_ID_40x2721:
7285 case WDC_NVME_SN655_DEV_ID0x2722:
7286 case WDC_NVME_SN655_DEV_ID_10x2723:
7287 case WDC_NVME_SNTMP_DEV_ID0x2761:
7288 case WDC_NVME_SNTMP_DEV_ID_10x2763:
7289 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
7290 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
7291 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
7292 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
7293 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
7294 if (uuid_index == 0) {
7295 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7296 uuid_index,
7297 namespace_id,
7298 fmt);
7299 } else {
7300 ret = nvme_get_print_c0_eol_log(hdl,
7301 uuid_index,
7302 namespace_id,
7303 fmt);
7304 }
7305 break;
7306 case WDC_NVME_ZN350_DEV_ID0x5010:
7307 case WDC_NVME_ZN350_DEV_ID_10x5018:
7308 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7309 0,
7310 NVME_NSID_ALL,
7311 fmt);
7312 break;
7313 case WDC_NVME_SN820CL_DEV_ID0x5037:
7314 /* Get the 0xC0 Extended Smart Cloud Attribute log data */
7315 data = NULL((void*)0);
7316 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
7317 uuid_index, namespace_id);
7318
7319 if (strcmp(format, "json"))
7320 nvme_show_status(ret);
7321
7322 if (!ret) {
7323 /* parse the data */
7324 wdc_print_ext_smart_cloud_log(data, fmt);
7325 } else {
7326 fprintf(stderrstderr, "ERROR: WDC: Unable to read C0 Log Page V1 data\n");
7327 ret = -1;
7328 }
7329
7330 free(data);
7331 break;
7332 default:
7333 fprintf(stderrstderr, "ERROR: WDC: Unknown device id - 0x%x\n", device_id);
7334 ret = -1;
7335 break;
7336
7337 }
7338
7339 return ret;
7340}
7341
7342static int wdc_print_latency_monitor_log(struct libnvme_transport_handle *hdl,
7343 struct wdc_ssd_latency_monitor_log *log_data,
7344 int fmt)
7345{
7346 if (!log_data) {
7347 fprintf(stderrstderr, "ERROR: WDC: Invalid C3 log data buffer\n");
7348 return -1;
7349 }
7350 switch (fmt) {
7351 case NORMAL:
7352 wdc_print_latency_monitor_log_normal(hdl, log_data);
7353 break;
7354 case JSON:
7355 wdc_print_latency_monitor_log_json(log_data);
7356 break;
7357 }
7358 return 0;
7359}
7360
7361static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
7362{
7363 if (!log_data) {
7364 fprintf(stderrstderr, "ERROR: WDC: Invalid C1 log data buffer\n");
7365 return -1;
7366 }
7367 switch (fmt) {
7368 case NORMAL:
7369 wdc_print_error_rec_log_normal(log_data);
7370 break;
7371 case JSON:
7372 wdc_print_error_rec_log_json(log_data);
7373 break;
7374 }
7375 return 0;
7376}
7377
7378static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
7379{
7380 if (!log_data) {
7381 fprintf(stderrstderr, "ERROR: WDC: Invalid C4 log data buffer\n");
7382 return -1;
7383 }
7384 switch (fmt) {
7385 case NORMAL:
7386 wdc_print_dev_cap_log_normal(log_data);
7387 break;
7388 case JSON:
7389 wdc_print_dev_cap_log_json(log_data);
7390 break;
7391 }
7392 return 0;
7393}
7394
7395static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
7396{
7397 if (!log_data) {
7398 fprintf(stderrstderr, "ERROR: WDC: Invalid C5 log data buffer\n");
7399 return -1;
7400 }
7401 switch (fmt) {
7402 case NORMAL:
7403 wdc_print_unsupported_reqs_log_normal(log_data);
7404 break;
7405 case JSON:
7406 wdc_print_unsupported_reqs_log_json(log_data);
7407 break;
7408 }
7409 return 0;
7410}
7411
7412static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
7413{
7414 if (!perf) {
7415 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read perf stats\n");
7416 return -1;
7417 }
7418 switch (fmt) {
7419 case NORMAL:
7420 wdc_print_fb_ca_log_normal(perf);
7421 break;
7422 case JSON:
7423 wdc_print_fb_ca_log_json(perf);
7424 break;
7425 }
7426 return 0;
7427}
7428
7429static int wdc_print_bd_ca_log(struct libnvme_transport_handle *hdl, void *bd_data, int fmt)
7430{
7431 if (!bd_data) {
7432 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read data\n");
7433 return -1;
7434 }
7435 switch (fmt) {
7436 case NORMAL:
7437 wdc_print_bd_ca_log_normal(hdl, bd_data);
7438 break;
7439 case JSON:
7440 wdc_print_bd_ca_log_json(bd_data);
7441 break;
7442 default:
7443 fprintf(stderrstderr, "ERROR: WDC: Unknown format - %d\n", fmt);
7444 return -1;
7445 }
7446 return 0;
7447}
7448
7449static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt)
7450{
7451 if (!perf) {
7452 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read perf stats\n");
7453 return -1;
7454 }
7455 switch (fmt) {
7456 case NORMAL:
7457 wdc_print_d0_log_normal(perf);
7458 break;
7459 case JSON:
7460 wdc_print_d0_log_json(perf);
7461 break;
7462 }
7463 return 0;
7464}
7465
7466static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt,
7467 __u32 cust_id, __u32 vendor_id,
7468 __u32 device_id)
7469{
7470 if (!data) {
7471 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read fw activate history entries\n");
7472 return -1;
7473 }
7474
7475 switch (fmt) {
7476 case NORMAL:
7477 wdc_print_fw_act_history_log_normal(data, num_entries, cust_id,
7478 vendor_id, device_id);
7479 break;
7480 case JSON:
7481 wdc_print_fw_act_history_log_json(data, num_entries, cust_id,
7482 vendor_id, device_id);
7483 break;
7484 }
7485 return 0;
7486}
7487
7488static int wdc_get_ca_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7489{
7490 uint32_t read_device_id, read_vendor_id;
7491 struct wdc_ssd_ca_perf_stats *perf;
7492 nvme_print_flags_t fmt;
7493 __u32 cust_id;
7494 __u8 *data;
7495 int ret;
7496
7497 if (!wdc_check_device(ctx, hdl))
7498 return -1;
7499 ret = validate_output_format(format, &fmt);
7500 if (ret < 0) {
7501 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7502 return ret;
7503 }
7504
7505 /* verify the 0xCA log page is supported */
7506 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7507 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
7508 fprintf(stderrstderr, "ERROR: WDC: 0xCA Log Page not supported\n");
7509 return -1;
7510 }
7511
7512 /* get the FW customer id */
7513 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7514 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7515 fprintf(stderrstderr, "%s: ERROR: WDC: invalid customer id\n", __func__);
7516 return -1;
7517 }
7518
7519 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
7520
7521 switch (read_device_id) {
7522 case WDC_NVME_SN200_DEV_ID0x0023:
7523 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7524 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7525 if (!data) {
7526 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7527 return -1;
7528 }
7529
7530 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7531
7532 ret = nvme_get_log_simple(hdl,
7533 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7534 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7535 if (strcmp(format, "json"))
7536 nvme_show_status(ret);
7537
7538 if (!ret) {
7539 /* parse the data */
7540 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7541 ret = wdc_print_fb_ca_log(perf, fmt);
7542 } else {
7543 fprintf(stderrstderr, "ERROR: WDC: Unable to read CA Log Page data\n");
7544 ret = -1;
7545 }
7546 } else {
7547
7548 fprintf(stderrstderr, "ERROR: WDC: Unsupported Customer id, id = 0x%x\n", cust_id);
7549 return -1;
7550 }
7551 break;
7552 case WDC_NVME_SN640_DEV_ID0x2400:
7553 case WDC_NVME_SN640_DEV_ID_10x2401:
7554 case WDC_NVME_SN640_DEV_ID_20x2402:
7555 case WDC_NVME_SN640_DEV_ID_30x2404:
7556 case WDC_NVME_SN840_DEV_ID0x2300:
7557 case WDC_NVME_SN840_DEV_ID_10x2500:
7558 case WDC_NVME_SN860_DEV_ID0x2730:
7559 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7560 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7561 if (!data) {
7562 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7563 return -1;
7564 }
7565
7566 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7567
7568 ret = nvme_get_log_simple(hdl,
7569 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7570 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7571 if (strcmp(format, "json"))
7572 nvme_show_status(ret);
7573
7574 if (!ret) {
7575 /* parse the data */
7576 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7577 ret = wdc_print_fb_ca_log(perf, fmt);
7578 } else {
7579 fprintf(stderrstderr, "ERROR: WDC: Unable to read CA Log Page data\n");
7580 ret = -1;
7581 }
7582 } else if ((cust_id == WDC_CUSTOMER_ID_GN0x0001) || (cust_id == WDC_CUSTOMER_ID_GD0x0101) ||
7583 (cust_id == WDC_CUSTOMER_ID_BD0x1009)) {
7584 data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7585 if (!data) {
7586 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7587 return -1;
7588 }
7589
7590 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7591 ret = nvme_get_log_simple(hdl,
7592 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7593 data, WDC_BD_CA_LOG_BUF_LEN0xA0);
7594 if (strcmp(format, "json"))
7595 nvme_show_status(ret);
7596
7597 if (!ret) {
7598 /* parse the data */
7599 ret = wdc_print_bd_ca_log(hdl, data, fmt);
7600 } else {
7601 fprintf(stderrstderr, "ERROR: WDC: Unable to read CA Log Page data\n");
7602 ret = -1;
7603 }
7604 } else {
7605 fprintf(stderrstderr, "ERROR: WDC: Unsupported Customer id, id = 0x%x\n", cust_id);
7606 return -1;
7607 }
7608 break;
7609 default:
7610 fprintf(stderrstderr, "ERROR: WDC: Log page 0xCA not supported for this device\n");
7611 return -1;
7612 }
7613
7614 free(data);
7615 return ret;
7616}
7617
7618static int wdc_get_c1_log_page(struct libnvme_global_ctx *ctx,
7619 struct libnvme_transport_handle *hdl, char *format,
7620 uint8_t interval)
7621{
7622 struct wdc_log_page_subpage_header *sph;
7623 struct wdc_ssd_perf_stats *perf;
7624 struct wdc_log_page_header *l;
7625 nvme_print_flags_t fmt;
7626 int total_subpages;
7627 int skip_cnt = 4;
7628 __u8 *data;
7629 __u8 *p;
7630 int i;
7631 int ret;
7632
7633 if (!wdc_check_device(ctx, hdl))
7634 return -1;
7635
7636 ret = validate_output_format(format, &fmt);
7637 if (ret < 0) {
7638 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7639 return ret;
7640 }
7641
7642 if (interval < 1 || interval > 15) {
7643 fprintf(stderrstderr, "ERROR: WDC: interval out of range [1-15]\n");
7644 return -1;
7645 }
7646
7647 data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7648 if (!data) {
7649 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7650 return -1;
7651 }
7652 memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7653
7654 ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE0xC1,
7655 data, WDC_ADD_LOG_BUF_LEN0x4000);
7656 if (strcmp(format, "json"))
7657 nvme_show_status(ret);
7658 if (!ret) {
7659 l = (struct wdc_log_page_header *)data;
7660 total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F - 1;
7661 for (i = 0, p = data + skip_cnt; i < total_subpages; i++, p += skip_cnt) {
7662 sph = (struct wdc_log_page_subpage_header *)p;
7663 if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37) {
7664 if (sph->pcset == interval) {
7665 perf = (struct wdc_ssd_perf_stats *)(p + 4);
7666 ret = wdc_print_log(perf, fmt);
7667 break;
7668 }
7669 }
7670 skip_cnt = le16_to_cpu(sph->subpage_length) + 4;
7671 }
7672 if (ret)
7673 fprintf(stderrstderr, "ERROR: WDC: Unable to read data from buffer\n");
7674 }
7675 free(data);
7676 return ret;
7677}
7678
7679static int wdc_get_c3_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7680{
7681 struct wdc_ssd_latency_monitor_log *log_data;
7682 nvme_print_flags_t fmt;
7683 __u8 *data;
7684 int ret;
7685 int i;
7686
7687 if (!wdc_check_device(ctx, hdl))
7688 return -1;
7689
7690 ret = validate_output_format(format, &fmt);
7691 if (ret < 0) {
7692 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7693 return ret;
7694 }
7695
7696 data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7697 if (!data) {
7698 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7699 return -1;
7700 }
7701 memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7702
7703 ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID0xC3,
7704 data, WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7705
7706 if (strcmp(format, "json"))
7707 fprintf(stderrstderr, "NVMe Status:%s(%x)\n", libnvme_status_to_string(ret, false0), ret);
7708
7709 if (!ret) {
7710 log_data = (struct wdc_ssd_latency_monitor_log *)data;
7711
7712 /* check log page version */
7713 if (log_data->log_page_version != WDC_LATENCY_MON_VERSION0x0001) {
7714 fprintf(stderrstderr, "ERROR: WDC: invalid latency monitor version\n");
7715 ret = -1;
7716 goto out;
7717 }
7718
7719 /* check log page guid */
7720 /* Verify GUID matches */
7721 for (i = 0; i < 16; i++) {
7722 if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) {
7723 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C3 Log Page data\n");
7724 int j;
7725
7726 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
7727 for (j = 0; j < 16; j++)
7728 fprintf(stderrstderr, "%x", wdc_lat_mon_guid[j]);
7729 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
7730 for (j = 0; j < 16; j++)
7731 fprintf(stderrstderr, "%x", log_data->log_page_guid[j]);
7732 fprintf(stderrstderr, "\n");
7733
7734 ret = -1;
7735 goto out;
7736 }
7737 }
7738
7739 /* parse the data */
7740 wdc_print_latency_monitor_log(hdl, log_data, fmt);
7741 } else {
7742 fprintf(stderrstderr, "ERROR: WDC: Unable to read C3 data from buffer\n");
7743 }
7744
7745out:
7746 free(data);
7747 return ret;
7748
7749}
7750
7751static int wdc_get_ocp_c1_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7752{
7753 struct wdc_ocp_c1_error_recovery_log *log_data;
7754 nvme_print_flags_t fmt;
7755 __u8 *data;
7756 int ret;
7757 int i;
7758
7759 if (!wdc_check_device(ctx, hdl))
7760 return -1;
7761
7762 ret = validate_output_format(format, &fmt);
7763 if (ret < 0) {
7764 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7765 return ret;
7766 }
7767
7768 data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7769 if (!data) {
7770 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7771 return -1;
7772 }
7773 memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7774
7775 ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID0xC1,
7776 data, WDC_ERROR_REC_LOG_BUF_LEN512);
7777
7778 if (strcmp(format, "json"))
7779 fprintf(stderrstderr, "NVMe Status:%s(%x)\n", libnvme_status_to_string(ret, false0), ret);
7780
7781 if (!ret) {
7782 log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
7783
7784 /* check log page version */
7785 if ((log_data->log_page_version < 1) ||
7786 (log_data->log_page_version > 3)) {
7787 fprintf(stderrstderr, "ERROR: WDC: invalid error recovery log version - %d\n",
7788 log_data->log_page_version);
7789 ret = -1;
7790 goto out;
7791 }
7792
7793 /* Verify GUID matches */
7794 for (i = 0; i < WDC_OCP_C1_GUID_LENGTH16; i++) {
7795 if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
7796 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C1 Log Page data\n");
7797 int j;
7798
7799 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
7800 for (j = 0; j < 16; j++)
7801 fprintf(stderrstderr, "%x", wdc_ocp_c1_guid[j]);
7802 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
7803 for (j = 0; j < 16; j++)
7804 fprintf(stderrstderr, "%x", log_data->log_page_guid[j]);
7805 fprintf(stderrstderr, "\n");
7806
7807 ret = -1;
7808 goto out;
7809 }
7810 }
7811
7812 /* parse the data */
7813 wdc_print_error_rec_log(log_data, fmt);
7814 } else {
7815 fprintf(stderrstderr, "ERROR: WDC: Unable to read error recovery (C1) data from buffer\n");
7816 }
7817
7818out:
7819 free(data);
7820 return ret;
7821}
7822
7823static int wdc_get_ocp_c4_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7824{
7825 struct wdc_ocp_C4_dev_cap_log *log_data;
7826 nvme_print_flags_t fmt;
7827 __u8 *data;
7828 int ret;
7829 int i;
7830
7831 if (!wdc_check_device(ctx, hdl))
7832 return -1;
7833
7834 ret = validate_output_format(format, &fmt);
7835 if (ret < 0) {
7836 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7837 return ret;
7838 }
7839
7840 data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7841 if (!data) {
7842 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7843 return -1;
7844 }
7845 memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
7846
7847 ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID0xC4,
7848 data, WDC_DEV_CAP_LOG_BUF_LEN4096);
7849
7850 if (strcmp(format, "json"))
7851 fprintf(stderrstderr, "NVMe Status:%s(%x)\n", libnvme_status_to_string(ret, false0), ret);
7852
7853 if (!ret) {
7854 log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
7855
7856 /* check log page version */
7857 if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION0001) {
7858 fprintf(stderrstderr, "ERROR: WDC: invalid device capabilities log version - %d\n", log_data->log_page_version);
7859 ret = -1;
7860 goto out;
7861 }
7862
7863 /* Verify GUID matches */
7864 for (i = 0; i < WDC_OCP_C4_GUID_LENGTH16; i++) {
7865 if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
7866 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C4 Log Page data\n");
7867 int j;
7868
7869 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
7870 for (j = 0; j < 16; j++)
7871 fprintf(stderrstderr, "%x", wdc_ocp_c4_guid[j]);
7872 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
7873 for (j = 0; j < 16; j++)
7874 fprintf(stderrstderr, "%x", log_data->log_page_guid[j]);
7875 fprintf(stderrstderr, "\n");
7876
7877 ret = -1;
7878 goto out;
7879 }
7880 }
7881
7882 /* parse the data */
7883 wdc_print_dev_cap_log(log_data, fmt);
7884 } else {
7885 fprintf(stderrstderr, "ERROR: WDC: Unable to read device capabilities (C4) data from buffer\n");
7886 }
7887
7888out:
7889 free(data);
7890 return ret;
7891}
7892
7893static int wdc_get_ocp_c5_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7894{
7895 struct wdc_ocp_C5_unsupported_reqs *log_data;
7896 nvme_print_flags_t fmt;
7897 int ret;
7898 __u8 *data;
7899 int i;
7900
7901 if (!wdc_check_device(ctx, hdl))
7902 return -1;
7903
7904 ret = validate_output_format(format, &fmt);
7905 if (ret < 0) {
7906 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7907 return ret;
7908 }
7909
7910 data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7911 if (!data) {
7912 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7913 return -1;
7914 }
7915 memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7916
7917 ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID0xC5,
7918 data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
7919
7920 if (strcmp(format, "json"))
7921 fprintf(stderrstderr, "NVMe Status:%s(%x)\n", libnvme_status_to_string(ret, false0), ret);
7922
7923 if (!ret) {
7924 log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
7925
7926 /* check log page version */
7927 if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION0001) {
7928 fprintf(stderrstderr, "ERROR: WDC: invalid 0xC5 log page version\n");
7929 fprintf(stderrstderr, "ERROR: WDC: log page version: %d\n",
7930 log_data->log_page_version);
7931 ret = -1;
7932 goto out;
7933 }
7934
7935 /* Verify GUID matches */
7936 for (i = 0; i < WDC_OCP_C5_GUID_LENGTH16; i++) {
7937 if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
7938 fprintf(stderrstderr, "ERROR: WDC: Unknown GUID in C5 Log Page data\n");
7939 int j;
7940
7941 fprintf(stderrstderr, "ERROR: WDC: Expected GUID: 0x");
7942 for (j = 0; j < 16; j++)
7943 fprintf(stderrstderr, "%x", wdc_ocp_c5_guid[j]);
7944 fprintf(stderrstderr, "\nERROR: WDC: Actual GUID: 0x");
7945 for (j = 0; j < 16; j++)
7946 fprintf(stderrstderr, "%x", log_data->log_page_guid[j]);
7947 fprintf(stderrstderr, "\n");
7948
7949 ret = -1;
7950 goto out;
7951 }
7952 }
7953
7954 /* parse the data */
7955 wdc_print_unsupported_reqs_log(log_data, fmt);
7956 } else {
7957 fprintf(stderrstderr, "ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer\n");
7958 }
7959
7960out:
7961 free(data);
7962 return ret;
7963}
7964
7965static int wdc_get_d0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7966{
7967 struct wdc_ssd_d0_smart_log *perf;
7968 nvme_print_flags_t fmt;
7969 int ret = 0;
7970 __u8 *data;
7971
7972 if (!wdc_check_device(ctx, hdl))
7973 return -1;
7974
7975 ret = validate_output_format(format, &fmt);
7976 if (ret < 0) {
7977 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
7978 return ret;
7979 }
7980
7981 /* verify the 0xD0 log page is supported */
7982 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7983 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == false0) {
7984 fprintf(stderrstderr, "ERROR: WDC: 0xD0 Log Page not supported\n");
7985 return -1;
7986 }
7987
7988 data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7989 if (!data) {
7990 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
7991 return -1;
7992 }
7993 memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
7994
7995 ret = nvme_get_log_simple(hdl,
7996 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0,
7997 data, WDC_NVME_VU_SMART_LOG_LEN0x200);
7998 if (strcmp(format, "json"))
7999 nvme_show_status(ret);
8000
8001 if (!ret) {
8002 /* parse the data */
8003 perf = (struct wdc_ssd_d0_smart_log *)(data);
8004 ret = wdc_print_d0_log(perf, fmt);
8005 } else {
8006 fprintf(stderrstderr, "ERROR: WDC: Unable to read D0 Log Page data\n");
8007 ret = -1;
8008 }
8009
8010 free(data);
8011 return ret;
8012}
8013
8014static long double le_to_float(__u8 *data, int byte_len)
8015{
8016 long double result = 0;
8017 int i;
8018
8019 for (i = 0; i < byte_len; i++) {
8020 result *= 256;
8021 result += data[15 - i];
8022 }
8023
8024 return result;
8025}
8026
8027static void stringify_log_page_guid(__u8 *guid, char *buf)
8028{
8029 char *ptr = buf;
8030 int i;
8031
8032 memset(buf, 0, sizeof(char) * 19);
8033
8034 ptr += sprintf(ptr, "0x");
8035 for (i = 0; i < 16; i++)
8036 ptr += sprintf(ptr, "%x", guid[15 - i]);
8037}
8038
8039static const char *const cloud_smart_log_thermal_status[] = {
8040 [0x00] = "unthrottled",
8041 [0x01] = "first_level",
8042 [0x02] = "second_level",
8043 [0x03] = "third_level",
8044};
8045
8046static const char *stringify_cloud_smart_log_thermal_status(__u8 status)
8047{
8048 if (status < ARRAY_SIZE(cloud_smart_log_thermal_status)(sizeof(cloud_smart_log_thermal_status) / sizeof((cloud_smart_log_thermal_status
)[0]))
&&
8049 cloud_smart_log_thermal_status[status])
8050 return cloud_smart_log_thermal_status[status];
8051 return "unrecognized";
8052}
8053
8054static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log)
8055{
8056 struct json_object *root;
8057 struct json_object *bad_user_nand_blocks;
8058 struct json_object *bad_system_nand_blocks;
8059 struct json_object *e2e_correction_counts;
8060 struct json_object *user_data_erase_counts;
8061 struct json_object *thermal_status;
8062 struct json_object *dssd_specific_ver;
8063 char buf[2 * sizeof(log->log_page_guid) + 3];
8064 char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1];
8065 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8066
8067 bad_user_nand_blocks = json_create_object()json_object_new_object();
8068 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)))
8069 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)))
;
8070 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)))
8071 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)))
;
8072
8073 bad_system_nand_blocks = json_create_object()json_object_new_object();
8074 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)))
8075 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)))
;
8076 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)))
8077 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)))
;
8078
8079 e2e_correction_counts = json_create_object()json_object_new_object();
8080 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)))
8081 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)))
;
8082 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)))
8083 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)))
;
8084
8085 user_data_erase_counts = json_create_object()json_object_new_object();
8086 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)))
8087 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)))
;
8088 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)))
8089 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)))
;
8090
8091 thermal_status = json_create_object()json_object_new_object();
8092 json_object_add_value_string(thermal_status, "current_status",
8093 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8094 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))
8095 log->thermal_status.num_events)json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
;
8096
8097 dssd_specific_ver = json_create_object()json_object_new_object();
8098 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))
8099 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))
;
8100 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)))
8101 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)))
;
8102 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)))
8103 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)))
;
8104 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))
8105 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))
;
8106
8107 root = json_create_object()json_object_new_object();
8108 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)))
8109 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)))
;
8110 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)))
8111 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)))
;
8112 json_object_add_value_object(root, "bad_user_nand_blocks",json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
8113 bad_user_nand_blocks)json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
;
8114 json_object_add_value_object(root, "bad_system_nand_blocks",json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
8115 bad_system_nand_blocks)json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
;
8116 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)))
8117 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)))
;
8118 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
)))
8119 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
)))
;
8120 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)))
8121 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)))
;
8122 json_object_add_value_object(root, "e2e_correction_counts",json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
8123 e2e_correction_counts)json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
;
8124 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))
8125 log->system_data_percent_used)json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
;
8126 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)))
8127 le64_to_cpu(log->refresh_counts))json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
;
8128 json_object_add_value_object(root, "user_data_erase_counts",json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
8129 user_data_erase_counts)json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
;
8130 json_object_add_value_object(root, "thermal_status", thermal_status)json_object_object_add(root, "thermal_status", thermal_status
)
;
8131 if (smart_log_ver >= 3)
8132 json_object_add_value_object(root, "dssd_specific_ver",json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
8133 dssd_specific_ver)json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
;
8134 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)))
8135 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)))
;
8136 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)))
8137 le32_to_cpu(log->incomplete_shutdowns))json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
;
8138 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))
8139 log->percent_free_blocks)json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
;
8140 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)))
8141 le16_to_cpu(log->capacitor_health))json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
;
8142 if (smart_log_ver >= 3) {
8143 if (smart_log_ver >= 4) {
8144 sprintf(buf, "%c", log->nvme_base_errata_ver);
8145 json_object_add_value_string(root, "nvme_base_errata_version", buf);
8146 sprintf(buf, "%c", log->nvme_cmd_set_errata_ver);
8147 json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf);
8148 } else {
8149 sprintf(buf, "%c", log->nvme_base_errata_ver);
8150 json_object_add_value_string(root, "nvme_errata_version", buf);
8151 }
8152 }
8153
8154 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)))
8155 le64_to_cpu(log->unaligned_io))json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
;
8156 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)))
8157 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)))
;
8158 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)))
8159 le64_to_cpu(log->total_nuse))json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
;
8160 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)))
8161 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)))
;
8162 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)))
8163 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)))
;
8164 if (smart_log_ver >= 3) {
8165 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)))
8166 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)))
;
8167 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)))
8168 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)))
;
8169 if (smart_log_ver >= 4) {
8170 snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s",
8171 (int)sizeof(log->lowest_permitted_fw_rev),
8172 log->lowest_permitted_fw_rev);
8173 json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr);
8174 } else
8175 json_object_add_value_uint128(root, "hardware_revision",json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]
)))
8176 le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]))json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0]
)))
;
8177 }
8178 json_object_add_value_uint(root, "log_page_version",json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
8179 smart_log_ver)json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
;
8180 stringify_log_page_guid(log->log_page_guid, buf);
8181 json_object_add_value_string(root, "log_page_guid", buf);
8182
8183 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8184 printf("\n");
8185 json_free_object(root)json_object_put(root);
8186}
8187
8188static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
8189 struct libnvme_transport_handle *hdl)
8190{
8191 char buf[2 * sizeof(log->log_page_guid) + 3];
8192 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8193
8194 printf("SMART Cloud Attributes for NVMe device : %s\n",
8195 libnvme_transport_handle_get_name(hdl));
8196 printf("Physical Media Units Written : %'.0Lf\n",
8197 le_to_float(log->physical_media_units_written, 16));
8198 printf("Physical Media Units Read : %'.0Lf\n",
8199 le_to_float(log->physical_media_units_read, 16));
8200 printf("Bad User NAND Blocks (Normalized) : %" PRIu16"u" "%%\n",
8201 le16_to_cpu(log->bad_user_nand_blocks.normalized));
8202 printf("Bad User NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8203 le64_to_cpu(log->bad_user_nand_blocks.raw));
8204 printf("Bad System NAND Blocks (Normalized) : %" PRIu16"u" "%%\n",
8205 le16_to_cpu(log->bad_system_nand_blocks.normalized));
8206 printf("Bad System NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8207 le64_to_cpu(log->bad_system_nand_blocks.raw));
8208 printf("XOR Recovery Count : %" PRIu64"l" "u" "\n",
8209 le64_to_cpu(log->xor_recovery_count));
8210 printf("Uncorrectable Read Error Count : %" PRIu64"l" "u" "\n",
8211 le64_to_cpu(log->uncorrectable_read_error_count));
8212 printf("Soft ECC Error Count : %" PRIu64"l" "u" "\n",
8213 le64_to_cpu(log->soft_ecc_error_count));
8214 printf("End to End Correction Counts (Corrected) : %" PRIu32"u" "\n",
8215 le32_to_cpu(log->e2e_correction_counts.corrected));
8216 printf("End to End Correction Counts (Detected) : %" PRIu32"u" "\n",
8217 le32_to_cpu(log->e2e_correction_counts.detected));
8218 printf("System Data %% Used : %" PRIu8"u" "%%\n",
8219 log->system_data_percent_used);
8220 printf("Refresh Counts : %" PRIu64"l" "u" "\n",
8221 le64_to_cpu(log->refresh_counts));
8222 printf("User Data Erase Counts (Minimum) : %" PRIu32"u" "\n",
8223 le32_to_cpu(log->user_data_erase_counts.minimum));
8224 printf("User Data Erase Counts (Maximum) : %" PRIu32"u" "\n",
8225 le32_to_cpu(log->user_data_erase_counts.maximum));
8226 printf("Thermal Throttling Status (Current Status) : %s\n",
8227 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8228 printf("Thermal Throttling Status (Number of Events) : %" PRIu8"u" "\n",
8229 log->thermal_status.num_events);
8230 if (smart_log_ver >= 3) {
8231 printf("NVMe Major Version : %" PRIu8"u" "\n",
8232 log->dssd_specific_ver.major_ver);
8233 printf(" Minor Version : %" PRIu16"u" "\n",
8234 le16_to_cpu(log->dssd_specific_ver.minor_ver));
8235 printf(" Point Version : %" PRIu16"u" "\n",
8236 le16_to_cpu(log->dssd_specific_ver.point_ver));
8237 printf(" Errata Version : %" PRIu8"u" "\n",
8238 log->dssd_specific_ver.errata_ver);
8239 }
8240 printf("PCIe Correctable Error Count : %" PRIu64"l" "u" "\n",
8241 le64_to_cpu(log->pcie_correctable_error_count));
8242 printf("Incomplete Shutdowns : %" PRIu32"u" "\n",
8243 le32_to_cpu(log->incomplete_shutdowns));
8244 printf("%% Free Blocks : %" PRIu8"u" "%%\n",
8245 log->percent_free_blocks);
8246 printf("Capacitor Health : %" PRIu16"u" "%%\n",
8247 le16_to_cpu(log->capacitor_health));
8248 if (smart_log_ver >= 3) {
8249 if (smart_log_ver >= 4) {
8250 printf("NVMe Base Errata Version : %c\n",
8251 log->nvme_base_errata_ver);
8252 printf("NVMe Command Set Errata Version : %c\n",
8253 log->nvme_cmd_set_errata_ver);
8254 } else {
8255 printf("NVMe Errata Version : %c\n",
8256 log->nvme_base_errata_ver);
8257 }
8258 }
8259 printf("Unaligned IO : %" PRIu64"l" "u" "\n",
8260 le64_to_cpu(log->unaligned_io));
8261 printf("Security Version Number : %" PRIu64"l" "u" "\n",
8262 le64_to_cpu(log->security_version_number));
8263 printf("Total NUSE : %" PRIu64"l" "u" "\n",
8264 le64_to_cpu(log->total_nuse));
8265 printf("PLP Start Count : %'.0Lf\n",
8266 le_to_float(log->plp_start_count, 16));
8267 printf("Endurance Estimate : %'.0Lf\n",
8268 le_to_float(log->endurance_estimate, 16));
8269 if (smart_log_ver >= 3) {
8270 printf("PCIe Link Retraining Count : %" PRIu64"l" "u" "\n",
8271 le64_to_cpu(log->pcie_link_retraining_cnt));
8272 printf("Power State Change Count : %" PRIu64"l" "u" "\n",
8273 le64_to_cpu(log->power_state_change_cnt));
8274 if (smart_log_ver >= 4)
8275 printf("Lowest Permitted FW Revision : %-.*s\n",
8276 (int)sizeof(log->lowest_permitted_fw_rev),
8277 log->lowest_permitted_fw_rev);
8278 else
8279 printf("Hardware Revision : %s\n",
8280 uint128_t_to_string(le128_to_cpu(
8281 (__u8 *)&log->lowest_permitted_fw_rev[0])));
8282 }
8283 printf("Log Page Version : %" PRIu16"u" "\n",
8284 smart_log_ver);
8285 stringify_log_page_guid(log->log_page_guid, buf);
8286 printf("Log Page GUID : %s\n", buf);
8287 printf("\n\n");
8288}
8289
8290static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd,
8291 struct plugin *plugin)
8292{
8293 const char *desc = "Retrieve additional performance statistics.";
8294 const char *interval = "Interval to read the statistics from [1, 15].";
8295 const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
8296 const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
8297 const char *namespace_id = "desired namespace id";
8298 nvme_print_flags_t fmt;
8299 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8300 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8301 int ret = 0;
8302 int uuid_index = 0;
8303 int page_mask = 0, num, i;
8304 int log_page_list[16];
8305 __u64 capabilities = 0;
8306 __u32 device_id, read_vendor_id;
8307
8308 struct config {
8309 uint8_t interval;
8310 __u8 log_page_version;
8311 char *log_page_mask;
8312 __u32 namespace_id;
8313 };
8314
8315 struct config cfg = {
8316 .interval = 14,
8317 .log_page_version = 0,
8318 .log_page_mask = "",
8319 .namespace_id = NVME_NSID_ALL,
8320 };
8321
8322 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8323 OPT_UINT("interval", 'i', &cfg.interval, interval),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8324 OPT_BYTE("log-page-version", 'l', &cfg.log_page_version, log_page_version),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8325 OPT_LIST("log-page-mask", 'p', &cfg.log_page_mask, log_page_mask),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8326 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
8327
8328 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8329 if (ret)
8330 return ret;
8331
8332 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8333 if (ret)
8334 return ret;
8335
8336 if (!cfg.log_page_version) {
8337 uuid_index = 0;
8338 } else if (cfg.log_page_version == 1) {
8339 uuid_index = 1;
8340 } else {
8341 fprintf(stderrstderr, "ERROR: WDC: unsupported log page version for this command\n");
8342 ret = -1;
8343 goto out;
8344 }
8345
8346 num = argconfig_parse_comma_sep_array(cfg.log_page_mask, log_page_list, 16);
8347
8348 if (num == -1) {
8349 fprintf(stderrstderr, "ERROR: WDC: log page list is malformed\n");
8350 ret = -1;
8351 goto out;
8352 }
8353
8354 if (!num) {
8355 page_mask |= WDC_ALL_PAGE_MASK0xFFFF;
8356 } else {
8357 for (i = 0; i < num; i++) {
8358 if (log_page_list[i] == 0xc0)
8359 page_mask |= WDC_C0_PAGE_MASK0x0001;
8360 if (log_page_list[i] == 0xc1)
8361 page_mask |= WDC_C1_PAGE_MASK0x0002;
8362 if (log_page_list[i] == 0xca)
8363 page_mask |= WDC_CA_PAGE_MASK0x0004;
8364 if (log_page_list[i] == 0xd0)
8365 page_mask |= WDC_D0_PAGE_MASK0x0008;
8366 }
8367 }
8368
8369 if (!page_mask)
8370 fprintf(stderrstderr, "ERROR: WDC: Unknown log page mask - %s\n", cfg.log_page_mask);
8371
8372 ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id);
8373
8374 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8375 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8376 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8377 ret = -1;
8378 goto out;
8379 }
8380
8381 if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) == WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) &&
8382 (page_mask & WDC_C0_PAGE_MASK0x0001)) {
8383 /* Get 0xC0 log page if possible. */
8384 if (!wdc_is_sn861(device_id)) {
8385 ret = wdc_get_c0_log_page(ctx, hdl,
8386 nvme_args.output_format,
8387 uuid_index, cfg.namespace_id);
8388 if (ret)
8389 fprintf(stderrstderr,
8390 "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n",
8391 ret);
8392 } else {
8393 ret = validate_output_format(nvme_args.output_format,
8394 &fmt);
8395 if (ret < 0) {
8396 fprintf(stderrstderr, "Invalid output format: %s\n",
8397 nvme_args.output_format);
8398 goto out;
8399 }
8400
8401 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
8402 0,
8403 NVME_NSID_ALL,
8404 fmt);
8405 }
8406 }
8407 if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) == (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) &&
8408 (page_mask & WDC_CA_PAGE_MASK0x0004) &&
8409 (!wdc_is_sn861(device_id))) {
8410 /* Get the CA Log Page */
8411 ret = wdc_get_ca_log_page(ctx, hdl, nvme_args.output_format);
8412 if (ret)
8413 fprintf(stderrstderr, "ERROR: WDC: Failure reading the CA Log Page, ret = %d\n", ret);
8414 }
8415 if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) == WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) &&
8416 (page_mask & WDC_C1_PAGE_MASK0x0002)) {
8417 /* Get the C1 Log Page */
8418 ret = wdc_get_c1_log_page(ctx, hdl, nvme_args.output_format,
8419 cfg.interval);
8420 if (ret)
8421 fprintf(stderrstderr, "ERROR: WDC: Failure reading the C1 Log Page, ret = %d\n", ret);
8422 }
8423 if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) == WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) &&
8424 (page_mask & WDC_D0_PAGE_MASK0x0008)) {
8425 /* Get the D0 Log Page */
8426 ret = wdc_get_d0_log_page(ctx, hdl, nvme_args.output_format);
8427 if (ret)
8428 fprintf(stderrstderr, "ERROR: WDC: Failure reading the D0 Log Page, ret = %d\n", ret);
8429 }
8430
8431out:
8432 return ret;
8433}
8434
8435static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd,
8436 struct plugin *plugin)
8437{
8438 const char *desc = "Retrieve customer unique smart log statistics.";
8439 const char *uuid_index = "The uuid index to select the correct log page implementation.";
8440 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8441 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8442 struct libnvme_passthru_cmd cmd;
8443 int ret = 0;
8444 __u64 capabilities = 0;
8445 uint32_t read_device_id, read_vendor_id;
8446 nvme_print_flags_t fmt;
8447 __u8 *data;
8448
8449 struct config {
8450 int uuid_index;
8451 };
8452
8453 struct config cfg = {
8454 .uuid_index = 0,
8455 };
8456
8457 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8458 OPT_UINT("uuid-index", 'u', &cfg.uuid_index, uuid_index))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
8459
8460 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8461 if (ret)
8462 return ret;
8463
8464 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8465 if (ret)
8466 return ret;
8467
8468 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8469 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8470 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8471 ret = -1;
8472 goto out;
8473 }
8474
8475 if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) == WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) {
8476 if (!wdc_check_device(ctx, hdl))
8477 return -1;
8478
8479 ret = validate_output_format(nvme_args.output_format, &fmt);
8480
8481 if (ret < 0) {
8482 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
8483 return ret;
8484 }
8485
8486 /* verify the 0xCA log page is supported */
8487 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8488 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
8489 fprintf(stderrstderr, "ERROR: WDC: 0xCA Log Page not supported\n");
8490 return -1;
8491 }
8492
8493 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
8494
8495 switch (read_device_id) {
8496 case WDC_NVME_SN861_DEV_ID0x2750:
8497 case WDC_NVME_SN861_DEV_ID_10x2751:
8498 data = (__u8 *)malloc(WDC_BD_CA_LOG_BUF_LEN0xA0);
8499 if (!data) {
8500 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
8501 ret = -1;
8502 break;
8503 }
8504
8505 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
8506
8507 /* Get the CA Log Page */
8508 nvme_init_get_log(&cmd, NVME_NSID_ALL,
8509 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0,
8510 NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN0xA0);
8511 cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8512 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8513 NVME_LOG_CDW14_UUID_MASK)(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
8514 ret = libnvme_get_log(hdl, &cmd, false0,
8515 NVME_LOG_PAGE_PDU_SIZE4096);
8516
8517 if (strcmp(nvme_args.output_format, "json"))
8518 nvme_show_status(ret);
8519
8520 if (!ret) {
8521 /* parse the data */
8522 ret = wdc_print_bd_ca_log(hdl, data, fmt);
8523 } else {
8524 fprintf(stderrstderr, "ERROR: WDC: Unable to read CA Log Page data\n");
8525 ret = -1;
8526 }
8527
8528 free(data);
8529 break;
8530 default:
8531 fprintf(stderrstderr, "ERROR: WDC: Command not supported on this device\n");
8532 ret = -1;
8533 }
8534 } else {
8535 fprintf(stderrstderr, "ERROR: WDC: CA log page supported on this device\n");
8536 ret = -1;
8537 }
8538
8539out:
8540 return ret;
8541}
8542
8543static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd,
8544 struct plugin *plugin)
8545{
8546 const char *desc = "Retrieve Cloud Log Smart/Health Information";
8547 const char *namespace_id = "desired namespace id";
8548 nvme_print_flags_t fmt;
8549 __u64 capabilities = 0;
8550 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8551 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8552 int ret;
8553 __u8 *data;
8554
8555 struct config {
8556 char *output_format;
8557 __u32 namespace_id;
8558 };
8559
8560 struct config cfg = {
8561 .output_format = "normal",
8562 .namespace_id = NVME_NSID_ALL,
8563 };
8564
8565 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8566 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
8567
8568 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8569 if (ret)
8570 return ret;
8571
8572 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8573 if (ret)
8574 return ret;
8575
8576 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8577
8578 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
8579 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8580 ret = -1;
8581 goto out;
8582 }
8583
8584 data = NULL((void*)0);
8585 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8586 cfg.namespace_id);
8587
8588 if (strcmp(cfg.output_format, "json"))
8589 nvme_show_status(ret);
8590
8591 if (!ret) {
8592 ret = validate_output_format(cfg.output_format, &fmt);
8593 if (ret < 0) {
8594 fprintf(stderrstderr, "ERROR: WDC %s: invalid output format\n", __func__);
8595 } else {
8596 /* parse the data */
8597 wdc_print_ext_smart_cloud_log(data, fmt);
8598 }
8599 } else {
8600 fprintf(stderrstderr, "ERROR: WDC: Unable to read C0 Log Page V1 data\n");
8601 ret = -1;
8602 }
8603
8604 free(data);
8605
8606out:
8607 return ret;
8608}
8609
8610static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd,
8611 struct plugin *plugin)
8612{
8613 const char *desc = "Retrieve Hardware Revision Log Information";
8614 const char *namespace_id = "desired namespace id";
8615 nvme_print_flags_t fmt;
8616 __u64 capabilities = 0;
8617 struct libnvme_transport_handle *hdl;
8618 int ret;
8619 __u8 *data = NULL((void*)0);
8620 struct libnvme_global_ctx *ctx;
8621
8622 struct config {
8623 char *output_format;
8624 __u32 namespace_id;
8625 };
8626
8627 struct config cfg = {
8628 .output_format = "normal",
8629 .namespace_id = NVME_NSID_ALL,
8630 };
8631
8632 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8633 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
8634
8635 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8636 if (ret)
8637 return ret;
8638
8639 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8640 if (ret)
8641 return ret;
8642
8643 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8644
8645 if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000)) {
8646 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8647 ret = -1;
8648 goto out;
8649 }
8650
8651 ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id);
8652
8653 if (strcmp(cfg.output_format, "json"))
8654 nvme_show_status(ret);
8655
8656 if (!ret) {
8657 ret = validate_output_format(cfg.output_format, &fmt);
8658 if (ret < 0) {
8659 fprintf(stderrstderr, "ERROR: WDC %s: invalid output format\n", __func__);
8660 goto free_buf;
8661 }
8662
8663 if (!data) {
8664 fprintf(stderrstderr, "ERROR: WDC: Invalid buffer to read Hardware Revision log\n");
8665 ret = -1;
8666 goto out;
8667 }
8668 switch (fmt) {
8669 case NORMAL:
8670 wdc_print_hw_rev_log_normal(data);
8671 break;
8672 case JSON:
8673 wdc_print_hw_rev_log_json(data);
8674 break;
8675 default:
8676 break;
8677 }
8678 } else {
8679 fprintf(stderrstderr, "ERROR: WDC: Unable to read Hardware Revision Log Page data\n");
8680 ret = -1;
8681 }
8682
8683free_buf:
8684 free(data);
8685
8686out:
8687 return ret;
8688}
8689
8690static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd,
8691 struct plugin *plugin)
8692{
8693 const char *desc = "Retrieve Device Write Amplication Factor";
8694 const char *namespace_id = "desired namespace id";
8695 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8696 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8697 struct nvme_smart_log smart_log;
8698 nvme_print_flags_t fmt;
8699 __u8 *data;
8700 int ret = 0;
8701 __u64 capabilities = 0;
8702 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr;
8703 long double data_units_written = 0,
8704 phys_media_units_written_tlc = 0,
8705 phys_media_units_written_slc = 0;
8706 struct json_object *root = NULL((void*)0);
8707 char tlc_waf_str[32] = { 0 },
8708 slc_waf_str[32] = { 0 };
8709
8710 struct config {
8711 char *output_format;
8712 __u32 namespace_id;
8713 };
8714
8715 struct config cfg = {
8716 .output_format = "normal",
8717 .namespace_id = NVME_NSID_ALL,
8718 };
8719
8720 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
8721 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
8722
8723 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8724 if (ret)
8725 return ret;
8726
8727 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8728 if (ret)
8729 return ret;
8730
8731 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8732
8733 if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000)) {
8734 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8735 ret = -1;
8736 goto out;
8737 }
8738
8739 /* get data units written from the smart log page */
8740 ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log);
8741 if (!ret) {
8742 data_units_written = int128_to_double(smart_log.data_units_written);
8743 } else if (ret > 0) {
8744 nvme_show_status(ret);
8745 ret = -1;
8746 goto out;
8747 } else {
8748 fprintf(stderrstderr, "smart log: %s\n", libnvme_strerror(errno(*__errno_location ())));
8749 ret = -1;
8750 goto out;
8751 }
8752
8753 /* get Physical Media Units Written from extended smart/C0 log page */
8754 data = NULL((void*)0);
8755 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8756 cfg.namespace_id);
8757
8758 if (!ret) {
8759 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
8760 phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
8761 phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
8762
8763 free(data);
8764 } else {
8765 fprintf(stderrstderr, "ERROR: WDC %s: get smart cloud log failure\n", __func__);
8766 ret = -1;
8767 goto out;
8768 }
8769
8770 if (strcmp(cfg.output_format, "json"))
8771 nvme_show_status(ret);
8772
8773 ret = validate_output_format(cfg.output_format, &fmt);
8774 if (ret < 0) {
8775 fprintf(stderrstderr, "ERROR: WDC %s: invalid output format\n", __func__);
8776 goto out;
8777 }
8778
8779 if (!data_units_written) {
8780 fprintf(stderrstderr, "ERROR: WDC %s: 0 data units written\n", __func__);
8781 ret = -1;
8782 goto out;
8783 }
8784
8785 if (fmt == NORMAL) {
8786 printf("Device Write Amplification Factor TLC : %4.2Lf\n",
8787 (phys_media_units_written_tlc/data_units_written));
8788 printf("Device Write Amplification Factor SLC : %4.2Lf\n",
8789 (phys_media_units_written_slc/data_units_written));
8790 } else if (fmt == JSON) {
8791 root = json_create_object()json_object_new_object();
8792 sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written));
8793 sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written));
8794
8795 json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
8796 json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
8797
8798 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8799 printf("\n");
8800
8801 json_free_object(root)json_object_put(root);
8802 }
8803
8804out:
8805 return ret;
8806}
8807
8808static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd,
8809 struct plugin *plugin)
8810{
8811 const char *desc = "Retrieve latency monitor log data.";
8812 __u64 capabilities = 0;
8813 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8814 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8815 int ret = 0;
8816
8817 struct config {
8818 char *output_format;
8819 };
8820
8821 struct config cfg = {
8822 .output_format = "normal",
8823 };
8824
8825 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
8826
8827 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8828 if (ret)
8829 return ret;
8830
8831 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8832 if (ret)
8833 return ret;
8834 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8835
8836 if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000)) {
8837 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8838 ret = -1;
8839 goto out;
8840 }
8841
8842 ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format);
8843 if (ret)
8844 fprintf(stderrstderr, "ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret);
8845
8846out:
8847 return ret;
8848}
8849
8850static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd,
8851 struct plugin *plugin)
8852{
8853 const char *desc = "Retrieve error recovery log data.";
8854 __u64 capabilities = 0;
8855 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8856 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8857 int ret = 0;
8858
8859 struct config {
8860 char *output_format;
8861 };
8862
8863 struct config cfg = {
8864 .output_format = "normal",
8865 };
8866
8867 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
8868
8869 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8870 if (ret)
8871 return ret;
8872
8873 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8874 if (ret)
8875 return ret;
8876
8877 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8878
8879 if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000)) {
8880 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8881 ret = -1;
8882 goto out;
8883 }
8884
8885 ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format);
8886 if (ret)
8887 fprintf(stderrstderr, "ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret);
8888
8889out:
8890 return ret;
8891}
8892
8893static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd,
8894 struct plugin *plugin)
8895{
8896 const char *desc = "Retrieve device capabilities log data.";
8897 __u64 capabilities = 0;
8898 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8899 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8900 int ret = 0;
8901
8902 struct config {
8903 char *output_format;
8904 };
8905
8906 struct config cfg = {
8907 .output_format = "normal",
8908 };
8909
8910 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
8911
8912 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8913 if (ret)
8914 return ret;
8915
8916 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8917 if (ret)
8918 return ret;
8919
8920 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8921
8922 if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000)) {
8923 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8924 ret = -1;
8925 goto out;
8926 }
8927
8928 ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format);
8929 if (ret)
8930 fprintf(stderrstderr, "ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret);
8931
8932out:
8933 return ret;
8934}
8935
8936static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd,
8937 struct plugin *plugin)
8938{
8939 const char *desc = "Retrieve unsupported requirements log data.";
8940 __u64 capabilities = 0;
8941 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8942 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8943 int ret = 0;
8944
8945 struct config {
8946 char *output_format;
8947 };
8948
8949 struct config cfg = {
8950 .output_format = "normal",
8951 };
8952
8953 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
8954
8955 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8956 if (ret)
8957 return ret;
8958
8959 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8960 if (ret)
8961 return ret;
8962
8963 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8964
8965 if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000)) {
8966 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
8967 ret = -1;
8968 goto out;
8969 }
8970
8971 ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format);
8972 if (ret)
8973 fprintf(stderrstderr, "ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret);
8974
8975out:
8976 return ret;
8977}
8978
8979static int wdc_do_clear_pcie_correctable_errors(struct libnvme_transport_handle *hdl)
8980{
8981 int ret;
8982 struct libnvme_passthru_cmd admin_cmd;
8983
8984 memset(&admin_cmd, 0, sizeof(admin_cmd));
8985 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6;
8986 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
8987 WDC_NVME_CLEAR_PCIE_CORR_CMD0x22);
8988
8989 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
8990 nvme_show_status(ret);
8991 return ret;
8992}
8993
8994static int wdc_do_clear_pcie_correctable_errors_vuc(struct libnvme_transport_handle *hdl)
8995{
8996 int ret;
8997 struct libnvme_passthru_cmd admin_cmd;
8998
8999 memset(&admin_cmd, 0, sizeof(admin_cmd));
9000 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2;
9001
9002 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9003 nvme_show_status(ret);
9004 return ret;
9005}
9006
9007static int wdc_do_clear_pcie_correctable_errors_fid(struct libnvme_transport_handle *hdl)
9008{
9009 int ret;
9010 __u64 result;
9011 __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
9012
9013 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3, false0,
9014 value, &result);
9015
9016 nvme_show_status(ret);
9017 return ret;
9018}
9019
9020static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
9021 struct plugin *plugin)
9022{
9023 const char *desc = "Clear PCIE Correctable Errors.";
9024 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9025 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9026 __u64 capabilities = 0;
9027 int ret;
9028
9029 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
9030
9031 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9032 if (ret)
9033 return ret;
9034
9035 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9036 if (ret || !wdc_check_device(ctx, hdl))
9037 return -1;
9038
9039 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9040 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
)) {
9041 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9042 ret = -1;
9043 goto out;
9044 }
9045
9046 if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080)
9047 ret = wdc_do_clear_pcie_correctable_errors(hdl);
9048 else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000)
9049 ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl);
9050 else
9051 ret = wdc_do_clear_pcie_correctable_errors_fid(hdl);
9052
9053out:
9054 return ret;
9055}
9056
9057static int wdc_drive_status(int argc, char **argv, struct command *acmd,
9058 struct plugin *plugin)
9059{
9060 const char *desc = "Get Drive Status.";
9061 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9062 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9063 int ret = 0;
9064 int uuid_index;
9065 void *dev_mng_log = NULL((void*)0);
9066 __u32 system_eol_state;
9067 __u32 user_eol_state;
9068 __u32 format_corrupt_reason = 0xFFFFFFFF;
9069 __u32 eol_status;
9070 __u32 assert_status = 0xFFFFFFFF;
9071 __u32 thermal_status = 0xFFFFFFFF;
9072 __u64 capabilities = 0;
9073 struct nvme_id_uuid_list uuid_list;
9074
9075 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
9076
9077 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9078 if (ret)
9079 return ret;
9080
9081 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9082 if (ret)
9083 return ret;
9084
9085 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9086
9087 if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) != WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) {
9088 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9089 ret = -1;
9090 goto out;
9091 }
9092
9093 uuid_index = 0;
9094
9095 /* Find the WDC UUID index */
9096 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
9097 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
9098 /* check for the Sandisk UUID first */
9099 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
9100
9101 if (uuid_index < 0)
9102 /* The Sandisk UUID is not found;
9103 * check for the WDC UUID second.
9104 */
9105 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
9106 }
9107
9108 /* WD UUID not found, use default uuid index - 0 */
9109 if (uuid_index < 0)
9110 uuid_index = 0;
9111
9112 /* verify the 0xC2 Device Manageability log page is supported */
9113 if (wdc_nvme_check_supported_log_page(ctx, hdl,
9114 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
9115 uuid_index) == false0) {
9116 fprintf(stderrstderr, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d\n",
9117 uuid_index);
9118 ret = -1;
9119 goto out;
9120 }
9121
9122 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
9123 fprintf(stderrstderr, "ERROR: WDC: 0xC2 Log Page not found\n");
9124 ret = -1;
9125 goto out;
9126 }
9127
9128 /* Get the assert dump present status */
9129 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &assert_status,
9130 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19))
9131 fprintf(stderrstderr, "ERROR: WDC: Get Assert Status Failed\n");
9132
9133 /* Get the thermal throttling status */
9134 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &thermal_status,
9135 WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18))
9136 fprintf(stderrstderr, "ERROR: WDC: Get Thermal Throttling Status Failed\n");
9137
9138 /* Get EOL status */
9139 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &eol_status,
9140 WDC_C2_USER_EOL_STATUS_ID0x1A)) {
9141 fprintf(stderrstderr, "ERROR: WDC: Get User EOL Status Failed\n");
9142 eol_status = cpu_to_le32(-1);
9143 }
9144
9145 /* Get Customer EOL state */
9146 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &user_eol_state,
9147 WDC_C2_USER_EOL_STATE_ID0x1C))
9148 fprintf(stderrstderr, "ERROR: WDC: Get User EOL State Failed\n");
9149
9150 /* Get System EOL state*/
9151 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &system_eol_state,
9152 WDC_C2_SYSTEM_EOL_STATE_ID0x1D))
9153 fprintf(stderrstderr, "ERROR: WDC: Get System EOL State Failed\n");
9154
9155 /* Get format corrupt reason*/
9156 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &format_corrupt_reason,
9157 WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E))
9158 fprintf(stderrstderr, "ERROR: WDC: Get Format Corrupt Reason Failed\n");
9159
9160 printf(" Drive Status :-\n");
9161 if ((int)le32_to_cpu(eol_status) >= 0)
9162 printf(" Percent Used: %"PRIu32"u""%%\n",
9163 le32_to_cpu(eol_status));
9164 else
9165 printf(" Percent Used: Unknown\n");
9166 if (system_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) && user_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000))
9167 printf(" Drive Life Status: Normal\n");
9168 else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) ||
9169 user_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001))
9170 printf(" Drive Life Status: End Of Life\n");
9171 else if (system_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) ||
9172 user_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002))
9173 printf(" Drive Life Status: Read Only\n");
9174 else
9175 printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n",
9176 le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state));
9177
9178 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001))
9179 printf(" Assert Dump Status: Present\n");
9180 else if (assert_status == WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000))
9181 printf(" Assert Dump Status: Not Present\n");
9182 else
9183 printf(" Assert Dump Status: Unknown : 0x%08x\n", le32_to_cpu(assert_status));
9184
9185 if (thermal_status == WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000))
9186 printf(" Thermal Throttling Status: Off\n");
9187 else if (thermal_status == WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001))
9188 printf(" Thermal Throttling Status: On\n");
9189 else if (thermal_status == WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002))
9190 printf(" Thermal Throttling Status: Unavailable\n");
9191 else
9192 printf(" Thermal Throttling Status: Unknown : 0x%08x\n", le32_to_cpu(thermal_status));
9193
9194 if (format_corrupt_reason == WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000))
9195 printf(" Format Corrupt Reason: Format Not Corrupted\n");
9196 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001))
9197 printf(" Format Corrupt Reason: Format Corrupt due to FW Assert\n");
9198 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF))
9199 printf(" Format Corrupt Reason: Format Corrupt for Unknown Reason\n");
9200 else
9201 printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
9202
9203 free(dev_mng_log);
9204out:
9205 return ret;
9206}
9207
9208static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
9209 struct plugin *plugin)
9210{
9211 const char *desc = "Clear Assert Dump Present Status.";
9212 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9213 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9214 int ret = -1;
9215 __le32 assert_status = cpu_to_le32(0xFFFFFFFF);
9216 __u64 capabilities = 0;
9217 struct libnvme_passthru_cmd admin_cmd;
9218
9219 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
9220
9221 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9222 if (ret)
9223 return ret;
9224
9225 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9226 if (ret)
9227 return ret;
9228
9229 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9230
9231 if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) != WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) {
9232 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9233 ret = -1;
9234 goto out;
9235 }
9236 if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status,
9237 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19)) {
9238 fprintf(stderrstderr, "ERROR: WDC: Get Assert Status Failed\n");
9239 ret = -1;
9240 goto out;
9241 }
9242
9243 /* Get the assert dump present status */
9244 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001)) {
9245 memset(&admin_cmd, 0, sizeof(admin_cmd));
9246 admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8;
9247 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9248 WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03);
9249
9250 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9251 nvme_show_status(ret);
9252 } else
9253 fprintf(stderrstderr, "INFO: WDC: No Assert Dump Present\n");
9254
9255out:
9256 return ret;
9257}
9258
9259static int wdc_get_fw_act_history(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9260 char *format)
9261{
9262 struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
9263 nvme_print_flags_t fmt;
9264 int ret;
9265 __u8 *data;
9266
9267 if (!wdc_check_device(ctx, hdl))
9268 return -1;
9269
9270 ret = validate_output_format(format, &fmt);
9271 if (ret < 0) {
9272 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
9273 return ret;
9274 }
9275
9276 /* verify the FW Activate History log page is supported */
9277 if (!wdc_nvme_check_supported_log_page(ctx, hdl,
9278 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) {
9279 fprintf(stderrstderr, "ERROR: WDC: %d Log Page not supported\n",
9280 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB);
9281 return -1;
9282 }
9283
9284 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9285 if (!data) {
9286 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
9287 return -1;
9288 }
9289
9290 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9291
9292 ret = nvme_get_log_simple(hdl,
9293 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB,
9294 data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9295
9296 if (strcmp(format, "json"))
9297 nvme_show_status(ret);
9298
9299 if (!ret) {
9300 /* parse the data */
9301 fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data);
9302
9303 if ((fw_act_history_hdr->num_entries > 0) &&
9304 (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES20)) {
9305 ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries,
9306 fmt, 0, 0, 0);
9307 } else if (!fw_act_history_hdr->num_entries) {
9308 fprintf(stderrstderr, "INFO: WDC: No FW Activate History entries found.\n");
9309 ret = 0;
9310 } else {
9311 fprintf(stderrstderr,
9312 "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n",
9313 fw_act_history_hdr->num_entries);
9314 ret = -1;
9315 }
9316 } else {
9317 fprintf(stderrstderr, "ERROR: WDC: Unable to read FW Activate History Log Page data\n");
9318 ret = -1;
9319 }
9320
9321 free(data);
9322 return ret;
9323}
9324
9325static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
9326{
9327
9328 __u32 cust_id = WDC_INVALID_CUSTOMER_ID-1;
9329 __u32 *cust_id_ptr = NULL((void*)0);
9330
9331 if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID0x15, (void *)&cust_id_ptr))
9332 fprintf(stderrstderr, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",
9333 __func__, WDC_C2_CUSTOMER_ID_ID0x15);
9334 else
9335 cust_id = *cust_id_ptr;
9336
9337 free(cust_id_ptr);
9338 return cust_id;
9339}
9340
9341static int wdc_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9342 char *format)
9343{
9344 struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
9345 __u32 tot_entries = 0, num_entries = 0;
9346 __u32 vendor_id = 0, device_id = 0;
9347 __u32 cust_id = 0;
9348 nvme_print_flags_t fmt;
9349 __u8 *data;
9350 int ret;
9351 bool_Bool c2GuidMatch = false0;
9352
9353 if (!wdc_check_device(ctx, hdl))
9354 return -1;
9355
9356 ret = validate_output_format(format, &fmt);
9357 if (ret < 0) {
9358 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
9359 return ret;
9360 }
9361
9362 ret = wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id);
9363
9364 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9365 if (!data) {
9366 fprintf(stderrstderr, "ERROR: WDC: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
9367 return -1;
9368 }
9369
9370 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9371
9372 ret = nvme_get_log_simple(hdl,
9373 WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
9374 data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9375
9376 if (strcmp(format, "json"))
9377 nvme_show_status(ret);
9378
9379 if (!ret) {
9380 /* Get the log page data and verify the GUID */
9381 fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data);
9382
9383 c2GuidMatch = !memcmp(ocp_C2_guid,
9384 fw_act_history_log->log_page_guid,
9385 WDC_C2_GUID_LENGTH16);
9386
9387 if (c2GuidMatch) {
9388 /* parse the data */
9389 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
9390
9391 if (tot_entries > 0) {
9392 /* get the FW customer id */
9393 if (!wdc_is_sn861(device_id)) {
9394 cust_id = wdc_get_fw_cust_id(ctx, hdl);
9395 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
9396 fprintf(stderrstderr,
9397 "%s: ERROR: WDC: invalid customer id\n",
9398 __func__);
9399 ret = -1;
9400 goto freeData;
9401 }
9402 }
9403 num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES20) ?
9404 tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES20;
9405 ret = wdc_print_fw_act_history_log(data, num_entries,
9406 fmt, cust_id, vendor_id, device_id);
9407 } else {
9408 fprintf(stderrstderr, "INFO: WDC: No entries found.\n");
9409 ret = 0;
9410 }
9411 } else {
9412 fprintf(stderrstderr, "ERROR: WDC: Invalid C2 log page GUID\n");
9413 ret = -1;
9414 }
9415 } else {
9416 fprintf(stderrstderr, "ERROR: WDC: Unable to read FW Activate History Log Page data\n");
9417 ret = -1;
9418 }
9419
9420freeData:
9421 free(data);
9422 return ret;
9423}
9424
9425static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd,
9426 struct plugin *plugin)
9427{
9428 const char *desc = "Retrieve FW activate history table.";
9429 __u64 capabilities = 0;
9430 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9431 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9432 int ret = -1;
9433
9434 struct config {
9435 char *output_format;
9436 };
9437
9438 struct config cfg = {
9439 .output_format = "normal",
9440 };
9441
9442 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
9443
9444 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9445 if (ret)
9446 return ret;
9447
9448 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9449 if (ret)
9450 return ret;
9451
9452 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9453
9454 if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000))) {
9455 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9456 ret = -1;
9457 goto out;
9458 }
9459
9460 if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000) {
9461 __u32 cust_fw_id = 0;
9462 /* get the FW customer id */
9463 cust_fw_id = wdc_get_fw_cust_id(ctx, hdl);
9464 if (cust_fw_id == WDC_INVALID_CUSTOMER_ID-1) {
9465 fprintf(stderrstderr, "%s: ERROR: WDC: invalid customer id\n", __func__);
9466 ret = -1;
9467 goto out;
9468 }
9469
9470 if ((cust_fw_id == WDC_CUSTOMER_ID_0x10040x1004) ||
9471 (cust_fw_id == WDC_CUSTOMER_ID_0x10080x1008) ||
9472 (cust_fw_id == WDC_CUSTOMER_ID_0x10050x1005) ||
9473 (cust_fw_id == WDC_CUSTOMER_ID_0x13040x1304))
9474 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9475 else
9476 ret = wdc_get_fw_act_history(ctx, hdl, cfg.output_format);
9477 } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
9478 ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
9479 }
9480
9481 if (ret)
9482 fprintf(stderrstderr, "ERROR: WDC: Failure reading the FW Activate History, ret = %d\n", ret);
9483out:
9484 return ret;
9485}
9486
9487static int wdc_do_clear_fw_activate_history_vuc(struct libnvme_transport_handle *hdl)
9488{
9489 int ret = -1;
9490 struct libnvme_passthru_cmd admin_cmd;
9491
9492 memset(&admin_cmd, 0, sizeof(admin_cmd));
9493 admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6;
9494 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9495 WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23);
9496
9497 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9498 nvme_show_status(ret);
9499
9500 return ret;
9501}
9502
9503static int wdc_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
9504{
9505 int ret = -1;
9506 __u64 result;
9507 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
9508
9509 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, false0,
9510 value, &result);
9511
9512 nvme_show_status(ret);
9513 return ret;
9514}
9515
9516static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd,
9517 struct plugin *plugin)
9518{
9519 const char *desc = "Clear FW activate history table.";
9520 __u64 capabilities = 0;
9521 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9522 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9523 int ret;
9524
9525 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
9526
9527 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9528 if (ret)
9529 return ret;
9530
9531 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9532 if (ret)
9533 return ret;
9534
9535 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9536
9537 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000))) {
9538 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9539 ret = -1;
9540 goto out;
9541 }
9542
9543 if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000)
9544 ret = wdc_do_clear_fw_activate_history_vuc(hdl);
9545 else
9546 ret = wdc_do_clear_fw_activate_history_fid(hdl);
9547
9548out:
9549 return ret;
9550}
9551
9552static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd,
9553 struct plugin *plugin)
9554{
9555 const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
9556 const char *disable = "Disable controller option of the telemetry log page.";
9557 const char *enable = "Enable controller option of the telemetry log page.";
9558 const char *status = "Displays the current state of the controller initiated log page.";
9559 __u64 capabilities = 0;
9560 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9561 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9562 __u64 result;
9563 int ret = -1;
9564
9565
9566 struct config {
9567 bool_Bool disable;
9568 bool_Bool enable;
9569 bool_Bool status;
9570 };
9571
9572 struct config cfg = {
9573 .disable = false0,
9574 .enable = false0,
9575 .status = false0,
9576 };
9577
9578 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
9579 OPT_FLAG("disable", 'd', &cfg.disable, disable),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
9580 OPT_FLAG("enable", 'e', &cfg.enable, enable),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
9581 OPT_FLAG("status", 's', &cfg.status, status))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
9582
9583 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9584 if (ret)
9585 return ret;
9586
9587 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9588 if (ret)
9589 return ret;
9590
9591 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9592
9593 if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) {
9594 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
9595 ret = -1;
9596 goto out;
9597 }
9598
9599 /* allow only one option at a time */
9600 if ((cfg.disable + cfg.enable + cfg.status) > 1) {
9601
9602 fprintf(stderrstderr, "ERROR: WDC: Invalid option\n");
9603 ret = -1;
9604 goto out;
9605 }
9606
9607 if (cfg.disable) {
9608 ret = nvme_set_features_simple(hdl, 0,
9609 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9610 false0, 1, &result);
9611
9612 wdc_clear_reason_id(hdl);
9613 } else {
9614 if (cfg.enable) {
9615 ret = nvme_set_features_simple(hdl, 0,
9616 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9617 false0, 0, &result);
9618 } else if (cfg.status) {
9619 ret = nvme_get_features_simple(hdl,
9620 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9621 NVME_GET_FEATURES_SEL_CURRENT,
9622 &result);
9623 if (!ret) {
9624 if (result)
9625 fprintf(stderrstderr, "Controller Option Telemetry Log Page State: Disabled\n");
9626 else
9627 fprintf(stderrstderr, "Controller Option Telemetry Log Page State: Enabled\n");
9628 } else {
9629 nvme_show_status(ret);
9630 }
9631 } else {
9632 fprintf(stderrstderr, "ERROR: WDC: unsupported option for this command\n");
9633 fprintf(stderrstderr, "Please provide an option, -d, -e or -s\n");
9634 ret = -1;
9635 goto out;
9636 }
9637 }
9638
9639out:
9640 return ret;
9641}
9642
9643
9644static int wdc_get_serial_and_fw_rev(struct libnvme_transport_handle *hdl, char *sn, char *fw_rev)
9645{
9646 struct nvme_id_ctrl ctrl;
9647 int ret;
9648 int i;
9649
9650 i = sizeof(ctrl.sn) - 1;
9651 memset(sn, 0, WDC_SERIAL_NO_LEN20);
9652 memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN9);
9653 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9654 ret = nvme_identify_ctrl(hdl, &ctrl);
9655 if (ret) {
9656 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
9657 return -1;
9658 }
9659 /* Remove trailing spaces from the name */
9660 while (i && ctrl.sn[i] == ' ') {
9661 ctrl.sn[i] = '\0';
9662 i--;
9663 }
9664 snprintf(sn, WDC_SERIAL_NO_LEN20, "%s", ctrl.sn);
9665 snprintf(fw_rev, WDC_NVME_FIRMWARE_REV_LEN9, "%s", ctrl.fr);
9666
9667 return 0;
9668}
9669
9670static int wdc_get_max_transfer_len(struct libnvme_transport_handle *hdl, __u32 *maxTransferLen)
9671{
9672 struct nvme_id_ctrl ctrl;
9673 int ret = 0;
9674
9675 __u32 maxTransferLenDevice = 0;
9676
9677 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9678 ret = nvme_identify_ctrl(hdl, &ctrl);
9679 if (ret) {
9680 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
9681 return -1;
9682 }
9683
9684 maxTransferLenDevice = (1 << ctrl.mdts) * getpagesize();
9685 *maxTransferLen = maxTransferLenDevice;
9686
9687 return ret;
9688}
9689
9690static int wdc_de_VU_read_size(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize)
9691{
9692 int ret = WDC_STATUS_FAILURE-1;
9693 struct libnvme_passthru_cmd cmd;
9694
9695 if (!logSize) {
9696 ret = WDC_STATUS_INVALID_PARAMETER-3;
9697 goto end;
9698 }
9699
9700 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9701 cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE0xC0;
9702 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9703 cmd.cdw13 = fileId << 16;
9704 cmd.cdw14 = spiDestn;
9705
9706 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9707
9708 if (!ret && logSize)
9709 *logSize = cmd.result;
9710 if (ret != WDC_STATUS_SUCCESS0) {
9711 fprintf(stderrstderr, "ERROR: WDC: VUReadSize() failed, ");
9712 nvme_show_status(ret);
9713 }
9714
9715end:
9716 return ret;
9717}
9718
9719static int wdc_de_VU_read_buffer(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn,
9720 __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize)
9721{
9722 int ret = WDC_STATUS_FAILURE-1;
9723 struct libnvme_passthru_cmd cmd;
9724 __u32 noOfDwordExpected = 0;
9725
9726 if (!dataBuffer || !bufferSize) {
9727 ret = WDC_STATUS_INVALID_PARAMETER-3;
9728 goto end;
9729 }
9730
9731 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9732 noOfDwordExpected = *bufferSize / sizeof(__u32);
9733 cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE0xC2;
9734 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9735 cmd.cdw10 = noOfDwordExpected;
9736 cmd.cdw13 = fileId << 16;
9737 cmd.cdw14 = spiDestn;
9738 cmd.cdw15 = offsetInDwords;
9739
9740 cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
9741 cmd.data_len = *bufferSize;
9742
9743 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9744
9745 if (ret != WDC_STATUS_SUCCESS0) {
9746 fprintf(stderrstderr, "ERROR: WDC: VUReadBuffer() failed, ");
9747 nvme_show_status(ret);
9748 }
9749
9750end:
9751 return ret;
9752}
9753
9754static int wdc_get_log_dir_max_entries(struct libnvme_transport_handle *hdl, __u32 *maxNumOfEntries)
9755{
9756 int ret = WDC_STATUS_FAILURE-1;
9757 __u32 headerPayloadSize = 0;
9758 __u8 *fileIdOffsetsBuffer = NULL((void*)0);
9759 __u32 fileIdOffsetsBufferSize = 0;
9760 __u32 fileNum = 0;
9761 __u16 fileOffset = 0;
9762
9763
9764 if (!maxNumOfEntries) {
9765 ret = WDC_STATUS_INVALID_PARAMETER-3;
9766 return ret;
9767 }
9768 /* 1.Get log directory first four bytes */
9769 ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize);
9770 if (ret != WDC_STATUS_SUCCESS0) {
9771 fprintf(stderrstderr,
9772 "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n",
9773 __func__, ret);
9774 return ret;
9775 }
9776
9777 fileIdOffsetsBufferSize =
9778 WDC_DE_FILE_HEADER_SIZE4 + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE2);
9779 fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize);
9780
9781 /* 2.Read to get file offsets */
9782 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize);
9783 if (ret != WDC_STATUS_SUCCESS0) {
9784 fprintf(stderrstderr,
9785 "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n",
9786 __func__, ret);
9787 goto end;
9788 }
9789 /* 3.Determine valid entries */
9790 for (fileNum = 0;
9791 fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9792 fileNum++) {
9793 fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9794 (fileNum * WDC_DE_FILE_OFFSET_SIZE2)] << 8) +
9795 fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
9796 (fileNum * WDC_DE_FILE_OFFSET_SIZE2) + 1];
9797 if (!fileOffset)
9798 continue;
9799 (*maxNumOfEntries)++;
9800 }
9801
9802end:
9803 free(fileIdOffsetsBuffer);
9804 return ret;
9805}
9806
9807static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[])
9808{
9809 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE;
9810
9811 if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME"core_dump"))
9812 essentialType = WDC_DE_TYPE_DUMPSNAPSHOT;
9813 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME"event_log"))
9814 essentialType = WDC_DE_TYPE_EVENTLOG;
9815 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info"))
9816 essentialType = WDC_DE_TYPE_NVME_MANF_INFO;
9817
9818 return essentialType;
9819}
9820
9821static int wdc_fetch_log_directory(struct libnvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory)
9822{
9823 int ret = WDC_STATUS_FAILURE-1;
9824 __u8 *fileOffset = NULL((void*)0);
9825 __u8 *fileDirectory = NULL((void*)0);
9826 __u32 headerSize = 0;
9827 __u32 fileNum = 0, startIdx = 0;
9828 __u16 fileOffsetTemp = 0;
9829 __u32 entryId = 0;
9830 __u32 fileDirectorySize = 0;
9831
9832 if (!directory) {
9833 ret = WDC_STATUS_INVALID_PARAMETER-3;
9834 goto end;
9835 }
9836
9837 ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize);
9838 if (ret != WDC_STATUS_SUCCESS0) {
9839 fprintf(stderrstderr,
9840 "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n",
9841 __func__, ret);
9842 goto end;
9843 }
9844
9845 fileDirectory = (__u8 *)calloc(1, fileDirectorySize);
9846 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize);
9847 if (ret != WDC_STATUS_SUCCESS0) {
9848 fprintf(stderrstderr, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d\n",
9849 __func__, ret);
9850 goto end;
9851 }
9852
9853 /* First four bytes of header directory is headerSize */
9854 memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE4);
9855
9856 /* minimum buffer for 1 entry is required */
9857 if (!directory->maxNumLogEntries) {
9858 ret = WDC_STATUS_INVALID_PARAMETER-3;
9859 goto end;
9860 }
9861
9862 for (fileNum = 0;
9863 fileNum < (headerSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
9864 fileNum++) {
9865 if (entryId >= directory->maxNumLogEntries)
9866 break;
9867
9868 startIdx = WDC_DE_FILE_HEADER_SIZE4 + (fileNum * WDC_DE_FILE_OFFSET_SIZE2);
9869 memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp));
9870 fileOffset = fileDirectory + fileOffsetTemp;
9871
9872 if (!fileOffsetTemp)
9873 continue;
9874
9875 memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS));
9876 memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA));
9877 directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE32 - 1] = '\0';
9878 wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName,
9879 WDC_DE_FILE_NAME_SIZE32, ' ');
9880 if (!directory->logEntry[entryId].metaData.fileID)
9881 continue;
9882
9883 directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName);
9884 entryId++;
9885 }
9886
9887 directory->numOfValidLogEntries = entryId;
9888
9889end:
9890 free(fileDirectory);
9891 return ret;
9892}
9893
9894static int wdc_fetch_log_file_from_device(struct libnvme_transport_handle *hdl, __u32 fileId,
9895 __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
9896{
9897 int ret = WDC_STATUS_FAILURE-1;
9898 __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9899 __u32 maximumTransferLength = 0;
9900 __u32 buffSize = 0;
9901 __u64 offsetIdx = 0;
9902
9903 if (!dataBuffer || !fileSize) {
9904 ret = WDC_STATUS_INVALID_PARAMETER-3;
9905 goto end;
9906 }
9907
9908 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) {
9909 ret = WDC_STATUS_FAILURE-1;
9910 goto end;
9911 }
9912
9913 /* Fetch Log File Data */
9914 if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) {
9915 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
9916 if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000)
9917 chunckSize = maximumTransferLength;
9918
9919 buffSize = chunckSize;
9920 for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) {
9921 if (((offsetIdx * chunckSize) + buffSize) > fileSize)
9922 buffSize = (__u32)(fileSize - (offsetIdx * chunckSize));
9923 /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */
9924 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9925 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize);
9926 if (ret != WDC_STATUS_SUCCESS0) {
9927 fprintf(stderrstderr, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n",
9928 __func__, ret, fileId, (unsigned long)fileSize);
9929 break;
9930 }
9931 }
9932 } else {
9933 buffSize = (__u32)fileSize;
9934 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
9935 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)),
9936 dataBuffer, &buffSize);
9937 if (ret != WDC_STATUS_SUCCESS0) {
9938 fprintf(stderrstderr, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n",
9939 __func__, ret, fileId, (unsigned long)fileSize);
9940 }
9941 }
9942
9943end:
9944 return ret;
9945}
9946
9947static int wdc_de_get_dump_trace(struct libnvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen,
9948 const char *binFileName)
9949{
9950 int ret = WDC_STATUS_FAILURE-1;
9951 __u8 *readBuffer = NULL((void*)0);
9952 __u32 readBufferLen = 0;
9953 __u32 lastPktReadBufferLen = 0;
9954 __u32 maxTransferLen = 0;
9955 __u32 dumptraceSize = 0;
9956 __u32 chunkSize;
9957 __u32 chunks;
9958 __u32 offset;
9959 __u32 i;
9960 __u32 maximumTransferLength = 0;
9961
9962 if (!binFileName || !filePath) {
9963 ret = WDC_STATUS_INVALID_PARAMETER-3;
9964 return ret;
9965 }
9966
9967 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0)
9968 return WDC_STATUS_FAILURE-1;
9969
9970 do {
9971 /* Get dumptrace size */
9972 ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, &dumptraceSize);
9973 if (ret != WDC_STATUS_SUCCESS0) {
9974 fprintf(stderrstderr, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d\n",
9975 __func__, ret);
9976 break;
9977 }
9978
9979 /* Make sure the size requested is greater than dword */
9980 if (dumptraceSize < 4) {
9981 ret = WDC_STATUS_FAILURE-1;
9982 fprintf(stderrstderr, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x\n",
9983 __func__, dumptraceSize);
9984 break;
9985 }
9986
9987 /* Choose the least max transfer length */
9988 maxTransferLen = maximumTransferLength < WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 ? maximumTransferLength : WDC_DE_READ_MAX_TRANSFER_SIZE0x8000;
9989
9990 /* Comment from FW Team:
9991 * The max non - block transfer size is 0xFFFF (16 bits allowed as the block size).Use 0x8000
9992 * to keep it on a word - boundary.
9993 * max_xfer = int(pow(2, id_data['MDTS'])) * 4096 # 4k page size as reported in pcie capabiltiies
9994 */
9995 chunkSize = dumptraceSize < maxTransferLen ? dumptraceSize : maxTransferLen;
9996 chunks = (dumptraceSize / maxTransferLen) + ((dumptraceSize % maxTransferLen) ? 1 : 0);
9997
9998 readBuffer = (unsigned char *)calloc(dumptraceSize, sizeof(unsigned char));
9999 readBufferLen = chunkSize;
10000 lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize;
10001
10002 if (!readBuffer) {
10003 fprintf(stderrstderr, "ERROR: WDC: %s: readBuffer calloc failed\n", __func__);
10004 ret = WDC_STATUS_INSUFFICIENT_MEMORY-2;
10005 break;
10006 }
10007
10008 for (i = 0; i < chunks; i++) {
10009 offset = (i * chunkSize) / 4;
10010
10011 /* Last loop call, Assign readBufferLen to read only left over bytes */
10012 if (i == (chunks - 1))
10013 readBufferLen = lastPktReadBufferLen;
10014
10015 ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, 0,
10016 readBuffer + offset, &readBufferLen);
10017 if (ret != WDC_STATUS_SUCCESS0) {
10018 fprintf(stderrstderr,
10019 "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n",
10020 __func__, ret, offset);
10021 break;
10022 }
10023 }
10024 } while (0);
10025
10026 if (ret == WDC_STATUS_SUCCESS0) {
10027 ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
10028 if (ret != WDC_STATUS_SUCCESS0)
10029 fprintf(stderrstderr, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d\n",
10030 __func__, ret);
10031 } else {
10032 fprintf(stderrstderr, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d\n", __func__,
10033 ret);
10034 }
10035
10036 free(readBuffer);
10037
10038 return ret;
10039}
10040
10041int wdc_fetch_vu_file_directory(struct libnvme_transport_handle *hdl,
10042 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList,
10043 __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString)
10044{
10045 int ret = wdc_fetch_log_directory(hdl, &deEssentialsList);
10046 __u32 listIdx;
10047 char *dataBuffer;
10048 char fileName[MAX_PATH_LEN256];
10049
10050 if (ret != WDC_STATUS_SUCCESS0) {
10051 fprintf(stderrstderr, "WDC: wdc_fetch_log_directory failed, ret = %d\n", ret);
10052 return ret;
10053 }
10054
10055 /* Get Debug Data Files */
10056 for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) {
10057 if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) {
10058 fprintf(stderrstderr, "ERROR: WDC: File Size for %s is 0\n",
10059 deEssentialsList.logEntry[listIdx].metaData.fileName);
10060 ret = WDC_STATUS_FILE_SIZE_ZERO-27;
10061 } else {
10062 /* Fetch Log File Data */
10063 dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10064 ret = wdc_fetch_log_file_from_device(hdl,
10065 deEssentialsList.logEntry[listIdx].metaData.fileID,
10066 WDC_DE_DESTN_SPI1,
10067 deEssentialsList.logEntry[listIdx].metaData.fileSize,
10068 (__u8 *)dataBuffer);
10069
10070 /* Write databuffer to file */
10071 if (ret == WDC_STATUS_SUCCESS0) {
10072 memset(fileName, 0, sizeof(fileName));
10073 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10074 deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString);
10075 if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) {
10076 wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF);
10077 wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF));
10078 } else {
10079 wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10080 }
10081 } else {
10082 fprintf(stderrstderr, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d\n",
10083 deEssentialsList.logEntry[listIdx].metaData.fileName, ret);
10084 }
10085 free(dataBuffer);
10086 }
10087 }
10088
10089 return ret;
10090}
10091
10092int wdc_read_debug_directory(struct libnvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo,
10093 __u8 *timeString)
10094{
10095 __u32 maxNumOfVUFiles = 0;
10096 int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles);
10097 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
10098
10099 if (ret != WDC_STATUS_SUCCESS0) {
10100 fprintf(stderrstderr, "WDC: wdc_get_log_dir_max_entries failed, ret = %d\n", ret);
10101 return ret;
10102 }
10103
10104 memset(&deEssentialsList, 0, sizeof(deEssentialsList));
10105 deEssentialsList.logEntry =
10106 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles);
10107 deEssentialsList.maxNumLogEntries = maxNumOfVUFiles;
10108
10109 ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo,
10110 timeString);
10111
10112 free(deEssentialsList.logEntry);
10113 deEssentialsList.logEntry = NULL((void*)0);
10114
10115 return ret;
10116}
10117
10118static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
10119 char *dir, char *key)
10120{
10121 int ret = 0;
10122 void *retPtr;
10123 char fileName[MAX_PATH_LEN256];
10124 __s8 bufferFolderPath[MAX_PATH_LEN256];
10125 char bufferFolderName[MAX_PATH_LEN256];
10126 char tarFileName[MAX_PATH_LEN256];
10127 char tarFiles[MAX_PATH_LEN256];
10128 char tarCmd[MAX_PATH_LEN256+MAX_PATH_LEN256];
10129 UtilsTimeInfo timeInfo;
10130 __u8 timeString[MAX_PATH_LEN256];
10131 __u8 serialNo[WDC_SERIAL_NO_LEN20];
10132 __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN9];
10133 __u8 idSerialNo[WDC_SERIAL_NO_LEN20];
10134 __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN9];
10135 __u8 featureIdBuff[4];
10136 char currDir[MAX_PATH_LEN256];
10137 char *dataBuffer = NULL((void*)0);
10138 __u32 elogNumEntries, elogBufferSize;
10139 __u32 dataBufferSize;
10140 __u32 listIdx = 0;
10141 __u32 vuLogIdx = 0;
10142 __u64 result;
10143 struct nvme_id_ctrl ctrl;
10144 struct nvme_id_ns ns;
10145 struct nvme_error_log_page *elogBuffer;
10146 struct nvme_smart_log smart_log;
10147 struct nvme_firmware_slot fw_log;
10148 struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL((void*)0);
10149
10150 memset(bufferFolderPath, 0, sizeof(bufferFolderPath));
10151 memset(bufferFolderName, 0, sizeof(bufferFolderName));
10152 memset(tarFileName, 0, sizeof(tarFileName));
10153 memset(tarFiles, 0, sizeof(tarFiles));
10154 memset(tarCmd, 0, sizeof(tarCmd));
10155 memset(&timeInfo, 0, sizeof(timeInfo));
10156
10157 if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) {
10158 fprintf(stderrstderr, "ERROR: WDC: get serial # and fw revision failed\n");
10159 return -1;
10160 }
10161
10162 fprintf(stderrstderr, "Get Drive Essentials Data for device serial #: %s and fw revision: %s\n",
10163 idSerialNo, idFwRev);
10164
10165 /* Create Drive Essentials directory */
10166 wdc_UtilsGetTime(&timeInfo);
10167 memset(timeString, 0, sizeof(timeString));
10168 wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10169 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10170 timeInfo.hour, timeInfo.minute, timeInfo.second);
10171
10172 wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN20, (char *)idSerialNo);
10173 /* Remove any space form serialNo */
10174 wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN20, ' ');
10175
10176 memset(firmwareRevision, 0, sizeof(firmwareRevision));
10177 wdc_UtilsSnprintf((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, (char *)idFwRev);
10178 /* Remove any space form FirmwareRevision */
10179 wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, ' ');
10180
10181 wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN256, "%s_%s_%s_%s",
10182 "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString);
10183
10184 if (dir) {
10185 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10186 (char *)dir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10187 } else {
10188 retPtr = getcwd((char *)currDir, MAX_PATH_LEN256);
10189 if (retPtr) {
10190 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10191 (char *)currDir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10192 } else {
10193 fprintf(stderrstderr, "ERROR: WDC: get current working directory failed\n");
10194 return -1;
10195 }
10196 }
10197
10198 ret = wdc_UtilsCreateDir((char *)bufferFolderPath);
10199 if (ret) {
10200 fprintf(stderrstderr, "ERROR: WDC: create directory failed, ret = %d, dir = %s\n", ret, bufferFolderPath);
10201 return -1;
10202 }
10203
10204 fprintf(stderrstderr, "Store Drive Essentials bin files in directory: %s\n", bufferFolderPath);
10205
10206 /* Get Identify Controller Data */
10207 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10208 ret = nvme_identify_ctrl(hdl, &ctrl);
10209 if (ret) {
10210 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed, ret = %d\n", ret);
10211 return -1;
10212 }
10213
10214 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath,
10215 WDC_DE_PATH_SEPARATOR"/", "IdentifyController", (char *)serialNo,
10216 (char *)timeString);
10217 wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl));
10218
10219 memset(&ns, 0, sizeof(struct nvme_id_ns));
10220 ret = nvme_identify_ns(hdl, 1, &ns);
10221 if (ret) {
10222 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ns() failed, ret = %d\n", ret);
10223 } else {
10224 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10225 "IdentifyNamespace", (char *)serialNo, (char *)timeString);
10226 wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns));
10227 }
10228
10229 /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */
10230 elogNumEntries = WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64;
10231 elogBufferSize = elogNumEntries*sizeof(struct nvme_error_log_page);
10232 dataBuffer = calloc(1, elogBufferSize);
10233 elogBuffer = (struct nvme_error_log_page *)dataBuffer;
10234
10235 ret = nvme_get_log_error(hdl, NVME_NSID_ALL, elogNumEntries, elogBuffer);
10236 if (ret) {
10237 fprintf(stderrstderr, "ERROR: WDC: nvme_error_log() failed, ret = %d\n", ret);
10238 } else {
10239 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10240 "ErrorLog", (char *)serialNo, (char *)timeString);
10241 wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize);
10242 }
10243
10244 free(dataBuffer);
10245 dataBuffer = NULL((void*)0);
10246
10247 /* Get Smart log page */
10248 memset(&smart_log, 0, sizeof(struct nvme_smart_log));
10249 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
10250 if (ret) {
10251 fprintf(stderrstderr, "ERROR: WDC: nvme_smart_log() failed, ret = %d\n", ret);
10252 } else {
10253 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10254 "SmartLog", (char *)serialNo, (char *)timeString);
10255 wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log));
10256 }
10257
10258 /* Get FW Slot log page */
10259 memset(&fw_log, 0, sizeof(struct nvme_firmware_slot));
10260 ret = nvme_get_log_fw_slot(hdl, false0, &fw_log);
10261 if (ret) {
10262 fprintf(stderrstderr, "ERROR: WDC: nvme_fw_log() failed, ret = %d\n", ret);
10263 } else {
10264 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10265 "FwSLotLog", (char *)serialNo, (char *)timeString);
10266 wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot));
10267 }
10268
10269 /* Get VU log pages */
10270 /* define inputs for vendor unique log pages */
10271 vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES));
10272 vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList)(sizeof(deVULogPagesList) / sizeof((deVULogPagesList)[0]));
10273
10274 for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) {
10275 dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen;
10276 dataBuffer = calloc(1, dataBufferSize);
10277 memset(dataBuffer, 0, dataBufferSize);
10278
10279 ret = nvme_get_log_simple(hdl,
10280 deVULogPagesList[vuLogIdx].logPageId,
10281 dataBuffer, dataBufferSize);
10282 if (ret) {
10283 fprintf(stderrstderr, "ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d\n",
10284 deVULogPagesList[vuLogIdx].logPageId, ret);
10285 } else {
10286 wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' ');
10287 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10288 "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString);
10289 wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize);
10290 }
10291
10292 free(dataBuffer);
10293 dataBuffer = NULL((void*)0);
10294 }
10295
10296 free(vuLogInput);
10297
10298 /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */
10299 for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList)(sizeof(deFeatureIdList) / sizeof((deFeatureIdList)[0])); listIdx++) {
10300 memset(featureIdBuff, 0, sizeof(featureIdBuff));
10301 /* skipping LbaRangeType as it is an optional nvme command and not supported */
10302 if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
10303 continue;
10304 ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID0xFFFFFFFF,
10305 (enum nvme_features_id)deFeatureIdList[listIdx].featureId,
10306 NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff,
10307 sizeof(featureIdBuff), &result);
10308 if (ret) {
10309 fprintf(stderrstderr, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d\n",
10310 deFeatureIdList[listIdx].featureId, ret);
10311 } else {
10312 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10313 "FEATURE_ID_", deFeatureIdList[listIdx].featureId,
10314 deFeatureIdList[listIdx].featureName, serialNo, timeString);
10315 wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff));
10316 }
10317 }
10318
10319 ret = wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString);
10320
10321 /* Get Dump Trace Data */
10322 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/", "dumptrace", serialNo, timeString);
10323 ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName);
10324 if (ret != WDC_STATUS_SUCCESS0)
10325 fprintf(stderrstderr, "ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d\n", ret);
10326
10327 /* Tar the Drive Essentials directory */
10328 wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
10329 if (dir)
10330 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s%s%s", (char *)dir,
10331 WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName,
10332 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10333 else
10334 wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s", (char *)bufferFolderName,
10335 WDC_DE_PATH_SEPARATOR"/", WDC_DE_TAR_FILES"*.bin");
10336 wdc_UtilsSnprintf(tarCmd, sizeof(tarCmd), "%s %s %s", WDC_DE_TAR_CMD"tar -czf", (char *)tarFileName, (char *)tarFiles);
10337
10338 ret = system(tarCmd);
10339
10340 if (ret)
10341 fprintf(stderrstderr, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d\n",
10342 ret);
10343
10344 fprintf(stderrstderr, "Get of Drive Essentials data successful\n");
10345 return 0;
10346}
10347
10348static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
10349 struct plugin *plugin)
10350{
10351 const char *desc = "Capture Drive Essentials.";
10352 const char *dirName = "Output directory pathname.";
10353 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10354 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10355 char d[PATH_MAX4096] = {0};
10356 char k[PATH_MAX4096] = {0};
10357 __u64 capabilities = 0;
10358 char *d_ptr;
10359 int ret;
10360
10361 struct config {
10362 char *dirName;
10363 };
10364
10365 struct config cfg = {
10366 .dirName = NULL((void*)0),
10367 };
10368
10369 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
10370 OPT_STRING("dir-name", 'd', "DIRECTORY", &cfg.dirName, dirName))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
10371
10372
10373 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10374 if (ret)
10375 return ret;
10376
10377 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10378 if (ret)
10379 return ret;
10380
10381 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10382
10383 if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) {
10384 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
10385 ret = -1;
10386 goto out;
10387 }
10388
10389 if (cfg.dirName) {
10390 strncpy(d, cfg.dirName, PATH_MAX4096 - 1);
10391 d_ptr = d;
10392 } else {
10393 d_ptr = NULL((void*)0);
10394 }
10395
10396 ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k);
10397out:
10398 return ret;
10399}
10400
10401static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size)
10402{
10403 int ret;
10404 struct libnvme_passthru_cmd admin_cmd;
10405
10406 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10407 admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE0xCC;
10408 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 << WDC_NVME_SUBCMD_SHIFT8) |
10409 WDC_NVME_DRIVE_RESIZE_CMD0x03);
10410 admin_cmd.cdw13 = new_size;
10411
10412 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10413 return ret;
10414}
10415
10416static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option)
10417{
10418 int ret;
10419 struct libnvme_passthru_cmd admin_cmd;
10420
10421 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10422 admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB;
10423 admin_cmd.nsid = nsid;
10424 admin_cmd.cdw10 = op_option;
10425
10426 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10427 return ret;
10428}
10429
10430static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result)
10431{
10432 int ret;
10433 struct libnvme_passthru_cmd admin_cmd;
10434
10435 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10436 admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE0xC6;
10437 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
10438 WDC_NVME_DRIVE_INFO_CMD0x22);
10439
10440 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10441
10442 if (!ret && result)
10443 *result = admin_cmd.result;
10444
10445 return ret;
10446}
10447
10448static int wdc_drive_resize(int argc, char **argv,
10449 struct command *command, struct plugin *plugin)
10450{
10451 const char *desc = "Send a Resize command.";
10452 const char *size = "The new size (in GB) to resize the drive to.";
10453 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10454 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10455 uint64_t capabilities = 0;
10456 int ret;
10457
10458 struct config {
10459 uint64_t size;
10460 };
10461
10462 struct config cfg = {
10463 .size = 0,
10464 };
10465
10466 NVME_ARGS(opts,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
10467 OPT_UINT("size", 's', &cfg.size, size))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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
10468
10469 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10470 if (ret)
10471 return ret;
10472
10473 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10474 if (ret || !wdc_check_device(ctx, hdl))
10475 return -1;
10476
10477 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10478
10479 if ((capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100) == WDC_DRIVE_CAP_RESIZE0x0000000000000100) {
10480 ret = wdc_do_drive_resize(hdl, cfg.size);
10481 } else {
10482 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
10483 ret = -1;
10484 }
10485
10486 if (!ret)
10487 printf("New size: %" PRIu64"l" "u" " GB\n", cfg.size);
10488
10489 nvme_show_status(ret);
10490 return ret;
10491}
10492
10493static int wdc_namespace_resize(int argc, char **argv,
10494 struct command *command, struct plugin *plugin)
10495{
10496 const char *desc = "Send a Namespace Resize command.";
10497 const char *namespace_id = "The namespace id to resize.";
10498 const char *op_option = "The over provisioning option to set for namespace.";
10499 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10500 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10501 uint64_t capabilities = 0;
10502 int ret;
10503
10504 struct config {
10505 __u32 namespace_id;
10506 __u32 op_option;
10507 };
10508
10509 struct config cfg = {
10510 .namespace_id = 0x1,
10511 .op_option = 0xF,
10512 };
10513
10514 NVME_ARGS(opts,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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
10515 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
10516 OPT_UINT("op-option", 'O', &cfg.op_option, op_option))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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
10517
10518 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10519 if (ret)
10520 return ret;
10521
10522 if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) &&
10523 (cfg.op_option != 0xF)) {
10524 fprintf(stderrstderr, "ERROR: WDC: unsupported OP option parameter\n");
10525 return -1;
10526 }
10527
10528 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10529 if (ret || !wdc_check_device(ctx, hdl))
10530 return -1;
10531
10532 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10533
10534 if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) == WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) {
10535 ret = wdc_do_namespace_resize(hdl, cfg.namespace_id,
10536 cfg.op_option);
10537
10538 if (ret)
10539 printf("ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed\n", cfg.namespace_id, cfg.op_option);
10540 } else {
10541 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
10542 ret = -1;
10543 }
10544
10545 nvme_show_status(ret);
10546 return ret;
10547}
10548
10549static int wdc_reason_identifier(int argc, char **argv,
10550 struct command *command, struct plugin *plugin)
10551{
10552 const char *desc = "Retrieve telemetry log reason identifier.";
10553 const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
10554 const char *fname = "File name to save raw binary identifier";
10555 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10556 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10557 int ret;
10558 uint64_t capabilities = 0;
10559 char f[PATH_MAX4096] = {0};
10560 char fileSuffix[PATH_MAX4096] = {0};
10561 UtilsTimeInfo timeInfo;
10562 __u8 timeStamp[MAX_PATH_LEN256];
10563
10564
10565 struct config {
10566 int log_id;
10567 char *file;
10568 };
10569 struct config cfg = {
10570 .log_id = 7,
10571 .file = NULL((void*)0),
10572 };
10573
10574 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
10575 OPT_UINT("log-id", 'i', &cfg.log_id, log_id),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
10576 OPT_FILE("file", 'O', &cfg.file, fname))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
10577
10578 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10579
10580 if (ret)
10581 return ret;
10582
10583 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10584 if (ret)
10585 return ret;
10586
10587 if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST &&
10588 cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
10589 fprintf(stderrstderr, "ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n");
10590 return -1;
10591 }
10592
10593 if (cfg.file) {
10594 int verify_file;
10595
10596 /* verify the passed in file name and path is valid before getting the dump data */
10597 verify_file = nvme_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
10598 if (verify_file < 0) {
10599 fprintf(stderrstderr, "ERROR: WDC: open: %s\n", libnvme_strerror(errno(*__errno_location ())));
10600 return -1;
10601 }
10602 close(verify_file);
10603 strncpy(f, cfg.file, PATH_MAX4096 - 1);
10604 } else {
10605 wdc_UtilsGetTime(&timeInfo);
10606 memset(timeStamp, 0, sizeof(timeStamp));
10607 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10608 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10609 timeInfo.hour, timeInfo.minute, timeInfo.second);
10610 if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
10611 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_ctlr_%s", (char *)timeStamp);
10612 else
10613 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_host_%s", (char *)timeStamp);
10614
10615 if (wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix) == -1) {
10616 fprintf(stderrstderr, "ERROR: WDC: failed to generate file name\n");
10617 return -1;
10618 }
10619 if (strlen(f) > PATH_MAX4096 - 5) {
10620 fprintf(stderrstderr, "ERROR: WDC: file name overflow\n");
10621 return -1;
10622 }
10623 strcat(f, ".bin");
10624 }
10625
10626 fprintf(stderrstderr, "%s: filename = %s\n", __func__, f);
10627
10628 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10629 if ((capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000) == WDC_DRIVE_CAP_REASON_ID0x0000000000010000) {
10630 ret = wdc_do_get_reason_id(hdl, f, cfg.log_id);
10631 } else {
10632 fprintf(stderrstderr, "ERROR: WDC:unsupported device for this command\n");
10633 ret = -1;
10634 }
10635
10636 nvme_show_status(ret);
10637
10638 return ret;
10639}
10640
10641static const char *nvme_log_id_to_string(__u8 log_id)
10642{
10643 switch (log_id) {
10644 case NVME_LOG_LID_ERROR:
10645 return "Error Information Log ID";
10646 case NVME_LOG_LID_SMART:
10647 return "Smart/Health Information Log ID";
10648 case NVME_LOG_LID_FW_SLOT:
10649 return "Firmware Slot Information Log ID";
10650 case NVME_LOG_LID_CHANGED_NS:
10651 return "Namespace Changed Log ID";
10652 case NVME_LOG_LID_CMD_EFFECTS:
10653 return "Commamds Supported and Effects Log ID";
10654 case NVME_LOG_LID_DEVICE_SELF_TEST:
10655 return "Device Self Test Log ID";
10656 case NVME_LOG_LID_TELEMETRY_HOST:
10657 return "Telemetry Host Initiated Log ID";
10658 case NVME_LOG_LID_TELEMETRY_CTRL:
10659 return "Telemetry Controller Generated Log ID";
10660 case NVME_LOG_LID_ENDURANCE_GROUP:
10661 return "Endurance Group Log ID";
10662 case NVME_LOG_LID_ANA:
10663 return "ANA Log ID";
10664 case NVME_LOG_LID_PERSISTENT_EVENT:
10665 return "Persistent Event Log ID";
10666 case NVME_LOG_LID_DISCOVERY:
10667 return "Discovery Log ID";
10668 case NVME_LOG_LID_RESERVATION:
10669 return "Reservation Notification Log ID";
10670 case NVME_LOG_LID_SANITIZE:
10671 return "Sanitize Status Log ID";
10672 case WDC_LOG_ID_C00xC0:
10673 return "WDC Vendor Unique Log ID C0";
10674 case WDC_LOG_ID_C10xC1:
10675 return "WDC Vendor Unique Log ID C1";
10676 case WDC_LOG_ID_C20xC2:
10677 return "WDC Vendor Unique Log ID C2";
10678 case WDC_LOG_ID_C30xC3:
10679 return "WDC Vendor Unique Log ID C3";
10680 case WDC_LOG_ID_C40xC4:
10681 return "WDC Vendor Unique Log ID C4";
10682 case WDC_LOG_ID_C50xC5:
10683 return "WDC Vendor Unique Log ID C5";
10684 case WDC_LOG_ID_C60xC6:
10685 return "WDC Vendor Unique Log ID C6";
10686 case WDC_LOG_ID_C80xC8:
10687 return "WDC Vendor Unique Log ID C8";
10688 case WDC_LOG_ID_CA0xCA:
10689 return "WDC Vendor Unique Log ID CA";
10690 case WDC_LOG_ID_CB0xCB:
10691 return "WDC Vendor Unique Log ID CB";
10692 case WDC_LOG_ID_D00xD0:
10693 return "WDC Vendor Unique Log ID D0";
10694 case WDC_LOG_ID_D10xD1:
10695 return "WDC Vendor Unique Log ID D1";
10696 case WDC_LOG_ID_D60xD6:
10697 return "WDC Vendor Unique Log ID D6";
10698 case WDC_LOG_ID_D70xD7:
10699 return "WDC Vendor Unique Log ID D7";
10700 case WDC_LOG_ID_D80xD8:
10701 return "WDC Vendor Unique Log ID D8";
10702 case WDC_LOG_ID_DE0xDE:
10703 return "WDC Vendor Unique Log ID DE";
10704 case WDC_LOG_ID_F00xF0:
10705 return "WDC Vendor Unique Log ID F0";
10706 case WDC_LOG_ID_F10xF1:
10707 return "WDC Vendor Unique Log ID F1";
10708 case WDC_LOG_ID_F20xF2:
10709 return "WDC Vendor Unique Log ID F2";
10710 case WDC_LOG_ID_FA0xFA:
10711 return "WDC Vendor Unique Log ID FA";
10712 default:
10713 return "Unknown Log ID";
10714 }
10715}
10716
10717static void __json_log_page_directory(struct log_page_directory *directory)
10718{
10719 __u32 bitmap_idx;
10720 __u8 log_id;
10721 struct json_object *root;
10722 struct json_object *entries;
10723
10724 root = json_create_object()json_object_new_object();
10725
10726 entries = json_create_array()json_object_new_array();
10727 json_object_add_value_array(root, "Entries", entries)json_object_object_add(root, "Entries", entries);
10728
10729 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10730 log_id = bitmap_idx;
10731 if (!log_page_name[log_id])
10732 continue;
10733 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10734 struct json_object *json_entry = json_create_object()json_object_new_object();
10735
10736 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))
;
10737 json_object_add_value_string(json_entry, "Log Page Name",
10738 log_page_name[log_id]);
10739
10740 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10741 }
10742 }
10743
10744 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10745 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10746 if (!log_page_name[log_id])
10747 continue;
10748 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10749 struct json_object *json_entry = json_create_object()json_object_new_object();
10750
10751 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))
;
10752 json_object_add_value_string(json_entry, "Log Page Name",
10753 log_page_name[log_id]);
10754
10755 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10756 }
10757 }
10758
10759 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10760 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10761 if (!log_page_name[log_id])
10762 continue;
10763 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10764 struct json_object *json_entry = json_create_object()json_object_new_object();
10765
10766 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))
;
10767 json_object_add_value_string(json_entry, "Log Page Name",
10768 log_page_name[log_id]);
10769
10770 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
10771 }
10772 }
10773
10774 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10775 printf("\n");
10776 json_free_object(root)json_object_put(root);
10777}
10778
10779
10780static void __show_log_page_directory(struct log_page_directory *directory)
10781{
10782 __u32 bitmap_idx;
10783 __u8 log_id;
10784
10785 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10786 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
10787 log_id = bitmap_idx;
10788 if (log_page_name[log_id])
10789 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10790 }
10791 }
10792
10793 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10794 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
10795 log_id = NVME_LOG_NS_BASE + bitmap_idx;
10796 if (log_page_name[log_id])
10797 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10798 }
10799 }
10800
10801 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
10802 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
10803 log_id = NVME_LOG_VS_BASE + bitmap_idx;
10804 if (log_page_name[log_id])
10805 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
10806 }
10807 }
10808}
10809
10810static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
10811 struct plugin *plugin)
10812{
10813 const char *desc = "Retrieve Log Page Directory.";
10814 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10815 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10816 nvme_print_flags_t fmt;
10817 int ret = 0;
10818 __u64 capabilities = 0;
10819 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
10820 int i, uuid_index = 0;
10821 __u8 log_id = 0;
10822 __u32 device_id, read_vendor_id;
10823 bool_Bool uuid_supported = false0;
10824 struct nvme_id_uuid_list uuid_list;
10825
10826 struct config {
10827 char *output_format;
10828 };
10829
10830 struct config cfg = {
10831 .output_format = "normal",
10832 };
10833
10834 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
10835
10836 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10837 if (ret)
10838 return ret;
10839
10840 ret = validate_output_format(cfg.output_format, &fmt);
10841 if (ret < 0) {
10842 fprintf(stderrstderr, "%s: ERROR: WDC: invalid output format\n", __func__);
10843 return ret;
10844 }
10845
10846 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10847 if (ret)
10848 return ret;
10849
10850 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10851
10852 if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000)) {
10853 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
10854 ret = -1;
10855 } else {
10856 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
10857 if (wdc_CheckUuidListSupport(hdl, &uuid_list))
10858 uuid_supported = true1;
10859
10860 if (uuid_supported)
10861 fprintf(stderrstderr, "WDC: UUID lists supported\n");
10862 else
10863 fprintf(stderrstderr, "WDC: UUID lists NOT supported\n");
10864
10865
10866 ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id);
10867 log_id = wdc_is_zn350(device_id) ?
10868 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 :
10869 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
10870
10871 if (!wdc_is_sn861(device_id)) {
10872 if (uuid_supported) {
10873 /* check for the Sandisk UUID first */
10874 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
10875
10876 if (uuid_index < 0)
10877 /* The Sandisk UUID is not found;
10878 * check for the WDC UUID second.
10879 */
10880 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
10881 }
10882
10883 /* WD UUID not found, use default uuid index - 0 */
10884 if (uuid_index < 0)
10885 uuid_index = 0;
10886
10887 /* verify the 0xC2 Device Manageability log page is supported */
10888 if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) {
10889 fprintf(stderrstderr, "%s: ERROR: WDC: 0x%x Log Page not supported\n",
10890 __func__, log_id);
10891 ret = -1;
10892 goto out;
10893 }
10894
10895 if (!get_dev_mgment_cbs_data(ctx, hdl,
10896 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
10897 (void *)&cbs_data)) {
10898 fprintf(stderrstderr,
10899 "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",
10900 __func__, WDC_C2_LOG_PAGES_SUPPORTED_ID0x08);
10901 ret = -1;
10902 goto out;
10903 }
10904 if (!cbs_data) {
10905 fprintf(stderrstderr, "%s: ERROR: WDC: NULL_data ptr\n", __func__);
10906 ret = -1;
10907 goto out;
10908 }
10909 printf("Log Page Directory\n");
10910 /* print the supported pages */
10911 if (!strcmp(cfg.output_format, "normal")) {
10912 for (i = 0; i < le32_to_cpu(cbs_data->length); i++)
10913 printf("0x%x - %s\n", cbs_data->data[i],
10914 nvme_log_id_to_string(cbs_data->data[i]));
10915 } else if (!strcmp(cfg.output_format, "binary")) {
10916 d((__u8 *)cbs_data->data,
10917 le32_to_cpu(cbs_data->length), 16, 1);
10918 } else if (!strcmp(cfg.output_format, "json")) {
10919 struct json_object *root = json_create_object()json_object_new_object();
10920
10921 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
10922 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]))
10923 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]))
10924 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]))
;
10925 }
10926
10927 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
10928 printf("\n");
10929 json_free_object(root)json_object_put(root);
10930 } else {
10931 fprintf(stderrstderr,
10932 "%s: ERROR: WDC: Invalid format, format = %s\n",
10933 __func__, cfg.output_format);
10934 }
10935
10936 free(cbs_data);
10937 } else {
10938 struct log_page_directory *dir;
10939 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *data = NULL((void*)0);
10940
10941 data = libnvme_alloc(512);
10942 if (!data) {
10943 fprintf(stderrstderr,
10944 "can not allocate log page directory payload\n");
10945 return -ENOMEM12;
10946 }
10947
10948 dir = (struct log_page_directory *)data;
10949 struct libnvme_passthru_cmd cmd = {
10950 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
10951 .cdw10 = 8,
10952 .cdw12 = WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2,
10953 .addr = (__u64)(uintptr_t)data,
10954 .data_len = 32,
10955 };
10956
10957 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10958 if (!ret) {
10959 switch (fmt) {
10960 case BINARY:
10961 d_raw((unsigned char *)data, 32);
10962 break;
10963 case JSON:
10964 __json_log_page_directory(dir);
10965 break;
10966 default:
10967 __show_log_page_directory(dir);
10968 }
10969 } else {
10970 fprintf(stderrstderr, "NVMe Status:%s(%x)\n",
10971 libnvme_status_to_string(ret, false0), ret);
10972 }
10973 }
10974 }
10975
10976out:
10977 return ret;
10978}
10979
10980static int wdc_get_drive_reason_id(struct libnvme_transport_handle *hdl, char *drive_reason_id, size_t len)
10981{
10982 const char *reason_id_str = "reason_id";
10983 struct nvme_id_ctrl ctrl;
10984 int res_len = 0;
10985 int i, j;
10986 int ret;
10987
10988 i = sizeof(ctrl.sn) - 1;
10989 j = sizeof(ctrl.mn) - 1;
10990 memset(drive_reason_id, 0, len);
10991 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10992 ret = nvme_identify_ctrl(hdl, &ctrl);
10993 if (ret) {
10994 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret);
10995 return -1;
10996 }
10997 /* Remove trailing spaces from the sn and mn */
10998 while (i && ctrl.sn[i] == ' ') {
10999 ctrl.sn[i] = '\0';
11000 i--;
11001 }
11002
11003 while (j && ctrl.mn[j] == ' ') {
11004 ctrl.mn[j] = '\0';
11005 j--;
11006 }
11007
11008 res_len = snprintf(drive_reason_id, len, "%s_%s_%s", ctrl.sn, ctrl.mn, reason_id_str);
11009 if (len <= res_len) {
11010 fprintf(stderrstderr,
11011 "ERROR: WDC: cannot format serial number due to data of unexpected length\n");
11012 return -1;
11013 }
11014
11015 return 0;
11016}
11017
11018static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size)
11019{
11020 int ret = 0;
11021 char *reason_id_file;
11022 char drive_reason_id[PATH_MAX4096] = {0};
11023 char reason_id_path[PATH_MAX4096] = WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli";
11024 struct stat st = {0};
11025
11026 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11027 fprintf(stderrstderr, "%s: ERROR: failed to get drive reason id\n", __func__);
11028 return -1;
11029 }
11030
11031 /* make the nvmecli dir in /usr/local if it doesn't already exist */
11032 if (stat(reason_id_path, &st) == -1) {
11033 if (mkdir(reason_id_path, 0700) < 0) {
11034 fprintf(stderrstderr, "%s: ERROR: failed to mkdir %s: %s\n",
11035 __func__, reason_id_path, libnvme_strerror(errno(*__errno_location ())));
11036 return -1;
11037 }
11038 }
11039
11040 if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
11041 drive_reason_id, ".bin") < 0)
11042 return -ENOMEM12;
11043
11044 fprintf(stderrstderr, "%s: reason id file = %s\n", __func__, reason_id_file);
11045
11046 /* save off the error reason identifier to a file in /usr/local/nvmecli */
11047 ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN128);
11048 free(reason_id_file);
11049
11050 return ret;
11051}
11052
11053static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl)
11054{
11055 int ret = -1;
11056 int verify_file;
11057 char *reason_id_file;
11058 char drive_reason_id[PATH_MAX4096] = {0};
11059
11060 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11061 fprintf(stderrstderr, "%s: ERROR: failed to get drive reason id\n", __func__);
11062 return -1;
11063 }
11064
11065 if (asprintf(&reason_id_file, "%s/%s%s", WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli",
11066 drive_reason_id, ".bin") < 0)
11067 return -ENOMEM12;
11068
11069 /* verify the drive reason id file name and path is valid */
11070 verify_file = nvme_open_rawdata(reason_id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((reason_id_file), (01 | 0100 | 01000), 0666);
11071 if (verify_file < 0) {
11072 ret = -1;
11073 goto free;
11074 }
11075 close(verify_file);
11076
11077 /* remove the reason id file */
11078 ret = remove(reason_id_file);
11079
11080free:
11081 free(reason_id_file);
11082
11083 return ret;
11084}
11085
11086static int wdc_dump_telemetry_hdr(struct libnvme_transport_handle *hdl, int log_id, struct nvme_telemetry_log *log_hdr)
11087{
11088 int ret = 0;
11089
11090 if (log_id == NVME_LOG_LID_TELEMETRY_HOST)
11091 ret = nvme_get_log_create_telemetry_host(hdl, log_hdr);
11092 else
11093 ret = nvme_get_log_telemetry_ctrl(hdl, false0, 0, (void *)log_hdr, 512);
11094
11095 if (ret < 0) {
11096 perror("get-telemetry-log");
11097 } else if (ret > 0) {
11098 nvme_show_status(ret);
11099 fprintf(stderrstderr, "%s: ERROR: Failed to acquire telemetry header, ret = %d!\n", __func__, ret);
11100 }
11101
11102 return ret;
11103}
11104
11105static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id)
11106{
11107 int ret;
11108 struct nvme_telemetry_log *log_hdr;
11109 __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
11110 __u32 reason_id_size = 0;
11111
11112 log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size);
11113 if (!log_hdr) {
11114 fprintf(stderrstderr, "%s: ERROR: malloc failed, size : 0x%x, status: %s\n", __func__, log_hdr_size, libnvme_strerror(errno(*__errno_location ())));
11115 ret = -1;
11116 goto out;
11117 }
11118 memset(log_hdr, 0, log_hdr_size);
11119
11120 ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr);
11121 if (ret) {
11122 fprintf(stderrstderr, "%s: ERROR: get telemetry header failed, ret : %d\n", __func__, ret);
11123 ret = -1;
11124 goto out;
11125 }
11126
11127 reason_id_size = sizeof(log_hdr->rsnident);
11128
11129 if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11130 wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size);
11131
11132 ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
11133
11134out:
11135 free(log_hdr);
11136 return ret;
11137}
11138
11139static void wdc_print_nand_stats_normal(__u16 version, void *data)
11140{
11141 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11142 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11143 __u64 temp_raw;
11144 __u16 temp_norm;
11145 __u64 *temp_ptr = NULL((void*)0);
11146
11147 switch (version) {
11148 case 0:
11149 printf(" NAND Statistics :-\n");
11150 printf(" NAND Writes TLC (Bytes) %s\n",
11151 uint128_t_to_string(
11152 le128_to_cpu(nand_stats->nand_write_tlc)));
11153 printf(" NAND Writes SLC (Bytes) %s\n",
11154 uint128_t_to_string(
11155 le128_to_cpu(nand_stats->nand_write_slc)));
11156 printf(" NAND Program Failures %"PRIu32"u""\n",
11157 (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure));
11158 printf(" NAND Erase Failures %"PRIu32"u""\n",
11159 (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure));
11160 printf(" Bad Block Count %"PRIu32"u""\n",
11161 (uint32_t)le32_to_cpu(nand_stats->bad_block_count));
11162 printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"l" "u""\n",
11163 le64_to_cpu(nand_stats->nand_rec_trigger_event));
11164 printf(" E2E Error Counter %"PRIu64"l" "u""\n",
11165 le64_to_cpu(nand_stats->e2e_error_counter));
11166 printf(" Number Successful NS Resizing Events %"PRIu64"l" "u""\n",
11167 le64_to_cpu(nand_stats->successful_ns_resize_event));
11168 printf(" log page version %"PRIu16"u""\n",
11169 le16_to_cpu(nand_stats->log_page_version));
11170 break;
11171 case 3:
11172 printf(" NAND Statistics V3:-\n");
11173 printf(" TLC Units Written %s\n",
11174 uint128_t_to_string(
11175 le128_to_cpu(nand_stats_v3->nand_write_tlc)));
11176 printf(" SLC Units Written %s\n",
11177 uint128_t_to_string(
11178 le128_to_cpu(nand_stats_v3->nand_write_slc)));
11179 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11180 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11181 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11182 printf(" Bad NAND Blocks Count - Normalized %"PRIu16"u""\n",
11183 le16_to_cpu(temp_norm));
11184 printf(" Bad NAND Blocks Count - Raw %"PRIu64"l" "u""\n",
11185 le64_to_cpu(temp_raw));
11186 printf(" NAND XOR Recovery count %"PRIu64"l" "u""\n",
11187 le64_to_cpu(nand_stats_v3->xor_recovery_count));
11188 printf(" UECC Read Error count %"PRIu64"l" "u""\n",
11189 le64_to_cpu(nand_stats_v3->uecc_read_error_count));
11190 printf(" SSD End to End corrected errors %"PRIu64"l" "u""\n",
11191 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
11192 printf(" SSD End to End detected errors %"PRIu32"u""\n",
11193 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
11194 printf(" SSD End to End uncorrected E2E errors %"PRIu32"u""\n",
11195 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
11196 printf(" System data %% life-used %u\n",
11197 nand_stats_v3->percent_life_used);
11198 printf(" User Data Erase Counts - TLC Min %"PRIu64"l" "u""\n",
11199 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
11200 printf(" User Data Erase Counts - TLC Max %"PRIu64"l" "u""\n",
11201 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
11202 printf(" User Data Erase Counts - SLC Min %"PRIu64"l" "u""\n",
11203 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
11204 printf(" User Data Erase Counts - SLC Max %"PRIu64"l" "u""\n",
11205 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
11206 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11207 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11208 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11209 printf(" Program Fail Count - Normalized %"PRIu16"u""\n",
11210 le16_to_cpu(temp_norm));
11211 printf(" Program Fail Count - Raw %"PRIu64"l" "u""\n",
11212 le64_to_cpu(temp_raw));
11213 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11214 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11215 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11216 printf(" Erase Fail Count - Normalized %"PRIu16"u""\n",
11217 le16_to_cpu(temp_norm));
11218 printf(" Erase Fail Count - Raw %"PRIu64"l" "u""\n",
11219 le64_to_cpu(temp_raw));
11220 printf(" PCIe Correctable Error Count %"PRIu16"u""\n",
11221 le16_to_cpu(nand_stats_v3->correctable_error_count));
11222 printf(" %% Free Blocks (User) %u\n",
11223 nand_stats_v3->percent_free_blocks_user);
11224 printf(" Security Version Number %"PRIu64"l" "u""\n",
11225 le64_to_cpu(nand_stats_v3->security_version_number));
11226 printf(" %% Free Blocks (System) %u\n",
11227 nand_stats_v3->percent_free_blocks_system);
11228 printf(" Data Set Management Commands %s\n",
11229 uint128_t_to_string(
11230 le128_to_cpu(nand_stats_v3->trim_completions)));
11231 printf(" Estimate of Incomplete Trim Data %"PRIu64"l" "u""\n",
11232 le64_to_cpu(nand_stats_v3->trim_completions[16]));
11233 printf(" %% of completed trim %u\n",
11234 nand_stats_v3->trim_completions[24]);
11235 printf(" Background Back-Pressure-Guage %u\n",
11236 nand_stats_v3->back_pressure_guage);
11237 printf(" Soft ECC Error Count %"PRIu64"l" "u""\n",
11238 le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
11239 printf(" Refresh Count %"PRIu64"l" "u""\n",
11240 le64_to_cpu(nand_stats_v3->refresh_count));
11241 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11242 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11243 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11244 printf(" Bad System Nand Block Count - Normalized %"PRIu16"u""\n",
11245 le16_to_cpu(temp_norm));
11246 printf(" Bad System Nand Block Count - Raw %"PRIu64"l" "u""\n",
11247 le64_to_cpu(temp_raw));
11248 printf(" Endurance Estimate %s\n",
11249 uint128_t_to_string(
11250 le128_to_cpu(nand_stats_v3->endurance_estimate)));
11251 printf(" Thermal Throttling Count %u\n",
11252 nand_stats_v3->thermal_throttling_st_ct[0]);
11253 printf(" Thermal Throttling Status %u\n",
11254 nand_stats_v3->thermal_throttling_st_ct[1]);
11255 printf(" Unaligned I/O %"PRIu64"l" "u""\n",
11256 le64_to_cpu(nand_stats_v3->unaligned_IO));
11257 printf(" Physical Media Units Read %s\n",
11258 uint128_t_to_string(
11259 le128_to_cpu(nand_stats_v3->physical_media_units)));
11260 printf(" log page version %"PRIu16"u""\n",
11261 le16_to_cpu(nand_stats_v3->log_page_version));
11262 break;
11263
11264 default:
11265 fprintf(stderrstderr, "WDC: Nand Stats ERROR: Invalid version\n");
11266 break;
11267
11268 }
11269}
11270
11271static void wdc_print_nand_stats_json(__u16 version, void *data)
11272{
11273 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11274 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11275 struct json_object *root = json_create_object()json_object_new_object();
11276 __u64 temp_raw;
11277 __u16 temp_norm;
11278 __u64 *temp_ptr = NULL((void*)0);
11279
11280 switch (version) {
11281 case 0:
11282 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)))
11283 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)))
;
11284 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)))
11285 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)))
;
11286 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)))
11287 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)))
;
11288 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)))
11289 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)))
;
11290 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)))
11291 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)))
;
11292 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
)))
11293 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
)))
;
11294 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)))
11295 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)))
;
11296 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
)))
11297 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
)))
;
11298
11299 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11300 printf("\n");
11301 break;
11302 case 3:
11303 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)))
11304 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)))
;
11305 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)))
11306 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)))
;
11307 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11308 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11309 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11310 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)))
11311 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11312 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)))
11313 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11314 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)))
11315 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)))
;
11316 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)))
11317 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)))
;
11318 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])))
11319 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])))
;
11320 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])))
11321 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])))
;
11322 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])))
11323 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])))
;
11324 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))
11325 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))
;
11326 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])))
11327 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])))
;
11328 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])))
11329 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])))
;
11330 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])))
11331 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])))
;
11332 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])))
11333 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])))
;
11334 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11335 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11336 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11337 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)))
11338 le16_to_cpu(temp_norm))json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11339 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)))
11340 le64_to_cpu(temp_raw))json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11341 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11342 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11343 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11344 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)))
11345 le16_to_cpu(temp_norm))json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11346 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)))
11347 le64_to_cpu(temp_raw))json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11348 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)))
11349 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)))
;
11350 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))
11351 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))
;
11352 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)))
11353 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)))
;
11354 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))
11355 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))
;
11356 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)))
11357 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)))
;
11358 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])))
11359 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])))
;
11360 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]))
11361 nand_stats_v3->trim_completions[24])json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
;
11362 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
))
11363 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
))
;
11364 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)))
11365 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)))
;
11366 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)))
11367 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)))
;
11368 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11369 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11370 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11371 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)))
11372 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)))
;
11373 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)))
11374 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)))
;
11375 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)))
11376 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)))
;
11377 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]))
11378 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]))
;
11379 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]))
11380 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]))
;
11381 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)))
11382 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)))
;
11383 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)))
11384 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)))
;
11385 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)))
11386 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)))
;
11387
11388 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11389 printf("\n");
11390 break;
11391 default:
11392 printf("%s: Invalid Stats Version = %d\n", __func__, version);
11393 break;
11394 }
11395
11396 json_free_object(root)json_object_put(root);
11397
11398}
11399
11400static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats)
11401{
11402 printf(" PCIE Statistics :-\n");
11403 printf(" Unsupported Request Error Counter %20"PRIu64"l" "u""\n",
11404 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
11405 printf(" ECRC Error Status Counter %20"PRIu64"l" "u""\n",
11406 le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
11407 printf(" Malformed TLP Status Counter %20"PRIu64"l" "u""\n",
11408 le64_to_cpu(pcie_stats->malformedTlpStatusCount));
11409 printf(" Receiver Overflow Status Counter %20"PRIu64"l" "u""\n",
11410 le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
11411 printf(" Unexpected Completion Status Counter %20"PRIu64"l" "u""\n",
11412 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
11413 printf(" Complete Abort Status Counter %20"PRIu64"l" "u""\n",
11414 le64_to_cpu(pcie_stats->completeAbortStatusCount));
11415 printf(" Completion Timeout Status Counter %20"PRIu64"l" "u""\n",
11416 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
11417 printf(" Flow Control Error Status Counter %20"PRIu64"l" "u""\n",
11418 le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
11419 printf(" Poisoned TLP Status Counter %20"PRIu64"l" "u""\n",
11420 le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
11421 printf(" Dlink Protocol Error Status Counter %20"PRIu64"l" "u""\n",
11422 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
11423 printf(" Advisory Non Fatal Error Status Counter %20"PRIu64"l" "u""\n",
11424 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
11425 printf(" Replay Timer TO Status Counter %20"PRIu64"l" "u""\n",
11426 le64_to_cpu(pcie_stats->replayTimerToStatusCount));
11427 printf(" Replay Number Rollover Status Counter %20"PRIu64"l" "u""\n",
11428 le64_to_cpu(pcie_stats->replayNumRolloverStCount));
11429 printf(" Bad DLLP Status Counter %20"PRIu64"l" "u""\n",
11430 le64_to_cpu(pcie_stats->badDllpStatusCount));
11431 printf(" Bad TLP Status Counter %20"PRIu64"l" "u""\n",
11432 le64_to_cpu(pcie_stats->badTlpStatusCount));
11433 printf(" Receiver Error Status Counter %20"PRIu64"l" "u""\n",
11434 le64_to_cpu(pcie_stats->receiverErrStatusCount));
11435
11436}
11437
11438static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
11439{
11440 struct json_object *root = json_create_object()json_object_new_object();
11441
11442 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
)))
11443 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
)))
;
11444 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)))
11445 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)))
;
11446 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)))
11447 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)))
;
11448
11449 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
)))
11450 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
)))
;
11451 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
)))
11452 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
)))
;
11453 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
)))
11454 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
)))
;
11455 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
)))
11456 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
)))
;
11457 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
)))
11458 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
)))
;
11459 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)))
11460 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)))
;
11461 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
)))
11462 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
)))
;
11463 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
)))
11464 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
)))
;
11465 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
)))
11466 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
)))
;
11467 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
)))
11468 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
)))
;
11469 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)))
11470 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)))
;
11471 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)))
11472 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)))
;
11473 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
)))
11474 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
)))
;
11475
11476 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11477 printf("\n");
11478
11479 json_free_object(root)json_object_put(root);
11480}
11481
11482static int wdc_do_vs_nand_stats_sn810_2(struct libnvme_transport_handle *hdl, char *format)
11483{
11484 nvme_print_flags_t fmt;
11485 uint8_t *data = NULL((void*)0);
11486 int ret;
11487
11488 data = NULL((void*)0);
11489 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
11490 NVME_NSID_ALL);
11491
11492 if (ret) {
11493 fprintf(stderrstderr, "ERROR: WDC: %s : Failed to retrieve NAND stats\n", __func__);
11494 goto out;
11495 } else {
11496 ret = validate_output_format(format, &fmt);
11497 if (ret < 0) {
11498 fprintf(stderrstderr, "ERROR: WDC: %s : invalid output format\n", __func__);
11499 goto out;
11500 }
11501
11502 /* parse the data */
11503 switch (fmt) {
11504 case NORMAL:
11505 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS0x1);
11506 break;
11507 case JSON:
11508 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS0x1);
11509 break;
11510 default:
11511 break;
11512 }
11513 }
11514
11515out:
11516 free(data);
11517 return ret;
11518}
11519
11520static int wdc_do_vs_nand_stats(struct libnvme_transport_handle *hdl, char *format)
11521{
11522 nvme_print_flags_t fmt;
11523 uint8_t *output = NULL((void*)0);
11524 __u16 version = 0;
11525 int ret;
11526
11527 output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE0x200, sizeof(uint8_t));
11528 if (!output) {
11529 fprintf(stderrstderr, "ERROR: WDC: calloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
11530 ret = -1;
11531 goto out;
11532 }
11533
11534 ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID0xFB,
11535 (void *)output, WDC_NVME_NAND_STATS_SIZE0x200);
11536 if (ret) {
11537 fprintf(stderrstderr, "ERROR: WDC: %s : Failed to retrieve NAND stats\n", __func__);
11538 goto out;
11539 } else {
11540 ret = validate_output_format(format, &fmt);
11541 if (ret < 0) {
11542 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
11543 goto out;
11544 }
11545
11546 version = output[WDC_NVME_NAND_STATS_SIZE0x200 - 2];
11547
11548 /* parse the data */
11549 switch (fmt) {
11550 case NORMAL:
11551 wdc_print_nand_stats_normal(version, output);
11552 break;
11553 case JSON:
11554 wdc_print_nand_stats_json(version, output);
11555 break;
11556 default:
11557 break;
11558 }
11559 }
11560
11561out:
11562 free(output);
11563 return ret;
11564}
11565
11566static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd,
11567 struct plugin *plugin)
11568{
11569 const char *desc = "Retrieve NAND statistics.";
11570 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11571 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11572 __u64 capabilities = 0;
11573 uint32_t read_device_id = 0, read_vendor_id = 0;
11574 int ret;
11575
11576 struct config {
11577 char *output_format;
11578 };
11579
11580 struct config cfg = {
11581 .output_format = "normal",
11582 };
11583
11584 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
11585
11586 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11587 if (ret)
11588 return ret;
11589
11590 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11591 if (ret)
11592 return ret;
11593
11594 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11595
11596 if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200)) {
11597 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
11598 ret = -1;
11599 } else {
11600 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
11601 if (ret < 0) {
11602 fprintf(stderrstderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret);
11603 return -1;
11604 }
11605
11606 switch (read_device_id) {
11607 case WDC_NVME_SN820CL_DEV_ID0x5037:
11608 ret = wdc_do_vs_nand_stats_sn810_2(hdl,
11609 cfg.output_format);
11610 break;
11611 default:
11612 ret = wdc_do_vs_nand_stats(hdl, cfg.output_format);
11613 break;
11614 }
11615 }
11616
11617 if (ret)
11618 fprintf(stderrstderr, "ERROR: WDC: Failure reading NAND statistics, ret = %d\n", ret);
11619
11620 return ret;
11621}
11622
11623static int wdc_do_vs_pcie_stats(struct libnvme_transport_handle *hdl,
11624 struct wdc_vs_pcie_stats *pcieStatsPtr)
11625{
11626 int ret;
11627 struct libnvme_passthru_cmd admin_cmd;
11628 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11629
11630 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
11631 admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE0xD1;
11632 admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
11633 admin_cmd.data_len = pcie_stats_size;
11634
11635 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
11636
11637 return ret;
11638}
11639
11640static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd,
11641 struct plugin *plugin)
11642{
11643 const char *desc = "Retrieve PCIE statistics.";
11644 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11645 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11646 nvme_print_flags_t fmt;
11647 int ret;
11648 __u64 capabilities = 0;
11649 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
11650 struct wdc_vs_pcie_stats *pcieStatsPtr = NULL((void*)0);
11651 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11652
11653 struct config {
11654 char *output_format;
11655 };
11656
11657 struct config cfg = {
11658 .output_format = "normal",
11659 };
11660
11661 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
11662
11663 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11664 if (ret)
11665 return ret;
11666
11667 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11668 if (ret)
11669 return ret;
11670
11671 ret = validate_output_format(cfg.output_format, &fmt);
11672 if (ret < 0) {
11673 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
11674 goto out;
11675 }
11676
11677 pcieStatsPtr = libnvme_alloc_huge(pcie_stats_size, &mh);
11678 if (!pcieStatsPtr) {
11679 fprintf(stderrstderr, "ERROR: WDC: PCIE Stats alloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
11680 ret = -1;
11681 goto out;
11682 }
11683
11684 memset((void *)pcieStatsPtr, 0, pcie_stats_size);
11685
11686 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11687
11688 if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000)) {
11689 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
11690 ret = -1;
11691 } else {
11692 ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr);
11693 if (ret) {
11694 fprintf(stderrstderr, "ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x\n", ret);
11695 } else {
11696 /* parse the data */
11697 switch (fmt) {
11698 case NORMAL:
11699 wdc_print_pcie_stats_normal(pcieStatsPtr);
11700 break;
11701 case JSON:
11702 wdc_print_pcie_stats_json(pcieStatsPtr);
11703 break;
11704 default:
11705 break;
11706 }
11707 }
11708 }
11709out:
11710 return ret;
11711}
11712
11713static int wdc_vs_drive_info(int argc, char **argv,
11714 struct command *command, struct plugin *plugin)
11715{
11716 const char *desc = "Send a vs-drive-info command.";
11717 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11718 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11719 nvme_print_flags_t fmt;
11720 uint64_t capabilities = 0;
11721 int ret;
11722 __le32 result;
11723 __u16 size;
11724 double rev;
11725 struct nvme_id_ctrl ctrl;
11726 char vsData[32] = {0};
11727 char major_rev = 0, minor_rev = 0;
11728 __u8 *data = NULL((void*)0);
11729 __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
11730 __u16 boot_spec_major = 0, boot_spec_minor = 0;
11731 struct json_object *root = NULL((void*)0);
11732 char formatter[41] = { 0 };
11733 char rev_str[16] = { 0 };
11734 uint32_t read_device_id = -1, read_vendor_id = -1;
11735 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
11736 struct ocp_drive_info info;
11737 __u32 data_len = 0;
11738 unsigned int num_dwords = 0;
11739
11740 struct config {
11741 char *output_format;
11742 };
11743
11744 struct config cfg = {
11745 .output_format = "normal",
11746 };
11747
11748 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
11749
11750 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11751 if (ret)
11752 return ret;
11753
11754 ret = validate_output_format(cfg.output_format, &fmt);
11755 if (ret < 0) {
11756 fprintf(stderrstderr, "ERROR: WDC %s invalid output format\n", __func__);
11757 return ret;
11758 }
11759
11760 /* get the id ctrl data used to fill in drive info below */
11761 ret = nvme_identify_ctrl(hdl, &ctrl);
11762 if (ret) {
11763 fprintf(stderrstderr, "ERROR: WDC %s: Identify Controller failed\n", __func__);
11764 return ret;
11765 }
11766
11767 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11768 if (ret || !wdc_check_device(ctx, hdl))
11769 return -1;
11770
11771 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11772
11773 if ((capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000) == WDC_DRIVE_CAP_INFO0x0000000000080000) {
11774 ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id);
11775 if (ret < 0) {
11776 fprintf(stderrstderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret);
11777 goto out;
11778 }
11779
11780 switch (read_device_id) {
11781 case WDC_NVME_SN640_DEV_ID0x2400:
11782 case WDC_NVME_SN640_DEV_ID_10x2401:
11783 case WDC_NVME_SN640_DEV_ID_20x2402:
11784 case WDC_NVME_SN640_DEV_ID_30x2404:
11785 case WDC_NVME_SN650_DEV_ID0x2700:
11786 case WDC_NVME_SN650_DEV_ID_10x2701:
11787 case WDC_NVME_SN650_DEV_ID_20x2702:
11788 case WDC_NVME_SN650_DEV_ID_30x2720:
11789 case WDC_NVME_SN650_DEV_ID_40x2721:
11790 case WDC_NVME_SN655_DEV_ID0x2722:
11791 case WDC_NVME_SN655_DEV_ID_10x2723:
11792 case WDC_NVME_SN560_DEV_ID_10x2712:
11793 case WDC_NVME_SN560_DEV_ID_20x2713:
11794 case WDC_NVME_SN560_DEV_ID_30x2714:
11795 case WDC_NVME_SN550_DEV_ID0x2708:
11796 case WDC_NVME_ZN350_DEV_ID0x5010:
11797 case WDC_NVME_ZN350_DEV_ID_10x5018:
11798 ret = wdc_do_drive_info(hdl, &result);
11799
11800 if (!ret) {
11801 size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
11802 rev = (double)(cpu_to_le32(result) & 0x0000ffff);
11803
11804 if (fmt == NORMAL) {
11805 printf("Drive HW Revision: %4.1f\n", (.1 * rev));
11806 printf("FTL Unit Size: 0x%x KB\n", size);
11807 printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
11808 } else if (fmt == JSON) {
11809 root = json_create_object()json_object_new_object();
11810 sprintf(rev_str, "%4.1f", (.1 * rev));
11811 json_object_add_value_string(root, "Drive HW Revision", rev_str);
11812
11813 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)))
;
11814 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
11815 json_object_add_value_string(root, "Customer SN", formatter);
11816
11817 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11818 printf("\n");
11819
11820 json_free_object(root)json_object_put(root);
11821 }
11822 }
11823 break;
11824 case WDC_NVME_SN730_DEV_ID0x5006:
11825 memcpy(vsData, &ctrl.vs[0], 32);
11826
11827 major_rev = ctrl.sn[12];
11828 minor_rev = ctrl.sn[13];
11829
11830 if (fmt == NORMAL) {
11831 printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev);
11832 printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
11833 } else if (fmt == JSON) {
11834 root = json_create_object()json_object_new_object();
11835 sprintf(rev_str, "%c.%c", major_rev, minor_rev);
11836 json_object_add_value_string(root, "Drive HW Revison", rev_str);
11837 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
11838 json_object_add_value_string(root, "Customer SN", formatter);
11839
11840 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11841 printf("\n");
11842
11843 json_free_object(root)json_object_put(root);
11844 }
11845 break;
11846 case WDC_NVME_SN820CL_DEV_ID0x5037:
11847 /* Get the Drive HW Rev from the C6 Log page */
11848 ret = nvme_get_hw_rev_log(hdl, &data, 0,
11849 NVME_NSID_ALL);
11850 if (!ret) {
11851 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
11852
11853 major_rev = log_data->hw_rev_gdr;
11854
11855 free(data);
11856 data = NULL((void*)0);
11857 } else {
11858 fprintf(stderrstderr, "ERROR: WDC: %s: failure to get hw revision log\n", __func__);
11859 ret = -1;
11860 goto out;
11861 }
11862
11863 /* Get the Smart C0 log page */
11864 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
11865 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
11866 ret = -1;
11867 goto out;
11868 }
11869
11870 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
11871 0, NVME_NSID_ALL);
11872
11873 if (!ret) {
11874 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
11875
11876 /* Set the FTL Unit size */
11877 ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
11878
11879 /* Set the Boot Spec Version */
11880 boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
11881 boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
11882
11883 /* Set the Drive Ownership Status */
11884 tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
11885 free(data);
11886 } else {
11887 fprintf(stderrstderr, "ERROR: WDC: %s: failure to get extended smart cloud log\n", __func__);
11888 ret = -1;
11889 goto out;
11890 }
11891
11892 if (fmt == NORMAL) {
11893 printf("Drive HW Revision: %2d\n", major_rev);
11894 printf("FTL Unit Size: %d\n", ftl_unit_size);
11895 printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
11896 printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
11897
11898 } else if (fmt == JSON) {
11899 root = json_create_object()json_object_new_object();
11900
11901 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))
;
11902 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))
;
11903 sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor);
11904 json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
11905 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))
;
11906
11907 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11908 printf("\n");
11909
11910 json_free_object(root)json_object_put(root);
11911 }
11912
11913 break;
11914 case WDC_NVME_SN861_DEV_ID0x2750:
11915 case WDC_NVME_SN861_DEV_ID_10x2751:
11916 case WDC_NVME_SN861_DEV_ID_20x2752:
11917 data_len = sizeof(info);
11918 num_dwords = data_len / 4;
11919 if (data_len % 4 != 0)
11920 num_dwords += 1;
11921
11922 struct libnvme_passthru_cmd cmd = {
11923 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
11924 .cdw10 = num_dwords,
11925 .cdw12 = WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2,
11926 .addr = (__u64)(uintptr_t)&info,
11927 .data_len = data_len,
11928 };
11929 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11930 if (!ret) {
11931 __u16 hw_rev_major, hw_rev_minor;
11932
11933 hw_rev_major = le32_to_cpu(info.hw_revision) / 10;
11934 hw_rev_minor = le32_to_cpu(info.hw_revision) % 10;
11935 if (fmt == NORMAL) {
11936 printf("HW Revision : %" PRIu32"u" ".%" PRIu32"u" "\n",
11937 hw_rev_major, hw_rev_minor);
11938 printf("FTL Unit Size : %" PRIu32"u" "\n",
11939 le32_to_cpu(info.ftl_unit_size));
11940 } else if (fmt == JSON) {
11941 char buf[20];
11942
11943 root = json_create_object()json_object_new_object();
11944
11945 memset((void *)buf, 0, 20);
11946 sprintf(buf, "%" PRIu32"u" ".%" PRIu32"u",
11947 hw_rev_major, hw_rev_minor);
11948
11949 json_object_add_value_string(root,
11950 "hw_revision", buf);
11951 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)))
11952 "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
11953 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)))
;
11954
11955 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11956 printf("\n");
11957 json_free_object(root)json_object_put(root);
11958 }
11959 }
11960 break;
11961 default:
11962 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
11963 ret = -1;
11964 break;
11965 }
11966 } else {
11967 fprintf(stderrstderr, "ERROR: WDC: capability not supported by this device\n");
11968 ret = -1;
11969 }
11970
11971out:
11972 nvme_show_status(ret);
11973 return ret;
11974}
11975
11976static int wdc_vs_temperature_stats(int argc, char **argv,
11977 struct command *command, struct plugin *plugin)
11978{
11979 const char *desc = "Send a vs-temperature-stats command.";
11980 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11981 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11982 struct nvme_smart_log smart_log;
11983 struct nvme_id_ctrl id_ctrl;
11984 nvme_print_flags_t fmt;
11985 uint64_t capabilities = 0;
11986 __u64 hctm_tmt;
11987 int temperature, temp_tmt1, temp_tmt2;
11988 int ret;
11989
11990 struct config {
11991 char *output_format;
11992 };
11993
11994 struct config cfg = {
11995 .output_format = "normal",
11996 };
11997
11998 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
11999
12000 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12001 if (ret)
12002 return ret;
12003
12004 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12005 if (ret)
12006 return ret;
12007
12008 ret = validate_output_format(cfg.output_format, &fmt);
12009 if (ret < 0) {
12010 fprintf(stderrstderr, "ERROR: WDC: invalid output format\n");
12011 goto out;
12012 }
12013
12014 /* check if command is supported */
12015 wdc_check_device(ctx, hdl);
12016 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12017 if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) != WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) {
12018 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
12019 ret = -1;
12020 goto out;
12021 }
12022
12023 /* get the temperature stats or report errors */
12024 ret = nvme_identify_ctrl(hdl, &id_ctrl);
12025 if (ret)
12026 goto out;
12027 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
12028 if (ret)
12029 goto out;
12030
12031 /* convert from kelvins to degrees Celsius */
12032 temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
12033
12034 /* retrieve HCTM Thermal Management Temperatures */
12035 nvme_get_features_simple(hdl, 0x10,
12036 NVME_GET_FEATURES_SEL_CURRENT, &hctm_tmt);
12037 temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
12038 temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
12039
12040 if (fmt == NORMAL) {
12041 /* print the temperature stats */
12042 printf("Temperature Stats for NVME device:%s namespace-id:%x\n",
12043 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
12044
12045 printf("Current Composite Temperature : %d °C\n", temperature);
12046 printf("WCTEMP : %"PRIu16"u"" °C\n", id_ctrl.wctemp - 273);
12047 printf("CCTEMP : %"PRIu16"u"" °C\n", id_ctrl.cctemp - 273);
12048 printf("DITT support : 0\n");
12049 printf("HCTM support : %"PRIu16"u""\n", id_ctrl.hctma);
12050
12051 printf("HCTM Light (TMT1) : %"PRIu16"u"" °C\n", temp_tmt1);
12052 printf("TMT1 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp1_trans_count);
12053 printf("TMT1 Total Time : %"PRIu32"u""\n", smart_log.thm_temp1_total_time);
12054
12055 printf("HCTM Heavy (TMT2) : %"PRIu16"u"" °C\n", temp_tmt2);
12056 printf("TMT2 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp2_trans_count);
12057 printf("TMT2 Total Time : %"PRIu32"u""\n", smart_log.thm_temp2_total_time);
12058 printf("Thermal Shutdown Threshold : 95 °C\n");
12059 } else if (fmt == JSON) {
12060 struct json_object *root;
12061
12062 root = json_create_object()json_object_new_object();
12063
12064 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)))
;
12065 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)))
;
12066 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)))
;
12067 json_object_add_value_int(root, "DITT support", 0)json_object_object_add(root, "DITT support", json_object_new_int
(0))
;
12068 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)))
;
12069
12070 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)))
;
12071 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)))
;
12072 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)))
;
12073
12074 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)))
;
12075 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)))
;
12076 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)))
;
12077 json_object_add_value_int(root, "Thermal Shutdown Threshold", 95)json_object_object_add(root, "Thermal Shutdown Threshold", json_object_new_int
(95))
;
12078
12079 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12080 printf("\n");
12081
12082 json_free_object(root)json_object_put(root);
12083 } else {
12084 printf("%s: Invalid format\n", __func__);
12085 }
12086
12087out:
12088 nvme_show_status(ret);
12089 return ret;
12090}
12091
12092static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12093{
12094 const char *desc = "Send a capabilities command.";
12095 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12096 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12097 uint64_t capabilities = 0;
12098 int ret;
12099
12100 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
12101
12102 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12103 if (ret)
12104 return ret;
12105
12106 /* get capabilities */
12107 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12108 if (ret || !wdc_check_device(ctx, hdl))
12109 return -1;
12110
12111 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12112
12113 /* print command and supported status */
12114 printf("WDC Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
12115 printf("cap-diag : %s\n",
12116 capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 ? "Supported" : "Not Supported");
12117 printf("drive-log : %s\n",
12118 capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 ? "Supported" : "Not Supported");
12119 printf("get-crash-dump : %s\n",
12120 capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 ? "Supported" : "Not Supported");
12121 printf("get-pfail-dump : %s\n",
12122 capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 ? "Supported" : "Not Supported");
12123 printf("id-ctrl : Supported\n");
12124 printf("purge : %s\n",
12125 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12126 printf("purge-monitor : %s\n",
12127 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12128 printf("vs-internal-log : %s\n",
12129 capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
? "Supported" : "Not Supported");
12130 printf("vs-nand-stats : %s\n",
12131 capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
12132 printf("vs-smart-add-log : %s\n",
12133 capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
12134 printf("--C0 Log Page : %s\n",
12135 capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
12136 printf("--C1 Log Page : %s\n",
12137 capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
12138 printf("--C3 Log Page : %s\n",
12139 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12140 printf("--CA Log Page : %s\n",
12141 capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
12142 printf("--D0 Log Page : %s\n",
12143 capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
12144 printf("clear-pcie-correctable-errors : %s\n",
12145 capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
12146 printf("drive-essentials : %s\n",
12147 capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 ? "Supported" : "Not Supported");
12148 printf("get-drive-status : %s\n",
12149 capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
12150 printf("clear-assert-dump : %s\n",
12151 capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
12152 printf("drive-resize : %s\n",
12153 capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100 ? "Supported" : "Not Supported");
12154 printf("vs-fw-activate-history : %s\n",
12155 capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" : "Not Supported");
12156 printf("clear-fw-activate-history : %s\n",
12157 capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" : "Not Supported");
12158 printf("vs-telemetry-controller-option: %s\n",
12159 capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
12160 printf("vs-error-reason-identifier : %s\n",
12161 capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
12162 printf("log-page-directory : %s\n",
12163 capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
12164 printf("namespace-resize : %s\n",
12165 capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
12166 printf("vs-drive-info : %s\n",
12167 capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
12168 printf("vs-temperature-stats : %s\n",
12169 capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
12170 printf("cloud-SSD-plugin-version : %s\n",
12171 capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
12172 printf("vs-pcie-stats : %s\n",
12173 capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
12174 printf("get-error-recovery-log : %s\n",
12175 capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
12176 printf("get-dev-capabilities-log : %s\n",
12177 capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
12178 printf("get-unsupported-reqs-log : %s\n",
12179 capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
12180 printf("get-latency-monitor-log : %s\n",
12181 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12182 printf("cloud-boot-SSD-version : %s\n",
12183 capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" : "Not Supported");
12184 printf("vs-cloud-log : %s\n",
12185 capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
12186 printf("vs-hw-rev-log : %s\n",
12187 capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
12188 printf("vs-device_waf : %s\n",
12189 capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
12190 printf("set-latency-monitor-feature : %s\n",
12191 capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
12192 printf("capabilities : Supported\n");
12193 return 0;
12194}
12195
12196static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd,
12197 struct plugin *plugin)
12198{
12199 const char *desc = "Get Cloud SSD Plugin Version command.";
12200 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12201 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12202 uint64_t capabilities = 0;
12203 int ret;
12204
12205 NVME_ARGS(opts)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
12206
12207 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12208 if (ret)
12209 return ret;
12210
12211 /* get capabilities */
12212 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12213 if (ret || !wdc_check_device(ctx, hdl))
12214 return -1;
12215
12216 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12217
12218 if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) {
12219 /* print command and supported status */
12220 printf("WDC Cloud SSD Plugin Version: 1.0\n");
12221 } else {
12222 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
12223 }
12224
12225 return 0;
12226}
12227
12228static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd,
12229 struct plugin *plugin)
12230{
12231 const char *desc = "Get Cloud Boot SSD Version command.";
12232 const char *namespace_id = "desired namespace id";
12233 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12234 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12235 uint64_t capabilities = 0;
12236 int ret;
12237 int major = 0, minor = 0;
12238 __u8 *data = NULL((void*)0);
12239 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12240
12241 struct config {
12242 __u32 namespace_id;
12243 };
12244
12245 struct config cfg = {
12246 .namespace_id = NVME_NSID_ALL,
12247 };
12248
12249 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
12250 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
12251
12252 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12253 if (ret)
12254 return ret;
12255
12256 /* get capabilities */
12257 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12258 if (ret || !wdc_check_device(ctx, hdl))
12259 return -1;
12260
12261 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12262
12263 if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) {
12264 /* Get the 0xC0 Smart Cloud Attribute V1 log data */
12265 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
12266 cfg.namespace_id);
12267
12268 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12269 if (!ret) {
12270 major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12271 minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12272
12273 /* print the version returned from the log page */
12274 printf("HyperScale Boot Version: %d.%d\n", major, minor);
12275 } else {
12276 fprintf(stderrstderr, "ERROR: WDC: Unable to read Extended Smart/C0 Log Page data\n");
12277 ret = -1;
12278 }
12279
12280 free(data);
12281 } else {
12282 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
12283 }
12284
12285 return ret;
12286}
12287
12288static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12289{
12290 const char *desc = "Get Enclosure Log.";
12291 const char *file = "Output file pathname.";
12292 const char *size = "Data retrieval transfer size.";
12293 const char *log = "Enclosure Log Page ID.";
12294 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12295 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12296 FILE *output_fd;
12297 int xfer_size = 0;
12298 int len;
12299 int err = 0;
12300
12301 struct config {
12302 char *file;
12303 __u32 xfer_size;
12304 __u32 log_id;
12305 };
12306
12307 struct config cfg = {
12308 .file = NULL((void*)0),
12309 .xfer_size = 0,
12310 .log_id = 0xffffffff,
12311 };
12312
12313 NVME_ARGS(opts,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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
12314 OPT_FILE("output-file", 'O', &cfg.file, file),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
12315 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size),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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
12316 OPT_UINT("log-id", 'l', &cfg.log_id, log))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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
12317
12318 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12319 if (err)
12320 return err;
12321
12322 if (!wdc_enc_check_model(hdl))
12323 return -EINVAL22;
12324
12325 if (cfg.log_id > 0xff) {
12326 fprintf(stderrstderr,
12327 "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n",
12328 cfg.log_id);
12329 return -EINVAL22;
12330 }
12331
12332 if (cfg.xfer_size) {
12333 xfer_size = cfg.xfer_size;
12334 if (!wdc_check_power_of_2(cfg.xfer_size)) {
12335 fprintf(stderrstderr, "%s: ERROR: xfer-size (%d) must be a power of 2\n",
12336 __func__, cfg.xfer_size);
12337 return -EINVAL22;
12338 }
12339 }
12340
12341 /* Log IDs are only for specific enclosures */
12342 if (cfg.log_id) {
12343 xfer_size = (xfer_size) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000;
12344 len = !cfg.file ? 0 : strlen(cfg.file);
12345 if (len > 0) {
12346 output_fd = fopen(cfg.file, "wb");
12347 if (!output_fd) {
12348 fprintf(stderrstderr, "%s: ERROR: opening:%s: %s\n", __func__, cfg.file,
12349 libnvme_strerror(errno(*__errno_location ())));
12350 return -EINVAL22;
12351 }
12352 } else {
12353 output_fd = stdoutstdout;
12354 }
12355 if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 ||
12356 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 ||
12357 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 ||
12358 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4) {
12359 fprintf(stderrstderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id,
12360 cfg.file);
12361 err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size,
12362 WDC_NVME_ENC_NIC_LOG_SIZE0x400000, output_fd);
12363 } else {
12364 fprintf(stderrstderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id,
12365 cfg.file);
12366 err = wdc_enc_submit_move_data(hdl, NULL((void*)0), 0, xfer_size, output_fd,
12367 cfg.log_id, 0, 0);
12368 }
12369
12370 if (err == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12371 fprintf(stderrstderr, "No Log/Crashdump available\n");
12372 err = 0;
12373 } else if (err) {
12374 fprintf(stderrstderr, "ERROR: 0x%x Failed to collect log-id:%x\n", err,
12375 cfg.log_id);
12376 }
12377 }
12378 return err;
12379}
12380
12381static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len,
12382 int xfer_size, FILE *out, int log_id,
12383 int cdw14, int cdw15)
12384{
12385 struct timespec time;
12386 uint32_t response_size, more;
12387 int err;
12388 int handle;
12389 uint32_t offset = 0;
12390 char *buf;
12391
12392 buf = (char *)malloc(sizeof(__u8) * xfer_size);
12393 if (!buf) {
12394 fprintf(stderrstderr, "%s: ERROR: malloc: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
12395 return -1;
12396 }
12397 /* send something no matter what */
12398 cmd = (len) ? cmd : buf;
12399 len = (len) ? len : 0x20;
12400
12401 struct libnvme_passthru_cmd nvme_cmd = {
12402 .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND0xC9,
12403 .nsid = 0,
12404 .addr = (__u64)(uintptr_t) cmd,
12405 .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t),
12406 .cdw10 = len,
12407 .cdw12 = log_id,
12408 .cdw13 = 0,
12409 .cdw14 = cdw14,
12410 .cdw15 = cdw15,
12411 };
12412
12413 clock_gettime(CLOCK_REALTIME0, &time);
12414 srand(time.tv_nsec);
12415 handle = random(); /* Handle to associate send request with receive request */
12416 nvme_cmd.cdw11 = handle;
12417
12418#ifdef WDC_NVME_CLI_DEBUG
12419 unsigned char *d = (unsigned char *)nvme_cmd.addr;
12420 unsigned char *md = (unsigned char *)nvme_cmd.metadata;
12421
12422 printf("NVME_ADMIN_COMMAND:\n");
12423 printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ",
12424 nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2);
12425 printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, "
12426 nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10);
12427 printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, "
12428 nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15);
12429 printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n",
12430 nvme_cmd.timeout_ms, nvme_cmd.result, md, d);
12431#endif
12432 nvme_cmd.result = 0;
12433 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12434 if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) {
12435 fprintf(stderrstderr, "%s: WARNING : WDC: No log ID:x%x available\n", __func__, log_id);
12436 } else if (err) {
12437 fprintf(stderrstderr, "%s: ERROR: WDC: NVMe Snd Mgmt\n", __func__);
12438 nvme_show_status(err);
12439 } else {
12440 if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12441 free(buf);
12442 return WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF;
12443 }
12444
12445 do {
12446 /* Sent request, now go retrieve response */
12447 nvme_cmd.flags = 0;
12448 nvme_cmd.opcode = WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA;
12449 nvme_cmd.addr = (__u64)(uintptr_t) buf;
12450 nvme_cmd.data_len = xfer_size;
12451 nvme_cmd.cdw10 = xfer_size / sizeof(uint32_t);
12452 nvme_cmd.cdw11 = handle;
12453 nvme_cmd.cdw12 = log_id;
12454 nvme_cmd.cdw13 = offset / sizeof(uint32_t);
12455 nvme_cmd.cdw14 = cdw14;
12456 nvme_cmd.cdw15 = cdw15;
12457 nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
12458 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12459 if (err) {
12460 more = 0;
12461 fprintf(stderrstderr, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__);
12462 nvme_show_status(err);
12463 } else {
12464 more = nvme_cmd.result & WDC_RESULT_MORE_DATA0x80000000;
12465 response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA0x80000000;
12466 fwrite(buf, response_size, 1, out);
12467 offset += response_size;
12468 if (more && (response_size & (sizeof(uint32_t)-1))) {
12469 fprintf(stderrstderr, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned\n",
12470 __func__, response_size);
12471 }
12472 }
12473 } while (more);
12474 }
12475
12476 free(buf);
12477 return err;
12478}
12479
12480static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out)
12481{
12482 __u8 *dump_data;
12483 __u32 curr_data_offset, curr_data_len;
12484 int i, ret = -1;
12485 struct libnvme_passthru_cmd admin_cmd;
12486 __u32 dump_length = data_len;
12487 __u32 numd;
12488 __u16 numdu, numdl;
12489
12490 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
12491 if (!dump_data) {
12492 fprintf(stderrstderr, "%s: ERROR: malloc: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
12493 return -1;
12494 }
12495 memset(dump_data, 0, sizeof(__u8) * dump_length);
12496 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12497 curr_data_offset = 0;
12498 curr_data_len = xfer_size;
12499 i = 0;
12500
12501 numd = (curr_data_len >> 2) - 1;
12502 numdu = numd >> 16;
12503 numdl = numd & 0xffff;
12504 admin_cmd.opcode = nvme_admin_get_log_page;
12505 admin_cmd.nsid = curr_data_offset;
12506 admin_cmd.addr = (__u64)(uintptr_t) dump_data;
12507 admin_cmd.data_len = curr_data_len;
12508 admin_cmd.cdw10 = log_id | (numdl << 16);
12509 admin_cmd.cdw11 = numdu;
12510
12511 while (curr_data_offset < data_len) {
12512#ifdef WDC_NVME_CLI_DEBUG
12513 fprintf(stderrstderr,
12514 "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",
12515 admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10,
12516 admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14);
12517#endif
12518 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
12519 if (ret) {
12520 nvme_show_status(ret);
12521 fprintf(stderrstderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
12522 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr);
12523 break;
12524 }
12525
12526 if ((curr_data_offset + xfer_size) <= data_len)
12527 curr_data_len = xfer_size;
12528 else
12529 curr_data_len = data_len - curr_data_offset; /* last transfer */
12530
12531 curr_data_offset += curr_data_len;
12532 numd = (curr_data_len >> 2) - 1;
12533 numdu = numd >> 16;
12534 numdl = numd & 0xffff;
12535 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
12536 admin_cmd.nsid = curr_data_offset;
12537 admin_cmd.data_len = curr_data_len;
12538 admin_cmd.cdw10 = log_id | (numdl << 16);
12539 admin_cmd.cdw11 = numdu;
12540 i++;
12541 }
12542 fwrite(dump_data, data_len, 1, out);
12543 free(dump_data);
12544 return ret;
12545}
12546
12547//------------------------------------------------------------------------------------
12548// Description: set latency monitor feature
12549//
12550int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd,
12551 struct plugin *plugin)
12552{
12553 const char *desc = "Set Latency Monitor feature.";
12554
12555 struct feature_latency_monitor buf = {0,};
12556 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12557 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12558 uint64_t capabilities = 0;
12559 __u64 result;
12560 int ret;
12561
12562 const char *active_bucket_timer_threshold =
12563 "This is the value that loads the Active Bucket Timer Threshold.";
12564 const char *active_threshold_a =
12565 "This is the value that loads into the Active Threshold A.";
12566 const char *active_threshold_b =
12567 "This is the value that loads into the Active Threshold B.";
12568 const char *active_threshold_c =
12569 "This is the value that loads into the Active Threshold C.";
12570 const char *active_threshold_d =
12571 "This is the value that loads into the Active Threshold D.";
12572 const char *active_latency_config =
12573 "This is the value that loads into the Active Latency Configuration.";
12574 const char *active_latency_minimum_window =
12575 "This is the value that loads into the Active Latency Minimum Window.";
12576 const char *debug_log_trigger_enable =
12577 "This is the value that loads into the Debug Log Trigger Enable.";
12578 const char *discard_debug_log = "Discard Debug Log.";
12579 const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable.";
12580
12581 struct config {
12582 __u16 active_bucket_timer_threshold;
12583 __u8 active_threshold_a;
12584 __u8 active_threshold_b;
12585 __u8 active_threshold_c;
12586 __u8 active_threshold_d;
12587 __u16 active_latency_config;
12588 __u8 active_latency_minimum_window;
12589 __u16 debug_log_trigger_enable;
12590 __u8 discard_debug_log;
12591 __u8 latency_monitor_feature_enable;
12592 };
12593
12594 struct config cfg = {
12595 .active_bucket_timer_threshold = 0x7E0,
12596 .active_threshold_a = 0x5,
12597 .active_threshold_b = 0x13,
12598 .active_threshold_c = 0x1E,
12599 .active_threshold_d = 0x2E,
12600 .active_latency_config = 0xFFF,
12601 .active_latency_minimum_window = 0xA,
12602 .debug_log_trigger_enable = 0,
12603 .discard_debug_log = 0,
12604 .latency_monitor_feature_enable = 0x7,
12605 };
12606
12607 NVME_ARGS(opts,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12608 OPT_UINT("active_bucket_timer_threshold", 't',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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12609 &cfg.active_bucket_timer_threshold,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12610 active_bucket_timer_threshold),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12611 OPT_UINT("active_threshold_a", 'a', &cfg.active_threshold_a,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12612 active_threshold_a),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12613 OPT_UINT("active_threshold_b", 'b', &cfg.active_threshold_b,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12614 active_threshold_b),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12615 OPT_UINT("active_threshold_c", 'c', &cfg.active_threshold_c,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12616 active_threshold_c),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12617 OPT_UINT("active_threshold_d", 'd', &cfg.active_threshold_d,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12618 active_threshold_d),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12619 OPT_UINT("active_latency_config", 'f',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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12620 &cfg.active_latency_config, active_latency_config),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12621 OPT_UINT("active_latency_minimum_window", 'w',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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12622 &cfg.active_latency_minimum_window,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12623 active_latency_minimum_window),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12624 OPT_UINT("debug_log_trigger_enable", 'r',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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12625 &cfg.debug_log_trigger_enable, debug_log_trigger_enable),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12626 OPT_UINT("discard_debug_log", 'l', &cfg.discard_debug_log,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12627 discard_debug_log),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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12628 OPT_UINT("latency_monitor_feature_enable", 'e',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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12629 &cfg.latency_monitor_feature_enable,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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
12630 latency_monitor_feature_enable))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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
12631
12632 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12633
12634 if (ret < 0)
12635 return ret;
12636
12637 /* get capabilities */
12638 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12639 if (ret || !wdc_check_device(ctx, hdl))
12640 return -1;
12641
12642 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12643
12644 if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000)) {
12645 fprintf(stderrstderr, "ERROR: WDC: unsupported device for this command\n");
12646 return -1;
12647 }
12648
12649 memset(&buf, 0, sizeof(struct feature_latency_monitor));
12650
12651 buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold;
12652 buf.active_threshold_a = cfg.active_threshold_a;
12653 buf.active_threshold_b = cfg.active_threshold_b;
12654 buf.active_threshold_c = cfg.active_threshold_c;
12655 buf.active_threshold_d = cfg.active_threshold_d;
12656 buf.active_latency_config = cfg.active_latency_config;
12657 buf.active_latency_minimum_window = cfg.active_latency_minimum_window;
12658 buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable;
12659 buf.discard_debug_log = cfg.discard_debug_log;
12660 buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable;
12661
12662 ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR0xC5, 1, 0, 0, 0,
12663 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result);
12664
12665 if (ret < 0) {
12666 perror("set-feature");
12667 } else if (!ret) {
12668 printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n",
12669 NVME_FEAT_OCP_LATENCY_MONITOR0xC5);
12670 printf("active bucket timer threshold: 0x%x\n",
12671 buf.active_bucket_timer_threshold);
12672 printf("active threshold a: 0x%x\n", buf.active_threshold_a);
12673 printf("active threshold b: 0x%x\n", buf.active_threshold_b);
12674 printf("active threshold c: 0x%x\n", buf.active_threshold_c);
12675 printf("active threshold d: 0x%x\n", buf.active_threshold_d);
12676 printf("active latency config: 0x%x\n", buf.active_latency_config);
12677 printf("active latency minimum window: 0x%x\n",
12678 buf.active_latency_minimum_window);
12679 printf("debug log trigger enable: 0x%x\n",
12680 buf.debug_log_trigger_enable);
12681 printf("discard debug log: 0x%x\n", buf.discard_debug_log);
12682 printf("latency monitor feature enable: 0x%x\n",
12683 buf.latency_monitor_feature_enable);
12684 } else if (ret > 0)
12685 fprintf(stderrstderr, "NVMe Status:%s(%x)\n",
12686 libnvme_status_to_string(ret, false0), ret);
12687
12688 return ret;
12689}
12690
12691/*
12692 * Externally available functions used to call the WDC Plugin commands
12693 */
12694int run_wdc_cloud_ssd_plugin_version(int argc, char **argv,
12695 struct command *command,
12696 struct plugin *plugin)
12697{
12698 return wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
12699}
12700
12701int run_wdc_vs_internal_fw_log(int argc, char **argv,
12702 struct command *command,
12703 struct plugin *plugin)
12704{
12705 return wdc_vs_internal_fw_log(argc, argv, command, plugin);
12706}
12707
12708int run_wdc_vs_nand_stats(int argc, char **argv,
12709 struct command *command,
12710 struct plugin *plugin)
12711{
12712 return wdc_vs_nand_stats(argc, argv, command, plugin);
12713}
12714
12715int run_wdc_vs_smart_add_log(int argc, char **argv,
12716 struct command *command,
12717 struct plugin *plugin)
12718{
12719 return wdc_vs_smart_add_log(argc, argv, command, plugin);
12720}
12721
12722int run_wdc_clear_pcie_correctable_errors(int argc, char **argv,
12723 struct command *command,
12724 struct plugin *plugin)
12725{
12726 return wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
12727}
12728
12729int run_wdc_drive_status(int argc, char **argv,
12730 struct command *command,
12731 struct plugin *plugin)
12732{
12733 return wdc_drive_status(argc, argv, command, plugin);
12734}
12735
12736int run_wdc_clear_assert_dump(int argc, char **argv,
12737 struct command *command,
12738 struct plugin *plugin)
12739{
12740 return wdc_clear_assert_dump(argc, argv, command, plugin);
12741}
12742
12743int run_wdc_drive_resize(int argc, char **argv,
12744 struct command *command,
12745 struct plugin *plugin)
12746{
12747 return wdc_drive_resize(argc, argv, command, plugin);
12748}
12749
12750int run_wdc_vs_fw_activate_history(int argc, char **argv,
12751 struct command *command,
12752 struct plugin *plugin)
12753{
12754 return wdc_vs_fw_activate_history(argc, argv, command, plugin);
12755}
12756
12757int run_wdc_clear_fw_activate_history(int argc, char **argv,
12758 struct command *command,
12759 struct plugin *plugin)
12760{
12761 return wdc_clear_fw_activate_history(argc, argv, command, plugin);
12762}
12763
12764int run_wdc_vs_telemetry_controller_option(int argc, char **argv,
12765 struct command *command,
12766 struct plugin *plugin)
12767{
12768 return wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
12769}
12770
12771int run_wdc_reason_identifier(int argc, char **argv,
12772 struct command *command,
12773 struct plugin *plugin)
12774{
12775 return wdc_reason_identifier(argc, argv, command, plugin);
12776}
12777
12778int run_wdc_log_page_directory(int argc, char **argv,
12779 struct command *command,
12780 struct plugin *plugin)
12781{
12782 return wdc_log_page_directory(argc, argv, command, plugin);
12783}
12784
12785int run_wdc_namespace_resize(int argc, char **argv,
12786 struct command *command,
12787 struct plugin *plugin)
12788{
12789 return wdc_namespace_resize(argc, argv, command, plugin);
12790}
12791
12792int run_wdc_vs_drive_info(int argc, char **argv,
12793 struct command *command,
12794 struct plugin *plugin)
12795{
12796 return wdc_vs_drive_info(argc, argv, command, plugin);
12797}
12798
12799int run_wdc_vs_pcie_stats(int argc, char **argv,
12800 struct command *command,
12801 struct plugin *plugin)
12802{
12803 return wdc_vs_pcie_stats(argc, argv, command, plugin);
12804}
12805
12806int run_wdc_get_latency_monitor_log(int argc, char **argv,
12807 struct command *command,
12808 struct plugin *plugin)
12809{
12810 return wdc_get_latency_monitor_log(argc, argv, command, plugin);
12811}
12812
12813int run_wdc_get_error_recovery_log(int argc, char **argv,
12814 struct command *command,
12815 struct plugin *plugin)
12816{
12817 return wdc_get_error_recovery_log(argc, argv, command, plugin);
12818}
12819
12820int run_wdc_get_dev_capabilities_log(int argc, char **argv,
12821 struct command *command,
12822 struct plugin *plugin)
12823{
12824 return wdc_get_dev_capabilities_log(argc, argv, command, plugin);
12825}
12826
12827int run_wdc_get_unsupported_reqs_log(int argc, char **argv,
12828 struct command *command,
12829 struct plugin *plugin)
12830{
12831 return wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
12832}
12833
12834int run_wdc_cloud_boot_SSD_version(int argc, char **argv,
12835 struct command *command,
12836 struct plugin *plugin)
12837{
12838 return wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
12839}
12840
12841int run_wdc_vs_cloud_log(int argc, char **argv,
12842 struct command *command,
12843 struct plugin *plugin)
12844{
12845 return wdc_vs_cloud_log(argc, argv, command, plugin);
12846}
12847
12848int run_wdc_vs_hw_rev_log(int argc, char **argv,
12849 struct command *command,
12850 struct plugin *plugin)
12851{
12852 return wdc_vs_hw_rev_log(argc, argv, command, plugin);
12853}
12854
12855int run_wdc_vs_device_waf(int argc, char **argv,
12856 struct command *command,
12857 struct plugin *plugin)
12858{
12859 return wdc_vs_device_waf(argc, argv, command, plugin);
12860}
12861
12862int run_wdc_set_latency_monitor_feature(int argc, char **argv,
12863 struct command *command,
12864 struct plugin *plugin)
12865{
12866 return wdc_set_latency_monitor_feature(argc, argv, command, plugin);
12867}
12868
12869int run_wdc_vs_temperature_stats(int argc, char **argv,
12870 struct command *command,
12871 struct plugin *plugin)
12872{
12873 return wdc_vs_temperature_stats(argc, argv, command, plugin);
12874}
12875
12876int run_wdc_cu_smart_log(int argc, char **argv,
12877 struct command *command,
12878 struct plugin *plugin)
12879{
12880 return wdc_cu_smart_log(argc, argv, command, plugin);
12881}
12882
12883
12884__u32 run_wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx,
12885 struct libnvme_transport_handle *hdl)
12886{
12887 return wdc_get_fw_cust_id(ctx, hdl);
12888}
12889
12890bool_Bool run_wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
12891 struct libnvme_transport_handle *hdl,
12892 __u8 log_id,
12893 __u8 uuid_index)
12894{
12895 return wdc_nvme_check_supported_log_page(ctx,
12896 hdl,
12897 log_id,
12898 uuid_index);
12899}
12900
12901__u64 run_wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx,
12902 struct libnvme_transport_handle *hdl)
12903{
12904 return wdc_get_drive_capabilities(ctx, hdl);
12905}