From owner-svn-src-all@freebsd.org Fri Aug 2 20:16:23 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 257D4BA6FC; Fri, 2 Aug 2019 20:16:23 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 460dj30sz5z4Rvd; Fri, 2 Aug 2019 20:16:23 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id F38007E81; Fri, 2 Aug 2019 20:16:22 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x72KGMAc005588; Fri, 2 Aug 2019 20:16:22 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x72KGL6S005582; Fri, 2 Aug 2019 20:16:21 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201908022016.x72KGL6S005582@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Fri, 2 Aug 2019 20:16:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r350541 - in head: sbin/nvmecontrol sys/dev/nvme X-SVN-Group: head X-SVN-Commit-Author: mav X-SVN-Commit-Paths: in head: sbin/nvmecontrol sys/dev/nvme X-SVN-Commit-Revision: 350541 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Aug 2019 20:16:23 -0000 Author: mav Date: Fri Aug 2 20:16:21 2019 New Revision: 350541 URL: https://svnweb.freebsd.org/changeset/base/350541 Log: Decode few more NVMe log pages. In particular: Changed Namespace List, Commands Supported and Effects, Reservation Notification, Sanitize Status. Add few new arguments to `nvmecontrol log` subcommand. MFC after: 2 weeks Sponsored by: iXsystems, Inc. Modified: head/sbin/nvmecontrol/firmware.c head/sbin/nvmecontrol/logpage.c head/sbin/nvmecontrol/nvmecontrol.8 head/sbin/nvmecontrol/nvmecontrol.h head/sys/dev/nvme/nvme.h head/sys/dev/nvme/nvme_ctrlr.c Modified: head/sbin/nvmecontrol/firmware.c ============================================================================== --- head/sbin/nvmecontrol/firmware.c Fri Aug 2 18:01:47 2019 (r350540) +++ head/sbin/nvmecontrol/firmware.c Fri Aug 2 20:16:21 2019 (r350541) @@ -104,7 +104,7 @@ slot_has_valid_firmware(int fd, int slot) int has_fw = false; read_logpage(fd, NVME_LOG_FIRMWARE_SLOT, - NVME_GLOBAL_NAMESPACE_TAG, &fw, sizeof(fw)); + NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0, &fw, sizeof(fw)); if (fw.revision[slot-1] != 0LLU) has_fw = true; Modified: head/sbin/nvmecontrol/logpage.c ============================================================================== --- head/sbin/nvmecontrol/logpage.c Fri Aug 2 18:01:47 2019 (r350540) +++ head/sbin/nvmecontrol/logpage.c Fri Aug 2 20:16:21 2019 (r350541) @@ -6,6 +6,7 @@ * * Copyright (C) 2012-2013 Intel Corporation * All rights reserved. + * Copyright (C) 2018-2019 Alexander Motin * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,12 +58,18 @@ static struct options { bool binary; bool hex; uint32_t page; + uint8_t lsp; + uint16_t lsi; + bool rae; const char *vendor; const char *dev; } opt = { .binary = false, .hex = false, .page = NONE, + .lsp = 0, + .lsi = 0, + .rae = false, .vendor = NULL, .dev = NULL, }; @@ -75,6 +82,12 @@ static const struct opts logpage_opts[] = { "Dump the log page as hex"), OPT("page", 'p', arg_uint32, opt, page, "Page to dump"), + OPT("lsp", 'f', arg_uint8, opt, lsp, + "Log Specific Field"), + OPT("lsi", 'i', arg_uint16, opt, lsp, + "Log Specific Identifier"), + OPT("rae", 'r', arg_none, opt, rae, + "Retain Asynchronous Event"), OPT("vendor", 'v', arg_string, opt, vendor, "Vendor specific formatting"), { NULL, 0, arg_none, NULL, NULL } @@ -103,11 +116,38 @@ CMD_COMMAND(logpage_cmd); static SLIST_HEAD(,logpage_function) logpages; +static int +logpage_compare(struct logpage_function *a, struct logpage_function *b) +{ + int c; + + if ((a->vendor == NULL) != (b->vendor == NULL)) + return (a->vendor == NULL ? -1 : 1); + if (a->vendor != NULL) { + c = strcmp(a->vendor, b->vendor); + if (c != 0) + return (c); + } + return ((int)a->log_page - (int)b->log_page); +} + void logpage_register(struct logpage_function *p) { + struct logpage_function *l, *a; - SLIST_INSERT_HEAD(&logpages, p, link); + a = NULL; + l = SLIST_FIRST(&logpages); + while (l != NULL) { + if (logpage_compare(l, p) > 0) + break; + a = l; + l = SLIST_NEXT(l, link); + } + if (a == NULL) + SLIST_INSERT_HEAD(&logpages, p, link); + else + SLIST_INSERT_AFTER(a, p, link); } const char * @@ -150,19 +190,28 @@ get_log_buffer(uint32_t size) } void -read_logpage(int fd, uint8_t log_page, uint32_t nsid, void *payload, - uint32_t payload_size) +read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp, + uint16_t lsi, uint8_t rae, void *payload, uint32_t payload_size) { struct nvme_pt_command pt; struct nvme_error_information_entry *err_entry; - int i, err_pages; + u_int i, err_pages, numd; + numd = payload_size / sizeof(uint32_t) - 1; memset(&pt, 0, sizeof(pt)); pt.cmd.opc = NVME_OPC_GET_LOG_PAGE; pt.cmd.nsid = htole32(nsid); - pt.cmd.cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16; - pt.cmd.cdw10 |= log_page; - pt.cmd.cdw10 = htole32(pt.cmd.cdw10); + pt.cmd.cdw10 = htole32( + (numd << 16) | /* NUMDL */ + (rae << 15) | /* RAE */ + (lsp << 8) | /* LSP */ + log_page); /* LID */ + pt.cmd.cdw11 = htole32( + ((uint32_t)lsi << 16) | /* LSI */ + (numd >> 16)); /* NUMDU */ + pt.cmd.cdw12 = 0; /* LPOL */ + pt.cmd.cdw13 = 0; /* LPOU */ + pt.cmd.cdw14 = 0; /* UUID Index */ pt.buf = payload; pt.len = payload_size; pt.is_read = 1; @@ -186,6 +235,21 @@ read_logpage(int fd, uint8_t log_page, uint32_t nsid, nvme_firmware_page_swapbytes( (struct nvme_firmware_page *)payload); break; + case NVME_LOG_CHANGED_NAMESPACE: + nvme_ns_list_swapbytes((struct nvme_ns_list *)payload); + break; + case NVME_LOG_COMMAND_EFFECT: + nvme_command_effects_page_swapbytes( + (struct nvme_command_effects_page *)payload); + break; + case NVME_LOG_RES_NOTIFICATION: + nvme_res_notification_page_swapbytes( + (struct nvme_res_notification_page *)payload); + break; + case NVME_LOG_SANITIZE_STATUS: + nvme_sanitize_status_page_swapbytes( + (struct nvme_sanitize_status_page *)payload); + break; case INTEL_LOG_TEMP_STATS: intel_log_temp_stats_swapbytes( (struct intel_log_temp_stats *)payload); @@ -369,6 +433,160 @@ print_log_firmware(const struct nvme_controller_data * } } +static void +print_log_ns(const struct nvme_controller_data *cdata __unused, void *buf, + uint32_t size __unused) +{ + struct nvme_ns_list *nsl; + u_int i; + + nsl = (struct nvme_ns_list *)buf; + printf("Changed Namespace List\n"); + printf("======================\n"); + + for (i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) { + printf("%08x\n", nsl->ns[i]); + } +} + +static void +print_log_command_effects(const struct nvme_controller_data *cdata __unused, + void *buf, uint32_t size __unused) +{ + struct nvme_command_effects_page *ce; + u_int i; + uint32_t s; + + ce = (struct nvme_command_effects_page *)buf; + printf("Commands Supported and Effects\n"); + printf("==============================\n"); + printf(" Command\tLBCC\tNCC\tNIC\tCCC\tCSE\tUUID\n"); + + for (i = 0; i < 255; i++) { + s = ce->acs[i]; + if (((s >> NVME_CE_PAGE_CSUP_SHIFT) & + NVME_CE_PAGE_CSUP_MASK) == 0) + continue; + printf("Admin\t%02x\t%s\t%s\t%s\t%s\t%u\t%s\n", i, + ((s >> NVME_CE_PAGE_LBCC_SHIFT) & + NVME_CE_PAGE_LBCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_NCC_SHIFT) & + NVME_CE_PAGE_NCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_NIC_SHIFT) & + NVME_CE_PAGE_NIC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_CCC_SHIFT) & + NVME_CE_PAGE_CCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_CSE_SHIFT) & + NVME_CE_PAGE_CSE_MASK), + ((s >> NVME_CE_PAGE_UUID_SHIFT) & + NVME_CE_PAGE_UUID_MASK) ? "Yes" : "No"); + } + for (i = 0; i < 255; i++) { + s = ce->iocs[i]; + if (((s >> NVME_CE_PAGE_CSUP_SHIFT) & + NVME_CE_PAGE_CSUP_MASK) == 0) + continue; + printf("I/O\t%02x\t%s\t%s\t%s\t%s\t%u\t%s\n", i, + ((s >> NVME_CE_PAGE_LBCC_SHIFT) & + NVME_CE_PAGE_LBCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_NCC_SHIFT) & + NVME_CE_PAGE_NCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_NIC_SHIFT) & + NVME_CE_PAGE_NIC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_CCC_SHIFT) & + NVME_CE_PAGE_CCC_MASK) ? "Yes" : "No", + ((s >> NVME_CE_PAGE_CSE_SHIFT) & + NVME_CE_PAGE_CSE_MASK), + ((s >> NVME_CE_PAGE_UUID_SHIFT) & + NVME_CE_PAGE_UUID_MASK) ? "Yes" : "No"); + } +} + +static void +print_log_res_notification(const struct nvme_controller_data *cdata __unused, + void *buf, uint32_t size __unused) +{ + struct nvme_res_notification_page *rn; + + rn = (struct nvme_res_notification_page *)buf; + printf("Reservation Notification\n"); + printf("========================\n"); + + printf("Log Page Count: %ju\n", rn->log_page_count); + printf("Log Page Type: "); + switch (rn->log_page_type) { + case 0: + printf("Empty Log Page\n"); + break; + case 1: + printf("Registration Preempted\n"); + break; + case 2: + printf("Reservation Released\n"); + break; + case 3: + printf("Reservation Preempted\n"); + break; + default: + printf("Unknown %x\n", rn->log_page_type); + break; + }; + printf("Number of Available Log Pages: %d\n", rn->available_log_pages); + printf("Namespace ID: 0x%x\n", rn->nsid); +} + +static void +print_log_sanitize_status(const struct nvme_controller_data *cdata __unused, + void *buf, uint32_t size __unused) +{ + struct nvme_sanitize_status_page *ss; + u_int p; + + ss = (struct nvme_sanitize_status_page *)buf; + printf("Sanitize Status\n"); + printf("===============\n"); + + printf("Sanitize Progress: %u%% (%u/65535)\n", + (ss->sprog * 100 + 32768) / 65536, ss->sprog); + printf("Sanitize Status: "); + switch ((ss->sstat >> NVME_SS_PAGE_SSTAT_STATUS_SHIFT) & + NVME_SS_PAGE_SSTAT_STATUS_MASK) { + case NVME_SS_PAGE_SSTAT_STATUS_NEVER: + printf("Never sanitized"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_COMPLETED: + printf("Completed"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_INPROG: + printf("In Progress"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_FAILED: + printf("Failed"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_COMPLETEDWD: + printf("Completed with deallocation"); + break; + default: + printf("Unknown"); + break; + } + p = (ss->sstat & NVME_SS_PAGE_SSTAT_PASSES_SHIFT) >> + NVME_SS_PAGE_SSTAT_PASSES_MASK; + if (p > 0) + printf(", %d passes", p); + if ((ss->sstat & NVME_SS_PAGE_SSTAT_GDE_SHIFT) >> + NVME_SS_PAGE_SSTAT_GDE_MASK) + printf(", Global Data Erased"); + printf("\n"); + printf("Sanitize Command Dword 10: 0x%x\n", ss->scdw10); + printf("Time For Overwrite: %u sec\n", ss->etfo); + printf("Time For Block Erase: %u sec\n", ss->etfbe); + printf("Time For Crypto Erase: %u sec\n", ss->etfce); + printf("Time For Overwrite No-Deallocate: %u sec\n", ss->etfownd); + printf("Time For Block Erase No-Deallocate: %u sec\n", ss->etfbewnd); + printf("Time For Crypto Erase No-Deallocate: %u sec\n", ss->etfcewnd); +} + /* * Table of log page printer / sizing. * @@ -384,6 +602,48 @@ NVME_LOGPAGE(health, NVME_LOGPAGE(fw, NVME_LOG_FIRMWARE_SLOT, NULL, "Firmware Information", print_log_firmware, sizeof(struct nvme_firmware_page)); +NVME_LOGPAGE(ns, + NVME_LOG_CHANGED_NAMESPACE, NULL, "Changed Namespace List", + print_log_ns, sizeof(struct nvme_ns_list)); +NVME_LOGPAGE(ce, + NVME_LOG_COMMAND_EFFECT, NULL, "Commands Supported and Effects", + print_log_command_effects, sizeof(struct nvme_command_effects_page)); +NVME_LOGPAGE(dst, + NVME_LOG_DEVICE_SELF_TEST, NULL, "Device Self-test", + NULL, 564); +NVME_LOGPAGE(thi, + NVME_LOG_TELEMETRY_HOST_INITIATED, NULL, "Telemetry Host-Initiated", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(tci, + NVME_LOG_TELEMETRY_CONTROLLER_INITIATED, NULL, "Telemetry Controller-Initiated", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(egi, + NVME_LOG_ENDURANCE_GROUP_INFORMATION, NULL, "Endurance Group Information", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(plpns, + NVME_LOG_PREDICTABLE_LATENCY_PER_NVM_SET, NULL, "Predictable Latency Per NVM Set", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(ple, + NVME_LOG_PREDICTABLE_LATENCY_EVENT_AGGREGATE, NULL, "Predictable Latency Event Aggregate", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(ana, + NVME_LOG_ASYMMETRIC_NAMESPAVE_ACCESS, NULL, "Asymmetric Namespace Access", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(pel, + NVME_LOG_PERSISTENT_EVENT_LOG, NULL, "Persistent Event Log", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(lbasi, + NVME_LOG_LBA_STATUS_INFORMATION, NULL, "LBA Status Information", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(egea, + NVME_LOG_ENDURANCE_GROUP_EVENT_AGGREGATE, NULL, "Endurance Group Event Aggregate", + NULL, DEFAULT_SIZE); +NVME_LOGPAGE(res_notification, + NVME_LOG_RES_NOTIFICATION, NULL, "Reservation Notification", + print_log_res_notification, sizeof(struct nvme_res_notification_page)); +NVME_LOGPAGE(sanitize_status, + NVME_LOG_SANITIZE_STATUS, NULL, "Sanitize Status", + print_log_sanitize_status, sizeof(struct nvme_sanitize_status_page)); static void logpage_help(void) @@ -475,7 +735,8 @@ logpage(const struct cmd *f, int argc, char *argv[]) continue; if (opt.page != lpf->log_page) continue; - print_fn = lpf->print_fn; + if (lpf->print_fn != NULL) + print_fn = lpf->print_fn; size = lpf->size; break; } @@ -488,7 +749,7 @@ logpage(const struct cmd *f, int argc, char *argv[]) /* Read the log page */ buf = get_log_buffer(size); - read_logpage(fd, opt.page, nsid, buf, size); + read_logpage(fd, opt.page, nsid, opt.lsp, opt.lsi, opt.rae, buf, size); print_fn(&cdata, buf, size); close(fd); Modified: head/sbin/nvmecontrol/nvmecontrol.8 ============================================================================== --- head/sbin/nvmecontrol/nvmecontrol.8 Fri Aug 2 18:01:47 2019 (r350540) +++ head/sbin/nvmecontrol/nvmecontrol.8 Fri Aug 2 20:16:21 2019 (r350541) @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 1, 2019 +.Dd August 2, 2019 .Dt NVMECONTROL 8 .Os .Sh NAME @@ -66,6 +66,9 @@ .Op Fl x .Op Fl v Ar vendor-string .Op Fl b +.Op Fl f Ar LSP +.Op Fl i Ar LSI +.Op Fl r .Aq device id .Aq namespace id .Nm @@ -172,6 +175,14 @@ Drive Error Log Health/SMART Data .It Dv Page 0x03 Firmware Information +.It Dv Page 0x04 +Changed Namespace List +.It Dv Page 0x05 +Commands Supported and Effects +.It Dv Page 0x80 +Reservation Notification +.It Dv Page 0x81 +Sanitize Status .It Dv Page 0xc1 Advanced SMART information (WDC/HGST) .It Dv Page 0xc1 @@ -185,13 +196,19 @@ Advanced SMART information (Intel) .El .Pp Specifying -.Fl p +.Fl v .Ic help will list all valid vendors and pages. .Fl x will print the page as hex. .Fl b will print the binary data for the page. +.Fl s +will set Log Specific Field. +.Fl i +will set Log Specific Identifier. +.Fl r +will set Retain Asynchronous Event. .Ss ns Various namespace management commands. If namespace management is supported by device, allow list, create and delete Modified: head/sbin/nvmecontrol/nvmecontrol.h ============================================================================== --- head/sbin/nvmecontrol/nvmecontrol.h Fri Aug 2 18:01:47 2019 (r350540) +++ head/sbin/nvmecontrol/nvmecontrol.h Fri Aug 2 20:16:21 2019 (r350541) @@ -74,8 +74,8 @@ void read_controller_data(int fd, struct nvme_controll void read_namespace_data(int fd, uint32_t nsid, struct nvme_namespace_data *nsdata); void print_hex(void *data, uint32_t length); void print_namespace(struct nvme_namespace_data *nsdata); -void read_logpage(int fd, uint8_t log_page, uint32_t nsid, void *payload, - uint32_t payload_size); +void read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp, + uint16_t lsi, uint8_t rae, void *payload, uint32_t payload_size); void print_temp(uint16_t t); void print_intel_add_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused); Modified: head/sys/dev/nvme/nvme.h ============================================================================== --- head/sys/dev/nvme/nvme.h Fri Aug 2 18:01:47 2019 (r350540) +++ head/sys/dev/nvme/nvme.h Fri Aug 2 20:16:21 2019 (r350541) @@ -445,6 +445,35 @@ enum nvme_critical_warning_state { #define NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT (0) #define NVME_FIRMWARE_PAGE_AFI_SLOT_MASK (0x7) +/* Commands Supported and Effects */ +#define NVME_CE_PAGE_CSUP_SHIFT (0) +#define NVME_CE_PAGE_CSUP_MASK (0x1) +#define NVME_CE_PAGE_LBCC_SHIFT (1) +#define NVME_CE_PAGE_LBCC_MASK (0x1) +#define NVME_CE_PAGE_NCC_SHIFT (2) +#define NVME_CE_PAGE_NCC_MASK (0x1) +#define NVME_CE_PAGE_NIC_SHIFT (3) +#define NVME_CE_PAGE_NIC_MASK (0x1) +#define NVME_CE_PAGE_CCC_SHIFT (4) +#define NVME_CE_PAGE_CCC_MASK (0x1) +#define NVME_CE_PAGE_CSE_SHIFT (16) +#define NVME_CE_PAGE_CSE_MASK (0x7) +#define NVME_CE_PAGE_UUID_SHIFT (19) +#define NVME_CE_PAGE_UUID_MASK (0x1) + +/* Sanitize Status */ +#define NVME_SS_PAGE_SSTAT_STATUS_SHIFT (0) +#define NVME_SS_PAGE_SSTAT_STATUS_MASK (0x7) +#define NVME_SS_PAGE_SSTAT_STATUS_NEVER (0) +#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETED (1) +#define NVME_SS_PAGE_SSTAT_STATUS_INPROG (2) +#define NVME_SS_PAGE_SSTAT_STATUS_FAILED (3) +#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETEDWD (4) +#define NVME_SS_PAGE_SSTAT_PASSES_SHIFT (3) +#define NVME_SS_PAGE_SSTAT_PASSES_MASK (0x1f) +#define NVME_SS_PAGE_SSTAT_GDE_SHIFT (8) +#define NVME_SS_PAGE_SSTAT_GDE_MASK (0x1) + /* CC register SHN field values */ enum shn_value { NVME_SHN_NORMAL = 0x1, @@ -1291,6 +1320,43 @@ struct nvme_ns_list { _Static_assert(sizeof(struct nvme_ns_list) == 4096, "bad size for nvme_ns_list"); +struct nvme_command_effects_page { + uint32_t acs[256]; + uint32_t iocs[256]; + uint8_t reserved[2048]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_command_effects_page) == 4096, + "bad size for nvme_command_effects_page"); + +struct nvme_res_notification_page { + uint64_t log_page_count; + uint8_t log_page_type; + uint8_t available_log_pages; + uint8_t reserved2; + uint32_t nsid; + uint8_t reserved[48]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_res_notification_page) == 64, + "bad size for nvme_res_notification_page"); + +struct nvme_sanitize_status_page { + uint16_t sprog; + uint16_t sstat; + uint32_t scdw10; + uint32_t etfo; + uint32_t etfbe; + uint32_t etfce; + uint32_t etfownd; + uint32_t etfbewnd; + uint32_t etfcewnd; + uint8_t reserved[480]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_sanitize_status_page) == 512, + "bad size for nvme_sanitize_status_page"); + struct intel_log_temp_stats { uint64_t current; @@ -1717,6 +1783,38 @@ void nvme_ns_list_swapbytes(struct nvme_ns_list *s) for (i = 0; i < 1024; i++) s->ns[i] = le32toh(s->ns[i]); +} + +static inline +void nvme_command_effects_page_swapbytes(struct nvme_command_effects_page *s) +{ + int i; + + for (i = 0; i < 256; i++) + s->acs[i] = le32toh(s->acs[i]); + for (i = 0; i < 256; i++) + s->iocs[i] = le32toh(s->iocs[i]); +} + +static inline +void nvme_res_notification_page_swapbytes(struct nvme_res_notification_page *s) +{ + s->log_page_count = le64toh(s->log_page_count); + s->nsid = le32toh(s->nsid); +} + +static inline +void nvme_sanitize_status_page_swapbytes(struct nvme_sanitize_status_page *s) +{ + s->sprog = le16toh(s->sprog); + s->sstat = le16toh(s->sstat); + s->scdw10 = le32toh(s->scdw10); + s->etfo = le32toh(s->etfo); + s->etfbe = le32toh(s->etfbe); + s->etfce = le32toh(s->etfce); + s->etfownd = le32toh(s->etfownd); + s->etfbewnd = le32toh(s->etfbewnd); + s->etfcewnd = le32toh(s->etfcewnd); } static inline Modified: head/sys/dev/nvme/nvme_ctrlr.c ============================================================================== --- head/sys/dev/nvme/nvme_ctrlr.c Fri Aug 2 18:01:47 2019 (r350540) +++ head/sys/dev/nvme/nvme_ctrlr.c Fri Aug 2 20:16:21 2019 (r350541) @@ -570,6 +570,9 @@ is_log_page_id_valid(uint8_t page_id) case NVME_LOG_HEALTH_INFORMATION: case NVME_LOG_FIRMWARE_SLOT: case NVME_LOG_CHANGED_NAMESPACE: + case NVME_LOG_COMMAND_EFFECT: + case NVME_LOG_RES_NOTIFICATION: + case NVME_LOG_SANITIZE_STATUS: return (TRUE); } @@ -596,6 +599,15 @@ nvme_ctrlr_get_log_page_size(struct nvme_controller *c case NVME_LOG_CHANGED_NAMESPACE: log_page_size = sizeof(struct nvme_ns_list); break; + case NVME_LOG_COMMAND_EFFECT: + log_page_size = sizeof(struct nvme_command_effects_page); + break; + case NVME_LOG_RES_NOTIFICATION: + log_page_size = sizeof(struct nvme_res_notification_page); + break; + case NVME_LOG_SANITIZE_STATUS: + log_page_size = sizeof(struct nvme_sanitize_status_page); + break; default: log_page_size = 0; break; @@ -665,6 +677,18 @@ nvme_ctrlr_async_event_log_page_cb(void *arg, const st case NVME_LOG_CHANGED_NAMESPACE: nvme_ns_list_swapbytes( (struct nvme_ns_list *)aer->log_page_buffer); + break; + case NVME_LOG_COMMAND_EFFECT: + nvme_command_effects_page_swapbytes( + (struct nvme_command_effects_page *)aer->log_page_buffer); + break; + case NVME_LOG_RES_NOTIFICATION: + nvme_res_notification_page_swapbytes( + (struct nvme_res_notification_page *)aer->log_page_buffer); + break; + case NVME_LOG_SANITIZE_STATUS: + nvme_sanitize_status_page_swapbytes( + (struct nvme_sanitize_status_page *)aer->log_page_buffer); break; case INTEL_LOG_TEMP_STATS: intel_log_temp_stats_swapbytes(