Commit 627bee96 authored by Stephen Bates's avatar Stephen Bates Committed by Jim Harris
Browse files

nvme_pci: Correct bug in CMB allocation



There was a bug reported by Cunyin Chang with regards to how the
cmb_current_offset was calculated when the CMB offset into the CMB BAR
is non-zero. This patch fixes this issue and also fixes the problem
that the last valid offset into the BAR *may* differ if registration
is utilized or not (due to the 2MiB alignment and length requirements
for registered memory).

Change-Id: Id08d6a5a40b828338f6a66599171cc8dd59768a3
Signed-off-by: default avatarStephen Bates <sbates@raithlin.com>
Reviewed-on: https://review.gerrithub.io/401832


Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 736f6937
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -85,9 +85,12 @@ struct nvme_pcie_ctrlr {
	/* Controller memory buffer size in Bytes */
	uint64_t cmb_size;

	/* Current offset of controller memory buffer */
	/* Current offset of controller memory buffer, relative to start of BAR virt addr */
	uint64_t cmb_current_offset;

	/* Last valid offset into CMB, this differs if CMB memory registration occurs or not */
	uint64_t cmb_max_offset;

	void *cmb_mem_register_addr;
	size_t cmb_mem_register_size;

@@ -490,6 +493,7 @@ nvme_pcie_ctrlr_map_cmb(struct nvme_pcie_ctrlr *pctrlr)
	pctrlr->cmb_bar_phys_addr = bar_phys_addr;
	pctrlr->cmb_size = size;
	pctrlr->cmb_current_offset = offset;
	pctrlr->cmb_max_offset = offset + size;

	if (!cmbsz.bits.sqs) {
		pctrlr->ctrlr.opts.use_cmb_sqs = false;
@@ -516,7 +520,8 @@ nvme_pcie_ctrlr_map_cmb(struct nvme_pcie_ctrlr *pctrlr)
		SPDK_ERRLOG("spdk_mem_register() failed\n");
		goto exit;
	}
	pctrlr->cmb_current_offset = mem_register_start - ((uint64_t)pctrlr->cmb_bar_virt_addr + offset);
	pctrlr->cmb_current_offset = mem_register_start - ((uint64_t)pctrlr->cmb_bar_virt_addr);
	pctrlr->cmb_max_offset = mem_register_end - ((uint64_t)pctrlr->cmb_bar_virt_addr);
	pctrlr->cmb_io_data_supported = true;

	return;
@@ -557,7 +562,9 @@ nvme_pcie_ctrlr_alloc_cmb(struct spdk_nvme_ctrlr *ctrlr, uint64_t length, uint64
	round_offset = pctrlr->cmb_current_offset;
	round_offset = (round_offset + (aligned - 1)) & ~(aligned - 1);

	if (round_offset + length > pctrlr->cmb_size) {
	/* CMB may only consume part of the BAR, calculate accordingly */
	if (round_offset + length > pctrlr->cmb_max_offset) {
		SPDK_ERRLOG("Tried to allocate past valid CMB range!\n");
		return -1;
	}