Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Aug 2019 20:16:21 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
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
Message-ID:  <201908022016.x72KGL6S005582@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <mav@FreeBSD.org>
  *
  * 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(



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908022016.x72KGL6S005582>