summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2018-08-01 00:11:50 +0000
committerRobert Mustacchi <rm@joyent.com>2018-09-22 20:16:33 +0000
commit48d370f1e98a10b1bdf160dd83a49e0f49f6c1b7 (patch)
treea80f0daa452ed5cfdc9eed874f09591add44c2f2
parentfd6d41c5025e9fb45a115fc82d86e9983d1e9fd6 (diff)
downloadillumos-joyent-48d370f1e98a10b1bdf160dd83a49e0f49f6c1b7.tar.gz
9809 nvme driver should attach to all NVMe 1.x devices
9810 Update parts of NVMe headers for newer specs 9811 nvmeadm(1M) should have ctf Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Yuri Pankov <yuripv@yuripv.net> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/cmd/nvmeadm/Makefile6
-rw-r--r--usr/src/man/man7d/nvme.7d7
-rw-r--r--usr/src/uts/common/io/nvme/nvme.c34
-rw-r--r--usr/src/uts/common/io/nvme/nvme_reg.h80
-rw-r--r--usr/src/uts/common/sys/nvme.h92
5 files changed, 196 insertions, 23 deletions
diff --git a/usr/src/cmd/nvmeadm/Makefile b/usr/src/cmd/nvmeadm/Makefile
index c919c51fce..a0cc24ead0 100644
--- a/usr/src/cmd/nvmeadm/Makefile
+++ b/usr/src/cmd/nvmeadm/Makefile
@@ -11,6 +11,7 @@
#
# Copyright 2015 Nexenta Systems, Inc.
+# Copyright (c) 2018, Joyent, Inc.
#
@@ -20,6 +21,7 @@ OBJS= nvmeadm.o nvmeadm_dev.o nvmeadm_print.o
SRCS= $(OBJS:%.o=%.c)
include ../Makefile.cmd
+include ../Makefile.ctf
.KEEP_STATE:
@@ -33,6 +35,10 @@ $(PROG): $(OBJS)
$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
+%.o: %.c
+ $(COMPILE.c) $<
+ $(POST_PROCESS_O)
+
install: all $(ROOTUSRSBINPROG)
clean:
diff --git a/usr/src/man/man7d/nvme.7d b/usr/src/man/man7d/nvme.7d
index 8043d53b2a..83f72f346a 100644
--- a/usr/src/man/man7d/nvme.7d
+++ b/usr/src/man/man7d/nvme.7d
@@ -10,8 +10,9 @@
.\"
.\"
.\" Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+.\" Copyright (c) 2018, Joyent, Inc.
.\"
-.Dd Mar 30, 2017
+.Dd July 31, 2018
.Dt NVME 7D
.Os
.Sh NAME
@@ -23,7 +24,7 @@ The
driver uses the
.Xr blkdev 7D
framework to provide access to
-.Tn Intel
+Intel
NVMe compliant solid-state storage devices.
.Lp
NVMe devices supporting multiple namespaces will present each
@@ -48,7 +49,7 @@ to attach to devices supporting newer version of the NVMe
specification.
The default value is 1, limiting
.Nm
-to work with devices up to specification version 1.2.
+to work with devices that support major version 1.
.It Va ignore-unknown-vendor-status
This can be set to 1 to allow
.Nm
diff --git a/usr/src/uts/common/io/nvme/nvme.c b/usr/src/uts/common/io/nvme/nvme.c
index ec6d18ca91..e7a1c1542c 100644
--- a/usr/src/uts/common/io/nvme/nvme.c
+++ b/usr/src/uts/common/io/nvme/nvme.c
@@ -13,7 +13,7 @@
* Copyright 2018 Nexenta Systems, Inc.
* Copyright 2016 Tegile Systems, Inc. All rights reserved.
* Copyright (c) 2016 The MathWorks, Inc. All rights reserved.
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -196,7 +196,7 @@
* The following driver properties can be changed to control some aspects of the
* drivers operation:
* - strict-version: can be set to 0 to allow devices conforming to newer
- * versions or namespaces with EUI64 to be used
+ * major versions to be used
* - ignore-unknown-vendor-status: can be set to 1 to not handle any vendor
* specific command status as a fatal error leading device faulting
* - admin-queue-len: the maximum length of the admin queue (16-4096)
@@ -258,10 +258,31 @@
#include "nvme_reg.h"
#include "nvme_var.h"
+/*
+ * Assertions to make sure that we've properly captured various aspects of the
+ * packed structures and haven't broken them during updates.
+ */
+CTASSERT(sizeof (nvme_identify_ctrl_t) == 0x1000);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_oacs) == 256);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_sqes) == 512);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_subnqn) == 768);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_nvmof) == 1792);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_psd) == 2048);
+CTASSERT(offsetof(nvme_identify_ctrl_t, id_vs) == 3072);
+
+CTASSERT(sizeof (nvme_identify_nsid_t) == 0x1000);
+CTASSERT(offsetof(nvme_identify_nsid_t, id_fpi) == 32);
+CTASSERT(offsetof(nvme_identify_nsid_t, id_nguid) == 104);
+CTASSERT(offsetof(nvme_identify_nsid_t, id_lbaf) == 128);
+CTASSERT(offsetof(nvme_identify_nsid_t, id_vs) == 384);
+
+CTASSERT(sizeof (nvme_identify_primary_caps_t) == 0x1000);
+CTASSERT(offsetof(nvme_identify_primary_caps_t, nipc_vqfrt) == 32);
+CTASSERT(offsetof(nvme_identify_primary_caps_t, nipc_vifrt) == 64);
+
/* NVMe spec version supported */
static const int nvme_version_major = 1;
-static const int nvme_version_minor = 2;
/* tunable for admin command timeout in seconds, default is 1s */
int nvme_admin_cmd_timeout = 1;
@@ -2265,10 +2286,9 @@ nvme_init(nvme_t *nvme)
dev_err(nvme->n_dip, CE_CONT, "?NVMe spec version %d.%d",
nvme->n_version.v_major, nvme->n_version.v_minor);
- if (NVME_VERSION_HIGHER(&nvme->n_version,
- nvme_version_major, nvme_version_minor)) {
- dev_err(nvme->n_dip, CE_WARN, "!no support for version > %d.%d",
- nvme_version_major, nvme_version_minor);
+ if (nvme->n_version.v_major > nvme_version_major) {
+ dev_err(nvme->n_dip, CE_WARN, "!no support for version > %d.x",
+ nvme_version_major);
if (nvme->n_strict_version)
goto fail;
}
diff --git a/usr/src/uts/common/io/nvme/nvme_reg.h b/usr/src/uts/common/io/nvme/nvme_reg.h
index acff0e2362..b332863876 100644
--- a/usr/src/uts/common/io/nvme/nvme_reg.h
+++ b/usr/src/uts/common/io/nvme/nvme_reg.h
@@ -11,6 +11,7 @@
/*
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
*/
/*
@@ -47,6 +48,11 @@ extern "C" {
#define NVME_REG_AQA 0x24 /* Admin Queue Attributes */
#define NVME_REG_ASQ 0x28 /* Admin Submission Queue */
#define NVME_REG_ACQ 0x30 /* Admin Completion Qeueu */
+#define NVME_REG_CMBLOC 0x38 /* Controller Memory Buffer Location */
+#define NVME_REG_CMBSZ 0x3C /* Controller Memory Buffer Size */
+#define NVME_REG_BPINFO 0x40 /* Boot Partition Information */
+#define NVME_REG_BPRSEL 0x44 /* Boot Partition Read Select */
+#define NVME_REG_BPMBL 0x48 /* Boot Partition Memory Buffer Loc */
#define NVME_REG_SQTDBL(nvme, n) \
(0x1000 + ((2 * (n)) * nvme->n_doorbell_stride))
#define NVME_REG_CQHDBL(nvme, n) \
@@ -66,7 +72,8 @@ typedef union {
uint16_t cap_dstrd:4; /* Doorbell Stride */
uint16_t cap_nssrs:1; /* NVM Subsystem Reset Supported */
uint16_t cap_css:8; /* Command Sets Supported */
- uint16_t cap_rsvd2:3;
+ uint16_t cap_rsvd2:2;
+ uint8_t cap_bps:1; /* Boot Partition Support */
uint8_t cap_mpsmin:4; /* Memory Page Size Minimum */
uint8_t cap_mpsmax:4; /* Memory Page Size Maximum */
uint8_t cap_rsvd3;
@@ -113,7 +120,8 @@ typedef union {
uint32_t csts_cfs:1; /* Controller Fatal Status */
uint32_t csts_shst:2; /* Shutdown Status */
uint32_t csts_nssro:1; /* NVM Subsystem Reset Occured */
- uint32_t csts_rsvd:27;
+ uint32_t csts_pp:1; /* Processing Paused */
+ uint32_t csts_rsvd:26;
} b;
uint32_t r;
} nvme_reg_csts_t;
@@ -145,6 +153,57 @@ typedef uint64_t nvme_reg_asq_t; /* Admin Submission Queue Base */
/* ACQ -- Admin Completion Queue Base Address */
typedef uint64_t nvme_reg_acq_t; /* Admin Completion Queue Base */
+/* CMBLOC - Controller Memory Buffer Location */
+typedef union {
+ struct {
+ uint32_t cmbloc_bir:3; /* Base Indicator Register */
+ uint32_t cmbloc_rsvd:9;
+ uint32_t cmbloc_ofst:20; /* Offset */
+ } b;
+ uint32_t r;
+} nvme_reg_cmbloc_t;
+
+/* CMBSZ - Controller Memory Buffer Size */
+typedef union {
+ struct {
+ uint32_t cmbsz_sqs:1; /* Submission Queue Support */
+ uint32_t cmbsz_cqs:1; /* Completion Queue Support */
+ uint32_t cmbsz_lists:1; /* PRP SGL List Support */
+ uint32_t cmbsz_rds:1; /* Read Data Support */
+ uint32_t cmbsz_wds:1; /* Write Data Support */
+ uint32_t cmbsz_rsvd:3;
+ uint32_t cmbsz_szu:4; /* Size Units */
+ uint32_t cmbsz_sz:20; /* Size */
+ } b;
+ uint32_t r;
+} nvme_reg_cmbsz_t;
+
+/* BPINFO - Boot Partition Information */
+typedef union {
+ struct {
+ uint32_t bpinfo_bpsz:15; /* Boot Partition Size */
+ uint32_t bpinfo_rsvd:9;
+ uint32_t bpinfo_brs:2; /* Boot Read Status */
+ uint32_t bpinfo_rsvd2:5;
+ uint32_t bpinfo_abpid:1; /* Active Boot Partition ID */
+ } b;
+ uint32_t r;
+} nvme_reg_bpinfo_t;
+
+/* BPRSEL - Boot Partition Read Select */
+typedef union {
+ struct {
+ uint32_t bprsel_bprsz:10; /* Boot Partition Read Size */
+ uint32_t bprsel_bprof:20; /* Boot Partition Read Offset */
+ uint32_t bprsel_rsvd:1;
+ uint32_t bprsel_bpid:1; /* Boot Partition Identifier */
+ } b;
+ uint32_t r;
+} nvme_reg_bprsel_t;
+
+/* BPMBL - Boot Partition Memory Location Buffer Location */
+typedef uint64_t nvme_reg_bpbml_t; /* Memory Buffer Base Address */
+
/* SQyTDBL -- Submission Queue y Tail Doorbell */
typedef union {
struct {
@@ -219,8 +278,18 @@ typedef struct {
#define NVME_OPC_SET_FEATURES 0x9
#define NVME_OPC_GET_FEATURES 0xa
#define NVME_OPC_ASYNC_EVENT 0xc
+#define NVME_OPC_NS_MGMT 0xd /* 1.2 */
#define NVME_OPC_FW_ACTIVATE 0x10
#define NVME_OPC_FW_IMAGE_LOAD 0x11
+#define NVME_OPC_SELF_TEST 0x14 /* 1.3 */
+#define NVME_OPC_NS_ATTACH 0x15 /* 1.2 */
+#define NVME_OPC_KEEP_ALIVE 0x18 /* 1.3 */
+#define NVME_OPC_DIRECTIVE_SEND 0x19 /* 1.3 */
+#define NVME_OPC_DIRECTIVE_RECV 0x1A /* 1.3 */
+#define NVME_OPC_VIRT_MGMT 0x1C /* 1.3 */
+#define NVME_OPC_NVMEMI_SEND 0x1D /* 1.3 */
+#define NVME_OPC_NVMEMI_RECV 0x1E /* 1.3 */
+#define NVME_OPC_DB_CONFIG 0x7C /* 1.3 */
/* NVMe NVM command set specific admin command opcodes */
#define NVME_OPC_NVM_FORMAT 0x80
@@ -351,7 +420,7 @@ typedef union {
typedef union {
struct {
uint16_t q_qid; /* Queue Identifier */
- uint16_t q_qsize; /* Queue Size */
+ uint16_t q_qsize; /* Queue Size */
} b;
uint32_t r;
} nvme_create_queue_dw10_t;
@@ -385,6 +454,11 @@ typedef union {
#define NVME_IDENTIFY_CTRL 0x1 /* Identify Controller */
#define NVME_IDENTIFY_LIST 0x2 /* Identify List Namespaces */
+#define NVME_IDENTIFY_NSID_ALLOC_LIST 0x10 /* List Allocated NSID */
+#define NVME_IDENTIFY_NSID_ALLOC 0x11 /* Identify Allocated NSID */
+#define NVME_IDENTIFY_NSID_CTRL_LIST 0x12 /* List Controllers on NSID */
+#define NVME_IDENTIFY_CTRL_LIST 0x13 /* Controller List */
+#define NVME_IDENTIFY_PRIMARY_CAPS 0x14 /* Primary Controller Caps */
/*
* NVMe Abort Command
diff --git a/usr/src/uts/common/sys/nvme.h b/usr/src/uts/common/sys/nvme.h
index 916b439f3f..98f203ef10 100644
--- a/usr/src/uts/common/sys/nvme.h
+++ b/usr/src/uts/common/sys/nvme.h
@@ -11,6 +11,7 @@
/*
* Copyright 2016 Nexenta Systems, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#ifndef _SYS_NVME_H
@@ -122,14 +123,22 @@ typedef struct {
uint8_t psd_rsvd5:3;
uint8_t psd_rwl:5; /* Relative Write Latency */
uint8_t psd_rsvd6:3;
- uint8_t psd_rsvd7[16];
+ uint16_t psd_idlp; /* Idle Power (1.2) */
+ uint8_t psd_rsvd7:6;
+ uint8_t psd_ips:2; /* Idle Power Scale (1.2) */
+ uint8_t psd_rsvd8;
+ uint16_t psd_actp; /* Active Power (1.2) */
+ uint8_t psd_apw:3; /* Active Power Workload (1.2) */
+ uint8_t psd_rsvd9:3;
+ uint8_t psd_aps:2; /* Active Power Scale */
+ uint8_t psd_rsvd10[9];
} nvme_idctl_psd_t;
/* NVMe Identify Controller Data Structure */
typedef struct {
/* Controller Capabilities & Features */
uint16_t id_vid; /* PCI vendor ID */
- uint16_t id_ssvid; /* PCI subsystem vendor ID */
+ uint16_t id_ssvid; /* PCI subsystem vendor ID */
char id_serial[20]; /* Serial Number */
char id_model[40]; /* Model Number */
char id_fwrev[8]; /* Firmware Revision */
@@ -143,7 +152,18 @@ typedef struct {
} id_mic;
uint8_t id_mdts; /* Maximum Data Transfer Size */
uint16_t id_cntlid; /* Unique Controller Identifier (1.1) */
- uint8_t id_rsvd_cc[256 - 80];
+ /* Added in NVMe 1.2 */
+ uint32_t id_ver; /* Version */
+ uint32_t id_rtd3r; /* RTD3 Resume Latency */
+ uint32_t id_rtd3e; /* RTD3 Entry Latency */
+ uint32_t id_oaes; /* Optional Asynchronous Events */
+ /* Added in NVMe 1.3 */
+ uint32_t id_ctratt; /* Controller Attributes */
+ uint8_t id_rsvd_cc[12];
+ uint8_t id_frguid[16]; /* FRU GUID */
+ uint8_t id_rsvd2_cc[240 - 128];
+ uint8_t id_rsvd_nvmemi[255 - 240];
+ uint8_t id_mec; /* Management Endpiont Capabilities */
/* Admin Command Set Attributes */
struct { /* Optional Admin Command Support */
@@ -173,12 +193,30 @@ typedef struct {
uint8_t ap_sup:1; /* APST supported (1.1) */
uint8_t ap_rsvd:7;
} id_apsta;
- uint8_t id_rsvd_ac[256 - 10];
+ /* Added in NVMe 1.2 */
+ uint16_t ap_wctemp; /* Warning Composite Temperature */
+ uint16_t ap_cctemp; /* Critical Composite Temperature */
+ uint16_t ap_mtfa; /* Maximum Firmware Activation Time */
+ uint32_t ap_hmpre; /* Host Memory Buffer Preferred Size */
+ uint32_t ap_hmmin; /* Host Memory Buffer Min Size */
+ uint8_t ap_tnvmcap[16]; /* Total NVM Capacity in Bytes */
+ uint8_t ap_unvmcap[16]; /* Unallocated NVM Capacity */
+ uint32_t ap_rpmbs; /* Replay Protected Memory Block */
+ /* Added in NVMe 1.3 */
+ uint16_t ap_edstt; /* Extended Device Self-test time */
+ uint8_t ap_dsto; /* Device Self-test Options */
+ uint8_t ap_fwug; /* Firmware Update Granularity */
+ uint16_t ap_kas; /* Keep Alive Support */
+ uint16_t ap_hctma; /* Host Thermal Management */
+ uint16_t ap_mntmt; /* Minimum Thermal Temperature */
+ uint16_t ap_mxtmt; /* Maximum Thermal Temperature */
+ uint32_t ap_sanitize; /* Sanitize Caps */
+ uint8_t id_rsvd_ac[512 - 332];
/* NVM Command Set Attributes */
nvme_idctl_qes_t id_sqes; /* Submission Queue Entry Size */
nvme_idctl_qes_t id_cqes; /* Completion Queue Entry Size */
- uint16_t id_rsvd_nc_1;
+ uint16_t id_maxcmd; /* Max Outstanding Commands (1.3) */
uint32_t id_nn; /* Number of Namespaces */
struct { /* Optional NVM Command Support */
uint16_t on_compare:1; /* Compare */
@@ -218,10 +256,12 @@ typedef struct {
uint16_t sgl_bucket:1; /* SGL Bit Bucket supported (1.1) */
uint16_t sgl_rsvd2:15;
} id_sgls;
- uint8_t id_rsvd_nc_4[192 - 28];
+ uint8_t id_rsvd_nc_4[768 - 540];
/* I/O Command Set Attributes */
- uint8_t id_rsvd_ioc[1344];
+ uint8_t id_subnqn[1024 - 768]; /* Subsystem Qualified Name (1.2.1+) */
+ uint8_t id_rsvd_ioc[1792 - 1024];
+ uint8_t id_nvmof[2048 - 1792]; /* NVMe over Fabrics */
/* Power State Descriptors */
nvme_idctl_psd_t id_psd[32];
@@ -285,15 +325,47 @@ typedef struct {
uint8_t rc_excl_a:1; /* Excl Acc - All Registrants (1.1) */
uint8_t rc_rsvd:1;
} id_rescap;
- uint8_t id_rsvd1[120 - 32];
+ uint8_t id_fpi; /* Format Progress Indicator (1.2) */
+ uint8_t id_dfleat; /* Deallocate Log. Block (1.3) */
+ uint16_t id_nawun; /* Atomic Write Unit Normal (1.2) */
+ uint16_t id_nawupf; /* Atomic Write Unit Power Fail (1.2) */
+ uint16_t id_nacwu; /* Atomic Compare & Write Unit (1.2) */
+ uint16_t id_nabsn; /* Atomic Boundary Size Normal (1.2) */
+ uint16_t id_nbao; /* Atomic Boundary Offset (1.2) */
+ uint16_t id_nabspf; /* Atomic Boundary Size Fail (1.2) */
+ uint16_t id_noiob; /* Optimal I/O Bondary (1.3) */
+ uint8_t id_nvmcap[16]; /* NVM Capacity */
+ uint8_t id_rsvd1[104 - 64];
+ uint8_t id_nguid[16]; /* Namespace GUID (1.2) */
uint8_t id_eui64[8]; /* IEEE Extended Unique Id (1.1) */
nvme_idns_lbaf_t id_lbaf[16]; /* LBA Formats */
- uint8_t id_rsvd2[192];
+ uint8_t id_rsvd2[384 - 192];
- uint8_t id_vs[3712]; /* Vendor Specific */
+ uint8_t id_vs[4096 - 384]; /* Vendor Specific */
} nvme_identify_nsid_t;
+/* NVMe Identify Primary Controller Capabilities */
+typedef struct {
+ uint16_t nipc_cntlid; /* Controller ID */
+ uint16_t nipc_portid; /* Port Identifier */
+ uint8_t nipc_crt; /* Controller Resource Types */
+ uint8_t nipc_rsvd0[32 - 5];
+ uint32_t nipc_vqfrt; /* VQ Resources Flexible Total */
+ uint32_t nipc_vqrfa; /* VQ Resources Flexible Assigned */
+ uint16_t nipc_vqrfap; /* VQ Resources to Primary */
+ uint16_t nipc_vqprt; /* VQ Resources Private Total */
+ uint16_t nipc_vqfrsm; /* VQ Resources Secondary Max */
+ uint16_t nipc_vqgran; /* VQ Flexible Resource Gran */
+ uint8_t nipc_rvsd1[64 - 48];
+ uint32_t nipc_vifrt; /* VI Flexible total */
+ uint32_t nipc_virfa; /* VI Flexible Assigned */
+ uint16_t nipc_virfap; /* VI Flexible Allocatd to Primary */
+ uint16_t nipc_viprt; /* VI Resources Private Total */
+ uint16_t nipc_vifrsm; /* VI Resources Secondary Max */
+ uint16_t nipc_vigran; /* VI Flexible Granularity */
+ uint8_t nipc_rsvd2[4096 - 80];
+} nvme_identify_primary_caps_t;
/*
* NVMe completion queue entry status field