nvme: combine CAP register into one 64-bit union
Previously, we used cap_lo and cap_hi to represent the 32-bit halves of the full CAP register. However, it is simpler to keep them in a single 64-bit structure, and is no less efficient on 64-bit platforms. Also name the NSSRS field from NVMe 1.2, which was previously reserved. Change-Id: I1d5d9b0dccbb12373b4aed3db29c883881d43223 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
80c350ed69
commit
0e93df5c34
@ -68,8 +68,8 @@ extern "C" {
|
||||
*/
|
||||
#define SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES 256
|
||||
|
||||
union spdk_nvme_cap_lo_register {
|
||||
uint32_t raw;
|
||||
union spdk_nvme_cap_register {
|
||||
uint64_t raw;
|
||||
struct {
|
||||
/** maximum queue entries supported */
|
||||
uint32_t mqes : 16;
|
||||
@ -84,17 +84,12 @@ union spdk_nvme_cap_lo_register {
|
||||
|
||||
/** timeout */
|
||||
uint32_t to : 8;
|
||||
} bits;
|
||||
};
|
||||
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cap_lo_register) == 4, "Incorrect size");
|
||||
|
||||
union spdk_nvme_cap_hi_register {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
/** doorbell stride */
|
||||
uint32_t dstrd : 4;
|
||||
|
||||
uint32_t reserved3 : 1;
|
||||
/** NVM subsystem reset supported */
|
||||
uint32_t nssrs : 1;
|
||||
|
||||
/** command sets supported */
|
||||
uint32_t css_nvm : 1;
|
||||
@ -108,10 +103,10 @@ union spdk_nvme_cap_hi_register {
|
||||
/** memory page size maximum */
|
||||
uint32_t mpsmax : 4;
|
||||
|
||||
uint32_t reserved1 : 8;
|
||||
uint32_t reserved3 : 8;
|
||||
} bits;
|
||||
};
|
||||
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cap_hi_register) == 4, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cap_register) == 8, "Incorrect size");
|
||||
|
||||
union spdk_nvme_cc_register {
|
||||
uint32_t raw;
|
||||
@ -236,8 +231,7 @@ SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmbsz_register) == 4, "Incorrect size"
|
||||
|
||||
struct spdk_nvme_registers {
|
||||
/** controller capabilities */
|
||||
union spdk_nvme_cap_lo_register cap_lo;
|
||||
union spdk_nvme_cap_hi_register cap_hi;
|
||||
union spdk_nvme_cap_register cap;
|
||||
|
||||
/** version of NVMe specification */
|
||||
union spdk_nvme_vs_register vs;
|
||||
@ -269,7 +263,7 @@ struct spdk_nvme_registers {
|
||||
};
|
||||
|
||||
/* NVMe controller register space offsets */
|
||||
SPDK_STATIC_ASSERT(0x00 == offsetof(struct spdk_nvme_registers, cap_lo),
|
||||
SPDK_STATIC_ASSERT(0x00 == offsetof(struct spdk_nvme_registers, cap),
|
||||
"Incorrect register offset");
|
||||
SPDK_STATIC_ASSERT(0x08 == offsetof(struct spdk_nvme_registers, vs), "Incorrect register offset");
|
||||
SPDK_STATIC_ASSERT(0x0C == offsetof(struct spdk_nvme_registers, intms),
|
||||
|
@ -330,8 +330,7 @@ union spdk_nvmf_capsule_attr_hi {
|
||||
SPDK_STATIC_ASSERT(sizeof(union spdk_nvmf_capsule_attr_hi) == 4, "Incorrect size");
|
||||
|
||||
struct spdk_nvmf_ctrlr_properties {
|
||||
union spdk_nvme_cap_lo_register cap_lo;
|
||||
union spdk_nvme_cap_hi_register cap_hi;
|
||||
union spdk_nvme_cap_register cap;
|
||||
|
||||
uint32_t vs;
|
||||
uint32_t intms;
|
||||
@ -360,7 +359,7 @@ struct spdk_nvmf_ctrlr_properties {
|
||||
uint8_t reserved5[0x2F0];
|
||||
};
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_properties) == 4864, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(SPDK_NVMF_PROP_CAP_OFST == offsetof(struct spdk_nvmf_ctrlr_properties, cap_lo),
|
||||
SPDK_STATIC_ASSERT(SPDK_NVMF_PROP_CAP_OFST == offsetof(struct spdk_nvmf_ctrlr_properties, cap),
|
||||
"Incorrect register offset");
|
||||
SPDK_STATIC_ASSERT(SPDK_NVMF_PROP_VS_OFST == offsetof(struct spdk_nvmf_ctrlr_properties, vs),
|
||||
"Incorrect register offset");
|
||||
|
@ -346,7 +346,7 @@ static int
|
||||
nvme_ctrlr_construct_io_qpairs(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
struct spdk_nvme_qpair *qpair;
|
||||
union spdk_nvme_cap_lo_register cap_lo;
|
||||
union spdk_nvme_cap_register cap;
|
||||
uint32_t i, num_entries, num_trackers;
|
||||
int rc;
|
||||
|
||||
@ -365,8 +365,8 @@ nvme_ctrlr_construct_io_qpairs(struct spdk_nvme_ctrlr *ctrlr)
|
||||
* devices may specify a smaller limit, so we need to check
|
||||
* the MQES field in the capabilities register.
|
||||
*/
|
||||
cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo.raw);
|
||||
num_entries = nvme_min(NVME_IO_ENTRIES, cap_lo.bits.mqes + 1);
|
||||
cap.raw = nvme_mmio_read_8(ctrlr, cap.raw);
|
||||
num_entries = nvme_min(NVME_IO_ENTRIES, cap.bits.mqes + 1);
|
||||
|
||||
/*
|
||||
* No need to have more trackers than entries in the submit queue.
|
||||
@ -450,7 +450,7 @@ nvme_ctrlr_enable(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
union spdk_nvme_cc_register cc;
|
||||
union spdk_nvme_aqa_register aqa;
|
||||
union spdk_nvme_cap_lo_register cap_lo;
|
||||
union spdk_nvme_cap_register cap;
|
||||
|
||||
cc.raw = nvme_mmio_read_4(ctrlr, cc.raw);
|
||||
|
||||
@ -477,18 +477,18 @@ nvme_ctrlr_enable(struct spdk_nvme_ctrlr *ctrlr)
|
||||
/* Page size is 2 ^ (12 + mps). */
|
||||
cc.bits.mps = nvme_u32log2(PAGE_SIZE) - 12;
|
||||
|
||||
cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo.raw);
|
||||
cap.raw = nvme_mmio_read_8(ctrlr, cap.raw);
|
||||
|
||||
switch (ctrlr->opts.arb_mechanism) {
|
||||
case SPDK_NVME_CC_AMS_RR:
|
||||
break;
|
||||
case SPDK_NVME_CC_AMS_WRR:
|
||||
if (SPDK_NVME_CAP_AMS_WRR & cap_lo.bits.ams) {
|
||||
if (SPDK_NVME_CAP_AMS_WRR & cap.bits.ams) {
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
case SPDK_NVME_CC_AMS_VS:
|
||||
if (SPDK_NVME_CAP_AMS_VS & cap_lo.bits.ams) {
|
||||
if (SPDK_NVME_CAP_AMS_VS & cap.bits.ams) {
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
@ -818,15 +818,15 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
union spdk_nvme_cc_register cc;
|
||||
union spdk_nvme_csts_register csts;
|
||||
union spdk_nvme_cap_lo_register cap_lo;
|
||||
union spdk_nvme_cap_register cap;
|
||||
uint32_t ready_timeout_in_ms;
|
||||
int rc;
|
||||
|
||||
cc.raw = nvme_mmio_read_4(ctrlr, cc.raw);
|
||||
csts.raw = nvme_mmio_read_4(ctrlr, csts.raw);
|
||||
cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo.raw);
|
||||
cap.raw = nvme_mmio_read_8(ctrlr, cap.raw);
|
||||
|
||||
ready_timeout_in_ms = 500 * cap_lo.bits.to;
|
||||
ready_timeout_in_ms = 500 * cap.bits.to;
|
||||
|
||||
/*
|
||||
* Check if the current initialization step is done or has timed out.
|
||||
@ -1080,7 +1080,7 @@ nvme_ctrlr_free_bars(struct spdk_nvme_ctrlr *ctrlr)
|
||||
int
|
||||
nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr, void *devhandle)
|
||||
{
|
||||
union spdk_nvme_cap_hi_register cap_hi;
|
||||
union spdk_nvme_cap_register cap;
|
||||
uint32_t cmd_reg;
|
||||
int status;
|
||||
int rc;
|
||||
@ -1099,13 +1099,13 @@ nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr, void *devhandle)
|
||||
cmd_reg |= 0x4;
|
||||
nvme_pcicfg_write32(devhandle, cmd_reg, 4);
|
||||
|
||||
cap_hi.raw = nvme_mmio_read_4(ctrlr, cap_hi.raw);
|
||||
cap.raw = nvme_mmio_read_8(ctrlr, cap.raw);
|
||||
|
||||
/* Doorbell stride is 2 ^ (dstrd + 2),
|
||||
* but we want multiples of 4, so drop the + 2 */
|
||||
ctrlr->doorbell_stride_u32 = 1 << cap_hi.bits.dstrd;
|
||||
ctrlr->doorbell_stride_u32 = 1 << cap.bits.dstrd;
|
||||
|
||||
ctrlr->min_page_size = 1 << (12 + cap_hi.bits.mpsmin);
|
||||
ctrlr->min_page_size = 1 << (12 + cap.bits.mpsmin);
|
||||
|
||||
rc = nvme_ctrlr_construct_admin_qpair(ctrlr);
|
||||
if (rc)
|
||||
|
@ -473,6 +473,9 @@ extern struct nvme_driver g_nvme_driver;
|
||||
#define nvme_mmio_read_4(sc, reg) \
|
||||
spdk_mmio_read_4(&(sc)->regs->reg)
|
||||
|
||||
#define nvme_mmio_read_8(sc, reg) \
|
||||
spdk_mmio_read_8(&(sc)->regs->reg)
|
||||
|
||||
#define nvme_mmio_write_4(sc, reg, val) \
|
||||
spdk_mmio_write_4(&(sc)->regs->reg, val)
|
||||
|
||||
|
@ -353,7 +353,7 @@ nvmf_init_conn_properites(struct spdk_nvmf_conn *conn,
|
||||
*/
|
||||
/* reset mdts in vcdata to equal the application default maximum */
|
||||
mdts = SPDK_NVMF_MAX_RECV_DATA_TRANSFER_SIZE /
|
||||
(1 << (12 + session->vcprop.cap_hi.bits.mpsmin));
|
||||
(1 << (12 + session->vcprop.cap.bits.mpsmin));
|
||||
if (mdts == 0) {
|
||||
SPDK_ERRLOG("Min page size exceeds max transfer size!\n");
|
||||
SPDK_ERRLOG("Verify setting of SPDK_NVMF_MAX_RECV_DATA_TRANSFER_SIZE and mpsmin\n");
|
||||
|
@ -102,16 +102,14 @@ nvmf_init_discovery_session_properties(struct nvmf_session *session)
|
||||
session->vcdata.sgls.sgl_offset = 1;
|
||||
|
||||
/* Properties */
|
||||
session->vcprop.cap_lo.raw = 0;
|
||||
session->vcprop.cap_lo.bits.cqr = 1; /* NVMF specification required */
|
||||
session->vcprop.cap_lo.bits.mqes = (session->vcdata.maxcmd - 1); /* max queue depth */
|
||||
session->vcprop.cap_lo.bits.ams = 0; /* optional arb mechanisms */
|
||||
|
||||
session->vcprop.cap_hi.raw = 0;
|
||||
session->vcprop.cap_hi.bits.dstrd = 0; /* fixed to 0 for NVMf */
|
||||
session->vcprop.cap_hi.bits.css_nvm = 1; /* NVM command set */
|
||||
session->vcprop.cap_hi.bits.mpsmin = 0; /* 2 ^ 12 + mpsmin == 4k */
|
||||
session->vcprop.cap_hi.bits.mpsmax = 0; /* 2 ^ 12 + mpsmax == 4k */
|
||||
session->vcprop.cap.raw = 0;
|
||||
session->vcprop.cap.bits.cqr = 1; /* NVMF specification required */
|
||||
session->vcprop.cap.bits.mqes = (session->vcdata.maxcmd - 1); /* max queue depth */
|
||||
session->vcprop.cap.bits.ams = 0; /* optional arb mechanisms */
|
||||
session->vcprop.cap.bits.dstrd = 0; /* fixed to 0 for NVMf */
|
||||
session->vcprop.cap.bits.css_nvm = 1; /* NVM command set */
|
||||
session->vcprop.cap.bits.mpsmin = 0; /* 2 ^ 12 + mpsmin == 4k */
|
||||
session->vcprop.cap.bits.mpsmax = 0; /* 2 ^ 12 + mpsmax == 4k */
|
||||
|
||||
session->vcprop.vs = 0x10000; /* Version Supported: Major 1, Minor 0 */
|
||||
|
||||
@ -180,17 +178,15 @@ nvmf_init_nvme_session_properties(struct nvmf_session *session, int aq_depth)
|
||||
/* feature: Number Of Queues. */
|
||||
session->max_io_queues = MAX_SESSION_IO_QUEUES;
|
||||
|
||||
session->vcprop.cap_lo.raw = 0;
|
||||
session->vcprop.cap_lo.bits.cqr = 0; /* queues not contiguous */
|
||||
session->vcprop.cap_lo.bits.mqes = (session->vcdata.maxcmd - 1); /* max queue depth */
|
||||
session->vcprop.cap_lo.bits.ams = 0; /* optional arb mechanisms */
|
||||
session->vcprop.cap_lo.bits.to = 1; /* ready timeout - 500 msec units */
|
||||
|
||||
session->vcprop.cap_hi.raw = 0;
|
||||
session->vcprop.cap_hi.bits.dstrd = 0; /* fixed to 0 for NVMf */
|
||||
session->vcprop.cap_hi.bits.css_nvm = 1; /* NVM command set */
|
||||
session->vcprop.cap_hi.bits.mpsmin = 0; /* 2 ^ 12 + mpsmin == 4k */
|
||||
session->vcprop.cap_hi.bits.mpsmax = 0; /* 2 ^ 12 + mpsmax == 4k */
|
||||
session->vcprop.cap.raw = 0;
|
||||
session->vcprop.cap.bits.cqr = 0; /* queues not contiguous */
|
||||
session->vcprop.cap.bits.mqes = (session->vcdata.maxcmd - 1); /* max queue depth */
|
||||
session->vcprop.cap.bits.ams = 0; /* optional arb mechanisms */
|
||||
session->vcprop.cap.bits.to = 1; /* ready timeout - 500 msec units */
|
||||
session->vcprop.cap.bits.dstrd = 0; /* fixed to 0 for NVMf */
|
||||
session->vcprop.cap.bits.css_nvm = 1; /* NVM command set */
|
||||
session->vcprop.cap.bits.mpsmin = 0; /* 2 ^ 12 + mpsmin == 4k */
|
||||
session->vcprop.cap.bits.mpsmax = 0; /* 2 ^ 12 + mpsmax == 4k */
|
||||
|
||||
session->vcprop.vs = 0x10000; /* Version Supported: Major 1, Minor 0 */
|
||||
|
||||
@ -213,10 +209,8 @@ nvmf_init_nvme_session_properties(struct nvmf_session *session, int aq_depth)
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: max io queues %x\n",
|
||||
session->max_io_queues);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: cap_lo %x\n",
|
||||
session->vcprop.cap_lo.raw);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: cap_hi %x\n",
|
||||
session->vcprop.cap_hi.raw);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: cap %" PRIx64 "\n",
|
||||
session->vcprop.cap.raw);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: vs %x\n", session->vcprop.vs);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: cc %x\n", session->vcprop.cc.raw);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " nvmf_init_session_properties: csts %x\n",
|
||||
@ -406,16 +400,16 @@ nvmf_property_get(struct nvmf_session *session,
|
||||
}
|
||||
|
||||
switch (cmd->ofst) {
|
||||
case (offsetof(struct spdk_nvmf_ctrlr_properties, cap_lo)):
|
||||
response->value.u32.low = session->vcprop.cap_lo.raw;
|
||||
case (offsetof(struct spdk_nvmf_ctrlr_properties, cap)):
|
||||
response->value.u32.low = session->vcprop.cap.raw;
|
||||
if (cmd->attrib == 1)
|
||||
response->value.u32.high = session->vcprop.cap_hi.raw;
|
||||
response->value.u64 = session->vcprop.cap.raw;
|
||||
break;
|
||||
case (offsetof(struct spdk_nvmf_ctrlr_properties, cap_hi)):
|
||||
case (offsetof(struct spdk_nvmf_ctrlr_properties, cap) + 4):
|
||||
if (cmd->attrib == 1)
|
||||
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
|
||||
else
|
||||
response->value.u32.low = session->vcprop.cap_hi.raw;
|
||||
response->value.u32.low = session->vcprop.cap.raw >> 32;
|
||||
break;
|
||||
case (offsetof(struct spdk_nvmf_ctrlr_properties, vs)):
|
||||
if (cmd->attrib == 1)
|
||||
|
@ -425,7 +425,7 @@ test_nvme_ctrlr_init_en_0_rdy_0_ams_rr(void)
|
||||
/*
|
||||
* Default round robin enabled
|
||||
*/
|
||||
g_ut_nvme_regs.cap_lo.bits.ams = 0x0;
|
||||
g_ut_nvme_regs.cap.bits.ams = 0x0;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(&ctrlr, NULL) == 0);
|
||||
ctrlr.cdata.nn = 1;
|
||||
@ -543,7 +543,7 @@ test_nvme_ctrlr_init_en_0_rdy_0_ams_wrr(void)
|
||||
/*
|
||||
* Weighted round robin enabled
|
||||
*/
|
||||
g_ut_nvme_regs.cap_lo.bits.ams = SPDK_NVME_CAP_AMS_WRR;
|
||||
g_ut_nvme_regs.cap.bits.ams = SPDK_NVME_CAP_AMS_WRR;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(&ctrlr, NULL) == 0);
|
||||
ctrlr.cdata.nn = 1;
|
||||
@ -662,7 +662,7 @@ test_nvme_ctrlr_init_en_0_rdy_0_ams_vs(void)
|
||||
/*
|
||||
* Default round robin enabled
|
||||
*/
|
||||
g_ut_nvme_regs.cap_lo.bits.ams = SPDK_NVME_CAP_AMS_VS;
|
||||
g_ut_nvme_regs.cap.bits.ams = SPDK_NVME_CAP_AMS_VS;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(&ctrlr, NULL) == 0);
|
||||
ctrlr.cdata.nn = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user