Bug Summary

File:.build-ci/../plugins/wdc/wdc-nvme.c
Warning:line 2153, 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-10-24-125112-639-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);
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
1498static double calc_percent(uint64_t numerator, uint64_t denominator)
1499{
1500 return denominator ?
1501 (uint64_t)(((double)numerator / (double)denominator) * 100) : 0;
1502}
1503
1504static int wdc_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id)
1505{
1506 struct libnvme_passthru_cmd cmd;
1507 struct nvme_id_ctrl ctrl;
1508 int ret;
1509
1510 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1511 nvme_init_identify_ctrl(&cmd, &ctrl);
8
Calling 'nvme_init_identify_ctrl'
13
Returning from 'nvme_init_identify_ctrl'
1512 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1513 if (ret) {
14
Assuming 'ret' is 0
15
Taking false branch
1514 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)
;
1515 return -1;
1516 }
1517
1518 *vendor_id = (uint32_t) ctrl.vid;
16
Value assigned to 'read_vendor_id', which participates in a condition later
1519
1520 return ret;
1521}
1522
1523static bool_Bool wdc_is_sn861(__u32 device_id)
1524{
1525 if ((device_id == WDC_NVME_SN861_DEV_ID0x2750) ||
1526 (device_id == WDC_NVME_SN861_DEV_ID_10x2751) ||
1527 (device_id == WDC_NVME_SN861_DEV_ID_20x2752))
1528 return true1;
1529 else
1530 return false0;
1531}
1532
1533
1534static bool_Bool wdc_is_sn640(__u32 device_id)
1535{
1536 if ((device_id == WDC_NVME_SN640_DEV_ID0x2400) ||
1537 (device_id == WDC_NVME_SN640_DEV_ID_10x2401) ||
1538 (device_id == WDC_NVME_SN640_DEV_ID_20x2402))
1539 return true1;
1540 else
1541 return false0;
1542}
1543
1544static bool_Bool wdc_is_sn650_u2(__u32 device_id)
1545{
1546 if (device_id == WDC_NVME_SN650_DEV_ID_30x2720)
1547 return true1;
1548 else
1549 return false0;
1550}
1551
1552static bool_Bool wdc_is_sn650_e1l(__u32 device_id)
1553{
1554 if (device_id == WDC_NVME_SN650_DEV_ID_40x2721)
1555 return true1;
1556 else
1557 return false0;
1558}
1559
1560static bool_Bool wdc_is_zn350(__u32 device_id)
1561{
1562 return (device_id == WDC_NVME_ZN350_DEV_ID0x5010 ||
1563 device_id == WDC_NVME_ZN350_DEV_ID_10x5018);
1564}
1565static bool_Bool needs_c2_log_page_check(__u32 device_id)
1566{
1567 if ((wdc_is_sn640(device_id)) ||
1568 (wdc_is_sn650_u2(device_id)) ||
1569 (wdc_is_sn650_e1l(device_id)))
1570 return true1;
1571 else
1572 return false0;
1573}
1574
1575static bool_Bool wdc_check_power_of_2(int num)
1576{
1577 return num && (!(num & (num-1)));
1578}
1579
1580static int wdc_get_model_number(struct libnvme_transport_handle *hdl, char *model)
1581{
1582 struct libnvme_passthru_cmd cmd;
1583 struct nvme_id_ctrl ctrl;
1584 int ret, i;
1585
1586 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
1587 nvme_init_identify_ctrl(&cmd, &ctrl);
1588 ret = libnvme_exec_admin_passthru(hdl, &cmd);
1589 if (ret) {
1590 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)
;
1591 return -1;
1592 }
1593
1594 memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE40);
1595 /* get rid of the padded spaces */
1596 i = NVME_ID_CTRL_MODEL_NUMBER_SIZE40-1;
1597 while (model[i] == ' ')
1598 i--;
1599 model[i+1] = 0;
1600
1601 return ret;
1602}
1603
1604static bool_Bool wdc_check_device(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1605{
1606 int ret;
1607 bool_Bool supported;
1608 uint32_t read_device_id = -1, read_vendor_id = -1;
1609
1610 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1611 if (ret < 0) {
1612 /* Use the identify nvme command to get vendor id due to NVMeOF device. */
1613 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1614 return false0;
1615 }
1616
1617 supported = false0;
1618
1619 if (read_vendor_id == WDC_NVME_VID0x1c58 ||
1620 read_vendor_id == WDC_NVME_VID_20x1b96 ||
1621 read_vendor_id == WDC_NVME_SNDK_VID0x15b7)
1622 supported = true1;
1623 else
1624 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)
1625 "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)
1626 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)
;
1627
1628 return supported;
1629}
1630
1631static bool_Bool wdc_enc_check_model(struct libnvme_transport_handle *hdl)
1632{
1633 int ret;
1634 bool_Bool supported;
1635 char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40+1];
1636
1637 ret = wdc_get_model_number(hdl, model);
1638 if (ret < 0)
1639 return false0;
1640
1641 supported = false0;
1642 model[NVME_ID_CTRL_MODEL_NUMBER_SIZE40] = 0; /* forced termination */
1643 if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL)_Generic (0 ? (model) : (void *) 1, const void *: (const char
*) (strstr (model, "OpenFlex")), default: strstr (model, "OpenFlex"
))
)
1644 supported = true1;
1645 else
1646 nvme_show_error("ERROR: WDC: unsupported WDC enclosure, Model = %s", model)nvme_show_message(1, "ERROR: WDC: unsupported WDC enclosure, Model = %s"
, model)
;
1647
1648 return supported;
1649}
1650
1651static __u64 wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
1652{
1653 int ret;
1654 uint32_t read_device_id = -1, read_vendor_id = -1;
1655 __u64 capabilities = 0;
1656 __u32 cust_id;
1657
1658 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1659 if (ret < 0) {
1
Assuming 'ret' is >= 0
1660 if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0)
1661 return capabilities;
1662 }
1663
1664 /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
1665 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
1666 capabilities = wdc_get_enc_drive_capabilities(ctx, hdl);
5
Calling 'wdc_get_enc_drive_capabilities'
1667 return capabilities;
1668 }
1669
1670 switch (read_vendor_id) {
1671 case WDC_NVME_VID0x1c58:
1672 switch (read_device_id) {
1673 case WDC_NVME_SN100_DEV_ID0x0003:
1674 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 |
1675 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1676 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1677 break;
1678
1679 case WDC_NVME_SN200_DEV_ID0x0023:
1680 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1681 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 |
1682 WDC_DRIVE_CAP_PURGE0x0000001000000000);
1683
1684 /* verify the 0xCA log page is supported */
1685 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1686 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1687 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1688
1689 /* verify the 0xC1 log page is supported */
1690 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1691 WDC_NVME_ADD_LOG_OPCODE0xC1, 0))
1692 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
1693 break;
1694
1695 default:
1696 capabilities = 0;
1697 }
1698 break;
1699
1700 case WDC_NVME_VID_20x1b96:
1701 switch (read_device_id) {
1702 case WDC_NVME_SN630_DEV_ID0x2200:
1703 case WDC_NVME_SN630_DEV_ID_10x2201:
1704 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1705 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1706 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1707 /* verify the 0xCA log page is supported */
1708 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1709 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1710 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1711
1712 /* verify the 0xD0 log page is supported */
1713 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1714 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1715 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1716 break;
1717
1718 case WDC_NVME_SN640_DEV_ID0x2400:
1719 case WDC_NVME_SN640_DEV_ID_10x2401:
1720 case WDC_NVME_SN640_DEV_ID_20x2402:
1721 case WDC_NVME_SN640_DEV_ID_30x2404:
1722 case WDC_NVME_SN560_DEV_ID_10x2712:
1723 case WDC_NVME_SN560_DEV_ID_20x2713:
1724 case WDC_NVME_SN560_DEV_ID_30x2714:
1725 case WDC_NVME_SN660_DEV_ID0x2704:
1726 /* verify the 0xC0 log page is supported */
1727 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1728 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)
1729 == true1) {
1730 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1731 }
1732
1733 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1734 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1735 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1736 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1737 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1738
1739 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1740 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1741 WDC_ERROR_REC_LOG_ID0xC1, 0))
1742 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1743
1744 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1745 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1746 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1747 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1748
1749 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1750 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1751 WDC_DEV_CAP_LOG_ID0xC4, 0))
1752 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1753
1754 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1755 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1756 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1757 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1758
1759 /* verify the 0xCA log page is supported */
1760 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1761 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1762 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1763
1764 /* verify the 0xD0 log page is supported */
1765 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1766 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1767 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1768
1769 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1770 /* Can still determine some capabilities in this case, but log an error */
1771 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1772 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1773 "%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)
1774 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1775
1776 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1777 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) || (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1778 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1779 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1780 else
1781 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1782
1783 break;
1784
1785 case WDC_NVME_SN840_DEV_ID0x2300:
1786 case WDC_NVME_SN840_DEV_ID_10x2500:
1787 case WDC_NVME_SN860_DEV_ID0x2730:
1788 /* verify the 0xC0 log page is supported */
1789 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1790 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, 0))
1791 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1792 fallthrough__attribute__((fallthrough));
1793 case WDC_NVME_ZN540_DEV_ID0x2600:
1794 case WDC_NVME_SN540_DEV_ID0x2610:
1795 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1796 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1797 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
1798 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1799 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 | WDC_DRIVE_CAP_REASON_ID0x0000000000010000 |
1800 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1801
1802 /* verify the 0xCA log page is supported */
1803 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1804 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0))
1805 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1806
1807 /* verify the 0xD0 log page is supported */
1808 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1809 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0))
1810 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
1811 break;
1812
1813 case WDC_NVME_SN650_DEV_ID0x2700:
1814 case WDC_NVME_SN650_DEV_ID_10x2701:
1815 case WDC_NVME_SN650_DEV_ID_20x2702:
1816 case WDC_NVME_SN650_DEV_ID_30x2720:
1817 case WDC_NVME_SN650_DEV_ID_40x2721:
1818 case WDC_NVME_SN655_DEV_ID0x2722:
1819 case WDC_NVME_SN655_DEV_ID_10x2723:
1820 case WDC_NVME_SN550_DEV_ID0x2708:
1821 /* verify the 0xC0 log page is supported */
1822 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1823 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
1824 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
1825
1826 /* verify the 0xC1 (OCP Error Recovery) log page is supported */
1827 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1828 WDC_ERROR_REC_LOG_ID0xC1, 0))
1829 capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000;
1830
1831 /* verify the 0xC3 (OCP Latency Monitor) log page is supported */
1832 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1833 WDC_LATENCY_MON_LOG_ID0xC3, 0))
1834 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
1835
1836 /* verify the 0xC4 (OCP Device Capabilities) log page is supported */
1837 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1838 WDC_DEV_CAP_LOG_ID0xC4, 0))
1839 capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000;
1840
1841 /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
1842 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1843 WDC_UNSUPPORTED_REQS_LOG_ID0xC5, 0))
1844 capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000;
1845
1846 /* verify the 0xCA log page is supported */
1847 if (wdc_nvme_check_supported_log_page(ctx, hdl,
1848 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
1849 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
1850
1851 capabilities |= (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1852 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1853 WDC_DRIVE_CAP_RESIZE0x0000000000000100 | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000 |
1854 WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 |
1855 WDC_DRIVE_CAP_REASON_ID0x0000000000010000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000);
1856
1857 cust_id = wdc_get_fw_cust_id(ctx, hdl);
1858 /* Can still determine some capabilities in this case, but log an error */
1859 if (cust_id == WDC_INVALID_CUSTOMER_ID-1)
1860 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
1861 "%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)
1862 __func__, read_device_id)nvme_show_message(1, "%s: ERROR: WDC: invalid customer ID; device ID = %x\n"
, __func__, read_device_id)
;
1863
1864 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) ||
1865 (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
1866 (cust_id == WDC_CUSTOMER_ID_0x10050x1005) ||
1867 (cust_id == WDC_CUSTOMER_ID_0x13040x1304))
1868 capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1869 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1870 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1871 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000);
1872 else
1873 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
1874 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
1875
1876 break;
1877
1878 case WDC_NVME_SN861_DEV_ID0x2750:
1879 case WDC_NVME_SN861_DEV_ID_10x2751:
1880 case WDC_NVME_SN861_DEV_ID_20x2752:
1881 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1882 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1883 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1884 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1885 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1886 WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
1887 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
1888 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1889 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
1890 WDC_DRIVE_CAP_INFO0x0000000000080000 |
1891 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1892 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1893 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1894 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1895 break;
1896
1897 case WDC_NVME_SNTMP_DEV_ID0x2761:
1898 case WDC_NVME_SNTMP_DEV_ID_10x2763:
1899 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1900 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1901 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1902 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1903 WDC_DRIVE_CAP_DUI0x0000000800000000 |
1904 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1905 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1906 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1907 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1908 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1909 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1910 break;
1911
1912 default:
1913 capabilities = 0;
1914 }
1915 break;
1916
1917 case WDC_NVME_SNDK_VID0x15b7:
1918 switch (read_device_id) {
1919 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
1920 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
1921 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
1922 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
1923 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
1924 capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1925 WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 |
1926 WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 |
1927 WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 |
1928 WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 |
1929 WDC_DRIVE_CAP_UDUI0x0000040000000000 |
1930 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
1931 WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
1932 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 |
1933 WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 |
1934 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 |
1935 WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000);
1936 break;
1937
1938 case WDC_NVME_SXSLCL_DEV_ID0x2001:
1939 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
1940 break;
1941
1942 case WDC_NVME_SN520_DEV_ID0x5003:
1943 case WDC_NVME_SN520_DEV_ID_10x5004:
1944 case WDC_NVME_SN520_DEV_ID_20x5005:
1945 case WDC_NVME_SN810_DEV_ID0x5011:
1946 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000;
1947 break;
1948
1949 case WDC_NVME_SN820CL_DEV_ID0x5037:
1950 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 |
1951 WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 |
1952 WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 | WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
1953 WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
1954 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1955 WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000;
1956 break;
1957
1958 case WDC_NVME_SN720_DEV_ID0x5002:
1959 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1960 WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000;
1961 break;
1962
1963 case WDC_NVME_SN730_DEV_ID0x5006:
1964 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000 | WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 |
1965 WDC_DRIVE_CAP_INFO0x0000000000080000 | WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 |
1966 WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000 | WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000;
1967 break;
1968
1969 case WDC_NVME_SN530_DEV_ID_10x5007:
1970 fallthrough__attribute__((fallthrough));
1971 case WDC_NVME_SN530_DEV_ID_20x5008:
1972 fallthrough__attribute__((fallthrough));
1973 case WDC_NVME_SN530_DEV_ID_30x5009:
1974 fallthrough__attribute__((fallthrough));
1975 case WDC_NVME_SN530_DEV_ID_40x500b:
1976 fallthrough__attribute__((fallthrough));
1977 case WDC_NVME_SN530_DEV_ID_50x501d:
1978 fallthrough__attribute__((fallthrough));
1979 case WDC_NVME_SN350_DEV_ID0x5019:
1980 fallthrough__attribute__((fallthrough));
1981 case WDC_NVME_SN570_DEV_ID0x501A:
1982 fallthrough__attribute__((fallthrough));
1983 case WDC_NVME_SN850X_DEV_ID0x5030:
1984 fallthrough__attribute__((fallthrough));
1985 case WDC_NVME_SN5000_DEV_ID_10x5034:
1986 fallthrough__attribute__((fallthrough));
1987 case WDC_NVME_SN5000_DEV_ID_20x5035:
1988 fallthrough__attribute__((fallthrough));
1989 case WDC_NVME_SN5000_DEV_ID_30x5036:
1990 fallthrough__attribute__((fallthrough));
1991 case WDC_NVME_SN5000_DEV_ID_40x504A:
1992 fallthrough__attribute__((fallthrough));
1993 case WDC_NVME_SN7000S_DEV_ID_10x5039:
1994 fallthrough__attribute__((fallthrough));
1995 case WDC_NVME_SN7150_DEV_ID_10x503b:
1996 fallthrough__attribute__((fallthrough));
1997 case WDC_NVME_SN7150_DEV_ID_20x503c:
1998 fallthrough__attribute__((fallthrough));
1999 case WDC_NVME_SN7150_DEV_ID_30x503d:
2000 fallthrough__attribute__((fallthrough));
2001 case WDC_NVME_SN7150_DEV_ID_40x503e:
2002 fallthrough__attribute__((fallthrough));
2003 case WDC_NVME_SN7150_DEV_ID_50x503f:
2004 fallthrough__attribute__((fallthrough));
2005 case WDC_NVME_SN7100_DEV_ID_10x5043:
2006 fallthrough__attribute__((fallthrough));
2007 case WDC_NVME_SN7100_DEV_ID_20x5044:
2008 fallthrough__attribute__((fallthrough));
2009 case WDC_NVME_SN7100_DEV_ID_30x5045:
2010 fallthrough__attribute__((fallthrough));
2011 case WDC_NVME_SN8000S_DEV_ID0x5049:
2012 fallthrough__attribute__((fallthrough));
2013 case WDC_NVME_SN5100S_DEV_ID_10x5061:
2014 fallthrough__attribute__((fallthrough));
2015 case WDC_NVME_SN5100S_DEV_ID_20x5062:
2016 fallthrough__attribute__((fallthrough));
2017 case WDC_NVME_SN5100S_DEV_ID_30x5063:
2018 fallthrough__attribute__((fallthrough));
2019 case WDC_NVME_SN740_DEV_ID0x5015:
2020 case WDC_NVME_SN740_DEV_ID_10x5016:
2021 case WDC_NVME_SN740_DEV_ID_20x5017:
2022 case WDC_NVME_SN740_DEV_ID_30x5025:
2023 case WDC_NVME_SN340_DEV_ID0x500d:
2024 capabilities = WDC_DRIVE_CAP_DUI0x0000000800000000;
2025 break;
2026
2027 case WDC_NVME_ZN350_DEV_ID0x5010:
2028 case WDC_NVME_ZN350_DEV_ID_10x5018:
2029 capabilities = WDC_DRIVE_CAP_DUI_DATA0x0000000200000000 | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 |
2030 WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 |
2031 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2032 WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | WDC_DRIVE_CAP_INFO0x0000000000080000 |
2033 WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000;
2034 break;
2035
2036 default:
2037 capabilities = 0;
2038 }
2039 break;
2040 default:
2041 capabilities = 0;
2042 }
2043
2044 return capabilities;
2045}
2046
2047static __u64 wdc_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx,
2048 struct libnvme_transport_handle *hdl)
2049{
2050 int ret;
2051 uint32_t read_vendor_id;
2052 __u64 capabilities = 0;
2053 __u32 cust_id, market_name_len;
6
'market_name_len' declared without an initial value
2054 char marketing_name[64];
2055 void *dev_mng_log = NULL((void*)0);
2056 int uuid_index = 0;
2057 struct nvme_id_uuid_list uuid_list;
2058
2059 memset(marketing_name, 0, 64);
2060
2061 ret = wdc_get_vendor_id(hdl, &read_vendor_id);
7
Calling 'wdc_get_vendor_id'
17
Returning from 'wdc_get_vendor_id'
2062 if (ret
17.1
'ret' is >= 0
17.1
'ret' is >= 0
< 0)
18
Taking false branch
2063 return capabilities;
2064
2065 switch (read_vendor_id) {
19
Control jumps to 'case 7062:' at line 2080
2066 case WDC_NVME_VID0x1c58:
2067 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080 |
2068 WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 | WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 | WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000);
2069
2070 /* verify the 0xCA log page is supported */
2071 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2072 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2073 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2074
2075 /* verify the 0xC1 log page is supported */
2076 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2077 WDC_NVME_ADD_LOG_OPCODE0xC1, 0) == true1)
2078 capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004;
2079 break;
2080 case WDC_NVME_VID_20x1b96:
2081 capabilities = (WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 | WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 |
2082 WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 |
2083 WDC_DRIVE_CAP_RESIZE0x0000000000000100);
2084
2085 /* Find the WDC UUID index */
2086 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2087 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
20
Assuming the condition is false
21
Taking false branch
2088 /* check for the Sandisk UUID first */
2089 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2090
2091 if (uuid_index < 0)
2092 /* The Sandisk UUID is not found;
2093 * check for the WDC UUID second.
2094 */
2095 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2096 }
2097
2098 /* WD UUID not found, use default uuid index - 0 */
2099 if (uuid_index
21.1
'uuid_index' is >= 0
21.1
'uuid_index' is >= 0
< 0)
22
Taking false branch
2100 uuid_index = 0;
2101
2102 /* verify the 0xC2 Device Manageability log page is supported */
2103 if (wdc_nvme_check_supported_log_page(ctx, hdl,
23
Assuming the condition is false
24
Taking false branch
2104 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
2105 uuid_index) == false0) {
2106 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)
2107 uuid_index)nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d"
, uuid_index)
;
2108 goto out;
2109 }
2110
2111 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
25
Assuming the condition is false
26
Taking false branch
2112 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
2113 goto out;
2114 }
2115
2116 /* Get the customer ID and marketing name from WD C2 log page */
2117 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log,
27
Taking true branch
2118 &cust_id,
2119 WDC_C2_CUSTOMER_ID_ID0x15))
2120 nvme_show_error("ERROR: SNDK: Get Customer FW ID Failed")nvme_show_message(1, "ERROR: SNDK: Get Customer FW ID Failed"
)
;
2121
2122 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
2123 WDC_C2_MARKETING_NAME_ID0x07,
2124 (char *)marketing_name,
2125 sizeof(marketing_name),
2126 &market_name_len))
2127 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
2128
2129 /* verify the 0xC0 log page is supported */
2130 if (wdc_nvme_check_supported_log_page(ctx, hdl,
39
Assuming the condition is false
40
Taking false branch
2131 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0))
2132 capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000;
2133
2134 /* verify the 0xC3 log page is supported */
2135 if (wdc_nvme_check_supported_log_page(ctx, hdl,
41
Assuming the condition is false
42
Taking false branch
2136 WDC_LATENCY_MON_LOG_ID0xC3, 0) == true1)
2137 capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000;
2138
2139 /* verify the 0xCA log page is supported */
2140 if (wdc_nvme_check_supported_log_page(ctx, hdl,
43
Assuming the condition is false
44
Taking false branch
2141 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == true1)
2142 capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008;
2143
2144 /* verify the 0xD0 log page is supported */
2145 if (wdc_nvme_check_supported_log_page(ctx, hdl,
45
Assuming the condition is false
2146 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == true1)
2147 capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010;
2148
2149 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) ||
2150 (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) ||
2151 (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) ||
2152 (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) ||
2153 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) ||
46
3rd function call argument is an uninitialized value
2154 (!strncmp(marketing_name, WDC_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len)))
2155 /* Set capabilities for OCP compliant drives */
2156 capabilities |= (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 |
2157 WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 |
2158 WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000);
2159 else {
2160 capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 |
2161 WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080);
2162
2163 /* if the 0xCB log page is supported */
2164 if (wdc_nvme_check_supported_log_page(ctx, hdl,
2165 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0) == true1)
2166 capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000;
2167 }
2168
2169 break;
2170 case WDC_NVME_SNDK_VID0x15b7:
2171 capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000;
2172 break;
2173 default:
2174 capabilities = 0;
2175 }
2176
2177out:
2178 return capabilities;
2179}
2180
2181static int wdc_get_serial_name(struct libnvme_transport_handle *hdl, char *file, size_t len,
2182 const char *suffix)
2183{
2184 int ret;
2185 int res_len = 0;
2186 char orig[PATH_MAX4096] = {0};
2187 struct libnvme_passthru_cmd cmd;
2188 struct nvme_id_ctrl ctrl;
2189 char sn[sizeof(ctrl.sn) + 1] = {0};
2190
2191 shr_strscpy(orig, file, sizeof(orig));
2192 memset(file, 0, len);
2193 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
2194 nvme_init_identify_ctrl(&cmd, &ctrl);
2195 ret = libnvme_exec_admin_passthru(hdl, &cmd);
2196 if (ret) {
2197 nvme_show_error("ERROR: WDC: nvme_identify_ctrl() failed 0x%x",nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
2198 ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
2199 return -1;
2200 }
2201
2202 snprintf(sn, sizeof(sn), "%-.*s",
2203 (int)sizeof(ctrl.sn), ctrl.sn);
2204 shr_sanitize_name(shr_rtrim(sn));
2205
2206 res_len = snprintf(file, len, "%s%s%s", orig, sn, suffix);
2207 if (len <= res_len) {
2208 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
2209 "ERROR: WDC: cannot format serial number due to data of unexpected length\n")nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
;
2210 return -1;
2211 }
2212
2213 return 0;
2214}
2215
2216static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
2217 __u32 drive_log_length)
2218{
2219 int fd;
2220 int ret;
2221
2222 if (!drive_log_length) {
2223 nvme_show_error("ERROR: WDC: invalid log file length")nvme_show_message(1, "ERROR: WDC: invalid log file length");
2224 return -1;
2225 }
2226
2227 fd = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
2228 if (fd < 0) {
2229 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
2230 return -1;
2231 }
2232
2233 while (drive_log_length > WRITE_SIZE(sizeof(__u8) * 4096)) {
2234 ret = write(fd, drive_log_data, WRITE_SIZE(sizeof(__u8) * 4096));
2235 if (ret < 0) {
2236 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2237 close(fd);
2238 return -1;
2239 }
2240 drive_log_data += WRITE_SIZE(sizeof(__u8) * 4096);
2241 drive_log_length -= WRITE_SIZE(sizeof(__u8) * 4096);
2242 }
2243
2244 ret = write(fd, drive_log_data, drive_log_length);
2245 if (ret < 0) {
2246 nvme_show_error("ERROR: WDC: write: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: write: %s", libnvme_strerror
((*__errno_location ())))
;
2247 close(fd);
2248 return -1;
2249 }
2250
2251 if (shr_fsync(fd) < 0) {
2252 nvme_show_error("ERROR: WDC: fsync: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: fsync: %s", libnvme_strerror
((*__errno_location ())))
;
2253 close(fd);
2254 return -1;
2255 }
2256 close(fd);
2257 return 0;
2258}
2259
2260bool_Bool wdc_validate_dev_mng_log(void *data)
2261{
2262 __u32 remaining_len = 0;
2263 __u32 log_length = 0;
2264 __u32 log_entry_size = 0;
2265 __u32 log_entry_id = 0;
2266 __u32 offset = 0;
2267 bool_Bool valid_log = false0;
2268 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2269 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2270
2271 log_length = le32_to_cpu(hdr_ptr->length);
2272 /* Ensure log data is large enough for common header */
2273 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2274 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2275 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2276 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2277 return valid_log;
2278 }
2279
2280 /* Get pointer to first log Entry */
2281 offset = sizeof(struct wdc_c2_log_page_header);
2282 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2283 remaining_len = log_length - offset;
2284
2285 /* Proceed only if there is at least enough data to read an entry header */
2286 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2287 /* Get size of the next entry */
2288 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2289 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2290 /*
2291 * If log entry size is 0 or the log entry goes past the end
2292 * of the data, we must be at the end of the data
2293 */
2294 if (!log_entry_size || log_entry_size > remaining_len) {
2295 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2296 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2297 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2298 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2299 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2300 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2301
2302 /* Force the loop to end */
2303 remaining_len = 0;
2304 } else if (!log_entry_id || log_entry_id > 200) {
2305 /* Invalid entry - fail the search */
2306 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2307 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2308 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2309 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2310 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2311
2312 /* Force the loop to end */
2313 remaining_len = 0;
2314 valid_log = false0;
2315 } else {
2316 /* A valid log has at least one entry and no invalid entries */
2317 valid_log = true1;
2318 remaining_len -= log_entry_size;
2319 if (remaining_len > 0) {
2320 /* Increment the offset counter */
2321 offset += log_entry_size;
2322 /* Get the next entry */
2323 p_next_log_entry =
2324 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2325 }
2326 }
2327 }
2328
2329 return valid_log;
2330}
2331
2332bool_Bool wdc_parse_dev_mng_log_entry(void *data, __u32 entry_id,
2333 struct wdc_c2_log_subpage_header **log_entry)
2334{
2335 __u32 remaining_len = 0;
2336 __u32 log_length = 0;
2337 __u32 log_entry_size = 0;
2338 __u32 log_entry_id = 0;
2339 __u32 offset = 0;
2340 bool_Bool found = false0;
2341 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2342 struct wdc_c2_log_page_header *hdr_ptr = (struct wdc_c2_log_page_header *)data;
2343
2344 log_length = le32_to_cpu(hdr_ptr->length);
2345 /* Ensure log data is large enough for common header */
2346 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2347 nvme_show_error(nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2348 "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2349 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2350 return found;
2351 }
2352
2353 /* Get pointer to first log Entry */
2354 offset = sizeof(struct wdc_c2_log_page_header);
2355 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2356 remaining_len = log_length - offset;
2357
2358 if (!log_entry) {
2359 nvme_show_error("ERROR: WDC - %s: No log entry pointer.", __func__)nvme_show_message(1, "ERROR: WDC - %s: No log entry pointer."
, __func__)
;
2360 return found;
2361 }
2362 *log_entry = NULL((void*)0);
2363
2364 /* Proceed only if there is at least enough data to read an entry header */
2365 while (remaining_len >= sizeof(struct wdc_c2_log_subpage_header)) {
2366 /* Get size of the next entry */
2367 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2368 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2369
2370 /*
2371 * If log entry size is 0 or the log entry goes past the end
2372 * of the data, we must be at the end of the data
2373 */
2374 if (!log_entry_size || log_entry_size > remaining_len) {
2375 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2376 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2377 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2378 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2379 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2380 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2381
2382 /* Force the loop to end */
2383 remaining_len = 0;
2384 } else if (!log_entry_id || log_entry_id > 200) {
2385 /* Invalid entry - fail the search */
2386 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2387 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2388 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2389 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2390 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2391
2392 /* Force the loop to end */
2393 remaining_len = 0;
2394 } else {
2395 if (log_entry_id == entry_id) {
2396 found = true1;
2397 *log_entry = p_next_log_entry;
2398 remaining_len = 0;
2399 } else {
2400 remaining_len -= log_entry_size;
2401 }
2402
2403 if (remaining_len > 0) {
2404 /* Increment the offset counter */
2405 offset += log_entry_size;
2406
2407 /* Get the next entry */
2408 p_next_log_entry =
2409 (struct wdc_c2_log_subpage_header *)(((__u8 *)data) + offset);
2410 }
2411 }
2412 }
2413
2414 return found;
2415}
2416
2417bool_Bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id,
2418 struct wdc_c2_log_page_header *p_log_hdr,
2419 struct wdc_c2_log_subpage_header **p_p_found_log_entry)
2420{
2421 __u32 remaining_len = 0;
2422 __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1;
2423 __u32 log_entry_size = 0;
2424 __u32 log_entry_id = 0;
2425 __u32 size = 0;
2426 bool_Bool valid_log;
2427 __u32 offset = 0;
2428 struct wdc_c2_log_subpage_header *p_next_log_entry = NULL((void*)0);
2429
2430 *p_p_found_log_entry = NULL((void*)0);
2431
2432 /* Ensure log data is large enough for common header */
2433 if (log_length < sizeof(struct wdc_c2_log_page_header)) {
2434 nvme_show_error(nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2435 "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"\n",nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
2436 __func__, log_length, sizeof(struct wdc_c2_log_page_header))nvme_show_message(1, "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"
"l" "x""\n", __func__, log_length, sizeof(struct wdc_c2_log_page_header
))
;
2437 return false0;
2438 }
2439
2440 /* Get pointer to first log Entry */
2441 size = sizeof(struct wdc_c2_log_page_header);
2442 offset = size;
2443 p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2444 remaining_len = log_length - size;
2445 valid_log = false0;
2446
2447 /*
2448 * Walk the entire structure. Perform a sanity check to make sure this is a
2449 * standard version of the structure. This means making sure each entry looks
2450 * valid. But allow for the data to overflow the allocated
2451 * buffer (we don't want a false negative because of a FW formatting error)
2452 */
2453
2454 /* Proceed only if there is at least enough data to read an entry header */
2455 while (remaining_len >= log_entry_hdr_size) {
2456 /* Get size of the next entry */
2457 log_entry_size = le32_to_cpu(p_next_log_entry->length);
2458 log_entry_id = le32_to_cpu(p_next_log_entry->entry_id);
2459
2460 /*
2461 * If log entry size is 0 or the log entry goes past the end
2462 * of the data, we must be at the end of the data
2463 */
2464 if (!log_entry_size || log_entry_size > remaining_len) {
2465 nvme_show_error("ERROR: WDC: %s: Detected unaligned end of the data. ",nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
2466 __func__)nvme_show_message(1, "ERROR: WDC: %s: Detected unaligned end of the data. "
, __func__)
;
2467 nvme_show_error("Data Offset: 0x%x Entry Size: 0x%x, ",nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
2468 offset, log_entry_size)nvme_show_message(1, "Data Offset: 0x%x Entry Size: 0x%x, ", offset
, log_entry_size)
;
2469 nvme_show_error("Remaining Log Length: 0x%x Entry Id: 0x%x",nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
2470 remaining_len, log_entry_id)nvme_show_message(1, "Remaining Log Length: 0x%x Entry Id: 0x%x"
, remaining_len, log_entry_id)
;
2471
2472 /* Force the loop to end */
2473 remaining_len = 0;
2474 } else if (!log_entry_id || log_entry_id > 200) {
2475 /* Invalid entry - fail the search */
2476 nvme_show_error("ERROR: WDC: %s: Invalid entry found at offset: 0x%x ",nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
2477 __func__, offset)nvme_show_message(1, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x "
, __func__, offset)
;
2478 nvme_show_error("Entry Size: 0x%x, Remaining Log Length: 0x%x ",nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
2479 log_entry_size, remaining_len)nvme_show_message(1, "Entry Size: 0x%x, Remaining Log Length: 0x%x "
, log_entry_size, remaining_len)
;
2480 nvme_show_error("Entry Id: 0x%x", log_entry_id)nvme_show_message(1, "Entry Id: 0x%x", log_entry_id);
2481
2482 /* Force the loop to end */
2483 remaining_len = 0;
2484 valid_log = false0;
2485
2486 /* The structure is invalid, so any match that was found is invalid. */
2487 *p_p_found_log_entry = NULL((void*)0);
2488 } else {
2489 /* Structure must have at least one valid entry to be considered valid */
2490 valid_log = true1;
2491 if (log_entry_id == entry_id)
2492 /* A potential match. */
2493 *p_p_found_log_entry = p_next_log_entry;
2494
2495 remaining_len -= log_entry_size;
2496
2497 if (remaining_len > 0) {
2498 /* Increment the offset counter */
2499 offset += log_entry_size;
2500
2501 /* Get the next entry */
2502 p_next_log_entry =
2503 (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + offset);
2504 }
2505 }
2506 }
2507
2508 return valid_log;
2509}
2510
2511static bool_Bool get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, void **log_data,
2512 __u8 uuid_ix)
2513{
2514 struct wdc_c2_log_page_header *hdr_ptr;
2515 struct libnvme_passthru_cmd cmd;
2516 bool_Bool valid = false0;
2517 __u32 length = 0;
2518 void *data;
2519 int ret = 0;
2520
2521 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2522 if (!data) {
2523 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2524 return false0;
2525 }
2526
2527 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2528
2529 /* get the log page length */
2530 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2531 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2532 WDC_C2_LOG_BUF_LEN0x1000);
2533 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2534 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2535 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2536 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2537 if (ret) {
2538 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2539 "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2540 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2541 goto end;
2542 }
2543
2544 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2545 length = le32_to_cpu(hdr_ptr->length);
2546
2547 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2548 /* Log page buffer too small for actual data */
2549 free(data);
2550 data = calloc(length, sizeof(__u8));
2551 if (!data) {
2552 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2553 goto end;
2554 }
2555
2556 /* get the log page data with the increased length */
2557 nvme_init_get_log(&cmd, NVME_NSID_ALL,
2558 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data,
2559 length);
2560 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2561 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2562 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2563 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2564 if (ret) {
2565 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2566 "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
2567 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n"
, 0xC2, uuid_ix, ret)
;
2568 goto end;
2569 }
2570 }
2571
2572 valid = wdc_validate_dev_mng_log(data);
2573 if (valid) {
2574 /* Ensure size of log data matches length in log header */
2575 *log_data = calloc(length, sizeof(__u8));
2576 if (!*log_data) {
2577 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2578 valid = false0;
2579 goto end;
2580 }
2581 memcpy((void *)*log_data, data, length);
2582 } else {
2583 nvme_show_error("ERROR: WDC: C2 log page not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
2584 uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log page not found with uuid index %d"
, uuid_ix)
;
2585 }
2586
2587end:
2588 free(data);
2589 return valid;
2590}
2591
2592static bool_Bool get_dev_mgmt_log_page_lid_data(struct libnvme_transport_handle *hdl,
2593 void **cbs_data,
2594 __u8 lid,
2595 __u8 log_id,
2596 __u8 uuid_ix)
2597{
2598 void *data;
2599 struct wdc_c2_log_page_header *hdr_ptr;
2600 struct wdc_c2_log_subpage_header *sph;
2601 struct libnvme_passthru_cmd cmd;
2602 __u32 length = 0;
2603 int ret = 0;
2604 bool_Bool found = false0;
2605
2606 data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2607 if (!data) {
2608 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2609 return false0;
2610 }
2611
2612 memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN0x1000);
2613
2614 /* get the log page length */
2615 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2616 WDC_C2_LOG_BUF_LEN0x1000);
2617 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2618 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2619 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2620 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2621 if (ret) {
2622 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2623 "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2624 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2625 goto end;
2626 }
2627
2628 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2629 length = le32_to_cpu(hdr_ptr->length);
2630
2631 if (length > WDC_C2_LOG_BUF_LEN0x1000) {
2632 /* Log Page buffer too small, free and reallocate the necessary size */
2633 free(data);
2634 data = calloc(length, sizeof(__u8));
2635 if (!data) {
2636 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
2637 goto end;
2638 }
2639
2640 /* get the log page data with the increased length */
2641 nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data,
2642 length);
2643 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2644 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2645 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2646 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2647 if (ret) {
2648 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2649 "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n",nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
2650 lid, uuid_ix, ret)nvme_show_message(1, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n"
, lid, uuid_ix, ret)
;
2651 goto end;
2652 }
2653 }
2654
2655 /* Check the log data to see if the WD version of log page ID's is found */
2656 hdr_ptr = (struct wdc_c2_log_page_header *)data;
2657 sph = NULL((void*)0);
2658 found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
2659 if (found && sph) {
2660 *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
2661 if (!*cbs_data) {
2662 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
2663 found = false0;
2664 goto end;
2665 }
2666 memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
2667 } else if(found && !sph) {
2668 nvme_show_error("ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d",log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not present in log page with uuid index %d"
,log_id, uuid_ix)
;
2669 found = false0;
2670 } else {
2671 nvme_show_error("ERROR: WDC: C2 log id 0x%x not found with uuid index %d",nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
2672 log_id, uuid_ix)nvme_show_message(1, "ERROR: WDC: C2 log id 0x%x not found with uuid index %d"
, log_id, uuid_ix)
;
2673 }
2674
2675end:
2676 free(data);
2677 return found;
2678}
2679
2680static bool_Bool get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2681 void **data)
2682{
2683 bool_Bool found = false0;
2684 __u32 device_id = 0, vendor_id = 0;
2685 int uuid_index = 0;
2686 struct nvme_id_uuid_list uuid_list;
2687
2688 *data = NULL((void*)0);
2689
2690 /* The nvme_get_pci_ids() function could fail when drives are connected
2691 * via a PCIe switch. Therefore, the return code is intentionally
2692 * being ignored. The device_id and vendor_id variables have been
2693 * initialized to 0 so the code can continue on without issue for
2694 * both cases: successful or failed.
2695 */
2696 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2697
2698 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2699 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2700 /* check for the Sandisk UUID first */
2701 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2702
2703 if (uuid_index < 0) {
2704 /* The Sandisk UUID is not found;
2705 * check for the WDC UUID second.
2706 */
2707 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2708 if (uuid_index < 0)
2709 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2710 }
2711
2712 if (uuid_index >= 0)
2713 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2714 else {
2715 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2716 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2717 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2718 }
2719 } else if (needs_c2_log_page_check(device_id)) {
2720 /* In certain devices that don't support UUID lists, there are multiple
2721 * definitions of the C2 logpage. In those cases, the code
2722 * needs to try two UUID indexes and use an identification algorithm
2723 * to determine which is returning the correct log page data.
2724 */
2725
2726 uuid_index = 1;
2727 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2728
2729 if (!found) {
2730 /* not found with uuid = 1 try with uuid = 0 */
2731 uuid_index = 0;
2732 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2733 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2734
2735 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2736 }
2737 } else {
2738 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2739 uuid_index = 0;
2740 found = get_dev_mgmt_log_page_data(hdl, data, uuid_index);
2741 }
2742
2743 return found;
2744}
2745
2746static bool_Bool get_dev_mgment_cbs_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
2747 __u8 log_id, void **cbs_data)
2748{
2749 bool_Bool found = false0;
2750 __u8 lid = 0;
2751 __u32 device_id = 0, vendor_id = 0;
2752 int uuid_index = 0;
2753 struct nvme_id_uuid_list uuid_list;
2754
2755 *cbs_data = NULL((void*)0);
2756
2757 /* The nvme_get_pci_ids function could fail when drives are connected
2758 * via a PCIe switch. Therefore, the return code is intentionally
2759 * being ignored. The device_id and vendor_id variables have been
2760 * initialized to 0 so the code can continue on without issue for
2761 * both cases: successful or failed.
2762 */
2763 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2764
2765 lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
2766
2767 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
2768 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
2769 /* check for the Sandisk UUID first */
2770 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
2771
2772 if (uuid_index < 0) {
2773 /* The Sandisk UUID is not found;
2774 * check for the WDC UUID second.
2775 */
2776 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
2777 if (uuid_index < 0)
2778 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3);
2779 }
2780
2781 if (uuid_index >= 0)
2782 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid,
2783 log_id, uuid_index);
2784 else {
2785 nvme_show_error("%s: UUID lists are supported but a matching ",nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
2786 __func__)nvme_show_message(1, "%s: UUID lists are supported but a matching "
, __func__)
;
2787 nvme_show_error("uuid was not found")nvme_show_message(1, "uuid was not found");
2788 }
2789 } else if (needs_c2_log_page_check(device_id)) {
2790 /* In certain devices that don't support UUID lists, there are multiple
2791 * definitions of the C2 logpage. In those cases, the code
2792 * needs to try two UUID indexes and use an identification algorithm
2793 * to determine which is returning the correct log page data.
2794 */
2795 uuid_index = 1;
2796 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2797 if (!found) {
2798 /* not found with uuid = 1 try with uuid = 0 */
2799 uuid_index = 0;
2800 nvme_show_error("Not found, requesting log page with uuid_index %d",nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
2801 uuid_index)nvme_show_message(1, "Not found, requesting log page with uuid_index %d"
, uuid_index)
;
2802
2803 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id,
2804 uuid_index);
2805 }
2806 } else {
2807 /* Default to uuid-index 0 for cases where UUID lists are not supported */
2808 uuid_index = 0;
2809 found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index);
2810 }
2811
2812 return found;
2813}
2814
2815static int wdc_get_supported_log_pages(struct libnvme_transport_handle *hdl,
2816 struct nvme_supported_log_pages *supported,
2817 int uuid_index)
2818{
2819 struct libnvme_passthru_cmd cmd;
2820
2821 memset(supported, 0, sizeof(*supported));
2822 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES,
2823 NVME_CSI_NVM, supported, sizeof(*supported));
2824 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2825 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
2826 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
2827 return libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
2828}
2829
2830static bool_Bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
2831 struct libnvme_transport_handle *hdl,
2832 __u8 log_id,
2833 __u8 uuid_index)
2834{
2835 int i;
2836 bool_Bool found = false0;
2837 int err = -1;
2838 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
2839
2840 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_supported_log_pages *supports = NULL((void*)0);
2841
2842 /* Check log page id 0 (supported log pages) first */
2843 supports = libnvme_alloc(sizeof(*supports));
2844 if (!supports)
2845 return -ENOMEM12;
2846
2847 err = wdc_get_supported_log_pages(hdl,
2848 supports,
2849 uuid_index);
2850
2851 if (!err) {
2852 /* Check support log page list for support */
2853 if (supports->lid_support[log_id])
2854 /* Support for Log Page found in supported log pages */
2855 found = true1;
2856 }
2857
2858 /* if not found in the supported log pages (log id 0),
2859 * check the WDC C2 log page
2860 */
2861 if (!found) {
2862 if (get_dev_mgment_cbs_data(ctx, hdl,
2863 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
2864 (void *)&cbs_data)) {
2865 if (cbs_data) {
2866 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
2867 if (log_id == cbs_data->data[i]) {
2868 found = true1;
2869 break;
2870 }
2871 }
2872
2873#ifdef WDC_NVME_CLI_DEBUG
2874 if (!found) {
2875 nvme_show_error("ERROR: WDC: Log Page 0x%x not supported",nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
2876 log_id)nvme_show_message(1, "ERROR: WDC: Log Page 0x%x not supported"
, log_id)
;
2877 nvme_show_error("WDC: Supported Log Pages:")nvme_show_message(1, "WDC: Supported Log Pages:");
2878 /* print the supported pages */
2879 d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length),
2880 16, 1);
2881 }
2882#endif
2883 free(cbs_data);
2884 } else {
2885 nvme_show_error("ERROR: WDC: cbs_data ptr = NULL")nvme_show_message(1, "ERROR: WDC: cbs_data ptr = NULL");
2886 }
2887 } else {
2888 nvme_show_error("ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found",nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
2889 WDC_C2_LOG_PAGES_SUPPORTED_ID)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, 0x08)
;
2890 }
2891 }
2892
2893 return found;
2894}
2895
2896static bool_Bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data,
2897 __u32 entry_id)
2898{
2899 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2900
2901 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
2902 if (entry_data) {
2903 *ret_data = le32_to_cpu(entry_data->data);
2904 return true1;
2905 }
2906 }
2907
2908 *ret_data = 0;
2909 return false0;
2910}
2911
2912static bool_Bool wdc_nvme_parse_dev_status_log_str(void *log_data,
2913 __u32 entry_id,
2914 char *ret_data,
2915 size_t ret_data_size,
2916 __u32 *ret_data_len)
2917{
2918 struct wdc_c2_log_subpage_header *entry_data = NULL((void*)0);
2919 struct wdc_c2_cbs_data *entry_str_data = NULL((void*)0);
2920 __u32 entry_len, entry_total_len, max_payload_len;
2921
2922 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
2923 return false0;
2924
2925 if (wdc_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) {
30
Assuming the condition is true
31
Taking true branch
2926 if (entry_data) {
32
Assuming 'entry_data' is non-null
33
Taking true branch
2927 entry_str_data = (struct wdc_c2_cbs_data *)&entry_data->data;
2928 entry_len = le32_to_cpu(entry_str_data->length);
2929 entry_total_len = le32_to_cpu(entry_data->length);
2930 if (entry_total_len <
34
Assuming the condition is true
35
Taking true branch
2931 sizeof(struct wdc_c2_log_subpage_header))
2932 return false0;
36
Returning without writing to '*ret_data_len'
2933 max_payload_len = entry_total_len -
2934 sizeof(struct wdc_c2_log_subpage_header);
2935 if (entry_len > max_payload_len ||
2936 entry_len >= ret_data_size)
2937 return false0;
2938 memcpy(ret_data,
2939 (void *)&entry_str_data->data,
2940 entry_len);
2941 ret_data[entry_len] = '\0';
2942 *ret_data_len = entry_len;
2943 return true1;
2944 }
2945 }
2946
2947 *ret_data = 0;
2948 *ret_data_len = 0;
2949 return false0;
2950}
2951
2952static bool_Bool wdc_nvme_get_dev_status_log_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, __le32 *ret_data,
2953 __u8 log_id)
2954{
2955 __u32 *cbs_data = NULL((void*)0);
2956
2957 if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data)) {
2958 if (cbs_data) {
2959 memcpy((void *)ret_data, (void *)cbs_data, 4);
2960 free(cbs_data);
2961
2962 return true1;
2963 }
2964 }
2965
2966 *ret_data = 0;
2967 return false0;
2968}
2969
2970static int wdc_do_clear_dump(struct libnvme_transport_handle *hdl, __u8 opcode, __u32 cdw12)
2971{
2972 int ret;
2973 struct libnvme_passthru_cmd admin_cmd;
2974
2975 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2976 admin_cmd.opcode = opcode;
2977 admin_cmd.cdw12 = cdw12;
2978 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
2979 if (ret)
2980 fprintf(stdoutstdout, "ERROR: WDC: Crash dump erase failed\n");
2981 nvme_show_status(ret);
2982 return ret;
2983}
2984
2985static __u32 wdc_dump_length(struct libnvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length)
2986{
2987 int ret;
2988 __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN0x08] = {0};
2989 struct wdc_log_size *l;
2990 struct libnvme_passthru_cmd admin_cmd;
2991
2992 l = (struct wdc_log_size *) buf;
2993 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
2994 admin_cmd.opcode = opcode;
2995 admin_cmd.addr = (__u64)(uintptr_t)buf;
2996 admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN0x08;
2997 admin_cmd.cdw10 = cdw10;
2998 admin_cmd.cdw12 = cdw12;
2999
3000 ret = libnvme_exec_admin_passthru(link, &admin_cmd);
3001 if (ret) {
3002 l->log_size = 0;
3003 ret = -1;
3004 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3005 nvme_show_status(ret);
3006 return ret;
3007 }
3008
3009 if (opcode == WDC_NVME_CAP_DIAG_OPCODE0xE6)
3010 *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07];
3011 else
3012 *dump_length = le32_to_cpu(l->log_size);
3013 return ret;
3014}
3015
3016static __u32 wdc_dump_length_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
3017{
3018 int ret;
3019 struct libnvme_passthru_cmd admin_cmd;
3020
3021 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3022 admin_cmd.opcode = opcode;
3023 admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
3024 admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3025 admin_cmd.cdw10 = cdw10;
3026 admin_cmd.cdw12 = cdw12;
3027
3028 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3029 if (ret) {
3030 nvme_show_error("ERROR: WDC: reading dump length failed")nvme_show_message(1, "ERROR: WDC: reading dump length failed"
)
;
3031 nvme_show_status(ret);
3032 }
3033
3034 return ret;
3035}
3036
3037static __u32 wdc_dump_dui_data(struct libnvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool_Bool last_xfer)
3038{
3039 int ret;
3040 struct libnvme_passthru_cmd admin_cmd;
3041
3042 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3043 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3044 admin_cmd.nsid = 0xFFFFFFFF;
3045 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3046 admin_cmd.data_len = dataLen;
3047 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3048 admin_cmd.cdw12 = offset;
3049 if (last_xfer)
3050 admin_cmd.cdw14 = 0;
3051 else
3052 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3053
3054
3055 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3056 if (ret) {
3057 nvme_show_error("ERROR: WDC: reading DUI data failed")nvme_show_message(1, "ERROR: WDC: reading DUI data failed");
3058 nvme_show_status(ret);
3059 }
3060
3061 return ret;
3062}
3063
3064static __u32 wdc_dump_dui_data_v2(struct libnvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool_Bool last_xfer)
3065{
3066 int ret;
3067 struct libnvme_passthru_cmd admin_cmd;
3068 __u64 offset_lo, offset_hi;
3069
3070 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3071 admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE0xFA;
3072 admin_cmd.nsid = 0xFFFFFFFF;
3073 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3074 admin_cmd.data_len = dataLen;
3075 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
3076 offset_lo = offset & 0x00000000FFFFFFFF;
3077 offset_hi = ((offset & 0xFFFFFFFF00000000) >> 32);
3078 admin_cmd.cdw12 = (__u32)offset_lo;
3079 admin_cmd.cdw13 = (__u32)offset_hi;
3080
3081 if (last_xfer)
3082 admin_cmd.cdw14 = 0;
3083 else
3084 admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO0x01;
3085
3086 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3087 if (ret) {
3088 nvme_show_error("ERROR: WDC: reading DUI data V2 failed")nvme_show_message(1, "ERROR: WDC: reading DUI data V2 failed"
)
;
3089 nvme_show_status(ret);
3090 }
3091
3092 return ret;
3093}
3094
3095static int wdc_do_dump(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3096 __u32 cdw12, const char *file, __u32 xfer_size)
3097{
3098 int ret = 0;
3099 __u8 *dump_data;
3100 __u32 curr_data_offset, curr_data_len;
3101 int i;
3102 struct libnvme_passthru_cmd admin_cmd;
3103 __u32 dump_length = data_len;
3104
3105 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
3106 if (!dump_data) {
3107 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3108 return -1;
3109 }
3110 memset(dump_data, 0, sizeof(__u8) * dump_length);
3111 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3112 curr_data_offset = 0;
3113 curr_data_len = xfer_size;
3114 i = 0;
3115
3116 admin_cmd.opcode = opcode;
3117 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
3118 admin_cmd.data_len = curr_data_len;
3119 admin_cmd.cdw10 = curr_data_len >> 2;
3120 admin_cmd.cdw12 = cdw12;
3121 admin_cmd.cdw13 = curr_data_offset;
3122
3123 while (curr_data_offset < data_len) {
3124 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3125 if (ret) {
3126 nvme_show_status(ret);
3127 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)
3128 __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)
;
3129 break;
3130 }
3131
3132 if ((curr_data_offset + xfer_size) <= data_len)
3133 curr_data_len = xfer_size;
3134 else
3135 curr_data_len = data_len - curr_data_offset; /* last transfer */
3136
3137 curr_data_offset += curr_data_len;
3138 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3139 admin_cmd.data_len = curr_data_len;
3140 admin_cmd.cdw10 = curr_data_len >> 2;
3141 admin_cmd.cdw13 = curr_data_offset >> 2;
3142 i++;
3143 }
3144
3145 if (!ret) {
3146 nvme_show_status(ret);
3147 ret = wdc_create_log_file(file, dump_data, dump_length);
3148 }
3149 free(dump_data);
3150 return ret;
3151}
3152
3153static int wdc_do_dump_e6(struct libnvme_transport_handle *hdl, __u32 opcode, __u32 data_len,
3154 __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
3155{
3156 int ret = 0;
3157 __u8 *dump_data;
3158 __u32 curr_data_offset, log_size;
3159 int i;
3160 struct libnvme_passthru_cmd admin_cmd;
3161
3162 /* data_len is device-supplied and must hold the header copied in below */
3163 if (data_len < WDC_NVME_LOG_SIZE_HDR_LEN0x08) {
3164 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)
3165 __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)
;
3166 return -EINVAL22;
3167 }
3168
3169 /* if data_len is not 4 byte aligned */
3170 if (data_len & 0x00000003) {
3171 /* Round down to the next 4 byte aligned value */
3172 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)
3173 __func__, data_len)nvme_show_message(1, "%s: INFO: data_len 0x%x not 4 byte aligned."
, __func__, data_len)
;
3174 data_len &= 0xFFFFFFFC;
3175 nvme_show_error("%s: INFO: Round down to 0x%x.",nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, data_len)
3176 __func__, data_len)nvme_show_message(1, "%s: INFO: Round down to 0x%x.", __func__
, data_len)
;
3177 }
3178
3179 dump_data = (__u8 *)malloc(sizeof(__u8) * data_len);
3180
3181 if (!dump_data) {
3182 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3183 return -1;
3184 }
3185 memset(dump_data, 0, sizeof(__u8) * data_len);
3186 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3187 curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN0x08;
3188 i = 0;
3189
3190 /* copy the 8 byte header into the dump_data buffer */
3191 memcpy(dump_data, log_hdr, WDC_NVME_LOG_SIZE_HDR_LEN0x08);
3192
3193 admin_cmd.opcode = opcode;
3194 admin_cmd.cdw12 = cdw12;
3195
3196 /* subtract off the header size since that was already copied into the buffer */
3197 log_size = (data_len - curr_data_offset);
3198 while (log_size > 0) {
3199 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; })
;
3200
3201 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
3202 admin_cmd.data_len = xfer_size;
3203 admin_cmd.cdw10 = xfer_size >> 2;
3204 admin_cmd.cdw13 = curr_data_offset >> 2;
3205
3206 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3207 if (ret) {
3208 nvme_show_status(ret);
3209 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)
3210 __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)
;
3211 break;
3212 }
3213
3214 log_size -= xfer_size;
3215 curr_data_offset += xfer_size;
3216 i++;
3217 }
3218
3219 if (!ret) {
3220 nvme_show_error("%s: INFO: ", __func__)nvme_show_message(1, "%s: INFO: ", __func__);
3221 nvme_show_status(ret);
3222 } else {
3223 nvme_show_error("%s: FAILURE: ", __func__)nvme_show_message(1, "%s: FAILURE: ", __func__);
3224 nvme_show_status(ret);
3225 nvme_show_error("%s: Partial data may have been captured", __func__)nvme_show_message(1, "%s: Partial data may have been captured"
, __func__)
;
3226 snprintf(file + strlen(file), PATH_MAX4096, "%s", "-PARTIAL");
3227 }
3228
3229 ret = wdc_create_log_file(file, dump_data, data_len);
3230
3231 free(dump_data);
3232 return ret;
3233}
3234
3235static int wdc_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
3236 struct libnvme_transport_handle *hdl, const char *file,
3237 __u32 bs, int type, int data_area)
3238{
3239 struct nvme_telemetry_log *log;
3240 size_t full_size = 0;
3241 int err = 0, output;
3242 int ctrl_init = 0;
3243 __u64 result;
3244 void *buf = NULL((void*)0);
3245 struct libnvme_passthru_cmd cmd;
3246 struct nvme_id_ctrl ctrl;
3247 __u64 capabilities = 0;
3248
3249 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
3250 nvme_init_identify_ctrl(&cmd, &ctrl);
3251 err = libnvme_exec_admin_passthru(hdl, &cmd);
3252 if (err) {
3253 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)
;
3254 return err;
3255 }
3256
3257 if (!(ctrl.lpa & 0x8)) {
3258 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"
)
;
3259 return -EINVAL22;
3260 }
3261
3262 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3263 if (err) {
3264 nvme_show_error("Failed to scan nvme subsystems")nvme_show_message(1, "Failed to scan nvme subsystems");
3265 return err;
3266 }
3267
3268 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3269
3270 if (type == WDC_TELEMETRY_TYPE_HOST0x1) {
3271 ctrl_init = 0;
3272 } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2) {
3273 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
3274 /* Verify the Controller Initiated Option is enabled */
3275 err = nvme_get_features(hdl, 0,
3276 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
3277 NVME_GET_FEATURES_SEL_CURRENT, 0, 0,
3278 buf, 4, &result);
3279 if (!err) {
3280 if (!result) {
3281 /* enabled */
3282 ctrl_init = 1;
3283 } else {
3284 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__)
;
3285 return -EINVAL22;
3286 }
3287 } else {
3288 nvme_show_error("ERROR: WDC: Get telemetry option feature failed.")nvme_show_message(1, "ERROR: WDC: Get telemetry option feature failed."
)
;
3289 nvme_show_status(err);
3290 return -EPERM1;
3291 }
3292 } else {
3293 ctrl_init = 1;
3294 }
3295 } else {
3296 nvme_show_error("%s: Invalid type parameter; type = %d", __func__, type)nvme_show_message(1, "%s: Invalid type parameter; type = %d",
__func__, type)
;
3297 return -EINVAL22;
3298 }
3299
3300 if (!file) {
3301 nvme_show_error("%s: Please provide an output file!", __func__)nvme_show_message(1, "%s: Please provide an output file!", __func__
)
;
3302 return -EINVAL22;
3303 }
3304
3305 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3306 if (output < 0) {
3307 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 ())))
3308 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3309 return output;
3310 }
3311
3312 if (ctrl_init)
3313 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
3314 data_area, &full_size);
3315 else
3316 err = libnvme_get_new_host_telemetry(hdl, &log,
3317 data_area, &full_size);
3318
3319 if (err < 0) {
3320 nvme_show_err(err, "get-telemetry-log");
3321 goto close_output;
3322 } else if (err > 0) {
3323 nvme_show_status(err);
3324 nvme_show_error("%s: Failed to acquire telemetry header!", __func__)nvme_show_message(1, "%s: Failed to acquire telemetry header!"
, __func__)
;
3325 goto close_output;
3326 }
3327
3328 /*
3329 * Continuously pull data until the offset hits the end of the last
3330 * block.
3331 */
3332 err = shr_write_all(output, log, full_size);
3333 if (err)
3334 nvme_show_error("ERROR: %s: write: %s", __func__, libnvme_strerror(-err))nvme_show_message(1, "ERROR: %s: write: %s", __func__, libnvme_strerror
(-err))
;
3335 else if (shr_fsync(output) < 0) {
3336 nvme_show_error("ERROR: %s: fsync: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "ERROR: %s: fsync: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3337 err = -1;
3338 }
3339
3340 free(log);
3341close_output:
3342 close(output);
3343 return err;
3344}
3345
3346static int wdc_do_cap_diag(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *file,
3347 __u32 xfer_size, int type, int data_area)
3348{
3349 int ret = -1;
3350 __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08;
3351 struct wdc_e6_log_hdr *log_hdr;
3352 __u32 cap_diag_length;
3353
3354 log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size);
3355 if (!log_hdr) {
3356 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
3357 ret = -1;
3358 goto out;
3359 }
3360 memset(log_hdr, 0, e6_log_hdr_size);
3361
3362 if (type == WDC_TELEMETRY_TYPE_NONE0x0) {
3363 if (data_area) {
3364 nvme_show_error(nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
3365 "%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__)
3366 __func__)nvme_show_message(1, "%s: ERROR: Data area parameter is not supported when type is NONE\n"
, __func__)
;
3367 ret = -1;
3368 goto out;
3369 }
3370 ret = wdc_dump_length_e6(hdl,
3371 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3372 WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE0x08>>2,
3373 0x00,
3374 log_hdr);
3375 if (ret == -1) {
3376 ret = -1;
3377 goto out;
3378 }
3379
3380 cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 |
3381 log_hdr->log_size[2] << 8 | log_hdr->log_size[3]);
3382
3383 if (!cap_diag_length) {
3384 nvme_show_error("INFO: WDC: Capture Diagnostics log is empty")nvme_show_message(1, "INFO: WDC: Capture Diagnostics log is empty"
)
;
3385 } else if (cap_diag_length < WDC_NVME_LOG_SIZE_HDR_LEN0x08) {
3386 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)
3387 __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)
;
3388 ret = -1;
3389 } else if (cap_diag_length > WDC_NVME_CAP_DIAG_LENGTH_MAX(1U << 30)) {
3390 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))
3391 __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))
;
3392 ret = -1;
3393 } else {
3394 ret = wdc_do_dump_e6(hdl,
3395 WDC_NVME_CAP_DIAG_OPCODE0xE6,
3396 cap_diag_length,
3397 (WDC_NVME_CAP_DIAG_SUBCMD0x00 << WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_CAP_DIAG_CMD0x00,
3398 file, xfer_size, (__u8 *)log_hdr);
3399
3400 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)
;
3401 }
3402 } else if ((type == WDC_TELEMETRY_TYPE_HOST0x1) ||
3403 (type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
3404 /* Get the desired telemetry log page */
3405 ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size,
3406 type, data_area);
3407 } else {
3408 nvme_show_error("%s: ERROR: Invalid type : %d", __func__, type)nvme_show_message(1, "%s: ERROR: Invalid type : %d", __func__
, type)
;
3409 }
3410
3411out:
3412 free(log_hdr);
3413 return ret;
3414}
3415
3416static int wdc_do_cap_dui_v1(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3417 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size)
3418{
3419 __s32 log_size = 0;
3420 __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size);
3421 __u32 curr_data_offset = 0;
3422 __u8 *buffer_addr;
3423 __u8 *dump_data = NULL((void*)0);
3424 bool_Bool last_xfer = false0;
3425 int err;
3426 int i;
3427 int j;
3428 int output;
3429 int ret = 0;
3430
3431 if (verbose) {
3432 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)
3433 data_area)nvme_show_message(1, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d"
, data_area)
;
3434 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)
;
3435 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)
;
3436 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)
;
3437 }
3438
3439 if (!cap_dui_length) {
3440 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"
)
;
3441 return 0;
3442 }
3443
3444 /* parse log header for all sections up to specified data area inclusively */
3445 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3446 for (j = 0; j < log_hdr->section_count; j++) {
3447 log_size += log_hdr->log_section[j].section_size;
3448 if (verbose)
3449 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)
3450 "%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)
3451 __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)
3452 (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)
3453 (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)
;
3454
3455 }
3456 } else {
3457 log_size = cap_dui_length;
3458 }
3459
3460 *total_size = log_size;
3461
3462 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size);
3463 if (!dump_data) {
3464 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)
3465 __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)
;
3466 return -1;
3467 }
3468 memset(dump_data, 0, sizeof(__u8) * xfer_size);
3469
3470 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3471 if (output < 0) {
3472 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 ())))
3473 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3474 free(dump_data);
3475 return output;
3476 }
3477
3478 /* write the telemetry and log headers into the dump_file */
3479 err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE0x400);
3480 if (err != WDC_NVME_CAP_DUI_HEADER_SIZE0x400) {
3481 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__)
;
3482 goto free_mem;
3483 }
3484
3485 log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3486 curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3487 i = 0;
3488 buffer_addr = dump_data;
3489
3490 for (; log_size > 0; log_size -= xfer_size) {
3491 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; })
;
3492
3493 if (log_size <= xfer_size)
3494 last_xfer = true1;
3495
3496 ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer);
3497 if (ret) {
3498 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)
3499 "%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)
3500 __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)
;
3501 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3502 nvme_show_status(ret);
3503 break;
3504 }
3505
3506 /* write the dump data into the file */
3507 err = write(output, (void *)buffer_addr, xfer_size);
3508 if (err != xfer_size) {
3509 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)
3510 "%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)
3511 __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)
;
3512 ret = -1;
3513 goto free_mem;
3514 }
3515
3516 curr_data_offset += xfer_size;
3517 i++;
3518 }
3519
3520free_mem:
3521 close(output);
3522 free(dump_data);
3523 return ret;
3524}
3525
3526static int wdc_do_cap_dui_v2_v3(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3527 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3528 __u64 offset)
3529{
3530 __u64 cap_dui_length_v3;
3531 __u64 curr_data_offset = 0;
3532 __s64 log_size = 0;
3533 __u64 xfer_size_long = (__u64)xfer_size;
3534 __u8 *buffer_addr;
3535 __u8 *dump_data = NULL((void*)0);
3536 bool_Bool last_xfer = false0;
3537 int err;
3538 int i;
3539 int j;
3540 int output;
3541 int ret = 0;
3542 struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr;
3543
3544 cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size);
3545
3546 if (verbose) {
3547 nvme_show_error(nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
3548 "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)
3549 data_area)nvme_show_message(1, "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n"
, data_area)
;
3550
3551 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)
3552 log_hdr_v3->hdr_version)nvme_show_message(1, "INFO: WDC: DUI Header Version = 0x%x", log_hdr_v3
->hdr_version)
;
3553 if ((log_hdr->hdr_version & 0xFF) == 0x03)
3554 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)
3555 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)
;
3556 }
3557
3558 if (!cap_dui_length_v3) {
3559 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"
)
;
3560 return 0;
3561 }
3562
3563 /* parse log header for all sections up to specified data area inclusively */
3564 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3565 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V30x23; j++) {
3566 if (log_hdr_v3->log_section[j].data_area_id <= data_area &&
3567 log_hdr_v3->log_section[j].data_area_id) {
3568 log_size += log_hdr_v3->log_section[j].section_size;
3569 if (verbose)
3570 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)
3571 "%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)
3572 __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)
3573 (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)
3574 (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)
;
3575 } else {
3576 if (verbose)
3577 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)
3578 __func__, (uint64_t)log_size)nvme_show_message(1, "%s: break, total size = 0x%""l" "x""\n"
, __func__, (uint64_t)log_size)
;
3579 break;
3580 }
3581 }
3582 } else {
3583 log_size = cap_dui_length_v3;
3584 }
3585
3586 *total_size = log_size;
3587
3588 if (offset >= *total_size) {
3589 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)
3590 "%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)
3591 __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)
;
3592 return -1;
3593 }
3594
3595 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3596 if (!dump_data) {
3597 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)
3598 "%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)
3599 __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)
;
3600 return -1;
3601 }
3602 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3603
3604 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3605 if (output < 0) {
3606 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 ())))
3607 __func__, file, libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3608 free(dump_data);
3609 return output;
3610 }
3611
3612 curr_data_offset = 0;
3613
3614 if (file_size) {
3615 /* Write the DUI data based on the passed in file size */
3616 if ((offset + file_size) > *total_size)
3617 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; })
;
3618 else
3619 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; })
;
3620
3621 if (verbose)
3622 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)
3623 "%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)
3624 __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)
3625 (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)
;
3626
3627 curr_data_offset = offset;
3628 }
3629
3630 i = 0;
3631 buffer_addr = dump_data;
3632
3633 for (; log_size > 0; log_size -= xfer_size_long) {
3634 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; })
;
3635
3636 if (log_size <= xfer_size_long)
3637 last_xfer = true1;
3638
3639 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr,
3640 last_xfer);
3641 if (ret) {
3642 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
)
3643 "%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
)
3644 __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
)
3645 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
)
;
3646 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3647 nvme_show_status(ret);
3648 break;
3649 }
3650
3651 /* write the dump data into the file */
3652 err = write(output, (void *)buffer_addr, xfer_size_long);
3653 if (err != xfer_size_long) {
3654 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)
3655 "%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)
3656 __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)
;
3657 ret = -1;
3658 goto free_mem;
3659 }
3660
3661 curr_data_offset += xfer_size_long;
3662 i++;
3663 }
3664
3665free_mem:
3666 close(output);
3667 free(dump_data);
3668 return ret;
3669}
3670
3671static int wdc_do_cap_dui_v4(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3672 struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size,
3673 __u64 offset)
3674{
3675 __s64 log_size = 0;
3676 __s64 section_size_bytes = 0;
3677 __s64 xfer_size_long = (__s64)xfer_size;
3678 __u64 cap_dui_length_v4;
3679 __u64 curr_data_offset = 0;
3680 __u8 *buffer_addr;
3681 __u8 *dump_data = NULL((void*)0);
3682 int err;
3683 int i;
3684 int j;
3685 int output;
3686 int ret = 0;
3687 bool_Bool last_xfer = false0;
3688 struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr;
3689
3690 cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE512;
3691
3692 if (verbose) {
3693 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)
;
3694 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)
;
3695 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)
;
3696 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)
;
3697 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)
;
3698 }
3699
3700 if (!cap_dui_length_v4) {
3701 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"
)
;
3702 return 0;
3703 }
3704
3705 /* parse log header for all sections up to specified data area inclusively */
3706 if (data_area != WDC_NVME_DUI_MAX_DATA_AREA0x05) {
3707 for (j = 0; j < WDC_NVME_DUI_MAX_SECTION0x3A; j++) {
3708 if (log_hdr_v4->log_section[j].data_area_id <= data_area &&
3709 log_hdr_v4->log_section[j].data_area_id) {
3710 section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE512);
3711 log_size += section_size_bytes;
3712 if (verbose)
3713 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)
3714 "%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)
3715 __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)
3716 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)
3717 (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)
;
3718 } else {
3719 if (verbose)
3720 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)
;
3721 break;
3722 }
3723 }
3724 } else {
3725 log_size = cap_dui_length_v4;
3726 }
3727
3728 *total_size = log_size;
3729
3730 if (offset >= *total_size) {
3731 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)
3732 "%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)
3733 __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)
;
3734 return -1;
3735 }
3736
3737 dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long);
3738 if (!dump_data) {
3739 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)
3740 __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)
;
3741 return -1;
3742 }
3743 memset(dump_data, 0, sizeof(__u8) * xfer_size_long);
3744
3745 output = shr_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
3746 if (output < 0) {
3747 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 ())))
3748 libnvme_strerror(errno))nvme_show_message(1, "%s: Failed to open output file %s: %s!"
, __func__, file, libnvme_strerror((*__errno_location ())))
;
3749 free(dump_data);
3750 return output;
3751 }
3752
3753 curr_data_offset = 0;
3754
3755 if (file_size) {
3756 /* Write the DUI data based on the passed in file size */
3757 if ((offset + file_size) > *total_size)
3758 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; })
;
3759 else
3760 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; })
;
3761
3762 if (verbose)
3763 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)
3764 "%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)
3765 __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)
3766 (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)
;
3767
3768 curr_data_offset = offset;
3769 }
3770
3771 i = 0;
3772 buffer_addr = dump_data;
3773
3774 for (; log_size > 0; log_size -= xfer_size_long) {
3775 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; })
;
3776
3777 if (log_size <= xfer_size_long)
3778 last_xfer = true1;
3779
3780 ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer);
3781 if (ret) {
3782 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)
3783 "%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)
3784 __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)
3785 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)
;
3786 nvme_show_error("%s: ERROR: WDC:", __func__)nvme_show_message(1, "%s: ERROR: WDC:", __func__);
3787 nvme_show_status(ret);
3788 break;
3789 }
3790
3791 /* write the dump data into the file */
3792 err = write(output, (void *)buffer_addr, xfer_size_long);
3793 if (err != xfer_size_long) {
3794 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)
3795 "%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)
3796 __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)
;
3797 ret = -1;
3798 goto free_mem;
3799 }
3800
3801 curr_data_offset += xfer_size_long;
3802 i++;
3803 }
3804
3805free_mem:
3806 close(output);
3807 free(dump_data);
3808 return ret;
3809}
3810
3811static int wdc_do_cap_dui(struct libnvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose,
3812 __u64 file_size, __u64 offset)
3813{
3814 int ret = 0;
3815 __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE0x400;
3816 struct wdc_dui_log_hdr *log_hdr;
3817 __s64 total_size = 0;
3818 bool_Bool last_xfer = false0;
3819
3820 log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size);
3821 if (!log_hdr) {
3822 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
)
3823 __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
)
;
3824 return -1;
3825 }
3826 memset(log_hdr, 0, dui_log_hdr_size);
3827
3828 /* get the dui telemetry and log headers */
3829 ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE0x400, 0x00, (__u8 *)log_hdr, last_xfer);
3830 if (ret) {
3831 nvme_show_error("%s: ERROR: WDC: Get DUI headers failed", __func__)nvme_show_message(1, "%s: ERROR: WDC: Get DUI headers failed"
, __func__)
;
3832 nvme_show_error("%s: ERROR: WDC: ", __func__)nvme_show_message(1, "%s: ERROR: WDC: ", __func__);
3833 nvme_show_status(ret);
3834 goto out;
3835 }
3836
3837 /* Check the Log Header version */
3838 if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) {
3839 ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr,
3840 &total_size);
3841 if (ret)
3842 goto out;
3843 } else if ((log_hdr->hdr_version & 0xFF) == 0x02 ||
3844 (log_hdr->hdr_version & 0xFF) == 0x03) {
3845 /* Process Version 2 or 3 header */
3846 ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr,
3847 &total_size, file_size, offset);
3848 if (ret)
3849 goto out;
3850 } else if ((log_hdr->hdr_version & 0xFF) == 0x04) {
3851 ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr,
3852 &total_size, file_size, offset);
3853 if (ret)
3854 goto out;
3855 } else {
3856 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)
3857 log_hdr->hdr_version)nvme_show_message(1, "INFO: WDC: Unsupported header version = 0x%x"
, log_hdr->hdr_version)
;
3858 goto out;
3859 }
3860
3861 nvme_show_status(ret);
3862 if (verbose)
3863 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)
3864 (uint64_t)total_size)nvme_show_message(1, "INFO: WDC: Capture Device Unit Info log, length = 0x%"
"l" "x""\n", (uint64_t)total_size)
;
3865
3866out:
3867 free(log_hdr);
3868 return ret;
3869}
3870
3871static int wdc_cap_diag(int argc, char **argv, struct command *acmd,
3872 struct plugin *plugin)
3873{
3874 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
3875 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
3876 const char *desc = "Capture Diagnostics Log.";
3877 const char *file = "Output file pathname.";
3878 const char *size = "Data retrieval transfer size.";
3879 __u64 capabilities = 0;
3880 char f[PATH_MAX4096] = {0};
3881 __u32 xfer_size = 0;
3882 int ret = 0;
3883
3884 struct config {
3885 char *file;
3886 __u32 xfer_size;
3887 };
3888
3889 struct config cfg = {
3890 .file = NULL((void*)0),
3891 .xfer_size = 0x10000
3892 };
3893
3894 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
3895 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, }
,
3896 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, }
,
3897 OPT_END(){ ((void*)0) }
3898 };
3899
3900 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3901 if (ret)
3902 return ret;
3903
3904 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
3905 if (ret)
3906 return ret;
3907
3908 if (cfg.file)
3909 shr_strscpy(f, cfg.file, sizeof(f));
3910 if (cfg.xfer_size)
3911 xfer_size = cfg.xfer_size;
3912 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "cap_diag");
3913 if (ret) {
3914 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
3915 return ret;
3916 }
3917 if (!cfg.file) {
3918 if (strlen(f) > PATH_MAX4096 - 5) {
3919 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
3920 return -1;
3921 }
3922 shr_strscat(f, ".bin", sizeof(f));
3923 }
3924
3925 capabilities = wdc_get_drive_capabilities(ctx, hdl);
3926 if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001) == WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001)
3927 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0);
3928 else
3929 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
3930 return ret;
3931}
3932
3933static int wdc_do_get_sn730_log_len(struct libnvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode)
3934{
3935 int ret;
3936 uint32_t *output = NULL((void*)0);
3937 struct libnvme_passthru_cmd admin_cmd;
3938
3939 output = (uint32_t *)malloc(sizeof(uint32_t));
3940 if (!output) {
3941 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3942 return -1;
3943 }
3944 memset(output, 0, sizeof(uint32_t));
3945 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3946
3947 admin_cmd.data_len = 8;
3948 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3949 admin_cmd.addr = (uintptr_t)output;
3950 admin_cmd.cdw12 = subopcode;
3951 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3952
3953 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3954 if (!ret)
3955 *len_buf = *output;
3956 free(output);
3957 return ret;
3958}
3959
3960static int wdc_do_get_sn730_log(struct libnvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode)
3961{
3962 int ret;
3963 uint8_t *output = NULL((void*)0);
3964 struct libnvme_passthru_cmd admin_cmd;
3965
3966 output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE0x1000, sizeof(uint8_t));
3967 if (!output) {
3968 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
3969 return -1;
3970 }
3971 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
3972 admin_cmd.data_len = SN730_LOG_CHUNK_SIZE0x1000;
3973 admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE0xc2;
3974 admin_cmd.addr = (uintptr_t)output;
3975 admin_cmd.cdw12 = subopcode;
3976 admin_cmd.cdw13 = offset;
3977 admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE0x1000 / 4;
3978
3979 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
3980 if (!ret)
3981 memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE0x1000);
3982 return ret;
3983}
3984
3985static int get_sn730_log_chunks(struct libnvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode)
3986{
3987 int ret = 0;
3988 uint8_t *chunk_buf = NULL((void*)0);
3989 int remaining = log_len;
3990 int curr_offset = 0;
3991
3992 chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE0x1000);
3993 if (!chunk_buf) {
3994 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
3995 ret = -1;
3996 goto out;
3997 }
3998
3999 while (remaining > 0) {
4000 memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE0x1000);
4001 ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode);
4002 if (!ret) {
4003 if (remaining >= SN730_LOG_CHUNK_SIZE0x1000) {
4004 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4005 chunk_buf, SN730_LOG_CHUNK_SIZE0x1000);
4006 } else {
4007 memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE0x1000),
4008 chunk_buf, remaining);
4009 }
4010 remaining -= SN730_LOG_CHUNK_SIZE0x1000;
4011 curr_offset += 1;
4012 } else {
4013 goto out;
4014 }
4015 }
4016out:
4017 free(chunk_buf);
4018 return ret;
4019}
4020
4021/* scandir() filter: regular ".bin" log files, skipping dotfiles. */
4022static int wdc_is_bin_file(const struct dirent *ent)
4023{
4024 size_t len = strlen(ent->d_name);
4025
4026 return ent->d_name[0] != '.' && len > 4 &&
4027 !strcmp(ent->d_name + len - 4, ".bin");
4028}
4029
4030/* scandir() filter: any entry, skipping dotfiles. */
4031static int wdc_is_log_file(const struct dirent *ent)
4032{
4033 return ent->d_name[0] != '.';
4034}
4035
4036static int wdc_dirent_cmp(const void *a, const void *b)
4037{
4038 const struct dirent *const *da = a;
4039 const struct dirent *const *db = b;
4040
4041 return strcmp((*da)->d_name, (*db)->d_name);
4042}
4043
4044/*
4045 * scandir() + alphasort() equivalent built on opendir()/readdir(): mingw's
4046 * dirent.h provides the latter but not the former.
4047 */
4048static int wdc_scandir(const char *dir, struct dirent ***namelist,
4049 int (*filter)(const struct dirent *))
4050{
4051 struct dirent *ent, **list = NULL((void*)0), **tmp;
4052 DIR *d;
4053 int n = 0;
4054
4055 d = opendir(dir);
4056 if (!d)
4057 return -1;
4058
4059 while ((ent = readdir(d))) {
4060 if (filter && !filter(ent))
4061 continue;
4062
4063 tmp = realloc(list, (n + 1) * sizeof(*list));
4064 if (!tmp)
4065 goto err;
4066 list = tmp;
4067
4068 list[n] = malloc(sizeof(*list[n]));
4069 if (!list[n])
4070 goto err;
4071 *list[n] = *ent;
4072 n++;
4073 }
4074
4075 closedir(d);
4076
4077 if (n > 0)
4078 qsort(list, n, sizeof(*list), wdc_dirent_cmp);
4079
4080 *namelist = list;
4081 return n;
4082
4083err:
4084 closedir(d);
4085 while (n > 0)
4086 free(list[--n]);
4087 free(list);
4088 return -1;
4089}
4090
4091/*
4092 * Archive dir's entries matching filter into tar_file (gzip), without
4093 * spawning an external process. If remove_after, delete the archived files
4094 * and dir itself once the archive is written, mirroring "tar --remove-files".
4095 */
4096static int wdc_tar_dir_files(const char *tar_file, const char *dir,
4097 int (*filter)(const struct dirent *),
4098 bool_Bool remove_after)
4099{
4100 __cleanup_dirents__attribute__((cleanup(cleanup_dirents))) struct dirents d = {};
4101 char **paths;
4102 int i, ret;
4103
4104 d.num = wdc_scandir(dir, &d.ents, filter);
4105 if (d.num <= 0) {
4106 nvme_show_error("ERROR: WDC: no log files found to archive")nvme_show_message(1, "ERROR: WDC: no log files found to archive"
)
;
4107 return -ENOENT2;
4108 }
4109
4110 paths = calloc(d.num, sizeof(*paths));
4111 if (!paths)
4112 return -ENOMEM12;
4113
4114 ret = 0;
4115 for (i = 0; i < d.num; i++) {
4116 if (asprintf(&paths[i], "%s%s%s", dir, WDC_DE_PATH_SEPARATOR"/",
4117 d.ents[i]->d_name) < 0) {
4118 ret = -ENOMEM12;
4119 break;
4120 }
4121 }
4122
4123 if (!ret) {
4124 ret = shr_tar_gz_create(tar_file,
4125 (const char *const *)paths, d.num);
4126 if (ret == -ENOTSUP95)
4127 nvme_show_error(nvme_show_message(1, "ERROR: WDC: nvme-cli was built without libarchive, archive creation is unavailable"
)
4128 "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"
)
;
4129 }
4130
4131 if (!ret && remove_after) {
4132 /*
4133 * Keep removing the rest even once something fails, but
4134 * report that first failure instead of the success the old
4135 * "tar --remove-files" exit status would no longer be here
4136 * to catch.
4137 */
4138 for (i = 0; i < d.num; i++) {
4139 if (unlink(paths[i]) && !ret)
4140 ret = -errno(*__errno_location ());
4141 }
4142 if (rmdir(dir) && !ret)
4143 ret = -errno(*__errno_location ());
4144 }
4145
4146 for (i = 0; i < d.num; i++)
4147 free(paths[i]);
4148 free(paths);
4149
4150 return ret;
4151}
4152
4153static int wdc_do_sn730_get_and_tar(struct libnvme_transport_handle *hdl, char *outputName)
4154{
4155 int ret = 0;
4156 void *retPtr;
4157 uint8_t *full_log_buf = NULL((void*)0);
4158 uint8_t *key_log_buf = NULL((void*)0);
4159 uint8_t *core_dump_log_buf = NULL((void*)0);
4160 uint8_t *extended_log_buf = NULL((void*)0);
4161 uint32_t full_log_len = 0;
4162 uint32_t key_log_len = 0;
4163 uint32_t core_dump_log_len = 0;
4164 uint32_t extended_log_len = 0;
4165 struct tarfile_metadata *tarInfo = NULL((void*)0);
4166
4167 tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata));
4168 if (!tarInfo) {
4169 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4170 ret = -1;
4171 goto free_buf;
4172 }
4173 memset(tarInfo, 0, sizeof(struct tarfile_metadata));
4174
4175 /* Create Logs directory */
4176 wdc_UtilsGetTime(&tarInfo->timeInfo);
4177 memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString));
4178 wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
4179 tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth,
4180 tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second);
4181
4182 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN256, "%s",
4183 (char *)outputName);
4184
4185 retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN256);
4186 if (retPtr) {
4187 wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
4188 (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR"/", (char *)tarInfo->bufferFolderName);
4189 } else {
4190 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
4191 goto free_buf;
4192 }
4193
4194 ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath);
4195 if (ret) {
4196 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)
;
4197 goto free_buf;
4198 } else {
4199 nvme_show_error("Stored log files in directory: %s", tarInfo->bufferFolderPath)nvme_show_message(1, "Stored log files in directory: %s", tarInfo
->bufferFolderPath)
;
4200 }
4201
4202 ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH0x00080009);
4203 if (ret) {
4204 nvme_show_status(ret);
4205 goto free_buf;
4206 }
4207 ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH0x00090009);
4208 if (ret) {
4209 nvme_show_status(ret);
4210 goto free_buf;
4211 }
4212 ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH0x00120009);
4213 if (ret) {
4214 nvme_show_status(ret);
4215 goto free_buf;
4216 }
4217 ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH0x00420009);
4218 if (ret) {
4219 nvme_show_status(ret);
4220 goto free_buf;
4221 }
4222
4223 full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t));
4224 key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t));
4225 core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t));
4226 extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t));
4227
4228 if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) {
4229 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4230 ret = -1;
4231 goto free_buf;
4232 }
4233
4234 /* Get the full log */
4235 ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE0x00010009);
4236 if (ret) {
4237 nvme_show_status(ret);
4238 goto free_buf;
4239 }
4240
4241 /* Get the key log */
4242 ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE0x00020009);
4243 if (ret) {
4244 nvme_show_status(ret);
4245 goto free_buf;
4246 }
4247
4248 /* Get the core dump log */
4249 ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE0x00030009);
4250 if (ret) {
4251 nvme_show_status(ret);
4252 goto free_buf;
4253 }
4254
4255 /* Get the extended log */
4256 ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE0x00040009);
4257 if (ret) {
4258 nvme_show_status(ret);
4259 goto free_buf;
4260 }
4261
4262 /* Write log files */
4263 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4264 "full_log", (char *)tarInfo->timeString);
4265 wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len);
4266
4267 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4268 "key_log", (char *)tarInfo->timeString);
4269 wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len);
4270
4271 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4272 "core_dump_log", (char *)tarInfo->timeString);
4273 wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len);
4274
4275 wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN256, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
4276 "extended_log", (char *)tarInfo->timeString);
4277 wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len);
4278
4279 /* Tar the log directory */
4280 wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
4281 ret = wdc_tar_dir_files(tarInfo->tarFileName,
4282 (char *)tarInfo->bufferFolderName,
4283 wdc_is_bin_file, false0);
4284
4285 if (ret)
4286 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)
;
4287
4288free_buf:
4289 free(tarInfo);
4290 free(full_log_buf);
4291 free(core_dump_log_buf);
4292 free(key_log_buf);
4293 free(extended_log_buf);
4294 return ret;
4295}
4296
4297static int dump_internal_logs(struct libnvme_transport_handle *hdl, const char *dir_name, int verbose)
4298{
4299 char file_path[PATH_MAX4096];
4300 void *telemetry_log;
4301 const size_t bs = 512;
4302 struct nvme_telemetry_log *hdr;
4303 struct libnvme_passthru_cmd cmd;
4304 size_t full_size, offset = bs;
4305 int err, output;
4306
4307 if (verbose)
4308 printf("NVMe Telemetry log...\n");
4309
4310 hdr = malloc(bs);
4311 telemetry_log = malloc(bs);
4312 if (!hdr || !telemetry_log) {
4313 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 ())))
;
4314 err = -ENOMEM12;
4315 goto free_mem;
4316 }
4317 memset(hdr, 0, bs);
4318
4319 snprintf(file_path, sizeof(file_path), "%s/telemetry.bin", dir_name);
4320 output = shr_open_rawdata(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file_path), (01 | 0100 | 01000), 0666);
4321 if (output < 0) {
4322 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 ())))
;
4323 err = output;
4324 goto free_mem;
4325 }
4326
4327 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4328 NVME_CSI_NVM, hdr, bs);
4329 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))
4330 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
4331 NVME_LOG_CDW10_LSP_MASK)(((__u32)(NVME_LOG_TELEM_HOST_LSP_CREATE) & (NVME_LOG_CDW10_LSP_MASK
)) << (NVME_LOG_CDW10_LSP_SHIFT))
;
4332 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4333 if (err < 0)
4334 nvme_show_err(err, "get-telemetry-log");
4335 else if (err > 0) {
4336 nvme_show_status(err);
4337 nvme_show_error("Failed to acquire telemetry header %d!", err)nvme_show_message(1, "Failed to acquire telemetry header %d!"
, err)
;
4338 goto close_output;
4339 }
4340
4341 err = write(output, (void *)hdr, bs);
4342 if (err != bs) {
4343 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4344 goto close_output;
4345 }
4346
4347 full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
4348
4349 while (offset != full_size) {
4350 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST,
4351 NVME_CSI_NVM, telemetry_log, bs);
4352 nvme_init_get_log_lpo(&cmd, offset);
4353 err = libnvme_get_log(hdl, &cmd, true1, NVME_LOG_PAGE_PDU_SIZE4096);
4354 if (err < 0) {
4355 nvme_show_err(err, "get-telemetry-log");
4356 break;
4357 } else if (err > 0) {
4358 nvme_show_error("Failed to acquire full telemetry log!")nvme_show_message(1, "Failed to acquire full telemetry log!");
4359 nvme_show_status(err);
4360 break;
4361 }
4362
4363 err = write(output, (void *)telemetry_log, bs);
4364 if (err != bs) {
4365 nvme_show_error("Failed to flush all data to file!")nvme_show_message(1, "Failed to flush all data to file!");
4366 break;
4367 }
4368 err = 0;
4369 offset += bs;
4370 }
4371
4372close_output:
4373 close(output);
4374free_mem:
4375 free(hdr);
4376 free(telemetry_log);
4377
4378 return err;
4379}
4380
4381static int wdc_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
4382 int *data_area)
4383{
4384 struct libnvme_passthru_cmd cmd;
4385 struct nvme_id_ctrl ctrl;
4386 int err;
4387
4388 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
4389 nvme_init_identify_ctrl(&cmd, &ctrl);
4390 err = libnvme_exec_admin_passthru(hdl, &cmd);
4391 if (err) {
4392 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)
;
4393 return err;
4394 }
4395
4396 if (ctrl.lpa & 0x40)
4397 *data_area = 4;
4398 else
4399 *data_area = 3;
4400
4401 return 0;
4402}
4403
4404static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd,
4405 struct plugin *plugin)
4406{
4407 const char *desc = "Internal Firmware Log.";
4408 const char *file = "Output file pathname.";
4409 const char *size = "Data retrieval transfer size.";
4410 const char *data_area =
4411 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
4412 const char *type =
4413 "Telemetry type - NONE, HOST, or CONTROLLER:\n" \
4414 " NONE - Default, capture without using NVMe telemetry.\n" \
4415 " HOST - Host-initiated telemetry.\n" \
4416 " CONTROLLER - Controller-initiated telemetry.";
4417 const char *file_size =
4418 "Output file size. Deprecated, see man page for supported devices.";
4419 const char *offset =
4420 "Output file data offset. Deprecated, see man page for supported devices.";
4421 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4422 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4423 int ret = -1;
4424
4425 struct argconfig_opt_val types[] = {
4426 VAL_ENUM("NONE", WDC_TELEMETRY_TYPE_NONE){"NONE", CFG_ENUM, .val.int_val = 0x0},
4427 VAL_ENUM("HOST", WDC_TELEMETRY_TYPE_HOST){"HOST", CFG_ENUM, .val.int_val = 0x1},
4428 VAL_ENUM("CONTROLLER", WDC_TELEMETRY_TYPE_CONTROLLER){"CONTROLLER", CFG_ENUM, .val.int_val = 0x2},
4429 VAL_END(){ ((void*)0) }
4430 };
4431
4432 struct wdc_vs_internal_fw_log_cfg cfg = {
4433 .file = NULL((void*)0),
4434 .xfer_size = 0x10000,
4435 .data_area = 0,
4436 .file_size = 0,
4437 .offset = 0,
4438 .type = WDC_TELEMETRY_TYPE_NONE0x0,
4439 };
4440
4441 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4442 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, }
,
4443 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, }
,
4444 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, }
,
4445 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, }
,
4446 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, }
,
4447 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, }
,
4448 OPT_END(){ ((void*)0) }
4449 };
4450
4451 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4452 if (ret)
4453 return ret;
4454
4455 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4456 if (ret)
4457 return ret;
4458
4459 return run_wdc_vs_internal_fw_log(ctx, hdl, &cfg);
4460}
4461
4462int run_wdc_vs_internal_fw_log(struct libnvme_global_ctx *ctx,
4463 struct libnvme_transport_handle *hdl,
4464 struct wdc_vs_internal_fw_log_cfg *cfg)
4465{
4466 char f[PATH_MAX4096] = {0};
4467 char fb[PATH_MAX4096/2] = {0};
4468 char fileSuffix[PATH_MAX4096] = {0};
4469 __u32 xfer_size = 0;
4470 int telemetry_type = 0, telemetry_data_area = 0;
4471 UtilsTimeInfo timeInfo;
4472 __u8 timeStamp[MAX_PATH_LEN256];
4473 __u64 capabilities = 0;
4474 __u32 device_id, read_vendor_id;
4475 char file_path[PATH_MAX4096/2] = {0};
4476 int ret = 0;
4477
4478 if (!wdc_check_device(ctx, hdl))
4479 goto out;
4480
4481 if (cfg->xfer_size) {
4482 xfer_size = cfg->xfer_size;
4483 } else {
4484 nvme_show_error("ERROR: WDC: Invalid length")nvme_show_message(1, "ERROR: WDC: Invalid length");
4485 goto out;
4486 }
4487
4488 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4489
4490 if (!wdc_is_sn861(device_id)) {
4491 if (cfg->file) {
4492 int verify_file;
4493
4494 /* verify file name and path is valid before getting dump data */
4495 verify_file = shr_open_rawdata(cfg->file,open((cfg->file), (01 | 0100 | 01000), 0666)
4496 O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg->file), (01 | 0100 | 01000), 0666);
4497 if (verify_file < 0) {
4498 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
4499 goto out;
4500 }
4501 close(verify_file);
4502 shr_strscpy(f, cfg->file, sizeof(f));
4503 } else {
4504 wdc_UtilsGetTime(&timeInfo);
4505 memset(timeStamp, 0, sizeof(timeStamp));
4506 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4507 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4508 timeInfo.month, timeInfo.dayOfMonth,
4509 timeInfo.hour, timeInfo.minute,
4510 timeInfo.second);
4511 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4512
4513 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix);
4514 if (ret) {
4515 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4516 goto out;
4517 }
4518 }
4519
4520 if (!cfg->file) {
4521 if (strlen(f) > PATH_MAX4096 - 5) {
4522 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4523 ret = -1;
4524 goto out;
4525 }
4526 shr_strscat(f, ".bin", sizeof(f));
4527 }
4528 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
4529
4530 if (cfg->data_area) {
4531 if (cfg->data_area > 5 || cfg->data_area < 1) {
4532 nvme_show_error("ERROR: WDC: Data area must be 1-5")nvme_show_message(1, "ERROR: WDC: Data area must be 1-5");
4533 ret = -1;
4534 goto out;
4535 }
4536 }
4537
4538 telemetry_type = cfg->type;
4539 if (telemetry_type == WDC_TELEMETRY_TYPE_NONE0x0)
4540 telemetry_data_area = 0;
4541 else
4542 telemetry_data_area = cfg->data_area;
4543 } else {
4544 if (cfg->file) {
4545 shr_strscpy(fb, cfg->file, sizeof(fb));
4546 } else {
4547 wdc_UtilsGetTime(&timeInfo);
4548 memset(timeStamp, 0, sizeof(timeStamp));
4549 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256,
4550 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
4551 timeInfo.month, timeInfo.dayOfMonth,
4552 timeInfo.hour, timeInfo.minute,
4553 timeInfo.second);
4554 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
4555
4556 ret = wdc_get_serial_name(hdl, fb, PATH_MAX4096/2 - 7, fileSuffix);
4557 if (ret) {
4558 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4559 goto out;
4560 }
4561
4562 if (strlen(fb) > PATH_MAX4096/2 - 7) {
4563 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
4564 ret = -1;
4565 goto out;
4566 }
4567 }
4568 nvme_show_error("%s: filename = %s.tar.gz", __func__, fb)nvme_show_message(1, "%s: filename = %s.tar.gz", __func__, fb
)
;
4569
4570
4571 memset(file_path, 0, sizeof(file_path));
4572 if (snprintf(file_path, PATH_MAX4096/2 - 8, "%s.tar.gz", fb) >= PATH_MAX4096/2 - 8) {
4573 nvme_show_error("File path is too long!")nvme_show_message(1, "File path is too long!");
4574 ret = -1;
4575 goto out;
4576 }
4577 if (access(file_path, F_OK0) != -1) {
4578 nvme_show_error("Output file already exists!")nvme_show_message(1, "Output file already exists!");
4579 ret = -EEXIST17;
4580 goto out;
4581 }
4582 }
4583
4584 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4585 if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) == WDC_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
4586 if (!wdc_is_sn861(device_id)) {
4587 if (telemetry_type != WDC_TELEMETRY_TYPE_NONE0x0 &&
4588 wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4589 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4590 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4591 return -EINVAL22;
4592 }
4593
4594 ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size,
4595 telemetry_type, telemetry_data_area);
4596 } else {
4597 if (nvme_args.verbose)
4598 printf("Creating temp directory...\n");
4599
4600 ret = shr_mkdir(fb, 0666);
4601 if (ret) {
4602 nvme_show_error("Failed to create directory!")nvme_show_message(1, "Failed to create directory!");
4603 goto out;
4604 }
4605
4606 ret = dump_internal_logs(hdl, fb, nvme_args.verbose);
4607 if (ret < 0)
4608 nvme_show_err(ret, "vs-internal-log");
4609
4610 if (nvme_args.verbose)
4611 printf("Archiving...\n");
4612
4613 ret = wdc_tar_dir_files(file_path, fb,
4614 wdc_is_log_file, true1);
4615 if (ret)
4616 nvme_show_error("Failed to create an archive file!")nvme_show_message(1, "Failed to create an archive file!");
4617 }
4618 goto out;
4619 }
4620 if ((capabilities & WDC_DRIVE_CAP_DUI0x0000000800000000) == WDC_DRIVE_CAP_DUI0x0000000800000000) {
4621 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4622 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4623 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4624 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4625 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4626 return -EINVAL22;
4627 }
4628 /* Get the desired telemetry log page */
4629 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4630 telemetry_type, telemetry_data_area);
4631 goto out;
4632 } else {
4633 if (!cfg->data_area)
4634 cfg->data_area = 1;
4635
4636 /* FW requirement - xfer size must be 256k for data area 4 */
4637 if (cfg->data_area >= 4)
4638 xfer_size = 0x40000;
4639 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4640 cfg->data_area,
4641 nvme_args.verbose, cfg->file_size,
4642 cfg->offset);
4643 goto out;
4644 }
4645 }
4646 if ((capabilities & WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) == WDC_DRIVE_CAP_DUI_DATA0x0000000200000000) {
4647 if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST0x1) ||
4648 (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER0x2)) {
4649 if (wdc_get_default_telemetry_da(hdl, &telemetry_data_area)) {
4650 nvme_show_error("%s: Error determining default telemetry data area",nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
4651 __func__)nvme_show_message(1, "%s: Error determining default telemetry data area"
, __func__)
;
4652 return -EINVAL22;
4653 }
4654 ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
4655 telemetry_type, telemetry_data_area);
4656 goto out;
4657 } else {
4658 ret = wdc_do_cap_dui(hdl, f, xfer_size,
4659 WDC_NVME_DUI_MAX_DATA_AREA0x05,
4660 nvme_args.verbose, 0, 0);
4661 goto out;
4662 }
4663 }
4664 if ((capabilities & WDC_SN730B_CAP_VUC_LOG0x0000000400000000) == WDC_SN730B_CAP_VUC_LOG0x0000000400000000) {
4665 ret = wdc_do_sn730_get_and_tar(hdl, f);
4666 } else {
4667 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4668 ret = -1;
4669 }
4670out:
4671 return ret;
4672}
4673
4674static int wdc_do_crash_dump(struct libnvme_transport_handle *hdl, char *file, int type)
4675{
4676 int ret;
4677 __u32 crash_dump_length;
4678 __u32 opcode;
4679 __u32 cdw12;
4680 __u32 cdw10_size;
4681 __u32 cdw12_size;
4682 __u32 cdw12_clear;
4683
4684 if (type == WDC_NVME_PFAIL_DUMP_TYPE2) {
4685 /* set parms to get the PFAIL Crash Dump */
4686 opcode = WDC_NVME_PF_CRASH_DUMP_OPCODE0xC6;
4687 cdw10_size = WDC_NVME_PF_CRASH_DUMP_SIZE_NDT0x02;
4688 cdw12_size = ((WDC_NVME_PF_CRASH_DUMP_SIZE_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4689 WDC_NVME_PF_CRASH_DUMP_SIZE_CMD0x20);
4690
4691 cdw12 = (WDC_NVME_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4692 WDC_NVME_PF_CRASH_DUMP_CMD0x20;
4693
4694 cdw12_clear = ((WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
4695 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4696
4697 } else {
4698 /* set parms to get the Crash Dump */
4699 opcode = WDC_NVME_CRASH_DUMP_OPCODE0xC6;
4700 cdw10_size = WDC_NVME_CRASH_DUMP_SIZE_NDT0x02;
4701 cdw12_size = ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD0x03 << WDC_NVME_SUBCMD_SHIFT8) |
4702 WDC_NVME_CRASH_DUMP_SIZE_CMD0x20);
4703
4704 cdw12 = (WDC_NVME_CRASH_DUMP_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
4705 WDC_NVME_CRASH_DUMP_CMD0x20;
4706
4707 cdw12_clear = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
4708 WDC_NVME_CLEAR_CRASH_DUMP_CMD0x03);
4709 }
4710
4711 ret = wdc_dump_length(hdl,
4712 opcode,
4713 cdw10_size,
4714 cdw12_size,
4715 &crash_dump_length);
4716
4717 if (ret == -1) {
4718 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4719 nvme_show_error("INFO: WDC: Pfail dump get size failed")nvme_show_message(1, "INFO: WDC: Pfail dump get size failed");
4720 else
4721 nvme_show_error("INFO: WDC: Crash dump get size failed")nvme_show_message(1, "INFO: WDC: Crash dump get size failed");
4722
4723 return -1;
4724 }
4725
4726 if (!crash_dump_length) {
4727 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4728 nvme_show_error("INFO: WDC: Pfail dump is empty")nvme_show_message(1, "INFO: WDC: Pfail dump is empty");
4729 else
4730 nvme_show_error("INFO: WDC: Crash dump is empty")nvme_show_message(1, "INFO: WDC: Crash dump is empty");
4731 } else {
4732 ret = wdc_do_dump(hdl,
4733 opcode,
4734 crash_dump_length,
4735 cdw12,
4736 file,
4737 crash_dump_length);
4738
4739 if (!ret)
4740 ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE0xFF,
4741 cdw12_clear);
4742 }
4743 return ret;
4744}
4745
4746static int wdc_crash_dump(struct libnvme_transport_handle *hdl, const char *file, int type)
4747{
4748 char f[PATH_MAX4096] = {0};
4749 const char *dump_type;
4750 int ret;
4751
4752 if (file)
4753 shr_strscpy(f, file, sizeof(f));
4754
4755 if (type == WDC_NVME_PFAIL_DUMP_TYPE2)
4756 dump_type = "_pfail_dump";
4757 else
4758 dump_type = "_crash_dump";
4759
4760 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, dump_type);
4761 if (ret)
4762 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4763 else
4764 ret = wdc_do_crash_dump(hdl, f, type);
4765 return ret;
4766}
4767
4768static int wdc_do_drive_log(struct libnvme_transport_handle *hdl, const char *file)
4769{
4770 int ret;
4771 __u8 *drive_log_data;
4772 __u32 drive_log_length;
4773 struct libnvme_passthru_cmd admin_cmd;
4774
4775 ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE0xC6,
4776 WDC_NVME_DRIVE_LOG_SIZE_NDT0x02,
4777 (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD0x01 <<
4778 WDC_NVME_SUBCMD_SHIFT8 | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20),
4779 &drive_log_length);
4780 if (ret == -1)
4781 return -1;
4782
4783 drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length);
4784 if (!drive_log_data) {
4785 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
4786 return -1;
4787 }
4788
4789 memset(drive_log_data, 0, sizeof(__u8) * drive_log_length);
4790 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
4791 admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE0xC6;
4792 admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
4793 admin_cmd.data_len = drive_log_length;
4794 admin_cmd.cdw10 = drive_log_length;
4795 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD0x00 <<
4796 WDC_NVME_SUBCMD_SHIFT8) | WDC_NVME_DRIVE_LOG_SIZE_CMD0x20);
4797
4798 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
4799 nvme_show_status(ret);
4800 if (!ret)
4801 ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
4802 free(drive_log_data);
4803 return ret;
4804}
4805
4806static int wdc_drive_log(int argc, char **argv, struct command *acmd,
4807 struct plugin *plugin)
4808{
4809 const char *desc = "Capture Drive Log.";
4810 const char *file = "Output file pathname.";
4811 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4812 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4813 char f[PATH_MAX4096] = {0};
4814 int ret;
4815 __u64 capabilities = 0;
4816 struct config {
4817 char *file;
4818 };
4819
4820 struct config cfg = {
4821 .file = NULL((void*)0)
4822 };
4823
4824 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4825 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, }
,
4826 OPT_END(){ ((void*)0) }
4827 };
4828
4829 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4830 if (ret)
4831 return ret;
4832
4833 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4834 if (ret || !wdc_check_device(ctx, hdl))
4835 return ret;
4836
4837 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4838
4839 if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400)) {
4840 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4841 ret = -1;
4842 } else {
4843 if (cfg.file)
4844 shr_strscpy(f, cfg.file, sizeof(f));
4845 ret = wdc_get_serial_name(hdl, f, PATH_MAX4096, "drive_log");
4846 if (ret)
4847 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
4848 else
4849 ret = wdc_do_drive_log(hdl, f);
4850 }
4851 return ret;
4852}
4853
4854static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd,
4855 struct plugin *plugin)
4856{
4857 const char *desc = "Get Crash Dump.";
4858 const char *file = "Output file pathname.";
4859 __u64 capabilities = 0;
4860 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4861 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4862 int ret;
4863
4864 struct config {
4865 char *file;
4866 };
4867
4868 struct config cfg = {
4869 .file = NULL((void*)0),
4870 };
4871
4872 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4873 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, }
,
4874 OPT_END(){ ((void*)0) }
4875 };
4876
4877 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4878 if (ret)
4879 return ret;
4880
4881 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4882 if (ret || !wdc_check_device(ctx, hdl))
4883 return ret;
4884
4885 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4886
4887 if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800)) {
4888 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4889 ret = -1;
4890 } else {
4891 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE1);
4892 if (ret)
4893 nvme_show_error("ERROR: WDC: failed to read crash dump")nvme_show_message(1, "ERROR: WDC: failed to read crash dump");
4894 }
4895 return ret;
4896}
4897
4898static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd,
4899 struct plugin *plugin)
4900{
4901 const char *desc = "Get Pfail Crash Dump.";
4902 const char *file = "Output file pathname.";
4903 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4904 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4905 __u64 capabilities = 0;
4906 struct config {
4907 char *file;
4908 };
4909 int ret;
4910
4911 struct config cfg = {
4912 .file = NULL((void*)0),
4913 };
4914
4915 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4916 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, }
,
4917 OPT_END(){ ((void*)0) }
4918 };
4919
4920 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
4921 if (ret)
4922 return ret;
4923
4924 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
4925 if (ret || !wdc_check_device(ctx, hdl))
4926 return ret;
4927
4928 capabilities = wdc_get_drive_capabilities(ctx, hdl);
4929 if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000)) {
4930 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
4931 ret = -1;
4932 } else {
4933 ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE2);
4934 if (ret)
4935 nvme_show_error("ERROR: WDC: failed to read pfail crash dump")nvme_show_message(1, "ERROR: WDC: failed to read pfail crash dump"
)
;
4936 }
4937 return ret;
4938}
4939
4940static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root)
4941{
4942 /* 24 bytes, not NUL terminated if all used */
4943 char vsn[25] = {0};
4944 int base = 3072;
4945 int vsn_start = 3081;
4946
4947 memcpy(vsn, &vs[vsn_start - base], sizeof(vsn) - 1);
4948 if (root)
4949 json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL");
4950 else
4951 printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL");
4952}
4953
4954static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
4955{
4956 return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl);
4957}
4958
4959static const char *wdc_purge_mon_status_to_string(__u32 status)
4960{
4961 const char *str;
4962
4963 switch (status) {
4964 case WDC_NVME_PURGE_STATE_IDLE0x00:
4965 str = "Purge State Idle.";
4966 break;
4967 case WDC_NVME_PURGE_STATE_DONE0x01:
4968 str = "Purge State Done.";
4969 break;
4970 case WDC_NVME_PURGE_STATE_BUSY0x02:
4971 str = "Purge State Busy.";
4972 break;
4973 case WDC_NVME_PURGE_STATE_REQ_PWR_CYC0x03:
4974 str = "Purge Operation resulted in an error that requires power cycle.";
4975 break;
4976 case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE0x04:
4977 str = "The previous purge operation was interrupted by a power cycle\n"
4978 "or reset interruption. Other commands may be rejected until\n"
4979 "Purge Execute is issued and completed.";
4980 break;
4981 default:
4982 str = "Unknown.";
4983 }
4984 return str;
4985}
4986
4987static int wdc_purge(int argc, char **argv,
4988 struct command *command, struct plugin *plugin)
4989{
4990 const char *desc = "Send a Purge command.";
4991 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
4992 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
4993 struct libnvme_passthru_cmd admin_cmd;
4994 __u64 capabilities = 0;
4995 char *err_str;
4996 int ret;
4997
4998 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
4999 OPT_END(){ ((void*)0) }
5000 };
5001
5002 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
5003 if (ret)
5004 return ret;
5005
5006 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
5007 if (ret || !wdc_check_device(ctx, hdl))
5008 return ret;
5009
5010 capabilities = wdc_get_drive_capabilities(ctx, hdl);
5011 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
5012 ret = -1;
5013 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
5014 } else {
5015 err_str = "";
5016 memset(&admin_cmd, 0, sizeof(admin_cmd));
5017 admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE0xDD;
5018
5019 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
5020 if (ret > 0) {
5021 switch (ret) {
5022 case WDC_NVME_PURGE_CMD_SEQ_ERR0x0C:
5023 err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n";
5024 break;
5025 case WDC_NVME_PURGE_INT_DEV_ERR0x06:
5026 err_str = "ERROR: WDC: Internal Device Error.\n";
5027 break;
5028 default:
5029 err_str = "ERROR: WDC\n";
5030 }
5031 }
5032
5033 nvme_show_error("%s", err_str)nvme_show_message(1, "%s", err_str);
5034 nvme_show_status(ret);
5035 }
5036 return ret;
5037}
5038
5039static int wdc_purge_monitor(int argc, char **argv,
5040 struct command *command, struct plugin *plugin)
5041{
5042 const char *desc = "Send a Purge Monitor command.";
5043 __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F];
5044 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
5045 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
5046 double progress_percent;
5047 struct libnvme_passthru_cmd admin_cmd;
5048 struct wdc_nvme_purge_monitor_data *mon;
5049 __u64 capabilities;
5050 int ret;
5051
5052 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
5053 OPT_END(){ ((void*)0) }
5054 };
5055
5056 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
5057 if (ret)
5058 return ret;
5059
5060 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
5061 if (ret || !wdc_check_device(ctx, hdl))
5062 return ret;
5063
5064 capabilities = wdc_get_drive_capabilities(ctx, hdl);
5065 if (!(capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000)) {
5066 ret = -1;
5067 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
5068 } else {
5069 memset(output, 0, sizeof(output));
5070 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
5071 admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE0xDE;
5072 admin_cmd.addr = (__u64)(uintptr_t)output;
5073 admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN0x2F;
5074 admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW100x0000000C;
5075 admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT0x7530;
5076
5077 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
5078 if (!ret) {
5079 mon = (struct wdc_nvme_purge_monitor_data *) output;
5080 printf("Purge state = 0x%0"PRIx64"l" "x""\n",
5081 (uint64_t)admin_cmd.result);
5082 printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result));
5083 if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY0x02) {
5084 progress_percent =
5085 ((double)le32_to_cpu(mon->entire_progress_current) * 100) /
5086 le32_to_cpu(mon->entire_progress_total);
5087 printf("Purge Progress = %f%%\n", progress_percent);
5088 }
5089 }
5090
5091 nvme_show_status(ret);
5092 }
5093 return ret;
5094}
5095
5096static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf)
5097{
5098 printf(" C1 Log Page Performance Statistics :-\n");
5099 printf(" Host Read Commands %20"PRIu64"l" "u""\n",
5100 le64_to_cpu(perf->hr_cmds));
5101 printf(" Host Read Blocks %20"PRIu64"l" "u""\n",
5102 le64_to_cpu(perf->hr_blks));
5103 printf(" Average Read Size %20lf\n",
5104 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))));
5105 printf(" Host Read Cache Hit Commands %20"PRIu64"l" "u""\n",
5106 le64_to_cpu(perf->hr_ch_cmds));
5107 printf(" Host Read Cache Hit_Percentage %20"PRIu64"l" "u""%%\n",
5108 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)));
5109 printf(" Host Read Cache Hit Blocks %20"PRIu64"l" "u""\n",
5110 le64_to_cpu(perf->hr_ch_blks));
5111 printf(" Average Read Cache Hit Size %20f\n",
5112 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))));
5113 printf(" Host Read Commands Stalled %20"PRIu64"l" "u""\n",
5114 le64_to_cpu(perf->hr_st_cmds));
5115 printf(" Host Read Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5116 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)));
5117 printf(" Host Write Commands %20"PRIu64"l" "u""\n",
5118 le64_to_cpu(perf->hw_cmds));
5119 printf(" Host Write Blocks %20"PRIu64"l" "u""\n",
5120 le64_to_cpu(perf->hw_blks));
5121 printf(" Average Write Size %20f\n",
5122 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))));
5123 printf(" Host Write Odd Start Commands %20"PRIu64"l" "u""\n",
5124 le64_to_cpu(perf->hw_os_cmds));
5125 printf(" Host Write Odd Start Commands Percentage %20"PRIu64"l" "u""%%\n",
5126 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))));
5127 printf(" Host Write Odd End Commands %20"PRIu64"l" "u""\n",
5128 le64_to_cpu(perf->hw_oe_cmds));
5129 printf(" Host Write Odd End Commands Percentage %20"PRIu64"l" "u""%%\n",
5130 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))));
5131 printf(" Host Write Commands Stalled %20"PRIu64"l" "u""\n",
5132 le64_to_cpu(perf->hw_st_cmds));
5133 printf(" Host Write Commands Stalled Percentage %20"PRIu64"l" "u""%%\n",
5134 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))));
5135 printf(" NAND Read Commands %20"PRIu64"l" "u""\n",
5136 le64_to_cpu(perf->nr_cmds));
5137 printf(" NAND Read Blocks Commands %20"PRIu64"l" "u""\n",
5138 le64_to_cpu(perf->nr_blks));
5139 printf(" Average NAND Read Size %20f\n",
5140 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))));
5141 printf(" Nand Write Commands %20"PRIu64"l" "u""\n",
5142 le64_to_cpu(perf->nw_cmds));
5143 printf(" NAND Write Blocks %20"PRIu64"l" "u""\n",
5144 le64_to_cpu(perf->nw_blks));
5145 printf(" Average NAND Write Size %20f\n",
5146 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))));
5147 printf(" NAND Read Before Write %20"PRIu64"l" "u""\n",
5148 le64_to_cpu(perf->nrbw));
5149}
5150
5151static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf)
5152{
5153 struct json_object *root = json_create_object()json_object_new_object();
5154
5155 json_object_add_value_int(root, "Host Read Commands", le64_to_cpu(perf->hr_cmds))json_object_object_add(root, "Host Read Commands", json_object_new_int
(le64_to_cpu(perf->hr_cmds)))
;
5156 json_object_add_value_int(root, "Host Read Blocks", le64_to_cpu(perf->hr_blks))json_object_object_add(root, "Host Read Blocks", json_object_new_int
(le64_to_cpu(perf->hr_blks)))
;
5157 json_object_add_value_int(root, "Average Read Size",json_object_object_add(root, "Average Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf
->hr_cmds)))))
5158 safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds))))json_object_object_add(root, "Average Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf
->hr_cmds)))))
;
5159 json_object_add_value_int(root, "Host Read Cache Hit Commands",json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_int
(le64_to_cpu(perf->hr_ch_cmds)))
5160 le64_to_cpu(perf->hr_ch_cmds))json_object_object_add(root, "Host Read Cache Hit Commands", json_object_new_int
(le64_to_cpu(perf->hr_ch_cmds)))
;
5161 json_object_add_value_int(root, "Host Read Cache Hit Percentage",json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_int((uint64_t) calc_percent(le64_to_cpu(perf
->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))))
5162 (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Cache Hit Percentage"
, json_object_new_int((uint64_t) calc_percent(le64_to_cpu(perf
->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))))
;
5163 json_object_add_value_int(root, "Host Read Cache Hit Blocks",json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_int
(le64_to_cpu(perf->hr_ch_blks)))
5164 le64_to_cpu(perf->hr_ch_blks))json_object_object_add(root, "Host Read Cache Hit Blocks", json_object_new_int
(le64_to_cpu(perf->hr_ch_blks)))
;
5165 json_object_add_value_int(root, "Average Read Cache Hit Size",json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu
(perf->hr_ch_cmds)))))
5166 safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds))))json_object_object_add(root, "Average Read Cache Hit Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu
(perf->hr_ch_cmds)))))
;
5167 json_object_add_value_int(root, "Host Read Commands Stalled",json_object_object_add(root, "Host Read Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hr_st_cmds)))
5168 le64_to_cpu(perf->hr_st_cmds))json_object_object_add(root, "Host Read Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hr_st_cmds)))
;
5169 json_object_add_value_int(root, "Host Read Commands Stalled Percentage",json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))))
5170 (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds)))json_object_object_add(root, "Host Read Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))))
;
5171 json_object_add_value_int(root, "Host Write Commands",json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
5172 le64_to_cpu(perf->hw_cmds))json_object_object_add(root, "Host Write Commands", json_object_new_int
(le64_to_cpu(perf->hw_cmds)))
;
5173 json_object_add_value_int(root, "Host Write Blocks",json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
5174 le64_to_cpu(perf->hw_blks))json_object_object_add(root, "Host Write Blocks", json_object_new_int
(le64_to_cpu(perf->hw_blks)))
;
5175 json_object_add_value_int(root, "Average Write Size",json_object_object_add(root, "Average Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf
->hw_cmds)))))
5176 safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Average Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf
->hw_cmds)))))
;
5177 json_object_add_value_int(root, "Host Write Odd Start Commands",json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_int(le64_to_cpu(perf->hw_os_cmds)))
5178 le64_to_cpu(perf->hw_os_cmds))json_object_object_add(root, "Host Write Odd Start Commands",
json_object_new_int(le64_to_cpu(perf->hw_os_cmds)))
;
5179 json_object_add_value_int(root, "Host Write Odd Start Commands Percentage",json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))))
5180 (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Odd Start Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))))
;
5181 json_object_add_value_int(root, "Host Write Odd End Commands",json_object_object_add(root, "Host Write Odd End Commands", json_object_new_int
(le64_to_cpu(perf->hw_oe_cmds)))
5182 le64_to_cpu(perf->hw_oe_cmds))json_object_object_add(root, "Host Write Odd End Commands", json_object_new_int
(le64_to_cpu(perf->hw_oe_cmds)))
;
5183 json_object_add_value_int(root, "Host Write Odd End Commands Percentage",json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))))
5184 (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds)))))json_object_object_add(root, "Host Write Odd End Commands Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))))
;
5185 json_object_add_value_int(root, "Host Write Commands Stalled",json_object_object_add(root, "Host Write Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hw_st_cmds)))
5186 le64_to_cpu(perf->hw_st_cmds))json_object_object_add(root, "Host Write Commands Stalled", json_object_new_int
(le64_to_cpu(perf->hw_st_cmds)))
;
5187 json_object_add_value_int(root, "Host Write Commands Stalled Percentage",json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))))
5188 (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds))))json_object_object_add(root, "Host Write Commands Stalled Percentage"
, json_object_new_int((uint64_t)calc_percent((le64_to_cpu(perf
->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))))
;
5189 json_object_add_value_int(root, "NAND Read Commands",json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
5190 le64_to_cpu(perf->nr_cmds))json_object_object_add(root, "NAND Read Commands", json_object_new_int
(le64_to_cpu(perf->nr_cmds)))
;
5191 json_object_add_value_int(root, "NAND Read Blocks Commands",json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_int
(le64_to_cpu(perf->nr_blks)))
5192 le64_to_cpu(perf->nr_blks))json_object_object_add(root, "NAND Read Blocks Commands", json_object_new_int
(le64_to_cpu(perf->nr_blks)))
;
5193 json_object_add_value_int(root, "Average NAND Read Size",json_object_object_add(root, "Average NAND Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf
->nr_cmds))))))
5194 safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds)))))json_object_object_add(root, "Average NAND Read Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf
->nr_cmds))))))
;
5195 json_object_add_value_int(root, "Nand Write Commands",json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
5196 le64_to_cpu(perf->nw_cmds))json_object_object_add(root, "Nand Write Commands", json_object_new_int
(le64_to_cpu(perf->nw_cmds)))
;
5197 json_object_add_value_int(root, "NAND Write Blocks",json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
5198 le64_to_cpu(perf->nw_blks))json_object_object_add(root, "NAND Write Blocks", json_object_new_int
(le64_to_cpu(perf->nw_blks)))
;
5199 json_object_add_value_int(root, "Average NAND Write Size",json_object_object_add(root, "Average NAND Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf
->nw_cmds)))))
5200 safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds))))json_object_object_add(root, "Average NAND Write Size", json_object_new_int
(safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf
->nw_cmds)))))
;
5201 json_object_add_value_int(root, "NAND Read Before Written",json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
5202 le64_to_cpu(perf->nrbw))json_object_object_add(root, "NAND Read Before Written", json_object_new_int
(le64_to_cpu(perf->nrbw)))
;
5203 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5204 printf("\n");
5205 json_free_object(root)json_object_put(root);
5206}
5207
5208static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt)
5209{
5210 if (!perf) {
5211 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
5212 return -1;
5213 }
5214 switch (fmt) {
5215 case NORMAL:
5216 wdc_print_log_normal(perf);
5217 break;
5218 case JSON:
5219 wdc_print_log_json(perf);
5220 break;
5221 }
5222 return 0;
5223}
5224
5225static int wdc_print_latency_monitor_log_normal(struct libnvme_transport_handle *hdl,
5226 struct wdc_ssd_latency_monitor_log *log_data)
5227{
5228 printf("Latency Monitor/C3 Log Page Data\n");
5229 printf(" Controller : %s\n", libnvme_transport_handle_get_name(hdl));
5230 int err = -1, i, j;
5231 struct libnvme_passthru_cmd cmd;
5232 struct nvme_id_ctrl ctrl;
5233 char ts_buf[128];
5234
5235 nvme_init_identify_ctrl(&cmd, &ctrl);
5236 err = libnvme_exec_admin_passthru(hdl, &cmd);
5237 if (!err) {
5238 printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn);
5239 } else {
5240 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)
;
5241 return err;
5242 }
5243
5244 printf(" Feature Status 0x%x\n", log_data->feature_status);
5245 printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer));
5246 printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold));
5247 printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1)));
5248 printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1)));
5249 printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1)));
5250 printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1)));
5251 printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config));
5252 printf(" Active Latency Minimum Window %d ms\n", 100*log_data->active_latency_min_window);
5253 printf(" Active Latency Stamp Units %d\n", le16_to_cpu(log_data->active_latency_stamp_units));
5254 printf(" Static Latency Stamp Units %d\n", le16_to_cpu(log_data->static_latency_stamp_units));
5255 if (le16_to_cpu(log_data->log_page_version) >= 4)
5256 printf(" Debug Telemetry Log Size %"PRIu64"l" "u""\n",
5257 le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size));
5258 printf(" Debug Log Trigger Enable %d\n",
5259 le16_to_cpu(log_data->debug_log_trigger_enable));
5260 printf(" Log Page Version %d\n",
5261 le16_to_cpu(log_data->log_page_version));
5262 printf(" Log page GUID 0x");
5263 for (j = 0; j < WDC_C3_GUID_LENGTH16; j++)
5264 printf("%x", log_data->log_page_guid[j]);
5265 printf("\n");
5266
5267 printf(" Read Write Deallocate/Trim\n");
5268 for (i = 0; i <= 3; i++)
5269 printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
5270 i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5271 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5272 le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5273
5274 for (i = 3; i >= 0; i--)
5275 printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5276 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5277 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5278 le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5279
5280 for (i = 3; i >= 0; i--) {
5281 printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
5282 for (j = 2; j >= 0; j--) {
5283 if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) {
5284 printf(" N/A ");
5285 } else {
5286 shr_format_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
5287 printf("%s ", ts_buf);
5288 }
5289 }
5290 printf("\n");
5291 }
5292
5293 for (i = 0; i <= 3; i++)
5294 printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
5295 i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ3]),
5296 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE2]),
5297 le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_TRIM1]));
5298
5299 for (i = 3; i >= 0; i--)
5300 printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
5301 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ2]),
5302 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE1]),
5303 le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM0]));
5304
5305 for (i = 3; i >= 0; i--) {
5306 printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
5307 for (j = 2; j >= 0; j--) {
5308 if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) {
5309 printf(" N/A ");
5310 } else {
5311 shr_format_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
5312 printf("%s ", ts_buf);
5313 }
5314 }
5315 printf("\n");
5316 }
5317
5318 return 0;
5319}
5320
5321static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data)
5322{
5323 int i, j;
5324 char buf[128];
5325 const char *operation[3] = {"Read", "Write", "Trim"};
5326 struct json_object *root = json_create_object()json_object_new_object();
5327
5328 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))
;
5329 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)))
;
5330 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
)))
;
5331 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)))
;
5332 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)))
;
5333 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)))
;
5334 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)))
;
5335 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)))
;
5336 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
))
;
5337 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)))
;
5338 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)))
;
5339 if (le16_to_cpu(log_data->log_page_version) >= 4) {
5340 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
)))
5341 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
)))
;
5342 }
5343 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)))
5344 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)))
;
5345 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)))
5346 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)))
;
5347
5348 char guid[40];
5349
5350 memset((void *)guid, 0, 40);
5351 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5352 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5353 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5354 json_object_add_value_string(root, "Log page GUID", guid);
5355
5356 for (i = 0; i <= 3; i++) {
5357 for (j = 2; j >= 0; j--) {
5358 snprintf(buf, sizeof(buf),
5359 "Active Bucket Counter: Bucket %d %s", i,
5360 operation[2-j]);
5361 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])))
;
5362 }
5363 }
5364 for (i = 3; i >= 0; i--) {
5365 for (j = 2; j >= 0; j--) {
5366 snprintf(buf, sizeof(buf),
5367 "Active Measured Latency: Bucket %d %s", 3-i,
5368 operation[2-j]);
5369 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])))
;
5370 }
5371 }
5372 for (i = 3; i >= 0; i--) {
5373 for (j = 2; j >= 0; j--) {
5374 snprintf(buf, sizeof(buf),
5375 "Active Latency Time Stamp: Bucket %d %s", 3-i,
5376 operation[2-j]);
5377 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])))
;
5378 }
5379 }
5380 for (i = 0; i <= 3; i++) {
5381 for (j = 2; j >= 0; j--) {
5382 snprintf(buf, sizeof(buf),
5383 "Static Bucket Counter: Bucket %d %s", i,
5384 operation[2-j]);
5385 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])))
;
5386 }
5387 }
5388 for (i = 3; i >= 0; i--) {
5389 for (j = 2; j >= 0; j--) {
5390 snprintf(buf, sizeof(buf),
5391 "Static Measured Latency: Bucket %d %s", 3-i,
5392 operation[2-j]);
5393 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])))
;
5394 }
5395 }
5396 for (i = 3; i >= 0; i--) {
5397 for (j = 2; j >= 0; j--) {
5398 snprintf(buf, sizeof(buf),
5399 "Static Latency Time Stamp: Bucket %d %s", 3-i,
5400 operation[2-j]);
5401 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])))
;
5402 }
5403 }
5404
5405 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5406 printf("\n");
5407
5408 json_free_object(root)json_object_put(root);
5409}
5410
5411static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data)
5412{
5413 int j;
5414
5415 printf("Error Recovery/C1 Log Page Data\n");
5416
5417 printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time));
5418 printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
5419 printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1);
5420 printf(" Panic ID : 0x%" PRIu64"l" "u" "\n", le64_to_cpu(log_data->panic_id));
5421 printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities));
5422 printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc);
5423 printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12));
5424 printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13));
5425 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5426 printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to);
5427 printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2);
5428 printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to);
5429 }
5430 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5431 printf(" Panic Count : 0x%x\n", log_data->panic_count);
5432 for (j = 0; j < 4; j++)
5433 printf(" Previous Panic ID N-%d : 0x%"PRIx64"l" "x""\n",
5434 j+1, le64_to_cpu(log_data->prev_panic_ids[j]));
5435 }
5436 printf(" Log Page Version : 0x%x\n",
5437 le16_to_cpu(log_data->log_page_version));
5438 printf(" Log page GUID : 0x");
5439 for (j = 0; j < WDC_OCP_C1_GUID_LENGTH16; j++)
5440 printf("%x", log_data->log_page_guid[j]);
5441 printf("\n");
5442}
5443
5444static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
5445{
5446 int j;
5447 char buf[128];
5448 struct json_object *root = json_create_object()json_object_new_object();
5449
5450 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)))
;
5451 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))
;
5452 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))
;
5453 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)))
;
5454 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)))
;
5455 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))
;
5456 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)))
;
5457 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)))
;
5458 if (le16_to_cpu(log_data->log_page_version) >= 2) {
5459 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))
;
5460 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))
;
5461 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))
;
5462 }
5463 if (le16_to_cpu(log_data->log_page_version) >= 3) {
5464 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))
;
5465 for (j = 0; j < 4; j++) {
5466 snprintf(buf, sizeof(buf), "Previous Panic ID N-%d",
5467 j+1);
5468 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])))
5469 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])))
;
5470 }
5471 }
5472 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)))
5473 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)))
;
5474
5475 char guid[40];
5476
5477 memset((void *)guid, 0, 40);
5478 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5479 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5480 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5481 json_object_add_value_string(root, "Log page GUID", guid);
5482
5483 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5484 printf("\n");
5485
5486 json_free_object(root)json_object_put(root);
5487}
5488
5489static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data)
5490{
5491 int j;
5492
5493 printf("Device Capabilities/C4 Log Page Data\n");
5494
5495 printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports));
5496 printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support));
5497 printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support));
5498 printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support));
5499 printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support));
5500 printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support));
5501 printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support));
5502 printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps));
5503
5504 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++)
5505 printf(" DSSD Power State %d Descriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]);
5506
5507 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5508 printf(" Log page GUID : 0x");
5509 for (j = 0; j < WDC_OCP_C4_GUID_LENGTH16; j++)
5510 printf("%x", log_data->log_page_guid[j]);
5511 printf("\n");
5512}
5513
5514static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
5515{
5516 int j;
5517 struct json_object *root = json_create_object()json_object_new_object();
5518
5519 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)))
;
5520 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
)))
;
5521 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)))
;
5522 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)))
;
5523 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)))
;
5524 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)))
;
5525 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)))
;
5526 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)))
;
5527
5528 char dssd_descr_str[40];
5529
5530 memset((void *)dssd_descr_str, 0, 40);
5531 for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR127; j++) {
5532 snprintf((char *)dssd_descr_str, sizeof(dssd_descr_str),
5533 "DSSD Power State %d Descriptor", j);
5534 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]))
;
5535 }
5536
5537 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)))
;
5538 char guid[40];
5539
5540 memset((void *)guid, 0, 40);
5541 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5542 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5543 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5544 json_object_add_value_string(root, "Log page GUID", guid);
5545
5546 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5547 printf("\n");
5548
5549 json_free_object(root)json_object_put(root);
5550}
5551
5552static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data)
5553{
5554 int j;
5555
5556 printf("Unsupported Requirements/C5 Log Page Data\n");
5557
5558 printf(" Number Unsupported Req IDs : 0x%x\n",
5559 le16_to_cpu(log_data->unsupported_count));
5560
5561 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++)
5562 printf(" Unsupported Requirement List %d : %s\n", j,
5563 log_data->unsupported_req_list[j]);
5564
5565 printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version));
5566 printf(" Log page GUID : 0x");
5567 for (j = 0; j < WDC_OCP_C5_GUID_LENGTH16; j++)
5568 printf("%x", log_data->log_page_guid[j]);
5569 printf("\n");
5570}
5571
5572static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
5573{
5574 int j;
5575 struct json_object *root = json_create_object()json_object_new_object();
5576
5577 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)))
;
5578
5579 char unsup_req_list_str[41];
5580
5581 memset((void *)unsup_req_list_str, 0, 41);
5582 for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
5583 snprintf((char *)unsup_req_list_str, sizeof(unsup_req_list_str),
5584 "Unsupported Requirement List %d", j);
5585 json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]);
5586 }
5587
5588 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)))
5589 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)))
;
5590 char guid[40];
5591
5592 memset((void *)guid, 0, 40);
5593 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
5594 shr_get_unaligned_le64(&log_data->log_page_guid[8]),
5595 shr_get_unaligned_le64(&log_data->log_page_guid[0]));
5596 json_object_add_value_string(root, "Log page GUID", guid);
5597
5598 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5599 printf("\n");
5600
5601 json_free_object(root)json_object_put(root);
5602}
5603
5604static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
5605{
5606 uint64_t converted = 0;
5607
5608 printf(" CA Log Page Performance Statistics :-\n");
5609 printf(" NAND Bytes Written %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5610 le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo));
5611 printf(" NAND Bytes Read %20"PRIu64"l" "u" "%20"PRIu64"l" "u""\n",
5612 le64_to_cpu(perf->nand_bytes_rd_hi), le64_to_cpu(perf->nand_bytes_rd_lo));
5613
5614 converted = le64_to_cpu(perf->nand_bad_block);
5615 printf(" NAND Bad Block Count (Normalized) %20"PRIu64"l" "u""\n",
5616 converted & 0xFFFF);
5617 printf(" NAND Bad Block Count (Raw) %20"PRIu64"l" "u""\n",
5618 converted >> 16);
5619
5620 printf(" Uncorrectable Read Count %20"PRIu64"l" "u""\n",
5621 le64_to_cpu(perf->uncorr_read_count));
5622 printf(" Soft ECC Error Count %20"PRIu64"l" "u""\n",
5623 le64_to_cpu(perf->ecc_error_count));
5624 printf(" SSD End to End Detected Correction Count %20"PRIu32"u""\n",
5625 (uint32_t)le32_to_cpu(perf->ssd_detect_count));
5626 printf(" SSD End to End Corrected Correction Count %20"PRIu32"u""\n",
5627 (uint32_t)le32_to_cpu(perf->ssd_correct_count));
5628 printf(" System Data Percent Used %20"PRIu32"u""%%\n",
5629 perf->data_percent_used);
5630 printf(" User Data Erase Counts Max %20"PRIu32"u""\n",
5631 (uint32_t)le32_to_cpu(perf->data_erase_max));
5632 printf(" User Data Erase Counts Min %20"PRIu32"u""\n",
5633 (uint32_t)le32_to_cpu(perf->data_erase_min));
5634 printf(" Refresh Count %20"PRIu64"l" "u""\n",
5635 le64_to_cpu(perf->refresh_count));
5636
5637 converted = le64_to_cpu(perf->program_fail);
5638 printf(" Program Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5639 converted & 0xFFFF);
5640 printf(" Program Fail Count (Raw) %20"PRIu64"l" "u""\n",
5641 converted >> 16);
5642
5643 converted = le64_to_cpu(perf->user_erase_fail);
5644 printf(" User Data Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5645 converted & 0xFFFF);
5646 printf(" User Data Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5647 converted >> 16);
5648
5649 converted = le64_to_cpu(perf->system_erase_fail);
5650 printf(" System Area Erase Fail Count (Normalized) %20"PRIu64"l" "u""\n",
5651 converted & 0xFFFF);
5652 printf(" System Area Erase Fail Count (Raw) %20"PRIu64"l" "u""\n",
5653 converted >> 16);
5654
5655 printf(" Thermal Throttling Status %20"PRIu8"hhu""\n",
5656 perf->thermal_throttle_status);
5657 printf(" Thermal Throttling Count %20"PRIu8"hhu""\n",
5658 perf->thermal_throttle_count);
5659 printf(" PCIe Correctable Error Count %20"PRIu64"l" "u""\n",
5660 le64_to_cpu(perf->pcie_corr_error));
5661 printf(" Incomplete Shutdown Count %20"PRIu32"u""\n",
5662 (uint32_t)le32_to_cpu(perf->incomplete_shutdown_count));
5663 printf(" Percent Free Blocks %20"PRIu32"u""%%\n",
5664 perf->percent_free_blocks);
5665}
5666
5667static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf)
5668{
5669 struct json_object *root = json_create_object()json_object_new_object();
5670 uint64_t converted = 0;
5671
5672 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)))
;
5673 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)))
;
5674 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)))
;
5675 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)))
;
5676
5677 converted = le64_to_cpu(perf->nand_bad_block);
5678 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))
5679 converted & 0xFFFF)json_object_object_add(root, "NAND Bad Block Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5680 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))
5681 converted >> 16)json_object_object_add(root, "NAND Bad Block Count (Raw)", json_object_new_int
(converted >> 16))
;
5682
5683 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)))
;
5684 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)))
;
5685 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))
)
5686 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))
)
;
5687 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)
))
5688 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)
))
;
5689 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))
5690 perf->data_percent_used)json_object_object_add(root, "System Data Percent Used", json_object_new_int
(perf->data_percent_used))
;
5691 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)))
5692 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)))
;
5693 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)))
5694 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)))
;
5695 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)))
;
5696
5697 converted = le64_to_cpu(perf->program_fail);
5698 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))
5699 converted & 0xFFFF)json_object_object_add(root, "Program Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5700 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))
5701 converted >> 16)json_object_object_add(root, "Program Fail Count (Raw)", json_object_new_int
(converted >> 16))
;
5702
5703 converted = le64_to_cpu(perf->user_erase_fail);
5704 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))
5705 converted & 0xFFFF)json_object_object_add(root, "User Data Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5706 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))
5707 converted >> 16)json_object_object_add(root, "User Data Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5708
5709 converted = le64_to_cpu(perf->system_erase_fail);
5710 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))
5711 converted & 0xFFFF)json_object_object_add(root, "System Area Erase Fail Count (Normalized)"
, json_object_new_int(converted & 0xFFFF))
;
5712 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))
5713 converted >> 16)json_object_object_add(root, "System Area Erase Fail Count (Raw)"
, json_object_new_int(converted >> 16))
;
5714
5715 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))
5716 perf->thermal_throttle_status)json_object_object_add(root, "Thermal Throttling Status", json_object_new_int
(perf->thermal_throttle_status))
;
5717 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))
5718 perf->thermal_throttle_count)json_object_object_add(root, "Thermal Throttling Count", json_object_new_int
(perf->thermal_throttle_count))
;
5719 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)))
;
5720 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)))
;
5721 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))
;
5722 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5723 printf("\n");
5724 json_free_object(root)json_object_put(root);
5725}
5726
5727static void wdc_print_bd_ca_log_normal(struct libnvme_transport_handle *hdl, void *data)
5728{
5729 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5730 struct wdc_bd_ca_log_format *end = bd_data +
5731 WDC_BD_CA_LOG_BUF_LEN0xA0 / sizeof(*bd_data);
5732 __u64 rawSwapped;
5733 __u8 *raw;
5734 bool_Bool valid_id = true1;
5735
5736 while (valid_id && bd_data < end) {
5737 raw = bd_data->raw_value;
5738 rawSwapped = shr_get_unaligned_le64(raw) >> 8;
5739
5740 switch (bd_data->field_id) {
5741 case 0x0:
5742 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
5743 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
5744 printf("key normalized raw\n");
5745 printf("program_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5746 bd_data->normalized_value, (uint64_t)rawSwapped);
5747 break;
5748 case 0x1:
5749 printf("erase_fail_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5750 bd_data->normalized_value, (uint64_t)rawSwapped);
5751 break;
5752 case 0x2:
5753 printf("wear_leveling : %3"PRIu8"hhu",
5754 bd_data->normalized_value);
5755 printf("%% min: %"PRIu16"hu"", max: %"PRIu16"hu"", avg: %"PRIu16"hu""\n",
5756 shr_get_unaligned_le16(&raw[1]),
5757 shr_get_unaligned_le16(&raw[3]),
5758 shr_get_unaligned_le16(&raw[5]));
5759 break;
5760 case 0x3:
5761 printf("end_to_end_error_detection_count: %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5762 bd_data->normalized_value, (uint64_t)rawSwapped);
5763 break;
5764 case 0x4:
5765 printf("crc_error_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5766 bd_data->normalized_value, (uint64_t)rawSwapped);
5767 break;
5768 case 0x5:
5769 printf("timed_workload_media_wear : %3"PRIu8"hhu""%% %-.3f%%\n",
5770 bd_data->normalized_value,
5771 safe_div_fp((rawSwapped), 1024.0));
5772 break;
5773 case 0x6:
5774 printf("timed_workload_host_reads : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5775 bd_data->normalized_value, (uint64_t)rawSwapped);
5776 break;
5777 case 0x7:
5778 printf("timed_workload_timer : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5779 bd_data->normalized_value, (uint64_t)rawSwapped);
5780 break;
5781 case 0x8:
5782 printf("thermal_throttle_status : %3"PRIu8"hhu""%% %"PRIu16"hu",
5783 bd_data->normalized_value, raw[1]);
5784 printf("%%, cnt: %"PRIu32"u""\n",
5785 shr_get_unaligned_le32(&raw[2]));
5786 break;
5787 case 0x9:
5788 printf("retry_buffer_overflow_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5789 bd_data->normalized_value, (uint64_t)rawSwapped);
5790 break;
5791 case 0xA:
5792 printf("pll_lock_loss_count : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5793 bd_data->normalized_value, (uint64_t)rawSwapped);
5794 break;
5795 case 0xB:
5796 printf("nand_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5797 bd_data->normalized_value, (uint64_t)rawSwapped);
5798 break;
5799 case 0xC:
5800 printf("host_bytes_written : %3"PRIu8"hhu""%% %"PRIu64"l" "u""\n",
5801 bd_data->normalized_value, (uint64_t)rawSwapped);
5802 /* last entry, break from while loop */
5803 valid_id = false0;
5804 break;
5805 default:
5806 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5807 break;
5808 }
5809
5810 bd_data++;
5811 }
5812
5813 return;
5814}
5815
5816static void wdc_print_bd_ca_log_json(void *data)
5817{
5818 struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data;
5819 struct wdc_bd_ca_log_format *end = bd_data +
5820 WDC_BD_CA_LOG_BUF_LEN0xA0 / sizeof(*bd_data);
5821 __u64 rawSwapped;
5822 __u8 *raw;
5823 bool_Bool valid_id = true1;
5824 struct json_object *root = json_create_object()json_object_new_object();
5825
5826 while (valid_id && bd_data < end) {
5827 raw = bd_data->raw_value;
5828 rawSwapped = shr_get_unaligned_le64(raw) >> 8;
5829
5830 switch (bd_data->field_id) {
5831 case 0x0:
5832 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))
5833 bd_data->normalized_value)json_object_object_add(root, "program_fail_count normalized",
json_object_new_int(bd_data->normalized_value))
;
5834 json_object_add_value_uint64(root, "program_fail_count raw",json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
5835 rawSwapped)json_object_object_add(root, "program_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5836 break;
5837 case 0x1:
5838 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))
5839 bd_data->normalized_value)json_object_object_add(root, "erase_fail_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5840 json_object_add_value_uint64(root, "erase_fail_count raw",json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
5841 rawSwapped)json_object_object_add(root, "erase_fail_count raw", json_object_new_uint64
(rawSwapped))
;
5842 break;
5843 case 0x2:
5844 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))
5845 bd_data->normalized_value)json_object_object_add(root, "wear_leveling normalized", json_object_new_int
(bd_data->normalized_value))
;
5846 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])))
5847 shr_get_unaligned_le16(&raw[1]))json_object_object_add(root, "wear_leveling min", json_object_new_int
(shr_get_unaligned_le16(&raw[1])))
;
5848 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])))
5849 shr_get_unaligned_le16(&raw[3]))json_object_object_add(root, "wear_leveling max", json_object_new_int
(shr_get_unaligned_le16(&raw[3])))
;
5850 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])))
5851 shr_get_unaligned_le16(&raw[5]))json_object_object_add(root, "wear_leveling avg", json_object_new_int
(shr_get_unaligned_le16(&raw[5])))
;
5852 break;
5853 case 0x3:
5854 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))
5855 "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))
5856 bd_data->normalized_value)json_object_object_add(root, "end_to_end_error_detection_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5857 json_object_add_value_uint64(root,json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5858 "end_to_end_error_detection_count raw",json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
5859 rawSwapped)json_object_object_add(root, "end_to_end_error_detection_count raw"
, json_object_new_uint64(rawSwapped))
;
5860 break;
5861 case 0x4:
5862 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))
5863 bd_data->normalized_value)json_object_object_add(root, "crc_error_count normalized", json_object_new_int
(bd_data->normalized_value))
;
5864 json_object_add_value_uint64(root, "crc_error_count raw",json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
5865 rawSwapped)json_object_object_add(root, "crc_error_count raw", json_object_new_uint64
(rawSwapped))
;
5866 break;
5867 case 0x5:
5868 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))
5869 bd_data->normalized_value)json_object_object_add(root, "timed_workload_media_wear normalized"
, json_object_new_int(bd_data->normalized_value))
;
5870 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)))
5871 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)))
;
5872 break;
5873 case 0x6:
5874 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))
5875 bd_data->normalized_value)json_object_object_add(root, "timed_workload_host_reads normalized"
, json_object_new_int(bd_data->normalized_value))
;
5876 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))
5877 rawSwapped)json_object_object_add(root, "timed_workload_host_reads raw",
json_object_new_uint64(rawSwapped))
;
5878 break;
5879 case 0x7:
5880 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))
5881 bd_data->normalized_value)json_object_object_add(root, "timed_workload_timer normalized"
, json_object_new_int(bd_data->normalized_value))
;
5882 json_object_add_value_uint64(root, "timed_workload_timer",json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
5883 rawSwapped)json_object_object_add(root, "timed_workload_timer", json_object_new_uint64
(rawSwapped))
;
5884 break;
5885 case 0x8:
5886 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))
5887 bd_data->normalized_value)json_object_object_add(root, "thermal_throttle_status normalized"
, json_object_new_int(bd_data->normalized_value))
;
5888 json_object_add_value_int(root, "thermal_throttle_status",json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(raw[1]))
5889 raw[1])json_object_object_add(root, "thermal_throttle_status", json_object_new_int
(raw[1]))
;
5890 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])))
5891 shr_get_unaligned_le32(&raw[2]))json_object_object_add(root, "thermal_throttle_cnt", json_object_new_int
(shr_get_unaligned_le32(&raw[2])))
;
5892 break;
5893 case 0x9:
5894 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))
5895 bd_data->normalized_value)json_object_object_add(root, "retry_buffer_overflow_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5896 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))
5897 rawSwapped)json_object_object_add(root, "retry_buffer_overflow_count raw"
, json_object_new_uint64(rawSwapped))
;
5898 break;
5899 case 0xA:
5900 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))
5901 bd_data->normalized_value)json_object_object_add(root, "pll_lock_loss_count normalized"
, json_object_new_int(bd_data->normalized_value))
;
5902 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))
5903 rawSwapped)json_object_object_add(root, "pll_lock_loss_count raw", json_object_new_uint64
(rawSwapped))
;
5904 break;
5905 case 0xB:
5906 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))
5907 bd_data->normalized_value)json_object_object_add(root, "nand_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5908 json_object_add_value_uint64(root, "nand_bytes_written raw",json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
5909 rawSwapped)json_object_object_add(root, "nand_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5910 break;
5911 case 0xC:
5912 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))
5913 bd_data->normalized_value)json_object_object_add(root, "host_bytes_written normalized",
json_object_new_int(bd_data->normalized_value))
;
5914 json_object_add_value_uint64(root, "host_bytes_written raw",json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
5915 rawSwapped)json_object_object_add(root, "host_bytes_written raw", json_object_new_uint64
(rawSwapped))
;
5916
5917 /* last entry, break from while loop */
5918 valid_id = false0;
5919 break;
5920 default:
5921 printf(" Invalid Field ID = %d\n", bd_data->field_id);
5922 break;
5923 }
5924
5925 bd_data++;
5926 }
5927
5928 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
5929 printf("\n");
5930 json_free_object(root)json_object_put(root);
5931
5932 return;
5933}
5934
5935static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf)
5936{
5937 printf(" D0 Smart Log Page Statistics :-\n");
5938 printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"u""\n",
5939 (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count));
5940 printf(" Lifetime Power on Hours %20"PRIu32"u""\n",
5941 (uint32_t)le32_to_cpu(perf->lifetime_power_on_hours));
5942 printf(" Lifetime UECC Count %20"PRIu32"u""\n",
5943 (uint32_t)le32_to_cpu(perf->lifetime_uecc_count));
5944 printf(" Lifetime Write Amplification Factor %20"PRIu32"u""\n",
5945 (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor));
5946 printf(" Trailing Hour Write Amplification Factor %20"PRIu32"u""\n",
5947 (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor));
5948 printf(" Reserve Erase Block Count %20"PRIu32"u""\n",
5949 (uint32_t)le32_to_cpu(perf->reserve_erase_block_count));
5950 printf(" Lifetime Program Fail Count %20"PRIu32"u""\n",
5951 (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count));
5952 printf(" Lifetime Block Erase Fail Count %20"PRIu32"u""\n",
5953 (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count));
5954 printf(" Lifetime Die Failure Count %20"PRIu32"u""\n",
5955 (uint32_t)le32_to_cpu(perf->lifetime_die_failure_count));
5956 printf(" Lifetime Link Rate Downgrade Count %20"PRIu32"u""\n",
5957 (uint32_t)le32_to_cpu(perf->lifetime_link_rate_downgrade_count));
5958 printf(" Lifetime Clean Shutdown Count on Power Loss %20"PRIu32"u""\n",
5959 (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count));
5960 printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"u""\n",
5961 (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count));
5962 printf(" Current Temperature %20"PRIu32"u""\n",
5963 (uint32_t)le32_to_cpu(perf->current_temp));
5964 printf(" Max Recorded Temperature %20"PRIu32"u""\n",
5965 (uint32_t)le32_to_cpu(perf->max_recorded_temp));
5966 printf(" Lifetime Retired Block Count %20"PRIu32"u""\n",
5967 (uint32_t)le32_to_cpu(perf->lifetime_retired_block_count));
5968 printf(" Lifetime Read Disturb Reallocation Events %20"PRIu32"u""\n",
5969 (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events));
5970 printf(" Lifetime NAND Writes %20"PRIu64"l" "u""\n",
5971 le64_to_cpu(perf->lifetime_nand_writes));
5972 printf(" Capacitor Health %20"PRIu32"u""%%\n",
5973 (uint32_t)le32_to_cpu(perf->capacitor_health));
5974 printf(" Lifetime User Writes %20"PRIu64"l" "u""\n",
5975 le64_to_cpu(perf->lifetime_user_writes));
5976 printf(" Lifetime User Reads %20"PRIu64"l" "u""\n",
5977 le64_to_cpu(perf->lifetime_user_reads));
5978 printf(" Lifetime Thermal Throttle Activations %20"PRIu32"u""\n",
5979 (uint32_t)le32_to_cpu(perf->lifetime_thermal_throttle_act));
5980 printf(" Percentage of P/E Cycles Remaining %20"PRIu32"u""%%\n",
5981 (uint32_t)le32_to_cpu(perf->percentage_pe_cycles_remaining));
5982}
5983
5984static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf)
5985{
5986 struct json_object *root = json_create_object()json_object_new_object();
5987
5988 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
)))
5989 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
)))
;
5990 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)))
5991 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)))
;
5992 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)))
5993 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)))
;
5994 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
)))
5995 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
)))
;
5996 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
)))
5997 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
)))
;
5998 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)))
5999 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)))
;
6000 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)))
6001 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)))
;
6002 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
)))
6003 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
)))
;
6004 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)))
6005 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)))
;
6006 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
)))
6007 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
)))
;
6008 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
)))
6009 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
)))
;
6010 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
)))
6011 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
)))
;
6012 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)))
6013 le32_to_cpu(perf->current_temp))json_object_object_add(root, "Current Temperature", json_object_new_int
(le32_to_cpu(perf->current_temp)))
;
6014 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)))
6015 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)))
;
6016 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)))
6017 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)))
;
6018 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
)))
6019 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
)))
;
6020 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)))
6021 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)))
;
6022 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)))
6023 le32_to_cpu(perf->capacitor_health))json_object_object_add(root, "Capacitor Health", json_object_new_int
(le32_to_cpu(perf->capacitor_health)))
;
6024 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)))
6025 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)))
;
6026 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)))
6027 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)))
;
6028 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
)))
6029 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
)))
;
6030 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
)))
6031 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
)))
;
6032
6033 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6034 printf("\n");
6035 json_free_object(root)json_object_put(root);
6036}
6037
6038static void wdc_get_commit_action_bin(__u8 commit_action_type,
6039 char *action_bin, size_t size)
6040{
6041
6042 switch (commit_action_type) {
6043 case 0:
6044 shr_strscpy(action_bin, "000b", size);
6045 break;
6046 case 1:
6047 shr_strscpy(action_bin, "001b", size);
6048 break;
6049 case 2:
6050 shr_strscpy(action_bin, "010b", size);
6051 break;
6052 case 3:
6053 shr_strscpy(action_bin, "011b", size);
6054 break;
6055 case 4:
6056 shr_strscpy(action_bin, "100b", size);
6057 break;
6058 case 5:
6059 shr_strscpy(action_bin, "101b", size);
6060 break;
6061 case 6:
6062 shr_strscpy(action_bin, "110b", size);
6063 break;
6064 case 7:
6065 shr_strscpy(action_bin, "111b", size);
6066 break;
6067 default:
6068 shr_strscpy(action_bin, "INVALID", size);
6069 }
6070
6071}
6072
6073static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
6074 __u32 cust_id, __u32 vendor_id,
6075 __u32 device_id)
6076{
6077 int i, j;
6078 char previous_fw[9];
6079 char new_fw[9];
6080 char commit_action_bin[8];
6081 char time_str[100];
6082 __u16 oldestEntryIdx = 0, entryIdx = 0;
6083 uint64_t timestamp;
6084 __u64 timestamp_sec;
6085 const char *null_fw = "--------";
6086
6087 memset((void *)time_str, '\0', 100);
6088
6089 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6090 printf(" Firmware Activate History Log\n");
6091 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005 ||
6092 vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6093 printf(" Power on Hour Power Cycle Previous New\n");
6094 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6095 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
6096 } else {
6097 printf(" Power Cycle Previous New\n");
6098 printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n");
6099 printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n");
6100 }
6101
6102 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6103
6104 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6105 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6106 /* find lowest/oldest entry */
6107 for (i = 0; i < num_entries; i++) {
6108 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6109 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6110 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6111 oldestEntryIdx = j;
6112 break;
6113 }
6114 }
6115 }
6116 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6117 entryIdx = 0;
6118 else
6119 entryIdx = oldestEntryIdx;
6120
6121 for (i = 0; i < num_entries; i++) {
6122 memset((void *)previous_fw, 0, 9);
6123 memset((void *)new_fw, 0, 9);
6124 memset((void *)commit_action_bin, 0, 8);
6125
6126 memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8);
6127 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6128 memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8);
6129 else
6130 memcpy(new_fw, null_fw, 8);
6131
6132 printf("%5"PRIu16"hu""", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
6133
6134 timestamp = (0x0000FFFFFFFFFFFF &
6135 le64_to_cpu(
6136 fw_act_history_entry->entry[entryIdx].timestamp));
6137 timestamp_sec = timestamp / 1000;
6138 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6139 printf(" ");
6140 memset((void *)time_str, 0, 9);
6141 snprintf((char *)time_str, sizeof(time_str),
6142 "%"PRIu32"u"":%u:%u",
6143 (__u32)(timestamp_sec/3600),
6144 (__u8)(timestamp_sec%3600/60),
6145 (__u8)(timestamp_sec%60));
6146
6147 printf("%s", time_str);
6148 printf(" ");
6149 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6150 printf(" ");
6151
6152 memset((void *)time_str, 0, 9);
6153 snprintf((char *)time_str, sizeof(time_str),
6154 "%"PRIu32"u"":%u:%u",
6155 (__u32)((timestamp_sec/3600)%24),
6156 (__u8)((timestamp_sec/60)%60),
6157 (__u8)(timestamp_sec%60));
6158 printf("%s", time_str);
6159 printf(" ");
6160 } else {
6161 printf(" ");
6162 printf("%16"PRIu64"l" "u""", timestamp);
6163 printf(" ");
6164 }
6165
6166 printf("%16"PRIu64"l" "u""", (uint64_t)le64_to_cpu(fw_act_history_entry->entry[entryIdx].power_cycle_count));
6167 printf(" ");
6168 printf("%s", (char *)previous_fw);
6169 printf(" ");
6170 printf("%s", (char *)new_fw);
6171 printf(" ");
6172 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number);
6173 printf(" ");
6174 wdc_get_commit_action_bin(
6175 fw_act_history_entry->entry[entryIdx].commit_action_type,
6176 commit_action_bin, sizeof(commit_action_bin));
6177 printf(" %s", (char *)commit_action_bin);
6178 printf(" ");
6179 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))
6180 printf("pass");
6181 else
6182 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result));
6183 printf("\n");
6184
6185 entryIdx++;
6186 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6187 entryIdx = 0;
6188 }
6189 } else {
6190 printf(" Firmware Activate History Log\n");
6191 printf(" Power on Hour Power Cycle Previous New\n");
6192 printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n");
6193 printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n");
6194
6195 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));
6196
6197 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6198 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6199 /* find lowest/oldest entry */
6200 for (i = 0; i < num_entries; i++) {
6201 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6202 oldestEntryIdx = i+1;
6203 break;
6204 }
6205 }
6206 }
6207
6208 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6209 entryIdx = 0;
6210 else
6211 entryIdx = oldestEntryIdx;
6212
6213 for (i = 0; i < num_entries; i++) {
6214 memset((void *)previous_fw, 0, 9);
6215 memset((void *)new_fw, 0, 9);
6216 memset((void *)commit_action_bin, 0, 8);
6217
6218 memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6219 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6220 memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6221 else
6222 memcpy(new_fw, null_fw, 8);
6223
6224 printf("%5"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].entry_num));
6225 printf(" ");
6226 printf("%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)/3600),
6227 (int)((le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%3600)/60),
6228 (int)(le64_to_cpu(fw_act_history_entry[entryIdx].power_on_seconds)%60));
6229 printf(" ");
6230 printf("%16"PRIu32"u""", (uint32_t)le32_to_cpu(fw_act_history_entry[entryIdx].power_cycle_count));
6231 printf(" ");
6232 printf("%s", (char *)previous_fw);
6233 printf(" ");
6234 printf("%s", (char *)new_fw);
6235 printf(" ");
6236 printf("%2"PRIu8"hhu""", (uint8_t)fw_act_history_entry[entryIdx].slot_number);
6237 printf(" ");
6238 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6239 commit_action_bin,
6240 sizeof(commit_action_bin));
6241 printf(" %s", (char *)commit_action_bin);
6242 printf(" ");
6243 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result))
6244 printf("pass");
6245 else
6246 printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result));
6247
6248 printf("\n");
6249
6250 entryIdx++;
6251 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6252 entryIdx = 0;
6253 }
6254 }
6255}
6256
6257static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
6258 __u32 cust_id, __u32 vendor_id,
6259 __u32 device_id)
6260{
6261 struct json_object *root = json_create_object()json_object_new_object();
6262 int i, j;
6263 char previous_fw[9];
6264 char new_fw[9];
6265 char commit_action_bin[8];
6266 char fail_str[32];
6267 char time_str[100];
6268 char ext_time_str[20];
6269 uint64_t timestamp;
6270 __u64 timestamp_sec;
6271
6272 memset((void *)previous_fw, 0, 9);
6273 memset((void *)new_fw, 0, 9);
6274 memset((void *)commit_action_bin, 0, 8);
6275 memset((void *)time_str, '\0', 100);
6276 memset((void *)ext_time_str, 0, 20);
6277 memset((void *)fail_str, 0, 11);
6278 char *null_fw = "--------";
6279 __u16 oldestEntryIdx = 0, entryIdx = 0;
6280
6281 if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
6282 struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
6283
6284 oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES20;
6285 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES20) {
6286 /* find lowest/oldest entry */
6287 for (i = 0; i < num_entries; i++) {
6288 j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
6289 if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) >
6290 le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) {
6291 oldestEntryIdx = j;
6292 break;
6293 }
6294 }
6295 }
6296 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6297 entryIdx = 0;
6298 else
6299 entryIdx = oldestEntryIdx;
6300
6301 for (i = 0; i < num_entries; i++) {
6302 struct wdc_fw_act_history_log_entry_c2 *e =
6303 &fw_act_history_entry->entry[entryIdx];
6304
6305 memcpy(previous_fw,
6306 (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version),
6307 8);
6308 if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1)
6309 memcpy(new_fw,
6310 (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version),
6311 8);
6312 else
6313 memcpy(new_fw, null_fw, 8);
6314
6315 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
)))
6316 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
)))
;
6317
6318 timestamp = (0x0000FFFFFFFFFFFF &
6319 le64_to_cpu(
6320 fw_act_history_entry->entry[entryIdx].timestamp));
6321 timestamp_sec = timestamp / 1000;
6322 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
6323 snprintf((char *)time_str, sizeof(time_str),
6324 "%"PRIu32"u"":%u:%u",
6325 (__u32)(timestamp_sec/3600),
6326 (__u8)(timestamp_sec%3600/60),
6327 (__u8)(timestamp_sec%60));
6328
6329 json_object_add_value_string(root, "Power on Hour", time_str);
6330
6331 } else if (vendor_id == WDC_NVME_SNDK_VID0x15b7) {
6332 snprintf((char *)time_str, sizeof(time_str),
6333 "%"PRIu32"u"":%u:%u",
6334 (__u32)((timestamp_sec/3600)%24),
6335 (__u8)((timestamp_sec/60)%60),
6336 (__u8)(timestamp_sec%60));
6337 json_object_add_value_string(root, "Power on Hour", time_str);
6338 } else {
6339 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
6340 }
6341
6342 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
)))
6343 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
)))
;
6344 json_object_add_value_string(root, "Previous Firmware",
6345 previous_fw);
6346 json_object_add_value_string(root, "New Firmware",
6347 new_fw);
6348 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))
6349 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))
;
6350
6351 wdc_get_commit_action_bin(
6352 fw_act_history_entry->entry[entryIdx].commit_action_type,
6353 commit_action_bin, sizeof(commit_action_bin));
6354 json_object_add_value_string(root, "Action", commit_action_bin);
6355
6356 if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) {
6357 json_object_add_value_string(root, "Result", "pass");
6358 } else {
6359 snprintf((char *)fail_str, sizeof(fail_str),
6360 "fail #%d",
6361 (int)(le16_to_cpu(e->result)));
6362 json_object_add_value_string(root, "Result", fail_str);
6363 }
6364
6365 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6366 printf("\n");
6367
6368 entryIdx++;
6369 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6370 entryIdx = 0;
6371 }
6372 } else {
6373 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));
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 if (le32_to_cpu(fw_act_history_entry[i].entry_num) > le32_to_cpu(fw_act_history_entry[i+1].entry_num)) {
6380 oldestEntryIdx = i+1;
6381 break;
6382 }
6383 }
6384 }
6385 if (oldestEntryIdx == WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6386 entryIdx = 0;
6387 else
6388 entryIdx = oldestEntryIdx;
6389
6390 for (i = 0; i < num_entries; i++) {
6391 struct wdc_fw_act_history_log_entry *e =
6392 &fw_act_history_entry[entryIdx];
6393 __u64 secs = le64_to_cpu(e->power_on_seconds);
6394
6395 memcpy(previous_fw,
6396 (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8);
6397 if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1)
6398 memcpy(new_fw,
6399 (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8);
6400 else
6401 memcpy(new_fw, null_fw, 8);
6402
6403 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)))
6404 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)))
;
6405
6406 snprintf((char *)time_str, sizeof(time_str),
6407 "%04d:%02d:%02d",
6408 (int)(secs / 3600), (int)((secs % 3600) / 60),
6409 (int)(secs % 60));
6410 json_object_add_value_string(root, "Power on Hour", time_str);
6411
6412 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
)))
6413 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
)))
;
6414 json_object_add_value_string(root, "Previous Firmware",
6415 previous_fw);
6416 json_object_add_value_string(root, "New Firmware",
6417 new_fw);
6418 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
6419 fw_act_history_entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_history_entry
[entryIdx].slot_number))
;
6420
6421 wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,
6422 commit_action_bin,
6423 sizeof(commit_action_bin));
6424 json_object_add_value_string(root, "Action", commit_action_bin);
6425
6426 if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) {
6427 json_object_add_value_string(root, "Result", "pass");
6428 } else {
6429 snprintf((char *)fail_str, sizeof(fail_str),
6430 "fail #%d",
6431 (int)(le16_to_cpu(e->result)));
6432 json_object_add_value_string(root, "Result", fail_str);
6433 }
6434
6435 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6436 printf("\n");
6437
6438 entryIdx++;
6439 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES20)
6440 entryIdx = 0;
6441 }
6442 }
6443
6444 json_free_object(root)json_object_put(root);
6445}
6446
6447static int nvme_get_print_ocp_cloud_smart_log(struct libnvme_transport_handle *hdl,
6448 int uuid_index,
6449 __u32 namespace_id,
6450 int fmt)
6451{
6452 struct ocp_cloud_smart_log *log_ptr = NULL((void*)0);
6453 struct libnvme_passthru_cmd cmd;
6454 int ret, i;
6455
6456 log_ptr = malloc(sizeof(*log_ptr));
6457 if (!log_ptr) {
6458 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6459 return -1;
6460 }
6461
6462 if (namespace_id == NVME_NSID_ALL) {
6463 ret = libnvme_get_nsid(hdl, &namespace_id);
6464 if (ret < 0)
6465 namespace_id = NVME_NSID_ALL;
6466 }
6467
6468 /* Get the 0xC0 log data */
6469 nvme_init_get_log(&cmd, namespace_id,
6470 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6471 log_ptr, sizeof(*log_ptr));
6472 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6473 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6474 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6475 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6476 if (fmt == JSON)
6477 nvme_show_status(ret);
6478
6479 if (!ret) {
6480 /* Verify GUID matches */
6481 for (i = 0; i < 16; i++) {
6482 if (scao_guid[i] != log_ptr->log_page_guid[i]) {
6483 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"
)
;
6484 int j;
6485
6486 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6487 for (j = 0; j < 16; j++)
6488 nvme_show_error("%x", scao_guid[j])nvme_show_message(1, "%x", scao_guid[j]);
6489 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6490 for (j = 0; j < 16; j++)
6491 nvme_show_error("%x", log_ptr->log_page_guid[j])nvme_show_message(1, "%x", log_ptr->log_page_guid[j]);
6492 nvme_show_error("")nvme_show_message(1, "");
6493
6494 ret = -1;
6495 break;
6496 }
6497 }
6498
6499 if (!ret)
6500 /* parse the data */
6501 wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl);
6502 } else {
6503 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"
)
;
6504 ret = -1;
6505 }
6506
6507 free(log_ptr);
6508 return ret;
6509}
6510
6511static int nvme_get_print_c0_eol_log(struct libnvme_transport_handle *hdl,
6512 int uuid_index,
6513 __u32 namespace_id,
6514 int fmt)
6515{
6516 __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN0x200;
6517 struct libnvme_passthru_cmd cmd;
6518 void *log_ptr = NULL((void*)0);
6519 int ret;
6520
6521 log_ptr = (void *)malloc(sizeof(__u8) * length);
6522 if (!log_ptr) {
6523 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6524 return -1;
6525 }
6526
6527 if (namespace_id == NVME_NSID_ALL) {
6528 ret = libnvme_get_nsid(hdl, &namespace_id);
6529 if (ret < 0)
6530 namespace_id = NVME_NSID_ALL;
6531 }
6532
6533 /* Get the 0xC0 log data */
6534 nvme_init_get_log(&cmd, namespace_id,
6535 WDC_NVME_GET_EOL_STATUS_LOG_OPCODE0xC0, NVME_CSI_NVM,
6536 log_ptr, length);
6537 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6538 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6539 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6540 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6541 if (fmt == JSON)
6542 nvme_show_status(ret);
6543
6544 if (!ret) {
6545 /* parse the data */
6546 wdc_print_c0_eol_log(log_ptr, fmt);
6547 } else {
6548 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 "
)
;
6549 nvme_show_error("with uuid index %d", uuid_index)nvme_show_message(1, "with uuid index %d", uuid_index);
6550 ret = -1;
6551 }
6552
6553 free(log_ptr);
6554 return ret;
6555}
6556
6557static int nvme_get_ext_smart_cloud_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6558{
6559 struct libnvme_passthru_cmd cmd;
6560 __u8 *log_ptr = NULL((void*)0);
6561 int ret, i;
6562
6563 log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6564 if (!log_ptr) {
6565 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6566 return -1;
6567 }
6568
6569 /* Get the 0xC0 log data */
6570 nvme_init_get_log(&cmd, namespace_id,
6571 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, NVME_CSI_NVM,
6572 log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN0x200);
6573 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6574 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6575 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6576 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6577 if (!ret) {
6578 /* Verify GUID matches */
6579 for (i = 0; i < WDC_C0_GUID_LENGTH16; i++) {
6580 if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
6581 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"
)
;
6582 int j;
6583
6584 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6585 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6586 nvme_show_error("%x", ext_smart_guid[j])nvme_show_message(1, "%x", ext_smart_guid[j]);
6587 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6588 for (j = 0; j < WDC_C0_GUID_LENGTH16; j++)
6589 nvme_show_error("%x", *&log_ptr[SCAO_V1_LPG + j])nvme_show_message(1, "%x", *&log_ptr[SCAO_V1_LPG + j]);
6590 nvme_show_error("")nvme_show_message(1, "");
6591
6592 ret = -1;
6593 break;
6594 }
6595 }
6596 }
6597
6598 *data = log_ptr;
6599
6600 return ret;
6601}
6602
6603
6604static int nvme_get_hw_rev_log(struct libnvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id)
6605{
6606 struct wdc_nvme_hw_rev_log *log_ptr = NULL((void*)0);
6607 struct libnvme_passthru_cmd cmd;
6608 int ret, i;
6609
6610 log_ptr = malloc(sizeof(*log_ptr));
6611 if (!log_ptr) {
6612 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
6613 return -1;
6614 }
6615
6616 /* Get the 0xC0 log data */
6617 nvme_init_get_log(&cmd, namespace_id,
6618 WDC_NVME_GET_HW_REV_LOG_OPCODE0xc6, NVME_CSI_NVM,
6619 log_ptr, sizeof(*log_ptr));
6620 cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6621 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
6622 NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
6623 ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
6624 if (!ret) {
6625 /* Verify GUID matches */
6626 for (i = 0; i < WDC_NVME_C6_GUID_LENGTH16; i++) {
6627 if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
6628 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"
)
;
6629 int j;
6630
6631 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
6632 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6633 nvme_show_error("%x", hw_rev_log_guid[j])nvme_show_message(1, "%x", hw_rev_log_guid[j]);
6634 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
6635 for (j = 0; j < WDC_NVME_C6_GUID_LENGTH16; j++)
6636 nvme_show_error("%x", log_ptr->hw_rev_guid[j])nvme_show_message(1, "%x", log_ptr->hw_rev_guid[j]);
6637 nvme_show_error("")nvme_show_message(1, "");
6638
6639 ret = -1;
6640 break;
6641 }
6642 }
6643 }
6644
6645 *data = (__u8 *)log_ptr;
6646
6647 return ret;
6648}
6649
6650
6651static void wdc_print_hw_rev_log_normal(void *data)
6652{
6653 int i;
6654 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6655
6656 printf(" Hardware Revision Log:-\n");
6657
6658 printf(" Global Device HW Revision : %d\n",
6659 log_data->hw_rev_gdr);
6660 printf(" ASIC HW Revision : %d\n",
6661 log_data->hw_rev_ar);
6662 printf(" PCB Manufacturer Code : %d\n",
6663 log_data->hw_rev_pbc_mc);
6664 printf(" DRAM Manufacturer Code : %d\n",
6665 log_data->hw_rev_dram_mc);
6666 printf(" NAND Manufacturer Code : %d\n",
6667 log_data->hw_rev_nand_mc);
6668 printf(" PMIC 1 Manufacturer Code : %d\n",
6669 log_data->hw_rev_pmic1_mc);
6670 printf(" PMIC 2 Manufacturer Code : %d\n",
6671 log_data->hw_rev_pmic2_mc);
6672 printf(" Other Component 1 Manf Code : %d\n",
6673 log_data->hw_rev_c1_mc);
6674 printf(" Other Component 2 Manf Code : %d\n",
6675 log_data->hw_rev_c2_mc);
6676 printf(" Other Component 3 Manf Code : %d\n",
6677 log_data->hw_rev_c3_mc);
6678 printf(" Other Component 4 Manf Code : %d\n",
6679 log_data->hw_rev_c4_mc);
6680 printf(" Other Component 5 Manf Code : %d\n",
6681 log_data->hw_rev_c5_mc);
6682 printf(" Other Component 6 Manf Code : %d\n",
6683 log_data->hw_rev_c6_mc);
6684 printf(" Other Component 7 Manf Code : %d\n",
6685 log_data->hw_rev_c7_mc);
6686 printf(" Other Component 8 Manf Code : %d\n",
6687 log_data->hw_rev_c8_mc);
6688 printf(" Other Component 9 Manf Code : %d\n",
6689 log_data->hw_rev_c9_mc);
6690
6691 printf(" Device Manf Detailed Info : 0x");
6692 for (i = 0; i < 16; i++) {
6693 printf("%02x", log_data->hw_rev_dev_mdi[i]);
6694 if (i == 7)
6695 printf(" 0x");
6696 }
6697 printf("\n");
6698 printf(" ASIC Detailed Info : 0x");
6699 for (i = 0; i < 16; i++) {
6700 printf("%02x", log_data->hw_rev_asic_di[i]);
6701 if (i == 7)
6702 printf(" 0x");
6703 }
6704 printf("\n");
6705 printf(" PCB Detailed Info : 0x");
6706 for (i = 0; i < 16; i++) {
6707 printf("%02x", log_data->hw_rev_pcb_di[i]);
6708 if (i == 7)
6709 printf(" 0x");
6710 }
6711 printf("\n");
6712 printf(" DRAM Detailed Info : 0x");
6713 for (i = 0; i < 16; i++) {
6714 printf("%02x", log_data->hw_rev_dram_di[i]);
6715 if (i == 7)
6716 printf(" 0x");
6717 }
6718 printf("\n");
6719 printf(" NAND Detailed Info : 0x");
6720 for (i = 0; i < 16; i++) {
6721 printf("%02x", log_data->hw_rev_nand_di[i]);
6722 if (i == 7)
6723 printf(" 0x");
6724 }
6725 printf("\n");
6726 printf(" PMIC 1 Detailed Info : 0x");
6727 for (i = 0; i < 16; i++) {
6728 printf("%02x", log_data->hw_rev_pmic1_di[i]);
6729 if (i == 7)
6730 printf(" 0x");
6731 }
6732 printf("\n");
6733 printf(" PMIC 2 Detailed Info : 0x");
6734 for (i = 0; i < 16; i++) {
6735 printf("%02x", log_data->hw_rev_pmic2_di[i]);
6736 if (i == 7)
6737 printf(" 0x");
6738 }
6739 printf("\n");
6740 printf(" Component 1 Detailed Info : 0x");
6741 for (i = 0; i < 16; i++) {
6742 printf("%02x", log_data->hw_rev_c1_di[i]);
6743 if (i == 7)
6744 printf(" 0x");
6745 }
6746 printf("\n");
6747 printf(" Component 2 Detailed Info : 0x");
6748 for (i = 0; i < 16; i++) {
6749 printf("%02x", log_data->hw_rev_c2_di[i]);
6750 if (i == 7)
6751 printf(" 0x");
6752 }
6753 printf("\n");
6754 printf(" Component 3 Detailed Info : 0x");
6755 for (i = 0; i < 16; i++) {
6756 printf("%02x", log_data->hw_rev_c3_di[i]);
6757 if (i == 7)
6758 printf(" 0x");
6759 }
6760 printf("\n");
6761 printf(" Component 4 Detailed Info : 0x");
6762 for (i = 0; i < 16; i++) {
6763 printf("%02x", log_data->hw_rev_c4_di[i]);
6764 if (i == 7)
6765 printf(" 0x");
6766 }
6767 printf("\n");
6768 printf(" Component 5 Detailed Info : 0x");
6769 for (i = 0; i < 16; i++) {
6770 printf("%02x", log_data->hw_rev_c5_di[i]);
6771 if (i == 7)
6772 printf(" 0x");
6773 }
6774 printf("\n");
6775 printf(" Component 6 Detailed Info : 0x");
6776 for (i = 0; i < 16; i++) {
6777 printf("%02x", log_data->hw_rev_c6_di[i]);
6778 if (i == 7)
6779 printf(" 0x");
6780 }
6781 printf("\n");
6782 printf(" Component 7 Detailed Info : 0x");
6783 for (i = 0; i < 16; i++) {
6784 printf("%02x", log_data->hw_rev_c7_di[i]);
6785 if (i == 7)
6786 printf(" 0x");
6787 }
6788 printf("\n");
6789 printf(" Component 8 Detailed Info : 0x");
6790 for (i = 0; i < 16; i++) {
6791 printf("%02x", log_data->hw_rev_c8_di[i]);
6792 if (i == 7)
6793 printf(" 0x");
6794 }
6795 printf("\n");
6796 printf(" Component 9 Detailed Info : 0x");
6797 for (i = 0; i < 16; i++) {
6798 printf("%02x", log_data->hw_rev_c9_di[i]);
6799 if (i == 7)
6800 printf(" 0x");
6801 }
6802 printf("\n");
6803 printf(" Serial Number : 0x");
6804 for (i = 0; i < 32; i++) {
6805 if ((i > 1) & !(i % 8))
6806 printf(" 0x");
6807 printf("%02x", log_data->hw_rev_sn[i]);
6808 }
6809 printf("\n");
6810
6811 printf(" Log Page Version : %d\n", log_data->hw_rev_version);
6812 printf(" Log page GUID : 0x");
6813 printf("%"PRIx64"l" "x""%"PRIx64"l" "x""\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6814 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6815 printf("\n");
6816}
6817
6818static void wdc_print_hw_rev_log_json(void *data)
6819{
6820 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
6821 struct json_object *root = json_create_object()json_object_new_object();
6822 char json_data[80];
6823
6824 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))
6825 log_data->hw_rev_gdr)json_object_object_add(root, "Global Device HW Revision", json_object_new_uint64
(log_data->hw_rev_gdr))
;
6826 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))
6827 log_data->hw_rev_ar)json_object_object_add(root, "ASIC HW Revision", json_object_new_uint64
(log_data->hw_rev_ar))
;
6828 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))
6829 log_data->hw_rev_pbc_mc)json_object_object_add(root, "PCB Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_pbc_mc))
;
6830 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))
6831 log_data->hw_rev_dram_mc)json_object_object_add(root, "DRAM Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_dram_mc))
;
6832 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))
6833 log_data->hw_rev_nand_mc)json_object_object_add(root, "NAND Manufacturer Code", json_object_new_uint64
(log_data->hw_rev_nand_mc))
;
6834 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))
6835 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))
;
6836 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))
6837 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))
;
6838 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))
6839 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))
;
6840 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))
6841 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))
;
6842 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))
6843 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))
;
6844 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))
6845 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))
;
6846 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))
6847 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))
;
6848 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))
6849 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))
;
6850 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))
6851 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))
;
6852 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))
6853 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))
;
6854 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))
6855 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))
;
6856
6857 memset((void *)json_data, 0, 40);
6858 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6859 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]),
6860 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
6861 json_object_add_value_string(root, "Device Manf Detailed Info", json_data);
6862
6863 memset((void *)json_data, 0, 40);
6864 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6865 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]),
6866 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
6867 json_object_add_value_string(root, "ASIC Detailed Info", json_data);
6868
6869 memset((void *)json_data, 0, 40);
6870 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6871 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]),
6872 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
6873 json_object_add_value_string(root, "PCB Detailed Info", json_data);
6874
6875 memset((void *)json_data, 0, 40);
6876 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6877 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]),
6878 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
6879 json_object_add_value_string(root, "DRAM Detailed Info", json_data);
6880
6881 memset((void *)json_data, 0, 40);
6882 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6883 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]),
6884 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
6885 json_object_add_value_string(root, "NAND Detailed Info", json_data);
6886
6887 memset((void *)json_data, 0, 40);
6888 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6889 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]),
6890 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
6891 json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
6892
6893 memset((void *)json_data, 0, 40);
6894 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6895 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
6896 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
6897 json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
6898
6899 memset((void *)json_data, 0, 40);
6900 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6901 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
6902 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
6903 json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
6904
6905 memset((void *)json_data, 0, 40);
6906 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6907 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
6908 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
6909 json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
6910
6911 memset((void *)json_data, 0, 40);
6912 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6913 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
6914 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
6915 json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
6916
6917 memset((void *)json_data, 0, 40);
6918 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6919 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
6920 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
6921 json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
6922
6923 memset((void *)json_data, 0, 40);
6924 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6925 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
6926 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
6927 json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
6928
6929 memset((void *)json_data, 0, 40);
6930 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6931 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
6932 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
6933 json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
6934
6935 memset((void *)json_data, 0, 40);
6936 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6937 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
6938 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
6939 json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
6940
6941 memset((void *)json_data, 0, 40);
6942 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6943 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
6944 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
6945 json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
6946
6947 memset((void *)json_data, 0, 40);
6948 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6949 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
6950 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
6951 json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
6952
6953 memset((void *)json_data, 0, 80);
6954 snprintf((char *)json_data, sizeof(json_data),
6955 "0x%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""%"PRIx64"l" "x""",
6956 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]),
6957 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
6958 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]),
6959 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
6960 json_object_add_value_string(root, "Serial Number", json_data);
6961
6962 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)))
6963 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)))
;
6964
6965 memset((void *)json_data, 0, 40);
6966 snprintf((char *)json_data, sizeof(json_data), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
6967 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
6968 le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
6969 json_object_add_value_string(root, "Log Page GUID", json_data);
6970
6971 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
6972 printf("\n");
6973 json_free_object(root)json_object_put(root);
6974}
6975
6976static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
6977{
6978 int i;
6979 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
6980
6981 if (mask == WDC_SCA_V1_NAND_STATS0x1)
6982 printf(" NAND Statistics :-\n");
6983 else
6984 printf(" SMART Cloud Attributes :-\n");
6985
6986 printf(" Physical Media Units Written TLC (Bytes): %s\n",
6987 uint128_t_to_string(le128_to_cpu(
6988 ext_smart_log_ptr->ext_smart_pmuwt)));
6989 printf(" Physical Media Units Written SLC (Bytes): %s\n",
6990 uint128_t_to_string(le128_to_cpu(
6991 ext_smart_log_ptr->ext_smart_pmuws)));
6992 printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
6993 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
6994 printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
6995 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
6996 printf(" XOR Recovery Count (Int) : %"PRIu64"l" "u""\n",
6997 le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
6998 printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"l" "u""\n",
6999 le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
7000 if (mask == WDC_SCA_V1_ALL0xF) {
7001 printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"l" "u""\n",
7002 le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
7003 printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"l" "u""\n",
7004 le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
7005 printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"l" "u""\n",
7006 le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
7007 printf(" System Data %% life-used : %d %%\n",
7008 ext_smart_log_ptr->ext_smart_sdpu);
7009 }
7010 printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"l" "u""\n",
7011 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
7012 printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"l" "u""\n",
7013 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
7014 printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"l" "u""\n",
7015 le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
7016 printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"l" "u""\n",
7017 le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
7018 printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"l" "u""\n",
7019 le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
7020 printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"l" "u""\n",
7021 le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
7022 printf(" Program Fail Count (Normalized) (Int) : %d\n",
7023 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
7024 printf(" Program Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7025 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
7026 printf(" Erase Fail Count (Normalized) (Int) : %d\n",
7027 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
7028 printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7029 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
7030 if (mask == WDC_SCA_V1_ALL0xF) {
7031 printf(" PCIe Correctable Error Count (Int) : %"PRIu64"l" "u""\n",
7032 le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
7033 printf(" %% Free Blocks (User) (Int) : %d %%\n",
7034 ext_smart_log_ptr->ext_smart_pfbu);
7035 printf(" Security Version Number (Int) : %"PRIu64"l" "u""\n",
7036 le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
7037 printf(" %% Free Blocks (System) (Int) : %d %%\n",
7038 ext_smart_log_ptr->ext_smart_pfbs);
7039 printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n",
7040 uint128_t_to_string(le128_to_cpu(
7041 ext_smart_log_ptr->ext_smart_dcc)));
7042 printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"l" "u""\n",
7043 le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
7044 printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
7045 le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
7046 printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
7047 ext_smart_log_ptr->ext_smart_bbpg);
7048 }
7049 printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"l" "u""\n",
7050 le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
7051 if (mask == WDC_SCA_V1_ALL0xF) {
7052 printf(" Total # of Read Refresh Count (Int) : %"PRIu64"l" "u""\n",
7053 le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
7054 }
7055 printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
7056 le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
7057 printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"l" "u""\n",
7058 le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
7059 printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n",
7060 uint128_t_to_string(
7061 le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)));
7062 if (mask == WDC_SCA_V1_ALL0xF) {
7063 printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
7064 le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
7065 printf(" Total # Unaligned I/O (Int) : %"PRIu64"l" "u""\n",
7066 le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
7067 }
7068 printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n",
7069 uint128_t_to_string(
7070 le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)));
7071 if (mask == WDC_SCA_V1_ALL0xF) {
7072 printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7073 le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
7074 printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7075 le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
7076 printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"u""\n",
7077 le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
7078 printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"l" "u""\n",
7079 le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
7080 printf(" Active Power State Change Count (Int) : %"PRIu64"l" "u""\n",
7081 le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
7082 }
7083 printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
7084 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7085 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7086 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7087 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7088 printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
7089 0, 0, 0, 0);
7090 if (mask == WDC_SCA_V1_ALL0xF) {
7091 printf(" FTL Unit Size : %"PRIu32"u""\n",
7092 le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
7093 printf(" TCG Ownership Status : %"PRIu32"u""\n",
7094 le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
7095 printf(" Log Page Version (Int) : %d\n",
7096 le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
7097 printf(" Log page GUID (Hex) : 0x");
7098 for (i = WDC_C0_GUID_LENGTH16; i > 0; i--)
7099 printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
7100 printf("\n");
7101 }
7102 printf("\n");
7103}
7104
7105static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
7106{
7107 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr =
7108 (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
7109 struct json_object *root = json_create_object()json_object_new_object();
7110
7111 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)))
7112 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)))
;
7113 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)))
7114 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)))
;
7115 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
)))
7116 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
)))
;
7117 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)))
7118 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)))
;
7119 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)))
7120 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)))
;
7121 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)))
7122 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)))
;
7123 if (mask == WDC_SCA_V1_ALL0xF) {
7124 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)))
7125 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)))
;
7126 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)))
7127 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)))
;
7128 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)))
7129 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)))
;
7130 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))
7131 (__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))
;
7132 }
7133 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
)))
7134 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
)))
;
7135 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
)))
7136 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
)))
;
7137 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
)))
7138 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
)))
;
7139 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
)))
7140 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
)))
;
7141 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
)))
7142 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
)))
;
7143 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
)))
7144 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
)))
;
7145 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)))
7146 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)))
;
7147 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)))
7148 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)))
;
7149 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
)))
7150 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
)))
;
7151 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)))
7152 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)))
;
7153 if (mask == WDC_SCA_V1_ALL0xF) {
7154 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)))
7155 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)))
;
7156 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))
7157 (__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))
;
7158 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)))
7159 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)))
;
7160 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))
7161 (__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))
;
7162 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)))
7163 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)))
;
7164 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)))
7165 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)))
;
7166 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)))
7167 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)))
;
7168 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))
7169 (__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))
;
7170 }
7171 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)))
7172 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)))
;
7173 if (mask == WDC_SCA_V1_ALL0xF)
7174 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)))
7175 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)))
;
7176 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
)))
7177 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
)))
;
7178 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)))
7179 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)))
;
7180 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)))
7181 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)))
;
7182 if (mask == WDC_SCA_V1_ALL0xF) {
7183 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)))
7184 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)))
;
7185 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)))
7186 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)))
;
7187 }
7188 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)))
7189 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)))
;
7190 if (mask == WDC_SCA_V1_ALL0xF) {
7191 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)))
7192 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)))
;
7193 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)))
7194 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)))
;
7195 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)))
7196 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)))
;
7197 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)))
7198 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)))
;
7199 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
)))
7200 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
)))
;
7201 }
7202 char vers_str[40];
7203
7204 memset((void *)vers_str, 0, 40);
7205 snprintf((char *)vers_str, sizeof(vers_str), "%d.%d.%d.%d",
7206 le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
7207 le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
7208 le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
7209 le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
7210 json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
7211 memset((void *)vers_str, 0, 40);
7212 snprintf((char *)vers_str, sizeof(vers_str), "%d.%d.%d.%d", 0, 0, 0, 0);
7213 json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
7214
7215 if (mask == WDC_SCA_V1_ALL0xF) {
7216 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)))
7217 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)))
;
7218 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)))
7219 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)))
;
7220 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)))
7221 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)))
;
7222 char guid[40];
7223 __u8 *lpg;
7224
7225 lpg = ext_smart_log_ptr->ext_smart_lpg;
7226 snprintf((char *)guid, sizeof(guid), "0x%"PRIx64"l" "x""%"PRIx64"l" "x""",
7227 shr_get_unaligned_le64(&lpg[8]),
7228 shr_get_unaligned_le64(&lpg[0]));
7229 json_object_add_value_string(root, "log_page_guid", guid);
7230 }
7231
7232 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7233 printf("\n");
7234 json_free_object(root)json_object_put(root);
7235}
7236
7237static void wdc_print_eol_c0_normal(void *data)
7238{
7239 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7240 (struct wdc_nvme_c0_eol_log_page *)data;
7241
7242 printf(" End of Life Log Page 0xC0 :-\n");
7243 printf(" Realloc Block Count %"PRIu32"u""\n",
7244 le32_to_cpu(eol_log_page_ptr->eol_rbc));
7245 printf(" Write Amp %"PRIu32"u""\n",
7246 le32_to_cpu(eol_log_page_ptr->eol_wra));
7247 printf(" Percent Life Remaining %"PRIu32"u""\n",
7248 le32_to_cpu(eol_log_page_ptr->eol_plr));
7249 printf(" Program Fail Count %"PRIu32"u""\n",
7250 le32_to_cpu(eol_log_page_ptr->eol_pfc));
7251 printf(" Erase Fail Count %"PRIu32"u""\n",
7252 le32_to_cpu(eol_log_page_ptr->eol_efc));
7253 printf(" Raw Read Error Rate %"PRIu32"u""\n",
7254 le32_to_cpu(eol_log_page_ptr->eol_rrer));
7255}
7256
7257static void wdc_print_eol_c0_json(void *data)
7258{
7259 struct wdc_nvme_c0_eol_log_page *eol_log_page_ptr =
7260 (struct wdc_nvme_c0_eol_log_page *)data;
7261 struct json_object *root = json_create_object()json_object_new_object();
7262
7263 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)))
7264 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)))
;
7265 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)))
7266 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)))
;
7267 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)))
7268 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)))
;
7269 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)))
7270 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)))
;
7271 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)))
7272 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)))
;
7273 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)))
7274 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)))
;
7275
7276 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
7277 printf("\n");
7278 json_free_object(root)json_object_put(root);
7279}
7280
7281static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
7282{
7283 if (!data) {
7284 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"
)
;
7285 return -1;
7286 }
7287 switch (fmt) {
7288 case NORMAL:
7289 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL0xF);
7290 break;
7291 case JSON:
7292 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL0xF);
7293 break;
7294 }
7295 return 0;
7296}
7297
7298static int wdc_print_c0_cloud_attr_log(void *data,
7299 int fmt,
7300 struct libnvme_transport_handle *hdl)
7301{
7302 struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data;
7303
7304 if (!data) {
7305 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7306 return -1;
7307 }
7308
7309 switch (fmt) {
7310 case BINARY:
7311 d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log));
7312 break;
7313 case NORMAL:
7314 wdc_show_cloud_smart_log_normal(log, hdl);
7315 break;
7316 case JSON:
7317 wdc_show_cloud_smart_log_json(log);
7318 break;
7319 }
7320 return 0;
7321}
7322
7323static int wdc_print_c0_eol_log(void *data, int fmt)
7324{
7325 if (!data) {
7326 nvme_show_error("ERROR: WDC: Invalid buffer to read 0xC0 log")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read 0xC0 log"
)
;
7327 return -1;
7328 }
7329 switch (fmt) {
7330 case BINARY:
7331 d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN0x200);
7332 break;
7333 case NORMAL:
7334 wdc_print_eol_c0_normal(data);
7335 break;
7336 case JSON:
7337 wdc_print_eol_c0_json(data);
7338 break;
7339 }
7340 return 0;
7341}
7342
7343static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct libnvme_transport_handle *hdl, int uuid_index,
7344 char *format, __u32 namespace_id, int fmt)
7345{
7346 int ret;
7347
7348 if (!uuid_index) {
7349 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7350 uuid_index,
7351 namespace_id,
7352 fmt);
7353 } else if (uuid_index == 1) {
7354 ret = nvme_get_print_c0_eol_log(hdl,
7355 uuid_index,
7356 namespace_id,
7357 fmt);
7358 } else {
7359 nvme_show_error("ERROR: WDC: Unknown uuid index")nvme_show_message(1, "ERROR: WDC: Unknown uuid index");
7360 ret = -1;
7361 }
7362
7363 return ret;
7364}
7365
7366static int wdc_get_c0_log_page_sn(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, int uuid_index, char *format,
7367 __u32 namespace_id, int fmt)
7368{
7369 int ret = 0;
7370 __u32 cust_id;
7371
7372 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7373 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7374 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7375 return -1;
7376 }
7377
7378 if ((cust_id == WDC_CUSTOMER_ID_0x10040x1004) || (cust_id == WDC_CUSTOMER_ID_0x10080x1008) ||
7379 (cust_id == WDC_CUSTOMER_ID_0x10050x1005)) {
7380 ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format,
7381 namespace_id, fmt);
7382 } else {
7383 ret = nvme_get_print_c0_eol_log(hdl,
7384 0,
7385 namespace_id,
7386 fmt);
7387 }
7388
7389 return ret;
7390}
7391
7392static int wdc_get_c0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format, int uuid_index,
7393 __u32 namespace_id)
7394{
7395 uint32_t device_id = 0, read_vendor_id;
7396 nvme_print_flags_t fmt;
7397 int ret;
7398 __u8 *data;
7399 void *dev_mng_log = NULL((void*)0);
7400 __u32 market_name_len = 0;
7401 char marketing_name[64];
7402
7403 memset(marketing_name, 0, 64);
7404
7405 if (!wdc_check_device(ctx, hdl))
7406 return -1;
7407 ret = validate_output_format(format, &fmt);
7408 if (ret < 0) {
7409 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7410 return ret;
7411 }
7412
7413 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7414 if (ret) {
7415 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))
;
7416 return ret;
7417 }
7418
7419 switch (device_id) {
7420 case WDC_NVME_SN640_DEV_ID0x2400:
7421 case WDC_NVME_SN640_DEV_ID_10x2401:
7422 case WDC_NVME_SN640_DEV_ID_20x2402:
7423 case WDC_NVME_SN640_DEV_ID_30x2404:
7424 case WDC_NVME_SN840_DEV_ID0x2300:
7425 case WDC_NVME_SN840_DEV_ID_10x2500:
7426 case WDC_NVME_SN860_DEV_ID0x2730:
7427 case WDC_NVME_SN560_DEV_ID_10x2712:
7428 case WDC_NVME_SN560_DEV_ID_20x2713:
7429 case WDC_NVME_SN560_DEV_ID_30x2714:
7430 case WDC_NVME_SN550_DEV_ID0x2708:
7431 ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt);
7432 break;
7433 case WDC_NVME_SN650_DEV_ID0x2700:
7434 case WDC_NVME_SN650_DEV_ID_10x2701:
7435 case WDC_NVME_SN650_DEV_ID_20x2702:
7436 case WDC_NVME_SN650_DEV_ID_30x2720:
7437 case WDC_NVME_SN650_DEV_ID_40x2721:
7438 case WDC_NVME_SN655_DEV_ID0x2722:
7439 case WDC_NVME_SN655_DEV_ID_10x2723:
7440 case WDC_NVME_SNTMP_DEV_ID0x2761:
7441 case WDC_NVME_SNTMP_DEV_ID_10x2763:
7442 case WDC_NVME_SNESSD1_DEV_ID_E1L0x2765:
7443 case WDC_NVME_SNESSD1_DEV_ID_E20x2766:
7444 case WDC_NVME_SNESSD1_DEV_ID_E3S0x2767:
7445 case WDC_NVME_SNESSD1_DEV_ID_E3L0x2768:
7446 case WDC_NVME_SNESSD1_DEV_ID_U20x2769:
7447 if (uuid_index == 0) {
7448 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7449 uuid_index,
7450 namespace_id,
7451 fmt);
7452 } else {
7453 ret = nvme_get_print_c0_eol_log(hdl,
7454 uuid_index,
7455 namespace_id,
7456 fmt);
7457 }
7458 break;
7459 case WDC_NVME_ZN350_DEV_ID0x5010:
7460 case WDC_NVME_ZN350_DEV_ID_10x5018:
7461 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7462 0,
7463 NVME_NSID_ALL,
7464 fmt);
7465 break;
7466 case WDC_NVME_SN820CL_DEV_ID0x5037:
7467 /* Get the 0xC0 Extended Smart Cloud Attribute log data */
7468 data = NULL((void*)0);
7469 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
7470 uuid_index, namespace_id);
7471
7472 if (strcmp(format, "json"))
7473 nvme_show_status(ret);
7474
7475 if (!ret) {
7476 /* parse the data */
7477 wdc_print_ext_smart_cloud_log(data, fmt);
7478 } else {
7479 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"
)
;
7480 ret = -1;
7481 }
7482
7483 free(data);
7484 break;
7485 default:
7486 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
7487 nvme_show_error("ERROR: SNDK: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: SNDK: 0xC2 Log Page not found");
7488 ret = -1;
7489 goto out;
7490 }
7491
7492 if (!wdc_nvme_parse_dev_status_log_str(dev_mng_log,
7493 WDC_C2_MARKETING_NAME_ID0x07,
7494 (char *)marketing_name,
7495 sizeof(marketing_name),
7496 &market_name_len)) {
7497 nvme_show_error("ERROR: SNDK: Get Marketing Name Failed")nvme_show_message(1, "ERROR: SNDK: Get Marketing Name Failed"
)
;
7498 ret = -1;
7499 goto out;
7500 }
7501
7502 if ((!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_1"Ultrastar DC SN655", market_name_len)) ||
7503 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_2"ULTRASTAR DC SN655", market_name_len)) ||
7504 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_3"SanDisk DC SN655", market_name_len)) ||
7505 (!strncmp(marketing_name, WDC_SN655_MARKETING_NAME_4"SANDISK DC SN655", market_name_len))) {
7506 if (uuid_index == 0) {
7507 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
7508 uuid_index,
7509 namespace_id,
7510 fmt);
7511 } else {
7512 ret = nvme_get_print_c0_eol_log(hdl,
7513 uuid_index,
7514 namespace_id,
7515 fmt);
7516 }
7517 } else {
7518 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)
7519 device_id, marketing_name)nvme_show_message(1, "ERROR: WDC: Unknown device id: 0x%x or marketing name: %s"
, device_id, marketing_name)
;
7520 ret = -1;
7521 }
7522 break;
7523 }
7524
7525out:
7526 return ret;
7527}
7528
7529static int wdc_print_latency_monitor_log(struct libnvme_transport_handle *hdl,
7530 struct wdc_ssd_latency_monitor_log *log_data,
7531 int fmt)
7532{
7533 if (!log_data) {
7534 nvme_show_error("ERROR: WDC: Invalid C3 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C3 log data buffer"
)
;
7535 return -1;
7536 }
7537 switch (fmt) {
7538 case NORMAL:
7539 wdc_print_latency_monitor_log_normal(hdl, log_data);
7540 break;
7541 case JSON:
7542 wdc_print_latency_monitor_log_json(log_data);
7543 break;
7544 }
7545 return 0;
7546}
7547
7548static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
7549{
7550 if (!log_data) {
7551 nvme_show_error("ERROR: WDC: Invalid C1 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C1 log data buffer"
)
;
7552 return -1;
7553 }
7554 switch (fmt) {
7555 case NORMAL:
7556 wdc_print_error_rec_log_normal(log_data);
7557 break;
7558 case JSON:
7559 wdc_print_error_rec_log_json(log_data);
7560 break;
7561 }
7562 return 0;
7563}
7564
7565static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
7566{
7567 if (!log_data) {
7568 nvme_show_error("ERROR: WDC: Invalid C4 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C4 log data buffer"
)
;
7569 return -1;
7570 }
7571 switch (fmt) {
7572 case NORMAL:
7573 wdc_print_dev_cap_log_normal(log_data);
7574 break;
7575 case JSON:
7576 wdc_print_dev_cap_log_json(log_data);
7577 break;
7578 }
7579 return 0;
7580}
7581
7582static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
7583{
7584 if (!log_data) {
7585 nvme_show_error("ERROR: WDC: Invalid C5 log data buffer")nvme_show_message(1, "ERROR: WDC: Invalid C5 log data buffer"
)
;
7586 return -1;
7587 }
7588 switch (fmt) {
7589 case NORMAL:
7590 wdc_print_unsupported_reqs_log_normal(log_data);
7591 break;
7592 case JSON:
7593 wdc_print_unsupported_reqs_log_json(log_data);
7594 break;
7595 }
7596 return 0;
7597}
7598
7599static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
7600{
7601 if (!perf) {
7602 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7603 return -1;
7604 }
7605 switch (fmt) {
7606 case NORMAL:
7607 wdc_print_fb_ca_log_normal(perf);
7608 break;
7609 case JSON:
7610 wdc_print_fb_ca_log_json(perf);
7611 break;
7612 }
7613 return 0;
7614}
7615
7616static int wdc_print_bd_ca_log(struct libnvme_transport_handle *hdl, void *bd_data, int fmt)
7617{
7618 if (!bd_data) {
7619 nvme_show_error("ERROR: WDC: Invalid buffer to read data")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read data"
)
;
7620 return -1;
7621 }
7622 switch (fmt) {
7623 case NORMAL:
7624 wdc_print_bd_ca_log_normal(hdl, bd_data);
7625 break;
7626 case JSON:
7627 wdc_print_bd_ca_log_json(bd_data);
7628 break;
7629 default:
7630 nvme_show_error("ERROR: WDC: Unknown format - %d", fmt)nvme_show_message(1, "ERROR: WDC: Unknown format - %d", fmt);
7631 return -1;
7632 }
7633 return 0;
7634}
7635
7636static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt)
7637{
7638 if (!perf) {
7639 nvme_show_error("ERROR: WDC: Invalid buffer to read perf stats")nvme_show_message(1, "ERROR: WDC: Invalid buffer to read perf stats"
)
;
7640 return -1;
7641 }
7642 switch (fmt) {
7643 case NORMAL:
7644 wdc_print_d0_log_normal(perf);
7645 break;
7646 case JSON:
7647 wdc_print_d0_log_json(perf);
7648 break;
7649 }
7650 return 0;
7651}
7652
7653static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt,
7654 __u32 cust_id, __u32 vendor_id,
7655 __u32 device_id)
7656{
7657 if (!data) {
7658 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"
)
;
7659 return -1;
7660 }
7661
7662 switch (fmt) {
7663 case NORMAL:
7664 wdc_print_fw_act_history_log_normal(data, num_entries, cust_id,
7665 vendor_id, device_id);
7666 break;
7667 case JSON:
7668 wdc_print_fw_act_history_log_json(data, num_entries, cust_id,
7669 vendor_id, device_id);
7670 break;
7671 }
7672 return 0;
7673}
7674
7675static int wdc_get_ca_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7676{
7677 uint32_t read_device_id = 0, read_vendor_id;
7678 struct wdc_ssd_ca_perf_stats *perf;
7679 nvme_print_flags_t fmt;
7680 __u32 cust_id;
7681 __u8 *data;
7682 int ret;
7683
7684 if (!wdc_check_device(ctx, hdl))
7685 return -1;
7686 ret = validate_output_format(format, &fmt);
7687 if (ret < 0) {
7688 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7689 return ret;
7690 }
7691
7692 /* verify the 0xCA log page is supported */
7693 if (wdc_nvme_check_supported_log_page(ctx, hdl,
7694 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
7695 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
7696 return -1;
7697 }
7698
7699 /* get the FW customer id */
7700 cust_id = wdc_get_fw_cust_id(ctx, hdl);
7701 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
7702 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
7703 return -1;
7704 }
7705
7706 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
7707 if (ret) {
7708 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))
;
7709 return ret;
7710 }
7711
7712 switch (read_device_id) {
7713 case WDC_NVME_SN200_DEV_ID0x0023:
7714 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7715 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7716 if (!data) {
7717 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7718 return -1;
7719 }
7720
7721 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7722
7723 ret = nvme_get_log_simple(hdl,
7724 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7725 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7726 if (strcmp(format, "json"))
7727 nvme_show_status(ret);
7728
7729 if (!ret) {
7730 /* parse the data */
7731 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7732 ret = wdc_print_fb_ca_log(perf, fmt);
7733 } else {
7734 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"
)
;
7735 ret = -1;
7736 }
7737 } else {
7738
7739 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)
;
7740 return -1;
7741 }
7742 break;
7743 case WDC_NVME_SN640_DEV_ID0x2400:
7744 case WDC_NVME_SN640_DEV_ID_10x2401:
7745 case WDC_NVME_SN640_DEV_ID_20x2402:
7746 case WDC_NVME_SN640_DEV_ID_30x2404:
7747 case WDC_NVME_SN840_DEV_ID0x2300:
7748 case WDC_NVME_SN840_DEV_ID_10x2500:
7749 case WDC_NVME_SN860_DEV_ID0x2730:
7750 if (cust_id == WDC_CUSTOMER_ID_0x10050x1005) {
7751 data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7752 if (!data) {
7753 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7754 return -1;
7755 }
7756
7757 memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN0x80);
7758
7759 ret = nvme_get_log_simple(hdl,
7760 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7761 data, WDC_FB_CA_LOG_BUF_LEN0x80);
7762 if (strcmp(format, "json"))
7763 nvme_show_status(ret);
7764
7765 if (!ret) {
7766 /* parse the data */
7767 perf = (struct wdc_ssd_ca_perf_stats *)(data);
7768 ret = wdc_print_fb_ca_log(perf, fmt);
7769 } else {
7770 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"
)
;
7771 ret = -1;
7772 }
7773 } else if ((cust_id == WDC_CUSTOMER_ID_GN0x0001) || (cust_id == WDC_CUSTOMER_ID_GD0x0101) ||
7774 (cust_id == WDC_CUSTOMER_ID_BD0x1009)) {
7775 data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7776 if (!data) {
7777 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7778 return -1;
7779 }
7780
7781 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
7782 ret = nvme_get_log_simple(hdl,
7783 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA,
7784 data, WDC_BD_CA_LOG_BUF_LEN0xA0);
7785 if (strcmp(format, "json"))
7786 nvme_show_status(ret);
7787
7788 if (!ret) {
7789 /* parse the data */
7790 ret = wdc_print_bd_ca_log(hdl, data, fmt);
7791 } else {
7792 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"
)
;
7793 ret = -1;
7794 }
7795 } else {
7796 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)
;
7797 return -1;
7798 }
7799 break;
7800 default:
7801 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"
)
;
7802 return -1;
7803 }
7804
7805 free(data);
7806 return ret;
7807}
7808
7809static int wdc_get_c1_log_page(struct libnvme_global_ctx *ctx,
7810 struct libnvme_transport_handle *hdl, char *format,
7811 uint8_t interval)
7812{
7813 struct wdc_log_page_subpage_header *sph;
7814 struct wdc_ssd_perf_stats *perf;
7815 struct wdc_log_page_header *l;
7816 nvme_print_flags_t fmt;
7817 int total_subpages;
7818 int skip_cnt = 4;
7819 size_t off;
7820 __u8 *data;
7821 __u8 *p;
7822 int i;
7823 int ret;
7824
7825 if (!wdc_check_device(ctx, hdl))
7826 return -1;
7827
7828 ret = validate_output_format(format, &fmt);
7829 if (ret < 0) {
7830 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7831 return ret;
7832 }
7833
7834 if (interval < 1 || interval > 15) {
7835 nvme_show_error("ERROR: WDC: interval out of range [1-15]")nvme_show_message(1, "ERROR: WDC: interval out of range [1-15]"
)
;
7836 return -1;
7837 }
7838
7839 data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7840 if (!data) {
7841 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7842 return -1;
7843 }
7844 memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN0x4000);
7845
7846 ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE0xC1,
7847 data, WDC_ADD_LOG_BUF_LEN0x4000);
7848 if (strcmp(format, "json"))
7849 nvme_show_status(ret);
7850 if (!ret) {
7851 l = (struct wdc_log_page_header *)data;
7852 total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME0x0F - 1;
7853 /* the subpages must fit the buffer */
7854 for (i = 0, off = skip_cnt; i < total_subpages &&
7855 off < WDC_ADD_LOG_BUF_LEN0x4000 &&
7856 WDC_ADD_LOG_BUF_LEN0x4000 - off >= sizeof(*sph);
7857 i++, off += skip_cnt) {
7858 p = data + off;
7859 sph = (struct wdc_log_page_subpage_header *)p;
7860 if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE0x37) {
7861 if (sph->pcset == interval) {
7862 if (WDC_ADD_LOG_BUF_LEN0x4000 - off - 4 <
7863 sizeof(*perf))
7864 break;
7865 perf = (struct wdc_ssd_perf_stats *)(p + 4);
7866 ret = wdc_print_log(perf, fmt);
7867 break;
7868 }
7869 }
7870 skip_cnt = le16_to_cpu(sph->subpage_length) + 4;
7871 }
7872 if (ret)
7873 nvme_show_error("ERROR: WDC: Unable to read data from buffer")nvme_show_message(1, "ERROR: WDC: Unable to read data from buffer"
)
;
7874 }
7875 free(data);
7876 return ret;
7877}
7878
7879static int wdc_get_c3_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7880{
7881 struct wdc_ssd_latency_monitor_log *log_data;
7882 nvme_print_flags_t fmt;
7883 __u8 *data;
7884 int ret;
7885 int i;
7886
7887 if (!wdc_check_device(ctx, hdl))
7888 return -1;
7889
7890 ret = validate_output_format(format, &fmt);
7891 if (ret < 0) {
7892 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7893 return ret;
7894 }
7895
7896 data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7897 if (!data) {
7898 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7899 return -1;
7900 }
7901 memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7902
7903 ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID0xC3,
7904 data, WDC_LATENCY_MON_LOG_BUF_LEN0x200);
7905
7906 if (strcmp(format, "json"))
7907 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)
;
7908
7909 if (!ret) {
7910 log_data = (struct wdc_ssd_latency_monitor_log *)data;
7911
7912 /* check log page version */
7913 if (le16_to_cpu(log_data->log_page_version) !=
7914 WDC_LATENCY_MON_VERSION0x0001) {
7915 nvme_show_error("ERROR: WDC: invalid latency monitor version")nvme_show_message(1, "ERROR: WDC: invalid latency monitor version"
)
;
7916 ret = -1;
7917 goto out;
7918 }
7919
7920 /* check log page guid */
7921 /* Verify GUID matches */
7922 for (i = 0; i < 16; i++) {
7923 if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) {
7924 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"
)
;
7925 int j;
7926
7927 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
7928 for (j = 0; j < 16; j++)
7929 nvme_show_error("%x", wdc_lat_mon_guid[j])nvme_show_message(1, "%x", wdc_lat_mon_guid[j]);
7930 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
7931 for (j = 0; j < 16; j++)
7932 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
7933 nvme_show_error("")nvme_show_message(1, "");
7934
7935 ret = -1;
7936 goto out;
7937 }
7938 }
7939
7940 /* parse the data */
7941 wdc_print_latency_monitor_log(hdl, log_data, fmt);
7942 } else {
7943 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"
)
;
7944 }
7945
7946out:
7947 free(data);
7948 return ret;
7949
7950}
7951
7952static int wdc_get_ocp_c1_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
7953{
7954 struct wdc_ocp_c1_error_recovery_log *log_data;
7955 nvme_print_flags_t fmt;
7956 __u8 *data;
7957 int ret;
7958 int i;
7959
7960 if (!wdc_check_device(ctx, hdl))
7961 return -1;
7962
7963 ret = validate_output_format(format, &fmt);
7964 if (ret < 0) {
7965 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
7966 return ret;
7967 }
7968
7969 data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7970 if (!data) {
7971 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
7972 return -1;
7973 }
7974 memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN512);
7975
7976 ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID0xC1,
7977 data, WDC_ERROR_REC_LOG_BUF_LEN512);
7978
7979 if (strcmp(format, "json"))
7980 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)
;
7981
7982 if (!ret) {
7983 log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
7984
7985 /* check log page version */
7986 if ((le16_to_cpu(log_data->log_page_version) < 1) ||
7987 (le16_to_cpu(log_data->log_page_version) > 3)) {
7988 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))
7989 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))
;
7990 ret = -1;
7991 goto out;
7992 }
7993
7994 /* Verify GUID matches */
7995 for (i = 0; i < WDC_OCP_C1_GUID_LENGTH16; i++) {
7996 if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
7997 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"
)
;
7998 int j;
7999
8000 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8001 for (j = 0; j < 16; j++)
8002 nvme_show_error("%x", wdc_ocp_c1_guid[j])nvme_show_message(1, "%x", wdc_ocp_c1_guid[j]);
8003 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8004 for (j = 0; j < 16; j++)
8005 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8006 nvme_show_error("")nvme_show_message(1, "");
8007
8008 ret = -1;
8009 goto out;
8010 }
8011 }
8012
8013 /* parse the data */
8014 wdc_print_error_rec_log(log_data, fmt);
8015 } else {
8016 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"
)
;
8017 }
8018
8019out:
8020 free(data);
8021 return ret;
8022}
8023
8024static int wdc_get_ocp_c4_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8025{
8026 struct wdc_ocp_C4_dev_cap_log *log_data;
8027 nvme_print_flags_t fmt;
8028 __u8 *data;
8029 int ret;
8030 int i;
8031
8032 if (!wdc_check_device(ctx, hdl))
8033 return -1;
8034
8035 ret = validate_output_format(format, &fmt);
8036 if (ret < 0) {
8037 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8038 return ret;
8039 }
8040
8041 data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
8042 if (!data) {
8043 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8044 return -1;
8045 }
8046 memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN4096);
8047
8048 ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID0xC4,
8049 data, WDC_DEV_CAP_LOG_BUF_LEN4096);
8050
8051 if (strcmp(format, "json"))
8052 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)
;
8053
8054 if (!ret) {
8055 log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
8056
8057 /* check log page version */
8058 if (le16_to_cpu(log_data->log_page_version) !=
8059 WDC_DEV_CAP_LOG_VERSION0001) {
8060 nvme_show_error(nvme_show_message(1, "ERROR: WDC: invalid device capabilities log version - %d"
, le16_to_cpu(log_data->log_page_version))
8061 "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))
8062 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))
;
8063 ret = -1;
8064 goto out;
8065 }
8066
8067 /* Verify GUID matches */
8068 for (i = 0; i < WDC_OCP_C4_GUID_LENGTH16; i++) {
8069 if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
8070 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"
)
;
8071 int j;
8072
8073 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8074 for (j = 0; j < 16; j++)
8075 nvme_show_error("%x", wdc_ocp_c4_guid[j])nvme_show_message(1, "%x", wdc_ocp_c4_guid[j]);
8076 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8077 for (j = 0; j < 16; j++)
8078 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8079 nvme_show_error("")nvme_show_message(1, "");
8080
8081 ret = -1;
8082 goto out;
8083 }
8084 }
8085
8086 /* parse the data */
8087 wdc_print_dev_cap_log(log_data, fmt);
8088 } else {
8089 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"
)
;
8090 }
8091
8092out:
8093 free(data);
8094 return ret;
8095}
8096
8097static int wdc_get_ocp_c5_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8098{
8099 struct wdc_ocp_C5_unsupported_reqs *log_data;
8100 nvme_print_flags_t fmt;
8101 int ret;
8102 __u8 *data;
8103 int i;
8104
8105 if (!wdc_check_device(ctx, hdl))
8106 return -1;
8107
8108 ret = validate_output_format(format, &fmt);
8109 if (ret < 0) {
8110 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8111 return ret;
8112 }
8113
8114 data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8115 if (!data) {
8116 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8117 return -1;
8118 }
8119 memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8120
8121 ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID0xC5,
8122 data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN4096);
8123
8124 if (strcmp(format, "json"))
8125 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)
;
8126
8127 if (!ret) {
8128 log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
8129
8130 /* check log page version */
8131 if (le16_to_cpu(log_data->log_page_version) !=
8132 WDC_UNSUPPORTED_REQS_LOG_VERSION0001) {
8133 nvme_show_error("ERROR: WDC: invalid 0xC5 log page version")nvme_show_message(1, "ERROR: WDC: invalid 0xC5 log page version"
)
;
8134 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))
8135 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))
;
8136 ret = -1;
8137 goto out;
8138 }
8139
8140 /* Verify GUID matches */
8141 for (i = 0; i < WDC_OCP_C5_GUID_LENGTH16; i++) {
8142 if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
8143 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"
)
;
8144 int j;
8145
8146 nvme_show_error("ERROR: WDC: Expected GUID: 0x")nvme_show_message(1, "ERROR: WDC: Expected GUID: 0x");
8147 for (j = 0; j < 16; j++)
8148 nvme_show_error("%x", wdc_ocp_c5_guid[j])nvme_show_message(1, "%x", wdc_ocp_c5_guid[j]);
8149 nvme_show_error("\nERROR: WDC: Actual GUID: 0x")nvme_show_message(1, "\nERROR: WDC: Actual GUID: 0x");
8150 for (j = 0; j < 16; j++)
8151 nvme_show_error("%x", log_data->log_page_guid[j])nvme_show_message(1, "%x", log_data->log_page_guid[j]);
8152 nvme_show_error("")nvme_show_message(1, "");
8153
8154 ret = -1;
8155 goto out;
8156 }
8157 }
8158
8159 /* parse the data */
8160 wdc_print_unsupported_reqs_log(log_data, fmt);
8161 } else {
8162 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"
)
;
8163 }
8164
8165out:
8166 free(data);
8167 return ret;
8168}
8169
8170static int wdc_get_d0_log_page(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, char *format)
8171{
8172 struct wdc_ssd_d0_smart_log *perf;
8173 nvme_print_flags_t fmt;
8174 int ret = 0;
8175 __u8 *data;
8176
8177 if (!wdc_check_device(ctx, hdl))
8178 return -1;
8179
8180 ret = validate_output_format(format, &fmt);
8181 if (ret < 0) {
8182 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
8183 return ret;
8184 }
8185
8186 /* verify the 0xD0 log page is supported */
8187 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8188 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0, 0) == false0) {
8189 nvme_show_error("ERROR: WDC: 0xD0 Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xD0 Log Page not supported"
)
;
8190 return -1;
8191 }
8192
8193 data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
8194 if (!data) {
8195 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8196 return -1;
8197 }
8198 memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN0x200);
8199
8200 ret = nvme_get_log_simple(hdl,
8201 WDC_NVME_GET_VU_SMART_LOG_OPCODE0xD0,
8202 data, WDC_NVME_VU_SMART_LOG_LEN0x200);
8203 if (strcmp(format, "json"))
8204 nvme_show_status(ret);
8205
8206 if (!ret) {
8207 /* parse the data */
8208 perf = (struct wdc_ssd_d0_smart_log *)(data);
8209 ret = wdc_print_d0_log(perf, fmt);
8210 } else {
8211 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"
)
;
8212 ret = -1;
8213 }
8214
8215 free(data);
8216 return ret;
8217}
8218
8219static long double le_to_float(__u8 *data, int byte_len)
8220{
8221 long double result = 0;
8222 int i;
8223
8224 for (i = 0; i < byte_len; i++) {
8225 result *= 256;
8226 result += data[15 - i];
8227 }
8228
8229 return result;
8230}
8231
8232/*
8233 * A counter of @byte_len bytes at @data, at most UINT64_MAX: a device can
8234 * report more, which a conversion of the long double would make undefined.
8235 */
8236static __u64 le_to_u64(__u8 *data, int byte_len)
8237{
8238 long double val = le_to_float(data, byte_len);
8239
8240 return val < 0x1p64L ? (__u64)val : UINT64_MAX(18446744073709551615UL);
8241}
8242
8243/* The GUID as "0x" and its bytes in hex, the most significant first */
8244static void stringify_log_page_guid(__u8 *guid, char *buf, size_t size)
8245{
8246 shr_strscpy(buf, "0x", size);
8247 shr_bin_to_hex(buf + 2, size - 2, guid, 16, SHR_HEX_REVERSE(1 << 1));
8248}
8249
8250static const char *const cloud_smart_log_thermal_status[] = {
8251 [0x00] = "unthrottled",
8252 [0x01] = "first_level",
8253 [0x02] = "second_level",
8254 [0x03] = "third_level",
8255};
8256
8257static const char *stringify_cloud_smart_log_thermal_status(__u8 status)
8258{
8259 if (status < ARRAY_SIZE(cloud_smart_log_thermal_status)(sizeof(cloud_smart_log_thermal_status) / sizeof((cloud_smart_log_thermal_status
)[0]) + 0)
&&
8260 cloud_smart_log_thermal_status[status])
8261 return cloud_smart_log_thermal_status[status];
8262 return "unrecognized";
8263}
8264
8265static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log)
8266{
8267 struct json_object *root;
8268 struct json_object *bad_user_nand_blocks;
8269 struct json_object *bad_system_nand_blocks;
8270 struct json_object *e2e_correction_counts;
8271 struct json_object *user_data_erase_counts;
8272 struct json_object *thermal_status;
8273 struct json_object *dssd_specific_ver;
8274 char buf[2 * sizeof(log->log_page_guid) + 3];
8275 char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1];
8276 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8277
8278 bad_user_nand_blocks = json_create_object()json_object_new_object();
8279 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)))
8280 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)))
;
8281 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)))
8282 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)))
;
8283
8284 bad_system_nand_blocks = json_create_object()json_object_new_object();
8285 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)))
8286 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)))
;
8287 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)))
8288 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)))
;
8289
8290 e2e_correction_counts = json_create_object()json_object_new_object();
8291 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)))
8292 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)))
;
8293 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)))
8294 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)))
;
8295
8296 user_data_erase_counts = json_create_object()json_object_new_object();
8297 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)))
8298 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)))
;
8299 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)))
8300 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)))
;
8301
8302 thermal_status = json_create_object()json_object_new_object();
8303 json_object_add_value_string(thermal_status, "current_status",
8304 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8305 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))
8306 log->thermal_status.num_events)json_object_object_add(thermal_status, "num_events", json_object_new_uint64
(log->thermal_status.num_events))
;
8307
8308 dssd_specific_ver = json_create_object()json_object_new_object();
8309 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))
8310 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))
;
8311 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)))
8312 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)))
;
8313 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)))
8314 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)))
;
8315 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))
8316 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))
;
8317
8318 root = json_create_object()json_object_new_object();
8319 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)))
8320 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)))
;
8321 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)))
8322 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)))
;
8323 json_object_add_value_object(root, "bad_user_nand_blocks",json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
8324 bad_user_nand_blocks)json_object_object_add(root, "bad_user_nand_blocks", bad_user_nand_blocks
)
;
8325 json_object_add_value_object(root, "bad_system_nand_blocks",json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
8326 bad_system_nand_blocks)json_object_object_add(root, "bad_system_nand_blocks", bad_system_nand_blocks
)
;
8327 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)))
8328 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)))
;
8329 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
)))
8330 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
)))
;
8331 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)))
8332 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)))
;
8333 json_object_add_value_object(root, "e2e_correction_counts",json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
8334 e2e_correction_counts)json_object_object_add(root, "e2e_correction_counts", e2e_correction_counts
)
;
8335 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))
8336 log->system_data_percent_used)json_object_object_add(root, "system_data_percent_used", json_object_new_uint64
(log->system_data_percent_used))
;
8337 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)))
8338 le64_to_cpu(log->refresh_counts))json_object_object_add(root, "refresh_counts", json_object_new_uint64
(le64_to_cpu(log->refresh_counts)))
;
8339 json_object_add_value_object(root, "user_data_erase_counts",json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
8340 user_data_erase_counts)json_object_object_add(root, "user_data_erase_counts", user_data_erase_counts
)
;
8341 json_object_add_value_object(root, "thermal_status", thermal_status)json_object_object_add(root, "thermal_status", thermal_status
)
;
8342 if (smart_log_ver >= 3)
8343 json_object_add_value_object(root, "dssd_specific_ver",json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
8344 dssd_specific_ver)json_object_object_add(root, "dssd_specific_ver", dssd_specific_ver
)
;
8345 else
8346 json_free_object(dssd_specific_ver)json_object_put(dssd_specific_ver);
8347 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)))
8348 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)))
;
8349 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)))
8350 le32_to_cpu(log->incomplete_shutdowns))json_object_object_add(root, "incomplete_shutdowns", json_object_new_uint64
(le32_to_cpu(log->incomplete_shutdowns)))
;
8351 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))
8352 log->percent_free_blocks)json_object_object_add(root, "percent_free_blocks", json_object_new_uint64
(log->percent_free_blocks))
;
8353 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)))
8354 le16_to_cpu(log->capacitor_health))json_object_object_add(root, "capacitor_health", json_object_new_uint64
(le16_to_cpu(log->capacitor_health)))
;
8355 if (smart_log_ver >= 3) {
8356 if (smart_log_ver >= 4) {
8357 snprintf(buf, sizeof(buf), "%c",
8358 log->nvme_base_errata_ver);
8359 json_object_add_value_string(root, "nvme_base_errata_version", buf);
8360 snprintf(buf, sizeof(buf), "%c",
8361 log->nvme_cmd_set_errata_ver);
8362 json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf);
8363 } else {
8364 snprintf(buf, sizeof(buf), "%c",
8365 log->nvme_base_errata_ver);
8366 json_object_add_value_string(root, "nvme_errata_version", buf);
8367 }
8368 }
8369
8370 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)))
8371 le64_to_cpu(log->unaligned_io))json_object_object_add(root, "unaligned_io", json_object_new_uint64
(le64_to_cpu(log->unaligned_io)))
;
8372 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)))
8373 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)))
;
8374 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)))
8375 le64_to_cpu(log->total_nuse))json_object_object_add(root, "total_nuse", json_object_new_uint64
(le64_to_cpu(log->total_nuse)))
;
8376 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)))
8377 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)))
;
8378 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)))
8379 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)))
;
8380 if (smart_log_ver >= 3) {
8381 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)))
8382 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)))
;
8383 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)))
8384 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)))
;
8385 if (smart_log_ver >= 4) {
8386 snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s",
8387 (int)sizeof(log->lowest_permitted_fw_rev),
8388 log->lowest_permitted_fw_rev);
8389 json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr);
8390 } else
8391 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)))
8392 le128_to_cpu(log->hardware_revision))json_object_object_add(root, "hardware_revision", util_json_object_new_uint128
(le128_to_cpu(log->hardware_revision)))
;
8393 }
8394 json_object_add_value_uint(root, "log_page_version",json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
8395 smart_log_ver)json_object_object_add(root, "log_page_version", json_object_new_uint64
(smart_log_ver))
;
8396 stringify_log_page_guid(log->log_page_guid, buf, sizeof(buf));
8397 json_object_add_value_string(root, "log_page_guid", buf);
8398
8399 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
8400 printf("\n");
8401 json_free_object(root)json_object_put(root);
8402}
8403
8404static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log,
8405 struct libnvme_transport_handle *hdl)
8406{
8407 char buf[2 * sizeof(log->log_page_guid) + 3];
8408 uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version);
8409
8410 printf("SMART Cloud Attributes for NVMe device : %s\n",
8411 libnvme_transport_handle_get_name(hdl));
8412 printf("Physical Media Units Written : %'.0Lf\n",
8413 le_to_float(log->physical_media_units_written, 16));
8414 printf("Physical Media Units Read : %'.0Lf\n",
8415 le_to_float(log->physical_media_units_read, 16));
8416 printf("Bad User NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8417 le16_to_cpu(log->bad_user_nand_blocks.normalized));
8418 printf("Bad User NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8419 le64_to_cpu(log->bad_user_nand_blocks.raw));
8420 printf("Bad System NAND Blocks (Normalized) : %" PRIu16"hu" "%%\n",
8421 le16_to_cpu(log->bad_system_nand_blocks.normalized));
8422 printf("Bad System NAND Blocks (Raw) : %" PRIu64"l" "u" "\n",
8423 le64_to_cpu(log->bad_system_nand_blocks.raw));
8424 printf("XOR Recovery Count : %" PRIu64"l" "u" "\n",
8425 le64_to_cpu(log->xor_recovery_count));
8426 printf("Uncorrectable Read Error Count : %" PRIu64"l" "u" "\n",
8427 le64_to_cpu(log->uncorrectable_read_error_count));
8428 printf("Soft ECC Error Count : %" PRIu64"l" "u" "\n",
8429 le64_to_cpu(log->soft_ecc_error_count));
8430 printf("End to End Correction Counts (Corrected) : %" PRIu32"u" "\n",
8431 le32_to_cpu(log->e2e_correction_counts.corrected));
8432 printf("End to End Correction Counts (Detected) : %" PRIu32"u" "\n",
8433 le32_to_cpu(log->e2e_correction_counts.detected));
8434 printf("System Data %% Used : %" PRIu8"hhu" "%%\n",
8435 log->system_data_percent_used);
8436 printf("Refresh Counts : %" PRIu64"l" "u" "\n",
8437 le64_to_cpu(log->refresh_counts));
8438 printf("User Data Erase Counts (Minimum) : %" PRIu32"u" "\n",
8439 le32_to_cpu(log->user_data_erase_counts.minimum));
8440 printf("User Data Erase Counts (Maximum) : %" PRIu32"u" "\n",
8441 le32_to_cpu(log->user_data_erase_counts.maximum));
8442 printf("Thermal Throttling Status (Current Status) : %s\n",
8443 stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status));
8444 printf("Thermal Throttling Status (Number of Events) : %" PRIu8"hhu" "\n",
8445 log->thermal_status.num_events);
8446 if (smart_log_ver >= 3) {
8447 printf("NVMe Major Version : %" PRIu8"hhu" "\n",
8448 log->dssd_specific_ver.major_ver);
8449 printf(" Minor Version : %" PRIu16"hu" "\n",
8450 le16_to_cpu(log->dssd_specific_ver.minor_ver));
8451 printf(" Point Version : %" PRIu16"hu" "\n",
8452 le16_to_cpu(log->dssd_specific_ver.point_ver));
8453 printf(" Errata Version : %" PRIu8"hhu" "\n",
8454 log->dssd_specific_ver.errata_ver);
8455 }
8456 printf("PCIe Correctable Error Count : %" PRIu64"l" "u" "\n",
8457 le64_to_cpu(log->pcie_correctable_error_count));
8458 printf("Incomplete Shutdowns : %" PRIu32"u" "\n",
8459 le32_to_cpu(log->incomplete_shutdowns));
8460 printf("%% Free Blocks : %" PRIu8"hhu" "%%\n",
8461 log->percent_free_blocks);
8462 printf("Capacitor Health : %" PRIu16"hu" "%%\n",
8463 le16_to_cpu(log->capacitor_health));
8464 if (smart_log_ver >= 3) {
8465 if (smart_log_ver >= 4) {
8466 printf("NVMe Base Errata Version : %c\n",
8467 log->nvme_base_errata_ver);
8468 printf("NVMe Command Set Errata Version : %c\n",
8469 log->nvme_cmd_set_errata_ver);
8470 } else {
8471 printf("NVMe Errata Version : %c\n",
8472 log->nvme_base_errata_ver);
8473 }
8474 }
8475 printf("Unaligned IO : %" PRIu64"l" "u" "\n",
8476 le64_to_cpu(log->unaligned_io));
8477 printf("Security Version Number : %" PRIu64"l" "u" "\n",
8478 le64_to_cpu(log->security_version_number));
8479 printf("Total NUSE : %" PRIu64"l" "u" "\n",
8480 le64_to_cpu(log->total_nuse));
8481 printf("PLP Start Count : %'.0Lf\n",
8482 le_to_float(log->plp_start_count, 16));
8483 printf("Endurance Estimate : %'.0Lf\n",
8484 le_to_float(log->endurance_estimate, 16));
8485 if (smart_log_ver >= 3) {
8486 printf("PCIe Link Retraining Count : %" PRIu64"l" "u" "\n",
8487 le64_to_cpu(log->pcie_link_retraining_cnt));
8488 printf("Power State Change Count : %" PRIu64"l" "u" "\n",
8489 le64_to_cpu(log->power_state_change_cnt));
8490 if (smart_log_ver >= 4)
8491 printf("Lowest Permitted FW Revision : %-.*s\n",
8492 (int)sizeof(log->lowest_permitted_fw_rev),
8493 log->lowest_permitted_fw_rev);
8494 else
8495 printf("Hardware Revision : %s\n",
8496 uint128_t_to_string(le128_to_cpu(log->hardware_revision)));
8497 }
8498 printf("Log Page Version : %" PRIu16"hu" "\n",
8499 smart_log_ver);
8500 stringify_log_page_guid(log->log_page_guid, buf, sizeof(buf));
8501 printf("Log Page GUID : %s\n", buf);
8502 printf("\n\n");
8503}
8504
8505static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd,
8506 struct plugin *plugin)
8507{
8508 const char *desc = "Retrieve additional performance statistics.";
8509 const char *interval = "Interval to read the statistics from [1, 15].";
8510 const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
8511 const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
8512 const char *namespace_id = "desired namespace id";
8513 nvme_print_flags_t fmt;
8514 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8515 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8516 int ret = 0;
8517 int uuid_index = 0;
8518 int page_mask = 0, num, i;
8519 int log_page_list[16];
8520 __u64 capabilities = 0;
8521 __u32 device_id, read_vendor_id;
8522
8523 struct config {
8524 uint8_t interval;
8525 __u8 log_page_version;
8526 char *log_page_mask;
8527 __u32 namespace_id;
8528 };
8529
8530 struct config cfg = {
8531 .interval = 14,
8532 .log_page_version = 0,
8533 .log_page_mask = "",
8534 .namespace_id = NVME_NSID_ALL,
8535 };
8536
8537 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8538 OPT_BYTE("interval", 'i', &cfg.interval, interval){"interval", 'i', "NUM", CFG_BYTE, _Generic(&cfg.interval
, uint8_t * : (&cfg.interval)), ARGCONFIG_ARG_REQUIRED, interval
, 0, }
,
8539 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, }
8540 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, }
,
8541 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, }
8542 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, }
,
8543 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}
8544 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}
,
8545 OPT_END(){ ((void*)0) }
8546 };
8547
8548 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8549 if (ret)
8550 return ret;
8551
8552 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8553 if (ret)
8554 return ret;
8555
8556 if (!cfg.log_page_version) {
8557 uuid_index = 0;
8558 } else if (cfg.log_page_version == 1) {
8559 uuid_index = 1;
8560 } else {
8561 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"
)
;
8562 ret = -1;
8563 goto out;
8564 }
8565
8566 num = shr_parse_csv_int(cfg.log_page_mask, log_page_list, 16);
8567
8568 if (num == -1) {
8569 nvme_show_error("ERROR: WDC: log page list is malformed")nvme_show_message(1, "ERROR: WDC: log page list is malformed"
)
;
8570 ret = -1;
8571 goto out;
8572 }
8573
8574 if (!num) {
8575 page_mask |= WDC_ALL_PAGE_MASK0xFFFF;
8576 } else {
8577 for (i = 0; i < num; i++) {
8578 if (log_page_list[i] == 0xc0)
8579 page_mask |= WDC_C0_PAGE_MASK0x0001;
8580 if (log_page_list[i] == 0xc1)
8581 page_mask |= WDC_C1_PAGE_MASK0x0002;
8582 if (log_page_list[i] == 0xca)
8583 page_mask |= WDC_CA_PAGE_MASK0x0004;
8584 if (log_page_list[i] == 0xd0)
8585 page_mask |= WDC_D0_PAGE_MASK0x0008;
8586 }
8587 }
8588
8589 if (!page_mask)
8590 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)
;
8591
8592 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8593
8594 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8595 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8596 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8597 ret = -1;
8598 goto out;
8599 }
8600
8601 if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) == WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000) &&
8602 (page_mask & WDC_C0_PAGE_MASK0x0001)) {
8603 /* Get 0xC0 log page if possible. */
8604 if (!wdc_is_sn861(device_id)) {
8605 ret = wdc_get_c0_log_page(ctx, hdl,
8606 nvme_args.output_format,
8607 uuid_index, cfg.namespace_id);
8608 if (ret)
8609 nvme_show_error(nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
8610 "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)
8611 ret)nvme_show_message(1, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n"
, ret)
;
8612 } else {
8613 fmt = nvme_args.output_flags;
8614
8615 ret = nvme_get_print_ocp_cloud_smart_log(hdl,
8616 0,
8617 NVME_NSID_ALL,
8618 fmt);
8619 }
8620 }
8621 if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) == (WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008)) &&
8622 (page_mask & WDC_CA_PAGE_MASK0x0004) &&
8623 (!wdc_is_sn861(device_id))) {
8624 /* Get the CA Log Page */
8625 ret = wdc_get_ca_log_page(ctx, hdl, nvme_args.output_format);
8626 if (ret)
8627 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)
;
8628 }
8629 if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) == WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004) &&
8630 (page_mask & WDC_C1_PAGE_MASK0x0002)) {
8631 /* Get the C1 Log Page */
8632 ret = wdc_get_c1_log_page(ctx, hdl, nvme_args.output_format,
8633 cfg.interval);
8634 if (ret)
8635 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)
;
8636 }
8637 if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) == WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010) &&
8638 (page_mask & WDC_D0_PAGE_MASK0x0008)) {
8639 /* Get the D0 Log Page */
8640 ret = wdc_get_d0_log_page(ctx, hdl, nvme_args.output_format);
8641 if (ret)
8642 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)
;
8643 }
8644
8645out:
8646 return ret;
8647}
8648
8649static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd,
8650 struct plugin *plugin)
8651{
8652 const char *desc = "Retrieve customer unique smart log statistics.";
8653 const char *uuid_index = "The uuid index to select the correct log page implementation.";
8654 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8655 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8656 struct libnvme_passthru_cmd cmd;
8657 int ret = 0;
8658 __u64 capabilities = 0;
8659 uint32_t read_device_id = 0, read_vendor_id;
8660 nvme_print_flags_t fmt;
8661 __u8 *data;
8662
8663 struct config {
8664 __u32 uuid_index;
8665 };
8666
8667 struct config cfg = {
8668 .uuid_index = 0,
8669 };
8670
8671 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8672 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, }
,
8673 OPT_END(){ ((void*)0) }
8674 };
8675
8676 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8677 if (ret)
8678 return ret;
8679
8680 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8681 if (ret)
8682 return ret;
8683
8684 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8685 if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
)) {
8686 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8687 ret = -1;
8688 goto out;
8689 }
8690
8691 if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) == WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008) {
8692 if (!wdc_check_device(ctx, hdl))
8693 return -1;
8694
8695 fmt = nvme_args.output_flags;
8696
8697 /* verify the 0xCA log page is supported */
8698 if (wdc_nvme_check_supported_log_page(ctx, hdl,
8699 WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE0xCA, 0) == false0) {
8700 nvme_show_error("ERROR: WDC: 0xCA Log Page not supported")nvme_show_message(1, "ERROR: WDC: 0xCA Log Page not supported"
)
;
8701 return -1;
8702 }
8703
8704 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
8705 if (ret) {
8706 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))
;
8707 return ret;
8708 }
8709
8710 switch (read_device_id) {
8711 case WDC_NVME_SN861_DEV_ID0x2750:
8712 case WDC_NVME_SN861_DEV_ID_10x2751:
8713 data = (__u8 *)malloc(WDC_BD_CA_LOG_BUF_LEN0xA0);
8714 if (!data) {
8715 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
8716 ret = -1;
8717 break;
8718 }
8719
8720 memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN0xA0);
8721
8722 /* Get the CA Log Page */
8723 nvme_init_get_log(&cmd, NVME_NSID_ALL,
8724 WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0,
8725 NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN0xA0);
8726 cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8727 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
8728 NVME_LOG_CDW14_UUID_MASK)(((__u32)(cfg.uuid_index) & (NVME_LOG_CDW14_UUID_MASK)) <<
(NVME_LOG_CDW14_UUID_SHIFT))
;
8729 ret = libnvme_get_log(hdl, &cmd, false0,
8730 NVME_LOG_PAGE_PDU_SIZE4096);
8731
8732 if (strcmp(nvme_args.output_format, "json"))
8733 nvme_show_status(ret);
8734
8735 if (!ret) {
8736 /* parse the data */
8737 ret = wdc_print_bd_ca_log(hdl, data, fmt);
8738 } else {
8739 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"
)
;
8740 ret = -1;
8741 }
8742
8743 free(data);
8744 break;
8745 default:
8746 nvme_show_error("ERROR: WDC: Command not supported on this device")nvme_show_message(1, "ERROR: WDC: Command not supported on this device"
)
;
8747 ret = -1;
8748 }
8749 } else {
8750 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"
)
;
8751 ret = -1;
8752 }
8753
8754out:
8755 return ret;
8756}
8757
8758static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd,
8759 struct plugin *plugin)
8760{
8761 const char *desc = "Retrieve Cloud Log Smart/Health Information";
8762 const char *namespace_id = "desired namespace id";
8763 nvme_print_flags_t fmt;
8764 __u64 capabilities = 0;
8765 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8766 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8767 int ret;
8768 __u8 *data;
8769
8770 struct config {
8771 char *output_format;
8772 __u32 namespace_id;
8773 };
8774
8775 struct config cfg = {
8776 .output_format = "normal",
8777 .namespace_id = NVME_NSID_ALL,
8778 };
8779
8780 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8781 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}
8782 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}
,
8783 OPT_END(){ ((void*)0) }
8784 };
8785
8786 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8787 if (ret)
8788 return ret;
8789
8790 cfg.output_format = nvme_args.output_format;
8791
8792 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8793 if (ret)
8794 return ret;
8795
8796 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8797
8798 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
8799 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8800 ret = -1;
8801 goto out;
8802 }
8803
8804 data = NULL((void*)0);
8805 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8806 cfg.namespace_id);
8807
8808 if (strcmp(cfg.output_format, "json"))
8809 nvme_show_status(ret);
8810
8811 if (!ret) {
8812 ret = validate_output_format(cfg.output_format, &fmt);
8813 if (ret < 0) {
8814 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8815 } else {
8816 /* parse the data */
8817 wdc_print_ext_smart_cloud_log(data, fmt);
8818 }
8819 } else {
8820 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"
)
;
8821 ret = -1;
8822 }
8823
8824 free(data);
8825
8826out:
8827 return ret;
8828}
8829
8830static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd,
8831 struct plugin *plugin)
8832{
8833 const char *desc = "Retrieve Hardware Revision Log Information";
8834 const char *namespace_id = "desired namespace id";
8835 nvme_print_flags_t fmt;
8836 __u64 capabilities = 0;
8837 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle)))
8838 struct libnvme_transport_handle *hdl = NULL((void*)0);
8839 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8840 __cleanup_free__attribute__((cleanup(shr_freep))) __u8 *data = NULL((void*)0);
8841 int ret;
8842
8843 struct config {
8844 char *output_format;
8845 __u32 namespace_id;
8846 };
8847
8848 struct config cfg = {
8849 .output_format = "normal",
8850 .namespace_id = NVME_NSID_ALL,
8851 };
8852
8853 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8854 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}
8855 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}
,
8856 OPT_END(){ ((void*)0) }
8857 };
8858
8859 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8860 if (ret)
8861 return ret;
8862
8863 cfg.output_format = nvme_args.output_format;
8864
8865 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8866 if (ret)
8867 return ret;
8868
8869 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8870
8871 if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000)) {
8872 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8873 ret = -1;
8874 goto out;
8875 }
8876
8877 ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id);
8878
8879 if (strcmp(cfg.output_format, "json"))
8880 nvme_show_status(ret);
8881
8882 if (!ret) {
8883 ret = validate_output_format(cfg.output_format, &fmt);
8884 if (ret < 0) {
8885 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
8886 goto out;
8887 }
8888
8889 if (!data) {
8890 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"
)
;
8891 ret = -1;
8892 goto out;
8893 }
8894 switch (fmt) {
8895 case NORMAL:
8896 wdc_print_hw_rev_log_normal(data);
8897 break;
8898 case JSON:
8899 wdc_print_hw_rev_log_json(data);
8900 break;
8901 default:
8902 break;
8903 }
8904 } else {
8905 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"
)
;
8906 ret = -1;
8907 }
8908
8909out:
8910 return ret;
8911}
8912
8913static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd,
8914 struct plugin *plugin)
8915{
8916 const char *desc = "Retrieve Device Write Amplication Factor";
8917 const char *namespace_id = "desired namespace id";
8918 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
8919 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
8920 struct nvme_smart_log smart_log;
8921 nvme_print_flags_t fmt;
8922 __u8 *data;
8923 int ret = 0;
8924 __u64 capabilities = 0;
8925 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr;
8926 long double data_units_written = 0,
8927 phys_media_units_written_tlc = 0,
8928 phys_media_units_written_slc = 0;
8929 struct json_object *root = NULL((void*)0);
8930 char tlc_waf_str[32] = { 0 },
8931 slc_waf_str[32] = { 0 };
8932
8933 struct config {
8934 char *output_format;
8935 __u32 namespace_id;
8936 };
8937
8938 struct config cfg = {
8939 .output_format = "normal",
8940 .namespace_id = NVME_NSID_ALL,
8941 };
8942
8943 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
8944 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}
8945 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}
,
8946 OPT_END(){ ((void*)0) }
8947 };
8948
8949 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
8950 if (ret)
8951 return ret;
8952
8953 cfg.output_format = nvme_args.output_format;
8954
8955 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
8956 if (ret)
8957 return ret;
8958
8959 capabilities = wdc_get_drive_capabilities(ctx, hdl);
8960
8961 if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000)) {
8962 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
8963 ret = -1;
8964 goto out;
8965 }
8966
8967 /* get data units written from the smart log page */
8968 ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log);
8969 if (!ret) {
8970 data_units_written = int128_to_double(smart_log.data_units_written);
8971 } else if (ret > 0) {
8972 nvme_show_status(ret);
8973 ret = -1;
8974 goto out;
8975 } else {
8976 nvme_show_error("smart log: %s", libnvme_strerror(errno))nvme_show_message(1, "smart log: %s", libnvme_strerror((*__errno_location
())))
;
8977 ret = -1;
8978 goto out;
8979 }
8980
8981 /* get Physical Media Units Written from extended smart/C0 log page */
8982 data = NULL((void*)0);
8983 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
8984 cfg.namespace_id);
8985
8986 if (!ret) {
8987 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
8988 phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
8989 phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
8990
8991 free(data);
8992 } else {
8993 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__)
;
8994 ret = -1;
8995 goto out;
8996 }
8997
8998 if (strcmp(cfg.output_format, "json"))
8999 nvme_show_status(ret);
9000
9001 ret = validate_output_format(cfg.output_format, &fmt);
9002 if (ret < 0) {
9003 nvme_show_error("ERROR: WDC %s: invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s: invalid output format", __func__
)
;
9004 goto out;
9005 }
9006
9007 if (!data_units_written) {
9008 nvme_show_error("ERROR: WDC %s: 0 data units written", __func__)nvme_show_message(1, "ERROR: WDC %s: 0 data units written", __func__
)
;
9009 ret = -1;
9010 goto out;
9011 }
9012
9013 if (fmt == NORMAL) {
9014 printf("Device Write Amplification Factor TLC : %4.2Lf\n",
9015 (phys_media_units_written_tlc/data_units_written));
9016 printf("Device Write Amplification Factor SLC : %4.2Lf\n",
9017 (phys_media_units_written_slc/data_units_written));
9018 } else if (fmt == JSON) {
9019 root = json_create_object()json_object_new_object();
9020 snprintf(tlc_waf_str, sizeof(tlc_waf_str), "%4.2Lf",
9021 (phys_media_units_written_tlc/data_units_written));
9022 snprintf(slc_waf_str, sizeof(slc_waf_str), "%4.2Lf",
9023 (phys_media_units_written_slc/data_units_written));
9024
9025 json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
9026 json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
9027
9028 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
9029 printf("\n");
9030
9031 json_free_object(root)json_object_put(root);
9032 }
9033
9034out:
9035 return ret;
9036}
9037
9038static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd,
9039 struct plugin *plugin)
9040{
9041 const char *desc = "Retrieve latency monitor log data.";
9042 __u64 capabilities = 0;
9043 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9044 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9045 int ret = 0;
9046
9047 struct config {
9048 char *output_format;
9049 };
9050
9051 struct config cfg = {
9052 .output_format = "normal",
9053 };
9054
9055 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9056 OPT_END(){ ((void*)0) }
9057 };
9058
9059 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9060 if (ret)
9061 return ret;
9062
9063 cfg.output_format = nvme_args.output_format;
9064
9065 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9066 if (ret)
9067 return ret;
9068 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9069
9070 if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000)) {
9071 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9072 ret = -1;
9073 goto out;
9074 }
9075
9076 ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format);
9077 if (ret)
9078 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)
;
9079
9080out:
9081 return ret;
9082}
9083
9084static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd,
9085 struct plugin *plugin)
9086{
9087 const char *desc = "Retrieve error recovery log data.";
9088 __u64 capabilities = 0;
9089 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9090 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9091 int ret = 0;
9092
9093 struct config {
9094 char *output_format;
9095 };
9096
9097 struct config cfg = {
9098 .output_format = "normal",
9099 };
9100
9101 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9102 OPT_END(){ ((void*)0) }
9103 };
9104
9105 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9106 if (ret)
9107 return ret;
9108
9109 cfg.output_format = nvme_args.output_format;
9110
9111 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9112 if (ret)
9113 return ret;
9114
9115 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9116
9117 if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000)) {
9118 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9119 ret = -1;
9120 goto out;
9121 }
9122
9123 ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format);
9124 if (ret)
9125 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)
;
9126
9127out:
9128 return ret;
9129}
9130
9131static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd,
9132 struct plugin *plugin)
9133{
9134 const char *desc = "Retrieve device capabilities log data.";
9135 __u64 capabilities = 0;
9136 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9137 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9138 int ret = 0;
9139
9140 struct config {
9141 char *output_format;
9142 };
9143
9144 struct config cfg = {
9145 .output_format = "normal",
9146 };
9147
9148 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9149 OPT_END(){ ((void*)0) }
9150 };
9151
9152 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9153 if (ret)
9154 return ret;
9155
9156 cfg.output_format = nvme_args.output_format;
9157
9158 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9159 if (ret)
9160 return ret;
9161
9162 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9163
9164 if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000)) {
9165 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9166 ret = -1;
9167 goto out;
9168 }
9169
9170 ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format);
9171 if (ret)
9172 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)
;
9173
9174out:
9175 return ret;
9176}
9177
9178static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd,
9179 struct plugin *plugin)
9180{
9181 const char *desc = "Retrieve unsupported requirements log data.";
9182 __u64 capabilities = 0;
9183 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9184 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9185 int ret = 0;
9186
9187 struct config {
9188 char *output_format;
9189 };
9190
9191 struct config cfg = {
9192 .output_format = "normal",
9193 };
9194
9195 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9196 OPT_END(){ ((void*)0) }
9197 };
9198
9199 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9200 if (ret)
9201 return ret;
9202
9203 cfg.output_format = nvme_args.output_format;
9204
9205 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9206 if (ret)
9207 return ret;
9208
9209 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9210
9211 if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000)) {
9212 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9213 ret = -1;
9214 goto out;
9215 }
9216
9217 ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format);
9218 if (ret)
9219 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)
;
9220
9221out:
9222 return ret;
9223}
9224
9225static int wdc_do_clear_pcie_correctable_errors(struct libnvme_transport_handle *hdl)
9226{
9227 int ret;
9228 struct libnvme_passthru_cmd admin_cmd;
9229
9230 memset(&admin_cmd, 0, sizeof(admin_cmd));
9231 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE0xC6;
9232 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD0x04 << WDC_NVME_SUBCMD_SHIFT8) |
9233 WDC_NVME_CLEAR_PCIE_CORR_CMD0x22);
9234
9235 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9236 nvme_show_status(ret);
9237 return ret;
9238}
9239
9240static int wdc_do_clear_pcie_correctable_errors_vuc(struct libnvme_transport_handle *hdl)
9241{
9242 int ret;
9243 struct libnvme_passthru_cmd admin_cmd;
9244
9245 memset(&admin_cmd, 0, sizeof(admin_cmd));
9246 admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC0xD2;
9247
9248 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9249 nvme_show_status(ret);
9250 return ret;
9251}
9252
9253static int wdc_do_clear_pcie_correctable_errors_fid(struct libnvme_transport_handle *hdl)
9254{
9255 int ret;
9256 __u64 result;
9257 __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
9258
9259 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID0xC3, false0,
9260 value, &result);
9261
9262 nvme_show_status(ret);
9263 return ret;
9264}
9265
9266static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd,
9267 struct plugin *plugin)
9268{
9269 const char *desc = "Clear PCIE Correctable Errors.";
9270 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9271 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9272 __u64 capabilities = 0;
9273 int ret;
9274
9275 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9276 OPT_END(){ ((void*)0) }
9277 };
9278
9279 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9280 if (ret)
9281 return ret;
9282
9283 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9284 if (ret || !wdc_check_device(ctx, hdl))
9285 return -1;
9286
9287 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9288 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
)) {
9289 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9290 ret = -1;
9291 goto out;
9292 }
9293
9294 if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE0x0000000000000080)
9295 ret = wdc_do_clear_pcie_correctable_errors(hdl);
9296 else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE0x0000000000400000)
9297 ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl);
9298 else
9299 ret = wdc_do_clear_pcie_correctable_errors_fid(hdl);
9300
9301out:
9302 return ret;
9303}
9304
9305static int wdc_drive_status(int argc, char **argv, struct command *acmd,
9306 struct plugin *plugin)
9307{
9308 const char *desc = "Get Drive Status.";
9309 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9310 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9311 int ret = 0;
9312 int uuid_index;
9313 void *dev_mng_log = NULL((void*)0);
9314 __u32 system_eol_state;
9315 __u32 user_eol_state;
9316 __u32 format_corrupt_reason = 0xFFFFFFFF;
9317 __u32 eol_status;
9318 __u32 assert_status = 0xFFFFFFFF;
9319 __u32 thermal_status = 0xFFFFFFFF;
9320 __u64 capabilities = 0;
9321 struct nvme_id_uuid_list uuid_list;
9322
9323 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9324 OPT_END(){ ((void*)0) }
9325 };
9326
9327 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9328 if (ret)
9329 return ret;
9330
9331 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9332 if (ret)
9333 return ret;
9334
9335 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9336
9337 if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) != WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020) {
9338 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9339 ret = -1;
9340 goto out;
9341 }
9342
9343 uuid_index = 0;
9344
9345 /* Find the WDC UUID index */
9346 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
9347 if (wdc_CheckUuidListSupport(hdl, &uuid_list)) {
9348 /* check for the Sandisk UUID first */
9349 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
9350
9351 if (uuid_index < 0)
9352 /* The Sandisk UUID is not found;
9353 * check for the WDC UUID second.
9354 */
9355 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
9356 }
9357
9358 /* WD UUID not found, use default uuid index - 0 */
9359 if (uuid_index < 0)
9360 uuid_index = 0;
9361
9362 /* verify the 0xC2 Device Manageability log page is supported */
9363 if (wdc_nvme_check_supported_log_page(ctx, hdl,
9364 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2,
9365 uuid_index) == false0) {
9366 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)
9367 uuid_index)nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d"
, uuid_index)
;
9368 ret = -1;
9369 goto out;
9370 }
9371
9372 if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) {
9373 nvme_show_error("ERROR: WDC: 0xC2 Log Page not found")nvme_show_message(1, "ERROR: WDC: 0xC2 Log Page not found");
9374 ret = -1;
9375 goto out;
9376 }
9377
9378 /* Get the assert dump present status */
9379 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &assert_status,
9380 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19))
9381 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9382
9383 /* Get the thermal throttling status */
9384 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &thermal_status,
9385 WDC_C2_THERMAL_THROTTLE_STATUS_ID0x18))
9386 nvme_show_error("ERROR: WDC: Get Thermal Throttling Status Failed")nvme_show_message(1, "ERROR: WDC: Get Thermal Throttling Status Failed"
)
;
9387
9388 /* Get EOL status */
9389 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &eol_status,
9390 WDC_C2_USER_EOL_STATUS_ID0x1A)) {
9391 nvme_show_error("ERROR: WDC: Get User EOL Status Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL Status Failed"
)
;
9392 eol_status = cpu_to_le32(-1);
9393 }
9394
9395 /* Get Customer EOL state */
9396 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &user_eol_state,
9397 WDC_C2_USER_EOL_STATE_ID0x1C))
9398 nvme_show_error("ERROR: WDC: Get User EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get User EOL State Failed");
9399
9400 /* Get System EOL state*/
9401 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &system_eol_state,
9402 WDC_C2_SYSTEM_EOL_STATE_ID0x1D))
9403 nvme_show_error("ERROR: WDC: Get System EOL State Failed")nvme_show_message(1, "ERROR: WDC: Get System EOL State Failed"
)
;
9404
9405 /* Get format corrupt reason*/
9406 if (!wdc_nvme_parse_dev_status_log_entry(dev_mng_log, &format_corrupt_reason,
9407 WDC_C2_FORMAT_CORRUPT_REASON_ID0x1E))
9408 nvme_show_error("ERROR: WDC: Get Format Corrupt Reason Failed")nvme_show_message(1, "ERROR: WDC: Get Format Corrupt Reason Failed"
)
;
9409
9410 printf(" Drive Status :-\n");
9411 if ((int)le32_to_cpu(eol_status) >= 0)
9412 printf(" Percent Used: %"PRIu32"u""%%\n",
9413 le32_to_cpu(eol_status));
9414 else
9415 printf(" Percent Used: Unknown\n");
9416 if (system_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000) && user_eol_state == WDC_EOL_STATUS_NORMALcpu_to_le32(0x00000000))
9417 printf(" Drive Life Status: Normal\n");
9418 else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001) ||
9419 user_eol_state == WDC_EOL_STATUS_END_OF_LIFEcpu_to_le32(0x00000001))
9420 printf(" Drive Life Status: End Of Life\n");
9421 else if (system_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002) ||
9422 user_eol_state == WDC_EOL_STATUS_READ_ONLYcpu_to_le32(0x00000002))
9423 printf(" Drive Life Status: Read Only\n");
9424 else
9425 printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n",
9426 le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state));
9427
9428 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001))
9429 printf(" Assert Dump Status: Present\n");
9430 else if (assert_status == WDC_ASSERT_DUMP_NOT_PRESENTcpu_to_le32(0x00000000))
9431 printf(" Assert Dump Status: Not Present\n");
9432 else
9433 printf(" Assert Dump Status: Unknown : 0x%08x\n", le32_to_cpu(assert_status));
9434
9435 if (thermal_status == WDC_THERMAL_THROTTLING_OFFcpu_to_le32(0x00000000))
9436 printf(" Thermal Throttling Status: Off\n");
9437 else if (thermal_status == WDC_THERMAL_THROTTLING_ONcpu_to_le32(0x00000001))
9438 printf(" Thermal Throttling Status: On\n");
9439 else if (thermal_status == WDC_THERMAL_THROTTLING_UNAVAILABLEcpu_to_le32(0x00000002))
9440 printf(" Thermal Throttling Status: Unavailable\n");
9441 else
9442 printf(" Thermal Throttling Status: Unknown : 0x%08x\n", le32_to_cpu(thermal_status));
9443
9444 if (format_corrupt_reason == WDC_FORMAT_NOT_CORRUPTcpu_to_le32(0x00000000))
9445 printf(" Format Corrupt Reason: Format Not Corrupted\n");
9446 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_FW_ASSERTcpu_to_le32(0x00000001))
9447 printf(" Format Corrupt Reason: Format Corrupt due to FW Assert\n");
9448 else if (format_corrupt_reason == WDC_FORMAT_CORRUPT_UNKNOWNcpu_to_le32(0x000000FF))
9449 printf(" Format Corrupt Reason: Format Corrupt for Unknown Reason\n");
9450 else
9451 printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
9452
9453 free(dev_mng_log);
9454out:
9455 return ret;
9456}
9457
9458static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd,
9459 struct plugin *plugin)
9460{
9461 const char *desc = "Clear Assert Dump Present Status.";
9462 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9463 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9464 int ret = -1;
9465 __le32 assert_status = cpu_to_le32(0xFFFFFFFF);
9466 __u64 capabilities = 0;
9467 struct libnvme_passthru_cmd admin_cmd;
9468
9469 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9470 OPT_END(){ ((void*)0) }
9471 };
9472
9473 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9474 if (ret)
9475 return ret;
9476
9477 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9478 if (ret)
9479 return ret;
9480
9481 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9482
9483 if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) != WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040) {
9484 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9485 ret = -1;
9486 goto out;
9487 }
9488 if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status,
9489 WDC_C2_ASSERT_DUMP_PRESENT_ID0x19)) {
9490 nvme_show_error("ERROR: WDC: Get Assert Status Failed")nvme_show_message(1, "ERROR: WDC: Get Assert Status Failed");
9491 ret = -1;
9492 goto out;
9493 }
9494
9495 /* Get the assert dump present status */
9496 if (assert_status == WDC_ASSERT_DUMP_PRESENTcpu_to_le32(0x00000001)) {
9497 memset(&admin_cmd, 0, sizeof(admin_cmd));
9498 admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE0xD8;
9499 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9500 WDC_NVME_CLEAR_ASSERT_DUMP_CMD0x03);
9501
9502 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9503 nvme_show_status(ret);
9504 } else
9505 nvme_show_error("INFO: WDC: No Assert Dump Present")nvme_show_message(1, "INFO: WDC: No Assert Dump Present");
9506
9507out:
9508 return ret;
9509}
9510
9511static int wdc_get_fw_act_history(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9512 char *format)
9513{
9514 struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
9515 nvme_print_flags_t fmt;
9516 int ret;
9517 __u8 *data;
9518
9519 if (!wdc_check_device(ctx, hdl))
9520 return -1;
9521
9522 ret = validate_output_format(format, &fmt);
9523 if (ret < 0) {
9524 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9525 return ret;
9526 }
9527
9528 /* verify the FW Activate History log page is supported */
9529 if (!wdc_nvme_check_supported_log_page(ctx, hdl,
9530 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) {
9531 nvme_show_error("ERROR: WDC: %d Log Page not supported",nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
9532 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)nvme_show_message(1, "ERROR: WDC: %d Log Page not supported",
0xCB)
;
9533 return -1;
9534 }
9535
9536 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9537 if (!data) {
9538 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9539 return -1;
9540 }
9541
9542 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9543
9544 ret = nvme_get_log_simple(hdl,
9545 WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB,
9546 data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN0x3d0);
9547
9548 if (strcmp(format, "json"))
9549 nvme_show_status(ret);
9550
9551 if (!ret) {
9552 /* parse the data */
9553 fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data);
9554
9555 if ((fw_act_history_hdr->num_entries > 0) &&
9556 (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES20)) {
9557 ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries,
9558 fmt, 0, 0, 0);
9559 } else if (!fw_act_history_hdr->num_entries) {
9560 nvme_show_error("INFO: WDC: No FW Activate History entries found.")nvme_show_message(1, "INFO: WDC: No FW Activate History entries found."
)
;
9561 ret = 0;
9562 } else {
9563 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)
9564 "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)
9565 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)
;
9566 ret = -1;
9567 }
9568 } else {
9569 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"
)
;
9570 ret = -1;
9571 }
9572
9573 free(data);
9574 return ret;
9575}
9576
9577static __u32 wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl)
9578{
9579
9580 __u32 cust_id = WDC_INVALID_CUSTOMER_ID-1;
9581 __u32 *cust_id_ptr = NULL((void*)0);
9582
9583 if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID0x15, (void *)&cust_id_ptr))
9584 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)
9585 __func__, WDC_C2_CUSTOMER_ID_ID)nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found"
, __func__, 0x15)
;
9586 else
9587 cust_id = *cust_id_ptr;
9588
9589 free(cust_id_ptr);
9590 return cust_id;
9591}
9592
9593static int wdc_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
9594 char *format)
9595{
9596 struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
9597 __u32 tot_entries = 0, num_entries = 0;
9598 __u32 vendor_id = 0, device_id = 0;
9599 __u32 cust_id = 0;
9600 nvme_print_flags_t fmt;
9601 __u8 *data;
9602 int ret;
9603 bool_Bool c2GuidMatch = false0;
9604
9605 if (!wdc_check_device(ctx, hdl))
9606 return -1;
9607
9608 ret = validate_output_format(format, &fmt);
9609 if (ret < 0) {
9610 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
9611 return ret;
9612 }
9613
9614 nvme_get_pci_ids(ctx, hdl, &vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
9615
9616 data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9617 if (!data) {
9618 nvme_show_error("ERROR: WDC: malloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: malloc: %s", libnvme_strerror
((*__errno_location ())))
;
9619 return -1;
9620 }
9621
9622 memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9623
9624 ret = nvme_get_log_simple(hdl,
9625 WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
9626 data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
9627
9628 if (strcmp(format, "json"))
9629 nvme_show_status(ret);
9630
9631 if (!ret) {
9632 /* Get the log page data and verify the GUID */
9633 fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data);
9634
9635 c2GuidMatch = !memcmp(ocp_C2_guid,
9636 fw_act_history_log->log_page_guid,
9637 WDC_C2_GUID_LENGTH16);
9638
9639 if (c2GuidMatch) {
9640 /* parse the data */
9641 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
9642
9643 if (tot_entries > 0) {
9644 /* get the FW customer id */
9645 if (!wdc_is_sn861(device_id)) {
9646 cust_id = wdc_get_fw_cust_id(ctx, hdl);
9647 if (cust_id == WDC_INVALID_CUSTOMER_ID-1) {
9648 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9649 "%s: ERROR: WDC: invalid customer id\n",nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
9650 __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id\n",
__func__)
;
9651 ret = -1;
9652 goto freeData;
9653 }
9654 }
9655 num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES20) ?
9656 tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES20;
9657 ret = wdc_print_fw_act_history_log(data, num_entries,
9658 fmt, cust_id, vendor_id, device_id);
9659 } else {
9660 nvme_show_error("INFO: WDC: No entries found.")nvme_show_message(1, "INFO: WDC: No entries found.");
9661 ret = 0;
9662 }
9663 } else {
9664 nvme_show_error("ERROR: WDC: Invalid C2 log page GUID")nvme_show_message(1, "ERROR: WDC: Invalid C2 log page GUID");
9665 ret = -1;
9666 }
9667 } else {
9668 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"
)
;
9669 ret = -1;
9670 }
9671
9672freeData:
9673 free(data);
9674 return ret;
9675}
9676
9677static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd,
9678 struct plugin *plugin)
9679{
9680 const char *desc = "Retrieve FW activate history table.";
9681 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9682 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9683 int ret;
9684
9685 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9686 OPT_END(){ ((void*)0) }
9687 };
9688
9689 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9690 if (ret)
9691 return ret;
9692
9693 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9694 if (ret)
9695 return ret;
9696
9697 return run_wdc_vs_fw_activate_history(ctx, hdl);
9698}
9699
9700int run_wdc_vs_fw_activate_history(struct libnvme_global_ctx *ctx,
9701 struct libnvme_transport_handle *hdl)
9702{
9703 char *output_format = nvme_args.output_format;
9704 __u64 capabilities = 0;
9705 int ret = -1;
9706
9707 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9708
9709 if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000))) {
9710 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9711 ret = -1;
9712 goto out;
9713 }
9714
9715 if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000) {
9716 __u32 cust_fw_id = 0;
9717 /* get the FW customer id */
9718 cust_fw_id = wdc_get_fw_cust_id(ctx, hdl);
9719 if (cust_fw_id == WDC_INVALID_CUSTOMER_ID-1) {
9720 nvme_show_error("%s: ERROR: WDC: invalid customer id", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid customer id", __func__
)
;
9721 ret = -1;
9722 goto out;
9723 }
9724
9725 if ((cust_fw_id == WDC_CUSTOMER_ID_0x10040x1004) ||
9726 (cust_fw_id == WDC_CUSTOMER_ID_0x10080x1008) ||
9727 (cust_fw_id == WDC_CUSTOMER_ID_0x10050x1005) ||
9728 (cust_fw_id == WDC_CUSTOMER_ID_0x13040x1304))
9729 ret = wdc_get_fw_act_history_C2(ctx, hdl,
9730 output_format);
9731 else
9732 ret = wdc_get_fw_act_history(ctx, hdl, output_format);
9733 } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
9734 ret = wdc_get_fw_act_history_C2(ctx, hdl, output_format);
9735 }
9736
9737 if (ret)
9738 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)
;
9739out:
9740 return ret;
9741}
9742
9743static int wdc_do_clear_fw_activate_history_vuc(struct libnvme_transport_handle *hdl)
9744{
9745 int ret = -1;
9746 struct libnvme_passthru_cmd admin_cmd;
9747
9748 memset(&admin_cmd, 0, sizeof(admin_cmd));
9749 admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE0xC6;
9750 admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD0x05 << WDC_NVME_SUBCMD_SHIFT8) |
9751 WDC_NVME_CLEAR_FW_ACT_HIST_CMD0x23);
9752
9753 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
9754 nvme_show_status(ret);
9755
9756 return ret;
9757}
9758
9759static int wdc_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
9760{
9761 int ret = -1;
9762 __u64 result;
9763 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
9764
9765 ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, false0,
9766 value, &result);
9767
9768 nvme_show_status(ret);
9769 return ret;
9770}
9771
9772static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd,
9773 struct plugin *plugin)
9774{
9775 const char *desc = "Clear FW activate history table.";
9776 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9777 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9778 int ret;
9779
9780 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9781 OPT_END(){ ((void*)0) }
9782 };
9783
9784 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9785 if (ret)
9786 return ret;
9787
9788 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9789 if (ret)
9790 return ret;
9791
9792 return run_wdc_clear_fw_activate_history(ctx, hdl);
9793}
9794
9795int run_wdc_clear_fw_activate_history(struct libnvme_global_ctx *ctx,
9796 struct libnvme_transport_handle *hdl)
9797{
9798 __u64 capabilities = 0;
9799 int ret;
9800
9801 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9802
9803 if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000))) {
9804 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9805 ret = -1;
9806 goto out;
9807 }
9808
9809 if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000)
9810 ret = wdc_do_clear_fw_activate_history_vuc(hdl);
9811 else
9812 ret = wdc_do_clear_fw_activate_history_fid(hdl);
9813
9814out:
9815 return ret;
9816}
9817
9818static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd,
9819 struct plugin *plugin)
9820{
9821 const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
9822 const char *disable = "Disable controller option of the telemetry log page.";
9823 const char *enable = "Enable controller option of the telemetry log page.";
9824 const char *status = "Displays the current state of the controller initiated log page.";
9825 __u64 capabilities = 0;
9826 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
9827 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
9828 struct libnvme_passthru_cmd cmd;
9829 __u64 result;
9830 int ret = -1;
9831
9832
9833 struct config {
9834 bool_Bool disable;
9835 bool_Bool enable;
9836 bool_Bool status;
9837 };
9838
9839 struct config cfg = {
9840 .disable = false0,
9841 .enable = false0,
9842 .status = false0,
9843 };
9844
9845 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
9846 OPT_FLAG("disable", 'd', &cfg.disable, disable){"disable", 'd', ((void*)0), CFG_FLAG, _Generic(&cfg.disable
, _Bool * : (&cfg.disable)), ARGCONFIG_ARG_NONE, disable,
0, }
,
9847 OPT_FLAG("enable", 'e', &cfg.enable, enable){"enable", 'e', ((void*)0), CFG_FLAG, _Generic(&cfg.enable
, _Bool * : (&cfg.enable)), ARGCONFIG_ARG_NONE, enable, 0
, }
,
9848 OPT_FLAG("status", 's', &cfg.status, status){"status", 's', ((void*)0), CFG_FLAG, _Generic(&cfg.status
, _Bool * : (&cfg.status)), ARGCONFIG_ARG_NONE, status, 0
, }
,
9849 OPT_END(){ ((void*)0) }
9850 };
9851
9852 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
9853 if (ret)
9854 return ret;
9855
9856 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
9857 if (ret)
9858 return ret;
9859
9860 capabilities = wdc_get_drive_capabilities(ctx, hdl);
9861
9862 if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000) {
9863 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
9864 ret = -1;
9865 goto out;
9866 }
9867
9868 /* allow only one option at a time */
9869 if ((cfg.disable + cfg.enable + cfg.status) > 1) {
9870
9871 nvme_show_error("ERROR: WDC: Invalid option")nvme_show_message(1, "ERROR: WDC: Invalid option");
9872 ret = -1;
9873 goto out;
9874 }
9875
9876 if (cfg.disable) {
9877 ret = nvme_set_features_simple(hdl, 0,
9878 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9879 false0, 1, &result);
9880
9881 wdc_clear_reason_id(hdl);
9882 } else {
9883 if (cfg.enable) {
9884 ret = nvme_set_features_simple(hdl, 0,
9885 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9886 false0, 0, &result);
9887 } else if (cfg.status) {
9888 nvme_init_get_features(&cmd,
9889 WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2,
9890 NVME_GET_FEATURES_SEL_CURRENT);
9891 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9892 result = cmd.result;
9893 if (!ret) {
9894 if (result)
9895 nvme_show_error("Controller Option Telemetry Log Page State: Disabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Disabled"
)
;
9896 else
9897 nvme_show_error("Controller Option Telemetry Log Page State: Enabled")nvme_show_message(1, "Controller Option Telemetry Log Page State: Enabled"
)
;
9898 } else {
9899 nvme_show_status(ret);
9900 }
9901 } else {
9902 nvme_show_error("ERROR: WDC: unsupported option for this command")nvme_show_message(1, "ERROR: WDC: unsupported option for this command"
)
;
9903 nvme_show_error("Please provide an option, -d, -e or -s")nvme_show_message(1, "Please provide an option, -d, -e or -s"
)
;
9904 ret = -1;
9905 goto out;
9906 }
9907 }
9908
9909out:
9910 return ret;
9911}
9912
9913
9914static int wdc_get_serial_and_fw_rev(struct libnvme_transport_handle *hdl, char *sn, char *fw_rev)
9915{
9916 struct libnvme_passthru_cmd cmd;
9917 struct nvme_id_ctrl ctrl;
9918 int ret;
9919 int i;
9920
9921 i = sizeof(ctrl.sn) - 1;
9922 memset(sn, 0, WDC_SERIAL_NO_LEN20);
9923 memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN9);
9924 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9925 nvme_init_identify_ctrl(&cmd, &ctrl);
9926 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9927 if (ret) {
9928 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)
;
9929 return -1;
9930 }
9931 /* Remove trailing spaces from the name */
9932 while (i && ctrl.sn[i] == ' ') {
9933 ctrl.sn[i] = '\0';
9934 i--;
9935 }
9936 snprintf(sn, WDC_SERIAL_NO_LEN20, "%s", ctrl.sn);
9937 snprintf(fw_rev, WDC_NVME_FIRMWARE_REV_LEN9, "%s", ctrl.fr);
9938
9939 return 0;
9940}
9941
9942static int wdc_get_max_transfer_len(struct libnvme_transport_handle *hdl, __u32 *maxTransferLen)
9943{
9944 struct libnvme_passthru_cmd cmd;
9945 struct nvme_id_ctrl ctrl;
9946 int ret = 0;
9947
9948 __u32 maxTransferLenDevice = 0;
9949
9950 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
9951 nvme_init_identify_ctrl(&cmd, &ctrl);
9952 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9953 if (ret) {
9954 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)
;
9955 return -1;
9956 }
9957
9958 maxTransferLenDevice = (1 << ctrl.mdts) * shr_getpagesize();
9959 *maxTransferLen = maxTransferLenDevice;
9960
9961 return ret;
9962}
9963
9964static int wdc_de_VU_read_size(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize)
9965{
9966 int ret = WDC_STATUS_FAILURE-1;
9967 struct libnvme_passthru_cmd cmd;
9968
9969 if (!logSize) {
9970 ret = WDC_STATUS_INVALID_PARAMETER-3;
9971 goto end;
9972 }
9973
9974 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
9975 cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE0xC0;
9976 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
9977 cmd.cdw13 = fileId << 16;
9978 cmd.cdw14 = spiDestn;
9979
9980 ret = libnvme_exec_admin_passthru(hdl, &cmd);
9981
9982 if (!ret && logSize)
9983 *logSize = cmd.result;
9984 if (ret != WDC_STATUS_SUCCESS0) {
9985 nvme_show_error("ERROR: WDC: VUReadSize() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadSize() failed, ");
9986 nvme_show_status(ret);
9987 }
9988
9989end:
9990 return ret;
9991}
9992
9993static int wdc_de_VU_read_buffer(struct libnvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn,
9994 __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize)
9995{
9996 int ret = WDC_STATUS_FAILURE-1;
9997 struct libnvme_passthru_cmd cmd;
9998 __u32 noOfDwordExpected = 0;
9999
10000 if (!dataBuffer || !bufferSize) {
10001 ret = WDC_STATUS_INVALID_PARAMETER-3;
10002 goto end;
10003 }
10004
10005 memset(&cmd, 0, sizeof(struct libnvme_passthru_cmd));
10006 noOfDwordExpected = *bufferSize / sizeof(__u32);
10007 cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE0xC2;
10008 cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID0x01;
10009 cmd.cdw10 = noOfDwordExpected;
10010 cmd.cdw13 = fileId << 16;
10011 cmd.cdw14 = spiDestn;
10012 cmd.cdw15 = offsetInDwords;
10013
10014 cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
10015 cmd.data_len = *bufferSize;
10016
10017 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10018
10019 if (ret != WDC_STATUS_SUCCESS0) {
10020 nvme_show_error("ERROR: WDC: VUReadBuffer() failed, ")nvme_show_message(1, "ERROR: WDC: VUReadBuffer() failed, ");
10021 nvme_show_status(ret);
10022 }
10023
10024end:
10025 return ret;
10026}
10027
10028static int wdc_get_log_dir_max_entries(struct libnvme_transport_handle *hdl, __u32 *maxNumOfEntries)
10029{
10030 int ret = WDC_STATUS_FAILURE-1;
10031 __u32 headerPayloadSize = 0;
10032 __u8 *fileIdOffsetsBuffer = NULL((void*)0);
10033 __u32 fileIdOffsetsBufferSize = 0;
10034 __u32 fileNum = 0;
10035 __u16 fileOffset = 0;
10036
10037
10038 if (!maxNumOfEntries) {
10039 ret = WDC_STATUS_INVALID_PARAMETER-3;
10040 return ret;
10041 }
10042 /* 1.Get log directory first four bytes */
10043 ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize);
10044 if (ret != WDC_STATUS_SUCCESS0) {
10045 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
10046 "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)
10047 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n"
, __func__, ret)
;
10048 return ret;
10049 }
10050
10051 fileIdOffsetsBufferSize =
10052 WDC_DE_FILE_HEADER_SIZE4 + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE2);
10053 fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize);
10054
10055 /* 2.Read to get file offsets */
10056 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize);
10057 if (ret != WDC_STATUS_SUCCESS0) {
10058 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
10059 "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)
10060 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n"
, __func__, ret)
;
10061 goto end;
10062 }
10063 /* 3.Determine valid entries */
10064 for (fileNum = 0;
10065 fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
10066 fileNum++) {
10067 fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
10068 (fileNum * WDC_DE_FILE_OFFSET_SIZE2)] << 8) +
10069 fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE4 +
10070 (fileNum * WDC_DE_FILE_OFFSET_SIZE2) + 1];
10071 if (!fileOffset)
10072 continue;
10073 (*maxNumOfEntries)++;
10074 }
10075
10076end:
10077 free(fileIdOffsetsBuffer);
10078 return ret;
10079}
10080
10081static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[])
10082{
10083 enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE;
10084
10085 if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME"core_dump"))
10086 essentialType = WDC_DE_TYPE_DUMPSNAPSHOT;
10087 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME"event_log"))
10088 essentialType = WDC_DE_TYPE_EVENTLOG;
10089 else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME"manufacturing_info"))
10090 essentialType = WDC_DE_TYPE_NVME_MANF_INFO;
10091
10092 return essentialType;
10093}
10094
10095static int wdc_fetch_log_directory(struct libnvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory)
10096{
10097 int ret = WDC_STATUS_FAILURE-1;
10098 __u8 *fileOffset = NULL((void*)0);
10099 __u8 *fileDirectory = NULL((void*)0);
10100 __u32 headerSize = 0;
10101 __u32 fileNum = 0, startIdx = 0;
10102 __u16 fileOffsetTemp = 0;
10103 __u32 entryId = 0;
10104 __u32 fileDirectorySize = 0;
10105
10106 if (!directory) {
10107 ret = WDC_STATUS_INVALID_PARAMETER-3;
10108 goto end;
10109 }
10110
10111 ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize);
10112 if (ret != WDC_STATUS_SUCCESS0) {
10113 nvme_show_error(nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
10114 "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)
10115 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n"
, __func__, ret)
;
10116 goto end;
10117 }
10118
10119 fileDirectory = (__u8 *)calloc(1, fileDirectorySize);
10120 ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize);
10121 if (ret != WDC_STATUS_SUCCESS0) {
10122 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)
10123 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d"
, __func__, ret)
;
10124 goto end;
10125 }
10126
10127 /* First four bytes of header directory is headerSize */
10128 memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE4);
10129
10130 /* headerSize describes the offset table inside fileDirectory */
10131 if (headerSize < WDC_DE_FILE_HEADER_SIZE4 || headerSize > fileDirectorySize) {
10132 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)
10133 __func__, headerSize, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid filesystem directory header size %u (buffer size %u)\n"
, __func__, headerSize, fileDirectorySize)
;
10134 ret = WDC_STATUS_FAILURE-1;
10135 goto end;
10136 }
10137
10138 /* minimum buffer for 1 entry is required */
10139 if (!directory->maxNumLogEntries) {
10140 ret = WDC_STATUS_INVALID_PARAMETER-3;
10141 goto end;
10142 }
10143
10144 for (fileNum = 0;
10145 fileNum < (headerSize - WDC_DE_FILE_HEADER_SIZE4) / WDC_DE_FILE_OFFSET_SIZE2;
10146 fileNum++) {
10147 if (entryId >= directory->maxNumLogEntries)
10148 break;
10149
10150 startIdx = WDC_DE_FILE_HEADER_SIZE4 + (fileNum * WDC_DE_FILE_OFFSET_SIZE2);
10151 memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp));
10152 fileOffset = fileDirectory + fileOffsetTemp;
10153
10154 if (!fileOffsetTemp)
10155 continue;
10156
10157 if (fileOffsetTemp + sizeof(struct WDC_DE_VU_FILE_META_DATA) > fileDirectorySize) {
10158 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)
10159 __func__, fileOffsetTemp, fileDirectorySize)nvme_show_message(1, "ERROR: WDC: %s: Invalid file offset %u (buffer size %u)\n"
, __func__, fileOffsetTemp, fileDirectorySize)
;
10160 ret = WDC_STATUS_FAILURE-1;
10161 goto end;
10162 }
10163
10164 memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS));
10165 memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed__attribute__((__packed__)) WDC_DE_VU_FILE_META_DATA));
10166 directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE32 - 1] = '\0';
10167 wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName,
10168 WDC_DE_FILE_NAME_SIZE32, ' ');
10169 if (!directory->logEntry[entryId].metaData.fileID)
10170 continue;
10171
10172 directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName);
10173 entryId++;
10174 }
10175
10176 directory->numOfValidLogEntries = entryId;
10177
10178end:
10179 free(fileDirectory);
10180 return ret;
10181}
10182
10183static int wdc_fetch_log_file_from_device(struct libnvme_transport_handle *hdl, __u32 fileId,
10184 __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
10185{
10186 int ret = WDC_STATUS_FAILURE-1;
10187 __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
10188 __u32 maximumTransferLength = 0;
10189 __u32 buffSize = 0;
10190 __u64 offsetIdx = 0;
10191
10192 if (!dataBuffer || !fileSize) {
10193 ret = WDC_STATUS_INVALID_PARAMETER-3;
10194 goto end;
10195 }
10196
10197 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) {
10198 ret = WDC_STATUS_FAILURE-1;
10199 goto end;
10200 }
10201
10202 /* Fetch Log File Data */
10203 if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) {
10204 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000;
10205 if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET0x8000)
10206 chunckSize = maximumTransferLength;
10207
10208 buffSize = chunckSize;
10209 for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) {
10210 if (((offsetIdx * chunckSize) + buffSize) > fileSize)
10211 buffSize = (__u32)(fileSize - (offsetIdx * chunckSize));
10212 /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */
10213 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
10214 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize);
10215 if (ret != WDC_STATUS_SUCCESS0) {
10216 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)
10217 __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)
;
10218 break;
10219 }
10220 }
10221 } else {
10222 buffSize = (__u32)fileSize;
10223 ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn,
10224 (__u32)((offsetIdx * chunckSize) / sizeof(__u32)),
10225 dataBuffer, &buffSize);
10226 if (ret != WDC_STATUS_SUCCESS0) {
10227 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)
10228 __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)
;
10229 }
10230 }
10231
10232end:
10233 return ret;
10234}
10235
10236static int wdc_de_get_dump_trace(struct libnvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen,
10237 const char *binFileName)
10238{
10239 int ret = WDC_STATUS_FAILURE-1;
10240 __u8 *readBuffer = NULL((void*)0);
10241 __u32 readBufferLen = 0;
10242 __u32 lastPktReadBufferLen = 0;
10243 __u32 maxTransferLen = 0;
10244 __u32 dumptraceSize = 0;
10245 __u32 chunkSize;
10246 __u32 chunks;
10247 __u32 offset;
10248 __u32 i;
10249 __u32 maximumTransferLength = 0;
10250
10251 if (!binFileName || !filePath) {
10252 ret = WDC_STATUS_INVALID_PARAMETER-3;
10253 return ret;
10254 }
10255
10256 if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0)
10257 return WDC_STATUS_FAILURE-1;
10258
10259 do {
10260 /* Get dumptrace size */
10261 ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, &dumptraceSize);
10262 if (ret != WDC_STATUS_SUCCESS0) {
10263 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)
10264 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d"
, __func__, ret)
;
10265 break;
10266 }
10267
10268 /* Make sure the size requested is greater than dword */
10269 if (dumptraceSize < 4) {
10270 ret = WDC_STATUS_FAILURE-1;
10271 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)
10272 __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)
;
10273 break;
10274 }
10275
10276 /* Choose the least max transfer length */
10277 maxTransferLen = maximumTransferLength < WDC_DE_READ_MAX_TRANSFER_SIZE0x8000 ? maximumTransferLength : WDC_DE_READ_MAX_TRANSFER_SIZE0x8000;
10278
10279 /* Comment from FW Team:
10280 * The max non - block transfer size is 0xFFFF (16 bits allowed as the block size).Use 0x8000
10281 * to keep it on a word - boundary.
10282 * max_xfer = int(pow(2, id_data['MDTS'])) * 4096 # 4k page size as reported in pcie capabiltiies
10283 */
10284 chunkSize = dumptraceSize < maxTransferLen ? dumptraceSize : maxTransferLen;
10285 chunks = (dumptraceSize / maxTransferLen) + ((dumptraceSize % maxTransferLen) ? 1 : 0);
10286
10287 readBuffer = (unsigned char *)calloc(dumptraceSize, sizeof(unsigned char));
10288 readBufferLen = chunkSize;
10289 lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize;
10290
10291 if (!readBuffer) {
10292 nvme_show_error("ERROR: WDC: %s: readBuffer calloc failed", __func__)nvme_show_message(1, "ERROR: WDC: %s: readBuffer calloc failed"
, __func__)
;
10293 ret = WDC_STATUS_INSUFFICIENT_MEMORY-2;
10294 break;
10295 }
10296
10297 for (i = 0; i < chunks; i++) {
10298 offset = (i * chunkSize) / 4;
10299
10300 /* Last loop call, Assign readBufferLen to read only left over bytes */
10301 if (i == (chunks - 1))
10302 readBufferLen = lastPktReadBufferLen;
10303
10304 ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION6, 0,
10305 readBuffer + offset, &readBufferLen);
10306 if (ret != WDC_STATUS_SUCCESS0) {
10307 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)
10308 "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)
10309 __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)
;
10310 break;
10311 }
10312 }
10313 } while (0);
10314
10315 if (ret == WDC_STATUS_SUCCESS0) {
10316 ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
10317 if (ret != WDC_STATUS_SUCCESS0)
10318 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)
10319 __func__, ret)nvme_show_message(1, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d"
, __func__, ret)
;
10320 } else {
10321 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)
10322 ret)nvme_show_message(1, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d"
, __func__, ret)
;
10323 }
10324
10325 free(readBuffer);
10326
10327 return ret;
10328}
10329
10330int wdc_fetch_vu_file_directory(struct libnvme_transport_handle *hdl,
10331 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList,
10332 __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString)
10333{
10334 int ret = wdc_fetch_log_directory(hdl, &deEssentialsList);
10335 __u32 listIdx;
10336 char *dataBuffer;
10337 char fileName[MAX_PATH_LEN256];
10338
10339 if (ret != WDC_STATUS_SUCCESS0) {
10340 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)
;
10341 return ret;
10342 }
10343
10344 /* Get Debug Data Files */
10345 for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) {
10346 if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) {
10347 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)
10348 deEssentialsList.logEntry[listIdx].metaData.fileName)nvme_show_message(1, "ERROR: WDC: File Size for %s is 0", deEssentialsList
.logEntry[listIdx].metaData.fileName)
;
10349 ret = WDC_STATUS_FILE_SIZE_ZERO-27;
10350 } else {
10351 /* Fetch Log File Data */
10352 dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10353 ret = wdc_fetch_log_file_from_device(hdl,
10354 deEssentialsList.logEntry[listIdx].metaData.fileID,
10355 WDC_DE_DESTN_SPI1,
10356 deEssentialsList.logEntry[listIdx].metaData.fileSize,
10357 (__u8 *)dataBuffer);
10358
10359 /* Write databuffer to file */
10360 if (ret == WDC_STATUS_SUCCESS0) {
10361 memset(fileName, 0, sizeof(fileName));
10362 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10363 deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString);
10364 if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) {
10365 wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF);
10366 wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF));
10367 } else {
10368 wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize);
10369 }
10370 } else {
10371 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)
10372 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)
;
10373 }
10374 free(dataBuffer);
10375 }
10376 }
10377
10378 return ret;
10379}
10380
10381int wdc_read_debug_directory(struct libnvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo,
10382 __u8 *timeString)
10383{
10384 __u32 maxNumOfVUFiles = 0;
10385 int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles);
10386 struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
10387
10388 if (ret != WDC_STATUS_SUCCESS0) {
10389 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)
;
10390 return ret;
10391 }
10392
10393 memset(&deEssentialsList, 0, sizeof(deEssentialsList));
10394 deEssentialsList.logEntry =
10395 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles);
10396 deEssentialsList.maxNumLogEntries = maxNumOfVUFiles;
10397
10398 ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo,
10399 timeString);
10400
10401 free(deEssentialsList.logEntry);
10402 deEssentialsList.logEntry = NULL((void*)0);
10403
10404 return ret;
10405}
10406
10407static int wdc_do_drive_essentials(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
10408 char *dir, char *key)
10409{
10410 int ret = 0;
10411 void *retPtr;
10412 char fileName[MAX_PATH_LEN256];
10413 __s8 bufferFolderPath[MAX_PATH_LEN256];
10414 char bufferFolderName[MAX_PATH_LEN256];
10415 char tarFileName[MAX_PATH_LEN256];
10416 char tarDir[MAX_PATH_LEN256];
10417 UtilsTimeInfo timeInfo;
10418 __u8 timeString[MAX_PATH_LEN256];
10419 __u8 serialNo[WDC_SERIAL_NO_LEN20];
10420 __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN9];
10421 __u8 idSerialNo[WDC_SERIAL_NO_LEN20];
10422 __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN9];
10423 __u8 featureIdBuff[4];
10424 char currDir[MAX_PATH_LEN256];
10425 char *dataBuffer = NULL((void*)0);
10426 __u32 elogNumEntries, elogBufferSize;
10427 __u32 dataBufferSize;
10428 __u32 listIdx = 0;
10429 __u32 vuLogIdx = 0;
10430 __u64 result;
10431 struct nvme_id_ctrl ctrl;
10432 struct nvme_id_ns ns;
10433 struct nvme_error_log_page *elogBuffer;
10434 struct nvme_smart_log smart_log;
10435 struct nvme_firmware_slot fw_log;
10436 struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL((void*)0);
10437 struct libnvme_passthru_cmd cmd;
10438
10439 memset(bufferFolderPath, 0, sizeof(bufferFolderPath));
10440 memset(bufferFolderName, 0, sizeof(bufferFolderName));
10441 memset(tarFileName, 0, sizeof(tarFileName));
10442 memset(tarDir, 0, sizeof(tarDir));
10443 memset(&timeInfo, 0, sizeof(timeInfo));
10444
10445 if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) {
10446 nvme_show_error("ERROR: WDC: get serial # and fw revision failed")nvme_show_message(1, "ERROR: WDC: get serial # and fw revision failed"
)
;
10447 return -1;
10448 }
10449
10450 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)
10451 idSerialNo, idFwRev)nvme_show_message(1, "Get Drive Essentials Data for device serial #: %s and fw revision: %s"
, idSerialNo, idFwRev)
;
10452
10453 /* Create Drive Essentials directory */
10454 wdc_UtilsGetTime(&timeInfo);
10455 memset(timeString, 0, sizeof(timeString));
10456 wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10457 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10458 timeInfo.hour, timeInfo.minute, timeInfo.second);
10459
10460 wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN20,
10461 "%s", (char *)idSerialNo);
10462 /* Remove any space form serialNo */
10463 wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN20, ' ');
10464
10465 memset(firmwareRevision, 0, sizeof(firmwareRevision));
10466 wdc_UtilsSnprintf((char *)firmwareRevision,
10467 WDC_NVME_FIRMWARE_REV_LEN9,
10468 "%s", (char *)idFwRev);
10469 /* Remove any space form FirmwareRevision */
10470 wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN9, ' ');
10471
10472 wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN256, "%s_%s_%s_%s",
10473 "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString);
10474
10475 if (dir) {
10476 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10477 (char *)dir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10478 } else {
10479 retPtr = getcwd((char *)currDir, MAX_PATH_LEN256);
10480 if (retPtr) {
10481 wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN256, "%s%s%s",
10482 (char *)currDir, WDC_DE_PATH_SEPARATOR"/", (char *)bufferFolderName);
10483 } else {
10484 nvme_show_error("ERROR: WDC: get current working directory failed")nvme_show_message(1, "ERROR: WDC: get current working directory failed"
)
;
10485 return -1;
10486 }
10487 }
10488
10489 ret = wdc_UtilsCreateDir((char *)bufferFolderPath);
10490 if (ret) {
10491 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)
;
10492 return -1;
10493 }
10494
10495 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)
;
10496
10497 /* Get Identify Controller Data */
10498 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
10499 nvme_init_identify_ctrl(&cmd, &ctrl);
10500 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10501 if (ret) {
10502 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)
;
10503 return -1;
10504 }
10505
10506 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath,
10507 WDC_DE_PATH_SEPARATOR"/", "IdentifyController", (char *)serialNo,
10508 (char *)timeString);
10509 wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl));
10510
10511 memset(&ns, 0, sizeof(struct nvme_id_ns));
10512 nvme_init_identify_ns(&cmd, 1, &ns);
10513 ret = libnvme_exec_admin_passthru(hdl, &cmd);
10514 if (ret) {
10515 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)
;
10516 } else {
10517 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10518 "IdentifyNamespace", (char *)serialNo, (char *)timeString);
10519 wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns));
10520 }
10521
10522 /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */
10523 elogNumEntries = WDC_DE_DEFAULT_NUMBER_OF_ERROR_ENTRIES64;
10524 elogBufferSize = elogNumEntries*sizeof(struct nvme_error_log_page);
10525 dataBuffer = calloc(1, elogBufferSize);
10526 elogBuffer = (struct nvme_error_log_page *)dataBuffer;
10527
10528 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR,
10529 NVME_CSI_NVM, elogBuffer, elogBufferSize);
10530
10531 ret = libnvme_get_log(hdl, &cmd, false0, elogBufferSize);
10532 if (ret) {
10533 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)
;
10534 } else {
10535 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10536 "ErrorLog", (char *)serialNo, (char *)timeString);
10537 wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize);
10538 }
10539
10540 free(dataBuffer);
10541 dataBuffer = NULL((void*)0);
10542
10543 /* Get Smart log page */
10544 memset(&smart_log, 0, sizeof(struct nvme_smart_log));
10545 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
10546 if (ret) {
10547 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)
;
10548 } else {
10549 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10550 "SmartLog", (char *)serialNo, (char *)timeString);
10551 wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log));
10552 }
10553
10554 /* Get FW Slot log page */
10555 memset(&fw_log, 0, sizeof(struct nvme_firmware_slot));
10556 nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT,
10557 NVME_CSI_NVM, &fw_log, sizeof(fw_log));
10558
10559 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(fw_log));
10560 if (ret) {
10561 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)
;
10562 } else {
10563 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10564 "FwSLotLog", (char *)serialNo, (char *)timeString);
10565 wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot));
10566 }
10567
10568 /* Get VU log pages */
10569 /* define inputs for vendor unique log pages */
10570 vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES));
10571 vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList)(sizeof(deVULogPagesList) / sizeof((deVULogPagesList)[0]) + 0
)
;
10572
10573 for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) {
10574 dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen;
10575 dataBuffer = calloc(1, dataBufferSize);
10576 memset(dataBuffer, 0, dataBufferSize);
10577
10578 ret = nvme_get_log_simple(hdl,
10579 deVULogPagesList[vuLogIdx].logPageId,
10580 dataBuffer, dataBufferSize);
10581 if (ret) {
10582 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)
10583 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)
;
10584 } else {
10585 wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' ');
10586 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10587 "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString);
10588 wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize);
10589 }
10590
10591 free(dataBuffer);
10592 }
10593
10594 free(vuLogInput);
10595
10596 /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */
10597 for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList)(sizeof(deFeatureIdList) / sizeof((deFeatureIdList)[0]) + 0); listIdx++) {
10598 memset(featureIdBuff, 0, sizeof(featureIdBuff));
10599 /* skipping LbaRangeType as it is an optional nvme command and not supported */
10600 if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
10601 continue;
10602 ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID0xFFFFFFFF,
10603 (enum nvme_features_id)deFeatureIdList[listIdx].featureId,
10604 NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff,
10605 sizeof(featureIdBuff), &result);
10606 if (ret) {
10607 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)
10608 deFeatureIdList[listIdx].featureId, ret)nvme_show_message(1, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d"
, deFeatureIdList[listIdx].featureId, ret)
;
10609 } else {
10610 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/",
10611 "FEATURE_ID_", deFeatureIdList[listIdx].featureId,
10612 deFeatureIdList[listIdx].featureName, serialNo, timeString);
10613 wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff));
10614 }
10615 }
10616
10617 wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString);
10618
10619 /* Get Dump Trace Data */
10620 wdc_UtilsSnprintf(fileName, MAX_PATH_LEN256, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR"/", "dumptrace", serialNo, timeString);
10621 ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName);
10622 if (ret != WDC_STATUS_SUCCESS0)
10623 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)
;
10624
10625 /* Tar the Drive Essentials directory */
10626 wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN".tar.gz");
10627 if (dir)
10628 wdc_UtilsSnprintf(tarDir, sizeof(tarDir), "%s%s%s",
10629 (char *)dir, WDC_DE_PATH_SEPARATOR"/",
10630 (char *)bufferFolderName);
10631 else
10632 wdc_UtilsSnprintf(tarDir, sizeof(tarDir), "%s",
10633 (char *)bufferFolderName);
10634 ret = wdc_tar_dir_files(tarFileName, tarDir, wdc_is_bin_file, false0);
10635
10636 if (ret)
10637 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)
10638 ret)nvme_show_message(1, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d"
, ret)
;
10639
10640 nvme_show_verbose_result("Get of Drive Essentials data successful")nvme_show_verbose_message("Get of Drive Essentials data successful"
)
;
10641 return 0;
10642}
10643
10644static int wdc_drive_essentials(int argc, char **argv, struct command *acmd,
10645 struct plugin *plugin)
10646{
10647 const char *desc = "Capture Drive Essentials.";
10648 const char *dirName = "Output directory pathname.";
10649 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10650 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10651 char d[PATH_MAX4096] = {0};
10652 char k[PATH_MAX4096] = {0};
10653 __u64 capabilities = 0;
10654 char *d_ptr;
10655 int ret;
10656
10657 struct config {
10658 char *dirName;
10659 };
10660
10661 struct config cfg = {
10662 .dirName = NULL((void*)0),
10663 };
10664
10665 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10666 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, }
,
10667 OPT_END(){ ((void*)0) }
10668 };
10669
10670
10671 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10672 if (ret)
10673 return ret;
10674
10675 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10676 if (ret)
10677 return ret;
10678
10679 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10680
10681 if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000) {
10682 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10683 ret = -1;
10684 goto out;
10685 }
10686
10687 if (cfg.dirName) {
10688 shr_strscpy(d, cfg.dirName, sizeof(d));
10689 d_ptr = d;
10690 } else {
10691 d_ptr = NULL((void*)0);
10692 }
10693
10694 ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k);
10695out:
10696 return ret;
10697}
10698
10699static int wdc_do_drive_resize(struct libnvme_transport_handle *hdl, uint64_t new_size)
10700{
10701 int ret;
10702 struct libnvme_passthru_cmd admin_cmd;
10703
10704 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10705 admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE0xCC;
10706 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD0x01 << WDC_NVME_SUBCMD_SHIFT8) |
10707 WDC_NVME_DRIVE_RESIZE_CMD0x03);
10708 admin_cmd.cdw13 = new_size;
10709
10710 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10711 return ret;
10712}
10713
10714static int wdc_do_namespace_resize(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 op_option)
10715{
10716 int ret;
10717 struct libnvme_passthru_cmd admin_cmd;
10718
10719 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10720 admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE0xFB;
10721 admin_cmd.nsid = nsid;
10722 admin_cmd.cdw10 = op_option;
10723
10724 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10725 return ret;
10726}
10727
10728static int wdc_do_drive_info(struct libnvme_transport_handle *hdl, __u32 *result)
10729{
10730 int ret;
10731 struct libnvme_passthru_cmd admin_cmd;
10732
10733 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
10734 admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE0xC6;
10735 admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD0x06 << WDC_NVME_SUBCMD_SHIFT8) |
10736 WDC_NVME_DRIVE_INFO_CMD0x22);
10737
10738 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
10739
10740 if (!ret && result)
10741 *result = admin_cmd.result;
10742
10743 return ret;
10744}
10745
10746static int wdc_drive_resize(int argc, char **argv,
10747 struct command *command, struct plugin *plugin)
10748{
10749 const char *desc = "Send a Resize command.";
10750 const char *size = "The new size (in GB) to resize the drive to.";
10751 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10752 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10753 int ret;
10754
10755 struct config {
10756 uint64_t size;
10757 };
10758
10759 struct config cfg = {
10760 .size = 0,
10761 };
10762
10763 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10764 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, }
,
10765 OPT_END(){ ((void*)0) }
10766 };
10767
10768 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10769 if (ret)
10770 return ret;
10771
10772 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10773 if (ret)
10774 return -1;
10775
10776 return run_wdc_drive_resize(ctx, hdl, cfg.size);
10777}
10778
10779int run_wdc_drive_resize(struct libnvme_global_ctx *ctx,
10780 struct libnvme_transport_handle *hdl, uint64_t size)
10781{
10782 uint64_t capabilities = 0;
10783 int ret;
10784
10785 if (!wdc_check_device(ctx, hdl))
10786 return -1;
10787
10788 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10789
10790 if ((capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100) == WDC_DRIVE_CAP_RESIZE0x0000000000000100) {
10791 ret = wdc_do_drive_resize(hdl, size);
10792 } else {
10793 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10794 ret = -1;
10795 }
10796
10797 if (!ret)
10798 printf("New size: %" PRIu64"l" "u" " GB\n", size);
10799
10800 nvme_show_status(ret);
10801 return ret;
10802}
10803
10804static int wdc_namespace_resize(int argc, char **argv,
10805 struct command *command, struct plugin *plugin)
10806{
10807 const char *desc = "Send a Namespace Resize command.";
10808 const char *namespace_id = "The namespace id to resize.";
10809 const char *op_option = "The over provisioning option to set for namespace.";
10810 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10811 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10812 uint64_t capabilities = 0;
10813 int ret;
10814
10815 struct config {
10816 __u32 namespace_id;
10817 __u32 op_option;
10818 };
10819
10820 struct config cfg = {
10821 .namespace_id = 0x1,
10822 .op_option = 0xF,
10823 };
10824
10825 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10826 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}
10827 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}
,
10828 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, }
,
10829 OPT_END(){ ((void*)0) }
10830 };
10831
10832 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10833 if (ret)
10834 return ret;
10835
10836 if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) &&
10837 (cfg.op_option != 0xF)) {
10838 nvme_show_error("ERROR: WDC: unsupported OP option parameter")nvme_show_message(1, "ERROR: WDC: unsupported OP option parameter"
)
;
10839 return -1;
10840 }
10841
10842 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10843 if (ret || !wdc_check_device(ctx, hdl))
10844 return -1;
10845
10846 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10847
10848 if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) == WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000) {
10849 ret = wdc_do_namespace_resize(hdl, cfg.namespace_id,
10850 cfg.op_option);
10851
10852 if (ret)
10853 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)
;
10854 } else {
10855 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
10856 ret = -1;
10857 }
10858
10859 nvme_show_status(ret);
10860 return ret;
10861}
10862
10863static int wdc_reason_identifier(int argc, char **argv,
10864 struct command *command, struct plugin *plugin)
10865{
10866 const char *desc = "Retrieve telemetry log reason identifier.";
10867 const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
10868 const char *fname = "File name to save raw binary identifier";
10869 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
10870 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
10871 int ret;
10872 uint64_t capabilities = 0;
10873 char f[PATH_MAX4096] = {0};
10874 char fileSuffix[PATH_MAX4096] = {0};
10875 UtilsTimeInfo timeInfo;
10876 __u8 timeStamp[MAX_PATH_LEN256];
10877
10878
10879 struct config {
10880 __u32 log_id;
10881 char *file;
10882 };
10883 struct config cfg = {
10884 .log_id = 7,
10885 .file = NULL((void*)0),
10886 };
10887
10888 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
10889 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, }
,
10890 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, }
,
10891 OPT_END(){ ((void*)0) }
10892 };
10893
10894 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
10895
10896 if (ret)
10897 return ret;
10898
10899 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
10900 if (ret)
10901 return ret;
10902
10903 if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST &&
10904 cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
10905 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)"
)
;
10906 return -1;
10907 }
10908
10909 if (cfg.file) {
10910 int verify_file;
10911
10912 /* verify the passed in file name and path is valid before getting the dump data */
10913 verify_file = shr_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
10914 if (verify_file < 0) {
10915 nvme_show_error("ERROR: WDC: open: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: open: %s", libnvme_strerror
((*__errno_location ())))
;
10916 return -1;
10917 }
10918 close(verify_file);
10919 shr_strscpy(f, cfg.file, sizeof(f));
10920 } else {
10921 wdc_UtilsGetTime(&timeInfo);
10922 memset(timeStamp, 0, sizeof(timeStamp));
10923 wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN256, "%02u%02u%02u_%02u%02u%02u",
10924 timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
10925 timeInfo.hour, timeInfo.minute, timeInfo.second);
10926 if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
10927 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_ctlr_%s", (char *)timeStamp);
10928 else
10929 snprintf(fileSuffix, PATH_MAX4096, "_error_reason_identifier_host_%s", (char *)timeStamp);
10930
10931 if (wdc_get_serial_name(hdl, f, PATH_MAX4096, fileSuffix) == -1) {
10932 nvme_show_error("ERROR: WDC: failed to generate file name")nvme_show_message(1, "ERROR: WDC: failed to generate file name"
)
;
10933 return -1;
10934 }
10935 if (strlen(f) > PATH_MAX4096 - 5) {
10936 nvme_show_error("ERROR: WDC: file name overflow")nvme_show_message(1, "ERROR: WDC: file name overflow");
10937 return -1;
10938 }
10939 shr_strscat(f, ".bin", sizeof(f));
10940 }
10941
10942 nvme_show_error("%s: filename = %s", __func__, f)nvme_show_message(1, "%s: filename = %s", __func__, f);
10943
10944 capabilities = wdc_get_drive_capabilities(ctx, hdl);
10945 if ((capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000) == WDC_DRIVE_CAP_REASON_ID0x0000000000010000) {
10946 ret = wdc_do_get_reason_id(hdl, f, cfg.log_id);
10947 } else {
10948 nvme_show_error("ERROR: WDC:unsupported device for this command")nvme_show_message(1, "ERROR: WDC:unsupported device for this command"
)
;
10949 ret = -1;
10950 }
10951
10952 nvme_show_status(ret);
10953
10954 return ret;
10955}
10956
10957static const char *nvme_log_id_to_string(__u8 log_id)
10958{
10959 switch (log_id) {
10960 case NVME_LOG_LID_ERROR:
10961 return "Error Information Log ID";
10962 case NVME_LOG_LID_SMART:
10963 return "Smart/Health Information Log ID";
10964 case NVME_LOG_LID_FW_SLOT:
10965 return "Firmware Slot Information Log ID";
10966 case NVME_LOG_LID_CHANGED_ATTACHED_NS:
10967 return "Attached Namespace Changed Log ID";
10968 case NVME_LOG_LID_CMD_EFFECTS:
10969 return "Commamds Supported and Effects Log ID";
10970 case NVME_LOG_LID_DEVICE_SELF_TEST:
10971 return "Device Self Test Log ID";
10972 case NVME_LOG_LID_TELEMETRY_HOST:
10973 return "Telemetry Host Initiated Log ID";
10974 case NVME_LOG_LID_TELEMETRY_CTRL:
10975 return "Telemetry Controller Generated Log ID";
10976 case NVME_LOG_LID_ENDURANCE_GROUP:
10977 return "Endurance Group Log ID";
10978 case NVME_LOG_LID_ANA:
10979 return "ANA Log ID";
10980 case NVME_LOG_LID_PERSISTENT_EVENT:
10981 return "Persistent Event Log ID";
10982 case NVME_LOG_LID_DISCOVERY:
10983 return "Discovery Log ID";
10984 case NVME_LOG_LID_RESERVATION:
10985 return "Reservation Notification Log ID";
10986 case NVME_LOG_LID_SANITIZE:
10987 return "Sanitize Status Log ID";
10988 case WDC_LOG_ID_C00xC0:
10989 return "WDC Vendor Unique Log ID C0";
10990 case WDC_LOG_ID_C10xC1:
10991 return "WDC Vendor Unique Log ID C1";
10992 case WDC_LOG_ID_C20xC2:
10993 return "WDC Vendor Unique Log ID C2";
10994 case WDC_LOG_ID_C30xC3:
10995 return "WDC Vendor Unique Log ID C3";
10996 case WDC_LOG_ID_C40xC4:
10997 return "WDC Vendor Unique Log ID C4";
10998 case WDC_LOG_ID_C50xC5:
10999 return "WDC Vendor Unique Log ID C5";
11000 case WDC_LOG_ID_C60xC6:
11001 return "WDC Vendor Unique Log ID C6";
11002 case WDC_LOG_ID_C80xC8:
11003 return "WDC Vendor Unique Log ID C8";
11004 case WDC_LOG_ID_CA0xCA:
11005 return "WDC Vendor Unique Log ID CA";
11006 case WDC_LOG_ID_CB0xCB:
11007 return "WDC Vendor Unique Log ID CB";
11008 case WDC_LOG_ID_D00xD0:
11009 return "WDC Vendor Unique Log ID D0";
11010 case WDC_LOG_ID_D10xD1:
11011 return "WDC Vendor Unique Log ID D1";
11012 case WDC_LOG_ID_D60xD6:
11013 return "WDC Vendor Unique Log ID D6";
11014 case WDC_LOG_ID_D70xD7:
11015 return "WDC Vendor Unique Log ID D7";
11016 case WDC_LOG_ID_D80xD8:
11017 return "WDC Vendor Unique Log ID D8";
11018 case WDC_LOG_ID_DE0xDE:
11019 return "WDC Vendor Unique Log ID DE";
11020 case WDC_LOG_ID_F00xF0:
11021 return "WDC Vendor Unique Log ID F0";
11022 case WDC_LOG_ID_F10xF1:
11023 return "WDC Vendor Unique Log ID F1";
11024 case WDC_LOG_ID_F20xF2:
11025 return "WDC Vendor Unique Log ID F2";
11026 case WDC_LOG_ID_FA0xFA:
11027 return "WDC Vendor Unique Log ID FA";
11028 default:
11029 return "Unknown Log ID";
11030 }
11031}
11032
11033static void __json_log_page_directory(struct log_page_directory *directory)
11034{
11035 __u32 bitmap_idx;
11036 __u8 log_id;
11037 struct json_object *root;
11038 struct json_object *entries;
11039
11040 root = json_create_object()json_object_new_object();
11041
11042 entries = json_create_array()json_object_new_array();
11043 json_object_add_value_array(root, "Entries", entries)json_object_object_add(root, "Entries", entries);
11044
11045 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11046 log_id = bitmap_idx;
11047 if (!log_page_name[log_id])
11048 continue;
11049 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
11050 struct json_object *json_entry = json_create_object()json_object_new_object();
11051
11052 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))
;
11053 json_object_add_value_string(json_entry, "Log Page Name",
11054 log_page_name[log_id]);
11055
11056 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11057 }
11058 }
11059
11060 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11061 log_id = NVME_LOG_NS_BASE + bitmap_idx;
11062 if (!log_page_name[log_id])
11063 continue;
11064 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
11065 struct json_object *json_entry = json_create_object()json_object_new_object();
11066
11067 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))
;
11068 json_object_add_value_string(json_entry, "Log Page Name",
11069 log_page_name[log_id]);
11070
11071 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11072 }
11073 }
11074
11075 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11076 log_id = NVME_LOG_VS_BASE + bitmap_idx;
11077 if (!log_page_name[log_id])
11078 continue;
11079 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
11080 struct json_object *json_entry = json_create_object()json_object_new_object();
11081
11082 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))
;
11083 json_object_add_value_string(json_entry, "Log Page Name",
11084 log_page_name[log_id]);
11085
11086 json_array_add_value_object(entries, json_entry)json_object_array_add(entries, json_entry);
11087 }
11088 }
11089
11090 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11091 printf("\n");
11092 json_free_object(root)json_object_put(root);
11093}
11094
11095
11096static void __show_log_page_directory(struct log_page_directory *directory)
11097{
11098 __u32 bitmap_idx;
11099 __u8 log_id;
11100
11101 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11102 if (directory->supported_lid_bitmap & (1ULL << bitmap_idx)) {
11103 log_id = bitmap_idx;
11104 if (log_page_name[log_id])
11105 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11106 }
11107 }
11108
11109 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11110 if (directory->supported_ns_lid_bitmap & (1ULL << bitmap_idx)) {
11111 log_id = NVME_LOG_NS_BASE + bitmap_idx;
11112 if (log_page_name[log_id])
11113 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11114 }
11115 }
11116
11117 for (bitmap_idx = 0; bitmap_idx < BYTE_TO_BIT(sizeof(__u64))((sizeof(__u64)) * 8); bitmap_idx++) {
11118 if (directory->supported_vs_lid_bitmap & (1ULL << bitmap_idx)) {
11119 log_id = NVME_LOG_VS_BASE + bitmap_idx;
11120 if (log_page_name[log_id])
11121 printf("0x%02X: %s\n", log_id, log_page_name[log_id]);
11122 }
11123 }
11124}
11125
11126static int wdc_log_page_directory(int argc, char **argv, struct command *acmd,
11127 struct plugin *plugin)
11128{
11129 const char *desc = "Retrieve Log Page Directory.";
11130 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11131 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11132 nvme_print_flags_t fmt;
11133 int ret = 0;
11134 __u64 capabilities = 0;
11135 struct wdc_c2_cbs_data *cbs_data = NULL((void*)0);
11136 int i, uuid_index = 0;
11137 __u8 log_id = 0;
11138 __u32 device_id, read_vendor_id;
11139 bool_Bool uuid_supported = false0;
11140 struct nvme_id_uuid_list uuid_list;
11141
11142 struct config {
11143 char *output_format;
11144 };
11145
11146 struct config cfg = {
11147 .output_format = "normal",
11148 };
11149
11150 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
11151 OPT_END(){ ((void*)0) }
11152 };
11153
11154 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11155 if (ret)
11156 return ret;
11157
11158 cfg.output_format = nvme_args.output_format;
11159
11160 ret = validate_output_format(cfg.output_format, &fmt);
11161 if (ret < 0) {
11162 nvme_show_error("%s: ERROR: WDC: invalid output format", __func__)nvme_show_message(1, "%s: ERROR: WDC: invalid output format",
__func__)
;
11163 return ret;
11164 }
11165
11166 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11167 if (ret)
11168 return ret;
11169
11170 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11171
11172 if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000)) {
11173 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11174 ret = -1;
11175 } else {
11176 memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
11177 if (wdc_CheckUuidListSupport(hdl, &uuid_list))
11178 uuid_supported = true1;
11179
11180 if (uuid_supported)
11181 nvme_show_error("WDC: UUID lists supported")nvme_show_message(1, "WDC: UUID lists supported");
11182 else
11183 nvme_show_error("WDC: UUID lists NOT supported")nvme_show_message(1, "WDC: UUID lists NOT supported");
11184
11185
11186 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11187 if (ret)
11188 return ret;
11189
11190 log_id = wdc_is_zn350(device_id) ?
11191 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C80xC8 :
11192 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2;
11193
11194 if (!wdc_is_sn861(device_id)) {
11195 if (uuid_supported) {
11196 /* check for the Sandisk UUID first */
11197 uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID);
11198
11199 if (uuid_index < 0)
11200 /* The Sandisk UUID is not found;
11201 * check for the WDC UUID second.
11202 */
11203 uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID);
11204 }
11205
11206 /* WD UUID not found, use default uuid index - 0 */
11207 if (uuid_index < 0)
11208 uuid_index = 0;
11209
11210 /* verify the 0xC2 Device Manageability log page is supported */
11211 if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) {
11212 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)
11213 __func__, log_id)nvme_show_message(1, "%s: ERROR: WDC: 0x%x Log Page not supported"
, __func__, log_id)
;
11214 ret = -1;
11215 goto out;
11216 }
11217
11218 if (!get_dev_mgment_cbs_data(ctx, hdl,
11219 WDC_C2_LOG_PAGES_SUPPORTED_ID0x08,
11220 (void *)&cbs_data)) {
11221 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n"
, __func__, 0x08)
11222 "%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)
11223 __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)
;
11224 ret = -1;
11225 goto out;
11226 }
11227 if (!cbs_data) {
11228 nvme_show_error("%s: ERROR: WDC: NULL_data ptr", __func__)nvme_show_message(1, "%s: ERROR: WDC: NULL_data ptr", __func__
)
;
11229 ret = -1;
11230 goto out;
11231 }
11232 printf("Log Page Directory\n");
11233 /* print the supported pages */
11234 if (!strcmp(cfg.output_format, "normal")) {
11235 for (i = 0; i < le32_to_cpu(cbs_data->length); i++)
11236 printf("0x%x - %s\n", cbs_data->data[i],
11237 nvme_log_id_to_string(cbs_data->data[i]));
11238 } else if (!strcmp(cfg.output_format, "binary")) {
11239 d((__u8 *)cbs_data->data,
11240 le32_to_cpu(cbs_data->length), 16, 1);
11241 } else if (!strcmp(cfg.output_format, "json")) {
11242 struct json_object *root = json_create_object()json_object_new_object();
11243
11244 for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
11245 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]))
11246 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]))
11247 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]))
;
11248 }
11249
11250 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11251 printf("\n");
11252 json_free_object(root)json_object_put(root);
11253 } else {
11254 nvme_show_error(nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
11255 "%s: ERROR: WDC: Invalid format, format = %s\n",nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
11256 __func__, cfg.output_format)nvme_show_message(1, "%s: ERROR: WDC: Invalid format, format = %s\n"
, __func__, cfg.output_format)
;
11257 }
11258
11259 free(cbs_data);
11260 } else {
11261 struct log_page_directory *dir;
11262 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *data = NULL((void*)0);
11263
11264 data = libnvme_alloc(512);
11265 if (!data) {
11266 nvme_show_error(nvme_show_message(1, "can not allocate log page directory payload\n"
)
11267 "can not allocate log page directory payload\n")nvme_show_message(1, "can not allocate log page directory payload\n"
)
;
11268 return -ENOMEM12;
11269 }
11270
11271 dir = (struct log_page_directory *)data;
11272 struct libnvme_passthru_cmd cmd = {
11273 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
11274 .cdw10 = 8,
11275 .cdw12 = WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2,
11276 .addr = (__u64)(uintptr_t)data,
11277 .data_len = 32,
11278 };
11279
11280 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11281 if (!ret) {
11282 switch (fmt) {
11283 case BINARY:
11284 d_raw((unsigned char *)data, 32);
11285 break;
11286 case JSON:
11287 __json_log_page_directory(dir);
11288 break;
11289 default:
11290 __show_log_page_directory(dir);
11291 }
11292 } else {
11293 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
11294 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
11295 }
11296 }
11297 }
11298
11299out:
11300 return ret;
11301}
11302
11303static int wdc_get_drive_reason_id(struct libnvme_transport_handle *hdl, char *drive_reason_id, size_t len)
11304{
11305 const char *reason_id_str = "reason_id";
11306 struct libnvme_passthru_cmd cmd;
11307 struct nvme_id_ctrl ctrl;
11308 char sn[sizeof(ctrl.sn) + 1] = {0};
11309 char mn[sizeof(ctrl.mn) + 1] = {0};
11310 int res_len = 0;
11311 int ret;
11312
11313 memset(drive_reason_id, 0, len);
11314 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
11315 nvme_init_identify_ctrl(&cmd, &ctrl);
11316 ret = libnvme_exec_admin_passthru(hdl, &cmd);
11317 if (ret) {
11318 nvme_show_error(nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
11319 "ERROR: WDC: nvme_identify_ctrl() failed 0x%x",nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
11320 ret)nvme_show_message(1, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x"
, ret)
;
11321 return -1;
11322 }
11323
11324 snprintf(sn, sizeof(sn), "%-.*s",
11325 (int)sizeof(ctrl.sn), ctrl.sn);
11326 snprintf(mn, sizeof(mn), "%-.*s",
11327 (int)sizeof(ctrl.mn), ctrl.mn);
11328 shr_sanitize_name(shr_rtrim(sn));
11329 shr_sanitize_name(shr_rtrim(mn));
11330
11331 res_len = snprintf(drive_reason_id, len,
11332 "%s_%s_%s", sn, mn, reason_id_str);
11333 if (len <= res_len) {
11334 nvme_show_error(nvme_show_message(1, "ERROR: WDC: cannot format serial number due to data of unexpected length\n"
)
11335 "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"
)
;
11336 return -1;
11337 }
11338
11339 return 0;
11340}
11341
11342static int wdc_save_reason_id(struct libnvme_transport_handle *hdl, __u8 *rsn_ident, int size)
11343{
11344 int ret = 0;
11345 char *reason_id_file;
11346 char drive_reason_id[PATH_MAX4096] = {0};
11347 char reason_id_path[PATH_MAX4096] = WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli";
11348 struct stat st = {0};
11349
11350 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11351 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__)
;
11352 return -1;
11353 }
11354
11355 /* make the nvmecli dir in /usr/local if it doesn't already exist */
11356 if (stat(reason_id_path, &st) == -1) {
11357 if (shr_mkdir(reason_id_path, 0700) < 0) {
11358 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 ())))
11359 __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 ())))
;
11360 return -1;
11361 }
11362 }
11363
11364 if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
11365 drive_reason_id, ".bin") < 0)
11366 return -ENOMEM12;
11367
11368 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
)
;
11369
11370 /* save off the error reason identifier to a file in /usr/local/nvmecli */
11371 ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN128);
11372 free(reason_id_file);
11373
11374 return ret;
11375}
11376
11377static int wdc_clear_reason_id(struct libnvme_transport_handle *hdl)
11378{
11379 int ret = -1;
11380 int verify_file;
11381 char *reason_id_file;
11382 char drive_reason_id[PATH_MAX4096] = {0};
11383
11384 if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX4096) == -1) {
11385 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__)
;
11386 return -1;
11387 }
11388
11389 if (asprintf(&reason_id_file, "%s/%s%s", WDC_REASON_ID_PATH_NAME"/usr/local/nvmecli",
11390 drive_reason_id, ".bin") < 0)
11391 return -ENOMEM12;
11392
11393 /* verify the drive reason id file name and path is valid */
11394 verify_file = shr_open_rawdata(reason_id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((reason_id_file), (01 | 0100 | 01000), 0666);
11395 if (verify_file < 0) {
11396 ret = -1;
11397 goto free;
11398 }
11399 close(verify_file);
11400
11401 /* remove the reason id file */
11402 ret = remove(reason_id_file);
11403
11404free:
11405 free(reason_id_file);
11406
11407 return ret;
11408}
11409
11410static int wdc_dump_telemetry_hdr(struct libnvme_transport_handle *hdl, int log_id, struct nvme_telemetry_log *log_hdr)
11411{
11412 int ret = 0;
11413
11414 if (log_id == NVME_LOG_LID_TELEMETRY_HOST) {
11415 struct libnvme_passthru_cmd cmd;
11416
11417 nvme_init_get_log_create_telemetry_host(&cmd, log_hdr);
11418
11419 ret = libnvme_get_log(hdl, &cmd, false0, sizeof(*log_hdr));
11420 } else {
11421 struct libnvme_passthru_cmd cmd;
11422
11423 nvme_init_get_log_telemetry_ctrl(&cmd, 0, (void *)log_hdr, 512);
11424
11425 ret = libnvme_get_log_dynamic_chunk(hdl, &cmd, false0, 512);
11426 }
11427
11428 if (ret < 0) {
11429 nvme_show_err(ret, "get-telemetry-log");
11430 } else if (ret > 0) {
11431 nvme_show_status(ret);
11432 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)
;
11433 }
11434
11435 return ret;
11436}
11437
11438static int wdc_do_get_reason_id(struct libnvme_transport_handle *hdl, const char *file, int log_id)
11439{
11440 int ret;
11441 struct nvme_telemetry_log *log_hdr;
11442 __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
11443 __u32 reason_id_size = 0;
11444
11445 log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size);
11446 if (!log_hdr) {
11447 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
())))
;
11448 ret = -1;
11449 goto out;
11450 }
11451 memset(log_hdr, 0, log_hdr_size);
11452
11453 ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr);
11454 if (ret) {
11455 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)
;
11456 ret = -1;
11457 goto out;
11458 }
11459
11460 reason_id_size = sizeof(log_hdr->rsnident);
11461
11462 if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
11463 wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size);
11464
11465 ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
11466
11467out:
11468 free(log_hdr);
11469 return ret;
11470}
11471
11472static void wdc_print_nand_stats_normal(__u16 version, void *data)
11473{
11474 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11475 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11476 __u64 temp_raw;
11477 __u16 temp_norm;
11478 __u64 *temp_ptr = NULL((void*)0);
11479
11480 switch (version) {
11481 case 0:
11482 printf(" NAND Statistics :-\n");
11483 printf(" NAND Writes TLC (Bytes) %s\n",
11484 uint128_t_to_string(
11485 le128_to_cpu(nand_stats->nand_write_tlc)));
11486 printf(" NAND Writes SLC (Bytes) %s\n",
11487 uint128_t_to_string(
11488 le128_to_cpu(nand_stats->nand_write_slc)));
11489 printf(" NAND Program Failures %"PRIu32"u""\n",
11490 (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure));
11491 printf(" NAND Erase Failures %"PRIu32"u""\n",
11492 (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure));
11493 printf(" Bad Block Count %"PRIu32"u""\n",
11494 (uint32_t)le32_to_cpu(nand_stats->bad_block_count));
11495 printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"l" "u""\n",
11496 le64_to_cpu(nand_stats->nand_rec_trigger_event));
11497 printf(" E2E Error Counter %"PRIu64"l" "u""\n",
11498 le64_to_cpu(nand_stats->e2e_error_counter));
11499 printf(" Number Successful NS Resizing Events %"PRIu64"l" "u""\n",
11500 le64_to_cpu(nand_stats->successful_ns_resize_event));
11501 printf(" log page version %"PRIu16"hu""\n",
11502 le16_to_cpu(nand_stats->log_page_version));
11503 break;
11504 case 3:
11505 printf(" NAND Statistics V3:-\n");
11506 printf(" TLC Units Written %s\n",
11507 uint128_t_to_string(
11508 le128_to_cpu(nand_stats_v3->nand_write_tlc)));
11509 printf(" SLC Units Written %s\n",
11510 uint128_t_to_string(
11511 le128_to_cpu(nand_stats_v3->nand_write_slc)));
11512 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11513 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11514 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11515 printf(" Bad NAND Blocks Count - Normalized %"PRIu16"hu""\n",
11516 le16_to_cpu(temp_norm));
11517 printf(" Bad NAND Blocks Count - Raw %"PRIu64"l" "u""\n",
11518 le64_to_cpu(temp_raw));
11519 printf(" NAND XOR Recovery count %"PRIu64"l" "u""\n",
11520 le64_to_cpu(nand_stats_v3->xor_recovery_count));
11521 printf(" UECC Read Error count %"PRIu64"l" "u""\n",
11522 le64_to_cpu(nand_stats_v3->uecc_read_error_count));
11523 printf(" SSD End to End corrected errors %"PRIu64"l" "u""\n",
11524 le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
11525 printf(" SSD End to End detected errors %"PRIu32"u""\n",
11526 le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
11527 printf(" SSD End to End uncorrected E2E errors %"PRIu32"u""\n",
11528 le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
11529 printf(" System data %% life-used %u\n",
11530 nand_stats_v3->percent_life_used);
11531 printf(" User Data Erase Counts - TLC Min %"PRIu64"l" "u""\n",
11532 le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
11533 printf(" User Data Erase Counts - TLC Max %"PRIu64"l" "u""\n",
11534 le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
11535 printf(" User Data Erase Counts - SLC Min %"PRIu64"l" "u""\n",
11536 le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
11537 printf(" User Data Erase Counts - SLC Max %"PRIu64"l" "u""\n",
11538 le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
11539 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11540 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11541 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11542 printf(" Program Fail Count - Normalized %"PRIu16"hu""\n",
11543 le16_to_cpu(temp_norm));
11544 printf(" Program Fail Count - Raw %"PRIu64"l" "u""\n",
11545 le64_to_cpu(temp_raw));
11546 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11547 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11548 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11549 printf(" Erase Fail Count - Normalized %"PRIu16"hu""\n",
11550 le16_to_cpu(temp_norm));
11551 printf(" Erase Fail Count - Raw %"PRIu64"l" "u""\n",
11552 le64_to_cpu(temp_raw));
11553 printf(" PCIe Correctable Error Count %"PRIu16"hu""\n",
11554 le16_to_cpu(nand_stats_v3->correctable_error_count));
11555 printf(" %% Free Blocks (User) %u\n",
11556 nand_stats_v3->percent_free_blocks_user);
11557 printf(" Security Version Number %"PRIu64"l" "u""\n",
11558 le64_to_cpu(nand_stats_v3->security_version_number));
11559 printf(" %% Free Blocks (System) %u\n",
11560 nand_stats_v3->percent_free_blocks_system);
11561 printf(" Data Set Management Commands %s\n",
11562 uint128_t_to_string(
11563 le128_to_cpu(nand_stats_v3->trim_completions)));
11564 printf(" Estimate of Incomplete Trim Data %"PRIu64"l" "u""\n",
11565 le64_to_cpu(nand_stats_v3->trim_completions[16]));
11566 printf(" %% of completed trim %u\n",
11567 nand_stats_v3->trim_completions[24]);
11568 printf(" Background Back-Pressure-Guage %u\n",
11569 nand_stats_v3->back_pressure_guage);
11570 printf(" Soft ECC Error Count %"PRIu64"l" "u""\n",
11571 le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
11572 printf(" Refresh Count %"PRIu64"l" "u""\n",
11573 le64_to_cpu(nand_stats_v3->refresh_count));
11574 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11575 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11576 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11577 printf(" Bad System Nand Block Count - Normalized %"PRIu16"hu""\n",
11578 le16_to_cpu(temp_norm));
11579 printf(" Bad System Nand Block Count - Raw %"PRIu64"l" "u""\n",
11580 le64_to_cpu(temp_raw));
11581 printf(" Endurance Estimate %s\n",
11582 uint128_t_to_string(
11583 le128_to_cpu(nand_stats_v3->endurance_estimate)));
11584 printf(" Thermal Throttling Count %u\n",
11585 nand_stats_v3->thermal_throttling_st_ct[0]);
11586 printf(" Thermal Throttling Status %u\n",
11587 nand_stats_v3->thermal_throttling_st_ct[1]);
11588 printf(" Unaligned I/O %"PRIu64"l" "u""\n",
11589 le64_to_cpu(nand_stats_v3->unaligned_IO));
11590 printf(" Physical Media Units Read %s\n",
11591 uint128_t_to_string(
11592 le128_to_cpu(nand_stats_v3->physical_media_units)));
11593 printf(" log page version %"PRIu16"hu""\n",
11594 le16_to_cpu(nand_stats_v3->log_page_version));
11595 break;
11596
11597 default:
11598 nvme_show_error("WDC: Nand Stats ERROR: Invalid version")nvme_show_message(1, "WDC: Nand Stats ERROR: Invalid version"
)
;
11599 break;
11600
11601 }
11602}
11603
11604static void wdc_print_nand_stats_json(__u16 version, void *data)
11605{
11606 struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
11607 struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data);
11608 struct json_object *root = json_create_object()json_object_new_object();
11609 __u64 temp_raw;
11610 __u16 temp_norm;
11611 __u64 *temp_ptr = NULL((void*)0);
11612
11613 switch (version) {
11614 case 0:
11615 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)))
11616 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)))
;
11617 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)))
11618 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)))
;
11619 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)))
11620 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)))
;
11621 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)))
11622 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)))
;
11623 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)))
11624 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)))
;
11625 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
)))
11626 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
)))
;
11627 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)))
11628 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)))
;
11629 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
)))
11630 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
)))
;
11631
11632 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11633 printf("\n");
11634 break;
11635 case 3:
11636 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)))
11637 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)))
;
11638 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)))
11639 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)))
;
11640 temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
11641 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11642 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11643 json_object_add_value_uint(root, "Bad NAND Blocks Count - Normalized",json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11644 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad NAND Blocks Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11645 json_object_add_value_uint64(root, "Bad NAND Blocks Count - Raw",json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11646 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad NAND Blocks Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11647 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)))
11648 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)))
;
11649 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)))
11650 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)))
;
11651 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])))
11652 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])))
;
11653 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])))
11654 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])))
;
11655 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])))
11656 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])))
;
11657 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))
11658 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))
;
11659 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])))
11660 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])))
;
11661 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])))
11662 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])))
;
11663 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])))
11664 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])))
;
11665 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])))
11666 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])))
;
11667 temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
11668 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11669 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11670 json_object_add_value_uint(root, "Program Fail Count - Normalized",json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11671 le16_to_cpu(temp_norm))json_object_object_add(root, "Program Fail Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11672 json_object_add_value_uint64(root, "Program Fail Count - Raw",json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11673 le64_to_cpu(temp_raw))json_object_object_add(root, "Program Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11674 temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
11675 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11676 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11677 json_object_add_value_uint(root, "Erase Fail Count - Normalized",json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
11678 le16_to_cpu(temp_norm))json_object_object_add(root, "Erase Fail Count - Normalized",
json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11679 json_object_add_value_uint64(root, "Erase Fail Count - Raw",json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
11680 le64_to_cpu(temp_raw))json_object_object_add(root, "Erase Fail Count - Raw", json_object_new_uint64
(le64_to_cpu(temp_raw)))
;
11681 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)))
11682 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)))
;
11683 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))
11684 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))
;
11685 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)))
11686 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)))
;
11687 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))
11688 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))
;
11689 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)))
11690 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)))
;
11691 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])))
11692 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])))
;
11693 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]))
11694 nand_stats_v3->trim_completions[24])json_object_object_add(root, "%% of completed trim", json_object_new_uint64
(nand_stats_v3->trim_completions[24]))
;
11695 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
))
11696 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
))
;
11697 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)))
11698 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)))
;
11699 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)))
11700 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)))
;
11701 temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
11702 temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
11703 temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
11704 json_object_add_value_uint(root, "Bad System Nand Block Count - Normalized",json_object_object_add(root, "Bad System Nand Block Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
11705 le16_to_cpu(temp_norm))json_object_object_add(root, "Bad System Nand Block Count - Normalized"
, json_object_new_uint64(le16_to_cpu(temp_norm)))
;
11706 json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw",json_object_object_add(root, "Bad System Nand Block Count - Raw"
, json_object_new_uint64(le64_to_cpu(temp_raw)))
11707 le64_to_cpu(temp_raw))json_object_object_add(root, "Bad System Nand Block Count - Raw"
, json_object_new_uint64(le64_to_cpu(temp_raw)))
;
11708 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)))
11709 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)))
;
11710 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]))
11711 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]))
;
11712 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]))
11713 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]))
;
11714 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)))
11715 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)))
;
11716 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)))
11717 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)))
;
11718 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)))
11719 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)))
;
11720
11721 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11722 printf("\n");
11723 break;
11724 default:
11725 nvme_show_error("%s: Invalid Stats Version = %d", __func__, version)nvme_show_message(1, "%s: Invalid Stats Version = %d", __func__
, version)
;
11726 break;
11727 }
11728
11729 json_free_object(root)json_object_put(root);
11730
11731}
11732
11733static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats)
11734{
11735 printf(" PCIE Statistics :-\n");
11736 printf(" Unsupported Request Error Counter %20"PRIu64"l" "u""\n",
11737 le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
11738 printf(" ECRC Error Status Counter %20"PRIu64"l" "u""\n",
11739 le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
11740 printf(" Malformed TLP Status Counter %20"PRIu64"l" "u""\n",
11741 le64_to_cpu(pcie_stats->malformedTlpStatusCount));
11742 printf(" Receiver Overflow Status Counter %20"PRIu64"l" "u""\n",
11743 le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
11744 printf(" Unexpected Completion Status Counter %20"PRIu64"l" "u""\n",
11745 le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
11746 printf(" Complete Abort Status Counter %20"PRIu64"l" "u""\n",
11747 le64_to_cpu(pcie_stats->completeAbortStatusCount));
11748 printf(" Completion Timeout Status Counter %20"PRIu64"l" "u""\n",
11749 le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
11750 printf(" Flow Control Error Status Counter %20"PRIu64"l" "u""\n",
11751 le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
11752 printf(" Poisoned TLP Status Counter %20"PRIu64"l" "u""\n",
11753 le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
11754 printf(" Dlink Protocol Error Status Counter %20"PRIu64"l" "u""\n",
11755 le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
11756 printf(" Advisory Non Fatal Error Status Counter %20"PRIu64"l" "u""\n",
11757 le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
11758 printf(" Replay Timer TO Status Counter %20"PRIu64"l" "u""\n",
11759 le64_to_cpu(pcie_stats->replayTimerToStatusCount));
11760 printf(" Replay Number Rollover Status Counter %20"PRIu64"l" "u""\n",
11761 le64_to_cpu(pcie_stats->replayNumRolloverStCount));
11762 printf(" Bad DLLP Status Counter %20"PRIu64"l" "u""\n",
11763 le64_to_cpu(pcie_stats->badDllpStatusCount));
11764 printf(" Bad TLP Status Counter %20"PRIu64"l" "u""\n",
11765 le64_to_cpu(pcie_stats->badTlpStatusCount));
11766 printf(" Receiver Error Status Counter %20"PRIu64"l" "u""\n",
11767 le64_to_cpu(pcie_stats->receiverErrStatusCount));
11768
11769}
11770
11771static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
11772{
11773 struct json_object *root = json_create_object()json_object_new_object();
11774
11775 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
)))
11776 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
)))
;
11777 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)))
11778 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)))
;
11779 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)))
11780 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)))
;
11781
11782 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
)))
11783 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
)))
;
11784 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
)))
11785 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
)))
;
11786 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
)))
11787 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
)))
;
11788 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
)))
11789 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
)))
;
11790 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
)))
11791 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
)))
;
11792 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)))
11793 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)))
;
11794 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
)))
11795 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
)))
;
11796 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
)))
11797 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
)))
;
11798 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
)))
11799 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
)))
;
11800 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
)))
11801 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
)))
;
11802 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)))
11803 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)))
;
11804 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)))
11805 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)))
;
11806 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
)))
11807 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
)))
;
11808
11809 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
11810 printf("\n");
11811
11812 json_free_object(root)json_object_put(root);
11813}
11814
11815static int wdc_do_vs_nand_stats_sn810_2(struct libnvme_transport_handle *hdl, char *format)
11816{
11817 nvme_print_flags_t fmt;
11818 uint8_t *data = NULL((void*)0);
11819 int ret;
11820
11821 data = NULL((void*)0);
11822 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
11823 NVME_NSID_ALL);
11824
11825 if (ret) {
11826 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__)
;
11827 goto out;
11828 } else {
11829 ret = validate_output_format(format, &fmt);
11830 if (ret < 0) {
11831 nvme_show_error("ERROR: WDC: %s : invalid output format", __func__)nvme_show_message(1, "ERROR: WDC: %s : invalid output format"
, __func__)
;
11832 goto out;
11833 }
11834
11835 /* parse the data */
11836 switch (fmt) {
11837 case NORMAL:
11838 wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS0x1);
11839 break;
11840 case JSON:
11841 wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS0x1);
11842 break;
11843 default:
11844 break;
11845 }
11846 }
11847
11848out:
11849 free(data);
11850 return ret;
11851}
11852
11853static int wdc_do_vs_nand_stats(struct libnvme_transport_handle *hdl, char *format)
11854{
11855 nvme_print_flags_t fmt;
11856 uint8_t *output = NULL((void*)0);
11857 __u16 version = 0;
11858 int ret;
11859
11860 output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE0x200, sizeof(uint8_t));
11861 if (!output) {
11862 nvme_show_error("ERROR: WDC: calloc: %s", libnvme_strerror(errno))nvme_show_message(1, "ERROR: WDC: calloc: %s", libnvme_strerror
((*__errno_location ())))
;
11863 ret = -1;
11864 goto out;
11865 }
11866
11867 ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID0xFB,
11868 (void *)output, WDC_NVME_NAND_STATS_SIZE0x200);
11869 if (ret) {
11870 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__)
;
11871 goto out;
11872 } else {
11873 ret = validate_output_format(format, &fmt);
11874 if (ret < 0) {
11875 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
11876 goto out;
11877 }
11878
11879 version = output[WDC_NVME_NAND_STATS_SIZE0x200 - 2];
11880
11881 /* parse the data */
11882 switch (fmt) {
11883 case NORMAL:
11884 wdc_print_nand_stats_normal(version, output);
11885 break;
11886 case JSON:
11887 wdc_print_nand_stats_json(version, output);
11888 break;
11889 default:
11890 break;
11891 }
11892 }
11893
11894out:
11895 free(output);
11896 return ret;
11897}
11898
11899static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd,
11900 struct plugin *plugin)
11901{
11902 const char *desc = "Retrieve NAND statistics.";
11903 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11904 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11905 __u64 capabilities = 0;
11906 uint32_t read_device_id = 0, read_vendor_id = 0;
11907 int ret;
11908
11909 struct config {
11910 char *output_format;
11911 };
11912
11913 struct config cfg = {
11914 .output_format = "normal",
11915 };
11916
11917 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
11918 OPT_END(){ ((void*)0) }
11919 };
11920
11921 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
11922 if (ret)
11923 return ret;
11924
11925 cfg.output_format = nvme_args.output_format;
11926
11927 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
11928 if (ret)
11929 return ret;
11930
11931 capabilities = wdc_get_drive_capabilities(ctx, hdl);
11932
11933 if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200)) {
11934 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
11935 ret = -1;
11936 } else {
11937 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
11938 if (ret < 0) {
11939 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)
;
11940 return -1;
11941 }
11942
11943 switch (read_device_id) {
11944 case WDC_NVME_SN820CL_DEV_ID0x5037:
11945 ret = wdc_do_vs_nand_stats_sn810_2(hdl,
11946 cfg.output_format);
11947 break;
11948 default:
11949 ret = wdc_do_vs_nand_stats(hdl, cfg.output_format);
11950 break;
11951 }
11952 }
11953
11954 if (ret)
11955 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)
;
11956
11957 return ret;
11958}
11959
11960static int wdc_do_vs_pcie_stats(struct libnvme_transport_handle *hdl,
11961 struct wdc_vs_pcie_stats *pcieStatsPtr)
11962{
11963 int ret;
11964 struct libnvme_passthru_cmd admin_cmd;
11965 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11966
11967 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
11968 admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE0xD1;
11969 admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
11970 admin_cmd.data_len = pcie_stats_size;
11971
11972 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
11973
11974 return ret;
11975}
11976
11977static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd,
11978 struct plugin *plugin)
11979{
11980 const char *desc = "Retrieve PCIE statistics.";
11981 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
11982 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
11983 nvme_print_flags_t fmt;
11984 int ret;
11985 __u64 capabilities = 0;
11986 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
11987 struct wdc_vs_pcie_stats *pcieStatsPtr = NULL((void*)0);
11988 int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
11989
11990 struct config {
11991 char *output_format;
11992 };
11993
11994 struct config cfg = {
11995 .output_format = "normal",
11996 };
11997
11998 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
11999 OPT_END(){ ((void*)0) }
12000 };
12001
12002 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12003 if (ret)
12004 return ret;
12005
12006 cfg.output_format = nvme_args.output_format;
12007
12008 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12009 if (ret)
12010 return ret;
12011
12012 ret = validate_output_format(cfg.output_format, &fmt);
12013 if (ret < 0) {
12014 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12015 goto out;
12016 }
12017
12018 pcieStatsPtr = libnvme_alloc_huge(pcie_stats_size, &mh);
12019 if (!pcieStatsPtr) {
12020 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 ())))
;
12021 ret = -1;
12022 goto out;
12023 }
12024
12025 memset((void *)pcieStatsPtr, 0, pcie_stats_size);
12026
12027 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12028
12029 if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000)) {
12030 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12031 ret = -1;
12032 } else {
12033 ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr);
12034 if (ret) {
12035 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)
;
12036 } else {
12037 /* parse the data */
12038 switch (fmt) {
12039 case NORMAL:
12040 wdc_print_pcie_stats_normal(pcieStatsPtr);
12041 break;
12042 case JSON:
12043 wdc_print_pcie_stats_json(pcieStatsPtr);
12044 break;
12045 default:
12046 break;
12047 }
12048 }
12049 }
12050out:
12051 return ret;
12052}
12053
12054static int wdc_vs_drive_info(int argc, char **argv,
12055 struct command *command, struct plugin *plugin)
12056{
12057 const char *desc = "Send a vs-drive-info command.";
12058 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12059 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12060 nvme_print_flags_t fmt;
12061 uint64_t capabilities = 0;
12062 int ret;
12063 __le32 result;
12064 __u16 size;
12065 double rev;
12066 struct libnvme_passthru_cmd cmd;
12067 struct nvme_id_ctrl ctrl;
12068 char vsData[32] = {0};
12069 char major_rev = 0, minor_rev = 0;
12070 __u8 *data = NULL((void*)0);
12071 __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
12072 __u16 boot_spec_major = 0, boot_spec_minor = 0;
12073 struct json_object *root = NULL((void*)0);
12074 char formatter[41] = { 0 };
12075 char rev_str[16] = { 0 };
12076 uint32_t read_device_id = -1, read_vendor_id = -1;
12077 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12078 struct ocp_drive_info info;
12079 __u32 data_len = 0;
12080 unsigned int num_dwords = 0;
12081
12082 struct config {
12083 char *output_format;
12084 };
12085
12086 struct config cfg = {
12087 .output_format = "normal",
12088 };
12089
12090 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12091 OPT_END(){ ((void*)0) }
12092 };
12093
12094 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12095 if (ret)
12096 return ret;
12097
12098 cfg.output_format = nvme_args.output_format;
12099
12100 ret = validate_output_format(cfg.output_format, &fmt);
12101 if (ret < 0) {
12102 nvme_show_error("ERROR: WDC %s invalid output format", __func__)nvme_show_message(1, "ERROR: WDC %s invalid output format", __func__
)
;
12103 return ret;
12104 }
12105
12106 /* get the id ctrl data used to fill in drive info below */
12107 nvme_init_identify_ctrl(&cmd, &ctrl);
12108 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12109 if (ret) {
12110 nvme_show_error("ERROR: WDC %s: Identify Controller failed", __func__)nvme_show_message(1, "ERROR: WDC %s: Identify Controller failed"
, __func__)
;
12111 return ret;
12112 }
12113
12114 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12115 if (ret || !wdc_check_device(ctx, hdl))
12116 return -1;
12117
12118 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12119
12120 if ((capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000) == WDC_DRIVE_CAP_INFO0x0000000000080000) {
12121 ret = nvme_get_pci_ids(ctx, hdl, &read_vendor_id, &read_device_id, NULL((void*)0), NULL((void*)0), NULL((void*)0));
12122 if (ret < 0) {
12123 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)
;
12124 goto out;
12125 }
12126
12127 switch (read_device_id) {
12128 case WDC_NVME_SN640_DEV_ID0x2400:
12129 case WDC_NVME_SN640_DEV_ID_10x2401:
12130 case WDC_NVME_SN640_DEV_ID_20x2402:
12131 case WDC_NVME_SN640_DEV_ID_30x2404:
12132 case WDC_NVME_SN650_DEV_ID0x2700:
12133 case WDC_NVME_SN650_DEV_ID_10x2701:
12134 case WDC_NVME_SN650_DEV_ID_20x2702:
12135 case WDC_NVME_SN650_DEV_ID_30x2720:
12136 case WDC_NVME_SN650_DEV_ID_40x2721:
12137 case WDC_NVME_SN655_DEV_ID0x2722:
12138 case WDC_NVME_SN655_DEV_ID_10x2723:
12139 case WDC_NVME_SN560_DEV_ID_10x2712:
12140 case WDC_NVME_SN560_DEV_ID_20x2713:
12141 case WDC_NVME_SN560_DEV_ID_30x2714:
12142 case WDC_NVME_SN550_DEV_ID0x2708:
12143 case WDC_NVME_ZN350_DEV_ID0x5010:
12144 case WDC_NVME_ZN350_DEV_ID_10x5018:
12145 ret = wdc_do_drive_info(hdl, &result);
12146
12147 if (!ret) {
12148 size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
12149 rev = (double)(cpu_to_le32(result) & 0x0000ffff);
12150
12151 if (fmt == NORMAL) {
12152 printf("Drive HW Revision: %4.1f\n", (.1 * rev));
12153 printf("FTL Unit Size: 0x%x KB\n", size);
12154 printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
12155 } else if (fmt == JSON) {
12156 root = json_create_object()json_object_new_object();
12157 snprintf(rev_str, sizeof(rev_str),
12158 "%4.1f", (.1 * rev));
12159 json_object_add_value_string(root, "Drive HW Revision", rev_str);
12160
12161 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)))
;
12162 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
12163 json_object_add_value_string(root, "Customer SN", formatter);
12164
12165 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12166 printf("\n");
12167
12168 json_free_object(root)json_object_put(root);
12169 }
12170 }
12171 break;
12172 case WDC_NVME_SN730_DEV_ID0x5006:
12173 memcpy(vsData, &ctrl.vs[0], 32);
12174
12175 major_rev = ctrl.sn[12];
12176 minor_rev = ctrl.sn[13];
12177
12178 if (fmt == NORMAL) {
12179 printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev);
12180 printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
12181 } else if (fmt == JSON) {
12182 root = json_create_object()json_object_new_object();
12183 snprintf(rev_str, sizeof(rev_str), "%c.%c",
12184 major_rev, minor_rev);
12185 json_object_add_value_string(root, "Drive HW Revison", rev_str);
12186 wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
12187 json_object_add_value_string(root, "Customer SN", formatter);
12188
12189 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12190 printf("\n");
12191
12192 json_free_object(root)json_object_put(root);
12193 }
12194 break;
12195 case WDC_NVME_SN820CL_DEV_ID0x5037:
12196 /* Get the Drive HW Rev from the C6 Log page */
12197 ret = nvme_get_hw_rev_log(hdl, &data, 0,
12198 NVME_NSID_ALL);
12199 if (!ret) {
12200 struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data;
12201
12202 major_rev = log_data->hw_rev_gdr;
12203
12204 free(data);
12205 data = NULL((void*)0);
12206 } else {
12207 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__)
;
12208 ret = -1;
12209 goto out;
12210 }
12211
12212 /* Get the Smart C0 log page */
12213 if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000)) {
12214 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12215 ret = -1;
12216 goto out;
12217 }
12218
12219 ret = nvme_get_ext_smart_cloud_log(hdl, &data,
12220 0, NVME_NSID_ALL);
12221
12222 if (!ret) {
12223 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12224
12225 /* Set the FTL Unit size */
12226 ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
12227
12228 /* Set the Boot Spec Version */
12229 boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12230 boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12231
12232 /* Set the Drive Ownership Status */
12233 tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
12234 free(data);
12235 } else {
12236 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__)
;
12237 ret = -1;
12238 goto out;
12239 }
12240
12241 if (fmt == NORMAL) {
12242 printf("Drive HW Revision: %2d\n", major_rev);
12243 printf("FTL Unit Size: %d\n", ftl_unit_size);
12244 printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
12245 printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
12246
12247 } else if (fmt == JSON) {
12248 root = json_create_object()json_object_new_object();
12249
12250 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))
;
12251 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))
;
12252 snprintf(rev_str, sizeof(rev_str), "%d.%d",
12253 boot_spec_major, boot_spec_minor);
12254 json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
12255 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))
;
12256
12257 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12258 printf("\n");
12259
12260 json_free_object(root)json_object_put(root);
12261 }
12262
12263 break;
12264 case WDC_NVME_SN861_DEV_ID0x2750:
12265 case WDC_NVME_SN861_DEV_ID_10x2751:
12266 case WDC_NVME_SN861_DEV_ID_20x2752:
12267 data_len = sizeof(info);
12268 num_dwords = data_len / 4;
12269 if (data_len % 4 != 0)
12270 num_dwords += 1;
12271
12272 struct libnvme_passthru_cmd cmd = {
12273 .opcode = WDC_NVME_ADMIN_VUC_OPCODE_D2,
12274 .cdw10 = num_dwords,
12275 .cdw12 = WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2,
12276 .addr = (__u64)(uintptr_t)&info,
12277 .data_len = data_len,
12278 };
12279 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12280 if (!ret) {
12281 __u16 hw_rev_major, hw_rev_minor;
12282
12283 hw_rev_major = le32_to_cpu(info.hw_revision) / 10;
12284 hw_rev_minor = le32_to_cpu(info.hw_revision) % 10;
12285 if (fmt == NORMAL) {
12286 printf("HW Revision : %" PRIu32"u" ".%" PRIu32"u" "\n",
12287 hw_rev_major, hw_rev_minor);
12288 printf("FTL Unit Size : %" PRIu32"u" "\n",
12289 le32_to_cpu(info.ftl_unit_size));
12290 } else if (fmt == JSON) {
12291 char buf[20];
12292
12293 root = json_create_object()json_object_new_object();
12294
12295 memset((void *)buf, 0, 20);
12296 snprintf(buf, sizeof(buf),
12297 "%" PRIu32"u" ".%" PRIu32"u",
12298 hw_rev_major, hw_rev_minor);
12299
12300 json_object_add_value_string(root,
12301 "hw_revision", buf);
12302 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)))
12303 "ftl_unit_size",json_object_object_add(root, "ftl_unit_size", json_object_new_uint64
(le32_to_cpu(info.ftl_unit_size)))
12304 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)))
;
12305
12306 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12307 printf("\n");
12308 json_free_object(root)json_object_put(root);
12309 }
12310 }
12311 break;
12312 default:
12313 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12314 ret = -1;
12315 break;
12316 }
12317 } else {
12318 nvme_show_error("ERROR: WDC: capability not supported by this device")nvme_show_message(1, "ERROR: WDC: capability not supported by this device"
)
;
12319 ret = -1;
12320 }
12321
12322out:
12323 nvme_show_status(ret);
12324 return ret;
12325}
12326
12327static int wdc_vs_temperature_stats(int argc, char **argv,
12328 struct command *command, struct plugin *plugin)
12329{
12330 const char *desc = "Send a vs-temperature-stats command.";
12331 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12332 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12333 struct libnvme_passthru_cmd cmd;
12334 struct nvme_smart_log smart_log;
12335 struct nvme_id_ctrl id_ctrl;
12336 nvme_print_flags_t fmt;
12337 uint64_t capabilities = 0;
12338 __u64 hctm_tmt;
12339 int temperature, temp_tmt1, temp_tmt2;
12340 int ret;
12341
12342 struct config {
12343 char *output_format;
12344 };
12345
12346 struct config cfg = {
12347 .output_format = "normal",
12348 };
12349
12350 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12351 OPT_END(){ ((void*)0) }
12352 };
12353
12354 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12355 if (ret)
12356 return ret;
12357
12358 cfg.output_format = nvme_args.output_format;
12359
12360 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12361 if (ret)
12362 return ret;
12363
12364 ret = validate_output_format(cfg.output_format, &fmt);
12365 if (ret < 0) {
12366 nvme_show_error("ERROR: WDC: invalid output format")nvme_show_message(1, "ERROR: WDC: invalid output format");
12367 goto out;
12368 }
12369
12370 /* check if command is supported */
12371 wdc_check_device(ctx, hdl);
12372 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12373 if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) != WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000) {
12374 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12375 ret = -1;
12376 goto out;
12377 }
12378
12379 /* get the temperature stats or report errors */
12380 nvme_init_identify_ctrl(&cmd, &id_ctrl);
12381 ret = libnvme_exec_admin_passthru(hdl, &cmd);
12382 if (ret)
12383 goto out;
12384 ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
12385 if (ret)
12386 goto out;
12387
12388 /* convert from kelvins to degrees Celsius */
12389 temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
12390
12391 /* retrieve HCTM Thermal Management Temperatures */
12392 nvme_init_get_features(&cmd, 0x10, NVME_GET_FEATURES_SEL_CURRENT);
12393 libnvme_exec_admin_passthru(hdl, &cmd);
12394 hctm_tmt = cmd.result;
12395 temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
12396 temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
12397
12398 if (fmt == NORMAL) {
12399 /* print the temperature stats */
12400 printf("Temperature Stats for NVME device:%s namespace-id:%x\n",
12401 libnvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID0xFFFFFFFF);
12402
12403 printf("Current Composite Temperature : %d °C\n", temperature);
12404 printf("WCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.wctemp - 273);
12405 printf("CCTEMP : %"PRIu16"hu"" °C\n", id_ctrl.cctemp - 273);
12406 printf("DITT support : 0\n");
12407 printf("HCTM support : %"PRIu16"hu""\n", id_ctrl.hctma);
12408
12409 printf("HCTM Light (TMT1) : %"PRIu16"hu"" °C\n", temp_tmt1);
12410 printf("TMT1 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp1_trans_count);
12411 printf("TMT1 Total Time : %"PRIu32"u""\n", smart_log.thm_temp1_total_time);
12412
12413 printf("HCTM Heavy (TMT2) : %"PRIu16"hu"" °C\n", temp_tmt2);
12414 printf("TMT2 Transition Counter : %"PRIu32"u""\n", smart_log.thm_temp2_trans_count);
12415 printf("TMT2 Total Time : %"PRIu32"u""\n", smart_log.thm_temp2_total_time);
12416 printf("Thermal Shutdown Threshold : 95 °C\n");
12417 } else if (fmt == JSON) {
12418 struct json_object *root;
12419
12420 root = json_create_object()json_object_new_object();
12421
12422 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)))
;
12423 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)))
;
12424 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)))
;
12425 json_object_add_value_int(root, "DITT support", 0)json_object_object_add(root, "DITT support", json_object_new_int
(0))
;
12426 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)))
;
12427
12428 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)))
;
12429 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)))
;
12430 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)))
;
12431
12432 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)))
;
12433 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)))
;
12434 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)))
;
12435 json_object_add_value_int(root, "Thermal Shutdown Threshold", 95)json_object_object_add(root, "Thermal Shutdown Threshold", json_object_new_int
(95))
;
12436
12437 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
12438 printf("\n");
12439
12440 json_free_object(root)json_object_put(root);
12441 } else {
12442 nvme_show_error("%s: Invalid format", __func__)nvme_show_message(1, "%s: Invalid format", __func__);
12443 }
12444
12445out:
12446 nvme_show_status(ret);
12447 return ret;
12448}
12449
12450static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12451{
12452 const char *desc = "Send a capabilities command.";
12453 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12454 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12455 uint64_t capabilities = 0;
12456 int ret;
12457
12458 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12459 OPT_END(){ ((void*)0) }
12460 };
12461
12462 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12463 if (ret)
12464 return ret;
12465
12466 /* get capabilities */
12467 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12468 if (ret || !wdc_check_device(ctx, hdl))
12469 return -1;
12470
12471 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12472
12473 /* print command and supported status */
12474 printf("WDC Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
12475 printf("cap-diag : %s\n",
12476 capabilities & WDC_DRIVE_CAP_CAP_DIAG0x0000000000000001 ? "Supported" : "Not Supported");
12477 printf("drive-log : %s\n",
12478 capabilities & WDC_DRIVE_CAP_DRIVE_LOG0x0000000000000400 ? "Supported" : "Not Supported");
12479 printf("get-crash-dump : %s\n",
12480 capabilities & WDC_DRIVE_CAP_CRASH_DUMP0x0000000000000800 ? "Supported" : "Not Supported");
12481 printf("get-pfail-dump : %s\n",
12482 capabilities & WDC_DRIVE_CAP_PFAIL_DUMP0x0000000000001000 ? "Supported" : "Not Supported");
12483 printf("id-ctrl : Supported\n");
12484 printf("purge : %s\n",
12485 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12486 printf("purge-monitor : %s\n",
12487 capabilities & WDC_DRIVE_CAP_PURGE0x0000001000000000 ? "Supported" : "Not Supported");
12488 printf("vs-internal-log : %s\n",
12489 capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000000200000000
| 0x0000000400000000)
? "Supported" : "Not Supported");
12490 printf("vs-nand-stats : %s\n",
12491 capabilities & WDC_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
12492 printf("vs-smart-add-log : %s\n",
12493 capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
12494 printf("--C0 Log Page : %s\n",
12495 capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
12496 printf("--C1 Log Page : %s\n",
12497 capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
12498 printf("--C3 Log Page : %s\n",
12499 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12500 printf("--CA Log Page : %s\n",
12501 capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
12502 printf("--D0 Log Page : %s\n",
12503 capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
12504 printf("clear-pcie-correctable-errors : %s\n",
12505 capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
12506 printf("drive-essentials : %s\n",
12507 capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS0x0000000100000000 ? "Supported" : "Not Supported");
12508 printf("get-drive-status : %s\n",
12509 capabilities & WDC_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
12510 printf("clear-assert-dump : %s\n",
12511 capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
12512 printf("drive-resize : %s\n",
12513 capabilities & WDC_DRIVE_CAP_RESIZE0x0000000000000100 ? "Supported" : "Not Supported");
12514 printf("vs-fw-activate-history : %s\n",
12515 capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" : "Not Supported");
12516 printf("clear-fw-activate-history : %s\n",
12517 capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" : "Not Supported");
12518 printf("vs-telemetry-controller-option: %s\n",
12519 capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
12520 printf("vs-error-reason-identifier : %s\n",
12521 capabilities & WDC_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
12522 printf("log-page-directory : %s\n",
12523 capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
12524 printf("namespace-resize : %s\n",
12525 capabilities & WDC_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
12526 printf("vs-drive-info : %s\n",
12527 capabilities & WDC_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
12528 printf("vs-temperature-stats : %s\n",
12529 capabilities & WDC_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
12530 printf("cloud-SSD-plugin-version : %s\n",
12531 capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
12532 printf("vs-pcie-stats : %s\n",
12533 capabilities & WDC_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
12534 printf("get-error-recovery-log : %s\n",
12535 capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
12536 printf("get-dev-capabilities-log : %s\n",
12537 capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
12538 printf("get-unsupported-reqs-log : %s\n",
12539 capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
12540 printf("get-latency-monitor-log : %s\n",
12541 capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
12542 printf("cloud-boot-SSD-version : %s\n",
12543 capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" : "Not Supported");
12544 printf("vs-cloud-log : %s\n",
12545 capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
12546 printf("vs-hw-rev-log : %s\n",
12547 capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
12548 printf("vs-device_waf : %s\n",
12549 capabilities & WDC_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
12550 printf("set-latency-monitor-feature : %s\n",
12551 capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
12552 printf("capabilities : Supported\n");
12553 return 0;
12554}
12555
12556static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd,
12557 struct plugin *plugin)
12558{
12559 const char *desc = "Get Cloud SSD Plugin Version command.";
12560 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12561 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12562 uint64_t capabilities = 0;
12563 int ret;
12564
12565 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12566 OPT_END(){ ((void*)0) }
12567 };
12568
12569 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12570 if (ret)
12571 return ret;
12572
12573 /* get capabilities */
12574 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12575 if (ret || !wdc_check_device(ctx, hdl))
12576 return -1;
12577
12578 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12579
12580 if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000) {
12581 /* print command and supported status */
12582 printf("WDC Cloud SSD Plugin Version: 1.0\n");
12583 } else {
12584 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12585 }
12586
12587 return 0;
12588}
12589
12590static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd,
12591 struct plugin *plugin)
12592{
12593 const char *desc = "Get Cloud Boot SSD Version command.";
12594 const char *namespace_id = "desired namespace id";
12595 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12596 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12597 uint64_t capabilities = 0;
12598 int ret;
12599 int major = 0, minor = 0;
12600 __u8 *data = NULL((void*)0);
12601 struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL((void*)0);
12602
12603 struct config {
12604 __u32 namespace_id;
12605 };
12606
12607 struct config cfg = {
12608 .namespace_id = NVME_NSID_ALL,
12609 };
12610
12611 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12612 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}
12613 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}
,
12614 OPT_END(){ ((void*)0) }
12615 };
12616
12617 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12618 if (ret)
12619 return ret;
12620
12621 /* get capabilities */
12622 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
12623 if (ret || !wdc_check_device(ctx, hdl))
12624 return -1;
12625
12626 capabilities = wdc_get_drive_capabilities(ctx, hdl);
12627
12628 if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000) {
12629 /* Get the 0xC0 Smart Cloud Attribute V1 log data */
12630 ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0,
12631 cfg.namespace_id);
12632
12633 ext_smart_log_ptr = (struct __packed__attribute__((__packed__)) wdc_nvme_ext_smart_log *)data;
12634 if (!ret) {
12635 major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
12636 minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
12637
12638 /* print the version returned from the log page */
12639 printf("HyperScale Boot Version: %d.%d\n", major, minor);
12640 } else {
12641 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"
)
;
12642 ret = -1;
12643 }
12644
12645 free(data);
12646 } else {
12647 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
12648 }
12649
12650 return ret;
12651}
12652
12653static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
12654{
12655 const char *desc = "Get Enclosure Log.";
12656 const char *file = "Output file pathname.";
12657 const char *size = "Data retrieval transfer size.";
12658 const char *log = "Enclosure Log Page ID.";
12659 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12660 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12661 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *output_file = NULL((void*)0);
12662 FILE *output_fd;
12663 int xfer_size = 0;
12664 int len;
12665 int err = 0;
12666
12667 struct config {
12668 char *file;
12669 __u32 xfer_size;
12670 __u32 log_id;
12671 };
12672
12673 struct config cfg = {
12674 .file = NULL((void*)0),
12675 .xfer_size = 0,
12676 .log_id = 0xffffffff,
12677 };
12678
12679 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12680 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, }
,
12681 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, }
,
12682 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, }
,
12683 OPT_END(){ ((void*)0) }
12684 };
12685
12686 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
12687 if (err)
12688 return err;
12689
12690 if (!wdc_enc_check_model(hdl))
12691 return -EINVAL22;
12692
12693 if (cfg.log_id > 0xff) {
12694 nvme_show_error(nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
12695 "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)
12696 cfg.log_id)nvme_show_message(1, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n"
, cfg.log_id)
;
12697 return -EINVAL22;
12698 }
12699
12700 if (cfg.xfer_size) {
12701 xfer_size = cfg.xfer_size;
12702 if (!wdc_check_power_of_2(cfg.xfer_size)) {
12703 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)
12704 __func__, cfg.xfer_size)nvme_show_message(1, "%s: ERROR: xfer-size (%d) must be a power of 2"
, __func__, cfg.xfer_size)
;
12705 return -EINVAL22;
12706 }
12707 }
12708
12709 /* Log IDs are only for specific enclosures */
12710 if (cfg.log_id) {
12711 xfer_size = (xfer_size) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK0x1000;
12712 len = !cfg.file ? 0 : strlen(cfg.file);
12713 if (len > 0) {
12714 output_file = fopen(cfg.file, "wb");
12715 if (!output_file) {
12716 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 ())))
12717 libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: opening:%s: %s", __func__, cfg
.file, libnvme_strerror((*__errno_location ())))
;
12718 return -EINVAL22;
12719 }
12720 output_fd = output_file;
12721 } else {
12722 output_fd = stdoutstdout;
12723 }
12724 if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_10xD1 ||
12725 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_20xD2 ||
12726 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_30xD3 ||
12727 cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_40xD4) {
12728 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)
12729 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12730 err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size,
12731 WDC_NVME_ENC_NIC_LOG_SIZE0x400000, output_fd);
12732 } else {
12733 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)
12734 cfg.file)nvme_show_message(1, "args - sz:%x logid:%x of:%s", xfer_size
, cfg.log_id, cfg.file)
;
12735 err = wdc_enc_submit_move_data(hdl, NULL((void*)0), 0, xfer_size, output_fd,
12736 cfg.log_id, 0, 0);
12737 }
12738
12739 if (err == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12740 nvme_show_error("No Log/Crashdump available")nvme_show_message(1, "No Log/Crashdump available");
12741 err = 0;
12742 } else if (err) {
12743 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)
12744 cfg.log_id)nvme_show_message(1, "ERROR: 0x%x Failed to collect log-id:%x"
, err, cfg.log_id)
;
12745 }
12746 }
12747 return err;
12748}
12749
12750static int wdc_enc_submit_move_data(struct libnvme_transport_handle *hdl, char *cmd, int len,
12751 int xfer_size, FILE *out, int log_id,
12752 int cdw14, int cdw15)
12753{
12754 uint32_t response_size, more;
12755 int err;
12756 int handle;
12757 uint32_t offset = 0;
12758 char *buf;
12759
12760 buf = malloc(xfer_size);
12761 if (!buf) {
12762 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12763 return -1;
12764 }
12765 /* send something no matter what */
12766 cmd = (len) ? cmd : buf;
12767 len = (len) ? len : 0x20;
12768
12769 struct libnvme_passthru_cmd nvme_cmd = {
12770 .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND0xC9,
12771 .nsid = 0,
12772 .addr = (__u64)(uintptr_t) cmd,
12773 .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t),
12774 .cdw10 = len,
12775 .cdw12 = log_id,
12776 .cdw13 = 0,
12777 .cdw14 = cdw14,
12778 .cdw15 = cdw15,
12779 };
12780
12781 /* Handle to associate send request with receive request */
12782 if (shr_getrandom(&handle, sizeof(handle)) != 0) {
12783 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__)
;
12784 free(buf);
12785 return -1;
12786 }
12787 nvme_cmd.cdw11 = handle;
12788
12789#ifdef WDC_NVME_CLI_DEBUG
12790 unsigned char *d = (unsigned char *)nvme_cmd.addr;
12791 unsigned char *md = (unsigned char *)nvme_cmd.metadata;
12792
12793 printf("NVME_ADMIN_COMMAND:\n");
12794 printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ",
12795 nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2);
12796 printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, "
12797 nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10);
12798 printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, "
12799 nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15);
12800 printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n",
12801 nvme_cmd.timeout_ms, nvme_cmd.result, md, d);
12802#endif
12803 nvme_cmd.result = 0;
12804 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12805 if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) {
12806 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)
;
12807 } else if (err) {
12808 nvme_show_error("%s: ERROR: WDC: NVMe Snd Mgmt", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Snd Mgmt", __func__
)
;
12809 nvme_show_status(err);
12810 } else {
12811 if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF) {
12812 free(buf);
12813 return WDC_RESULT_NOT_AVAILABLE0x7FFFFFFF;
12814 }
12815
12816 do {
12817 /* Sent request, now go retrieve response */
12818 nvme_cmd.flags = 0;
12819 nvme_cmd.opcode = WDC_NVME_ADMIN_ENC_MGMT_RCV0xCA;
12820 nvme_cmd.addr = (__u64)(uintptr_t) buf;
12821 nvme_cmd.data_len = xfer_size;
12822 nvme_cmd.cdw10 = xfer_size / sizeof(uint32_t);
12823 nvme_cmd.cdw11 = handle;
12824 nvme_cmd.cdw12 = log_id;
12825 nvme_cmd.cdw13 = offset / sizeof(uint32_t);
12826 nvme_cmd.cdw14 = cdw14;
12827 nvme_cmd.cdw15 = cdw15;
12828 nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
12829 err = libnvme_exec_admin_passthru(hdl, &nvme_cmd);
12830 if (err) {
12831 more = 0;
12832 nvme_show_error("%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__
)
;
12833 nvme_show_status(err);
12834 } else {
12835 more = nvme_cmd.result & WDC_RESULT_MORE_DATA0x80000000;
12836 response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA0x80000000;
12837 fwrite(buf, response_size, 1, out);
12838 offset += response_size;
12839 if (more && (response_size & (sizeof(uint32_t)-1))) {
12840 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)
12841 __func__, response_size)nvme_show_message(1, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned"
, __func__, response_size)
;
12842 }
12843 }
12844 } while (more);
12845 }
12846
12847 free(buf);
12848 return err;
12849}
12850
12851static int wdc_enc_get_nic_log(struct libnvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out)
12852{
12853 __u8 *dump_data;
12854 __u32 curr_data_offset, curr_data_len;
12855 int i, ret = -1;
12856 struct libnvme_passthru_cmd admin_cmd;
12857 __u32 dump_length = data_len;
12858 __u32 numd;
12859 __u16 numdu, numdl;
12860
12861 dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length);
12862 if (!dump_data) {
12863 nvme_show_error("%s: ERROR: malloc: %s", __func__, libnvme_strerror(errno))nvme_show_message(1, "%s: ERROR: malloc: %s", __func__, libnvme_strerror
((*__errno_location ())))
;
12864 return -1;
12865 }
12866 memset(dump_data, 0, sizeof(__u8) * dump_length);
12867 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
12868 curr_data_offset = 0;
12869 curr_data_len = xfer_size;
12870 i = 0;
12871
12872 numd = (curr_data_len >> 2) - 1;
12873 numdu = numd >> 16;
12874 numdl = numd & 0xffff;
12875 admin_cmd.opcode = nvme_admin_get_log_page;
12876 admin_cmd.nsid = curr_data_offset;
12877 admin_cmd.addr = (__u64)(uintptr_t) dump_data;
12878 admin_cmd.data_len = curr_data_len;
12879 admin_cmd.cdw10 = log_id | (numdl << 16);
12880 admin_cmd.cdw11 = numdu;
12881
12882 while (curr_data_offset < data_len) {
12883#ifdef WDC_NVME_CLI_DEBUG
12884 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)
12885 "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)
12886 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)
12887 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)
;
12888#endif
12889 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
12890 if (ret) {
12891 nvme_show_status(ret);
12892 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)
12893 __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)
;
12894 break;
12895 }
12896
12897 if ((curr_data_offset + xfer_size) <= data_len)
12898 curr_data_len = xfer_size;
12899 else
12900 curr_data_len = data_len - curr_data_offset; /* last transfer */
12901
12902 curr_data_offset += curr_data_len;
12903 numd = (curr_data_len >> 2) - 1;
12904 numdu = numd >> 16;
12905 numdl = numd & 0xffff;
12906 admin_cmd.addr = (__u64)(uintptr_t)dump_data + (__u64)curr_data_offset;
12907 admin_cmd.nsid = curr_data_offset;
12908 admin_cmd.data_len = curr_data_len;
12909 admin_cmd.cdw10 = log_id | (numdl << 16);
12910 admin_cmd.cdw11 = numdu;
12911 i++;
12912 }
12913 fwrite(dump_data, data_len, 1, out);
12914 free(dump_data);
12915 return ret;
12916}
12917
12918//------------------------------------------------------------------------------------
12919// Description: set latency monitor feature
12920//
12921int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd,
12922 struct plugin *plugin)
12923{
12924 const char *desc = "Set Latency Monitor feature.";
12925
12926 struct feature_latency_monitor buf = {0,};
12927 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
12928 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
12929 uint64_t capabilities = 0;
12930 __u64 result;
12931 int ret;
12932
12933 const char *active_bucket_timer_threshold =
12934 "This is the value that loads the Active Bucket Timer Threshold.";
12935 const char *active_threshold_a =
12936 "This is the value that loads into the Active Threshold A.";
12937 const char *active_threshold_b =
12938 "This is the value that loads into the Active Threshold B.";
12939 const char *active_threshold_c =
12940 "This is the value that loads into the Active Threshold C.";
12941 const char *active_threshold_d =
12942 "This is the value that loads into the Active Threshold D.";
12943 const char *active_latency_config =
12944 "This is the value that loads into the Active Latency Configuration.";
12945 const char *active_latency_minimum_window =
12946 "This is the value that loads into the Active Latency Minimum Window.";
12947 const char *debug_log_trigger_enable =
12948 "This is the value that loads into the Debug Log Trigger Enable.";
12949 const char *discard_debug_log = "Discard Debug Log.";
12950 const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable.";
12951
12952 struct config {
12953 __u16 active_bucket_timer_threshold;
12954 __u8 active_threshold_a;
12955 __u8 active_threshold_b;
12956 __u8 active_threshold_c;
12957 __u8 active_threshold_d;
12958 __u16 active_latency_config;
12959 __u8 active_latency_minimum_window;
12960 __u16 debug_log_trigger_enable;
12961 __u8 discard_debug_log;
12962 __u8 latency_monitor_feature_enable;
12963 };
12964
12965 struct config cfg = {
12966 .active_bucket_timer_threshold = 0x7E0,
12967 .active_threshold_a = 0x5,
12968 .active_threshold_b = 0x13,
12969 .active_threshold_c = 0x1E,
12970 .active_threshold_d = 0x2E,
12971 .active_latency_config = 0xFFF,
12972 .active_latency_minimum_window = 0xA,
12973 .debug_log_trigger_enable = 0,
12974 .discard_debug_log = 0,
12975 .latency_monitor_feature_enable = 0x7,
12976 };
12977
12978 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
12979 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, }
12980 &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, }
12981 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, }
,
12982 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, }
12983 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, }
,
12984 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, }
12985 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, }
,
12986 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, }
12987 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, }
,
12988 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, }
12989 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, }
,
12990 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, }
12991 &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, }
,
12992 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, }
12993 &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, }
12994 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, }
,
12995 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, }
12996 &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, }
12997 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, }
,
12998 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, }
12999 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, }
,
13000 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, }
13001 &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, }
13002 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, }
,
13003 OPT_END(){ ((void*)0) }
13004 };
13005
13006 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
13007
13008 if (ret)
13009 return ret;
13010
13011 /* get capabilities */
13012 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
13013 if (ret || !wdc_check_device(ctx, hdl))
13014 return -1;
13015
13016 capabilities = wdc_get_drive_capabilities(ctx, hdl);
13017
13018 if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000)) {
13019 nvme_show_error("ERROR: WDC: unsupported device for this command")nvme_show_message(1, "ERROR: WDC: unsupported device for this command"
)
;
13020 return -1;
13021 }
13022
13023 memset(&buf, 0, sizeof(struct feature_latency_monitor));
13024
13025 buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold;
13026 buf.active_threshold_a = cfg.active_threshold_a;
13027 buf.active_threshold_b = cfg.active_threshold_b;
13028 buf.active_threshold_c = cfg.active_threshold_c;
13029 buf.active_threshold_d = cfg.active_threshold_d;
13030 buf.active_latency_config = cfg.active_latency_config;
13031 buf.active_latency_minimum_window = cfg.active_latency_minimum_window;
13032 buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable;
13033 buf.discard_debug_log = cfg.discard_debug_log;
13034 buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable;
13035
13036 ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR0xC5, 1, 0, 0, 0,
13037 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result);
13038
13039 if (ret < 0) {
13040 nvme_show_err(ret, "set-feature");
13041 } else if (!ret) {
13042 printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n",
13043 NVME_FEAT_OCP_LATENCY_MONITOR0xC5);
13044 printf("active bucket timer threshold: 0x%x\n",
13045 buf.active_bucket_timer_threshold);
13046 printf("active threshold a: 0x%x\n", buf.active_threshold_a);
13047 printf("active threshold b: 0x%x\n", buf.active_threshold_b);
13048 printf("active threshold c: 0x%x\n", buf.active_threshold_c);
13049 printf("active threshold d: 0x%x\n", buf.active_threshold_d);
13050 printf("active latency config: 0x%x\n", buf.active_latency_config);
13051 printf("active latency minimum window: 0x%x\n",
13052 buf.active_latency_minimum_window);
13053 printf("debug log trigger enable: 0x%x\n",
13054 buf.debug_log_trigger_enable);
13055 printf("discard debug log: 0x%x\n", buf.discard_debug_log);
13056 printf("latency monitor feature enable: 0x%x\n",
13057 buf.latency_monitor_feature_enable);
13058 } else if (ret > 0)
13059 nvme_show_error("NVMe Status:%s(%x)",nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
13060 libnvme_status_to_string(ret, false), ret)nvme_show_message(1, "NVMe Status:%s(%x)", libnvme_status_to_string
(ret, 0), ret)
;
13061
13062 return ret;
13063}
13064
13065/*
13066 * Externally available functions used to call the WDC Plugin commands
13067 */
13068int run_wdc_cloud_ssd_plugin_version(int argc, char **argv,
13069 struct command *command,
13070 struct plugin *plugin)
13071{
13072 return wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
13073}
13074
13075int run_wdc_vs_nand_stats(int argc, char **argv,
13076 struct command *command,
13077 struct plugin *plugin)
13078{
13079 return wdc_vs_nand_stats(argc, argv, command, plugin);
13080}
13081
13082int run_wdc_vs_smart_add_log(int argc, char **argv,
13083 struct command *command,
13084 struct plugin *plugin)
13085{
13086 return wdc_vs_smart_add_log(argc, argv, command, plugin);
13087}
13088
13089int run_wdc_clear_pcie_correctable_errors(int argc, char **argv,
13090 struct command *command,
13091 struct plugin *plugin)
13092{
13093 return wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
13094}
13095
13096int run_wdc_drive_status(int argc, char **argv,
13097 struct command *command,
13098 struct plugin *plugin)
13099{
13100 return wdc_drive_status(argc, argv, command, plugin);
13101}
13102
13103int run_wdc_clear_assert_dump(int argc, char **argv,
13104 struct command *command,
13105 struct plugin *plugin)
13106{
13107 return wdc_clear_assert_dump(argc, argv, command, plugin);
13108}
13109
13110int run_wdc_vs_telemetry_controller_option(int argc, char **argv,
13111 struct command *command,
13112 struct plugin *plugin)
13113{
13114 return wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
13115}
13116
13117int run_wdc_reason_identifier(int argc, char **argv,
13118 struct command *command,
13119 struct plugin *plugin)
13120{
13121 return wdc_reason_identifier(argc, argv, command, plugin);
13122}
13123
13124int run_wdc_log_page_directory(int argc, char **argv,
13125 struct command *command,
13126 struct plugin *plugin)
13127{
13128 return wdc_log_page_directory(argc, argv, command, plugin);
13129}
13130
13131int run_wdc_namespace_resize(int argc, char **argv,
13132 struct command *command,
13133 struct plugin *plugin)
13134{
13135 return wdc_namespace_resize(argc, argv, command, plugin);
13136}
13137
13138int run_wdc_vs_drive_info(int argc, char **argv,
13139 struct command *command,
13140 struct plugin *plugin)
13141{
13142 return wdc_vs_drive_info(argc, argv, command, plugin);
13143}
13144
13145int run_wdc_vs_pcie_stats(int argc, char **argv,
13146 struct command *command,
13147 struct plugin *plugin)
13148{
13149 return wdc_vs_pcie_stats(argc, argv, command, plugin);
13150}
13151
13152int run_wdc_get_latency_monitor_log(int argc, char **argv,
13153 struct command *command,
13154 struct plugin *plugin)
13155{
13156 return wdc_get_latency_monitor_log(argc, argv, command, plugin);
13157}
13158
13159int run_wdc_get_error_recovery_log(int argc, char **argv,
13160 struct command *command,
13161 struct plugin *plugin)
13162{
13163 return wdc_get_error_recovery_log(argc, argv, command, plugin);
13164}
13165
13166int run_wdc_get_dev_capabilities_log(int argc, char **argv,
13167 struct command *command,
13168 struct plugin *plugin)
13169{
13170 return wdc_get_dev_capabilities_log(argc, argv, command, plugin);
13171}
13172
13173int run_wdc_get_unsupported_reqs_log(int argc, char **argv,
13174 struct command *command,
13175 struct plugin *plugin)
13176{
13177 return wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
13178}
13179
13180int run_wdc_cloud_boot_SSD_version(int argc, char **argv,
13181 struct command *command,
13182 struct plugin *plugin)
13183{
13184 return wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
13185}
13186
13187int run_wdc_vs_cloud_log(int argc, char **argv,
13188 struct command *command,
13189 struct plugin *plugin)
13190{
13191 return wdc_vs_cloud_log(argc, argv, command, plugin);
13192}
13193
13194int run_wdc_vs_hw_rev_log(int argc, char **argv,
13195 struct command *command,
13196 struct plugin *plugin)
13197{
13198 return wdc_vs_hw_rev_log(argc, argv, command, plugin);
13199}
13200
13201int run_wdc_vs_device_waf(int argc, char **argv,
13202 struct command *command,
13203 struct plugin *plugin)
13204{
13205 return wdc_vs_device_waf(argc, argv, command, plugin);
13206}
13207
13208int run_wdc_set_latency_monitor_feature(int argc, char **argv,
13209 struct command *command,
13210 struct plugin *plugin)
13211{
13212 return wdc_set_latency_monitor_feature(argc, argv, command, plugin);
13213}
13214
13215int run_wdc_vs_temperature_stats(int argc, char **argv,
13216 struct command *command,
13217 struct plugin *plugin)
13218{
13219 return wdc_vs_temperature_stats(argc, argv, command, plugin);
13220}
13221
13222int run_wdc_cu_smart_log(int argc, char **argv,
13223 struct command *command,
13224 struct plugin *plugin)
13225{
13226 return wdc_cu_smart_log(argc, argv, command, plugin);
13227}
13228
13229
13230__u32 run_wdc_get_fw_cust_id(struct libnvme_global_ctx *ctx,
13231 struct libnvme_transport_handle *hdl)
13232{
13233 return wdc_get_fw_cust_id(ctx, hdl);
13234}
13235
13236bool_Bool run_wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx,
13237 struct libnvme_transport_handle *hdl,
13238 __u8 log_id,
13239 __u8 uuid_index)
13240{
13241 return wdc_nvme_check_supported_log_page(ctx,
13242 hdl,
13243 log_id,
13244 uuid_index);
13245}
13246
13247__u64 run_wdc_get_drive_capabilities(struct libnvme_global_ctx *ctx,
13248 struct libnvme_transport_handle *hdl)
13249{
13250 return wdc_get_drive_capabilities(ctx, hdl);
13251}
13252
13253static struct command wdc_cap_diag_cmd = {
13254 .name = "cap-diag",
13255 .help = "WDC Capture-Diagnostics",
13256 .fn = wdc_cap_diag,
13257};
13258
13259static struct command wdc_drive_log_cmd = {
13260 .name = "drive-log",
13261 .help = "WDC Drive Log",
13262 .fn = wdc_drive_log,
13263};
13264
13265static struct command wdc_get_crash_dump_cmd = {
13266 .name = "get-crash-dump",
13267 .help = "WDC Crash Dump",
13268 .fn = wdc_get_crash_dump,
13269};
13270
13271static struct command wdc_get_pfail_dump_cmd = {
13272 .name = "get-pfail-dump",
13273 .help = "WDC Pfail Dump",
13274 .fn = wdc_get_pfail_dump,
13275};
13276
13277static struct command wdc_id_ctrl_cmd = {
13278 .name = "id-ctrl",
13279 .help = "WDC identify controller",
13280 .fn = wdc_id_ctrl,
13281};
13282
13283static struct command wdc_purge_cmd = {
13284 .name = "purge",
13285 .help = "WDC Purge",
13286 .fn = wdc_purge,
13287};
13288
13289static struct command wdc_purge_monitor_cmd = {
13290 .name = "purge-monitor",
13291 .help = "WDC Purge Monitor",
13292 .fn = wdc_purge_monitor,
13293};
13294
13295static struct command wdc_vs_internal_fw_log_cmd = {
13296 .name = "vs-internal-log",
13297 .help = "WDC Internal Firmware Log",
13298 .fn = wdc_vs_internal_fw_log,
13299};
13300
13301static struct command wdc_vs_nand_stats_cmd = {
13302 .name = "vs-nand-stats",
13303 .help = "WDC NAND Statistics",
13304 .fn = wdc_vs_nand_stats,
13305};
13306
13307static struct command wdc_vs_smart_add_log_cmd = {
13308 .name = "vs-smart-add-log",
13309 .help = "WDC Additional Smart Log",
13310 .fn = wdc_vs_smart_add_log,
13311};
13312
13313static struct command wdc_clear_pcie_correctable_errors_cmd = {
13314 .name = "clear-pcie-correctable-errors",
13315 .help = "WDC Clear PCIe Correctable Error Count",
13316 .fn = wdc_clear_pcie_correctable_errors,
13317};
13318
13319static struct command wdc_drive_essentials_cmd = {
13320 .name = "drive-essentials",
13321 .help = "WDC Drive Essentials",
13322 .fn = wdc_drive_essentials,
13323};
13324
13325static struct command wdc_drive_status_cmd = {
13326 .name = "get-drive-status",
13327 .help = "WDC Get Drive Status",
13328 .fn = wdc_drive_status,
13329};
13330
13331static struct command wdc_clear_assert_dump_cmd = {
13332 .name = "clear-assert-dump",
13333 .help = "WDC Clear Assert Dump",
13334 .fn = wdc_clear_assert_dump,
13335};
13336
13337static struct command wdc_drive_resize_cmd = {
13338 .name = "drive-resize",
13339 .help = "WDC Drive Resize",
13340 .fn = wdc_drive_resize,
13341};
13342
13343static struct command wdc_vs_fw_activate_history_cmd = {
13344 .name = "vs-fw-activate-history",
13345 .help = "WDC Get FW Activate History",
13346 .fn = wdc_vs_fw_activate_history,
13347};
13348
13349static struct command wdc_clear_fw_activate_history_cmd = {
13350 .name = "clear-fw-activate-history",
13351 .help = "WDC Clear FW Activate History",
13352 .fn = wdc_clear_fw_activate_history,
13353};
13354
13355static struct command wdc_enc_get_log_cmd = {
13356 .name = "enc-get-log",
13357 .help = "WDC Get Enclosure Log",
13358 .fn = wdc_enc_get_log,
13359};
13360
13361static struct command wdc_vs_telemetry_controller_option_cmd = {
13362 .name = "vs-telemetry-controller-option",
13363 .help = "WDC Enable/Disable Controller Initiated Telemetry Log",
13364 .fn = wdc_vs_telemetry_controller_option,
13365 .needs_root = true1,
13366};
13367
13368static struct command wdc_reason_identifier_cmd = {
13369 .name = "vs-error-reason-identifier",
13370 .help = "WDC Telemetry Reason Identifier",
13371 .fn = wdc_reason_identifier,
13372 .needs_root = true1,
13373};
13374
13375static struct command wdc_log_page_directory_cmd = {
13376 .name = "log-page-directory",
13377 .help = "WDC Get Log Page Directory",
13378 .fn = wdc_log_page_directory,
13379};
13380
13381static struct command wdc_namespace_resize_cmd = {
13382 .name = "namespace-resize",
13383 .help = "WDC NamespaceDrive Resize",
13384 .fn = wdc_namespace_resize,
13385};
13386
13387static struct command wdc_vs_drive_info_cmd = {
13388 .name = "vs-drive-info",
13389 .help = "WDC Get Drive Info",
13390 .fn = wdc_vs_drive_info,
13391};
13392
13393static struct command wdc_vs_temperature_stats_cmd = {
13394 .name = "vs-temperature-stats",
13395 .help = "WDC Get Temperature Stats",
13396 .fn = wdc_vs_temperature_stats,
13397};
13398
13399static struct command wdc_capabilities_cmd = {
13400 .name = "capabilities",
13401 .help = "WDC Device Capabilities",
13402 .fn = wdc_capabilities,
13403};
13404
13405static struct command wdc_cloud_ssd_plugin_version_cmd = {
13406 .name = "cloud-SSD-plugin-version",
13407 .help = "WDC Cloud SSD Plugin Version",
13408 .fn = wdc_cloud_ssd_plugin_version,
13409};
13410
13411static struct command wdc_vs_pcie_stats_cmd = {
13412 .name = "vs-pcie-stats",
13413 .help = "WDC VS PCIE Statistics",
13414 .fn = wdc_vs_pcie_stats,
13415};
13416
13417static struct command wdc_get_latency_monitor_log_cmd = {
13418 .name = "get-latency-monitor-log",
13419 .help = "WDC Get Latency Monitor Log Page",
13420 .fn = wdc_get_latency_monitor_log,
13421};
13422
13423static struct command wdc_get_error_recovery_log_cmd = {
13424 .name = "get-error-recovery-log",
13425 .help = "WDC Get Error Recovery Log Page",
13426 .fn = wdc_get_error_recovery_log,
13427};
13428
13429static struct command wdc_get_dev_capabilities_log_cmd = {
13430 .name = "get-dev-capabilities-log",
13431 .help = "WDC Get Device Capabilities Log Page",
13432 .fn = wdc_get_dev_capabilities_log,
13433};
13434
13435static struct command wdc_get_unsupported_reqs_log_cmd = {
13436 .name = "get-unsupported-reqs-log",
13437 .help = "WDC Get Unsupported Requirements Log Page",
13438 .fn = wdc_get_unsupported_reqs_log,
13439};
13440
13441static struct command wdc_cloud_boot_SSD_version_cmd = {
13442 .name = "cloud-boot-SSD-version",
13443 .help = "WDC Get the Cloud Boot SSD Version",
13444 .fn = wdc_cloud_boot_SSD_version,
13445};
13446
13447static struct command wdc_vs_cloud_log_cmd = {
13448 .name = "vs-cloud-log",
13449 .help = "WDC Get the Cloud Log Page",
13450 .fn = wdc_vs_cloud_log,
13451};
13452
13453static struct command wdc_vs_hw_rev_log_cmd = {
13454 .name = "vs-hw-rev-log",
13455 .help = "WDC Get the Hardware Revision Log Page",
13456 .fn = wdc_vs_hw_rev_log,
13457};
13458
13459static struct command wdc_vs_device_waf_cmd = {
13460 .name = "vs-device-waf",
13461 .help = "WDC Calculate Device Write Amplication Factor",
13462 .fn = wdc_vs_device_waf,
13463};
13464
13465static struct command wdc_set_latency_monitor_feature_cmd = {
13466 .name = "set-latency-monitor-feature",
13467 .help = "WDC set Latency Monitor feature",
13468 .fn = wdc_set_latency_monitor_feature,
13469};
13470
13471static struct command wdc_cu_smart_log_cmd = {
13472 .name = "cu-smart-log",
13473 .help = "WDC Get Customer Unique Smart Log",
13474 .fn = wdc_cu_smart_log,
13475};
13476
13477static struct command *commands[] = {
13478 &wdc_cap_diag_cmd,
13479 &wdc_drive_log_cmd,
13480 &wdc_get_crash_dump_cmd,
13481 &wdc_get_pfail_dump_cmd,
13482 &wdc_id_ctrl_cmd,
13483 &wdc_purge_cmd,
13484 &wdc_purge_monitor_cmd,
13485 &wdc_vs_internal_fw_log_cmd,
13486 &wdc_vs_nand_stats_cmd,
13487 &wdc_vs_smart_add_log_cmd,
13488 &wdc_clear_pcie_correctable_errors_cmd,
13489 &wdc_drive_essentials_cmd,
13490 &wdc_drive_status_cmd,
13491 &wdc_clear_assert_dump_cmd,
13492 &wdc_drive_resize_cmd,
13493 &wdc_vs_fw_activate_history_cmd,
13494 &wdc_clear_fw_activate_history_cmd,
13495 &wdc_enc_get_log_cmd,
13496 &wdc_vs_telemetry_controller_option_cmd,
13497 &wdc_reason_identifier_cmd,
13498 &wdc_log_page_directory_cmd,
13499 &wdc_namespace_resize_cmd,
13500 &wdc_vs_drive_info_cmd,
13501 &wdc_vs_temperature_stats_cmd,
13502 &wdc_capabilities_cmd,
13503 &wdc_cloud_ssd_plugin_version_cmd,
13504 &wdc_vs_pcie_stats_cmd,
13505 &wdc_get_latency_monitor_log_cmd,
13506 &wdc_get_error_recovery_log_cmd,
13507 &wdc_get_dev_capabilities_log_cmd,
13508 &wdc_get_unsupported_reqs_log_cmd,
13509 &wdc_cloud_boot_SSD_version_cmd,
13510 &wdc_vs_cloud_log_cmd,
13511 &wdc_vs_hw_rev_log_cmd,
13512 &wdc_vs_device_waf_cmd,
13513 &wdc_set_latency_monitor_feature_cmd,
13514 &wdc_cu_smart_log_cmd,
13515 NULL((void*)0),
13516};
13517
13518static struct plugin plugin = {
13519 .name = "wdc",
13520 .desc = "Western Digital vendor specific extensions",
13521 .version = WDC_PLUGIN_VERSION"2.15.1",
13522};
13523
13524static void __shr_constructor__attribute__((constructor)) register_plugin(void)
13525{
13526 plugin_add_group(&plugin, NULL((void*)0), commands);
13527 register_extension(&plugin);
13528}

←

../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