nvmf/vfio-user: add map_q function
The map_q function is used to map Guest's physical memory address to Host virtual address for SQ/CQ. This function can be used both for initializing SQ/CQ and remap SQ/CQ, when used for remap SQ/CQ, we don't need to unmap the related memory region. Change-Id: Ia42e01a68482e5678dbaf8d0d4e8c04c1a94789d Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9012 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ziye Yang <ziye.yang@intel.com>
This commit is contained in:
parent
7d136a2088
commit
e9fd737a8e
@ -633,11 +633,39 @@ sqhd_advance(struct nvmf_vfio_user_ctrlr *ctrlr, struct nvmf_vfio_user_qpair *qp
|
|||||||
qpair->sq.head = (qpair->sq.head + 1) % qpair->sq.size;
|
qpair->sq.head = (qpair->sq.head + 1) % qpair->sq.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
map_q(struct nvmf_vfio_user_ctrlr *vu_ctrlr, struct nvme_q *q, bool is_cq, bool unmap)
|
||||||
|
{
|
||||||
|
uint64_t len;
|
||||||
|
|
||||||
|
assert(q->size);
|
||||||
|
assert(q->addr == NULL);
|
||||||
|
|
||||||
|
if (is_cq) {
|
||||||
|
len = q->size * sizeof(struct spdk_nvme_cpl);
|
||||||
|
} else {
|
||||||
|
len = q->size * sizeof(struct spdk_nvme_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
q->addr = map_one(vu_ctrlr->endpoint->vfu_ctx, q->prp1, len, q->sg,
|
||||||
|
&q->iov, is_cq ? PROT_READ | PROT_WRITE : PROT_READ);
|
||||||
|
if (q->addr == NULL) {
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unmap) {
|
||||||
|
memset(q->addr, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
asq_setup(struct nvmf_vfio_user_ctrlr *ctrlr)
|
asq_setup(struct nvmf_vfio_user_ctrlr *ctrlr)
|
||||||
{
|
{
|
||||||
struct nvme_q *sq;
|
struct nvme_q *sq;
|
||||||
const struct spdk_nvmf_registers *regs;
|
const struct spdk_nvmf_registers *regs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
assert(ctrlr != NULL);
|
assert(ctrlr != NULL);
|
||||||
assert(ctrlr->qp[0] != NULL);
|
assert(ctrlr->qp[0] != NULL);
|
||||||
@ -647,16 +675,16 @@ asq_setup(struct nvmf_vfio_user_ctrlr *ctrlr)
|
|||||||
regs = spdk_nvmf_ctrlr_get_regs(ctrlr->qp[0]->qpair.ctrlr);
|
regs = spdk_nvmf_ctrlr_get_regs(ctrlr->qp[0]->qpair.ctrlr);
|
||||||
sq = &ctrlr->qp[0]->sq;
|
sq = &ctrlr->qp[0]->sq;
|
||||||
sq->size = regs->aqa.bits.asqs + 1;
|
sq->size = regs->aqa.bits.asqs + 1;
|
||||||
|
sq->prp1 = regs->asq;
|
||||||
sq->head = ctrlr->doorbells[0] = 0;
|
sq->head = ctrlr->doorbells[0] = 0;
|
||||||
sq->cqid = 0;
|
sq->cqid = 0;
|
||||||
sq->addr = map_one(ctrlr->endpoint->vfu_ctx, regs->asq,
|
|
||||||
sq->size * sizeof(struct spdk_nvme_cmd), sq->sg,
|
|
||||||
&sq->iov, PROT_READ);
|
|
||||||
if (sq->addr == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(sq->addr, 0, sq->size * sizeof(struct spdk_nvme_cmd));
|
|
||||||
sq->is_cq = false;
|
sq->is_cq = false;
|
||||||
|
|
||||||
|
ret = map_q(ctrlr, sq, false, true);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
*tdbl(ctrlr, sq) = 0;
|
*tdbl(ctrlr, sq) = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -719,6 +747,7 @@ acq_setup(struct nvmf_vfio_user_ctrlr *ctrlr)
|
|||||||
{
|
{
|
||||||
struct nvme_q *cq;
|
struct nvme_q *cq;
|
||||||
const struct spdk_nvmf_registers *regs;
|
const struct spdk_nvmf_registers *regs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
assert(ctrlr != NULL);
|
assert(ctrlr != NULL);
|
||||||
assert(ctrlr->qp[0] != NULL);
|
assert(ctrlr->qp[0] != NULL);
|
||||||
@ -728,16 +757,15 @@ acq_setup(struct nvmf_vfio_user_ctrlr *ctrlr)
|
|||||||
assert(regs != NULL);
|
assert(regs != NULL);
|
||||||
cq = &ctrlr->qp[0]->cq;
|
cq = &ctrlr->qp[0]->cq;
|
||||||
cq->size = regs->aqa.bits.acqs + 1;
|
cq->size = regs->aqa.bits.acqs + 1;
|
||||||
|
cq->prp1 = regs->acq;
|
||||||
cq->tail = 0;
|
cq->tail = 0;
|
||||||
cq->addr = map_one(ctrlr->endpoint->vfu_ctx, regs->acq,
|
|
||||||
cq->size * sizeof(struct spdk_nvme_cpl), cq->sg,
|
|
||||||
&cq->iov, PROT_READ | PROT_WRITE);
|
|
||||||
if (cq->addr == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(cq->addr, 0, cq->size * sizeof(struct spdk_nvme_cpl));
|
|
||||||
cq->is_cq = true;
|
cq->is_cq = true;
|
||||||
cq->ien = true;
|
cq->ien = true;
|
||||||
|
|
||||||
|
ret = map_q(ctrlr, cq, true, true);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
*hdbl(ctrlr, cq) = 0;
|
*hdbl(ctrlr, cq) = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1034,14 +1062,12 @@ static int
|
|||||||
handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
|
handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
|
||||||
struct spdk_nvme_cmd *cmd, const bool is_cq)
|
struct spdk_nvme_cmd *cmd, const bool is_cq)
|
||||||
{
|
{
|
||||||
size_t entry_size;
|
|
||||||
uint16_t qid, qsize;
|
uint16_t qid, qsize;
|
||||||
uint16_t sc = SPDK_NVME_SC_SUCCESS;
|
uint16_t sc = SPDK_NVME_SC_SUCCESS;
|
||||||
uint16_t sct = SPDK_NVME_SCT_GENERIC;
|
uint16_t sct = SPDK_NVME_SCT_GENERIC;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct nvmf_vfio_user_qpair *vu_qpair;
|
struct nvmf_vfio_user_qpair *vu_qpair;
|
||||||
struct nvme_q *io_q;
|
struct nvme_q *io_q;
|
||||||
int prot;
|
|
||||||
|
|
||||||
assert(ctrlr != NULL);
|
assert(ctrlr != NULL);
|
||||||
assert(cmd != NULL);
|
assert(cmd != NULL);
|
||||||
@ -1084,7 +1110,6 @@ handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
io_q = &ctrlr->qp[qid]->cq;
|
io_q = &ctrlr->qp[qid]->cq;
|
||||||
entry_size = sizeof(struct spdk_nvme_cpl);
|
|
||||||
if (cmd->cdw11_bits.create_io_cq.pc != 0x1) {
|
if (cmd->cdw11_bits.create_io_cq.pc != 0x1) {
|
||||||
SPDK_ERRLOG("%s: non-PC CQ not supporred\n", ctrlr_id(ctrlr));
|
SPDK_ERRLOG("%s: non-PC CQ not supporred\n", ctrlr_id(ctrlr));
|
||||||
sc = SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF;
|
sc = SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF;
|
||||||
@ -1103,7 +1128,6 @@ handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
io_q = &ctrlr->qp[qid]->sq;
|
io_q = &ctrlr->qp[qid]->sq;
|
||||||
entry_size = sizeof(struct spdk_nvme_cmd);
|
|
||||||
if (cmd->cdw11_bits.create_io_sq.pc != 0x1) {
|
if (cmd->cdw11_bits.create_io_sq.pc != 0x1) {
|
||||||
SPDK_ERRLOG("%s: non-PC SQ not supported\n", ctrlr_id(ctrlr));
|
SPDK_ERRLOG("%s: non-PC SQ not supported\n", ctrlr_id(ctrlr));
|
||||||
sc = SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF;
|
sc = SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF;
|
||||||
@ -1117,19 +1141,14 @@ handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
|
|||||||
|
|
||||||
io_q->is_cq = is_cq;
|
io_q->is_cq = is_cq;
|
||||||
io_q->size = qsize;
|
io_q->size = qsize;
|
||||||
prot = PROT_READ;
|
io_q->prp1 = cmd->dptr.prp.prp1;
|
||||||
if (is_cq) {
|
|
||||||
prot |= PROT_WRITE;
|
err = map_q(ctrlr, io_q, is_cq, true);
|
||||||
}
|
if (err) {
|
||||||
io_q->addr = map_one(ctrlr->endpoint->vfu_ctx, cmd->dptr.prp.prp1,
|
|
||||||
io_q->size * entry_size, io_q->sg, &io_q->iov, prot);
|
|
||||||
if (io_q->addr == NULL) {
|
|
||||||
sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
||||||
SPDK_ERRLOG("%s: failed to map I/O queue: %m\n", ctrlr_id(ctrlr));
|
SPDK_ERRLOG("%s: failed to map I/O queue: %m\n", ctrlr_id(ctrlr));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
io_q->prp1 = cmd->dptr.prp.prp1;
|
|
||||||
memset(io_q->addr, 0, io_q->size * entry_size);
|
|
||||||
|
|
||||||
SPDK_DEBUGLOG(nvmf_vfio, "%s: mapped %cQ%d IOVA=%#lx vaddr=%#llx\n",
|
SPDK_DEBUGLOG(nvmf_vfio, "%s: mapped %cQ%d IOVA=%#lx vaddr=%#llx\n",
|
||||||
ctrlr_id(ctrlr), is_cq ? 'C' : 'S',
|
ctrlr_id(ctrlr), is_cq ? 'C' : 'S',
|
||||||
|
Loading…
Reference in New Issue
Block a user