{"id":2235130,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2235130/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260508154245.0E24868BFE@verein.lst.de/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.2/projects/18/?format=json","name":"U-Boot","link_name":"uboot","list_id":"u-boot.lists.denx.de","list_email":"u-boot@lists.denx.de","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260508154245.0E24868BFE@verein.lst.de>","list_archive_url":null,"date":"2026-05-08T15:42:45","name":"[2/3] nvme: Fix missing address translation for PCIe inbound access","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"99cce3a6a4ec8ce8bf43f4d3b227812ed0aa3e6e","submitter":{"id":2722,"url":"http://patchwork.ozlabs.org/api/1.2/people/2722/?format=json","name":"Torsten Duwe","email":"duwe@lst.de"},"delegate":{"id":84350,"url":"http://patchwork.ozlabs.org/api/1.2/users/84350/?format=json","username":"narmstrong","first_name":"Neil","last_name":"Armstrong","email":"narmstrong@baylibre.com"},"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260508154245.0E24868BFE@verein.lst.de/mbox/","series":[{"id":503410,"url":"http://patchwork.ozlabs.org/api/1.2/series/503410/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=503410","date":"2026-05-08T15:41:08","name":"Fix NVMe, not only on Raspberry Pi 5","version":1,"mbox":"http://patchwork.ozlabs.org/series/503410/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2235130/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2235130/checks/","tags":{},"related":[],"headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=fail (p=none dis=none) header.from=lst.de","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n dmarc=fail (p=none dis=none) header.from=lst.de","phobos.denx.de; spf=pass smtp.mailfrom=duwe@lst.de"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4gBtg05zFxz1yJq\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 09 May 2026 01:42:52 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 3C23684D6D;\n\tFri,  8 May 2026 17:42:50 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id A227A84D5B; Fri,  8 May 2026 17:42:48 +0200 (CEST)","from verein.lst.de (verein.lst.de [213.95.11.211])\n (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 4E6EA84D2F\n for <u-boot@lists.denx.de>; Fri,  8 May 2026 17:42:46 +0200 (CEST)","by verein.lst.de (Postfix, from userid 2005)\n id 0E24868BFE; Fri,  8 May 2026 17:42:45 +0200 (CEST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-1.9 required=5.0 tests=BAYES_00,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2","To":"Bin Meng <bmeng.cn@gmail.com>,\n Andrew Goodbody <andrew.goodbody@linaro.org>","Cc":"=?unknown-8bit?q?Peter_Robinson_=3Cpbrobinson=40gmail=2Ecom=3E=2C_Matthi?=\n\t=?unknown-8bit?q?as_Brugger_=3Cmbrugger=40suse=2Ecom=3E=2C?=\n\t=?unknown-8bit?q?_Tom_Rini_=3Ctrini=40konsulko=2Ecom=3E=2C_Andrea_della_Port?=\n\t=?unknown-8bit?q?a_=3Candrea=2Eporta=40suse=2Ecom=3E=2C?=\n\t=?unknown-8bit?q?_Neil_Armstrong_=3Cneil=2Earmstrong=40linaro=2Eorg=3E=2C_Si?=\n\t=?unknown-8bit?q?mon_Glass_=3Csjg=40chromium=2Eorg=3E=2C?=\n\t=?unknown-8bit?b?ICJKYW4gxIxlcm3DoWsiIDxzYWlyb25Ac2Fpcm9uLmN6PiwgdS1ib290?=\n\t=?unknown-8bit?b?QGxpc3RzLmRlbnguZGU=?=","Subject":"[PATCH 2/3] nvme: Fix missing address translation for PCIe inbound\n access","In-Reply-To":"<20260508154108.336B968BEB@verein.lst.de>","References":"<20260508154108.336B968BEB@verein.lst.de>","Message-Id":"<20260508154245.0E24868BFE@verein.lst.de>","Date":"Fri,  8 May 2026 17:42:45 +0200 (CEST)","From":"duwe@lst.de (Torsten Duwe)","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"},"content":"From: Torsten Duwe <duwe@suse.de>\n\nU-Boot currently does not account for PCIe bridges with a non-zero\ninbound access offset when talking NVMe, it only works on platforms\nwhere this offset happens to be zero.\n\nThis patch enhances the NVMe driver with the ability to also handle\nthese cases.\n\nSigned-off-by: Torsten Duwe <duwe@suse.de>\n\n---\n drivers/nvme/nvme.c | 34 +++++++++++++++++++++-------------\n 1 file changed, 21 insertions(+), 13 deletions(-)","diff":"diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c\nindex 2b14437f69c..99a47bf25f2 100644\n--- a/drivers/nvme/nvme.c\n+++ b/drivers/nvme/nvme.c\n@@ -12,6 +12,7 @@\n #include <log.h>\n #include <malloc.h>\n #include <memalign.h>\n+#include <phys2bus.h>\n #include <time.h>\n #include <dm/device-internal.h>\n #include <linux/compat.h>\n@@ -27,6 +28,13 @@\n #define IO_TIMEOUT\t\t30\n #define MAX_PRP_POOL\t\t512\n \n+/*\n+ * Convert a memory address to the value needed by the PCI device to\n+ * access the given location, taking into account inbound window\n+ * translations of PCI bridges:\n+ */\n+#define DEV_ADDR(a)\t\tdev_phys_to_bus(dev->udev, (a))\n+\n static int nvme_wait_csts(struct nvme_dev *dev, u32 mask, u32 val)\n {\n \tint timeout;\n@@ -91,12 +99,12 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,\n \ti = 0;\n \twhile (nprps) {\n \t\tif ((i == (prps_per_page - 1)) && nprps > 1) {\n-\t\t\t*(prp_pool + i) = cpu_to_le64((ulong)prp_pool +\n-\t\t\t\t\tpage_size);\n+\t\t\t*(prp_pool + i) = cpu_to_le64(DEV_ADDR((ulong)prp_pool +\n+\t\t\t\t\t\t\t\tpage_size));\n \t\t\ti = 0;\n \t\t\tprp_pool += page_size;\n \t\t}\n-\t\t*(prp_pool + i++) = cpu_to_le64(dma_addr);\n+\t\t*(prp_pool + i++) = cpu_to_le64(DEV_ADDR(dma_addr));\n \t\tdma_addr += page_size;\n \t\tnprps--;\n \t}\n@@ -393,8 +401,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)\n \tdev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;\n \n \twritel(aqa, &dev->bar->aqa);\n-\tnvme_writeq((ulong)nvmeq->sq_cmds, &dev->bar->asq);\n-\tnvme_writeq((ulong)nvmeq->cqes, &dev->bar->acq);\n+\tnvme_writeq(DEV_ADDR((ulong)nvmeq->sq_cmds), &dev->bar->asq);\n+\tnvme_writeq(DEV_ADDR((ulong)nvmeq->cqes), &dev->bar->acq);\n \n \tresult = nvme_enable_ctrl(dev);\n \tif (result)\n@@ -420,7 +428,7 @@ static int nvme_alloc_cq(struct nvme_dev *dev, u16 qid,\n \n \tmemset(&c, 0, sizeof(c));\n \tc.create_cq.opcode = nvme_admin_create_cq;\n-\tc.create_cq.prp1 = cpu_to_le64((ulong)nvmeq->cqes);\n+\tc.create_cq.prp1 = cpu_to_le64(DEV_ADDR((ulong)nvmeq->cqes));\n \tc.create_cq.cqid = cpu_to_le16(qid);\n \tc.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);\n \tc.create_cq.cq_flags = cpu_to_le16(flags);\n@@ -437,7 +445,7 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,\n \n \tmemset(&c, 0, sizeof(c));\n \tc.create_sq.opcode = nvme_admin_create_sq;\n-\tc.create_sq.prp1 = cpu_to_le64((ulong)nvmeq->sq_cmds);\n+\tc.create_sq.prp1 = cpu_to_le64(DEV_ADDR((ulong)nvmeq->sq_cmds));\n \tc.create_sq.sqid = cpu_to_le16(qid);\n \tc.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);\n \tc.create_sq.sq_flags = cpu_to_le16(flags);\n@@ -458,14 +466,14 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid,\n \tmemset(&c, 0, sizeof(c));\n \tc.identify.opcode = nvme_admin_identify;\n \tc.identify.nsid = cpu_to_le32(nsid);\n-\tc.identify.prp1 = cpu_to_le64(dma_addr);\n+\tc.identify.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));\n \n \tlength -= (page_size - offset);\n \tif (length <= 0) {\n \t\tc.identify.prp2 = 0;\n \t} else {\n \t\tdma_addr += (page_size - offset);\n-\t\tc.identify.prp2 = cpu_to_le64(dma_addr);\n+\t\tc.identify.prp2 = cpu_to_le64(DEV_ADDR(dma_addr));\n \t}\n \n \tc.identify.cns = cpu_to_le32(cns);\n@@ -490,7 +498,7 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,\n \tmemset(&c, 0, sizeof(c));\n \tc.features.opcode = nvme_admin_get_features;\n \tc.features.nsid = cpu_to_le32(nsid);\n-\tc.features.prp1 = cpu_to_le64(dma_addr);\n+\tc.features.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));\n \tc.features.fid = cpu_to_le32(fid);\n \n \tret = nvme_submit_admin_cmd(dev, &c, result);\n@@ -516,7 +524,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,\n \n \tmemset(&c, 0, sizeof(c));\n \tc.features.opcode = nvme_admin_set_features;\n-\tc.features.prp1 = cpu_to_le64(dma_addr);\n+\tc.features.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));\n \tc.features.fid = cpu_to_le32(fid);\n \tc.features.dword11 = cpu_to_le32(dword11);\n \n@@ -785,8 +793,8 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,\n \t\tc.rw.slba = cpu_to_le64(slba);\n \t\tslba += lbas;\n \t\tc.rw.length = cpu_to_le16(lbas - 1);\n-\t\tc.rw.prp1 = cpu_to_le64(temp_buffer);\n-\t\tc.rw.prp2 = cpu_to_le64(prp2);\n+\t\tc.rw.prp1 = cpu_to_le64(DEV_ADDR(temp_buffer));\n+\t\tc.rw.prp2 = cpu_to_le64(DEV_ADDR(prp2));\n \t\tstatus = nvme_submit_sync_cmd(dev->queues[NVME_IO_Q],\n \t\t\t\t&c, NULL, IO_TIMEOUT);\n \t\tif (status)\n","prefixes":["2/3"]}