Commit 48aed8a5 authored by Krishna Kanth Reddy's avatar Krishna Kanth Reddy Committed by Tomasz Zawadzki
Browse files

lib/nvme: Adding support for PMR Identification



Identify application prints the PMR details if it is supported

Signed-off-by: default avatarKrishna 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: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 9529803f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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`
+18 −0
Original line number Diff line number Diff line
@@ -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",
+9 −0
Original line number Diff line number Diff line
@@ -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.
 *
+174 −2
Original line number Diff line number Diff line
@@ -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,
+18 −0
Original line number Diff line number Diff line
@@ -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)
{
Loading