From c4eef59faab6ae4ecb1beae6d4391b0889bc3ff3 Mon Sep 17 00:00:00 2001
From: Jon Lin <jon.lin@rock-chips.com>
Date: Tue, 19 Oct 2021 10:40:54 +0800
Subject: [PATCH] nvme: Fix error in nvme_setup_prps
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

Consulting to "NVM Express® Base Specification, revision 2.0".

If more PRP List pages are required, then the last entry of
the PRP List contains the Page Base Address of the next PRP
List page. The next PRP List page shall be memory page aligned.

Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
---
 drivers/nvme/nvme.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 9623c896a1..22ded626a5 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -100,7 +100,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);
 
 	if (nprps > dev->prp_entry_num) {
 		free(dev->prp_pool);
@@ -119,10 +119,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
 	prp_pool = dev->prp_pool;
 	i = 0;
 	while (nprps) {
-		if (i == ((page_size >> 3) - 1)) {
-			*(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
+		if (i == prps_per_page) {
+			*(prp_pool + i) = *(prp_pool + i - 1);
+			*(prp_pool + i - 1) = cpu_to_le64((ulong)prp_pool +
 					page_size);
-			i = 0;
+			i = 1;
 			prp_pool += page_size;
 		}
 		*(prp_pool + i++) = cpu_to_le64(dma_addr);
-- 
2.39.5