From f185e4ecf8b8266d4e5fa6b20642a73699b7d464 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Fri, 21 Apr 2017 16:23:05 -0700 Subject: [PATCH] nvme/pcie: register CMB with spdk_mem_register() Enable address translation for I/O buffers within the controller memory buffer region by registering the CMB using spdk_mem_register(). Change-Id: I44829757ad15fbc3ea96fa494b9fb32dd67a7138 Signed-off-by: Daniel Verkamp Signed-off-by: Stephen Bates Reviewed-on: https://review.gerrithub.io/397035 Reviewed-by: Jim Harris Tested-by: SPDK Automated Test System --- lib/nvme/nvme_pcie.c | 32 +++++++++++++++++++ test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c | 3 ++ 2 files changed, 35 insertions(+) diff --git a/lib/nvme/nvme_pcie.c b/lib/nvme/nvme_pcie.c index 7363dc294..c48f0e2d3 100644 --- a/lib/nvme/nvme_pcie.c +++ b/lib/nvme/nvme_pcie.c @@ -88,6 +88,9 @@ struct nvme_pcie_ctrlr { /* Current offset of controller memory buffer */ uint64_t cmb_current_offset; + void *cmb_mem_register_addr; + size_t cmb_mem_register_size; + /** stride in uint32_t units between doorbell registers (1 = 4 bytes, 2 = 8 bytes, ...) */ uint32_t doorbell_stride_u32; @@ -442,6 +445,7 @@ nvme_pcie_ctrlr_map_cmb(struct nvme_pcie_ctrlr *pctrlr) union spdk_nvme_cmbsz_register cmbsz; union spdk_nvme_cmbloc_register cmbloc; uint64_t size, unit_size, offset, bar_size, bar_phys_addr; + uint64_t mem_register_start, mem_register_end; if (nvme_pcie_ctrlr_get_cmbsz(pctrlr, &cmbsz) || nvme_pcie_ctrlr_get_cmbloc(pctrlr, &cmbloc)) { @@ -489,6 +493,30 @@ nvme_pcie_ctrlr_map_cmb(struct nvme_pcie_ctrlr *pctrlr) pctrlr->ctrlr.opts.use_cmb_sqs = false; } + /* If only SQS is supported use legacy mapping */ + if (cmbsz.bits.sqs && !(cmbsz.bits.wds || cmbsz.bits.rds)) { + return; + } + + /* If CMB is less than 4MiB in size then abort CMB mapping */ + if (pctrlr->cmb_size < (1ULL << 22)) { + goto exit; + } + + mem_register_start = (((uintptr_t)pctrlr->cmb_bar_virt_addr + offset + 0x1fffff) & ~(0x200000 - 1)); + mem_register_end = ((uintptr_t)pctrlr->cmb_bar_virt_addr + offset + pctrlr->cmb_size); + mem_register_end &= ~(uint64_t)(0x200000 - 1); + pctrlr->cmb_mem_register_addr = (void *)mem_register_start; + pctrlr->cmb_mem_register_size = mem_register_end - mem_register_start; + + rc = spdk_mem_register(pctrlr->cmb_mem_register_addr, pctrlr->cmb_mem_register_size); + if (rc) { + SPDK_ERRLOG("spdk_mem_register() failed\n"); + goto exit; + } + pctrlr->cmb_current_offset = mem_register_start - ((uint64_t)pctrlr->cmb_bar_virt_addr + offset); + + return; exit: pctrlr->cmb_bar_virt_addr = NULL; @@ -504,6 +532,10 @@ nvme_pcie_ctrlr_unmap_cmb(struct nvme_pcie_ctrlr *pctrlr) void *addr = pctrlr->cmb_bar_virt_addr; if (addr) { + if (pctrlr->cmb_mem_register_addr) { + spdk_mem_unregister(pctrlr->cmb_mem_register_addr, pctrlr->cmb_mem_register_size); + } + if (nvme_pcie_ctrlr_get_cmbloc(pctrlr, &cmbloc)) { SPDK_ERRLOG("get_cmbloc() failed\n"); return -EIO; diff --git a/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c b/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c index b4a296afe..7e2e68867 100644 --- a/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c +++ b/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c @@ -39,6 +39,9 @@ #include "nvme/nvme_pcie.c" +DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0); +DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0); + struct spdk_trace_flag SPDK_LOG_NVME = { .name = "nvme", .enabled = false,