From be6d1e1fb9a08357165b07125d8e8b94d20e31c8 Mon Sep 17 00:00:00 2001 From: Joel Granados Date: Mon, 27 May 2024 13:58:09 +0200 Subject: [PATCH 1/2] examples/io: Use op_len as transfer size Use the already existing transfer size variable op_len when calling mapping and transfer functions Signed-off-by: Joel Granados --- examples/io.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/io.c b/examples/io.c index f751ef8e..1db47944 100644 --- a/examples/io.c +++ b/examples/io.c @@ -69,6 +69,9 @@ int main(int argc, char **argv) opt_free_table(); + if (op_len == 0) + op_len = 0x1000; + fd = op_read ? STDOUT_FILENO : STDIN_FILENO; if (nvme_init(&ctrl, bdf, &ctrl_opts)) @@ -77,15 +80,15 @@ int main(int argc, char **argv) if (nvme_create_ioqpair(&ctrl, 1, 64, -1, 0x0)) err(1, "could not create io queue pair"); - vaddr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + vaddr = mmap(NULL, op_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - if (iommu_map_vaddr(__iommu_ctx(&ctrl), vaddr, 0x1000, &iova, 0x0)) + if (iommu_map_vaddr(__iommu_ctx(&ctrl), vaddr, op_len, &iova, 0x0)) err(1, "failed to reserve iova"); if (op_write) { fprintf(stderr, "reading payload\n"); - ret = readmaxfd(fd, vaddr, 0x1000); + ret = readmaxfd(fd, vaddr, op_len); if (ret < 0) err(1, "could not read fd"); @@ -99,7 +102,7 @@ int main(int argc, char **argv) .nsid = cpu_to_le32(nsid), }; - ret = nvme_rq_map_prp(&ctrl, rq, &cmd, iova, 0x1000); + ret = nvme_rq_map_prp(&ctrl, rq, &cmd, iova, op_len); if (ret) err(1, "could not map prps"); @@ -111,7 +114,7 @@ int main(int argc, char **argv) if (op_read) { fprintf(stderr, "writing payload\n"); - ret = writeallfd(fd, vaddr, 0x1000); + ret = writeallfd(fd, vaddr, op_len); if (ret < 0) err(1, "could not write fd"); From 66e71c117f4d0a2824053c0a660790f0cb33e781 Mon Sep 17 00:00:00 2001 From: Joel Granados Date: Mon, 27 May 2024 14:01:01 +0200 Subject: [PATCH 2/2] examples/io: Calculate and forward size in number of LBAs Qemu uses the number of LBAs in order to traverse the "correct" number of prps for the transfer. If this value is not forwarded it acts like if there were just one PRP. Signed-off-by: Joel Granados --- examples/io.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/examples/io.c b/examples/io.c index 1db47944..a2b18c8b 100644 --- a/examples/io.c +++ b/examples/io.c @@ -45,6 +45,36 @@ static struct opt_table opts[] = { OPT_ENDTABLE, }; +unsigned int get_lb_bytes(struct nvme_ctrl *ctrl, unsigned long nsid) +{ + void *vaddr; + ssize_t len; + union nvme_cmd cmd; + struct nvme_id_ns *id_ns; + struct nvme_lbaf *lbaf; + unsigned int lb_bytes; + + len = pgmap(&vaddr, NVME_IDENTIFY_DATA_SIZE); + if (len < 0) + err(1, "could not allocate aligned memory"); + + cmd.identify = (struct nvme_cmd_identify) { + .opcode = nvme_admin_identify, + .cns = NVME_IDENTIFY_CNS_NS, + .nsid = cpu_to_le32(nsid), + }; + + if (nvme_admin(ctrl, &cmd, vaddr, len, NULL)) + err(1, "nvme_admin"); + + id_ns = vaddr; + lbaf = &id_ns->lbaf[id_ns->flbas]; + lb_bytes = 1ULL << lbaf->ds; + + pgunmap(vaddr, len); + return lb_bytes; +} + int main(int argc, char **argv) { void *vaddr; @@ -77,6 +107,8 @@ int main(int argc, char **argv) if (nvme_init(&ctrl, bdf, &ctrl_opts)) err(1, "failed to init nvme controller"); + unsigned int lb_nbytes = get_lb_bytes(&ctrl, nsid); + if (nvme_create_ioqpair(&ctrl, 1, 64, -1, 0x0)) err(1, "could not create io queue pair"); @@ -100,6 +132,7 @@ int main(int argc, char **argv) cmd.rw = (struct nvme_cmd_rw) { .opcode = op_write ? nvme_cmd_write : nvme_cmd_read, .nsid = cpu_to_le32(nsid), + .nlb = (ROUND_UP(op_len, lb_nbytes)/lb_nbytes) - 1, }; ret = nvme_rq_map_prp(&ctrl, rq, &cmd, iova, op_len);