drivers/nvme: Add namespace support
Based on FreeBSD's implementation made by James Harris, Intel Copyright 2012-2016. Namespace in this context, will be a disk. It's not exposed from DTS, as an actualy NVMe hardware controller card can bring more than one namespace (disk). Thus namespace are not instanciated through the device driver model, but statically allocated and runtime configured, depending on what the controller exposes. By default the amount of namespace supported is one as it is the most common setup. Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
7499fae5cd
commit
22db7b76ad
9 changed files with 518 additions and 3 deletions
|
|
@ -1,4 +1,9 @@
|
|||
# Copyright (c) 2022 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library_sources(nvme_controller.c nvme_cmd.c nvme_controller_cmd.c)
|
||||
zephyr_library_sources(
|
||||
nvme_controller.c
|
||||
nvme_cmd.c
|
||||
nvme_controller_cmd.c
|
||||
nvme_namespace.c
|
||||
)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,15 @@ config NVME_REQUEST_TIMEOUT
|
|||
This sets the waiting time for a request to succeed.
|
||||
Do not touch this unless you know what you are doing.
|
||||
|
||||
config NVME_MAX_NAMESPACES
|
||||
int "Maximum namespace to allocate"
|
||||
range 1 16
|
||||
default 1
|
||||
help
|
||||
This sets the maximum namespace to allocate. Note that there may
|
||||
be much less to be actually instantiated at runtime.
|
||||
This option can be used to reduce the memory usage a bit then.
|
||||
|
||||
config NVME_INT_PRIORITY
|
||||
int "Interrupt priority"
|
||||
default 2
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@
|
|||
#ifndef ZEPHYR_DRIVERS_DISK_NVME_NHME_H_
|
||||
#define ZEPHYR_DRIVERS_DISK_NVME_NVME_H_
|
||||
|
||||
#include "nvme_helpers.h"
|
||||
#include "nvme_cmd.h"
|
||||
#include "nvme_namespace.h"
|
||||
|
||||
struct nvme_registers {
|
||||
uint32_t cap_lo; /* controller capabilities */
|
||||
|
|
@ -444,6 +446,16 @@ struct nvme_controller {
|
|||
|
||||
/** maximum i/o size in bytes */
|
||||
uint32_t max_xfer_size;
|
||||
|
||||
struct nvme_namespace ns[CONFIG_NVME_MAX_NAMESPACES];
|
||||
};
|
||||
|
||||
static inline
|
||||
bool nvme_controller_has_dataset_mgmt(struct nvme_controller *ctrlr)
|
||||
{
|
||||
/* Assumes cd was byte swapped by nvme_controller_data_swapbytes() */
|
||||
return ((ctrlr->cdata.oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) &
|
||||
NVME_CTRLR_DATA_ONCS_DSM_MASK);
|
||||
}
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_DISK_NVME_NHME_H_ */
|
||||
|
|
|
|||
|
|
@ -382,6 +382,10 @@ int nvme_cmd_identify_controller(struct nvme_controller *ctrlr,
|
|||
int nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
|
||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||
|
||||
int nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
|
||||
uint32_t nsid, void *payload,
|
||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||
|
||||
int nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
|
||||
struct nvme_cmd_qpair *io_queue,
|
||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||
|
|
|
|||
|
|
@ -394,6 +394,22 @@ static int nvme_controller_identify(struct nvme_controller *nvme_ctrlr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nvme_controller_setup_namespaces(struct nvme_controller *nvme_ctrlr)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0;
|
||||
i < MIN(nvme_ctrlr->cdata.nn, CONFIG_NVME_MAX_NAMESPACES); i++) {
|
||||
struct nvme_namespace *ns = &nvme_ctrlr->ns[i];
|
||||
|
||||
if (nvme_namespace_construct(ns, i+1, nvme_ctrlr) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DBG("Namespace id %u setup and running", i);
|
||||
}
|
||||
}
|
||||
|
||||
static int nvme_controller_init(const struct device *dev)
|
||||
{
|
||||
struct nvme_controller *nvme_ctrlr = dev->data;
|
||||
|
|
@ -437,6 +453,8 @@ static int nvme_controller_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
nvme_controller_setup_namespaces(nvme_ctrlr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
* Copyright (c) 2022 Intel Corp.
|
||||
*/
|
||||
|
||||
#define LOG_LEVEL CONFIG_NVME_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(nvme_ctrlr_cmd);
|
||||
LOG_MODULE_DECLARE(nvme, CONFIG_NVME_LOG_LEVEL);
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "nvme.h"
|
||||
#include "nvme_helpers.h"
|
||||
|
||||
|
|
@ -32,6 +33,28 @@ int nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
|
|||
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
|
||||
}
|
||||
|
||||
int nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
|
||||
uint32_t nsid, void *payload,
|
||||
nvme_cb_fn_t cb_fn, void *cb_arg)
|
||||
{
|
||||
struct nvme_request *request;
|
||||
|
||||
request = nvme_allocate_request_vaddr(
|
||||
payload, sizeof(struct nvme_namespace_data),
|
||||
cb_fn, cb_arg);
|
||||
if (!request) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
request->cmd.cdw0.opc = NVME_OPC_IDENTIFY;
|
||||
/*
|
||||
* TODO: create an identify command data structure
|
||||
*/
|
||||
request->cmd.nsid = sys_cpu_to_le32(nsid);
|
||||
|
||||
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
|
||||
}
|
||||
|
||||
int nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
|
||||
struct nvme_cmd_qpair *io_queue,
|
||||
nvme_cb_fn_t cb_fn, void *cb_arg)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@
|
|||
#define NVME_MAJOR(r) (((r) >> 16) & 0xffff)
|
||||
#define NVME_MINOR(r) (((r) >> 8) & 0xff)
|
||||
|
||||
/*
|
||||
* Use to mark a command to apply to all namespaces, or to retrieve global
|
||||
* log pages.
|
||||
*/
|
||||
#define NVME_GLOBAL_NAMESPACE_TAG ((uint32_t)0xFFFFFFFF)
|
||||
|
||||
/* Many items are expressed in terms of power of two times MPS */
|
||||
#define NVME_MPS_SHIFT 12
|
||||
|
||||
|
|
@ -342,6 +348,127 @@
|
|||
#define NVME_CTRLR_DATA_VWC_ALL_NO (2)
|
||||
#define NVME_CTRLR_DATA_VWC_ALL_YES (3)
|
||||
|
||||
/** namespace features */
|
||||
/* thin provisioning */
|
||||
#define NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT (0)
|
||||
#define NVME_NS_DATA_NSFEAT_THIN_PROV_MASK (0x1)
|
||||
/* NAWUN, NAWUPF, and NACWU fields are valid */
|
||||
#define NVME_NS_DATA_NSFEAT_NA_FIELDS_SHIFT (1)
|
||||
#define NVME_NS_DATA_NSFEAT_NA_FIELDS_MASK (0x1)
|
||||
/* Deallocated or Unwritten Logical Block errors supported */
|
||||
#define NVME_NS_DATA_NSFEAT_DEALLOC_SHIFT (2)
|
||||
#define NVME_NS_DATA_NSFEAT_DEALLOC_MASK (0x1)
|
||||
/* NGUID and EUI64 fields are not reusable */
|
||||
#define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_SHIFT (3)
|
||||
#define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_MASK (0x1)
|
||||
/* NPWG, NPWA, NPDG, NPDA, and NOWS are valid */
|
||||
#define NVME_NS_DATA_NSFEAT_NPVALID_SHIFT (4)
|
||||
#define NVME_NS_DATA_NSFEAT_NPVALID_MASK (0x1)
|
||||
|
||||
/** formatted lba size */
|
||||
#define NVME_NS_DATA_FLBAS_FORMAT_SHIFT (0)
|
||||
#define NVME_NS_DATA_FLBAS_FORMAT_MASK (0xF)
|
||||
#define NVME_NS_DATA_FLBAS_EXTENDED_SHIFT (4)
|
||||
#define NVME_NS_DATA_FLBAS_EXTENDED_MASK (0x1)
|
||||
|
||||
/** metadata capabilities */
|
||||
/* metadata can be transferred as part of data prp list */
|
||||
#define NVME_NS_DATA_MC_EXTENDED_SHIFT (0)
|
||||
#define NVME_NS_DATA_MC_EXTENDED_MASK (0x1)
|
||||
/* metadata can be transferred with separate metadata pointer */
|
||||
#define NVME_NS_DATA_MC_POINTER_SHIFT (1)
|
||||
#define NVME_NS_DATA_MC_POINTER_MASK (0x1)
|
||||
|
||||
/** end-to-end data protection capabilities */
|
||||
/* protection information type 1 */
|
||||
#define NVME_NS_DATA_DPC_PIT1_SHIFT (0)
|
||||
#define NVME_NS_DATA_DPC_PIT1_MASK (0x1)
|
||||
/* protection information type 2 */
|
||||
#define NVME_NS_DATA_DPC_PIT2_SHIFT (1)
|
||||
#define NVME_NS_DATA_DPC_PIT2_MASK (0x1)
|
||||
/* protection information type 3 */
|
||||
#define NVME_NS_DATA_DPC_PIT3_SHIFT (2)
|
||||
#define NVME_NS_DATA_DPC_PIT3_MASK (0x1)
|
||||
/* first eight bytes of metadata */
|
||||
#define NVME_NS_DATA_DPC_MD_START_SHIFT (3)
|
||||
#define NVME_NS_DATA_DPC_MD_START_MASK (0x1)
|
||||
/* last eight bytes of metadata */
|
||||
#define NVME_NS_DATA_DPC_MD_END_SHIFT (4)
|
||||
#define NVME_NS_DATA_DPC_MD_END_MASK (0x1)
|
||||
|
||||
/** end-to-end data protection type settings */
|
||||
/* protection information type */
|
||||
#define NVME_NS_DATA_DPS_PIT_SHIFT (0)
|
||||
#define NVME_NS_DATA_DPS_PIT_MASK (0x7)
|
||||
/* 1 == protection info transferred at start of metadata */
|
||||
/* 0 == protection info transferred at end of metadata */
|
||||
#define NVME_NS_DATA_DPS_MD_START_SHIFT (3)
|
||||
#define NVME_NS_DATA_DPS_MD_START_MASK (0x1)
|
||||
|
||||
/** Namespace Multi-path I/O and Namespace Sharing Capabilities */
|
||||
/* the namespace may be attached to two or more controllers */
|
||||
#define NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT (0)
|
||||
#define NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK (0x1)
|
||||
|
||||
/** Reservation Capabilities */
|
||||
/* Persist Through Power Loss */
|
||||
#define NVME_NS_DATA_RESCAP_PTPL_SHIFT (0)
|
||||
#define NVME_NS_DATA_RESCAP_PTPL_MASK (0x1)
|
||||
/* supports the Write Exclusive */
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_SHIFT (1)
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_MASK (0x1)
|
||||
/* supports the Exclusive Access */
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_SHIFT (2)
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_MASK (0x1)
|
||||
/* supports the Write Exclusive – Registrants Only */
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_RO_SHIFT (3)
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_RO_MASK (0x1)
|
||||
/* supports the Exclusive Access - Registrants Only */
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_RO_SHIFT (4)
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_RO_MASK (0x1)
|
||||
/* supports the Write Exclusive – All Registrants */
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_AR_SHIFT (5)
|
||||
#define NVME_NS_DATA_RESCAP_WR_EX_AR_MASK (0x1)
|
||||
/* supports the Exclusive Access - All Registrants */
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_AR_SHIFT (6)
|
||||
#define NVME_NS_DATA_RESCAP_EX_AC_AR_MASK (0x1)
|
||||
/* Ignore Existing Key is used as defined in revision 1.3 or later */
|
||||
#define NVME_NS_DATA_RESCAP_IEKEY13_SHIFT (7)
|
||||
#define NVME_NS_DATA_RESCAP_IEKEY13_MASK (0x1)
|
||||
|
||||
/** Format Progress Indicator */
|
||||
/* percentage of the Format NVM command that remains to be completed */
|
||||
#define NVME_NS_DATA_FPI_PERC_SHIFT (0)
|
||||
#define NVME_NS_DATA_FPI_PERC_MASK (0x7f)
|
||||
/* namespace supports the Format Progress Indicator */
|
||||
#define NVME_NS_DATA_FPI_SUPP_SHIFT (7)
|
||||
#define NVME_NS_DATA_FPI_SUPP_MASK (0x1)
|
||||
|
||||
/** Deallocate Logical Block Features */
|
||||
/* deallocated logical block read behavior */
|
||||
#define NVME_NS_DATA_DLFEAT_READ_SHIFT (0)
|
||||
#define NVME_NS_DATA_DLFEAT_READ_MASK (0x07)
|
||||
#define NVME_NS_DATA_DLFEAT_READ_NR (0x00)
|
||||
#define NVME_NS_DATA_DLFEAT_READ_00 (0x01)
|
||||
#define NVME_NS_DATA_DLFEAT_READ_FF (0x02)
|
||||
/* supports the Deallocate bit in the Write Zeroes */
|
||||
#define NVME_NS_DATA_DLFEAT_DWZ_SHIFT (3)
|
||||
#define NVME_NS_DATA_DLFEAT_DWZ_MASK (0x01)
|
||||
/* Guard field for deallocated logical blocks is set to the CRC */
|
||||
#define NVME_NS_DATA_DLFEAT_GCRC_SHIFT (4)
|
||||
#define NVME_NS_DATA_DLFEAT_GCRC_MASK (0x01)
|
||||
|
||||
/** lba format support */
|
||||
/* metadata size */
|
||||
#define NVME_NS_DATA_LBAF_MS_SHIFT (0)
|
||||
#define NVME_NS_DATA_LBAF_MS_MASK (0xFFFF)
|
||||
/* lba data size */
|
||||
#define NVME_NS_DATA_LBAF_LBADS_SHIFT (16)
|
||||
#define NVME_NS_DATA_LBAF_LBADS_MASK (0xFF)
|
||||
/* relative performance */
|
||||
#define NVME_NS_DATA_LBAF_RP_SHIFT (24)
|
||||
#define NVME_NS_DATA_LBAF_RP_MASK (0x3)
|
||||
|
||||
enum nvme_critical_warning_state {
|
||||
NVME_CRIT_WARN_ST_AVAILABLE_SPARE = 0x1,
|
||||
NVME_CRIT_WARN_ST_TEMPERATURE = 0x2,
|
||||
|
|
|
|||
126
drivers/disk/nvme/nvme_namespace.c
Normal file
126
drivers/disk/nvme/nvme_namespace.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (c) 2022 Intel Corp.
|
||||
*/
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(nvme, CONFIG_NVME_LOG_LEVEL);
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include "nvme.h"
|
||||
|
||||
uint32_t nvme_namespace_get_sector_size(struct nvme_namespace *ns)
|
||||
{
|
||||
uint8_t flbas_fmt, lbads;
|
||||
|
||||
flbas_fmt = (ns->data.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
|
||||
NVME_NS_DATA_FLBAS_FORMAT_MASK;
|
||||
lbads = (ns->data.lbaf[flbas_fmt] >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
|
||||
NVME_NS_DATA_LBAF_LBADS_MASK;
|
||||
|
||||
return 1 << lbads;
|
||||
}
|
||||
|
||||
uint64_t nvme_namespace_get_num_sectors(struct nvme_namespace *ns)
|
||||
{
|
||||
return ns->data.nsze;
|
||||
}
|
||||
|
||||
uint64_t nvme_namespace_get_size(struct nvme_namespace *ns)
|
||||
{
|
||||
return nvme_namespace_get_num_sectors(ns) *
|
||||
nvme_namespace_get_sector_size(ns);
|
||||
}
|
||||
|
||||
uint32_t nvme_namespace_get_flags(struct nvme_namespace *ns)
|
||||
{
|
||||
return ns->flags;
|
||||
}
|
||||
|
||||
const char *nvme_namespace_get_serial_number(struct nvme_namespace *ns)
|
||||
{
|
||||
return (const char *)ns->ctrlr->cdata.sn;
|
||||
}
|
||||
|
||||
const char *nvme_namespace_get_model_number(struct nvme_namespace *ns)
|
||||
{
|
||||
return (const char *)ns->ctrlr->cdata.mn;
|
||||
}
|
||||
|
||||
const struct nvme_namespace_data *
|
||||
nvme_namespace_get_data(struct nvme_namespace *ns)
|
||||
{
|
||||
return &ns->data;
|
||||
}
|
||||
|
||||
uint32_t nvme_namespace_get_stripesize(struct nvme_namespace *ns)
|
||||
{
|
||||
if (((ns->data.nsfeat >> NVME_NS_DATA_NSFEAT_NPVALID_SHIFT) &
|
||||
NVME_NS_DATA_NSFEAT_NPVALID_MASK) != 0) {
|
||||
uint32_t ss = nvme_namespace_get_sector_size(ns);
|
||||
|
||||
if (ns->data.npwa != 0) {
|
||||
return (ns->data.npwa + 1) * ss;
|
||||
} else if (ns->data.npwg != 0) {
|
||||
return (ns->data.npwg + 1) * ss;
|
||||
}
|
||||
}
|
||||
|
||||
return ns->boundary;
|
||||
}
|
||||
|
||||
int nvme_namespace_construct(struct nvme_namespace *ns,
|
||||
uint32_t id,
|
||||
struct nvme_controller *ctrlr)
|
||||
{
|
||||
struct nvme_completion_poll_status status =
|
||||
NVME_CPL_STATUS_POLL_INIT(status);
|
||||
uint8_t flbas_fmt;
|
||||
uint8_t vwc_present;
|
||||
|
||||
ns->ctrlr = ctrlr;
|
||||
ns->id = id;
|
||||
|
||||
nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data,
|
||||
nvme_completion_poll_cb,
|
||||
&status);
|
||||
nvme_completion_poll(&status);
|
||||
|
||||
if (nvme_cpl_status_is_error(&status)) {
|
||||
LOG_DBG("Identifying NS id %d failed", id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
nvme_namespace_data_swapbytes(&ns->data);
|
||||
|
||||
if (nvme_namespace_get_num_sectors(ns) == 0) {
|
||||
LOG_DBG("Namespace %d not present", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
flbas_fmt = (ns->data.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
|
||||
NVME_NS_DATA_FLBAS_FORMAT_MASK;
|
||||
|
||||
/* Note: format is a 0-based value, so > is appropriate here not >=. */
|
||||
if (flbas_fmt > ns->data.nlbaf) {
|
||||
LOG_DBG("NS id %d: lba format %d exceeds number supported (%d)",
|
||||
id, flbas_fmt, ns->data.nlbaf + 1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ns->boundary = ns->data.noiob * nvme_namespace_get_sector_size(ns);
|
||||
|
||||
if (nvme_controller_has_dataset_mgmt(ctrlr)) {
|
||||
ns->flags |= NVME_NS_DEALLOCATE_SUPPORTED;
|
||||
}
|
||||
|
||||
vwc_present = (ctrlr->cdata.vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) &
|
||||
NVME_CTRLR_DATA_VWC_PRESENT_MASK;
|
||||
if (vwc_present) {
|
||||
ns->flags |= NVME_NS_FLUSH_SUPPORTED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
191
drivers/disk/nvme/nvme_namespace.h
Normal file
191
drivers/disk/nvme/nvme_namespace.h
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_
|
||||
#define ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_
|
||||
|
||||
struct nvme_namespace_data {
|
||||
/** namespace size */
|
||||
uint64_t nsze;
|
||||
|
||||
/** namespace capacity */
|
||||
uint64_t ncap;
|
||||
|
||||
/** namespace utilization */
|
||||
uint64_t nuse;
|
||||
|
||||
/** namespace features */
|
||||
uint8_t nsfeat;
|
||||
|
||||
/** number of lba formats */
|
||||
uint8_t nlbaf;
|
||||
|
||||
/** formatted lba size */
|
||||
uint8_t flbas;
|
||||
|
||||
/** metadata capabilities */
|
||||
uint8_t mc;
|
||||
|
||||
/** end-to-end data protection capabilities */
|
||||
uint8_t dpc;
|
||||
|
||||
/** end-to-end data protection type settings */
|
||||
uint8_t dps;
|
||||
|
||||
/** Namespace Multi-path I/O and Namespace Sharing Capabilities */
|
||||
uint8_t nmic;
|
||||
|
||||
/** Reservation Capabilities */
|
||||
uint8_t rescap;
|
||||
|
||||
/** Format Progress Indicator */
|
||||
uint8_t fpi;
|
||||
|
||||
/** Deallocate Logical Block Features */
|
||||
uint8_t dlfeat;
|
||||
|
||||
/** Namespace Atomic Write Unit Normal */
|
||||
uint16_t nawun;
|
||||
|
||||
/** Namespace Atomic Write Unit Power Fail */
|
||||
uint16_t nawupf;
|
||||
|
||||
/** Namespace Atomic Compare & Write Unit */
|
||||
uint16_t nacwu;
|
||||
|
||||
/** Namespace Atomic Boundary Size Normal */
|
||||
uint16_t nabsn;
|
||||
|
||||
/** Namespace Atomic Boundary Offset */
|
||||
uint16_t nabo;
|
||||
|
||||
/** Namespace Atomic Boundary Size Power Fail */
|
||||
uint16_t nabspf;
|
||||
|
||||
/** Namespace Optimal IO Boundary */
|
||||
uint16_t noiob;
|
||||
|
||||
/** NVM Capacity */
|
||||
uint8_t nvmcap[16];
|
||||
|
||||
/** Namespace Preferred Write Granularity */
|
||||
uint16_t npwg;
|
||||
|
||||
/** Namespace Preferred Write Alignment */
|
||||
uint16_t npwa;
|
||||
|
||||
/** Namespace Preferred Deallocate Granularity */
|
||||
uint16_t npdg;
|
||||
|
||||
/** Namespace Preferred Deallocate Alignment */
|
||||
uint16_t npda;
|
||||
|
||||
/** Namespace Optimal Write Size */
|
||||
uint16_t nows;
|
||||
|
||||
/* bytes 74-91: Reserved */
|
||||
uint8_t reserved5[18];
|
||||
|
||||
/** ANA Group Identifier */
|
||||
uint32_t anagrpid;
|
||||
|
||||
/* bytes 96-98: Reserved */
|
||||
uint8_t reserved6[3];
|
||||
|
||||
/** Namespace Attributes */
|
||||
uint8_t nsattr;
|
||||
|
||||
/** NVM Set Identifier */
|
||||
uint16_t nvmsetid;
|
||||
|
||||
/** Endurance Group Identifier */
|
||||
uint16_t endgid;
|
||||
|
||||
/** Namespace Globally Unique Identifier */
|
||||
uint8_t nguid[16];
|
||||
|
||||
/** IEEE Extended Unique Identifier */
|
||||
uint8_t eui64[8];
|
||||
|
||||
/** lba format support */
|
||||
uint32_t lbaf[16];
|
||||
|
||||
uint8_t reserved7[192];
|
||||
|
||||
uint8_t vendor_specific[3712];
|
||||
} __packed __aligned(4);
|
||||
|
||||
static inline
|
||||
void nvme_namespace_data_swapbytes(struct nvme_namespace_data *s)
|
||||
{
|
||||
#if _BYTE_ORDER != _LITTLE_ENDIAN
|
||||
int i;
|
||||
|
||||
s->nsze = sys_le64_to_cpu(s->nsze);
|
||||
s->ncap = sys_le64_to_cpu(s->ncap);
|
||||
s->nuse = sys_le64_to_cpu(s->nuse);
|
||||
s->nawun = sys_le16_to_cpu(s->nawun);
|
||||
s->nawupf = sys_le16_to_cpu(s->nawupf);
|
||||
s->nacwu = sys_le16_to_cpu(s->nacwu);
|
||||
s->nabsn = sys_le16_to_cpu(s->nabsn);
|
||||
s->nabo = sys_le16_to_cpu(s->nabo);
|
||||
s->nabspf = sys_le16_to_cpu(s->nabspf);
|
||||
s->noiob = sys_le16_to_cpu(s->noiob);
|
||||
s->npwg = sys_le16_to_cpu(s->npwg);
|
||||
s->npwa = sys_le16_to_cpu(s->npwa);
|
||||
s->npdg = sys_le16_to_cpu(s->npdg);
|
||||
s->npda = sys_le16_to_cpu(s->npda);
|
||||
s->nows = sys_le16_to_cpu(s->nows);
|
||||
s->anagrpid = sys_le32_to_cpu(s->anagrpid);
|
||||
s->nvmsetid = sys_le16_to_cpu(s->nvmsetid);
|
||||
s->endgid = sys_le16_to_cpu(s->endgid);
|
||||
for (i = 0; i < 16; i++) {
|
||||
s->lbaf[i] = sys_le32_to_cpu(s->lbaf[i]);
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Readable identifier: nvme%%n%%\0 */
|
||||
#define NVME_NAMESPACE_NAME_MAX_LENGTH 10
|
||||
|
||||
struct nvme_namespace {
|
||||
struct nvme_controller *ctrlr;
|
||||
struct nvme_namespace_data data __aligned(0x1000);
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
uint32_t boundary;
|
||||
char name[NVME_NAMESPACE_NAME_MAX_LENGTH];
|
||||
};
|
||||
|
||||
enum nvme_namespace_flags {
|
||||
NVME_NS_DEALLOCATE_SUPPORTED = 0x1,
|
||||
NVME_NS_FLUSH_SUPPORTED = 0x2,
|
||||
};
|
||||
|
||||
uint32_t nvme_namespace_get_sector_size(struct nvme_namespace *ns);
|
||||
|
||||
uint64_t nvme_namespace_get_num_sectors(struct nvme_namespace *ns);
|
||||
|
||||
uint64_t nvme_namespace_get_size(struct nvme_namespace *ns);
|
||||
|
||||
uint32_t nvme_namespace_get_flags(struct nvme_namespace *ns);
|
||||
|
||||
const char *nvme_namespace_get_serial_number(struct nvme_namespace *ns);
|
||||
|
||||
const char *nvme_namespace_get_model_number(struct nvme_namespace *ns);
|
||||
|
||||
const struct nvme_namespace_data *
|
||||
nvme_namespace_get_data(struct nvme_namespace *ns);
|
||||
|
||||
uint32_t nvme_namespace_get_stripesize(struct nvme_namespace *ns);
|
||||
|
||||
int nvme_namespace_construct(struct nvme_namespace *ns,
|
||||
uint32_t id,
|
||||
struct nvme_controller *ctrlr);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_ */
|
||||
Loading…
Reference in a new issue