diff options
author | Robert Mustacchi <rm@joyent.com> | 2018-08-01 00:11:50 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2018-09-22 20:16:33 +0000 |
commit | 48d370f1e98a10b1bdf160dd83a49e0f49f6c1b7 (patch) | |
tree | a80f0daa452ed5cfdc9eed874f09591add44c2f2 | |
parent | fd6d41c5025e9fb45a115fc82d86e9983d1e9fd6 (diff) | |
download | illumos-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/Makefile | 6 | ||||
-rw-r--r-- | usr/src/man/man7d/nvme.7d | 7 | ||||
-rw-r--r-- | usr/src/uts/common/io/nvme/nvme.c | 34 | ||||
-rw-r--r-- | usr/src/uts/common/io/nvme/nvme_reg.h | 80 | ||||
-rw-r--r-- | usr/src/uts/common/sys/nvme.h | 92 |
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 |