lib/nvme: Adding support for PMR Identification

Identify application prints the PMR details if it is supported

Signed-off-by: Krishna Kanth Reddy <krish.reddy@samsung.com>
Change-Id: Iaba4c15e18e1402035b11a34b2defe8078855751
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6209
Community-CI: Broadcom CI
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Krishna Kanth Reddy 2021-02-01 18:14:52 +05:30 committed by Tomasz Zawadzki
parent 9529803fe0
commit 48aed8a578
7 changed files with 223 additions and 2 deletions

View File

@ -137,6 +137,8 @@ Change the return type of function `spdk_nbd_stop` from void to int. And update
### nvme
Added a new function `spdk_nvme_ctrlr_get_regs_pmrcap` to get the PMR capabilities.
Directives support was added to the NVMe driver.
Two async APIs `spdk_nvme_ctrlr_cmd_directive_receive` and `spdk_nvme_ctrlr_cmd_directive_send`

View File

@ -1074,6 +1074,7 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
union spdk_nvme_cap_register cap;
union spdk_nvme_vs_register vs;
union spdk_nvme_cmbsz_register cmbsz;
union spdk_nvme_pmrcap_register pmrcap;
uint8_t str[512];
uint32_t i, j;
struct spdk_nvme_error_information_entry *error_entry;
@ -1086,6 +1087,7 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
cap = spdk_nvme_ctrlr_get_regs_cap(ctrlr);
vs = spdk_nvme_ctrlr_get_regs_vs(ctrlr);
cmbsz = spdk_nvme_ctrlr_get_regs_cmbsz(ctrlr);
pmrcap = spdk_nvme_ctrlr_get_regs_pmrcap(ctrlr);
if (!spdk_nvme_ctrlr_is_discovery(ctrlr)) {
/*
@ -1198,6 +1200,9 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
(uint64_t)1 << (12 + cap.bits.mpsmin));
printf("Memory Page Size Maximum: %" PRIu64 " bytes\n",
(uint64_t)1 << (12 + cap.bits.mpsmax));
printf("Persistent Memory Region: %s\n",
cap.bits.pmrs ? "Supported" : "Not Supported");
printf("Optional Asynchronous Events Supported\n");
printf(" Namespace Attribute Notices: %s\n",
cdata->oaes.ns_attribute_notices ? "Supported" : "Not Supported");
@ -1233,6 +1238,19 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
}
printf("\n");
printf("Persistent Memory Region Support\n");
printf("================================\n");
if (cap.bits.pmrs != 0) {
printf("Supported: Yes\n");
printf("Read data and metadata in PMR %s\n",
pmrcap.bits.rds ? "Supported" : "Not Supported");
printf("Write data and metadata in PMR: %s\n",
pmrcap.bits.wds ? "Supported" : "Not Supported");
} else {
printf("Supported: No\n");
}
printf("\n");
printf("Admin Command Set Attributes\n");
printf("============================\n");
printf("Security Send/Receive: %s\n",

View File

@ -1017,6 +1017,15 @@ union spdk_nvme_vs_register spdk_nvme_ctrlr_get_regs_vs(struct spdk_nvme_ctrlr *
*/
union spdk_nvme_cmbsz_register spdk_nvme_ctrlr_get_regs_cmbsz(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the NVMe controller PMRCAP (Persistent Memory Region Capabilities) register.
*
* \param ctrlr Opaque handle to NVMe controller.
*
* \return the NVMe controller PMRCAP (Persistent Memory Region Capabilities) register.
*/
union spdk_nvme_pmrcap_register spdk_nvme_ctrlr_get_regs_pmrcap(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the number of namespaces for the given NVMe controller.
*

View File

@ -109,7 +109,10 @@ union spdk_nvme_cap_register {
/** memory page size maximum */
uint32_t mpsmax : 4;
uint32_t reserved3 : 8;
/** persistent memory region supported */
uint32_t pmrs : 1;
uint32_t reserved3 : 7;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cap_register) == 8, "Incorrect size");
@ -299,6 +302,139 @@ union spdk_nvme_cmbsts_register {
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmbsts_register) == 4, "Incorrect size");
union spdk_nvme_pmrcap_register {
uint32_t raw;
struct {
uint32_t reserved1 : 3;
/** read data support */
uint32_t rds : 1;
/** write data support */
uint32_t wds : 1;
/** base indicator register */
uint32_t bir : 3;
/**
* persistent memory region time units
* 00b: 500 milliseconds
* 01b: minutes
*/
uint32_t pmrtu : 2;
/** persistent memory region write barrier mechanisms */
uint32_t pmrwbm : 4;
uint32_t reserved2 : 2;
/** persistent memory region timeout */
uint32_t pmrto : 8;
/** controller memory space supported */
uint32_t cmss : 1;
uint32_t reserved3 : 7;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrcap_register) == 4, "Incorrect size");
union spdk_nvme_pmrctl_register {
uint32_t raw;
struct {
/** enable */
uint32_t en : 1;
uint32_t reserved : 31;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrctl_register) == 4, "Incorrect size");
union spdk_nvme_pmrsts_register {
uint32_t raw;
struct {
/** err */
uint32_t err : 8;
/** not ready */
uint32_t nrdy : 1;
/**
* health status
* 000b: Normal Operation
* 001b: Restore Error
* 010b: Read Only
* 011b: Unreliable
*/
uint32_t hsts : 3;
/** controller base address invalid */
uint32_t cbai : 1;
uint32_t reserved : 19;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrsts_register) == 4, "Incorrect size");
union spdk_nvme_pmrebs_register {
uint32_t raw;
struct {
/**
* pmr elasicity buffer size units
* 0h: Bytes
* 1h: 1 KiB
* 2h: 1 MiB
* 3h: 1 GiB
*/
uint32_t pmrszu : 4;
/** read bypass behavior */
uint32_t rbb : 1;
uint32_t reserved : 3;
/** pmr elasticity buffer size base */
uint32_t pmrwbz : 24;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrebs_register) == 4, "Incorrect size");
union spdk_nvme_pmrswtp_register {
uint32_t raw;
struct {
/**
* pmr sustained write throughput units
* 0h: Bytes per second
* 1h: 1 KiB / s
* 2h: 1 MiB / s
* 3h: 1 GiB / s
*/
uint32_t pmrswtu : 4;
uint32_t reserved : 4;
/** pmr sustained write throughput */
uint32_t pmrswtv : 24;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrswtp_register) == 4, "Incorrect size");
union spdk_nvme_pmrmscl_register {
uint32_t raw;
struct {
uint32_t reserved1 : 1;
/** controller memory space enable */
uint32_t cmse : 1;
uint32_t reserved2 : 10;
/** controller base address */
uint32_t cba : 20;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrmscl_register) == 4, "Incorrect size");
/** Boot partition information */
union spdk_nvme_bpinfo_register {
uint32_t raw;
@ -387,7 +523,29 @@ struct spdk_nvme_registers {
/** controller memory buffer status */
union spdk_nvme_cmbsts_register cmbsts;
uint32_t reserved3[0x3e9];
uint32_t reserved2[0x369];
/** persistent memory region capabilities */
union spdk_nvme_pmrcap_register pmrcap;
/** persistent memory region control */
union spdk_nvme_pmrctl_register pmrctl;
/** persistent memory region status */
union spdk_nvme_pmrsts_register pmrsts;
/** persistent memory region elasticity buffer size */
union spdk_nvme_pmrebs_register pmrebs;
/** persistent memory region sustained write throughput */
union spdk_nvme_pmrswtp_register pmrswtp;
/** persistent memory region memory space control lower */
union spdk_nvme_pmrmscl_register pmrmscl;
uint32_t pmrmscu; /* persistent memory region memory space control upper */
uint32_t reserved3[0x79];
struct {
uint32_t sq_tdbl; /* submission queue tail doorbell */
@ -423,6 +581,20 @@ SPDK_STATIC_ASSERT(0x50 == offsetof(struct spdk_nvme_registers, cmbmsc),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0x58 == offsetof(struct spdk_nvme_registers, cmbsts),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE00 == offsetof(struct spdk_nvme_registers, pmrcap),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE04 == offsetof(struct spdk_nvme_registers, pmrctl),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE08 == offsetof(struct spdk_nvme_registers, pmrsts),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE0C == offsetof(struct spdk_nvme_registers, pmrebs),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE10 == offsetof(struct spdk_nvme_registers, pmrswtp),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE14 == offsetof(struct spdk_nvme_registers, pmrmscl),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE18 == offsetof(struct spdk_nvme_registers, pmrmscu),
"Incorrect register offset");
enum spdk_nvme_sgl_descriptor_type {
SPDK_NVME_SGL_TYPE_DATA_BLOCK = 0x0,

View File

@ -91,6 +91,13 @@ nvme_ctrlr_get_cmbsz(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cmbsz_regist
&cmbsz->raw);
}
int
nvme_ctrlr_get_pmrcap(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_pmrcap_register *pmrcap)
{
return nvme_transport_ctrlr_get_reg_4(ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
&pmrcap->raw);
}
static int
nvme_ctrlr_set_nssr(struct spdk_nvme_ctrlr *ctrlr, uint32_t nssr_value)
{
@ -3539,6 +3546,17 @@ union spdk_nvme_cmbsz_register spdk_nvme_ctrlr_get_regs_cmbsz(struct spdk_nvme_c
return cmbsz;
}
union spdk_nvme_pmrcap_register spdk_nvme_ctrlr_get_regs_pmrcap(struct spdk_nvme_ctrlr *ctrlr)
{
union spdk_nvme_pmrcap_register pmrcap;
if (nvme_ctrlr_get_pmrcap(ctrlr, &pmrcap)) {
pmrcap.raw = 0;
}
return pmrcap;
}
uint32_t
spdk_nvme_ctrlr_get_num_ns(struct spdk_nvme_ctrlr *ctrlr)
{

View File

@ -1019,6 +1019,7 @@ int nvme_ctrlr_submit_admin_request(struct spdk_nvme_ctrlr *ctrlr,
int nvme_ctrlr_get_cap(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cap_register *cap);
int nvme_ctrlr_get_vs(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_vs_register *vs);
int nvme_ctrlr_get_cmbsz(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cmbsz_register *cmbsz);
int nvme_ctrlr_get_pmrcap(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_pmrcap_register *pmrcap);
bool nvme_ctrlr_multi_iocs_enabled(struct spdk_nvme_ctrlr *ctrlr);
void nvme_ctrlr_init_cap(struct spdk_nvme_ctrlr *ctrlr, const union spdk_nvme_cap_register *cap,
const union spdk_nvme_vs_register *vs);

View File

@ -41,6 +41,7 @@
spdk_nvme_ctrlr_get_regs_cap;
spdk_nvme_ctrlr_get_regs_vs;
spdk_nvme_ctrlr_get_regs_cmbsz;
spdk_nvme_ctrlr_get_regs_pmrcap;
spdk_nvme_ctrlr_get_num_ns;
spdk_nvme_ctrlr_get_pci_device;
spdk_nvme_ctrlr_get_max_xfer_size;