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 <m...@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(
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to