xref: /freebsd/sys/cam/ctl/ctl_nvme_all.c (revision 6f308bcf572467c0884db833e169d9f14b7b49b2)
1*6f308bcfSJohn Baldwin /*-
2*6f308bcfSJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause
3*6f308bcfSJohn Baldwin  *
4*6f308bcfSJohn Baldwin  * Copyright (C) 2012-2014 Intel Corporation
5*6f308bcfSJohn Baldwin  * All rights reserved.
6*6f308bcfSJohn Baldwin  *
7*6f308bcfSJohn Baldwin  * Copyright (c) 2023 Chelsio Communications, Inc.
8*6f308bcfSJohn Baldwin  */
9*6f308bcfSJohn Baldwin 
10*6f308bcfSJohn Baldwin #include <sys/types.h>
11*6f308bcfSJohn Baldwin #include <sys/sbuf.h>
12*6f308bcfSJohn Baldwin #ifndef _KERNEL
13*6f308bcfSJohn Baldwin #include <sys/time.h>
14*6f308bcfSJohn Baldwin #include <stdio.h>
15*6f308bcfSJohn Baldwin #endif
16*6f308bcfSJohn Baldwin 
17*6f308bcfSJohn Baldwin #include <dev/nvme/nvme.h>
18*6f308bcfSJohn Baldwin 
19*6f308bcfSJohn Baldwin #include <cam/ctl/ctl_io.h>
20*6f308bcfSJohn Baldwin #include <cam/ctl/ctl_nvme_all.h>
21*6f308bcfSJohn Baldwin 
22*6f308bcfSJohn Baldwin /* XXX: This duplicates lists in nvme_qpair.c. */
23*6f308bcfSJohn Baldwin 
24*6f308bcfSJohn Baldwin #define OPC_ENTRY(x)		[NVME_OPC_ ## x] = #x
25*6f308bcfSJohn Baldwin 
26*6f308bcfSJohn Baldwin static const char *admin_opcode[256] = {
27*6f308bcfSJohn Baldwin 	OPC_ENTRY(DELETE_IO_SQ),
28*6f308bcfSJohn Baldwin 	OPC_ENTRY(CREATE_IO_SQ),
29*6f308bcfSJohn Baldwin 	OPC_ENTRY(GET_LOG_PAGE),
30*6f308bcfSJohn Baldwin 	OPC_ENTRY(DELETE_IO_CQ),
31*6f308bcfSJohn Baldwin 	OPC_ENTRY(CREATE_IO_CQ),
32*6f308bcfSJohn Baldwin 	OPC_ENTRY(IDENTIFY),
33*6f308bcfSJohn Baldwin 	OPC_ENTRY(ABORT),
34*6f308bcfSJohn Baldwin 	OPC_ENTRY(SET_FEATURES),
35*6f308bcfSJohn Baldwin 	OPC_ENTRY(GET_FEATURES),
36*6f308bcfSJohn Baldwin 	OPC_ENTRY(ASYNC_EVENT_REQUEST),
37*6f308bcfSJohn Baldwin 	OPC_ENTRY(NAMESPACE_MANAGEMENT),
38*6f308bcfSJohn Baldwin 	OPC_ENTRY(FIRMWARE_ACTIVATE),
39*6f308bcfSJohn Baldwin 	OPC_ENTRY(FIRMWARE_IMAGE_DOWNLOAD),
40*6f308bcfSJohn Baldwin 	OPC_ENTRY(DEVICE_SELF_TEST),
41*6f308bcfSJohn Baldwin 	OPC_ENTRY(NAMESPACE_ATTACHMENT),
42*6f308bcfSJohn Baldwin 	OPC_ENTRY(KEEP_ALIVE),
43*6f308bcfSJohn Baldwin 	OPC_ENTRY(DIRECTIVE_SEND),
44*6f308bcfSJohn Baldwin 	OPC_ENTRY(DIRECTIVE_RECEIVE),
45*6f308bcfSJohn Baldwin 	OPC_ENTRY(VIRTUALIZATION_MANAGEMENT),
46*6f308bcfSJohn Baldwin 	OPC_ENTRY(NVME_MI_SEND),
47*6f308bcfSJohn Baldwin 	OPC_ENTRY(NVME_MI_RECEIVE),
48*6f308bcfSJohn Baldwin 	OPC_ENTRY(CAPACITY_MANAGEMENT),
49*6f308bcfSJohn Baldwin 	OPC_ENTRY(LOCKDOWN),
50*6f308bcfSJohn Baldwin 	OPC_ENTRY(DOORBELL_BUFFER_CONFIG),
51*6f308bcfSJohn Baldwin 	OPC_ENTRY(FABRICS_COMMANDS),
52*6f308bcfSJohn Baldwin 	OPC_ENTRY(FORMAT_NVM),
53*6f308bcfSJohn Baldwin 	OPC_ENTRY(SECURITY_SEND),
54*6f308bcfSJohn Baldwin 	OPC_ENTRY(SECURITY_RECEIVE),
55*6f308bcfSJohn Baldwin 	OPC_ENTRY(SANITIZE),
56*6f308bcfSJohn Baldwin 	OPC_ENTRY(GET_LBA_STATUS),
57*6f308bcfSJohn Baldwin };
58*6f308bcfSJohn Baldwin 
59*6f308bcfSJohn Baldwin static const char *nvm_opcode[256] = {
60*6f308bcfSJohn Baldwin 	OPC_ENTRY(FLUSH),
61*6f308bcfSJohn Baldwin 	OPC_ENTRY(WRITE),
62*6f308bcfSJohn Baldwin 	OPC_ENTRY(READ),
63*6f308bcfSJohn Baldwin 	OPC_ENTRY(WRITE_UNCORRECTABLE),
64*6f308bcfSJohn Baldwin 	OPC_ENTRY(COMPARE),
65*6f308bcfSJohn Baldwin 	OPC_ENTRY(WRITE_ZEROES),
66*6f308bcfSJohn Baldwin 	OPC_ENTRY(DATASET_MANAGEMENT),
67*6f308bcfSJohn Baldwin 	OPC_ENTRY(VERIFY),
68*6f308bcfSJohn Baldwin 	OPC_ENTRY(RESERVATION_REGISTER),
69*6f308bcfSJohn Baldwin 	OPC_ENTRY(RESERVATION_REPORT),
70*6f308bcfSJohn Baldwin 	OPC_ENTRY(RESERVATION_ACQUIRE),
71*6f308bcfSJohn Baldwin 	OPC_ENTRY(RESERVATION_RELEASE),
72*6f308bcfSJohn Baldwin 	OPC_ENTRY(COPY),
73*6f308bcfSJohn Baldwin };
74*6f308bcfSJohn Baldwin 
75*6f308bcfSJohn Baldwin void
76*6f308bcfSJohn Baldwin ctl_nvme_command_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
77*6f308bcfSJohn Baldwin {
78*6f308bcfSJohn Baldwin 	const char *s, *type;
79*6f308bcfSJohn Baldwin 
80*6f308bcfSJohn Baldwin 	if (ctnio->io_hdr.io_type == CTL_IO_NVME_ADMIN) {
81*6f308bcfSJohn Baldwin 		s = admin_opcode[ctnio->cmd.opc];
82*6f308bcfSJohn Baldwin 		type = "ADMIN";
83*6f308bcfSJohn Baldwin 	} else {
84*6f308bcfSJohn Baldwin 		s = nvm_opcode[ctnio->cmd.opc];
85*6f308bcfSJohn Baldwin 		type = "NVM";
86*6f308bcfSJohn Baldwin 	}
87*6f308bcfSJohn Baldwin 	if (s == NULL)
88*6f308bcfSJohn Baldwin 		sbuf_printf(sb, "%s:0x%02x", type, ctnio->cmd.opc);
89*6f308bcfSJohn Baldwin 	else
90*6f308bcfSJohn Baldwin 		sbuf_printf(sb, "%s", s);
91*6f308bcfSJohn Baldwin }
92*6f308bcfSJohn Baldwin 
93*6f308bcfSJohn Baldwin #define SC_ENTRY(x)		[NVME_SC_ ## x] = #x
94*6f308bcfSJohn Baldwin 
95*6f308bcfSJohn Baldwin static const char *generic_status[256] = {
96*6f308bcfSJohn Baldwin 	SC_ENTRY(SUCCESS),
97*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_OPCODE),
98*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_FIELD),
99*6f308bcfSJohn Baldwin 	SC_ENTRY(COMMAND_ID_CONFLICT),
100*6f308bcfSJohn Baldwin 	SC_ENTRY(DATA_TRANSFER_ERROR),
101*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_POWER_LOSS),
102*6f308bcfSJohn Baldwin 	SC_ENTRY(INTERNAL_DEVICE_ERROR),
103*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_BY_REQUEST),
104*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_SQ_DELETION),
105*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_FAILED_FUSED),
106*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_MISSING_FUSED),
107*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_NAMESPACE_OR_FORMAT),
108*6f308bcfSJohn Baldwin 	SC_ENTRY(COMMAND_SEQUENCE_ERROR),
109*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_SGL_SEGMENT_DESCR),
110*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_NUMBER_OF_SGL_DESCR),
111*6f308bcfSJohn Baldwin 	SC_ENTRY(DATA_SGL_LENGTH_INVALID),
112*6f308bcfSJohn Baldwin 	SC_ENTRY(METADATA_SGL_LENGTH_INVALID),
113*6f308bcfSJohn Baldwin 	SC_ENTRY(SGL_DESCRIPTOR_TYPE_INVALID),
114*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_USE_OF_CMB),
115*6f308bcfSJohn Baldwin 	SC_ENTRY(PRP_OFFET_INVALID),
116*6f308bcfSJohn Baldwin 	SC_ENTRY(ATOMIC_WRITE_UNIT_EXCEEDED),
117*6f308bcfSJohn Baldwin 	SC_ENTRY(OPERATION_DENIED),
118*6f308bcfSJohn Baldwin 	SC_ENTRY(SGL_OFFSET_INVALID),
119*6f308bcfSJohn Baldwin 	SC_ENTRY(HOST_ID_INCONSISTENT_FORMAT),
120*6f308bcfSJohn Baldwin 	SC_ENTRY(KEEP_ALIVE_TIMEOUT_EXPIRED),
121*6f308bcfSJohn Baldwin 	SC_ENTRY(KEEP_ALIVE_TIMEOUT_INVALID),
122*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORTED_DUE_TO_PREEMPT),
123*6f308bcfSJohn Baldwin 	SC_ENTRY(SANITIZE_FAILED),
124*6f308bcfSJohn Baldwin 	SC_ENTRY(SANITIZE_IN_PROGRESS),
125*6f308bcfSJohn Baldwin 	SC_ENTRY(SGL_DATA_BLOCK_GRAN_INVALID),
126*6f308bcfSJohn Baldwin 	SC_ENTRY(NOT_SUPPORTED_IN_CMB),
127*6f308bcfSJohn Baldwin 	SC_ENTRY(NAMESPACE_IS_WRITE_PROTECTED),
128*6f308bcfSJohn Baldwin 	SC_ENTRY(COMMAND_INTERRUPTED),
129*6f308bcfSJohn Baldwin 	SC_ENTRY(TRANSIENT_TRANSPORT_ERROR),
130*6f308bcfSJohn Baldwin 
131*6f308bcfSJohn Baldwin 	SC_ENTRY(LBA_OUT_OF_RANGE),
132*6f308bcfSJohn Baldwin 	SC_ENTRY(CAPACITY_EXCEEDED),
133*6f308bcfSJohn Baldwin 	SC_ENTRY(NAMESPACE_NOT_READY),
134*6f308bcfSJohn Baldwin 	SC_ENTRY(RESERVATION_CONFLICT),
135*6f308bcfSJohn Baldwin 	SC_ENTRY(FORMAT_IN_PROGRESS),
136*6f308bcfSJohn Baldwin };
137*6f308bcfSJohn Baldwin 
138*6f308bcfSJohn Baldwin static const char *command_specific_status[256] = {
139*6f308bcfSJohn Baldwin 	SC_ENTRY(COMPLETION_QUEUE_INVALID),
140*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_QUEUE_IDENTIFIER),
141*6f308bcfSJohn Baldwin 	SC_ENTRY(MAXIMUM_QUEUE_SIZE_EXCEEDED),
142*6f308bcfSJohn Baldwin 	SC_ENTRY(ABORT_COMMAND_LIMIT_EXCEEDED),
143*6f308bcfSJohn Baldwin 	SC_ENTRY(ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED),
144*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_FIRMWARE_SLOT),
145*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_FIRMWARE_IMAGE),
146*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_INTERRUPT_VECTOR),
147*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_LOG_PAGE),
148*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_FORMAT),
149*6f308bcfSJohn Baldwin 	SC_ENTRY(FIRMWARE_REQUIRES_RESET),
150*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_QUEUE_DELETION),
151*6f308bcfSJohn Baldwin 	SC_ENTRY(FEATURE_NOT_SAVEABLE),
152*6f308bcfSJohn Baldwin 	SC_ENTRY(FEATURE_NOT_CHANGEABLE),
153*6f308bcfSJohn Baldwin 	SC_ENTRY(FEATURE_NOT_NS_SPECIFIC),
154*6f308bcfSJohn Baldwin 	SC_ENTRY(FW_ACT_REQUIRES_NVMS_RESET),
155*6f308bcfSJohn Baldwin 	SC_ENTRY(FW_ACT_REQUIRES_RESET),
156*6f308bcfSJohn Baldwin 	SC_ENTRY(FW_ACT_REQUIRES_TIME),
157*6f308bcfSJohn Baldwin 	SC_ENTRY(FW_ACT_PROHIBITED),
158*6f308bcfSJohn Baldwin 	SC_ENTRY(OVERLAPPING_RANGE),
159*6f308bcfSJohn Baldwin 	SC_ENTRY(NS_INSUFFICIENT_CAPACITY),
160*6f308bcfSJohn Baldwin 	SC_ENTRY(NS_ID_UNAVAILABLE),
161*6f308bcfSJohn Baldwin 	SC_ENTRY(NS_ALREADY_ATTACHED),
162*6f308bcfSJohn Baldwin 	SC_ENTRY(NS_IS_PRIVATE),
163*6f308bcfSJohn Baldwin 	SC_ENTRY(NS_NOT_ATTACHED),
164*6f308bcfSJohn Baldwin 	SC_ENTRY(THIN_PROV_NOT_SUPPORTED),
165*6f308bcfSJohn Baldwin 	SC_ENTRY(CTRLR_LIST_INVALID),
166*6f308bcfSJohn Baldwin 	SC_ENTRY(SELF_TEST_IN_PROGRESS),
167*6f308bcfSJohn Baldwin 	SC_ENTRY(BOOT_PART_WRITE_PROHIB),
168*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_CTRLR_ID),
169*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_SEC_CTRLR_STATE),
170*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_NUM_OF_CTRLR_RESRC),
171*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_RESOURCE_ID),
172*6f308bcfSJohn Baldwin 	SC_ENTRY(SANITIZE_PROHIBITED_WPMRE),
173*6f308bcfSJohn Baldwin 	SC_ENTRY(ANA_GROUP_ID_INVALID),
174*6f308bcfSJohn Baldwin 	SC_ENTRY(ANA_ATTACH_FAILED),
175*6f308bcfSJohn Baldwin 
176*6f308bcfSJohn Baldwin 	SC_ENTRY(CONFLICTING_ATTRIBUTES),
177*6f308bcfSJohn Baldwin 	SC_ENTRY(INVALID_PROTECTION_INFO),
178*6f308bcfSJohn Baldwin 	SC_ENTRY(ATTEMPTED_WRITE_TO_RO_PAGE),
179*6f308bcfSJohn Baldwin };
180*6f308bcfSJohn Baldwin 
181*6f308bcfSJohn Baldwin static const char *media_error_status[256] = {
182*6f308bcfSJohn Baldwin 	SC_ENTRY(WRITE_FAULTS),
183*6f308bcfSJohn Baldwin 	SC_ENTRY(UNRECOVERED_READ_ERROR),
184*6f308bcfSJohn Baldwin 	SC_ENTRY(GUARD_CHECK_ERROR),
185*6f308bcfSJohn Baldwin 	SC_ENTRY(APPLICATION_TAG_CHECK_ERROR),
186*6f308bcfSJohn Baldwin 	SC_ENTRY(REFERENCE_TAG_CHECK_ERROR),
187*6f308bcfSJohn Baldwin 	SC_ENTRY(COMPARE_FAILURE),
188*6f308bcfSJohn Baldwin 	SC_ENTRY(ACCESS_DENIED),
189*6f308bcfSJohn Baldwin 	SC_ENTRY(DEALLOCATED_OR_UNWRITTEN),
190*6f308bcfSJohn Baldwin };
191*6f308bcfSJohn Baldwin 
192*6f308bcfSJohn Baldwin static const char *path_related_status[256] = {
193*6f308bcfSJohn Baldwin 	SC_ENTRY(INTERNAL_PATH_ERROR),
194*6f308bcfSJohn Baldwin 	SC_ENTRY(ASYMMETRIC_ACCESS_PERSISTENT_LOSS),
195*6f308bcfSJohn Baldwin 	SC_ENTRY(ASYMMETRIC_ACCESS_INACCESSIBLE),
196*6f308bcfSJohn Baldwin 	SC_ENTRY(ASYMMETRIC_ACCESS_TRANSITION),
197*6f308bcfSJohn Baldwin 	SC_ENTRY(CONTROLLER_PATHING_ERROR),
198*6f308bcfSJohn Baldwin 	SC_ENTRY(HOST_PATHING_ERROR),
199*6f308bcfSJohn Baldwin 	SC_ENTRY(COMMAND_ABORTED_BY_HOST),
200*6f308bcfSJohn Baldwin };
201*6f308bcfSJohn Baldwin 
202*6f308bcfSJohn Baldwin void
203*6f308bcfSJohn Baldwin ctl_nvme_status_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
204*6f308bcfSJohn Baldwin {
205*6f308bcfSJohn Baldwin 	const char *s, *type;
206*6f308bcfSJohn Baldwin 	uint16_t status;
207*6f308bcfSJohn Baldwin 
208*6f308bcfSJohn Baldwin 	status = le16toh(ctnio->cpl.status);
209*6f308bcfSJohn Baldwin 	switch (NVME_STATUS_GET_SCT(status)) {
210*6f308bcfSJohn Baldwin 	case NVME_SCT_GENERIC:
211*6f308bcfSJohn Baldwin 		s = generic_status[NVME_STATUS_GET_SC(status)];
212*6f308bcfSJohn Baldwin 		type = "GENERIC";
213*6f308bcfSJohn Baldwin 		break;
214*6f308bcfSJohn Baldwin 	case NVME_SCT_COMMAND_SPECIFIC:
215*6f308bcfSJohn Baldwin 		s = command_specific_status[NVME_STATUS_GET_SC(status)];
216*6f308bcfSJohn Baldwin 		type = "COMMAND SPECIFIC";
217*6f308bcfSJohn Baldwin 		break;
218*6f308bcfSJohn Baldwin 	case NVME_SCT_MEDIA_ERROR:
219*6f308bcfSJohn Baldwin 		s = media_error_status[NVME_STATUS_GET_SC(status)];
220*6f308bcfSJohn Baldwin 		type = "MEDIA ERROR";
221*6f308bcfSJohn Baldwin 		break;
222*6f308bcfSJohn Baldwin 	case NVME_SCT_PATH_RELATED:
223*6f308bcfSJohn Baldwin 		s = path_related_status[NVME_STATUS_GET_SC(status)];
224*6f308bcfSJohn Baldwin 		type = "PATH RELATED";
225*6f308bcfSJohn Baldwin 		break;
226*6f308bcfSJohn Baldwin 	case NVME_SCT_VENDOR_SPECIFIC:
227*6f308bcfSJohn Baldwin 		s = NULL;
228*6f308bcfSJohn Baldwin 		type = "VENDOR SPECIFIC";
229*6f308bcfSJohn Baldwin 		break;
230*6f308bcfSJohn Baldwin 	default:
231*6f308bcfSJohn Baldwin 		s = "RESERVED";
232*6f308bcfSJohn Baldwin 		type = NULL;
233*6f308bcfSJohn Baldwin 		break;
234*6f308bcfSJohn Baldwin 	}
235*6f308bcfSJohn Baldwin 
236*6f308bcfSJohn Baldwin 	if (s == NULL)
237*6f308bcfSJohn Baldwin 		sbuf_printf(sb, "%s:0x%02x", type, NVME_STATUS_GET_SC(status));
238*6f308bcfSJohn Baldwin 	else
239*6f308bcfSJohn Baldwin 		sbuf_printf(sb, "%s", s);
240*6f308bcfSJohn Baldwin 	if (NVME_STATUS_GET_M(status) != 0)
241*6f308bcfSJohn Baldwin 		sbuf_printf(sb, " M");
242*6f308bcfSJohn Baldwin 	if (NVME_STATUS_GET_DNR(status) != 0)
243*6f308bcfSJohn Baldwin 		sbuf_printf(sb, " DNR");
244*6f308bcfSJohn Baldwin }
245