Bug Summary

File:.build-ci/../plugins/wdc/wdc-nvme.c
Warning:line 2166, column 6
3rd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name wdc-nvme.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-11-02-081605-642-1 -x c ../plugins/wdc/wdc-nvme.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 <dirent.h>
26#include <errno(*__errno_location ()).h>
27#include <fcntl.h>
28#include <inttypes.h>
29#include <limits.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35#include <libnvme.h>
36
37#include <ccan/array_size/array_size.h>
38#include <ccan/endian/endian.h>
39#include <ccan/minmax/minmax.h>
40#include <shared/archive-util.h>
41#include <shared/compiler-attributes-util.h>
42#include <shared/crypto-util.h>
43#include <shared/fs-util.h>
44#include <shared/hex-util.h>
45#include <shared/io-util.h>
46#include <shared/parse-util.h>
47#include <shared/string-util.h>
48#include <shared/time-util.h>
49#include <shared/uint128-util.h>
50#include <shared/unaligned-util.h>
51
52#include "global-ctx.h"
53#include "nvme-cmds.h"
54#include "nvme-pci-ids.h"
55#include "nvme-print.h"
56#include "plugin.h"
57#include "src/cleanup.h"
58
59#define WDC_PLUGIN_VERSION"2.15.1" "2.15.1"
60
61#include "wdc-nvme-cmds.h"
62#include "wdc-utils.h"
63
64#define WRITE_SIZE(sizeof(__u8) * 4096) (sizeof(__u8) * 4096)
65
66#define WDC_NVME_SUBCMD_SHIFT8 8
67
68#define WDC_NVME_LOG_SIZE_DATA_LEN0x08 0x08
69#define WDC_NVME_LOG_SIZE_HDR_LEN0x08 0x08
70
71/* Enclosure */
72#define WDC_OPENFLEX_MI_DEVICE_MODEL"OpenFlex" "OpenFlex"
73#define WDC_RESULT_MORE_DATA0x80000000 0x80000000
74#define WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF 0x7FFFFFFF
75
76/* Device Config */
77#define WDC_NVME_VID0x1c58 0x1c58
78#define WDC_NVME_VID_20x1b96 0x1b96
79#define WDC_NVME_SNDK_VID0x15b7 0x15b7
80
81#define WDC_NVME_SN100_DEV_ID0x0003 0x0003
82#define WDC_NVME_SN200_DEV_ID0x0023 0x0023
83#define WDC_NVME_SN630_DEV_ID0x2200 0x2200
84#define WDC_NVME_SN630_DEV_ID_10x2201 0x2201
85#define WDC_NVME_SN840_DEV_ID0x2300 0x2300
86#define WDC_NVME_SN840_DEV_ID_10x2500 0x2500
87#define WDC_NVME_SN640_DEV_ID0x2400 0x2400
88#define WDC_NVME_SN640_DEV_ID_10x2401 0x2401
89#define WDC_NVME_SN640_DEV_ID_20x2402 0x2402
90#define WDC_NVME_SN640_DEV_ID_30x2404 0x2404
91#define WDC_NVME_ZN540_DEV_ID0x2600 0x2600
92#define WDC_NVME_SN540_DEV_ID0x2610 0x2610
93#define WDC_NVME_SN650_DEV_ID0x2700 0x2700
94#define WDC_NVME_SN650_DEV_ID_10x2701 0x2701
95#define WDC_NVME_SN650_DEV_ID_20x2702 0x2702
96#define WDC_NVME_SN650_DEV_ID_30x2720 0x2720
97#define WDC_NVME_SN650_DEV_ID_40x2721 0x2721
98#define WDC_NVME_SN655_DEV_ID0x2722 0x2722
99#define WDC_NVME_SN655_DEV_ID_10x2723 0x2723
100#define WDC_NVME_SN860_DEV_ID0x2730 0x2730
101#define WDC_NVME_SN660_DEV_ID0x2704 0x2704
102#define WDC_NVME_SN560_DEV_ID_10x2712 0x2712
103#define WDC_NVME_SN560_DEV_ID_20x2713 0x2713
104#define WDC_NVME_SN560_DEV_ID_30x2714 0x2714
105#define WDC_NVME_SN861_DEV_ID0x2750 0x2750
106#define WDC_NVME_SN861_DEV_ID_10x2751 0x2751
107#define WDC_NVME_SN861_DEV_ID_20x2752 0x2752
108#define WDC_NVME_SNTMP_DEV_ID0x2761 0x2761
109#define WDC_NVME_SNTMP_DEV_ID_10x2763 0x2763
110
111#define WDC_NVME_SNESSD1_DEV_ID_E1L0x2765 0x2765
112#define WDC_NVME_SNESSD1_DEV_ID_E20x2766 0x2766
113#define WDC_NVME_SNESSD1_DEV_ID_E3S0x2767 0x2767
114#define WDC_NVME_SNESSD1_DEV_ID_E3L0x2768 0x2768
115#define WDC_NVME_SNESSD1_DEV_ID_U20x2769 0x2769
116
117/* This id's are no longer supported, delete ?? */
118#define WDC_NVME_SN550_DEV_ID0x2708 0x2708
119
120#define WDC_NVME_SXSLCL_DEV_ID0x2001 0x2001
121#define WDC_NVME_SN520_DEV_ID0x5003 0x5003
122#define WDC_NVME_SN520_DEV_ID_10x5004 0x5004
123#define WDC_NVME_SN520_DEV_ID_20x5005 0x5005
124
125#define WDC_NVME_SN530_DEV_ID_10x5007 0x5007
126#define WDC_NVME_SN530_DEV_ID_20x5008 0x5008
127#define WDC_NVME_SN530_DEV_ID_30x5009 0x5009
128#define WDC_NVME_SN530_DEV_ID_40x500b 0x500b
129#define WDC_NVME_SN530_DEV_ID_50x501d 0x501d
130
131#define WDC_NVME_SN350_DEV_ID0x5019 0x5019
132
133#define WDC_NVME_SN570_DEV_ID0x501A 0x501A
134
135#define WDC_NVME_SN850X_DEV_ID0x5030 0x5030
136
137#define WDC_NVME_SN5000_DEV_ID_10x5034 0x5034
138#define WDC_NVME_SN5000_DEV_ID_20x5035 0x5035
139#define WDC_NVME_SN5000_DEV_ID_30x5036 0x5036
140#define WDC_NVME_SN5000_DEV_ID_40x504A 0x504A
141
142#define WDC_NVME_SN7000S_DEV_ID_10x5039 0x5039
143
144#define WDC_NVME_SN7150_DEV_ID_10x503b 0x503b
145#define WDC_NVME_SN7150_DEV_ID_20x503c 0x503c
146#define WDC_NVME_SN7150_DEV_ID_30x503d 0x503d
147#define WDC_NVME_SN7150_DEV_ID_40x503e 0x503e
148#define WDC_NVME_SN7150_DEV_ID_50x503f 0x503f
149
150#define WDC_NVME_SN7100_DEV_ID_10x5043 0x5043
151#define WDC_NVME_SN7100_DEV_ID_20x5044 0x5044
152#define WDC_NVME_SN7100_DEV_ID_30x5045 0x5045
153
154#define WDC_NVME_SN8000S_DEV_ID0x5049 0x5049
155
156#define WDC_NVME_SN720_DEV_ID0x5002 0x5002
157#define WDC_NVME_SN730_DEV_ID0x5006 0x5006
158#define WDC_NVME_SN740_DEV_ID0x5015 0x5015
159#define WDC_NVME_SN740_DEV_ID_10x5016 0x5016
160#define WDC_NVME_SN740_DEV_ID_20x5017 0x5017
161#define WDC_NVME_SN740_DEV_ID_30x5025 0x5025
162#define WDC_NVME_SN340_DEV_ID0x500d 0x500d
163#define WDC_NVME_ZN350_DEV_ID0x5010 0x5010
164#define WDC_NVME_ZN350_DEV_ID_10x5018 0x5018
165#define WDC_NVME_SN810_DEV_ID0x5011 0x5011
166#define WDC_NVME_SN820CL_DEV_ID0x5037 0x5037
167
168#define WDC_NVME_SN5100S_DEV_ID_10x5061 0x5061
169#define WDC_NVME_SN5100S_DEV_ID_20x5062 0x5062
170#define WDC_NVME_SN5100S_DEV_ID_30x5063 0x5063
171
172/* Shared flag space with SNDK plugin, should be kept in sync */
173#define WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 0x0000000000000001
174#define WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 0x0000000000000002
175#define WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 0x0000000000000004
176#define WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 0x0000000000000008
177#define WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 0x0000000000000010
178#define WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 0x0000000000000020
179#define WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 0x0000000000000040
180#define WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 0x0000000000000080
181#define WDC_DRIVE_CAP_RESIZE0x0000000000000100 0x0000000000000100
182#define WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 0x0000000000000200
183#define WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 0x0000000000000400
184#define WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 0x0000000000000800
185#define WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 0x0000000000001000
186#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 0x0000000000002000
187#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 0x0000000000004000
188#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 0x0000000000008000
189#define WDC_DRIVE_CAP_REASON_ID0x0000000000010000 0x0000000000010000
190#define WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 0x0000000000020000
191#define WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 0x0000000000040000
192#define WDC_DRIVE_CAP_INFO0x0000000000080000 0x0000000000080000
193#define WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 0x0000000000100000
194#define WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 0x0000000000200000
195#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 0x0000000000400000
196#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 0x0000000000800000
197#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 0x0000000001000000
198#define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 0x0000000002000000
199#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 0x0000000004000000
200#define WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 0x0000000008000000
201#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 0x0000000010000000
202#define WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 0x0000000020000000
203#define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 0x0000000040000000
204#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 0x0000000080000000
205#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 0x0000000100000000
206#define WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 0x0000000200000000
207#define WDC_SN730B_CAP_VUC_LOG0x0000000400000000 0x0000000400000000
208#define WDC_DRIVE_CAP_DUI0x0000000800000000 0x0000000800000000
209#define WDC_DRIVE_CAP_PURGE0x0000001000000000 0x0000001000000000
210#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 0x0000002000000000
211#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 0x0000004000000000
212#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 0x0000008000000000
213#define WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 0x0000010000000000
214#define WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 0x0000020000000000
215#define WDC_DRIVE_CAP_UDUI0x0000040000000000 0x0000040000000000
216#define WDC_DRIVE_CAP_RESIZE_SN8610x0000080000000000 0x0000080000000000
217
218/* Any new capability flags should be added to the SNDK plugin */
219
220#define WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
(WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | \
221 WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 | \
222 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | \
223 WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010)
224#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
(WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 | \
225 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | \
226 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000)
227#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | \
228 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000)
229#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | \
230 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000)
231#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
(WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | \
232 WDC_DRIVE_CAP_DUI0x0000000800000000 | \
233 WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | \
234 WDC_SN730B_CAP_VUC_LOG0x0000000400000000)
235
236/* SN730 Get Log Capabilities */
237#define SN730_NVME_GET_LOG_OPCODE0xc2 0xc2
238#define SN730_GET_FULL_LOG_LENGTH0x00080009 0x00080009
239#define SN730_GET_KEY_LOG_LENGTH0x00090009 0x00090009
240#define SN730_GET_COREDUMP_LOG_LENGTH0x00120009 0x00120009
241#define SN730_GET_EXTENDED_LOG_LENGTH0x00420009 0x00420009
242
243#define SN730_GET_FULL_LOG_SUBOPCODE0x00010009 0x00010009
244#define SN730_GET_KEY_LOG_SUBOPCODE0x00020009 0x00020009
245#define SN730_GET_CORE_LOG_SUBOPCODE0x00030009 0x00030009
246#define SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009 0x00040009
247#define SN730_LOG_CHUNK_SIZE0x1000 0x1000
248
249/* Customer ID's */
250#define WDC_CUSTOMER_ID_GN0x0001 0x0001
251#define WDC_CUSTOMER_ID_GD0x0101 0x0101
252#define WDC_CUSTOMER_ID_BD0x1009 0x1009
253
254#define WDC_CUSTOMER_ID_0x00F00x00F0 0x00F0
255#define WDC_CUSTOMER_ID_0x10040x1004 0x1004
256#define WDC_CUSTOMER_ID_0x10050x1005 0x1005
257#define WDC_CUSTOMER_ID_0x10080x1008 0x1008
258#define WDC_CUSTOMER_ID_0x13040x1304 0x1304
259#define WDC_INVALID_CUSTOMER_ID-1 -1
260
261#define WDC_ALL_PAGE_MASK0xFFFF 0xFFFF
262#define WDC_C0_PAGE_MASK0x0001 0x0001
263#define WDC_C1_PAGE_MASK0x0002 0x0002
264#define WDC_CA_PAGE_MASK0x0004 0x0004
265#define WDC_D0_PAGE_MASK0x0008 0x0008
266
267/* Drive Resize */
268#define WDC_NVME_DRIVE_RESIZE_OPCODE0xCC 0xCC
269#define WDC_NVME_DRIVE_RESIZE_CMD0x03 0x03
270#define WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 0x01
271
272/* Namespace Resize */
273#define WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB 0xFB
274
275/* Drive Info */
276#define WDC_NVME_DRIVE_INFO_OPCODE0xC6 0xC6
277#define WDC_NVME_DRIVE_INFO_CMD0x22 0x22
278#define WDC_NVME_DRIVE_INFO_SUBCMD0x06 0x06
279
280/* VS PCIE Stats */
281#define WDC_NVME_PCIE_STATS_OPCODE0xD1 0xD1
282
283/* Capture Diagnostics */
284#define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
285#define WDC_NVME_CAP_DIAG_OPCODE0xE6 0xE6
286/* Sanity bound on the device-reported Capture Diagnostics log length. */
287#define WDC_NVME_CAP_DIAG_LENGTH_MAX(1U << 30) (1U << 30)
288#define WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6 0xC6
289#define WDC_NVME_CAP_DIAG_SUBCMD0x00 0x00
290#define WDC_NVME_CAP_DIAG_CMD0x00 0x00
291
292#define WDC_NVME_CRASH_DUMP_TYPE1 1
293#define WDC_NVME_PFAIL_DUMP_TYPE2 2
294
295/* Capture Device Unit Info */
296#define WDC_NVME_CAP_DUI_HEADER_SIZE0x400 0x400
297#define WDC_NVME_CAP_DUI_OPCODE0xFA 0xFA
298#define WDC_NVME_CAP_DUI_DISABLE_IO0x01 0x01
299#define WDC_NVME_DUI_MAX_SECTION0x3A 0x3A
300#define WDC_NVME_DUI_MAX_SECTION_V20x26 0x26
301#define WDC_NVME_DUI_MAX_SECTION_V30x23 0x23
302#define WDC_NVME_DUI_MAX_DATA_AREA0x05 0x05
303#define WDC_NVME_SN730_SECTOR_SIZE512 512
304
305/* Telemtery types for vs-internal-log command */
306#define WDC_TELEMETRY_TYPE_NONE0x0 0x0
307#define WDC_TELEMETRY_TYPE_HOST0x1 0x1
308#define WDC_TELEMETRY_TYPE_CONTROLLER0x2 0x2
309#define WDC_TELEMETRY_HEADER_LENGTH512 512
310#define WDC_TELEMETRY_BLOCK_SIZE512 512
311
312/* Crash dump */
313#define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
314#define WDC_NVME_CRASH_DUMP_SIZE_NDT0x02 0x02
315#define WDC_NVME_CRASH_DUMP_SIZE_CMD0x20 0x20
316#define WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 0x03
317
318#define WDC_NVME_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
319#define WDC_NVME_CRASH_DUMP_CMD0x20 0x20
320#define WDC_NVME_CRASH_DUMP_SUBCMD0x04 0x04
321
322/* PFail Crash dump */
323#define WDC_NVME_PF_CRASH_DUMP_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_HDR_LEN0x08
324#define WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02 0x02
325#define WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20 0x20
326#define WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 0x05
327
328#define WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
329#define WDC_NVME_PF_CRASH_DUMP_CMD0x20 0x20
330#define WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 0x06
331
332/* Drive Log */
333#define WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
334#define WDC_NVME_DRIVE_LOG_SIZE_DATA_LEN0x08 WDC_NVME_LOG_SIZE_DATA_LEN0x08
335#define WDC_NVME_DRIVE_LOG_SIZE_NDT0x02 0x02
336#define WDC_NVME_DRIVE_LOG_SIZE_CMD0x20 0x20
337#define WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 0x01
338
339#define WDC_NVME_DRIVE_LOG_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
340#define WDC_NVME_DRIVE_LOG_CMD0x20 0x20
341#define WDC_NVME_DRIVE_LOG_SUBCMD0x00 0x00
342
343/* Purge and Purge Monitor */
344#define WDC_NVME_PURGE_CMD_OPCODE0xDD 0xDD
345#define WDC_NVME_PURGE_MONITOR_OPCODE0xDE 0xDE
346#define WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F 0x2F
347#define WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C 0x0000000C
348#define WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530 0x7530
349#define WDC_NVME_PURGE_CMD_SEQ_ERR0x0C 0x0C
350#define WDC_NVME_PURGE_INT_DEV_ERR0x06 0x06
351
352#define WDC_NVME_PURGE_STATE_IDLE0x00 0x00
353#define WDC_NVME_PURGE_STATE_DONE0x01 0x01
354#define WDC_NVME_PURGE_STATE_BUSY0x02 0x02
355#define WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03 0x03
356#define WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04 0x04
357
358/* Clear dumps */
359#define WDC_NVME_CLEAR_DUMP_OPCODE0xFF 0xFF
360#define WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03 0x03
361#define WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 0x05
362#define WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 0x06
363
364/* Clear FW Activate History */
365#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6 0xC6
366#define WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23 0x23
367#define WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 0x05
368#define WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1 0xC1
369
370/* Additional Smart Log */
371#define WDC_ADD_LOG_BUF_LEN0x4000 0x4000
372#define WDC_NVME_ADD_LOG_OPCODE0xC1 0xC1
373#define WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37 0x37
374#define WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F 0x0F
375
376/* C2 Log Page */
377#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2 0xC2
378#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 0xC8
379#define WDC_C2_LOG_BUF_LEN0x1000 0x1000
380#define WDC_C2_MARKETING_NAME_ID0x07 0x07
381#define WDC_C2_LOG_PAGES_SUPPORTED_ID0x08 0x08
382#define WDC_C2_CUSTOMER_ID_ID0x15 0x15
383#define WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18 0x18
384#define WDC_C2_ASSERT_DUMP_PRESENT_ID0x19 0x19
385#define WDC_C2_USER_EOL_STATUS_ID0x1A 0x1A
386#define WDC_C2_USER_EOL_STATE_ID0x1C 0x1C
387#define WDC_C2_SYSTEM_EOL_STATE_ID0x1D 0x1D
388#define WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E 0x1E
389#define WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
390#define WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
391#define WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
392#define WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
393#define WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
394#define WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
395#define WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
396#define WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002) cpu_to_le32(0x00000002)
397#define WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000) cpu_to_le32(0x00000000)
398#define WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001) cpu_to_le32(0x00000001)
399#define WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF) cpu_to_le32(0x000000FF)
400#define WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861" "Ultrastar DC SN861"
401#define WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861" "ULTRASTAR DC SN861"
402#define WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655" "Ultrastar DC SN655"
403#define WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655" "ULTRASTAR DC SN655"
404#define WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655" "SanDisk DC SN655"
405#define WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655" "SANDISK DC SN655"
406
407/* CA Log Page */
408#define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA 0xCA
409#define WDC_FB_CA_LOG_BUF_LEN0x80 0x80
410/* Added 4 padding bytes to resolve build warning messages */
411#define WDC_BD_CA_LOG_BUF_LEN0xA0 0xA0
412
413/* C0 EOL Status Log Page */
414#define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0 0xC0
415#define WDC_NVME_EOL_STATUS_LOG_LEN0x200 0x200
416#define WDC_NVME_SMART_CLOUD_ATTR_LEN0x200 0x200
417
418/* C0 SMART Cloud Attributes Log Page*/
419#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0 0xC0
420
421/* CB - FW Activate History Log Page */
422#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB 0xCB
423#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0 0x3d0
424
425/* C2 - FW Activation History Log Page */
426#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2 0xC2
427#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000 0x1000
428#define WDC_MAX_NUM_ACT_HIST_ENTRIES20 20
429#define WDC_C2_GUID_LENGTH16 16
430
431/* C3 Latency Monitor Log Page */
432#define WDC_LATENCY_MON_LOG_BUF_LEN0x200 0x200
433#define WDC_LATENCY_MON_LOG_ID0xC3 0xC3
434#define WDC_LATENCY_MON_VERSION0x0001 0x0001
435
436#define WDC_C3_GUID_LENGTH16 16
437static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH16] = {
438 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c,
439 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85
440};
441
442/* D0 Smart Log Page */
443#define WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0 0xD0
444#define WDC_NVME_VU_SMART_LOG_LEN0x200 0x200
445
446/* Log Page Directory defines */
447#define NVME_LOG_PERSISTENT_EVENT0x0D 0x0D
448#define WDC_LOG_ID_C00xC0 0xC0
449#define WDC_LOG_ID_C10xC1 0xC1
450#define WDC_LOG_ID_C20xC2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2
451#define WDC_LOG_ID_C30xC3 0xC3
452#define WDC_LOG_ID_C40xC4 0xC4
453#define WDC_LOG_ID_C50xC5 0xC5
454#define WDC_LOG_ID_C60xC6 0xC6
455#define WDC_LOG_ID_C80xC8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8
456#define WDC_LOG_ID_CA0xCA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA
457#define WDC_LOG_ID_CB0xCB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB
458#define WDC_LOG_ID_D00xD0 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0
459#define WDC_LOG_ID_D10xD1 0xD1
460#define WDC_LOG_ID_D60xD6 0xD6
461#define WDC_LOG_ID_D70xD7 0xD7
462#define WDC_LOG_ID_D80xD8 0xD8
463#define WDC_LOG_ID_DE0xDE 0xDE
464#define WDC_LOG_ID_F00xF0 0xF0
465#define WDC_LOG_ID_F10xF1 0xF1
466#define WDC_LOG_ID_F20xF2 0xF2
467#define WDC_LOG_ID_FA0xFA 0xFA
468
469/* Clear PCIe Correctable Errors */
470#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6 WDC_NVME_CAP_DIAG_CMD_OPCODE0xC6
471#define WDC_NVME_CLEAR_PCIE_CORR_CMD0x22 0x22
472#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 0x04
473#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2 0xD2
474#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3 0xC3
475/* Clear Assert Dump Status */
476#define WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8 0xD8
477#define WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03 0x03
478#define WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 0x05
479
480#define WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2 0xD2
481
482/* Drive Essentials */
483#define WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64 64
484#define WDC_DE_GENERIC_BUFFER_SIZE80 80
485#define WDC_DE_GLOBAL_NSID0xFFFFFFFF 0xFFFFFFFF
486#define WDC_DE_DEFAULT_NAMESPACE_ID0x01 0x01
487#define WDC_DE_PATH_SEPARATOR"/" "/"
488#define WDC_DE_TAR_FILE_EXTN".tar.gz" ".tar.gz"
489
490/* VS NAND Stats */
491#define WDC_NVME_NAND_STATS_LOG_ID0xFB 0xFB
492#define WDC_NVME_NAND_STATS_SIZE0x200 0x200
493
494/* VU Opcodes */
495#define WDC_DE_VU_READ_SIZE_OPCODE0xC0 0xC0
496#define WDC_DE_VU_READ_BUFFER_OPCODE0xC2 0xC2
497#define WDC_NVME_ADMIN_ENC_MGMT_SND0xC9 0xC9
498#define WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA 0xCA
499
500#define WDC_DE_FILE_HEADER_SIZE4 4
501#define WDC_DE_FILE_OFFSET_SIZE2 2
502#define WDC_DE_FILE_NAME_SIZE32 32
503#define WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000 0x8000
504#define WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 0x8000
505
506#define WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info" "manufacturing_info" /* Unique log entry page name. */
507#define WDC_DE_CORE_DUMP_FILE_NAME"core_dump" "core_dump"
508#define WDC_DE_EVENT_LOG_FILE_NAME"event_log" "event_log"
509#define WDC_DE_DESTN_SPI1 1
510#define WDC_DE_DUMPTRACE_DESTINATION6 6
511
512#define NVME_ID_CTRL_MODEL_NUMBER_SIZE40 40
513#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE20 20
514
515/* Enclosure log */
516#define WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000 0x1000
517#define WDC_NVME_ENC_NIC_LOG_SIZE0x400000 0x400000
518
519/* Enclosure nic crash dump get-log id */
520#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 0xD1
521#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 0xD2
522#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 0xD3
523#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4 0xD4
524#define WDC_ENC_CRASH_DUMP_ID0xE4 0xE4
525#define WDC_ENC_LOG_DUMP_ID0xE2 0xE2
526
527/* OCP Log Page Directory Data Structure */
528#define BYTE_TO_BIT(byte)((byte) * 8) ((byte) * 8)
529
530/* Set latency monitor feature */
531#define NVME_FEAT_OCP_LATENCY_MONITOR0xC5 0xC5
532
533enum _NVME_FEATURES_SELECT {
534 FS_CURRENT = 0,
535 FS_DEFAULT = 1,
536 FS_SAVED = 2,
537 FS_SUPPORTED_CAPBILITIES = 3
538};
539
540enum NVME_FEATURE_IDENTIFIERS {
541 FID_ARBITRATION = 0x01,
542 FID_POWER_MANAGEMENT = 0x02,
543 FID_LBA_RANGE_TYPE = 0x03,
544 FID_TEMPERATURE_THRESHOLD = 0x04,
545 FID_ERROR_RECOVERY = 0x05,
546 FID_VOLATILE_WRITE_CACHE = 0x06,
547 FID_NUMBER_OF_QUEUES = 0x07,
548 FID_INTERRUPT_COALESCING = 0x08,
549 FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
550 FID_WRITE_ATOMICITY = 0x0A,
551 FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B,
552 FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C,
553 /*Below FID's are NVM Command Set Specific*/
554 FID_SOFTWARE_PROGRESS_MARKER = 0x80,
555 FID_HOST_IDENTIFIER = 0x81,
556 FID_RESERVATION_NOTIFICATION_MASK = 0x82,
557 FID_RESERVATION_PERSISTENCE = 0x83
558};
559
560/* WDC UUID value */
561static const __u8 WDC_UUID[NVME_UUID_LEN16] = {
562 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15,
563 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
564};
565
566/* WDC_UUID value for SN640_3 devices */
567static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN16] = {
568 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
569 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
570};
571
572/* Sandisk UUID value */
573static const __u8 SNDK_UUID[NVME_UUID_LEN16] = {
574 0xde, 0x87, 0xd1, 0xeb, 0x72, 0xc5, 0x58, 0x0b,
575 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70
576};
577
578enum WDC_DRIVE_ESSENTIAL_TYPE {
579 WDC_DE_TYPE_IDENTIFY = 0x1,
580 WDC_DE_TYPE_SMARTATTRIBUTEDUMP = 0x2,
581 WDC_DE_TYPE_EVENTLOG = 0x4,
582 WDC_DE_TYPE_DUMPTRACE = 0x8,
583 WDC_DE_TYPE_DUMPSNAPSHOT = 0x10,
584 WDC_DE_TYPE_ATA_LOGS = 0x20,
585 WDC_DE_TYPE_SMART_LOGS = 0x40,
586 WDC_DE_TYPE_SCSI_LOGS = 0x80,
587 WDC_DE_TYPE_SCSI_MODE_PAGES = 0x100,
588 WDC_DE_TYPE_NVMe_FEATURES = 0x200,
589 WDC_DE_TYPE_DUMPSMARTERRORLOG3 = 0x400,
590 WDC_DE_TYPE_DUMPLOG3E = 0x800,
591 WDC_DE_TYPE_DUMPSCRAM = 0x1000,
592 WDC_DE_TYPE_PCU_LOG = 0x2000,
593 WDC_DE_TYPE_DUMP_ERROR_LOGS = 0x4000,
594 WDC_DE_TYPE_FW_SLOT_LOGS = 0x8000,
595 WDC_DE_TYPE_MEDIA_SETTINGS = 0x10000,
596 WDC_DE_TYPE_SMART_DATA = 0x20000,
597 WDC_DE_TYPE_NVME_SETTINGS = 0x40000,
598 WDC_DE_TYPE_NVME_ERROR_LOGS = 0x80000,
599 WDC_DE_TYPE_NVME_LOGS = 0x100000,
600 WDC_DE_TYPE_UART_LOGS = 0x200000,
601 WDC_DE_TYPE_DLOGS_SPI = 0x400000,
602 WDC_DE_TYPE_DLOGS_RAM = 0x800000,
603 WDC_DE_TYPE_NVME_MANF_INFO = 0x2000000,
604 WDC_DE_TYPE_NONE = 0x1000000,
605 WDC_DE_TYPE_ALL = 0xFFFFFFF,
606};
607
608#define WDC_C0_GUID_LENGTH16 16
609#define WDC_SCA_V1_NAND_STATS0x1 0x1
610#define WDC_SCA_V1_ALL0xF 0xF
611enum {
612 SCAO_V1_PMUWT = 0, /* Physical media units written TLC */
613 SCAO_V1_PMUWS = 16, /* Physical media units written SLC */
614 SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */
615 SCAO_V1_BUNBR = 34, /* Bad user nand blocks raw */
616 SCAO_V1_XRC = 40, /* XOR recovery count */
617 SCAO_V1_UREC = 48, /* Uncorrectable read error count */
618 SCAO_V1_EECE = 56, /* End to end corrected errors */
619 SCAO_V1_EEDE = 64, /* End to end detected errors */
620 SCAO_V1_EEUE = 72, /* End to end uncorrected errors */
621 SCAO_V1_SDPU = 80, /* System data percent used */
622 SCAO_V1_MNUDEC = 84, /* Min User data erase counts (TLC) */
623 SCAO_V1_MXUDEC = 92, /* Max User data erase counts (TLC) */
624 SCAO_V1_AVUDEC = 100, /* Average User data erase counts (TLC) */
625 SCAO_V1_MNEC = 108, /* Min Erase counts (SLC) */
626 SCAO_V1_MXEC = 116, /* Max Erase counts (SLC) */
627 SCAO_V1_AVEC = 124, /* Average Erase counts (SLC) */
628 SCAO_V1_PFCN = 132, /* Program fail count normalized */
629 SCAO_V1_PFCR = 134, /* Program fail count raw */
630 SCAO_V1_EFCN = 140, /* Erase fail count normalized */
631 SCAO_V1_EFCR = 142, /* Erase fail count raw */
632 SCAO_V1_PCEC = 148, /* PCIe correctable error count */
633 SCAO_V1_PFBU = 156, /* Percent free blocks (User) */
634 SCAO_V1_SVN = 160, /* Security Version Number */
635 SCAO_V1_PFBS = 168, /* Percent free blocks (System) */
636 SCAO_V1_DCC = 172, /* Deallocate Commands Completed */
637 SCAO_V1_TNU = 188, /* Total Namespace Utilization */
638 SCAO_V1_FCC = 196, /* Format NVM Commands Completed */
639 SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */
640 SCAO_V1_SEEC = 202, /* Soft ECC error count */
641 SCAO_V1_RFSC = 210, /* Refresh count */
642 SCAO_V1_BSNBN = 218, /* Bad system nand blocks normalized */
643 SCAO_V1_BSNBR = 220, /* Bad system nand blocks raw */
644 SCAO_V1_EEST = 226, /* Endurance estimate */
645 SCAO_V1_TTC = 242, /* Thermal throttling count */
646 SCAO_V1_UIO = 244, /* Unaligned I/O */
647 SCAO_V1_PMUR = 252, /* Physical media units read */
648 SCAO_V1_RTOC = 268, /* Read command timeout count */
649 SCAO_V1_WTOC = 272, /* Write command timeout count */
650 SCAO_V1_TTOC = 276, /* Trim command timeout count */
651 SCAO_V1_PLRC = 284, /* PCIe Link Retraining Count */
652 SCAO_V1_PSCC = 292, /* Power State Change Count */
653 SCAO_V1_MAVF = 300, /* Boot SSD major version field */
654 SCAO_V1_MIVF = 302, /* Boot SSD minor version field */
655 SCAO_V1_PVF = 304, /* Boot SSD point version field */
656 SCAO_V1_EVF = 306, /* Boot SSD errata version field */
657 SCAO_V1_FTLUS = 308, /* FTL Unit Size */
658 SCAO_V1_TCGOS = 312, /* TCG Ownership Status */
659
660 SCAO_V1_LPV = 494, /* Log page version - 0x0001 */
661 SCAO_V1_LPG = 496, /* Log page GUID */
662};
663
664static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH16] = {
665 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1,
666 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4
667};
668
669struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log {
670 __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */
671 __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */
672 __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */
673 __u64 ext_smart_xrc; /* 040 XOR recovery count */
674 __u64 ext_smart_urec; /* 048 Uncorrectable read error count */
675 __u64 ext_smart_eece; /* 056 End to end corrected errors */
676 __u64 ext_smart_eede; /* 064 End to end detected errors */
677 __u64 ext_smart_eeue; /* 072 End to end uncorrected errors */
678 __u8 ext_smart_sdpu; /* 080 System data percent used */
679 __u8 ext_smart_rsvd1[3]; /* 081 reserved */
680 __u64 ext_smart_mnudec; /* 084 Min User data erase counts (TLC) */
681 __u64 ext_smart_mxudec; /* 092 Max User data erase counts (TLC) */
682 __u64 ext_smart_avudec; /* 100 Average User data erase counts (TLC) */
683 __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */
684 __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */
685 __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */
686 __u8 ext_smart_pfc[8]; /* 132 Program fail count */
687 __u8 ext_smart_efc[8]; /* 140 Erase fail count */
688 __u64 ext_smart_pcec; /* 148 PCIe correctable error count */
689 __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */
690 __u8 ext_smart_rsvd2[3]; /* 157 reserved */
691 __u64 ext_smart_svn; /* 160 Security Version Number */
692 __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */
693 __u8 ext_smart_rsvd3[3]; /* 169 reserved */
694 __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */
695 __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */
696 __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */
697 __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */
698 __u8 ext_smart_rsvd4[3]; /* 199 reserved */
699 __u64 ext_smart_seec; /* 202 Soft ECC error count */
700 __u64 ext_smart_rfsc; /* 210 Refresh count */
701 __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */
702 __u8 ext_smart_eest[16]; /* 226 Endurance estimate */
703 __u16 ext_smart_ttc; /* 242 Thermal throttling count */
704 __u64 ext_smart_uio; /* 244 Unaligned I/O */
705 __u8 ext_smart_pmur[16]; /* 252 Physical media units read */
706 __u32 ext_smart_rtoc; /* 268 Read command timeout count */
707 __u32 ext_smart_wtoc; /* 272 Write command timeout count */
708 __u32 ext_smart_ttoc; /* 276 Trim command timeout count */
709 __u8 ext_smart_rsvd5[4]; /* 280 reserved */
710 __u64 ext_smart_plrc; /* 284 PCIe Link Retraining Count */
711 __u64 ext_smart_pscc; /* 292 Power State Change Count */
712 __u16 ext_smart_maj; /* 300 Boot SSD major version field */
713 __u16 ext_smart_min; /* 302 Boot SSD minor version field */
714 __u16 ext_smart_pt; /* 304 Boot SSD point version field */
715 __u16 ext_smart_err; /* 306 Boot SSD errata version field */
716 __u32 ext_smart_ftlus; /* 308 FTL Unit Size */
717 __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */
718 __u8 ext_smart_rsvd6[178]; /* 316 reserved */
719 __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */
720 __u8 ext_smart_lpg[16]; /* 496 Log page GUID */
721};
722
723struct ocp_bad_nand_block_count {
724 __u64 raw : 48;
725 __u16 normalized : 16;
726};
727
728struct ocp_e2e_correction_count {
729 __u32 detected;
730 __u32 corrected;
731};
732
733struct ocp_user_data_erase_count {
734 __u32 maximum;
735 __u32 minimum;
736};
737
738struct ocp_thermal_status {
739 __u8 num_events;
740 __u8 current_status;
741};
742
743struct __packed__attribute__((__packed__)) ocp_dssd_specific_ver {
744 __u8 errata_ver;
745 __u16 point_ver;
746 __u16 minor_ver;
747 __u8 major_ver;
748};
749
750struct ocp_cloud_smart_log {
751 __u8 physical_media_units_written[16];
752 __u8 physical_media_units_read[16];
753 struct ocp_bad_nand_block_count bad_user_nand_blocks;
754 struct ocp_bad_nand_block_count bad_system_nand_blocks;
755 __u64 xor_recovery_count;
756 __u64 uncorrectable_read_error_count;
757 __u64 soft_ecc_error_count;
758 struct ocp_e2e_correction_count e2e_correction_counts;
759 __u8 system_data_percent_used;
760 __u64 refresh_counts : 56;
761 struct ocp_user_data_erase_count user_data_erase_counts;
762 struct ocp_thermal_status thermal_status;
763 struct ocp_dssd_specific_ver dssd_specific_ver;
764 __u64 pcie_correctable_error_count;
765 __u32 incomplete_shutdowns;
766 __u8 rsvd116[4];
767 __u8 percent_free_blocks;
768 __u8 rsvd121[7];
769 __u16 capacitor_health;
770 __u8 nvme_base_errata_ver;
771 __u8 nvme_cmd_set_errata_ver;
772 __u8 rsvd132[4];
773 __u64 unaligned_io;
774 __u64 security_version_number;
775 __u64 total_nuse;
776 __u8 plp_start_count[16];
777 __u8 endurance_estimate[16];
778 __u64 pcie_link_retraining_cnt;
779 __u64 power_state_change_cnt;
780 union {
781 char lowest_permitted_fw_rev[8]; /* log_page_version >= 4 */
782 __u8 hardware_revision[16]; /* log_page_version == 3 */
783 };
784 __u8 rsvd224[270];
785 __u16 log_page_version;
786 __u8 log_page_guid[16];
787};
788
789static __u8 scao_guid[WDC_C0_GUID_LENGTH16] = {
790 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
791 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF
792};
793
794struct __packed__attribute__((__packed__)) wdc_nvme_c0_eol_log_page {
795 __u8 rsvd1[76];
796 __u32 eol_rbc;
797 __u32 eol_rsvd2;
798 __u32 eol_wra;
799 __u32 eol_plr;
800 __u32 eol_rsvd3;
801 __u32 eol_pfc;
802 __u32 eol_efc;
803 __u32 eol_rsvd4;
804 __u32 eol_rrer;
805 __u16 eol_cp_status;
806 __u16 eol_ip_status;
807 __u8 eol_cp_state;
808 __u8 eol_ip_state;
809};
810
811#define WDC_NVME_C6_GUID_LENGTH16 16
812#define WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6 0xc6
813#define WDC_NVME_HW_REV_LOG_PAGE_LEN512 512
814
815struct __packed__attribute__((__packed__)) wdc_nvme_hw_rev_log {
816 __u8 hw_rev_gdr; /* 0 Global Device HW Revision */
817 __u8 hw_rev_ar; /* 1 ASIC HW Revision */
818 __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */
819 __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */
820 __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */
821 __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */
822 __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */
823 __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */
824 __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */
825 __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */
826 __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */
827 __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */
828 __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */
829 __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */
830 __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */
831 __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */
832 __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */
833 __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */
834 __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */
835 __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */
836 __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */
837 __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */
838 __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */
839 __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */
840 __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */
841 __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */
842 __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */
843 __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */
844 __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */
845 __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */
846 __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */
847 __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */
848 __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */
849 __u8 hw_rev_sn[32]; /* 320 Serial Number */
850 __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */
851 __u16 hw_rev_version; /* 494 Log Page Version */
852 __u8 hw_rev_guid[16]; /* 496 Log Page GUID */
853};
854
855static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH16] = {
856 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15,
857 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C
858};
859
860struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA {
861 __u8 fileName[WDC_DE_FILE_NAME_SIZE32];
862 __u16 fileID;
863 __u64 fileSize;
864};
865
866struct WDC_DRIVE_ESSENTIALS {
867 struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA metaData;
868 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType;
869};
870
871struct WDC_DE_VU_LOG_DIRECTORY {
872 struct WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */
873 __u32 maxNumLogEntries; /* Caller to input memory allocated */
874 __u32 numOfValidLogEntries; /* API will output this value */
875};
876
877struct WDC_DE_CSA_FEATURE_ID_LIST {
878 enum NVME_FEATURE_IDENTIFIERS featureId;
879 __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE80];
880};
881
882struct tarfile_metadata {
883 char fileName[MAX_PATH_LEN256];
884 int8_t bufferFolderPath[MAX_PATH_LEN256];
885 char bufferFolderName[MAX_PATH_LEN256];
886 char tarFileName[MAX_PATH_LEN256];
887 char currDir[MAX_PATH_LEN256];
888 UtilsTimeInfo timeInfo;
889 uint8_t *timeString[MAX_PATH_LEN256];
890};
891
892static struct WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = {
893 {0x00, "Dummy Placeholder"},
894 {FID_ARBITRATION, "Arbitration"},
895 {FID_POWER_MANAGEMENT, "PowerMgmnt"},
896 {FID_LBA_RANGE_TYPE, "LbaRangeType"},
897 {FID_TEMPERATURE_THRESHOLD, "TempThreshold"},
898 {FID_ERROR_RECOVERY, "ErrorRecovery"},
899 {FID_VOLATILE_WRITE_CACHE, "VolatileWriteCache"},
900 {FID_NUMBER_OF_QUEUES, "NumOfQueues"},
901 {FID_INTERRUPT_COALESCING, "InterruptCoalesing"},
902 {FID_INTERRUPT_VECTOR_CONFIGURATION, "InterruptVectorConfig"},
903 {FID_WRITE_ATOMICITY, "WriteAtomicity"},
904 {FID_ASYNCHRONOUS_EVENT_CONFIGURATION, "AsynEventConfig"},
905 {FID_AUTONOMOUS_POWER_STATE_TRANSITION, "AutonomousPowerState"},
906};
907
908enum NVME_VU_DE_LOGPAGE_NAMES {
909 NVME_DE_LOGPAGE_E3 = 0x01,
910 NVME_DE_LOGPAGE_C0 = 0x02
911};
912
913struct NVME_VU_DE_LOGPAGE_LIST {
914 enum NVME_VU_DE_LOGPAGE_NAMES logPageName;
915 __u32 logPageId;
916 __u32 logPageLen;
917 char logPageIdStr[5];
918};
919
920struct WDC_NVME_DE_VU_LOGPAGES {
921 enum NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd;
922 __u32 numOfVULogPages;
923};
924
925static struct NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = {
926 { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"},
927 { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"}
928};
929
930enum {
931 WDC_NVME_ADMIN_VUC_OPCODE_D2 = 0xD2,
932 WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2 = 0x0000010A,
933 WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2 = 0x00000105,
934};
935
936enum {
937 NVME_LOG_NS_BASE = 0x80,
938 NVME_LOG_VS_BASE = 0xC0,
939};
940
941/*drive_info struct*/
942struct ocp_drive_info {
943 __u32 hw_revision;
944 __u32 ftl_unit_size;
945};
946
947/*get log page directory struct*/
948struct log_page_directory {
949 __u64 supported_lid_bitmap;
950 __u64 rsvd;
951 __u64 supported_ns_lid_bitmap;
952 __u64 supported_vs_lid_bitmap;
953};
954
955/*set latency monitor feature */
956struct __packed__attribute__((__packed__)) feature_latency_monitor {
957 __u16 active_bucket_timer_threshold;
958 __u8 active_threshold_a;
959 __u8 active_threshold_b;
960 __u8 active_threshold_c;
961 __u8 active_threshold_d;
962 __u16 active_latency_config;
963 __u8 active_latency_minimum_window;
964 __u16 debug_log_trigger_enable;
965 __u8 discard_debug_log;
966 __u8 latency_monitor_feature_enable;
967 __u8 reserved[4083];
968};
969
970static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len, const char *suffix);
971static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
972 __u32 drive_log_length);
973static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12);
974static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12,
975 const char *file, __u32 xfer_size);
976static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type);
977static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type);
978static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
979 struct plugin *plugin);
980static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file);
981static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin);
982static const char *wdc_purge_mon_status_to_string(__u32 status);
983static int wdc_purge(int argc, char **argv, struct command *acmd, struct plugin *plugin);
984static int wdc_purge_monitor(int argc, char **argv, struct command *acmd, struct plugin *plugin);
985static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
986 struct libnvme_transport_handle *hdl,
987 __u8 log_id,
988 __u8 uuid_index);
989static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
990 struct plugin *plugin);
991static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *dir, char *key);
992static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
993 struct plugin *plugin);
994static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin);
995static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
996 struct plugin *plugin);
997static int wdc_drive_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin);
998static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size);
999static int wdc_namespace_resize(int argc, char **argv, struct command *acmd,
1000 struct plugin *plugin);
1001static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option);
1002static int wdc_reason_identifier(int argc, char **argv, struct command *acmd,
1003 struct plugin *plugin);
1004static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id);
1005static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size);
1006static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl);
1007static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
1008 struct plugin *plugin);
1009static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result);
1010static int wdc_vs_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin);
1011static int wdc_vs_temperature_stats(int argc, char **argv, struct command *acmd,
1012 struct plugin *plugin);
1013static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1014static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len,
1015 FILE *out);
1016static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len, int xfer_size,
1017 FILE *out, int data_id, int cdw14, int cdw15);
1018static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __u8 log_id,
1019 void **cbs_data, size_t *cbs_len);
1020static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl);
1021static int wdc_print_c0_cloud_attr_log(void *data,
1022 int fmt,
1023 struct libnvme_transport_handle *hdl);
1024static int wdc_print_c0_eol_log(void *data, int fmt);
1025static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
1026 struct libnvme_transport_handle *hdl);
1027static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log);
1028static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx,
1029 struct libnvme_transport_handle *hdl,
1030 void **data);
1031static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data,
1032 __u32 *ret_data,
1033 __u32 entry_id);
1034static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
1035 __u32 entry_id,
1036 char *ret_data,
1037 size_t ret_data_size,
1038 __u32 *ret_data_len);
1039
1040/* Drive log data size */
1041struct wdc_log_size {
1042 __le32 log_size;
1043};
1044
1045/* E6 log header */
1046struct wdc_e6_log_hdr {
1047 __le32 eye_catcher;
1048 __u8 log_size[4];
1049};
1050
1051/* DUI log header */
1052struct wdc_dui_log_section {
1053 __le16 section_type;
1054 __le16 reserved;
1055 __le32 section_size;
1056};
1057
1058/* DUI log header V2 */
1059struct __packed__attribute__((__packed__)) wdc_dui_log_section_v2 {
1060 __le16 section_type;
1061 __le16 data_area_id;
1062 __le64 section_size;
1063};
1064
1065/* DUI log header V4 */
1066struct wdc_dui_log_section_v4 {
1067 __le16 section_type;
1068 __u8 data_area_id;
1069 __u8 reserved;
1070 __le32 section_size_sectors;
1071};
1072
1073struct wdc_dui_log_hdr {
1074 __u8 telemetry_hdr[512];
1075 __le16 hdr_version;
1076 __le16 section_count;
1077 __le32 log_size;
1078 struct wdc_dui_log_section log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1079 __u8 log_data[40];
1080};
1081
1082struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v2 {
1083 __u8 telemetry_hdr[512];
1084 __u8 hdr_version;
1085 __u8 product_id;
1086 __le16 section_count;
1087 __le64 log_size;
1088 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V20x26];
1089 __u8 log_data[40];
1090};
1091
1092struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v3 {
1093 __u8 telemetry_hdr[512];
1094 __u8 hdr_version;
1095 __u8 product_id;
1096 __le16 section_count;
1097 __le64 log_size;
1098 struct wdc_dui_log_section_v2 log_section[WDC_NVME_DUI_MAX_SECTION_V30x23];
1099 __u8 securityNonce[36];
1100 __u8 log_data[40];
1101};
1102
1103struct __packed__attribute__((__packed__)) wdc_dui_log_hdr_v4 {
1104 __u8 telemetry_hdr[512];
1105 __u8 hdr_version;
1106 __u8 product_id;
1107 __le16 section_count;
1108 __le32 log_size_sectors;
1109 struct wdc_dui_log_section_v4 log_section[WDC_NVME_DUI_MAX_SECTION0x3A];
1110 __u8 log_data[40];
1111};
1112
1113/* Purge monitor response */
1114struct wdc_nvme_purge_monitor_data {
1115 __le16 rsvd1;
1116 __le16 rsvd2;
1117 __le16 first_erase_failure_cnt;
1118 __le16 second_erase_failure_cnt;
1119 __le16 rsvd3;
1120 __le16 programm_failure_cnt;
1121 __le32 rsvd4;
1122 __le32 rsvd5;
1123 __le32 entire_progress_total;
1124 __le32 entire_progress_current;
1125 __u8 rsvd6[14];
1126};
1127
1128/* Additional Smart Log */
1129struct wdc_log_page_header {
1130 uint8_t num_subpages;
1131 uint8_t reserved;
1132 __le16 total_log_size;
1133};
1134
1135struct wdc_log_page_subpage_header {
1136 uint8_t spcode;
1137 uint8_t pcset;
1138 __le16 subpage_length;
1139};
1140
1141struct wdc_ssd_perf_stats {
1142 __le64 hr_cmds; /* Host Read Commands */
1143 __le64 hr_blks; /* Host Read Blocks */
1144 __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */
1145 __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */
1146 __le64 hr_st_cmds; /* Host Read Stalled Commands */
1147 __le64 hw_cmds; /* Host Write Commands */
1148 __le64 hw_blks; /* Host Write Blocks */
1149 __le64 hw_os_cmds; /* Host Write Odd Start Commands */
1150 __le64 hw_oe_cmds; /* Host Write Odd End Commands */
1151 __le64 hw_st_cmds; /* Host Write Commands Stalled */
1152 __le64 nr_cmds; /* NAND Read Commands */
1153 __le64 nr_blks; /* NAND Read Blocks */
1154 __le64 nw_cmds; /* NAND Write Commands */
1155 __le64 nw_blks; /* NAND Write Blocks */
1156 __le64 nrbw; /* NAND Read Before Write */
1157};
1158
1159/* Additional C2 Log Page */
1160struct wdc_c2_log_page_header {
1161 __le32 length;
1162 __le32 version;
1163};
1164
1165struct wdc_c2_log_subpage_header {
1166 __le32 length;
1167 __le32 entry_id;
1168 __le32 data;
1169};
1170
1171struct wdc_c2_cbs_data {
1172 __le32 length;
1173 __u8 data[];
1174};
1175
1176struct __packed__attribute__((__packed__)) wdc_bd_ca_log_format {
1177 __u8 field_id;
1178 __u8 reserved1[2];
1179 __u8 normalized_value;
1180 __u8 raw_value[8];
1181};
1182
1183#define WDC_LATENCY_LOG_BUCKET_READ3 3
1184#define WDC_LATENCY_LOG_BUCKET_WRITE2 2
1185#define WDC_LATENCY_LOG_BUCKET_TRIM1 1
1186#define WDC_LATENCY_LOG_BUCKET_RESERVED0 0
1187
1188#define WDC_LATENCY_LOG_MEASURED_LAT_READ2 2
1189#define WDC_LATENCY_LOG_MEASURED_LAT_WRITE1 1
1190#define WDC_LATENCY_LOG_MEASURED_LAT_TRIM0 0
1191
1192struct __packed__attribute__((__packed__)) wdc_ssd_latency_monitor_log {
1193 __u8 feature_status; /* 0x00 */
1194 __u8 rsvd1; /* 0x01 */
1195 __le16 active_bucket_timer; /* 0x02 */
1196 __le16 active_bucket_timer_threshold; /* 0x04 */
1197 __u8 active_threshold_a; /* 0x06 */
1198 __u8 active_threshold_b; /* 0x07 */
1199 __u8 active_threshold_c; /* 0x08 */
1200 __u8 active_threshold_d; /* 0x09 */
1201 __le16 active_latency_config; /* 0x0A */
1202 __u8 active_latency_min_window; /* 0x0C */
1203 __u8 rsvd2[0x13]; /* 0x0D */
1204
1205 __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */
1206 __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
1207 __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
1208 __le16 active_latency_stamp_units; /* 0xD8 */
1209 __u8 rsvd3[0x16]; /* 0xDA */
1210
1211 __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
1212 __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
1213 __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
1214 __le16 static_latency_stamp_units; /* 0x1A8 */
1215 __u8 rsvd4[10]; /* 0x1AA */
1216
1217 __u8 debug_telemetry_log_size[12]; /* 0x1B4 */
1218 __le16 debug_log_trigger_enable; /* 0x1C0 */
1219 __le16 debug_log_measured_latency; /* 0x1C2 */
1220 __le64 debug_log_latency_stamp; /* 0x1C4 */
1221 __le16 debug_log_ptr; /* 0x1CC */
1222 __le16 debug_log_counter_trigger; /* 0x1CE */
1223 __u8 debug_log_stamp_units; /* 0x1D0 */
1224 __u8 rsvd5[0x1D]; /* 0x1D1 */
1225
1226 __le16 log_page_version; /* 0x1EE */
1227 __u8 log_page_guid[0x10]; /* 0x1F0 */
1228};
1229
1230struct __packed__attribute__((__packed__)) wdc_ssd_ca_perf_stats {
1231 __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */
1232 __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */
1233 __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */
1234 __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */
1235 __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */
1236 __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */
1237 __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */
1238 __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */
1239 __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */
1240 __u8 data_percent_used; /* 0x40 - System Data Percent Used */
1241 __le32 data_erase_max; /* 0x41 - User Data Erase Counts */
1242 __le32 data_erase_min; /* 0x45 - User Data Erase Counts */
1243 __le64 refresh_count; /* 0x49 - Refresh Count */
1244 __le64 program_fail; /* 0x51 - Program Fail Count */
1245 __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */
1246 __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */
1247 __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */
1248 __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */
1249 __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */
1250 __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */
1251 __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */
1252 __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */
1253};
1254
1255struct __packed__attribute__((__packed__)) wdc_ssd_d0_smart_log {
1256 __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */
1257 __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */
1258 __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */
1259 __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */
1260 __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */
1261 __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */
1262 __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */
1263 __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */
1264 __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */
1265 __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */
1266 __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */
1267 __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */
1268 __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */
1269 __le32 current_temp; /* 0x34 - Current temperature */
1270 __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */
1271 __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */
1272 __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */
1273 __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */
1274 __le32 capacitor_health; /* 0x4C - Capacitor health */
1275 __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */
1276 __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */
1277 __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */
1278 __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */
1279 __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */
1280};
1281
1282#define WDC_OCP_C1_GUID_LENGTH16 16
1283#define WDC_ERROR_REC_LOG_BUF_LEN512 512
1284#define WDC_ERROR_REC_LOG_ID0xC1 0xC1
1285
1286struct __packed__attribute__((__packed__)) wdc_ocp_c1_error_recovery_log {
1287 __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */
1288 __u8 panic_reset_action; /* 002 - Panic Reset Action */
1289 __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */
1290 __le64 panic_id; /* 004 - Panic ID */
1291 __le32 dev_capabilities; /* 012 - Device Capabilities */
1292 __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */
1293 __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */
1294 __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */
1295 __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */
1296 __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */
1297 __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */
1298 __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2 */
1299 __u8 panic_count; /* 031 - Number of panics encountered */
1300 __le64 prev_panic_ids[4]; /* 032 - 063 Previous Panic ID's */
1301 __u8 rsvd2[430]; /* 064 - 493 Reserved Bytes */
1302 /* 430 reserved bytes aligns with the rest */
1303 /* of the data structure. The size of 463 */
1304 /* bytes mentioned in the OCP spec */
1305 /* (version 2.5) would not fit here. */
1306 __le16 log_page_version; /* 494 - Log Page Version */
1307 __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH16]; /* 496 - Log Page GUID */
1308};
1309
1310static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH16] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE,
1311 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A };
1312
1313/* NAND Stats */
1314struct __packed__attribute__((__packed__)) wdc_nand_stats {
1315 __u8 nand_write_tlc[16];
1316 __u8 nand_write_slc[16];
1317 __le32 nand_prog_failure;
1318 __le32 nand_erase_failure;
1319 __le32 bad_block_count;
1320 __le64 nand_rec_trigger_event;
1321 __le64 e2e_error_counter;
1322 __le64 successful_ns_resize_event;
1323 __u8 rsvd[442];
1324 __u16 log_page_version;
1325};
1326
1327struct __packed__attribute__((__packed__)) wdc_nand_stats_V3 {
1328 __u8 nand_write_tlc[16];
1329 __u8 nand_write_slc[16];
1330 __u8 bad_nand_block_count[8];
1331 __le64 xor_recovery_count;
1332 __le64 uecc_read_error_count;
1333 __u8 ssd_correction_counts[16];
1334 __u8 percent_life_used;
1335 __le64 user_data_erase_counts[4];
1336 __u8 program_fail_count[8];
1337 __u8 erase_fail_count[8];
1338 __le64 correctable_error_count;
1339 __u8 percent_free_blocks_user;
1340 __le64 security_version_number;
1341 __u8 percent_free_blocks_system;
1342 __u8 trim_completions[25];
1343 __u8 back_pressure_guage;
1344 __le64 soft_ecc_error_count;
1345 __le64 refresh_count;
1346 __u8 bad_sys_nand_block_count[8];
1347 __u8 endurance_estimate[16];
1348 __u8 thermal_throttling_st_ct[2];
1349 __le64 unaligned_IO;
1350 __u8 physical_media_units[16];
1351 __u8 reserved[279];
1352 __u16 log_page_version;
1353};
1354
1355struct wdc_vs_pcie_stats {
1356 __le64 unsupportedRequestErrorCount;
1357 __le64 ecrcErrorStatusCount;
1358 __le64 malformedTlpStatusCount;
1359 __le64 receiverOverflowStatusCount;
1360 __le64 unexpectedCmpltnStatusCount;
1361 __le64 completeAbortStatusCount;
1362 __le64 cmpltnTimoutStatusCount;
1363 __le64 flowControlErrorStatusCount;
1364 __le64 poisonedTlpStatusCount;
1365 __le64 dLinkPrtclErrorStatusCount;
1366 __le64 advsryNFatalErrStatusCount;
1367 __le64 replayTimerToStatusCount;
1368 __le64 replayNumRolloverStCount;
1369 __le64 badDllpStatusCount;
1370 __le64 badTlpStatusCount;
1371 __le64 receiverErrStatusCount;
1372 __u8 reserved1[384];
1373};
1374
1375struct wdc_fw_act_history_log_hdr {
1376 __le32 eye_catcher;
1377 __u8 version;
1378 __u8 reserved1;
1379 __u8 num_entries;
1380 __u8 reserved2;
1381 __le32 entry_size;
1382 __le32 reserved3;
1383};
1384
1385struct wdc_fw_act_history_log_entry {
1386 __le32 entry_num;
1387 __le32 power_cycle_count;
1388 __le64 power_on_seconds;
1389 __le64 previous_fw_version;
1390 __le64 new_fw_version;
1391 __u8 slot_number;
1392 __u8 commit_action_type;
1393 __le16 result;
1394 __u8 reserved[12];
1395};
1396
1397struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 {
1398 __u8 entry_version_num;
1399 __u8 entry_len;
1400 __le16 reserved;
1401 __le16 fw_act_hist_entries;
1402 __le64 timestamp;
1403 __u8 reserved2[8];
1404 __le64 power_cycle_count;
1405 __le64 previous_fw_version;
1406 __le64 current_fw_version;
1407 __u8 slot_number;
1408 __u8 commit_action_type;
1409 __le16 result;
1410 __u8 reserved3[14];
1411};
1412
1413struct __packed__attribute__((__packed__)) wdc_fw_act_history_log_format_c2 {
1414 __u8 log_identifier;
1415 __u8 reserved[3];
1416 __le32 num_entries;
1417 struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES20];
1418 __u8 reserved2[2790];
1419 __le16 log_page_version;
1420 __u8 log_page_guid[WDC_C2_GUID_LENGTH16];
1421};
1422
1423static __u8 ocp_C2_guid[WDC_C2_GUID_LENGTH16] = {
1424 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
1425 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
1426};
1427
1428#define WDC_OCP_C4_GUID_LENGTH16 16
1429#define WDC_DEV_CAP_LOG_BUF_LEN4096 4096
1430#define WDC_DEV_CAP_LOG_ID0xC4 0xC4
1431#define WDC_DEV_CAP_LOG_VERSION0001 0001
1432#define WDC_OCP_C4_NUM_PS_DESCR127 127
1433
1434struct __packed__attribute__((__packed__)) wdc_ocp_C4_dev_cap_log {
1435 __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */
1436 __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */
1437 __le16 wrt_zeros_support; /* 0004 - Write Zeros Command Support */
1438 __le16 sanitize_support; /* 0006 - Sanitize Command Support */
1439 __le16 dsm_support; /* 0008 - Dataset Management Command Support */
1440 __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */
1441 __le16 fused_support; /* 0012 - Fused Operation Support */
1442 __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */
1443 __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */
1444 __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR127];/* 0017 - DSSD Power State Descriptors */
1445 __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */
1446 __le16 log_page_version; /* 4078 - Log Page Version */
1447 __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1448};
1449
1450static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH16] = {
1451 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98,
1452 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7
1453};
1454
1455#define WDC_OCP_C5_GUID_LENGTH16 16
1456#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096 4096
1457#define WDC_UNSUPPORTED_REQS_LOG_ID0xC5 0xC5
1458#define WDC_UNSUPPORTED_REQS_LOG_VERSION0001 0001
1459#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES253 253
1460
1461struct __packed__attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs {
1462 __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */
1463 __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */
1464 __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES253][16]; /* 0016 - Unsupported Requirements List */
1465 __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */
1466 __le16 log_page_version; /* 4078 - Log Page Version */
1467 __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH16]; /* 4080 - Log Page GUID */
1468};
1469
1470static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH16] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB,
1471 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 };
1472
1473#define WDC_REASON_INDEX_MAX16 16
1474#define WDC_REASON_ID_ENTRY_LEN128 128
1475#define WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli" "/usr/local/nvmecli"
1476
1477const char *log_page_name[256] = {
1478 [NVME_LOG_LID_ERROR] = "Error Information",
1479 [NVME_LOG_LID_SMART] = "SMART / Health Information",
1480 [NVME_LOG_LID_FW_SLOT] = "Firmware Slot Information",
1481 [NVME_LOG_LID_CHANGED_ATTACHED_NS] = "Changed Attached Namespace List",
1482 [NVME_LOG_LID_CMD_EFFECTS] = "Command Supported and Effects",
1483 [NVME_LOG_LID_TELEMETRY_HOST] = "Telemetry Host-Initiated",
1484 [NVME_LOG_LID_TELEMETRY_CTRL] = "Telemetry Controller-Initiated",
1485 [NVME_LOG_LID_SANITIZE] = "Sanitize Status",
1486 [WDC_LOG_ID_C00xC0] = "Extended SMART Information",
1487 [WDC_LOG_ID_C20xC2] = "Firmware Activation History",
1488 [WDC_LOG_ID_C30xC3] = "Latency Monitor",
1489 [WDC_LOG_ID_C40xC4] = "Device Capabilities",
1490 [WDC_LOG_ID_C50xC5] = "Unsupported Requirements",
1491};
1492
1493static double safe_div_fp(double numerator, double denominator)
1494{
1495 return denominator ? numerator / denominator : 0;
1496}
1497
1498/* At most UINT64_MAX: the device reports the counters */
1499static uint64_t calc_percent(uint64_t numerator, uint64_t denominator)
1500{
1501 double percent;
1502
1503 if (!denominator)
1504 return 0;
1505 percent = (double)numerator / (double)denominator * 100;
1506 return percent < 0x1p64 ? (uint64_t)percent : UINT64_MAX(18446744073709551615UL);
1507}
1508
1509/* An average of the JSON output, at most UINT64_MAX */
1510static uint64_t json_avg(double numerator, double denominator)
1511{
1512 double avg = safe_div_fp(numerator, denominator);
1513
1514 return avg < 0x1p64 ? (uint64_t)avg : UINT64_MAX(18446744073709551615UL);
1515}
1516
1517static int wdc_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id)
1518{
1519 struct libnvme_passthru_cmd cmd;
1520 struct nvme_id_ctrl ctrl;
1521 int ret;
1522
1523 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1524 nvme_init_identify_ctrl(&cmd, &ctrl);
8
Calling 'nvme_init_identify_ctrl'
13
Returning from 'nvme_init_identify_ctrl'
1525 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1526 if (ret) {
14
Assuming 'ret' is 0
15
Taking false branch
1527 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
1528 return -1;
1529 }
1530
1531 *vendor_id = (uint32_t) ctrl.vid;
16
Value assigned to 'read_vendor_id', which participates in a condition later
1532
1533 return ret;
1534}
1535
1536static bool_Bool wdc_is_sn861(__u32 device_id)
1537{
1538 if ((device_id == WDC_NVME_SN861_DEV_ID0x2750) ||
1539 (device_id == WDC_NVME_SN861_DEV_ID_10x2751) ||
1540 (device_id == WDC_NVME_SN861_DEV_ID_20x2752))
1541 return true1;
1542 else
1543 return false0;
1544}
1545
1546
1547static bool_Bool wdc_is_sn640(__u32 device_id)
1548{
1549 if ((device_id == WDC_NVME_SN640_DEV_ID0x2400) ||
1550 (device_id == WDC_NVME_SN640_DEV_ID_10x2401) ||
1551 (device_id == WDC_NVME_SN640_DEV_ID_20x2402))
1552 return true1;
1553 else
1554 return false0;
1555}
1556
1557static bool_Bool wdc_is_sn650_u2(__u32 device_id)
1558{
1559 if (device_id == WDC_NVME_SN650_DEV_ID_30x2720)
1560 return true1;
1561 else
1562 return false0;
1563}
1564
1565static bool_Bool wdc_is_sn650_e1l(__u32 device_id)
1566{
1567 if (device_id == WDC_NVME_SN650_DEV_ID_40x2721)
1568 return true1;
1569 else
1570 return false0;
1571}
1572
1573static bool_Bool wdc_is_zn350(__u32 device_id)
1574{
1575 return (device_id == WDC_NVME_ZN350_DEV_ID0x5010 ||
1576 device_id == WDC_NVME_ZN350_DEV_ID_10x5018);
1577}
1578static bool_Bool needs_c2_log_page_check(__u32 device_id)
1579{
1580 if ((wdc_is_sn640(device_id)) ||
1581 (wdc_is_sn650_u2(device_id)) ||
1582 (wdc_is_sn650_e1l(device_id)))
1583 return true1;
1584 else
1585 return false0;
1586}
1587
1588static bool_Bool wdc_check_power_of_2(int num)
1589{
1590 return num && (!(num & (num-1)));
1591}
1592
1593static int wdc_get_model_number(struct libnvme_transport_handle *hdl, char *model)
1594{
1595 struct libnvme_passthru_cmd cmd;
1596 struct nvme_id_ctrl ctrl;
1597 int ret, i;
1598
1599 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1600 nvme_init_identify_ctrl(&cmd, &ctrl);
1601 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1602 if (ret) {
1603 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
1604 return -1;
1605 }
1606
1607 memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE40);
1608 /* get rid of the padded spaces */
1609 i = NVME_ID_CTRL_MODEL_NUMBER_SIZE40-1;
1610 while (model[i] == ' ')
1611 i--;
1612 model[i+1] = 0;
1613
1614 return ret;
1615}
1616
1617static bool_Bool wdc_check_device(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1618{
1619 int ret;
1620 bool_Bool supported;
1621 uint32_t read_device_id = -1, read_vendor_id = -1;
1622
1623 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1624 if (ret < 0) {
1625 /* Use the identify nvme command to get vendor id due to NVMeOF device. */
1626 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1627 return false0;
1628 }
1629
1630 supported = false0;
1631
1632 if (read_vendor_id == WDC_NVME_VID0x1c58 ||
1633 read_vendor_id == WDC_NVME_VID_20x1b96 ||
1634 read_vendor_id == WDC_NVME_SNDK_VID0x15b7)
1635 supported = true1;
1636 else
1637 nvme_show_error(nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
1638 "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n",nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
1639 read_vendor_id, read_device_id)nvme_show_message(1, "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n"
, read_vendor_id, read_device_id)
;
1640
1641 return supported;
1642}
1643
1644static bool_Bool wdc_enc_check_model(struct libnvme_transport_handle *hdl)
1645{
1646 int ret;
1647 bool_Bool supported;
1648 char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40+1];
1649
1650 ret = wdc_get_model_number(hdl, model);
1651 if (ret < 0)
1652 return false0;
1653
1654 supported = false0;
1655 model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40] = 0; /* forced termination */
1656 if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL)_Generic (0 ? (model) : (void *) 1, const void *: (const char
*) (strstr (model, "OpenFlex")), default: strstr (model, "OpenFlex"
))
)
1657 supported = true1;
1658 else
1659 nvme_show_error("ERROR: WDC: unsupported WDC enclosure, Model = %s", model)nvme_show_message(1, "ERROR: WDC: unsupported WDC enclosure, Model = %s"
, model)
;
1660
1661 return supported;
1662}
1663
1664static __u64 wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1665{
1666 int ret;
1667 uint32_t read_device_id = -1, read_vendor_id = -1;
1668 __u64 capabilities = 0;
1669 __u32 cust_id;
1670
1671 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1672 if (ret < 0) {
1
Assuming 'ret' is >= 0
1673 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1674 return capabilities;
1675 }
1676
1677 /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
1678 if (read_device_id == -1 && read_vendor_id != -1) {
2
Assuming the condition is true
3
Assuming the condition is true
4
Taking true branch
1679 capabilities = wdc_get_enc_drive_capabilities(ctx, hdl);
5
Calling 'wdc_get_enc_drive_capabilities'
1680 return capabilities;
1681 }
1682
1683 switch (read_vendor_id) {
1684 case WDC_NVME_VID0x1c58:
1685 switch (read_device_id) {
1686 case WDC_NVME_SN100_DEV_ID0x0003:
1687 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 |
1688 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1689 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1690 break;
1691
1692 case WDC_NVME_SN200_DEV_ID0x0023:
1693 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1694 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1695 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1696
1697 /* verify the 0xCA log page is supported */
1698 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1699 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1700 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1701
1702 /* verify the 0xC1 log page is supported */
1703 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1704 WDC_NVME_ADD_LOG_OPCODE0xC1, 0))
1705 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
1706 break;
1707
1708 default:
1709 capabilities = 0;
1710 }
1711 break;
1712
1713 case WDC_NVME_VID_20x1b96:
1714 switch (read_device_id) {
1715 case WDC_NVME_SN630_DEV_ID0x2200:
1716 case WDC_NVME_SN630_DEV_ID_10x2201:
1717 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1718 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1719 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1720 /* verify the 0xCA log page is supported */
1721 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1722 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1723 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1724
1725 /* verify the 0xD0 log page is supported */
1726 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1727 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1728 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1729 break;
1730
1731 case WDC_NVME_SN640_DEV_ID0x2400:
1732 case WDC_NVME_SN640_DEV_ID_10x2401:
1733 case WDC_NVME_SN640_DEV_ID_20x2402:
1734 case WDC_NVME_SN640_DEV_ID_30x2404:
1735 case WDC_NVME_SN560_DEV_ID_10x2712:
1736 case WDC_NVME_SN560_DEV_ID_20x2713:
1737 case WDC_NVME_SN560_DEV_ID_30x2714:
1738 case WDC_NVME_SN660_DEV_ID0x2704:
1739 /* verify the 0xC0 log page is supported */
1740 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1741 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)
1742 == true1) {
1743 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1744 }
1745
1746 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1747 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1748 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1749 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1750 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1751
1752 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1753 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1754 WDC_ERROR_REC_LOG_ID0xC1, 0))
1755 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1756
1757 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1758 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1759 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1760 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1761
1762 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1763 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1764 WDC_DEV_CAP_LOG_ID0xC4, 0))
1765 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1766
1767 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1768 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1769 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1770 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1771
1772 /* verify the 0xCA log page is supported */
1773 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1774 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1775 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1776
1777 /* verify the 0xD0 log page is supported */
1778 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1779 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1780 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1781
1782 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1783 /* Can still determine some capabilities in this case, but log an error */
1784 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1785 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1786 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1787 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1788
1789 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1790 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) || (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1791 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1792 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1793 else
1794 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1795
1796 break;
1797
1798 case WDC_NVME_SN840_DEV_ID0x2300:
1799 case WDC_NVME_SN840_DEV_ID_10x2500:
1800 case WDC_NVME_SN860_DEV_ID0x2730:
1801 /* verify the 0xC0 log page is supported */
1802 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1803 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, 0))
1804 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1805 fallthrough__attribute__((fallthrough));
1806 case WDC_NVME_ZN540_DEV_ID0x2600:
1807 case WDC_NVME_SN540_DEV_ID0x2610:
1808 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1809 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1810 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1811 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1812 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1813 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1814
1815 /* verify the 0xCA log page is supported */
1816 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1817 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1818 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1819
1820 /* verify the 0xD0 log page is supported */
1821 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1822 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1823 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1824 break;
1825
1826 case WDC_NVME_SN650_DEV_ID0x2700:
1827 case WDC_NVME_SN650_DEV_ID_10x2701:
1828 case WDC_NVME_SN650_DEV_ID_20x2702:
1829 case WDC_NVME_SN650_DEV_ID_30x2720:
1830 case WDC_NVME_SN650_DEV_ID_40x2721:
1831 case WDC_NVME_SN655_DEV_ID0x2722:
1832 case WDC_NVME_SN655_DEV_ID_10x2723:
1833 case WDC_NVME_SN550_DEV_ID0x2708:
1834 /* verify the 0xC0 log page is supported */
1835 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1836 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
1837 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1838
1839 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1840 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1841 WDC_ERROR_REC_LOG_ID0xC1, 0))
1842 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1843
1844 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1845 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1846 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1847 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1848
1849 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1850 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1851 WDC_DEV_CAP_LOG_ID0xC4, 0))
1852 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1853
1854 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1855 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1856 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1857 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1858
1859 /* verify the 0xCA log page is supported */
1860 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1861 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
1862 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1863
1864 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1865 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1866 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1867 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 |
1868 WDC_DRIVE_CAP_REASON_ID0x0000000000010000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1869
1870 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1871 /* Can still determine some capabilities in this case, but log an error */
1872 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1873 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1874 "%s: ERROR: WDC: invalid customer ID; device ID = %x\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1875 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1876
1877 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
1878 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1879 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
1880 (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1881 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1882 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1883 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1884 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1885 else
1886 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1887 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1888
1889 break;
1890
1891 case WDC_NVME_SN861_DEV_ID0x2750:
1892 case WDC_NVME_SN861_DEV_ID_10x2751:
1893 case WDC_NVME_SN861_DEV_ID_20x2752:
1894 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1895 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1896 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1897 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1898 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1899 WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1900 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
1901 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1902 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1903 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1904 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1905 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1906 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1907 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1908 break;
1909
1910 case WDC_NVME_SNTMP_DEV_ID0x2761:
1911 case WDC_NVME_SNTMP_DEV_ID_10x2763:
1912 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1913 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1914 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1915 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1916 WDC_DRIVE_CAP_DUI0x0000000800000000 |
1917 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1918 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1919 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1920 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1921 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1922 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1923 break;
1924
1925 default:
1926 capabilities = 0;
1927 }
1928 break;
1929
1930 case WDC_NVME_SNDK_VID0x15b7:
1931 switch (read_device_id) {
1932 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
1933 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
1934 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
1935 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
1936 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
1937 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1938 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1939 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1940 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1941 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1942 WDC_DRIVE_CAP_UDUI0x0000040000000000 |
1943 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1944 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1945 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1946 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1947 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1948 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1949 break;
1950
1951 case WDC_NVME_SXSLCL_DEV_ID0x2001:
1952 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
1953 break;
1954
1955 case WDC_NVME_SN520_DEV_ID0x5003:
1956 case WDC_NVME_SN520_DEV_ID_10x5004:
1957 case WDC_NVME_SN520_DEV_ID_20x5005:
1958 case WDC_NVME_SN810_DEV_ID0x5011:
1959 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000;
1960 break;
1961
1962 case WDC_NVME_SN820CL_DEV_ID0x5037:
1963 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 |
1964 WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 |
1965 WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 | WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1966 WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
1967 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1968 WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000;
1969 break;
1970
1971 case WDC_NVME_SN720_DEV_ID0x5002:
1972 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1973 WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000;
1974 break;
1975
1976 case WDC_NVME_SN730_DEV_ID0x5006:
1977 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1978 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 |
1979 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000;
1980 break;
1981
1982 case WDC_NVME_SN530_DEV_ID_10x5007:
1983 fallthrough__attribute__((fallthrough));
1984 case WDC_NVME_SN530_DEV_ID_20x5008:
1985 fallthrough__attribute__((fallthrough));
1986 case WDC_NVME_SN530_DEV_ID_30x5009:
1987 fallthrough__attribute__((fallthrough));
1988 case WDC_NVME_SN530_DEV_ID_40x500b:
1989 fallthrough__attribute__((fallthrough));
1990 case WDC_NVME_SN530_DEV_ID_50x501d:
1991 fallthrough__attribute__((fallthrough));
1992 case WDC_NVME_SN350_DEV_ID0x5019:
1993 fallthrough__attribute__((fallthrough));
1994 case WDC_NVME_SN570_DEV_ID0x501A:
1995 fallthrough__attribute__((fallthrough));
1996 case WDC_NVME_SN850X_DEV_ID0x5030:
1997 fallthrough__attribute__((fallthrough));
1998 case WDC_NVME_SN5000_DEV_ID_10x5034:
1999 fallthrough__attribute__((fallthrough));
2000 case WDC_NVME_SN5000_DEV_ID_20x5035:
2001 fallthrough__attribute__((fallthrough));
2002 case WDC_NVME_SN5000_DEV_ID_30x5036:
2003 fallthrough__attribute__((fallthrough));
2004 case WDC_NVME_SN5000_DEV_ID_40x504A:
2005 fallthrough__attribute__((fallthrough));
2006 case WDC_NVME_SN7000S_DEV_ID_10x5039:
2007 fallthrough__attribute__((fallthrough));
2008 case WDC_NVME_SN7150_DEV_ID_10x503b:
2009 fallthrough__attribute__((fallthrough));
2010 case WDC_NVME_SN7150_DEV_ID_20x503c:
2011 fallthrough__attribute__((fallthrough));
2012 case WDC_NVME_SN7150_DEV_ID_30x503d:
2013 fallthrough__attribute__((fallthrough));
2014 case WDC_NVME_SN7150_DEV_ID_40x503e:
2015 fallthrough__attribute__((fallthrough));
2016 case WDC_NVME_SN7150_DEV_ID_50x503f:
2017 fallthrough__attribute__((fallthrough));
2018 case WDC_NVME_SN7100_DEV_ID_10x5043:
2019 fallthrough__attribute__((fallthrough));
2020 case WDC_NVME_SN7100_DEV_ID_20x5044:
2021 fallthrough__attribute__((fallthrough));
2022 case WDC_NVME_SN7100_DEV_ID_30x5045:
2023 fallthrough__attribute__((fallthrough));
2024 case WDC_NVME_SN8000S_DEV_ID0x5049:
2025 fallthrough__attribute__((fallthrough));
2026 case WDC_NVME_SN5100S_DEV_ID_10x5061:
2027 fallthrough__attribute__((fallthrough));
2028 case WDC_NVME_SN5100S_DEV_ID_20x5062:
2029 fallthrough__attribute__((fallthrough));
2030 case WDC_NVME_SN5100S_DEV_ID_30x5063:
2031 fallthrough__attribute__((fallthrough));
2032 case WDC_NVME_SN740_DEV_ID0x5015:
2033 case WDC_NVME_SN740_DEV_ID_10x5016:
2034 case WDC_NVME_SN740_DEV_ID_20x5017:
2035 case WDC_NVME_SN740_DEV_ID_30x5025:
2036 case WDC_NVME_SN340_DEV_ID0x500d:
2037 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000;
2038 break;
2039
2040 case WDC_NVME_ZN350_DEV_ID0x5010:
2041 case WDC_NVME_ZN350_DEV_ID_10x5018:
2042 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
2043 WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
2044 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2045 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
2046 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000;
2047 break;
2048
2049 default:
2050 capabilities = 0;
2051 }
2052 break;
2053 default:
2054 capabilities = 0;
2055 }
2056
2057 return capabilities;
2058}
2059
2060static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx,
2061 struct libnvme_transport_handle *hdl)
2062{
2063 int ret;
2064 uint32_t read_vendor_id;
2065 __u64 capabilities = 0;
2066 __u32 cust_id, market_name_len;
6
'market_name_len' declared without an initial value
2067 char marketing_name[64];
2068 void *dev_mng_log = NULL((void*)0);
2069 int uuid_index = 0;
2070 struct nvme_id_uuid_list uuid_list;
2071
2072 memset(marketing_name, 0, 64);
2073
2074 ret = wdc_get_vendor_id(hdl, &read_vendor_id);
7
Calling 'wdc_get_vendor_id'
17
Returning from 'wdc_get_vendor_id'
2075 if (ret
17.1
'ret' is >= 0
17.1
'ret' is >= 0
< 0)
18
Taking false branch
2076 return capabilities;
2077
2078 switch (read_vendor_id) {
19
Control jumps to 'case 7062:' at line 2093
2079 case WDC_NVME_VID0x1c58:
2080 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
2081 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000);
2082
2083 /* verify the 0xCA log page is supported */
2084 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2085 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2086 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2087
2088 /* verify the 0xC1 log page is supported */
2089 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2090 WDC_NVME_ADD_LOG_OPCODE0xC1, 0) == true1)
2091 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
2092 break;
2093 case WDC_NVME_VID_20x1b96:
2094 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
2095 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
2096 WDC_DRIVE_CAP_RESIZE0x0000000000000100);
2097
2098 /* Find the WDC UUID index */
2099 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2100 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
20
Assuming the condition is false
21
Taking false branch
2101 /* check for the Sandisk UUID first */
2102 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2103
2104 if (uuid_index < 0)
2105 /* The Sandisk UUID is not found;
2106 * check for the WDC UUID second.
2107 */
2108 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2109 }
2110
2111 /* WD UUID not found, use default uuid index - 0 */
2112 if (uuid_index
21.1
'uuid_index' is >= 0
21.1
'uuid_index' is >= 0
< 0)
22
Taking false branch
2113 uuid_index = 0;
2114
2115 /* verify the 0xC2 Device Manageability log page is supported */
2116 if (wdc_nvme_check_supported_log_page(ctx, hdl,
23
Assuming the condition is false
24
Taking false branch
2117 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
2118 uuid_index) == false0) {
2119 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not supported, index: %d",nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
2120 uuid_index)nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
;
2121 goto out;
2122 }
2123
2124 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
25
Assuming the condition is false
26
Taking false branch
2125 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
2126 goto out;
2127 }
2128
2129 /* Get the customer ID and marketing name from WD C2 log page */
2130 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log,
27
Taking true branch
2131 &cust_id,
2132 WDC_C2_CUSTOMER_ID_ID0x15))
2133 nvme_show_error("ERROR: SNDK: Get Customer FW ID Failed")nvme_show_message(1, "ERROR: SNDK: Get Customer FW ID Failed"
)
;
2134
2135 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
28
Calling 'wdc_nvme_parse_dev_status_log_str'
37
Returning from 'wdc_nvme_parse_dev_status_log_str'
38
Taking true branch
2136 WDC_C2_MARKETING_NAME_ID0x07,
2137 (char *)marketing_name,
2138 sizeof(marketing_name),
2139 &market_name_len))
2140 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
2141
2142 /* verify the 0xC0 log page is supported */
2143 if (wdc_nvme_check_supported_log_page(ctx, hdl,
39
Assuming the condition is false
40
Taking false branch
2144 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
2145 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
2146
2147 /* verify the 0xC3 log page is supported */
2148 if (wdc_nvme_check_supported_log_page(ctx, hdl,
41
Assuming the condition is false
42
Taking false branch
2149 WDC_LATENCY_MON_LOG_ID0xC3, 0) == true1)
2150 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
2151
2152 /* verify the 0xCA log page is supported */
2153 if (wdc_nvme_check_supported_log_page(ctx, hdl,
43
Assuming the condition is false
44
Taking false branch
2154 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2155 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2156
2157 /* verify the 0xD0 log page is supported */
2158 if (wdc_nvme_check_supported_log_page(ctx, hdl,
45
Assuming the condition is false
2159 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == true1)
2160 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
2161
2162 if ((cust_id
45.1
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1004
45.1
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1004
== WDC_CUSTOMER_ID_0x10040x1004) ||
2163 (cust_id
45.2
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1008
45.2
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1008
== WDC_CUSTOMER_ID_0x10080x1008) ||
2164 (cust_id
45.3
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1005
45.3
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1005
== WDC_CUSTOMER_ID_0x10050x1005) ||
2165 (cust_id
45.4
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1304
45.4
'cust_id' is not equal to WDC_CUSTOMER_ID_0x1304
== WDC_CUSTOMER_ID_0x13040x1304) ||
2166 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) ||
46
3rd function call argument is an uninitialized value
2167 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len)))
2168 /* Set capabilities for OCP compliant drives */
2169 capabilities |= (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
2170 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2171 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000);
2172 else {
2173 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
2174 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
2175
2176 /* if the 0xCB log page is supported */
2177 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2178 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0) == true1)
2179 capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000;
2180 }
2181
2182 break;
2183 case WDC_NVME_SNDK_VID0x15b7:
2184 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
2185 break;
2186 default:
2187 capabilities = 0;
2188 }
2189
2190out:
2191 return capabilities;
2192}
2193
2194static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len,
2195 const char *suffix)
2196{
2197 int ret;
2198 int res_len = 0;
2199 char orig[PATH_MAX4096] = {0};
2200 struct libnvme_passthru_cmd cmd;
2201 struct nvme_id_ctrl ctrl;
2202 char sn[sizeof(ctrl.sn) + 1] = {0};
2203
2204 shr_strscpy(orig, file, sizeof(orig));
2205 memset(file, 0, len);
2206 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
2207 nvme_init_identify_ctrl(&cmd, &ctrl);
2208 ret = libnvme_exec_admin_passthru(hdl, &cmd);
2209 if (ret) {
2210 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x",nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
2211 ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
2212 return -1;
2213 }
2214
2215 snprintf(sn, sizeof(sn), "%-.*s",
2216 (int)sizeof(ctrl.sn), ctrl.sn);
2217 shr_sanitize_name(shr_rtrim(sn));
2218
2219 res_len = snprintf(file, len, "%s%s%s", orig, sn, suffix);
2220 if (len <= res_len) {
2221 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
2222 "ERROR: WDC: cannot format serial number due to data of unexpected length\n")nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
;
2223 return -1;
2224 }
2225
2226 return 0;
2227}
2228
2229static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
2230 __u32 drive_log_length)
2231{
2232 int fd;
2233 int ret;
2234
2235 if (!drive_log_length) {
2236 nvme_show_error("ERROR: WDC: invalid log file length")nvme_show_message(1, "ERROR: WDC: invalid log file length");
2237 return -1;
2238 }
2239
2240 fd = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
2241 if (fd < 0) {
2242 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
2243 return -1;
2244 }
2245
2246 while (drive_log_length > WRITE_SIZE(sizeof(__u8) * 4096)) {
2247 ret = write(fd, drive_log_data, WRITE_SIZE(sizeof(__u8) * 4096));
2248 if (ret < 0) {
2249 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2250 close(fd);
2251 return -1;
2252 }
2253 drive_log_data += WRITE_SIZE(sizeof(__u8) * 4096);
2254 drive_log_length -= WRITE_SIZE(sizeof(__u8) * 4096);
2255 }
2256
2257 ret = write(fd, drive_log_data, drive_log_length);
2258 if (ret < 0) {
2259 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2260 close(fd);
2261 return -1;
2262 }
2263
2264 if (shr_fsync(fd) < 0) {
2265 nvme_show_error("ERROR: WDC: fsync: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: fsync: %s", libnvme_strerror
((*__errno_location ())))
;
2266 close(fd);
2267 return -1;
2268 }
2269 close(fd);
2270 return 0;
2271}
2272
2273/*
2274 * A C2 log entry starts where the lengths of the entries before it put
2275 * it, at any byte: read its fields unaligned.
2276 */
2277static __u32 wdc_c2_entry_length(const void *entry)
2278{
2279 return shr_get_unaligned_le32(entry);
2280}
2281
2282static __u32 wdc_c2_entry_id(const void *entry)
2283{
2284 return shr_get_unaligned_le32((const __u8 *)entry +
2285 offsetof(struct wdc_c2_log_subpage_header, entry_id)__builtin_offsetof(struct wdc_c2_log_subpage_header, entry_id
)
);
2286}
2287
2288static const __u8 *wdc_c2_entry_data(const void *entry)
2289{
2290 return (const __u8 *)entry +
2291 offsetof(struct wdc_c2_log_subpage_header, data)__builtin_offsetof(struct wdc_c2_log_subpage_header, data);
2292}
2293
2294bool_Bool wdc_validate_dev_mng_log(void *data)
2295{
2296 __u32 remaining_len = 0;
2297 __u32 log_length = 0;
2298 __u32 log_entry_size = 0;
2299 __u32 log_entry_id = 0;
2300 __u32 offset = 0;
2301 bool_Bool valid_log = false0;
2302 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2303 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2304
2305 log_length = le32_to_cpu(hdr_ptr->length);
2306 /* Ensure log data is large enough for common header */
2307 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2308 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2309 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2310 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2311 return valid_log;
2312 }
2313
2314 /* Get pointer to first log Entry */
2315 offset = sizeof(struct wdc_c2_log_page_header);
2316 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2317 remaining_len = log_length - offset;
2318
2319 /* Proceed only if there is at least enough data to read an entry header */
2320 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2321 /* Get size of the next entry */
2322 log_entry_size = wdc_c2_entry_length(p_next_log_entry);
2323 log_entry_id = wdc_c2_entry_id(p_next_log_entry);
2324 /*
2325 * If log entry size is 0 or the log entry goes past the end
2326 * of the data, we must be at the end of the data
2327 */
2328 if (!log_entry_size || log_entry_size > remaining_len) {
2329 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2330 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2331 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2332 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2333 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2334 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2335
2336 /* Force the loop to end */
2337 remaining_len = 0;
2338 } else if (!log_entry_id || log_entry_id > 200) {
2339 /* Invalid entry - fail the search */
2340 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2341 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2342 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2343 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2344 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2345
2346 /* Force the loop to end */
2347 remaining_len = 0;
2348 valid_log = false0;
2349 } else {
2350 /* A valid log has at least one entry and no invalid entries */
2351 valid_log = true1;
2352 remaining_len -= log_entry_size;
2353 if (remaining_len > 0) {
2354 /* Increment the offset counter */
2355 offset += log_entry_size;
2356 /* Get the next entry */
2357 p_next_log_entry =
2358 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2359 }
2360 }
2361 }
2362
2363 return valid_log;
2364}
2365
2366bool_Bool wdc_parse_dev_mng_log_entry(void *data, __u32 entry_id,
2367 struct wdc_c2_log_subpage_header **log_entry)
2368{
2369 __u32 remaining_len = 0;
2370 __u32 log_length = 0;
2371 __u32 log_entry_size = 0;
2372 __u32 log_entry_id = 0;
2373 __u32 offset = 0;
2374 bool_Bool found = false0;
2375 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2376 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2377
2378 log_length = le32_to_cpu(hdr_ptr->length);
2379 /* Ensure log data is large enough for common header */
2380 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2381 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2382 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2383 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2384 return found;
2385 }
2386
2387 /* Get pointer to first log Entry */
2388 offset = sizeof(struct wdc_c2_log_page_header);
2389 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2390 remaining_len = log_length - offset;
2391
2392 if (!log_entry) {
2393 nvme_show_error("ERROR: WDC - %s: No log entry pointer.", __func__)nvme_show_message(1, "ERROR: WDC - %s: No log entry pointer."
, __func__)
;
2394 return found;
2395 }
2396 *log_entry = NULL((void*)0);
2397
2398 /* Proceed only if there is at least enough data to read an entry header */
2399 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2400 /* Get size of the next entry */
2401 log_entry_size = wdc_c2_entry_length(p_next_log_entry);
2402 log_entry_id = wdc_c2_entry_id(p_next_log_entry);
2403
2404 /*
2405 * If log entry size is 0 or the log entry goes past the end
2406 * of the data, we must be at the end of the data
2407 */
2408 if (!log_entry_size || log_entry_size > remaining_len) {
2409 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2410 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2411 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2412 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2413 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2414 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2415
2416 /* Force the loop to end */
2417 remaining_len = 0;
2418 } else if (!log_entry_id || log_entry_id > 200) {
2419 /* Invalid entry - fail the search */
2420 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2421 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2422 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2423 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2424 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2425
2426 /* Force the loop to end */
2427 remaining_len = 0;
2428 } else {
2429 if (log_entry_id == entry_id) {
2430 found = true1;
2431 *log_entry = p_next_log_entry;
2432 remaining_len = 0;
2433 } else {
2434 remaining_len -= log_entry_size;
2435 }
2436
2437 if (remaining_len > 0) {
2438 /* Increment the offset counter */
2439 offset += log_entry_size;
2440
2441 /* Get the next entry */
2442 p_next_log_entry =
2443 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2444 }
2445 }
2446 }
2447
2448 return found;
2449}
2450
2451bool_Bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id,
2452 struct wdc_c2_log_page_header *p_log_hdr,
2453 struct wdc_c2_log_subpage_header **p_p_found_log_entry)
2454{
2455 __u32 remaining_len = 0;
2456 __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1;
2457 __u32 log_entry_size = 0;
2458 __u32 log_entry_id = 0;
2459 __u32 size = 0;
2460 bool_Bool valid_log;
2461 __u32 offset = 0;
2462 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2463
2464 *p_p_found_log_entry = NULL((void*)0);
2465
2466 /* Ensure log data is large enough for common header */
2467 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2468 nvme_show_error(nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2469 "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2470 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2471 return false0;
2472 }
2473
2474 /* Get pointer to first log Entry */
2475 size = sizeof(struct wdc_c2_log_page_header);
2476 offset = size;
2477 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2478 remaining_len = log_length - size;
2479 valid_log = false0;
2480
2481 /*
2482 * Walk the entire structure. Perform a sanity check to make sure this is a
2483 * standard version of the structure. This means making sure each entry looks
2484 * valid. But allow for the data to overflow the allocated
2485 * buffer (we don't want a false negative because of a FW formatting error)
2486 */
2487
2488 /* Proceed only if there is at least enough data to read an entry header */
2489 while (remaining_len >= log_entry_hdr_size) {
2490 /* Get size of the next entry */
2491 log_entry_size = wdc_c2_entry_length(p_next_log_entry);
2492 log_entry_id = wdc_c2_entry_id(p_next_log_entry);
2493
2494 /*
2495 * If log entry size is 0 or the log entry goes past the end
2496 * of the data, we must be at the end of the data
2497 */
2498 if (!log_entry_size || log_entry_size > remaining_len) {
2499 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2500 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2501 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2502 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2503 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2504 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2505
2506 /* Force the loop to end */
2507 remaining_len = 0;
2508 } else if (!log_entry_id || log_entry_id > 200) {
2509 /* Invalid entry - fail the search */
2510 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2511 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2512 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2513 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2514 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2515
2516 /* Force the loop to end */
2517 remaining_len = 0;
2518 valid_log = false0;
2519
2520 /* The structure is invalid, so any match that was found is invalid. */
2521 *p_p_found_log_entry = NULL((void*)0);
2522 } else {
2523 /* Structure must have at least one valid entry to be considered valid */
2524 valid_log = true1;
2525 if (log_entry_id == entry_id)
2526 /* A potential match. */
2527 *p_p_found_log_entry = p_next_log_entry;
2528
2529 remaining_len -= log_entry_size;
2530
2531 if (remaining_len > 0) {
2532 /* Increment the offset counter */
2533 offset += log_entry_size;
2534
2535 /* Get the next entry */
2536 p_next_log_entry =
2537 (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2538 }
2539 }
2540 }
2541
2542 return valid_log;
2543}
2544
2545static bool_Bool get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, void **log_data,
2546 __u8 uuid_ix)
2547{
2548 struct wdc_c2_log_page_header *hdr_ptr;
2549 struct libnvme_passthru_cmd cmd;
2550 bool_Bool valid = false0;
2551 __u32 length = 0;
2552 void *data;
2553 int ret = 0;
2554
2555 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2556 if (!data) {
2557 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2558 return false0;
2559 }
2560
2561 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2562
2563 /* get the log page length */
2564 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2565 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2566 WDC_C2_LOG_BUF_LEN0x1000);
2567 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2568 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2569 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2570 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2571 if (ret) {
2572 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2573 "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2574 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2575 goto end;
2576 }
2577
2578 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2579 length = le32_to_cpu(hdr_ptr->length);
2580
2581 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2582 /* Log page buffer too small for actual data */
2583 free(data);
2584 data = calloc(length, sizeof(__u8));
2585 if (!data) {
2586 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2587 goto end;
2588 }
2589
2590 /* get the log page data with the increased length */
2591 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2592 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2593 length);
2594 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2595 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2596 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2597 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2598 if (ret) {
2599 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2600 "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2601 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2602 goto end;
2603 }
2604 }
2605
2606 valid = wdc_validate_dev_mng_log(data);
2607 if (valid) {
2608 /* Ensure size of log data matches length in log header */
2609 *log_data = calloc(length, sizeof(__u8));
2610 if (!*log_data) {
2611 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2612 valid = false0;
2613 goto end;
2614 }
2615 memcpy((void *)*log_data, data, length);
2616 } else {
2617 nvme_show_error("ERROR: WDC: C2 log page not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
2618 uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
;
2619 }
2620
2621end:
2622 free(data);
2623 return valid;
2624}
2625
2626static bool_Bool get_dev_mgmt_log_page_lid_data(struct libnvme_transport_handle *hdl,
2627 void **cbs_data,
2628 size_t *cbs_len,
2629 __u8 lid,
2630 __u8 log_id,
2631 __u8 uuid_ix)
2632{
2633 void *data;
2634 struct wdc_c2_log_page_header *hdr_ptr;
2635 struct wdc_c2_log_subpage_header *sph;
2636 struct libnvme_passthru_cmd cmd;
2637 __u32 length = 0;
2638 int ret = 0;
2639 bool_Bool found = false0;
2640
2641 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2642 if (!data) {
2643 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2644 return false0;
2645 }
2646
2647 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2648
2649 /* get the log page length */
2650 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2651 WDC_C2_LOG_BUF_LEN0x1000);
2652 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2653 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2654 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2655 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2656 if (ret) {
2657 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2658 "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2659 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2660 goto end;
2661 }
2662
2663 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2664 length = le32_to_cpu(hdr_ptr->length);
2665
2666 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2667 /* Log Page buffer too small, free and reallocate the necessary size */
2668 free(data);
2669 data = calloc(length, sizeof(__u8));
2670 if (!data) {
2671 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2672 goto end;
2673 }
2674
2675 /* get the log page data with the increased length */
2676 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2677 length);
2678 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2679 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2680 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2681 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2682 if (ret) {
2683 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2684 "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2685 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2686 goto end;
2687 }
2688 }
2689
2690 /* Check the log data to see if the WD version of log page ID's is found */
2691 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2692 sph = NULL((void*)0);
2693 found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
2694 if (found && sph) {
2695 /*
2696 * The data of the entry, after its header: zero padded, so
2697 * that one shorter than the dword of a value still has one.
2698 */
2699 size_t hdr_len =
2700 offsetof(struct wdc_c2_log_subpage_header, data)__builtin_offsetof(struct wdc_c2_log_subpage_header, data);
2701 size_t entry_len = wdc_c2_entry_length(sph);
2702 size_t len = entry_len > hdr_len ? entry_len - hdr_len : 0;
2703
2704 *cbs_data = calloc(len + sizeof(__le32), sizeof(__u8));
2705 if (!*cbs_data) {
2706 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2707 found = false0;
2708 goto end;
2709 }
2710 memcpy((void *)*cbs_data, wdc_c2_entry_data(sph), len);
2711 *cbs_len = len;
2712 } else if(found && !sph) {
2713 nvme_show_error("ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d",log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d"
,log_id, uuid_ix)
;
2714 found = false0;
2715 } else {
2716 nvme_show_error("ERROR: WDC: C2 log id 0x%x not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
2717 log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
;
2718 }
2719
2720end:
2721 free(data);
2722 return found;
2723}
2724
2725static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2726 void **data)
2727{
2728 bool_Bool found = false0;
2729 __u32 device_id = 0, vendor_id = 0;
2730 int uuid_index = 0;
2731 struct nvme_id_uuid_list uuid_list;
2732
2733 *data = NULL((void*)0);
2734
2735 /* The nvme_get_pci_ids() function could fail when drives are connected
2736 * via a PCIe switch. Therefore, the return code is intentionally
2737 * being ignored. The device_id and vendor_id variables have been
2738 * initialized to 0 so the code can continue on without issue for
2739 * both cases: successful or failed.
2740 */
2741 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2742
2743 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2744 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2745 /* check for the Sandisk UUID first */
2746 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2747
2748 if (uuid_index < 0) {
2749 /* The Sandisk UUID is not found;
2750 * check for the WDC UUID second.
2751 */
2752 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2753 if (uuid_index < 0)
2754 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2755 }
2756
2757 if (uuid_index >= 0)
2758 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2759 else {
2760 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2761 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2762 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2763 }
2764 } else if (needs_c2_log_page_check(device_id)) {
2765 /* In certain devices that don't support UUID lists, there are multiple
2766 * definitions of the C2 logpage. In those cases, the code
2767 * needs to try two UUID indexes and use an identification algorithm
2768 * to determine which is returning the correct log page data.
2769 */
2770
2771 uuid_index = 1;
2772 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2773
2774 if (!found) {
2775 /* not found with uuid = 1 try with uuid = 0 */
2776 uuid_index = 0;
2777 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2778 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2779
2780 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2781 }
2782 } else {
2783 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2784 uuid_index = 0;
2785 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2786 }
2787
2788 return found;
2789}
2790
2791/*
2792 * The bytes of the C2 entry data @cbs of @len bytes, a length and the
2793 * bytes it counts: those which are in the data.
2794 */
2795static __u32 wdc_cbs_len(const struct wdc_c2_cbs_data *cbs, size_t len)
2796{
2797 size_t max = len > sizeof(cbs->length) ? len - sizeof(cbs->length) : 0;
2798
2799 size_t cbs_len = le32_to_cpu(cbs->length);
2800
2801 return cbs_len < max ? cbs_len : max;
2802}
2803
2804static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2805 __u8 log_id, void **cbs_data, size_t *cbs_len)
2806{
2807 size_t len;
2808
2809 bool_Bool found = false0;
2810 __u8 lid = 0;
2811 __u32 device_id = 0, vendor_id = 0;
2812 int uuid_index = 0;
2813 struct nvme_id_uuid_list uuid_list;
2814
2815 *cbs_data = NULL((void*)0);
2816
2817 /* The nvme_get_pci_ids function could fail when drives are connected
2818 * via a PCIe switch. Therefore, the return code is intentionally
2819 * being ignored. The device_id and vendor_id variables have been
2820 * initialized to 0 so the code can continue on without issue for
2821 * both cases: successful or failed.
2822 */
2823 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2824
2825 lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
2826
2827 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2828 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2829 /* check for the Sandisk UUID first */
2830 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2831
2832 if (uuid_index < 0) {
2833 /* The Sandisk UUID is not found;
2834 * check for the WDC UUID second.
2835 */
2836 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2837 if (uuid_index < 0)
2838 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2839 }
2840
2841 if (uuid_index >= 0)
2842 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data,
2843 &len, lid, log_id, uuid_index);
2844 else {
2845 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2846 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2847 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2848 }
2849 } else if (needs_c2_log_page_check(device_id)) {
2850 /* In certain devices that don't support UUID lists, there are multiple
2851 * definitions of the C2 logpage. In those cases, the code
2852 * needs to try two UUID indexes and use an identification algorithm
2853 * to determine which is returning the correct log page data.
2854 */
2855 uuid_index = 1;
2856 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data,
2857 &len, lid, log_id, uuid_index);
2858 if (!found) {
2859 /* not found with uuid = 1 try with uuid = 0 */
2860 uuid_index = 0;
2861 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2862 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2863
2864 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data,
2865 &len, lid, log_id, uuid_index);
2866 }
2867 } else {
2868 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2869 uuid_index = 0;
2870 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data,
2871 &len, lid, log_id, uuid_index);
2872 }
2873
2874 if (found && cbs_len)
2875 *cbs_len = len;
2876 return found;
2877}
2878
2879static int wdc_get_supported_log_pages(struct libnvme_transport_handle *hdl,
2880 struct nvme_supported_log_pages *supported,
2881 int uuid_index)
2882{
2883 struct libnvme_passthru_cmd cmd;
2884
2885 memset(supported, 0, sizeof(*supported));
2886 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
2887 NVME_CSI_NVM, supported, sizeof(*supported));
2888 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2889 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2890 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2891 return libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2892}
2893
2894static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
2895 struct libnvme_transport_handle *hdl,
2896 __u8 log_id,
2897 __u8 uuid_index)
2898{
2899 int i;
2900 bool_Bool found = false0;
2901 int err = -1;
2902 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
2903 size_t cbs_len = 0;
2904
2905 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_supported_log_pages *supports = NULL((void*)0);
2906
2907 /* Check log page id 0 (supported log pages) first */
2908 supports = libnvme_alloc(sizeof(*supports));
2909 if (!supports)
2910 return -ENOMEM12;
2911
2912 err = wdc_get_supported_log_pages(hdl,
2913 supports,
2914 uuid_index);
2915
2916 if (!err) {
2917 /* Check support log page list for support */
2918 if (supports->lid_support[log_id])
2919 /* Support for Log Page found in supported log pages */
2920 found = true1;
2921 }
2922
2923 /* if not found in the supported log pages (log id 0),
2924 * check the WDC C2 log page
2925 */
2926 if (!found) {
2927 if (get_dev_mgment_cbs_data(ctx, hdl,
2928 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
2929 (void *)&cbs_data, &cbs_len)) {
2930 if (cbs_data) {
2931 __u32 n = wdc_cbs_len(cbs_data, cbs_len);
2932
2933 for (i = 0; i < n; i++) {
2934 if (log_id == cbs_data->data[i]) {
2935 found = true1;
2936 break;
2937 }
2938 }
2939
2940#ifdef WDC_NVME_CLI_DEBUG
2941 if (!found) {
2942 nvme_show_error("ERROR: WDC: Log Page 0x%x not supported",nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
2943 log_id)nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
;
2944 nvme_show_error("WDC: Supported Log Pages:")nvme_show_message(1, "WDC: Supported Log Pages:");
2945 /* print the supported pages */
2946 d((__u8 *)cbs_data->data, n, 16, 1);
2947 }
2948#endif
2949 free(cbs_data);
2950 } else {
2951 nvme_show_error("ERROR: WDC: cbs_data ptr = NULL")nvme_show_message(1, "ERROR: WDC: cbs_data ptr = NULL");
2952 }
2953 } else {
2954 nvme_show_error("ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found",nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
2955 WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
;
2956 }
2957 }
2958
2959 return found;
2960}
2961
2962static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data,
2963 __u32 entry_id)
2964{
2965 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2966
2967 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2968 if (entry_data) {
2969 *ret_data = shr_get_unaligned_le32(
2970 wdc_c2_entry_data(entry_data));
2971 return true1;
2972 }
2973 }
2974
2975 *ret_data = 0;
2976 return false0;
2977}
2978
2979static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
2980 __u32 entry_id,
2981 char *ret_data,
2982 size_t ret_data_size,
2983 __u32 *ret_data_len)
2984{
2985 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2986 const __u8 *entry_str_data;
2987 __u32 entry_len, entry_total_len, max_payload_len;
2988
2989 if (!ret_data
28.1
'ret_data' is non-null
28.1
'ret_data' is non-null
|| !ret_data_len
28.2
'ret_data_len' is non-null
28.2
'ret_data_len' is non-null
|| ret_data_size
28.3
'ret_data_size' is not equal to 0
28.3
'ret_data_size' is not equal to 0
== 0)
29
Taking false branch
2990 return false0;
2991
2992 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
30
Assuming the condition is true
31
Taking true branch
2993 if (entry_data) {
32
Assuming 'entry_data' is non-null
33
Taking true branch
2994 entry_str_data = wdc_c2_entry_data(entry_data);
2995 entry_len = shr_get_unaligned_le32(entry_str_data);
2996 entry_total_len = wdc_c2_entry_length(entry_data);
2997 if (entry_total_len <
34
Assuming the condition is true
35
Taking true branch
2998 sizeof(struct wdc_c2_log_subpage_header))
2999 return false0;
36
Returning without writing to '*ret_data_len'
3000 max_payload_len = entry_total_len -
3001 sizeof(struct wdc_c2_log_subpage_header);
3002 if (entry_len > max_payload_len ||
3003 entry_len >= ret_data_size)
3004 return false0;
3005 memcpy(ret_data, entry_str_data +
3006 offsetof(struct wdc_c2_cbs_data, data)__builtin_offsetof(struct wdc_c2_cbs_data, data),
3007 entry_len);
3008 ret_data[entry_len] = '\0';
3009 *ret_data_len = entry_len;
3010 return true1;
3011 }
3012 }
3013
3014 *ret_data = 0;
3015 *ret_data_len = 0;
3016 return false0;
3017}
3018
3019static bool_Bool wdc_nvme_get_dev_status_log_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __le32 *ret_data,
3020 __u8 log_id)
3021{
3022 __u32 *cbs_data = NULL((void*)0);
3023
3024 if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data,
3025 NULL((void*)0))) {
3026 if (cbs_data) {
3027 memcpy((void *)ret_data, (void *)cbs_data, 4);
3028 free(cbs_data);
3029
3030 return true1;
3031 }
3032 }
3033
3034 *ret_data = 0;
3035 return false0;
3036}
3037
3038static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12)
3039{
3040 int ret;
3041 struct libnvme_passthru_cmd admin_cmd;
3042
3043 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3044 admin_cmd.opcode = opcode;
3045 admin_cmd.cdw12 = cdw12;
3046 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3047 if (ret)
3048 fprintf(stdoutstdout, "ERROR: WDC: Crash dump erase failed\n");
3049 nvme_show_status(ret);
3050 return ret;
3051}
3052
3053static __u32 wdc_dump_length(struct libnvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length)
3054{
3055 int ret;
3056 __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN0x08] = {0};
3057 struct wdc_log_size *l;
3058 struct libnvme_passthru_cmd admin_cmd;
3059
3060 l = (struct wdc_log_size *) buf;
3061 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3062 admin_cmd.opcode = opcode;
3063 admin_cmd.addr = (__u64)(uintptr_t)buf;
3064 admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN0x08;
3065 admin_cmd.cdw10 = cdw10;
3066 admin_cmd.cdw12 = cdw12;
3067
3068 ret = libnvme_exec_admin_passthru(link, &admin_cmd);
3069 if (ret) {
3070 l->log_size = 0;
3071 ret = -1;
3072 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3073 nvme_show_status(ret);
3074 return ret;
3075 }
3076
3077 if (opcode == WDC_NVME_CAP_DIAG_OPCODE0xE6)
3078 *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07];
3079 else
3080 *dump_length = le32_to_cpu(l->log_size);
3081 return ret;
3082}
3083
3084static __u32 wdc_dump_length_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
3085{
3086 int ret;
3087 struct libnvme_passthru_cmd admin_cmd;
3088
3089 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3090 admin_cmd.opcode = opcode;
3091 admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
3092 admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3093 admin_cmd.cdw10 = cdw10;
3094 admin_cmd.cdw12 = cdw12;
3095
3096 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3097 if (ret) {
3098 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3099 nvme_show_status(ret);
3100 }
3101
3102 return ret;
3103}
3104
3105static __u32 wdc_dump_dui_data(struct libnvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool_Bool last_xfer)
3106{
3107 int ret;
3108 struct libnvme_passthru_cmd admin_cmd;
3109
3110 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3111 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3112 admin_cmd.nsid = 0xFFFFFFFF;
3113 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3114 admin_cmd.data_len = dataLen;
3115 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3116 admin_cmd.cdw12 = offset;
3117 if (last_xfer)
3118 admin_cmd.cdw14 = 0;
3119 else
3120 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3121
3122
3123 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3124 if (ret) {
3125 nvme_show_error("ERROR: WDC: reading DUI data failed")nvme_show_message(1, "ERROR: WDC: reading DUI data failed");
3126 nvme_show_status(ret);
3127 }
3128
3129 return ret;
3130}
3131
3132static __u32 wdc_dump_dui_data_v2(struct libnvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool_Bool last_xfer)
3133{
3134 int ret;
3135 struct libnvme_passthru_cmd admin_cmd;
3136 __u64 offset_lo, offset_hi;
3137
3138 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3139 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3140 admin_cmd.nsid = 0xFFFFFFFF;
3141 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3142 admin_cmd.data_len = dataLen;
3143 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3144 offset_lo = offset & 0x00000000FFFFFFFF;
3145 offset_hi = ((offset & 0xFFFFFFFF00000000) >> 32);
3146 admin_cmd.cdw12 = (__u32)offset_lo;
3147 admin_cmd.cdw13 = (__u32)offset_hi;
3148
3149 if (last_xfer)
3150 admin_cmd.cdw14 = 0;
3151 else
3152 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3153
3154 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3155 if (ret) {
3156 nvme_show_error("ERROR: WDC: reading DUI data V2 failed")nvme_show_message(1, "ERROR: WDC: reading DUI data V2 failed"
)
;
3157 nvme_show_status(ret);
3158 }
3159
3160 return ret;
3161}
3162
3163static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3164 __u32 cdw12, const char *file, __u32 xfer_size)
3165{
3166 int ret = 0;
3167 __u8 *dump_data;
3168 __u32 curr_data_offset, curr_data_len;
3169 int i;
3170 struct libnvme_passthru_cmd admin_cmd;
3171 __u32 dump_length = data_len;
3172
3173 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
3174 if (!dump_data) {
3175 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3176 return -1;
3177 }
3178 memset(dump_data, 0, sizeof(__u8) * dump_length);
3179 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3180 curr_data_offset = 0;
3181 curr_data_len = xfer_size;
3182 i = 0;
3183
3184 admin_cmd.opcode = opcode;
3185 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3186 admin_cmd.data_len = curr_data_len;
3187 admin_cmd.cdw10 = curr_data_len >> 2;
3188 admin_cmd.cdw12 = cdw12;
3189 admin_cmd.cdw13 = curr_data_offset;
3190
3191 while (curr_data_offset < data_len) {
3192 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3193 if (ret) {
3194 nvme_show_status(ret);
3195 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
3196 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
3197 break;
3198 }
3199
3200 if ((curr_data_offset + xfer_size) <= data_len)
3201 curr_data_len = xfer_size;
3202 else
3203 curr_data_len = data_len - curr_data_offset; /* last transfer */
3204
3205 curr_data_offset += curr_data_len;
3206 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3207 admin_cmd.data_len = curr_data_len;
3208 admin_cmd.cdw10 = curr_data_len >> 2;
3209 admin_cmd.cdw13 = curr_data_offset >> 2;
3210 i++;
3211 }
3212
3213 if (!ret) {
3214 nvme_show_status(ret);
3215 ret = wdc_create_log_file(file, dump_data, dump_length);
3216 }
3217 free(dump_data);
3218 return ret;
3219}
3220
3221static int wdc_do_dump_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3222 __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
3223{
3224 int ret = 0;
3225 __u8 *dump_data;
3226 __u32 curr_data_offset, log_size;
3227 int i;
3228 struct libnvme_passthru_cmd admin_cmd;
3229
3230 /* data_len is device-supplied and must hold the header copied in below */
3231 if (data_len < WDC_NVME_LOG_SIZE_HDR_LEN0x08) {
3232 nvme_show_error("%s: ERROR: invalid log length (0x%x), must be >= 0x%x",nvme_show_message(1, "%s: ERROR: invalid log length (0x%x), must be >= 0x%x"
, __func__, data_len, 0x08)
3233 __func__, data_len, WDC_NVME_LOG_SIZE_HDR_LEN)nvme_show_message(1, "%s: ERROR: invalid log length (0x%x), must be >= 0x%x"
, __func__, data_len, 0x08)
;
3234 return -EINVAL22;
3235 }
3236
3237 /* if data_len is not 4 byte aligned */
3238 if (data_len & 0x00000003) {
3239 /* Round down to the next 4 byte aligned value */
3240 nvme_show_error("%s: INFO: data_len 0x%x not 4 byte aligned.",nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
3241 __func__, data_len)nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
;
3242 data_len &= 0xFFFFFFFC;
3243 nvme_show_error("%s: INFO: Round down to 0x%x.",nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, data_len)
3244 __func__, data_len)nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, data_len)
;
3245 }
3246
3247 dump_data = (__u8 *)malloc(sizeof(__u8) * data_len);
3248
3249 if (!dump_data) {
3250 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3251 return -1;
3252 }
3253 memset(dump_data, 0, sizeof(__u8) * data_len);
3254 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3255 curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3256 i = 0;
3257
3258 /* copy the 8 byte header into the dump_data buffer */
3259 memcpy(dump_data, log_hdr, WDC_NVME_LOG_SIZE_HDR_LEN0x08);
3260
3261 admin_cmd.opcode = opcode;
3262 admin_cmd.cdw12 = cdw12;
3263
3264 /* subtract off the header size since that was already copied into the buffer */
3265 log_size = (data_len - curr_data_offset);
3266 while (log_size > 0) {
3267 xfer_size = min(xfer_size, log_size)({ typeof(xfer_size) _a = (xfer_size); typeof(log_size) _b = (
log_size); do { } while (0); _a < _b ? _a : _b; })
;
3268
3269 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3270 admin_cmd.data_len = xfer_size;
3271 admin_cmd.cdw10 = xfer_size >> 2;
3272 admin_cmd.cdw13 = curr_data_offset >> 2;
3273
3274 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3275 if (ret) {
3276 nvme_show_status(ret);
3277 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
3278 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
3279 break;
3280 }
3281
3282 log_size -= xfer_size;
3283 curr_data_offset += xfer_size;
3284 i++;
3285 }
3286
3287 if (!ret) {
3288 nvme_show_error("%s: INFO: ", __func__)nvme_show_message(1, "%s: INFO: ", __func__);
3289 nvme_show_status(ret);
3290 } else {
3291 nvme_show_error("%s: FAILURE: ", __func__)nvme_show_message(1, "%s: FAILURE: ", __func__);
3292 nvme_show_status(ret);
3293 nvme_show_error("%s: Partial data may have been captured", __func__)nvme_show_message(1, "%s: Partial data may have been captured"
, __func__)
;
3294 snprintf(file + strlen(file), PATH_MAX4096, "%s", "-PARTIAL");
3295 }
3296
3297 ret = wdc_create_log_file(file, dump_data, data_len);
3298
3299 free(dump_data);
3300 return ret;
3301}
3302
3303static int wdc_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
3304 struct libnvme_transport_handle *hdl, const char *file,
3305 __u32 bs, int type, int data_area)
3306{
3307 struct nvme_telemetry_log *log;
3308 size_t full_size = 0;
3309 int err = 0, output;
3310 int ctrl_init = 0;
3311 __u64 result;
3312 void *buf = NULL((void*)0);
3313 struct libnvme_passthru_cmd cmd;
3314 struct nvme_id_ctrl ctrl;
3315 __u64 capabilities = 0;
3316
3317 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
3318 nvme_init_identify_ctrl(&cmd, &ctrl);
3319 err = libnvme_exec_admin_passthru(hdl, &cmd);
3320 if (err) {
3321 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", err)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, err)
;
3322 return err;
3323 }
3324
3325 if (!(ctrl.lpa & 0x8)) {
3326 nvme_show_error("Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported")nvme_show_message(1, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported"
)
;
3327 return -EINVAL22;
3328 }
3329
3330 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3331 if (err) {
3332 nvme_show_error("Failed to scan nvme subsystems")nvme_show_message(1, "Failed to scan nvme subsystems");
3333 return err;
3334 }
3335
3336 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3337
3338 if (type == WDC_TELEMETRY_TYPE_HOST0x1) {
3339 ctrl_init = 0;
3340 } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2) {
3341 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
3342 /* Verify the Controller Initiated Option is enabled */
3343 err = nvme_get_features(hdl, 0,
3344 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
3345 NVME_GET_FEATURES_SEL_CURRENT, 0, 0,
3346 buf, 4, &result);
3347 if (!err) {
3348 if (!result) {
3349 /* enabled */
3350 ctrl_init = 1;
3351 } else {
3352 nvme_show_error("%s: Controller initiated option telemetry log page disabled", __func__)nvme_show_message(1, "%s: Controller initiated option telemetry log page disabled"
, __func__)
;
3353 return -EINVAL22;
3354 }
3355 } else {
3356 nvme_show_error("ERROR: WDC: Get telemetry option feature failed.")nvme_show_message(1, "ERROR: WDC: Get telemetry option feature failed."
)
;
3357 nvme_show_status(err);
3358 return -EPERM1;
3359 }
3360 } else {
3361 ctrl_init = 1;
3362 }
3363 } else {
3364 nvme_show_error("%s: Invalid type parameter; type = %d", __func__, type)nvme_show_message(1, "%s: Invalid type parameter; type = %d",
__func__, type)
;
3365 return -EINVAL22;
3366 }
3367
3368 if (!file) {
3369 nvme_show_error("%s: Please provide an output file!", __func__)nvme_show_message(1, "%s: Please provide an output file!", __func__
)
;
3370 return -EINVAL22;
3371 }
3372
3373 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3374 if (output < 0) {
3375 nvme_show_error("%s: Failed to open output file %s: %s!",nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3376 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3377 return output;
3378 }
3379
3380 if (ctrl_init)
3381 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
3382 data_area, &full_size);
3383 else
3384 err = libnvme_get_new_host_telemetry(hdl, &log,
3385 data_area, &full_size);
3386
3387 if (err < 0) {
3388 nvme_show_err(err, "get-telemetry-log");
3389 goto close_output;
3390 } else if (err > 0) {
3391 nvme_show_status(err);
3392 nvme_show_error("%s: Failed to acquire telemetry header!", __func__)nvme_show_message(1, "%s: Failed to acquire telemetry header!"
, __func__)
;
3393 goto close_output;
3394 }
3395
3396 /*
3397 * Continuously pull data until the offset hits the end of the last
3398 * block.
3399 */
3400 err = shr_write_all(output, log, full_size);
3401 if (err)
3402 nvme_show_error("ERROR: %s: write: %s", __func__, libnvme_strerror(-err))nvme_show_message(1, "ERROR: %s: write: %s", __func__, libnvme_strerror
(-err))
;
3403 else if (shr_fsync(output) < 0) {
3404 nvme_show_error("ERROR: %s: fsync: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "ERROR: %s: fsync: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3405 err = -1;
3406 }
3407
3408 free(log);
3409close_output:
3410 close(output);
3411 return err;
3412}
3413
3414static int wdc_do_cap_diag(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *file,
3415 __u32 xfer_size, int type, int data_area)
3416{
3417 int ret = -1;
3418 __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08;
3419 struct wdc_e6_log_hdr *log_hdr;
3420 __u32 cap_diag_length;
3421
3422 log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size);
3423 if (!log_hdr) {
3424 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3425 ret = -1;
3426 goto out;
3427 }
3428 memset(log_hdr, 0, e6_log_hdr_size);
3429
3430 if (type == WDC_TELEMETRY_TYPE_NONE0x0) {
3431 if (data_area) {
3432 nvme_show_error(nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3433 "%s: ERROR: Data area parameter is not supported when type is NONE\n",nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3434 __func__)nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
;
3435 ret = -1;
3436 goto out;
3437 }
3438 ret = wdc_dump_length_e6(hdl,
3439 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3440 WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08>>2,
3441 0x00,
3442 log_hdr);
3443 if (ret == -1) {
3444 ret = -1;
3445 goto out;
3446 }
3447
3448 cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 |
3449 log_hdr->log_size[2] << 8 | log_hdr->log_size[3]);
3450
3451 if (!cap_diag_length) {
3452 nvme_show_error("INFO: WDC: Capture Diagnostics log is empty")nvme_show_message(1, "INFO: WDC: Capture Diagnostics log is empty"
)
;
3453 } else if (cap_diag_length < WDC_NVME_LOG_SIZE_HDR_LEN0x08) {
3454 nvme_show_error("%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)",nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)"
, __func__, cap_diag_length, 0x08)
3455 __func__, cap_diag_length, WDC_NVME_LOG_SIZE_HDR_LEN)nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x is smaller than the header (0x%x)"
, __func__, cap_diag_length, 0x08)
;
3456 ret = -1;
3457 } else if (cap_diag_length > WDC_NVME_CAP_DIAG_LENGTH_MAX(1U << 30)) {
3458 nvme_show_error("%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x",nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x"
, __func__, cap_diag_length, (1U << 30))
3459 __func__, cap_diag_length, WDC_NVME_CAP_DIAG_LENGTH_MAX)nvme_show_message(1, "%s: ERROR: Capture Diagnostics log length 0x%x exceeds maximum 0x%x"
, __func__, cap_diag_length, (1U << 30))
;
3460 ret = -1;
3461 } else {
3462 ret = wdc_do_dump_e6(hdl,
3463 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3464 cap_diag_length,
3465 (WDC_NVME_CAP_DIAG_SUBCMD0x00 << WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_CAP_DIAG_CMD0x00,
3466 file, xfer_size, (__u8 *)log_hdr);
3467
3468 nvme_show_error("INFO: WDC: Capture Diagnostics log, length = 0x%x", cap_diag_length)nvme_show_message(1, "INFO: WDC: Capture Diagnostics log, length = 0x%x"
, cap_diag_length)
;
3469 }
3470 } else if ((type == WDC_TELEMETRY_TYPE_HOST0x1) ||
3471 (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
3472 /* Get the desired telemetry log page */
3473 ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size,
3474 type, data_area);
3475 } else {
3476 nvme_show_error("%s: ERROR: Invalid type : %d", __func__, type)nvme_show_message(1, "%s: ERROR: Invalid type : %d", __func__
, type)
;
3477 }
3478
3479out:
3480 free(log_hdr);
3481 return ret;
3482}
3483
3484static int wdc_do_cap_dui_v1(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3485 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size)
3486{
3487 __s32 log_size = 0;
3488 __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size);
3489 __u32 curr_data_offset = 0;
3490 __u8 *buffer_addr;
3491 __u8 *dump_data = NULL((void*)0);
3492 bool_Bool last_xfer = false0;
3493 int err;
3494 int i;
3495 int j;
3496 int output;
3497 int ret = 0;
3498
3499 if (verbose) {
3500 nvme_show_error("INFO: WDC: Capture V1 Device Unit Info log, data area = %d",nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
3501 data_area)nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
;
3502 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x", log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr
->hdr_version)
;
3503 nvme_show_error("INFO: WDC: DUI section count = 0x%x", log_hdr->section_count)nvme_show_message(1, "INFO: WDC: DUI section count = 0x%x", log_hdr
->section_count)
;
3504 nvme_show_error("INFO: WDC: DUI log size = 0x%x", log_hdr->log_size)nvme_show_message(1, "INFO: WDC: DUI log size = 0x%x", log_hdr
->log_size)
;
3505 }
3506
3507 if (!cap_dui_length) {
3508 nvme_show_error("INFO: WDC: Capture V1 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log is empty"
)
;
3509 return 0;
3510 }
3511
3512 /* parse log header for all sections up to specified data area inclusively */
3513 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3514 for (j = 0; j < log_hdr->section_count; j++) {
3515 log_size += log_hdr->log_section[j].section_size;
3516 if (verbose)
3517 nvme_show_error(nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3518 "%s: section size 0x%x, total size = 0x%x\n",nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3519 __func__,nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3520 (unsigned int)log_hdr->log_section[j].section_size,nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
3521 (unsigned int)log_size)nvme_show_message(1, "%s: section size 0x%x, total size = 0x%x\n"
, __func__, (unsigned int)log_hdr->log_section[j].section_size
, (unsigned int)log_size)
;
3522
3523 }
3524 } else {
3525 log_size = cap_dui_length;
3526 }
3527
3528 *total_size = log_size;
3529
3530 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size);
3531 if (!dump_data) {
3532 nvme_show_error("%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x",nvme_show_message(1, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size)
3533 __func__, libnvme_strerror(errno), (unsigned int)xfer_size)nvme_show_message(1, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size)
;
3534 return -1;
3535 }
3536 memset(dump_data, 0, sizeof(__u8) * xfer_size);
3537
3538 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3539 if (output < 0) {
3540 nvme_show_error("%s: Failed to open output file %s: %s!", __func__, file,nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3541 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3542 free(dump_data);
3543 return output;
3544 }
3545
3546 /* write the telemetry and log headers into the dump_file */
3547 err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE0x400);
3548 if (err != WDC_NVME_CAP_DUI_HEADER_SIZE0x400) {
3549 nvme_show_error("%s: Failed to flush header data to file!", __func__)nvme_show_message(1, "%s: Failed to flush header data to file!"
, __func__)
;
3550 goto free_mem;
3551 }
3552
3553 log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3554 curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3555 i = 0;
3556 buffer_addr = dump_data;
3557
3558 for (; log_size > 0; log_size -= xfer_size) {
3559 xfer_size = min(xfer_size, log_size)({ typeof(xfer_size) _a = (xfer_size); typeof(log_size) _b = (
log_size); do { } while (0); _a < _b ? _a : _b; })
;
3560
3561 if (log_size <= xfer_size)
3562 last_xfer = true1;
3563
3564 ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer);
3565 if (ret) {
3566 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
3567 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
3568 __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t
)log_size, curr_data_offset, buffer_addr)
;
3569 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3570 nvme_show_status(ret);
3571 break;
3572 }
3573
3574 /* write the dump data into the file */
3575 err = write(output, (void *)buffer_addr, xfer_size);
3576 if (err != xfer_size) {
3577 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
3578 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
3579 __func__, i, err, xfer_size)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n"
, __func__, i, err, xfer_size)
;
3580 ret = -1;
3581 goto free_mem;
3582 }
3583
3584 curr_data_offset += xfer_size;
3585 i++;
3586 }
3587
3588free_mem:
3589 close(output);
3590 free(dump_data);
3591 return ret;
3592}
3593
3594static int wdc_do_cap_dui_v2_v3(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3595 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3596 __u64 offset)
3597{
3598 __u64 cap_dui_length_v3;
3599 __u64 curr_data_offset = 0;
3600 __s64 log_size = 0;
3601 __u64 xfer_size_long = (__u64)xfer_size;
3602 __u8 *buffer_addr;
3603 __u8 *dump_data = NULL((void*)0);
3604 bool_Bool last_xfer = false0;
3605 int err;
3606 int i;
3607 int j;
3608 int output;
3609 int ret = 0;
3610 struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr;
3611
3612 cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size);
3613
3614 if (verbose) {
3615 nvme_show_error(nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3616 "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n",nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3617 data_area)nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
;
3618
3619 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x",nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
3620 log_hdr_v3->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
;
3621 if ((log_hdr->hdr_version & 0xFF) == 0x03)
3622 nvme_show_error("INFO: WDC: DUI Product ID = 0x%x/%c",nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v3
->product_id, log_hdr_v3->product_id)
3623 log_hdr_v3->product_id, log_hdr_v3->product_id)nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v3
->product_id, log_hdr_v3->product_id)
;
3624 }
3625
3626 if (!cap_dui_length_v3) {
3627 nvme_show_error("INFO: WDC: Capture V2 or V3 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log is empty"
)
;
3628 return 0;
3629 }
3630
3631 /* parse log header for all sections up to specified data area inclusively */
3632 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3633 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V30x23; j++) {
3634 if (log_hdr_v3->log_section[j].data_area_id <= data_area &&
3635 log_hdr_v3->log_section[j].data_area_id) {
3636 log_size += log_hdr_v3->log_section[j].section_size;
3637 if (verbose)
3638 nvme_show_error(nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3639 "%s: Data area ID %d : section size 0x%x, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3640 __func__, log_hdr_v3->log_section[j].data_area_id,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3641 (unsigned int)log_hdr_v3->log_section[j].section_size,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
3642 (uint64_t)log_size)nvme_show_message(1, "%s: Data area ID %d : section size 0x%x, total size = 0x%"
"l" "x""\n", __func__, log_hdr_v3->log_section[j].data_area_id
, (unsigned int)log_hdr_v3->log_section[j].section_size, (
uint64_t)log_size)
;
3643 } else {
3644 if (verbose)
3645 nvme_show_error("%s: break, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
3646 __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3647 break;
3648 }
3649 }
3650 } else {
3651 log_size = cap_dui_length_v3;
3652 }
3653
3654 *total_size = log_size;
3655
3656 if (offset >= *total_size) {
3657 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3658 "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3659 __func__, (uint64_t)offset, (uint64_t)*total_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
;
3660 return -1;
3661 }
3662
3663 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3664 if (!dump_data) {
3665 nvme_show_error(nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
3666 "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
3667 __func__, libnvme_strerror(errno), (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"
"l" "x""\n", __func__, libnvme_strerror((*__errno_location ()
)), (uint64_t)xfer_size_long)
;
3668 return -1;
3669 }
3670 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3671
3672 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3673 if (output < 0) {
3674 nvme_show_error("%s: Failed to open output file %s: %s!",nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3675 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3676 free(dump_data);
3677 return output;
3678 }
3679
3680 curr_data_offset = 0;
3681
3682 if (file_size) {
3683 /* Write the DUI data based on the passed in file size */
3684 if ((offset + file_size) > *total_size)
3685 log_size = min((*total_size - offset), file_size)({ typeof((*total_size - offset)) _a = ((*total_size - offset
)); typeof(file_size) _b = (file_size); do { } while (0); _a <
_b ? _a : _b; })
;
3686 else
3687 log_size = min(*total_size, file_size)({ typeof(*total_size) _a = (*total_size); typeof(file_size) _b
= (file_size); do { } while (0); _a < _b ? _a : _b; })
;
3688
3689 if (verbose)
3690 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3691 "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3692 __func__, (uint64_t)offset,nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3693 (uint64_t)file_size, (uint64_t)*total_size, (uint64_t)log_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
;
3694
3695 curr_data_offset = offset;
3696 }
3697
3698 i = 0;
3699 buffer_addr = dump_data;
3700
3701 for (; log_size > 0; log_size -= xfer_size_long) {
3702 xfer_size_long = min(xfer_size_long, log_size)({ typeof(xfer_size_long) _a = (xfer_size_long); typeof(log_size
) _b = (log_size); do { } while (0); _a < _b ? _a : _b; })
;
3703
3704 if (log_size <= xfer_size_long)
3705 last_xfer = true1;
3706
3707 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr,
3708 last_xfer);
3709 if (ret) {
3710 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3711 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3712 __func__, i, (uint64_t)*total_size, (uint64_t)curr_data_offset,nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
3713 buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)*total_size, (uint64_t)curr_data_offset, buffer_addr
)
;
3714 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3715 nvme_show_status(ret);
3716 break;
3717 }
3718
3719 /* write the dump data into the file */
3720 err = write(output, (void *)buffer_addr, xfer_size_long);
3721 if (err != xfer_size_long) {
3722 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3723 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3724 __func__, i, err, (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
;
3725 ret = -1;
3726 goto free_mem;
3727 }
3728
3729 curr_data_offset += xfer_size_long;
3730 i++;
3731 }
3732
3733free_mem:
3734 close(output);
3735 free(dump_data);
3736 return ret;
3737}
3738
3739static int wdc_do_cap_dui_v4(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3740 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3741 __u64 offset)
3742{
3743 __s64 log_size = 0;
3744 __s64 section_size_bytes = 0;
3745 __s64 xfer_size_long = (__s64)xfer_size;
3746 __u64 cap_dui_length_v4;
3747 __u64 curr_data_offset = 0;
3748 __u8 *buffer_addr;
3749 __u8 *dump_data = NULL((void*)0);
3750 int err;
3751 int i;
3752 int j;
3753 int output;
3754 int ret = 0;
3755 bool_Bool last_xfer = false0;
3756 struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr;
3757
3758 cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE512;
3759
3760 if (verbose) {
3761 nvme_show_error("INFO: WDC: Capture V4 Device Unit Info log, data area = %d", data_area)nvme_show_message(1, "INFO: WDC: Capture V4 Device Unit Info log, data area = %d"
, data_area)
;
3762 nvme_show_error("INFO: WDC: DUI Header Version = 0x%x", log_hdr_v4->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v4
->hdr_version)
;
3763 nvme_show_error("INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v4->product_id, log_hdr_v4->product_id)nvme_show_message(1, "INFO: WDC: DUI Product ID = 0x%x/%c", log_hdr_v4
->product_id, log_hdr_v4->product_id)
;
3764 nvme_show_error("INFO: WDC: DUI log size sectors = 0x%x", log_hdr_v4->log_size_sectors)nvme_show_message(1, "INFO: WDC: DUI log size sectors = 0x%x"
, log_hdr_v4->log_size_sectors)
;
3765 nvme_show_error("INFO: WDC: DUI cap_dui_length = 0x%"PRIx64"\n", (uint64_t)cap_dui_length_v4)nvme_show_message(1, "INFO: WDC: DUI cap_dui_length = 0x%""l"
"x""\n", (uint64_t)cap_dui_length_v4)
;
3766 }
3767
3768 if (!cap_dui_length_v4) {
3769 nvme_show_error("INFO: WDC: Capture V4 Device Unit Info log is empty")nvme_show_message(1, "INFO: WDC: Capture V4 Device Unit Info log is empty"
)
;
3770 return 0;
3771 }
3772
3773 /* parse log header for all sections up to specified data area inclusively */
3774 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3775 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION0x3A; j++) {
3776 if (log_hdr_v4->log_section[j].data_area_id <= data_area &&
3777 log_hdr_v4->log_section[j].data_area_id) {
3778 section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE512);
3779 log_size += section_size_bytes;
3780 if (verbose)
3781 nvme_show_error(nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3782 "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"PRIx64" bytes, total size = 0x%"PRIx64"\n",nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3783 __func__, log_hdr_v4->log_section[j].data_area_id,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3784 log_hdr_v4->log_section[j].section_size_sectors,nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
3785 (uint64_t)section_size_bytes, (uint64_t)log_size)nvme_show_message(1, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"
"l" "x"" bytes, total size = 0x%""l" "x""\n", __func__, log_hdr_v4
->log_section[j].data_area_id, log_hdr_v4->log_section[
j].section_size_sectors, (uint64_t)section_size_bytes, (uint64_t
)log_size)
;
3786 } else {
3787 if (verbose)
3788 nvme_show_error("%s: break, total size = 0x%"PRIx64"\n", __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3789 break;
3790 }
3791 }
3792 } else {
3793 log_size = cap_dui_length_v4;
3794 }
3795
3796 *total_size = log_size;
3797
3798 if (offset >= *total_size) {
3799 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3800 "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
3801 __func__, (uint64_t)offset, (uint64_t)*total_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"" exceeds total size 0x%"
"l" "x"", no data retrieved\n", __func__, (uint64_t)offset, (
uint64_t)*total_size)
;
3802 return -1;
3803 }
3804
3805 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3806 if (!dump_data) {
3807 nvme_show_error("%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x",nvme_show_message(1, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size_long)
3808 __func__, libnvme_strerror(errno), (unsigned int)xfer_size_long)nvme_show_message(1, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), (unsigned
int)xfer_size_long)
;
3809 return -1;
3810 }
3811 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3812
3813 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3814 if (output < 0) {
3815 nvme_show_error("%s: Failed to open output file %s: %s!", __func__, file,nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
3816 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3817 free(dump_data);
3818 return output;
3819 }
3820
3821 curr_data_offset = 0;
3822
3823 if (file_size) {
3824 /* Write the DUI data based on the passed in file size */
3825 if ((offset + file_size) > *total_size)
3826 log_size = min((*total_size - offset), file_size)({ typeof((*total_size - offset)) _a = ((*total_size - offset
)); typeof(file_size) _b = (file_size); do { } while (0); _a <
_b ? _a : _b; })
;
3827 else
3828 log_size = min(*total_size, file_size)({ typeof(*total_size) _a = (*total_size); typeof(file_size) _b
= (file_size); do { } while (0); _a < _b ? _a : _b; })
;
3829
3830 if (verbose)
3831 nvme_show_error(nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3832 "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n",nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3833 __func__, (uint64_t)offset, (uint64_t)file_size,nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
3834 (uint64_t)*total_size, (uint64_t)log_size)nvme_show_message(1, "%s: INFO: WDC: Offset 0x%""l" "x"", file size 0x%"
"l" "x"", total size 0x%""l" "x"", log size 0x%""l" "x""\n", __func__
, (uint64_t)offset, (uint64_t)file_size, (uint64_t)*total_size
, (uint64_t)log_size)
;
3835
3836 curr_data_offset = offset;
3837 }
3838
3839 i = 0;
3840 buffer_addr = dump_data;
3841
3842 for (; log_size > 0; log_size -= xfer_size_long) {
3843 xfer_size_long = min(xfer_size_long, log_size)({ typeof(xfer_size_long) _a = (xfer_size_long); typeof(log_size
) _b = (log_size); do { } while (0); _a < _b ? _a : _b; })
;
3844
3845 if (log_size <= xfer_size_long)
3846 last_xfer = true1;
3847
3848 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer);
3849 if (ret) {
3850 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3851 "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3852 __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset,nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
3853 buffer_addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%"
"l" "x"", offset = 0x%""l" "x"", addr = %p\n", __func__, i, (
uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr)
;
3854 nvme_show_error("%s: ERROR: WDC:", __func__)nvme_show_message(1, "%s: ERROR: WDC:", __func__);
3855 nvme_show_status(ret);
3856 break;
3857 }
3858
3859 /* write the dump data into the file */
3860 err = write(output, (void *)buffer_addr, xfer_size_long);
3861 if (err != xfer_size_long) {
3862 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3863 "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"PRIx64"\n",nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
3864 __func__, i, err, (uint64_t)xfer_size_long)nvme_show_message(1, "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"
"l" "x""\n", __func__, i, err, (uint64_t)xfer_size_long)
;
3865 ret = -1;
3866 goto free_mem;
3867 }
3868
3869 curr_data_offset += xfer_size_long;
3870 i++;
3871 }
3872
3873free_mem:
3874 close(output);
3875 free(dump_data);
3876 return ret;
3877}
3878
3879static int wdc_do_cap_dui(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3880 __u64 file_size, __u64 offset)
3881{
3882 int ret = 0;
3883 __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3884 struct wdc_dui_log_hdr *log_hdr;
3885 __s64 total_size = 0;
3886 bool_Bool last_xfer = false0;
3887
3888 log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size);
3889 if (!log_hdr) {
3890 nvme_show_error("%s: ERROR: log header malloc failed : status %s, size 0x%x",nvme_show_message(1, "%s: ERROR: log header malloc failed : status %s, size 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), dui_log_hdr_size
)
3891 __func__, libnvme_strerror(errno), dui_log_hdr_size)nvme_show_message(1, "%s: ERROR: log header malloc failed : status %s, size 0x%x"
, __func__, libnvme_strerror((*__errno_location ())), dui_log_hdr_size
)
;
3892 return -1;
3893 }
3894 memset(log_hdr, 0, dui_log_hdr_size);
3895
3896 /* get the dui telemetry and log headers */
3897 ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE0x400, 0x00, (__u8 *)log_hdr, last_xfer);
3898 if (ret) {
3899 nvme_show_error("%s: ERROR: WDC: Get DUI headers failed", __func__)nvme_show_message(1, "%s: ERROR: WDC: Get DUI headers failed"
, __func__)
;
3900 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3901 nvme_show_status(ret);
3902 goto out;
3903 }
3904
3905 /* Check the Log Header version */
3906 if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) {
3907 ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr,
3908 &total_size);
3909 if (ret)
3910 goto out;
3911 } else if ((log_hdr->hdr_version & 0xFF) == 0x02 ||
3912 (log_hdr->hdr_version & 0xFF) == 0x03) {
3913 /* Process Version 2 or 3 header */
3914 ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr,
3915 &total_size, file_size, offset);
3916 if (ret)
3917 goto out;
3918 } else if ((log_hdr->hdr_version & 0xFF) == 0x04) {
3919 ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr,
3920 &total_size, file_size, offset);
3921 if (ret)
3922 goto out;
3923 } else {
3924 nvme_show_error("INFO: WDC: Unsupported header version = 0x%x",nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
3925 log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
;
3926 goto out;
3927 }
3928
3929 nvme_show_status(ret);
3930 if (verbose)
3931 nvme_show_error("INFO: WDC: Capture Device Unit Info log, length = 0x%"PRIx64"\n",nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
3932 (uint64_t)total_size)nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
;
3933
3934out:
3935 free(log_hdr);
3936 return ret;
3937}
3938
3939static int wdc_cap_diag(int argc, char **argv, struct command *acmd,
3940 struct plugin *plugin)
3941{
3942 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
3943 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
3944 const char *desc = "Capture Diagnostics Log.";
3945 const char *file = "Output file pathname.";
3946 const char *size = "Data retrieval transfer size.";
3947 __u64 capabilities = 0;
3948 char f[PATH_MAX4096] = {0};
3949 __u32 xfer_size = 0;
3950 int ret = 0;
3951
3952 struct config {
3953 char *file;
3954 __u32 xfer_size;
3955 };
3956
3957 struct config cfg = {
3958 .file = NULL((void*)0),
3959 .xfer_size = 0x10000
3960 };
3961
3962 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
3963 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
3964 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size){"transfer-size", 's', "NUM", CFG_POSITIVE, _Generic(&cfg
.xfer_size, uint32_t * : (&cfg.xfer_size)), ARGCONFIG_ARG_REQUIRED
, size, 0, }
,
3965 OPT_END(){ ((void*)0) }
3966 };
3967
3968 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3969 if (ret)
3970 return ret;
3971
3972 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3973 if (ret)
3974 return ret;
3975
3976 if (cfg.file)
3977 shr_strscpy(f, cfg.file, sizeof(f));
3978 if (cfg.xfer_size)
3979 xfer_size = cfg.xfer_size;
3980 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "cap_diag");
3981 if (ret) {
3982 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
3983 return ret;
3984 }
3985 if (!cfg.file) {
3986 if (strlen(f) > PATH_MAX4096 - 5) {
3987 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
3988 return -1;
3989 }
3990 shr_strscat(f, ".bin", sizeof(f));
3991 }
3992
3993 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3994 if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001) == WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001)
3995 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0);
3996 else
3997 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
3998 return ret;
3999}
4000
4001static int wdc_do_get_sn730_log_len(struct libnvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode)
4002{
4003 int ret;
4004 uint32_t *output = NULL((void*)0);
4005 struct libnvme_passthru_cmd admin_cmd;
4006
4007 output = (uint32_t *)malloc(sizeof(uint32_t));
4008 if (!output) {
4009 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4010 return -1;
4011 }
4012 memset(output, 0, sizeof(uint32_t));
4013 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4014
4015 admin_cmd.data_len = 8;
4016 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
4017 admin_cmd.addr = (uintptr_t)output;
4018 admin_cmd.cdw12 = subopcode;
4019 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
4020
4021 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4022 if (!ret)
4023 *len_buf = *output;
4024 free(output);
4025 return ret;
4026}
4027
4028static int wdc_do_get_sn730_log(struct libnvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode)
4029{
4030 int ret;
4031 uint8_t *output = NULL((void*)0);
4032 struct libnvme_passthru_cmd admin_cmd;
4033
4034 output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE0x1000, sizeof(uint8_t));
4035 if (!output) {
4036 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
4037 return -1;
4038 }
4039 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4040 admin_cmd.data_len = SN730_LOG_CHUNK_SIZE0x1000;
4041 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
4042 admin_cmd.addr = (uintptr_t)output;
4043 admin_cmd.cdw12 = subopcode;
4044 admin_cmd.cdw13 = offset;
4045 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
4046
4047 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4048 if (!ret)
4049 memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE0x1000);
4050 return ret;
4051}
4052
4053static int get_sn730_log_chunks(struct libnvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode)
4054{
4055 int ret = 0;
4056 uint8_t *chunk_buf = NULL((void*)0);
4057 int remaining = log_len;
4058 int curr_offset = 0;
4059
4060 chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE0x1000);
4061 if (!chunk_buf) {
4062 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4063 ret = -1;
4064 goto out;
4065 }
4066
4067 while (remaining > 0) {
4068 memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE0x1000);
4069 ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode);
4070 if (!ret) {
4071 if (remaining >= SN730_LOG_CHUNK_SIZE0x1000) {
4072 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4073 chunk_buf, SN730_LOG_CHUNK_SIZE0x1000);
4074 } else {
4075 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4076 chunk_buf, remaining);
4077 }
4078 remaining -= SN730_LOG_CHUNK_SIZE0x1000;
4079 curr_offset += 1;
4080 } else {
4081 goto out;
4082 }
4083 }
4084out:
4085 free(chunk_buf);
4086 return ret;
4087}
4088
4089/* scandir() filter: regular ".bin" log files, skipping dotfiles. */
4090static int wdc_is_bin_file(const struct dirent *ent)
4091{
4092 size_t len = strlen(ent->d_name);
4093
4094 return ent->d_name[0] != '.' && len > 4 &&
4095 !strcmp(ent->d_name + len - 4, ".bin");
4096}
4097
4098/* scandir() filter: any entry, skipping dotfiles. */
4099static int wdc_is_log_file(const struct dirent *ent)
4100{
4101 return ent->d_name[0] != '.';
4102}
4103
4104static int wdc_dirent_cmp(const void *a, const void *b)
4105{
4106 const struct dirent *const *da = a;
4107 const struct dirent *const *db = b;
4108
4109 return strcmp((*da)->d_name, (*db)->d_name);
4110}
4111
4112/*
4113 * scandir() + alphasort() equivalent built on opendir()/readdir(): mingw's
4114 * dirent.h provides the latter but not the former.
4115 */
4116static int wdc_scandir(const char *dir, struct dirent ***namelist,
4117 int (*filter)(const struct dirent *))
4118{
4119 struct dirent *ent, **list = NULL((void*)0), **tmp;
4120 DIR *d;
4121 int n = 0;
4122
4123 d = opendir(dir);
4124 if (!d)
4125 return -1;
4126
4127 while ((ent = readdir(d))) {
4128 if (filter && !filter(ent))
4129 continue;
4130
4131 tmp = realloc(list, (n + 1) * sizeof(*list));
4132 if (!tmp)
4133 goto err;
4134 list = tmp;
4135
4136 list[n] = malloc(sizeof(*list[n]));
4137 if (!list[n])
4138 goto err;
4139 *list[n] = *ent;
4140 n++;
4141 }
4142
4143 closedir(d);
4144
4145 if (n > 0)
4146 qsort(list, n, sizeof(*list), wdc_dirent_cmp);
4147
4148 *namelist = list;
4149 return n;
4150
4151err:
4152 closedir(d);
4153 while (n > 0)
4154 free(list[--n]);
4155 free(list);
4156 return -1;
4157}
4158
4159/*
4160 * Archive dir's entries matching filter into tar_file (gzip), without
4161 * spawning an external process. If remove_after, delete the archived files
4162 * and dir itself once the archive is written, mirroring "tar --remove-files".
4163 */
4164static int wdc_tar_dir_files(const char *tar_file, const char *dir,
4165 int (*filter)(const struct dirent *),
4166 bool_Bool remove_after)
4167{
4168 __cleanup_dirents__attribute__((cleanup(cleanup_dirents))) struct dirents d = {};
4169 char **paths;
4170 int i, ret;
4171
4172 d.num = wdc_scandir(dir, &d.ents, filter);
4173 if (d.num <= 0) {
4174 nvme_show_error("ERROR: WDC: no log files found to archive")nvme_show_message(1, "ERROR: WDC: no log files found to archive"
)
;
4175 return -ENOENT2;
4176 }
4177
4178 paths = calloc(d.num, sizeof(*paths));
4179 if (!paths)
4180 return -ENOMEM12;
4181
4182 ret = 0;
4183 for (i = 0; i < d.num; i++) {
4184 if (asprintf(&paths[i], "%s%s%s", dir, WDC_DE_PATH_SEPARATOR"/",
4185 d.ents[i]->d_name) < 0) {
4186 ret = -ENOMEM12;
4187 break;
4188 }
4189 }
4190
4191 if (!ret) {
4192 ret = shr_tar_gz_create(tar_file,
4193 (const char *const *)paths, d.num);
4194 if (ret == -ENOTSUP95)
4195 nvme_show_error(nvme_show_message(1, "ERROR: WDC: nvme-cli was built without libarchive, archive creation is unavailable"
)
4196 "ERROR: WDC: nvme-cli was built without libarchive, archive creation is unavailable")nvme_show_message(1, "ERROR: WDC: nvme-cli was built without libarchive, archive creation is unavailable"
)
;
4197 }
4198
4199 if (!ret && remove_after) {
4200 /*
4201 * Keep removing the rest even once something fails, but
4202 * report that first failure instead of the success the old
4203 * "tar --remove-files" exit status would no longer be here
4204 * to catch.
4205 */
4206 for (i = 0; i < d.num; i++) {
4207 if (unlink(paths[i]) && !ret)
4208 ret = -errno(*__errno_location ());
4209 }
4210 if (rmdir(dir) && !ret)
4211 ret = -errno(*__errno_location ());
4212 }
4213
4214 for (i = 0; i < d.num; i++)
4215 free(paths[i]);
4216 free(paths);
4217
4218 return ret;
4219}
4220
4221static int wdc_do_sn730_get_and_tar(struct libnvme_transport_handle *hdl, char *outputName)
4222{
4223 int ret = 0;
4224 void *retPtr;
4225 uint8_t *full_log_buf = NULL((void*)0);
4226 uint8_t *key_log_buf = NULL((void*)0);
4227 uint8_t *core_dump_log_buf = NULL((void*)0);
4228 uint8_t *extended_log_buf = NULL((void*)0);
4229 uint32_t full_log_len = 0;
4230 uint32_t key_log_len = 0;
4231 uint32_t core_dump_log_len = 0;
4232 uint32_t extended_log_len = 0;
4233 struct tarfile_metadata *tarInfo = NULL((void*)0);
4234
4235 tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata));
4236 if (!tarInfo) {
4237 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4238 ret = -1;
4239 goto free_buf;
4240 }
4241 memset(tarInfo, 0, sizeof(struct tarfile_metadata));
4242
4243 /* Create Logs directory */
4244 wdc_UtilsGetTime(&tarInfo->timeInfo);
4245 memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString));
4246 wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
4247 tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth,
4248 tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second);
4249
4250 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN256, "%s",
4251 (char *)outputName);
4252
4253 retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN256);
4254 if (retPtr) {
4255 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
4256 (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR"/", (char *)tarInfo->bufferFolderName);
4257 } else {
4258 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
4259 goto free_buf;
4260 }
4261
4262 ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath);
4263 if (ret) {
4264 nvme_show_error("ERROR: WDC: create directory failed, ret = %d, dir = %s", ret, tarInfo->bufferFolderPath)nvme_show_message(1, "ERROR: WDC: create directory failed, ret = %d, dir = %s"
, ret, tarInfo->bufferFolderPath)
;
4265 goto free_buf;
4266 } else {
4267 nvme_show_error("Stored log files in directory: %s", tarInfo->bufferFolderPath)nvme_show_message(1, "Stored log files in directory: %s", tarInfo
->bufferFolderPath)
;
4268 }
4269
4270 ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH0x00080009);
4271 if (ret) {
4272 nvme_show_status(ret);
4273 goto free_buf;
4274 }
4275 ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH0x00090009);
4276 if (ret) {
4277 nvme_show_status(ret);
4278 goto free_buf;
4279 }
4280 ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH0x00120009);
4281 if (ret) {
4282 nvme_show_status(ret);
4283 goto free_buf;
4284 }
4285 ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH0x00420009);
4286 if (ret) {
4287 nvme_show_status(ret);
4288 goto free_buf;
4289 }
4290
4291 full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t));
4292 key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t));
4293 core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t));
4294 extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t));
4295
4296 if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) {
4297 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4298 ret = -1;
4299 goto free_buf;
4300 }
4301
4302 /* Get the full log */
4303 ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE0x00010009);
4304 if (ret) {
4305 nvme_show_status(ret);
4306 goto free_buf;
4307 }
4308
4309 /* Get the key log */
4310 ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE0x00020009);
4311 if (ret) {
4312 nvme_show_status(ret);
4313 goto free_buf;
4314 }
4315
4316 /* Get the core dump log */
4317 ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE0x00030009);
4318 if (ret) {
4319 nvme_show_status(ret);
4320 goto free_buf;
4321 }
4322
4323 /* Get the extended log */
4324 ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009);
4325 if (ret) {
4326 nvme_show_status(ret);
4327 goto free_buf;
4328 }
4329
4330 /* Write log files */
4331 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4332 "full_log", (char *)tarInfo->timeString);
4333 wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len);
4334
4335 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4336 "key_log", (char *)tarInfo->timeString);
4337 wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len);
4338
4339 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4340 "core_dump_log", (char *)tarInfo->timeString);
4341 wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len);
4342
4343 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4344 "extended_log", (char *)tarInfo->timeString);
4345 wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len);
4346
4347 /* Tar the log directory */
4348 wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
4349 ret = wdc_tar_dir_files(tarInfo->tarFileName,
4350 (char *)tarInfo->bufferFolderName,
4351 wdc_is_bin_file, false0);
4352
4353 if (ret)
4354 nvme_show_error("ERROR: WDC: Tar of log data failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Tar of log data failed, ret = %d"
, ret)
;
4355
4356free_buf:
4357 free(tarInfo);
4358 free(full_log_buf);
4359 free(core_dump_log_buf);
4360 free(key_log_buf);
4361 free(extended_log_buf);
4362 return ret;
4363}
4364
4365static int dump_internal_logs(struct libnvme_transport_handle *hdl, const char *dir_name, int verbose)
4366{
4367 char file_path[PATH_MAX4096];
4368 void *telemetry_log;
4369 const size_t bs = 512;
4370 struct nvme_telemetry_log *hdr;
4371 struct libnvme_passthru_cmd cmd;
4372 size_t full_size, offset = bs;
4373 int err, output;
4374
4375 if (verbose)
4376 printf("NVMe Telemetry log...\n");
4377
4378 hdr = malloc(bs);
4379 telemetry_log = malloc(bs);
4380 if (!hdr || !telemetry_log) {
4381 nvme_show_error("Failed to allocate %zu bytes for log: %s", bs, libnvme_strerror(errno))nvme_show_message(1, "Failed to allocate %zu bytes for log: %s"
, bs, libnvme_strerror((*__errno_location ())))
;
4382 err = -ENOMEM12;
4383 goto free_mem;
4384 }
4385 memset(hdr, 0, bs);
4386
4387 snprintf(file_path, sizeof(file_path), "%s/telemetry.bin", dir_name);
4388 output = shr_open_rawdata(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file_path), (01 | 0100 | 01000), 0666);
4389 if (output < 0) {
4390 nvme_show_error("Failed to open output file %s: %s!", file_path, libnvme_strerror(errno))nvme_show_message(1, "Failed to open output file %s: %s!", file_path
, libnvme_strerror((*__errno_location ())))
;
4391 err = output;
4392 goto free_mem;
4393 }
4394
4395 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4396 NVME_CSI_NVM, hdr, bs);
4397 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))
4398 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4399 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
4400 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4401 if (err < 0)
4402 nvme_show_err(err, "get-telemetry-log");
4403 else if (err > 0) {
4404 nvme_show_status(err);
4405 nvme_show_error("Failed to acquire telemetry header %d!", err)nvme_show_message(1, "Failed to acquire telemetry header %d!"
, err)
;
4406 goto close_output;
4407 }
4408
4409 err = write(output, (void *)hdr, bs);
4410 if (err != bs) {
4411 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4412 goto close_output;
4413 }
4414
4415 full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
4416
4417 while (offset != full_size) {
4418 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4419 NVME_CSI_NVM, telemetry_log, bs);
4420 nvme_init_get_log_lpo(&cmd, offset);
4421 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4422 if (err < 0) {
4423 nvme_show_err(err, "get-telemetry-log");
4424 break;
4425 } else if (err > 0) {
4426 nvme_show_error("Failed to acquire full telemetry log!")nvme_show_message(1, "Failed to acquire full telemetry log!");
4427 nvme_show_status(err);
4428 break;
4429 }
4430
4431 err = write(output, (void *)telemetry_log, bs);
4432 if (err != bs) {
4433 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4434 break;
4435 }
4436 err = 0;
4437 offset += bs;
4438 }
4439
4440close_output:
4441 close(output);
4442free_mem:
4443 free(hdr);
4444 free(telemetry_log);
4445
4446 return err;
4447}
4448
4449static int wdc_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
4450 int *data_area)
4451{
4452 struct libnvme_passthru_cmd cmd;
4453 struct nvme_id_ctrl ctrl;
4454 int err;
4455
4456 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
4457 nvme_init_identify_ctrl(&cmd, &ctrl);
4458 err = libnvme_exec_admin_passthru(hdl, &cmd);
4459 if (err) {
4460 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", err)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, err)
;
4461 return err;
4462 }
4463
4464 if (ctrl.lpa & 0x40)
4465 *data_area = 4;
4466 else
4467 *data_area = 3;
4468
4469 return 0;
4470}
4471
4472static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd,
4473 struct plugin *plugin)
4474{
4475 const char *desc = "Internal Firmware Log.";
4476 const char *file = "Output file pathname.";
4477 const char *size = "Data retrieval transfer size.";
4478 const char *data_area =
4479 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
4480 const char *type =
4481 "Telemetry type - NONE, HOST, or CONTROLLER:\n" \
4482 " NONE - Default, capture without using NVMe telemetry.\n" \
4483 " HOST - Host-initiated telemetry.\n" \
4484 " CONTROLLER - Controller-initiated telemetry.";
4485 const char *file_size =
4486 "Output file size. Deprecated, see man page for supported devices.";
4487 const char *offset =
4488 "Output file data offset. Deprecated, see man page for supported devices.";
4489 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4490 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4491 int ret = -1;
4492
4493 struct argconfig_opt_val types[] = {
4494 VAL_ENUM("NONE", WDC_TELEMETRY_TYPE_NONE){"NONE", CFG_ENUM, .val.int_val = 0x0},
4495 VAL_ENUM("HOST", WDC_TELEMETRY_TYPE_HOST){"HOST", CFG_ENUM, .val.int_val = 0x1},
4496 VAL_ENUM("CONTROLLER", WDC_TELEMETRY_TYPE_CONTROLLER){"CONTROLLER", CFG_ENUM, .val.int_val = 0x2},
4497 VAL_END(){ ((void*)0) }
4498 };
4499
4500 struct wdc_vs_internal_fw_log_cfg cfg = {
4501 .file = NULL((void*)0),
4502 .xfer_size = 0x10000,
4503 .data_area = 0,
4504 .file_size = 0,
4505 .offset = 0,
4506 .type = WDC_TELEMETRY_TYPE_NONE0x0,
4507 };
4508
4509 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4510 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
4511 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size){"transfer-size", 's', "NUM", CFG_POSITIVE, _Generic(&cfg
.xfer_size, uint32_t * : (&cfg.xfer_size)), ARGCONFIG_ARG_REQUIRED
, size, 0, }
,
4512 OPT_UINT("data-area", 'd', &cfg.data_area, data_area){"data-area", 'd', "NUM", CFG_POSITIVE, _Generic(&cfg.data_area
, uint32_t * : (&cfg.data_area)), ARGCONFIG_ARG_REQUIRED,
data_area, 0, }
,
4513 OPT_ENUM("type", 't', &cfg.type, type, types){"type", 't', "NAME", CFG_ENUM, _Generic(&cfg.type, int *
: (&cfg.type)), ARGCONFIG_ARG_REQUIRED, type, 0, types, }
,
4514 OPT_LONG("file-size", 'f', &cfg.file_size, file_size){"file-size", 'f', "NUM", CFG_LONG, _Generic(&cfg.file_size
, uint64_t * : (&cfg.file_size), default : _Generic(&
cfg.file_size, unsigned long long * : (&cfg.file_size), default
: (void)0)), ARGCONFIG_ARG_REQUIRED, file_size, 0, }
,
4515 OPT_LONG("offset", 'e', &cfg.offset, offset){"offset", 'e', "NUM", CFG_LONG, _Generic(&cfg.offset, uint64_t
* : (&cfg.offset), default : _Generic(&cfg.offset, unsigned
long long * : (&cfg.offset), default : (void)0)), ARGCONFIG_ARG_REQUIRED
, offset, 0, }
,
4516 OPT_END(){ ((void*)0) }
4517 };
4518
4519 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4520 if (ret)
4521 return ret;
4522
4523 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4524 if (ret)
4525 return ret;
4526
4527 return run_wdc_vs_internal_fw_log(ctx, hdl, &cfg);
4528}
4529
4530int run_wdc_vs_internal_fw_log(struct libnvme_global_ctx *ctx,
4531 struct libnvme_transport_handle *hdl,
4532 struct wdc_vs_internal_fw_log_cfg *cfg)
4533{
4534 char f[PATH_MAX4096] = {0};
4535 char fb[PATH_MAX4096/2] = {0};
4536 char fileSuffix[PATH_MAX4096] = {0};
4537 __u32 xfer_size = 0;
4538 int telemetry_type = 0, telemetry_data_area = 0;
4539 UtilsTimeInfo timeInfo;
4540 __u8 timeStamp[MAX_PATH_LEN256];
4541 __u64 capabilities = 0;
4542 __u32 device_id, read_vendor_id;
4543 char file_path[PATH_MAX4096/2] = {0};
4544 int ret = 0;
4545
4546 if (!wdc_check_device(ctx, hdl))
4547 goto out;
4548
4549 if (cfg->xfer_size) {
4550 xfer_size = cfg->xfer_size;
4551 } else {
4552 nvme_show_error("ERROR: WDC: Invalid length")nvme_show_message(1, "ERROR: WDC: Invalid length");
4553 goto out;
4554 }
4555
4556 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4557
4558 if (!wdc_is_sn861(device_id)) {
4559 if (cfg->file) {
4560 int verify_file;
4561
4562 /* verify file name and path is valid before getting dump data */
4563 verify_file = shr_open_rawdata(cfg->file,open((cfg->file), (01 | 0100 | 01000), 0666)
4564 O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg->file), (01 | 0100 | 01000), 0666);
4565 if (verify_file < 0) {
4566 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
4567 goto out;
4568 }
4569 close(verify_file);
4570 shr_strscpy(f, cfg->file, sizeof(f));
4571 } else {
4572 wdc_UtilsGetTime(&timeInfo);
4573 memset(timeStamp, 0, sizeof(timeStamp));
4574 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4575 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4576 timeInfo.month, timeInfo.dayOfMonth,
4577 timeInfo.hour, timeInfo.minute,
4578 timeInfo.second);
4579 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4580
4581 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix);
4582 if (ret) {
4583 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4584 goto out;
4585 }
4586 }
4587
4588 if (!cfg->file) {
4589 if (strlen(f) > PATH_MAX4096 - 5) {
4590 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4591 ret = -1;
4592 goto out;
4593 }
4594 shr_strscat(f, ".bin", sizeof(f));
4595 }
4596 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
4597
4598 if (cfg->data_area) {
4599 if (cfg->data_area > 5 || cfg->data_area < 1) {
4600 nvme_show_error("ERROR: WDC: Data area must be 1-5")nvme_show_message(1, "ERROR: WDC: Data area must be 1-5");
4601 ret = -1;
4602 goto out;
4603 }
4604 }
4605
4606 telemetry_type = cfg->type;
4607 if (telemetry_type == WDC_TELEMETRY_TYPE_NONE0x0)
4608 telemetry_data_area = 0;
4609 else
4610 telemetry_data_area = cfg->data_area;
4611 } else {
4612 if (cfg->file) {
4613 shr_strscpy(fb, cfg->file, sizeof(fb));
4614 } else {
4615 wdc_UtilsGetTime(&timeInfo);
4616 memset(timeStamp, 0, sizeof(timeStamp));
4617 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4618 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4619 timeInfo.month, timeInfo.dayOfMonth,
4620 timeInfo.hour, timeInfo.minute,
4621 timeInfo.second);
4622 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4623
4624 ret = wdc_get_serial_name(hdl, fb, PATH_MAX4096/2 - 7, fileSuffix);
4625 if (ret) {
4626 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4627 goto out;
4628 }
4629
4630 if (strlen(fb) > PATH_MAX4096/2 - 7) {
4631 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4632 ret = -1;
4633 goto out;
4634 }
4635 }
4636 nvme_show_error("%s: filename = %s.tar.gz", __func__, fb)nvme_show_message(1, "%s: filename = %s.tar.gz", __func__, fb
)
;
4637
4638
4639 memset(file_path, 0, sizeof(file_path));
4640 if (snprintf(file_path, PATH_MAX4096/2 - 8, "%s.tar.gz", fb) >= PATH_MAX4096/2 - 8) {
4641 nvme_show_error("File path is too long!")nvme_show_message(1, "File path is too long!");
4642 ret = -1;
4643 goto out;
4644 }
4645 if (access(file_path, F_OK0) != -1) {
4646 nvme_show_error("Output file already exists!")nvme_show_message(1, "Output file already exists!");
4647 ret = -EEXIST17;
4648 goto out;
4649 }
4650 }
4651
4652 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4653 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
4654 if (!wdc_is_sn861(device_id)) {
4655 if (telemetry_type != WDC_TELEMETRY_TYPE_NONE0x0 &&
4656 wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4657 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4658 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4659 return -EINVAL22;
4660 }
4661
4662 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size,
4663 telemetry_type, telemetry_data_area);
4664 } else {
4665 if (nvme_args.verbose)
4666 printf("Creating temp directory...\n");
4667
4668 ret = shr_mkdir(fb, 0666);
4669 if (ret) {
4670 nvme_show_error("Failed to create directory!")nvme_show_message(1, "Failed to create directory!");
4671 goto out;
4672 }
4673
4674 ret = dump_internal_logs(hdl, fb, nvme_args.verbose);
4675 if (ret < 0)
4676 nvme_show_err(ret, "vs-internal-log");
4677
4678 if (nvme_args.verbose)
4679 printf("Archiving...\n");
4680
4681 ret = wdc_tar_dir_files(file_path, fb,
4682 wdc_is_log_file, true1);
4683 if (ret)
4684 nvme_show_error("Failed to create an archive file!")nvme_show_message(1, "Failed to create an archive file!");
4685 }
4686 goto out;
4687 }
4688 if ((capabilities & WDC_DRIVE_CAP_DUI0x0000000800000000) == WDC_DRIVE_CAP_DUI0x0000000800000000) {
4689 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4690 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4691 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4692 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4693 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4694 return -EINVAL22;
4695 }
4696 /* Get the desired telemetry log page */
4697 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4698 telemetry_type, telemetry_data_area);
4699 goto out;
4700 } else {
4701 if (!cfg->data_area)
4702 cfg->data_area = 1;
4703
4704 /* FW requirement - xfer size must be 256k for data area 4 */
4705 if (cfg->data_area >= 4)
4706 xfer_size = 0x40000;
4707 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4708 cfg->data_area,
4709 nvme_args.verbose, cfg->file_size,
4710 cfg->offset);
4711 goto out;
4712 }
4713 }
4714 if ((capabilities & WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) == WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) {
4715 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4716 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4717 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4718 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4719 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4720 return -EINVAL22;
4721 }
4722 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4723 telemetry_type, telemetry_data_area);
4724 goto out;
4725 } else {
4726 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4727 WDC_NVME_DUI_MAX_DATA_AREA0x05,
4728 nvme_args.verbose, 0, 0);
4729 goto out;
4730 }
4731 }
4732 if ((capabilities & WDC_SN730B_CAP_VUC_LOG0x0000000400000000) == WDC_SN730B_CAP_VUC_LOG0x0000000400000000) {
4733 ret = wdc_do_sn730_get_and_tar(hdl, f);
4734 } else {
4735 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4736 ret = -1;
4737 }
4738out:
4739 return ret;
4740}
4741
4742static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type)
4743{
4744 int ret;
4745 __u32 crash_dump_length;
4746 __u32 opcode;
4747 __u32 cdw12;
4748 __u32 cdw10_size;
4749 __u32 cdw12_size;
4750 __u32 cdw12_clear;
4751
4752 if (type == WDC_NVME_PFAIL_DUMP_TYPE2) {
4753 /* set parms to get the PFAIL Crash Dump */
4754 opcode = WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6;
4755 cdw10_size = WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02;
4756 cdw12_size = ((WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4757 WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20);
4758
4759 cdw12 = (WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4760 WDC_NVME_PF_CRASH_DUMP_CMD0x20;
4761
4762 cdw12_clear = ((WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4763 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4764
4765 } else {
4766 /* set parms to get the Crash Dump */
4767 opcode = WDC_NVME_CRASH_DUMP_OPCODE0xC6;
4768 cdw10_size = WDC_NVME_CRASH_DUMP_SIZE_NDT0x02;
4769 cdw12_size = ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 << WDC_NVME_SUBCMD_SHIFT8) |
4770 WDC_NVME_CRASH_DUMP_SIZE_CMD0x20);
4771
4772 cdw12 = (WDC_NVME_CRASH_DUMP_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
4773 WDC_NVME_CRASH_DUMP_CMD0x20;
4774
4775 cdw12_clear = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4776 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4777 }
4778
4779 ret = wdc_dump_length(hdl,
4780 opcode,
4781 cdw10_size,
4782 cdw12_size,
4783 &crash_dump_length);
4784
4785 if (ret == -1) {
4786 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4787 nvme_show_error("INFO: WDC: Pfail dump get size failed")nvme_show_message(1, "INFO: WDC: Pfail dump get size failed");
4788 else
4789 nvme_show_error("INFO: WDC: Crash dump get size failed")nvme_show_message(1, "INFO: WDC: Crash dump get size failed");
4790
4791 return -1;
4792 }
4793
4794 if (!crash_dump_length) {
4795 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4796 nvme_show_error("INFO: WDC: Pfail dump is empty")nvme_show_message(1, "INFO: WDC: Pfail dump is empty");
4797 else
4798 nvme_show_error("INFO: WDC: Crash dump is empty")nvme_show_message(1, "INFO: WDC: Crash dump is empty");
4799 } else {
4800 ret = wdc_do_dump(hdl,
4801 opcode,
4802 crash_dump_length,
4803 cdw12,
4804 file,
4805 crash_dump_length);
4806
4807 if (!ret)
4808 ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE0xFF,
4809 cdw12_clear);
4810 }
4811 return ret;
4812}
4813
4814static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type)
4815{
4816 char f[PATH_MAX4096] = {0};
4817 const char *dump_type;
4818 int ret;
4819
4820 if (file)
4821 shr_strscpy(f, file, sizeof(f));
4822
4823 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4824 dump_type = "_pfail_dump";
4825 else
4826 dump_type = "_crash_dump";
4827
4828 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, dump_type);
4829 if (ret)
4830 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4831 else
4832 ret = wdc_do_crash_dump(hdl, f, type);
4833 return ret;
4834}
4835
4836static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file)
4837{
4838 int ret;
4839 __u8 *drive_log_data;
4840 __u32 drive_log_length;
4841 struct libnvme_passthru_cmd admin_cmd;
4842
4843 ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6,
4844 WDC_NVME_DRIVE_LOG_SIZE_NDT0x02,
4845 (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 <<
4846 WDC_NVME_SUBCMD_SHIFT8 | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20),
4847 &drive_log_length);
4848 if (ret == -1)
4849 return -1;
4850
4851 drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length);
4852 if (!drive_log_data) {
4853 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4854 return -1;
4855 }
4856
4857 memset(drive_log_data, 0, sizeof(__u8) * drive_log_length);
4858 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4859 admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE0xC6;
4860 admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
4861 admin_cmd.data_len = drive_log_length;
4862 admin_cmd.cdw10 = drive_log_length;
4863 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD0x00 <<
4864 WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20);
4865
4866 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4867 nvme_show_status(ret);
4868 if (!ret)
4869 ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
4870 free(drive_log_data);
4871 return ret;
4872}
4873
4874static int wdc_drive_log(int argc, char **argv, struct command *acmd,
4875 struct plugin *plugin)
4876{
4877 const char *desc = "Capture Drive Log.";
4878 const char *file = "Output file pathname.";
4879 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4880 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4881 char f[PATH_MAX4096] = {0};
4882 int ret;
4883 __u64 capabilities = 0;
4884 struct config {
4885 char *file;
4886 };
4887
4888 struct config cfg = {
4889 .file = NULL((void*)0)
4890 };
4891
4892 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4893 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
4894 OPT_END(){ ((void*)0) }
4895 };
4896
4897 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4898 if (ret)
4899 return ret;
4900
4901 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4902 if (ret || !wdc_check_device(ctx, hdl))
4903 return ret;
4904
4905 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4906
4907 if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400)) {
4908 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4909 ret = -1;
4910 } else {
4911 if (cfg.file)
4912 shr_strscpy(f, cfg.file, sizeof(f));
4913 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "drive_log");
4914 if (ret)
4915 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4916 else
4917 ret = wdc_do_drive_log(hdl, f);
4918 }
4919 return ret;
4920}
4921
4922static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
4923 struct plugin *plugin)
4924{
4925 const char *desc = "Get Crash Dump.";
4926 const char *file = "Output file pathname.";
4927 __u64 capabilities = 0;
4928 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4929 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4930 int ret;
4931
4932 struct config {
4933 char *file;
4934 };
4935
4936 struct config cfg = {
4937 .file = NULL((void*)0),
4938 };
4939
4940 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4941 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
4942 OPT_END(){ ((void*)0) }
4943 };
4944
4945 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4946 if (ret)
4947 return ret;
4948
4949 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4950 if (ret || !wdc_check_device(ctx, hdl))
4951 return ret;
4952
4953 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4954
4955 if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800)) {
4956 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4957 ret = -1;
4958 } else {
4959 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE1);
4960 if (ret)
4961 nvme_show_error("ERROR: WDC: failed to read crash dump")nvme_show_message(1, "ERROR: WDC: failed to read crash dump");
4962 }
4963 return ret;
4964}
4965
4966static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd,
4967 struct plugin *plugin)
4968{
4969 const char *desc = "Get Pfail Crash Dump.";
4970 const char *file = "Output file pathname.";
4971 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4972 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4973 __u64 capabilities = 0;
4974 struct config {
4975 char *file;
4976 };
4977 int ret;
4978
4979 struct config cfg = {
4980 .file = NULL((void*)0),
4981 };
4982
4983 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4984 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
4985 OPT_END(){ ((void*)0) }
4986 };
4987
4988 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4989 if (ret)
4990 return ret;
4991
4992 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4993 if (ret || !wdc_check_device(ctx, hdl))
4994 return ret;
4995
4996 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4997 if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000)) {
4998 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4999 ret = -1;
5000 } else {
5001 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE2);
5002 if (ret)
5003 nvme_show_error("ERROR: WDC: failed to read pfail crash dump")nvme_show_message(1, "ERROR: WDC: failed to read pfail crash dump"
)
;
5004 }
5005 return ret;
5006}
5007
5008static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root)
5009{
5010 /* 24 bytes, not NUL terminated if all used */
5011 char vsn[25] = {0};
5012 int base = 3072;
5013 int vsn_start = 3081;
5014
5015 memcpy(vsn, &vs[vsn_start - base], sizeof(vsn) - 1);
5016 if (root)
5017 json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL");
5018 else
5019 printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL");
5020}
5021
5022static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
5023{
5024 return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl);
5025}
5026
5027static const char *wdc_purge_mon_status_to_string(__u32 status)
5028{
5029 const char *str;
5030
5031 switch (status) {
5032 case WDC_NVME_PURGE_STATE_IDLE0x00:
5033 str = "Purge State Idle.";
5034 break;
5035 case WDC_NVME_PURGE_STATE_DONE0x01:
5036 str = "Purge State Done.";
5037 break;
5038 case WDC_NVME_PURGE_STATE_BUSY0x02:
5039 str = "Purge State Busy.";
5040 break;
5041 case WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03:
5042 str = "Purge Operation resulted in an error that requires power cycle.";
5043 break;
5044 case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04:
5045 str = "The previous purge operation was interrupted by a power cycle\n"
5046 "or reset interruption. Other commands may be rejected until\n"
5047 "Purge Execute is issued and completed.";
5048 break;
5049 default:
5050 str = "Unknown.";
5051 }
5052 return str;
5053}
5054
5055static int wdc_purge(int argc, char **argv,
5056 struct command *command, struct plugin *plugin)
5057{
5058 const char *desc = "Send a Purge command.";
5059 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
5060 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
5061 struct libnvme_passthru_cmd admin_cmd;
5062 __u64 capabilities = 0;
5063 char *err_str;
5064 int ret;
5065
5066 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
5067 OPT_END(){ ((void*)0) }
5068 };
5069
5070 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
5071 if (ret)
5072 return ret;
5073
5074 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
5075 if (ret || !wdc_check_device(ctx, hdl))
5076 return ret;
5077
5078 capabilities = wdc_get_drive_capabilities(ctx, hdl);
5079 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
5080 ret = -1;
5081 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
5082 } else {
5083 err_str = "";
5084 memset(&admin_cmd, 0, sizeof(admin_cmd));
5085 admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE0xDD;
5086
5087 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
5088 if (ret > 0) {
5089 switch (ret) {
5090 case WDC_NVME_PURGE_CMD_SEQ_ERR0x0C:
5091 err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n";
5092 break;
5093 case WDC_NVME_PURGE_INT_DEV_ERR0x06:
5094 err_str = "ERROR: WDC: Internal Device Error.\n";
5095 break;
5096 default:
5097 err_str = "ERROR: WDC\n";
5098 }
5099 }
5100
5101 nvme_show_error("%s", err_str)nvme_show_message(1, "%s", err_str);
5102 nvme_show_status(ret);
5103 }
5104 return ret;
5105}
5106
5107static int wdc_purge_monitor(int argc, char **argv,
5108 struct command *command, struct plugin *plugin)
5109{
5110 const char *desc = "Send a Purge Monitor command.";
5111 __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F];
5112 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
5113 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
5114 double progress_percent;
5115 struct libnvme_passthru_cmd admin_cmd;
5116 struct wdc_nvme_purge_monitor_data *mon;
5117 __u64 capabilities;
5118 int ret;
5119
5120 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
5121 OPT_END(){ ((void*)0) }
5122 };
5123
5124 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
5125 if (ret)
5126 return ret;
5127
5128 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
5129 if (ret || !wdc_check_device(ctx, hdl))
5130 return ret;
5131
5132 capabilities = wdc_get_drive_capabilities(ctx, hdl);
5133 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
5134 ret = -1;
5135 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
5136 } else {
5137 memset(output, 0, sizeof(output));
5138 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
5139 admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE0xDE;
5140 admin_cmd.addr = (__u64)(uintptr_t)output;
5141 admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F;
5142 admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C;
5143 admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530;
5144
5145 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
5146 if (!ret) {
5147 mon = (struct wdc_nvme_purge_monitor_data *) output;
5148 printf("Purge state = 0x%0"PRIx64"l" "x""\n",
5149 (uint64_t)admin_cmd.result);
5150 printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result));
5151 if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY0x02) {
5152 progress_percent =
5153 ((double)le32_to_cpu(mon->entire_progress_current) * 100) /
5154 le32_to_cpu(mon->entire_progress_total);
5155 printf("Purge Progress = %f%%\n", progress_percent);
5156 }
5157 }
5158
5159 nvme_show_status(ret);
5160 }
5161 return ret;
5162}
5163
5164static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf)
5165{
5166 printf(" C1 Log Page Performance Statistics :-\n");
5167 printf(" Host Read Commands %20"PRIu64"l" "u""\n",
5168 le64_to_cpu(perf->hr_cmds));
5169 printf(" Host Read Blocks %20"PRIu64"l" "u""\n",
5170 le64_to_cpu(perf->hr_blks));
5171 printf(" Average Read Size %20lf\n",
5172 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))));
5173 printf(" Host Read Cache Hit Commands %20"PRIu64"l" "u""\n",
5174 le64_to_cpu(perf->hr_ch_cmds));
5175 printf(" Host Read Cache Hit_Percentage %20"PRIu64"l" "u""%%\n",
5176 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)));
5177 printf(" Host Read Cache Hit Blocks %20"PRIu64"l" "u""\n",
5178 le64_to_cpu(perf->hr_ch_blks));
5179 printf(" Average Read Cache Hit Size %20f\n",
5180 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))));
5181 printf(" Host Read Commands Stalled %20"PRIu64"l" "u""\n",
5182 le64_to_cpu(perf->hr_st_cmds));
5183 printf(" Host Read Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5184 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)));
5185 printf(" Host Write Commands %20"PRIu64"l" "u""\n",
5186 le64_to_cpu(perf->hw_cmds));
5187 printf(" Host Write Blocks %20"PRIu64"l" "u""\n",
5188 le64_to_cpu(perf->hw_blks));
5189 printf(" Average Write Size %20f\n",
5190 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))));
5191 printf(" Host Write Odd Start Commands %20"PRIu64"l" "u""\n",
5192 le64_to_cpu(perf->hw_os_cmds));
5193 printf(" Host Write Odd Start Commands Percentage %20"PRIu64"l" "u""%%\n",
5194 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))));
5195 printf(" Host Write Odd End Commands %20"PRIu64"l" "u""\n",
5196 le64_to_cpu(perf->hw_oe_cmds));
5197 printf(" Host Write Odd End Commands Percentage %20"PRIu64"l" "u""%%\n",
5198 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))));
5199 printf(" Host Write Commands Stalled %20"PRIu64"l" "u""\n",
5200 le64_to_cpu(perf->hw_st_cmds));
5201 printf(" Host Write Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5202 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))));
5203 printf(" NAND Read Commands %20"PRIu64"l" "u""\n",
5204 le64_to_cpu(perf->nr_cmds));
5205 printf(" NAND Read Blocks Commands %20"PRIu64"l" "u""\n",
5206 le64_to_cpu(perf->nr_blks));
5207 printf(" Average NAND Read Size %20f\n",
5208 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))));
5209 printf(" Nand Write Commands %20"PRIu64"l" "u""\n",
5210 le64_to_cpu(perf->nw_cmds));
5211 printf(" NAND Write Blocks %20"PRIu64"l" "u""\n",
5212 le64_to_cpu(perf->nw_blks));
5213 printf(" Average NAND Write Size %20f\n",
5214 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))));
5215 printf(" NAND Read Before Write %20"PRIu64"l" "u""\n",
5216 le64_to_cpu(perf->nrbw));
5217}
5218
5219static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf)
5220{
5221 struct json_object *root = json_create_object()json_object_new_object();
5222
5223 json_object_add_value_uint64(root, "Host Read Commands",json_object_object_add(root, "Host Read Commands", json_object_new_uint64
(le64_to_cpu(perf->hr_cmds)))
5224 le64_to_cpu(perf->hr_cmds))json_object_object_add(root, "Host Read Commands", json_object_new_uint64
(le64_to_cpu(perf->hr_cmds)))
;
5225 json_object_add_value_uint64(root, "Host Read Blocks",json_object_object_add(root, "Host Read Blocks", json_object_new_uint64
(le64_to_cpu(perf->hr_blks)))
5226 le64_to_cpu(perf->hr_blks))json_object_object_add(root, "Host Read Blocks", json_object_new_uint64
(le64_to_cpu(perf->hr_blks)))
;
5227 json_object_add_value_uint64(root, "Average Read Size",json_object_object_add(root, "Average Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_blks), le64_to_cpu(perf->
hr_cmds))))
5228 json_avg(le64_to_cpu(perf->hr_blks),json_object_object_add(root, "Average Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_blks), le64_to_cpu(perf->
hr_cmds))))
5229 le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Average Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_blks), le64_to_cpu(perf->
hr_cmds))))
;
5230 json_object_add_value_uint64(root, "Host Read Cache Hit Commands",json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_uint64
(le64_to_cpu(perf->hr_ch_cmds)))
5231 le64_to_cpu(perf->hr_ch_cmds))json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_uint64
(le64_to_cpu(perf->hr_ch_cmds)))
;
5232 json_object_add_value_uint64(root, "Host Read Cache Hit Percentage",json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_uint64(calc_percent(le64_to_cpu(perf->hr_ch_cmds
), le64_to_cpu(perf->hr_cmds))))
5233 calc_percent(le64_to_cpu(perf->hr_ch_cmds),json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_uint64(calc_percent(le64_to_cpu(perf->hr_ch_cmds
), le64_to_cpu(perf->hr_cmds))))
5234 le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_uint64(calc_percent(le64_to_cpu(perf->hr_ch_cmds
), le64_to_cpu(perf->hr_cmds))))
;
5235 json_object_add_value_uint64(root, "Host Read Cache Hit Blocks",json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_uint64
(le64_to_cpu(perf->hr_ch_blks)))
5236 le64_to_cpu(perf->hr_ch_blks))json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_uint64
(le64_to_cpu(perf->hr_ch_blks)))
;
5237 json_object_add_value_uint64(root, "Average Read Cache Hit Size",json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_ch_blks), le64_to_cpu(perf->
hr_ch_cmds))))
5238 json_avg(le64_to_cpu(perf->hr_ch_blks),json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_ch_blks), le64_to_cpu(perf->
hr_ch_cmds))))
5239 le64_to_cpu(perf->hr_ch_cmds)))json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hr_ch_blks), le64_to_cpu(perf->
hr_ch_cmds))))
;
5240 json_object_add_value_uint64(root, "Host Read Commands Stalled",json_object_object_add(root, "Host Read Commands Stalled", json_object_new_uint64
(le64_to_cpu(perf->hr_st_cmds)))
5241 le64_to_cpu(perf->hr_st_cmds))json_object_object_add(root, "Host Read Commands Stalled", json_object_new_uint64
(le64_to_cpu(perf->hr_st_cmds)))
;
5242 json_object_add_value_uint64(root,json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hr_st_cmds
)), le64_to_cpu(perf->hr_cmds))))
5243 "Host Read Commands Stalled Percentage",json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hr_st_cmds
)), le64_to_cpu(perf->hr_cmds))))
5244 calc_percent((le64_to_cpu(perf->hr_st_cmds)),json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hr_st_cmds
)), le64_to_cpu(perf->hr_cmds))))
5245 le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hr_st_cmds
)), le64_to_cpu(perf->hr_cmds))))
;
5246 json_object_add_value_uint64(root, "Host Write Commands",json_object_object_add(root, "Host Write Commands", json_object_new_uint64
(le64_to_cpu(perf->hw_cmds)))
5247 le64_to_cpu(perf->hw_cmds))json_object_object_add(root, "Host Write Commands", json_object_new_uint64
(le64_to_cpu(perf->hw_cmds)))
;
5248 json_object_add_value_uint64(root, "Host Write Blocks",json_object_object_add(root, "Host Write Blocks", json_object_new_uint64
(le64_to_cpu(perf->hw_blks)))
5249 le64_to_cpu(perf->hw_blks))json_object_object_add(root, "Host Write Blocks", json_object_new_uint64
(le64_to_cpu(perf->hw_blks)))
;
5250 json_object_add_value_uint64(root, "Average Write Size",json_object_object_add(root, "Average Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hw_blks), le64_to_cpu(perf->
hw_cmds))))
5251 json_avg(le64_to_cpu(perf->hw_blks),json_object_object_add(root, "Average Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hw_blks), le64_to_cpu(perf->
hw_cmds))))
5252 le64_to_cpu(perf->hw_cmds)))json_object_object_add(root, "Average Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->hw_blks), le64_to_cpu(perf->
hw_cmds))))
;
5253 json_object_add_value_uint64(root, "Host Write Odd Start Commands",json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_uint64(le64_to_cpu(perf->hw_os_cmds)))
5254 le64_to_cpu(perf->hw_os_cmds))json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_uint64(le64_to_cpu(perf->hw_os_cmds)))
;
5255 json_object_add_value_uint64(root,json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_os_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5256 "Host Write Odd Start Commands Percentage",json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_os_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5257 calc_percent((le64_to_cpu(perf->hw_os_cmds)),json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_os_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5258 (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_os_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
;
5259 json_object_add_value_uint64(root, "Host Write Odd End Commands",json_object_object_add(root, "Host Write Odd End Commands", json_object_new_uint64
(le64_to_cpu(perf->hw_oe_cmds)))
5260 le64_to_cpu(perf->hw_oe_cmds))json_object_object_add(root, "Host Write Odd End Commands", json_object_new_uint64
(le64_to_cpu(perf->hw_oe_cmds)))
;
5261 json_object_add_value_uint64(root,json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_oe_cmds
)), (le64_to_cpu((perf->hw_cmds))))))
5262 "Host Write Odd End Commands Percentage",json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_oe_cmds
)), (le64_to_cpu((perf->hw_cmds))))))
5263 calc_percent((le64_to_cpu(perf->hw_oe_cmds)),json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_oe_cmds
)), (le64_to_cpu((perf->hw_cmds))))))
5264 (le64_to_cpu((perf->hw_cmds)))))json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_oe_cmds
)), (le64_to_cpu((perf->hw_cmds))))))
;
5265 json_object_add_value_uint64(root, "Host Write Commands Stalled",json_object_object_add(root, "Host Write Commands Stalled", json_object_new_uint64
(le64_to_cpu(perf->hw_st_cmds)))
5266 le64_to_cpu(perf->hw_st_cmds))json_object_object_add(root, "Host Write Commands Stalled", json_object_new_uint64
(le64_to_cpu(perf->hw_st_cmds)))
;
5267 json_object_add_value_uint64(root,json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_st_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5268 "Host Write Commands Stalled Percentage",json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_st_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5269 calc_percent((le64_to_cpu(perf->hw_st_cmds)),json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_st_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
5270 (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_uint64(calc_percent((le64_to_cpu(perf->hw_st_cmds
)), (le64_to_cpu(perf->hw_cmds)))))
;
5271 json_object_add_value_uint64(root, "NAND Read Commands",json_object_object_add(root, "NAND Read Commands", json_object_new_uint64
(le64_to_cpu(perf->nr_cmds)))
5272 le64_to_cpu(perf->nr_cmds))json_object_object_add(root, "NAND Read Commands", json_object_new_uint64
(le64_to_cpu(perf->nr_cmds)))
;
5273 json_object_add_value_uint64(root, "NAND Read Blocks Commands",json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_uint64
(le64_to_cpu(perf->nr_blks)))
5274 le64_to_cpu(perf->nr_blks))json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_uint64
(le64_to_cpu(perf->nr_blks)))
;
5275 json_object_add_value_uint64(root, "Average NAND Read Size",json_object_object_add(root, "Average NAND Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nr_blks), le64_to_cpu(perf->
nr_cmds))))
5276 json_avg(le64_to_cpu(perf->nr_blks),json_object_object_add(root, "Average NAND Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nr_blks), le64_to_cpu(perf->
nr_cmds))))
5277 le64_to_cpu(perf->nr_cmds)))json_object_object_add(root, "Average NAND Read Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nr_blks), le64_to_cpu(perf->
nr_cmds))))
;
5278 json_object_add_value_uint64(root, "Nand Write Commands",json_object_object_add(root, "Nand Write Commands", json_object_new_uint64
(le64_to_cpu(perf->nw_cmds)))
5279 le64_to_cpu(perf->nw_cmds))json_object_object_add(root, "Nand Write Commands", json_object_new_uint64
(le64_to_cpu(perf->nw_cmds)))
;
5280 json_object_add_value_uint64(root, "NAND Write Blocks",json_object_object_add(root, "NAND Write Blocks", json_object_new_uint64
(le64_to_cpu(perf->nw_blks)))
5281 le64_to_cpu(perf->nw_blks))json_object_object_add(root, "NAND Write Blocks", json_object_new_uint64
(le64_to_cpu(perf->nw_blks)))
;
5282 json_object_add_value_uint64(root, "Average NAND Write Size",json_object_object_add(root, "Average NAND Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nw_blks), le64_to_cpu(perf->
nw_cmds))))
5283 json_avg(le64_to_cpu(perf->nw_blks),json_object_object_add(root, "Average NAND Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nw_blks), le64_to_cpu(perf->
nw_cmds))))
5284 le64_to_cpu(perf->nw_cmds)))json_object_object_add(root, "Average NAND Write Size", json_object_new_uint64
(json_avg(le64_to_cpu(perf->nw_blks), le64_to_cpu(perf->
nw_cmds))))
;
5285 json_object_add_value_uint64(root, "NAND Read Before Written",json_object_object_add(root, "NAND Read Before Written", json_object_new_uint64
(le64_to_cpu(perf->nrbw)))
5286 le64_to_cpu(perf->nrbw))json_object_object_add(root, "NAND Read Before Written", json_object_new_uint64
(le64_to_cpu(perf->nrbw)))
;
5287 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5288 printf("\n");
5289 json_free_object(root)json_object_put(root);
5290}
5291
5292static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt)
5293{
5294 if (!perf) {
5295 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
5296 return -1;
5297 }
5298 switch (fmt) {
5299 case NORMAL:
5300 wdc_print_log_normal(perf);
5301 break;
5302 case JSON:
5303 wdc_print_log_json(perf);
5304 break;
5305 }
5306 return 0;
5307}
5308
5309static int wdc_print_latency_monitor_log_normal(struct libnvme_transport_handle *hdl,
5310 struct wdc_ssd_latency_monitor_log *log_data)
5311{
5312 printf("Latency Monitor/C3 Log Page Data\n");
5313 printf(" Controller : %s\n", libnvme_transport_handle_get_name(hdl));
5314 int err = -1, i, j;
5315 struct libnvme_passthru_cmd cmd;
5316 struct nvme_id_ctrl ctrl;
5317 char ts_buf[128];
5318
5319 nvme_init_identify_ctrl(&cmd, &ctrl);
5320 err = libnvme_exec_admin_passthru(hdl, &cmd);
5321 if (!err) {
5322 printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn);
5323 } else {
5324 nvme_show_error("ERROR: WDC: latency monitor read id ctrl failure, err = %d", err)nvme_show_message(1, "ERROR: WDC: latency monitor read id ctrl failure, err = %d"
, err)
;
5325 return err;
5326 }
5327
5328 printf(" Feature Status 0x%x\n", log_data->feature_status);
5329 printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer));
5330 printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold));
5331 printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1)));
5332 printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1)));
5333 printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1)));
5334 printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1)));
5335 printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config));
5336 printf(" Active Latency Minimum Window %d ms\n", 100*log_data->active_latency_min_window);
5337 printf(" Active Latency Stamp Units %d\n", le16_to_cpu(log_data->active_latency_stamp_units));
5338 printf(" Static Latency Stamp Units %d\n", le16_to_cpu(log_data->static_latency_stamp_units));
5339 if (le16_to_cpu(log_data->log_page_version) >= 4)
5340 printf(" Debug Telemetry Log Size %"PRIu64"l" "u""\n",
5341 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size));
5342 printf(" Debug Log Trigger Enable %d\n",
5343 le16_to_cpu(log_data->debug_log_trigger_enable));
5344 printf(" Log Page Version %d\n",
5345 le16_to_cpu(log_data->log_page_version));
5346 printf(" Log page GUID 0x");
5347 for (j = 0; j < WDC_C3_GUID_LENGTH16; j++)
5348 printf("%x", log_data->log_page_guid[j]);
5349 printf("\n");
5350
5351 printf(" Read Write Deallocate/Trim\n");
5352 for (i = 0; i <= 3; i++)
5353 printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
5354 i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5355 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5356 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5357
5358 for (i = 3; i >= 0; i--)
5359 printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5360 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5361 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5362 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5363
5364 for (i = 3; i >= 0; i--) {
5365 printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
5366 for (j = 2; j >= 0; j--) {
5367 if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) {
5368 printf(" N/A ");
5369 } else {
5370 shr_format_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
5371 printf("%s ", ts_buf);
5372 }
5373 }
5374 printf("\n");
5375 }
5376
5377 for (i = 0; i <= 3; i++)
5378 printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
5379 i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5380 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5381 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5382
5383 for (i = 3; i >= 0; i--)
5384 printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5385 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5386 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5387 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5388
5389 for (i = 3; i >= 0; i--) {
5390 printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
5391 for (j = 2; j >= 0; j--) {
5392 if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) {
5393 printf(" N/A ");
5394 } else {
5395 shr_format_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
5396 printf("%s ", ts_buf);
5397 }
5398 }
5399 printf("\n");
5400 }
5401
5402 return 0;
5403}
5404
5405static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data)
5406{
5407 int i, j;
5408 char buf[128];
5409 const char *operation[3] = {"Read", "Write", "Trim"};
5410 struct json_object *root = json_create_object()json_object_new_object();
5411
5412 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))
;
5413 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)))
;
5414 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
)))
;
5415 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)))
;
5416 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)))
;
5417 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)))
;
5418 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)))
;
5419 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)))
;
5420 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
))
;
5421 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)))
;
5422 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)))
;
5423 if (le16_to_cpu(log_data->log_page_version) >= 4) {
5424 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
)))
5425 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
)))
;
5426 }
5427 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)))
5428 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)))
;
5429 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)))
5430 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)))
;
5431
5432 char guid[40];
5433
5434 memset((void *)guid, 0, 40);
5435 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5436 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5437 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5438 json_object_add_value_string(root, "Log page GUID", guid);
5439
5440 for (i = 0; i <= 3; i++) {
5441 for (j = 2; j >= 0; j--) {
5442 snprintf(buf, sizeof(buf),
5443 "Active Bucket Counter: Bucket %d %s", i,
5444 operation[2-j]);
5445 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])))
;
5446 }
5447 }
5448 for (i = 3; i >= 0; i--) {
5449 for (j = 2; j >= 0; j--) {
5450 snprintf(buf, sizeof(buf),
5451 "Active Measured Latency: Bucket %d %s", 3-i,
5452 operation[2-j]);
5453 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])))
;
5454 }
5455 }
5456 for (i = 3; i >= 0; i--) {
5457 for (j = 2; j >= 0; j--) {
5458 snprintf(buf, sizeof(buf),
5459 "Active Latency Time Stamp: Bucket %d %s", 3-i,
5460 operation[2-j]);
5461 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])))
;
5462 }
5463 }
5464 for (i = 0; i <= 3; i++) {
5465 for (j = 2; j >= 0; j--) {
5466 snprintf(buf, sizeof(buf),
5467 "Static Bucket Counter: Bucket %d %s", i,
5468 operation[2-j]);
5469 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])))
;
5470 }
5471 }
5472 for (i = 3; i >= 0; i--) {
5473 for (j = 2; j >= 0; j--) {
5474 snprintf(buf, sizeof(buf),
5475 "Static Measured Latency: Bucket %d %s", 3-i,
5476 operation[2-j]);
5477 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])))
;
5478 }
5479 }
5480 for (i = 3; i >= 0; i--) {
5481 for (j = 2; j >= 0; j--) {
5482 snprintf(buf, sizeof(buf),
5483 "Static Latency Time Stamp: Bucket %d %s", 3-i,
5484 operation[2-j]);
5485 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])))
;
5486 }
5487 }
5488
5489 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5490 printf("\n");
5491
5492 json_free_object(root)json_object_put(root);
5493}
5494
5495static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data)
5496{
5497 int j;
5498
5499 printf("Error Recovery/C1 Log Page Data\n");
5500
5501 printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time));
5502 printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
5503 printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1);
5504 printf(" Panic ID : 0x%" PRIu64"l" "u" "\n", le64_to_cpu(log_data->panic_id));
5505 printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities));
5506 printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc);
5507 printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12));
5508 printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13));
5509 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5510 printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to);
5511 printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2);
5512 printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to);
5513 }
5514 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5515 printf(" Panic Count : 0x%x\n", log_data->panic_count);
5516 for (j = 0; j < 4; j++)
5517 printf(" Previous Panic ID N-%d : 0x%"PRIx64"l" "x""\n",
5518 j+1, le64_to_cpu(log_data->prev_panic_ids[j]));
5519 }
5520 printf(" Log Page Version : 0x%x\n",
5521 le16_to_cpu(log_data->log_page_version));
5522 printf(" Log page GUID : 0x");
5523 for (j = 0; j < WDC_OCP_C1_GUID_LENGTH16; j++)
5524 printf("%x", log_data->log_page_guid[j]);
5525 printf("\n");
5526}
5527
5528static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
5529{
5530 int j;
5531 char buf[128];
5532 struct json_object *root = json_create_object()json_object_new_object();
5533
5534 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)))
;
5535 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))
;
5536 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))
;
5537 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)))
;
5538 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)))
;
5539 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))
;
5540 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)))
;
5541 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)))
;
5542 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5543 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))
;
5544 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))
;
5545 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))
;
5546 }
5547 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5548 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))
;
5549 for (j = 0; j < 4; j++) {
5550 snprintf(buf, sizeof(buf), "Previous Panic ID N-%d",
5551 j+1);
5552 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])))
5553 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])))
;
5554 }
5555 }
5556 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)))
5557 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)))
;
5558
5559 char guid[40];
5560
5561 memset((void *)guid, 0, 40);
5562 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5563 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5564 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5565 json_object_add_value_string(root, "Log page GUID", guid);
5566
5567 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5568 printf("\n");
5569
5570 json_free_object(root)json_object_put(root);
5571}
5572
5573static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data)
5574{
5575 int j;
5576
5577 printf("Device Capabilities/C4 Log Page Data\n");
5578
5579 printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports));
5580 printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support));
5581 printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support));
5582 printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support));
5583 printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support));
5584 printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support));
5585 printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support));
5586 printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps));
5587
5588 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++)
5589 printf(" DSSD Power State %d Descriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]);
5590
5591 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5592 printf(" Log page GUID : 0x");
5593 for (j = 0; j < WDC_OCP_C4_GUID_LENGTH16; j++)
5594 printf("%x", log_data->log_page_guid[j]);
5595 printf("\n");
5596}
5597
5598static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
5599{
5600 int j;
5601 struct json_object *root = json_create_object()json_object_new_object();
5602
5603 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)))
;
5604 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
)))
;
5605 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)))
;
5606 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)))
;
5607 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)))
;
5608 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)))
;
5609 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)))
;
5610 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)))
;
5611
5612 char dssd_descr_str[40];
5613
5614 memset((void *)dssd_descr_str, 0, 40);
5615 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++) {
5616 snprintf((char *)dssd_descr_str, sizeof(dssd_descr_str),
5617 "DSSD Power State %d Descriptor", j);
5618 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]))
;
5619 }
5620
5621 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)))
;
5622 char guid[40];
5623
5624 memset((void *)guid, 0, 40);
5625 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5626 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5627 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5628 json_object_add_value_string(root, "Log page GUID", guid);
5629
5630 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5631 printf("\n");
5632
5633 json_free_object(root)json_object_put(root);
5634}
5635
5636static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data)
5637{
5638 int j;
5639
5640 printf("Unsupported Requirements/C5 Log Page Data\n");
5641
5642 printf(" Number Unsupported Req IDs : 0x%x\n",
5643 le16_to_cpu(log_data->unsupported_count));
5644
5645 for (j = 0; j < le16_to_cpu(log_data->unsupported_count) &&
5646 j < ARRAY_SIZE(log_data->unsupported_req_list)(sizeof(log_data->unsupported_req_list) / sizeof((log_data
->unsupported_req_list)[0]) + 0)
; j++)
5647 printf(" Unsupported Requirement List %d : %.*s\n", j,
5648 (int)sizeof(log_data->unsupported_req_list[j]),
5649 (char *)log_data->unsupported_req_list[j]);
5650
5651 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5652 printf(" Log page GUID : 0x");
5653 for (j = 0; j < WDC_OCP_C5_GUID_LENGTH16; j++)
5654 printf("%x", log_data->log_page_guid[j]);
5655 printf("\n");
5656}
5657
5658static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
5659{
5660 int j;
5661 struct json_object *root = json_create_object()json_object_new_object();
5662
5663 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)))
;
5664
5665 char unsup_req_list_str[41];
5666
5667 memset((void *)unsup_req_list_str, 0, 41);
5668 for (j = 0; j < le16_to_cpu(log_data->unsupported_count) &&
5669 j < ARRAY_SIZE(log_data->unsupported_req_list)(sizeof(log_data->unsupported_req_list) / sizeof((log_data
->unsupported_req_list)[0]) + 0)
; j++) {
5670 char req[sizeof(log_data->unsupported_req_list[j]) + 1] = {};
5671
5672 memcpy(req, log_data->unsupported_req_list[j],
5673 sizeof(log_data->unsupported_req_list[j]));
5674 snprintf((char *)unsup_req_list_str, sizeof(unsup_req_list_str),
5675 "Unsupported Requirement List %d", j);
5676 json_object_add_value_string(root, unsup_req_list_str, req);
5677 }
5678
5679 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)))
5680 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)))
;
5681 char guid[40];
5682
5683 memset((void *)guid, 0, 40);
5684 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5685 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5686 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5687 json_object_add_value_string(root, "Log page GUID", guid);
5688
5689 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5690 printf("\n");
5691
5692 json_free_object(root)json_object_put(root);
5693}
5694
5695static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
5696{
5697 uint64_t converted = 0;
5698
5699 printf(" CA Log Page Performance Statistics :-\n");
5700 printf(" NAND Bytes Written %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5701 le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo));
5702 printf(" NAND Bytes Read %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5703 le64_to_cpu(perf->nand_bytes_rd_hi), le64_to_cpu(perf->nand_bytes_rd_lo));
5704
5705 converted = le64_to_cpu(perf->nand_bad_block);
5706 printf(" NAND Bad Block Count (Normalized) %20"PRIu64"l" "u""\n",
5707 converted & 0xFFFF);
5708 printf(" NAND Bad Block Count (Raw) %20"PRIu64"l" "u""\n",
5709 converted >> 16);
5710
5711 printf(" Uncorrectable Read Count %20"PRIu64"l" "u""\n",
5712 le64_to_cpu(perf->uncorr_read_count));
5713 printf(" Soft ECC Error Count %20"PRIu64"l" "u""\n",
5714 le64_to_cpu(perf->ecc_error_count));
5715 printf(" SSD End to End Detected Correction Count %20"PRIu32"u""\n",
5716 (uint32_t)le32_to_cpu(perf->ssd_detect_count));
5717 printf(" SSD End to End Corrected Correction Count %20"PRIu32"u""\n",
5718 (uint32_t)le32_to_cpu(perf->ssd_correct_count));
5719 printf(" System Data Percent Used %20"PRIu32"u""%%\n",
5720 perf->data_percent_used);
5721 printf(" User Data Erase Counts Max %20"PRIu32"u""\n",
5722 (uint32_t)le32_to_cpu(perf->data_erase_max));
5723 printf(" User Data Erase Counts Min %20"PRIu32"u""\n",
5724 (uint32_t)le32_to_cpu(perf->data_erase_min));
5725 printf(" Refresh Count %20"PRIu64"l" "u""\n",
5726 le64_to_cpu(perf->refresh_count));
5727
5728 converted = le64_to_cpu(perf->program_fail);
5729 printf(" Program Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5730 converted & 0xFFFF);
5731 printf(" Program Fail Count (Raw) %20"PRIu64"l" "u""\n",
5732 converted >> 16);
5733
5734 converted = le64_to_cpu(perf->user_erase_fail);
5735 printf(" User Data Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5736 converted & 0xFFFF);
5737 printf(" User Data Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5738 converted >> 16);
5739
5740 converted = le64_to_cpu(perf->system_erase_fail);
5741 printf(" System Area Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5742 converted & 0xFFFF);
5743 printf(" System Area Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5744 converted >> 16);
5745
5746 printf(" Thermal Throttling Status %20"PRIu8"hhu""\n",
5747 perf->thermal_throttle_status);
5748 printf(" Thermal Throttling Count %20"PRIu8"hhu""\n",
5749 perf->thermal_throttle_count);
5750 printf(" PCIe Correctable Error Count %20"PRIu64"l" "u""\n",
5751 le64_to_cpu(perf->pcie_corr_error));
5752 printf(" Incomplete Shutdown Count %20"PRIu32"u""\n",
5753 (uint32_t)le32_to_cpu(perf->incomplete_shutdown_count));
5754 printf(" Percent Free Blocks %20"PRIu32"u""%%\n",
5755 perf->percent_free_blocks);
5756}
5757
5758static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf)
5759{
5760 struct json_object *root = json_create_object()json_object_new_object();
5761 uint64_t converted = 0;
5762
5763 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)))
;
5764 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)))
;
5765 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)))
;
5766 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)))
;
5767
5768 converted = le64_to_cpu(perf->nand_bad_block);
5769 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))
5770 converted & 0xFFFF)json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5771 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))
5772 converted >> 16)json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
;
5773
5774 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)))
;
5775 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)))
;
5776 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))
)
5777 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))
)
;
5778 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)
))
5779 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)
))
;
5780 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))
5781 perf->data_percent_used)json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
;
5782 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)))
5783 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)))
;
5784 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)))
5785 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)))
;
5786 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)))
;
5787
5788 converted = le64_to_cpu(perf->program_fail);
5789 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))
5790 converted & 0xFFFF)json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5791 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))
5792 converted >> 16)json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
;
5793
5794 converted = le64_to_cpu(perf->user_erase_fail);
5795 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))
5796 converted & 0xFFFF)json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5797 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))
5798 converted >> 16)json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5799
5800 converted = le64_to_cpu(perf->system_erase_fail);
5801 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))
5802 converted & 0xFFFF)json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5803 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))
5804 converted >> 16)json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5805
5806 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))
5807 perf->thermal_throttle_status)json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
;
5808 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))
5809 perf->thermal_throttle_count)json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
;
5810 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)))
;
5811 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)))
;
5812 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))
;
5813 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5814 printf("\n");
5815 json_free_object(root)json_object_put(root);
5816}
5817
5818static void wdc_print_bd_ca_log_normal(struct libnvme_transport_handle *hdl, void *data)
5819{
5820 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5821 struct wdc_bd_ca_log_format *end = bd_data +
5822 WDC_BD_CA_LOG_BUF_LEN0xA0 / sizeof(*bd_data);
5823 __u64 rawSwapped;
5824 __u8 *raw;
5825 bool_Bool valid_id = true1;
5826
5827 while (valid_id && bd_data < end) {
5828 raw = bd_data->raw_value;
5829 rawSwapped = shr_get_unaligned_le64(raw) >> 8;
5830
5831 switch (bd_data->field_id) {
5832 case 0x0:
5833 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
5834 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
5835 printf("key normalized raw\n");
5836 printf("program_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5837 bd_data->normalized_value, (uint64_t)rawSwapped);
5838 break;
5839 case 0x1:
5840 printf("erase_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5841 bd_data->normalized_value, (uint64_t)rawSwapped);
5842 break;
5843 case 0x2:
5844 printf("wear_leveling : %3"PRIu8"hhu",
5845 bd_data->normalized_value);
5846 printf("%% min: %"PRIu16"hu"", max: %"PRIu16"hu"", avg: %"PRIu16"hu""\n",
5847 shr_get_unaligned_le16(&raw[1]),
5848 shr_get_unaligned_le16(&raw[3]),
5849 shr_get_unaligned_le16(&raw[5]));
5850 break;
5851 case 0x3:
5852 printf("end_to_end_error_detection_count: %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5853 bd_data->normalized_value, (uint64_t)rawSwapped);
5854 break;
5855 case 0x4:
5856 printf("crc_error_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5857 bd_data->normalized_value, (uint64_t)rawSwapped);
5858 break;
5859 case 0x5:
5860 printf("timed_workload_media_wear : %3"PRIu8"hhu""%% %-.3f%%\n",
5861 bd_data->normalized_value,
5862 safe_div_fp((rawSwapped), 1024.0));
5863 break;
5864 case 0x6:
5865 printf("timed_workload_host_reads : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5866 bd_data->normalized_value, (uint64_t)rawSwapped);
5867 break;
5868 case 0x7:
5869 printf("timed_workload_timer : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5870 bd_data->normalized_value, (uint64_t)rawSwapped);
5871 break;
5872 case 0x8:
5873 printf("thermal_throttle_status : %3"PRIu8"hhu""%% %"PRIu16"hu",
5874 bd_data->normalized_value, raw[1]);
5875 printf("%%, cnt: %"PRIu32"u""\n",
5876 shr_get_unaligned_le32(&raw[2]));
5877 break;
5878 case 0x9:
5879 printf("retry_buffer_overflow_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5880 bd_data->normalized_value, (uint64_t)rawSwapped);
5881 break;
5882 case 0xA:
5883 printf("pll_lock_loss_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5884 bd_data->normalized_value, (uint64_t)rawSwapped);
5885 break;
5886 case 0xB:
5887 printf("nand_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5888 bd_data->normalized_value, (uint64_t)rawSwapped);
5889 break;
5890 case 0xC:
5891 printf("host_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5892 bd_data->normalized_value, (uint64_t)rawSwapped);
5893 /* last entry, break from while loop */
5894 valid_id = false0;
5895 break;
5896 default:
5897 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5898 break;
5899 }
5900
5901 bd_data++;
5902 }
5903
5904 return;
5905}
5906
5907static void wdc_print_bd_ca_log_json(void *data)
5908{
5909 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5910 struct wdc_bd_ca_log_format *end = bd_data +
5911 WDC_BD_CA_LOG_BUF_LEN0xA0 / sizeof(*bd_data);
5912 __u64 rawSwapped;
5913 __u8 *raw;
5914 bool_Bool valid_id = true1;
5915 struct json_object *root = json_create_object()json_object_new_object();
5916
5917 while (valid_id && bd_data < end) {
5918 raw = bd_data->raw_value;
5919 rawSwapped = shr_get_unaligned_le64(raw) >> 8;
5920
5921 switch (bd_data->field_id) {
5922 case 0x0:
5923 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))
5924 bd_data->normalized_value)json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
;
5925 json_object_add_value_uint64(root, "program_fail_count raw",json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
5926 rawSwapped)json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5927 break;
5928 case 0x1:
5929 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))
5930 bd_data->normalized_value)json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5931 json_object_add_value_uint64(root, "erase_fail_count raw",json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
5932 rawSwapped)json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5933 break;
5934 case 0x2:
5935 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))
5936 bd_data->normalized_value)json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
;
5937 json_object_add_value_int(root, "wear_leveling min",json_object_object_add(root, "wear_leveling min", json_object_new_int
(shr_get_unaligned_le16(&raw[1])))
5938 shr_get_unaligned_le16(&raw[1]))json_object_object_add(root, "wear_leveling min", json_object_new_int
(shr_get_unaligned_le16(&raw[1])))
;
5939 json_object_add_value_int(root, "wear_leveling max",json_object_object_add(root, "wear_leveling max", json_object_new_int
(shr_get_unaligned_le16(&raw[3])))
5940 shr_get_unaligned_le16(&raw[3]))json_object_object_add(root, "wear_leveling max", json_object_new_int
(shr_get_unaligned_le16(&raw[3])))
;
5941 json_object_add_value_int(root, "wear_leveling avg",json_object_object_add(root, "wear_leveling avg", json_object_new_int
(shr_get_unaligned_le16(&raw[5])))
5942 shr_get_unaligned_le16(&raw[5]))json_object_object_add(root, "wear_leveling avg", json_object_new_int
(shr_get_unaligned_le16(&raw[5])))
;
5943 break;
5944 case 0x3:
5945 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))
5946 "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))
5947 bd_data->normalized_value)json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5948 json_object_add_value_uint64(root,json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5949 "end_to_end_error_detection_count raw",json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5950 rawSwapped)json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
;
5951 break;
5952 case 0x4:
5953 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))
5954 bd_data->normalized_value)json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5955 json_object_add_value_uint64(root, "crc_error_count raw",json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
5956 rawSwapped)json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
;
5957 break;
5958 case 0x5:
5959 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))
5960 bd_data->normalized_value)json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
;
5961 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)))
5962 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)))
;
5963 break;
5964 case 0x6:
5965 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))
5966 bd_data->normalized_value)json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
;
5967 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))
5968 rawSwapped)json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
;
5969 break;
5970 case 0x7:
5971 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))
5972 bd_data->normalized_value)json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
;
5973 json_object_add_value_uint64(root, "timed_workload_timer",json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
5974 rawSwapped)json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
;
5975 break;
5976 case 0x8:
5977 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))
5978 bd_data->normalized_value)json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
;
5979 json_object_add_value_int(root, "thermal_throttle_status",json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(raw[1]))
5980 raw[1])json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(raw[1]))
;
5981 json_object_add_value_int(root, "thermal_throttle_cnt",json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(shr_get_unaligned_le32(&raw[2])))
5982 shr_get_unaligned_le32(&raw[2]))json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(shr_get_unaligned_le32(&raw[2])))
;
5983 break;
5984 case 0x9:
5985 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))
5986 bd_data->normalized_value)json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5987 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))
5988 rawSwapped)json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
;
5989 break;
5990 case 0xA:
5991 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))
5992 bd_data->normalized_value)json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5993 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))
5994 rawSwapped)json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
;
5995 break;
5996 case 0xB:
5997 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))
5998 bd_data->normalized_value)json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5999 json_object_add_value_uint64(root, "nand_bytes_written raw",json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
6000 rawSwapped)json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
6001 break;
6002 case 0xC:
6003 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))
6004 bd_data->normalized_value)json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
6005 json_object_add_value_uint64(root, "host_bytes_written raw",json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
6006 rawSwapped)json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
6007
6008 /* last entry, break from while loop */
6009 valid_id = false0;
6010 break;
6011 default:
6012 printf(" Invalid Field ID = %d\n", bd_data->field_id);
6013 break;
6014 }
6015
6016 bd_data++;
6017 }
6018
6019 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6020 printf("\n");
6021 json_free_object(root)json_object_put(root);
6022
6023 return;
6024}
6025
6026static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf)
6027{
6028 printf(" D0 Smart Log Page Statistics :-\n");
6029 printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"u""\n",
6030 (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count));
6031 printf(" Lifetime Power on Hours %20"PRIu32"u""\n",
6032 (uint32_t)le32_to_cpu(perf->lifetime_power_on_hours));
6033 printf(" Lifetime UECC Count %20"PRIu32"u""\n",
6034 (uint32_t)le32_to_cpu(perf->lifetime_uecc_count));
6035 printf(" Lifetime Write Amplification Factor %20"PRIu32"u""\n",
6036 (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor));
6037 printf(" Trailing Hour Write Amplification Factor %20"PRIu32"u""\n",
6038 (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor));
6039 printf(" Reserve Erase Block Count %20"PRIu32"u""\n",
6040 (uint32_t)le32_to_cpu(perf->reserve_erase_block_count));
6041 printf(" Lifetime Program Fail Count %20"PRIu32"u""\n",
6042 (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count));
6043 printf(" Lifetime Block Erase Fail Count %20"PRIu32"u""\n",
6044 (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count));
6045 printf(" Lifetime Die Failure Count %20"PRIu32"u""\n",
6046 (uint32_t)le32_to_cpu(perf->lifetime_die_failure_count));
6047 printf(" Lifetime Link Rate Downgrade Count %20"PRIu32"u""\n",
6048 (uint32_t)le32_to_cpu(perf->lifetime_link_rate_downgrade_count));
6049 printf(" Lifetime Clean Shutdown Count on Power Loss %20"PRIu32"u""\n",
6050 (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count));
6051 printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"u""\n",
6052 (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count));
6053 printf(" Current Temperature %20"PRIu32"u""\n",
6054 (uint32_t)le32_to_cpu(perf->current_temp));
6055 printf(" Max Recorded Temperature %20"PRIu32"u""\n",
6056 (uint32_t)le32_to_cpu(perf->max_recorded_temp));
6057 printf(" Lifetime Retired Block Count %20"PRIu32"u""\n",
6058 (uint32_t)le32_to_cpu(perf->lifetime_retired_block_count));
6059 printf(" Lifetime Read Disturb Reallocation Events %20"PRIu32"u""\n",
6060 (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events));
6061 printf(" Lifetime NAND Writes %20"PRIu64"l" "u""\n",
6062 le64_to_cpu(perf->lifetime_nand_writes));
6063 printf(" Capacitor Health %20"PRIu32"u""%%\n",
6064 (uint32_t)le32_to_cpu(perf->capacitor_health));
6065 printf(" Lifetime User Writes %20"PRIu64"l" "u""\n",
6066 le64_to_cpu(perf->lifetime_user_writes));
6067 printf(" Lifetime User Reads %20"PRIu64"l" "u""\n",
6068 le64_to_cpu(perf->lifetime_user_reads));
6069 printf(" Lifetime Thermal Throttle Activations %20"PRIu32"u""\n",
6070 (uint32_t)le32_to_cpu(perf->lifetime_thermal_throttle_act));
6071 printf(" Percentage of P/E Cycles Remaining %20"PRIu32"u""%%\n",
6072 (uint32_t)le32_to_cpu(perf->percentage_pe_cycles_remaining));
6073}
6074
6075static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf)
6076{
6077 struct json_object *root = json_create_object()json_object_new_object();
6078
6079 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
)))
6080 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
)))
;
6081 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)))
6082 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)))
;
6083 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)))
6084 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)))
;
6085 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
)))
6086 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
)))
;
6087 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
)))
6088 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
)))
;
6089 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)))
6090 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)))
;
6091 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)))
6092 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)))
;
6093 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
)))
6094 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
)))
;
6095 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)))
6096 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)))
;
6097 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
)))
6098 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
)))
;
6099 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
)))
6100 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
)))
;
6101 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
)))
6102 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
)))
;
6103 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)))
6104 le32_to_cpu(perf->current_temp))json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
;
6105 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)))
6106 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)))
;
6107 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)))
6108 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)))
;
6109 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
)))
6110 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
)))
;
6111 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)))
6112 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)))
;
6113 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)))
6114 le32_to_cpu(perf->capacitor_health))json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
;
6115 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)))
6116 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)))
;
6117 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)))
6118 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)))
;
6119 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
)))
6120 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
)))
;
6121 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
)))
6122 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
)))
;
6123
6124 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6125 printf("\n");
6126 json_free_object(root)json_object_put(root);
6127}
6128
6129static void wdc_get_commit_action_bin(__u8 commit_action_type,
6130 char *action_bin, size_t size)
6131{
6132
6133 switch (commit_action_type) {
6134 case 0:
6135 shr_strscpy(action_bin, "000b", size);
6136 break;
6137 case 1:
6138 shr_strscpy(action_bin, "001b", size);
6139 break;
6140 case 2:
6141 shr_strscpy(action_bin, "010b", size);
6142 break;
6143 case 3:
6144 shr_strscpy(action_bin, "011b", size);
6145 break;
6146 case 4:
6147 shr_strscpy(action_bin, "100b", size);
6148 break;
6149 case 5:
6150 shr_strscpy(action_bin, "101b", size);
6151 break;
6152 case 6:
6153 shr_strscpy(action_bin, "110b", size);
6154 break;
6155 case 7:
6156 shr_strscpy(action_bin, "111b", size);
6157 break;
6158 default:
6159 shr_strscpy(action_bin, "INVALID", size);
6160 }
6161
6162}
6163
6164static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
6165 __u32 cust_id, __u32 vendor_id,
6166 __u32 device_id)
6167{
6168 int i, j;
6169 char previous_fw[9];
6170 char new_fw[9];
6171 char commit_action_bin[8];
6172 char time_str[100];
6173 __u16 oldestEntryIdx = 0, entryIdx = 0;
6174 uint64_t timestamp;
6175 __u64 timestamp_sec;
6176 const char *null_fw = "--------";
6177
6178 memset((void *)time_str, '\0', 100);
6179
6180 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6181 printf(" Firmware Activate History Log\n");
6182 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005 ||
6183 vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6184 printf(" Power on Hour Power Cycle Previous New\n");
6185 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6186 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
6187 } else {
6188 printf(" Power Cycle Previous New\n");
6189 printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n");
6190 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
6191 }
6192
6193 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6194
6195 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6196 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6197 /* find lowest/oldest entry */
6198 for (i = 0; i < num_entries; i++) {
6199 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6200 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6201 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6202 oldestEntryIdx = j;
6203 break;
6204 }
6205 }
6206 }
6207 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6208 entryIdx = 0;
6209 else
6210 entryIdx = oldestEntryIdx;
6211
6212 for (i = 0; i < num_entries; i++) {
6213 memset((void *)previous_fw, 0, 9);
6214 memset((void *)new_fw, 0, 9);
6215 memset((void *)commit_action_bin, 0, 8);
6216
6217 memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8);
6218 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6219 memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8);
6220 else
6221 memcpy(new_fw, null_fw, 8);
6222
6223 printf("%5"PRIu16"hu""", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
6224
6225 timestamp = (0x0000FFFFFFFFFFFF &
6226 le64_to_cpu(
6227 fw_act_history_entry->entry[entryIdx].timestamp));
6228 timestamp_sec = timestamp / 1000;
6229 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6230 printf(" ");
6231 memset((void *)time_str, 0, 9);
6232 snprintf((char *)time_str, sizeof(time_str),
6233 "%"PRIu32"u"":%u:%u",
6234 (__u32)(timestamp_sec/3600),
6235 (__u8)(timestamp_sec%3600/60),
6236 (__u8)(timestamp_sec%60));
6237
6238 printf("%s", time_str);
6239 printf(" ");
6240 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6241 printf(" ");
6242
6243 memset((void *)time_str, 0, 9);
6244 snprintf((char *)time_str, sizeof(time_str),
6245 "%"PRIu32"u"":%u:%u",
6246 (__u32)((timestamp_sec/3600)%24),
6247 (__u8)((timestamp_sec/60)%60),
6248 (__u8)(timestamp_sec%60));
6249 printf("%s", time_str);
6250 printf(" ");
6251 } else {
6252 printf(" ");
6253 printf("%16"PRIu64"l" "u""", timestamp);
6254 printf(" ");
6255 }
6256
6257 printf("%16"PRIu64"l" "u""", (uint64_t)le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count));
6258 printf(" ");
6259 printf("%s", (char *)previous_fw);
6260 printf(" ");
6261 printf("%s", (char *)new_fw);
6262 printf(" ");
6263 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number);
6264 printf(" ");
6265 wdc_get_commit_action_bin(
6266 fw_act_history_entry->entry[entryIdx].commit_action_type,
6267 commit_action_bin, sizeof(commit_action_bin));
6268 printf(" %s", (char *)commit_action_bin);
6269 printf(" ");
6270 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))
6271 printf("pass");
6272 else
6273 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result));
6274 printf("\n");
6275
6276 entryIdx++;
6277 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6278 entryIdx = 0;
6279 }
6280 } else {
6281 printf(" Firmware Activate History Log\n");
6282 printf(" Power on Hour Power Cycle Previous New\n");
6283 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6284 printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n");
6285
6286 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));
6287
6288 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6289 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6290 /* find lowest/oldest entry */
6291 for (i = 0; i < num_entries; i++) {
6292 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6293 oldestEntryIdx = i+1;
6294 break;
6295 }
6296 }
6297 }
6298
6299 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6300 entryIdx = 0;
6301 else
6302 entryIdx = oldestEntryIdx;
6303
6304 for (i = 0; i < num_entries; i++) {
6305 memset((void *)previous_fw, 0, 9);
6306 memset((void *)new_fw, 0, 9);
6307 memset((void *)commit_action_bin, 0, 8);
6308
6309 memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6310 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6311 memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6312 else
6313 memcpy(new_fw, null_fw, 8);
6314
6315 printf("%5"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].entry_num));
6316 printf(" ");
6317 printf("%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6318 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6319 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6320 printf(" ");
6321 printf("%16"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count));
6322 printf(" ");
6323 printf("%s", (char *)previous_fw);
6324 printf(" ");
6325 printf("%s", (char *)new_fw);
6326 printf(" ");
6327 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry[entryIdx].slot_number);
6328 printf(" ");
6329 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6330 commit_action_bin,
6331 sizeof(commit_action_bin));
6332 printf(" %s", (char *)commit_action_bin);
6333 printf(" ");
6334 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result))
6335 printf("pass");
6336 else
6337 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result));
6338
6339 printf("\n");
6340
6341 entryIdx++;
6342 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6343 entryIdx = 0;
6344 }
6345 }
6346}
6347
6348static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
6349 __u32 cust_id, __u32 vendor_id,
6350 __u32 device_id)
6351{
6352 struct json_object *root = json_create_object()json_object_new_object();
6353 int i, j;
6354 char previous_fw[9];
6355 char new_fw[9];
6356 char commit_action_bin[8];
6357 char fail_str[32];
6358 char time_str[100];
6359 char ext_time_str[20];
6360 uint64_t timestamp;
6361 __u64 timestamp_sec;
6362
6363 memset((void *)previous_fw, 0, 9);
6364 memset((void *)new_fw, 0, 9);
6365 memset((void *)commit_action_bin, 0, 8);
6366 memset((void *)time_str, '\0', 100);
6367 memset((void *)ext_time_str, 0, 20);
6368 memset((void *)fail_str, 0, 11);
6369 char *null_fw = "--------";
6370 __u16 oldestEntryIdx = 0, entryIdx = 0;
6371
6372 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6373 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6374
6375 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6376 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6377 /* find lowest/oldest entry */
6378 for (i = 0; i < num_entries; i++) {
6379 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6380 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6381 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6382 oldestEntryIdx = j;
6383 break;
6384 }
6385 }
6386 }
6387 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6388 entryIdx = 0;
6389 else
6390 entryIdx = oldestEntryIdx;
6391
6392 for (i = 0; i < num_entries; i++) {
6393 struct wdc_fw_act_history_log_entry_c2 *e =
6394 &fw_act_history_entry->entry[entryIdx];
6395
6396 memcpy(previous_fw,
6397 (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version),
6398 8);
6399 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6400 memcpy(new_fw,
6401 (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version),
6402 8);
6403 else
6404 memcpy(new_fw, null_fw, 8);
6405
6406 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
)))
6407 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
)))
;
6408
6409 timestamp = (0x0000FFFFFFFFFFFF &
6410 le64_to_cpu(
6411 fw_act_history_entry->entry[entryIdx].timestamp));
6412 timestamp_sec = timestamp / 1000;
6413 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6414 snprintf((char *)time_str, sizeof(time_str),
6415 "%"PRIu32"u"":%u:%u",
6416 (__u32)(timestamp_sec/3600),
6417 (__u8)(timestamp_sec%3600/60),
6418 (__u8)(timestamp_sec%60));
6419
6420 json_object_add_value_string(root, "Power on Hour", time_str);
6421
6422 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6423 snprintf((char *)time_str, sizeof(time_str),
6424 "%"PRIu32"u"":%u:%u",
6425 (__u32)((timestamp_sec/3600)%24),
6426 (__u8)((timestamp_sec/60)%60),
6427 (__u8)(timestamp_sec%60));
6428 json_object_add_value_string(root, "Power on Hour", time_str);
6429 } else {
6430 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
6431 }
6432
6433 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
)))
6434 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
)))
;
6435 json_object_add_value_string(root, "Previous Firmware",
6436 previous_fw);
6437 json_object_add_value_string(root, "New Firmware",
6438 new_fw);
6439 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))
6440 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))
;
6441
6442 wdc_get_commit_action_bin(
6443 fw_act_history_entry->entry[entryIdx].commit_action_type,
6444 commit_action_bin, sizeof(commit_action_bin));
6445 json_object_add_value_string(root, "Action", commit_action_bin);
6446
6447 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) {
6448 json_object_add_value_string(root, "Result", "pass");
6449 } else {
6450 snprintf((char *)fail_str, sizeof(fail_str),
6451 "fail #%d",
6452 (int)(le16_to_cpu(e->result)));
6453 json_object_add_value_string(root, "Result", fail_str);
6454 }
6455
6456 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6457 printf("\n");
6458
6459 entryIdx++;
6460 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6461 entryIdx = 0;
6462 }
6463 } else {
6464 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));
6465
6466 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6467 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6468 /* find lowest/oldest entry */
6469 for (i = 0; i < num_entries; i++) {
6470 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6471 oldestEntryIdx = i+1;
6472 break;
6473 }
6474 }
6475 }
6476 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6477 entryIdx = 0;
6478 else
6479 entryIdx = oldestEntryIdx;
6480
6481 for (i = 0; i < num_entries; i++) {
6482 struct wdc_fw_act_history_log_entry *e =
6483 &fw_act_history_entry[entryIdx];
6484 __u64 secs = le64_to_cpu(e->power_on_seconds);
6485
6486 memcpy(previous_fw,
6487 (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6488 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6489 memcpy(new_fw,
6490 (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6491 else
6492 memcpy(new_fw, null_fw, 8);
6493
6494 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)))
6495 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)))
;
6496
6497 snprintf((char *)time_str, sizeof(time_str),
6498 "%04d:%02d:%02d",
6499 (int)(secs / 3600), (int)((secs % 3600) / 60),
6500 (int)(secs % 60));
6501 json_object_add_value_string(root, "Power on Hour", time_str);
6502
6503 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
)))
6504 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
)))
;
6505 json_object_add_value_string(root, "Previous Firmware",
6506 previous_fw);
6507 json_object_add_value_string(root, "New Firmware",
6508 new_fw);
6509 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
6510 fw_act_history_entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
;
6511
6512 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6513 commit_action_bin,
6514 sizeof(commit_action_bin));
6515 json_object_add_value_string(root, "Action", commit_action_bin);
6516
6517 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) {
6518 json_object_add_value_string(root, "Result", "pass");
6519 } else {
6520 snprintf((char *)fail_str, sizeof(fail_str),
6521 "fail #%d",
6522 (int)(le16_to_cpu(e->result)));
6523 json_object_add_value_string(root, "Result", fail_str);
6524 }
6525
6526 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6527 printf("\n");
6528
6529 entryIdx++;
6530 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6531 entryIdx = 0;
6532 }
6533 }
6534
6535 json_free_object(root)json_object_put(root);
6536}
6537
6538static int nvme_get_print_ocp_cloud_smart_log(struct libnvme_transport_handle *hdl,
6539 int uuid_index,
6540 __u32 namespace_id,
6541 int fmt)
6542{
6543 struct ocp_cloud_smart_log *log_ptr = NULL((void*)0);
6544 struct libnvme_passthru_cmd cmd;
6545 int ret, i;
6546
6547 log_ptr = malloc(sizeof(*log_ptr));
6548 if (!log_ptr) {
6549 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6550 return -1;
6551 }
6552
6553 if (namespace_id == NVME_NSID_ALL) {
6554 ret = libnvme_get_nsid(hdl, &namespace_id);
6555 if (ret < 0)
6556 namespace_id = NVME_NSID_ALL;
6557 }
6558
6559 /* Get the 0xC0 log data */
6560 nvme_init_get_log(&cmd, namespace_id,
6561 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6562 log_ptr, sizeof(*log_ptr));
6563 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6564 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6565 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6566 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6567 if (fmt == JSON)
6568 nvme_show_status(ret);
6569
6570 if (!ret) {
6571 /* Verify GUID matches */
6572 for (i = 0; i < 16; i++) {
6573 if (scao_guid[i] != log_ptr->log_page_guid[i]) {
6574 nvme_show_error("ERROR: WDC: Unknown GUID in C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C0 Log Page data"
)
;
6575 int j;
6576
6577 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6578 for (j = 0; j < 16; j++)
6579 nvme_show_error("%x", scao_guid[j])nvme_show_message(1, "%x", scao_guid[j]);
6580 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6581 for (j = 0; j < 16; j++)
6582 nvme_show_error("%x", log_ptr->log_page_guid[j])nvme_show_message(1, "%x", log_ptr->log_page_guid[j]);
6583 nvme_show_error("")nvme_show_message(1, "");
6584
6585 ret = -1;
6586 break;
6587 }
6588 }
6589
6590 if (!ret)
6591 /* parse the data */
6592 wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl);
6593 } else {
6594 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page data"
)
;
6595 ret = -1;
6596 }
6597
6598 free(log_ptr);
6599 return ret;
6600}
6601
6602static int nvme_get_print_c0_eol_log(struct libnvme_transport_handle *hdl,
6603 int uuid_index,
6604 __u32 namespace_id,
6605 int fmt)
6606{
6607 __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN0x200;
6608 struct libnvme_passthru_cmd cmd;
6609 void *log_ptr = NULL((void*)0);
6610 int ret;
6611
6612 log_ptr = (void *)malloc(sizeof(__u8) * length);
6613 if (!log_ptr) {
6614 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6615 return -1;
6616 }
6617
6618 if (namespace_id == NVME_NSID_ALL) {
6619 ret = libnvme_get_nsid(hdl, &namespace_id);
6620 if (ret < 0)
6621 namespace_id = NVME_NSID_ALL;
6622 }
6623
6624 /* Get the 0xC0 log data */
6625 nvme_init_get_log(&cmd, namespace_id,
6626 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, NVME_CSI_NVM,
6627 log_ptr, length);
6628 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6629 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6630 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6631 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6632 if (fmt == JSON)
6633 nvme_show_status(ret);
6634
6635 if (!ret) {
6636 /* parse the data */
6637 wdc_print_c0_eol_log(log_ptr, fmt);
6638 } else {
6639 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page data ")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page data "
)
;
6640 nvme_show_error("with uuid index %d", uuid_index)nvme_show_message(1, "with uuid index %d", uuid_index);
6641 ret = -1;
6642 }
6643
6644 free(log_ptr);
6645 return ret;
6646}
6647
6648static int nvme_get_ext_smart_cloud_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6649{
6650 struct libnvme_passthru_cmd cmd;
6651 __cleanup_free__attribute__((cleanup(shr_freep))) __u8 *log_ptr = NULL((void*)0);
6652 int ret, i;
6653
6654 /* the log only on success: the callers free it only then */
6655 *data = NULL((void*)0);
6656 log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6657 if (!log_ptr) {
6658 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6659 return -1;
6660 }
6661
6662 /* Get the 0xC0 log data */
6663 nvme_init_get_log(&cmd, namespace_id,
6664 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6665 log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6666 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6667 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6668 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6669 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6670 if (!ret) {
6671 /* Verify GUID matches */
6672 for (i = 0; i < WDC_C0_GUID_LENGTH16; i++) {
6673 if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
6674 nvme_show_error("ERROR: WDC: Unknown GUID in C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C0 Log Page V1 data"
)
;
6675 int j;
6676
6677 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6678 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6679 nvme_show_error("%x", ext_smart_guid[j])nvme_show_message(1, "%x", ext_smart_guid[j]);
6680 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6681 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6682 nvme_show_error("%x", *&log_ptr[SCAO_V1_LPG + j])nvme_show_message(1, "%x", *&log_ptr[SCAO_V1_LPG + j]);
6683 nvme_show_error("")nvme_show_message(1, "");
6684
6685 ret = -1;
6686 break;
6687 }
6688 }
6689 }
6690 if (ret)
6691 return ret;
6692
6693 *data = log_ptr;
6694 log_ptr = NULL((void*)0);
6695
6696 return 0;
6697}
6698
6699
6700static int nvme_get_hw_rev_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6701{
6702 __cleanup_free__attribute__((cleanup(shr_freep))) struct wdc_nvme_hw_rev_log *log_ptr = NULL((void*)0);
6703 struct libnvme_passthru_cmd cmd;
6704 int ret, i;
6705
6706 /* the log only on success: the callers free it only then */
6707 *data = NULL((void*)0);
6708 log_ptr = malloc(sizeof(*log_ptr));
6709 if (!log_ptr) {
6710 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6711 return -1;
6712 }
6713
6714 /* Get the 0xC0 log data */
6715 nvme_init_get_log(&cmd, namespace_id,
6716 WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6, NVME_CSI_NVM,
6717 log_ptr, sizeof(*log_ptr));
6718 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6719 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6720 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6721 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6722 if (!ret) {
6723 /* Verify GUID matches */
6724 for (i = 0; i < WDC_NVME_C6_GUID_LENGTH16; i++) {
6725 if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
6726 nvme_show_error("ERROR: WDC: Unknown GUID in HW Revision Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in HW Revision Log Page data"
)
;
6727 int j;
6728
6729 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6730 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6731 nvme_show_error("%x", hw_rev_log_guid[j])nvme_show_message(1, "%x", hw_rev_log_guid[j]);
6732 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6733 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6734 nvme_show_error("%x", log_ptr->hw_rev_guid[j])nvme_show_message(1, "%x", log_ptr->hw_rev_guid[j]);
6735 nvme_show_error("")nvme_show_message(1, "");
6736
6737 ret = -1;
6738 break;
6739 }
6740 }
6741 }
6742 if (ret)
6743 return ret;
6744
6745 *data = (__u8 *)log_ptr;
6746 log_ptr = NULL((void*)0);
6747
6748 return 0;
6749}
6750
6751
6752static void wdc_print_hw_rev_log_normal(void *data)
6753{
6754 int i;
6755 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6756
6757 printf(" Hardware Revision Log:-\n");
6758
6759 printf(" Global Device HW Revision : %d\n",
6760 log_data->hw_rev_gdr);
6761 printf(" ASIC HW Revision : %d\n",
6762 log_data->hw_rev_ar);
6763 printf(" PCB Manufacturer Code : %d\n",
6764 log_data->hw_rev_pbc_mc);
6765 printf(" DRAM Manufacturer Code : %d\n",
6766 log_data->hw_rev_dram_mc);
6767 printf(" NAND Manufacturer Code : %d\n",
6768 log_data->hw_rev_nand_mc);
6769 printf(" PMIC 1 Manufacturer Code : %d\n",
6770 log_data->hw_rev_pmic1_mc);
6771 printf(" PMIC 2 Manufacturer Code : %d\n",
6772 log_data->hw_rev_pmic2_mc);
6773 printf(" Other Component 1 Manf Code : %d\n",
6774 log_data->hw_rev_c1_mc);
6775 printf(" Other Component 2 Manf Code : %d\n",
6776 log_data->hw_rev_c2_mc);
6777 printf(" Other Component 3 Manf Code : %d\n",
6778 log_data->hw_rev_c3_mc);
6779 printf(" Other Component 4 Manf Code : %d\n",
6780 log_data->hw_rev_c4_mc);
6781 printf(" Other Component 5 Manf Code : %d\n",
6782 log_data->hw_rev_c5_mc);
6783 printf(" Other Component 6 Manf Code : %d\n",
6784 log_data->hw_rev_c6_mc);
6785 printf(" Other Component 7 Manf Code : %d\n",
6786 log_data->hw_rev_c7_mc);
6787 printf(" Other Component 8 Manf Code : %d\n",
6788 log_data->hw_rev_c8_mc);
6789 printf(" Other Component 9 Manf Code : %d\n",
6790 log_data->hw_rev_c9_mc);
6791
6792 printf(" Device Manf Detailed Info : 0x");
6793 for (i = 0; i < 16; i++) {
6794 printf("%02x", log_data->hw_rev_dev_mdi[i]);
6795 if (i == 7)
6796 printf(" 0x");
6797 }
6798 printf("\n");
6799 printf(" ASIC Detailed Info : 0x");
6800 for (i = 0; i < 16; i++) {
6801 printf("%02x", log_data->hw_rev_asic_di[i]);
6802 if (i == 7)
6803 printf(" 0x");
6804 }
6805 printf("\n");
6806 printf(" PCB Detailed Info : 0x");
6807 for (i = 0; i < 16; i++) {
6808 printf("%02x", log_data->hw_rev_pcb_di[i]);
6809 if (i == 7)
6810 printf(" 0x");
6811 }
6812 printf("\n");
6813 printf(" DRAM Detailed Info : 0x");
6814 for (i = 0; i < 16; i++) {
6815 printf("%02x", log_data->hw_rev_dram_di[i]);
6816 if (i == 7)
6817 printf(" 0x");
6818 }
6819 printf("\n");
6820 printf(" NAND Detailed Info : 0x");
6821 for (i = 0; i < 16; i++) {
6822 printf("%02x", log_data->hw_rev_nand_di[i]);
6823 if (i == 7)
6824 printf(" 0x");
6825 }
6826 printf("\n");
6827 printf(" PMIC 1 Detailed Info : 0x");
6828 for (i = 0; i < 16; i++) {
6829 printf("%02x", log_data->hw_rev_pmic1_di[i]);
6830 if (i == 7)
6831 printf(" 0x");
6832 }
6833 printf("\n");
6834 printf(" PMIC 2 Detailed Info : 0x");
6835 for (i = 0; i < 16; i++) {
6836 printf("%02x", log_data->hw_rev_pmic2_di[i]);
6837 if (i == 7)
6838 printf(" 0x");
6839 }
6840 printf("\n");
6841 printf(" Component 1 Detailed Info : 0x");
6842 for (i = 0; i < 16; i++) {
6843 printf("%02x", log_data->hw_rev_c1_di[i]);
6844 if (i == 7)
6845 printf(" 0x");
6846 }
6847 printf("\n");
6848 printf(" Component 2 Detailed Info : 0x");
6849 for (i = 0; i < 16; i++) {
6850 printf("%02x", log_data->hw_rev_c2_di[i]);
6851 if (i == 7)
6852 printf(" 0x");
6853 }
6854 printf("\n");
6855 printf(" Component 3 Detailed Info : 0x");
6856 for (i = 0; i < 16; i++) {
6857 printf("%02x", log_data->hw_rev_c3_di[i]);
6858 if (i == 7)
6859 printf(" 0x");
6860 }
6861 printf("\n");
6862 printf(" Component 4 Detailed Info : 0x");
6863 for (i = 0; i < 16; i++) {
6864 printf("%02x", log_data->hw_rev_c4_di[i]);
6865 if (i == 7)
6866 printf(" 0x");
6867 }
6868 printf("\n");
6869 printf(" Component 5 Detailed Info : 0x");
6870 for (i = 0; i < 16; i++) {
6871 printf("%02x", log_data->hw_rev_c5_di[i]);
6872 if (i == 7)
6873 printf(" 0x");
6874 }
6875 printf("\n");
6876 printf(" Component 6 Detailed Info : 0x");
6877 for (i = 0; i < 16; i++) {
6878 printf("%02x", log_data->hw_rev_c6_di[i]);
6879 if (i == 7)
6880 printf(" 0x");
6881 }
6882 printf("\n");
6883 printf(" Component 7 Detailed Info : 0x");
6884 for (i = 0; i < 16; i++) {
6885 printf("%02x", log_data->hw_rev_c7_di[i]);
6886 if (i == 7)
6887 printf(" 0x");
6888 }
6889 printf("\n");
6890 printf(" Component 8 Detailed Info : 0x");
6891 for (i = 0; i < 16; i++) {
6892 printf("%02x", log_data->hw_rev_c8_di[i]);
6893 if (i == 7)
6894 printf(" 0x");
6895 }
6896 printf("\n");
6897 printf(" Component 9 Detailed Info : 0x");
6898 for (i = 0; i < 16; i++) {
6899 printf("%02x", log_data->hw_rev_c9_di[i]);
6900 if (i == 7)
6901 printf(" 0x");
6902 }
6903 printf("\n");
6904 printf(" Serial Number : 0x");
6905 for (i = 0; i < 32; i++) {
6906 if ((i > 1) & !(i % 8))
6907 printf(" 0x");
6908 printf("%02x", log_data->hw_rev_sn[i]);
6909 }
6910 printf("\n");
6911
6912 printf(" Log Page Version : %d\n", log_data->hw_rev_version);
6913 printf(" Log page GUID : 0x");
6914 printf("%"PRIx64"l" "x""%"PRIx64"l" "x""\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6915 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6916 printf("\n");
6917}
6918
6919static void wdc_print_hw_rev_log_json(void *data)
6920{
6921 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6922 struct json_object *root = json_create_object()json_object_new_object();
6923 char json_data[80];
6924
6925 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))
6926 log_data->hw_rev_gdr)json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
;
6927 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))
6928 log_data->hw_rev_ar)json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
;
6929 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))
6930 log_data->hw_rev_pbc_mc)json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
;
6931 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))
6932 log_data->hw_rev_dram_mc)json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
;
6933 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))
6934 log_data->hw_rev_nand_mc)json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
;
6935 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))
6936 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))
;
6937 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))
6938 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))
;
6939 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))
6940 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))
;
6941 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))
6942 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))
;
6943 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))
6944 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))
;
6945 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))
6946 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))
;
6947 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))
6948 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))
;
6949 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))
6950 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))
;
6951 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))
6952 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))
;
6953 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))
6954 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))
;
6955 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))
6956 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))
;
6957
6958 memset((void *)json_data, 0, 40);
6959 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6960 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]),
6961 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
6962 json_object_add_value_string(root, "Device Manf Detailed Info", json_data);
6963
6964 memset((void *)json_data, 0, 40);
6965 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6966 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]),
6967 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
6968 json_object_add_value_string(root, "ASIC Detailed Info", json_data);
6969
6970 memset((void *)json_data, 0, 40);
6971 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6972 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]),
6973 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
6974 json_object_add_value_string(root, "PCB Detailed Info", json_data);
6975
6976 memset((void *)json_data, 0, 40);
6977 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6978 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]),
6979 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
6980 json_object_add_value_string(root, "DRAM Detailed Info", json_data);
6981
6982 memset((void *)json_data, 0, 40);
6983 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6984 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]),
6985 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
6986 json_object_add_value_string(root, "NAND Detailed Info", json_data);
6987
6988 memset((void *)json_data, 0, 40);
6989 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6990 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]),
6991 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
6992 json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
6993
6994 memset((void *)json_data, 0, 40);
6995 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6996 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
6997 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
6998 json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
6999
7000 memset((void *)json_data, 0, 40);
7001 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7002 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
7003 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
7004 json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
7005
7006 memset((void *)json_data, 0, 40);
7007 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7008 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
7009 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
7010 json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
7011
7012 memset((void *)json_data, 0, 40);
7013 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7014 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
7015 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
7016 json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
7017
7018 memset((void *)json_data, 0, 40);
7019 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7020 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
7021 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
7022 json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
7023
7024 memset((void *)json_data, 0, 40);
7025 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7026 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
7027 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
7028 json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
7029
7030 memset((void *)json_data, 0, 40);
7031 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7032 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
7033 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
7034 json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
7035
7036 memset((void *)json_data, 0, 40);
7037 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7038 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
7039 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
7040 json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
7041
7042 memset((void *)json_data, 0, 40);
7043 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7044 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
7045 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
7046 json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
7047
7048 memset((void *)json_data, 0, 40);
7049 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7050 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
7051 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
7052 json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
7053
7054 memset((void *)json_data, 0, 80);
7055 snprintf((char *)json_data, sizeof(json_data),
7056 "0x%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""",
7057 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]),
7058 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
7059 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]),
7060 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
7061 json_object_add_value_string(root, "Serial Number", json_data);
7062
7063 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)))
7064 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)))
;
7065
7066 memset((void *)json_data, 0, 40);
7067 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7068 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
7069 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
7070 json_object_add_value_string(root, "Log Page GUID", json_data);
7071
7072 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7073 printf("\n");
7074 json_free_object(root)json_object_put(root);
7075}
7076
7077static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
7078{
7079 int i;
7080 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
7081
7082 if (mask == WDC_SCA_V1_NAND_STATS0x1)
7083 printf(" NAND Statistics :-\n");
7084 else
7085 printf(" SMART Cloud Attributes :-\n");
7086
7087 printf(" Physical Media Units Written TLC (Bytes): %s\n",
7088 uint128_t_to_string(le128_to_cpu(
7089 ext_smart_log_ptr->ext_smart_pmuwt)));
7090 printf(" Physical Media Units Written SLC (Bytes): %s\n",
7091 uint128_t_to_string(le128_to_cpu(
7092 ext_smart_log_ptr->ext_smart_pmuws)));
7093 printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
7094 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
7095 printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7096 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
7097 printf(" XOR Recovery Count (Int) : %"PRIu64"l" "u""\n",
7098 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
7099 printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"l" "u""\n",
7100 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
7101 if (mask == WDC_SCA_V1_ALL0xF) {
7102 printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"l" "u""\n",
7103 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
7104 printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"l" "u""\n",
7105 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
7106 printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"l" "u""\n",
7107 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
7108 printf(" System Data %% life-used : %d %%\n",
7109 ext_smart_log_ptr->ext_smart_sdpu);
7110 }
7111 printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"l" "u""\n",
7112 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
7113 printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"l" "u""\n",
7114 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
7115 printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"l" "u""\n",
7116 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
7117 printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"l" "u""\n",
7118 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
7119 printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"l" "u""\n",
7120 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
7121 printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"l" "u""\n",
7122 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
7123 printf(" Program Fail Count (Normalized) (Int) : %d\n",
7124 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
7125 printf(" Program Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7126 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
7127 printf(" Erase Fail Count (Normalized) (Int) : %d\n",
7128 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
7129 printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7130 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
7131 if (mask == WDC_SCA_V1_ALL0xF) {
7132 printf(" PCIe Correctable Error Count (Int) : %"PRIu64"l" "u""\n",
7133 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
7134 printf(" %% Free Blocks (User) (Int) : %d %%\n",
7135 ext_smart_log_ptr->ext_smart_pfbu);
7136 printf(" Security Version Number (Int) : %"PRIu64"l" "u""\n",
7137 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
7138 printf(" %% Free Blocks (System) (Int) : %d %%\n",
7139 ext_smart_log_ptr->ext_smart_pfbs);
7140 printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n",
7141 uint128_t_to_string(le128_to_cpu(
7142 ext_smart_log_ptr->ext_smart_dcc)));
7143 printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"l" "u""\n",
7144 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
7145 printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
7146 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
7147 printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
7148 ext_smart_log_ptr->ext_smart_bbpg);
7149 }
7150 printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"l" "u""\n",
7151 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
7152 if (mask == WDC_SCA_V1_ALL0xF) {
7153 printf(" Total # of Read Refresh Count (Int) : %"PRIu64"l" "u""\n",
7154 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
7155 }
7156 printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
7157 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
7158 printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7159 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
7160 printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n",
7161 uint128_t_to_string(
7162 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)));
7163 if (mask == WDC_SCA_V1_ALL0xF) {
7164 printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
7165 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
7166 printf(" Total # Unaligned I/O (Int) : %"PRIu64"l" "u""\n",
7167 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
7168 }
7169 printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n",
7170 uint128_t_to_string(
7171 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)));
7172 if (mask == WDC_SCA_V1_ALL0xF) {
7173 printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7174 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
7175 printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7176 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
7177 printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7178 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
7179 printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"l" "u""\n",
7180 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
7181 printf(" Active Power State Change Count (Int) : %"PRIu64"l" "u""\n",
7182 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
7183 }
7184 printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
7185 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7186 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7187 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7188 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7189 printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
7190 0, 0, 0, 0);
7191 if (mask == WDC_SCA_V1_ALL0xF) {
7192 printf(" FTL Unit Size : %"PRIu32"u""\n",
7193 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
7194 printf(" TCG Ownership Status : %"PRIu32"u""\n",
7195 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
7196 printf(" Log Page Version (Int) : %d\n",
7197 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
7198 printf(" Log page GUID (Hex) : 0x");
7199 for (i = WDC_C0_GUID_LENGTH16; i > 0; i--)
7200 printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
7201 printf("\n");
7202 }
7203 printf("\n");
7204}
7205
7206static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
7207{
7208 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr =
7209 (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
7210 struct json_object *root = json_create_object()json_object_new_object();
7211
7212 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)))
7213 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)))
;
7214 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)))
7215 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)))
;
7216 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
)))
7217 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
)))
;
7218 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)))
7219 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)))
;
7220 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)))
7221 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)))
;
7222 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)))
7223 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)))
;
7224 if (mask == WDC_SCA_V1_ALL0xF) {
7225 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)))
7226 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)))
;
7227 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)))
7228 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)))
;
7229 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)))
7230 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)))
;
7231 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))
7232 (__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))
;
7233 }
7234 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
)))
7235 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
)))
;
7236 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
)))
7237 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
)))
;
7238 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
)))
7239 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
)))
;
7240 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
)))
7241 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
)))
;
7242 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
)))
7243 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
)))
;
7244 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
)))
7245 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
)))
;
7246 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)))
7247 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)))
;
7248 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)))
7249 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)))
;
7250 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
)))
7251 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
)))
;
7252 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)))
7253 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)))
;
7254 if (mask == WDC_SCA_V1_ALL0xF) {
7255 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)))
7256 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)))
;
7257 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))
7258 (__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))
;
7259 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)))
7260 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)))
;
7261 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))
7262 (__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))
;
7263 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)))
7264 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)))
;
7265 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)))
7266 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)))
;
7267 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)))
7268 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)))
;
7269 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))
7270 (__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))
;
7271 }
7272 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)))
7273 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)))
;
7274 if (mask == WDC_SCA_V1_ALL0xF)
7275 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)))
7276 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)))
;
7277 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
)))
7278 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
)))
;
7279 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)))
7280 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)))
;
7281 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)))
7282 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)))
;
7283 if (mask == WDC_SCA_V1_ALL0xF) {
7284 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)))
7285 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)))
;
7286 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)))
7287 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)))
;
7288 }
7289 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)))
7290 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)))
;
7291 if (mask == WDC_SCA_V1_ALL0xF) {
7292 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)))
7293 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)))
;
7294 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)))
7295 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)))
;
7296 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)))
7297 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)))
;
7298 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)))
7299 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)))
;
7300 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
)))
7301 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
)))
;
7302 }
7303 char vers_str[40];
7304
7305 memset((void *)vers_str, 0, 40);
7306 snprintf((char *)vers_str, sizeof(vers_str), "%d.%d.%d.%d",
7307 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7308 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7309 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7310 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7311 json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
7312 memset((void *)vers_str, 0, 40);
7313 snprintf((char *)vers_str, sizeof(vers_str), "%d.%d.%d.%d", 0, 0, 0, 0);
7314 json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
7315
7316 if (mask == WDC_SCA_V1_ALL0xF) {
7317 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)))
7318 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)))
;
7319 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)))
7320 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)))
;
7321 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)))
7322 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)))
;
7323 char guid[40];
7324 __u8 *lpg;
7325
7326 lpg = ext_smart_log_ptr->ext_smart_lpg;
7327 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7328 shr_get_unaligned_le64(&lpg[8]),
7329 shr_get_unaligned_le64(&lpg[0]));
7330 json_object_add_value_string(root, "log_page_guid", guid);
7331 }
7332
7333 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7334 printf("\n");
7335 json_free_object(root)json_object_put(root);
7336}
7337
7338static void wdc_print_eol_c0_normal(void *data)
7339{
7340 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7341 (struct wdc_nvme_c0_eol_log_page *)data;
7342
7343 printf(" End of Life Log Page 0xC0 :-\n");
7344 printf(" Realloc Block Count %"PRIu32"u""\n",
7345 le32_to_cpu(eol_log_page_ptr->eol_rbc));
7346 printf(" Write Amp %"PRIu32"u""\n",
7347 le32_to_cpu(eol_log_page_ptr->eol_wra));
7348 printf(" Percent Life Remaining %"PRIu32"u""\n",
7349 le32_to_cpu(eol_log_page_ptr->eol_plr));
7350 printf(" Program Fail Count %"PRIu32"u""\n",
7351 le32_to_cpu(eol_log_page_ptr->eol_pfc));
7352 printf(" Erase Fail Count %"PRIu32"u""\n",
7353 le32_to_cpu(eol_log_page_ptr->eol_efc));
7354 printf(" Raw Read Error Rate %"PRIu32"u""\n",
7355 le32_to_cpu(eol_log_page_ptr->eol_rrer));
7356}
7357
7358static void wdc_print_eol_c0_json(void *data)
7359{
7360 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7361 (struct wdc_nvme_c0_eol_log_page *)data;
7362 struct json_object *root = json_create_object()json_object_new_object();
7363
7364 json_object_add_value_uint(root, "Realloc Block Count",json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rbc)))
7365 le32_to_cpu(eol_log_page_ptr->eol_rbc))json_object_object_add(root, "Realloc Block Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rbc)))
;
7366 json_object_add_value_uint(root, "Write Amp",json_object_object_add(root, "Write Amp", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_wra)))
7367 le32_to_cpu(eol_log_page_ptr->eol_wra))json_object_object_add(root, "Write Amp", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_wra)))
;
7368 json_object_add_value_uint(root, "Percent Life Remaining",json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_plr)))
7369 le32_to_cpu(eol_log_page_ptr->eol_plr))json_object_object_add(root, "Percent Life Remaining", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_plr)))
;
7370 json_object_add_value_uint(root, "Program Fail Count",json_object_object_add(root, "Program Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_pfc)))
7371 le32_to_cpu(eol_log_page_ptr->eol_pfc))json_object_object_add(root, "Program Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_pfc)))
;
7372 json_object_add_value_uint(root, "Erase Fail Count",json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_efc)))
7373 le32_to_cpu(eol_log_page_ptr->eol_efc))json_object_object_add(root, "Erase Fail Count", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_efc)))
;
7374 json_object_add_value_uint(root, "Raw Read Error Rate",json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rrer)))
7375 le32_to_cpu(eol_log_page_ptr->eol_rrer))json_object_object_add(root, "Raw Read Error Rate", json_object_new_uint64
(le32_to_cpu(eol_log_page_ptr->eol_rrer)))
;
7376
7377 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7378 printf("\n");
7379 json_free_object(root)json_object_put(root);
7380}
7381
7382static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
7383{
7384 if (!data) {
7385 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 V1 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 V1 log"
)
;
7386 return -1;
7387 }
7388 switch (fmt) {
7389 case NORMAL:
7390 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL0xF);
7391 break;
7392 case JSON:
7393 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL0xF);
7394 break;
7395 }
7396 return 0;
7397}
7398
7399static int wdc_print_c0_cloud_attr_log(void *data,
7400 int fmt,
7401 struct libnvme_transport_handle *hdl)
7402{
7403 struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data;
7404
7405 if (!data) {
7406 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7407 return -1;
7408 }
7409
7410 switch (fmt) {
7411 case BINARY:
7412 d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log));
7413 break;
7414 case NORMAL:
7415 wdc_show_cloud_smart_log_normal(log, hdl);
7416 break;
7417 case JSON:
7418 wdc_show_cloud_smart_log_json(log);
7419 break;
7420 }
7421 return 0;
7422}
7423
7424static int wdc_print_c0_eol_log(void *data, int fmt)
7425{
7426 if (!data) {
7427 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7428 return -1;
7429 }
7430 switch (fmt) {
7431 case BINARY:
7432 d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN0x200);
7433 break;
7434 case NORMAL:
7435 wdc_print_eol_c0_normal(data);
7436 break;
7437 case JSON:
7438 wdc_print_eol_c0_json(data);
7439 break;
7440 }
7441 return 0;
7442}
7443
7444static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct libnvme_transport_handle *hdl, int uuid_index,
7445 char *format, __u32 namespace_id, int fmt)
7446{
7447 int ret;
7448
7449 if (!uuid_index) {
7450 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7451 uuid_index,
7452 namespace_id,
7453 fmt);
7454 } else if (uuid_index == 1) {
7455 ret = nvme_get_print_c0_eol_log(hdl,
7456 uuid_index,
7457 namespace_id,
7458 fmt);
7459 } else {
7460 nvme_show_error("ERROR: WDC: Unknown uuid index")nvme_show_message(1, "ERROR: WDC: Unknown uuid index");
7461 ret = -1;
7462 }
7463
7464 return ret;
7465}
7466
7467static int wdc_get_c0_log_page_sn(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, int uuid_index, char *format,
7468 __u32 namespace_id, int fmt)
7469{
7470 int ret = 0;
7471 __u32 cust_id;
7472
7473 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7474 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7475 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7476 return -1;
7477 }
7478
7479 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
7480 (cust_id == WDC_CUSTOMER_ID_0x10050x1005)) {
7481 ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format,
7482 namespace_id, fmt);
7483 } else {
7484 ret = nvme_get_print_c0_eol_log(hdl,
7485 0,
7486 namespace_id,
7487 fmt);
7488 }
7489
7490 return ret;
7491}
7492
7493static int wdc_get_c0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format, int uuid_index,
7494 __u32 namespace_id)
7495{
7496 uint32_t device_id = 0, read_vendor_id;
7497 nvme_print_flags_t fmt;
7498 int ret;
7499 __u8 *data;
7500 void *dev_mng_log = NULL((void*)0);
7501 __u32 market_name_len = 0;
7502 char marketing_name[64];
7503
7504 memset(marketing_name, 0, 64);
7505
7506 if (!wdc_check_device(ctx, hdl))
7507 return -1;
7508 ret = validate_output_format(format, &fmt);
7509 if (ret < 0) {
7510 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7511 return ret;
7512 }
7513
7514 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7515 if (ret) {
7516 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
7517 return ret;
7518 }
7519
7520 switch (device_id) {
7521 case WDC_NVME_SN640_DEV_ID0x2400:
7522 case WDC_NVME_SN640_DEV_ID_10x2401:
7523 case WDC_NVME_SN640_DEV_ID_20x2402:
7524 case WDC_NVME_SN640_DEV_ID_30x2404:
7525 case WDC_NVME_SN840_DEV_ID0x2300:
7526 case WDC_NVME_SN840_DEV_ID_10x2500:
7527 case WDC_NVME_SN860_DEV_ID0x2730:
7528 case WDC_NVME_SN560_DEV_ID_10x2712:
7529 case WDC_NVME_SN560_DEV_ID_20x2713:
7530 case WDC_NVME_SN560_DEV_ID_30x2714:
7531 case WDC_NVME_SN550_DEV_ID0x2708:
7532 ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt);
7533 break;
7534 case WDC_NVME_SN650_DEV_ID0x2700:
7535 case WDC_NVME_SN650_DEV_ID_10x2701:
7536 case WDC_NVME_SN650_DEV_ID_20x2702:
7537 case WDC_NVME_SN650_DEV_ID_30x2720:
7538 case WDC_NVME_SN650_DEV_ID_40x2721:
7539 case WDC_NVME_SN655_DEV_ID0x2722:
7540 case WDC_NVME_SN655_DEV_ID_10x2723:
7541 case WDC_NVME_SNTMP_DEV_ID0x2761:
7542 case WDC_NVME_SNTMP_DEV_ID_10x2763:
7543 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
7544 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
7545 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
7546 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
7547 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
7548 if (uuid_index == 0) {
7549 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7550 uuid_index,
7551 namespace_id,
7552 fmt);
7553 } else {
7554 ret = nvme_get_print_c0_eol_log(hdl,
7555 uuid_index,
7556 namespace_id,
7557 fmt);
7558 }
7559 break;
7560 case WDC_NVME_ZN350_DEV_ID0x5010:
7561 case WDC_NVME_ZN350_DEV_ID_10x5018:
7562 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7563 0,
7564 NVME_NSID_ALL,
7565 fmt);
7566 break;
7567 case WDC_NVME_SN820CL_DEV_ID0x5037:
7568 /* Get the 0xC0 Extended Smart Cloud Attribute log data */
7569 data = NULL((void*)0);
7570 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
7571 uuid_index, namespace_id);
7572
7573 if (strcmp(format, "json"))
7574 nvme_show_status(ret);
7575
7576 if (!ret) {
7577 /* parse the data */
7578 wdc_print_ext_smart_cloud_log(data, fmt);
7579 } else {
7580 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page V1 data"
)
;
7581 ret = -1;
7582 }
7583
7584 free(data);
7585 break;
7586 default:
7587 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
7588 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
7589 ret = -1;
7590 goto out;
7591 }
7592
7593 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
7594 WDC_C2_MARKETING_NAME_ID0x07,
7595 (char *)marketing_name,
7596 sizeof(marketing_name),
7597 &market_name_len)) {
7598 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
7599 ret = -1;
7600 goto out;
7601 }
7602
7603 if ((!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655", market_name_len)) ||
7604 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655", market_name_len)) ||
7605 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655", market_name_len)) ||
7606 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655", market_name_len))) {
7607 if (uuid_index == 0) {
7608 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7609 uuid_index,
7610 namespace_id,
7611 fmt);
7612 } else {
7613 ret = nvme_get_print_c0_eol_log(hdl,
7614 uuid_index,
7615 namespace_id,
7616 fmt);
7617 }
7618 } else {
7619 nvme_show_error("ERROR: WDC: Unknown device id: 0x%x or marketing name: %s",nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
7620 device_id, marketing_name)nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
;
7621 ret = -1;
7622 }
7623 break;
7624 }
7625
7626out:
7627 return ret;
7628}
7629
7630static int wdc_print_latency_monitor_log(struct libnvme_transport_handle *hdl,
7631 struct wdc_ssd_latency_monitor_log *log_data,
7632 int fmt)
7633{
7634 if (!log_data) {
7635 nvme_show_error("ERROR: WDC: Invalid C3 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C3 log data buffer"
)
;
7636 return -1;
7637 }
7638 switch (fmt) {
7639 case NORMAL:
7640 wdc_print_latency_monitor_log_normal(hdl, log_data);
7641 break;
7642 case JSON:
7643 wdc_print_latency_monitor_log_json(log_data);
7644 break;
7645 }
7646 return 0;
7647}
7648
7649static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
7650{
7651 if (!log_data) {
7652 nvme_show_error("ERROR: WDC: Invalid C1 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C1 log data buffer"
)
;
7653 return -1;
7654 }
7655 switch (fmt) {
7656 case NORMAL:
7657 wdc_print_error_rec_log_normal(log_data);
7658 break;
7659 case JSON:
7660 wdc_print_error_rec_log_json(log_data);
7661 break;
7662 }
7663 return 0;
7664}
7665
7666static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
7667{
7668 if (!log_data) {
7669 nvme_show_error("ERROR: WDC: Invalid C4 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C4 log data buffer"
)
;
7670 return -1;
7671 }
7672 switch (fmt) {
7673 case NORMAL:
7674 wdc_print_dev_cap_log_normal(log_data);
7675 break;
7676 case JSON:
7677 wdc_print_dev_cap_log_json(log_data);
7678 break;
7679 }
7680 return 0;
7681}
7682
7683static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
7684{
7685 if (!log_data) {
7686 nvme_show_error("ERROR: WDC: Invalid C5 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C5 log data buffer"
)
;
7687 return -1;
7688 }
7689 switch (fmt) {
7690 case NORMAL:
7691 wdc_print_unsupported_reqs_log_normal(log_data);
7692 break;
7693 case JSON:
7694 wdc_print_unsupported_reqs_log_json(log_data);
7695 break;
7696 }
7697 return 0;
7698}
7699
7700static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
7701{
7702 if (!perf) {
7703 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7704 return -1;
7705 }
7706 switch (fmt) {
7707 case NORMAL:
7708 wdc_print_fb_ca_log_normal(perf);
7709 break;
7710 case JSON:
7711 wdc_print_fb_ca_log_json(perf);
7712 break;
7713 }
7714 return 0;
7715}
7716
7717static int wdc_print_bd_ca_log(struct libnvme_transport_handle *hdl, void *bd_data, int fmt)
7718{
7719 if (!bd_data) {
7720 nvme_show_error("ERROR: WDC: Invalid buffer to read data")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read data"
)
;
7721 return -1;
7722 }
7723 switch (fmt) {
7724 case NORMAL:
7725 wdc_print_bd_ca_log_normal(hdl, bd_data);
7726 break;
7727 case JSON:
7728 wdc_print_bd_ca_log_json(bd_data);
7729 break;
7730 default:
7731 nvme_show_error("ERROR: WDC: Unknown format - %d", fmt)nvme_show_message(1, "ERROR: WDC: Unknown format - %d", fmt);
7732 return -1;
7733 }
7734 return 0;
7735}
7736
7737static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt)
7738{
7739 if (!perf) {
7740 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7741 return -1;
7742 }
7743 switch (fmt) {
7744 case NORMAL:
7745 wdc_print_d0_log_normal(perf);
7746 break;
7747 case JSON:
7748 wdc_print_d0_log_json(perf);
7749 break;
7750 }
7751 return 0;
7752}
7753
7754static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt,
7755 __u32 cust_id, __u32 vendor_id,
7756 __u32 device_id)
7757{
7758 if (!data) {
7759 nvme_show_error("ERROR: WDC: Invalid buffer to read fw activate history entries")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read fw activate history entries"
)
;
7760 return -1;
7761 }
7762
7763 switch (fmt) {
7764 case NORMAL:
7765 wdc_print_fw_act_history_log_normal(data, num_entries, cust_id,
7766 vendor_id, device_id);
7767 break;
7768 case JSON:
7769 wdc_print_fw_act_history_log_json(data, num_entries, cust_id,
7770 vendor_id, device_id);
7771 break;
7772 }
7773 return 0;
7774}
7775
7776static int wdc_get_ca_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7777{
7778 uint32_t read_device_id = 0, read_vendor_id;
7779 struct wdc_ssd_ca_perf_stats *perf;
7780 nvme_print_flags_t fmt;
7781 __u32 cust_id;
7782 __u8 *data;
7783 int ret;
7784
7785 if (!wdc_check_device(ctx, hdl))
7786 return -1;
7787 ret = validate_output_format(format, &fmt);
7788 if (ret < 0) {
7789 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7790 return ret;
7791 }
7792
7793 /* verify the 0xCA log page is supported */
7794 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7795 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
7796 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
7797 return -1;
7798 }
7799
7800 /* get the FW customer id */
7801 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7802 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7803 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7804 return -1;
7805 }
7806
7807 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7808 if (ret) {
7809 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
7810 return ret;
7811 }
7812
7813 switch (read_device_id) {
7814 case WDC_NVME_SN200_DEV_ID0x0023:
7815 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7816 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7817 if (!data) {
7818 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7819 return -1;
7820 }
7821
7822 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7823
7824 ret = nvme_get_log_simple(hdl,
7825 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7826 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7827 if (strcmp(format, "json"))
7828 nvme_show_status(ret);
7829
7830 if (!ret) {
7831 /* parse the data */
7832 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7833 ret = wdc_print_fb_ca_log(perf, fmt);
7834 } else {
7835 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7836 ret = -1;
7837 }
7838 } else {
7839
7840 nvme_show_error("ERROR: WDC: Unsupported Customer id, id = 0x%x", cust_id)nvme_show_message(1, "ERROR: WDC: Unsupported Customer id, id = 0x%x"
, cust_id)
;
7841 return -1;
7842 }
7843 break;
7844 case WDC_NVME_SN640_DEV_ID0x2400:
7845 case WDC_NVME_SN640_DEV_ID_10x2401:
7846 case WDC_NVME_SN640_DEV_ID_20x2402:
7847 case WDC_NVME_SN640_DEV_ID_30x2404:
7848 case WDC_NVME_SN840_DEV_ID0x2300:
7849 case WDC_NVME_SN840_DEV_ID_10x2500:
7850 case WDC_NVME_SN860_DEV_ID0x2730:
7851 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7852 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7853 if (!data) {
7854 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7855 return -1;
7856 }
7857
7858 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7859
7860 ret = nvme_get_log_simple(hdl,
7861 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7862 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7863 if (strcmp(format, "json"))
7864 nvme_show_status(ret);
7865
7866 if (!ret) {
7867 /* parse the data */
7868 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7869 ret = wdc_print_fb_ca_log(perf, fmt);
7870 } else {
7871 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7872 ret = -1;
7873 }
7874 } else if ((cust_id == WDC_CUSTOMER_ID_GN0x0001) || (cust_id == WDC_CUSTOMER_ID_GD0x0101) ||
7875 (cust_id == WDC_CUSTOMER_ID_BD0x1009)) {
7876 data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7877 if (!data) {
7878 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7879 return -1;
7880 }
7881
7882 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7883 ret = nvme_get_log_simple(hdl,
7884 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7885 data, WDC_BD_CA_LOG_BUF_LEN0xA0);
7886 if (strcmp(format, "json"))
7887 nvme_show_status(ret);
7888
7889 if (!ret) {
7890 /* parse the data */
7891 ret = wdc_print_bd_ca_log(hdl, data, fmt);
7892 } else {
7893 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
7894 ret = -1;
7895 }
7896 } else {
7897 nvme_show_error("ERROR: WDC: Unsupported Customer id, id = 0x%x", cust_id)nvme_show_message(1, "ERROR: WDC: Unsupported Customer id, id = 0x%x"
, cust_id)
;
7898 return -1;
7899 }
7900 break;
7901 default:
7902 nvme_show_error("ERROR: WDC: Log page 0xCA not supported for this device")nvme_show_message(1, "ERROR: WDC: Log page 0xCA not supported for this device"
)
;
7903 return -1;
7904 }
7905
7906 free(data);
7907 return ret;
7908}
7909
7910static int wdc_get_c1_log_page(struct libnvme_global_ctx *ctx,
7911 struct libnvme_transport_handle *hdl, char *format,
7912 uint8_t interval)
7913{
7914 struct wdc_log_page_subpage_header sph;
7915 struct wdc_ssd_perf_stats perf;
7916 struct wdc_log_page_header *l;
7917 nvme_print_flags_t fmt;
7918 int total_subpages;
7919 int skip_cnt = 4;
7920 size_t off;
7921 __u8 *data;
7922 __u8 *p;
7923 int i;
7924 int ret;
7925
7926 if (!wdc_check_device(ctx, hdl))
7927 return -1;
7928
7929 ret = validate_output_format(format, &fmt);
7930 if (ret < 0) {
7931 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7932 return ret;
7933 }
7934
7935 if (interval < 1 || interval > 15) {
7936 nvme_show_error("ERROR: WDC: interval out of range [1-15]")nvme_show_message(1, "ERROR: WDC: interval out of range [1-15]"
)
;
7937 return -1;
7938 }
7939
7940 data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7941 if (!data) {
7942 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7943 return -1;
7944 }
7945 memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7946
7947 ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE0xC1,
7948 data, WDC_ADD_LOG_BUF_LEN0x4000);
7949 if (strcmp(format, "json"))
7950 nvme_show_status(ret);
7951 if (!ret) {
7952 l = (struct wdc_log_page_header *)data;
7953 total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F - 1;
7954 /* the subpages must fit the buffer */
7955 for (i = 0, off = skip_cnt; i < total_subpages &&
7956 off < WDC_ADD_LOG_BUF_LEN0x4000 &&
7957 WDC_ADD_LOG_BUF_LEN0x4000 - off >= sizeof(sph);
7958 i++, off += skip_cnt) {
7959 /* a subpage starts at any byte: copy what is read */
7960 p = data + off;
7961 memcpy(&sph, p, sizeof(sph));
7962 if (sph.spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37) {
7963 if (sph.pcset == interval) {
7964 if (WDC_ADD_LOG_BUF_LEN0x4000 - off - 4 <
7965 sizeof(perf))
7966 break;
7967 memcpy(&perf, p + 4, sizeof(perf));
7968 ret = wdc_print_log(&perf, fmt);
7969 break;
7970 }
7971 }
7972 skip_cnt = le16_to_cpu(sph.subpage_length) + 4;
7973 }
7974 if (ret)
7975 nvme_show_error("ERROR: WDC: Unable to read data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read data from buffer"
)
;
7976 }
7977 free(data);
7978 return ret;
7979}
7980
7981static int wdc_get_c3_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7982{
7983 struct wdc_ssd_latency_monitor_log *log_data;
7984 nvme_print_flags_t fmt;
7985 __u8 *data;
7986 int ret;
7987 int i;
7988
7989 if (!wdc_check_device(ctx, hdl))
7990 return -1;
7991
7992 ret = validate_output_format(format, &fmt);
7993 if (ret < 0) {
7994 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7995 return ret;
7996 }
7997
7998 data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7999 if (!data) {
8000 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8001 return -1;
8002 }
8003 memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
8004
8005 ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID0xC3,
8006 data, WDC_LATENCY_MON_LOG_BUF_LEN0x200);
8007
8008 if (strcmp(format, "json"))
8009 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
8010
8011 if (!ret) {
8012 log_data = (struct wdc_ssd_latency_monitor_log *)data;
8013
8014 /* check log page version */
8015 if (le16_to_cpu(log_data->log_page_version) !=
8016 WDC_LATENCY_MON_VERSION0x0001) {
8017 nvme_show_error("ERROR: WDC: invalid latency monitor version")nvme_show_message(1, "ERROR: WDC: invalid latency monitor version"
)
;
8018 ret = -1;
8019 goto out;
8020 }
8021
8022 /* check log page guid */
8023 /* Verify GUID matches */
8024 for (i = 0; i < 16; i++) {
8025 if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) {
8026 nvme_show_error("ERROR: WDC: Unknown GUID in C3 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C3 Log Page data"
)
;
8027 int j;
8028
8029 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8030 for (j = 0; j < 16; j++)
8031 nvme_show_error("%x", wdc_lat_mon_guid[j])nvme_show_message(1, "%x", wdc_lat_mon_guid[j]);
8032 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8033 for (j = 0; j < 16; j++)
8034 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8035 nvme_show_error("")nvme_show_message(1, "");
8036
8037 ret = -1;
8038 goto out;
8039 }
8040 }
8041
8042 /* parse the data */
8043 wdc_print_latency_monitor_log(hdl, log_data, fmt);
8044 } else {
8045 nvme_show_error("ERROR: WDC: Unable to read C3 data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read C3 data from buffer"
)
;
8046 }
8047
8048out:
8049 free(data);
8050 return ret;
8051
8052}
8053
8054static int wdc_get_ocp_c1_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8055{
8056 struct wdc_ocp_c1_error_recovery_log *log_data;
8057 nvme_print_flags_t fmt;
8058 __u8 *data;
8059 int ret;
8060 int i;
8061
8062 if (!wdc_check_device(ctx, hdl))
8063 return -1;
8064
8065 ret = validate_output_format(format, &fmt);
8066 if (ret < 0) {
8067 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8068 return ret;
8069 }
8070
8071 data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
8072 if (!data) {
8073 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8074 return -1;
8075 }
8076 memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
8077
8078 ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID0xC1,
8079 data, WDC_ERROR_REC_LOG_BUF_LEN512);
8080
8081 if (strcmp(format, "json"))
8082 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
8083
8084 if (!ret) {
8085 log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
8086
8087 /* check log page version */
8088 if ((le16_to_cpu(log_data->log_page_version) < 1) ||
8089 (le16_to_cpu(log_data->log_page_version) > 3)) {
8090 nvme_show_error("ERROR: WDC: invalid error recovery log version - %d",nvme_show_message(1, "ERROR: WDC: invalid error recovery log version - %d"
, le16_to_cpu(log_data->log_page_version))
8091 le16_to_cpu(log_data->log_page_version))nvme_show_message(1, "ERROR: WDC: invalid error recovery log version - %d"
, le16_to_cpu(log_data->log_page_version))
;
8092 ret = -1;
8093 goto out;
8094 }
8095
8096 /* Verify GUID matches */
8097 for (i = 0; i < WDC_OCP_C1_GUID_LENGTH16; i++) {
8098 if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
8099 nvme_show_error("ERROR: WDC: Unknown GUID in C1 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C1 Log Page data"
)
;
8100 int j;
8101
8102 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8103 for (j = 0; j < 16; j++)
8104 nvme_show_error("%x", wdc_ocp_c1_guid[j])nvme_show_message(1, "%x", wdc_ocp_c1_guid[j]);
8105 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8106 for (j = 0; j < 16; j++)
8107 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8108 nvme_show_error("")nvme_show_message(1, "");
8109
8110 ret = -1;
8111 goto out;
8112 }
8113 }
8114
8115 /* parse the data */
8116 wdc_print_error_rec_log(log_data, fmt);
8117 } else {
8118 nvme_show_error("ERROR: WDC: Unable to read error recovery (C1) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read error recovery (C1) data from buffer"
)
;
8119 }
8120
8121out:
8122 free(data);
8123 return ret;
8124}
8125
8126static int wdc_get_ocp_c4_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8127{
8128 struct wdc_ocp_C4_dev_cap_log *log_data;
8129 nvme_print_flags_t fmt;
8130 __u8 *data;
8131 int ret;
8132 int i;
8133
8134 if (!wdc_check_device(ctx, hdl))
8135 return -1;
8136
8137 ret = validate_output_format(format, &fmt);
8138 if (ret < 0) {
8139 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8140 return ret;
8141 }
8142
8143 data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
8144 if (!data) {
8145 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8146 return -1;
8147 }
8148 memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
8149
8150 ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID0xC4,
8151 data, WDC_DEV_CAP_LOG_BUF_LEN4096);
8152
8153 if (strcmp(format, "json"))
8154 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
8155
8156 if (!ret) {
8157 log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
8158
8159 /* check log page version */
8160 if (le16_to_cpu(log_data->log_page_version) !=
8161 WDC_DEV_CAP_LOG_VERSION0001) {
8162 nvme_show_error(nvme_show_message(1, "ERROR: WDC: invalid device capabilities log version - %d"
, le16_to_cpu(log_data->log_page_version))
8163 "ERROR: WDC: invalid device capabilities log version - %d",nvme_show_message(1, "ERROR: WDC: invalid device capabilities log version - %d"
, le16_to_cpu(log_data->log_page_version))
8164 le16_to_cpu(log_data->log_page_version))nvme_show_message(1, "ERROR: WDC: invalid device capabilities log version - %d"
, le16_to_cpu(log_data->log_page_version))
;
8165 ret = -1;
8166 goto out;
8167 }
8168
8169 /* Verify GUID matches */
8170 for (i = 0; i < WDC_OCP_C4_GUID_LENGTH16; i++) {
8171 if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
8172 nvme_show_error("ERROR: WDC: Unknown GUID in C4 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C4 Log Page data"
)
;
8173 int j;
8174
8175 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8176 for (j = 0; j < 16; j++)
8177 nvme_show_error("%x", wdc_ocp_c4_guid[j])nvme_show_message(1, "%x", wdc_ocp_c4_guid[j]);
8178 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8179 for (j = 0; j < 16; j++)
8180 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8181 nvme_show_error("")nvme_show_message(1, "");
8182
8183 ret = -1;
8184 goto out;
8185 }
8186 }
8187
8188 /* parse the data */
8189 wdc_print_dev_cap_log(log_data, fmt);
8190 } else {
8191 nvme_show_error("ERROR: WDC: Unable to read device capabilities (C4) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read device capabilities (C4) data from buffer"
)
;
8192 }
8193
8194out:
8195 free(data);
8196 return ret;
8197}
8198
8199static int wdc_get_ocp_c5_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8200{
8201 struct wdc_ocp_C5_unsupported_reqs *log_data;
8202 nvme_print_flags_t fmt;
8203 int ret;
8204 __u8 *data;
8205 int i;
8206
8207 if (!wdc_check_device(ctx, hdl))
8208 return -1;
8209
8210 ret = validate_output_format(format, &fmt);
8211 if (ret < 0) {
8212 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8213 return ret;
8214 }
8215
8216 data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8217 if (!data) {
8218 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8219 return -1;
8220 }
8221 memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8222
8223 ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID0xC5,
8224 data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8225
8226 if (strcmp(format, "json"))
8227 nvme_show_error("NVMe Status:%s(%x)", libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
8228
8229 if (!ret) {
8230 log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
8231
8232 /* check log page version */
8233 if (le16_to_cpu(log_data->log_page_version) !=
8234 WDC_UNSUPPORTED_REQS_LOG_VERSION0001) {
8235 nvme_show_error("ERROR: WDC: invalid 0xC5 log page version")nvme_show_message(1, "ERROR: WDC: invalid 0xC5 log page version"
)
;
8236 nvme_show_error("ERROR: WDC: log page version: %d",nvme_show_message(1, "ERROR: WDC: log page version: %d", le16_to_cpu
(log_data->log_page_version))
8237 le16_to_cpu(log_data->log_page_version))nvme_show_message(1, "ERROR: WDC: log page version: %d", le16_to_cpu
(log_data->log_page_version))
;
8238 ret = -1;
8239 goto out;
8240 }
8241
8242 /* Verify GUID matches */
8243 for (i = 0; i < WDC_OCP_C5_GUID_LENGTH16; i++) {
8244 if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
8245 nvme_show_error("ERROR: WDC: Unknown GUID in C5 Log Page data")nvme_show_message(1, "ERROR: WDC: Unknown GUID in C5 Log Page data"
)
;
8246 int j;
8247
8248 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8249 for (j = 0; j < 16; j++)
8250 nvme_show_error("%x", wdc_ocp_c5_guid[j])nvme_show_message(1, "%x", wdc_ocp_c5_guid[j]);
8251 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8252 for (j = 0; j < 16; j++)
8253 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8254 nvme_show_error("")nvme_show_message(1, "");
8255
8256 ret = -1;
8257 goto out;
8258 }
8259 }
8260
8261 /* parse the data */
8262 wdc_print_unsupported_reqs_log(log_data, fmt);
8263 } else {
8264 nvme_show_error("ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer"
)
;
8265 }
8266
8267out:
8268 free(data);
8269 return ret;
8270}
8271
8272static int wdc_get_d0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8273{
8274 struct wdc_ssd_d0_smart_log *perf;
8275 nvme_print_flags_t fmt;
8276 int ret = 0;
8277 __u8 *data;
8278
8279 if (!wdc_check_device(ctx, hdl))
8280 return -1;
8281
8282 ret = validate_output_format(format, &fmt);
8283 if (ret < 0) {
8284 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8285 return ret;
8286 }
8287
8288 /* verify the 0xD0 log page is supported */
8289 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8290 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == false0) {
8291 nvme_show_error("ERROR: WDC: 0xD0 Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xD0 Log Page not supported"
)
;
8292 return -1;
8293 }
8294
8295 data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
8296 if (!data) {
8297 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8298 return -1;
8299 }
8300 memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
8301
8302 ret = nvme_get_log_simple(hdl,
8303 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0,
8304 data, WDC_NVME_VU_SMART_LOG_LEN0x200);
8305 if (strcmp(format, "json"))
8306 nvme_show_status(ret);
8307
8308 if (!ret) {
8309 /* parse the data */
8310 perf = (struct wdc_ssd_d0_smart_log *)(data);
8311 ret = wdc_print_d0_log(perf, fmt);
8312 } else {
8313 nvme_show_error("ERROR: WDC: Unable to read D0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read D0 Log Page data"
)
;
8314 ret = -1;
8315 }
8316
8317 free(data);
8318 return ret;
8319}
8320
8321static long double le_to_float(__u8 *data, int byte_len)
8322{
8323 long double result = 0;
8324 int i;
8325
8326 for (i = 0; i < byte_len; i++) {
8327 result *= 256;
8328 result += data[15 - i];
8329 }
8330
8331 return result;
8332}
8333
8334/*
8335 * A counter of @byte_len bytes at @data, at most UINT64_MAX: a device can
8336 * report more, which a conversion of the long double would make undefined.
8337 */
8338static __u64 le_to_u64(__u8 *data, int byte_len)
8339{
8340 long double val = le_to_float(data, byte_len);
8341
8342 return val < 0x1p64L ? (__u64)val : UINT64_MAX(18446744073709551615UL);
8343}
8344
8345/* The GUID as "0x" and its bytes in hex, the most significant first */
8346static void stringify_log_page_guid(__u8 *guid, char *buf, size_t size)
8347{
8348 shr_strscpy(buf, "0x", size);
8349 shr_bin_to_hex(buf + 2, size - 2, guid, 16, SHR_HEX_REVERSE(1 << 1));
8350}
8351
8352static const char *const cloud_smart_log_thermal_status[] = {
8353 [0x00] = "unthrottled",
8354 [0x01] = "first_level",
8355 [0x02] = "second_level",
8356 [0x03] = "third_level",
8357};
8358
8359static const char *stringify_cloud_smart_log_thermal_status(__u8 status)
8360{
8361 if (status < ARRAY_SIZE(cloud_smart_log_thermal_status)(sizeof(cloud_smart_log_thermal_status) / sizeof((cloud_smart_log_thermal_status
)[0]) + 0)
&&
8362 cloud_smart_log_thermal_status[status])
8363 return cloud_smart_log_thermal_status[status];
8364 return "unrecognized";
8365}
8366
8367static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log)
8368{
8369 struct json_object *root;
8370 struct json_object *bad_user_nand_blocks;
8371 struct json_object *bad_system_nand_blocks;
8372 struct json_object *e2e_correction_counts;
8373 struct json_object *user_data_erase_counts;
8374 struct json_object *thermal_status;
8375 struct json_object *dssd_specific_ver;
8376 char buf[2 * sizeof(log->log_page_guid) + 3];
8377 char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1];
8378 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8379
8380 bad_user_nand_blocks = json_create_object()json_object_new_object();
8381 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)))
8382 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)))
;
8383 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)))
8384 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)))
;
8385
8386 bad_system_nand_blocks = json_create_object()json_object_new_object();
8387 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)))
8388 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)))
;
8389 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)))
8390 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)))
;
8391
8392 e2e_correction_counts = json_create_object()json_object_new_object();
8393 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)))
8394 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)))
;
8395 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)))
8396 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)))
;
8397
8398 user_data_erase_counts = json_create_object()json_object_new_object();
8399 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)))
8400 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)))
;
8401 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)))
8402 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)))
;
8403
8404 thermal_status = json_create_object()json_object_new_object();
8405 json_object_add_value_string(thermal_status, "current_status",
8406 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8407 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))
8408 log->thermal_status.num_events)json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
;
8409
8410 dssd_specific_ver = json_create_object()json_object_new_object();
8411 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))
8412 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))
;
8413 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)))
8414 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)))
;
8415 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)))
8416 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)))
;
8417 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))
8418 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))
;
8419
8420 root = json_create_object()json_object_new_object();
8421 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_u64(log->physical_media_units_written, 16)))
8422 le_to_u64(log->physical_media_units_written, 16))json_object_object_add(root, "physical_media_units_written", json_object_new_uint64
(le_to_u64(log->physical_media_units_written, 16)))
;
8423 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_u64(log->physical_media_units_read, 16)))
8424 le_to_u64(log->physical_media_units_read, 16))json_object_object_add(root, "physical_media_units_read", json_object_new_uint64
(le_to_u64(log->physical_media_units_read, 16)))
;
8425 json_object_add_value_object(root, "bad_user_nand_blocks",json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
8426 bad_user_nand_blocks)json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
;
8427 json_object_add_value_object(root, "bad_system_nand_blocks",json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
8428 bad_system_nand_blocks)json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
;
8429 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)))
8430 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)))
;
8431 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
)))
8432 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
)))
;
8433 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)))
8434 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)))
;
8435 json_object_add_value_object(root, "e2e_correction_counts",json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
8436 e2e_correction_counts)json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
;
8437 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))
8438 log->system_data_percent_used)json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
;
8439 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)))
8440 le64_to_cpu(log->refresh_counts))json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
;
8441 json_object_add_value_object(root, "user_data_erase_counts",json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
8442 user_data_erase_counts)json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
;
8443 json_object_add_value_object(root, "thermal_status", thermal_status)json_object_object_add(root, "thermal_status", thermal_status
)
;
8444 if (smart_log_ver >= 3)
8445 json_object_add_value_object(root, "dssd_specific_ver",json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
8446 dssd_specific_ver)json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
;
8447 else
8448 json_free_object(dssd_specific_ver)json_object_put(dssd_specific_ver);
8449 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)))
8450 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)))
;
8451 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)))
8452 le32_to_cpu(log->incomplete_shutdowns))json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
;
8453 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))
8454 log->percent_free_blocks)json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
;
8455 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)))
8456 le16_to_cpu(log->capacitor_health))json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
;
8457 if (smart_log_ver >= 3) {
8458 if (smart_log_ver >= 4) {
8459 snprintf(buf, sizeof(buf), "%c",
8460 log->nvme_base_errata_ver);
8461 json_object_add_value_string(root, "nvme_base_errata_version", buf);
8462 snprintf(buf, sizeof(buf), "%c",
8463 log->nvme_cmd_set_errata_ver);
8464 json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf);
8465 } else {
8466 snprintf(buf, sizeof(buf), "%c",
8467 log->nvme_base_errata_ver);
8468 json_object_add_value_string(root, "nvme_errata_version", buf);
8469 }
8470 }
8471
8472 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)))
8473 le64_to_cpu(log->unaligned_io))json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
;
8474 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)))
8475 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)))
;
8476 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)))
8477 le64_to_cpu(log->total_nuse))json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
;
8478 json_object_add_value_uint64(root, "plp_start_count",json_object_object_add(root, "plp_start_count", json_object_new_uint64
(le_to_u64(log->plp_start_count, 16)))
8479 le_to_u64(log->plp_start_count, 16))json_object_object_add(root, "plp_start_count", json_object_new_uint64
(le_to_u64(log->plp_start_count, 16)))
;
8480 json_object_add_value_uint64(root, "endurance_estimate",json_object_object_add(root, "endurance_estimate", json_object_new_uint64
(le_to_u64(log->endurance_estimate, 16)))
8481 le_to_u64(log->endurance_estimate, 16))json_object_object_add(root, "endurance_estimate", json_object_new_uint64
(le_to_u64(log->endurance_estimate, 16)))
;
8482 if (smart_log_ver >= 3) {
8483 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)))
8484 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)))
;
8485 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)))
8486 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)))
;
8487 if (smart_log_ver >= 4) {
8488 snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s",
8489 (int)sizeof(log->lowest_permitted_fw_rev),
8490 log->lowest_permitted_fw_rev);
8491 json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr);
8492 } else
8493 json_object_add_value_uint128(root, "hardware_revision",json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu(log->hardware_revision)))
8494 le128_to_cpu(log->hardware_revision))json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu(log->hardware_revision)))
;
8495 }
8496 json_object_add_value_uint(root, "log_page_version",json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
8497 smart_log_ver)json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
;
8498 stringify_log_page_guid(log->log_page_guid, buf, sizeof(buf));
8499 json_object_add_value_string(root, "log_page_guid", buf);
8500
8501 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8502 printf("\n");
8503 json_free_object(root)json_object_put(root);
8504}
8505
8506static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
8507 struct libnvme_transport_handle *hdl)
8508{
8509 char buf[2 * sizeof(log->log_page_guid) + 3];
8510 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8511
8512 printf("SMART Cloud Attributes for NVMe device : %s\n",
8513 libnvme_transport_handle_get_name(hdl));
8514 printf("Physical Media Units Written : %'.0Lf\n",
8515 le_to_float(log->physical_media_units_written, 16));
8516 printf("Physical Media Units Read : %'.0Lf\n",
8517 le_to_float(log->physical_media_units_read, 16));
8518 printf("Bad User NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8519 le16_to_cpu(log->bad_user_nand_blocks.normalized));
8520 printf("Bad User NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8521 le64_to_cpu(log->bad_user_nand_blocks.raw));
8522 printf("Bad System NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8523 le16_to_cpu(log->bad_system_nand_blocks.normalized));
8524 printf("Bad System NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8525 le64_to_cpu(log->bad_system_nand_blocks.raw));
8526 printf("XOR Recovery Count : %" PRIu64"l" "u" "\n",
8527 le64_to_cpu(log->xor_recovery_count));
8528 printf("Uncorrectable Read Error Count : %" PRIu64"l" "u" "\n",
8529 le64_to_cpu(log->uncorrectable_read_error_count));
8530 printf("Soft ECC Error Count : %" PRIu64"l" "u" "\n",
8531 le64_to_cpu(log->soft_ecc_error_count));
8532 printf("End to End Correction Counts (Corrected) : %" PRIu32"u" "\n",
8533 le32_to_cpu(log->e2e_correction_counts.corrected));
8534 printf("End to End Correction Counts (Detected) : %" PRIu32"u" "\n",
8535 le32_to_cpu(log->e2e_correction_counts.detected));
8536 printf("System Data %% Used : %" PRIu8"hhu" "%%\n",
8537 log->system_data_percent_used);
8538 printf("Refresh Counts : %" PRIu64"l" "u" "\n",
8539 le64_to_cpu(log->refresh_counts));
8540 printf("User Data Erase Counts (Minimum) : %" PRIu32"u" "\n",
8541 le32_to_cpu(log->user_data_erase_counts.minimum));
8542 printf("User Data Erase Counts (Maximum) : %" PRIu32"u" "\n",
8543 le32_to_cpu(log->user_data_erase_counts.maximum));
8544 printf("Thermal Throttling Status (Current Status) : %s\n",
8545 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8546 printf("Thermal Throttling Status (Number of Events) : %" PRIu8"hhu" "\n",
8547 log->thermal_status.num_events);
8548 if (smart_log_ver >= 3) {
8549 printf("NVMe Major Version : %" PRIu8"hhu" "\n",
8550 log->dssd_specific_ver.major_ver);
8551 printf(" Minor Version : %" PRIu16"hu" "\n",
8552 le16_to_cpu(log->dssd_specific_ver.minor_ver));
8553 printf(" Point Version : %" PRIu16"hu" "\n",
8554 le16_to_cpu(log->dssd_specific_ver.point_ver));
8555 printf(" Errata Version : %" PRIu8"hhu" "\n",
8556 log->dssd_specific_ver.errata_ver);
8557 }
8558 printf("PCIe Correctable Error Count : %" PRIu64"l" "u" "\n",
8559 le64_to_cpu(log->pcie_correctable_error_count));
8560 printf("Incomplete Shutdowns : %" PRIu32"u" "\n",
8561 le32_to_cpu(log->incomplete_shutdowns));
8562 printf("%% Free Blocks : %" PRIu8"hhu" "%%\n",
8563 log->percent_free_blocks);
8564 printf("Capacitor Health : %" PRIu16"hu" "%%\n",
8565 le16_to_cpu(log->capacitor_health));
8566 if (smart_log_ver >= 3) {
8567 if (smart_log_ver >= 4) {
8568 printf("NVMe Base Errata Version : %c\n",
8569 log->nvme_base_errata_ver);
8570 printf("NVMe Command Set Errata Version : %c\n",
8571 log->nvme_cmd_set_errata_ver);
8572 } else {
8573 printf("NVMe Errata Version : %c\n",
8574 log->nvme_base_errata_ver);
8575 }
8576 }
8577 printf("Unaligned IO : %" PRIu64"l" "u" "\n",
8578 le64_to_cpu(log->unaligned_io));
8579 printf("Security Version Number : %" PRIu64"l" "u" "\n",
8580 le64_to_cpu(log->security_version_number));
8581 printf("Total NUSE : %" PRIu64"l" "u" "\n",
8582 le64_to_cpu(log->total_nuse));
8583 printf("PLP Start Count : %'.0Lf\n",
8584 le_to_float(log->plp_start_count, 16));
8585 printf("Endurance Estimate : %'.0Lf\n",
8586 le_to_float(log->endurance_estimate, 16));
8587 if (smart_log_ver >= 3) {
8588 printf("PCIe Link Retraining Count : %" PRIu64"l" "u" "\n",
8589 le64_to_cpu(log->pcie_link_retraining_cnt));
8590 printf("Power State Change Count : %" PRIu64"l" "u" "\n",
8591 le64_to_cpu(log->power_state_change_cnt));
8592 if (smart_log_ver >= 4)
8593 printf("Lowest Permitted FW Revision : %-.*s\n",
8594 (int)sizeof(log->lowest_permitted_fw_rev),
8595 log->lowest_permitted_fw_rev);
8596 else
8597 printf("Hardware Revision : %s\n",
8598 uint128_t_to_string(le128_to_cpu(log->hardware_revision)));
8599 }
8600 printf("Log Page Version : %" PRIu16"hu" "\n",
8601 smart_log_ver);
8602 stringify_log_page_guid(log->log_page_guid, buf, sizeof(buf));
8603 printf("Log Page GUID : %s\n", buf);
8604 printf("\n\n");
8605}
8606
8607static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd,
8608 struct plugin *plugin)
8609{
8610 const char *desc = "Retrieve additional performance statistics.";
8611 const char *interval = "Interval to read the statistics from [1, 15].";
8612 const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
8613 const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
8614 const char *namespace_id = "desired namespace id";
8615 nvme_print_flags_t fmt;
8616 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8617 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8618 int ret = 0;
8619 int uuid_index = 0;
8620 int page_mask = 0, num, i;
8621 int log_page_list[16];
8622 __u64 capabilities = 0;
8623 __u32 device_id, read_vendor_id;
8624
8625 struct config {
8626 uint8_t interval;
8627 __u8 log_page_version;
8628 char *log_page_mask;
8629 __u32 namespace_id;
8630 };
8631
8632 struct config cfg = {
8633 .interval = 14,
8634 .log_page_version = 0,
8635 .log_page_mask = "",
8636 .namespace_id = NVME_NSID_ALL,
8637 };
8638
8639 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8640 OPT_BYTE("interval", 'i', &cfg.interval, interval){"interval", 'i', "NUM", CFG_BYTE, _Generic(&cfg.interval
, uint8_t * : (&cfg.interval)), ARGCONFIG_ARG_REQUIRED, interval
, 0, }
,
8641 OPT_BYTE("log-page-version", 'l', &cfg.log_page_version,{"log-page-version", 'l', "NUM", CFG_BYTE, _Generic(&cfg.
log_page_version, uint8_t * : (&cfg.log_page_version)), ARGCONFIG_ARG_REQUIRED
, log_page_version, 0, }
8642 log_page_version){"log-page-version", 'l', "NUM", CFG_BYTE, _Generic(&cfg.
log_page_version, uint8_t * : (&cfg.log_page_version)), ARGCONFIG_ARG_REQUIRED
, log_page_version, 0, }
,
8643 OPT_LIST("log-page-mask", 'p', &cfg.log_page_mask,{"log-page-mask", 'p', "LIST", CFG_STRING, _Generic(&cfg.
log_page_mask, char ** : (&cfg.log_page_mask), const char
** : (&cfg.log_page_mask)), ARGCONFIG_ARG_REQUIRED, log_page_mask
, 0, }
8644 log_page_mask){"log-page-mask", 'p', "LIST", CFG_STRING, _Generic(&cfg.
log_page_mask, char ** : (&cfg.log_page_mask), const char
** : (&cfg.log_page_mask)), ARGCONFIG_ARG_REQUIRED, log_page_mask
, 0, }
,
8645 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
8646 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
8647 OPT_END(){ ((void*)0) }
8648 };
8649
8650 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8651 if (ret)
8652 return ret;
8653
8654 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8655 if (ret)
8656 return ret;
8657
8658 if (!cfg.log_page_version) {
8659 uuid_index = 0;
8660 } else if (cfg.log_page_version == 1) {
8661 uuid_index = 1;
8662 } else {
8663 nvme_show_error("ERROR: WDC: unsupported log page version for this command")nvme_show_message(1, "ERROR: WDC: unsupported log page version for this command"
)
;
8664 ret = -1;
8665 goto out;
8666 }
8667
8668 num = shr_parse_csv_int(cfg.log_page_mask, log_page_list, 16);
8669
8670 if (num == -1) {
8671 nvme_show_error("ERROR: WDC: log page list is malformed")nvme_show_message(1, "ERROR: WDC: log page list is malformed"
)
;
8672 ret = -1;
8673 goto out;
8674 }
8675
8676 if (!num) {
8677 page_mask |= WDC_ALL_PAGE_MASK0xFFFF;
8678 } else {
8679 for (i = 0; i < num; i++) {
8680 if (log_page_list[i] == 0xc0)
8681 page_mask |= WDC_C0_PAGE_MASK0x0001;
8682 if (log_page_list[i] == 0xc1)
8683 page_mask |= WDC_C1_PAGE_MASK0x0002;
8684 if (log_page_list[i] == 0xca)
8685 page_mask |= WDC_CA_PAGE_MASK0x0004;
8686 if (log_page_list[i] == 0xd0)
8687 page_mask |= WDC_D0_PAGE_MASK0x0008;
8688 }
8689 }
8690
8691 if (!page_mask)
8692 nvme_show_error("ERROR: WDC: Unknown log page mask - %s", cfg.log_page_mask)nvme_show_message(1, "ERROR: WDC: Unknown log page mask - %s"
, cfg.log_page_mask)
;
8693
8694 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8695
8696 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8697 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8698 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8699 ret = -1;
8700 goto out;
8701 }
8702
8703 if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) == WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) &&
8704 (page_mask & WDC_C0_PAGE_MASK0x0001)) {
8705 /* Get 0xC0 log page if possible. */
8706 if (!wdc_is_sn861(device_id)) {
8707 ret = wdc_get_c0_log_page(ctx, hdl,
8708 nvme_args.output_format,
8709 uuid_index, cfg.namespace_id);
8710 if (ret)
8711 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8712 "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n",nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8713 ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
;
8714 } else {
8715 fmt = nvme_args.output_flags;
8716
8717 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
8718 0,
8719 NVME_NSID_ALL,
8720 fmt);
8721 }
8722 }
8723 if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) == (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) &&
8724 (page_mask & WDC_CA_PAGE_MASK0x0004) &&
8725 (!wdc_is_sn861(device_id))) {
8726 /* Get the CA Log Page */
8727 ret = wdc_get_ca_log_page(ctx, hdl, nvme_args.output_format);
8728 if (ret)
8729 nvme_show_error("ERROR: WDC: Failure reading the CA Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the CA Log Page, ret = %d"
, ret)
;
8730 }
8731 if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) == WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) &&
8732 (page_mask & WDC_C1_PAGE_MASK0x0002)) {
8733 /* Get the C1 Log Page */
8734 ret = wdc_get_c1_log_page(ctx, hdl, nvme_args.output_format,
8735 cfg.interval);
8736 if (ret)
8737 nvme_show_error("ERROR: WDC: Failure reading the C1 Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C1 Log Page, ret = %d"
, ret)
;
8738 }
8739 if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) == WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) &&
8740 (page_mask & WDC_D0_PAGE_MASK0x0008)) {
8741 /* Get the D0 Log Page */
8742 ret = wdc_get_d0_log_page(ctx, hdl, nvme_args.output_format);
8743 if (ret)
8744 nvme_show_error("ERROR: WDC: Failure reading the D0 Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the D0 Log Page, ret = %d"
, ret)
;
8745 }
8746
8747out:
8748 return ret;
8749}
8750
8751static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd,
8752 struct plugin *plugin)
8753{
8754 const char *desc = "Retrieve customer unique smart log statistics.";
8755 const char *uuid_index = "The uuid index to select the correct log page implementation.";
8756 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8757 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8758 struct libnvme_passthru_cmd cmd;
8759 int ret = 0;
8760 __u64 capabilities = 0;
8761 uint32_t read_device_id = 0, read_vendor_id;
8762 nvme_print_flags_t fmt;
8763 __u8 *data;
8764
8765 struct config {
8766 __u32 uuid_index;
8767 };
8768
8769 struct config cfg = {
8770 .uuid_index = 0,
8771 };
8772
8773 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8774 OPT_UINT("uuid-index", 'u', &cfg.uuid_index, uuid_index){"uuid-index", 'u', "NUM", CFG_POSITIVE, _Generic(&cfg.uuid_index
, uint32_t * : (&cfg.uuid_index)), ARGCONFIG_ARG_REQUIRED
, uuid_index, 0, }
,
8775 OPT_END(){ ((void*)0) }
8776 };
8777
8778 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8779 if (ret)
8780 return ret;
8781
8782 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8783 if (ret)
8784 return ret;
8785
8786 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8787 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8788 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8789 ret = -1;
8790 goto out;
8791 }
8792
8793 if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) == WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) {
8794 if (!wdc_check_device(ctx, hdl))
8795 return -1;
8796
8797 fmt = nvme_args.output_flags;
8798
8799 /* verify the 0xCA log page is supported */
8800 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8801 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
8802 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
8803 return -1;
8804 }
8805
8806 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8807 if (ret) {
8808 nvme_show_error("ERROR: WDC: failed to read PCI IDs: %s", libnvme_strerror(-ret))nvme_show_message(1, "ERROR: WDC: failed to read PCI IDs: %s"
, libnvme_strerror(-ret))
;
8809 return ret;
8810 }
8811
8812 switch (read_device_id) {
8813 case WDC_NVME_SN861_DEV_ID0x2750:
8814 case WDC_NVME_SN861_DEV_ID_10x2751:
8815 data = (__u8 *)malloc(WDC_BD_CA_LOG_BUF_LEN0xA0);
8816 if (!data) {
8817 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8818 ret = -1;
8819 break;
8820 }
8821
8822 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
8823
8824 /* Get the CA Log Page */
8825 nvme_init_get_log(&cmd, NVME_NSID_ALL,
8826 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0,
8827 NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN0xA0);
8828 cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8829 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8830 NVME_LOG_CDW14_UUID_MASK)(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
8831 ret = libnvme_get_log(hdl, &cmd, false0,
8832 NVME_LOG_PAGE_PDU_SIZE4096);
8833
8834 if (strcmp(nvme_args.output_format, "json"))
8835 nvme_show_status(ret);
8836
8837 if (!ret) {
8838 /* parse the data */
8839 ret = wdc_print_bd_ca_log(hdl, data, fmt);
8840 } else {
8841 nvme_show_error("ERROR: WDC: Unable to read CA Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read CA Log Page data"
)
;
8842 ret = -1;
8843 }
8844
8845 free(data);
8846 break;
8847 default:
8848 nvme_show_error("ERROR: WDC: Command not supported on this device")nvme_show_message(1, "ERROR: WDC: Command not supported on this device"
)
;
8849 ret = -1;
8850 }
8851 } else {
8852 nvme_show_error("ERROR: WDC: CA log page supported on this device")nvme_show_message(1, "ERROR: WDC: CA log page supported on this device"
)
;
8853 ret = -1;
8854 }
8855
8856out:
8857 return ret;
8858}
8859
8860static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd,
8861 struct plugin *plugin)
8862{
8863 const char *desc = "Retrieve Cloud Log Smart/Health Information";
8864 const char *namespace_id = "desired namespace id";
8865 nvme_print_flags_t fmt;
8866 __u64 capabilities = 0;
8867 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8868 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8869 int ret;
8870 __u8 *data;
8871
8872 struct config {
8873 char *output_format;
8874 __u32 namespace_id;
8875 };
8876
8877 struct config cfg = {
8878 .output_format = "normal",
8879 .namespace_id = NVME_NSID_ALL,
8880 };
8881
8882 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8883 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
8884 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
8885 OPT_END(){ ((void*)0) }
8886 };
8887
8888 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8889 if (ret)
8890 return ret;
8891
8892 cfg.output_format = nvme_args.output_format;
8893
8894 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8895 if (ret)
8896 return ret;
8897
8898 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8899
8900 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
8901 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8902 ret = -1;
8903 goto out;
8904 }
8905
8906 data = NULL((void*)0);
8907 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8908 cfg.namespace_id);
8909
8910 if (strcmp(cfg.output_format, "json"))
8911 nvme_show_status(ret);
8912
8913 if (!ret) {
8914 ret = validate_output_format(cfg.output_format, &fmt);
8915 if (ret < 0) {
8916 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8917 } else {
8918 /* parse the data */
8919 wdc_print_ext_smart_cloud_log(data, fmt);
8920 }
8921 } else {
8922 nvme_show_error("ERROR: WDC: Unable to read C0 Log Page V1 data")nvme_show_message(1, "ERROR: WDC: Unable to read C0 Log Page V1 data"
)
;
8923 ret = -1;
8924 }
8925
8926 free(data);
8927
8928out:
8929 return ret;
8930}
8931
8932static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd,
8933 struct plugin *plugin)
8934{
8935 const char *desc = "Retrieve Hardware Revision Log Information";
8936 const char *namespace_id = "desired namespace id";
8937 nvme_print_flags_t fmt;
8938 __u64 capabilities = 0;
8939 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle)))
8940 struct libnvme_transport_handle *hdl = NULL((void*)0);
8941 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8942 __cleanup_free__attribute__((cleanup(shr_freep))) __u8 *data = NULL((void*)0);
8943 int ret;
8944
8945 struct config {
8946 char *output_format;
8947 __u32 namespace_id;
8948 };
8949
8950 struct config cfg = {
8951 .output_format = "normal",
8952 .namespace_id = NVME_NSID_ALL,
8953 };
8954
8955 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8956 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
8957 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
8958 OPT_END(){ ((void*)0) }
8959 };
8960
8961 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8962 if (ret)
8963 return ret;
8964
8965 cfg.output_format = nvme_args.output_format;
8966
8967 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8968 if (ret)
8969 return ret;
8970
8971 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8972
8973 if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000)) {
8974 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8975 ret = -1;
8976 goto out;
8977 }
8978
8979 ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id);
8980
8981 if (strcmp(cfg.output_format, "json"))
8982 nvme_show_status(ret);
8983
8984 if (!ret) {
8985 ret = validate_output_format(cfg.output_format, &fmt);
8986 if (ret < 0) {
8987 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8988 goto out;
8989 }
8990
8991 if (!data) {
8992 nvme_show_error("ERROR: WDC: Invalid buffer to read Hardware Revision log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read Hardware Revision log"
)
;
8993 ret = -1;
8994 goto out;
8995 }
8996 switch (fmt) {
8997 case NORMAL:
8998 wdc_print_hw_rev_log_normal(data);
8999 break;
9000 case JSON:
9001 wdc_print_hw_rev_log_json(data);
9002 break;
9003 default:
9004 break;
9005 }
9006 } else {
9007 nvme_show_error("ERROR: WDC: Unable to read Hardware Revision Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read Hardware Revision Log Page data"
)
;
9008 ret = -1;
9009 }
9010
9011out:
9012 return ret;
9013}
9014
9015static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd,
9016 struct plugin *plugin)
9017{
9018 const char *desc = "Retrieve Device Write Amplication Factor";
9019 const char *namespace_id = "desired namespace id";
9020 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9021 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9022 struct nvme_smart_log smart_log;
9023 nvme_print_flags_t fmt;
9024 __u8 *data;
9025 int ret = 0;
9026 __u64 capabilities = 0;
9027 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr;
9028 long double data_units_written = 0,
9029 phys_media_units_written_tlc = 0,
9030 phys_media_units_written_slc = 0;
9031 struct json_object *root = NULL((void*)0);
9032 char tlc_waf_str[32] = { 0 },
9033 slc_waf_str[32] = { 0 };
9034
9035 struct config {
9036 char *output_format;
9037 __u32 namespace_id;
9038 };
9039
9040 struct config cfg = {
9041 .output_format = "normal",
9042 .namespace_id = NVME_NSID_ALL,
9043 };
9044
9045 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9046 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
9047 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
9048 OPT_END(){ ((void*)0) }
9049 };
9050
9051 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9052 if (ret)
9053 return ret;
9054
9055 cfg.output_format = nvme_args.output_format;
9056
9057 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9058 if (ret)
9059 return ret;
9060
9061 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9062
9063 if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000)) {
9064 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9065 ret = -1;
9066 goto out;
9067 }
9068
9069 /* get data units written from the smart log page */
9070 ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log);
9071 if (!ret) {
9072 data_units_written = int128_to_double(smart_log.data_units_written);
9073 } else if (ret > 0) {
9074 nvme_show_status(ret);
9075 ret = -1;
9076 goto out;
9077 } else {
9078 nvme_show_error("smart log: %s", libnvme_strerror(-ret))nvme_show_message(1, "smart log: %s", libnvme_strerror(-ret));
9079 ret = -1;
9080 goto out;
9081 }
9082
9083 /* get Physical Media Units Written from extended smart/C0 log page */
9084 data = NULL((void*)0);
9085 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
9086 cfg.namespace_id);
9087
9088 if (!ret) {
9089 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
9090 phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
9091 phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
9092
9093 free(data);
9094 } else {
9095 nvme_show_error("ERROR: WDC %s: get smart cloud log failure", __func__)nvme_show_message(1, "ERROR: WDC %s: get smart cloud log failure"
, __func__)
;
9096 ret = -1;
9097 goto out;
9098 }
9099
9100 if (strcmp(cfg.output_format, "json"))
9101 nvme_show_status(ret);
9102
9103 ret = validate_output_format(cfg.output_format, &fmt);
9104 if (ret < 0) {
9105 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
9106 goto out;
9107 }
9108
9109 if (!data_units_written) {
9110 nvme_show_error("ERROR: WDC %s: 0 data units written", __func__)nvme_show_message(1, "ERROR: WDC %s: 0 data units written", __func__
)
;
9111 ret = -1;
9112 goto out;
9113 }
9114
9115 if (fmt == NORMAL) {
9116 printf("Device Write Amplification Factor TLC : %4.2Lf\n",
9117 (phys_media_units_written_tlc/data_units_written));
9118 printf("Device Write Amplification Factor SLC : %4.2Lf\n",
9119 (phys_media_units_written_slc/data_units_written));
9120 } else if (fmt == JSON) {
9121 root = json_create_object()json_object_new_object();
9122 snprintf(tlc_waf_str, sizeof(tlc_waf_str), "%4.2Lf",
9123 (phys_media_units_written_tlc/data_units_written));
9124 snprintf(slc_waf_str, sizeof(slc_waf_str), "%4.2Lf",
9125 (phys_media_units_written_slc/data_units_written));
9126
9127 json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
9128 json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
9129
9130 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
9131 printf("\n");
9132
9133 json_free_object(root)json_object_put(root);
9134 }
9135
9136out:
9137 return ret;
9138}
9139
9140static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd,
9141 struct plugin *plugin)
9142{
9143 const char *desc = "Retrieve latency monitor log data.";
9144 __u64 capabilities = 0;
9145 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9146 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9147 int ret = 0;
9148
9149 struct config {
9150 char *output_format;
9151 };
9152
9153 struct config cfg = {
9154 .output_format = "normal",
9155 };
9156
9157 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9158 OPT_END(){ ((void*)0) }
9159 };
9160
9161 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9162 if (ret)
9163 return ret;
9164
9165 cfg.output_format = nvme_args.output_format;
9166
9167 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9168 if (ret)
9169 return ret;
9170 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9171
9172 if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000)) {
9173 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9174 ret = -1;
9175 goto out;
9176 }
9177
9178 ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format);
9179 if (ret)
9180 nvme_show_error("ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d"
, ret)
;
9181
9182out:
9183 return ret;
9184}
9185
9186static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd,
9187 struct plugin *plugin)
9188{
9189 const char *desc = "Retrieve error recovery log data.";
9190 __u64 capabilities = 0;
9191 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9192 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9193 int ret = 0;
9194
9195 struct config {
9196 char *output_format;
9197 };
9198
9199 struct config cfg = {
9200 .output_format = "normal",
9201 };
9202
9203 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9204 OPT_END(){ ((void*)0) }
9205 };
9206
9207 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9208 if (ret)
9209 return ret;
9210
9211 cfg.output_format = nvme_args.output_format;
9212
9213 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9214 if (ret)
9215 return ret;
9216
9217 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9218
9219 if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000)) {
9220 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9221 ret = -1;
9222 goto out;
9223 }
9224
9225 ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format);
9226 if (ret)
9227 nvme_show_error("ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x"
, ret)
;
9228
9229out:
9230 return ret;
9231}
9232
9233static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd,
9234 struct plugin *plugin)
9235{
9236 const char *desc = "Retrieve device capabilities log data.";
9237 __u64 capabilities = 0;
9238 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9239 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9240 int ret = 0;
9241
9242 struct config {
9243 char *output_format;
9244 };
9245
9246 struct config cfg = {
9247 .output_format = "normal",
9248 };
9249
9250 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9251 OPT_END(){ ((void*)0) }
9252 };
9253
9254 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9255 if (ret)
9256 return ret;
9257
9258 cfg.output_format = nvme_args.output_format;
9259
9260 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9261 if (ret)
9262 return ret;
9263
9264 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9265
9266 if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000)) {
9267 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9268 ret = -1;
9269 goto out;
9270 }
9271
9272 ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format);
9273 if (ret)
9274 nvme_show_error("ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x"
, ret)
;
9275
9276out:
9277 return ret;
9278}
9279
9280static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd,
9281 struct plugin *plugin)
9282{
9283 const char *desc = "Retrieve unsupported requirements log data.";
9284 __u64 capabilities = 0;
9285 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9286 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9287 int ret = 0;
9288
9289 struct config {
9290 char *output_format;
9291 };
9292
9293 struct config cfg = {
9294 .output_format = "normal",
9295 };
9296
9297 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9298 OPT_END(){ ((void*)0) }
9299 };
9300
9301 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9302 if (ret)
9303 return ret;
9304
9305 cfg.output_format = nvme_args.output_format;
9306
9307 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9308 if (ret)
9309 return ret;
9310
9311 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9312
9313 if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000)) {
9314 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9315 ret = -1;
9316 goto out;
9317 }
9318
9319 ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format);
9320 if (ret)
9321 nvme_show_error("ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x"
, ret)
;
9322
9323out:
9324 return ret;
9325}
9326
9327static int wdc_do_clear_pcie_correctable_errors(struct libnvme_transport_handle *hdl)
9328{
9329 int ret;
9330 struct libnvme_passthru_cmd admin_cmd;
9331
9332 memset(&admin_cmd, 0, sizeof(admin_cmd));
9333 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6;
9334 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
9335 WDC_NVME_CLEAR_PCIE_CORR_CMD0x22);
9336
9337 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9338 nvme_show_status(ret);
9339 return ret;
9340}
9341
9342static int wdc_do_clear_pcie_correctable_errors_vuc(struct libnvme_transport_handle *hdl)
9343{
9344 int ret;
9345 struct libnvme_passthru_cmd admin_cmd;
9346
9347 memset(&admin_cmd, 0, sizeof(admin_cmd));
9348 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2;
9349
9350 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9351 nvme_show_status(ret);
9352 return ret;
9353}
9354
9355static int wdc_do_clear_pcie_correctable_errors_fid(struct libnvme_transport_handle *hdl)
9356{
9357 int ret;
9358 __u64 result;
9359 __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
9360
9361 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3, false0,
9362 value, &result);
9363
9364 nvme_show_status(ret);
9365 return ret;
9366}
9367
9368static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
9369 struct plugin *plugin)
9370{
9371 const char *desc = "Clear PCIE Correctable Errors.";
9372 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9373 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9374 __u64 capabilities = 0;
9375 int ret;
9376
9377 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9378 OPT_END(){ ((void*)0) }
9379 };
9380
9381 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9382 if (ret)
9383 return ret;
9384
9385 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9386 if (ret || !wdc_check_device(ctx, hdl))
9387 return -1;
9388
9389 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9390 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
)) {
9391 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9392 ret = -1;
9393 goto out;
9394 }
9395
9396 if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080)
9397 ret = wdc_do_clear_pcie_correctable_errors(hdl);
9398 else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000)
9399 ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl);
9400 else
9401 ret = wdc_do_clear_pcie_correctable_errors_fid(hdl);
9402
9403out:
9404 return ret;
9405}
9406
9407static int wdc_drive_status(int argc, char **argv, struct command *acmd,
9408 struct plugin *plugin)
9409{
9410 const char *desc = "Get Drive Status.";
9411 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9412 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9413 int ret = 0;
9414 int uuid_index;
9415 void *dev_mng_log = NULL((void*)0);
9416 __u32 system_eol_state;
9417 __u32 user_eol_state;
9418 __u32 format_corrupt_reason = 0xFFFFFFFF;
9419 __u32 eol_status;
9420 __u32 assert_status = 0xFFFFFFFF;
9421 __u32 thermal_status = 0xFFFFFFFF;
9422 __u64 capabilities = 0;
9423 struct nvme_id_uuid_list uuid_list;
9424
9425 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9426 OPT_END(){ ((void*)0) }
9427 };
9428
9429 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9430 if (ret)
9431 return ret;
9432
9433 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9434 if (ret)
9435 return ret;
9436
9437 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9438
9439 if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) != WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) {
9440 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9441 ret = -1;
9442 goto out;
9443 }
9444
9445 uuid_index = 0;
9446
9447 /* Find the WDC UUID index */
9448 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
9449 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
9450 /* check for the Sandisk UUID first */
9451 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
9452
9453 if (uuid_index < 0)
9454 /* The Sandisk UUID is not found;
9455 * check for the WDC UUID second.
9456 */
9457 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
9458 }
9459
9460 /* WD UUID not found, use default uuid index - 0 */
9461 if (uuid_index < 0)
9462 uuid_index = 0;
9463
9464 /* verify the 0xC2 Device Manageability log page is supported */
9465 if (wdc_nvme_check_supported_log_page(ctx, hdl,
9466 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
9467 uuid_index) == false0) {
9468 nvme_show_error("ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d",nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
9469 uuid_index)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
;
9470 ret = -1;
9471 goto out;
9472 }
9473
9474 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
9475 nvme_show_error("ERROR: WDC: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not found");
9476 ret = -1;
9477 goto out;
9478 }
9479
9480 /* Get the assert dump present status */
9481 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &assert_status,
9482 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19))
9483 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9484
9485 /* Get the thermal throttling status */
9486 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &thermal_status,
9487 WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18))
9488 nvme_show_error("ERROR: WDC: Get Thermal Throttling Status Failed")nvme_show_message(1, "ERROR: WDC: Get Thermal Throttling Status Failed"
)
;
9489
9490 /* Get EOL status */
9491 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &eol_status,
9492 WDC_C2_USER_EOL_STATUS_ID0x1A)) {
9493 nvme_show_error("ERROR: WDC: Get User EOL Status Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL Status Failed"
)
;
9494 eol_status = cpu_to_le32(-1);
9495 }
9496
9497 /* Get Customer EOL state */
9498 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &user_eol_state,
9499 WDC_C2_USER_EOL_STATE_ID0x1C))
9500 nvme_show_error("ERROR: WDC: Get User EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL State Failed");
9501
9502 /* Get System EOL state*/
9503 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &system_eol_state,
9504 WDC_C2_SYSTEM_EOL_STATE_ID0x1D))
9505 nvme_show_error("ERROR: WDC: Get System EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get System EOL State Failed"
)
;
9506
9507 /* Get format corrupt reason*/
9508 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &format_corrupt_reason,
9509 WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E))
9510 nvme_show_error("ERROR: WDC: Get Format Corrupt Reason Failed")nvme_show_message(1, "ERROR: WDC: Get Format Corrupt Reason Failed"
)
;
9511
9512 printf(" Drive Status :-\n");
9513 if ((int)le32_to_cpu(eol_status) >= 0)
9514 printf(" Percent Used: %"PRIu32"u""%%\n",
9515 le32_to_cpu(eol_status));
9516 else
9517 printf(" Percent Used: Unknown\n");
9518 if (system_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) && user_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000))
9519 printf(" Drive Life Status: Normal\n");
9520 else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) ||
9521 user_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001))
9522 printf(" Drive Life Status: End Of Life\n");
9523 else if (system_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) ||
9524 user_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002))
9525 printf(" Drive Life Status: Read Only\n");
9526 else
9527 printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n",
9528 le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state));
9529
9530 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001))
9531 printf(" Assert Dump Status: Present\n");
9532 else if (assert_status == WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000))
9533 printf(" Assert Dump Status: Not Present\n");
9534 else
9535 printf(" Assert Dump Status: Unknown : 0x%08x\n", le32_to_cpu(assert_status));
9536
9537 if (thermal_status == WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000))
9538 printf(" Thermal Throttling Status: Off\n");
9539 else if (thermal_status == WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001))
9540 printf(" Thermal Throttling Status: On\n");
9541 else if (thermal_status == WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002))
9542 printf(" Thermal Throttling Status: Unavailable\n");
9543 else
9544 printf(" Thermal Throttling Status: Unknown : 0x%08x\n", le32_to_cpu(thermal_status));
9545
9546 if (format_corrupt_reason == WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000))
9547 printf(" Format Corrupt Reason: Format Not Corrupted\n");
9548 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001))
9549 printf(" Format Corrupt Reason: Format Corrupt due to FW Assert\n");
9550 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF))
9551 printf(" Format Corrupt Reason: Format Corrupt for Unknown Reason\n");
9552 else
9553 printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
9554
9555 free(dev_mng_log);
9556out:
9557 return ret;
9558}
9559
9560static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
9561 struct plugin *plugin)
9562{
9563 const char *desc = "Clear Assert Dump Present Status.";
9564 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9565 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9566 int ret = -1;
9567 __le32 assert_status = cpu_to_le32(0xFFFFFFFF);
9568 __u64 capabilities = 0;
9569 struct libnvme_passthru_cmd admin_cmd;
9570
9571 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9572 OPT_END(){ ((void*)0) }
9573 };
9574
9575 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9576 if (ret)
9577 return ret;
9578
9579 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9580 if (ret)
9581 return ret;
9582
9583 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9584
9585 if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) != WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) {
9586 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9587 ret = -1;
9588 goto out;
9589 }
9590 if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status,
9591 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19)) {
9592 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9593 ret = -1;
9594 goto out;
9595 }
9596
9597 /* Get the assert dump present status */
9598 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001)) {
9599 memset(&admin_cmd, 0, sizeof(admin_cmd));
9600 admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8;
9601 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9602 WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03);
9603
9604 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9605 nvme_show_status(ret);
9606 } else
9607 nvme_show_error("INFO: WDC: No Assert Dump Present")nvme_show_message(1, "INFO: WDC: No Assert Dump Present");
9608
9609out:
9610 return ret;
9611}
9612
9613static int wdc_get_fw_act_history(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9614 char *format)
9615{
9616 struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
9617 nvme_print_flags_t fmt;
9618 int ret;
9619 __u8 *data;
9620
9621 if (!wdc_check_device(ctx, hdl))
9622 return -1;
9623
9624 ret = validate_output_format(format, &fmt);
9625 if (ret < 0) {
9626 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9627 return ret;
9628 }
9629
9630 /* verify the FW Activate History log page is supported */
9631 if (!wdc_nvme_check_supported_log_page(ctx, hdl,
9632 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) {
9633 nvme_show_error("ERROR: WDC: %d Log Page not supported",nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
9634 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
;
9635 return -1;
9636 }
9637
9638 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9639 if (!data) {
9640 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9641 return -1;
9642 }
9643
9644 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9645
9646 ret = nvme_get_log_simple(hdl,
9647 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB,
9648 data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9649
9650 if (strcmp(format, "json"))
9651 nvme_show_status(ret);
9652
9653 if (!ret) {
9654 /* parse the data */
9655 fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data);
9656
9657 if ((fw_act_history_hdr->num_entries > 0) &&
9658 (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES20)) {
9659 ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries,
9660 fmt, 0, 0, 0);
9661 } else if (!fw_act_history_hdr->num_entries) {
9662 nvme_show_error("INFO: WDC: No FW Activate History entries found.")nvme_show_message(1, "INFO: WDC: No FW Activate History entries found."
)
;
9663 ret = 0;
9664 } else {
9665 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
9666 "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n",nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
9667 fw_act_history_hdr->num_entries)nvme_show_message(1, "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n"
, fw_act_history_hdr->num_entries)
;
9668 ret = -1;
9669 }
9670 } else {
9671 nvme_show_error("ERROR: WDC: Unable to read FW Activate History Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read FW Activate History Log Page data"
)
;
9672 ret = -1;
9673 }
9674
9675 free(data);
9676 return ret;
9677}
9678
9679static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
9680{
9681
9682 __u32 cust_id = WDC_INVALID_CUSTOMER_ID-1;
9683 __u32 *cust_id_ptr = NULL((void*)0);
9684
9685 if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID0x15,
9686 (void *)&cust_id_ptr, NULL((void*)0)))
9687 nvme_show_error("%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found",nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
9688 __func__, WDC_C2_CUSTOMER_ID_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
;
9689 else
9690 cust_id = *cust_id_ptr;
9691
9692 free(cust_id_ptr);
9693 return cust_id;
9694}
9695
9696static int wdc_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9697 char *format)
9698{
9699 struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
9700 __u32 tot_entries = 0, num_entries = 0;
9701 __u32 vendor_id = 0, device_id = 0;
9702 __u32 cust_id = 0;
9703 nvme_print_flags_t fmt;
9704 __u8 *data;
9705 int ret;
9706 bool_Bool c2GuidMatch = false0;
9707
9708 if (!wdc_check_device(ctx, hdl))
9709 return -1;
9710
9711 ret = validate_output_format(format, &fmt);
9712 if (ret < 0) {
9713 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9714 return ret;
9715 }
9716
9717 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
9718
9719 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9720 if (!data) {
9721 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9722 return -1;
9723 }
9724
9725 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9726
9727 ret = nvme_get_log_simple(hdl,
9728 WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
9729 data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9730
9731 if (strcmp(format, "json"))
9732 nvme_show_status(ret);
9733
9734 if (!ret) {
9735 /* Get the log page data and verify the GUID */
9736 fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data);
9737
9738 c2GuidMatch = !memcmp(ocp_C2_guid,
9739 fw_act_history_log->log_page_guid,
9740 WDC_C2_GUID_LENGTH16);
9741
9742 if (c2GuidMatch) {
9743 /* parse the data */
9744 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
9745
9746 if (tot_entries > 0) {
9747 /* get the FW customer id */
9748 if (!wdc_is_sn861(device_id)) {
9749 cust_id = wdc_get_fw_cust_id(ctx, hdl);
9750 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
9751 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9752 "%s: ERROR: WDC: invalid customer id\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9753 __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
;
9754 ret = -1;
9755 goto freeData;
9756 }
9757 }
9758 num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES20) ?
9759 tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES20;
9760 ret = wdc_print_fw_act_history_log(data, num_entries,
9761 fmt, cust_id, vendor_id, device_id);
9762 } else {
9763 nvme_show_error("INFO: WDC: No entries found.")nvme_show_message(1, "INFO: WDC: No entries found.");
9764 ret = 0;
9765 }
9766 } else {
9767 nvme_show_error("ERROR: WDC: Invalid C2 log page GUID")nvme_show_message(1, "ERROR: WDC: Invalid C2 log page GUID");
9768 ret = -1;
9769 }
9770 } else {
9771 nvme_show_error("ERROR: WDC: Unable to read FW Activate History Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read FW Activate History Log Page data"
)
;
9772 ret = -1;
9773 }
9774
9775freeData:
9776 free(data);
9777 return ret;
9778}
9779
9780static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd,
9781 struct plugin *plugin)
9782{
9783 const char *desc = "Retrieve FW activate history table.";
9784 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9785 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9786 int ret;
9787
9788 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9789 OPT_END(){ ((void*)0) }
9790 };
9791
9792 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9793 if (ret)
9794 return ret;
9795
9796 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9797 if (ret)
9798 return ret;
9799
9800 return run_wdc_vs_fw_activate_history(ctx, hdl);
9801}
9802
9803int run_wdc_vs_fw_activate_history(struct libnvme_global_ctx *ctx,
9804 struct libnvme_transport_handle *hdl)
9805{
9806 char *output_format = nvme_args.output_format;
9807 __u64 capabilities = 0;
9808 int ret = -1;
9809
9810 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9811
9812 if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000))) {
9813 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9814 ret = -1;
9815 goto out;
9816 }
9817
9818 if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000) {
9819 __u32 cust_fw_id = 0;
9820 /* get the FW customer id */
9821 cust_fw_id = wdc_get_fw_cust_id(ctx, hdl);
9822 if (cust_fw_id == WDC_INVALID_CUSTOMER_ID-1) {
9823 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
9824 ret = -1;
9825 goto out;
9826 }
9827
9828 if ((cust_fw_id == WDC_CUSTOMER_ID_0x10040x1004) ||
9829 (cust_fw_id == WDC_CUSTOMER_ID_0x10080x1008) ||
9830 (cust_fw_id == WDC_CUSTOMER_ID_0x10050x1005) ||
9831 (cust_fw_id == WDC_CUSTOMER_ID_0x13040x1304))
9832 ret = wdc_get_fw_act_history_C2(ctx, hdl,
9833 output_format);
9834 else
9835 ret = wdc_get_fw_act_history(ctx, hdl, output_format);
9836 } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
9837 ret = wdc_get_fw_act_history_C2(ctx, hdl, output_format);
9838 }
9839
9840 if (ret)
9841 nvme_show_error("ERROR: WDC: Failure reading the FW Activate History, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading the FW Activate History, ret = %d"
, ret)
;
9842out:
9843 return ret;
9844}
9845
9846static int wdc_do_clear_fw_activate_history_vuc(struct libnvme_transport_handle *hdl)
9847{
9848 int ret = -1;
9849 struct libnvme_passthru_cmd admin_cmd;
9850
9851 memset(&admin_cmd, 0, sizeof(admin_cmd));
9852 admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6;
9853 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9854 WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23);
9855
9856 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9857 nvme_show_status(ret);
9858
9859 return ret;
9860}
9861
9862static int wdc_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
9863{
9864 int ret = -1;
9865 __u64 result;
9866 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
9867
9868 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, false0,
9869 value, &result);
9870
9871 nvme_show_status(ret);
9872 return ret;
9873}
9874
9875static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd,
9876 struct plugin *plugin)
9877{
9878 const char *desc = "Clear FW activate history table.";
9879 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9880 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9881 int ret;
9882
9883 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9884 OPT_END(){ ((void*)0) }
9885 };
9886
9887 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9888 if (ret)
9889 return ret;
9890
9891 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9892 if (ret)
9893 return ret;
9894
9895 return run_wdc_clear_fw_activate_history(ctx, hdl);
9896}
9897
9898int run_wdc_clear_fw_activate_history(struct libnvme_global_ctx *ctx,
9899 struct libnvme_transport_handle *hdl)
9900{
9901 __u64 capabilities = 0;
9902 int ret;
9903
9904 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9905
9906 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000))) {
9907 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9908 ret = -1;
9909 goto out;
9910 }
9911
9912 if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000)
9913 ret = wdc_do_clear_fw_activate_history_vuc(hdl);
9914 else
9915 ret = wdc_do_clear_fw_activate_history_fid(hdl);
9916
9917out:
9918 return ret;
9919}
9920
9921static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd,
9922 struct plugin *plugin)
9923{
9924 const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
9925 const char *disable = "Disable controller option of the telemetry log page.";
9926 const char *enable = "Enable controller option of the telemetry log page.";
9927 const char *status = "Displays the current state of the controller initiated log page.";
9928 __u64 capabilities = 0;
9929 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9930 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9931 struct libnvme_passthru_cmd cmd;
9932 __u64 result;
9933 int ret = -1;
9934
9935
9936 struct config {
9937 bool_Bool disable;
9938 bool_Bool enable;
9939 bool_Bool status;
9940 };
9941
9942 struct config cfg = {
9943 .disable = false0,
9944 .enable = false0,
9945 .status = false0,
9946 };
9947
9948 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9949 OPT_FLAG("disable", 'd', &cfg.disable, disable){"disable", 'd', ((void*)0), CFG_FLAG, _Generic(&cfg.disable
, _Bool * : (&cfg.disable)), ARGCONFIG_ARG_NONE, disable,
0, }
,
9950 OPT_FLAG("enable", 'e', &cfg.enable, enable){"enable", 'e', ((void*)0), CFG_FLAG, _Generic(&cfg.enable
, _Bool * : (&cfg.enable)), ARGCONFIG_ARG_NONE, enable, 0
, }
,
9951 OPT_FLAG("status", 's', &cfg.status, status){"status", 's', ((void*)0), CFG_FLAG, _Generic(&cfg.status
, _Bool * : (&cfg.status)), ARGCONFIG_ARG_NONE, status, 0
, }
,
9952 OPT_END(){ ((void*)0) }
9953 };
9954
9955 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9956 if (ret)
9957 return ret;
9958
9959 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9960 if (ret)
9961 return ret;
9962
9963 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9964
9965 if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) {
9966 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9967 ret = -1;
9968 goto out;
9969 }
9970
9971 /* allow only one option at a time */
9972 if ((cfg.disable + cfg.enable + cfg.status) > 1) {
9973
9974 nvme_show_error("ERROR: WDC: Invalid option")nvme_show_message(1, "ERROR: WDC: Invalid option");
9975 ret = -1;
9976 goto out;
9977 }
9978
9979 if (cfg.disable) {
9980 ret = nvme_set_features_simple(hdl, 0,
9981 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9982 false0, 1, &result);
9983
9984 wdc_clear_reason_id(hdl);
9985 } else {
9986 if (cfg.enable) {
9987 ret = nvme_set_features_simple(hdl, 0,
9988 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9989 false0, 0, &result);
9990 } else if (cfg.status) {
9991 nvme_init_get_features(&cmd,
9992 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9993 NVME_GET_FEATURES_SEL_CURRENT);
9994 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9995 result = cmd.result;
9996 if (!ret) {
9997 if (result)
9998 nvme_show_error("Controller Option Telemetry Log Page State: Disabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Disabled"
)
;
9999 else
10000 nvme_show_error("Controller Option Telemetry Log Page State: Enabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Enabled"
)
;
10001 } else {
10002 nvme_show_status(ret);
10003 }
10004 } else {
10005 nvme_show_error("ERROR: WDC: unsupported option for this command")nvme_show_message(1, "ERROR: WDC: unsupported option for this command"
)
;
10006 nvme_show_error("Please provide an option, -d, -e or -s")nvme_show_message(1, "Please provide an option, -d, -e or -s"
)
;
10007 ret = -1;
10008 goto out;
10009 }
10010 }
10011
10012out:
10013 return ret;
10014}
10015
10016
10017static int wdc_get_serial_and_fw_rev(struct libnvme_transport_handle *hdl, char *sn, char *fw_rev)
10018{
10019 struct libnvme_passthru_cmd cmd;
10020 struct nvme_id_ctrl ctrl;
10021 int ret;
10022 int i;
10023
10024 i = sizeof(ctrl.sn) - 1;
10025 memset(sn, 0, WDC_SERIAL_NO_LEN20);
10026 memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN9);
10027 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10028 nvme_init_identify_ctrl(&cmd, &ctrl);
10029 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10030 if (ret) {
10031 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
10032 return -1;
10033 }
10034 /* Remove trailing spaces from the name */
10035 while (i && ctrl.sn[i] == ' ') {
10036 ctrl.sn[i] = '\0';
10037 i--;
10038 }
10039 snprintf(sn, WDC_SERIAL_NO_LEN20, "%s", ctrl.sn);
10040 snprintf(fw_rev, WDC_NVME_FIRMWARE_REV_LEN9, "%s", ctrl.fr);
10041
10042 return 0;
10043}
10044
10045static int wdc_get_max_transfer_len(struct libnvme_transport_handle *hdl, __u32 *maxTransferLen)
10046{
10047 struct libnvme_passthru_cmd cmd;
10048 struct nvme_id_ctrl ctrl;
10049 int ret = 0;
10050
10051 __u32 maxTransferLenDevice = 0;
10052
10053 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10054 nvme_init_identify_ctrl(&cmd, &ctrl);
10055 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10056 if (ret) {
10057 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
10058 return -1;
10059 }
10060
10061 maxTransferLenDevice = (1 << ctrl.mdts) * shr_getpagesize();
10062 *maxTransferLen = maxTransferLenDevice;
10063
10064 return ret;
10065}
10066
10067static int wdc_de_VU_read_size(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize)
10068{
10069 int ret = WDC_STATUS_FAILURE-1;
10070 struct libnvme_passthru_cmd cmd;
10071
10072 if (!logSize) {
10073 ret = WDC_STATUS_INVALID_PARAMETER-3;
10074 goto end;
10075 }
10076
10077 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
10078 cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE0xC0;
10079 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
10080 cmd.cdw13 = fileId << 16;
10081 cmd.cdw14 = spiDestn;
10082
10083 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10084
10085 if (!ret && logSize)
10086 *logSize = cmd.result;
10087 if (ret != WDC_STATUS_SUCCESS0) {
10088 nvme_show_error("ERROR: WDC: VUReadSize() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadSize() failed, ");
10089 nvme_show_status(ret);
10090 }
10091
10092end:
10093 return ret;
10094}
10095
10096static int wdc_de_VU_read_buffer(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn,
10097 __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize)
10098{
10099 int ret = WDC_STATUS_FAILURE-1;
10100 struct libnvme_passthru_cmd cmd;
10101 __u32 noOfDwordExpected = 0;
10102
10103 if (!dataBuffer || !bufferSize) {
10104 ret = WDC_STATUS_INVALID_PARAMETER-3;
10105 goto end;
10106 }
10107
10108 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
10109 noOfDwordExpected = *bufferSize / sizeof(__u32);
10110 cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE0xC2;
10111 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
10112 cmd.cdw10 = noOfDwordExpected;
10113 cmd.cdw13 = fileId << 16;
10114 cmd.cdw14 = spiDestn;
10115 cmd.cdw15 = offsetInDwords;
10116
10117 cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
10118 cmd.data_len = *bufferSize;
10119
10120 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10121
10122 if (ret != WDC_STATUS_SUCCESS0) {
10123 nvme_show_error("ERROR: WDC: VUReadBuffer() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadBuffer() failed, ");
10124 nvme_show_status(ret);
10125 }
10126
10127end:
10128 return ret;
10129}
10130
10131static int wdc_get_log_dir_max_entries(struct libnvme_transport_handle *hdl, __u32 *maxNumOfEntries)
10132{
10133 int ret = WDC_STATUS_FAILURE-1;
10134 __u32 headerPayloadSize = 0;
10135 __u8 *fileIdOffsetsBuffer = NULL((void*)0);
10136 __u32 fileIdOffsetsBufferSize = 0;
10137 __u32 fileNum = 0;
10138 __u16 fileOffset = 0;
10139
10140
10141 if (!maxNumOfEntries) {
10142 ret = WDC_STATUS_INVALID_PARAMETER-3;
10143 return ret;
10144 }
10145 /* 1.Get log directory first four bytes */
10146 ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize);
10147 if (ret != WDC_STATUS_SUCCESS0) {
10148 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
10149 "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
10150 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
;
10151 return ret;
10152 }
10153
10154 fileIdOffsetsBufferSize =
10155 WDC_DE_FILE_HEADER_SIZE4 + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE2);
10156 fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize);
10157
10158 /* 2.Read to get file offsets */
10159 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize);
10160 if (ret != WDC_STATUS_SUCCESS0) {
10161 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
10162 "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
10163 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
;
10164 goto end;
10165 }
10166 /* 3.Determine valid entries */
10167 for (fileNum = 0;
10168 fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
10169 fileNum++) {
10170 fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
10171 (fileNum * WDC_DE_FILE_OFFSET_SIZE2)] << 8) +
10172 fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
10173 (fileNum * WDC_DE_FILE_OFFSET_SIZE2) + 1];
10174 if (!fileOffset)
10175 continue;
10176 (*maxNumOfEntries)++;
10177 }
10178
10179end:
10180 free(fileIdOffsetsBuffer);
10181 return ret;
10182}
10183
10184static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[])
10185{
10186 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE;
10187
10188 if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME"core_dump"))
10189 essentialType = WDC_DE_TYPE_DUMPSNAPSHOT;
10190 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME"event_log"))
10191 essentialType = WDC_DE_TYPE_EVENTLOG;
10192 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info"))
10193 essentialType = WDC_DE_TYPE_NVME_MANF_INFO;
10194
10195 return essentialType;
10196}
10197
10198static int wdc_fetch_log_directory(struct libnvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory)
10199{
10200 int ret = WDC_STATUS_FAILURE-1;
10201 __u8 *fileOffset = NULL((void*)0);
10202 __u8 *fileDirectory = NULL((void*)0);
10203 __u32 headerSize = 0;
10204 __u32 fileNum = 0, startIdx = 0;
10205 __u16 fileOffsetTemp = 0;
10206 __u32 entryId = 0;
10207 __u32 fileDirectorySize = 0;
10208
10209 if (!directory) {
10210 ret = WDC_STATUS_INVALID_PARAMETER-3;
10211 goto end;
10212 }
10213
10214 ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize);
10215 if (ret != WDC_STATUS_SUCCESS0) {
10216 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
10217 "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n",nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
10218 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
;
10219 goto end;
10220 }
10221
10222 fileDirectory = (__u8 *)calloc(1, fileDirectorySize);
10223 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize);
10224 if (ret != WDC_STATUS_SUCCESS0) {
10225 nvme_show_error("ERROR: WDC: %s: Failed to get filesystem directory, ret = %d",nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
10226 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
;
10227 goto end;
10228 }
10229
10230 /* First four bytes of header directory is headerSize */
10231 memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE4);
10232
10233 /* headerSize describes the offset table inside fileDirectory */
10234 if (headerSize < WDC_DE_FILE_HEADER_SIZE4 || headerSize > fileDirectorySize) {
10235 nvme_show_error("ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n",nvme_show_message(1, "ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n"
, __func__, headerSize, fileDirectorySize)
10236 __func__, headerSize, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n"
, __func__, headerSize, fileDirectorySize)
;
10237 ret = WDC_STATUS_FAILURE-1;
10238 goto end;
10239 }
10240
10241 /* minimum buffer for 1 entry is required */
10242 if (!directory->maxNumLogEntries) {
10243 ret = WDC_STATUS_INVALID_PARAMETER-3;
10244 goto end;
10245 }
10246
10247 for (fileNum = 0;
10248 fileNum < (headerSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
10249 fileNum++) {
10250 if (entryId >= directory->maxNumLogEntries)
10251 break;
10252
10253 startIdx = WDC_DE_FILE_HEADER_SIZE4 + (fileNum * WDC_DE_FILE_OFFSET_SIZE2);
10254 memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp));
10255 fileOffset = fileDirectory + fileOffsetTemp;
10256
10257 if (!fileOffsetTemp)
10258 continue;
10259
10260 if (fileOffsetTemp + sizeof(struct WDC_DE_VU_FILE_META_DATA) > fileDirectorySize) {
10261 nvme_show_error("ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n",nvme_show_message(1, "ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n"
, __func__, fileOffsetTemp, fileDirectorySize)
10262 __func__, fileOffsetTemp, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n"
, __func__, fileOffsetTemp, fileDirectorySize)
;
10263 ret = WDC_STATUS_FAILURE-1;
10264 goto end;
10265 }
10266
10267 memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS));
10268 memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA));
10269 directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE32 - 1] = '\0';
10270 wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName,
10271 WDC_DE_FILE_NAME_SIZE32, ' ');
10272 if (!directory->logEntry[entryId].metaData.fileID)
10273 continue;
10274
10275 directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName);
10276 entryId++;
10277 }
10278
10279 directory->numOfValidLogEntries = entryId;
10280
10281end:
10282 free(fileDirectory);
10283 return ret;
10284}
10285
10286static int wdc_fetch_log_file_from_device(struct libnvme_transport_handle *hdl, __u32 fileId,
10287 __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
10288{
10289 int ret = WDC_STATUS_FAILURE-1;
10290 __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
10291 __u32 maximumTransferLength = 0;
10292 __u32 buffSize = 0;
10293 __u64 offsetIdx = 0;
10294
10295 if (!dataBuffer || !fileSize) {
10296 ret = WDC_STATUS_INVALID_PARAMETER-3;
10297 goto end;
10298 }
10299
10300 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) {
10301 ret = WDC_STATUS_FAILURE-1;
10302 goto end;
10303 }
10304
10305 /* Fetch Log File Data */
10306 if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) {
10307 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
10308 if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000)
10309 chunckSize = maximumTransferLength;
10310
10311 buffSize = chunckSize;
10312 for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) {
10313 if (((offsetIdx * chunckSize) + buffSize) > fileSize)
10314 buffSize = (__u32)(fileSize - (offsetIdx * chunckSize));
10315 /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */
10316 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
10317 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize);
10318 if (ret != WDC_STATUS_SUCCESS0) {
10319 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
10320 __func__, ret, fileId, (unsigned long)fileSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
;
10321 break;
10322 }
10323 }
10324 } else {
10325 buffSize = (__u32)fileSize;
10326 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
10327 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)),
10328 dataBuffer, &buffSize);
10329 if (ret != WDC_STATUS_SUCCESS0) {
10330 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
10331 __func__, ret, fileId, (unsigned long)fileSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx"
, __func__, ret, fileId, (unsigned long)fileSize)
;
10332 }
10333 }
10334
10335end:
10336 return ret;
10337}
10338
10339static int wdc_de_get_dump_trace(struct libnvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen,
10340 const char *binFileName)
10341{
10342 int ret = WDC_STATUS_FAILURE-1;
10343 __u8 *readBuffer = NULL((void*)0);
10344 __u32 readBufferLen = 0;
10345 __u32 lastPktReadBufferLen = 0;
10346 __u32 maxTransferLen = 0;
10347 __u32 dumptraceSize = 0;
10348 __u32 chunkSize;
10349 __u32 chunks;
10350 __u32 offset;
10351 __u32 i;
10352 __u32 maximumTransferLength = 0;
10353
10354 if (!binFileName || !filePath) {
10355 ret = WDC_STATUS_INVALID_PARAMETER-3;
10356 return ret;
10357 }
10358
10359 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0)
10360 return WDC_STATUS_FAILURE-1;
10361
10362 do {
10363 /* Get dumptrace size */
10364 ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, &dumptraceSize);
10365 if (ret != WDC_STATUS_SUCCESS0) {
10366 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
10367 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
;
10368 break;
10369 }
10370
10371 /* Make sure the size requested is greater than dword */
10372 if (dumptraceSize < 4) {
10373 ret = WDC_STATUS_FAILURE-1;
10374 nvme_show_error("ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x"
, __func__, dumptraceSize)
10375 __func__, dumptraceSize)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x"
, __func__, dumptraceSize)
;
10376 break;
10377 }
10378
10379 /* Choose the least max transfer length */
10380 maxTransferLen = maximumTransferLength < WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 ? maximumTransferLength : WDC_DE_READ_MAX_TRANSFER_SIZE0x8000;
10381
10382 /* Comment from FW Team:
10383 * The max non - block transfer size is 0xFFFF (16 bits allowed as the block size).Use 0x8000
10384 * to keep it on a word - boundary.
10385 * max_xfer = int(pow(2, id_data['MDTS'])) * 4096 # 4k page size as reported in pcie capabiltiies
10386 */
10387 chunkSize = dumptraceSize < maxTransferLen ? dumptraceSize : maxTransferLen;
10388 chunks = (dumptraceSize / maxTransferLen) + ((dumptraceSize % maxTransferLen) ? 1 : 0);
10389
10390 readBuffer = (unsigned char *)calloc(dumptraceSize, sizeof(unsigned char));
10391 readBufferLen = chunkSize;
10392 lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize;
10393
10394 if (!readBuffer) {
10395 nvme_show_error("ERROR: WDC: %s: readBuffer calloc failed", __func__)nvme_show_message(1, "ERROR: WDC: %s: readBuffer calloc failed"
, __func__)
;
10396 ret = WDC_STATUS_INSUFFICIENT_MEMORY-2;
10397 break;
10398 }
10399
10400 for (i = 0; i < chunks; i++) {
10401 offset = (i * chunkSize) / 4;
10402
10403 /* Last loop call, Assign readBufferLen to read only left over bytes */
10404 if (i == (chunks - 1))
10405 readBufferLen = lastPktReadBufferLen;
10406
10407 ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, 0,
10408 readBuffer + offset, &readBufferLen);
10409 if (ret != WDC_STATUS_SUCCESS0) {
10410 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
10411 "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n",nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
10412 __func__, ret, offset)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n"
, __func__, ret, offset)
;
10413 break;
10414 }
10415 }
10416 } while (0);
10417
10418 if (ret == WDC_STATUS_SUCCESS0) {
10419 ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
10420 if (ret != WDC_STATUS_SUCCESS0)
10421 nvme_show_error("ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d",nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
10422 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
;
10423 } else {
10424 nvme_show_error("ERROR: WDC: %s: Read Buffer Loop failed, ret = %d", __func__,nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
10425 ret)nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
;
10426 }
10427
10428 free(readBuffer);
10429
10430 return ret;
10431}
10432
10433int wdc_fetch_vu_file_directory(struct libnvme_transport_handle *hdl,
10434 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList,
10435 __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString)
10436{
10437 int ret = wdc_fetch_log_directory(hdl, &deEssentialsList);
10438 __u32 listIdx;
10439 char *dataBuffer;
10440 char fileName[MAX_PATH_LEN256];
10441
10442 if (ret != WDC_STATUS_SUCCESS0) {
10443 nvme_show_error("WDC: wdc_fetch_log_directory failed, ret = %d", ret)nvme_show_message(1, "WDC: wdc_fetch_log_directory failed, ret = %d"
, ret)
;
10444 return ret;
10445 }
10446
10447 /* Get Debug Data Files */
10448 for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) {
10449 if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) {
10450 nvme_show_error("ERROR: WDC: File Size for %s is 0",nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
10451 deEssentialsList.logEntry[listIdx].metaData.fileName)nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
;
10452 ret = WDC_STATUS_FILE_SIZE_ZERO-27;
10453 } else {
10454 /* Fetch Log File Data */
10455 dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10456 ret = wdc_fetch_log_file_from_device(hdl,
10457 deEssentialsList.logEntry[listIdx].metaData.fileID,
10458 WDC_DE_DESTN_SPI1,
10459 deEssentialsList.logEntry[listIdx].metaData.fileSize,
10460 (__u8 *)dataBuffer);
10461
10462 /* Write databuffer to file */
10463 if (ret == WDC_STATUS_SUCCESS0) {
10464 memset(fileName, 0, sizeof(fileName));
10465 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10466 deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString);
10467 if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) {
10468 wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF);
10469 wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF));
10470 } else {
10471 wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10472 }
10473 } else {
10474 nvme_show_error("ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d",nvme_show_message(1, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d"
, deEssentialsList.logEntry[listIdx].metaData.fileName, ret)
10475 deEssentialsList.logEntry[listIdx].metaData.fileName, ret)nvme_show_message(1, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d"
, deEssentialsList.logEntry[listIdx].metaData.fileName, ret)
;
10476 }
10477 free(dataBuffer);
10478 }
10479 }
10480
10481 return ret;
10482}
10483
10484int wdc_read_debug_directory(struct libnvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo,
10485 __u8 *timeString)
10486{
10487 __u32 maxNumOfVUFiles = 0;
10488 int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles);
10489 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
10490
10491 if (ret != WDC_STATUS_SUCCESS0) {
10492 nvme_show_error("WDC: wdc_get_log_dir_max_entries failed, ret = %d", ret)nvme_show_message(1, "WDC: wdc_get_log_dir_max_entries failed, ret = %d"
, ret)
;
10493 return ret;
10494 }
10495
10496 memset(&deEssentialsList, 0, sizeof(deEssentialsList));
10497 deEssentialsList.logEntry =
10498 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles);
10499 deEssentialsList.maxNumLogEntries = maxNumOfVUFiles;
10500
10501 ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo,
10502 timeString);
10503
10504 free(deEssentialsList.logEntry);
10505 deEssentialsList.logEntry = NULL((void*)0);
10506
10507 return ret;
10508}
10509
10510static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
10511 char *dir, char *key)
10512{
10513 int ret = 0;
10514 void *retPtr;
10515 char fileName[MAX_PATH_LEN256];
10516 __s8 bufferFolderPath[MAX_PATH_LEN256];
10517 char bufferFolderName[MAX_PATH_LEN256];
10518 char tarFileName[MAX_PATH_LEN256];
10519 char tarDir[MAX_PATH_LEN256];
10520 UtilsTimeInfo timeInfo;
10521 __u8 timeString[MAX_PATH_LEN256];
10522 __u8 serialNo[WDC_SERIAL_NO_LEN20];
10523 __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN9];
10524 __u8 idSerialNo[WDC_SERIAL_NO_LEN20];
10525 __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN9];
10526 __u8 featureIdBuff[4];
10527 char currDir[MAX_PATH_LEN256];
10528 char *dataBuffer = NULL((void*)0);
10529 __u32 elogNumEntries, elogBufferSize;
10530 __u32 dataBufferSize;
10531 __u32 listIdx = 0;
10532 __u32 vuLogIdx = 0;
10533 __u64 result;
10534 struct nvme_id_ctrl ctrl;
10535 struct nvme_id_ns ns;
10536 struct nvme_error_log_page *elogBuffer;
10537 struct nvme_smart_log smart_log;
10538 struct nvme_firmware_slot fw_log;
10539 struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL((void*)0);
10540 struct libnvme_passthru_cmd cmd;
10541
10542 memset(bufferFolderPath, 0, sizeof(bufferFolderPath));
10543 memset(bufferFolderName, 0, sizeof(bufferFolderName));
10544 memset(tarFileName, 0, sizeof(tarFileName));
10545 memset(tarDir, 0, sizeof(tarDir));
10546 memset(&timeInfo, 0, sizeof(timeInfo));
10547
10548 if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) {
10549 nvme_show_error("ERROR: WDC: get serial # and fw revision failed")nvme_show_message(1, "ERROR: WDC: get serial # and fw revision failed"
)
;
10550 return -1;
10551 }
10552
10553 nvme_show_error("Get Drive Essentials Data for device serial #: %s and fw revision: %s",nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
10554 idSerialNo, idFwRev)nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
;
10555
10556 /* Create Drive Essentials directory */
10557 wdc_UtilsGetTime(&timeInfo);
10558 memset(timeString, 0, sizeof(timeString));
10559 wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10560 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10561 timeInfo.hour, timeInfo.minute, timeInfo.second);
10562
10563 wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN20,
10564 "%s", (char *)idSerialNo);
10565 /* Remove any space form serialNo */
10566 wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN20, ' ');
10567
10568 memset(firmwareRevision, 0, sizeof(firmwareRevision));
10569 wdc_UtilsSnprintf((char *)firmwareRevision,
10570 WDC_NVME_FIRMWARE_REV_LEN9,
10571 "%s", (char *)idFwRev);
10572 /* Remove any space form FirmwareRevision */
10573 wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, ' ');
10574
10575 wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN256, "%s_%s_%s_%s",
10576 "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString);
10577
10578 if (dir) {
10579 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10580 (char *)dir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10581 } else {
10582 retPtr = getcwd((char *)currDir, MAX_PATH_LEN256);
10583 if (retPtr) {
10584 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10585 (char *)currDir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10586 } else {
10587 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
10588 return -1;
10589 }
10590 }
10591
10592 ret = wdc_UtilsCreateDir((char *)bufferFolderPath);
10593 if (ret) {
10594 nvme_show_error("ERROR: WDC: create directory failed, ret = %d, dir = %s", ret, bufferFolderPath)nvme_show_message(1, "ERROR: WDC: create directory failed, ret = %d, dir = %s"
, ret, bufferFolderPath)
;
10595 return -1;
10596 }
10597
10598 nvme_show_error("Store Drive Essentials bin files in directory: %s", bufferFolderPath)nvme_show_message(1, "Store Drive Essentials bin files in directory: %s"
, bufferFolderPath)
;
10599
10600 /* Get Identify Controller Data */
10601 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10602 nvme_init_identify_ctrl(&cmd, &ctrl);
10603 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10604 if (ret) {
10605 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed, ret = %d"
, ret)
;
10606 return -1;
10607 }
10608
10609 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath,
10610 WDC_DE_PATH_SEPARATOR"/", "IdentifyController", (char *)serialNo,
10611 (char *)timeString);
10612 wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl));
10613
10614 memset(&ns, 0, sizeof(struct nvme_id_ns));
10615 nvme_init_identify_ns(&cmd, 1, &ns);
10616 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10617 if (ret) {
10618 nvme_show_error("ERROR: WDC: nvme_identify_ns() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ns() failed, ret = %d"
, ret)
;
10619 } else {
10620 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10621 "IdentifyNamespace", (char *)serialNo, (char *)timeString);
10622 wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns));
10623 }
10624
10625 /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */
10626 elogNumEntries = WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64;
10627 elogBufferSize = elogNumEntries*sizeof(struct nvme_error_log_page);
10628 dataBuffer = calloc(1, elogBufferSize);
10629 elogBuffer = (struct nvme_error_log_page *)dataBuffer;
10630
10631 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR,
10632 NVME_CSI_NVM, elogBuffer, elogBufferSize);
10633
10634 ret = libnvme_get_log(hdl, &cmd, false0, elogBufferSize);
10635 if (ret) {
10636 nvme_show_error("ERROR: WDC: nvme_error_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_error_log() failed, ret = %d"
, ret)
;
10637 } else {
10638 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10639 "ErrorLog", (char *)serialNo, (char *)timeString);
10640 wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize);
10641 }
10642
10643 free(dataBuffer);
10644 dataBuffer = NULL((void*)0);
10645
10646 /* Get Smart log page */
10647 memset(&smart_log, 0, sizeof(struct nvme_smart_log));
10648 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
10649 if (ret) {
10650 nvme_show_error("ERROR: WDC: nvme_smart_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_smart_log() failed, ret = %d"
, ret)
;
10651 } else {
10652 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10653 "SmartLog", (char *)serialNo, (char *)timeString);
10654 wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log));
10655 }
10656
10657 /* Get FW Slot log page */
10658 memset(&fw_log, 0, sizeof(struct nvme_firmware_slot));
10659 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT,
10660 NVME_CSI_NVM, &fw_log, sizeof(fw_log));
10661
10662 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(fw_log));
10663 if (ret) {
10664 nvme_show_error("ERROR: WDC: nvme_fw_log() failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: nvme_fw_log() failed, ret = %d"
, ret)
;
10665 } else {
10666 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10667 "FwSLotLog", (char *)serialNo, (char *)timeString);
10668 wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot));
10669 }
10670
10671 /* Get VU log pages */
10672 /* define inputs for vendor unique log pages */
10673 vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES));
10674 vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList)(sizeof(deVULogPagesList) / sizeof((deVULogPagesList)[0]) + 0
)
;
10675
10676 for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) {
10677 dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen;
10678 dataBuffer = calloc(1, dataBufferSize);
10679 memset(dataBuffer, 0, dataBufferSize);
10680
10681 ret = nvme_get_log_simple(hdl,
10682 deVULogPagesList[vuLogIdx].logPageId,
10683 dataBuffer, dataBufferSize);
10684 if (ret) {
10685 nvme_show_error("ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d",nvme_show_message(1, "ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d"
, deVULogPagesList[vuLogIdx].logPageId, ret)
10686 deVULogPagesList[vuLogIdx].logPageId, ret)nvme_show_message(1, "ERROR: WDC: libnvme_get_log() for log page 0x%x failed, ret = %d"
, deVULogPagesList[vuLogIdx].logPageId, ret)
;
10687 } else {
10688 wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' ');
10689 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10690 "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString);
10691 wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize);
10692 }
10693
10694 free(dataBuffer);
10695 }
10696
10697 free(vuLogInput);
10698
10699 /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */
10700 for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList)(sizeof(deFeatureIdList) / sizeof((deFeatureIdList)[0]) + 0); listIdx++) {
10701 memset(featureIdBuff, 0, sizeof(featureIdBuff));
10702 /* skipping LbaRangeType as it is an optional nvme command and not supported */
10703 if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
10704 continue;
10705 ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID0xFFFFFFFF,
10706 (enum nvme_features_id)deFeatureIdList[listIdx].featureId,
10707 NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff,
10708 sizeof(featureIdBuff), &result);
10709 if (ret) {
10710 nvme_show_error("ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d",nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
10711 deFeatureIdList[listIdx].featureId, ret)nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
;
10712 } else {
10713 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10714 "FEATURE_ID_", deFeatureIdList[listIdx].featureId,
10715 deFeatureIdList[listIdx].featureName, serialNo, timeString);
10716 wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff));
10717 }
10718 }
10719
10720 wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString);
10721
10722 /* Get Dump Trace Data */
10723 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/", "dumptrace", serialNo, timeString);
10724 ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName);
10725 if (ret != WDC_STATUS_SUCCESS0)
10726 nvme_show_error("ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d"
, ret)
;
10727
10728 /* Tar the Drive Essentials directory */
10729 wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
10730 if (dir)
10731 wdc_UtilsSnprintf(tarDir, sizeof(tarDir), "%s%s%s",
10732 (char *)dir, WDC_DE_PATH_SEPARATOR"/",
10733 (char *)bufferFolderName);
10734 else
10735 wdc_UtilsSnprintf(tarDir, sizeof(tarDir), "%s",
10736 (char *)bufferFolderName);
10737 ret = wdc_tar_dir_files(tarFileName, tarDir, wdc_is_bin_file, false0);
10738
10739 if (ret)
10740 nvme_show_error("ERROR: WDC: Tar of Drive Essentials data failed, ret = %d",nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
10741 ret)nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
;
10742
10743 nvme_show_verbose_result("Get of Drive Essentials data successful")nvme_show_verbose_message("Get of Drive Essentials data successful"
)
;
10744 return 0;
10745}
10746
10747static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
10748 struct plugin *plugin)
10749{
10750 const char *desc = "Capture Drive Essentials.";
10751 const char *dirName = "Output directory pathname.";
10752 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10753 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10754 char d[PATH_MAX4096] = {0};
10755 char k[PATH_MAX4096] = {0};
10756 __u64 capabilities = 0;
10757 char *d_ptr;
10758 int ret;
10759
10760 struct config {
10761 char *dirName;
10762 };
10763
10764 struct config cfg = {
10765 .dirName = NULL((void*)0),
10766 };
10767
10768 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10769 OPT_DIR("dir-name", 'd', &cfg.dirName, dirName){"dir-name", 'd', "DIRECTORY", CFG_DIR, _Generic(&cfg.dirName
, char ** : (&cfg.dirName), const char ** : (&cfg.dirName
)), ARGCONFIG_ARG_REQUIRED, dirName, 0, }
,
10770 OPT_END(){ ((void*)0) }
10771 };
10772
10773
10774 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10775 if (ret)
10776 return ret;
10777
10778 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10779 if (ret)
10780 return ret;
10781
10782 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10783
10784 if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) {
10785 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10786 ret = -1;
10787 goto out;
10788 }
10789
10790 if (cfg.dirName) {
10791 shr_strscpy(d, cfg.dirName, sizeof(d));
10792 d_ptr = d;
10793 } else {
10794 d_ptr = NULL((void*)0);
10795 }
10796
10797 ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k);
10798out:
10799 return ret;
10800}
10801
10802static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size)
10803{
10804 int ret;
10805 struct libnvme_passthru_cmd admin_cmd;
10806
10807 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10808 admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE0xCC;
10809 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 << WDC_NVME_SUBCMD_SHIFT8) |
10810 WDC_NVME_DRIVE_RESIZE_CMD0x03);
10811 admin_cmd.cdw13 = new_size;
10812
10813 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10814 return ret;
10815}
10816
10817static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option)
10818{
10819 int ret;
10820 struct libnvme_passthru_cmd admin_cmd;
10821
10822 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10823 admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB;
10824 admin_cmd.nsid = nsid;
10825 admin_cmd.cdw10 = op_option;
10826
10827 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10828 return ret;
10829}
10830
10831static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result)
10832{
10833 int ret;
10834 struct libnvme_passthru_cmd admin_cmd;
10835
10836 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10837 admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE0xC6;
10838 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
10839 WDC_NVME_DRIVE_INFO_CMD0x22);
10840
10841 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10842
10843 if (!ret && result)
10844 *result = admin_cmd.result;
10845
10846 return ret;
10847}
10848
10849static int wdc_drive_resize(int argc, char **argv,
10850 struct command *command, struct plugin *plugin)
10851{
10852 const char *desc = "Send a Resize command.";
10853 const char *size = "The new size (in GB) to resize the drive to.";
10854 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10855 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10856 int ret;
10857
10858 struct config {
10859 uint64_t size;
10860 };
10861
10862 struct config cfg = {
10863 .size = 0,
10864 };
10865
10866 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10867 OPT_LONG("size", 's', &cfg.size, size){"size", 's', "NUM", CFG_LONG, _Generic(&cfg.size, uint64_t
* : (&cfg.size), default : _Generic(&cfg.size, unsigned
long long * : (&cfg.size), default : (void)0)), ARGCONFIG_ARG_REQUIRED
, size, 0, }
,
10868 OPT_END(){ ((void*)0) }
10869 };
10870
10871 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10872 if (ret)
10873 return ret;
10874
10875 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10876 if (ret)
10877 return -1;
10878
10879 return run_wdc_drive_resize(ctx, hdl, cfg.size);
10880}
10881
10882int run_wdc_drive_resize(struct libnvme_global_ctx *ctx,
10883 struct libnvme_transport_handle *hdl, uint64_t size)
10884{
10885 uint64_t capabilities = 0;
10886 int ret;
10887
10888 if (!wdc_check_device(ctx, hdl))
10889 return -1;
10890
10891 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10892
10893 if ((capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100) == WDC_DRIVE_CAP_RESIZE0x0000000000000100) {
10894 ret = wdc_do_drive_resize(hdl, size);
10895 } else {
10896 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10897 ret = -1;
10898 }
10899
10900 if (!ret)
10901 printf("New size: %" PRIu64"l" "u" " GB\n", size);
10902
10903 nvme_show_status(ret);
10904 return ret;
10905}
10906
10907static int wdc_namespace_resize(int argc, char **argv,
10908 struct command *command, struct plugin *plugin)
10909{
10910 const char *desc = "Send a Namespace Resize command.";
10911 const char *namespace_id = "The namespace id to resize.";
10912 const char *op_option = "The over provisioning option to set for namespace.";
10913 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10914 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10915 uint64_t capabilities = 0;
10916 int ret;
10917
10918 struct config {
10919 __u32 namespace_id;
10920 __u32 op_option;
10921 };
10922
10923 struct config cfg = {
10924 .namespace_id = 0x1,
10925 .op_option = 0xF,
10926 };
10927
10928 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10929 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
10930 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
10931 OPT_UINT("op-option", 'O', &cfg.op_option, op_option){"op-option", 'O', "NUM", CFG_POSITIVE, _Generic(&cfg.op_option
, uint32_t * : (&cfg.op_option)), ARGCONFIG_ARG_REQUIRED,
op_option, 0, }
,
10932 OPT_END(){ ((void*)0) }
10933 };
10934
10935 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10936 if (ret)
10937 return ret;
10938
10939 if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) &&
10940 (cfg.op_option != 0xF)) {
10941 nvme_show_error("ERROR: WDC: unsupported OP option parameter")nvme_show_message(1, "ERROR: WDC: unsupported OP option parameter"
)
;
10942 return -1;
10943 }
10944
10945 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10946 if (ret || !wdc_check_device(ctx, hdl))
10947 return -1;
10948
10949 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10950
10951 if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) == WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) {
10952 ret = wdc_do_namespace_resize(hdl, cfg.namespace_id,
10953 cfg.op_option);
10954
10955 if (ret)
10956 nvme_show_error("ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed", cfg.namespace_id, cfg.op_option)nvme_show_message(1, "ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed"
, cfg.namespace_id, cfg.op_option)
;
10957 } else {
10958 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10959 ret = -1;
10960 }
10961
10962 nvme_show_status(ret);
10963 return ret;
10964}
10965
10966static int wdc_reason_identifier(int argc, char **argv,
10967 struct command *command, struct plugin *plugin)
10968{
10969 const char *desc = "Retrieve telemetry log reason identifier.";
10970 const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
10971 const char *fname = "File name to save raw binary identifier";
10972 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10973 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10974 int ret;
10975 uint64_t capabilities = 0;
10976 char f[PATH_MAX4096] = {0};
10977 char fileSuffix[PATH_MAX4096] = {0};
10978 UtilsTimeInfo timeInfo;
10979 __u8 timeStamp[MAX_PATH_LEN256];
10980
10981
10982 struct config {
10983 __u32 log_id;
10984 char *file;
10985 };
10986 struct config cfg = {
10987 .log_id = 7,
10988 .file = NULL((void*)0),
10989 };
10990
10991 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10992 OPT_UINT("log-id", 'i', &cfg.log_id, log_id){"log-id", 'i', "NUM", CFG_POSITIVE, _Generic(&cfg.log_id
, uint32_t * : (&cfg.log_id)), ARGCONFIG_ARG_REQUIRED, log_id
, 0, }
,
10993 OPT_FILE("file", 'O', &cfg.file, fname){"file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file, char *
* : (&cfg.file), const char ** : (&cfg.file)), ARGCONFIG_ARG_REQUIRED
, fname, 0, }
,
10994 OPT_END(){ ((void*)0) }
10995 };
10996
10997 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10998
10999 if (ret)
11000 return ret;
11001
11002 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11003 if (ret)
11004 return ret;
11005
11006 if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST &&
11007 cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
11008 nvme_show_error("ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)")nvme_show_message(1, "ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)"
)
;
11009 return -1;
11010 }
11011
11012 if (cfg.file) {
11013 int verify_file;
11014
11015 /* verify the passed in file name and path is valid before getting the dump data */
11016 verify_file = shr_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
11017 if (verify_file < 0) {
11018 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
11019 return -1;
11020 }
11021 close(verify_file);
11022 shr_strscpy(f, cfg.file, sizeof(f));
11023 } else {
11024 wdc_UtilsGetTime(&timeInfo);
11025 memset(timeStamp, 0, sizeof(timeStamp));
11026 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
11027 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
11028 timeInfo.hour, timeInfo.minute, timeInfo.second);
11029 if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11030 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_ctlr_%s", (char *)timeStamp);
11031 else
11032 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_host_%s", (char *)timeStamp);
11033
11034 if (wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix) == -1) {
11035 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
11036 return -1;
11037 }
11038 if (strlen(f) > PATH_MAX4096 - 5) {
11039 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
11040 return -1;
11041 }
11042 shr_strscat(f, ".bin", sizeof(f));
11043 }
11044
11045 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
11046
11047 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11048 if ((capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000) == WDC_DRIVE_CAP_REASON_ID0x0000000000010000) {
11049 ret = wdc_do_get_reason_id(hdl, f, cfg.log_id);
11050 } else {
11051 nvme_show_error("ERROR: WDC:unsupported device for this command")nvme_show_message(1, "ERROR: WDC:unsupported device for this command"
)
;
11052 ret = -1;
11053 }
11054
11055 nvme_show_status(ret);
11056
11057 return ret;
11058}
11059
11060static const char *nvme_log_id_to_string(__u8 log_id)
11061{
11062 switch (log_id) {
11063 case NVME_LOG_LID_ERROR:
11064 return "Error Information Log ID";
11065 case NVME_LOG_LID_SMART:
11066 return "Smart/Health Information Log ID";
11067 case NVME_LOG_LID_FW_SLOT:
11068 return "Firmware Slot Information Log ID";
11069 case NVME_LOG_LID_CHANGED_ATTACHED_NS:
11070 return "Attached Namespace Changed Log ID";
11071 case NVME_LOG_LID_CMD_EFFECTS:
11072 return "Commamds Supported and Effects Log ID";
11073 case NVME_LOG_LID_DEVICE_SELF_TEST:
11074 return "Device Self Test Log ID";
11075 case NVME_LOG_LID_TELEMETRY_HOST:
11076 return "Telemetry Host Initiated Log ID";
11077 case NVME_LOG_LID_TELEMETRY_CTRL:
11078 return "Telemetry Controller Generated Log ID";
11079 case NVME_LOG_LID_ENDURANCE_GROUP:
11080 return "Endurance Group Log ID";
11081 case NVME_LOG_LID_ANA:
11082 return "ANA Log ID";
11083 case NVME_LOG_LID_PERSISTENT_EVENT:
11084 return "Persistent Event Log ID";
11085 case NVME_LOG_LID_DISCOVERY:
11086 return "Discovery Log ID";
11087 case NVME_LOG_LID_RESERVATION:
11088 return "Reservation Notification Log ID";
11089 case NVME_LOG_LID_SANITIZE:
11090 return "Sanitize Status Log ID";
11091 case WDC_LOG_ID_C00xC0:
11092 return "WDC Vendor Unique Log ID C0";
11093 case WDC_LOG_ID_C10xC1:
11094 return "WDC Vendor Unique Log ID C1";
11095 case WDC_LOG_ID_C20xC2:
11096 return "WDC Vendor Unique Log ID C2";
11097 case WDC_LOG_ID_C30xC3:
11098 return "WDC Vendor Unique Log ID C3";
11099 case WDC_LOG_ID_C40xC4:
11100 return "WDC Vendor Unique Log ID C4";
11101 case WDC_LOG_ID_C50xC5:
11102 return "WDC Vendor Unique Log ID C5";
11103 case WDC_LOG_ID_C60xC6:
11104 return "WDC Vendor Unique Log ID C6";
11105 case WDC_LOG_ID_C80xC8:
11106 return "WDC Vendor Unique Log ID C8";
11107 case WDC_LOG_ID_CA0xCA:
11108 return "WDC Vendor Unique Log ID CA";
11109 case WDC_LOG_ID_CB0xCB:
11110 return "WDC Vendor Unique Log ID CB";
11111 case WDC_LOG_ID_D00xD0:
11112 return "WDC Vendor Unique Log ID D0";
11113 case WDC_LOG_ID_D10xD1:
11114 return "WDC Vendor Unique Log ID D1";
11115 case WDC_LOG_ID_D60xD6:
11116 return "WDC Vendor Unique Log ID D6";
11117 case WDC_LOG_ID_D70xD7:
11118 return "WDC Vendor Unique Log ID D7";
11119 case WDC_LOG_ID_D80xD8:
11120 return "WDC Vendor Unique Log ID D8";
11121 case WDC_LOG_ID_DE0xDE:
11122 return "WDC Vendor Unique Log ID DE";
11123 case WDC_LOG_ID_F00xF0:
11124 return "WDC Vendor Unique Log ID F0";
11125 case WDC_LOG_ID_F10xF1:
11126 return "WDC Vendor Unique Log ID F1";
11127 case WDC_LOG_ID_F20xF2:
11128 return "WDC Vendor Unique Log ID F2";
11129 case WDC_LOG_ID_FA0xFA:
11130 return "WDC Vendor Unique Log ID FA";
11131 default:
11132 return "Unknown Log ID";
11133 }
11134}
11135
11136static void __json_log_page_directory(struct log_page_directory *directory)
11137{
11138 __u32 bitmap_idx;
11139 __u8 log_id;
11140 struct json_object *root;
11141 struct json_object *entries;
11142
11143 root = json_create_object()json_object_new_object();
11144
11145 entries = json_create_array()json_object_new_array();
11146 json_object_add_value_array(root, "Entries", entries)json_object_object_add(root, "Entries", entries);
11147
11148 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11149 log_id = bitmap_idx;
11150 if (!log_page_name[log_id])
11151 continue;
11152 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
11153 struct json_object *json_entry = json_create_object()json_object_new_object();
11154
11155 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))
;
11156 json_object_add_value_string(json_entry, "Log Page Name",
11157 log_page_name[log_id]);
11158
11159 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11160 }
11161 }
11162
11163 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11164 log_id = NVME_LOG_NS_BASE + bitmap_idx;
11165 if (!log_page_name[log_id])
11166 continue;
11167 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
11168 struct json_object *json_entry = json_create_object()json_object_new_object();
11169
11170 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))
;
11171 json_object_add_value_string(json_entry, "Log Page Name",
11172 log_page_name[log_id]);
11173
11174 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11175 }
11176 }
11177
11178 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11179 log_id = NVME_LOG_VS_BASE + bitmap_idx;
11180 if (!log_page_name[log_id])
11181 continue;
11182 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
11183 struct json_object *json_entry = json_create_object()json_object_new_object();
11184
11185 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))
;
11186 json_object_add_value_string(json_entry, "Log Page Name",
11187 log_page_name[log_id]);
11188
11189 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11190 }
11191 }
11192
11193 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11194 printf("\n");
11195 json_free_object(root)json_object_put(root);
11196}
11197
11198
11199static void __show_log_page_directory(struct log_page_directory *directory)
11200{
11201 __u32 bitmap_idx;
11202 __u8 log_id;
11203
11204 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11205 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
11206 log_id = bitmap_idx;
11207 if (log_page_name[log_id])
11208 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11209 }
11210 }
11211
11212 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11213 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
11214 log_id = NVME_LOG_NS_BASE + bitmap_idx;
11215 if (log_page_name[log_id])
11216 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11217 }
11218 }
11219
11220 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11221 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
11222 log_id = NVME_LOG_VS_BASE + bitmap_idx;
11223 if (log_page_name[log_id])
11224 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11225 }
11226 }
11227}
11228
11229static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
11230 struct plugin *plugin)
11231{
11232 const char *desc = "Retrieve Log Page Directory.";
11233 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11234 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11235 nvme_print_flags_t fmt;
11236 int ret = 0;
11237 __u64 capabilities = 0;
11238 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
11239 size_t cbs_len = 0;
11240 __u32 n;
11241 int i, uuid_index = 0;
11242 __u8 log_id = 0;
11243 __u32 device_id, read_vendor_id;
11244 bool_Bool uuid_supported = false0;
11245 struct nvme_id_uuid_list uuid_list;
11246
11247 struct config {
11248 char *output_format;
11249 };
11250
11251 struct config cfg = {
11252 .output_format = "normal",
11253 };
11254
11255 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
11256 OPT_END(){ ((void*)0) }
11257 };
11258
11259 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11260 if (ret)
11261 return ret;
11262
11263 cfg.output_format = nvme_args.output_format;
11264
11265 ret = validate_output_format(cfg.output_format, &fmt);
11266 if (ret < 0) {
11267 nvme_show_error("%s: ERROR: WDC: invalid output format", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid output format",
__func__)
;
11268 return ret;
11269 }
11270
11271 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11272 if (ret)
11273 return ret;
11274
11275 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11276
11277 if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000)) {
11278 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11279 ret = -1;
11280 } else {
11281 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
11282 if (wdc_CheckUuidListSupport(hdl, &uuid_list))
11283 uuid_supported = true1;
11284
11285 if (uuid_supported)
11286 nvme_show_error("WDC: UUID lists supported")nvme_show_message(1, "WDC: UUID lists supported");
11287 else
11288 nvme_show_error("WDC: UUID lists NOT supported")nvme_show_message(1, "WDC: UUID lists NOT supported");
11289
11290
11291 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11292 if (ret)
11293 return ret;
11294
11295 log_id = wdc_is_zn350(device_id) ?
11296 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 :
11297 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
11298
11299 if (!wdc_is_sn861(device_id)) {
11300 if (uuid_supported) {
11301 /* check for the Sandisk UUID first */
11302 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
11303
11304 if (uuid_index < 0)
11305 /* The Sandisk UUID is not found;
11306 * check for the WDC UUID second.
11307 */
11308 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
11309 }
11310
11311 /* WD UUID not found, use default uuid index - 0 */
11312 if (uuid_index < 0)
11313 uuid_index = 0;
11314
11315 /* verify the 0xC2 Device Manageability log page is supported */
11316 if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) {
11317 nvme_show_error("%s: ERROR: WDC: 0x%x Log Page not supported",nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
11318 __func__, log_id)nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
;
11319 ret = -1;
11320 goto out;
11321 }
11322
11323 if (!get_dev_mgment_cbs_data(ctx, hdl,
11324 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
11325 (void *)&cbs_data, &cbs_len)) {
11326 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
11327 "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
11328 __func__, WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
;
11329 ret = -1;
11330 goto out;
11331 }
11332 if (!cbs_data) {
11333 nvme_show_error("%s: ERROR: WDC: NULL_data ptr", __func__)nvme_show_message(1, "%s: ERROR: WDC: NULL_data ptr", __func__
)
;
11334 ret = -1;
11335 goto out;
11336 }
11337 n = wdc_cbs_len(cbs_data, cbs_len);
11338 printf("Log Page Directory\n");
11339 /* print the supported pages */
11340 if (!strcmp(cfg.output_format, "normal")) {
11341 for (i = 0; i < n; i++)
11342 printf("0x%x - %s\n", cbs_data->data[i],
11343 nvme_log_id_to_string(cbs_data->data[i]));
11344 } else if (!strcmp(cfg.output_format, "binary")) {
11345 d((__u8 *)cbs_data->data, n, 16, 1);
11346 } else if (!strcmp(cfg.output_format, "json")) {
11347 struct json_object *root = json_create_object()json_object_new_object();
11348
11349 for (i = 0; i < n; i++) {
11350 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]))
11351 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]))
11352 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]))
;
11353 }
11354
11355 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11356 printf("\n");
11357 json_free_object(root)json_object_put(root);
11358 } else {
11359 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
11360 "%s: ERROR: WDC: Invalid format, format = %s\n",nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
11361 __func__, cfg.output_format)nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
;
11362 }
11363
11364 free(cbs_data);
11365 } else {
11366 struct log_page_directory *dir;
11367 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *data = NULL((void*)0);
11368
11369 data = libnvme_alloc(512);
11370 if (!data) {
11371 nvme_show_error(nvme_show_message(1, "can not allocate log page directory payload\n"
)
11372 "can not allocate log page directory payload\n")nvme_show_message(1, "can not allocate log page directory payload\n"
)
;
11373 return -ENOMEM12;
11374 }
11375
11376 dir = (struct log_page_directory *)data;
11377 struct libnvme_passthru_cmd cmd = {
11378 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
11379 .cdw10 = 8,
11380 .cdw12 = WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2,
11381 .addr = (__u64)(uintptr_t)data,
11382 .data_len = 32,
11383 };
11384
11385 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11386 if (!ret) {
11387 switch (fmt) {
11388 case BINARY:
11389 d_raw((unsigned char *)data, 32);
11390 break;
11391 case JSON:
11392 __json_log_page_directory(dir);
11393 break;
11394 default:
11395 __show_log_page_directory(dir);
11396 }
11397 } else {
11398 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
11399 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
11400 }
11401 }
11402 }
11403
11404out:
11405 return ret;
11406}
11407
11408static int wdc_get_drive_reason_id(struct libnvme_transport_handle *hdl, char *drive_reason_id, size_t len)
11409{
11410 const char *reason_id_str = "reason_id";
11411 struct libnvme_passthru_cmd cmd;
11412 struct nvme_id_ctrl ctrl;
11413 char sn[sizeof(ctrl.sn) + 1] = {0};
11414 char mn[sizeof(ctrl.mn) + 1] = {0};
11415 int res_len = 0;
11416 int ret;
11417
11418 memset(drive_reason_id, 0, len);
11419 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
11420 nvme_init_identify_ctrl(&cmd, &ctrl);
11421 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11422 if (ret) {
11423 nvme_show_error(nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
11424 "ERROR: WDC: nvme_identify_ctrl() failed 0x%x",nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
11425 ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
11426 return -1;
11427 }
11428
11429 snprintf(sn, sizeof(sn), "%-.*s",
11430 (int)sizeof(ctrl.sn), ctrl.sn);
11431 snprintf(mn, sizeof(mn), "%-.*s",
11432 (int)sizeof(ctrl.mn), ctrl.mn);
11433 shr_sanitize_name(shr_rtrim(sn));
11434 shr_sanitize_name(shr_rtrim(mn));
11435
11436 res_len = snprintf(drive_reason_id, len,
11437 "%s_%s_%s", sn, mn, reason_id_str);
11438 if (len <= res_len) {
11439 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
11440 "ERROR: WDC: cannot format serial number due to data of unexpected length\n")nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
;
11441 return -1;
11442 }
11443
11444 return 0;
11445}
11446
11447static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size)
11448{
11449 int ret = 0;
11450 char *reason_id_file;
11451 char drive_reason_id[PATH_MAX4096] = {0};
11452 char reason_id_path[PATH_MAX4096] = WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli";
11453 struct stat st = {0};
11454
11455 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11456 nvme_show_error("%s: ERROR: failed to get drive reason id", __func__)nvme_show_message(1, "%s: ERROR: failed to get drive reason id"
, __func__)
;
11457 return -1;
11458 }
11459
11460 /* make the nvmecli dir in /usr/local if it doesn't already exist */
11461 if (stat(reason_id_path, &st) == -1) {
11462 if (shr_mkdir(reason_id_path, 0700) < 0) {
11463 nvme_show_error("%s: ERROR: failed to mkdir %s: %s",nvme_show_message(1, "%s: ERROR: failed to mkdir %s: %s", __func__
, reason_id_path, libnvme_strerror((*__errno_location ())))
11464 __func__, reason_id_path, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: failed to mkdir %s: %s", __func__
, reason_id_path, libnvme_strerror((*__errno_location ())))
;
11465 return -1;
11466 }
11467 }
11468
11469 if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
11470 drive_reason_id, ".bin") < 0)
11471 return -ENOMEM12;
11472
11473 nvme_show_error("%s: reason id file = %s", __func__, reason_id_file)nvme_show_message(1, "%s: reason id file = %s", __func__, reason_id_file
)
;
11474
11475 /* save off the error reason identifier to a file in /usr/local/nvmecli */
11476 ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN128);
11477 free(reason_id_file);
11478
11479 return ret;
11480}
11481
11482static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl)
11483{
11484 int ret = -1;
11485 int verify_file;
11486 char *reason_id_file;
11487 char drive_reason_id[PATH_MAX4096] = {0};
11488
11489 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11490 nvme_show_error("%s: ERROR: failed to get drive reason id", __func__)nvme_show_message(1, "%s: ERROR: failed to get drive reason id"
, __func__)
;
11491 return -1;
11492 }
11493
11494 if (asprintf(&reason_id_file, "%s/%s%s", WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli",
11495 drive_reason_id, ".bin") < 0)
11496 return -ENOMEM12;
11497
11498 /* verify the drive reason id file name and path is valid */
11499 verify_file = shr_open_rawdata(reason_id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((reason_id_file), (01 | 0100 | 01000), 0666);
11500 if (verify_file < 0) {
11501 ret = -1;
11502 goto free;
11503 }
11504 close(verify_file);
11505
11506 /* remove the reason id file */
11507 ret = remove(reason_id_file);
11508
11509free:
11510 free(reason_id_file);
11511
11512 return ret;
11513}
11514
11515static int wdc_dump_telemetry_hdr(struct libnvme_transport_handle *hdl, int log_id, struct nvme_telemetry_log *log_hdr)
11516{
11517 int ret = 0;
11518
11519 if (log_id == NVME_LOG_LID_TELEMETRY_HOST) {
11520 struct libnvme_passthru_cmd cmd;
11521
11522 nvme_init_get_log_create_telemetry_host(&cmd, log_hdr);
11523
11524 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(*log_hdr));
11525 } else {
11526 struct libnvme_passthru_cmd cmd;
11527
11528 nvme_init_get_log_telemetry_ctrl(&cmd, 0, (void *)log_hdr, 512);
11529
11530 ret = libnvme_get_log_dynamic_chunk(hdl, &cmd, false0, 512);
11531 }
11532
11533 if (ret < 0) {
11534 nvme_show_err(ret, "get-telemetry-log");
11535 } else if (ret > 0) {
11536 nvme_show_status(ret);
11537 nvme_show_error("%s: ERROR: Failed to acquire telemetry header, ret = %d!", __func__, ret)nvme_show_message(1, "%s: ERROR: Failed to acquire telemetry header, ret = %d!"
, __func__, ret)
;
11538 }
11539
11540 return ret;
11541}
11542
11543static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id)
11544{
11545 int ret;
11546 struct nvme_telemetry_log *log_hdr;
11547 __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
11548 __u32 reason_id_size = 0;
11549
11550 log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size);
11551 if (!log_hdr) {
11552 nvme_show_error("%s: ERROR: malloc failed, size : 0x%x, status: %s", __func__, log_hdr_size, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc failed, size : 0x%x, status: %s"
, __func__, log_hdr_size, libnvme_strerror((*__errno_location
())))
;
11553 ret = -1;
11554 goto out;
11555 }
11556 memset(log_hdr, 0, log_hdr_size);
11557
11558 ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr);
11559 if (ret) {
11560 nvme_show_error("%s: ERROR: get telemetry header failed, ret : %d", __func__, ret)nvme_show_message(1, "%s: ERROR: get telemetry header failed, ret : %d"
, __func__, ret)
;
11561 ret = -1;
11562 goto out;
11563 }
11564
11565 reason_id_size = sizeof(log_hdr->rsnident);
11566
11567 if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11568 wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size);
11569
11570 ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
11571
11572out:
11573 free(log_hdr);
11574 return ret;
11575}
11576
11577static void wdc_print_nand_stats_normal(__u16 version, void *data)
11578{
11579 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11580 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11581 uint64_t temp_raw;
11582 __u16 temp_norm;
11583 uint64_t temp;
11584
11585 switch (version) {
11586 case 0:
11587 printf(" NAND Statistics :-\n");
11588 printf(" NAND Writes TLC (Bytes) %s\n",
11589 uint128_t_to_string(
11590 le128_to_cpu(nand_stats->nand_write_tlc)));
11591 printf(" NAND Writes SLC (Bytes) %s\n",
11592 uint128_t_to_string(
11593 le128_to_cpu(nand_stats->nand_write_slc)));
11594 printf(" NAND Program Failures %"PRIu32"u""\n",
11595 (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure));
11596 printf(" NAND Erase Failures %"PRIu32"u""\n",
11597 (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure));
11598 printf(" Bad Block Count %"PRIu32"u""\n",
11599 (uint32_t)le32_to_cpu(nand_stats->bad_block_count));
11600 printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"l" "u""\n",
11601 le64_to_cpu(nand_stats->nand_rec_trigger_event));
11602 printf(" E2E Error Counter %"PRIu64"l" "u""\n",
11603 le64_to_cpu(nand_stats->e2e_error_counter));
11604 printf(" Number Successful NS Resizing Events %"PRIu64"l" "u""\n",
11605 le64_to_cpu(nand_stats->successful_ns_resize_event));
11606 printf(" log page version %"PRIu16"hu""\n",
11607 le16_to_cpu(nand_stats->log_page_version));
11608 break;
11609 case 3:
11610 printf(" NAND Statistics V3:-\n");
11611 printf(" TLC Units Written %s\n",
11612 uint128_t_to_string(
11613 le128_to_cpu(nand_stats_v3->nand_write_tlc)));
11614 printf(" SLC Units Written %s\n",
11615 uint128_t_to_string(
11616 le128_to_cpu(nand_stats_v3->nand_write_slc)));
11617 temp = shr_get_unaligned_le64(
11618 nand_stats_v3->bad_nand_block_count);
11619 temp_norm = temp & 0xffff;
11620 temp_raw = temp >> 16;
11621 printf(" Bad NAND Blocks Count - Normalized %"PRIu16"hu""\n",
11622 temp_norm);
11623 printf(" Bad NAND Blocks Count - Raw %"PRIu64"l" "u""\n",
11624 temp_raw);
11625 printf(" NAND XOR Recovery count %"PRIu64"l" "u""\n",
11626 le64_to_cpu(nand_stats_v3->xor_recovery_count));
11627 printf(" UECC Read Error count %"PRIu64"l" "u""\n",
11628 le64_to_cpu(nand_stats_v3->uecc_read_error_count));
11629 printf(" SSD End to End corrected errors %"PRIu64"l" "u""\n",
11630 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
11631 printf(" SSD End to End detected errors %"PRIu32"u""\n",
11632 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
11633 printf(" SSD End to End uncorrected E2E errors %"PRIu32"u""\n",
11634 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
11635 printf(" System data %% life-used %u\n",
11636 nand_stats_v3->percent_life_used);
11637 printf(" User Data Erase Counts - TLC Min %"PRIu64"l" "u""\n",
11638 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
11639 printf(" User Data Erase Counts - TLC Max %"PRIu64"l" "u""\n",
11640 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
11641 printf(" User Data Erase Counts - SLC Min %"PRIu64"l" "u""\n",
11642 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
11643 printf(" User Data Erase Counts - SLC Max %"PRIu64"l" "u""\n",
11644 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
11645 temp = shr_get_unaligned_le64(
11646 nand_stats_v3->program_fail_count);
11647 temp_norm = temp & 0xffff;
11648 temp_raw = temp >> 16;
11649 printf(" Program Fail Count - Normalized %"PRIu16"hu""\n",
11650 temp_norm);
11651 printf(" Program Fail Count - Raw %"PRIu64"l" "u""\n",
11652 temp_raw);
11653 temp = shr_get_unaligned_le64(
11654 nand_stats_v3->erase_fail_count);
11655 temp_norm = temp & 0xffff;
11656 temp_raw = temp >> 16;
11657 printf(" Erase Fail Count - Normalized %"PRIu16"hu""\n",
11658 temp_norm);
11659 printf(" Erase Fail Count - Raw %"PRIu64"l" "u""\n",
11660 temp_raw);
11661 printf(" PCIe Correctable Error Count %"PRIu16"hu""\n",
11662 le16_to_cpu(nand_stats_v3->correctable_error_count));
11663 printf(" %% Free Blocks (User) %u\n",
11664 nand_stats_v3->percent_free_blocks_user);
11665 printf(" Security Version Number %"PRIu64"l" "u""\n",
11666 le64_to_cpu(nand_stats_v3->security_version_number));
11667 printf(" %% Free Blocks (System) %u\n",
11668 nand_stats_v3->percent_free_blocks_system);
11669 printf(" Data Set Management Commands %s\n",
11670 uint128_t_to_string(
11671 le128_to_cpu(nand_stats_v3->trim_completions)));
11672 printf(" Estimate of Incomplete Trim Data %"PRIu64"l" "u""\n",
11673 le64_to_cpu(nand_stats_v3->trim_completions[16]));
11674 printf(" %% of completed trim %u\n",
11675 nand_stats_v3->trim_completions[24]);
11676 printf(" Background Back-Pressure-Guage %u\n",
11677 nand_stats_v3->back_pressure_guage);
11678 printf(" Soft ECC Error Count %"PRIu64"l" "u""\n",
11679 le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
11680 printf(" Refresh Count %"PRIu64"l" "u""\n",
11681 le64_to_cpu(nand_stats_v3->refresh_count));
11682 temp = shr_get_unaligned_le64(
11683 nand_stats_v3->bad_sys_nand_block_count);
11684 temp_norm = temp & 0xffff;
11685 temp_raw = temp >> 16;
11686 printf(" Bad System Nand Block Count - Normalized %"PRIu16"hu""\n",
11687 temp_norm);
11688 printf(" Bad System Nand Block Count - Raw %"PRIu64"l" "u""\n",
11689 temp_raw);
11690 printf(" Endurance Estimate %s\n",
11691 uint128_t_to_string(
11692 le128_to_cpu(nand_stats_v3->endurance_estimate)));
11693 printf(" Thermal Throttling Count %u\n",
11694 nand_stats_v3->thermal_throttling_st_ct[0]);
11695 printf(" Thermal Throttling Status %u\n",
11696 nand_stats_v3->thermal_throttling_st_ct[1]);
11697 printf(" Unaligned I/O %"PRIu64"l" "u""\n",
11698 le64_to_cpu(nand_stats_v3->unaligned_IO));
11699 printf(" Physical Media Units Read %s\n",
11700 uint128_t_to_string(
11701 le128_to_cpu(nand_stats_v3->physical_media_units)));
11702 printf(" log page version %"PRIu16"hu""\n",
11703 le16_to_cpu(nand_stats_v3->log_page_version));
11704 break;
11705
11706 default:
11707 nvme_show_error("WDC: Nand Stats ERROR: Invalid version")nvme_show_message(1, "WDC: Nand Stats ERROR: Invalid version"
)
;
11708 break;
11709
11710 }
11711}
11712
11713static void wdc_print_nand_stats_json(__u16 version, void *data)
11714{
11715 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11716 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11717 struct json_object *root = json_create_object()json_object_new_object();
11718 uint64_t temp_raw;
11719 __u16 temp_norm;
11720 uint64_t temp;
11721
11722 switch (version) {
11723 case 0:
11724 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)))
11725 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)))
;
11726 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)))
11727 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)))
;
11728 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)))
11729 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)))
;
11730 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)))
11731 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)))
;
11732 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)))
11733 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)))
;
11734 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
)))
11735 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
)))
;
11736 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)))
11737 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)))
;
11738 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
)))
11739 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
)))
;
11740
11741 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11742 printf("\n");
11743 break;
11744 case 3:
11745 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)))
11746 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)))
;
11747 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)))
11748 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)))
;
11749 temp = shr_get_unaligned_le64(
11750 nand_stats_v3->bad_nand_block_count);
11751 temp_norm = temp & 0xffff;
11752 temp_raw = temp >> 16;
11753 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(temp_norm))
11754 temp_norm)json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(temp_norm))
;
11755 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
(temp_raw))
11756 temp_raw)json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(temp_raw))
;
11757 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)))
11758 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)))
;
11759 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)))
11760 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)))
;
11761 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])))
11762 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])))
;
11763 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])))
11764 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])))
;
11765 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])))
11766 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])))
;
11767 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))
11768 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))
;
11769 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])))
11770 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])))
;
11771 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])))
11772 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])))
;
11773 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])))
11774 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])))
;
11775 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])))
11776 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])))
;
11777 temp = shr_get_unaligned_le64(
11778 nand_stats_v3->program_fail_count);
11779 temp_norm = temp & 0xffff;
11780 temp_raw = temp >> 16;
11781 json_object_add_value_uint(root, "Program Fail Count - Normalized",json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(temp_norm))
11782 temp_norm)json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(temp_norm))
;
11783 json_object_add_value_uint64(root, "Program Fail Count - Raw",json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(temp_raw))
11784 temp_raw)json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(temp_raw))
;
11785 temp = shr_get_unaligned_le64(
11786 nand_stats_v3->erase_fail_count);
11787 temp_norm = temp & 0xffff;
11788 temp_raw = temp >> 16;
11789 json_object_add_value_uint(root, "Erase Fail Count - Normalized",json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(temp_norm))
11790 temp_norm)json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(temp_norm))
;
11791 json_object_add_value_uint64(root, "Erase Fail Count - Raw",json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(temp_raw))
11792 temp_raw)json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(temp_raw))
;
11793 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)))
11794 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)))
;
11795 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))
11796 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))
;
11797 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)))
11798 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)))
;
11799 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))
11800 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))
;
11801 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)))
11802 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)))
;
11803 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])))
11804 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])))
;
11805 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]))
11806 nand_stats_v3->trim_completions[24])json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
;
11807 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
))
11808 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
))
;
11809 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)))
11810 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)))
;
11811 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)))
11812 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)))
;
11813 temp = shr_get_unaligned_le64(
11814 nand_stats_v3->bad_sys_nand_block_count);
11815 temp_norm = temp & 0xffff;
11816 temp_raw = temp >> 16;
11817 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(temp_norm))
11818 temp_norm)json_object_object_add(root, "Bad System Nand Block Count - Normalized"
, json_object_new_uint64(temp_norm))
;
11819 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(temp_raw))
11820 temp_raw)json_object_object_add(root, "Bad System Nand Block Count - Raw"
, json_object_new_uint64(temp_raw))
;
11821 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)))
11822 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)))
;
11823 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]))
11824 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]))
;
11825 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]))
11826 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]))
;
11827 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)))
11828 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)))
;
11829 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)))
11830 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)))
;
11831 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)))
11832 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)))
;
11833
11834 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11835 printf("\n");
11836 break;
11837 default:
11838 nvme_show_error("%s: Invalid Stats Version = %d", __func__, version)nvme_show_message(1, "%s: Invalid Stats Version = %d", __func__
, version)
;
11839 break;
11840 }
11841
11842 json_free_object(root)json_object_put(root);
11843
11844}
11845
11846static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats)
11847{
11848 printf(" PCIE Statistics :-\n");
11849 printf(" Unsupported Request Error Counter %20"PRIu64"l" "u""\n",
11850 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
11851 printf(" ECRC Error Status Counter %20"PRIu64"l" "u""\n",
11852 le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
11853 printf(" Malformed TLP Status Counter %20"PRIu64"l" "u""\n",
11854 le64_to_cpu(pcie_stats->malformedTlpStatusCount));
11855 printf(" Receiver Overflow Status Counter %20"PRIu64"l" "u""\n",
11856 le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
11857 printf(" Unexpected Completion Status Counter %20"PRIu64"l" "u""\n",
11858 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
11859 printf(" Complete Abort Status Counter %20"PRIu64"l" "u""\n",
11860 le64_to_cpu(pcie_stats->completeAbortStatusCount));
11861 printf(" Completion Timeout Status Counter %20"PRIu64"l" "u""\n",
11862 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
11863 printf(" Flow Control Error Status Counter %20"PRIu64"l" "u""\n",
11864 le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
11865 printf(" Poisoned TLP Status Counter %20"PRIu64"l" "u""\n",
11866 le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
11867 printf(" Dlink Protocol Error Status Counter %20"PRIu64"l" "u""\n",
11868 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
11869 printf(" Advisory Non Fatal Error Status Counter %20"PRIu64"l" "u""\n",
11870 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
11871 printf(" Replay Timer TO Status Counter %20"PRIu64"l" "u""\n",
11872 le64_to_cpu(pcie_stats->replayTimerToStatusCount));
11873 printf(" Replay Number Rollover Status Counter %20"PRIu64"l" "u""\n",
11874 le64_to_cpu(pcie_stats->replayNumRolloverStCount));
11875 printf(" Bad DLLP Status Counter %20"PRIu64"l" "u""\n",
11876 le64_to_cpu(pcie_stats->badDllpStatusCount));
11877 printf(" Bad TLP Status Counter %20"PRIu64"l" "u""\n",
11878 le64_to_cpu(pcie_stats->badTlpStatusCount));
11879 printf(" Receiver Error Status Counter %20"PRIu64"l" "u""\n",
11880 le64_to_cpu(pcie_stats->receiverErrStatusCount));
11881
11882}
11883
11884static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
11885{
11886 struct json_object *root = json_create_object()json_object_new_object();
11887
11888 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
)))
11889 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
)))
;
11890 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)))
11891 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)))
;
11892 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)))
11893 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)))
;
11894
11895 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
)))
11896 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
)))
;
11897 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
)))
11898 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
)))
;
11899 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
)))
11900 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
)))
;
11901 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
)))
11902 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
)))
;
11903 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
)))
11904 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
)))
;
11905 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)))
11906 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)))
;
11907 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
)))
11908 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
)))
;
11909 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
)))
11910 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
)))
;
11911 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
)))
11912 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
)))
;
11913 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
)))
11914 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
)))
;
11915 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)))
11916 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)))
;
11917 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)))
11918 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)))
;
11919 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
)))
11920 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
)))
;
11921
11922 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11923 printf("\n");
11924
11925 json_free_object(root)json_object_put(root);
11926}
11927
11928static int wdc_do_vs_nand_stats_sn810_2(struct libnvme_transport_handle *hdl, char *format)
11929{
11930 nvme_print_flags_t fmt;
11931 uint8_t *data = NULL((void*)0);
11932 int ret;
11933
11934 data = NULL((void*)0);
11935 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
11936 NVME_NSID_ALL);
11937
11938 if (ret) {
11939 nvme_show_error("ERROR: WDC: %s : Failed to retrieve NAND stats", __func__)nvme_show_message(1, "ERROR: WDC: %s : Failed to retrieve NAND stats"
, __func__)
;
11940 goto out;
11941 } else {
11942 ret = validate_output_format(format, &fmt);
11943 if (ret < 0) {
11944 nvme_show_error("ERROR: WDC: %s : invalid output format", __func__)nvme_show_message(1, "ERROR: WDC: %s : invalid output format"
, __func__)
;
11945 goto out;
11946 }
11947
11948 /* parse the data */
11949 switch (fmt) {
11950 case NORMAL:
11951 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS0x1);
11952 break;
11953 case JSON:
11954 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS0x1);
11955 break;
11956 default:
11957 break;
11958 }
11959 }
11960
11961out:
11962 free(data);
11963 return ret;
11964}
11965
11966static int wdc_do_vs_nand_stats(struct libnvme_transport_handle *hdl, char *format)
11967{
11968 nvme_print_flags_t fmt;
11969 uint8_t *output = NULL((void*)0);
11970 __u16 version = 0;
11971 int ret;
11972
11973 output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE0x200, sizeof(uint8_t));
11974 if (!output) {
11975 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
11976 ret = -1;
11977 goto out;
11978 }
11979
11980 ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID0xFB,
11981 (void *)output, WDC_NVME_NAND_STATS_SIZE0x200);
11982 if (ret) {
11983 nvme_show_error("ERROR: WDC: %s : Failed to retrieve NAND stats", __func__)nvme_show_message(1, "ERROR: WDC: %s : Failed to retrieve NAND stats"
, __func__)
;
11984 goto out;
11985 } else {
11986 ret = validate_output_format(format, &fmt);
11987 if (ret < 0) {
11988 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11989 goto out;
11990 }
11991
11992 version = output[WDC_NVME_NAND_STATS_SIZE0x200 - 2];
11993
11994 /* parse the data */
11995 switch (fmt) {
11996 case NORMAL:
11997 wdc_print_nand_stats_normal(version, output);
11998 break;
11999 case JSON:
12000 wdc_print_nand_stats_json(version, output);
12001 break;
12002 default:
12003 break;
12004 }
12005 }
12006
12007out:
12008 free(output);
12009 return ret;
12010}
12011
12012static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd,
12013 struct plugin *plugin)
12014{
12015 const char *desc = "Retrieve NAND statistics.";
12016 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12017 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12018 __u64 capabilities = 0;
12019 uint32_t read_device_id = 0, read_vendor_id = 0;
12020 int ret;
12021
12022 struct config {
12023 char *output_format;
12024 };
12025
12026 struct config cfg = {
12027 .output_format = "normal",
12028 };
12029
12030 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12031 OPT_END(){ ((void*)0) }
12032 };
12033
12034 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12035 if (ret)
12036 return ret;
12037
12038 cfg.output_format = nvme_args.output_format;
12039
12040 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12041 if (ret)
12042 return ret;
12043
12044 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12045
12046 if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200)) {
12047 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12048 ret = -1;
12049 } else {
12050 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
12051 if (ret < 0) {
12052 nvme_show_error("ERROR: WDC: %s: failure to get pci ids, ret = %d", __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: failure to get pci ids, ret = %d"
, __func__, ret)
;
12053 return -1;
12054 }
12055
12056 switch (read_device_id) {
12057 case WDC_NVME_SN820CL_DEV_ID0x5037:
12058 ret = wdc_do_vs_nand_stats_sn810_2(hdl,
12059 cfg.output_format);
12060 break;
12061 default:
12062 ret = wdc_do_vs_nand_stats(hdl, cfg.output_format);
12063 break;
12064 }
12065 }
12066
12067 if (ret)
12068 nvme_show_error("ERROR: WDC: Failure reading NAND statistics, ret = %d", ret)nvme_show_message(1, "ERROR: WDC: Failure reading NAND statistics, ret = %d"
, ret)
;
12069
12070 return ret;
12071}
12072
12073static int wdc_do_vs_pcie_stats(struct libnvme_transport_handle *hdl,
12074 struct wdc_vs_pcie_stats *pcieStatsPtr)
12075{
12076 int ret;
12077 struct libnvme_passthru_cmd admin_cmd;
12078 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
12079
12080 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12081 admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE0xD1;
12082 admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
12083 admin_cmd.data_len = pcie_stats_size;
12084
12085 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
12086
12087 return ret;
12088}
12089
12090static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd,
12091 struct plugin *plugin)
12092{
12093 const char *desc = "Retrieve PCIE statistics.";
12094 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12095 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12096 nvme_print_flags_t fmt;
12097 int ret;
12098 __u64 capabilities = 0;
12099 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
12100 struct wdc_vs_pcie_stats *pcieStatsPtr = NULL((void*)0);
12101 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
12102
12103 struct config {
12104 char *output_format;
12105 };
12106
12107 struct config cfg = {
12108 .output_format = "normal",
12109 };
12110
12111 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12112 OPT_END(){ ((void*)0) }
12113 };
12114
12115 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12116 if (ret)
12117 return ret;
12118
12119 cfg.output_format = nvme_args.output_format;
12120
12121 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12122 if (ret)
12123 return ret;
12124
12125 ret = validate_output_format(cfg.output_format, &fmt);
12126 if (ret < 0) {
12127 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12128 goto out;
12129 }
12130
12131 pcieStatsPtr = libnvme_alloc_huge(pcie_stats_size, &mh);
12132 if (!pcieStatsPtr) {
12133 nvme_show_error("ERROR: WDC: PCIE Stats alloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: PCIE Stats alloc: %s", libnvme_strerror
((*__errno_location ())))
;
12134 ret = -1;
12135 goto out;
12136 }
12137
12138 memset((void *)pcieStatsPtr, 0, pcie_stats_size);
12139
12140 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12141
12142 if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000)) {
12143 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12144 ret = -1;
12145 } else {
12146 ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr);
12147 if (ret) {
12148 nvme_show_error("ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x", ret)nvme_show_message(1, "ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x"
, ret)
;
12149 } else {
12150 /* parse the data */
12151 switch (fmt) {
12152 case NORMAL:
12153 wdc_print_pcie_stats_normal(pcieStatsPtr);
12154 break;
12155 case JSON:
12156 wdc_print_pcie_stats_json(pcieStatsPtr);
12157 break;
12158 default:
12159 break;
12160 }
12161 }
12162 }
12163out:
12164 return ret;
12165}
12166
12167static int wdc_vs_drive_info(int argc, char **argv,
12168 struct command *command, struct plugin *plugin)
12169{
12170 const char *desc = "Send a vs-drive-info command.";
12171 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12172 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12173 nvme_print_flags_t fmt;
12174 uint64_t capabilities = 0;
12175 int ret;
12176 __le32 result;
12177 __u16 size;
12178 double rev;
12179 struct libnvme_passthru_cmd cmd;
12180 struct nvme_id_ctrl ctrl;
12181 char vsData[32] = {0};
12182 char major_rev = 0, minor_rev = 0;
12183 __u8 *data = NULL((void*)0);
12184 __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
12185 __u16 boot_spec_major = 0, boot_spec_minor = 0;
12186 struct json_object *root = NULL((void*)0);
12187 char formatter[41] = { 0 };
12188 char rev_str[16] = { 0 };
12189 uint32_t read_device_id = -1, read_vendor_id = -1;
12190 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12191 struct ocp_drive_info info;
12192 __u32 data_len = 0;
12193 unsigned int num_dwords = 0;
12194
12195 struct config {
12196 char *output_format;
12197 };
12198
12199 struct config cfg = {
12200 .output_format = "normal",
12201 };
12202
12203 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12204 OPT_END(){ ((void*)0) }
12205 };
12206
12207 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12208 if (ret)
12209 return ret;
12210
12211 cfg.output_format = nvme_args.output_format;
12212
12213 ret = validate_output_format(cfg.output_format, &fmt);
12214 if (ret < 0) {
12215 nvme_show_error("ERROR: WDC %s invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s invalid output format", __func__
)
;
12216 return ret;
12217 }
12218
12219 /* get the id ctrl data used to fill in drive info below */
12220 nvme_init_identify_ctrl(&cmd, &ctrl);
12221 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12222 if (ret) {
12223 nvme_show_error("ERROR: WDC %s: Identify Controller failed", __func__)nvme_show_message(1, "ERROR: WDC %s: Identify Controller failed"
, __func__)
;
12224 return ret;
12225 }
12226
12227 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12228 if (ret || !wdc_check_device(ctx, hdl))
12229 return -1;
12230
12231 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12232
12233 if ((capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000) == WDC_DRIVE_CAP_INFO0x0000000000080000) {
12234 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
12235 if (ret < 0) {
12236 nvme_show_error("ERROR: WDC: %s: failure to get pci ids, ret = %d", __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: failure to get pci ids, ret = %d"
, __func__, ret)
;
12237 goto out;
12238 }
12239
12240 switch (read_device_id) {
12241 case WDC_NVME_SN640_DEV_ID0x2400:
12242 case WDC_NVME_SN640_DEV_ID_10x2401:
12243 case WDC_NVME_SN640_DEV_ID_20x2402:
12244 case WDC_NVME_SN640_DEV_ID_30x2404:
12245 case WDC_NVME_SN650_DEV_ID0x2700:
12246 case WDC_NVME_SN650_DEV_ID_10x2701:
12247 case WDC_NVME_SN650_DEV_ID_20x2702:
12248 case WDC_NVME_SN650_DEV_ID_30x2720:
12249 case WDC_NVME_SN650_DEV_ID_40x2721:
12250 case WDC_NVME_SN655_DEV_ID0x2722:
12251 case WDC_NVME_SN655_DEV_ID_10x2723:
12252 case WDC_NVME_SN560_DEV_ID_10x2712:
12253 case WDC_NVME_SN560_DEV_ID_20x2713:
12254 case WDC_NVME_SN560_DEV_ID_30x2714:
12255 case WDC_NVME_SN550_DEV_ID0x2708:
12256 case WDC_NVME_ZN350_DEV_ID0x5010:
12257 case WDC_NVME_ZN350_DEV_ID_10x5018:
12258 ret = wdc_do_drive_info(hdl, &result);
12259
12260 if (!ret) {
12261 size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
12262 rev = (double)(cpu_to_le32(result) & 0x0000ffff);
12263
12264 if (fmt == NORMAL) {
12265 printf("Drive HW Revision: %4.1f\n", (.1 * rev));
12266 printf("FTL Unit Size: 0x%x KB\n", size);
12267 printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
12268 } else if (fmt == JSON) {
12269 root = json_create_object()json_object_new_object();
12270 snprintf(rev_str, sizeof(rev_str),
12271 "%4.1f", (.1 * rev));
12272 json_object_add_value_string(root, "Drive HW Revision", rev_str);
12273
12274 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)))
;
12275 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
12276 json_object_add_value_string(root, "Customer SN", formatter);
12277
12278 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12279 printf("\n");
12280
12281 json_free_object(root)json_object_put(root);
12282 }
12283 }
12284 break;
12285 case WDC_NVME_SN730_DEV_ID0x5006:
12286 memcpy(vsData, &ctrl.vs[0], 32);
12287
12288 major_rev = ctrl.sn[12];
12289 minor_rev = ctrl.sn[13];
12290
12291 if (fmt == NORMAL) {
12292 printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev);
12293 printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
12294 } else if (fmt == JSON) {
12295 root = json_create_object()json_object_new_object();
12296 snprintf(rev_str, sizeof(rev_str), "%c.%c",
12297 major_rev, minor_rev);
12298 json_object_add_value_string(root, "Drive HW Revison", rev_str);
12299 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
12300 json_object_add_value_string(root, "Customer SN", formatter);
12301
12302 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12303 printf("\n");
12304
12305 json_free_object(root)json_object_put(root);
12306 }
12307 break;
12308 case WDC_NVME_SN820CL_DEV_ID0x5037:
12309 /* Get the Drive HW Rev from the C6 Log page */
12310 ret = nvme_get_hw_rev_log(hdl, &data, 0,
12311 NVME_NSID_ALL);
12312 if (!ret) {
12313 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
12314
12315 major_rev = log_data->hw_rev_gdr;
12316
12317 free(data);
12318 data = NULL((void*)0);
12319 } else {
12320 nvme_show_error("ERROR: WDC: %s: failure to get hw revision log", __func__)nvme_show_message(1, "ERROR: WDC: %s: failure to get hw revision log"
, __func__)
;
12321 ret = -1;
12322 goto out;
12323 }
12324
12325 /* Get the Smart C0 log page */
12326 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
12327 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12328 ret = -1;
12329 goto out;
12330 }
12331
12332 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
12333 0, NVME_NSID_ALL);
12334
12335 if (!ret) {
12336 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12337
12338 /* Set the FTL Unit size */
12339 ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
12340
12341 /* Set the Boot Spec Version */
12342 boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12343 boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12344
12345 /* Set the Drive Ownership Status */
12346 tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
12347 free(data);
12348 } else {
12349 nvme_show_error("ERROR: WDC: %s: failure to get extended smart cloud log", __func__)nvme_show_message(1, "ERROR: WDC: %s: failure to get extended smart cloud log"
, __func__)
;
12350 ret = -1;
12351 goto out;
12352 }
12353
12354 if (fmt == NORMAL) {
12355 printf("Drive HW Revision: %2d\n", major_rev);
12356 printf("FTL Unit Size: %d\n", ftl_unit_size);
12357 printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
12358 printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
12359
12360 } else if (fmt == JSON) {
12361 root = json_create_object()json_object_new_object();
12362
12363 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))
;
12364 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))
;
12365 snprintf(rev_str, sizeof(rev_str), "%d.%d",
12366 boot_spec_major, boot_spec_minor);
12367 json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
12368 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))
;
12369
12370 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12371 printf("\n");
12372
12373 json_free_object(root)json_object_put(root);
12374 }
12375
12376 break;
12377 case WDC_NVME_SN861_DEV_ID0x2750:
12378 case WDC_NVME_SN861_DEV_ID_10x2751:
12379 case WDC_NVME_SN861_DEV_ID_20x2752:
12380 data_len = sizeof(info);
12381 num_dwords = data_len / 4;
12382 if (data_len % 4 != 0)
12383 num_dwords += 1;
12384
12385 struct libnvme_passthru_cmd cmd = {
12386 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
12387 .cdw10 = num_dwords,
12388 .cdw12 = WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2,
12389 .addr = (__u64)(uintptr_t)&info,
12390 .data_len = data_len,
12391 };
12392 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12393 if (!ret) {
12394 __u16 hw_rev_major, hw_rev_minor;
12395
12396 hw_rev_major = le32_to_cpu(info.hw_revision) / 10;
12397 hw_rev_minor = le32_to_cpu(info.hw_revision) % 10;
12398 if (fmt == NORMAL) {
12399 printf("HW Revision : %" PRIu32"u" ".%" PRIu32"u" "\n",
12400 hw_rev_major, hw_rev_minor);
12401 printf("FTL Unit Size : %" PRIu32"u" "\n",
12402 le32_to_cpu(info.ftl_unit_size));
12403 } else if (fmt == JSON) {
12404 char buf[20];
12405
12406 root = json_create_object()json_object_new_object();
12407
12408 memset((void *)buf, 0, 20);
12409 snprintf(buf, sizeof(buf),
12410 "%" PRIu32"u" ".%" PRIu32"u",
12411 hw_rev_major, hw_rev_minor);
12412
12413 json_object_add_value_string(root,
12414 "hw_revision", buf);
12415 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)))
12416 "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
12417 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)))
;
12418
12419 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12420 printf("\n");
12421 json_free_object(root)json_object_put(root);
12422 }
12423 }
12424 break;
12425 default:
12426 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12427 ret = -1;
12428 break;
12429 }
12430 } else {
12431 nvme_show_error("ERROR: WDC: capability not supported by this device")nvme_show_message(1, "ERROR: WDC: capability not supported by this device"
)
;
12432 ret = -1;
12433 }
12434
12435out:
12436 nvme_show_status(ret);
12437 return ret;
12438}
12439
12440static int wdc_vs_temperature_stats(int argc, char **argv,
12441 struct command *command, struct plugin *plugin)
12442{
12443 const char *desc = "Send a vs-temperature-stats command.";
12444 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12445 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12446 struct libnvme_passthru_cmd cmd;
12447 struct nvme_smart_log smart_log;
12448 struct nvme_id_ctrl id_ctrl;
12449 nvme_print_flags_t fmt;
12450 uint64_t capabilities = 0;
12451 __u64 hctm_tmt;
12452 int temperature, temp_tmt1, temp_tmt2;
12453 int ret;
12454
12455 struct config {
12456 char *output_format;
12457 };
12458
12459 struct config cfg = {
12460 .output_format = "normal",
12461 };
12462
12463 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12464 OPT_END(){ ((void*)0) }
12465 };
12466
12467 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12468 if (ret)
12469 return ret;
12470
12471 cfg.output_format = nvme_args.output_format;
12472
12473 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12474 if (ret)
12475 return ret;
12476
12477 ret = validate_output_format(cfg.output_format, &fmt);
12478 if (ret < 0) {
12479 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12480 goto out;
12481 }
12482
12483 /* check if command is supported */
12484 wdc_check_device(ctx, hdl);
12485 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12486 if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) != WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) {
12487 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12488 ret = -1;
12489 goto out;
12490 }
12491
12492 /* get the temperature stats or report errors */
12493 nvme_init_identify_ctrl(&cmd, &id_ctrl);
12494 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12495 if (ret)
12496 goto out;
12497 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
12498 if (ret)
12499 goto out;
12500
12501 /* convert from kelvins to degrees Celsius */
12502 temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
12503
12504 /* retrieve HCTM Thermal Management Temperatures */
12505 nvme_init_get_features(&cmd, 0x10, NVME_GET_FEATURES_SEL_CURRENT);
12506 libnvme_exec_admin_passthru(hdl, &cmd);
12507 hctm_tmt = cmd.result;
12508 temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
12509 temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
12510
12511 if (fmt == NORMAL) {
12512 /* print the temperature stats */
12513 printf("Temperature Stats for NVME device:%s namespace-id:%x\n",
12514 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
12515
12516 printf("Current Composite Temperature : %d °C\n", temperature);
12517 printf("WCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.wctemp - 273);
12518 printf("CCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.cctemp - 273);
12519 printf("DITT support : 0\n");
12520 printf("HCTM support : %"PRIu16"hu""\n", id_ctrl.hctma);
12521
12522 printf("HCTM Light (TMT1) : %"PRIu16"hu"" °C\n", temp_tmt1);
12523 printf("TMT1 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp1_trans_count);
12524 printf("TMT1 Total Time : %"PRIu32"u""\n", smart_log.thm_temp1_total_time);
12525
12526 printf("HCTM Heavy (TMT2) : %"PRIu16"hu"" °C\n", temp_tmt2);
12527 printf("TMT2 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp2_trans_count);
12528 printf("TMT2 Total Time : %"PRIu32"u""\n", smart_log.thm_temp2_total_time);
12529 printf("Thermal Shutdown Threshold : 95 °C\n");
12530 } else if (fmt == JSON) {
12531 struct json_object *root;
12532
12533 root = json_create_object()json_object_new_object();
12534
12535 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)))
;
12536 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)))
;
12537 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)))
;
12538 json_object_add_value_int(root, "DITT support", 0)json_object_object_add(root, "DITT support", json_object_new_int
(0))
;
12539 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)))
;
12540
12541 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)))
;
12542 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)))
;
12543 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)))
;
12544
12545 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)))
;
12546 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)))
;
12547 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)))
;
12548 json_object_add_value_int(root, "Thermal Shutdown Threshold", 95)json_object_object_add(root, "Thermal Shutdown Threshold", json_object_new_int
(95))
;
12549
12550 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12551 printf("\n");
12552
12553 json_free_object(root)json_object_put(root);
12554 } else {
12555 nvme_show_error("%s: Invalid format", __func__)nvme_show_message(1, "%s: Invalid format", __func__);
12556 }
12557
12558out:
12559 nvme_show_status(ret);
12560 return ret;
12561}
12562
12563static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12564{
12565 const char *desc = "Send a capabilities command.";
12566 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12567 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12568 uint64_t capabilities = 0;
12569 int ret;
12570
12571 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12572 OPT_END(){ ((void*)0) }
12573 };
12574
12575 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12576 if (ret)
12577 return ret;
12578
12579 /* get capabilities */
12580 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12581 if (ret || !wdc_check_device(ctx, hdl))
12582 return -1;
12583
12584 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12585
12586 /* print command and supported status */
12587 printf("WDC Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
12588 printf("cap-diag : %s\n",
12589 capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 ? "Supported" : "Not Supported");
12590 printf("drive-log : %s\n",
12591 capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 ? "Supported" : "Not Supported");
12592 printf("get-crash-dump : %s\n",
12593 capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 ? "Supported" : "Not Supported");
12594 printf("get-pfail-dump : %s\n",
12595 capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 ? "Supported" : "Not Supported");
12596 printf("id-ctrl : Supported\n");
12597 printf("purge : %s\n",
12598 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12599 printf("purge-monitor : %s\n",
12600 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12601 printf("vs-internal-log : %s\n",
12602 capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
? "Supported" : "Not Supported");
12603 printf("vs-nand-stats : %s\n",
12604 capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
12605 printf("vs-smart-add-log : %s\n",
12606 capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
12607 printf("--C0 Log Page : %s\n",
12608 capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
12609 printf("--C1 Log Page : %s\n",
12610 capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
12611 printf("--C3 Log Page : %s\n",
12612 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12613 printf("--CA Log Page : %s\n",
12614 capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
12615 printf("--D0 Log Page : %s\n",
12616 capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
12617 printf("clear-pcie-correctable-errors : %s\n",
12618 capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
12619 printf("drive-essentials : %s\n",
12620 capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 ? "Supported" : "Not Supported");
12621 printf("get-drive-status : %s\n",
12622 capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
12623 printf("clear-assert-dump : %s\n",
12624 capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
12625 printf("drive-resize : %s\n",
12626 capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100 ? "Supported" : "Not Supported");
12627 printf("vs-fw-activate-history : %s\n",
12628 capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" : "Not Supported");
12629 printf("clear-fw-activate-history : %s\n",
12630 capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" : "Not Supported");
12631 printf("vs-telemetry-controller-option: %s\n",
12632 capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
12633 printf("vs-error-reason-identifier : %s\n",
12634 capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
12635 printf("log-page-directory : %s\n",
12636 capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
12637 printf("namespace-resize : %s\n",
12638 capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
12639 printf("vs-drive-info : %s\n",
12640 capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
12641 printf("vs-temperature-stats : %s\n",
12642 capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
12643 printf("cloud-SSD-plugin-version : %s\n",
12644 capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
12645 printf("vs-pcie-stats : %s\n",
12646 capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
12647 printf("get-error-recovery-log : %s\n",
12648 capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
12649 printf("get-dev-capabilities-log : %s\n",
12650 capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
12651 printf("get-unsupported-reqs-log : %s\n",
12652 capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
12653 printf("get-latency-monitor-log : %s\n",
12654 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12655 printf("cloud-boot-SSD-version : %s\n",
12656 capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" : "Not Supported");
12657 printf("vs-cloud-log : %s\n",
12658 capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
12659 printf("vs-hw-rev-log : %s\n",
12660 capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
12661 printf("vs-device_waf : %s\n",
12662 capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
12663 printf("set-latency-monitor-feature : %s\n",
12664 capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
12665 printf("capabilities : Supported\n");
12666 return 0;
12667}
12668
12669static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd,
12670 struct plugin *plugin)
12671{
12672 const char *desc = "Get Cloud SSD Plugin Version command.";
12673 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12674 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12675 uint64_t capabilities = 0;
12676 int ret;
12677
12678 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12679 OPT_END(){ ((void*)0) }
12680 };
12681
12682 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12683 if (ret)
12684 return ret;
12685
12686 /* get capabilities */
12687 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12688 if (ret || !wdc_check_device(ctx, hdl))
12689 return -1;
12690
12691 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12692
12693 if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) {
12694 /* print command and supported status */
12695 printf("WDC Cloud SSD Plugin Version: 1.0\n");
12696 } else {
12697 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12698 }
12699
12700 return 0;
12701}
12702
12703static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd,
12704 struct plugin *plugin)
12705{
12706 const char *desc = "Get Cloud Boot SSD Version command.";
12707 const char *namespace_id = "desired namespace id";
12708 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12709 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12710 uint64_t capabilities = 0;
12711 int ret;
12712 int major = 0, minor = 0;
12713 __u8 *data = NULL((void*)0);
12714 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12715
12716 struct config {
12717 __u32 namespace_id;
12718 };
12719
12720 struct config cfg = {
12721 .namespace_id = NVME_NSID_ALL,
12722 };
12723
12724 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12725 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
12726 nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_id, 0, nvme_nsid_values}
,
12727 OPT_END(){ ((void*)0) }
12728 };
12729
12730 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12731 if (ret)
12732 return ret;
12733
12734 /* get capabilities */
12735 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12736 if (ret || !wdc_check_device(ctx, hdl))
12737 return -1;
12738
12739 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12740
12741 if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) {
12742 /* Get the 0xC0 Smart Cloud Attribute V1 log data */
12743 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
12744 cfg.namespace_id);
12745
12746 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12747 if (!ret) {
12748 major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12749 minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12750
12751 /* print the version returned from the log page */
12752 printf("HyperScale Boot Version: %d.%d\n", major, minor);
12753 } else {
12754 nvme_show_error("ERROR: WDC: Unable to read Extended Smart/C0 Log Page data")nvme_show_message(1, "ERROR: WDC: Unable to read Extended Smart/C0 Log Page data"
)
;
12755 ret = -1;
12756 }
12757
12758 free(data);
12759 } else {
12760 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12761 }
12762
12763 return ret;
12764}
12765
12766static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12767{
12768 const char *desc = "Get Enclosure Log.";
12769 const char *file = "Output file pathname.";
12770 const char *size = "Data retrieval transfer size.";
12771 const char *log = "Enclosure Log Page ID.";
12772 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12773 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12774 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *output_file = NULL((void*)0);
12775 FILE *output_fd;
12776 int xfer_size = 0;
12777 int len;
12778 int err = 0;
12779
12780 struct config {
12781 char *file;
12782 __u32 xfer_size;
12783 __u32 log_id;
12784 };
12785
12786 struct config cfg = {
12787 .file = NULL((void*)0),
12788 .xfer_size = 0,
12789 .log_id = 0xffffffff,
12790 };
12791
12792 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12793 OPT_FILE("output-file", 'O', &cfg.file, file){"output-file", 'O', "FILE", CFG_FILE, _Generic(&cfg.file
, char ** : (&cfg.file), const char ** : (&cfg.file))
, ARGCONFIG_ARG_REQUIRED, file, 0, }
,
12794 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size){"transfer-size", 's', "NUM", CFG_POSITIVE, _Generic(&cfg
.xfer_size, uint32_t * : (&cfg.xfer_size)), ARGCONFIG_ARG_REQUIRED
, size, 0, }
,
12795 OPT_UINT("log-id", 'l', &cfg.log_id, log){"log-id", 'l', "NUM", CFG_POSITIVE, _Generic(&cfg.log_id
, uint32_t * : (&cfg.log_id)), ARGCONFIG_ARG_REQUIRED, log
, 0, }
,
12796 OPT_END(){ ((void*)0) }
12797 };
12798
12799 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12800 if (err)
12801 return err;
12802
12803 if (!wdc_enc_check_model(hdl))
12804 return -EINVAL22;
12805
12806 if (cfg.log_id > 0xff) {
12807 nvme_show_error(nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12808 "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n",nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12809 cfg.log_id)nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
;
12810 return -EINVAL22;
12811 }
12812
12813 if (cfg.xfer_size) {
12814 xfer_size = cfg.xfer_size;
12815 if (!wdc_check_power_of_2(cfg.xfer_size)) {
12816 nvme_show_error("%s: ERROR: xfer-size (%d) must be a power of 2",nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
12817 __func__, cfg.xfer_size)nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
;
12818 return -EINVAL22;
12819 }
12820 }
12821
12822 /* Log IDs are only for specific enclosures */
12823 if (cfg.log_id) {
12824 xfer_size = (xfer_size) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000;
12825 len = !cfg.file ? 0 : strlen(cfg.file);
12826 if (len > 0) {
12827 output_file = fopen(cfg.file, "wb");
12828 if (!output_file) {
12829 nvme_show_error("%s: ERROR: opening:%s: %s", __func__, cfg.file,nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
12830 libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
;
12831 return -EINVAL22;
12832 }
12833 output_fd = output_file;
12834 } else {
12835 output_fd = stdoutstdout;
12836 }
12837 if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 ||
12838 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 ||
12839 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 ||
12840 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4) {
12841 nvme_show_error("args - sz:%x logid:%x of:%s", xfer_size, cfg.log_id,nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
12842 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12843 err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size,
12844 WDC_NVME_ENC_NIC_LOG_SIZE0x400000, output_fd);
12845 } else {
12846 nvme_show_error("args - sz:%x logid:%x of:%s", xfer_size, cfg.log_id,nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
12847 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12848 err = wdc_enc_submit_move_data(hdl, NULL((void*)0), 0, xfer_size, output_fd,
12849 cfg.log_id, 0, 0);
12850 }
12851
12852 if (err == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12853 nvme_show_error("No Log/Crashdump available")nvme_show_message(1, "No Log/Crashdump available");
12854 err = 0;
12855 } else if (err) {
12856 nvme_show_error("ERROR: 0x%x Failed to collect log-id:%x", err,nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
12857 cfg.log_id)nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
;
12858 }
12859 }
12860 return err;
12861}
12862
12863static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len,
12864 int xfer_size, FILE *out, int log_id,
12865 int cdw14, int cdw15)
12866{
12867 uint32_t response_size, more;
12868 int err;
12869 int handle;
12870 uint32_t offset = 0;
12871 char *buf;
12872
12873 buf = malloc(xfer_size);
12874 if (!buf) {
12875 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12876 return -1;
12877 }
12878 /* send something no matter what */
12879 cmd = (len) ? cmd : buf;
12880 len = (len) ? len : 0x20;
12881
12882 struct libnvme_passthru_cmd nvme_cmd = {
12883 .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND0xC9,
12884 .nsid = 0,
12885 .addr = (__u64)(uintptr_t) cmd,
12886 .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t),
12887 .cdw10 = len,
12888 .cdw12 = log_id,
12889 .cdw13 = 0,
12890 .cdw14 = cdw14,
12891 .cdw15 = cdw15,
12892 };
12893
12894 /* Handle to associate send request with receive request */
12895 if (shr_getrandom(&handle, sizeof(handle)) != 0) {
12896 nvme_show_error("%s: ERROR: failed to generate a random handle", __func__)nvme_show_message(1, "%s: ERROR: failed to generate a random handle"
, __func__)
;
12897 free(buf);
12898 return -1;
12899 }
12900 nvme_cmd.cdw11 = handle;
12901
12902#ifdef WDC_NVME_CLI_DEBUG
12903 unsigned char *d = (unsigned char *)nvme_cmd.addr;
12904 unsigned char *md = (unsigned char *)nvme_cmd.metadata;
12905
12906 printf("NVME_ADMIN_COMMAND:\n");
12907 printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ",
12908 nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2);
12909 printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, "
12910 nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10);
12911 printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, "
12912 nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15);
12913 printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n",
12914 nvme_cmd.timeout_ms, nvme_cmd.result, md, d);
12915#endif
12916 nvme_cmd.result = 0;
12917 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12918 if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) {
12919 nvme_show_error("%s: WARNING : WDC: No log ID:x%x available", __func__, log_id)nvme_show_message(1, "%s: WARNING : WDC: No log ID:x%x available"
, __func__, log_id)
;
12920 } else if (err) {
12921 nvme_show_error("%s: ERROR: WDC: NVMe Snd Mgmt", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Snd Mgmt", __func__
)
;
12922 nvme_show_status(err);
12923 } else {
12924 if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12925 free(buf);
12926 return WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF;
12927 }
12928
12929 do {
12930 /* Sent request, now go retrieve response */
12931 nvme_cmd.flags = 0;
12932 nvme_cmd.opcode = WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA;
12933 nvme_cmd.addr = (__u64)(uintptr_t) buf;
12934 nvme_cmd.data_len = xfer_size;
12935 nvme_cmd.cdw10 = xfer_size / sizeof(uint32_t);
12936 nvme_cmd.cdw11 = handle;
12937 nvme_cmd.cdw12 = log_id;
12938 nvme_cmd.cdw13 = offset / sizeof(uint32_t);
12939 nvme_cmd.cdw14 = cdw14;
12940 nvme_cmd.cdw15 = cdw15;
12941 nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
12942 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12943 if (err) {
12944 more = 0;
12945 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__
)
;
12946 nvme_show_status(err);
12947 } else {
12948 more = nvme_cmd.result & WDC_RESULT_MORE_DATA0x80000000;
12949 response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA0x80000000;
12950 fwrite(buf, response_size, 1, out);
12951 offset += response_size;
12952 if (more && (response_size & (sizeof(uint32_t)-1))) {
12953 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned",nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
12954 __func__, response_size)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
;
12955 }
12956 }
12957 } while (more);
12958 }
12959
12960 free(buf);
12961 return err;
12962}
12963
12964static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out)
12965{
12966 __u8 *dump_data;
12967 __u32 curr_data_offset, curr_data_len;
12968 int i, ret = -1;
12969 struct libnvme_passthru_cmd admin_cmd;
12970 __u32 dump_length = data_len;
12971 __u32 numd;
12972 __u16 numdu, numdl;
12973
12974 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
12975 if (!dump_data) {
12976 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12977 return -1;
12978 }
12979 memset(dump_data, 0, sizeof(__u8) * dump_length);
12980 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12981 curr_data_offset = 0;
12982 curr_data_len = xfer_size;
12983 i = 0;
12984
12985 numd = (curr_data_len >> 2) - 1;
12986 numdu = numd >> 16;
12987 numdl = numd & 0xffff;
12988 admin_cmd.opcode = nvme_admin_get_log_page;
12989 admin_cmd.nsid = curr_data_offset;
12990 admin_cmd.addr = (__u64)(uintptr_t) dump_data;
12991 admin_cmd.data_len = curr_data_len;
12992 admin_cmd.cdw10 = log_id | (numdl << 16);
12993 admin_cmd.cdw11 = numdu;
12994
12995 while (curr_data_offset < data_len) {
12996#ifdef WDC_NVME_CLI_DEBUG
12997 nvme_show_error(nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
12998 "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n",nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
12999 admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10,nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
13000 admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14)nvme_show_message(1, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n"
, admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd
.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd
.cdw14)
;
13001#endif
13002 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
13003 if (ret) {
13004 nvme_show_status(ret);
13005 nvme_show_error("%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx",nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
13006 __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr)nvme_show_message(1, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx"
, __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned
long)admin_cmd.addr)
;
13007 break;
13008 }
13009
13010 if ((curr_data_offset + xfer_size) <= data_len)
13011 curr_data_len = xfer_size;
13012 else
13013 curr_data_len = data_len - curr_data_offset; /* last transfer */
13014
13015 curr_data_offset += curr_data_len;
13016 numd = (curr_data_len >> 2) - 1;
13017 numdu = numd >> 16;
13018 numdl = numd & 0xffff;
13019 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
13020 admin_cmd.nsid = curr_data_offset;
13021 admin_cmd.data_len = curr_data_len;
13022 admin_cmd.cdw10 = log_id | (numdl << 16);
13023 admin_cmd.cdw11 = numdu;
13024 i++;
13025 }
13026 fwrite(dump_data, data_len, 1, out);
13027 free(dump_data);
13028 return ret;
13029}
13030
13031//------------------------------------------------------------------------------------
13032// Description: set latency monitor feature
13033//
13034int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd,
13035 struct plugin *plugin)
13036{
13037 const char *desc = "Set Latency Monitor feature.";
13038
13039 struct feature_latency_monitor buf = {0,};
13040 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
13041 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
13042 uint64_t capabilities = 0;
13043 __u64 result;
13044 int ret;
13045
13046 const char *active_bucket_timer_threshold =
13047 "This is the value that loads the Active Bucket Timer Threshold.";
13048 const char *active_threshold_a =
13049 "This is the value that loads into the Active Threshold A.";
13050 const char *active_threshold_b =
13051 "This is the value that loads into the Active Threshold B.";
13052 const char *active_threshold_c =
13053 "This is the value that loads into the Active Threshold C.";
13054 const char *active_threshold_d =
13055 "This is the value that loads into the Active Threshold D.";
13056 const char *active_latency_config =
13057 "This is the value that loads into the Active Latency Configuration.";
13058 const char *active_latency_minimum_window =
13059 "This is the value that loads into the Active Latency Minimum Window.";
13060 const char *debug_log_trigger_enable =
13061 "This is the value that loads into the Debug Log Trigger Enable.";
13062 const char *discard_debug_log = "Discard Debug Log.";
13063 const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable.";
13064
13065 struct config {
13066 __u16 active_bucket_timer_threshold;
13067 __u8 active_threshold_a;
13068 __u8 active_threshold_b;
13069 __u8 active_threshold_c;
13070 __u8 active_threshold_d;
13071 __u16 active_latency_config;
13072 __u8 active_latency_minimum_window;
13073 __u16 debug_log_trigger_enable;
13074 __u8 discard_debug_log;
13075 __u8 latency_monitor_feature_enable;
13076 };
13077
13078 struct config cfg = {
13079 .active_bucket_timer_threshold = 0x7E0,
13080 .active_threshold_a = 0x5,
13081 .active_threshold_b = 0x13,
13082 .active_threshold_c = 0x1E,
13083 .active_threshold_d = 0x2E,
13084 .active_latency_config = 0xFFF,
13085 .active_latency_minimum_window = 0xA,
13086 .debug_log_trigger_enable = 0,
13087 .discard_debug_log = 0,
13088 .latency_monitor_feature_enable = 0x7,
13089 };
13090
13091 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
13092 OPT_SHRT("active_bucket_timer_threshold", 't',{"active_bucket_timer_threshold", 't', "NUM", CFG_SHORT, _Generic
(&cfg.active_bucket_timer_threshold, uint16_t * : (&cfg
.active_bucket_timer_threshold)), ARGCONFIG_ARG_REQUIRED, active_bucket_timer_threshold
, 0, }
13093 &cfg.active_bucket_timer_threshold,{"active_bucket_timer_threshold", 't', "NUM", CFG_SHORT, _Generic
(&cfg.active_bucket_timer_threshold, uint16_t * : (&cfg
.active_bucket_timer_threshold)), ARGCONFIG_ARG_REQUIRED, active_bucket_timer_threshold
, 0, }
13094 active_bucket_timer_threshold){"active_bucket_timer_threshold", 't', "NUM", CFG_SHORT, _Generic
(&cfg.active_bucket_timer_threshold, uint16_t * : (&cfg
.active_bucket_timer_threshold)), ARGCONFIG_ARG_REQUIRED, active_bucket_timer_threshold
, 0, }
,
13095 OPT_BYTE("active_threshold_a", 'a', &cfg.active_threshold_a,{"active_threshold_a", 'a', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_a, uint8_t * : (&cfg.active_threshold_a
)), ARGCONFIG_ARG_REQUIRED, active_threshold_a, 0, }
13096 active_threshold_a){"active_threshold_a", 'a', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_a, uint8_t * : (&cfg.active_threshold_a
)), ARGCONFIG_ARG_REQUIRED, active_threshold_a, 0, }
,
13097 OPT_BYTE("active_threshold_b", 'b', &cfg.active_threshold_b,{"active_threshold_b", 'b', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_b, uint8_t * : (&cfg.active_threshold_b
)), ARGCONFIG_ARG_REQUIRED, active_threshold_b, 0, }
13098 active_threshold_b){"active_threshold_b", 'b', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_b, uint8_t * : (&cfg.active_threshold_b
)), ARGCONFIG_ARG_REQUIRED, active_threshold_b, 0, }
,
13099 OPT_BYTE("active_threshold_c", 'c', &cfg.active_threshold_c,{"active_threshold_c", 'c', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_c, uint8_t * : (&cfg.active_threshold_c
)), ARGCONFIG_ARG_REQUIRED, active_threshold_c, 0, }
13100 active_threshold_c){"active_threshold_c", 'c', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_c, uint8_t * : (&cfg.active_threshold_c
)), ARGCONFIG_ARG_REQUIRED, active_threshold_c, 0, }
,
13101 OPT_BYTE("active_threshold_d", 'd', &cfg.active_threshold_d,{"active_threshold_d", 'd', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_d, uint8_t * : (&cfg.active_threshold_d
)), ARGCONFIG_ARG_REQUIRED, active_threshold_d, 0, }
13102 active_threshold_d){"active_threshold_d", 'd', "NUM", CFG_BYTE, _Generic(&cfg
.active_threshold_d, uint8_t * : (&cfg.active_threshold_d
)), ARGCONFIG_ARG_REQUIRED, active_threshold_d, 0, }
,
13103 OPT_SHRT("active_latency_config", 'f',{"active_latency_config", 'f', "NUM", CFG_SHORT, _Generic(&
cfg.active_latency_config, uint16_t * : (&cfg.active_latency_config
)), ARGCONFIG_ARG_REQUIRED, active_latency_config, 0, }
13104 &cfg.active_latency_config, active_latency_config){"active_latency_config", 'f', "NUM", CFG_SHORT, _Generic(&
cfg.active_latency_config, uint16_t * : (&cfg.active_latency_config
)), ARGCONFIG_ARG_REQUIRED, active_latency_config, 0, }
,
13105 OPT_BYTE("active_latency_minimum_window", 'w',{"active_latency_minimum_window", 'w', "NUM", CFG_BYTE, _Generic
(&cfg.active_latency_minimum_window, uint8_t * : (&cfg
.active_latency_minimum_window)), ARGCONFIG_ARG_REQUIRED, active_latency_minimum_window
, 0, }
13106 &cfg.active_latency_minimum_window,{"active_latency_minimum_window", 'w', "NUM", CFG_BYTE, _Generic
(&cfg.active_latency_minimum_window, uint8_t * : (&cfg
.active_latency_minimum_window)), ARGCONFIG_ARG_REQUIRED, active_latency_minimum_window
, 0, }
13107 active_latency_minimum_window){"active_latency_minimum_window", 'w', "NUM", CFG_BYTE, _Generic
(&cfg.active_latency_minimum_window, uint8_t * : (&cfg
.active_latency_minimum_window)), ARGCONFIG_ARG_REQUIRED, active_latency_minimum_window
, 0, }
,
13108 OPT_SHRT("debug_log_trigger_enable", 'r',{"debug_log_trigger_enable", 'r', "NUM", CFG_SHORT, _Generic(
&cfg.debug_log_trigger_enable, uint16_t * : (&cfg.debug_log_trigger_enable
)), ARGCONFIG_ARG_REQUIRED, debug_log_trigger_enable, 0, }
13109 &cfg.debug_log_trigger_enable,{"debug_log_trigger_enable", 'r', "NUM", CFG_SHORT, _Generic(
&cfg.debug_log_trigger_enable, uint16_t * : (&cfg.debug_log_trigger_enable
)), ARGCONFIG_ARG_REQUIRED, debug_log_trigger_enable, 0, }
13110 debug_log_trigger_enable){"debug_log_trigger_enable", 'r', "NUM", CFG_SHORT, _Generic(
&cfg.debug_log_trigger_enable, uint16_t * : (&cfg.debug_log_trigger_enable
)), ARGCONFIG_ARG_REQUIRED, debug_log_trigger_enable, 0, }
,
13111 OPT_BYTE("discard_debug_log", 'l', &cfg.discard_debug_log,{"discard_debug_log", 'l', "NUM", CFG_BYTE, _Generic(&cfg
.discard_debug_log, uint8_t * : (&cfg.discard_debug_log))
, ARGCONFIG_ARG_REQUIRED, discard_debug_log, 0, }
13112 discard_debug_log){"discard_debug_log", 'l', "NUM", CFG_BYTE, _Generic(&cfg
.discard_debug_log, uint8_t * : (&cfg.discard_debug_log))
, ARGCONFIG_ARG_REQUIRED, discard_debug_log, 0, }
,
13113 OPT_BYTE("latency_monitor_feature_enable", 'e',{"latency_monitor_feature_enable", 'e', "NUM", CFG_BYTE, _Generic
(&cfg.latency_monitor_feature_enable, uint8_t * : (&cfg
.latency_monitor_feature_enable)), ARGCONFIG_ARG_REQUIRED, latency_monitor_feature_enable
, 0, }
13114 &cfg.latency_monitor_feature_enable,{"latency_monitor_feature_enable", 'e', "NUM", CFG_BYTE, _Generic
(&cfg.latency_monitor_feature_enable, uint8_t * : (&cfg
.latency_monitor_feature_enable)), ARGCONFIG_ARG_REQUIRED, latency_monitor_feature_enable
, 0, }
13115 latency_monitor_feature_enable){"latency_monitor_feature_enable", 'e', "NUM", CFG_BYTE, _Generic
(&cfg.latency_monitor_feature_enable, uint8_t * : (&cfg
.latency_monitor_feature_enable)), ARGCONFIG_ARG_REQUIRED, latency_monitor_feature_enable
, 0, }
,
13116 OPT_END(){ ((void*)0) }
13117 };
13118
13119 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
13120
13121 if (ret)
13122 return ret;
13123
13124 /* get capabilities */
13125 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
13126 if (ret || !wdc_check_device(ctx, hdl))
13127 return -1;
13128
13129 capabilities = wdc_get_drive_capabilities(ctx, hdl);
13130
13131 if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000)) {
13132 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
13133 return -1;
13134 }
13135
13136 memset(&buf, 0, sizeof(struct feature_latency_monitor));
13137
13138 buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold;
13139 buf.active_threshold_a = cfg.active_threshold_a;
13140 buf.active_threshold_b = cfg.active_threshold_b;
13141 buf.active_threshold_c = cfg.active_threshold_c;
13142 buf.active_threshold_d = cfg.active_threshold_d;
13143 buf.active_latency_config = cfg.active_latency_config;
13144 buf.active_latency_minimum_window = cfg.active_latency_minimum_window;
13145 buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable;
13146 buf.discard_debug_log = cfg.discard_debug_log;
13147 buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable;
13148
13149 ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR0xC5, 1, 0, 0, 0,
13150 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result);
13151
13152 if (ret < 0) {
13153 nvme_show_err(ret, "set-feature");
13154 } else if (!ret) {
13155 printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n",
13156 NVME_FEAT_OCP_LATENCY_MONITOR0xC5);
13157 printf("active bucket timer threshold: 0x%x\n",
13158 buf.active_bucket_timer_threshold);
13159 printf("active threshold a: 0x%x\n", buf.active_threshold_a);
13160 printf("active threshold b: 0x%x\n", buf.active_threshold_b);
13161 printf("active threshold c: 0x%x\n", buf.active_threshold_c);
13162 printf("active threshold d: 0x%x\n", buf.active_threshold_d);
13163 printf("active latency config: 0x%x\n", buf.active_latency_config);
13164 printf("active latency minimum window: 0x%x\n",
13165 buf.active_latency_minimum_window);
13166 printf("debug log trigger enable: 0x%x\n",
13167 buf.debug_log_trigger_enable);
13168 printf("discard debug log: 0x%x\n", buf.discard_debug_log);
13169 printf("latency monitor feature enable: 0x%x\n",
13170 buf.latency_monitor_feature_enable);
13171 } else if (ret > 0)
13172 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
13173 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
13174
13175 return ret;
13176}
13177
13178/*
13179 * Externally available functions used to call the WDC Plugin commands
13180 */
13181int run_wdc_cloud_ssd_plugin_version(int argc, char **argv,
13182 struct command *command,
13183 struct plugin *plugin)
13184{
13185 return wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
13186}
13187
13188int run_wdc_vs_nand_stats(int argc, char **argv,
13189 struct command *command,
13190 struct plugin *plugin)
13191{
13192 return wdc_vs_nand_stats(argc, argv, command, plugin);
13193}
13194
13195int run_wdc_vs_smart_add_log(int argc, char **argv,
13196 struct command *command,
13197 struct plugin *plugin)
13198{
13199 return wdc_vs_smart_add_log(argc, argv, command, plugin);
13200}
13201
13202int run_wdc_clear_pcie_correctable_errors(int argc, char **argv,
13203 struct command *command,
13204 struct plugin *plugin)
13205{
13206 return wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
13207}
13208
13209int run_wdc_drive_status(int argc, char **argv,
13210 struct command *command,
13211 struct plugin *plugin)
13212{
13213 return wdc_drive_status(argc, argv, command, plugin);
13214}
13215
13216int run_wdc_clear_assert_dump(int argc, char **argv,
13217 struct command *command,
13218 struct plugin *plugin)
13219{
13220 return wdc_clear_assert_dump(argc, argv, command, plugin);
13221}
13222
13223int run_wdc_vs_telemetry_controller_option(int argc, char **argv,
13224 struct command *command,
13225 struct plugin *plugin)
13226{
13227 return wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
13228}
13229
13230int run_wdc_reason_identifier(int argc, char **argv,
13231 struct command *command,
13232 struct plugin *plugin)
13233{
13234 return wdc_reason_identifier(argc, argv, command, plugin);
13235}
13236
13237int run_wdc_log_page_directory(int argc, char **argv,
13238 struct command *command,
13239 struct plugin *plugin)
13240{
13241 return wdc_log_page_directory(argc, argv, command, plugin);
13242}
13243
13244int run_wdc_namespace_resize(int argc, char **argv,
13245 struct command *command,
13246 struct plugin *plugin)
13247{
13248 return wdc_namespace_resize(argc, argv, command, plugin);
13249}
13250
13251int run_wdc_vs_drive_info(int argc, char **argv,
13252 struct command *command,
13253 struct plugin *plugin)
13254{
13255 return wdc_vs_drive_info(argc, argv, command, plugin);
13256}
13257
13258int run_wdc_vs_pcie_stats(int argc, char **argv,
13259 struct command *command,
13260 struct plugin *plugin)
13261{
13262 return wdc_vs_pcie_stats(argc, argv, command, plugin);
13263}
13264
13265int run_wdc_get_latency_monitor_log(int argc, char **argv,
13266 struct command *command,
13267 struct plugin *plugin)
13268{
13269 return wdc_get_latency_monitor_log(argc, argv, command, plugin);
13270}
13271
13272int run_wdc_get_error_recovery_log(int argc, char **argv,
13273 struct command *command,
13274 struct plugin *plugin)
13275{
13276 return wdc_get_error_recovery_log(argc, argv, command, plugin);
13277}
13278
13279int run_wdc_get_dev_capabilities_log(int argc, char **argv,
13280 struct command *command,
13281 struct plugin *plugin)
13282{
13283 return wdc_get_dev_capabilities_log(argc, argv, command, plugin);
13284}
13285
13286int run_wdc_get_unsupported_reqs_log(int argc, char **argv,
13287 struct command *command,
13288 struct plugin *plugin)
13289{
13290 return wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
13291}
13292
13293int run_wdc_cloud_boot_SSD_version(int argc, char **argv,
13294 struct command *command,
13295 struct plugin *plugin)
13296{
13297 return wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
13298}
13299
13300int run_wdc_vs_cloud_log(int argc, char **argv,
13301 struct command *command,
13302 struct plugin *plugin)
13303{
13304 return wdc_vs_cloud_log(argc, argv, command, plugin);
13305}
13306
13307int run_wdc_vs_hw_rev_log(int argc, char **argv,
13308 struct command *command,
13309 struct plugin *plugin)
13310{
13311 return wdc_vs_hw_rev_log(argc, argv, command, plugin);
13312}
13313
13314int run_wdc_vs_device_waf(int argc, char **argv,
13315 struct command *command,
13316 struct plugin *plugin)
13317{
13318 return wdc_vs_device_waf(argc, argv, command, plugin);
13319}
13320
13321int run_wdc_set_latency_monitor_feature(int argc, char **argv,
13322 struct command *command,
13323 struct plugin *plugin)
13324{
13325 return wdc_set_latency_monitor_feature(argc, argv, command, plugin);
13326}
13327
13328int run_wdc_vs_temperature_stats(int argc, char **argv,
13329 struct command *command,
13330 struct plugin *plugin)
13331{
13332 return wdc_vs_temperature_stats(argc, argv, command, plugin);
13333}
13334
13335int run_wdc_cu_smart_log(int argc, char **argv,
13336 struct command *command,
13337 struct plugin *plugin)
13338{
13339 return wdc_cu_smart_log(argc, argv, command, plugin);
13340}
13341
13342
13343__u32 run_wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx,
13344 struct libnvme_transport_handle *hdl)
13345{
13346 return wdc_get_fw_cust_id(ctx, hdl);
13347}
13348
13349bool_Bool run_wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
13350 struct libnvme_transport_handle *hdl,
13351 __u8 log_id,
13352 __u8 uuid_index)
13353{
13354 return wdc_nvme_check_supported_log_page(ctx,
13355 hdl,
13356 log_id,
13357 uuid_index);
13358}
13359
13360__u64 run_wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx,
13361 struct libnvme_transport_handle *hdl)
13362{
13363 return wdc_get_drive_capabilities(ctx, hdl);
13364}
13365
13366static struct command wdc_cap_diag_cmd = {
13367 .name = "cap-diag",
13368 .help = "WDC Capture-Diagnostics",
13369 .fn = wdc_cap_diag,
13370};
13371
13372static struct command wdc_drive_log_cmd = {
13373 .name = "drive-log",
13374 .help = "WDC Drive Log",
13375 .fn = wdc_drive_log,
13376};
13377
13378static struct command wdc_get_crash_dump_cmd = {
13379 .name = "get-crash-dump",
13380 .help = "WDC Crash Dump",
13381 .fn = wdc_get_crash_dump,
13382};
13383
13384static struct command wdc_get_pfail_dump_cmd = {
13385 .name = "get-pfail-dump",
13386 .help = "WDC Pfail Dump",
13387 .fn = wdc_get_pfail_dump,
13388};
13389
13390static struct command wdc_id_ctrl_cmd = {
13391 .name = "id-ctrl",
13392 .help = "WDC identify controller",
13393 .fn = wdc_id_ctrl,
13394};
13395
13396static struct command wdc_purge_cmd = {
13397 .name = "purge",
13398 .help = "WDC Purge",
13399 .fn = wdc_purge,
13400};
13401
13402static struct command wdc_purge_monitor_cmd = {
13403 .name = "purge-monitor",
13404 .help = "WDC Purge Monitor",
13405 .fn = wdc_purge_monitor,
13406};
13407
13408static struct command wdc_vs_internal_fw_log_cmd = {
13409 .name = "vs-internal-log",
13410 .help = "WDC Internal Firmware Log",
13411 .fn = wdc_vs_internal_fw_log,
13412};
13413
13414static struct command wdc_vs_nand_stats_cmd = {
13415 .name = "vs-nand-stats",
13416 .help = "WDC NAND Statistics",
13417 .fn = wdc_vs_nand_stats,
13418};
13419
13420static struct command wdc_vs_smart_add_log_cmd = {
13421 .name = "vs-smart-add-log",
13422 .help = "WDC Additional Smart Log",
13423 .fn = wdc_vs_smart_add_log,
13424};
13425
13426static struct command wdc_clear_pcie_correctable_errors_cmd = {
13427 .name = "clear-pcie-correctable-errors",
13428 .help = "WDC Clear PCIe Correctable Error Count",
13429 .fn = wdc_clear_pcie_correctable_errors,
13430};
13431
13432static struct command wdc_drive_essentials_cmd = {
13433 .name = "drive-essentials",
13434 .help = "WDC Drive Essentials",
13435 .fn = wdc_drive_essentials,
13436};
13437
13438static struct command wdc_drive_status_cmd = {
13439 .name = "get-drive-status",
13440 .help = "WDC Get Drive Status",
13441 .fn = wdc_drive_status,
13442};
13443
13444static struct command wdc_clear_assert_dump_cmd = {
13445 .name = "clear-assert-dump",
13446 .help = "WDC Clear Assert Dump",
13447 .fn = wdc_clear_assert_dump,
13448};
13449
13450static struct command wdc_drive_resize_cmd = {
13451 .name = "drive-resize",
13452 .help = "WDC Drive Resize",
13453 .fn = wdc_drive_resize,
13454};
13455
13456static struct command wdc_vs_fw_activate_history_cmd = {
13457 .name = "vs-fw-activate-history",
13458 .help = "WDC Get FW Activate History",
13459 .fn = wdc_vs_fw_activate_history,
13460};
13461
13462static struct command wdc_clear_fw_activate_history_cmd = {
13463 .name = "clear-fw-activate-history",
13464 .help = "WDC Clear FW Activate History",
13465 .fn = wdc_clear_fw_activate_history,
13466};
13467
13468static struct command wdc_enc_get_log_cmd = {
13469 .name = "enc-get-log",
13470 .help = "WDC Get Enclosure Log",
13471 .fn = wdc_enc_get_log,
13472};
13473
13474static struct command wdc_vs_telemetry_controller_option_cmd = {
13475 .name = "vs-telemetry-controller-option",
13476 .help = "WDC Enable/Disable Controller Initiated Telemetry Log",
13477 .fn = wdc_vs_telemetry_controller_option,
13478 .needs_root = true1,
13479};
13480
13481static struct command wdc_reason_identifier_cmd = {
13482 .name = "vs-error-reason-identifier",
13483 .help = "WDC Telemetry Reason Identifier",
13484 .fn = wdc_reason_identifier,
13485 .needs_root = true1,
13486};
13487
13488static struct command wdc_log_page_directory_cmd = {
13489 .name = "log-page-directory",
13490 .help = "WDC Get Log Page Directory",
13491 .fn = wdc_log_page_directory,
13492};
13493
13494static struct command wdc_namespace_resize_cmd = {
13495 .name = "namespace-resize",
13496 .help = "WDC NamespaceDrive Resize",
13497 .fn = wdc_namespace_resize,
13498};
13499
13500static struct command wdc_vs_drive_info_cmd = {
13501 .name = "vs-drive-info",
13502 .help = "WDC Get Drive Info",
13503 .fn = wdc_vs_drive_info,
13504};
13505
13506static struct command wdc_vs_temperature_stats_cmd = {
13507 .name = "vs-temperature-stats",
13508 .help = "WDC Get Temperature Stats",
13509 .fn = wdc_vs_temperature_stats,
13510};
13511
13512static struct command wdc_capabilities_cmd = {
13513 .name = "capabilities",
13514 .help = "WDC Device Capabilities",
13515 .fn = wdc_capabilities,
13516};
13517
13518static struct command wdc_cloud_ssd_plugin_version_cmd = {
13519 .name = "cloud-SSD-plugin-version",
13520 .help = "WDC Cloud SSD Plugin Version",
13521 .fn = wdc_cloud_ssd_plugin_version,
13522};
13523
13524static struct command wdc_vs_pcie_stats_cmd = {
13525 .name = "vs-pcie-stats",
13526 .help = "WDC VS PCIE Statistics",
13527 .fn = wdc_vs_pcie_stats,
13528};
13529
13530static struct command wdc_get_latency_monitor_log_cmd = {
13531 .name = "get-latency-monitor-log",
13532 .help = "WDC Get Latency Monitor Log Page",
13533 .fn = wdc_get_latency_monitor_log,
13534};
13535
13536static struct command wdc_get_error_recovery_log_cmd = {
13537 .name = "get-error-recovery-log",
13538 .help = "WDC Get Error Recovery Log Page",
13539 .fn = wdc_get_error_recovery_log,
13540};
13541
13542static struct command wdc_get_dev_capabilities_log_cmd = {
13543 .name = "get-dev-capabilities-log",
13544 .help = "WDC Get Device Capabilities Log Page",
13545 .fn = wdc_get_dev_capabilities_log,
13546};
13547
13548static struct command wdc_get_unsupported_reqs_log_cmd = {
13549 .name = "get-unsupported-reqs-log",
13550 .help = "WDC Get Unsupported Requirements Log Page",
13551 .fn = wdc_get_unsupported_reqs_log,
13552};
13553
13554static struct command wdc_cloud_boot_SSD_version_cmd = {
13555 .name = "cloud-boot-SSD-version",
13556 .help = "WDC Get the Cloud Boot SSD Version",
13557 .fn = wdc_cloud_boot_SSD_version,
13558};
13559
13560static struct command wdc_vs_cloud_log_cmd = {
13561 .name = "vs-cloud-log",
13562 .help = "WDC Get the Cloud Log Page",
13563 .fn = wdc_vs_cloud_log,
13564};
13565
13566static struct command wdc_vs_hw_rev_log_cmd = {
13567 .name = "vs-hw-rev-log",
13568 .help = "WDC Get the Hardware Revision Log Page",
13569 .fn = wdc_vs_hw_rev_log,
13570};
13571
13572static struct command wdc_vs_device_waf_cmd = {
13573 .name = "vs-device-waf",
13574 .help = "WDC Calculate Device Write Amplication Factor",
13575 .fn = wdc_vs_device_waf,
13576};
13577
13578static struct command wdc_set_latency_monitor_feature_cmd = {
13579 .name = "set-latency-monitor-feature",
13580 .help = "WDC set Latency Monitor feature",
13581 .fn = wdc_set_latency_monitor_feature,
13582};
13583
13584static struct command wdc_cu_smart_log_cmd = {
13585 .name = "cu-smart-log",
13586 .help = "WDC Get Customer Unique Smart Log",
13587 .fn = wdc_cu_smart_log,
13588};
13589
13590static struct command *commands[] = {
13591 &wdc_cap_diag_cmd,
13592 &wdc_drive_log_cmd,
13593 &wdc_get_crash_dump_cmd,
13594 &wdc_get_pfail_dump_cmd,
13595 &wdc_id_ctrl_cmd,
13596 &wdc_purge_cmd,
13597 &wdc_purge_monitor_cmd,
13598 &wdc_vs_internal_fw_log_cmd,
13599 &wdc_vs_nand_stats_cmd,
13600 &wdc_vs_smart_add_log_cmd,
13601 &wdc_clear_pcie_correctable_errors_cmd,
13602 &wdc_drive_essentials_cmd,
13603 &wdc_drive_status_cmd,
13604 &wdc_clear_assert_dump_cmd,
13605 &wdc_drive_resize_cmd,
13606 &wdc_vs_fw_activate_history_cmd,
13607 &wdc_clear_fw_activate_history_cmd,
13608 &wdc_enc_get_log_cmd,
13609 &wdc_vs_telemetry_controller_option_cmd,
13610 &wdc_reason_identifier_cmd,
13611 &wdc_log_page_directory_cmd,
13612 &wdc_namespace_resize_cmd,
13613 &wdc_vs_drive_info_cmd,
13614 &wdc_vs_temperature_stats_cmd,
13615 &wdc_capabilities_cmd,
13616 &wdc_cloud_ssd_plugin_version_cmd,
13617 &wdc_vs_pcie_stats_cmd,
13618 &wdc_get_latency_monitor_log_cmd,
13619 &wdc_get_error_recovery_log_cmd,
13620 &wdc_get_dev_capabilities_log_cmd,
13621 &wdc_get_unsupported_reqs_log_cmd,
13622 &wdc_cloud_boot_SSD_version_cmd,
13623 &wdc_vs_cloud_log_cmd,
13624 &wdc_vs_hw_rev_log_cmd,
13625 &wdc_vs_device_waf_cmd,
13626 &wdc_set_latency_monitor_feature_cmd,
13627 &wdc_cu_smart_log_cmd,
13628 NULL((void*)0),
13629};
13630
13631static struct plugin plugin = {
13632 .name = "wdc",
13633 .desc = "Western Digital vendor specific extensions",
13634 .version = WDC_PLUGIN_VERSION"2.15.1",
13635};
13636
13637static void __shr_constructor__attribute__((constructor)) register_plugin(void)
13638{
13639 plugin_add_group(&plugin, NULL((void*)0), commands);
13640 register_extension(&plugin);
13641}

←

../libnvme/src/nvme/nvme-cmds-base.h

1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * This file is part of libnvme.
4 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
5 *
6 * Authors: Keith Busch <keith.busch@wdc.com>
7 * Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
8 * Daniel Wagner <dwagner@suse.de>
9 */
10
11#pragma once
12
13/**
14 * DOC: nvme-base-cmds.h
15 *
16 * NVMe Base Specification Admin Commands
17 */
18
19#include <errno(*__errno_location ()).h>
20#include <string.h>
21
22#include <nvme/endian.h>
23#include <nvme/ioctl.h>
24#include <nvme/nvme-types-base.h>
25#include <nvme/nvme-types-nvm.h>
26#include <nvme/nvme-types-slm.h>
27
28#ifndef NVME_FIELD_ENCODE
29#define NVME_FIELD_ENCODE(value, shift, mask)(((__u32)(value) & (mask)) << (shift)) \
30 (((__u32)(value) & (mask)) << (shift))
31#endif
32
33/* Base Admin Command DWord Field Definitions */
34enum {
35 /* Get Log Page - Admin Opcode 0x02 */
36 NVME_LOG_CDW10_LID_SHIFT = 0,
37 NVME_LOG_CDW10_LSP_SHIFT = 8,
38 NVME_LOG_CDW10_NUMDL_SHIFT = 16,
39 NVME_LOG_CDW10_RAE_SHIFT = 15,
40 NVME_LOG_CDW11_LSI_SHIFT = 16,
41 NVME_LOG_CDW11_NUMDU_SHIFT = 0,
42 NVME_LOG_CDW14_CSI_SHIFT = 24,
43 NVME_LOG_CDW14_OT_SHIFT = 23,
44 NVME_LOG_CDW14_UUID_SHIFT = 0,
45 NVME_LOG_CDW10_LID_MASK = 0xff,
46 NVME_LOG_CDW10_LSP_MASK = 0x7f,
47 NVME_LOG_CDW10_NUMDL_MASK = 0xffff,
48 NVME_LOG_CDW10_RAE_MASK = 0x1,
49 NVME_LOG_CDW11_LSI_MASK = 0xffff,
50 NVME_LOG_CDW11_NUMDU_MASK = 0xffff,
51 NVME_LOG_CDW14_CSI_MASK = 0xff,
52 NVME_LOG_CDW14_OT_MASK = 0x1,
53 NVME_LOG_CDW14_UUID_MASK = 0x7f,
54
55
56 /* Identify - Admin Opcode 0x06 */
57 NVME_IDENTIFY_CDW10_CNS_SHIFT = 0,
58 NVME_IDENTIFY_CDW10_CNTID_SHIFT = 16,
59 NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT = 0,
60 NVME_IDENTIFY_CDW11_CSI_SHIFT = 24,
61 NVME_IDENTIFY_CDW11_DOMID_SHIFT = 0,
62 NVME_IDENTIFY_CDW11_ENGGID_SHIFT = 0,
63 NVME_IDENTIFY_CDW11_FIDX_SHIFT = 0,
64 NVME_IDENTIFY_CDW14_UUID_SHIFT = 0,
65 NVME_IDENTIFY_CDW10_CNS_MASK = 0xff,
66 NVME_IDENTIFY_CDW10_CNTID_MASK = 0xffff,
67 NVME_IDENTIFY_CDW11_CNSSPECID_MASK = 0xffff,
68 NVME_IDENTIFY_CDW11_CSI_MASK = 0xff,
69 NVME_IDENTIFY_CDW11_DOMID_MASK = 0xffff,
70 NVME_IDENTIFY_CDW11_ENGGID_MASK = 0xffff,
71 NVME_IDENTIFY_CDW11_FIDX_MASK = 0xffff,
72 NVME_IDENTIFY_CDW14_UUID_MASK = 0x7f,
73
74
75 /* Abort - Admin Opcode 0x08 */
76 NVME_ABORT_CDW10_SQID_SHIFT = 0,
77 NVME_ABORT_CDW10_CID_SHIFT = 16,
78 NVME_ABORT_CDW10_SQID_MASK = 0xffff,
79 NVME_ABORT_CDW10_CID_MASK = 0xffff,
80
81
82 /* Set Features - Admin Opcode 0x09 */
83 NVME_SET_FEATURES_CDW10_FID_SHIFT = 0,
84 NVME_SET_FEATURES_CDW10_SV_SHIFT = 31,
85 NVME_SET_FEATURES_CDW11_NUM_SHIFT = 0,
86 NVME_SET_FEATURES_CDW14_UUID_SHIFT = 0,
87 NVME_SET_FEATURES_CDW10_FID_MASK = 0xff,
88 NVME_SET_FEATURES_CDW10_SV_MASK = 0x1,
89 NVME_SET_FEATURES_CDW11_NUM_MASK = 0x3f,
90 NVME_SET_FEATURES_CDW14_UUID_MASK = 0x7f,
91
92
93 /* Get Features - Admin Opcode 0x0a */
94 NVME_GET_FEATURES_CDW10_FID_SHIFT = 0,
95 NVME_GET_FEATURES_CDW10_SEL_SHIFT = 8,
96 NVME_GET_FEATURES_CDW14_UUID_SHIFT = 0,
97 NVME_GET_FEATURES_CDW10_FID_MASK = 0xff,
98 NVME_GET_FEATURES_CDW10_SEL_MASK = 0x7,
99 NVME_GET_FEATURES_CDW14_UUID_MASK = 0x7f,
100
101
102 /* Namespace Management - Admin Opcode 0x0d */
103 NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT = 0,
104 NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT = 24,
105 NVME_NAMESPACE_MGMT_CDW10_SEL_MASK = 0xf,
106 NVME_NAMESPACE_MGMT_CDW11_CSI_MASK = 0xff,
107
108
109 /* Firmware Commit - Admin Opcode 0x10 */
110 NVME_FW_COMMIT_CDW10_BPID_SHIFT = 31,
111 NVME_FW_COMMIT_CDW10_CA_SHIFT = 3,
112 NVME_FW_COMMIT_CDW10_FS_SHIFT = 0,
113 NVME_FW_COMMIT_CDW10_BPID_MASK = 0x1,
114 NVME_FW_COMMIT_CDW10_CA_MASK = 0x7,
115 NVME_FW_COMMIT_CDW10_FS_MASK = 0x7,
116
117
118 /* Namespace Attachment - Admin Opcode 0x15 */
119 NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT = 0,
120 NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK = 0xf,
121
122
123 /* Directive Send/Receive - Admin Opcode 0x19/0x1a */
124 NVME_DIRECTIVE_CDW11_DOPER_SHIFT = 0,
125 NVME_DIRECTIVE_CDW11_DPSEC_SHIFT = 16,
126 NVME_DIRECTIVE_CDW11_DTYPE_SHIFT = 8,
127
128 /* Directive Send - Identify - Admin Opcode 0x19 */
129 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT = 1,
130 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT = 0,
131 NVME_DIRECTIVE_CDW11_DOPER_MASK = 0xff,
132 NVME_DIRECTIVE_CDW11_DPSEC_MASK = 0xffff,
133 NVME_DIRECTIVE_CDW11_DTYPE_MASK = 0xff,
134 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK = 0x1,
135 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK = 0x1,
136
137
138 /* Device Self-test - Admin Opcode 0x1c */
139 NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT = 0,
140 NVME_DEVICE_SELF_TEST_CDW10_STC_MASK = 0xf,
141
142
143 /* Virtualization Management - Admin Opcode 0x1d */
144 NVME_VIRT_MGMT_CDW10_ACT_SHIFT = 0,
145 NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT = 16,
146 NVME_VIRT_MGMT_CDW10_RT_SHIFT = 8,
147 NVME_VIRT_MGMT_CDW11_NR_SHIFT = 0,
148 NVME_VIRT_MGMT_CDW10_ACT_MASK = 0xf,
149 NVME_VIRT_MGMT_CDW10_CNTLID_MASK = 0xffff,
150 NVME_VIRT_MGMT_CDW10_RT_MASK = 0x7,
151 NVME_VIRT_MGMT_CDW11_NR_MASK = 0xffff,
152
153
154 /* Capacity Management - Admin Opcode 0x20 */
155 NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT = 16,
156 NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT = 0,
157 NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT = 0,
158 NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT = 0,
159 NVME_CAPACITY_MGMT_CDW10_ELID_MASK = 0xffff,
160 NVME_CAPACITY_MGMT_CDW10_OPER_MASK = 0xf,
161 NVME_CAPACITY_MGMT_CDW11_CAPL_MASK = 0xffffffff,
162 NVME_CAPACITY_MGMT_CDW12_CAPU_MASK = 0xffffffff,
163
164
165 /* Lockdown - Admin Opcode 0x24 */
166 NVME_LOCKDOWN_CDW10_IFC_SHIFT = 5,
167 NVME_LOCKDOWN_CDW10_OFI_SHIFT = 8,
168 NVME_LOCKDOWN_CDW10_PRHBT_SHIFT = 4,
169 NVME_LOCKDOWN_CDW10_SCP_SHIFT = 0,
170 NVME_LOCKDOWN_CDW10_CSEL_SHIFT = 16,
171 NVME_LOCKDOWN_CDW14_UIDX_SHIFT = 0,
172 NVME_LOCKDOWN_CDW14_CSS_SHIFT = 16,
173 NVME_LOCKDOWN_CDW10_IFC_MASK = 0x3,
174 NVME_LOCKDOWN_CDW10_OFI_MASK = 0xff,
175 NVME_LOCKDOWN_CDW10_PRHBT_MASK = 0x1,
176 NVME_LOCKDOWN_CDW10_SCP_MASK = 0xf,
177 NVME_LOCKDOWN_CDW10_CSEL_MASK = 0xf,
178 NVME_LOCKDOWN_CDW14_UIDX_MASK = 0x7f,
179 NVME_LOCKDOWN_CDW14_CSS_MASK = 0xffff,
180
181
182 /* Format NVM - Admin Opcode 0x80 */
183 NVME_FORMAT_CDW10_LBAFL_SHIFT = 0,
184 NVME_FORMAT_CDW10_LBAFU_SHIFT = 12,
185 NVME_FORMAT_CDW10_MSET_SHIFT = 4,
186 NVME_FORMAT_CDW10_PIL_SHIFT = 8,
187 NVME_FORMAT_CDW10_PI_SHIFT = 5,
188 NVME_FORMAT_CDW10_SES_SHIFT = 9,
189 NVME_FORMAT_CDW10_LBAFL_MASK = 0xf,
190 NVME_FORMAT_CDW10_LBAFU_MASK = 0x3,
191 NVME_FORMAT_CDW10_MSET_MASK = 0x1,
192 NVME_FORMAT_CDW10_PIL_MASK = 0x1,
193 NVME_FORMAT_CDW10_PI_MASK = 0x7,
194 NVME_FORMAT_CDW10_SES_MASK = 0x7,
195
196
197 /* Security Send/Receive - Admin Opcode 0x81/0x82 */
198 NVME_SECURITY_NSSF_SHIFT = 0,
199 NVME_SECURITY_SECP_SHIFT = 24,
200 NVME_SECURITY_SPSP0_SHIFT = 8,
201 NVME_SECURITY_SPSP1_SHIFT = 16,
202 NVME_SECURITY_NSSF_MASK = 0xff,
203 NVME_SECURITY_SECP_MASK = 0xffff,
204 NVME_SECURITY_SPSP0_MASK = 0xff,
205 NVME_SECURITY_SPSP1_MASK = 0xff,
206
207
208 /* Sanitize - Admin Opcode 0x84 */
209 NVME_SANITIZE_CDW10_AUSE_SHIFT = 3,
210 NVME_SANITIZE_CDW10_EMVS_SHIFT = 10,
211 NVME_SANITIZE_CDW10_NDAS_SHIFT = 9,
212 NVME_SANITIZE_CDW10_OIPBP_SHIFT = 8,
213 NVME_SANITIZE_CDW10_OWPASS_SHIFT = 4,
214 NVME_SANITIZE_CDW10_SANACT_SHIFT = 0,
215 NVME_SANITIZE_CDW10_PREQ_SHIFT = 11,
216 NVME_SANITIZE_CDW10_AUSE_MASK = 0x1,
217 NVME_SANITIZE_CDW10_EMVS_MASK = 0x1,
218 NVME_SANITIZE_CDW10_NDAS_MASK = 0x1,
219 NVME_SANITIZE_CDW10_OIPBP_MASK = 0x1,
220 NVME_SANITIZE_CDW10_OWPASS_MASK = 0xf,
221 NVME_SANITIZE_CDW10_SANACT_MASK = 0x7,
222 NVME_SANITIZE_CDW10_PREQ_MASK = 0x1,
223
224 /* Sanitize Namespace - Admin Opcode 0x8c */
225 NVME_SANITIZE_NS_CDW10_PREQ_SHIFT = 4,
226 NVME_SANITIZE_NS_CDW10_PREQ_MASK = 0x1,
227
228
229 /* Get LBA Status - Admin Opcode 0x86 */
230 NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT = 24,
231 NVME_GET_LBA_STATUS_CDW13_RL_SHIFT = 0,
232 NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK = 0xff,
233 NVME_GET_LBA_STATUS_CDW13_RL_MASK = 0xffff,
234};
235
236/* I/O Command Set Common Field Definitions */
237enum {
238 /* I/O Command Set Common Fields */
239 NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT = 0,
240 NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT = 0,
241 NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT = 16,
242 NVME_IOCS_COMMON_CDW12_DEAC_SHIFT = 25,
243 NVME_IOCS_COMMON_CDW12_DTYPE_SHIFT = 20,
244 NVME_IOCS_COMMON_CDW12_FUA_SHIFT = 30,
245 NVME_IOCS_COMMON_CDW12_LR_SHIFT = 31,
246 NVME_IOCS_COMMON_CDW12_NLB_SHIFT = 0,
247 NVME_IOCS_COMMON_CDW12_PIREMAP_SHIFT = 25,
248 NVME_IOCS_COMMON_CDW12_PRINFO_SHIFT = 26,
249 NVME_IOCS_COMMON_CDW12_STC_SHIFT = 24,
250 NVME_IOCS_COMMON_CDW13_CEV_SHIFT = 0,
251 NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT = 0,
252 NVME_IOCS_COMMON_CDW13_DSM_AL_SHIFT = 4,
253 NVME_IOCS_COMMON_CDW13_DSM_INCPRS_SHIFT = 7,
254 NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_SHIFT = 6,
255 NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT = 16,
256 NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT = 0,
257 NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT = 16,
258 NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT = 0,
259 NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT = 0,
260 NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT = 0,
261 NVME_IOCS_COMMON_CDW10_SLBAL_MASK = 0xffffffff,
262 NVME_IOCS_COMMON_CDW11_SLBAU_MASK = 0xffffffff,
263 NVME_IOCS_COMMON_CDW12_CETYPE_MASK = 0xf,
264 NVME_IOCS_COMMON_CDW12_DEAC_MASK = 0x1,
265 NVME_IOCS_COMMON_CDW12_DTYPE_MASK = 0xf,
266 NVME_IOCS_COMMON_CDW12_FUA_MASK = 0x1,
267 NVME_IOCS_COMMON_CDW12_LR_MASK = 0x1,
268 NVME_IOCS_COMMON_CDW12_NLB_MASK = 0xffff,
269 NVME_IOCS_COMMON_CDW12_PIREMAP_MASK = 0x1,
270 NVME_IOCS_COMMON_CDW12_PRINFO_MASK = 0xf,
271 NVME_IOCS_COMMON_CDW12_STC_MASK = 0x1,
272 NVME_IOCS_COMMON_CDW13_CEV_MASK = 0xffff,
273 NVME_IOCS_COMMON_CDW13_DSM_AF_MASK = 0xf,
274 NVME_IOCS_COMMON_CDW13_DSM_AL_MASK = 0x3,
275 NVME_IOCS_COMMON_CDW13_DSM_INCPRS_MASK = 0x1,
276 NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_MASK = 0x1,
277 NVME_IOCS_COMMON_CDW13_DSPEC_MASK = 0xffff,
278 NVME_IOCS_COMMON_CDW14_ELBTL_MASK = 0xffffffff,
279 NVME_IOCS_COMMON_CDW15_ELBATM_MASK = 0xffff,
280 NVME_IOCS_COMMON_CDW15_ELBAT_MASK = 0xffff,
281 NVME_IOCS_COMMON_CDW2_ELBTU_MASK = 0xffff,
282 NVME_IOCS_COMMON_CDW3_ELBTU_MASK = 0xffffffff,
283 NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT =
284 NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT,
285 NVME_IOCS_COMMON_CDW13_DSM_SHIFT =
286 NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT,
287 NVME_IOCS_COMMON_CDW12_CONTROL_MASK =
288 (NVME_VAL(IOCS_COMMON_CDW12_CETYPE)((__u32)NVME_IOCS_COMMON_CDW12_CETYPE_MASK << NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT
)
|
289 NVME_VAL(IOCS_COMMON_CDW12_DTYPE)((__u32)NVME_IOCS_COMMON_CDW12_DTYPE_MASK << NVME_IOCS_COMMON_CDW12_DTYPE_SHIFT
)
|
290 NVME_VAL(IOCS_COMMON_CDW12_STC)((__u32)NVME_IOCS_COMMON_CDW12_STC_MASK << NVME_IOCS_COMMON_CDW12_STC_SHIFT
)
|
291 NVME_VAL(IOCS_COMMON_CDW12_DEAC)((__u32)NVME_IOCS_COMMON_CDW12_DEAC_MASK << NVME_IOCS_COMMON_CDW12_DEAC_SHIFT
)
|
292 NVME_VAL(IOCS_COMMON_CDW12_PRINFO)((__u32)NVME_IOCS_COMMON_CDW12_PRINFO_MASK << NVME_IOCS_COMMON_CDW12_PRINFO_SHIFT
)
|
293 NVME_VAL(IOCS_COMMON_CDW12_FUA)((__u32)NVME_IOCS_COMMON_CDW12_FUA_MASK << NVME_IOCS_COMMON_CDW12_FUA_SHIFT
)
|
294 NVME_VAL(IOCS_COMMON_CDW12_LR)((__u32)NVME_IOCS_COMMON_CDW12_LR_MASK << NVME_IOCS_COMMON_CDW12_LR_SHIFT
)
) >>
295 NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT,
296 NVME_IOCS_COMMON_CDW13_DSM_MASK =
297 (NVME_VAL(IOCS_COMMON_CDW13_DSM_AF)((__u32)NVME_IOCS_COMMON_CDW13_DSM_AF_MASK << NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT
)
|
298 NVME_VAL(IOCS_COMMON_CDW13_DSM_AL)((__u32)NVME_IOCS_COMMON_CDW13_DSM_AL_MASK << NVME_IOCS_COMMON_CDW13_DSM_AL_SHIFT
)
|
299 NVME_VAL(IOCS_COMMON_CDW13_DSM_SEQREQ)((__u32)NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_MASK << NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_SHIFT
)
|
300 NVME_VAL(IOCS_COMMON_CDW13_DSM_INCPRS)((__u32)NVME_IOCS_COMMON_CDW13_DSM_INCPRS_MASK << NVME_IOCS_COMMON_CDW13_DSM_INCPRS_SHIFT
)
) >>
301 NVME_IOCS_COMMON_CDW13_DSM_SHIFT,
302
303 /* Directive I/O Management */
304 NVME_DIM_TAS_SHIFT = 0,
305 NVME_DIM_TAS_MASK = 0xf,
306};
307
308/* NVM Command Set I/O Command DWord Field Definitions */
309enum {
310 /* Dataset Management - I/O Opcode 0x09 */
311 NVME_DSM_CDW10_NR_SHIFT = 0,
312 NVME_DSM_CDW11_AD_SHIFT = 2,
313 NVME_DSM_CDW11_IDR_SHIFT = 0,
314 NVME_DSM_CDW11_IDW_SHIFT = 1,
315 NVME_DSM_CDW10_NR_MASK = 0xff,
316 NVME_DSM_CDW11_AD_MASK = 0x1,
317 NVME_DSM_CDW11_IDR_MASK = 0x1,
318 NVME_DSM_CDW11_IDW_MASK = 0x1,
319
320
321 /* Reservation Register - I/O Opcode 0x0d */
322 NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT = 30,
323 NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT = 4,
324 NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT = 3,
325 NVME_RESV_REGISTER_CDW10_RREGA_SHIFT = 0,
326 NVME_RESV_REGISTER_CDW10_CPTPL_MASK = 0x3,
327 NVME_RESV_REGISTER_CDW10_DISNSRS_MASK = 0x1,
328 NVME_RESV_REGISTER_CDW10_IEKEY_MASK = 0x1,
329 NVME_RESV_REGISTER_CDW10_RREGA_MASK = 0x7,
330
331
332 /* Reservation Report - I/O Opcode 0x0e */
333 NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT = 1,
334 NVME_RESV_REPORT_CDW11_EDS_SHIFT = 0,
335 NVME_RESV_REPORT_CDW11_DISNSRS_MASK = 0x1,
336 NVME_RESV_REPORT_CDW11_EDS_MASK = 0x1,
337
338
339 /* Reservation Acquire - I/O Opcode 0x11 */
340 NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT = 4,
341 NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT = 3,
342 NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT = 0,
343 NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT = 8,
344 NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK = 0x1,
345 NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK = 0x1,
346 NVME_RESV_ACQUIRE_CDW10_RACQA_MASK = 0x7,
347 NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK = 0xff,
348
349
350 /* I/O Management Receive - I/O Opcode 0x12 */
351 NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT = 16,
352 NVME_IO_MGMT_RECV_CDW10_MO_SHIFT = 0,
353 NVME_IO_MGMT_RECV_CDW10_MOS_MASK = 0xffff,
354 NVME_IO_MGMT_RECV_CDW10_MO_MASK = 0xff,
355
356
357 /* Reservation Release - I/O Opcode 0x15 */
358 NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT = 4,
359 NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT = 3,
360 NVME_RESV_RELEASE_CDW10_RRELA_SHIFT = 0,
361 NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT = 8,
362 NVME_RESV_RELEASE_CDW10_DISNSRS_MASK = 0x1,
363 NVME_RESV_RELEASE_CDW10_IEKEY_MASK = 0x1,
364 NVME_RESV_RELEASE_CDW10_RRELA_MASK = 0x7,
365 NVME_RESV_RELEASE_CDW10_RTYPE_MASK = 0xff,
366
367
368 /* Cancel - I/O Opcode 0x18 */
369 NVME_CANCEL_CDW10_SQID_SHIFT = 0,
370 NVME_CANCEL_CDW10_SQID_MASK = 0xffff,
371 NVME_CANCEL_CDW10_CID_SHIFT = 16,
372 NVME_CANCEL_CDW10_CID_MASK = 0xffff,
373 NVME_CANCEL_CDW11_ACODE_SHIFT = 0,
374 NVME_CANCEL_CDW11_ACODE_MASK = 0x3,
375
376
377 /* Copy - I/O Opcode 0x19 */
378 NVME_COPY_CDW10_SDLBAL_SHIFT = 0,
379 NVME_COPY_CDW11_SDLBAU_SHIFT = 0,
380 NVME_COPY_CDW12_CETYPE_SHIFT = 16,
381 NVME_COPY_CDW12_DESFMT_SHIFT = 8,
382 NVME_COPY_CDW12_DTYPE_SHIFT = 20,
383 NVME_COPY_CDW12_FUA_SHIFT = 30,
384 NVME_COPY_CDW12_LR_SHIFT = 31,
385 NVME_COPY_CDW12_NR_SHIFT = 0,
386 NVME_COPY_CDW12_PRINFOR_SHIFT = 12,
387 NVME_COPY_CDW12_PRINFOW_SHIFT = 26,
388 NVME_COPY_CDW12_STCR_SHIFT = 25,
389 NVME_COPY_CDW12_STCW_SHIFT = 24,
390 NVME_COPY_CDW14_LBTL_SHIFT = 0,
391 NVME_COPY_CDW15_LBATM_SHIFT = 16,
392 NVME_COPY_CDW15_LBAT_SHIFT = 0,
393 NVME_COPY_CDW3_LBTU_SHIFT = 0,
394 NVME_COPY_CDW10_SDLBAL_MASK = 0xffffffff,
395 NVME_COPY_CDW11_SDLBAU_MASK = 0xffffffff,
396 NVME_COPY_CDW12_CETYPE_MASK = 0xf,
397 NVME_COPY_CDW12_DESFMT_MASK = 0xf,
398 NVME_COPY_CDW12_DTYPE_MASK = 0xf,
399 NVME_COPY_CDW12_FUA_MASK = 0x1,
400 NVME_COPY_CDW12_LR_MASK = 0x1,
401 NVME_COPY_CDW12_NR_MASK = 0xff,
402 NVME_COPY_CDW12_PRINFOR_MASK = 0xf,
403 NVME_COPY_CDW12_PRINFOW_MASK = 0xf,
404 NVME_COPY_CDW12_STCR_MASK = 0x1,
405 NVME_COPY_CDW12_STCW_MASK = 0x1,
406 NVME_COPY_CDW14_LBTL_MASK = 0xffffffff,
407 NVME_COPY_CDW15_LBATM_MASK = 0xffff,
408 NVME_COPY_CDW15_LBAT_MASK = 0xffff,
409 NVME_COPY_CDW3_LBTU_MASK = 0xffffffff,
410
411
412 /* I/O Management Send - I/O Opcode 0x1d */
413 NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT = 16,
414 NVME_IO_MGMT_SEND_CDW10_MO_SHIFT = 0,
415 NVME_IO_MGMT_SEND_CDW10_MOS_MASK = 0xffff,
416 NVME_IO_MGMT_SEND_CDW10_MO_MASK = 0xff,
417};
418
419/* ZNS Command Set DWord Field Definitions */
420enum {
421 /* Zone Management Send - I/O Opcode 0x79 */
422 NVME_ZNS_MGMT_SEND_SEL_SHIFT = 8,
423 NVME_ZNS_MGMT_SEND_ZM_SHIFT = 16,
424 NVME_ZNS_MGMT_SEND_ZSASO_SHIFT = 9,
425 NVME_ZNS_MGMT_SEND_ZSA_SHIFT = 0,
426 NVME_ZNS_MGMT_SEND_SEL_MASK = 0x1,
427 NVME_ZNS_MGMT_SEND_ZM_MASK = 0xff,
428 NVME_ZNS_MGMT_SEND_ZSASO_MASK = 0x1,
429 NVME_ZNS_MGMT_SEND_ZSA_MASK = 0xff,
430
431
432 /* Zone Management Receive - I/O Opcode 0x7a */
433 NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT = 16,
434 NVME_ZNS_MGMT_RECV_ZRAS_SHIFT = 8,
435 NVME_ZNS_MGMT_RECV_ZRA_SHIFT = 0,
436 NVME_ZNS_MGMT_RECV_ZRASPF_MASK = 0x1,
437 NVME_ZNS_MGMT_RECV_ZRAS_MASK = 0xff,
438 NVME_ZNS_MGMT_RECV_ZRA_MASK = 0xff,
439};
440
441/* MI Admin Command DWord Field Definitions */
442enum {
443 /* MI Admin Command Flags */
444 NVME_MI_ADMIN_CFLAGS_ISH_SHIFT = 2,
445 NVME_MI_ADMIN_CFLAGS_ISH_MASK = 0x1,
446};
447
448/**
449 * nvme_init_get_log_lpo() - Initialize passthru command with a
450 * Log Page Offset
451 * @cmd: Passthru command
452 * @lpo: Log Page Offset to set
453 */
454static inline void
455nvme_init_get_log_lpo(struct libnvme_passthru_cmd *cmd, __u64 lpo)
456{
457 cmd->cdw12 = lpo & 0xffffffff;
458 cmd->cdw13 = lpo >> 32;
459}
460
461/**
462 * nvme_init_get_log() - Initialize passthru command for
463 * NVMe Admin Get Log
464 * @cmd: Passthru command to use
465 * @nsid: Namespace identifier, if applicable
466 * @lid: Log Page Identifier, see &enum nvme_cmd_get_log_lid
467 * @csi: Command set identifier, see &enum nvme_csi for known values
468 * @data: User space destination address to transfer the data
469 * @len: Length of provided user buffer to hold the log data in bytes
470 */
471static inline void
472nvme_init_get_log(struct libnvme_passthru_cmd *cmd, __u32 nsid,
473 enum nvme_cmd_get_log_lid lid, enum nvme_csi csi,
474 void *data, __u32 len)
475{
476 __u32 numd = (len >> 2) - 1;
477 __u16 numdu = numd >> 16;
478 __u16 numdl = numd & 0xffff;
479 __u32 cdw10 = NVME_FIELD_ENCODE(lid,(((__u32)(lid) & (NVME_LOG_CDW10_LID_MASK)) << (NVME_LOG_CDW10_LID_SHIFT
))
480 NVME_LOG_CDW10_LID_SHIFT,(((__u32)(lid) & (NVME_LOG_CDW10_LID_MASK)) << (NVME_LOG_CDW10_LID_SHIFT
))
481 NVME_LOG_CDW10_LID_MASK)(((__u32)(lid) & (NVME_LOG_CDW10_LID_MASK)) << (NVME_LOG_CDW10_LID_SHIFT
))
|
482 NVME_FIELD_ENCODE(numdl,(((__u32)(numdl) & (NVME_LOG_CDW10_NUMDL_MASK)) << (
NVME_LOG_CDW10_NUMDL_SHIFT))
483 NVME_LOG_CDW10_NUMDL_SHIFT,(((__u32)(numdl) & (NVME_LOG_CDW10_NUMDL_MASK)) << (
NVME_LOG_CDW10_NUMDL_SHIFT))
484 NVME_LOG_CDW10_NUMDL_MASK)(((__u32)(numdl) & (NVME_LOG_CDW10_NUMDL_MASK)) << (
NVME_LOG_CDW10_NUMDL_SHIFT))
;
485 __u32 cdw11 = NVME_FIELD_ENCODE(numdu,(((__u32)(numdu) & (NVME_LOG_CDW11_NUMDU_MASK)) << (
NVME_LOG_CDW11_NUMDU_SHIFT))
486 NVME_LOG_CDW11_NUMDU_SHIFT,(((__u32)(numdu) & (NVME_LOG_CDW11_NUMDU_MASK)) << (
NVME_LOG_CDW11_NUMDU_SHIFT))
487 NVME_LOG_CDW11_NUMDU_MASK)(((__u32)(numdu) & (NVME_LOG_CDW11_NUMDU_MASK)) << (
NVME_LOG_CDW11_NUMDU_SHIFT))
;
488 __u32 cdw14 = NVME_FIELD_ENCODE(csi,(((__u32)(csi) & (NVME_LOG_CDW14_CSI_MASK)) << (NVME_LOG_CDW14_CSI_SHIFT
))
489 NVME_LOG_CDW14_CSI_SHIFT,(((__u32)(csi) & (NVME_LOG_CDW14_CSI_MASK)) << (NVME_LOG_CDW14_CSI_SHIFT
))
490 NVME_LOG_CDW14_CSI_MASK)(((__u32)(csi) & (NVME_LOG_CDW14_CSI_MASK)) << (NVME_LOG_CDW14_CSI_SHIFT
))
;
491
492 memset(cmd, 0, sizeof(*cmd));
493
494 cmd->opcode = nvme_admin_get_log_page;
495 cmd->nsid = nsid;
496 cmd->cdw10 = cdw10;
497 cmd->cdw11 = cdw11;
498 cmd->cdw14 = cdw14;
499 cmd->data_len = len;
500 cmd->addr = (__u64)(uintptr_t)data;
501}
502
503/**
504 * nvme_init_get_log_supported_log_pages() - Initialize passthru command for
505 * Supported Log Pages
506 * @cmd: Passthru command to use
507 * @csi: Command set identifier, see &enum nvme_csi for known values
508 * @log: Array of LID supported and Effects data structures
509 *
510 * Initializes the passthru command buffer for the Get Log command with
511 * LID value %NVME_LOG_LID_SUPPORTED_LOG_PAGES.
512 */
513static inline void
514nvme_init_get_log_supported_log_pages(struct libnvme_passthru_cmd *cmd,
515 enum nvme_csi csi, struct nvme_supported_log_pages *log)
516{
517 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
518 csi, log, sizeof(*log));
519}
520
521/**
522 * nvme_init_get_log_error() - Initialize passthru command for Error Information
523 * @cmd: Passthru command to use
524 * @nr_entries: Number of error log entries allocated
525 * @err_log: Array of error logs of size 'entries'
526 *
527 * Initializes the passthru command buffer for the Get Log command with
528 * LID value %NVME_LOG_LID_ERROR.
529 */
530static inline void
531nvme_init_get_log_error(struct libnvme_passthru_cmd *cmd,
532 unsigned int nr_entries, struct nvme_error_log_page *err_log)
533{
534 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR,
535 NVME_CSI_NVM, err_log, sizeof(*err_log) * nr_entries);
536}
537
538/**
539 * nvme_init_get_log_smart() - Initialize passthru command for
540 * SMART / Health Information
541 * @cmd: Passthru command to use
542 * @nsid: Optional namespace identifier
543 * @smart_log: User address to store the smart log
544 *
545 * Initializes the passthru command buffer for the Get Log command with
546 * LID value %NVME_LOG_LID_SMART.
547 */
548static inline void
549nvme_init_get_log_smart(struct libnvme_passthru_cmd *cmd, __u32 nsid,
550 struct nvme_smart_log *smart_log)
551{
552 nvme_init_get_log(cmd, nsid, NVME_LOG_LID_SMART, NVME_CSI_NVM,
553 smart_log, sizeof(*smart_log));
554}
555
556/**
557 * nvme_init_get_log_fw_slot() - Initialize passthru command for
558 * Firmware Slot Information
559 * @cmd: Passthru command to use
560 * @fw_log: User address to store the log page
561 *
562 * Initializes the passthru command buffer for the Get Log command with
563 * LID value %NVME_LOG_LID_SMART.
564 */
565static inline void
566nvme_init_get_log_fw_slot(struct libnvme_passthru_cmd *cmd,
567 struct nvme_firmware_slot *fw_log)
568{
569 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT,
570 NVME_CSI_NVM, fw_log, sizeof(*fw_log));
571}
572
573/**
574 * nvme_init_get_log_changed_ns() - Initialize passthru command for
575 * Changed Attached Namespace List
576 * @cmd: Passthru command to use
577 * @ns_log: User address to store the log page
578 *
579 * Initializes the passthru command buffer for the Get Log command with
580 * LID value %NVME_LOG_LID_CHANGED_ATTACHED_NS.
581 */
582static inline void
583nvme_init_get_log_changed_ns(struct libnvme_passthru_cmd *cmd,
584 struct nvme_ns_list *ns_log)
585{
586 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CHANGED_ATTACHED_NS,
587 NVME_CSI_NVM, ns_log, sizeof(*ns_log));
588}
589
590/**
591 * nvme_init_get_log_cmd_effects() - Initialize passthru command for
592 * Commands Supported and Effects
593 * @cmd: Passthru command to use
594 * @csi: Command Set Identifier
595 * @effects_log:User address to store the effects log
596 *
597 * Initializes the passthru command buffer for the Get Log command with
598 * LID value %NVME_LOG_LID_CMD_EFFECTS.
599 */
600static inline void
601nvme_init_get_log_cmd_effects(struct libnvme_passthru_cmd *cmd,
602 enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log)
603{
604 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CMD_EFFECTS, csi,
605 effects_log, sizeof(*effects_log));
606}
607
608/**
609 * nvme_init_get_log_device_self_test() - Initialize passthru command for
610 * Device Self-test
611 * @cmd: Passthru command to use
612 * @log: Userspace address of the log payload
613 *
614 * Initializes the passthru command buffer for the Get Log command with
615 * LID value %NVME_LOG_LID_DEVICE_SELF_TEST.
616 */
617static inline void
618nvme_init_get_log_device_self_test(struct libnvme_passthru_cmd *cmd,
619 struct nvme_self_test_log *log)
620{
621 nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST,
622 NVME_CSI_NVM, log, sizeof(*log));
623}
624
625/**
626 * nvme_init_get_log_telemetry_host() - Initialize passthru command for
627 * Telemetry Host-Initiated
628 * @cmd: Passthru command to use
629 * @lpo: Offset into the telemetry data
630 * @log: User address for log page data
631 * @len: Length of provided user buffer to hold the log data in bytes
632 *
633 * Initializes the passthru command buffer for the Get Log command with
634 * LID value %NVME_LOG_LID_TELEMETRY_HOST.
635 */
636static inline void
637nvme_init_get_log_telemetry_host(struct libnvme_passthru_cmd *cmd, __u64 lpo,
638 void *log, __u32 len)
639{
640 nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST,
641 NVME_CSI_NVM, log, len);
642 cmd->cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_RETAIN,(((__u32)(NVME_LOG_TELEM_HOST_LSP_RETAIN) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
643 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_RETAIN) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
644 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_RETAIN) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
645 nvme_init_get_log_lpo(cmd, lpo);
646}
647
648/**
649 * nvme_init_get_log_create_telemetry_host_mcda() - Initialize passthru
650 * command for Create Telemetry Host-Initiated
651 * @cmd: Passthru command to use
652 * @mcda: Maximum Created Data Area
653 * @log: Userspace address of the log payload
654 *
655 * Initializes the passthru command buffer for the Get Log command with
656 * LID value %NVME_LOG_LID_TELEMETRY_HOST and
657 * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE.
658 */
659static inline void
660nvme_init_get_log_create_telemetry_host_mcda(struct libnvme_passthru_cmd *cmd,
661 enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log)
662{
663 nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST,
664 NVME_CSI_NVM, log, sizeof(*log));
665 cmd->cdw10 |= NVME_FIELD_ENCODE((((__u32)(mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE) &
(NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
666 mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE,(((__u32)(mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE) &
(NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
667 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE) &
(NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
668 NVME_LOG_CDW10_LSP_MASK)(((__u32)(mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE) &
(NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
669}
670
671/**
672 * nvme_init_get_log_create_telemetry_host() - Initialize passthru command for
673 * Create Telemetry Host-Initiated
674 * @cmd: Passthru command to use
675 * @log: Userspace address of the log payload
676 *
677 * Initializes the passthru command buffer for the Get Log command with
678 * LID value %NVME_LOG_LID_TELEMETRY_HOST and
679 * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE.
680 */
681static inline void
682nvme_init_get_log_create_telemetry_host(struct libnvme_passthru_cmd *cmd,
683 struct nvme_telemetry_log *log)
684{
685 nvme_init_get_log_create_telemetry_host_mcda(cmd,
686 NVME_TELEMETRY_DA_CTRL_DETERMINE, log);
687}
688
689/**
690 * nvme_init_get_log_telemetry_ctrl() - Initialize passthru command for
691 * Telemetry Controller-Initiated
692 * @cmd: Passthru command to use
693 * @lpo: Offset into the telemetry data
694 * @log: User address for log page data
695 * @len: Length of provided user buffer to hold the log data in bytes
696 *
697 * Initializes the passthru command buffer for the Get Log command with
698 * LID value %NVME_LOG_LID_TELEMETRY_CTRL.
699 */
700static inline void
701nvme_init_get_log_telemetry_ctrl(struct libnvme_passthru_cmd *cmd,
702 __u64 lpo, void *log, __u32 len)
703{
704 nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_CTRL,
705 NVME_CSI_NVM, log, len);
706 nvme_init_get_log_lpo(cmd, lpo);
707}
708
709/**
710 * nvme_init_get_log_endurance_group() - Initialize passthru command for
711 * Endurance Group Information
712 * @cmd: Passthru command to use
713 * @endgid: Starting group identifier to return in the list
714 * @log: User address to store the endurance log
715 *
716 * Initializes the passthru command buffer for the Get Log command with
717 * LID value %NVME_LOG_LID_ENDURANCE_GROUP.
718 */
719static inline void
720nvme_init_get_log_endurance_group(struct libnvme_passthru_cmd *cmd,
721 __u16 endgid, struct nvme_endurance_group_log *log)
722{
723 nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_ENDURANCE_GROUP,
724 NVME_CSI_NVM, log, sizeof(*log));
725 cmd->cdw11 |= NVME_FIELD_ENCODE(endgid,(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
726 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
727 NVME_LOG_CDW11_LSI_MASK)(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
;
728}
729
730/**
731 * nvme_init_get_log_predictable_lat_nvmset() - Initialize passthru command for
732 * Predictable Latency Per NVM Set
733 * @cmd: Passthru command to use
734 * @nvmsetid: NVM set id
735 * @log: User address to store the predictable latency log
736 *
737 * Initializes the passthru command buffer for the Get Log command with
738 * LID value %NVME_LOG_LID_PREDICTABLE_LAT_NVMSET.
739 */
740static inline void
741nvme_init_get_log_predictable_lat_nvmset(struct libnvme_passthru_cmd *cmd,
742 __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log)
743{
744 nvme_init_get_log(cmd, NVME_NSID_NONE,
745 NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, NVME_CSI_NVM,
746 log, sizeof(*log));
747 cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
748 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(nvmsetid) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
749 NVME_LOG_CDW11_LSI_MASK)(((__u32)(nvmsetid) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
;
750}
751
752/**
753 * nvme_init_get_log_predictable_lat_event() - Initialize passthru command for
754 * Predictable Latency Event Aggregate
755 * @cmd: Passthru command to use
756 * @lpo: Offset into the predictable latency event
757 * @log: User address for log page data
758 * @len: Length of provided user buffer to hold the log data in bytes
759 *
760 * Initializes the passthru command buffer for the Get Log command with
761 * LID value %NVME_LOG_LID_PREDICTABLE_LAT_AGG.
762 */
763static inline void
764nvme_init_get_log_predictable_lat_event(struct libnvme_passthru_cmd *cmd,
765 __u64 lpo, void *log, __u32 len)
766{
767 nvme_init_get_log(cmd, NVME_NSID_NONE,
768 NVME_LOG_LID_PREDICTABLE_LAT_AGG, NVME_CSI_NVM,
769 log, len);
770 cmd->cdw12 = lpo & 0xffffffff;
771 cmd->cdw13 = lpo >> 32;
772}
773
774/**
775 * nvme_init_get_log_ana() - Initialize passthru command for
776 * Asymmetric Namespace Access
777 * @cmd: Passthru command to use
778 * @lsp: Log specific, see &enum nvme_get_log_ana_lsp
779 * @lpo: Offset to the start of the log page
780 * @log: User address to store the ana log
781 * @len: The allocated length of the log page
782 *
783 * Initializes the passthru command buffer for the Get Log command with
784 * LID value %NVME_LOG_LID_ANA.
785 */
786static inline void
787nvme_init_get_log_ana(struct libnvme_passthru_cmd *cmd,
788 enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len)
789{
790 nvme_init_get_log(cmd, NVME_NSID_NONE,
791 NVME_LOG_LID_ANA, NVME_CSI_NVM,
792 log, len);
793 cmd->cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
794 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
795 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
796 cmd->cdw12 = lpo & 0xffffffff;
797 cmd->cdw13 = lpo >> 32;
798}
799
800/**
801 * nvme_init_get_log_ana_groups() - Initialize passthru command for
802 * Asymmetric Namespace Access groups
803 * @cmd: Passthru command to use
804 * @log: User address to store the ana group log
805 * @len: The allocated length of the log page
806 *
807 * Initializes the passthru command buffer for the Get Log command with
808 * LID value %NVME_LOG_LID_ANA and LSP value %NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY
809 */
810static inline void
811nvme_init_get_log_ana_groups(struct libnvme_passthru_cmd *cmd,
812 struct nvme_ana_log *log, __u32 len)
813{
814 nvme_init_get_log_ana(cmd, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY,
815 0, log, len);
816}
817
818/**
819 * nvme_init_get_log_persistent_event() - Initialize passthru command for
820 * Persistent Event Log
821 * @cmd: Passthru command to use
822 * @action: Action the controller should take during processing this command
823 * @pevent_log: User address to store the persistent event log
824 * @len: Size of @pevent_log
825 *
826 * Initializes the passthru command buffer for the Get Log command with
827 * LID value %NVME_LOG_PERSISTENT_EVENT
828 */
829static inline void
830nvme_init_get_log_persistent_event(struct libnvme_passthru_cmd *cmd,
831 enum nvme_pevent_log_action action,
832 void *pevent_log, __u32 len)
833{
834 nvme_init_get_log(cmd, NVME_NSID_ALL,
835 NVME_LOG_LID_PERSISTENT_EVENT, NVME_CSI_NVM,
836 pevent_log, len);
837 cmd->cdw10 |= NVME_FIELD_ENCODE(action,(((__u32)(action) & (NVME_LOG_CDW10_LSP_MASK)) << (
NVME_LOG_CDW10_LSP_SHIFT))
838 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(action) & (NVME_LOG_CDW10_LSP_MASK)) << (
NVME_LOG_CDW10_LSP_SHIFT))
839 NVME_LOG_CDW10_LSP_MASK)(((__u32)(action) & (NVME_LOG_CDW10_LSP_MASK)) << (
NVME_LOG_CDW10_LSP_SHIFT))
;
840}
841
842/**
843 * nvme_init_get_log_lba_status() - Initialize passthru command for
844 * Retrieve LBA Status
845 * @cmd: Passthru command to use
846 * @lpo: Offset to the start of the log page
847 * @log: User address to store the log page
848 * @len: The allocated length of the log page
849 *
850 * Initializes the passthru command buffer for the Get Log command with
851 * LID value %NVME_LOG_LID_LBA_STATUS
852 */
853static inline void
854nvme_init_get_log_lba_status(struct libnvme_passthru_cmd *cmd,
855 __u64 lpo, void *log, __u32 len)
856{
857 nvme_init_get_log(cmd, NVME_NSID_NONE,
858 NVME_LOG_LID_LBA_STATUS, NVME_CSI_NVM,
859 log, len);
860 cmd->cdw12 = lpo & 0xffffffff;
861 cmd->cdw13 = lpo >> 32;
862}
863
864/**
865 * nvme_init_get_log_endurance_grp_evt() - Initialize passthru command for
866 * Endurance Group Event Aggregate
867 * @cmd: Passthru command to use
868 * @lpo: Offset to the start of the log page
869 * @log: User address to store the log page
870 * @len: The allocated length of the log page
871 *
872 * Initializes the passthru command buffer for the Get Log command with
873 * LID value %NVME_LOG_LID_ENDURANCE_GRP_EVT
874 */
875static inline void
876nvme_init_get_log_endurance_grp_evt(struct libnvme_passthru_cmd *cmd,
877 __u64 lpo, void *log, __u32 len)
878{
879 nvme_init_get_log(cmd, NVME_NSID_NONE,
880 NVME_LOG_LID_ENDURANCE_GRP_EVT, NVME_CSI_NVM,
881 log, len);
882 nvme_init_get_log_lpo(cmd, lpo);
883}
884
885/**
886 * nvme_init_get_log_media_unit_stat() - Initialize passthru command for
887 * Media Unit Status
888 * @cmd: Passthru command to use
889 * @domid: Domain Identifier selection, if supported
890 * @mus: User address to store the Media Unit statistics log
891 *
892 * Initializes the passthru command buffer for the Get Log command with
893 * LID value %NVME_LOG_LID_MEDIA_UNIT_STATUS
894 */
895static inline void
896nvme_init_get_log_media_unit_stat(struct libnvme_passthru_cmd *cmd,
897 __u16 domid, struct nvme_media_unit_stat_log *mus)
898{
899 nvme_init_get_log(cmd, NVME_NSID_NONE,
900 NVME_LOG_LID_MEDIA_UNIT_STATUS, NVME_CSI_NVM,
901 mus, sizeof(*mus));
902 cmd->cdw11 |= NVME_FIELD_ENCODE(domid,(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
903 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
904 NVME_LOG_CDW11_LSI_MASK)(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
905}
906
907/**
908 * nvme_init_get_log_support_cap_config_list() - Initialize passthru command for
909 * Supported Capacity Configuration List
910 * @cmd: Passthru command to use
911 * @domid: Domain Identifier selection, if supported
912 * @cap: User address to store supported capabilities config list
913 *
914 * Initializes the passthru command buffer for the Get Log command with
915 * LID value %NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST
916 */
917static inline void
918nvme_init_get_log_support_cap_config_list(struct libnvme_passthru_cmd *cmd,
919 __u16 domid, struct nvme_supported_cap_config_list_log *cap)
920{
921 nvme_init_get_log(cmd, NVME_NSID_NONE,
922 NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, NVME_CSI_NVM,
923 cap, sizeof(*cap));
924 cmd->cdw11 |= NVME_FIELD_ENCODE(domid,(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
925 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
926 NVME_LOG_CDW11_LSI_MASK)(((__u32)(domid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
927}
928
929/**
930 * nvme_init_get_log_fid_supported_effects() - Initialize passthru command for
931 * Feature Identifiers Supported and Effects
932 * @cmd: Passthru command to use
933 * @csi: Command set identifier, see &enum nvme_csi for known values
934 * @log: FID Supported and Effects data structure
935 *
936 * Initializes the passthru command buffer for the Get Log command with
937 * LID value %NVME_LOG_LID_FID_SUPPORTED_EFFECTS
938 */
939static inline void
940nvme_init_get_log_fid_supported_effects(struct libnvme_passthru_cmd *cmd,
941 enum nvme_csi csi, struct nvme_fid_supported_effects_log *log)
942{
943 nvme_init_get_log(cmd, NVME_NSID_NONE,
944 NVME_LOG_LID_FID_SUPPORTED_EFFECTS, csi,
945 log, sizeof(*log));
946}
947
948/**
949 * nvme_init_get_log_lockdown() - Initialize passthru command for
950 * Command and Feature Lockdown
951 * @cmd: Passthru command to use
952 * @cnscp: Contents and Scope of Command and Feature Identifier
953 * Lists, see &enum nvme_lockdown_log_lsp. Set the
954 * NVME_LOCKDOWN_LOG_LSP_ELPF bit to request the
955 * Controller-scoped Enhanced log page format instead of
956 * the original format.
957 * @cntlid: Controller Identifier: scopes the returned log page
958 * to the specified controller if the ELPF bit is set in
959 * @cnscp. Ignored otherwise.
960 * @lockdown_log: Buffer to store the lockdown log
961 *
962 * Initializes the passthru command buffer for the Get Log command with
963 * LID value %NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN
964 */
965static inline void
966nvme_init_get_log_lockdown(struct libnvme_passthru_cmd *cmd,
967 __u8 cnscp, __u16 cntlid, struct nvme_lockdown_log *lockdown_log)
968{
969 nvme_init_get_log(cmd, NVME_NSID_ALL,
970 NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, NVME_CSI_NVM,
971 lockdown_log, sizeof(*lockdown_log));
972 cmd->cdw10 |= NVME_FIELD_ENCODE(cnscp,(((__u32)(cnscp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
973 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(cnscp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
974 NVME_LOG_CDW10_LSP_MASK)(((__u32)(cnscp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
975 cmd->cdw11 |= NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
976 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(cntlid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
977 NVME_LOG_CDW11_LSI_MASK)(((__u32)(cntlid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
;
978}
979
980/**
981 * nvme_init_get_log_boot_partition() - Initialize passthru command for
982 * Boot Partition
983 * @cmd: Passthru command to use
984 * @lsp: The log specified field of LID
985 * @part: User address to store the log page
986 * @len: The allocated size, minimum
987 * struct nvme_boot_partition
988 *
989 * Initializes the passthru command buffer for the Get Log command with
990 * LID value %NVME_LOG_LID_BOOT_PARTITION
991 */
992static inline void
993nvme_init_get_log_boot_partition(struct libnvme_passthru_cmd *cmd,
994 __u8 lsp, struct nvme_boot_partition *part, __u32 len)
995{
996 nvme_init_get_log(cmd, NVME_NSID_NONE,
997 NVME_LOG_LID_BOOT_PARTITION, NVME_CSI_NVM,
998 part, len);
999 cmd->cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1000 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1001 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
1002}
1003
1004/**
1005 * nvme_init_get_log_rotational_media_info() - Initialize passthru command for
1006 * Rotational Media Information Log
1007 * @cmd: Passthru command to use
1008 * @endgid: Endurance Group Identifier
1009 * @log: User address to store the log page
1010 * @len: The allocated length of the log page
1011 *
1012 * Initializes the passthru command buffer for the Get Log command with
1013 * LID value %NVME_LOG_LID_ROTATIONAL_MEDIA_INFO
1014 */
1015static inline void
1016nvme_init_get_log_rotational_media_info(struct libnvme_passthru_cmd *cmd,
1017 __u16 endgid, struct nvme_rotational_media_info_log *log,
1018 __u32 len)
1019{
1020 nvme_init_get_log(cmd, NVME_NSID_NONE,
1021 NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, NVME_CSI_NVM,
1022 log, len);
1023 cmd->cdw11 |= NVME_FIELD_ENCODE(endgid,(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
1024 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
1025 NVME_LOG_CDW11_LSI_MASK)(((__u32)(endgid) & (NVME_LOG_CDW11_LSI_MASK)) << (
NVME_LOG_CDW11_LSI_SHIFT))
;
1026}
1027
1028/**
1029 * nvme_init_get_log_dispersed_ns_participating_nss() - Initialize passthru
1030 * command for Dispersed Namespace Participating NVM Subsystems
1031 * @cmd: Passthru command to use
1032 * @nsid: Namespace Identifier
1033 * @log: User address to store the log page
1034 * @len: The allocated length of the log page
1035 *
1036 * Initializes the passthru command buffer for the Get Log command with
1037 * LID value %NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS
1038 */
1039static inline void
1040nvme_init_get_log_dispersed_ns_participating_nss(
1041 struct libnvme_passthru_cmd *cmd, __u32 nsid,
1042 struct nvme_dispersed_ns_participating_nss_log *log, __u32 len)
1043{
1044 nvme_init_get_log(cmd, nsid,
1045 NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, NVME_CSI_NVM,
1046 log, len);
1047}
1048
1049/**
1050 * nvme_init_get_log_mgmt_addr_list() - Initialize passthru command for
1051 * Management Address List
1052 * @cmd: Passthru command to use
1053 * @log: User address to store the log page
1054 * @len: The allocated length of the log page
1055 *
1056 * Initializes the passthru command buffer for the Get Log command with
1057 * LID value %NVME_LOG_LID_MGMT_ADDR_LIST
1058 */
1059static inline void
1060nvme_init_get_log_mgmt_addr_list(struct libnvme_passthru_cmd *cmd,
1061 struct nvme_mgmt_addr_list_log *log, __u32 len)
1062{
1063 nvme_init_get_log(cmd, NVME_NSID_ALL,
1064 NVME_LOG_LID_MGMT_ADDR_LIST, NVME_CSI_NVM,
1065 log, len);
1066}
1067
1068/**
1069 * nvme_init_get_log_power_measurement() - Initialize passthru command for
1070 * Power Measurement
1071 * @cmd: Passthru command to use
1072 * @log: User address to store the log page
1073 * @len: The allocated length of the log page
1074 *
1075 * Initializes the passthru command buffer for the Get Log command with
1076 * LID value %NVME_LOG_LID_POWER_MEASUREMENT
1077 */
1078static inline void
1079nvme_init_get_log_power_measurement(struct libnvme_passthru_cmd *cmd,
1080 struct nvme_power_meas_log *log, __u32 len)
1081{
1082 nvme_init_get_log(cmd, NVME_NSID_ALL,
1083 NVME_LOG_LID_POWER_MEASUREMENT, NVME_CSI_NVM,
1084 log, len);
1085}
1086
1087/**
1088 * nvme_init_get_log_voltage_measurement() - Initialize passthru command for
1089 * Voltage Measurement
1090 * @cmd: Passthru command to use
1091 * @log: User address to store the log page
1092 * @len: The allocated length of the log page
1093 *
1094 * Initializes the passthru command buffer for the Get Log command with
1095 * LID value %NVME_LOG_LID_VOLTAGE_MEASUREMENT
1096 */
1097static inline void
1098nvme_init_get_log_voltage_measurement(struct libnvme_passthru_cmd *cmd,
1099 struct nvme_voltage_measurement_log *log, __u32 len)
1100{
1101 nvme_init_get_log(cmd, NVME_NSID_ALL,
1102 NVME_LOG_LID_VOLTAGE_MEASUREMENT, NVME_CSI_NVM,
1103 log, len);
1104}
1105
1106/**
1107 * nvme_init_get_log_phy_rx_eom() - Initialize passthru command for
1108 * Physical Interface Receiver Eye Opening Measurement
1109 * @cmd: Passthru command to use
1110 * @lsp: Log specific, controls action and measurement quality
1111 * @controller: Target controller ID
1112 * @log: User address to store the log page
1113 * @len: The allocated size, minimum
1114 * struct nvme_phy_rx_eom_log
1115 *
1116 * Initializes the passthru command buffer for the Get Log command with
1117 * LID value %NVME_LOG_LID_PHY_RX_EOM
1118 */
1119static inline void
1120nvme_init_get_log_phy_rx_eom(struct libnvme_passthru_cmd *cmd,
1121 __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log,
1122 __u32 len)
1123{
1124 nvme_init_get_log(cmd, NVME_NSID_NONE,
1125 NVME_LOG_LID_PHY_RX_EOM, NVME_CSI_NVM,
1126 log, len);
1127 cmd->cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1128 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1129 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
1130 cmd->cdw11 |= NVME_FIELD_ENCODE(controller,(((__u32)(controller) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
1131 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(controller) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
1132 NVME_LOG_CDW11_LSI_MASK)(((__u32)(controller) & (NVME_LOG_CDW11_LSI_MASK)) <<
(NVME_LOG_CDW11_LSI_SHIFT))
;
1133}
1134
1135/**
1136 * nvme_init_get_log_reachability_groups() - Initialize passthru command for
1137 * Retrieve Reachability Groups
1138 * @cmd: Passthru command to use
1139 * @rgo: Return groups only
1140 * @log: User address to store the log page
1141 * @len: The allocated length of the log page
1142 *
1143 * Initializes the passthru command buffer for the Get Log command with
1144 * LID value %NVME_LOG_LID_REACHABILITY_GROUPS
1145 */
1146static inline void
1147nvme_init_get_log_reachability_groups(struct libnvme_passthru_cmd *cmd,
1148 bool_Bool rgo, struct nvme_reachability_groups_log *log, __u32 len)
1149{
1150 nvme_init_get_log(cmd, NVME_NSID_ALL,
1151 NVME_LOG_LID_REACHABILITY_GROUPS, NVME_CSI_NVM,
1152 log, len);
1153 cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rgo,(((__u32)((__u8)rgo) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
1154 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)((__u8)rgo) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
1155 NVME_LOG_CDW10_LSP_MASK)(((__u32)((__u8)rgo) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
;
1156}
1157
1158/**
1159 * nvme_init_get_log_reachability_associations() - Initialize passthru command
1160 * for Reachability Associations Log
1161 * @cmd: Passthru command to use
1162 * @rao: Return associations only
1163 * @log: User address to store the log page
1164 * @len: The allocated length of the log page
1165 *
1166 * Initializes the passthru command buffer for the Get Log command with
1167 * LID value %NVME_LOG_LID_REACHABILITY_ASSOCIATIONS
1168 */
1169static inline void
1170nvme_init_get_log_reachability_associations(struct libnvme_passthru_cmd *cmd,
1171 bool_Bool rao, struct nvme_reachability_associations_log *log,
1172 __u32 len)
1173{
1174 nvme_init_get_log(cmd, NVME_NSID_ALL,
1175 NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, NVME_CSI_NVM,
1176 log, len);
1177 cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rao,(((__u32)((__u8)rao) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
1178 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)((__u8)rao) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
1179 NVME_LOG_CDW10_LSP_MASK)(((__u32)((__u8)rao) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
;
1180}
1181
1182/**
1183 * nvme_init_get_log_changed_alloc_ns() - Initialize passthru command for
1184 * Changed Allocated Namespace List
1185 * @cmd: Passthru command to use
1186 * @log: User address to store the log page
1187 * @len: The allocated length of the log page
1188 *
1189 * Initializes the passthru command buffer for the Get Log command with
1190 * LID value %NVME_LOG_LID_CHANGED_ALLOC_NS
1191 */
1192static inline void
1193nvme_init_get_log_changed_alloc_ns(struct libnvme_passthru_cmd *cmd,
1194 struct nvme_ns_list *log, __u32 len)
1195{
1196 nvme_init_get_log(cmd, NVME_NSID_ALL,
1197 NVME_LOG_LID_CHANGED_ALLOC_NS, NVME_CSI_NVM,
1198 log, len);
1199}
1200
1201/**
1202 * nvme_init_get_log_fdp_configurations() - Initialize passthru command for
1203 * Flexible Data Placement Configurations
1204 * @cmd: Passthru command to use
1205 * @egid: Endurance group identifier
1206 * @lpo: Offset into log page
1207 * @log: Log page data buffer
1208 * @len: Length (in bytes) of provided user buffer to hold the log data
1209 *
1210 * Initializes the passthru command buffer for the Get Log command with
1211 * LID value %NVME_LOG_LID_FDP_CONFIGS
1212 */
1213static inline void
1214nvme_init_get_log_fdp_configurations(struct libnvme_passthru_cmd *cmd,
1215 __u16 egid, __u64 lpo, void *log, __u32 len)
1216{
1217 nvme_init_get_log(cmd, NVME_NSID_NONE,
1218 NVME_LOG_LID_FDP_CONFIGS, NVME_CSI_NVM,
1219 log, len);
1220 cmd->cdw11 |= NVME_FIELD_ENCODE(egid,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1221 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1222 NVME_LOG_CDW11_LSI_MASK)(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
1223 nvme_init_get_log_lpo(cmd, lpo);
1224}
1225
1226/**
1227 * nvme_init_get_log_reclaim_unit_handle_usage() - Initialize passthru
1228 * command for Reclaim Unit Handle Usage
1229 * @cmd: Passthru command to use
1230 * @egid: Endurance group identifier
1231 * @lpo: Offset into log page
1232 * @log: Log page data buffer
1233 * @len: Length (in bytes) of provided user buffer to hold the log data
1234 *
1235 * Initializes the passthru command buffer for the Get Log command with
1236 * LID value %NVME_LOG_LID_RUH_USAGE
1237 */
1238static inline void
1239nvme_init_get_log_reclaim_unit_handle_usage(struct libnvme_passthru_cmd *cmd,
1240 __u16 egid, __u64 lpo, void *log, __u32 len)
1241{
1242 nvme_init_get_log(cmd, NVME_NSID_NONE,
1243 NVME_LOG_LID_FDP_RUH_USAGE, NVME_CSI_NVM,
1244 log, len);
1245 cmd->cdw11 |= NVME_FIELD_ENCODE(egid,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1246 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1247 NVME_LOG_CDW11_LSI_MASK)(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
1248 nvme_init_get_log_lpo(cmd, lpo);
1249}
1250
1251/**
1252 * nvme_init_get_log_fdp_stats() - Initialize passthru command for
1253 * Get Flexible Data Placement Statistics
1254 * @cmd: Passthru command to use
1255 * @egid: Endurance group identifier
1256 * @lpo: Offset into log page
1257 * @log: Log page data buffer
1258 * @len: Length (in bytes) of provided user buffer to hold the log data
1259 *
1260 * Initializes the passthru command buffer for the Get Log command with
1261 * LID value %NVME_LOG_LID_FDP_STATS
1262 */
1263static inline
1264void nvme_init_get_log_fdp_stats(struct libnvme_passthru_cmd *cmd,
1265 __u16 egid, __u64 lpo, void *log, __u32 len)
1266{
1267 nvme_init_get_log(cmd, NVME_NSID_NONE,
1268 NVME_LOG_LID_FDP_STATS, NVME_CSI_NVM,
1269 log, len);
1270 cmd->cdw11 |= NVME_FIELD_ENCODE(egid,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1271 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1272 NVME_LOG_CDW11_LSI_MASK)(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
1273 nvme_init_get_log_lpo(cmd, lpo);
1274}
1275
1276/**
1277 * nvme_init_get_log_fdp_events() - Initialize passthru command for
1278 * Flexible Data Placement Events
1279 * @cmd: Passthru command to use
1280 * @host_events: Whether to report host or controller events
1281 * @egid: Endurance group identifier
1282 * @lpo: Offset into log page
1283 * @log: Log page data buffer
1284 * @len: Length (in bytes) of provided user buffer to hold
1285 * the log data
1286 *
1287 * Initializes the passthru command buffer for the Get Log command with
1288 * LID value %NVME_LOG_LID_FDP_EVENTS
1289 */
1290static inline void
1291nvme_init_get_log_fdp_events(struct libnvme_passthru_cmd *cmd,
1292 bool_Bool host_events, __u16 egid, __u64 lpo, void *log, __u32 len)
1293{
1294 nvme_init_get_log(cmd, NVME_NSID_NONE,
1295 NVME_LOG_LID_FDP_EVENTS, NVME_CSI_NVM,
1296 log, len);
1297 cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)(host_events ? 0x1 : 0x0),(((__u32)((__u8)(host_events ? 0x1 : 0x0)) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
1298 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)((__u8)(host_events ? 0x1 : 0x0)) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
1299 NVME_LOG_CDW10_LSP_MASK)(((__u32)((__u8)(host_events ? 0x1 : 0x0)) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
1300 cmd->cdw11 |= NVME_FIELD_ENCODE(egid,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1301 NVME_LOG_CDW11_LSI_SHIFT,(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
1302 NVME_LOG_CDW11_LSI_MASK)(((__u32)(egid) & (NVME_LOG_CDW11_LSI_MASK)) << (NVME_LOG_CDW11_LSI_SHIFT
))
;
1303 nvme_init_get_log_lpo(cmd, lpo);
1304}
1305
1306/**
1307 * nvme_init_get_log_rate_limiting() - Initialize passthru command for
1308 * Rate Limiting
1309 * @cmd: Passthru command to use
1310 * @lpo: Offset into log page
1311 * @log: Log page data buffer
1312 * @len: Length (in bytes) of provided user buffer to hold the log data
1313 *
1314 * Initializes the passthru command buffer for the Get Log command with
1315 * LID value %NVME_LOG_LID_RATE_LIMITING
1316 */
1317static inline void
1318nvme_init_get_log_rate_limiting(struct libnvme_passthru_cmd *cmd,
1319 __u64 lpo, void *log, __u32 len)
1320{
1321 nvme_init_get_log(cmd, NVME_NSID_NONE,
1322 NVME_LOG_LID_RATE_LIMITING, NVME_CSI_NVM,
1323 log, len);
1324 nvme_init_get_log_lpo(cmd, lpo);
1325}
1326
1327/**
1328 * nvme_init_get_log_host_addressable_ns() - Initialize passthru command for
1329 * Host Addressable Namespaces
1330 * @cmd: Passthru command to use
1331 * @lpo: Offset into log page
1332 * @log: Log page data buffer
1333 * @len: Length (in bytes) of provided user buffer to hold the log data
1334 *
1335 * Initializes the passthru command buffer for the Get Log command with
1336 * LID value %NVME_LOG_LID_HOST_ADDRESSABLE_NS
1337 */
1338static inline void
1339nvme_init_get_log_host_addressable_ns(struct libnvme_passthru_cmd *cmd,
1340 __u64 lpo, void *log, __u32 len)
1341{
1342 nvme_init_get_log(cmd, NVME_NSID_NONE,
1343 NVME_LOG_LID_HOST_ADDRESSABLE_NS, NVME_CSI_SLM,
1344 log, len);
1345 nvme_init_get_log_lpo(cmd, lpo);
1346}
1347
1348/**
1349 * nvme_init_get_log_reservation() - Initialize passthru command for
1350 * Reservation Notification
1351 * @cmd: Passthru command to use
1352 * @log: User address to store the reservation log
1353 *
1354 * Initializes the passthru command buffer for the Get Log command with
1355 * LID value %NVME_LOG_LID_RESERVATION
1356 */
1357static inline void
1358nvme_init_get_log_reservation(struct libnvme_passthru_cmd *cmd,
1359 struct nvme_resv_notification_log *log)
1360{
1361 nvme_init_get_log(cmd, NVME_NSID_ALL,
1362 NVME_LOG_LID_RESERVATION, NVME_CSI_NVM,
1363 log, sizeof(*log));
1364}
1365
1366/**
1367 * nvme_init_get_log_sanitize() - Initialize passthru command for
1368 * Sanitize Status
1369 * @cmd: Passthru command to use
1370 * @log: User address to store the sanitize log
1371 *
1372 * Initializes the passthru command buffer for the Get Log command with
1373 * LID value %NVME_LOG_LID_SANITIZE
1374 */
1375static inline void
1376nvme_init_get_log_sanitize(struct libnvme_passthru_cmd *cmd,
1377 struct nvme_sanitize_log_page *log)
1378{
1379 nvme_init_get_log(cmd, NVME_NSID_ALL,
1380 NVME_LOG_LID_SANITIZE, NVME_CSI_NVM,
1381 log, sizeof(*log));
1382}
1383
1384/**
1385 * nvme_init_get_log_mfg_default_config_status() - Initialize passthru
1386 * command for Manufacturer Default Configuration Status
1387 * @cmd: Passthru command to use
1388 * @log: User address to store the log
1389 *
1390 * Initializes the passthru command buffer for the Get Log command with
1391 * LID value %NVME_LOG_LID_MFG_DEFAULT_CONFIG
1392 */
1393static inline void
1394nvme_init_get_log_mfg_default_config_status(struct libnvme_passthru_cmd *cmd,
1395 struct nvme_mfg_default_config_status_log *log)
1396{
1397 nvme_init_get_log(cmd, NVME_NSID_NONE,
1398 NVME_LOG_LID_MFG_DEFAULT_CONFIG, NVME_CSI_NVM,
1399 log, sizeof(*log));
1400}
1401
1402/**
1403 * nvme_init_get_log_dev_personality() - Initialize passthru command for
1404 * Device Personalities
1405 * @cmd: Passthru command to use
1406 * @log: User address to store the log page
1407 * @len: The allocated length of the log page
1408 *
1409 * Initializes the passthru command buffer for the Get Log command with
1410 * LID value %NVME_LOG_LID_DEV_PERSONALITY
1411 */
1412static inline void
1413nvme_init_get_log_dev_personality(struct libnvme_passthru_cmd *cmd,
1414 struct nvme_dev_personalities_log *log, __u32 len)
1415{
1416 nvme_init_get_log(cmd, NVME_NSID_NONE,
1417 NVME_LOG_LID_DEV_PERSONALITY, NVME_CSI_NVM,
1418 log, len);
1419}
1420
1421/**
1422 * nvme_init_identify() - Initialize passthru command for
1423 * NVMe Identify
1424 * @cmd: Command data structure to initialize
1425 * @nsid: Namespace identifier
1426 * @csi: Command Set Identifier
1427 * @cns: The Controller or Namespace structure,
1428 * see @enum nvme_identify_cns
1429 * @data: User space destination address to transfer the data
1430 * @len: Length of provided user buffer to hold the data in bytes
1431 *
1432 * Prepare the @cmd data structure for the NVMe Identify command.
1433 */
1434static inline void
1435nvme_init_identify(struct libnvme_passthru_cmd *cmd,
1436 __u32 nsid, enum nvme_csi csi, enum nvme_identify_cns cns,
1437 void *data, __u32 len)
1438{
1439 __u32 cdw10 = NVME_FIELD_ENCODE(cns,(((__u32)(cns) & (NVME_IDENTIFY_CDW10_CNS_MASK)) <<
(NVME_IDENTIFY_CDW10_CNS_SHIFT))
1440 NVME_IDENTIFY_CDW10_CNS_SHIFT,(((__u32)(cns) & (NVME_IDENTIFY_CDW10_CNS_MASK)) <<
(NVME_IDENTIFY_CDW10_CNS_SHIFT))
1441 NVME_IDENTIFY_CDW10_CNS_MASK)(((__u32)(cns) & (NVME_IDENTIFY_CDW10_CNS_MASK)) <<
(NVME_IDENTIFY_CDW10_CNS_SHIFT))
;
1442 __u32 cdw11 = NVME_FIELD_ENCODE(csi,(((__u32)(csi) & (NVME_IDENTIFY_CDW11_CSI_MASK)) <<
(NVME_IDENTIFY_CDW11_CSI_SHIFT))
1443 NVME_IDENTIFY_CDW11_CSI_SHIFT,(((__u32)(csi) & (NVME_IDENTIFY_CDW11_CSI_MASK)) <<
(NVME_IDENTIFY_CDW11_CSI_SHIFT))
1444 NVME_IDENTIFY_CDW11_CSI_MASK)(((__u32)(csi) & (NVME_IDENTIFY_CDW11_CSI_MASK)) <<
(NVME_IDENTIFY_CDW11_CSI_SHIFT))
;
1445
1446 memset(cmd, 0, sizeof(*cmd));
1447
1448 cmd->opcode = nvme_admin_identify;
1449 cmd->nsid = nsid;
1450 cmd->cdw10 = cdw10;
1451 cmd->cdw11 = cdw11;
1452 cmd->data_len = len;
1453 cmd->addr = (__u64)(uintptr_t)data;
1454}
10
Returning without writing to 'data->vid', which participates in a condition later
1455
1456/**
1457 * nvme_init_identify_ns() - Initialize passthru command for
1458 * NVMe Identify Namespace data structure
1459 * @cmd: Command data structure to initialize
1460 * @nsid: Namespace identifier
1461 * @id: User space destination address to transfer the data
1462 *
1463 * Initializes the passthru command buffer for the Identify command with
1464 * CNS value %NVME_IDENTIFY_CNS_NS.
1465 */
1466static inline void
1467nvme_init_identify_ns(struct libnvme_passthru_cmd *cmd,
1468 __u32 nsid, struct nvme_id_ns *id)
1469{
1470 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1471 NVME_IDENTIFY_CNS_NS,
1472 id, sizeof(*id));
1473}
1474
1475/**
1476 * nvme_init_identify_ctrl() - Initialize passthru command for
1477 * NVMe Identify Controller data structure
1478 * @cmd: Command data structure to initialize
1479 * @id: User space destination address to transfer the data,
1480 *
1481 * Initializes the passthru command buffer for the Identify command with
1482 * CNS value %NVME_IDENTIFY_CNS_CTRL.
1483 */
1484static inline void
1485nvme_init_identify_ctrl(struct libnvme_passthru_cmd *cmd,
1486 struct nvme_id_ctrl *id)
1487{
1488 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
9
Calling 'nvme_init_identify'
11
Returning from 'nvme_init_identify'
1489 NVME_IDENTIFY_CNS_CTRL,
1490 id, sizeof(*id));
1491}
12
Returning without writing to 'id->vid', which participates in a condition later
1492
1493/**
1494 * nvme_init_identify_active_ns_list() - Initialize passthru command for
1495 * Active Namespaces ID list
1496 * @cmd: Command data structure to initialize
1497 * @nsid: Namespace identifier
1498 * @list: User space destination address to transfer the data
1499 *
1500 * Initializes the passthru command buffer for the Identify command with
1501 * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST.
1502 */
1503static inline void
1504nvme_init_identify_active_ns_list(struct libnvme_passthru_cmd *cmd,
1505 __u32 nsid, struct nvme_ns_list *list)
1506{
1507 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1508 NVME_IDENTIFY_CNS_NS_ACTIVE_LIST,
1509 list, sizeof(*list));
1510}
1511
1512/**
1513 * nvme_init_identify_ns_descs_list() - Initialize passthru command for
1514 * Namespace Descriptor list
1515 * @cmd: Command data structure to initialize
1516 * @nsid: The namespace id to retrieve descriptors
1517 * @descs: User space destination address to transfer the data
1518 *
1519 * Initializes the passthru command buffer for the Identify command with
1520 * CNS value %NVME_IDENTIFY_CNS_NS_DESC_LIST.
1521 */
1522static inline void
1523nvme_init_identify_ns_descs_list(struct libnvme_passthru_cmd *cmd,
1524 __u32 nsid, struct nvme_ns_id_desc *descs)
1525{
1526 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1527 NVME_IDENTIFY_CNS_NS_DESC_LIST,
1528 descs, NVME_IDENTIFY_DATA_SIZE);
1529}
1530
1531/**
1532 * nvme_init_identify_nvmset_list() - Initialize passthru command for
1533 * NVM Set List data structure
1534 * @cmd: Command data structure to initialize
1535 * @nsid: Namespace identifier
1536 * @nvmsetid: NVM Set Identifier
1537 * @nvmset: User space destination address to transfer the data
1538 *
1539 * Initializes the passthru command buffer for the Identify command with
1540 * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST.
1541 */
1542static inline void
1543nvme_init_identify_nvmset_list(struct libnvme_passthru_cmd *cmd,
1544 __u32 nsid, __u16 nvmsetid, struct nvme_id_nvmset_list *nvmset)
1545{
1546 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1547 NVME_IDENTIFY_CNS_NVMSET_LIST,
1548 nvmset, sizeof(*nvmset));
1549 cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK
)) << (NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
1550 NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT,(((__u32)(nvmsetid) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK
)) << (NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
1551 NVME_IDENTIFY_CDW11_CNSSPECID_MASK)(((__u32)(nvmsetid) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK
)) << (NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
;
1552}
1553
1554/**
1555 * nvme_init_identify_csi_ns() - Initialize passthru command for
1556 * I/O Command Set specific Identify Namespace data structure
1557 * @cmd: Command data structure to initialize
1558 * @nsid: Namespace identifier
1559 * @csi: Command Set Identifier
1560 * @uidx: UUID Index for differentiating vendor specific encoding
1561 * @data: User space destination address to transfer the data
1562 *
1563 * Initializes the passthru command buffer for the Identify command with
1564 * CNS value %NVME_IDENTIFY_CNS_CSI_NS.
1565 */
1566static inline void
1567nvme_init_identify_csi_ns(struct libnvme_passthru_cmd *cmd,
1568 __u32 nsid, enum nvme_csi csi, __u8 uidx, void *data)
1569{
1570 nvme_init_identify(cmd, nsid, csi,
1571 NVME_IDENTIFY_CNS_CSI_NS,
1572 data, NVME_IDENTIFY_DATA_SIZE);
1573 cmd->cdw14 |= NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1574 NVME_IDENTIFY_CDW14_UUID_SHIFT,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1575 NVME_IDENTIFY_CDW14_UUID_MASK)(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
;
1576}
1577
1578/**
1579 * nvme_init_identify_csi_ctrl() - Initialize passthru command for
1580 * I/O Command Set specific Identify Controller data structure
1581 * @cmd: Command data structure to initialize
1582 * @csi: Command Set Identifier
1583 * @data: User space destination address to transfer the data
1584 *
1585 * Initializes the passthru command buffer for the Identify command with
1586 * CNS value %NVME_IDENTIFY_CNS_CSI_CTRL.
1587 */
1588static inline void
1589nvme_init_identify_csi_ctrl(struct libnvme_passthru_cmd *cmd,
1590 enum nvme_csi csi, void *data)
1591{
1592 nvme_init_identify(cmd, NVME_NSID_NONE, csi,
1593 NVME_IDENTIFY_CNS_CSI_CTRL,
1594 data, NVME_IDENTIFY_DATA_SIZE);
1595}
1596
1597/**
1598 * nvme_init_identify_csi_active_ns_list() - Initialize passthru command
1599 * for Active namespace ID list
1600 * @cmd: Command data structure to initialize
1601 * @nsid: Return namespaces greater than this identifier
1602 * @csi: Command Set Identifier
1603 * @ns_list: User space destination address to transfer the data
1604 *
1605 * Initializes the passthru command buffer for the Identify command with
1606 * CNS value %NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST.
1607 */
1608static inline void
1609nvme_init_identify_csi_active_ns_list(struct libnvme_passthru_cmd *cmd,
1610 __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list)
1611{
1612 nvme_init_identify(cmd, nsid, csi,
1613 NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST,
1614 ns_list, sizeof(*ns_list));
1615}
1616
1617/**
1618 * nvme_init_identify_csi_independent_identify_id_ns() -Initialize passthru
1619 * command for I/O Command Set Independent Identify Namespace data structure
1620 * @cmd: Command data structure to initialize
1621 * @nsid: Return namespaces greater than this identifier
1622 * @ns: I/O Command Set Independent Identify Namespace data
1623 * structure
1624 *
1625 * Initializes the passthru command buffer for the Identify command with
1626 * CNS value %NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS.
1627 */
1628static inline void
1629nvme_init_identify_csi_independent_identify_id_ns(
1630 struct libnvme_passthru_cmd *cmd,
1631 __u32 nsid, struct nvme_id_independent_id_ns *ns)
1632{
1633 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1634 NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS,
1635 ns, sizeof(*ns));
1636}
1637
1638/**
1639 * nvme_init_identify_ns_user_data_format() - Initialize passthru command
1640 * for Identify namespace user data format
1641 * @cmd: Command data structure to initialize
1642 * @csi: Command Set Identifier
1643 * @fidx: Format Index
1644 * @uidx: UUID selection, if supported
1645 * @data: User space destination address to transfer the data
1646 *
1647 * Initializes the passthru command buffer for the Identify command with
1648 * CNS value %NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT.
1649 */
1650static inline void
1651nvme_init_identify_ns_user_data_format(struct libnvme_passthru_cmd *cmd,
1652 enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data)
1653{
1654 nvme_init_identify(cmd, NVME_NSID_NONE, csi,
1655 NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT,
1656 data, NVME_IDENTIFY_DATA_SIZE);
1657 cmd->cdw11 |= NVME_FIELD_ENCODE(fidx,(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
1658 NVME_IDENTIFY_CDW11_FIDX_SHIFT,(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
1659 NVME_IDENTIFY_CDW11_FIDX_MASK)(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
;
1660 cmd->cdw14 |= NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1661 NVME_IDENTIFY_CDW14_UUID_SHIFT,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1662 NVME_IDENTIFY_CDW14_UUID_MASK)(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
;
1663}
1664
1665/**
1666 * nvme_init_identify_csi_ns_user_data_format() - Initialize passthru
1667 * command for Identify namespace user data format
1668 * @cmd: Command data structure to initialize
1669 * @csi: Command Set Identifier
1670 * @fidx: Format Index
1671 * @uidx: UUID selection, if supported
1672 * @data: User space destination address to transfer the data
1673 *
1674 * Initializes the passthru command buffer for the Identify command with
1675 * CNS value %NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT.
1676 */
1677static inline void
1678nvme_init_identify_csi_ns_user_data_format(struct libnvme_passthru_cmd *cmd,
1679 enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data)
1680{
1681 nvme_init_identify(cmd, NVME_NSID_NONE, csi,
1682 NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT,
1683 data, NVME_IDENTIFY_DATA_SIZE);
1684 cmd->cdw11 |= NVME_FIELD_ENCODE(fidx,(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
1685 NVME_IDENTIFY_CDW11_FIDX_SHIFT,(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
1686 NVME_IDENTIFY_CDW11_FIDX_MASK)(((__u32)(fidx) & (NVME_IDENTIFY_CDW11_FIDX_MASK)) <<
(NVME_IDENTIFY_CDW11_FIDX_SHIFT))
;
1687 cmd->cdw14 |= NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1688 NVME_IDENTIFY_CDW14_UUID_SHIFT,(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
1689 NVME_IDENTIFY_CDW14_UUID_MASK)(((__u32)(uidx) & (NVME_IDENTIFY_CDW14_UUID_MASK)) <<
(NVME_IDENTIFY_CDW14_UUID_SHIFT))
;
1690}
1691
1692/**
1693 * nvme_init_identify_allocated_ns_list() - Initialize passthru command
1694 * for Allocated namespace ID list
1695 * @cmd: Command data structure to initialize
1696 * @nsid: Return namespaces greater than this identifier
1697 * @ns_list: User space destination address to transfer the data
1698 *
1699 * Initializes the passthru command buffer for the Identify command with
1700 * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST.
1701 */
1702static inline void
1703nvme_init_identify_allocated_ns_list(struct libnvme_passthru_cmd *cmd,
1704 __u32 nsid, struct nvme_ns_list *ns_list)
1705{
1706 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1707 NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST,
1708 ns_list, sizeof(*ns_list));
1709}
1710
1711/**
1712 * nvme_init_identify_allocated_ns() - Initialize passthru command
1713 * for allocated Namespace ID list
1714 * @cmd: Command data structure to initialize
1715 * @nsid: Namespace to identify
1716 * @ns: User space destination address to transfer the data
1717 *
1718 * Initializes the passthru command buffer for the Identify command with
1719 * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS.
1720 */
1721static inline void
1722nvme_init_identify_allocated_ns(struct libnvme_passthru_cmd *cmd,
1723 __u32 nsid, struct nvme_id_ns *ns)
1724{
1725 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1726 NVME_IDENTIFY_CNS_ALLOCATED_NS,
1727 ns, sizeof(*ns));
1728}
1729
1730/**
1731 * nvme_init_identify_ns_ctrl_list() - Initialize passhtru command
1732 * for Controller List
1733 * @cmd: Command data structure to initialize
1734 * @nsid: Return controllers that are attached to this nsid
1735 * @cntid: Starting CNTLID to return in the list
1736 * @cntlist: User space destination address to transfer the data
1737 *
1738 * Initializes the passthru command buffer for the Identify command with
1739 * CNS value %NVME_IDENTIFY_CNS_NS_CTRL_LIST.
1740 */
1741static inline void
1742nvme_init_identify_ns_ctrl_list(struct libnvme_passthru_cmd *cmd,
1743 __u32 nsid, __u16 cntid, struct nvme_ctrl_list *cntlist)
1744{
1745 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
1746 NVME_IDENTIFY_CNS_NS_CTRL_LIST,
1747 cntlist, sizeof(*cntlist));
1748 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1749 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1750 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
1751}
1752
1753/**
1754 * nvme_init_identify_ctrl_list() - Initialize passthru command for
1755 * Controller List of controllers
1756 * @cmd: Command data structure to initialize
1757 * @cntid: Starting CNTLID to return in the list
1758 * @cntlist: User space destination address to transfer the data
1759 *
1760 * Initializes the passthru command buffer for the Identify command with
1761 * CNS value %NVME_IDENTIFY_CNS_CTRL_LIST.
1762 */
1763static inline void
1764nvme_init_identify_ctrl_list(struct libnvme_passthru_cmd *cmd,
1765 __u16 cntid, struct nvme_ctrl_list *cntlist)
1766{
1767 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1768 NVME_IDENTIFY_CNS_CTRL_LIST,
1769 cntlist, sizeof(*cntlist));
1770 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1771 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1772 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
1773}
1774
1775/**
1776 * nvme_init_identify_primary_ctrl_cap() - Initialize passthru command
1777 * for Primary Controller Capabilities data
1778 * @cmd: Command data structure to initialize
1779 * @cntid: Return controllers starting at this identifier
1780 * @cap: User space destination buffer address to transfer the data
1781 *
1782 * Initializes the passthru command buffer for the Identify command with
1783 * CNS value %NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP.
1784 */
1785static inline void
1786nvme_init_identify_primary_ctrl_cap(struct libnvme_passthru_cmd *cmd,
1787 __u16 cntid, struct nvme_primary_ctrl_cap *cap)
1788{
1789 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1790 NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP,
1791 cap, sizeof(*cap));
1792 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1793 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1794 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
1795}
1796
1797/**
1798 * nvme_init_identify_secondary_ctrl_list() - Initialize passhru command
1799 * for Secondary Controller list
1800 * @cmd: Command data structure to initialize
1801 * @cntid: Return controllers starting at this identifier
1802 * @sc_list: User space destination address to transfer the data
1803 *
1804 * Initializes the passthru command buffer for the Identify command with
1805 * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST.
1806 */
1807static inline void
1808nvme_init_identify_secondary_ctrl_list(struct libnvme_passthru_cmd *cmd,
1809 __u16 cntid, struct nvme_secondary_ctrl_list *sc_list)
1810{
1811 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1812 NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST,
1813 sc_list, sizeof(*sc_list));
1814 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1815 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1816 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
1817}
1818
1819/**
1820 * nvme_init_identify_ns_granularity() - Initialize passthru command for
1821 * Namespace Granularity list
1822 * @cmd: Command data structure to initialize
1823 * @gr_list: User space destination address to transfer the data
1824 *
1825 * Initializes the passthru command buffer for the Identify command with
1826 * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST.
1827 */
1828static inline void
1829nvme_init_identify_ns_granularity(struct libnvme_passthru_cmd *cmd,
1830 struct nvme_id_ns_granularity_list *gr_list)
1831{
1832 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1833 NVME_IDENTIFY_CNS_NS_GRANULARITY,
1834 gr_list, sizeof(*gr_list));
1835}
1836
1837/**
1838 * nvme_init_identify_uuid_list() - Initialize passthru command for
1839 * UUID list
1840 * @cmd: Command data structure to initialize
1841 * @uuid_list: User space destination address to transfer the data
1842 *
1843 * Initializes the passthru command buffer for the Identify command with
1844 * CNS value %NVME_IDENTIFY_CNS_UUID_LIST.
1845 */
1846static inline void
1847nvme_init_identify_uuid_list(struct libnvme_passthru_cmd *cmd,
1848 struct nvme_id_uuid_list *uuid_list)
1849{
1850 nvme_init_identify(cmd, NVME_UUID_NONE, NVME_CSI_NVM,
1851 NVME_IDENTIFY_CNS_UUID_LIST,
1852 uuid_list, sizeof(*uuid_list));
1853}
1854
1855/**
1856 * nvme_init_identify_domain_list() - Initialize passthru command for
1857 * Domain list
1858 * @cmd: Command data structure to initialize
1859 * @domid: Domain ID
1860 * @list: User space destination address to transfer data
1861 *
1862 * Initializes the passthru command buffer for the Identify command with
1863 * CNS value %NVME_IDENTIFY_CNS_DOMAIN_LIST.
1864 */
1865static inline void
1866nvme_init_identify_domain_list(struct libnvme_passthru_cmd *cmd,
1867 __u16 domid, struct nvme_id_domain_list *list)
1868{
1869 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1870 NVME_IDENTIFY_CNS_DOMAIN_LIST,
1871 list, sizeof(*list));
1872 cmd->cdw11 |= NVME_FIELD_ENCODE(domid,(((__u32)(domid) & (NVME_IDENTIFY_CDW11_DOMID_MASK)) <<
(NVME_IDENTIFY_CDW11_DOMID_SHIFT))
1873 NVME_IDENTIFY_CDW11_DOMID_SHIFT,(((__u32)(domid) & (NVME_IDENTIFY_CDW11_DOMID_MASK)) <<
(NVME_IDENTIFY_CDW11_DOMID_SHIFT))
1874 NVME_IDENTIFY_CDW11_DOMID_MASK)(((__u32)(domid) & (NVME_IDENTIFY_CDW11_DOMID_MASK)) <<
(NVME_IDENTIFY_CDW11_DOMID_SHIFT))
;
1875}
1876
1877/**
1878 * nvme_init_identify_endurance_group_id() - Initialize passthru command for
1879 * Endurance group list
1880 * @cmd: Command data structure to initialize
1881 * @enggid: Endurance group identifier
1882 * @list: Array of endurance group identifiers
1883 */
1884static inline void
1885nvme_init_identify_endurance_group_id(struct libnvme_passthru_cmd *cmd,
1886 __u16 enggid, struct nvme_id_endurance_group_list *list)
1887{
1888 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1889 NVME_IDENTIFY_CNS_ENDURANCE_GROUP_ID,
1890 list, sizeof(*list));
1891 cmd->cdw11 |= NVME_FIELD_ENCODE(enggid,(((__u32)(enggid) & (NVME_IDENTIFY_CDW11_ENGGID_MASK)) <<
(NVME_IDENTIFY_CDW11_ENGGID_SHIFT))
1892 NVME_IDENTIFY_CDW11_ENGGID_SHIFT,(((__u32)(enggid) & (NVME_IDENTIFY_CDW11_ENGGID_MASK)) <<
(NVME_IDENTIFY_CDW11_ENGGID_SHIFT))
1893 NVME_IDENTIFY_CDW11_ENGGID_MASK)(((__u32)(enggid) & (NVME_IDENTIFY_CDW11_ENGGID_MASK)) <<
(NVME_IDENTIFY_CDW11_ENGGID_SHIFT))
;
1894}
1895
1896/**
1897 * nvme_init_identify_csi_allocated_ns_list() - Initialize passthru command for
1898 * I/O Command Set specific Allocated Namespace Id list
1899 * @cmd: Command data structure to initialize
1900 * @nsid: Return namespaces greater than this identifier
1901 * @csi: Command Set Identifier
1902 * @ns_list: User space destination address to transfer the data
1903 *
1904 * Initializes the passthru command buffer for the Identify command with
1905 * CNS value %NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST.
1906 */
1907static inline void
1908nvme_init_identify_csi_allocated_ns_list(struct libnvme_passthru_cmd *cmd,
1909 __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list)
1910{
1911 nvme_init_identify(cmd, nsid, csi,
1912 NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST,
1913 ns_list, sizeof(*ns_list));
1914}
1915
1916/**
1917 * nvme_init_identify_csi_id_ns_data_structure() - Initialize passthru command
1918 * for I/O Command Set specific Identify Namespace data structure
1919 * @cmd: Command data structure to initialize
1920 * @nsid: Return namespaces greater than this identifier
1921 * @csi: Command Set Identifier
1922 * @data: User space destination address to transfer the data
1923 *
1924 * Initializes the passthru command buffer for the Identify command with
1925 * CNS value %NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE.
1926 */
1927static inline void
1928nvme_init_identify_csi_id_ns_data_structure(struct libnvme_passthru_cmd *cmd,
1929 __u32 nsid, enum nvme_csi csi, void *data)
1930{
1931 nvme_init_identify(cmd, nsid, csi,
1932 NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE,
1933 data, NVME_IDENTIFY_DATA_SIZE);
1934}
1935
1936/**
1937 * nvme_init_identify_command_set_structure() - Initialize passthru command for
1938 * I/O Command Set data structure
1939 * @cmd: Command data structure to initialize
1940 * @cntid: Controller ID
1941 * @iocs: User space destination address to transfer the data
1942 *
1943 * Retrieves list of the controller's supported io command set vectors. See
1944 * &struct nvme_id_iocs.
1945 */
1946static inline void
1947nvme_init_identify_command_set_structure(struct libnvme_passthru_cmd *cmd,
1948 __u16 cntid, struct nvme_id_iocs *iocs)
1949{
1950 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1951 NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE,
1952 iocs, sizeof(*iocs));
1953 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1954 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
1955 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
1956}
1957
1958/**
1959 * nvme_init_identify_underlying_ns_list() - Initialize passthru command for
1960 * Get Underlying Namespace List
1961 * @cmd: Command data structure to initialize
1962 * @idx: Index into the list of reportable Underlying Namespaces to
1963 * start reporting from
1964 * @list: User space destination address to transfer the data
1965 *
1966 * Initializes the passthru command buffer for the Identify command with
1967 * CNS value %NVME_IDENTIFY_CNS_UNDERLYING_NS_LIST.
1968 */
1969static inline void
1970nvme_init_identify_underlying_ns_list(struct libnvme_passthru_cmd *cmd,
1971 __u16 idx, struct nvme_underlying_ns_list *list)
1972{
1973 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1974 NVME_IDENTIFY_CNS_UNDERLYING_NS_LIST,
1975 list, sizeof(*list));
1976 cmd->cdw11 |= NVME_FIELD_ENCODE(idx,(((__u32)(idx) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK)) <<
(NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
1977 NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT,(((__u32)(idx) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK)) <<
(NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
1978 NVME_IDENTIFY_CDW11_CNSSPECID_MASK)(((__u32)(idx) & (NVME_IDENTIFY_CDW11_CNSSPECID_MASK)) <<
(NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT))
;
1979}
1980
1981/**
1982 * nvme_init_identify_ports_list() - Initialize passthru command for
1983 * Get Ports List
1984 * @cmd: Command data structure to initialize
1985 * @list: User space destination address to transfer the data
1986 * @len: The allocated length of @list
1987 *
1988 * Initializes the passthru command buffer for the Identify command with
1989 * CNS value %NVME_IDENTIFY_CNS_PORTS_LIST.
1990 */
1991static inline void
1992nvme_init_identify_ports_list(struct libnvme_passthru_cmd *cmd,
1993 struct nvme_ports_list *list, __u32 len)
1994{
1995 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
1996 NVME_IDENTIFY_CNS_PORTS_LIST,
1997 list, len);
1998}
1999
2000/**
2001 * nvme_init_identify_iocs_ind_id_alloc_ns() - Initialize passthru command for
2002 * I/O Command Set Independent Identify Namespace data structure for an
2003 * Allocated Namespace ID
2004 * @cmd: Command data structure to initialize
2005 * @nsid: Allocated namespace identifier
2006 * @ns: I/O Command Set Independent Identify Namespace data structure
2007 *
2008 * Initializes the passthru command buffer for the Identify command with
2009 * CNS value %NVME_IDENTIFY_CNS_IOCS_IND_ID_ALLOC_NS.
2010 */
2011static inline void
2012nvme_init_identify_iocs_ind_id_alloc_ns(struct libnvme_passthru_cmd *cmd,
2013 __u32 nsid, struct nvme_id_independent_id_ns *ns)
2014{
2015 nvme_init_identify(cmd, nsid, NVME_CSI_NVM,
2016 NVME_IDENTIFY_CNS_IOCS_IND_ID_ALLOC_NS,
2017 ns, sizeof(*ns));
2018}
2019
2020/**
2021 * nvme_init_identify_supported_ctrl_state_formats() - Initialize passthru
2022 * command for Supported Controller State Formats
2023 * @cmd: Command data structure to initialize
2024 * @formats: User space destination address to transfer the data
2025 *
2026 * Initializes the passthru command buffer for the Identify command with
2027 * CNS value %NVME_IDENTIFY_CNS_SUPPORTED_CTRL_STATE_FORMATS.
2028 */
2029static inline void
2030nvme_init_identify_supported_ctrl_state_formats(
2031 struct libnvme_passthru_cmd *cmd,
2032 struct nvme_supported_ctrl_state_formats *formats)
2033{
2034 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
2035 NVME_IDENTIFY_CNS_SUPPORTED_CTRL_STATE_FORMATS,
2036 formats, sizeof(*formats));
2037}
2038
2039/**
2040 * nvme_init_identify_underlying_ctrl_list() - Initialize passthru command
2041 * for Get Underlying Controller List
2042 * @cmd: Command data structure to initialize
2043 * @cntid: Starting CNTLID to return in the list
2044 * @cntlist: User space destination address to transfer the data
2045 *
2046 * Initializes the passthru command buffer for the Identify command with
2047 * CNS value %NVME_IDENTIFY_CNS_UNDERLYING_CTRL_LIST.
2048 */
2049static inline void
2050nvme_init_identify_underlying_ctrl_list(struct libnvme_passthru_cmd *cmd,
2051 __u16 cntid, struct nvme_ctrl_list *cntlist)
2052{
2053 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
2054 NVME_IDENTIFY_CNS_UNDERLYING_CTRL_LIST,
2055 cntlist, sizeof(*cntlist));
2056 cmd->cdw10 |= NVME_FIELD_ENCODE(cntid,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
2057 NVME_IDENTIFY_CDW10_CNTID_SHIFT,(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
2058 NVME_IDENTIFY_CDW10_CNTID_MASK)(((__u32)(cntid) & (NVME_IDENTIFY_CDW10_CNTID_MASK)) <<
(NVME_IDENTIFY_CDW10_CNTID_SHIFT))
;
2059}
2060
2061/**
2062 * nvme_init_identify_exported_nvm_subsys_template_uuid_list() - Initialize
2063 * passthru command for Exported NVM Subsystem Template UUID List
2064 * @cmd: Command data structure to initialize
2065 * @list: User space destination address to transfer the data
2066 *
2067 * Initializes the passthru command buffer for the Identify command with
2068 * CNS value %NVME_IDENTIFY_CNS_EXPORTED_NVM_SUBSYS_TEMPLATE_UUID_LIST.
2069 */
2070static inline void
2071nvme_init_identify_exported_nvm_subsys_template_uuid_list(
2072 struct libnvme_passthru_cmd *cmd,
2073 struct nvme_exported_nvm_subsys_template_uuid_list *list)
2074{
2075 nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM,
2076 NVME_IDENTIFY_CNS_EXPORTED_NVM_SUBSYS_TEMPLATE_UUID_LIST,
2077 list, sizeof(*list));
2078}
2079
2080/**
2081 * nvme_init_abort() - Initialize passthru command for
2082 * Abort command
2083 * @cmd: Passthru command to use
2084 * @sqid: Submission Queue Identifier (SQID) of the command to abort
2085 * @cid: Command Identifier (CID) of the command to abort
2086 *
2087 * Initializes the passthru command buffer for the Abort command.
2088 */
2089static inline void
2090nvme_init_abort(struct libnvme_passthru_cmd *cmd, __u16 sqid, __u16 cid)
2091{
2092 memset(cmd, 0, sizeof(*cmd));
2093 cmd->opcode = nvme_admin_abort_cmd;
2094 cmd->cdw10 = NVME_FIELD_ENCODE(cid, NVME_ABORT_CDW10_CID_SHIFT,(((__u32)(cid) & (NVME_ABORT_CDW10_CID_MASK)) << (NVME_ABORT_CDW10_CID_SHIFT
))
2095 NVME_ABORT_CDW10_CID_MASK)(((__u32)(cid) & (NVME_ABORT_CDW10_CID_MASK)) << (NVME_ABORT_CDW10_CID_SHIFT
))
|
2096 NVME_FIELD_ENCODE(sqid, NVME_ABORT_CDW10_SQID_SHIFT,(((__u32)(sqid) & (NVME_ABORT_CDW10_SQID_MASK)) << (
NVME_ABORT_CDW10_SQID_SHIFT))
2097 NVME_ABORT_CDW10_SQID_MASK)(((__u32)(sqid) & (NVME_ABORT_CDW10_SQID_MASK)) << (
NVME_ABORT_CDW10_SQID_SHIFT))
;
2098}
2099
2100/**
2101 * nvme_init_async_event() - Initialize passthru command for
2102 * Asynchronous Event Request command
2103 * @cmd: Passthru command to use
2104 *
2105 * Initializes the passthru command buffer for the Asynchronous Event
2106 * Request command. All command specific fields are reserved.
2107 */
2108static inline void
2109nvme_init_async_event(struct libnvme_passthru_cmd *cmd)
2110{
2111 memset(cmd, 0, sizeof(*cmd));
2112 cmd->opcode = nvme_admin_async_event;
2113}
2114
2115/**
2116 * nvme_init_set_features() - Initialize passthru command for
2117 * Set Features
2118 * @cmd: Passthru command to use
2119 * @fid: Feature identifier
2120 * @sv: Save value across power states
2121 */
2122static inline void
2123nvme_init_set_features(struct libnvme_passthru_cmd *cmd, __u8 fid, bool_Bool sv)
2124{
2125 __u32 cdw10 = NVME_FIELD_ENCODE(fid,(((__u32)(fid) & (NVME_SET_FEATURES_CDW10_FID_MASK)) <<
(NVME_SET_FEATURES_CDW10_FID_SHIFT))
2126 NVME_SET_FEATURES_CDW10_FID_SHIFT,(((__u32)(fid) & (NVME_SET_FEATURES_CDW10_FID_MASK)) <<
(NVME_SET_FEATURES_CDW10_FID_SHIFT))
2127 NVME_SET_FEATURES_CDW10_FID_MASK)(((__u32)(fid) & (NVME_SET_FEATURES_CDW10_FID_MASK)) <<
(NVME_SET_FEATURES_CDW10_FID_SHIFT))
|
2128 NVME_FIELD_ENCODE(sv,(((__u32)(sv) & (NVME_SET_FEATURES_CDW10_SV_MASK)) <<
(NVME_SET_FEATURES_CDW10_SV_SHIFT))
2129 NVME_SET_FEATURES_CDW10_SV_SHIFT,(((__u32)(sv) & (NVME_SET_FEATURES_CDW10_SV_MASK)) <<
(NVME_SET_FEATURES_CDW10_SV_SHIFT))
2130 NVME_SET_FEATURES_CDW10_SV_MASK)(((__u32)(sv) & (NVME_SET_FEATURES_CDW10_SV_MASK)) <<
(NVME_SET_FEATURES_CDW10_SV_SHIFT))
;
2131
2132 memset(cmd, 0, sizeof(*cmd));
2133
2134 cmd->opcode = nvme_admin_set_features;
2135 cmd->cdw10 = cdw10;
2136}
2137
2138/**
2139 * nvme_init_set_features_arbitration() -Initialize passthru command for
2140 * Arbitration Features
2141 * @cmd: Passthru command to use
2142 * @sv: Save value across power states
2143 * @ab: Arbitration Burst
2144 * @lpw: Low Priority Weight
2145 * @mpw: Medium Priority Weight
2146 * @hpw: High Priority Weight
2147 *
2148 * Initializes the passthru command buffer for the Set Features command with
2149 * FID value %NVME_FEAT_FID_ARBRITARTION
2150 */
2151static inline void
2152nvme_init_set_features_arbitration(struct libnvme_passthru_cmd *cmd,
2153 bool_Bool sv, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw)
2154{
2155 nvme_init_set_features(cmd, NVME_FEAT_FID_ARBITRATION, sv);
2156 cmd->cdw11 = NVME_FIELD_ENCODE(ab,(((__u32)(ab) & (NVME_FEAT_ARBITRATION_BURST_MASK)) <<
(NVME_FEAT_ARBITRATION_BURST_SHIFT))
2157 NVME_FEAT_ARBITRATION_BURST_SHIFT,(((__u32)(ab) & (NVME_FEAT_ARBITRATION_BURST_MASK)) <<
(NVME_FEAT_ARBITRATION_BURST_SHIFT))
2158 NVME_FEAT_ARBITRATION_BURST_MASK)(((__u32)(ab) & (NVME_FEAT_ARBITRATION_BURST_MASK)) <<
(NVME_FEAT_ARBITRATION_BURST_SHIFT))
|
2159 NVME_FIELD_ENCODE(lpw,(((__u32)(lpw) & (NVME_FEAT_ARBITRATION_LPW_MASK)) <<
(NVME_FEAT_ARBITRATION_LPW_SHIFT))
2160 NVME_FEAT_ARBITRATION_LPW_SHIFT,(((__u32)(lpw) & (NVME_FEAT_ARBITRATION_LPW_MASK)) <<
(NVME_FEAT_ARBITRATION_LPW_SHIFT))
2161 NVME_FEAT_ARBITRATION_LPW_MASK)(((__u32)(lpw) & (NVME_FEAT_ARBITRATION_LPW_MASK)) <<
(NVME_FEAT_ARBITRATION_LPW_SHIFT))
|
2162 NVME_FIELD_ENCODE(mpw,(((__u32)(mpw) & (NVME_FEAT_ARBITRATION_MPW_MASK)) <<
(NVME_FEAT_ARBITRATION_MPW_SHIFT))
2163 NVME_FEAT_ARBITRATION_MPW_SHIFT,(((__u32)(mpw) & (NVME_FEAT_ARBITRATION_MPW_MASK)) <<
(NVME_FEAT_ARBITRATION_MPW_SHIFT))
2164 NVME_FEAT_ARBITRATION_MPW_MASK)(((__u32)(mpw) & (NVME_FEAT_ARBITRATION_MPW_MASK)) <<
(NVME_FEAT_ARBITRATION_MPW_SHIFT))
|
2165 NVME_FIELD_ENCODE(hpw,(((__u32)(hpw) & (NVME_FEAT_ARBITRATION_HPW_MASK)) <<
(NVME_FEAT_ARBITRATION_HPW_SHIFT))
2166 NVME_FEAT_ARBITRATION_HPW_SHIFT,(((__u32)(hpw) & (NVME_FEAT_ARBITRATION_HPW_MASK)) <<
(NVME_FEAT_ARBITRATION_HPW_SHIFT))
2167 NVME_FEAT_ARBITRATION_HPW_MASK)(((__u32)(hpw) & (NVME_FEAT_ARBITRATION_HPW_MASK)) <<
(NVME_FEAT_ARBITRATION_HPW_SHIFT))
;
2168}
2169
2170/**
2171 * nvme_init_set_features_power_mgmt() - Initialize passthru command for
2172 * Power Management
2173 * @cmd: Passthru command to use
2174 * @sv: Save value across power states
2175 * @ps: Power State
2176 * @wh: Workload Hint
2177 *
2178 * Initializes the passthru command buffer for the Set Features command with
2179 * FID value %NVME_FEAT_FID_PWRMGMT_PS
2180 */
2181static inline void
2182nvme_init_set_features_power_mgmt(struct libnvme_passthru_cmd *cmd,
2183 bool_Bool sv, __u8 ps, __u8 wh)
2184{
2185
2186 nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_MGMT, sv);
2187 cmd->cdw11 = NVME_FIELD_ENCODE(ps,(((__u32)(ps) & (NVME_FEAT_PWRMGMT_PS_MASK)) << (NVME_FEAT_PWRMGMT_PS_SHIFT
))
2188 NVME_FEAT_PWRMGMT_PS_SHIFT,(((__u32)(ps) & (NVME_FEAT_PWRMGMT_PS_MASK)) << (NVME_FEAT_PWRMGMT_PS_SHIFT
))
2189 NVME_FEAT_PWRMGMT_PS_MASK)(((__u32)(ps) & (NVME_FEAT_PWRMGMT_PS_MASK)) << (NVME_FEAT_PWRMGMT_PS_SHIFT
))
|
2190 NVME_FIELD_ENCODE(wh,(((__u32)(wh) & (NVME_FEAT_PWRMGMT_WH_MASK)) << (NVME_FEAT_PWRMGMT_WH_SHIFT
))
2191 NVME_FEAT_PWRMGMT_WH_SHIFT,(((__u32)(wh) & (NVME_FEAT_PWRMGMT_WH_MASK)) << (NVME_FEAT_PWRMGMT_WH_SHIFT
))
2192 NVME_FEAT_PWRMGMT_WH_MASK)(((__u32)(wh) & (NVME_FEAT_PWRMGMT_WH_MASK)) << (NVME_FEAT_PWRMGMT_WH_SHIFT
))
;
2193}
2194
2195/**
2196 * nvme_init_set_features_lba_range() - Initialize passthru command for
2197 * LBA Range
2198 * @cmd: Passthru command to use
2199 * @nsid: Namespace ID
2200 * @sv: Save value across power states
2201 * @num: Number of ranges in @data
2202 * @data: User address of feature data
2203 *
2204 * Initializes the passthru command buffer for the Set Features command with
2205 * FID value %NVME_FEAT_FID_LBA_RANGE
2206 */
2207static inline void
2208nvme_init_set_features_lba_range(struct libnvme_passthru_cmd *cmd,
2209 __u32 nsid, bool_Bool sv, __u8 num,
2210 struct nvme_lba_range_type *data)
2211{
2212 nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_RANGE, sv);
2213 cmd->nsid = nsid;
2214 cmd->cdw11 = NVME_FIELD_ENCODE(num - 1,(((__u32)(num - 1) & (NVME_SET_FEATURES_CDW11_NUM_MASK)) <<
(NVME_SET_FEATURES_CDW11_NUM_SHIFT))
2215 NVME_SET_FEATURES_CDW11_NUM_SHIFT,(((__u32)(num - 1) & (NVME_SET_FEATURES_CDW11_NUM_MASK)) <<
(NVME_SET_FEATURES_CDW11_NUM_SHIFT))
2216 NVME_SET_FEATURES_CDW11_NUM_MASK)(((__u32)(num - 1) & (NVME_SET_FEATURES_CDW11_NUM_MASK)) <<
(NVME_SET_FEATURES_CDW11_NUM_SHIFT))
;
2217 cmd->data_len = sizeof(*data);
2218 cmd->addr = (__u64)(uintptr_t)data;
2219}
2220
2221/**
2222 * nvme_init_set_features_temp_thresh() - Initialize passthru command for
2223 * Temperature Threshold
2224 * @cmd: Passthru command to use
2225 * @sv: Save value across power states
2226 * @tmpth: Temperature Threshold
2227 * @tmpsel: Threshold Temperature Select
2228 * @thsel: Threshold Type Select
2229 * @tmpthh: Temperature Threshold Hysteresis
2230 *
2231 * Initializes the passthru command buffer for the Set Features command with
2232 * FID value %NVME_FEAT_FID_TEMP_THRESH
2233 */
2234static inline void
2235nvme_init_set_features_temp_thresh(struct libnvme_passthru_cmd *cmd,
2236 bool_Bool sv, __u16 tmpth, __u8 tmpsel,
2237 enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh)
2238{
2239
2240 nvme_init_set_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sv);
2241 cmd->cdw11 = NVME_FIELD_ENCODE(tmpth,(((__u32)(tmpth) & (NVME_FEAT_TT_TMPTH_MASK)) << (NVME_FEAT_TT_TMPTH_SHIFT
))
2242 NVME_FEAT_TT_TMPTH_SHIFT,(((__u32)(tmpth) & (NVME_FEAT_TT_TMPTH_MASK)) << (NVME_FEAT_TT_TMPTH_SHIFT
))
2243 NVME_FEAT_TT_TMPTH_MASK)(((__u32)(tmpth) & (NVME_FEAT_TT_TMPTH_MASK)) << (NVME_FEAT_TT_TMPTH_SHIFT
))
|
2244 NVME_FIELD_ENCODE(tmpsel,(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
2245 NVME_FEAT_TT_TMPSEL_SHIFT,(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
2246 NVME_FEAT_TT_TMPSEL_MASK)(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
|
2247 NVME_FIELD_ENCODE(thsel,(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
2248 NVME_FEAT_TT_THSEL_SHIFT,(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
2249 NVME_FEAT_TT_THSEL_MASK)(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
|
2250 NVME_FIELD_ENCODE(tmpthh,(((__u32)(tmpthh) & (NVME_FEAT_TT_TMPTHH_MASK)) << (
NVME_FEAT_TT_TMPTHH_SHIFT))
2251 NVME_FEAT_TT_TMPTHH_SHIFT,(((__u32)(tmpthh) & (NVME_FEAT_TT_TMPTHH_MASK)) << (
NVME_FEAT_TT_TMPTHH_SHIFT))
2252 NVME_FEAT_TT_TMPTHH_MASK)(((__u32)(tmpthh) & (NVME_FEAT_TT_TMPTHH_MASK)) << (
NVME_FEAT_TT_TMPTHH_SHIFT))
;
2253}
2254
2255/**
2256 * nvme_init_set_features_err_recovery() - Initialize passthru command for
2257 * Error Recovery
2258 * @cmd: Passthru command to use
2259 * @nsid: Namespace ID
2260 * @sv: Save value across power states
2261 * @tler: Time-limited error recovery value
2262 * @dulbe: Deallocated or Unwritten Logical Block Error Enable
2263 *
2264 * Initializes the passthru command buffer for the Set Features command with
2265 * FID value %NVME_FEAT_FID_ERR_RECOVERY
2266 */
2267static inline void
2268nvme_init_set_features_err_recovery(struct libnvme_passthru_cmd *cmd,
2269 __u32 nsid, bool_Bool sv, __u16 tler, bool_Bool dulbe)
2270{
2271 nvme_init_set_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sv);
2272 cmd->nsid = nsid;
2273 cmd->cdw11 = NVME_FIELD_ENCODE(tler,(((__u32)(tler) & (NVME_FEAT_ERROR_RECOVERY_TLER_MASK)) <<
(NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT))
2274 NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT,(((__u32)(tler) & (NVME_FEAT_ERROR_RECOVERY_TLER_MASK)) <<
(NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT))
2275 NVME_FEAT_ERROR_RECOVERY_TLER_MASK)(((__u32)(tler) & (NVME_FEAT_ERROR_RECOVERY_TLER_MASK)) <<
(NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT))
|
2276 NVME_FIELD_ENCODE(dulbe,(((__u32)(dulbe) & (NVME_FEAT_ERROR_RECOVERY_DULBE_MASK))
<< (NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT))
2277 NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT,(((__u32)(dulbe) & (NVME_FEAT_ERROR_RECOVERY_DULBE_MASK))
<< (NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT))
2278 NVME_FEAT_ERROR_RECOVERY_DULBE_MASK)(((__u32)(dulbe) & (NVME_FEAT_ERROR_RECOVERY_DULBE_MASK))
<< (NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT))
;
2279}
2280
2281/**
2282 * nvme_init_set_features_volatile_wc() - Initialize passthru command for
2283 * Volatile Write Cache
2284 * @cmd: Passthru command to use
2285 * @sv: Save value across power states
2286 * @wce: Write cache enable
2287 *
2288 * Initializes the passthru command buffer for the Set Features command with
2289 * FID value %NVME_FEAT_FID_VOLATILE_WC
2290 */
2291static inline void
2292nvme_init_set_features_volatile_wc(struct libnvme_passthru_cmd *cmd,
2293 bool_Bool sv, bool_Bool wce)
2294{
2295 nvme_init_set_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sv);
2296 cmd->cdw11 = NVME_FIELD_ENCODE(wce,(((__u32)(wce) & (NVME_FEAT_VWC_WCE_MASK)) << (NVME_FEAT_VWC_WCE_SHIFT
))
2297 NVME_FEAT_VWC_WCE_SHIFT,(((__u32)(wce) & (NVME_FEAT_VWC_WCE_MASK)) << (NVME_FEAT_VWC_WCE_SHIFT
))
2298 NVME_FEAT_VWC_WCE_MASK)(((__u32)(wce) & (NVME_FEAT_VWC_WCE_MASK)) << (NVME_FEAT_VWC_WCE_SHIFT
))
;
2299}
2300
2301/**
2302 * nvme_init_set_features_irq_coalesce() - Initialize passthru command for
2303 * IRQ Coalescing
2304 * @cmd: Passthru command to use
2305 * @sv: Save value across power states
2306 * @thr: Aggregation Threshold
2307 * @time: Aggregation Time
2308 *
2309 * Initializes the passthru command buffer for the Set Features command with
2310 * FID value %NVME_FEAT_FID_IRQ_COALESCE
2311 */
2312static inline void
2313nvme_init_set_features_irq_coalesce(struct libnvme_passthru_cmd *cmd,
2314 bool_Bool sv, __u8 thr, __u8 time)
2315{
2316 nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sv);
2317 cmd->cdw11 = NVME_FIELD_ENCODE(thr,(((__u32)(thr) & (NVME_FEAT_IRQC_THR_MASK)) << (NVME_FEAT_IRQC_THR_SHIFT
))
2318 NVME_FEAT_IRQC_THR_SHIFT,(((__u32)(thr) & (NVME_FEAT_IRQC_THR_MASK)) << (NVME_FEAT_IRQC_THR_SHIFT
))
2319 NVME_FEAT_IRQC_THR_MASK)(((__u32)(thr) & (NVME_FEAT_IRQC_THR_MASK)) << (NVME_FEAT_IRQC_THR_SHIFT
))
|
2320 NVME_FIELD_ENCODE(time,(((__u32)(time) & (NVME_FEAT_IRQC_TIME_MASK)) << (NVME_FEAT_IRQC_TIME_SHIFT
))
2321 NVME_FEAT_IRQC_TIME_SHIFT,(((__u32)(time) & (NVME_FEAT_IRQC_TIME_MASK)) << (NVME_FEAT_IRQC_TIME_SHIFT
))
2322 NVME_FEAT_IRQC_TIME_MASK)(((__u32)(time) & (NVME_FEAT_IRQC_TIME_MASK)) << (NVME_FEAT_IRQC_TIME_SHIFT
))
;
2323}
2324
2325/**
2326 * nvme_init_set_features_irq_config() - Initialize passthru command for
2327 * IRQ Config
2328 * @cmd: Passthru command to use
2329 * @sv: Save value across power states
2330 * @iv: Interrupt Vector
2331 * @cd: Coalescing Disable
2332 *
2333 * Initializes the passthru command buffer for the Set Features command with
2334 * FID value %NVME_FEAT_FID_IRQ_CONFIG
2335 */
2336static inline void
2337nvme_init_set_features_irq_config(struct libnvme_passthru_cmd *cmd,
2338 bool_Bool sv, __u16 iv, bool_Bool cd)
2339{
2340 nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sv);
2341 cmd->cdw11 = NVME_FIELD_ENCODE(iv,(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
2342 NVME_FEAT_ICFG_IV_SHIFT,(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
2343 NVME_FEAT_ICFG_IV_MASK)(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
|
2344 NVME_FIELD_ENCODE(cd,(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
2345 NVME_FEAT_ICFG_CD_SHIFT,(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
2346 NVME_FEAT_ICFG_CD_MASK)(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
;
2347}
2348
2349/**
2350 * nvme_init_set_features_write_atomic() - Initialize passthru command for
2351 * Write Atomic
2352 * @cmd: Passthru command to use
2353 * @sv: Save value across power states
2354 * @dn: Disable Normal
2355 *
2356 * Initializes the passthru command buffer for the Set Features command with
2357 * FID value %NVME_FEAT_FID_WRITE_ATOMIC
2358 */
2359static inline void
2360nvme_init_set_features_write_atomic(struct libnvme_passthru_cmd *cmd,
2361 bool_Bool sv, bool_Bool dn)
2362{
2363 nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sv);
2364 cmd->cdw11 = NVME_FIELD_ENCODE(dn,(((__u32)(dn) & (NVME_FEAT_WA_DN_MASK)) << (NVME_FEAT_WA_DN_SHIFT
))
2365 NVME_FEAT_WA_DN_SHIFT,(((__u32)(dn) & (NVME_FEAT_WA_DN_MASK)) << (NVME_FEAT_WA_DN_SHIFT
))
2366 NVME_FEAT_WA_DN_MASK)(((__u32)(dn) & (NVME_FEAT_WA_DN_MASK)) << (NVME_FEAT_WA_DN_SHIFT
))
;
2367}
2368
2369/**
2370 * nvme_init_set_features_async_event() - Initialize passthru command for
2371 * Asynchronous Event Configuration
2372 * @cmd: Passthru command to use
2373 * @sv: Save value across power states
2374 * @events: Events to enable
2375 *
2376 * Initializes the passthru command buffer for the Set Features command with
2377 * FID value %NVME_FEAT_FID_ASYNC_EVENT
2378 */
2379static inline void
2380nvme_init_set_features_async_event(struct libnvme_passthru_cmd *cmd,
2381 bool_Bool sv, __u32 events)
2382{
2383 nvme_init_set_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sv);
2384 cmd->cdw11 = events;
2385}
2386
2387/**
2388 * nvme_init_set_features_auto_pst() - Initialize passthru command for
2389 * Autonomous Power State Transition
2390 * @cmd: Passthru command to use
2391 * @sv: Save value across power states
2392 * @apste: Autonomous Power State Transition Enable
2393 * @apst: Autonomous Power State Transition data buffer
2394 *
2395 * Initializes the passthru command buffer for the Set Features command with
2396 * FID value %NVME_FEAT_FID_AUTO_PST
2397 */
2398static inline void
2399nvme_init_set_features_auto_pst(struct libnvme_passthru_cmd *cmd,
2400 bool_Bool sv, bool_Bool apste, struct nvme_feat_auto_pst *apst)
2401{
2402 nvme_init_set_features(cmd, NVME_FEAT_FID_AUTO_PST, sv);
2403 cmd->cdw11 = NVME_FIELD_ENCODE(apste,(((__u32)(apste) & (NVME_FEAT_APST_APSTE_MASK)) << (
NVME_FEAT_APST_APSTE_SHIFT))
2404 NVME_FEAT_APST_APSTE_SHIFT,(((__u32)(apste) & (NVME_FEAT_APST_APSTE_MASK)) << (
NVME_FEAT_APST_APSTE_SHIFT))
2405 NVME_FEAT_APST_APSTE_MASK)(((__u32)(apste) & (NVME_FEAT_APST_APSTE_MASK)) << (
NVME_FEAT_APST_APSTE_SHIFT))
;
2406 cmd->data_len = sizeof(*apst);
2407 cmd->addr = (__u64)(uintptr_t)apst;
2408}
2409
2410/**
2411 * nvme_init_set_features_timestamp() - Initialize passthru command for
2412 * Timestamp
2413 * @cmd: Passthru command to use
2414 * @sv: Save value across power states
2415 * @tstmp: The current timestamp value to assign to this feature
2416 * @ts: Timestamp data buffer (populated by this function)
2417 *
2418 * Initializes the passthru command buffer for the Set Features command with
2419 * FID value %NVME_FEAT_FID_TIMESTAMP. The caller must provide a valid
2420 * buffer via @ts, which this function will populate.
2421 */
2422static inline void
2423nvme_init_set_features_timestamp(struct libnvme_passthru_cmd *cmd,
2424 bool_Bool sv, __u64 tstmp, struct nvme_timestamp *ts)
2425{
2426 __le64 t = htole64(tstmp)__uint64_identity (tstmp);
2427
2428 memcpy(ts, &t, sizeof(__le64));
2429
2430 nvme_init_set_features(cmd, NVME_FEAT_FID_TIMESTAMP, sv);
2431 cmd->data_len = sizeof(*ts);
2432 cmd->addr = (__u64)(uintptr_t)ts;
2433}
2434
2435/**
2436 * nvme_init_set_features_hctm() - Initialize passthru command for
2437 * Host Controlled Thermal Management
2438 * @cmd: Passthru command to use
2439 * @sv: Save value across power states
2440 * @tmt2: Thermal Management Temperature 2
2441 * @tmt1: Thermal Management Temperature 1
2442 *
2443 * Initializes the passthru command buffer for the Set Features command with
2444 * FID value %NVME_FEAT_FID_HCTM
2445 */
2446static inline void
2447nvme_init_set_features_hctm(struct libnvme_passthru_cmd *cmd,
2448 bool_Bool sv, __u16 tmt2, __u16 tmt1)
2449{
2450 nvme_init_set_features(cmd, NVME_FEAT_FID_HCTM, sv);
2451 cmd->cdw11 = NVME_FIELD_ENCODE(tmt2,(((__u32)(tmt2) & (NVME_FEAT_HCTM_TMT2_MASK)) << (NVME_FEAT_HCTM_TMT2_SHIFT
))
2452 NVME_FEAT_HCTM_TMT2_SHIFT,(((__u32)(tmt2) & (NVME_FEAT_HCTM_TMT2_MASK)) << (NVME_FEAT_HCTM_TMT2_SHIFT
))
2453 NVME_FEAT_HCTM_TMT2_MASK)(((__u32)(tmt2) & (NVME_FEAT_HCTM_TMT2_MASK)) << (NVME_FEAT_HCTM_TMT2_SHIFT
))
|
2454 NVME_FIELD_ENCODE(tmt1,(((__u32)(tmt1) & (NVME_FEAT_HCTM_TMT1_MASK)) << (NVME_FEAT_HCTM_TMT1_SHIFT
))
2455 NVME_FEAT_HCTM_TMT1_SHIFT,(((__u32)(tmt1) & (NVME_FEAT_HCTM_TMT1_MASK)) << (NVME_FEAT_HCTM_TMT1_SHIFT
))
2456 NVME_FEAT_HCTM_TMT1_MASK)(((__u32)(tmt1) & (NVME_FEAT_HCTM_TMT1_MASK)) << (NVME_FEAT_HCTM_TMT1_SHIFT
))
;
2457}
2458
2459/**
2460 * nvme_init_set_features_nopsc() - Initialize passthru command for
2461 * Non-Operational Power State Config
2462 * @cmd: Passthru command to use
2463 * @sv: Save value across power states
2464 * @noppme: Non-Operational Power State Permissive Mode Enable
2465 *
2466 * Initializes the passthru command buffer for the Set Features command with
2467 * FID value %NVME_FEAT_FID_NOPSC
2468 */
2469static inline void
2470nvme_init_set_features_nopsc(struct libnvme_passthru_cmd *cmd,
2471 bool_Bool sv, bool_Bool noppme)
2472{
2473 nvme_init_set_features(cmd, NVME_FEAT_FID_NOPSC, sv);
2474 cmd->cdw11 = NVME_FIELD_ENCODE(noppme,(((__u32)(noppme) & (NVME_FEAT_NOPS_NOPPME_MASK)) <<
(NVME_FEAT_NOPS_NOPPME_SHIFT))
2475 NVME_FEAT_NOPS_NOPPME_SHIFT,(((__u32)(noppme) & (NVME_FEAT_NOPS_NOPPME_MASK)) <<
(NVME_FEAT_NOPS_NOPPME_SHIFT))
2476 NVME_FEAT_NOPS_NOPPME_MASK)(((__u32)(noppme) & (NVME_FEAT_NOPS_NOPPME_MASK)) <<
(NVME_FEAT_NOPS_NOPPME_SHIFT))
;
2477}
2478
2479/**
2480 * nvme_init_set_features_rrl() - Initialize passthru command for
2481 * Read Recovery Level
2482 * @cmd: Passthru command to use
2483 * @sv: Save value across power states
2484 * @nvmsetid: NVM set id
2485 * @rrl: Read recovery level setting
2486 *
2487 * Initializes the passthru command buffer for the Set Features command with
2488 * FID value %NVME_FEAT_FID_RRL
2489 */
2490static inline void
2491nvme_init_set_features_rrl(struct libnvme_passthru_cmd *cmd,
2492 bool_Bool sv, __u16 nvmsetid, __u8 rrl)
2493{
2494 nvme_init_set_features(cmd, NVME_FEAT_FID_RRL, sv);
2495 cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_FEAT_RRL_NVMSETID_MASK)) <<
(NVME_FEAT_RRL_NVMSETID_SHIFT))
2496 NVME_FEAT_RRL_NVMSETID_SHIFT,(((__u32)(nvmsetid) & (NVME_FEAT_RRL_NVMSETID_MASK)) <<
(NVME_FEAT_RRL_NVMSETID_SHIFT))
2497 NVME_FEAT_RRL_NVMSETID_MASK)(((__u32)(nvmsetid) & (NVME_FEAT_RRL_NVMSETID_MASK)) <<
(NVME_FEAT_RRL_NVMSETID_SHIFT))
;
2498 cmd->cdw12 = NVME_FIELD_ENCODE(rrl,(((__u32)(rrl) & (NVME_FEAT_RRL_RRL_MASK)) << (NVME_FEAT_RRL_RRL_SHIFT
))
2499 NVME_FEAT_RRL_RRL_SHIFT,(((__u32)(rrl) & (NVME_FEAT_RRL_RRL_MASK)) << (NVME_FEAT_RRL_RRL_SHIFT
))
2500 NVME_FEAT_RRL_RRL_MASK)(((__u32)(rrl) & (NVME_FEAT_RRL_RRL_MASK)) << (NVME_FEAT_RRL_RRL_SHIFT
))
;
2501}
2502
2503/**
2504 * nvme_init_set_features_plm_config() - Initialize passthru command for
2505 * Predictable Latency Mode Config
2506 * @cmd: Passthru command to use
2507 * @sv: Save value across power states
2508 * @nvmsetid: NVM Set Identifier
2509 * @lpe: Predictable Latency Enable
2510 * @data: Pointer to structure nvme_plm_config
2511 *
2512 * Initializes the passthru command buffer for the Set Features command with
2513 * FID value %NVME_FEAT_FID_PLM_CONFIG
2514 */
2515static inline void
2516nvme_init_set_features_plm_config(struct libnvme_passthru_cmd *cmd,
2517 bool_Bool sv, __u16 nvmsetid, bool_Bool lpe, struct nvme_plm_config *data)
2518{
2519 nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sv);
2520 cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
2521 NVME_FEAT_PLM_NVMSETID_SHIFT,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
2522 NVME_FEAT_PLM_NVMSETID_MASK)(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
;
2523 cmd->cdw12 = NVME_FIELD_ENCODE(lpe,(((__u32)(lpe) & (NVME_FEAT_PLM_LPE_MASK)) << (NVME_FEAT_PLM_LPE_SHIFT
))
2524 NVME_FEAT_PLM_LPE_SHIFT,(((__u32)(lpe) & (NVME_FEAT_PLM_LPE_MASK)) << (NVME_FEAT_PLM_LPE_SHIFT
))
2525 NVME_FEAT_PLM_LPE_MASK)(((__u32)(lpe) & (NVME_FEAT_PLM_LPE_MASK)) << (NVME_FEAT_PLM_LPE_SHIFT
))
;
2526 cmd->data_len = sizeof(*data);
2527 cmd->addr = (__u64)(uintptr_t)data;
2528}
2529
2530/**
2531 * nvme_init_set_features_plm_window() - Initialize passthru command for
2532 * Predictable Latency Mode Window
2533 * @cmd: Passthru command to use
2534 * @sv: Save value across power states
2535 * @nvmsetid: NVM Set Identifier
2536 * @wsel: Window Select
2537 *
2538 * Initializes the passthru command buffer for the Set Features command with
2539 * FID value %NVME_FEAT_FID_PLM_WINDOW
2540 */
2541static inline void
2542nvme_init_set_features_plm_window(struct libnvme_passthru_cmd *cmd,
2543 bool_Bool sv, __u16 nvmsetid,
2544 enum nvme_feat_plm_window_select wsel)
2545{
2546 nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sv);
2547 cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
2548 NVME_FEAT_PLM_NVMSETID_SHIFT,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
2549 NVME_FEAT_PLM_NVMSETID_MASK)(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
;
2550 cmd->cdw12 = NVME_FIELD_ENCODE(wsel,(((__u32)(wsel) & (NVME_FEAT_PLMW_WS_MASK)) << (NVME_FEAT_PLMW_WS_SHIFT
))
2551 NVME_FEAT_PLMW_WS_SHIFT,(((__u32)(wsel) & (NVME_FEAT_PLMW_WS_MASK)) << (NVME_FEAT_PLMW_WS_SHIFT
))
2552 NVME_FEAT_PLMW_WS_MASK)(((__u32)(wsel) & (NVME_FEAT_PLMW_WS_MASK)) << (NVME_FEAT_PLMW_WS_SHIFT
))
;
2553}
2554
2555/**
2556 * nvme_init_set_features_lba_sts_interval() - Initialize passthru command for
2557 * LBA Status Information Interval
2558 * @cmd: Passthru command to use
2559 * @sv: Save value across power states
2560 * @lsiri: LBA Status Information Report Interval
2561 * @lsipi: LBA Status Information Poll Interval
2562 *
2563 * Initializes the passthru command buffer for the Set Features command with
2564 * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL
2565 */
2566static inline void
2567nvme_init_set_features_lba_sts_interval(struct libnvme_passthru_cmd *cmd,
2568 bool_Bool sv, __u16 lsiri, __u16 lsipi)
2569{
2570 nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sv);
2571 cmd->cdw11 = NVME_FIELD_ENCODE(lsiri,(((__u32)(lsiri) & (NVME_FEAT_LBAS_LSIRI_MASK)) << (
NVME_FEAT_LBAS_LSIRI_SHIFT))
2572 NVME_FEAT_LBAS_LSIRI_SHIFT,(((__u32)(lsiri) & (NVME_FEAT_LBAS_LSIRI_MASK)) << (
NVME_FEAT_LBAS_LSIRI_SHIFT))
2573 NVME_FEAT_LBAS_LSIRI_MASK)(((__u32)(lsiri) & (NVME_FEAT_LBAS_LSIRI_MASK)) << (
NVME_FEAT_LBAS_LSIRI_SHIFT))
|
2574 NVME_FIELD_ENCODE(lsipi,(((__u32)(lsipi) & (NVME_FEAT_LBAS_LSIPI_MASK)) << (
NVME_FEAT_LBAS_LSIPI_SHIFT))
2575 NVME_FEAT_LBAS_LSIPI_SHIFT,(((__u32)(lsipi) & (NVME_FEAT_LBAS_LSIPI_MASK)) << (
NVME_FEAT_LBAS_LSIPI_SHIFT))
2576 NVME_FEAT_LBAS_LSIPI_MASK)(((__u32)(lsipi) & (NVME_FEAT_LBAS_LSIPI_MASK)) << (
NVME_FEAT_LBAS_LSIPI_SHIFT))
;
2577}
2578
2579/**
2580 * nvme_init_set_features_host_behavior() - Initialize passthru command for
2581 * Host Behavior
2582 * @cmd: Passthru command to use
2583 * @sv: Save value across power states
2584 * @data: Pointer to structure nvme_feat_host_behavior
2585 *
2586 * Initializes the passthru command buffer for the Set Features command with
2587 * FID value %NVME_FEAT_FID_HOST_BEHAVIOR
2588 */
2589static inline void
2590nvme_init_set_features_host_behavior(struct libnvme_passthru_cmd *cmd,
2591 bool_Bool sv, struct nvme_feat_host_behavior *data)
2592{
2593 nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sv);
2594 cmd->data_len = sizeof(*data);
2595 cmd->addr = (__u64)(uintptr_t)data;
2596}
2597
2598/**
2599 * nvme_init_set_features_sanitize() - Initialize passthru command for
2600 * Sanitize
2601 * @cmd: Passthru command to use
2602 * @sv: Save value across power states
2603 * @nodrm: No-Deallocate Response Mode
2604 *
2605 * Initializes the passthru command buffer for the Set Features command with
2606 * FID value %NVME_FEAT_FID_SANITIZE
2607 */
2608static inline void
2609nvme_init_set_features_sanitize(struct libnvme_passthru_cmd *cmd,
2610 bool_Bool sv, bool_Bool nodrm)
2611{
2612 nvme_init_set_features(cmd, NVME_FEAT_FID_SANITIZE, sv);
2613 cmd->cdw11 = NVME_FIELD_ENCODE(nodrm,(((__u32)(nodrm) & (NVME_FEAT_SANITIZE_NODRM_MASK)) <<
(NVME_FEAT_SANITIZE_NODRM_SHIFT))
2614 NVME_FEAT_SANITIZE_NODRM_SHIFT,(((__u32)(nodrm) & (NVME_FEAT_SANITIZE_NODRM_MASK)) <<
(NVME_FEAT_SANITIZE_NODRM_SHIFT))
2615 NVME_FEAT_SANITIZE_NODRM_MASK)(((__u32)(nodrm) & (NVME_FEAT_SANITIZE_NODRM_MASK)) <<
(NVME_FEAT_SANITIZE_NODRM_SHIFT))
;
2616}
2617
2618/**
2619 * nvme_init_set_features_endurance_evt_cfg() - Initialize passthru command for
2620 * Endurance Group Event Configuration
2621 * @cmd: Passthru command to use
2622 * @sv: Save value across power states
2623 * @endgid: Endurance Group Identifier
2624 * @egcw: Flags to enable warning,
2625 * see &enum nvme_eg_critical_warning_flags
2626 *
2627 * Initializes the passthru command buffer for the Set Features command with
2628 * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG
2629 */
2630static inline void
2631nvme_init_set_features_endurance_evt_cfg(struct libnvme_passthru_cmd *cmd,
2632 bool_Bool sv, __u16 endgid, __u8 egcw)
2633{
2634 nvme_init_set_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sv);
2635 cmd->cdw11 = NVME_FIELD_ENCODE(endgid,(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
2636 NVME_FEAT_EG_ENDGID_SHIFT,(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
2637 NVME_FEAT_EG_ENDGID_MASK)(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
|
2638 NVME_FIELD_ENCODE(egcw,(((__u32)(egcw) & (NVME_FEAT_EG_EGCW_MASK)) << (NVME_FEAT_EG_EGCW_SHIFT
))
2639 NVME_FEAT_EG_EGCW_SHIFT,(((__u32)(egcw) & (NVME_FEAT_EG_EGCW_MASK)) << (NVME_FEAT_EG_EGCW_SHIFT
))
2640 NVME_FEAT_EG_EGCW_MASK)(((__u32)(egcw) & (NVME_FEAT_EG_EGCW_MASK)) << (NVME_FEAT_EG_EGCW_SHIFT
))
;
2641}
2642
2643/**
2644 * nvme_init_set_features_sw_progress() - Initialize passthru command for
2645 * Software Pogress Marker
2646 * @cmd: Passthru command to use
2647 * @sv: Save value across power states
2648 * @pbslc: Pre-boot Software Load Count
2649 *
2650 * Initializes the passthru command buffer for the Set Features command with
2651 * FID value %NVME_FEAT_FID_SW_PROGRESS
2652 */
2653static inline void
2654nvme_init_set_features_sw_progress(struct libnvme_passthru_cmd *cmd,
2655 bool_Bool sv, __u8 pbslc)
2656{
2657 nvme_init_set_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sv);
2658 cmd->cdw11 = NVME_FIELD_ENCODE(pbslc,(((__u32)(pbslc) & (NVME_FEAT_SPM_PBSLC_MASK)) << (
NVME_FEAT_SPM_PBSLC_SHIFT))
2659 NVME_FEAT_SPM_PBSLC_SHIFT,(((__u32)(pbslc) & (NVME_FEAT_SPM_PBSLC_MASK)) << (
NVME_FEAT_SPM_PBSLC_SHIFT))
2660 NVME_FEAT_SPM_PBSLC_MASK)(((__u32)(pbslc) & (NVME_FEAT_SPM_PBSLC_MASK)) << (
NVME_FEAT_SPM_PBSLC_SHIFT))
;
2661}
2662
2663/**
2664 * nvme_init_set_features_host_id() - Initialize passthru command for
2665 * Host Identifier
2666 * @cmd: Passthru command to use
2667 * @sv: Save value across power states
2668 * @exhid: Enable Extended Host Identifier
2669 * @hostid: Host ID buffer to set
2670 *
2671 * Initializes the passthru command buffer for the Set Features command with
2672 * FID value %NVME_FEAT_FID_HOST_ID.
2673 */
2674static inline void
2675nvme_init_set_features_host_id(struct libnvme_passthru_cmd *cmd,
2676 bool_Bool sv, bool_Bool exhid, __u8 *hostid)
2677{
2678 nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_ID, sv);
2679 cmd->cdw11 = NVME_FIELD_ENCODE(exhid,(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
2680 NVME_FEAT_HOSTID_EXHID_SHIFT,(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
2681 NVME_FEAT_HOSTID_EXHID_MASK)(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
;
2682 cmd->data_len = exhid ? 16 : 8;
2683 cmd->addr = (__u64)(uintptr_t)hostid;
2684}
2685
2686/**
2687 * nvme_init_set_features_resv_nf_mask() - Initialize passthru command for
2688 * Reservation Notification Mask
2689 * @cmd: Passthru command to use
2690 * @nsid: Namespace ID
2691 * @sv: Save value across power states
2692 * @mask: Reservation Notification Mask Field
2693 *
2694 * Initializes the passthru command buffer for the Set Features command with
2695 * FID value %NVME_FEAT_FID_RESV_NF_MASK
2696 */
2697static inline void
2698nvme_init_set_features_resv_nf_mask(struct libnvme_passthru_cmd *cmd, __u32 nsid,
2699 bool_Bool sv, __u32 mask)
2700{
2701 nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_NF_MASK, sv);
2702 cmd->nsid = nsid;
2703 cmd->cdw11 = mask;
2704}
2705
2706/**
2707 * nvme_init_set_features_resv_persist() - Initialize passthru command for
2708 * Reservation Persistence
2709 * @cmd: Passthru command to use
2710 * @nsid: Namespace ID
2711 * @sv: Save value across power states
2712 * @ptpl: Persist Through Power Loss
2713 *
2714 * Initializes the passthru command buffer for the Set Features command with
2715 * FID value %NVME_FEAT_FID_RESV_PERSIST
2716 */
2717static inline void
2718nvme_init_set_features_resv_persist(struct libnvme_passthru_cmd *cmd, __u32 nsid,
2719 bool_Bool sv, bool_Bool ptpl)
2720{
2721 nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sv);
2722 cmd->nsid = nsid;
2723 cmd->cdw11 = NVME_FIELD_ENCODE(ptpl,(((__u32)(ptpl) & (NVME_FEAT_RESP_PTPL_MASK)) << (NVME_FEAT_RESP_PTPL_SHIFT
))
2724 NVME_FEAT_RESP_PTPL_SHIFT,(((__u32)(ptpl) & (NVME_FEAT_RESP_PTPL_MASK)) << (NVME_FEAT_RESP_PTPL_SHIFT
))
2725 NVME_FEAT_RESP_PTPL_MASK)(((__u32)(ptpl) & (NVME_FEAT_RESP_PTPL_MASK)) << (NVME_FEAT_RESP_PTPL_SHIFT
))
;
2726}
2727
2728/**
2729 * nvme_init_set_features_write_protect() - Initialize passthru command for
2730 * Write Protect
2731 * @cmd: Passthru command to use
2732 * @nsid: Namespace ID
2733 * @sv: Save value across power states
2734 * @wps: Write Protection State
2735 *
2736 * Initializes the passthru command buffer for the Set Features command with
2737 * FID value %NVME_FEAT_FID_WRITE_PROTECT
2738 */
2739static inline void
2740nvme_init_set_features_write_protect(struct libnvme_passthru_cmd *cmd,
2741 __u32 nsid, bool_Bool sv, enum nvme_feat_nswpcfg_state wps)
2742{
2743 nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sv);
2744 cmd->nsid = nsid;
2745 cmd->cdw11 = NVME_FIELD_ENCODE(wps,(((__u32)(wps) & (NVME_FEAT_WP_WPS_MASK)) << (NVME_FEAT_WP_WPS_SHIFT
))
2746 NVME_FEAT_WP_WPS_SHIFT,(((__u32)(wps) & (NVME_FEAT_WP_WPS_MASK)) << (NVME_FEAT_WP_WPS_SHIFT
))
2747 NVME_FEAT_WP_WPS_MASK)(((__u32)(wps) & (NVME_FEAT_WP_WPS_MASK)) << (NVME_FEAT_WP_WPS_SHIFT
))
;
2748}
2749
2750/**
2751 * nvme_init_set_features_iocs_profile() - Initialize passthru command for
2752 * I/O Command Set Profile
2753 * @cmd: Passthru command to use
2754 * @sv: Save value across power states
2755 * @iocsci: I/O Command Set Combination Index
2756 *
2757 * Initializes the passthru command buffer for the Set Features command with
2758 * FID value %NVME_FEAT_FID_IOCS_PROFILE
2759 */
2760static inline void
2761nvme_init_set_features_iocs_profile(struct libnvme_passthru_cmd *cmd,
2762 bool_Bool sv, __u16 iocsci)
2763{
2764 nvme_init_set_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sv);
2765 cmd->cdw11 = NVME_FIELD_ENCODE(iocsci,(((__u32)(iocsci) & (NVME_FEAT_IOCSP_IOCSCI_MASK)) <<
(NVME_FEAT_IOCSP_IOCSCI_SHIFT))
2766 NVME_FEAT_IOCSP_IOCSCI_SHIFT,(((__u32)(iocsci) & (NVME_FEAT_IOCSP_IOCSCI_MASK)) <<
(NVME_FEAT_IOCSP_IOCSCI_SHIFT))
2767 NVME_FEAT_IOCSP_IOCSCI_MASK)(((__u32)(iocsci) & (NVME_FEAT_IOCSP_IOCSCI_MASK)) <<
(NVME_FEAT_IOCSP_IOCSCI_SHIFT))
;
2768}
2769
2770/**
2771 * nvme_init_lm_set_features_ctrl_data_queue() - Initialize passthru command for
2772 * Set Controller Data Queue feature
2773 * @cmd: Passthru command to use
2774 * @cdqid: Controller Data Queue ID (CDQID)
2775 * @hp: Head Pointer (passed in cdw12)
2776 * @tpt: Tail Pointer Trigger (passed in cdw13)
2777 * @etpt: Enable Tail Pointer Trigger
2778 *
2779 * Initializes the passthru command buffer for the Set Features command with
2780 * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE.
2781 */
2782static inline void
2783nvme_init_lm_set_features_ctrl_data_queue(struct libnvme_passthru_cmd *cmd,
2784 __u16 cdqid, __u32 hp, __u32 tpt, bool_Bool etpt)
2785{
2786 nvme_init_set_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, false0);
2787 cmd->cdw11 = cdqid |
2788 NVME_FIELD_ENCODE(etpt,(((__u32)(etpt) & (NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK)) <<
(NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT))
2789 NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT,(((__u32)(etpt) & (NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK)) <<
(NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT))
2790 NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK)(((__u32)(etpt) & (NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK)) <<
(NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT))
;
2791 cmd->cdw12 = hp;
2792 cmd->cdw13 = tpt;
2793}
2794
2795/**
2796 * nvme_init_set_features_rate_limiting() - Initialize passthru command for
2797 * Rate Limiting
2798 * @cmd: Passthru command to use
2799 * @sv: Save value across power states
2800 * @target: Target of the rate limits setting, see
2801 * &enum nvme_rate_limiting_target
2802 * @tid: Target Identifier for the target specified by @target
2803 * @data: User address of the Rate Limiting data buffer, see
2804 * &struct nvme_rate_limiting_data
2805 *
2806 * Initializes the passthru command buffer for the Set Features command with
2807 * FID value %NVME_FEAT_FID_RATE_LIMITING
2808 */
2809static inline void
2810nvme_init_set_features_rate_limiting(struct libnvme_passthru_cmd *cmd,
2811 bool_Bool sv, __u8 target, __u16 tid,
2812 struct nvme_rate_limiting_data *data)
2813{
2814 nvme_init_set_features(cmd, NVME_FEAT_FID_RATE_LIMITING, sv);
2815 cmd->cdw11 = NVME_FIELD_ENCODE(target,(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
2816 NVME_FEAT_RATE_LIMITING_TGT_SHIFT,(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
2817 NVME_FEAT_RATE_LIMITING_TGT_MASK)(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
|
2818 NVME_FIELD_ENCODE(tid,(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
2819 NVME_FEAT_RATE_LIMITING_TID_SHIFT,(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
2820 NVME_FEAT_RATE_LIMITING_TID_MASK)(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
;
2821 cmd->data_len = sizeof(*data);
2822 cmd->addr = (__u64)(uintptr_t)data;
2823}
2824
2825/**
2826 * nvme_init_set_features_spinup_control() - Initialize passthru command for
2827 * Spinup Control
2828 * @cmd: Passthru command to use
2829 * @sv: Save value across power states
2830 * @sce: Spinup Control Enable (SCE)
2831 *
2832 * Initializes the passthru command buffer for the Set Features command with
2833 * FID value %NVME_FEAT_FID_SPINUP_CONTROL
2834 */
2835static inline void
2836nvme_init_set_features_spinup_control(struct libnvme_passthru_cmd *cmd,
2837 bool_Bool sv, bool_Bool sce)
2838{
2839 nvme_init_set_features(cmd, NVME_FEAT_FID_SPINUP_CONTROL, sv);
2840 cmd->cdw11 = NVME_FIELD_ENCODE(sce,(((__u32)(sce) & (NVME_FEAT_SPINUP_CONTROL_MASK)) <<
(NVME_FEAT_SPINUP_CONTROL_SHIFT))
2841 NVME_FEAT_SPINUP_CONTROL_SHIFT,(((__u32)(sce) & (NVME_FEAT_SPINUP_CONTROL_MASK)) <<
(NVME_FEAT_SPINUP_CONTROL_SHIFT))
2842 NVME_FEAT_SPINUP_CONTROL_MASK)(((__u32)(sce) & (NVME_FEAT_SPINUP_CONTROL_MASK)) <<
(NVME_FEAT_SPINUP_CONTROL_SHIFT))
;
2843}
2844
2845/**
2846 * nvme_init_set_features_power_loss_signal() - Initialize passthru command
2847 * for Power Loss Signaling Config
2848 * @cmd: Passthru command to use
2849 * @sv: Save value across power states
2850 * @plsm: Power Loss Signaling Mode (PLSM)
2851 *
2852 * Initializes the passthru command buffer for the Set Features command with
2853 * FID value %NVME_FEAT_FID_POWER_LOSS_SIGNAL
2854 */
2855static inline void
2856nvme_init_set_features_power_loss_signal(struct libnvme_passthru_cmd *cmd,
2857 bool_Bool sv, __u8 plsm)
2858{
2859 nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_LOSS_SIGNAL, sv);
2860 cmd->cdw11 = NVME_FIELD_ENCODE(plsm,(((__u32)(plsm) & (NVME_FEAT_PLS_MODE_MASK)) << (NVME_FEAT_PLS_MODE_SHIFT
))
2861 NVME_FEAT_PLS_MODE_SHIFT,(((__u32)(plsm) & (NVME_FEAT_PLS_MODE_MASK)) << (NVME_FEAT_PLS_MODE_SHIFT
))
2862 NVME_FEAT_PLS_MODE_MASK)(((__u32)(plsm) & (NVME_FEAT_PLS_MODE_MASK)) << (NVME_FEAT_PLS_MODE_SHIFT
))
;
2863}
2864
2865/**
2866 * nvme_init_set_features_perf_characteristics() - Initialize passthru
2867 * command for Performance Characteristics
2868 * @cmd: Passthru command to use
2869 * @sv: Save value across power states
2870 * @attri: Attribute Index (ATTRI)
2871 * @rvspa: Revert Vendor Specific Performance Attribute (RVSPA)
2872 * @data: Pointer to structure nvme_perf_characteristics
2873 *
2874 * Initializes the passthru command buffer for the Set Features command with
2875 * FID value %NVME_FEAT_FID_PERF_CHARACTERISTICS
2876 */
2877static inline void
2878nvme_init_set_features_perf_characteristics(struct libnvme_passthru_cmd *cmd,
2879 bool_Bool sv, __u8 attri, bool_Bool rvspa,
2880 struct nvme_perf_characteristics *data)
2881{
2882 nvme_init_set_features(cmd, NVME_FEAT_FID_PERF_CHARACTERISTICS, sv);
2883 cmd->cdw11 = NVME_FIELD_ENCODE(attri,(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
2884 NVME_FEAT_PERFC_ATTRI_SHIFT,(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
2885 NVME_FEAT_PERFC_ATTRI_MASK)(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
|
2886 NVME_FIELD_ENCODE(rvspa,(((__u32)(rvspa) & (NVME_FEAT_PERFC_RVSPA_MASK)) <<
(NVME_FEAT_PERFC_RVSPA_SHIFT))
2887 NVME_FEAT_PERFC_RVSPA_SHIFT,(((__u32)(rvspa) & (NVME_FEAT_PERFC_RVSPA_MASK)) <<
(NVME_FEAT_PERFC_RVSPA_SHIFT))
2888 NVME_FEAT_PERFC_RVSPA_MASK)(((__u32)(rvspa) & (NVME_FEAT_PERFC_RVSPA_MASK)) <<
(NVME_FEAT_PERFC_RVSPA_SHIFT))
;
2889 cmd->data_len = sizeof(*data);
2890 cmd->addr = (__u64)(uintptr_t)data;
2891}
2892
2893/**
2894 * nvme_init_set_features_fdp() - Initialize passthru command for
2895 * Flexible Data Placement
2896 * @cmd: Passthru command to use
2897 * @sv: Save value across power states
2898 * @endgid: Endurance Group Identifier (ENDGID)
2899 * @fdpcidx: Flexible Data Placement Configuration Index (FDPCIDX)
2900 * @fdpe: Flexible Data Placement Enable (FDPE)
2901 *
2902 * Initializes the passthru command buffer for the Set Features command with
2903 * FID value %NVME_FEAT_FID_FDP
2904 */
2905static inline void
2906nvme_init_set_features_fdp(struct libnvme_passthru_cmd *cmd,
2907 bool_Bool sv, __u16 endgid, __u8 fdpcidx, bool_Bool fdpe)
2908{
2909 nvme_init_set_features(cmd, NVME_FEAT_FID_FDP, sv);
2910 cmd->cdw11 = endgid;
2911 cmd->cdw12 = NVME_FIELD_ENCODE(fdpcidx,(((__u32)(fdpcidx) & (NVME_FEAT_FDP_INDEX_MASK)) <<
(NVME_FEAT_FDP_INDEX_SHIFT))
2912 NVME_FEAT_FDP_INDEX_SHIFT,(((__u32)(fdpcidx) & (NVME_FEAT_FDP_INDEX_MASK)) <<
(NVME_FEAT_FDP_INDEX_SHIFT))
2913 NVME_FEAT_FDP_INDEX_MASK)(((__u32)(fdpcidx) & (NVME_FEAT_FDP_INDEX_MASK)) <<
(NVME_FEAT_FDP_INDEX_SHIFT))
|
2914 NVME_FIELD_ENCODE(fdpe,(((__u32)(fdpe) & (NVME_FEAT_FDP_ENABLED_MASK)) << (
NVME_FEAT_FDP_ENABLED_SHIFT))
2915 NVME_FEAT_FDP_ENABLED_SHIFT,(((__u32)(fdpe) & (NVME_FEAT_FDP_ENABLED_MASK)) << (
NVME_FEAT_FDP_ENABLED_SHIFT))
2916 NVME_FEAT_FDP_ENABLED_MASK)(((__u32)(fdpe) & (NVME_FEAT_FDP_ENABLED_MASK)) << (
NVME_FEAT_FDP_ENABLED_SHIFT))
;
2917}
2918
2919/**
2920 * nvme_init_set_features_fdp_events() - Initialize passthru command for
2921 * Flexible Data Placement Events
2922 * @cmd: Passthru command to use
2923 * @sv: Save value across power states
2924 * @phndl: Placement Handle (PHNDL)
2925 * @fdpee: FDP Event Enable (FDPEE)
2926 * @event_types: FDP Event Type List data buffer, see Figure 504 of the Base
2927 * Specification
2928 * @noet: Number of FDP Event Types (NOET) contained in @event_types
2929 *
2930 * Initializes the passthru command buffer for the Set Features command with
2931 * FID value %NVME_FEAT_FID_FDP_EVENTS
2932 */
2933static inline void
2934nvme_init_set_features_fdp_events(struct libnvme_passthru_cmd *cmd,
2935 bool_Bool sv, __u16 phndl, bool_Bool fdpee, __u8 *event_types, __u8 noet)
2936{
2937 nvme_init_set_features(cmd, NVME_FEAT_FID_FDP_EVENTS, sv);
2938 cmd->cdw11 = NVME_FIELD_ENCODE(phndl,(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
2939 NVME_FEAT_FDPE_PHNDL_SHIFT,(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
2940 NVME_FEAT_FDPE_PHNDL_MASK)(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
|
2941 NVME_FIELD_ENCODE(noet,(((__u32)(noet) & (NVME_FEAT_FDPE_NOET_MASK)) << (NVME_FEAT_FDPE_NOET_SHIFT
))
2942 NVME_FEAT_FDPE_NOET_SHIFT,(((__u32)(noet) & (NVME_FEAT_FDPE_NOET_MASK)) << (NVME_FEAT_FDPE_NOET_SHIFT
))
2943 NVME_FEAT_FDPE_NOET_MASK)(((__u32)(noet) & (NVME_FEAT_FDPE_NOET_MASK)) << (NVME_FEAT_FDPE_NOET_SHIFT
))
;
2944 cmd->cdw12 = NVME_FIELD_ENCODE(fdpee,(((__u32)(fdpee) & (NVME_FEAT_FDP_EVENTS_ENABLE_MASK)) <<
(NVME_FEAT_FDP_EVENTS_ENABLE_SHIFT))
2945 NVME_FEAT_FDP_EVENTS_ENABLE_SHIFT,(((__u32)(fdpee) & (NVME_FEAT_FDP_EVENTS_ENABLE_MASK)) <<
(NVME_FEAT_FDP_EVENTS_ENABLE_SHIFT))
2946 NVME_FEAT_FDP_EVENTS_ENABLE_MASK)(((__u32)(fdpee) & (NVME_FEAT_FDP_EVENTS_ENABLE_MASK)) <<
(NVME_FEAT_FDP_EVENTS_ENABLE_SHIFT))
;
2947 cmd->data_len = noet;
2948 cmd->addr = (__u64)(uintptr_t)event_types;
2949}
2950
2951/**
2952 * nvme_init_set_features_ns_admin_label() - Initialize passthru command for
2953 * Namespace Admin Label
2954 * @cmd: Passthru command to use
2955 * @nsid: Namespace Identifier
2956 * @sv: Save value across power states
2957 * @label: 256 byte, null-terminated UTF-8 Namespace Admin Label (NSAL)
2958 * data buffer
2959 *
2960 * Initializes the passthru command buffer for the Set Features command with
2961 * FID value %NVME_FEAT_FID_NS_ADMIN_LABEL
2962 */
2963static inline void
2964nvme_init_set_features_ns_admin_label(struct libnvme_passthru_cmd *cmd,
2965 __u32 nsid, bool_Bool sv, void *label)
2966{
2967 nvme_init_set_features(cmd, NVME_FEAT_FID_NS_ADMIN_LABEL, sv);
2968 cmd->nsid = nsid;
2969 cmd->data_len = 256;
2970 cmd->addr = (__u64)(uintptr_t)label;
2971}
2972
2973/**
2974 * nvme_init_set_features_personality() - Initialize passthru command for
2975 * Configurable Device Personality
2976 * @cmd: Passthru command to use
2977 * @sv: Save value across power states
2978 * @perid: Personality Identifier (PERID), see &enum nvme_personality_identifier
2979 * @chps: Change Personality Settings (CHPS)
2980 * @perfs: Personality Freeze State (PERFS)
2981 * @cdw11: Personality Identifier specific Command Dword 11 value
2982 * @data: Personality Identifier specific data buffer, or NULL if the
2983 * personality does not use the data buffer
2984 * @len: Length of @data
2985 *
2986 * Initializes the passthru command buffer for the Set Features command with
2987 * FID value %NVME_FEAT_FID_CONF_DEV_PERSONALITY
2988 */
2989static inline void
2990nvme_init_set_features_personality(struct libnvme_passthru_cmd *cmd,
2991 bool_Bool sv, __u8 perid, bool_Bool chps, bool_Bool perfs, __u32 cdw11,
2992 void *data, __u32 len)
2993{
2994 nvme_init_set_features(cmd, NVME_FEAT_FID_CONF_DEV_PERSONALITY, sv);
2995 cmd->cdw11 = cdw11;
2996 cmd->cdw13 = NVME_FIELD_ENCODE(perid,(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
2997 NVME_FEAT_CDP_PERID_SHIFT,(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
2998 NVME_FEAT_CDP_PERID_MASK)(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
|
2999 (chps ? NVME_FEAT_CDP_CHPS : 0) |
3000 (perfs ? NVME_FEAT_CDP_PERFS : 0);
3001 cmd->data_len = len;
3002 cmd->addr = (__u64)(uintptr_t)data;
3003}
3004
3005/**
3006 * nvme_init_set_features_power_limit() - Initialize passthru command for
3007 * Power Limit
3008 * @cmd: Passthru command to use
3009 * @sv: Save value across power states
3010 * @pls: Power Limit Scale (PLS)
3011 * @plv: Power Limit Value (PLV)
3012 *
3013 * Initializes the passthru command buffer for the Set Features command with
3014 * FID value %NVME_FEAT_FID_POWER_LIMIT
3015 */
3016static inline void
3017nvme_init_set_features_power_limit(struct libnvme_passthru_cmd *cmd,
3018 bool_Bool sv, __u8 pls, __u16 plv)
3019{
3020 nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_LIMIT, sv);
3021 cmd->cdw13 = NVME_FIELD_ENCODE(pls,(((__u32)(pls) & (NVME_FEAT_POWER_LIMIT_PLS_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLS_SHIFT))
3022 NVME_FEAT_POWER_LIMIT_PLS_SHIFT,(((__u32)(pls) & (NVME_FEAT_POWER_LIMIT_PLS_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLS_SHIFT))
3023 NVME_FEAT_POWER_LIMIT_PLS_MASK)(((__u32)(pls) & (NVME_FEAT_POWER_LIMIT_PLS_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLS_SHIFT))
|
3024 NVME_FIELD_ENCODE(plv,(((__u32)(plv) & (NVME_FEAT_POWER_LIMIT_PLV_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLV_SHIFT))
3025 NVME_FEAT_POWER_LIMIT_PLV_SHIFT,(((__u32)(plv) & (NVME_FEAT_POWER_LIMIT_PLV_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLV_SHIFT))
3026 NVME_FEAT_POWER_LIMIT_PLV_MASK)(((__u32)(plv) & (NVME_FEAT_POWER_LIMIT_PLV_MASK)) <<
(NVME_FEAT_POWER_LIMIT_PLV_SHIFT))
;
3027}
3028
3029/**
3030 * nvme_init_set_features_power_threshold() - Initialize passthru command for
3031 * Power Threshold
3032 * @cmd: Passthru command to use
3033 * @sv: Save value across power states
3034 * @ept: Enable Power Threshold (EPT)
3035 * @pmts: Power Measurement Type Select (PMTS)
3036 * @pts: Power Threshold Scale (PTS)
3037 * @ptv: Power Threshold Value (PTV)
3038 *
3039 * Initializes the passthru command buffer for the Set Features command with
3040 * FID value %NVME_FEAT_FID_POWER_THRESH
3041 */
3042static inline void
3043nvme_init_set_features_power_threshold(struct libnvme_passthru_cmd *cmd,
3044 bool_Bool sv, bool_Bool ept, __u8 pmts, __u8 pts, __u16 ptv)
3045{
3046 nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_THRESH, sv);
3047 cmd->cdw11 = NVME_FIELD_ENCODE(ept,(((__u32)(ept) & (NVME_FEAT_POWER_THRESH_EPT_MASK)) <<
(NVME_FEAT_POWER_THRESH_EPT_SHIFT))
3048 NVME_FEAT_POWER_THRESH_EPT_SHIFT,(((__u32)(ept) & (NVME_FEAT_POWER_THRESH_EPT_MASK)) <<
(NVME_FEAT_POWER_THRESH_EPT_SHIFT))
3049 NVME_FEAT_POWER_THRESH_EPT_MASK)(((__u32)(ept) & (NVME_FEAT_POWER_THRESH_EPT_MASK)) <<
(NVME_FEAT_POWER_THRESH_EPT_SHIFT))
|
3050 NVME_FIELD_ENCODE(pmts,(((__u32)(pmts) & (NVME_FEAT_POWER_THRESH_PMTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PMTS_SHIFT))
3051 NVME_FEAT_POWER_THRESH_PMTS_SHIFT,(((__u32)(pmts) & (NVME_FEAT_POWER_THRESH_PMTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PMTS_SHIFT))
3052 NVME_FEAT_POWER_THRESH_PMTS_MASK)(((__u32)(pmts) & (NVME_FEAT_POWER_THRESH_PMTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PMTS_SHIFT))
|
3053 NVME_FIELD_ENCODE(pts,(((__u32)(pts) & (NVME_FEAT_POWER_THRESH_PTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTS_SHIFT))
3054 NVME_FEAT_POWER_THRESH_PTS_SHIFT,(((__u32)(pts) & (NVME_FEAT_POWER_THRESH_PTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTS_SHIFT))
3055 NVME_FEAT_POWER_THRESH_PTS_MASK)(((__u32)(pts) & (NVME_FEAT_POWER_THRESH_PTS_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTS_SHIFT))
|
3056 NVME_FIELD_ENCODE(ptv,(((__u32)(ptv) & (NVME_FEAT_POWER_THRESH_PTV_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTV_SHIFT))
3057 NVME_FEAT_POWER_THRESH_PTV_SHIFT,(((__u32)(ptv) & (NVME_FEAT_POWER_THRESH_PTV_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTV_SHIFT))
3058 NVME_FEAT_POWER_THRESH_PTV_MASK)(((__u32)(ptv) & (NVME_FEAT_POWER_THRESH_PTV_MASK)) <<
(NVME_FEAT_POWER_THRESH_PTV_SHIFT))
;
3059}
3060
3061/**
3062 * nvme_init_set_features_power_measurement() - Initialize passthru command
3063 * for Power Measurement
3064 * @cmd: Passthru command to use
3065 * @sv: Save value across power states
3066 * @act: Action (ACT), see &enum nvme_voltage_measurement_act (the
3067 * Power Measurement and Voltage Measurement Action field
3068 * values are defined identically)
3069 * @pmts: Power Measurement Type Select (PMTS), used if @act requests
3070 * Start Power Measurements
3071 * @smt: Stop Measurement Time (SMT), used if @act requests Start Power
3072 * Measurements
3073 * @actsp: Action Specific (ACTSP) Command Dword 12 value
3074 *
3075 * Initializes the passthru command buffer for the Set Features command with
3076 * FID value %NVME_FEAT_FID_POWER_MEASUREMENT
3077 */
3078static inline void
3079nvme_init_set_features_power_measurement(struct libnvme_passthru_cmd *cmd,
3080 bool_Bool sv, __u8 act, __u8 pmts, __u16 smt, __u32 actsp)
3081{
3082 nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_MEASUREMENT, sv);
3083 cmd->cdw11 = NVME_FIELD_ENCODE(smt,(((__u32)(smt) & (NVME_FEAT_POWER_MEAS_SMT_MASK)) <<
(NVME_FEAT_POWER_MEAS_SMT_SHIFT))
3084 NVME_FEAT_POWER_MEAS_SMT_SHIFT,(((__u32)(smt) & (NVME_FEAT_POWER_MEAS_SMT_MASK)) <<
(NVME_FEAT_POWER_MEAS_SMT_SHIFT))
3085 NVME_FEAT_POWER_MEAS_SMT_MASK)(((__u32)(smt) & (NVME_FEAT_POWER_MEAS_SMT_MASK)) <<
(NVME_FEAT_POWER_MEAS_SMT_SHIFT))
|
3086 NVME_FIELD_ENCODE(pmts,(((__u32)(pmts) & (NVME_FEAT_POWER_MEAS_PMTS_MASK)) <<
(NVME_FEAT_POWER_MEAS_PMTS_SHIFT))
3087 NVME_FEAT_POWER_MEAS_PMTS_SHIFT,(((__u32)(pmts) & (NVME_FEAT_POWER_MEAS_PMTS_MASK)) <<
(NVME_FEAT_POWER_MEAS_PMTS_SHIFT))
3088 NVME_FEAT_POWER_MEAS_PMTS_MASK)(((__u32)(pmts) & (NVME_FEAT_POWER_MEAS_PMTS_MASK)) <<
(NVME_FEAT_POWER_MEAS_PMTS_SHIFT))
|
3089 NVME_FIELD_ENCODE(act,(((__u32)(act) & (NVME_FEAT_POWER_MEAS_ACT_MASK)) <<
(NVME_FEAT_POWER_MEAS_ACT_SHIFT))
3090 NVME_FEAT_POWER_MEAS_ACT_SHIFT,(((__u32)(act) & (NVME_FEAT_POWER_MEAS_ACT_MASK)) <<
(NVME_FEAT_POWER_MEAS_ACT_SHIFT))
3091 NVME_FEAT_POWER_MEAS_ACT_MASK)(((__u32)(act) & (NVME_FEAT_POWER_MEAS_ACT_MASK)) <<
(NVME_FEAT_POWER_MEAS_ACT_SHIFT))
;
3092 cmd->cdw12 = actsp;
3093}
3094
3095/**
3096 * nvme_init_set_features_voltage_threshold() - Initialize passthru command
3097 * for Voltage Threshold
3098 * @cmd: Passthru command to use
3099 * @sv: Save value across power states
3100 * @vsens: Voltage Sensor Select (VSENS)
3101 * @evt: Enable Voltage Threshold (EVT)
3102 * @ovt: Overvoltage Threshold (OVT)
3103 * @uvt: Undervoltage Threshold (UVT)
3104 *
3105 * Initializes the passthru command buffer for the Set Features command with
3106 * FID value %NVME_FEAT_FID_VOLTAGE_THRESHOLD
3107 */
3108static inline void
3109nvme_init_set_features_voltage_threshold(struct libnvme_passthru_cmd *cmd,
3110 bool_Bool sv, __u8 vsens, bool_Bool evt, __u16 ovt, __u16 uvt)
3111{
3112 nvme_init_set_features(cmd, NVME_FEAT_FID_VOLTAGE_THRESHOLD, sv);
3113 cmd->cdw11 = NVME_FIELD_ENCODE(vsens,(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
3114 NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT,(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
3115 NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK)(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
|
3116 (evt ? NVME_FEAT_VOLTAGE_THRESHOLD_EVT : 0) |
3117 NVME_FIELD_ENCODE(ovt,(((__u32)(ovt) & (NVME_FEAT_VOLTAGE_THRESHOLD_OVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_OVT_SHIFT))
3118 NVME_FEAT_VOLTAGE_THRESHOLD_OVT_SHIFT,(((__u32)(ovt) & (NVME_FEAT_VOLTAGE_THRESHOLD_OVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_OVT_SHIFT))
3119 NVME_FEAT_VOLTAGE_THRESHOLD_OVT_MASK)(((__u32)(ovt) & (NVME_FEAT_VOLTAGE_THRESHOLD_OVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_OVT_SHIFT))
|
3120 NVME_FIELD_ENCODE(uvt,(((__u32)(uvt) & (NVME_FEAT_VOLTAGE_THRESHOLD_UVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_UVT_SHIFT))
3121 NVME_FEAT_VOLTAGE_THRESHOLD_UVT_SHIFT,(((__u32)(uvt) & (NVME_FEAT_VOLTAGE_THRESHOLD_UVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_UVT_SHIFT))
3122 NVME_FEAT_VOLTAGE_THRESHOLD_UVT_MASK)(((__u32)(uvt) & (NVME_FEAT_VOLTAGE_THRESHOLD_UVT_MASK)) <<
(NVME_FEAT_VOLTAGE_THRESHOLD_UVT_SHIFT))
;
3123}
3124
3125/**
3126 * nvme_init_set_features_voltage_measurement() - Initialize passthru command
3127 * for Voltage Measurement
3128 * @cmd: Passthru command to use
3129 * @sv: Save value across power states
3130 * @act: Action (ACT), see &enum nvme_voltage_measurement_act
3131 * @data: Start Voltage Measurements data buffer, used if @act is
3132 * %NVME_VOLTAGE_MEASUREMENT_ACT_START, otherwise NULL, see
3133 * &struct nvme_voltage_measurement_start_data
3134 *
3135 * Initializes the passthru command buffer for the Set Features command with
3136 * FID value %NVME_FEAT_FID_VOLTAGE_MEASUREMENT
3137 */
3138static inline void
3139nvme_init_set_features_voltage_measurement(struct libnvme_passthru_cmd *cmd,
3140 bool_Bool sv, __u8 act, struct nvme_voltage_measurement_start_data *data)
3141{
3142 nvme_init_set_features(cmd, NVME_FEAT_FID_VOLTAGE_MEASUREMENT, sv);
3143 cmd->cdw11 = NVME_FIELD_ENCODE(act,(((__u32)(act) & (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_MASK)
) << (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_SHIFT))
3144 NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_SHIFT,(((__u32)(act) & (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_MASK)
) << (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_SHIFT))
3145 NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_MASK)(((__u32)(act) & (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_MASK)
) << (NVME_FEAT_VOLTAGE_MEASUREMENT_ACT_SHIFT))
;
3146 if (act == NVME_VOLTAGE_MEASUREMENT_ACT_START && data) {
3147 cmd->data_len = sizeof(*data);
3148 cmd->addr = (__u64)(uintptr_t)data;
3149 }
3150}
3151
3152/**
3153 * nvme_init_set_features_emb_mgmt_ctrl_addr() - Initialize passthru command
3154 * for Embedded Management Controller Address
3155 * @cmd: Passthru command to use
3156 * @sv: Save value across power states
3157 * @data: 512 byte Embedded Management Controller Address (EMCA) data
3158 * buffer, see &struct nvme_mgmt_addr_desc
3159 *
3160 * Initializes the passthru command buffer for the Set Features command with
3161 * FID value %NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR
3162 */
3163static inline void
3164nvme_init_set_features_emb_mgmt_ctrl_addr(struct libnvme_passthru_cmd *cmd,
3165 bool_Bool sv, void *data)
3166{
3167 nvme_init_set_features(cmd, NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR, sv);
3168 cmd->data_len = sizeof(struct nvme_mgmt_addr_desc);
3169 cmd->addr = (__u64)(uintptr_t)data;
3170}
3171
3172/**
3173 * nvme_init_set_features_host_mgmt_agent_addr() - Initialize passthru
3174 * command for Host Management Agent Address
3175 * @cmd: Passthru command to use
3176 * @sv: Save value across power states
3177 * @data: 512 byte Host Management Agent Address (HMAA) data buffer,
3178 * see &struct nvme_mgmt_addr_desc
3179 *
3180 * Initializes the passthru command buffer for the Set Features command with
3181 * FID value %NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR
3182 */
3183static inline void
3184nvme_init_set_features_host_mgmt_agent_addr(struct libnvme_passthru_cmd *cmd,
3185 bool_Bool sv, void *data)
3186{
3187 nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR, sv);
3188 cmd->data_len = sizeof(struct nvme_mgmt_addr_desc);
3189 cmd->addr = (__u64)(uintptr_t)data;
3190}
3191
3192/**
3193 * nvme_init_set_features_enh_ctrl_metadata() - Initialize passthru command
3194 * for Enhanced Controller Metadata
3195 * @cmd: Passthru command to use
3196 * @sv: Save value across power states
3197 * @ea: Element Action (EA), see &enum nvme_host_metadata_ea
3198 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
3199 *
3200 * Initializes the passthru command buffer for the Set Features command with
3201 * FID value %NVME_FEAT_FID_ENH_CTRL_METADATA
3202 */
3203static inline void
3204nvme_init_set_features_enh_ctrl_metadata(struct libnvme_passthru_cmd *cmd,
3205 bool_Bool sv, __u8 ea, struct nvme_host_metadata *data)
3206{
3207 nvme_init_set_features(cmd, NVME_FEAT_FID_ENH_CTRL_METADATA, sv);
3208 cmd->cdw11 = NVME_FIELD_ENCODE(ea,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3209 NVME_HOST_METADATA_EA_SHIFT,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3210 NVME_HOST_METADATA_EA_MASK)(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
;
3211 cmd->data_len = sizeof(*data);
3212 cmd->addr = (__u64)(uintptr_t)data;
3213}
3214
3215/**
3216 * nvme_init_set_features_ctrl_metadata() - Initialize passthru command for
3217 * Controller Metadata
3218 * @cmd: Passthru command to use
3219 * @sv: Save value across power states
3220 * @ea: Element Action (EA), see &enum nvme_host_metadata_ea
3221 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
3222 *
3223 * Initializes the passthru command buffer for the Set Features command with
3224 * FID value %NVME_FEAT_FID_CTRL_METADATA
3225 */
3226static inline void
3227nvme_init_set_features_ctrl_metadata(struct libnvme_passthru_cmd *cmd,
3228 bool_Bool sv, __u8 ea, struct nvme_host_metadata *data)
3229{
3230 nvme_init_set_features(cmd, NVME_FEAT_FID_CTRL_METADATA, sv);
3231 cmd->cdw11 = NVME_FIELD_ENCODE(ea,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3232 NVME_HOST_METADATA_EA_SHIFT,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3233 NVME_HOST_METADATA_EA_MASK)(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
;
3234 cmd->data_len = sizeof(*data);
3235 cmd->addr = (__u64)(uintptr_t)data;
3236}
3237
3238/**
3239 * nvme_init_set_features_ns_metadata() - Initialize passthru command for
3240 * Namespace Metadata
3241 * @cmd: Passthru command to use
3242 * @sv: Save value across power states
3243 * @ea: Element Action (EA), see &enum nvme_host_metadata_ea
3244 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
3245 *
3246 * Initializes the passthru command buffer for the Set Features command with
3247 * FID value %NVME_FEAT_FID_NS_METADATA
3248 */
3249static inline void
3250nvme_init_set_features_ns_metadata(struct libnvme_passthru_cmd *cmd,
3251 bool_Bool sv, __u8 ea, struct nvme_host_metadata *data)
3252{
3253 nvme_init_set_features(cmd, NVME_FEAT_FID_NS_METADATA, sv);
3254 cmd->cdw11 = NVME_FIELD_ENCODE(ea,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3255 NVME_HOST_METADATA_EA_SHIFT,(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
3256 NVME_HOST_METADATA_EA_MASK)(((__u32)(ea) & (NVME_HOST_METADATA_EA_MASK)) << (NVME_HOST_METADATA_EA_SHIFT
))
;
3257 cmd->data_len = sizeof(*data);
3258 cmd->addr = (__u64)(uintptr_t)data;
3259}
3260
3261/**
3262 * nvme_init_set_features_bp_write_protect() - Initialize passthru command
3263 * for Boot Partition Write Protection Config
3264 * @cmd: Passthru command to use
3265 * @sv: Save value across power states
3266 * @bp0wps: Boot Partition 0 Write Protection State (BP0WPS)
3267 * @bp1wps: Boot Partition 1 Write Protection State (BP1WPS)
3268 *
3269 * Initializes the passthru command buffer for the Set Features command with
3270 * FID value %NVME_FEAT_FID_BP_WRITE_PROTECT
3271 */
3272static inline void
3273nvme_init_set_features_bp_write_protect(struct libnvme_passthru_cmd *cmd,
3274 bool_Bool sv, __u8 bp0wps, __u8 bp1wps)
3275{
3276 nvme_init_set_features(cmd, NVME_FEAT_FID_BP_WRITE_PROTECT, sv);
3277 cmd->cdw11 = NVME_FIELD_ENCODE(bp0wps,(((__u32)(bp0wps) & (NVME_FEAT_BPWPC_BP0WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP0WPS_SHIFT))
3278 NVME_FEAT_BPWPC_BP0WPS_SHIFT,(((__u32)(bp0wps) & (NVME_FEAT_BPWPC_BP0WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP0WPS_SHIFT))
3279 NVME_FEAT_BPWPC_BP0WPS_MASK)(((__u32)(bp0wps) & (NVME_FEAT_BPWPC_BP0WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP0WPS_SHIFT))
|
3280 NVME_FIELD_ENCODE(bp1wps,(((__u32)(bp1wps) & (NVME_FEAT_BPWPC_BP1WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP1WPS_SHIFT))
3281 NVME_FEAT_BPWPC_BP1WPS_SHIFT,(((__u32)(bp1wps) & (NVME_FEAT_BPWPC_BP1WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP1WPS_SHIFT))
3282 NVME_FEAT_BPWPC_BP1WPS_MASK)(((__u32)(bp1wps) & (NVME_FEAT_BPWPC_BP1WPS_MASK)) <<
(NVME_FEAT_BPWPC_BP1WPS_SHIFT))
;
3283}
3284
3285/**
3286 * nvme_init_get_features() - Initialize passthru command for
3287 * Get Features
3288 * @cmd: Passthru command to use
3289 * @fid: Feature identifier, see &enum nvme_features_id
3290 * @sel: Select which type of attribute to return,
3291 * see &enum nvme_get_features_sel
3292 */
3293static inline void
3294nvme_init_get_features(struct libnvme_passthru_cmd *cmd, __u8 fid,
3295 enum nvme_get_features_sel sel)
3296{
3297 __u32 cdw10 = NVME_FIELD_ENCODE(fid,(((__u32)(fid) & (NVME_GET_FEATURES_CDW10_FID_MASK)) <<
(NVME_GET_FEATURES_CDW10_FID_SHIFT))
3298 NVME_GET_FEATURES_CDW10_FID_SHIFT,(((__u32)(fid) & (NVME_GET_FEATURES_CDW10_FID_MASK)) <<
(NVME_GET_FEATURES_CDW10_FID_SHIFT))
3299 NVME_GET_FEATURES_CDW10_FID_MASK)(((__u32)(fid) & (NVME_GET_FEATURES_CDW10_FID_MASK)) <<
(NVME_GET_FEATURES_CDW10_FID_SHIFT))
|
3300 NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_GET_FEATURES_CDW10_SEL_MASK)) <<
(NVME_GET_FEATURES_CDW10_SEL_SHIFT))
3301 NVME_GET_FEATURES_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_GET_FEATURES_CDW10_SEL_MASK)) <<
(NVME_GET_FEATURES_CDW10_SEL_SHIFT))
3302 NVME_GET_FEATURES_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_GET_FEATURES_CDW10_SEL_MASK)) <<
(NVME_GET_FEATURES_CDW10_SEL_SHIFT))
;
3303
3304 memset(cmd, 0, sizeof(*cmd));
3305
3306 cmd->opcode = nvme_admin_get_features;
3307 cmd->cdw10 = cdw10;
3308}
3309
3310/**
3311 * nvme_init_get_features_arbitration() - Initialize passthru command for
3312 * Get Features - Arbitration
3313 * @cmd: Passthru command to use
3314 * @sel: Select which type of attribute to return,
3315 * see &enum nvme_get_features_sel
3316 *
3317 * Initializes the passthru command buffer for the Get Features command with
3318 * FID value %NVME_FEAT_FID_ARBITRATION
3319 */
3320static inline void
3321nvme_init_get_features_arbitration(struct libnvme_passthru_cmd *cmd,
3322 enum nvme_get_features_sel sel)
3323{
3324 nvme_init_get_features(cmd, NVME_FEAT_FID_ARBITRATION, sel);
3325}
3326
3327/**
3328 * nvme_init_get_features_power_mgmt() - Initialize passthru command for
3329 * Get Features - Power Management
3330 * @cmd: Passthru command to use
3331 * @sel: Select which type of attribute to return,
3332 * see &enum nvme_get_features_sel
3333 *
3334 * Initializes the passthru command buffer for the Get Features command with
3335 * FID value %NVME_FEAT_FID_POWER_MGMT
3336 */
3337static inline void
3338nvme_init_get_features_power_mgmt(struct libnvme_passthru_cmd *cmd,
3339 enum nvme_get_features_sel sel)
3340{
3341 nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_MGMT, sel);
3342}
3343
3344/**
3345 * nvme_init_get_features_lba_range() - Initialize passthru command for
3346 * Get Features - LBA Range
3347 * @cmd: Passthru command to use
3348 * @nsid: Namespace ID
3349 * @sel: Select which type of attribute to return,
3350 * see &enum nvme_get_features_sel
3351 * @lrt: Buffer to receive LBA Range Type data structure
3352 *
3353 * Initializes the passthru command buffer for the Get Features command with
3354 * FID value %NVME_FEAT_FID_LBA_RANGE
3355 */
3356static inline void
3357nvme_init_get_features_lba_range(struct libnvme_passthru_cmd *cmd, __u32 nsid,
3358 enum nvme_get_features_sel sel, struct nvme_lba_range_type *lrt)
3359{
3360 nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_RANGE, sel);
3361 cmd->nsid = nsid;
3362 cmd->data_len = sizeof(*lrt);
3363 cmd->addr = (__u64)(uintptr_t)lrt;
3364}
3365
3366/**
3367 * nvme_init_get_features_temp_thresh() - Initialize passthru command for
3368 * Get Features - Temperature Threshold
3369 * @cmd: Passthru command to use
3370 * @sel: Select which type of attribute to return,
3371 * see &enum nvme_get_features_sel
3372 * @tmpsel: Threshold Temperature Select
3373 * @thsel: Threshold Type Select
3374 *
3375 * Initializes the passthru command buffer for the Get Features command with
3376 * FID value %NVME_FEAT_FID_TEMP_THRESH
3377 */
3378static inline void
3379nvme_init_get_features_temp_thresh(struct libnvme_passthru_cmd *cmd,
3380 enum nvme_get_features_sel sel,
3381 __u8 tmpsel, enum nvme_feat_tmpthresh_thsel thsel)
3382{
3383
3384 nvme_init_get_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sel);
3385 cmd->cdw11 = NVME_FIELD_ENCODE(tmpsel,(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
3386 NVME_FEAT_TT_TMPSEL_SHIFT,(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
3387 NVME_FEAT_TT_TMPSEL_MASK)(((__u32)(tmpsel) & (NVME_FEAT_TT_TMPSEL_MASK)) << (
NVME_FEAT_TT_TMPSEL_SHIFT))
|
3388 NVME_FIELD_ENCODE(thsel,(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
3389 NVME_FEAT_TT_THSEL_SHIFT,(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
3390 NVME_FEAT_TT_THSEL_MASK)(((__u32)(thsel) & (NVME_FEAT_TT_THSEL_MASK)) << (NVME_FEAT_TT_THSEL_SHIFT
))
;
3391}
3392
3393/**
3394 * nvme_init_get_features_err_recovery() - Initialize passthru command for
3395 * Get Features - Error Recovery
3396 * @cmd: Passthru command to use
3397 * @nsid: Namespace ID
3398 * @sel: Select which type of attribute to return,
3399 * see &enum nvme_get_features_sel
3400 *
3401 * Initializes the passthru command buffer for the Get Features command with
3402 * FID value %NVME_FEAT_FID_ERR_RECOVERY
3403 */
3404static inline void
3405nvme_init_get_features_err_recovery(struct libnvme_passthru_cmd *cmd,
3406 __u32 nsid, enum nvme_get_features_sel sel)
3407{
3408 nvme_init_get_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sel);
3409 cmd->nsid = nsid;
3410}
3411
3412/**
3413 * nvme_init_get_features_volatile_wc() - Initialize passthru command for
3414 * Get Features - Volatile Write Cache
3415 * @cmd: Passthru command to use
3416 * @sel: Select which type of attribute to return,
3417 * see &enum nvme_get_features_sel
3418 *
3419 * Initializes the passthru command buffer for the Get Features command with
3420 * FID value %NVME_FEAT_FID_VOLATILE_WC
3421 */
3422static inline void
3423nvme_init_get_features_volatile_wc(struct libnvme_passthru_cmd *cmd,
3424 enum nvme_get_features_sel sel)
3425{
3426 nvme_init_get_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sel);
3427}
3428
3429/**
3430 * nvme_init_get_features_num_queues() - Initialize passthru command for
3431 * Get Features - Number of Queues
3432 * @cmd: Passthru command to use
3433 * @sel: Select which type of attribute to return,
3434 * see &enum nvme_get_features_sel
3435 *
3436 * Initializes the passthru command buffer for the Get Features command with
3437 * FID value %NVME_FEAT_FID_NUM_QUEUES
3438 */
3439static inline void
3440nvme_init_get_features_num_queues(struct libnvme_passthru_cmd *cmd,
3441 enum nvme_get_features_sel sel)
3442{
3443 nvme_init_get_features(cmd, NVME_FEAT_FID_NUM_QUEUES, sel);
3444}
3445
3446/**
3447 * nvme_init_get_features_irq_coalesce() - Initialize passthru command for
3448 * Get Features - IRQ Coalesce
3449 * @cmd: Passthru command to use
3450 * @sel: Select which type of attribute to return,
3451 * see &enum nvme_get_features_sel
3452 *
3453 * Initializes the passthru command buffer for the Get Features command with
3454 * FID value %NVME_FEAT_FID_IRQ_COALESCE
3455 */
3456static inline void
3457nvme_init_get_features_irq_coalesce(struct libnvme_passthru_cmd *cmd,
3458 enum nvme_get_features_sel sel)
3459{
3460 nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sel);
3461}
3462
3463/**
3464 * nvme_init_get_features_irq_config() - Initialize passthru command for
3465 * Get Features - IRQ Config
3466 * @cmd: Passthru command to use
3467 * @sel: Select which type of attribute to return,
3468 * see &enum nvme_get_features_sel
3469 * @iv: Interrupt Vector
3470 * @cd: Coalescing Disable
3471 *
3472 * Initializes the passthru command buffer for the Get Features command with
3473 * FID value %NVME_FEAT_FID_IRQ_CONFIG
3474 */
3475static inline void
3476nvme_init_get_features_irq_config(struct libnvme_passthru_cmd *cmd,
3477 enum nvme_get_features_sel sel, __u16 iv, bool_Bool cd)
3478{
3479 __u32 cdw11 = NVME_FIELD_ENCODE(iv,(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
3480 NVME_FEAT_ICFG_IV_SHIFT,(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
3481 NVME_FEAT_ICFG_IV_MASK)(((__u32)(iv) & (NVME_FEAT_ICFG_IV_MASK)) << (NVME_FEAT_ICFG_IV_SHIFT
))
|
3482 NVME_FIELD_ENCODE(cd,(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
3483 NVME_FEAT_ICFG_CD_SHIFT,(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
3484 NVME_FEAT_ICFG_CD_MASK)(((__u32)(cd) & (NVME_FEAT_ICFG_CD_MASK)) << (NVME_FEAT_ICFG_CD_SHIFT
))
;
3485
3486 nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sel);
3487 cmd->cdw11 = cdw11;
3488}
3489
3490/**
3491 * nvme_init_get_features_write_atomic() - Initialize passthru command for
3492 * Get Features - Write Atomic
3493 * @cmd: Passthru command to use
3494 * @sel: Select which type of attribute to return,
3495 * see &enum nvme_get_features_sel
3496 *
3497 * Initializes the passthru command buffer for the Get Features command with
3498 * FID value %NVME_FEAT_FID_WRITE_ATOMIC
3499 */
3500static inline void
3501nvme_init_get_features_write_atomic(struct libnvme_passthru_cmd *cmd,
3502 enum nvme_get_features_sel sel)
3503{
3504 nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sel);
3505}
3506
3507/**
3508 * nvme_init_get_features_async_event() - Initialize passthru command for
3509 * Get Features - Asynchronous Event Configuration
3510 * @cmd: Passthru command to use
3511 * @sel: Select which type of attribute to return,
3512 * see &enum nvme_get_features_sel
3513 *
3514 * Initializes the passthru command buffer for the Get Features command with
3515 * FID value %NVME_FEAT_FID_ASYNC_EVENT
3516 */
3517static inline void
3518nvme_init_get_features_async_event(struct libnvme_passthru_cmd *cmd,
3519 enum nvme_get_features_sel sel)
3520{
3521 nvme_init_get_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sel);
3522}
3523
3524/**
3525 * nvme_init_get_features_auto_pst() - Initialize passthru command for
3526 * Get Features - Autonomous Power State Transition
3527 * @cmd: Passthru command to use
3528 * @sel: Select which type of attribute to return,
3529 * see &enum nvme_get_features_sel
3530 * @apst: Autonomous Power State Transition data buffer
3531 *
3532 * Initializes the passthru command buffer for the Get Features command with
3533 * FID value %NVME_FEAT_FID_AUTO_PST
3534 */
3535static inline void
3536nvme_init_get_features_auto_pst(struct libnvme_passthru_cmd *cmd,
3537 enum nvme_get_features_sel sel, struct nvme_feat_auto_pst *apst)
3538{
3539 nvme_init_get_features(cmd, NVME_FEAT_FID_AUTO_PST, sel);
3540 cmd->data_len = sizeof(*apst);
3541 cmd->addr = (__u64)(uintptr_t)apst;
3542}
3543
3544/**
3545 * nvme_init_get_features_host_mem_buf() - Initialize passthru command for
3546 * Get Features - Host Memory Buffer
3547 * @cmd: Passthru command to use
3548 * @sel: Select which type of attribute to return,
3549 * see &enum nvme_get_features_sel
3550 * @attrs: Buffer for returned Host Memory Buffer Attributes
3551 *
3552 * Initializes the passthru command buffer for the Get Features command with
3553 * FID value %NVME_FEAT_FID_HOST_MEM_BUF
3554 */
3555static inline void
3556nvme_init_get_features_host_mem_buf(struct libnvme_passthru_cmd *cmd,
3557 enum nvme_get_features_sel sel,
3558 struct nvme_host_mem_buf_attrs *attrs)
3559{
3560 nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_MEM_BUF, sel);
3561 cmd->data_len = sizeof(*attrs);
3562 cmd->addr = (__u64)(uintptr_t)attrs;
3563}
3564
3565/**
3566 * nvme_init_get_features_timestamp() - Initialize passthru command for
3567 * Get Features - Timestamp
3568 * @cmd: Passthru command to use
3569 * @sel: Select which type of attribute to return,
3570 * see &enum nvme_get_features_sel
3571 * @ts: Current timestamp buffer
3572 *
3573 * Initializes the passthru command buffer for the Get Features command with
3574 * FID value %NVME_FEAT_FID_TIMESTAMP
3575 */
3576static inline void
3577nvme_init_get_features_timestamp(struct libnvme_passthru_cmd *cmd,
3578 enum nvme_get_features_sel sel, struct nvme_timestamp *ts)
3579{
3580 nvme_init_get_features(cmd, NVME_FEAT_FID_TIMESTAMP, sel);
3581 cmd->data_len = sizeof(*ts);
3582 cmd->addr = (__u64)(uintptr_t)ts;
3583}
3584
3585/**
3586 * nvme_init_get_features_kato() - Initialize passthru command for
3587 * Get Features - Keep Alive Timeout
3588 * @cmd: Passthru command to use
3589 * @sel: Select which type of attribute to return,
3590 * see &enum nvme_get_features_sel
3591 *
3592 * Initializes the passthru command buffer for the Get Features command with
3593 * FID value %NVME_FEAT_FID_KATO
3594 */
3595static inline void
3596nvme_init_get_features_kato(struct libnvme_passthru_cmd *cmd,
3597 enum nvme_get_features_sel sel)
3598{
3599 nvme_init_get_features(cmd, NVME_FEAT_FID_KATO, sel);
3600}
3601
3602/**
3603 * nvme_init_get_features_hctm() - Initialize passthru command for
3604 * Get Features - Host Controlled Thermal Management
3605 * @cmd: Passthru command to use
3606 * @sel: Select which type of attribute to return,
3607 * see &enum nvme_get_features_sel
3608 *
3609 * Initializes the passthru command buffer for the Get Features command with
3610 * FID value %NVME_FEAT_FID_HCTM
3611 */
3612static inline void
3613nvme_init_get_features_hctm(struct libnvme_passthru_cmd *cmd,
3614 enum nvme_get_features_sel sel)
3615{
3616 nvme_init_get_features(cmd, NVME_FEAT_FID_HCTM, sel);
3617}
3618
3619/**
3620 * nvme_init_get_features_nopsc() - Initialize passthru command for
3621 * Get Features - Non-Operational Power State Config
3622 * @cmd: Passthru command to use
3623 * @sel: Select which type of attribute to return,
3624 * see &enum nvme_get_features_sel
3625 *
3626 * Initializes the passthru command buffer for the Get Features command with
3627 * FID value %NVME_FEAT_FID_NOPSC
3628 */
3629static inline void
3630nvme_init_get_features_nopsc(struct libnvme_passthru_cmd *cmd,
3631 enum nvme_get_features_sel sel)
3632{
3633 nvme_init_get_features(cmd, NVME_FEAT_FID_NOPSC, sel);
3634}
3635
3636/**
3637 * nvme_init_get_features_rrl() - Initialize passthru command for
3638 * Get Features - Read Recovery Level
3639 * @cmd: Passthru command to use
3640 * @sel: Select which type of attribute to return,
3641 * see &enum nvme_get_features_sel
3642 *
3643 * Initializes the passthru command buffer for the Get Features command with
3644 * FID value %NVME_FEAT_FID_RRL
3645 */
3646static inline void
3647nvme_init_get_features_rrl(struct libnvme_passthru_cmd *cmd,
3648 enum nvme_get_features_sel sel)
3649{
3650 nvme_init_get_features(cmd, NVME_FEAT_FID_RRL, sel);
3651}
3652
3653/**
3654 * nvme_init_get_features_plm_config() - Initialize passthru command for
3655 * Get Features - Predictable Latency Mode Config
3656 * @cmd: Passthru command to use
3657 * @sel: Select which type of attribute to return,
3658 * see &enum nvme_get_features_sel
3659 * @nvmsetid: NVM set id
3660 * @plmc: Buffer for returned Predictable Latency Mode Config
3661 *
3662 * Initializes the passthru command buffer for the Get Features command with
3663 * FID value %NVME_FEAT_FID_PLM_CONFIG
3664 */
3665static inline void
3666nvme_init_get_features_plm_config(struct libnvme_passthru_cmd *cmd,
3667 enum nvme_get_features_sel sel, __u16 nvmsetid,
3668 struct nvme_plm_config *plmc)
3669{
3670 nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sel);
3671 cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
3672 NVME_FEAT_PLM_NVMSETID_SHIFT,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
3673 NVME_FEAT_PLM_NVMSETID_MASK)(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
;
3674 cmd->data_len = sizeof(*plmc);
3675 cmd->addr = (__u64)(uintptr_t)plmc;
3676}
3677
3678/**
3679 * nvme_init_get_features_plm_window() - Initialize passthru command for
3680 * Get Features - Predictable Latency Mode Window
3681 * @cmd: Passthru command to use
3682 * @sel: Select which type of attribute to return,
3683 * see &enum nvme_get_features_sel
3684 * @nvmsetid: NVM set id
3685 *
3686 * Initializes the passthru command buffer for the Get Features command with
3687 * FID value %NVME_FEAT_FID_PLM_WINDOW
3688 */
3689static inline void
3690nvme_init_get_features_plm_window(struct libnvme_passthru_cmd *cmd,
3691 enum nvme_get_features_sel sel, __u16 nvmsetid)
3692{
3693 nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sel);
3694 cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
3695 NVME_FEAT_PLM_NVMSETID_SHIFT,(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
3696 NVME_FEAT_PLM_NVMSETID_MASK)(((__u32)(nvmsetid) & (NVME_FEAT_PLM_NVMSETID_MASK)) <<
(NVME_FEAT_PLM_NVMSETID_SHIFT))
;
3697}
3698
3699/**
3700 * nvme_init_get_features_lba_sts_interval() - Initialize passthru command for
3701 * Get Features - LBA Status Information Interval
3702 * @cmd: Passthru command to use
3703 * @sel: Select which type of attribute to return,
3704 * see &enum nvme_get_features_sel
3705 *
3706 * Initializes the passthru command buffer for the Get Features command with
3707 * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL
3708 */
3709static inline void
3710nvme_init_get_features_lba_sts_interval(struct libnvme_passthru_cmd *cmd,
3711 enum nvme_get_features_sel sel)
3712{
3713 nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sel);
3714}
3715
3716/**
3717 * nvme_init_get_features_host_behavior() - Initialize passthru command for
3718 * Get Features - Host Behavior
3719 * @cmd: Passthru command to use
3720 * @sel: Select which type of attribute to return,
3721 * see &enum nvme_get_features_sel
3722 * @fhb: Pointer to structure nvme_feat_host_behavior
3723 *
3724 * Initializes the passthru command buffer for the Get Features command with
3725 * FID value %NVME_FEAT_FID_HOST_BEHAVIOR
3726 */
3727static inline void
3728nvme_init_get_features_host_behavior(struct libnvme_passthru_cmd *cmd,
3729 enum nvme_get_features_sel sel,
3730 struct nvme_feat_host_behavior *fhb)
3731{
3732 nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sel);
3733 cmd->data_len = sizeof(*fhb);
3734 cmd->addr = (__u64)(uintptr_t)fhb;
3735}
3736
3737/**
3738 * nvme_init_get_features_sanitize() - Initialize passthru command for
3739 * Get Features - Sanitize
3740 * @cmd: Passthru command to use
3741 * @sel: Select which type of attribute to return,
3742 * see &enum nvme_get_features_sel
3743 *
3744 * Initializes the passthru command buffer for the Get Features command with
3745 * FID value %NVME_FEAT_FID_SANITIZE
3746 */
3747static inline void
3748nvme_init_get_features_sanitize(struct libnvme_passthru_cmd *cmd,
3749 enum nvme_get_features_sel sel)
3750{
3751 nvme_init_get_features(cmd, NVME_FEAT_FID_SANITIZE, sel);
3752}
3753
3754/**
3755 * nvme_init_get_features_endurance_event_cfg() - Initialize passthru command
3756 * for Get Features - Endurance Group Event Configuration
3757 * @cmd: Passthru command to use
3758 * @sel: Select which type of attribute to return,
3759 * see &enum nvme_get_features_sel
3760 * @endgid: Endurance Group Identifier
3761 *
3762 * Initializes the passthru command buffer for the Get Features command with
3763 * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG
3764 */
3765static inline void
3766nvme_init_get_features_endurance_event_cfg(struct libnvme_passthru_cmd *cmd,
3767 enum nvme_get_features_sel sel, __u16 endgid)
3768{
3769 nvme_init_get_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sel);
3770 cmd->cdw11 = NVME_FIELD_ENCODE(endgid,(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
3771 NVME_FEAT_EG_ENDGID_SHIFT,(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
3772 NVME_FEAT_EG_ENDGID_MASK)(((__u32)(endgid) & (NVME_FEAT_EG_ENDGID_MASK)) << (
NVME_FEAT_EG_ENDGID_SHIFT))
;
3773}
3774
3775/**
3776 * nvme_init_get_features_sw_progress() - Initialize passthru command for
3777 * Get Features - Software Progress
3778 * @cmd: Passthru command to use
3779 * @sel: Select which type of attribute to return,
3780 * see &enum nvme_get_features_sel
3781 *
3782 * Initializes the passthru command buffer for the Get Features command with
3783 * FID value %NVME_FEAT_FID_SW_PROGRESS
3784 */
3785static inline void
3786nvme_init_get_features_sw_progress(struct libnvme_passthru_cmd *cmd,
3787 enum nvme_get_features_sel sel)
3788{
3789 nvme_init_get_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sel);
3790}
3791
3792/**
3793 * nvme_init_get_features_host_id() - Initialize passthru command for
3794 * Get Features - Host Identifier
3795 * @cmd: Passthru command to use
3796 * @sel: Select which type of attribute to return,
3797 * see &enum nvme_get_features_sel
3798 * @exhid: Enable Extended Host Identifier
3799 * @hostid: Buffer for returned host ID
3800 * @len: Length of @hostid
3801 *
3802 * Initializes the passthru command buffer for the Get Features command with
3803 * FID value %NVME_FEAT_FID_HOST_ID
3804 */
3805static inline void
3806nvme_init_get_features_host_id(struct libnvme_passthru_cmd *cmd,
3807 enum nvme_get_features_sel sel, bool_Bool exhid,
3808 void *hostid, __u32 len)
3809{
3810 nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_ID, sel);
3811 cmd->cdw11 = NVME_FIELD_ENCODE(exhid,(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
3812 NVME_FEAT_HOSTID_EXHID_SHIFT,(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
3813 NVME_FEAT_HOSTID_EXHID_MASK)(((__u32)(exhid) & (NVME_FEAT_HOSTID_EXHID_MASK)) <<
(NVME_FEAT_HOSTID_EXHID_SHIFT))
;
3814 cmd->data_len = len;
3815 cmd->addr = (__u64)(uintptr_t)hostid;
3816}
3817
3818/**
3819 * nvme_init_get_features_resv_nf_mask() - Initialize passthru command for
3820 * Get Features - Reservation Notification Mask
3821 * @cmd: Passthru command to use
3822 * @nsid: Namespace ID
3823 * @sel: Select which type of attribute to return,
3824 * see &enum nvme_get_features_sel
3825 *
3826 * Initializes the passthru command buffer for the Get Features command with
3827 * FID value %NVME_FEAT_FID_RESV_NF_MASK
3828 */
3829static inline void
3830nvme_init_get_features_resv_nf_mask(struct libnvme_passthru_cmd *cmd, __u32 nsid,
3831 enum nvme_get_features_sel sel)
3832{
3833 nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_NF_MASK, sel);
3834 cmd->nsid = nsid;
3835}
3836
3837/**
3838 * nvme_init_get_features_resv_persist() - Initialize passthru command for
3839 * Get Features - Reservation Persistence
3840 * @cmd: Passthru command to use
3841 * @nsid: Namespace ID
3842 * @sel: Select which type of attribute to return,
3843 * see &enum nvme_get_features_sel
3844 *
3845 * Initializes the passthru command buffer for the Get Features command with
3846 * FID value %NVME_FEAT_FID_RESV_PERSIST
3847 */
3848static inline void
3849nvme_init_get_features_resv_persist(struct libnvme_passthru_cmd *cmd,
3850 __u32 nsid, enum nvme_get_features_sel sel)
3851{
3852 nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sel);
3853 cmd->nsid = nsid;
3854}
3855
3856/**
3857 * nvme_init_get_features_write_protect() - Initialize passthru command for
3858 * Get Features - Write Protect
3859 * @cmd: Passthru command to use
3860 * @nsid: Namespace ID
3861 * @sel: Select which type of attribute to return,
3862 * see &enum nvme_get_features_sel
3863 *
3864 * Initializes the passthru command buffer for the Get Features command with
3865 * FID value %NVME_FEAT_FID_WRITE_PROTECT
3866 */
3867static inline void
3868nvme_init_get_features_write_protect(struct libnvme_passthru_cmd *cmd,
3869 __u32 nsid, enum nvme_get_features_sel sel)
3870{
3871 nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sel);
3872 cmd->nsid = nsid;
3873}
3874
3875/**
3876 * nvme_init_get_features_iocs_profile() - Initialize passthru command for
3877 * Get Features - I/O Command Set Profile
3878 * @cmd: Passthru command to use
3879 * @sel: Select which type of attribute to return,
3880 * see &enum nvme_get_features_sel
3881 *
3882 * Initializes the passthru command buffer for the Get Features command with
3883 * FID value %NVME_FEAT_FID_IOCS_PROFILE
3884 */
3885static inline void
3886nvme_init_get_features_iocs_profile(struct libnvme_passthru_cmd *cmd,
3887 enum nvme_get_features_sel sel)
3888{
3889 nvme_init_get_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sel);
3890}
3891
3892/**
3893 * nvme_init_lm_get_features_ctrl_data_queue() - Initialize passthru command for
3894 * Get Controller Data Queue feature
3895 * @cmd: Passthru command to use
3896 * @sel: Select which type of attribute to return,
3897 * see &enum nvme_get_features_sel
3898 * @cdqid: Controller Data Queue ID (CDQID)
3899 * @qfd: Get Controller Data Queue feature data buffer
3900 *
3901 * Initializes the passthru command buffer for the Get Features command with
3902 * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE.
3903 */
3904static inline void
3905nvme_init_lm_get_features_ctrl_data_queue(struct libnvme_passthru_cmd *cmd,
3906 enum nvme_get_features_sel sel, __u16 cdqid,
3907 struct nvme_lm_ctrl_data_queue_fid_data *qfd)
3908{
3909 nvme_init_get_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, sel);
3910 cmd->data_len = sizeof(*qfd);
3911 cmd->addr = (__u64)(uintptr_t)qfd;
3912 cmd->cdw11 = cdqid;
3913}
3914
3915/**
3916 * nvme_init_get_features_rate_limiting() - Initialize passthru command for
3917 * Get Features - Rate Limiting
3918 * @cmd: Passthru command to use
3919 * @sel: Select which type of attribute to return,
3920 * see &enum nvme_get_features_sel
3921 * @target: Target of the rate limits setting, see
3922 * &enum nvme_rate_limiting_target
3923 * @tid: Target Identifier for the target specified by @target
3924 * @data: Buffer to receive the Rate Limiting data buffer, see
3925 * &struct nvme_rate_limiting_data
3926 *
3927 * Initializes the passthru command buffer for the Get Features command with
3928 * FID value %NVME_FEAT_FID_RATE_LIMITING
3929 */
3930static inline void
3931nvme_init_get_features_rate_limiting(struct libnvme_passthru_cmd *cmd,
3932 enum nvme_get_features_sel sel, __u8 target, __u16 tid,
3933 struct nvme_rate_limiting_data *data)
3934{
3935 nvme_init_get_features(cmd, NVME_FEAT_FID_RATE_LIMITING, sel);
3936 cmd->cdw11 = NVME_FIELD_ENCODE(target,(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
3937 NVME_FEAT_RATE_LIMITING_TGT_SHIFT,(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
3938 NVME_FEAT_RATE_LIMITING_TGT_MASK)(((__u32)(target) & (NVME_FEAT_RATE_LIMITING_TGT_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TGT_SHIFT))
|
3939 NVME_FIELD_ENCODE(tid,(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
3940 NVME_FEAT_RATE_LIMITING_TID_SHIFT,(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
3941 NVME_FEAT_RATE_LIMITING_TID_MASK)(((__u32)(tid) & (NVME_FEAT_RATE_LIMITING_TID_MASK)) <<
(NVME_FEAT_RATE_LIMITING_TID_SHIFT))
;
3942 cmd->data_len = sizeof(*data);
3943 cmd->addr = (__u64)(uintptr_t)data;
3944}
3945
3946/**
3947 * nvme_init_get_features_spinup_control() - Initialize passthru command for
3948 * Get Features - Spinup Control
3949 * @cmd: Passthru command to use
3950 * @sel: Select which type of attribute to return,
3951 * see &enum nvme_get_features_sel
3952 *
3953 * Initializes the passthru command buffer for the Get Features command with
3954 * FID value %NVME_FEAT_FID_SPINUP_CONTROL
3955 */
3956static inline void
3957nvme_init_get_features_spinup_control(struct libnvme_passthru_cmd *cmd,
3958 enum nvme_get_features_sel sel)
3959{
3960 nvme_init_get_features(cmd, NVME_FEAT_FID_SPINUP_CONTROL, sel);
3961}
3962
3963/**
3964 * nvme_init_get_features_power_loss_signal() - Initialize passthru command
3965 * for Get Features - Power Loss Signaling Config
3966 * @cmd: Passthru command to use
3967 * @sel: Select which type of attribute to return,
3968 * see &enum nvme_get_features_sel
3969 *
3970 * Initializes the passthru command buffer for the Get Features command with
3971 * FID value %NVME_FEAT_FID_POWER_LOSS_SIGNAL
3972 */
3973static inline void
3974nvme_init_get_features_power_loss_signal(struct libnvme_passthru_cmd *cmd,
3975 enum nvme_get_features_sel sel)
3976{
3977 nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_LOSS_SIGNAL, sel);
3978}
3979
3980/**
3981 * nvme_init_get_features_perf_characteristics() - Initialize passthru
3982 * command for Get Features - Performance Characteristics
3983 * @cmd: Passthru command to use
3984 * @sel: Select which type of attribute to return,
3985 * see &enum nvme_get_features_sel
3986 * @attri: Attribute Index (ATTRI)
3987 * @data: Buffer for returned struct nvme_perf_characteristics
3988 *
3989 * Initializes the passthru command buffer for the Get Features command with
3990 * FID value %NVME_FEAT_FID_PERF_CHARACTERISTICS
3991 */
3992static inline void
3993nvme_init_get_features_perf_characteristics(struct libnvme_passthru_cmd *cmd,
3994 enum nvme_get_features_sel sel, __u8 attri,
3995 struct nvme_perf_characteristics *data)
3996{
3997 nvme_init_get_features(cmd, NVME_FEAT_FID_PERF_CHARACTERISTICS, sel);
3998 cmd->cdw11 = NVME_FIELD_ENCODE(attri,(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
3999 NVME_FEAT_PERFC_ATTRI_SHIFT,(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
4000 NVME_FEAT_PERFC_ATTRI_MASK)(((__u32)(attri) & (NVME_FEAT_PERFC_ATTRI_MASK)) <<
(NVME_FEAT_PERFC_ATTRI_SHIFT))
;
4001 cmd->data_len = sizeof(*data);
4002 cmd->addr = (__u64)(uintptr_t)data;
4003}
4004
4005/**
4006 * nvme_init_get_features_fdp() - Initialize passthru command for
4007 * Get Features - Flexible Data Placement
4008 * @cmd: Passthru command to use
4009 * @sel: Select which type of attribute to return,
4010 * see &enum nvme_get_features_sel
4011 * @endgid: Endurance Group Identifier (ENDGID)
4012 *
4013 * Initializes the passthru command buffer for the Get Features command with
4014 * FID value %NVME_FEAT_FID_FDP
4015 */
4016static inline void
4017nvme_init_get_features_fdp(struct libnvme_passthru_cmd *cmd,
4018 enum nvme_get_features_sel sel, __u16 endgid)
4019{
4020 nvme_init_get_features(cmd, NVME_FEAT_FID_FDP, sel);
4021 cmd->cdw11 = endgid;
4022}
4023
4024/**
4025 * nvme_init_get_features_fdp_events() - Initialize passthru command for
4026 * Get Features - Flexible Data Placement Events
4027 * @cmd: Passthru command to use
4028 * @sel: Select which type of attribute to return,
4029 * see &enum nvme_get_features_sel
4030 * @phndl: Placement Handle (PHNDL)
4031 * @data: Supported FDP Event Type List data buffer, see &struct
4032 * nvme_fdp_supported_event_desc
4033 * @len: Length of @data
4034 *
4035 * Initializes the passthru command buffer for the Get Features command with
4036 * FID value %NVME_FEAT_FID_FDP_EVENTS
4037 */
4038static inline void
4039nvme_init_get_features_fdp_events(struct libnvme_passthru_cmd *cmd,
4040 enum nvme_get_features_sel sel, __u16 phndl,
4041 void *data, __u32 len)
4042{
4043 nvme_init_get_features(cmd, NVME_FEAT_FID_FDP_EVENTS, sel);
4044 cmd->cdw11 = NVME_FIELD_ENCODE(phndl,(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
4045 NVME_FEAT_FDPE_PHNDL_SHIFT,(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
4046 NVME_FEAT_FDPE_PHNDL_MASK)(((__u32)(phndl) & (NVME_FEAT_FDPE_PHNDL_MASK)) << (
NVME_FEAT_FDPE_PHNDL_SHIFT))
;
4047 cmd->data_len = len;
4048 cmd->addr = (__u64)(uintptr_t)data;
4049}
4050
4051/**
4052 * nvme_init_get_features_ns_admin_label() - Initialize passthru command for
4053 * Get Features - Namespace Admin Label
4054 * @cmd: Passthru command to use
4055 * @sel: Select which type of attribute to return,
4056 * see &enum nvme_get_features_sel
4057 * @label: 256 byte, null-terminated UTF-8 Namespace Admin Label (NSAL)
4058 * data buffer
4059 *
4060 * Initializes the passthru command buffer for the Get Features command with
4061 * FID value %NVME_FEAT_FID_NS_ADMIN_LABEL
4062 */
4063static inline void
4064nvme_init_get_features_ns_admin_label(struct libnvme_passthru_cmd *cmd,
4065 enum nvme_get_features_sel sel, void *label)
4066{
4067 nvme_init_get_features(cmd, NVME_FEAT_FID_NS_ADMIN_LABEL, sel);
4068 cmd->data_len = 256;
4069 cmd->addr = (__u64)(uintptr_t)label;
4070}
4071
4072/**
4073 * nvme_init_get_features_personality() - Initialize passthru command for
4074 * Get Features - Configurable Device Personality
4075 * @cmd: Passthru command to use
4076 * @sel: Select which type of attribute to return,
4077 * see &enum nvme_get_features_sel
4078 * @perid: Personality Identifier (PERID), see &enum
4079 * nvme_personality_identifier
4080 * @data: Personality Identifier specific data buffer, or NULL if the
4081 * personality does not use the data buffer
4082 * @len: Length of @data
4083 *
4084 * Initializes the passthru command buffer for the Get Features command with
4085 * FID value %NVME_FEAT_FID_CONF_DEV_PERSONALITY
4086 */
4087static inline void
4088nvme_init_get_features_personality(struct libnvme_passthru_cmd *cmd,
4089 enum nvme_get_features_sel sel, __u8 perid,
4090 void *data, __u32 len)
4091{
4092 nvme_init_get_features(cmd, NVME_FEAT_FID_CONF_DEV_PERSONALITY, sel);
4093 cmd->cdw13 = NVME_FIELD_ENCODE(perid,(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
4094 NVME_FEAT_CDP_PERID_SHIFT,(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
4095 NVME_FEAT_CDP_PERID_MASK)(((__u32)(perid) & (NVME_FEAT_CDP_PERID_MASK)) << (
NVME_FEAT_CDP_PERID_SHIFT))
;
4096 cmd->data_len = len;
4097 cmd->addr = (__u64)(uintptr_t)data;
4098}
4099
4100/**
4101 * nvme_init_get_features_power_limit() - Initialize passthru command for
4102 * Get Features - Power Limit
4103 * @cmd: Passthru command to use
4104 * @sel: Select which type of attribute to return,
4105 * see &enum nvme_get_features_sel
4106 *
4107 * Initializes the passthru command buffer for the Get Features command with
4108 * FID value %NVME_FEAT_FID_POWER_LIMIT
4109 */
4110static inline void
4111nvme_init_get_features_power_limit(struct libnvme_passthru_cmd *cmd,
4112 enum nvme_get_features_sel sel)
4113{
4114 nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_LIMIT, sel);
4115}
4116
4117/**
4118 * nvme_init_get_features_power_threshold() - Initialize passthru command for
4119 * Get Features - Power Threshold
4120 * @cmd: Passthru command to use
4121 * @sel: Select which type of attribute to return,
4122 * see &enum nvme_get_features_sel
4123 *
4124 * Initializes the passthru command buffer for the Get Features command with
4125 * FID value %NVME_FEAT_FID_POWER_THRESH
4126 */
4127static inline void
4128nvme_init_get_features_power_threshold(struct libnvme_passthru_cmd *cmd,
4129 enum nvme_get_features_sel sel)
4130{
4131 nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_THRESH, sel);
4132}
4133
4134/**
4135 * nvme_init_get_features_power_measurement() - Initialize passthru command
4136 * for Get Features - Power Measurement
4137 * @cmd: Passthru command to use
4138 * @sel: Select which type of attribute to return,
4139 * see &enum nvme_get_features_sel
4140 *
4141 * Initializes the passthru command buffer for the Get Features command with
4142 * FID value %NVME_FEAT_FID_POWER_MEASUREMENT
4143 */
4144static inline void
4145nvme_init_get_features_power_measurement(struct libnvme_passthru_cmd *cmd,
4146 enum nvme_get_features_sel sel)
4147{
4148 nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_MEASUREMENT, sel);
4149}
4150
4151/**
4152 * nvme_init_get_features_voltage_threshold() - Initialize passthru command
4153 * for Get Features - Voltage Threshold
4154 * @cmd: Passthru command to use
4155 * @sel: Select which type of attribute to return,
4156 * see &enum nvme_get_features_sel
4157 * @vsens: Voltage Sensor Select (VSENS)
4158 *
4159 * Initializes the passthru command buffer for the Get Features command with
4160 * FID value %NVME_FEAT_FID_VOLTAGE_THRESHOLD
4161 */
4162static inline void
4163nvme_init_get_features_voltage_threshold(struct libnvme_passthru_cmd *cmd,
4164 enum nvme_get_features_sel sel, __u8 vsens)
4165{
4166 nvme_init_get_features(cmd, NVME_FEAT_FID_VOLTAGE_THRESHOLD, sel);
4167 cmd->cdw11 = NVME_FIELD_ENCODE(vsens,(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
4168 NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT,(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
4169 NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK)(((__u32)(vsens) & (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_MASK
)) << (NVME_FEAT_VOLTAGE_THRESHOLD_VSENS_SHIFT))
;
4170}
4171
4172/**
4173 * nvme_init_get_features_voltage_measurement() - Initialize passthru command
4174 * for Get Features - Voltage Measurement
4175 * @cmd: Passthru command to use
4176 * @sel: Select which type of attribute to return,
4177 * see &enum nvme_get_features_sel
4178 * @data: Start Voltage Measurements data buffer, see &struct
4179 * nvme_voltage_measurement_start_data
4180 * @len: Length of @data
4181 *
4182 * Initializes the passthru command buffer for the Get Features command with
4183 * FID value %NVME_FEAT_FID_VOLTAGE_MEASUREMENT
4184 */
4185static inline void
4186nvme_init_get_features_voltage_measurement(struct libnvme_passthru_cmd *cmd,
4187 enum nvme_get_features_sel sel, void *data, __u32 len)
4188{
4189 nvme_init_get_features(cmd, NVME_FEAT_FID_VOLTAGE_MEASUREMENT, sel);
4190 cmd->data_len = len;
4191 cmd->addr = (__u64)(uintptr_t)data;
4192}
4193
4194/**
4195 * nvme_init_get_features_emb_mgmt_ctrl_addr() - Initialize passthru command
4196 * for Get Features - Embedded Management Controller Address
4197 * @cmd: Passthru command to use
4198 * @sel: Select which type of attribute to return,
4199 * see &enum nvme_get_features_sel
4200 * @data: 512 byte Embedded Management Controller Address (EMCA) data
4201 * buffer, see &struct nvme_mgmt_addr_desc
4202 *
4203 * Initializes the passthru command buffer for the Get Features command with
4204 * FID value %NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR
4205 */
4206static inline void
4207nvme_init_get_features_emb_mgmt_ctrl_addr(struct libnvme_passthru_cmd *cmd,
4208 enum nvme_get_features_sel sel, void *data)
4209{
4210 nvme_init_get_features(cmd, NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR, sel);
4211 cmd->data_len = sizeof(struct nvme_mgmt_addr_desc);
4212 cmd->addr = (__u64)(uintptr_t)data;
4213}
4214
4215/**
4216 * nvme_init_get_features_host_mgmt_agent_addr() - Initialize passthru
4217 * command for Get Features - Host Management Agent Address
4218 * @cmd: Passthru command to use
4219 * @sel: Select which type of attribute to return,
4220 * see &enum nvme_get_features_sel
4221 * @data: 512 byte Host Management Agent Address (HMAA) data buffer,
4222 * see &struct nvme_mgmt_addr_desc
4223 *
4224 * Initializes the passthru command buffer for the Get Features command with
4225 * FID value %NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR
4226 */
4227static inline void
4228nvme_init_get_features_host_mgmt_agent_addr(struct libnvme_passthru_cmd *cmd,
4229 enum nvme_get_features_sel sel, void *data)
4230{
4231 nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR, sel);
4232 cmd->data_len = sizeof(struct nvme_mgmt_addr_desc);
4233 cmd->addr = (__u64)(uintptr_t)data;
4234}
4235
4236/**
4237 * nvme_init_get_features_enh_ctrl_metadata() - Initialize passthru command
4238 * for Get Features - Enhanced Controller Metadata
4239 * @cmd: Passthru command to use
4240 * @sel: Select which type of attribute to return,
4241 * see &enum nvme_get_features_sel
4242 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
4243 *
4244 * Initializes the passthru command buffer for the Get Features command with
4245 * FID value %NVME_FEAT_FID_ENH_CTRL_METADATA
4246 */
4247static inline void
4248nvme_init_get_features_enh_ctrl_metadata(struct libnvme_passthru_cmd *cmd,
4249 enum nvme_get_features_sel sel, struct nvme_host_metadata *data)
4250{
4251 nvme_init_get_features(cmd, NVME_FEAT_FID_ENH_CTRL_METADATA, sel);
4252 cmd->data_len = sizeof(*data);
4253 cmd->addr = (__u64)(uintptr_t)data;
4254}
4255
4256/**
4257 * nvme_init_get_features_ctrl_metadata() - Initialize passthru command for
4258 * Get Features - Controller Metadata
4259 * @cmd: Passthru command to use
4260 * @sel: Select which type of attribute to return,
4261 * see &enum nvme_get_features_sel
4262 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
4263 *
4264 * Initializes the passthru command buffer for the Get Features command with
4265 * FID value %NVME_FEAT_FID_CTRL_METADATA
4266 */
4267static inline void
4268nvme_init_get_features_ctrl_metadata(struct libnvme_passthru_cmd *cmd,
4269 enum nvme_get_features_sel sel, struct nvme_host_metadata *data)
4270{
4271 nvme_init_get_features(cmd, NVME_FEAT_FID_CTRL_METADATA, sel);
4272 cmd->data_len = sizeof(*data);
4273 cmd->addr = (__u64)(uintptr_t)data;
4274}
4275
4276/**
4277 * nvme_init_get_features_ns_metadata() - Initialize passthru command for
4278 * Get Features - Namespace Metadata
4279 * @cmd: Passthru command to use
4280 * @sel: Select which type of attribute to return,
4281 * see &enum nvme_get_features_sel
4282 * @data: Host Metadata data buffer, see &struct nvme_host_metadata
4283 *
4284 * Initializes the passthru command buffer for the Get Features command with
4285 * FID value %NVME_FEAT_FID_NS_METADATA
4286 */
4287static inline void
4288nvme_init_get_features_ns_metadata(struct libnvme_passthru_cmd *cmd,
4289 enum nvme_get_features_sel sel, struct nvme_host_metadata *data)
4290{
4291 nvme_init_get_features(cmd, NVME_FEAT_FID_NS_METADATA, sel);
4292 cmd->data_len = sizeof(*data);
4293 cmd->addr = (__u64)(uintptr_t)data;
4294}
4295
4296/**
4297 * nvme_init_get_features_bp_write_protect() - Initialize passthru command
4298 * for Get Features - Boot Partition Write Protection Config
4299 * @cmd: Passthru command to use
4300 * @sel: Select which type of attribute to return,
4301 * see &enum nvme_get_features_sel
4302 *
4303 * Initializes the passthru command buffer for the Get Features command with
4304 * FID value %NVME_FEAT_FID_BP_WRITE_PROTECT
4305 */
4306static inline void
4307nvme_init_get_features_bp_write_protect(struct libnvme_passthru_cmd *cmd,
4308 enum nvme_get_features_sel sel)
4309{
4310 nvme_init_get_features(cmd, NVME_FEAT_FID_BP_WRITE_PROTECT, sel);
4311}
4312
4313/**
4314 * nvme_init_ns_mgmt() - Initialize passthru command for Namespace Management
4315 * @cmd: Passthru command to use
4316 * @nsid: Namespace identifier
4317 * @sel: Type of management operation to perform
4318 * @csi: Command Set Identifier
4319 * @data: Host Software Specified Fields buffer
4320 *
4321 * Initializes the passthru command buffer for the Namespace Management command.
4322 */
4323static inline void
4324nvme_init_ns_mgmt(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4325 enum nvme_ns_mgmt_sel sel, __u8 csi,
4326 struct nvme_ns_mgmt_host_sw_specified *data)
4327{
4328 memset(cmd, 0, sizeof(*cmd));
4329
4330 cmd->opcode = nvme_admin_ns_mgmt;
4331 cmd->nsid = nsid;
4332 cmd->data_len = data ? sizeof(*data) : 0;
4333 cmd->addr = (__u64)(uintptr_t)data;
4334 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_NAMESPACE_MGMT_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT))
4335 NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_NAMESPACE_MGMT_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT))
4336 NVME_NAMESPACE_MGMT_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_NAMESPACE_MGMT_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT))
;
4337 cmd->cdw11 = NVME_FIELD_ENCODE(csi,(((__u32)(csi) & (NVME_NAMESPACE_MGMT_CDW11_CSI_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT))
4338 NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT,(((__u32)(csi) & (NVME_NAMESPACE_MGMT_CDW11_CSI_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT))
4339 NVME_NAMESPACE_MGMT_CDW11_CSI_MASK)(((__u32)(csi) & (NVME_NAMESPACE_MGMT_CDW11_CSI_MASK)) <<
(NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT))
;
4340}
4341
4342/**
4343 * nvme_init_ns_mgmt_create() - Initialize passthru command to create a
4344 * non attached namespace
4345 * @cmd: Passthru command to use
4346 * @csi: Command Set Identifier
4347 * @data: Host Software Specified Fields buffer that defines NS
4348 * creation parameters
4349 *
4350 * Initializes the passthru command buffer for the Namespace Management - Create
4351 * command. The command uses NVME_NSID_NONE as the target NSID.
4352 */
4353static inline void
4354nvme_init_ns_mgmt_create(struct libnvme_passthru_cmd *cmd, __u8 csi,
4355 struct nvme_ns_mgmt_host_sw_specified *data)
4356{
4357 nvme_init_ns_mgmt(cmd, NVME_NSID_NONE, NVME_NS_MGMT_SEL_CREATE,
4358 csi, data);
4359}
4360
4361/**
4362 * nvme_init_ns_mgmt_delete() - Initialize passthru command to delete a
4363 * non attached namespace
4364 * @cmd: Passthru command to use
4365 * @nsid: Namespace identifier to delete
4366 *
4367 * Initializes the passthru command buffer for the Namespace Management - Delete
4368 * command (NVME_NS_MGMT_SEL_DELETE). The command uses the provided @nsid as
4369 * the target NSID.
4370 */
4371static inline void
4372nvme_init_ns_mgmt_delete(struct libnvme_passthru_cmd *cmd, __u32 nsid)
4373{
4374 nvme_init_ns_mgmt(cmd, nsid, NVME_NS_MGMT_SEL_DELETE,
4375 NVME_CSI_NVM, NULL((void*)0));
4376}
4377
4378/**
4379 * nvme_init_ns_mgmt_restore_default_config() - Initialize passthru command to
4380 * restore the default NVM subsystem namespace configuration
4381 * @cmd: Passthru command to use
4382 *
4383 * Initializes the passthru command buffer for the Namespace Management -
4384 * Restore Default Namespace Configuration operation
4385 * (NVME_NS_MGMT_SEL_RESTORE_DEFAULT_CONFIG). The NSID field is unused for
4386 * this operation and is cleared to 0h.
4387 */
4388static inline void
4389nvme_init_ns_mgmt_restore_default_config(struct libnvme_passthru_cmd *cmd)
4390{
4391 nvme_init_ns_mgmt(cmd, NVME_NSID_NONE,
4392 NVME_NS_MGMT_SEL_RESTORE_DEFAULT_CONFIG, 0, NULL((void*)0));
4393}
4394
4395/**
4396 * nvme_init_fw_commit() - Initialize passthru command to commit firmware
4397 * using the specified action
4398 * @cmd: Passthru command to use
4399 * @fs: Firmware slot to commit the downloaded image
4400 * @ca: Action to use for the firmware image,
4401 * see &enum nvme_fw_commit_ca
4402 * @bpid: Set to true to select the boot partition id
4403 *
4404 * Initializes the passthru command buffer for the Firmware Commit command.
4405 */
4406static inline void
4407nvme_init_fw_commit(struct libnvme_passthru_cmd *cmd, __u8 fs,
4408 enum nvme_fw_commit_ca ca, bool_Bool bpid)
4409{
4410 memset(cmd, 0, sizeof(*cmd));
4411
4412 cmd->opcode = nvme_admin_fw_commit;
4413 cmd->cdw10 = NVME_FIELD_ENCODE(fs,(((__u32)(fs) & (NVME_FW_COMMIT_CDW10_FS_MASK)) << (
NVME_FW_COMMIT_CDW10_FS_SHIFT))
4414 NVME_FW_COMMIT_CDW10_FS_SHIFT,(((__u32)(fs) & (NVME_FW_COMMIT_CDW10_FS_MASK)) << (
NVME_FW_COMMIT_CDW10_FS_SHIFT))
4415 NVME_FW_COMMIT_CDW10_FS_MASK)(((__u32)(fs) & (NVME_FW_COMMIT_CDW10_FS_MASK)) << (
NVME_FW_COMMIT_CDW10_FS_SHIFT))
|
4416 NVME_FIELD_ENCODE(ca,(((__u32)(ca) & (NVME_FW_COMMIT_CDW10_CA_MASK)) << (
NVME_FW_COMMIT_CDW10_CA_SHIFT))
4417 NVME_FW_COMMIT_CDW10_CA_SHIFT,(((__u32)(ca) & (NVME_FW_COMMIT_CDW10_CA_MASK)) << (
NVME_FW_COMMIT_CDW10_CA_SHIFT))
4418 NVME_FW_COMMIT_CDW10_CA_MASK)(((__u32)(ca) & (NVME_FW_COMMIT_CDW10_CA_MASK)) << (
NVME_FW_COMMIT_CDW10_CA_SHIFT))
|
4419 NVME_FIELD_ENCODE(bpid,(((__u32)(bpid) & (NVME_FW_COMMIT_CDW10_BPID_MASK)) <<
(NVME_FW_COMMIT_CDW10_BPID_SHIFT))
4420 NVME_FW_COMMIT_CDW10_BPID_SHIFT,(((__u32)(bpid) & (NVME_FW_COMMIT_CDW10_BPID_MASK)) <<
(NVME_FW_COMMIT_CDW10_BPID_SHIFT))
4421 NVME_FW_COMMIT_CDW10_BPID_MASK)(((__u32)(bpid) & (NVME_FW_COMMIT_CDW10_BPID_MASK)) <<
(NVME_FW_COMMIT_CDW10_BPID_SHIFT))
;
4422}
4423
4424/**
4425 * nvme_init_fw_download() - Initialize passthru command to download part or
4426 * all of a firmware image to the controller
4427 * @cmd: Passthru command to use
4428 * @data: Userspace address of the firmware data buffer
4429 * @len: Length of data in this command in bytes
4430 * @offset: Offset in the firmware data
4431 *
4432 * Initializes the passthru command buffer for the Firmware Image
4433 * Download command.
4434 *
4435 * Note: Caller must ensure data_len and offset are DWord-aligned (0x4).
4436 *
4437 * Return: 0 on success, negative error code otherwise.
4438 */
4439static inline int
4440nvme_init_fw_download(struct libnvme_passthru_cmd *cmd, void *data,
4441 __u32 len, __u32 offset)
4442{
4443 if (len & 0x3 || !len)
4444 return -EINVAL22;
4445
4446 if (offset & 0x3)
4447 return -EINVAL22;
4448
4449 memset(cmd, 0, sizeof(*cmd));
4450
4451 cmd->opcode = nvme_admin_fw_download;
4452 cmd->data_len = len;
4453 cmd->addr = (__u64)(uintptr_t)data;
4454 cmd->cdw10 = (len >> 2) - 1;
4455 cmd->cdw11 = offset >> 2;
4456
4457 return 0;
4458}
4459
4460/**
4461 * nvme_init_dev_self_test() - Initialize passthru command to start or
4462 * abort a self test
4463 * @cmd: Passthru command to use
4464 * @nsid: Namespace ID to test
4465 * @stc: Self test code, see &enum nvme_dst_stc
4466 *
4467 * Initializes the passthru command buffer for the Device Self-test command.
4468 */
4469static inline void
4470nvme_init_dev_self_test(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4471 enum nvme_dst_stc stc)
4472{
4473 memset(cmd, 0, sizeof(*cmd));
4474
4475 cmd->opcode = nvme_admin_dev_self_test;
4476 cmd->nsid = nsid;
4477 cmd->cdw10 = NVME_FIELD_ENCODE(stc,(((__u32)(stc) & (NVME_DEVICE_SELF_TEST_CDW10_STC_MASK)) <<
(NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT))
4478 NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT,(((__u32)(stc) & (NVME_DEVICE_SELF_TEST_CDW10_STC_MASK)) <<
(NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT))
4479 NVME_DEVICE_SELF_TEST_CDW10_STC_MASK)(((__u32)(stc) & (NVME_DEVICE_SELF_TEST_CDW10_STC_MASK)) <<
(NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT))
;
4480}
4481
4482/**
4483 * nvme_init_ns_attach() - Initialize passthru command for
4484 * Namespace Attach/Detach
4485 * @cmd: Passthru command to use
4486 * @nsid: Namespace ID to execute attach selection
4487 * @sel: Attachment selection, see &enum nvme_ns_attach_sel
4488 * @ctrlist: Controller list buffer to modify attachment state of nsid
4489 *
4490 * Initializes the passthru command buffer for the Namespace Attach/Detach
4491 * command.
4492 */
4493static inline void
4494nvme_init_ns_attach(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4495 enum nvme_ns_attach_sel sel, struct nvme_ctrl_list *ctrlist)
4496{
4497 memset(cmd, 0, sizeof(*cmd));
4498
4499 cmd->opcode = nvme_admin_ns_attach;
4500 cmd->nsid = nsid;
4501 cmd->data_len = sizeof(*ctrlist);
4502 cmd->addr = (__u64)(uintptr_t)ctrlist;
4503 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT))
4504 NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT))
4505 NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK)) <<
(NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT))
;
4506}
4507
4508/**
4509 * nvme_init_ns_attach_ctrls() - Initialize passthru command to attach
4510 * namespace to controllers
4511 * @cmd: Passthru command to use
4512 * @nsid: Namespace ID to attach
4513 * @ctrlist: Controller list buffer to modify attachment state of nsid
4514 *
4515 * Initializes the passthru command buffer for the Namespace Attach command
4516 * (NVME_NS_ATTACH_SEL_CTRL_ATTACH).
4517 */
4518static inline void
4519nvme_init_ns_attach_ctrls(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4520 struct nvme_ctrl_list *ctrlist)
4521{
4522 nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_ATTACH,
4523 ctrlist);
4524}
4525
4526/**
4527 * nvme_init_ns_detach_ctrls() - Initialize passthru command to detach
4528 * namespace from controllers
4529 * @cmd: Passthru command to use
4530 * @nsid: Namespace ID to detach
4531 * @ctrlist: Controller list buffer to modify attachment state of nsid
4532 *
4533 * Initializes the passthru command buffer for the Namespace Detach command
4534 * (NVME_NS_ATTACH_SEL_CTRL_DEATTACH).
4535 */
4536static inline void
4537nvme_init_ns_detach_ctrls(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4538 struct nvme_ctrl_list *ctrlist)
4539{
4540 nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_DEATTACH,
4541 ctrlist);
4542}
4543
4544/**
4545 * nvme_init_keep_alive() - Initialize passthru command for
4546 * Keep Alive command
4547 * @cmd: Passthru command to use
4548 *
4549 * Initializes the passthru command buffer for the Keep Alive command. All
4550 * command specific fields are reserved.
4551 */
4552static inline void
4553nvme_init_keep_alive(struct libnvme_passthru_cmd *cmd)
4554{
4555 memset(cmd, 0, sizeof(*cmd));
4556 cmd->opcode = nvme_admin_keep_alive;
4557}
4558
4559/**
4560 * nvme_init_directive_send() - Initialize passthru command for Directive Send
4561 * @cmd: Passthru command to use
4562 * @nsid: Namespace ID, if applicable
4563 * @doper: Directive send operation, see &enum nvme_directive_send_doper
4564 * @dtype: Directive type, see &enum nvme_directive_dtype
4565 * @dspec: Directive specific field
4566 * @data: Data payload buffer to be send
4567 * @len: Length of data payload in bytes
4568 *
4569 * Initializes the passthru command buffer for the Directive Send command.
4570 */
4571static inline void
4572nvme_init_directive_send(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4573 enum nvme_directive_send_doper doper,
4574 enum nvme_directive_dtype dtype, __u16 dspec,
4575 void *data, __u32 len)
4576{
4577
4578 memset(cmd, 0, sizeof(*cmd));
4579
4580 cmd->opcode = nvme_admin_directive_send;
4581 cmd->nsid = nsid;
4582 cmd->data_len = len;
4583 cmd->addr = (__u64)(uintptr_t)data;
4584 cmd->cdw10 = len ? (len >> 2) - 1 : 0;
4585 cmd->cdw11 = NVME_FIELD_ENCODE(doper,(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
4586 NVME_DIRECTIVE_CDW11_DOPER_SHIFT,(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
4587 NVME_DIRECTIVE_CDW11_DOPER_MASK)(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
|
4588 NVME_FIELD_ENCODE(dtype,(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
4589 NVME_DIRECTIVE_CDW11_DTYPE_SHIFT,(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
4590 NVME_DIRECTIVE_CDW11_DTYPE_MASK)(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
|
4591 NVME_FIELD_ENCODE(dspec,(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
4592 NVME_DIRECTIVE_CDW11_DPSEC_SHIFT,(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
4593 NVME_DIRECTIVE_CDW11_DPSEC_MASK)(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
;
4594}
4595
4596/**
4597 * nvme_init_directive_send_id_endir() - Initialize passthru command for
4598 * Directive Send Enable Directive
4599 * @cmd: Passthru command to use
4600 * @nsid: Namespace Identifier
4601 * @endir: Enable Directive
4602 * @dtype: Directive Type
4603 * @id: Pointer to structure nvme_id_directives
4604 *
4605 * Initializes the passthru command buffer for the Directive Send - Identify
4606 * (Enable Directive) command.
4607 */
4608static inline void
4609nvme_init_directive_send_id_endir(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4610 bool_Bool endir, enum nvme_directive_dtype dtype,
4611 struct nvme_id_directives *id)
4612{
4613 nvme_init_directive_send(cmd, nsid,
4614 NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR,
4615 NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id));
4616 cmd->cdw12 = NVME_FIELD_ENCODE(dtype,(((__u32)(dtype) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT))
4617 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT,(((__u32)(dtype) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT))
4618 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK)(((__u32)(dtype) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT))
|
4619 NVME_FIELD_ENCODE(endir,(((__u32)(endir) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT))
4620 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT,(((__u32)(endir) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT))
4621 NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK)(((__u32)(endir) & (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK
)) << (NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT))
;
4622}
4623
4624/**
4625 * nvme_init_directive_send_stream_release_identifier() - Initialize passthru
4626 * command for Directive Send Stream release identifier
4627 * @cmd: Passthru command to use
4628 * @nsid: Namespace ID
4629 * @stream_id: Stream identifier
4630 *
4631 * Initializes the passthru command buffer for the Directive Send - Stream
4632 * Release Identifier command.
4633 */
4634static inline void
4635nvme_init_directive_send_stream_release_identifier(
4636 struct libnvme_passthru_cmd *cmd,
4637 __u32 nsid, __u16 stream_id)
4638{
4639 nvme_init_directive_send(cmd, nsid,
4640 NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER,
4641 NVME_DIRECTIVE_DTYPE_STREAMS, stream_id, NULL((void*)0), 0);
4642}
4643
4644/**
4645 * nvme_init_directive_send_stream_release_resource() - Initialize passthru
4646 * command for Directive Send Stream release resources
4647 * @cmd: Passthru command to use
4648 * @nsid: Namespace ID
4649 *
4650 * Initializes the passthru command buffer for the Directive Send - Stream
4651 * Release Resource command.
4652 */
4653static inline void
4654nvme_init_directive_send_stream_release_resource(
4655 struct libnvme_passthru_cmd *cmd, __u32 nsid)
4656{
4657 nvme_init_directive_send(cmd, nsid,
4658 NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE,
4659 NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL((void*)0), 0);
4660}
4661
4662/**
4663 * nvme_init_directive_recv() - Initialize passthru command for
4664 * Directive Receive
4665 * @cmd: Passthru command to use
4666 * @nsid: Namespace ID, if applicable
4667 * @doper: Directive receive operation,
4668 * see &enum nvme_directive_receive_doper
4669 * @dtype: Directive type, see &enum nvme_directive_dtype
4670 * @dspec: Directive specific field
4671 * @data: Userspace address of data payload buffer
4672 * @len: Length of data payload in bytes
4673 *
4674 * Initializes the passthru command buffer for the Directive Receive command.
4675 */
4676static inline void
4677nvme_init_directive_recv(struct libnvme_passthru_cmd *cmd, __u32 nsid,
4678 enum nvme_directive_receive_doper doper,
4679 enum nvme_directive_dtype dtype, __u16 dspec,
4680 void *data, __u32 len)
4681{
4682
4683 memset(cmd, 0, sizeof(*cmd));
4684
4685 cmd->opcode = nvme_admin_directive_recv;
4686 cmd->nsid = nsid;
4687 cmd->data_len = len;
4688 cmd->addr = (__u64)(uintptr_t)data;
4689 cmd->cdw10 = len ? (len >> 2) - 1 : 0;
4690 cmd->cdw11 = NVME_FIELD_ENCODE(doper,(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
4691 NVME_DIRECTIVE_CDW11_DOPER_SHIFT,(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
4692 NVME_DIRECTIVE_CDW11_DOPER_MASK)(((__u32)(doper) & (NVME_DIRECTIVE_CDW11_DOPER_MASK)) <<
(NVME_DIRECTIVE_CDW11_DOPER_SHIFT))
|
4693 NVME_FIELD_ENCODE(dtype,(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
4694 NVME_DIRECTIVE_CDW11_DTYPE_SHIFT,(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
4695 NVME_DIRECTIVE_CDW11_DTYPE_MASK)(((__u32)(dtype) & (NVME_DIRECTIVE_CDW11_DTYPE_MASK)) <<
(NVME_DIRECTIVE_CDW11_DTYPE_SHIFT))
|
4696 NVME_FIELD_ENCODE(dspec,(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
4697 NVME_DIRECTIVE_CDW11_DPSEC_SHIFT,(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
4698 NVME_DIRECTIVE_CDW11_DPSEC_MASK)(((__u32)(dspec) & (NVME_DIRECTIVE_CDW11_DPSEC_MASK)) <<
(NVME_DIRECTIVE_CDW11_DPSEC_SHIFT))
;
4699}
4700
4701/**
4702 * nvme_init_directive_recv_identify_parameters() - Initialize passthru command
4703 * for Directive Receive Identify Parameters
4704 * @cmd: Passthru command to use
4705 * @nsid: Namespace ID
4706 * @id: Identify parameters buffer
4707 *
4708 * Initializes the passthru command buffer for the Directive Receive - Identify
4709 * Parameters command.
4710 */
4711static inline void
4712nvme_init_directive_recv_identify_parameters(struct libnvme_passthru_cmd *cmd,
4713 __u32 nsid, struct nvme_id_directives *id)
4714{
4715 nvme_init_directive_recv(cmd, nsid,
4716 NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM,
4717 NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id));
4718}
4719
4720/**
4721 * nvme_init_directive_recv_stream_parameters() - Initialize passthru command
4722 * for Directive Receive Stream Parameters
4723 * @cmd: Passthru command to use
4724 * @nsid: Namespace ID
4725 * @parms: Streams directive parameters buffer
4726 *
4727 * Initializes the passthru command buffer for the Directive Receive - Stream
4728 * Parameters command.
4729 */
4730static inline void
4731nvme_init_directive_recv_stream_parameters(struct libnvme_passthru_cmd *cmd,
4732 __u32 nsid, struct nvme_streams_directive_params *parms)
4733{
4734 nvme_init_directive_recv(cmd, nsid,
4735 NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM,
4736 NVME_DIRECTIVE_DTYPE_STREAMS, 0, parms, sizeof(*parms));
4737}
4738
4739/**
4740 * nvme_init_directive_recv_stream_allocate() - Initialize passthru command for
4741 * Directive Receive Stream Allocate
4742 * @cmd: Passthru command to use
4743 * @nsid: Namespace ID
4744 * @nsr: Namespace Streams Requested
4745 *
4746 * Initializes the passthru command buffer for the Directive Receive - Stream
4747 * Allocate command.
4748 */
4749static inline void
4750nvme_init_directive_recv_stream_allocate(struct libnvme_passthru_cmd *cmd,
4751 __u32 nsid, __u16 nsr)
4752{
4753 nvme_init_directive_recv(cmd, nsid,
4754 NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE,
4755 NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL((void*)0), 0);
4756 cmd->cdw12 = nsr;
4757}
4758
4759/**
4760 * nvme_init_directive_recv_stream_status() - Initialize passthru command for
4761 * Directive Receive Stream Status
4762 * @cmd: Passthru command to use
4763 * @nsid: Namespace ID
4764 * @nr_entries: Number of streams to receive
4765 * @id: Stream status buffer
4766 *
4767 * Initializes the passthru command buffer for the Directive Receive - Stream
4768 * Status command.
4769 *
4770 * Return: 0 on success, negative error code otherwise.
4771 */
4772static inline int
4773nvme_init_directive_recv_stream_status(struct libnvme_passthru_cmd *cmd,
4774 __u32 nsid, unsigned int nr_entries,
4775 struct nvme_streams_directive_status *id)
4776{
4777 if (nr_entries > NVME_STREAM_ID_MAX)
4778 return -EINVAL22;
4779
4780 nvme_init_directive_recv(cmd, nsid,
4781 NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS,
4782 NVME_DIRECTIVE_DTYPE_STREAMS, 0, id,
4783 (__u32)(sizeof(*id) + nr_entries * sizeof(__le16)));
4784
4785 return 0;
4786}
4787
4788/**
4789 * nvme_init_virtual_mgmt() - Initialize passthru command for
4790 * Virtualization Resource Management
4791 * @cmd: Passthru command to use
4792 * @act: Virtual resource action, see &enum nvme_virt_mgmt_act
4793 * @rt: Resource type to modify, see &enum nvme_virt_mgmt_rt
4794 * @cntlid: Controller id for which resources are bing modified
4795 * @nr: Number of resources being allocated or assigned
4796 *
4797 * Initializes the passthru command buffer for the Virtualization
4798 * Management command.
4799 */
4800static inline void
4801nvme_init_virtual_mgmt(struct libnvme_passthru_cmd *cmd,
4802 enum nvme_virt_mgmt_act act, enum nvme_virt_mgmt_rt rt,
4803 __u16 cntlid, __u16 nr)
4804{
4805 memset(cmd, 0, sizeof(*cmd));
4806 cmd->opcode = nvme_admin_virtual_mgmt;
4807 cmd->cdw10 = NVME_FIELD_ENCODE(act,(((__u32)(act) & (NVME_VIRT_MGMT_CDW10_ACT_MASK)) <<
(NVME_VIRT_MGMT_CDW10_ACT_SHIFT))
4808 NVME_VIRT_MGMT_CDW10_ACT_SHIFT,(((__u32)(act) & (NVME_VIRT_MGMT_CDW10_ACT_MASK)) <<
(NVME_VIRT_MGMT_CDW10_ACT_SHIFT))
4809 NVME_VIRT_MGMT_CDW10_ACT_MASK)(((__u32)(act) & (NVME_VIRT_MGMT_CDW10_ACT_MASK)) <<
(NVME_VIRT_MGMT_CDW10_ACT_SHIFT))
|
4810 NVME_FIELD_ENCODE(rt,(((__u32)(rt) & (NVME_VIRT_MGMT_CDW10_RT_MASK)) << (
NVME_VIRT_MGMT_CDW10_RT_SHIFT))
4811 NVME_VIRT_MGMT_CDW10_RT_SHIFT,(((__u32)(rt) & (NVME_VIRT_MGMT_CDW10_RT_MASK)) << (
NVME_VIRT_MGMT_CDW10_RT_SHIFT))
4812 NVME_VIRT_MGMT_CDW10_RT_MASK)(((__u32)(rt) & (NVME_VIRT_MGMT_CDW10_RT_MASK)) << (
NVME_VIRT_MGMT_CDW10_RT_SHIFT))
|
4813 NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_VIRT_MGMT_CDW10_CNTLID_MASK)) <<
(NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT))
4814 NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_VIRT_MGMT_CDW10_CNTLID_MASK)) <<
(NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT))
4815 NVME_VIRT_MGMT_CDW10_CNTLID_MASK)(((__u32)(cntlid) & (NVME_VIRT_MGMT_CDW10_CNTLID_MASK)) <<
(NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT))
;
4816 cmd->cdw11 = NVME_FIELD_ENCODE(nr,(((__u32)(nr) & (NVME_VIRT_MGMT_CDW11_NR_MASK)) << (
NVME_VIRT_MGMT_CDW11_NR_SHIFT))
4817 NVME_VIRT_MGMT_CDW11_NR_SHIFT,(((__u32)(nr) & (NVME_VIRT_MGMT_CDW11_NR_MASK)) << (
NVME_VIRT_MGMT_CDW11_NR_SHIFT))
4818 NVME_VIRT_MGMT_CDW11_NR_MASK)(((__u32)(nr) & (NVME_VIRT_MGMT_CDW11_NR_MASK)) << (
NVME_VIRT_MGMT_CDW11_NR_SHIFT))
;
4819}
4820
4821/**
4822 * nvme_init_capacity_mgmt() - Initialize passthru command for
4823 * Capacity Management
4824 * @cmd: Passthru command to use
4825 * @oper: Operation to be performed by the controller
4826 * @elid: Value specific to the value of the Operation field
4827 * @cap: Capacity in bytes of the Endurance Group or NVM Set to
4828 * be created
4829 *
4830 * Initializes the passthru command buffer for the Capacity Management command.
4831 */
4832static inline void
4833nvme_init_capacity_mgmt(struct libnvme_passthru_cmd *cmd,
4834 __u8 oper, __u16 elid, __u64 cap)
4835{
4836 memset(cmd, 0, sizeof(*cmd));
4837
4838 cmd->opcode = nvme_admin_capacity_mgmt;
4839 cmd->cdw10 = NVME_FIELD_ENCODE(oper,(((__u32)(oper) & (NVME_CAPACITY_MGMT_CDW10_OPER_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT))
4840 NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT,(((__u32)(oper) & (NVME_CAPACITY_MGMT_CDW10_OPER_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT))
4841 NVME_CAPACITY_MGMT_CDW10_OPER_MASK)(((__u32)(oper) & (NVME_CAPACITY_MGMT_CDW10_OPER_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT))
|
4842 NVME_FIELD_ENCODE(elid,(((__u32)(elid) & (NVME_CAPACITY_MGMT_CDW10_ELID_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT))
4843 NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT,(((__u32)(elid) & (NVME_CAPACITY_MGMT_CDW10_ELID_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT))
4844 NVME_CAPACITY_MGMT_CDW10_ELID_MASK)(((__u32)(elid) & (NVME_CAPACITY_MGMT_CDW10_ELID_MASK)) <<
(NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT))
;
4845 cmd->cdw11 = NVME_FIELD_ENCODE(cap,(((__u32)(cap) & (NVME_CAPACITY_MGMT_CDW11_CAPL_MASK)) <<
(NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT))
4846 NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT,(((__u32)(cap) & (NVME_CAPACITY_MGMT_CDW11_CAPL_MASK)) <<
(NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT))
4847 NVME_CAPACITY_MGMT_CDW11_CAPL_MASK)(((__u32)(cap) & (NVME_CAPACITY_MGMT_CDW11_CAPL_MASK)) <<
(NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT))
;
4848 cmd->cdw12 = NVME_FIELD_ENCODE(cap >> 32,(((__u32)(cap >> 32) & (NVME_CAPACITY_MGMT_CDW12_CAPU_MASK
)) << (NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT))
4849 NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT,(((__u32)(cap >> 32) & (NVME_CAPACITY_MGMT_CDW12_CAPU_MASK
)) << (NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT))
4850 NVME_CAPACITY_MGMT_CDW12_CAPU_MASK)(((__u32)(cap >> 32) & (NVME_CAPACITY_MGMT_CDW12_CAPU_MASK
)) << (NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT))
;
4851}
4852
4853/**
4854 * nvme_init_capacity_mgmt_restore_default_config() - Initialize passthru
4855 * command to restore the default Endurance Groups and NVM Sets configuration
4856 * @cmd: Passthru command to use
4857 *
4858 * Initializes the passthru command buffer for the Capacity Management -
4859 * Restore Default Capacity Management Configuration operation
4860 * (NVME_CAPACITY_MGMT_OPER_RESTORE_DEFAULT_CONFIG).
4861 */
4862static inline void
4863nvme_init_capacity_mgmt_restore_default_config(struct libnvme_passthru_cmd *cmd)
4864{
4865 nvme_init_capacity_mgmt(cmd,
4866 NVME_CAPACITY_MGMT_OPER_RESTORE_DEFAULT_CONFIG, 0, 0);
4867}
4868
4869/**
4870 * nvme_init_dim_send() - Initialize passthru command for
4871 * Discovery Information Management (DIM) Send
4872 * @cmd: Passthru command to use
4873 * @tas: Task field of the Command Dword 10 (cdw10)
4874 * @data: Pointer to the DIM data buffer
4875 * @len: Length of @data
4876 *
4877 * Initializes the passthru command buffer for the Discovery Information
4878 * Management Send command.
4879 */
4880static inline void
4881nvme_init_dim_send(struct libnvme_passthru_cmd *cmd,
4882 __u8 tas, void *data, __u32 len)
4883{
4884 memset(cmd, 0, sizeof(*cmd));
4885
4886 cmd->opcode = nvme_admin_discovery_info_mgmt;
4887 cmd->data_len = len;
4888 cmd->addr = (__u64)(uintptr_t)data;
4889 cmd->cdw10 = NVME_FIELD_ENCODE(tas,(((__u32)(tas) & (NVME_DIM_TAS_MASK)) << (NVME_DIM_TAS_SHIFT
))
4890 NVME_DIM_TAS_SHIFT,(((__u32)(tas) & (NVME_DIM_TAS_MASK)) << (NVME_DIM_TAS_SHIFT
))
4891 NVME_DIM_TAS_MASK)(((__u32)(tas) & (NVME_DIM_TAS_MASK)) << (NVME_DIM_TAS_SHIFT
))
;
4892
4893}
4894
4895/**
4896 * nvme_init_clear_export_nvm_res() - Initialize passthru command for
4897 * Clear Exported NVM Resource Configuration
4898 * @cmd: Passthru command to use
4899 *
4900 * Initializes the passthru command buffer for the Clear Exported NVM
4901 * Resource Configuration command. All command specific fields are
4902 * reserved.
4903 */
4904static inline void
4905nvme_init_clear_export_nvm_res(struct libnvme_passthru_cmd *cmd)
4906{
4907 memset(cmd, 0, sizeof(*cmd));
4908 cmd->opcode = nvme_admin_clear_export_nvm_res;
4909}
4910
4911/**
4912 * nvme_init_manage_export_nvms_receive() - Initialize passthru command for
4913 * Manage Exported NVM Subsystem Receive
4914 * @cmd: Passthru command to use
4915 * @sel: Select (SEL): management operation to perform, see &enum
4916 * nvme_manage_export_nvms_recv_sel
4917 * @mos: Management Operation Specific (MOS): specific to @sel
4918 * @mose: Management Operation Specific Extended (MOSE): specific to
4919 * @sel
4920 * @mosi: Management Operation Specific Identifier (MOSI): specific to
4921 * @sel
4922 * @ol: Offset Lower (OL), in dwords: specific to @sel
4923 * @ou: Offset Upper (OU), in dwords: specific to @sel
4924 * @numdl: Number of Dwords (NUMDL) requested, 0's based: specific to
4925 * @sel
4926 * @data: Pointer to data buffer
4927 * @len: Length of @data
4928 *
4929 * Initializes the passthru command buffer for the Manage Exported NVM
4930 * Subsystem Receive command.
4931 */
4932static inline void
4933nvme_init_manage_export_nvms_receive(struct libnvme_passthru_cmd *cmd,
4934 __u8 sel, __u8 mos, __u16 mose, __u16 mosi,
4935 __u32 ol, __u32 ou, __u32 numdl, void *data, __u32 len)
4936{
4937 memset(cmd, 0, sizeof(*cmd));
4938 cmd->opcode = nvme_admin_manage_export_nvms_receive;
4939 cmd->data_len = len;
4940 cmd->addr = (__u64)(uintptr_t)data;
4941 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_SHIFT))
4942 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_SHIFT))
4943 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_SEL_SHIFT))
|
4944 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_SHIFT))
4945 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_SHIFT,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_SHIFT))
4946 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_MASK)(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOS_SHIFT))
|
4947 NVME_FIELD_ENCODE(mose,(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_SHIFT))
4948 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_SHIFT,(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_SHIFT))
4949 NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_MASK)(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW10_MOSE_SHIFT))
;
4950 cmd->cdw12 = ol;
4951 cmd->cdw13 = ou;
4952 cmd->cdw14 = NVME_FIELD_ENCODE(mosi,(((__u32)(mosi) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_SHIFT))
4953 NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_SHIFT,(((__u32)(mosi) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_SHIFT))
4954 NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_MASK)(((__u32)(mosi) & (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_RECV_CDW14_MOSI_SHIFT))
;
4955 cmd->cdw15 = numdl;
4956}
4957
4958/**
4959 * nvme_init_manage_export_nvms_receive_create() - Initialize passthru
4960 * command for Manage Exported NVM Subsystem Receive - Create Exported NVM
4961 * Subsystem
4962 * @cmd: Passthru command to use
4963 * @tr: Template Required (TR)
4964 * @ensti: Exported NVM Subsystem Template Index (ENSTI), used if @tr is
4965 * set. Indexes the Exported NVM Subsystem Template UUID List,
4966 * see %NVME_IDENTIFY_CNS_EXPORTED_NVM_SUBSYS_TEMPLATE_UUID_LIST.
4967 * @ra: Restricted Access (RA): message-based transports only,
4968 * ignored by memory-based transports
4969 * @data: Create Exported NVM Subsystem data buffer, see &struct
4970 * nvme_exported_nvm_subsys_create_data. The assigned Exported
4971 * NVM Subsystem NQN is returned in this same buffer.
4972 *
4973 * Initializes the passthru command buffer for the Manage Exported NVM
4974 * Subsystem Receive command with SEL value
4975 * %NVME_MANAGE_EXPORT_NVMS_RECV_SEL_CREATE. The created Exported NVM
4976 * Subsystem Identifier is returned in the CQE result, see &enum
4977 * nvme_export_nvms_create_cqe_dw0.
4978 */
4979static inline void
4980nvme_init_manage_export_nvms_receive_create(struct libnvme_passthru_cmd *cmd,
4981 bool_Bool tr, __u8 ensti, bool_Bool ra,
4982 struct nvme_exported_nvm_subsys_create_data *data)
4983{
4984 __u8 mos = ra ? NVME_EXPORT_NVMS_CREATE_MOS_RA : 0;
4985
4986 nvme_init_manage_export_nvms_receive(cmd,
4987 NVME_MANAGE_EXPORT_NVMS_RECV_SEL_CREATE, mos, 0, 0, 0, 0, 0,
4988 data, sizeof(*data));
4989 cmd->cdw11 = NVME_FIELD_ENCODE(ensti,(((__u32)(ensti) & (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_MASK
)) << (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_SHIFT))
4990 NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_SHIFT,(((__u32)(ensti) & (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_MASK
)) << (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_SHIFT))
4991 NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_MASK)(((__u32)(ensti) & (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_MASK
)) << (NVME_EXPORT_NVMS_CREATE_CDW11_ENSTI_SHIFT))
|
4992 (tr ? NVME_EXPORT_NVMS_CREATE_CDW11_TR : 0);
4993}
4994
4995/**
4996 * nvme_init_manage_export_nvms_receive_list_subsystems() - Initialize
4997 * passthru command for Manage Exported NVM Subsystem Receive - List
4998 * Exported NVM Subsystems
4999 * @cmd: Passthru command to use
5000 * @esubid: Return Exported NVM Subsystems with an Exported NVM
5001 * Subsystem Identifier greater than or equal to this value
5002 * @list: User address to store the Exported NVM Subsystems List data
5003 * structure, see &struct nvme_exported_nvm_subsys_list
5004 * @len: The allocated length of @list
5005 *
5006 * Initializes the passthru command buffer for the Manage Exported NVM
5007 * Subsystem Receive command with SEL value
5008 * %NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_SUBSYSTEMS.
5009 */
5010static inline void
5011nvme_init_manage_export_nvms_receive_list_subsystems(
5012 struct libnvme_passthru_cmd *cmd, __u16 esubid,
5013 struct nvme_exported_nvm_subsys_list *list, __u32 len)
5014{
5015 __u32 numdl = len ? (len >> 2) - 1 : 0;
5016
5017 nvme_init_manage_export_nvms_receive(cmd,
5018 NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_SUBSYSTEMS, 0, 0,
5019 esubid, 0, 0, numdl, list, len);
5020}
5021
5022/**
5023 * nvme_init_manage_export_nvms_receive_list_namespaces() - Initialize
5024 * passthru command for Manage Exported NVM Subsystem Receive - List
5025 * Exported Namespaces
5026 * @cmd: Passthru command to use
5027 * @nsid: Return Exported Namespaces associated with this Exported NVM
5028 * Subsystem, with an Exported Namespace Identifier greater
5029 * than this value
5030 * @list: User address to store the Exported Namespace List data
5031 * structure, see &struct nvme_exported_ns_list
5032 * @len: The allocated length of @list
5033 *
5034 * Initializes the passthru command buffer for the Manage Exported NVM
5035 * Subsystem Receive command with SEL value
5036 * %NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_NAMESPACES.
5037 */
5038static inline void
5039nvme_init_manage_export_nvms_receive_list_namespaces(
5040 struct libnvme_passthru_cmd *cmd, __u32 nsid,
5041 struct nvme_exported_ns_list *list, __u32 len)
5042{
5043 __u32 numdl = len ? (len >> 2) - 1 : 0;
5044
5045 nvme_init_manage_export_nvms_receive(cmd,
5046 NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_NAMESPACES, 0, 0, 0,
5047 0, 0, numdl, list, len);
5048 cmd->nsid = nsid;
5049}
5050
5051/**
5052 * nvme_init_manage_export_nvms_receive_list_controllers() - Initialize
5053 * passthru command for Manage Exported NVM Subsystem Receive - List
5054 * Exported Controllers (message-based transports only)
5055 * @cmd: Passthru command to use
5056 * @ecntlid: Return Exported Controllers with an Exported Controller
5057 * Identifier greater than or equal to this value
5058 * @list: User address to store the Exported Controller List data
5059 * structure, see &struct nvme_exported_ctrl_list
5060 * @len: The allocated length of @list
5061 *
5062 * Initializes the passthru command buffer for the Manage Exported NVM
5063 * Subsystem Receive command with SEL value
5064 * %NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_CONTROLLERS.
5065 */
5066static inline void
5067nvme_init_manage_export_nvms_receive_list_controllers(
5068 struct libnvme_passthru_cmd *cmd, __u16 ecntlid,
5069 struct nvme_exported_ctrl_list *list, __u32 len)
5070{
5071 __u32 numdl = len ? (len >> 2) - 1 : 0;
5072
5073 nvme_init_manage_export_nvms_receive(cmd,
5074 NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_CONTROLLERS, 0, ecntlid,
5075 0, 0, 0, numdl, list, len);
5076}
5077
5078/**
5079 * nvme_init_manage_export_nvms_receive_list_ports() - Initialize passthru
5080 * command for Manage Exported NVM Subsystem Receive - List Exported Ports
5081 * (memory-based transports only)
5082 * @cmd: Passthru command to use
5083 * @epid: Return Exported Ports with an Exported Port Identifier
5084 * greater than or equal to this value
5085 * @list: User address to store the Exported Ports List data
5086 * structure, see &struct nvme_exported_port_list
5087 * @len: The allocated length of @list
5088 *
5089 * Initializes the passthru command buffer for the Manage Exported NVM
5090 * Subsystem Receive command with SEL value
5091 * %NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_PORTS.
5092 */
5093static inline void
5094nvme_init_manage_export_nvms_receive_list_ports(
5095 struct libnvme_passthru_cmd *cmd, __u16 epid,
5096 struct nvme_exported_port_list *list, __u32 len)
5097{
5098 __u32 numdl = len ? (len >> 2) - 1 : 0;
5099
5100 nvme_init_manage_export_nvms_receive(cmd,
5101 NVME_MANAGE_EXPORT_NVMS_RECV_SEL_LIST_PORTS, 0, epid,
5102 0, 0, 0, numdl, list, len);
5103}
5104
5105/**
5106 * nvme_init_manage_export_ns() - Initialize passthru command for
5107 * Manage Exported Namespace
5108 * @cmd: Passthru command to use
5109 * @sel: Select (SEL): management operation to perform, see &enum
5110 * nvme_manage_export_ns_sel
5111 * @mos: Management Operation Specific (MOS): specific to @sel
5112 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5113 * @esubid identifies the target Exported NVM Subsystem;
5114 * otherwise the target is identified by the SUBNQN in @data
5115 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5116 * @esubidv is set
5117 * @data: Pointer to data buffer
5118 * @len: Length of @data
5119 *
5120 * Initializes the passthru command buffer for the Manage Exported
5121 * Namespace command.
5122 */
5123static inline void
5124nvme_init_manage_export_ns(struct libnvme_passthru_cmd *cmd,
5125 __u8 sel, __u8 mos, bool_Bool esubidv, __u16 esubid,
5126 void *data, __u32 len)
5127{
5128 memset(cmd, 0, sizeof(*cmd));
5129 cmd->opcode = nvme_admin_manage_export_ns;
5130 cmd->data_len = len;
5131 cmd->addr = (__u64)(uintptr_t)data;
5132 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NS_CDW10_SEL_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_SEL_SHIFT))
5133 NVME_MANAGE_EXPORT_NS_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NS_CDW10_SEL_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_SEL_SHIFT))
5134 NVME_MANAGE_EXPORT_NS_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_MANAGE_EXPORT_NS_CDW10_SEL_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_SEL_SHIFT))
|
5135 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NS_CDW10_MOS_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_MOS_SHIFT))
5136 NVME_MANAGE_EXPORT_NS_CDW10_MOS_SHIFT,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NS_CDW10_MOS_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_MOS_SHIFT))
5137 NVME_MANAGE_EXPORT_NS_CDW10_MOS_MASK)(((__u32)(mos) & (NVME_MANAGE_EXPORT_NS_CDW10_MOS_MASK)) <<
(NVME_MANAGE_EXPORT_NS_CDW10_MOS_SHIFT))
;
5138 cmd->cdw14 = NVME_FIELD_ENCODE(esubid,(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_SHIFT))
5139 NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_SHIFT,(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_SHIFT))
5140 NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_MASK)(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NS_CDW14_ESUBID_SHIFT))
|
5141 (esubidv ? NVME_MANAGE_EXPORT_NS_CDW14_ESUBIDV : 0);
5142}
5143
5144/**
5145 * nvme_init_manage_export_ns_associate() - Initialize passthru command for
5146 * Manage Exported Namespace - Associate Namespace
5147 * @cmd: Passthru command to use
5148 * @andsf: Associate Namespace Data Structure Format (ANDSF): the bit
5149 * number in the Exported Namespace Data Structure Formats
5150 * Supported (ENDSFS) field (Identify Controller data structure)
5151 * that defines the format of @data. Bit 1 selects the format
5152 * defined by &struct nvme_associate_ns_data.
5153 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5154 * @esubid identifies the target Exported NVM Subsystem;
5155 * otherwise the target is identified by the ENSNQN field in
5156 * @data
5157 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5158 * @esubidv is set
5159 * @data: Associate Namespace data buffer, see &struct
5160 * nvme_associate_ns_data
5161 *
5162 * Initializes the passthru command buffer for the Manage Exported
5163 * Namespace command with SEL value %NVME_MANAGE_EXPORT_NS_SEL_ASSOCIATE.
5164 */
5165static inline void
5166nvme_init_manage_export_ns_associate(struct libnvme_passthru_cmd *cmd,
5167 __u8 andsf, bool_Bool esubidv, __u16 esubid,
5168 struct nvme_associate_ns_data *data)
5169{
5170 nvme_init_manage_export_ns(cmd, NVME_MANAGE_EXPORT_NS_SEL_ASSOCIATE,
5171 andsf, esubidv, esubid, data, sizeof(*data));
5172}
5173
5174/**
5175 * nvme_init_manage_export_ns_disassociate() - Initialize passthru command
5176 * for Manage Exported Namespace - Disassociate Namespace
5177 * @cmd: Passthru command to use
5178 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5179 * @esubid identifies the target Exported NVM Subsystem;
5180 * otherwise the target is identified by the ENSNQN field in
5181 * @data
5182 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5183 * @esubidv is set
5184 * @data: Disassociate Namespace data buffer, see &struct
5185 * nvme_disassociate_ns_data
5186 *
5187 * Initializes the passthru command buffer for the Manage Exported
5188 * Namespace command with SEL value
5189 * %NVME_MANAGE_EXPORT_NS_SEL_DISASSOCIATE.
5190 */
5191static inline void
5192nvme_init_manage_export_ns_disassociate(struct libnvme_passthru_cmd *cmd,
5193 bool_Bool esubidv, __u16 esubid,
5194 struct nvme_disassociate_ns_data *data)
5195{
5196 nvme_init_manage_export_ns(cmd, NVME_MANAGE_EXPORT_NS_SEL_DISASSOCIATE,
5197 0, esubidv, esubid, data, sizeof(*data));
5198}
5199
5200/**
5201 * nvme_init_manage_export_nvms_send() - Initialize passthru command for
5202 * Manage Exported NVM Subsystem Send
5203 * @cmd: Passthru command to use
5204 * @sel: Select (SEL): management operation to perform, see &enum
5205 * nvme_manage_export_nvms_send_sel
5206 * @mos: Management Operation Specific (MOS): specific to @sel
5207 * @mose: Management Operation Specific Extended (MOSE): specific to
5208 * @sel
5209 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5210 * @esubid identifies the target Exported NVM Subsystem;
5211 * otherwise the target is identified by the SUBNQN in @data
5212 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5213 * @esubidv is set
5214 * @data: Pointer to data buffer
5215 * @len: Length of @data
5216 *
5217 * Initializes the passthru command buffer for the Manage Exported NVM
5218 * Subsystem Send command.
5219 */
5220static inline void
5221nvme_init_manage_export_nvms_send(struct libnvme_passthru_cmd *cmd,
5222 __u8 sel, __u8 mos, __u16 mose, bool_Bool esubidv, __u16 esubid,
5223 void *data, __u32 len)
5224{
5225 memset(cmd, 0, sizeof(*cmd));
5226 cmd->opcode = nvme_admin_manage_export_nvms_send;
5227 cmd->data_len = len;
5228 cmd->addr = (__u64)(uintptr_t)data;
5229 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_SHIFT))
5230 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_SHIFT,(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_SHIFT))
5231 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_MASK)(((__u32)(sel) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_SEL_SHIFT))
|
5232 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_SHIFT))
5233 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_SHIFT,(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_SHIFT))
5234 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_MASK)(((__u32)(mos) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOS_SHIFT))
|
5235 NVME_FIELD_ENCODE(mose,(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_SHIFT))
5236 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_SHIFT,(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_SHIFT))
5237 NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_MASK)(((__u32)(mose) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW10_MOSE_SHIFT))
;
5238 cmd->cdw14 = NVME_FIELD_ENCODE(esubid,(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_SHIFT)
)
5239 NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_SHIFT,(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_SHIFT)
)
5240 NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_MASK)(((__u32)(esubid) & (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_MASK
)) << (NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBID_SHIFT)
)
|
5241 (esubidv ? NVME_MANAGE_EXPORT_NVMS_SEND_CDW14_ESUBIDV : 0);
5242}
5243
5244/**
5245 * nvme_init_manage_export_nvms_send_delete() - Initialize passthru command
5246 * for Manage Exported NVM Subsystem Send - Delete
5247 * @cmd: Passthru command to use
5248 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5249 * @esubid identifies the Exported NVM Subsystem to delete;
5250 * otherwise it is identified by the SUBNQN in @data
5251 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5252 * @esubidv is set
5253 * @data: Exported NVM Subsystem NQN data buffer, see &struct
5254 * nvme_exported_nvm_subsys_nqn_data. Ignored if @esubidv is set.
5255 *
5256 * Initializes the passthru command buffer for the Manage Exported NVM
5257 * Subsystem Send command with SEL value
5258 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_DELETE.
5259 */
5260static inline void
5261nvme_init_manage_export_nvms_send_delete(struct libnvme_passthru_cmd *cmd,
5262 bool_Bool esubidv, __u16 esubid,
5263 struct nvme_exported_nvm_subsys_nqn_data *data)
5264{
5265 nvme_init_manage_export_nvms_send(cmd,
5266 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_DELETE, 0, 0,
5267 esubidv, esubid,
5268 esubidv ? NULL((void*)0) : data,
5269 esubidv ? 0 : sizeof(*data));
5270}
5271
5272/**
5273 * nvme_init_manage_export_nvms_send_change_access_mode() - Initialize
5274 * passthru command for Manage Exported NVM Subsystem Send - Change Access
5275 * Mode (message-based transports only)
5276 * @cmd: Passthru command to use
5277 * @ra: Restricted Access (RA): if set, the Exported NVM Subsystem is
5278 * configured to restrict access to Host NQNs in its Allowed
5279 * Host List; if clear, unrestricted access is allowed
5280 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5281 * @esubid identifies the target Exported NVM Subsystem;
5282 * otherwise the target is identified by the SUBNQN in @data
5283 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5284 * @esubidv is set
5285 * @data: Exported NVM Subsystem NQN data buffer, see &struct
5286 * nvme_exported_nvm_subsys_nqn_data. Ignored if @esubidv is set.
5287 *
5288 * Initializes the passthru command buffer for the Manage Exported NVM
5289 * Subsystem Send command with SEL value
5290 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_CHANGE_ACCESS_MODE.
5291 */
5292static inline void
5293nvme_init_manage_export_nvms_send_change_access_mode(
5294 struct libnvme_passthru_cmd *cmd, bool_Bool ra,
5295 bool_Bool esubidv, __u16 esubid,
5296 struct nvme_exported_nvm_subsys_nqn_data *data)
5297{
5298 __u8 mos = ra ? NVME_EXPORT_NVMS_CHANGE_ACCESS_MODE_MOS_RA : 0;
5299
5300 nvme_init_manage_export_nvms_send(cmd,
5301 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_CHANGE_ACCESS_MODE, mos, 0,
5302 esubidv, esubid,
5303 esubidv ? NULL((void*)0) : data,
5304 esubidv ? 0 : sizeof(*data));
5305}
5306
5307/**
5308 * nvme_init_manage_export_nvms_send_grant_host_access() - Initialize
5309 * passthru command for Manage Exported NVM Subsystem Send - Grant Host
5310 * Access (message-based transports only)
5311 * @cmd: Passthru command to use
5312 * @data: Subsystem Management data buffer, see &struct
5313 * nvme_exported_subsys_mgmt_data
5314 * @len: Length of @data
5315 *
5316 * Initializes the passthru command buffer for the Manage Exported NVM
5317 * Subsystem Send command with SEL value
5318 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_GRANT_HOST_ACCESS. Command Dword 14
5319 * (ESUBIDV/ESUBID) is not used by this operation - the target Exported NVM
5320 * Subsystem(s) are specified in @data.
5321 */
5322static inline void
5323nvme_init_manage_export_nvms_send_grant_host_access(
5324 struct libnvme_passthru_cmd *cmd,
5325 struct nvme_exported_subsys_mgmt_data *data, __u32 len)
5326{
5327 nvme_init_manage_export_nvms_send(cmd,
5328 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_GRANT_HOST_ACCESS, 0, 0,
5329 false0, 0, data, len);
5330}
5331
5332/**
5333 * nvme_init_manage_export_nvms_send_revoke_host_access() - Initialize
5334 * passthru command for Manage Exported NVM Subsystem Send - Revoke Host
5335 * Access (message-based transports only)
5336 * @cmd: Passthru command to use
5337 * @data: Subsystem Management data buffer, see &struct
5338 * nvme_exported_subsys_mgmt_data
5339 * @len: Length of @data
5340 *
5341 * Initializes the passthru command buffer for the Manage Exported NVM
5342 * Subsystem Send command with SEL value
5343 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_REVOKE_HOST_ACCESS. Command Dword 14
5344 * (ESUBIDV/ESUBID) is not used by this operation - the target Exported NVM
5345 * Subsystem(s) are specified in @data.
5346 */
5347static inline void
5348nvme_init_manage_export_nvms_send_revoke_host_access(
5349 struct libnvme_passthru_cmd *cmd,
5350 struct nvme_exported_subsys_mgmt_data *data, __u32 len)
5351{
5352 nvme_init_manage_export_nvms_send(cmd,
5353 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_REVOKE_HOST_ACCESS, 0, 0,
5354 false0, 0, data, len);
5355}
5356
5357/**
5358 * nvme_init_manage_export_nvms_send_associate_controllers() - Initialize
5359 * passthru command for Manage Exported NVM Subsystem Send - Associate
5360 * Controllers (memory-based transports only)
5361 * @cmd: Passthru command to use
5362 * @esubid: Exported NVM Subsystem Identifier (ESUBID) of the target
5363 * Exported NVM Subsystem
5364 * @data: Associate Controllers data buffer, see &struct
5365 * nvme_exported_ctrl_assoc_data
5366 * @len: Length of @data
5367 *
5368 * Initializes the passthru command buffer for the Manage Exported NVM
5369 * Subsystem Send command with SEL value
5370 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_ASSOCIATE_CONTROLLERS.
5371 */
5372static inline void
5373nvme_init_manage_export_nvms_send_associate_controllers(
5374 struct libnvme_passthru_cmd *cmd, __u16 esubid,
5375 struct nvme_exported_ctrl_assoc_data *data, __u32 len)
5376{
5377 nvme_init_manage_export_nvms_send(cmd,
5378 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_ASSOCIATE_CONTROLLERS, 0, 0,
5379 true1, esubid, data, len);
5380}
5381
5382/**
5383 * nvme_init_manage_export_nvms_send_set_config_state() - Initialize
5384 * passthru command for Manage Exported NVM Subsystem Send - Set Exported
5385 * Configuration State
5386 * @cmd: Passthru command to use
5387 * @esubidv: Exported NVM Subsystem Identifier Valid (ESUBIDV): if set,
5388 * @esubid identifies the target Exported NVM Subsystem;
5389 * otherwise the target is identified by the SUBNQN in @data
5390 * @esubid: Exported NVM Subsystem Identifier (ESUBID), used if
5391 * @esubidv is set
5392 * @data: Exported NVM Subsystem Template specific configuration state
5393 * data buffer
5394 * @len: Length of @data
5395 *
5396 * Initializes the passthru command buffer for the Manage Exported NVM
5397 * Subsystem Send command with SEL value
5398 * %NVME_MANAGE_EXPORT_NVMS_SEND_SEL_SET_CONFIG_STATE. On failure with
5399 * status %NVME_SC_INVALID_EXPORTED_CONFIG_STATE, the location of the first
5400 * invalid bit is returned in the CQE result, see &enum
5401 * nvme_export_nvms_set_config_state_cqe_dw0.
5402 */
5403static inline void
5404nvme_init_manage_export_nvms_send_set_config_state(
5405 struct libnvme_passthru_cmd *cmd, bool_Bool esubidv, __u16 esubid,
5406 void *data, __u32 len)
5407{
5408 nvme_init_manage_export_nvms_send(cmd,
5409 NVME_MANAGE_EXPORT_NVMS_SEND_SEL_SET_CONFIG_STATE, 0, 0,
5410 esubidv, esubid, data, len);
5411 cmd->cdw15 = len ? (len - 1) / sizeof(__u32) : 0;
5412}
5413
5414/**
5415 * nvme_init_lockdown() - Initialize passthru command for Lockdown
5416 * @cmd: Passthru command to use
5417 * @scp: Scope of the command
5418 * @prhbt: Prohibit or allow the command opcode or Set Features command
5419 * @ifc: Affected interface
5420 * @ofi: Opcode or Feature Identifier
5421 * @uidx: UUID Index if controller supports this id selection method
5422 * @csel: Controller Select (CSEL): specifies the controller(s)
5423 * affected by this command, see &enum nvme_lockdown_csel
5424 * @css: Controller Select Specific (CSS): meaning is specific to
5425 * @csel (a Controller Identifier, a Primary Controller
5426 * Identifier, or vendor specific). Ignored if @csel is
5427 * %NVME_LOCKDOWN_CSEL_NVM_SUBSYSTEM.
5428 *
5429 * Initializes the passthru command buffer for the Lockdown command.
5430 */
5431static inline void
5432nvme_init_lockdown(struct libnvme_passthru_cmd *cmd, __u8 scp, __u8 prhbt,
5433 __u8 ifc, __u8 ofi, __u8 uidx, __u8 csel, __u16 css)
5434{
5435 memset(cmd, 0, sizeof(*cmd));
5436
5437 cmd->opcode = nvme_admin_lockdown;
5438 cmd->cdw10 = NVME_FIELD_ENCODE(ofi,(((__u32)(ofi) & (NVME_LOCKDOWN_CDW10_OFI_MASK)) <<
(NVME_LOCKDOWN_CDW10_OFI_SHIFT))
5439 NVME_LOCKDOWN_CDW10_OFI_SHIFT,(((__u32)(ofi) & (NVME_LOCKDOWN_CDW10_OFI_MASK)) <<
(NVME_LOCKDOWN_CDW10_OFI_SHIFT))
5440 NVME_LOCKDOWN_CDW10_OFI_MASK)(((__u32)(ofi) & (NVME_LOCKDOWN_CDW10_OFI_MASK)) <<
(NVME_LOCKDOWN_CDW10_OFI_SHIFT))
|
5441 NVME_FIELD_ENCODE(ifc,(((__u32)(ifc) & (NVME_LOCKDOWN_CDW10_IFC_MASK)) <<
(NVME_LOCKDOWN_CDW10_IFC_SHIFT))
5442 NVME_LOCKDOWN_CDW10_IFC_SHIFT,(((__u32)(ifc) & (NVME_LOCKDOWN_CDW10_IFC_MASK)) <<
(NVME_LOCKDOWN_CDW10_IFC_SHIFT))
5443 NVME_LOCKDOWN_CDW10_IFC_MASK)(((__u32)(ifc) & (NVME_LOCKDOWN_CDW10_IFC_MASK)) <<
(NVME_LOCKDOWN_CDW10_IFC_SHIFT))
|
5444 NVME_FIELD_ENCODE(prhbt,(((__u32)(prhbt) & (NVME_LOCKDOWN_CDW10_PRHBT_MASK)) <<
(NVME_LOCKDOWN_CDW10_PRHBT_SHIFT))
5445 NVME_LOCKDOWN_CDW10_PRHBT_SHIFT,(((__u32)(prhbt) & (NVME_LOCKDOWN_CDW10_PRHBT_MASK)) <<
(NVME_LOCKDOWN_CDW10_PRHBT_SHIFT))
5446 NVME_LOCKDOWN_CDW10_PRHBT_MASK)(((__u32)(prhbt) & (NVME_LOCKDOWN_CDW10_PRHBT_MASK)) <<
(NVME_LOCKDOWN_CDW10_PRHBT_SHIFT))
|
5447 NVME_FIELD_ENCODE(scp,(((__u32)(scp) & (NVME_LOCKDOWN_CDW10_SCP_MASK)) <<
(NVME_LOCKDOWN_CDW10_SCP_SHIFT))
5448 NVME_LOCKDOWN_CDW10_SCP_SHIFT,(((__u32)(scp) & (NVME_LOCKDOWN_CDW10_SCP_MASK)) <<
(NVME_LOCKDOWN_CDW10_SCP_SHIFT))
5449 NVME_LOCKDOWN_CDW10_SCP_MASK)(((__u32)(scp) & (NVME_LOCKDOWN_CDW10_SCP_MASK)) <<
(NVME_LOCKDOWN_CDW10_SCP_SHIFT))
|
5450 NVME_FIELD_ENCODE(csel,(((__u32)(csel) & (NVME_LOCKDOWN_CDW10_CSEL_MASK)) <<
(NVME_LOCKDOWN_CDW10_CSEL_SHIFT))
5451 NVME_LOCKDOWN_CDW10_CSEL_SHIFT,(((__u32)(csel) & (NVME_LOCKDOWN_CDW10_CSEL_MASK)) <<
(NVME_LOCKDOWN_CDW10_CSEL_SHIFT))
5452 NVME_LOCKDOWN_CDW10_CSEL_MASK)(((__u32)(csel) & (NVME_LOCKDOWN_CDW10_CSEL_MASK)) <<
(NVME_LOCKDOWN_CDW10_CSEL_SHIFT))
;
5453 cmd->cdw14 = NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_LOCKDOWN_CDW14_UIDX_MASK)) <<
(NVME_LOCKDOWN_CDW14_UIDX_SHIFT))
5454 NVME_LOCKDOWN_CDW14_UIDX_SHIFT,(((__u32)(uidx) & (NVME_LOCKDOWN_CDW14_UIDX_MASK)) <<
(NVME_LOCKDOWN_CDW14_UIDX_SHIFT))
5455 NVME_LOCKDOWN_CDW14_UIDX_MASK)(((__u32)(uidx) & (NVME_LOCKDOWN_CDW14_UIDX_MASK)) <<
(NVME_LOCKDOWN_CDW14_UIDX_SHIFT))
|
5456 NVME_FIELD_ENCODE(css,(((__u32)(css) & (NVME_LOCKDOWN_CDW14_CSS_MASK)) <<
(NVME_LOCKDOWN_CDW14_CSS_SHIFT))
5457 NVME_LOCKDOWN_CDW14_CSS_SHIFT,(((__u32)(css) & (NVME_LOCKDOWN_CDW14_CSS_MASK)) <<
(NVME_LOCKDOWN_CDW14_CSS_SHIFT))
5458 NVME_LOCKDOWN_CDW14_CSS_MASK)(((__u32)(css) & (NVME_LOCKDOWN_CDW14_CSS_MASK)) <<
(NVME_LOCKDOWN_CDW14_CSS_SHIFT))
;
5459}
5460
5461/**
5462 * nvme_init_lm_track_send() - Initialize passthru command for
5463 * Track Send command
5464 * @cmd: Passthru command to use
5465 * @sel: Select (SEL): This field specifies the type of
5466 * management operation to perform
5467 * @mos: Management Operation Specific (MOS): This field
5468 * is specific to the SEL type. For the Track Memory Changes
5469 * operation, see &enum nvme_lm_tact for the Tracking Action
5470 * (TACT) bit.
5471 * @cdqid: Controller Data Queue ID (CDQID) for the Log User Data Changes
5472 * operation, or Controller Identifier (CNTLID) for the Track
5473 * Memory Changes operation
5474 * @data: Track Memory Changes data buffer, see &struct
5475 * nvme_lm_track_memory_changes_data. Only used for the Track
5476 * Memory Changes operation with TACT set to
5477 * %NVME_LM_TACT_START_TRACKING, otherwise NULL.
5478 * @len: Length of @data
5479 *
5480 * Initializes the passthru command buffer for the Track Send command.
5481 */
5482static inline void
5483nvme_init_lm_track_send(struct libnvme_passthru_cmd *cmd,
5484 __u8 sel, __u16 mos, __u16 cdqid, void *data, __u32 len)
5485{
5486
5487 memset(cmd, 0, sizeof(*cmd));
5488 cmd->opcode = nvme_admin_track_send;
5489 cmd->data_len = len;
5490 cmd->addr = (__u64)(uintptr_t)data;
5491 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_LM_TRACK_SEND_SEL_MASK)) << (
NVME_LM_TRACK_SEND_SEL_SHIFT))
5492 NVME_LM_TRACK_SEND_SEL_SHIFT,(((__u32)(sel) & (NVME_LM_TRACK_SEND_SEL_MASK)) << (
NVME_LM_TRACK_SEND_SEL_SHIFT))
5493 NVME_LM_TRACK_SEND_SEL_MASK)(((__u32)(sel) & (NVME_LM_TRACK_SEND_SEL_MASK)) << (
NVME_LM_TRACK_SEND_SEL_SHIFT))
|
5494 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_LM_TRACK_SEND_MOS_MASK)) << (
NVME_LM_TRACK_SEND_MOS_SHIFT))
5495 NVME_LM_TRACK_SEND_MOS_SHIFT,(((__u32)(mos) & (NVME_LM_TRACK_SEND_MOS_MASK)) << (
NVME_LM_TRACK_SEND_MOS_SHIFT))
5496 NVME_LM_TRACK_SEND_MOS_MASK)(((__u32)(mos) & (NVME_LM_TRACK_SEND_MOS_MASK)) << (
NVME_LM_TRACK_SEND_MOS_SHIFT))
;
5497 cmd->cdw11 = cdqid;
5498}
5499
5500/**
5501 * nvme_init_lm_track_receive() - Initialize passthru command for
5502 * Track Receive command
5503 * @cmd: Passthru command to use
5504 * @sel: Select (SEL): This field specifies the type of management
5505 * operation to perform.
5506 * @cntlid: Controller Identifier (CNTLID): Specifies the identifier of
5507 * the controller for which the tracked memory changes, if any,
5508 * are to be returned. Used by the Tracked Memory Changes
5509 * management operation.
5510 * @data: Pointer to data buffer
5511 * @len: Length of @data
5512 *
5513 * Initializes the passthru command buffer for the Track Receive command.
5514 */
5515static inline void
5516nvme_init_lm_track_receive(struct libnvme_passthru_cmd *cmd,
5517 __u8 sel, __u16 cntlid, void *data, __u32 len)
5518{
5519 memset(cmd, 0, sizeof(*cmd));
5520 cmd->opcode = nvme_admin_track_receive;
5521 cmd->addr = (__u64)(uintptr_t)data;
5522 cmd->data_len = len;
5523 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_LM_TRACK_RECV_SEL_MASK)) << (
NVME_LM_TRACK_RECV_SEL_SHIFT))
5524 NVME_LM_TRACK_RECV_SEL_SHIFT,(((__u32)(sel) & (NVME_LM_TRACK_RECV_SEL_MASK)) << (
NVME_LM_TRACK_RECV_SEL_SHIFT))
5525 NVME_LM_TRACK_RECV_SEL_MASK)(((__u32)(sel) & (NVME_LM_TRACK_RECV_SEL_MASK)) << (
NVME_LM_TRACK_RECV_SEL_SHIFT))
;
5526 cmd->cdw11 = NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_MASK
)) << (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_SHIFT))
5527 NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_MASK
)) << (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_SHIFT))
5528 NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_MASK
)) << (NVME_LM_TRACKED_MEMORY_CHANGES_CNTLID_SHIFT))
;
5529 cmd->cdw12 = len ? (__u32)((len - 1) / sizeof(__u32)) : 0;
5530}
5531
5532/**
5533 * nvme_init_lm_migration_send() - Initialize passthru command for
5534 * Migration Send command
5535 * @cmd: Passthru command to use
5536 * @sel: Select (SEL): This field specifies the type of management
5537 * operation to perform.
5538 * @mos: Management Operation Specific (MOS): This field is specific
5539 * to the SEL type
5540 * @cntlid: Controller ID: This field specifies the identifier of the
5541 * controller to which the operation is performed.
5542 * @stype: Suspend Type (STYPE): This field specifies the type of suspend.
5543 * @dudmq: Delete User Data Migration Queue (DUDMQ): If set, the migration
5544 * queue is deleted is deleted as part of the Suspend operation.
5545 * @csvi: Controller State Version Index (CSVI)
5546 * @csuuidi: Controller State UUID Index (CSUUIDI)
5547 * @cso: Offset: This field specifies the offset, in bytes, within
5548 * the data available to be returned and specifies the starting
5549 * point for that data for what is actually returned to the host.
5550 * @uidx: UUID Index (UIDX)
5551 * @data: Pointer to data buffer
5552 * @len: Length of @data
5553 *
5554 * Initializes the passthru command buffer for the Migration Send command.
5555 */
5556static inline void
5557nvme_init_lm_migration_send(struct libnvme_passthru_cmd *cmd,
5558 __u16 sel, __u16 mos, __u16 cntlid, __u8 stype, bool_Bool dudmq,
5559 __u8 csvi, __u16 csuuidi, __u64 cso, __u8 uidx,
5560 void *data, __u32 len)
5561{
5562 __u32 cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_LM_MIGRATION_SEND_SEL_MASK)) <<
(NVME_LM_MIGRATION_SEND_SEL_SHIFT))
5563 NVME_LM_MIGRATION_SEND_SEL_SHIFT,(((__u32)(sel) & (NVME_LM_MIGRATION_SEND_SEL_MASK)) <<
(NVME_LM_MIGRATION_SEND_SEL_SHIFT))
5564 NVME_LM_MIGRATION_SEND_SEL_MASK)(((__u32)(sel) & (NVME_LM_MIGRATION_SEND_SEL_MASK)) <<
(NVME_LM_MIGRATION_SEND_SEL_SHIFT))
|
5565 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_LM_MIGRATION_SEND_MOS_MASK)) <<
(NVME_LM_MIGRATION_SEND_MOS_SHIFT))
5566 NVME_LM_MIGRATION_SEND_MOS_SHIFT,(((__u32)(mos) & (NVME_LM_MIGRATION_SEND_MOS_MASK)) <<
(NVME_LM_MIGRATION_SEND_MOS_SHIFT))
5567 NVME_LM_MIGRATION_SEND_MOS_MASK)(((__u32)(mos) & (NVME_LM_MIGRATION_SEND_MOS_MASK)) <<
(NVME_LM_MIGRATION_SEND_MOS_SHIFT))
;
5568 __u32 cdw11 = 0;
5569 __u32 cdw14 = NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_LM_MIGRATION_SEND_UIDX_MASK)) <<
(NVME_LM_MIGRATION_SEND_UIDX_SHIFT))
5570 NVME_LM_MIGRATION_SEND_UIDX_SHIFT,(((__u32)(uidx) & (NVME_LM_MIGRATION_SEND_UIDX_MASK)) <<
(NVME_LM_MIGRATION_SEND_UIDX_SHIFT))
5571 NVME_LM_MIGRATION_SEND_UIDX_MASK)(((__u32)(uidx) & (NVME_LM_MIGRATION_SEND_UIDX_MASK)) <<
(NVME_LM_MIGRATION_SEND_UIDX_SHIFT))
;
5572
5573 if (sel == NVME_LM_SEL_SUSPEND) {
5574 cdw11 = NVME_FIELD_ENCODE(stype,(((__u32)(stype) & (NVME_LM_STYPE_MASK)) << (NVME_LM_STYPE_SHIFT
))
5575 NVME_LM_STYPE_SHIFT,(((__u32)(stype) & (NVME_LM_STYPE_MASK)) << (NVME_LM_STYPE_SHIFT
))
5576 NVME_LM_STYPE_MASK)(((__u32)(stype) & (NVME_LM_STYPE_MASK)) << (NVME_LM_STYPE_SHIFT
))
|
5577 NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_SUSPEND_CNTLID_MASK)) <<
(NVME_LM_SUSPEND_CNTLID_SHIFT))
5578 NVME_LM_SUSPEND_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_SUSPEND_CNTLID_MASK)) <<
(NVME_LM_SUSPEND_CNTLID_SHIFT))
5579 NVME_LM_SUSPEND_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_SUSPEND_CNTLID_MASK)) <<
(NVME_LM_SUSPEND_CNTLID_SHIFT))
;
5580 if (dudmq)
5581 cdw11 |= NVME_LM_DUDMQ;
5582 } else if (sel == NVME_LM_SEL_RESUME) {
5583 cdw11 = NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_RESUME_CNTLID_MASK)) <<
(NVME_LM_RESUME_CNTLID_SHIFT))
5584 NVME_LM_RESUME_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_RESUME_CNTLID_MASK)) <<
(NVME_LM_RESUME_CNTLID_SHIFT))
5585 NVME_LM_RESUME_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_RESUME_CNTLID_MASK)) <<
(NVME_LM_RESUME_CNTLID_SHIFT))
;
5586 } else if (sel == NVME_LM_SEL_SET_CONTROLLER_STATE) {
5587 cdw11 = NVME_FIELD_ENCODE(csuuidi,(((__u32)(csuuidi) & (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT))
5588 NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT,(((__u32)(csuuidi) & (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT))
5589 NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK)(((__u32)(csuuidi) & (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT))
|
5590 NVME_FIELD_ENCODE(csvi,(((__u32)(csvi) & (NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT))
5591 NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT,(((__u32)(csvi) & (NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT))
5592 NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK)(((__u32)(csvi) & (NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT))
|
5593 NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT))
5594 NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT))
5595 NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT))
;
5596 }
5597
5598 memset(cmd, 0, sizeof(*cmd));
5599
5600 cmd->opcode = nvme_admin_migration_send;
5601 cmd->data_len = len;
5602 cmd->addr = (__u64)(uintptr_t)data;
5603 cmd->cdw10 = cdw10;
5604 cmd->cdw11 = cdw11;
5605 cmd->cdw12 = (__u32)cso;
5606 cmd->cdw13 = (__u32)(cso >> 32);
5607 cmd->cdw14 = cdw14;
5608 cmd->cdw15 = len / sizeof(__u32);
5609}
5610
5611/**
5612 * nvme_init_lm_migration_recv() - Initialize passthru command for
5613 * Migration Receive command
5614 * @cmd: Passthru command to use
5615 * @offset: Offset: This field specifies the offset, in bytes, within
5616 * the data available to be returned and specifies the starting
5617 * point for that data for what is actually returned to the host.
5618 * @mos: Management Operation Specific (MOS): This field is specific to
5619 * the SEL type
5620 * @cntlid: Controller ID: This field specifies the identifier of the
5621 * controller to which the operation is performed.
5622 * @csuuidi: Controller State UUID Index (CSUUIDI)
5623 * @sel: Select (SEL): This field specifies the type of management
5624 * operation to perform
5625 * @uidx: UUID Index (UIDX)
5626 * @csuidxp: Controller State UUID Index Parameter (CSUIDXP)
5627 * @data: Pointer to data buffer
5628 * @len: Length of @data
5629 *
5630 * Initializes the passthru command buffer for the Migration Receive command.
5631 */
5632static inline void
5633nvme_init_lm_migration_recv(struct libnvme_passthru_cmd *cmd,
5634 __u64 offset, __u16 mos, __u16 cntlid, __u16 csuuidi, __u8 sel,
5635 __u8 uidx, __u8 csuidxp, void *data, __u32 len)
5636{
5637 __u32 cdw11 = 0;
5638 __u32 data_len = 0;
5639
5640 if (sel == NVME_LM_SEL_GET_CONTROLLER_STATE) {
5641 cdw11 = NVME_FIELD_ENCODE(csuidxp,(((__u32)(csuidxp) & (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT))
5642 NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT,(((__u32)(csuidxp) & (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT))
5643 NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK)(((__u32)(csuidxp) & (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT))
|
5644 NVME_FIELD_ENCODE(csuuidi,(((__u32)(csuuidi) & (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT))
5645 NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT,(((__u32)(csuuidi) & (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT))
5646 NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK)(((__u32)(csuuidi) & (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT))
|
5647 NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT))
5648 NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT))
5649 NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK
)) << (NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT))
;
5650 data_len = len;
5651 }
5652
5653 memset(cmd, 0, sizeof(*cmd));
5654
5655 cmd->opcode = nvme_admin_migration_receive;
5656 cmd->data_len = data_len;
5657 cmd->addr = (__u64)(uintptr_t)data;
5658 cmd->cdw10 = NVME_FIELD_ENCODE(sel,(((__u32)(sel) & (NVME_LM_MIGRATION_RECV_SEL_MASK)) <<
(NVME_LM_MIGRATION_RECV_SEL_SHIFT))
5659 NVME_LM_MIGRATION_RECV_SEL_SHIFT,(((__u32)(sel) & (NVME_LM_MIGRATION_RECV_SEL_MASK)) <<
(NVME_LM_MIGRATION_RECV_SEL_SHIFT))
5660 NVME_LM_MIGRATION_RECV_SEL_MASK)(((__u32)(sel) & (NVME_LM_MIGRATION_RECV_SEL_MASK)) <<
(NVME_LM_MIGRATION_RECV_SEL_SHIFT))
|
5661 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_LM_MIGRATION_RECV_MOS_MASK)) <<
(NVME_LM_MIGRATION_RECV_MOS_SHIFT))
5662 NVME_LM_MIGRATION_RECV_MOS_SHIFT,(((__u32)(mos) & (NVME_LM_MIGRATION_RECV_MOS_MASK)) <<
(NVME_LM_MIGRATION_RECV_MOS_SHIFT))
5663 NVME_LM_MIGRATION_RECV_MOS_MASK)(((__u32)(mos) & (NVME_LM_MIGRATION_RECV_MOS_MASK)) <<
(NVME_LM_MIGRATION_RECV_MOS_SHIFT))
;
5664 cmd->cdw11 = cdw11;
5665 cmd->cdw12 = (__u32)offset;
5666 cmd->cdw13 = (__u32)(offset >> 32);
5667 cmd->cdw14 = NVME_FIELD_ENCODE(uidx,(((__u32)(uidx) & (NVME_LM_MIGRATION_RECV_UIDX_MASK)) <<
(NVME_LM_MIGRATION_RECV_UIDX_SHIFT))
5668 NVME_LM_MIGRATION_RECV_UIDX_SHIFT,(((__u32)(uidx) & (NVME_LM_MIGRATION_RECV_UIDX_MASK)) <<
(NVME_LM_MIGRATION_RECV_UIDX_SHIFT))
5669 NVME_LM_MIGRATION_RECV_UIDX_MASK)(((__u32)(uidx) & (NVME_LM_MIGRATION_RECV_UIDX_MASK)) <<
(NVME_LM_MIGRATION_RECV_UIDX_SHIFT))
;
5670 cmd->cdw15 = len ? (__u32)((len - 1) / sizeof(__u32)) : 0;
5671}
5672
5673/**
5674 * nvme_init_lm_cdq_create() - Initialize passthru command for
5675 * Controller Data Queue create - Controller Data Queue command
5676 * @cmd: Passthru command to use
5677 * @mos: Management Operation Specific (MOS): This field is
5678 * specific to the SEL type
5679 * @cntlid: Controller ID: For Create CDQ, specifies the target
5680 * migratable controller
5681 * @cdqsize: For Create CDQ, specifies the size of CDQ, in dwords - 4 byte
5682 * @data: Pointer to data buffer
5683 *
5684 * Initializes the passthru command buffer for the Controller Data Queue
5685 * command. Note: The result CDQID is returned in the CQE dword0, which the
5686 * submission function must handle.
5687 */
5688static inline void
5689nvme_init_lm_cdq_create(struct libnvme_passthru_cmd *cmd,
5690 __u16 mos, __u16 cntlid, __u32 cdqsize, void *data)
5691{
5692 __u16 cqs;
5693
5694 memset(cmd, 0, sizeof(*cmd));
5695
5696 cqs = NVME_FIELD_ENCODE(cntlid,(((__u32)(cntlid) & (NVME_LM_CREATE_CDQ_CNTLID_MASK)) <<
(NVME_LM_CREATE_CDQ_CNTLID_SHIFT))
5697 NVME_LM_CREATE_CDQ_CNTLID_SHIFT,(((__u32)(cntlid) & (NVME_LM_CREATE_CDQ_CNTLID_MASK)) <<
(NVME_LM_CREATE_CDQ_CNTLID_SHIFT))
5698 NVME_LM_CREATE_CDQ_CNTLID_MASK)(((__u32)(cntlid) & (NVME_LM_CREATE_CDQ_CNTLID_MASK)) <<
(NVME_LM_CREATE_CDQ_CNTLID_SHIFT))
;
5699
5700 cmd->opcode = nvme_admin_ctrl_data_queue;
5701 cmd->data_len = cdqsize << 2;
5702 cmd->addr = (__u64)(uintptr_t)data;
5703 cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_CREATE_CDQ,(((__u32)(NVME_LM_SEL_CREATE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
5704 NVME_LM_CDQ_SEL_SHIFT,(((__u32)(NVME_LM_SEL_CREATE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
5705 NVME_LM_CDQ_SEL_MASK)(((__u32)(NVME_LM_SEL_CREATE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
|
5706 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
5707 NVME_LM_CDQ_MOS_SHIFT,(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
5708 NVME_LM_CDQ_MOS_MASK)(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
;
5709 cmd->cdw11 = NVME_FIELD_ENCODE(NVME_LM_CREATE_CDQ_PC,(((__u32)(NVME_LM_CREATE_CDQ_PC) & (NVME_LM_CREATE_CDQ_PC_MASK
)) << (NVME_LM_CREATE_CDQ_PC_SHIFT))
5710 NVME_LM_CREATE_CDQ_PC_SHIFT,(((__u32)(NVME_LM_CREATE_CDQ_PC) & (NVME_LM_CREATE_CDQ_PC_MASK
)) << (NVME_LM_CREATE_CDQ_PC_SHIFT))
5711 NVME_LM_CREATE_CDQ_PC_MASK)(((__u32)(NVME_LM_CREATE_CDQ_PC) & (NVME_LM_CREATE_CDQ_PC_MASK
)) << (NVME_LM_CREATE_CDQ_PC_SHIFT))
|
5712 NVME_FIELD_ENCODE(cqs,(((__u32)(cqs) & (NVME_LM_CQS_MASK)) << (NVME_LM_CQS_SHIFT
))
5713 NVME_LM_CQS_SHIFT,(((__u32)(cqs) & (NVME_LM_CQS_MASK)) << (NVME_LM_CQS_SHIFT
))
5714 NVME_LM_CQS_MASK)(((__u32)(cqs) & (NVME_LM_CQS_MASK)) << (NVME_LM_CQS_SHIFT
))
;
5715 cmd->cdw12 = cdqsize;
5716}
5717
5718/**
5719 * nvme_init_lm_cdq_delete() - Initialize passthru command for
5720 * Controller Data Queue delete - Controller Data Queue command
5721 * @cmd: Passthru command to use
5722 * @mos: Management Operation Specific (MOS): This field is
5723 * specific to the SEL type
5724 * @cdqid: Controller Data Queue ID (CDQID): For Delete CDQ, this
5725 * field is the CDQID to delete.
5726 *
5727 * Initializes the passthru command buffer for the Controller Data Queue delete
5728 * command.
5729 */
5730static inline void
5731nvme_init_lm_cdq_delete(struct libnvme_passthru_cmd *cmd,
5732 __u16 mos, __u16 cdqid)
5733{
5734 memset(cmd, 0, sizeof(*cmd));
5735
5736 cmd->opcode = nvme_admin_ctrl_data_queue;
5737 cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_DELETE_CDQ,(((__u32)(NVME_LM_SEL_DELETE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
5738 NVME_LM_CDQ_SEL_SHIFT,(((__u32)(NVME_LM_SEL_DELETE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
5739 NVME_LM_CDQ_SEL_MASK)(((__u32)(NVME_LM_SEL_DELETE_CDQ) & (NVME_LM_CDQ_SEL_MASK
)) << (NVME_LM_CDQ_SEL_SHIFT))
|
5740 NVME_FIELD_ENCODE(mos,(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
5741 NVME_LM_CDQ_MOS_SHIFT,(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
5742 NVME_LM_CDQ_MOS_MASK)(((__u32)(mos) & (NVME_LM_CDQ_MOS_MASK)) << (NVME_LM_CDQ_MOS_SHIFT
))
;
5743 cmd->cdw11 = NVME_FIELD_ENCODE(cdqid,(((__u32)(cdqid) & (NVME_LM_DELETE_CDQ_CDQID_MASK)) <<
(NVME_LM_DELETE_CDQ_CDQID_SHIFT))
5744 NVME_LM_DELETE_CDQ_CDQID_SHIFT,(((__u32)(cdqid) & (NVME_LM_DELETE_CDQ_CDQID_MASK)) <<
(NVME_LM_DELETE_CDQ_CDQID_SHIFT))
5745 NVME_LM_DELETE_CDQ_CDQID_MASK)(((__u32)(cdqid) & (NVME_LM_DELETE_CDQ_CDQID_MASK)) <<
(NVME_LM_DELETE_CDQ_CDQID_SHIFT))
;
5746}
5747
5748/**
5749 * nvme_init_format_nvm() - Initialize passthru command for Format NVM
5750 * @cmd: Passthru command to use
5751 * @nsid: Namespace ID to format
5752 * @lbaf: Logical block address format
5753 * @mset: Metadata settings (extended or separated)
5754 * @pi: Protection information type
5755 * @pil: Protection information location (beginning or end)
5756 * @ses: Secure erase settings
5757 *
5758 * Initializes the passthru command buffer for the Format NVM command.
5759 */
5760static inline void
5761nvme_init_format_nvm(struct libnvme_passthru_cmd *cmd, __u32 nsid, __u8 lbaf,
5762 enum nvme_cmd_format_mset mset, enum nvme_cmd_format_pi pi,
5763 enum nvme_cmd_format_pil pil, enum nvme_cmd_format_ses ses)
5764{
5765 memset(cmd, 0, sizeof(*cmd));
5766
5767 cmd->opcode = nvme_admin_format_nvm;
5768 cmd->nsid = nsid;
5769 cmd->cdw10 = NVME_FIELD_ENCODE(lbaf,(((__u32)(lbaf) & (NVME_FORMAT_CDW10_LBAFL_MASK)) <<
(NVME_FORMAT_CDW10_LBAFL_SHIFT))
5770 NVME_FORMAT_CDW10_LBAFL_SHIFT,(((__u32)(lbaf) & (NVME_FORMAT_CDW10_LBAFL_MASK)) <<
(NVME_FORMAT_CDW10_LBAFL_SHIFT))
5771 NVME_FORMAT_CDW10_LBAFL_MASK)(((__u32)(lbaf) & (NVME_FORMAT_CDW10_LBAFL_MASK)) <<
(NVME_FORMAT_CDW10_LBAFL_SHIFT))
|
5772 NVME_FIELD_ENCODE(mset,(((__u32)(mset) & (NVME_FORMAT_CDW10_MSET_MASK)) <<
(NVME_FORMAT_CDW10_MSET_SHIFT))
5773 NVME_FORMAT_CDW10_MSET_SHIFT,(((__u32)(mset) & (NVME_FORMAT_CDW10_MSET_MASK)) <<
(NVME_FORMAT_CDW10_MSET_SHIFT))
5774 NVME_FORMAT_CDW10_MSET_MASK)(((__u32)(mset) & (NVME_FORMAT_CDW10_MSET_MASK)) <<
(NVME_FORMAT_CDW10_MSET_SHIFT))
|
5775 NVME_FIELD_ENCODE(pi,(((__u32)(pi) & (NVME_FORMAT_CDW10_PI_MASK)) << (NVME_FORMAT_CDW10_PI_SHIFT
))
5776 NVME_FORMAT_CDW10_PI_SHIFT,(((__u32)(pi) & (NVME_FORMAT_CDW10_PI_MASK)) << (NVME_FORMAT_CDW10_PI_SHIFT
))
5777 NVME_FORMAT_CDW10_PI_MASK)(((__u32)(pi) & (NVME_FORMAT_CDW10_PI_MASK)) << (NVME_FORMAT_CDW10_PI_SHIFT
))
|
5778 NVME_FIELD_ENCODE(pil,(((__u32)(pil) & (NVME_FORMAT_CDW10_PIL_MASK)) << (
NVME_FORMAT_CDW10_PIL_SHIFT))
5779 NVME_FORMAT_CDW10_PIL_SHIFT,(((__u32)(pil) & (NVME_FORMAT_CDW10_PIL_MASK)) << (
NVME_FORMAT_CDW10_PIL_SHIFT))
5780 NVME_FORMAT_CDW10_PIL_MASK)(((__u32)(pil) & (NVME_FORMAT_CDW10_PIL_MASK)) << (
NVME_FORMAT_CDW10_PIL_SHIFT))
|
5781 NVME_FIELD_ENCODE(ses,(((__u32)(ses) & (NVME_FORMAT_CDW10_SES_MASK)) << (
NVME_FORMAT_CDW10_SES_SHIFT))
5782 NVME_FORMAT_CDW10_SES_SHIFT,(((__u32)(ses) & (NVME_FORMAT_CDW10_SES_MASK)) << (
NVME_FORMAT_CDW10_SES_SHIFT))
5783 NVME_FORMAT_CDW10_SES_MASK)(((__u32)(ses) & (NVME_FORMAT_CDW10_SES_MASK)) << (
NVME_FORMAT_CDW10_SES_SHIFT))
|
5784 NVME_FIELD_ENCODE((lbaf >> 4),(((__u32)((lbaf >> 4)) & (NVME_FORMAT_CDW10_LBAFU_MASK
)) << (NVME_FORMAT_CDW10_LBAFU_SHIFT))
5785 NVME_FORMAT_CDW10_LBAFU_SHIFT,(((__u32)((lbaf >> 4)) & (NVME_FORMAT_CDW10_LBAFU_MASK
)) << (NVME_FORMAT_CDW10_LBAFU_SHIFT))
5786 NVME_FORMAT_CDW10_LBAFU_MASK)(((__u32)((lbaf >> 4)) & (NVME_FORMAT_CDW10_LBAFU_MASK
)) << (NVME_FORMAT_CDW10_LBAFU_SHIFT))
;
5787}
5788
5789/**
5790 * nvme_init_security_send() - Initialize passthru command for Security Send
5791 * @cmd: Passthru command to use
5792 * @nsid: Namespace ID to issue security command on
5793 * @nssf: NVMe Security Specific field
5794 * @spsp: Security Protocol Specific field
5795 * @secp: Security Protocol
5796 * @tl: Protocol specific transfer length
5797 * @data: Security data payload buffer to send
5798 * @len: Data length of the payload in bytes
5799 *
5800 * Initializes the passthru command buffer for the Security Send command.
5801 */
5802static inline void
5803nvme_init_security_send(struct libnvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf,
5804 __u16 spsp, __u8 secp, __u32 tl, void *data, __u32 len)
5805{
5806 memset(cmd, 0, sizeof(*cmd));
5807
5808 cmd->opcode = nvme_admin_security_send;
5809 cmd->nsid = nsid;
5810 cmd->data_len = len;
5811 cmd->addr = (__u64)(uintptr_t)data;
5812 cmd->cdw10 = NVME_FIELD_ENCODE(secp,(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
5813 NVME_SECURITY_SECP_SHIFT,(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
5814 NVME_SECURITY_SECP_MASK)(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
|
5815 NVME_FIELD_ENCODE(spsp,(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
5816 NVME_SECURITY_SPSP0_SHIFT,(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
5817 NVME_SECURITY_SPSP0_MASK)(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
|
5818 NVME_FIELD_ENCODE(spsp >> 8,(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
5819 NVME_SECURITY_SPSP1_SHIFT,(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
5820 NVME_SECURITY_SPSP1_MASK)(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
|
5821 NVME_FIELD_ENCODE(nssf,(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
5822 NVME_SECURITY_NSSF_SHIFT,(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
5823 NVME_SECURITY_NSSF_MASK)(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
;
5824 cmd->cdw11 = tl;
5825}
5826
5827/**
5828 * nvme_init_security_receive() - Initialize passthru command for
5829 * Security Receive
5830 * @cmd: Passthru command to use
5831 * @nsid: Namespace ID to issue security command on
5832 * @nssf: NVMe Security Specific field
5833 * @spsp: Security Protocol Specific field
5834 * @secp: Security Protocol
5835 * @al: Protocol specific allocation length
5836 * @data: Security data payload buffer to receive data into
5837 * @len: Data length of the payload in bytes (must match @al)
5838 *
5839 * Initializes the passthru command buffer for the Security Receive command.
5840 */
5841static inline void
5842nvme_init_security_receive(struct libnvme_passthru_cmd *cmd, __u32 nsid,
5843 __u8 nssf, __u16 spsp, __u8 secp, __u32 al, void *data,
5844 __u32 len)
5845{
5846 memset(cmd, 0, sizeof(*cmd));
5847
5848 cmd->opcode = nvme_admin_security_recv;
5849 cmd->nsid = nsid;
5850 cmd->data_len = len;
5851 cmd->addr = (__u64)(uintptr_t)data;
5852 cmd->cdw10 = NVME_FIELD_ENCODE(secp,(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
5853 NVME_SECURITY_SECP_SHIFT,(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
5854 NVME_SECURITY_SECP_MASK)(((__u32)(secp) & (NVME_SECURITY_SECP_MASK)) << (NVME_SECURITY_SECP_SHIFT
))
|
5855 NVME_FIELD_ENCODE(spsp,(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
5856 NVME_SECURITY_SPSP0_SHIFT,(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
5857 NVME_SECURITY_SPSP0_MASK)(((__u32)(spsp) & (NVME_SECURITY_SPSP0_MASK)) << (NVME_SECURITY_SPSP0_SHIFT
))
|
5858 NVME_FIELD_ENCODE(spsp >> 8,(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
5859 NVME_SECURITY_SPSP1_SHIFT,(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
5860 NVME_SECURITY_SPSP1_MASK)(((__u32)(spsp >> 8) & (NVME_SECURITY_SPSP1_MASK)) <<
(NVME_SECURITY_SPSP1_SHIFT))
|
5861 NVME_FIELD_ENCODE(nssf,(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
5862 NVME_SECURITY_NSSF_SHIFT,(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
5863 NVME_SECURITY_NSSF_MASK)(((__u32)(nssf) & (NVME_SECURITY_NSSF_MASK)) << (NVME_SECURITY_NSSF_SHIFT
))
;
5864 cmd->cdw11 = al;
5865}
5866
5867/**
5868 * nvme_init_sanitize_nvm() - Initialize passthru command to start a
5869 * sanitize operation
5870 * @cmd: Passthru command to use
5871 * @sanact: Sanitize action, see &enum nvme_sanitize_sanact
5872 * @ause: Set to allow unrestricted sanitize exit
5873 * @owpass: Overwrite pass count
5874 * @oipbp: Set to overwrite invert pattern between passes
5875 * @ndas: Set to not deallocate blocks after sanitizing
5876 * @emvs: Set to enter media verification state
5877 * @preq: Set to require the sanitize operation to purge user data, as
5878 * defined by IEEE Std 2883, or fail
5879 * @ovrpat: Overwrite pattern
5880 *
5881 * Initializes the passthru command buffer for the Sanitize NVM command.
5882 */
5883static inline void
5884nvme_init_sanitize_nvm(struct libnvme_passthru_cmd *cmd,
5885 enum nvme_sanitize_sanact sanact, bool_Bool ause, __u8 owpass,
5886 bool_Bool oipbp, bool_Bool ndas, bool_Bool emvs, bool_Bool preq, __u32 ovrpat)
5887{
5888 memset(cmd, 0, sizeof(*cmd));
5889
5890 cmd->opcode = nvme_admin_sanitize_nvm;
5891 cmd->cdw10 = NVME_FIELD_ENCODE(sanact,(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
5892 NVME_SANITIZE_CDW10_SANACT_SHIFT,(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
5893 NVME_SANITIZE_CDW10_SANACT_MASK)(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
|
5894 NVME_FIELD_ENCODE(ause,(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
5895 NVME_SANITIZE_CDW10_AUSE_SHIFT,(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
5896 NVME_SANITIZE_CDW10_AUSE_MASK)(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
|
5897 NVME_FIELD_ENCODE(owpass,(((__u32)(owpass) & (NVME_SANITIZE_CDW10_OWPASS_MASK)) <<
(NVME_SANITIZE_CDW10_OWPASS_SHIFT))
5898 NVME_SANITIZE_CDW10_OWPASS_SHIFT,(((__u32)(owpass) & (NVME_SANITIZE_CDW10_OWPASS_MASK)) <<
(NVME_SANITIZE_CDW10_OWPASS_SHIFT))
5899 NVME_SANITIZE_CDW10_OWPASS_MASK)(((__u32)(owpass) & (NVME_SANITIZE_CDW10_OWPASS_MASK)) <<
(NVME_SANITIZE_CDW10_OWPASS_SHIFT))
|
5900 NVME_FIELD_ENCODE(oipbp,(((__u32)(oipbp) & (NVME_SANITIZE_CDW10_OIPBP_MASK)) <<
(NVME_SANITIZE_CDW10_OIPBP_SHIFT))
5901 NVME_SANITIZE_CDW10_OIPBP_SHIFT,(((__u32)(oipbp) & (NVME_SANITIZE_CDW10_OIPBP_MASK)) <<
(NVME_SANITIZE_CDW10_OIPBP_SHIFT))
5902 NVME_SANITIZE_CDW10_OIPBP_MASK)(((__u32)(oipbp) & (NVME_SANITIZE_CDW10_OIPBP_MASK)) <<
(NVME_SANITIZE_CDW10_OIPBP_SHIFT))
|
5903 NVME_FIELD_ENCODE(ndas,(((__u32)(ndas) & (NVME_SANITIZE_CDW10_NDAS_MASK)) <<
(NVME_SANITIZE_CDW10_NDAS_SHIFT))
5904 NVME_SANITIZE_CDW10_NDAS_SHIFT,(((__u32)(ndas) & (NVME_SANITIZE_CDW10_NDAS_MASK)) <<
(NVME_SANITIZE_CDW10_NDAS_SHIFT))
5905 NVME_SANITIZE_CDW10_NDAS_MASK)(((__u32)(ndas) & (NVME_SANITIZE_CDW10_NDAS_MASK)) <<
(NVME_SANITIZE_CDW10_NDAS_SHIFT))
|
5906 NVME_FIELD_ENCODE(emvs,(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
5907 NVME_SANITIZE_CDW10_EMVS_SHIFT,(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
5908 NVME_SANITIZE_CDW10_EMVS_MASK)(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
|
5909 NVME_FIELD_ENCODE(preq,(((__u32)(preq) & (NVME_SANITIZE_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_CDW10_PREQ_SHIFT))
5910 NVME_SANITIZE_CDW10_PREQ_SHIFT,(((__u32)(preq) & (NVME_SANITIZE_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_CDW10_PREQ_SHIFT))
5911 NVME_SANITIZE_CDW10_PREQ_MASK)(((__u32)(preq) & (NVME_SANITIZE_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_CDW10_PREQ_SHIFT))
;
5912 cmd->cdw11 = ovrpat;
5913}
5914
5915/**
5916 * nvme_init_get_lba_status() - Initialize passthru command to retrieve
5917 * information on possibly unrecoverable LBAs
5918 * @cmd: Passthru command to use
5919 * @nsid: Namespace ID to retrieve LBA status
5920 * @slba: Starting logical block address to check statuses
5921 * @mndw: Maximum number of dwords to return
5922 * @atype: Action type mechanism to determine LBA status descriptors to
5923 * return, see &enum nvme_lba_status_atype
5924 * @rl: Range length from slba to perform the action
5925 * @lbas: Data payload buffer to return status descriptors
5926 *
5927 * Initializes the passthru command buffer for the Get LBA Status command.
5928 */
5929static inline void
5930nvme_init_get_lba_status(struct libnvme_passthru_cmd *cmd, __u32 nsid,
5931 __u64 slba, __u32 mndw, enum nvme_lba_status_atype atype,
5932 __u16 rl, struct nvme_lba_status *lbas)
5933{
5934 memset(cmd, 0, sizeof(*cmd));
5935
5936 cmd->opcode = nvme_admin_get_lba_status;
5937 cmd->nsid = nsid;
5938 cmd->data_len = (mndw + 1) << 2;
5939 cmd->addr = (__u64)(uintptr_t)lbas;
5940 cmd->cdw10 = slba & 0xffffffff;
5941 cmd->cdw11 = slba >> 32;
5942 cmd->cdw12 = mndw;
5943 cmd->cdw13 = NVME_FIELD_ENCODE(rl,(((__u32)(rl) & (NVME_GET_LBA_STATUS_CDW13_RL_MASK)) <<
(NVME_GET_LBA_STATUS_CDW13_RL_SHIFT))
5944 NVME_GET_LBA_STATUS_CDW13_RL_SHIFT,(((__u32)(rl) & (NVME_GET_LBA_STATUS_CDW13_RL_MASK)) <<
(NVME_GET_LBA_STATUS_CDW13_RL_SHIFT))
5945 NVME_GET_LBA_STATUS_CDW13_RL_MASK)(((__u32)(rl) & (NVME_GET_LBA_STATUS_CDW13_RL_MASK)) <<
(NVME_GET_LBA_STATUS_CDW13_RL_SHIFT))
|
5946 NVME_FIELD_ENCODE(atype,(((__u32)(atype) & (NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK)
) << (NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT))
5947 NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT,(((__u32)(atype) & (NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK)
) << (NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT))
5948 NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK)(((__u32)(atype) & (NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK)
) << (NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT))
;
5949}
5950
5951/**
5952 * nvme_init_sanitize_ns() - Initialize passthru command to start a
5953 * sanitize namespace operation
5954 * @cmd: Passthru command to use
5955 * @sanact: Sanitize action, see &enum nvme_sanitize_sanact
5956 * @ause: Set to allow unrestricted sanitize exit
5957 * @emvs: Set to enter media verification state
5958 * @preq: Set to require the sanitize operation to purge user data, as
5959 * defined by IEEE Std 2883, or fail
5960 *
5961 * Initializes the passthru command buffer for the Sanitize namespace command.
5962 */
5963static inline void
5964nvme_init_sanitize_ns(struct libnvme_passthru_cmd *cmd,
5965 enum nvme_sanitize_sanact sanact, bool_Bool ause, bool_Bool emvs,
5966 bool_Bool preq)
5967{
5968 memset(cmd, 0, sizeof(*cmd));
5969
5970 cmd->opcode = nvme_admin_sanitize_ns;
5971 cmd->cdw10 = NVME_FIELD_ENCODE(sanact,(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
5972 NVME_SANITIZE_CDW10_SANACT_SHIFT,(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
5973 NVME_SANITIZE_CDW10_SANACT_MASK)(((__u32)(sanact) & (NVME_SANITIZE_CDW10_SANACT_MASK)) <<
(NVME_SANITIZE_CDW10_SANACT_SHIFT))
|
5974 NVME_FIELD_ENCODE(ause,(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
5975 NVME_SANITIZE_CDW10_AUSE_SHIFT,(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
5976 NVME_SANITIZE_CDW10_AUSE_MASK)(((__u32)(ause) & (NVME_SANITIZE_CDW10_AUSE_MASK)) <<
(NVME_SANITIZE_CDW10_AUSE_SHIFT))
|
5977 NVME_FIELD_ENCODE(emvs,(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
5978 NVME_SANITIZE_CDW10_EMVS_SHIFT,(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
5979 NVME_SANITIZE_CDW10_EMVS_MASK)(((__u32)(emvs) & (NVME_SANITIZE_CDW10_EMVS_MASK)) <<
(NVME_SANITIZE_CDW10_EMVS_SHIFT))
|
5980 NVME_FIELD_ENCODE(preq,(((__u32)(preq) & (NVME_SANITIZE_NS_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_NS_CDW10_PREQ_SHIFT))
5981 NVME_SANITIZE_NS_CDW10_PREQ_SHIFT,(((__u32)(preq) & (NVME_SANITIZE_NS_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_NS_CDW10_PREQ_SHIFT))
5982 NVME_SANITIZE_NS_CDW10_PREQ_MASK)(((__u32)(preq) & (NVME_SANITIZE_NS_CDW10_PREQ_MASK)) <<
(NVME_SANITIZE_NS_CDW10_PREQ_SHIFT))
;
5983}
5984
5985/*
5986 * Helper Functions
5987 */
5988
5989/**
5990 * nvme_init_ctrl_list() - Initialize an nvme_ctrl_list structure from an array.
5991 * @cntlist: The controller list structure to initialize
5992 * @num_ctrls: The number of controllers in the array, &ctrlist.
5993 * @ctrlist: An array of controller identifiers in CPU native endian.
5994 *
5995 * This is intended to be used with any command that takes a controller list
5996 * argument. See nvme_ns_attach_ctrls() and nvme_ns_detach().
5997 */
5998static inline void
5999nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls,
6000 __u16 *ctrlist)
6001{
6002 int i;
6003
6004 cntlist->num = htole16(num_ctrls)__uint16_identity (num_ctrls);
6005 for (i = 0; i < num_ctrls; i++)
6006 cntlist->identifier[i] = htole16(ctrlist[i])__uint16_identity (ctrlist[i]);
6007}
6008