freebsd-src/sys/cam/ctl/ctl_nvme_all.c
John Baldwin 6f308bcf57 ctl: Support NVMe requests in debug trace functions
Reviewed by:	imp
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D44719
2024-05-02 16:31:34 -07:00

245 lines
6.4 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2014 Intel Corporation
* All rights reserved.
*
* Copyright (c) 2023 Chelsio Communications, Inc.
*/
#include <sys/types.h>
#include <sys/sbuf.h>
#ifndef _KERNEL
#include <sys/time.h>
#include <stdio.h>
#endif
#include <dev/nvme/nvme.h>
#include <cam/ctl/ctl_io.h>
#include <cam/ctl/ctl_nvme_all.h>
/* XXX: This duplicates lists in nvme_qpair.c. */
#define OPC_ENTRY(x) [NVME_OPC_ ## x] = #x
static const char *admin_opcode[256] = {
OPC_ENTRY(DELETE_IO_SQ),
OPC_ENTRY(CREATE_IO_SQ),
OPC_ENTRY(GET_LOG_PAGE),
OPC_ENTRY(DELETE_IO_CQ),
OPC_ENTRY(CREATE_IO_CQ),
OPC_ENTRY(IDENTIFY),
OPC_ENTRY(ABORT),
OPC_ENTRY(SET_FEATURES),
OPC_ENTRY(GET_FEATURES),
OPC_ENTRY(ASYNC_EVENT_REQUEST),
OPC_ENTRY(NAMESPACE_MANAGEMENT),
OPC_ENTRY(FIRMWARE_ACTIVATE),
OPC_ENTRY(FIRMWARE_IMAGE_DOWNLOAD),
OPC_ENTRY(DEVICE_SELF_TEST),
OPC_ENTRY(NAMESPACE_ATTACHMENT),
OPC_ENTRY(KEEP_ALIVE),
OPC_ENTRY(DIRECTIVE_SEND),
OPC_ENTRY(DIRECTIVE_RECEIVE),
OPC_ENTRY(VIRTUALIZATION_MANAGEMENT),
OPC_ENTRY(NVME_MI_SEND),
OPC_ENTRY(NVME_MI_RECEIVE),
OPC_ENTRY(CAPACITY_MANAGEMENT),
OPC_ENTRY(LOCKDOWN),
OPC_ENTRY(DOORBELL_BUFFER_CONFIG),
OPC_ENTRY(FABRICS_COMMANDS),
OPC_ENTRY(FORMAT_NVM),
OPC_ENTRY(SECURITY_SEND),
OPC_ENTRY(SECURITY_RECEIVE),
OPC_ENTRY(SANITIZE),
OPC_ENTRY(GET_LBA_STATUS),
};
static const char *nvm_opcode[256] = {
OPC_ENTRY(FLUSH),
OPC_ENTRY(WRITE),
OPC_ENTRY(READ),
OPC_ENTRY(WRITE_UNCORRECTABLE),
OPC_ENTRY(COMPARE),
OPC_ENTRY(WRITE_ZEROES),
OPC_ENTRY(DATASET_MANAGEMENT),
OPC_ENTRY(VERIFY),
OPC_ENTRY(RESERVATION_REGISTER),
OPC_ENTRY(RESERVATION_REPORT),
OPC_ENTRY(RESERVATION_ACQUIRE),
OPC_ENTRY(RESERVATION_RELEASE),
OPC_ENTRY(COPY),
};
void
ctl_nvme_command_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
{
const char *s, *type;
if (ctnio->io_hdr.io_type == CTL_IO_NVME_ADMIN) {
s = admin_opcode[ctnio->cmd.opc];
type = "ADMIN";
} else {
s = nvm_opcode[ctnio->cmd.opc];
type = "NVM";
}
if (s == NULL)
sbuf_printf(sb, "%s:0x%02x", type, ctnio->cmd.opc);
else
sbuf_printf(sb, "%s", s);
}
#define SC_ENTRY(x) [NVME_SC_ ## x] = #x
static const char *generic_status[256] = {
SC_ENTRY(SUCCESS),
SC_ENTRY(INVALID_OPCODE),
SC_ENTRY(INVALID_FIELD),
SC_ENTRY(COMMAND_ID_CONFLICT),
SC_ENTRY(DATA_TRANSFER_ERROR),
SC_ENTRY(ABORTED_POWER_LOSS),
SC_ENTRY(INTERNAL_DEVICE_ERROR),
SC_ENTRY(ABORTED_BY_REQUEST),
SC_ENTRY(ABORTED_SQ_DELETION),
SC_ENTRY(ABORTED_FAILED_FUSED),
SC_ENTRY(ABORTED_MISSING_FUSED),
SC_ENTRY(INVALID_NAMESPACE_OR_FORMAT),
SC_ENTRY(COMMAND_SEQUENCE_ERROR),
SC_ENTRY(INVALID_SGL_SEGMENT_DESCR),
SC_ENTRY(INVALID_NUMBER_OF_SGL_DESCR),
SC_ENTRY(DATA_SGL_LENGTH_INVALID),
SC_ENTRY(METADATA_SGL_LENGTH_INVALID),
SC_ENTRY(SGL_DESCRIPTOR_TYPE_INVALID),
SC_ENTRY(INVALID_USE_OF_CMB),
SC_ENTRY(PRP_OFFET_INVALID),
SC_ENTRY(ATOMIC_WRITE_UNIT_EXCEEDED),
SC_ENTRY(OPERATION_DENIED),
SC_ENTRY(SGL_OFFSET_INVALID),
SC_ENTRY(HOST_ID_INCONSISTENT_FORMAT),
SC_ENTRY(KEEP_ALIVE_TIMEOUT_EXPIRED),
SC_ENTRY(KEEP_ALIVE_TIMEOUT_INVALID),
SC_ENTRY(ABORTED_DUE_TO_PREEMPT),
SC_ENTRY(SANITIZE_FAILED),
SC_ENTRY(SANITIZE_IN_PROGRESS),
SC_ENTRY(SGL_DATA_BLOCK_GRAN_INVALID),
SC_ENTRY(NOT_SUPPORTED_IN_CMB),
SC_ENTRY(NAMESPACE_IS_WRITE_PROTECTED),
SC_ENTRY(COMMAND_INTERRUPTED),
SC_ENTRY(TRANSIENT_TRANSPORT_ERROR),
SC_ENTRY(LBA_OUT_OF_RANGE),
SC_ENTRY(CAPACITY_EXCEEDED),
SC_ENTRY(NAMESPACE_NOT_READY),
SC_ENTRY(RESERVATION_CONFLICT),
SC_ENTRY(FORMAT_IN_PROGRESS),
};
static const char *command_specific_status[256] = {
SC_ENTRY(COMPLETION_QUEUE_INVALID),
SC_ENTRY(INVALID_QUEUE_IDENTIFIER),
SC_ENTRY(MAXIMUM_QUEUE_SIZE_EXCEEDED),
SC_ENTRY(ABORT_COMMAND_LIMIT_EXCEEDED),
SC_ENTRY(ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED),
SC_ENTRY(INVALID_FIRMWARE_SLOT),
SC_ENTRY(INVALID_FIRMWARE_IMAGE),
SC_ENTRY(INVALID_INTERRUPT_VECTOR),
SC_ENTRY(INVALID_LOG_PAGE),
SC_ENTRY(INVALID_FORMAT),
SC_ENTRY(FIRMWARE_REQUIRES_RESET),
SC_ENTRY(INVALID_QUEUE_DELETION),
SC_ENTRY(FEATURE_NOT_SAVEABLE),
SC_ENTRY(FEATURE_NOT_CHANGEABLE),
SC_ENTRY(FEATURE_NOT_NS_SPECIFIC),
SC_ENTRY(FW_ACT_REQUIRES_NVMS_RESET),
SC_ENTRY(FW_ACT_REQUIRES_RESET),
SC_ENTRY(FW_ACT_REQUIRES_TIME),
SC_ENTRY(FW_ACT_PROHIBITED),
SC_ENTRY(OVERLAPPING_RANGE),
SC_ENTRY(NS_INSUFFICIENT_CAPACITY),
SC_ENTRY(NS_ID_UNAVAILABLE),
SC_ENTRY(NS_ALREADY_ATTACHED),
SC_ENTRY(NS_IS_PRIVATE),
SC_ENTRY(NS_NOT_ATTACHED),
SC_ENTRY(THIN_PROV_NOT_SUPPORTED),
SC_ENTRY(CTRLR_LIST_INVALID),
SC_ENTRY(SELF_TEST_IN_PROGRESS),
SC_ENTRY(BOOT_PART_WRITE_PROHIB),
SC_ENTRY(INVALID_CTRLR_ID),
SC_ENTRY(INVALID_SEC_CTRLR_STATE),
SC_ENTRY(INVALID_NUM_OF_CTRLR_RESRC),
SC_ENTRY(INVALID_RESOURCE_ID),
SC_ENTRY(SANITIZE_PROHIBITED_WPMRE),
SC_ENTRY(ANA_GROUP_ID_INVALID),
SC_ENTRY(ANA_ATTACH_FAILED),
SC_ENTRY(CONFLICTING_ATTRIBUTES),
SC_ENTRY(INVALID_PROTECTION_INFO),
SC_ENTRY(ATTEMPTED_WRITE_TO_RO_PAGE),
};
static const char *media_error_status[256] = {
SC_ENTRY(WRITE_FAULTS),
SC_ENTRY(UNRECOVERED_READ_ERROR),
SC_ENTRY(GUARD_CHECK_ERROR),
SC_ENTRY(APPLICATION_TAG_CHECK_ERROR),
SC_ENTRY(REFERENCE_TAG_CHECK_ERROR),
SC_ENTRY(COMPARE_FAILURE),
SC_ENTRY(ACCESS_DENIED),
SC_ENTRY(DEALLOCATED_OR_UNWRITTEN),
};
static const char *path_related_status[256] = {
SC_ENTRY(INTERNAL_PATH_ERROR),
SC_ENTRY(ASYMMETRIC_ACCESS_PERSISTENT_LOSS),
SC_ENTRY(ASYMMETRIC_ACCESS_INACCESSIBLE),
SC_ENTRY(ASYMMETRIC_ACCESS_TRANSITION),
SC_ENTRY(CONTROLLER_PATHING_ERROR),
SC_ENTRY(HOST_PATHING_ERROR),
SC_ENTRY(COMMAND_ABORTED_BY_HOST),
};
void
ctl_nvme_status_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
{
const char *s, *type;
uint16_t status;
status = le16toh(ctnio->cpl.status);
switch (NVME_STATUS_GET_SCT(status)) {
case NVME_SCT_GENERIC:
s = generic_status[NVME_STATUS_GET_SC(status)];
type = "GENERIC";
break;
case NVME_SCT_COMMAND_SPECIFIC:
s = command_specific_status[NVME_STATUS_GET_SC(status)];
type = "COMMAND SPECIFIC";
break;
case NVME_SCT_MEDIA_ERROR:
s = media_error_status[NVME_STATUS_GET_SC(status)];
type = "MEDIA ERROR";
break;
case NVME_SCT_PATH_RELATED:
s = path_related_status[NVME_STATUS_GET_SC(status)];
type = "PATH RELATED";
break;
case NVME_SCT_VENDOR_SPECIFIC:
s = NULL;
type = "VENDOR SPECIFIC";
break;
default:
s = "RESERVED";
type = NULL;
break;
}
if (s == NULL)
sbuf_printf(sb, "%s:0x%02x", type, NVME_STATUS_GET_SC(status));
else
sbuf_printf(sb, "%s", s);
if (NVME_STATUS_GET_M(status) != 0)
sbuf_printf(sb, " M");
if (NVME_STATUS_GET_DNR(status) != 0)
sbuf_printf(sb, " DNR");
}