<div dir="ltr"><div>From a17975b5fe0cb2b17fdf0335430d5f4d2ab3ba4d Mon Sep 17 00:00:00 2001</div><div>From: Matt DeVillier <<a href="mailto:matt.devillier@gmail.com">matt.devillier@gmail.com</a>></div><div>Date: Sun, 12 Aug 2018 15:26:59 -0500</div><div>Subject: [PATCH 1/1] nvme: fix I/O queue length calculation overflow</div><div><br></div><div>Commit cd47172 changed the I/O queue length calculation to use the</div><div>Maximum Queue Entries Supported (MQES) value from the capabilities</div><div>register, plus one, with a maximum value of NVME_PAGE_SIZE.</div><div><br></div><div>An unintended effect from this is that a MQES value of 0xFFFF yields</div><div>a length of zero, resulting in the queue allocation failing. Fix this</div><div>by checking for a zero length when checking that the length exceeds</div><div>NVME_PAGE_SIZE, and setting to NVME_PAGE_SIZE.</div><div><br></div><div>TEST: build/boot on a Purism Librem13v2 with a MyDigitalSSD BPX NVMe</div><div>drive, which reports a MQES of 0xFFFF. Verify NVMe drive present in</div><div>boot menu and OS boots successfully.</div><div><br></div><div>Signed-off-by: Matt DeVillier <<a href="mailto:matt.devillier@gmail.com">matt.devillier@gmail.com</a>></div><div>---</div><div> src/hw/nvme.c | 4 ++--</div><div> 1 file changed, 2 insertions(+), 2 deletions(-)</div><div><br></div><div>diff --git a/src/hw/nvme.c b/src/hw/nvme.c</div><div>index e6d739d..c2d6863 100644</div><div>--- a/src/hw/nvme.c</div><div>+++ b/src/hw/nvme.c</div><div>@@ -319,7 +319,7 @@ nvme_create_io_cq(struct nvme_ctrl *ctrl, struct nvme_cq *cq, u16 q_idx)</div><div>     int rc;</div><div>     struct nvme_sqe *cmd_create_cq;</div><div>     u16 length = 1 + (ctrl->reg->cap & 0xffff);</div><div>-    if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe))</div><div>+    if (length == 0 || length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe))</div><div>         length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe);</div><div> </div><div>     rc = nvme_init_cq(ctrl, cq, q_idx, length);</div><div>@@ -363,7 +363,7 @@ nvme_create_io_sq(struct nvme_ctrl *ctrl, struct nvme_sq *sq, u16 q_idx, struct</div><div>     int rc;</div><div>     struct nvme_sqe *cmd_create_sq;</div><div>     u16 length = 1 + (ctrl->reg->cap & 0xffff);</div><div>-    if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe))</div><div>+    if (length == 0 || length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe))</div><div>         length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe);</div><div> </div><div>     rc = nvme_init_sq(ctrl, sq, q_idx, length, cq);</div><div>-- </div><div>2.17.1</div></div>