[PATCH 1/1] nvme: Fix multipage prp-list

Alexander Sowarka alexander.sowarka at gmail.com
Sun Aug 28 21:30:20 CEST 2022


The nvme driver falsely assumed that the last entry on a page
of the prp-list always points to the next page of the prp-list.
This potentially can lead to the illegal creation of pages on
the prp-list with only a single entry. This change now ensures
that splitting the prp-list into multiple pages, behaves now as
required by the NVME-Spec.

Related to this, also the size of the memory allocation is adjusted
accordingly.

Signed-off-by: Alexander Sowarka <alexander.sowarka at aerq.com>
---

 drivers/nvme/nvme.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 1d56517e99..55cce0a778 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -72,7 +72,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
 	}
 
 	nprps = DIV_ROUND_UP(length, page_size);
-	num_pages = DIV_ROUND_UP(nprps, prps_per_page);
+	num_pages = DIV_ROUND_UP(nprps - 1, prps_per_page - 1);
 
 	if (nprps > dev->prp_entry_num) {
 		free(dev->prp_pool);
@@ -85,13 +85,13 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
 			printf("Error: malloc prp_pool fail\n");
 			return -ENOMEM;
 		}
-		dev->prp_entry_num = prps_per_page * num_pages;
+		dev->prp_entry_num = num_pages * (prps_per_page - 1) + 1;
 	}
 
 	prp_pool = dev->prp_pool;
 	i = 0;
 	while (nprps) {
-		if (i == ((page_size >> 3) - 1)) {
+		if ((i == (prps_per_page - 1)) && nprps > 1) {
 			*(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
 					page_size);
 			i = 0;
@@ -104,7 +104,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
 	*prp2 = (ulong)dev->prp_pool;
 
 	flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
-			   dev->prp_entry_num * sizeof(u64));
+			   num_pages * page_size);
 
 	return 0;
 }
-- 
2.37.1



More information about the U-Boot mailing list