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