* [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register
@ 2026-09-08 6:18 Sumit Kumar
2026-09-08 6:25 ` sashiko-bot
2026-09-08 15:08 ` Niklas Cassel
0 siblings, 2 replies; 5+ messages in thread
From: Sumit Kumar @ 2026-09-08 6:18 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas
Cc: linux-pci, linux-kernel, Sumit Kumar
An outbound iATU region matches any local (AXI/application-side)
address that falls within its Base/Limit window and rewrites it to
the PCIe-side address programmed in that region's Target Address
Registers before the transaction goes out on the link. This matching
does not distinguish CPU-initiated transactions from ones issued by
the internal DMA engine (eDMA/HDMA).
Example: outbound region 0 is programmed with Base/Limit covering
local addresses 0x8000_0000-0x8000_0FFF and Target 0x1_0000_0000, for
CPU-initiated accesses. The DMA engine is later given a descriptor
whose destination is the host address 0x8000_0080, which happens to
fall inside region 0's Base/Limit range. The iATU matches the DMA
transaction against region 0 too and rewrites it to 0x1_0000_0080
instead of passing 0x8000_0080 through unchanged. The transaction
then lands on the wrong host address, causing data corruption or an
IOMMU fault when the rewritten address has no valid mapping.
Set the DMA_BYPASS bit (bit 27) in PCIE_ATU_REGION_CTRL2 when
programming outbound iATU regions so only CPU/AXI-initiated
transactions are matched against the region; DMA engine transactions
bypass the translation and go out on the PCIe link with their
original address.
Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
---
pci: designware: Set DMA_BYPASS in outbound IATU to prevent HDMA
interception
---
Changes in v2:
- Rewrote the commit message according to suggestion(Mani).
- Link to v1: https://lore.kernel.org/r/20260826-dma_bypass-v1-1-3a53dc748ce2@oss.qualcomm.com
---
drivers/pci/controller/dwc/pcie-designware.c | 2 ++
drivers/pci/controller/dwc/pcie-designware.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 593388f29bdd48381cb04710f445042aaf2be29f..9297d0e607e3a1caaeb585b23742f9a29607b7f2 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -577,6 +577,8 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
/* The data-less messages only for now */
val |= PCIE_ATU_INHIBIT_PAYLOAD | atu->code;
}
+ if (dw_pcie_ver_is_ge(pci, 460A))
+ val |= PCIE_ATU_DMA_BYPASS;
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL2, val);
/*
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 0735ae94092404bc2976af67a58f6842cc5e5c50..668a5ba1c6f59aef1aaf15566b77a649bd282ce0 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -201,6 +201,7 @@
#define PCIE_ATU_ENABLE BIT(31)
#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28)
+#define PCIE_ATU_DMA_BYPASS BIT(27)
#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22)
#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
#define PCIE_ATU_LOWER_BASE 0x008
---
base-commit: 45c13f3f9e3bb15fd89ff2864c6f627a3b4b4229
change-id: 20260826-dma_bypass-bbbf8a0c9af7
Best regards,
--
Sumit Kumar <sumit.kumar@oss.qualcomm.com>
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register
2026-09-08 6:18 [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register Sumit Kumar
@ 2026-09-08 6:25 ` sashiko-bot
2026-09-08 15:08 ` Niklas Cassel
1 sibling, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-09-08 6:25 UTC (permalink / raw)
To: Sumit Kumar; +Cc: linux-pci
> An outbound iATU region matches any local (AXI/application-side)
> address that falls within its Base/Limit window and rewrites it to
> the PCIe-side address programmed in that region's Target Address
> Registers before the transaction goes out on the link. This matching
> does not distinguish CPU-initiated transactions from ones issued by
> the internal DMA engine (eDMA/HDMA).
>
> Example: outbound region 0 is programmed with Base/Limit covering
> local addresses 0x8000_0000-0x8000_0FFF and Target 0x1_0000_0000, for
> CPU-initiated accesses. The DMA engine is later given a descriptor
> whose destination is the host address 0x8000_0080, which happens to
> fall inside region 0's Base/Limit range. The iATU matches the DMA
> transaction against region 0 too and rewrites it to 0x1_0000_0080
> instead of passing 0x8000_0080 through unchanged. The transaction
> then lands on the wrong host address, causing data corruption or an
> IOMMU fault when the rewritten address has no valid mapping.
>
> Set the DMA_BYPASS bit (bit 27) in PCIE_ATU_REGION_CTRL2 when
> programming outbound iATU regions so only CPU/AXI-initiated
> transactions are matched against the region; DMA engine transactions
> bypass the translation and go out on the PCIe link with their
> original address.
>
> Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-dma_bypass-v2-1-c3c81d408c0c@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register
2026-09-08 6:18 [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register Sumit Kumar
2026-09-08 6:25 ` sashiko-bot
@ 2026-09-08 15:08 ` Niklas Cassel
2026-09-13 9:35 ` Manivannan Sadhasivam
1 sibling, 1 reply; 5+ messages in thread
From: Niklas Cassel @ 2026-09-08 15:08 UTC (permalink / raw)
To: Sumit Kumar
Cc: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas, linux-pci,
linux-kernel
Hello Sumit,
On Tue, Sep 08, 2026 at 11:48:22AM +0530, Sumit Kumar wrote:
> An outbound iATU region matches any local (AXI/application-side)
> address that falls within its Base/Limit window and rewrites it to
> the PCIe-side address programmed in that region's Target Address
> Registers before the transaction goes out on the link. This matching
> does not distinguish CPU-initiated transactions from ones issued by
> the internal DMA engine (eDMA/HDMA).
>
> Example: outbound region 0 is programmed with Base/Limit covering
> local addresses 0x8000_0000-0x8000_0FFF and Target 0x1_0000_0000, for
> CPU-initiated accesses. The DMA engine is later given a descriptor
> whose destination is the host address 0x8000_0080, which happens to
> fall inside region 0's Base/Limit range. The iATU matches the DMA
> transaction against region 0 too and rewrites it to 0x1_0000_0080
> instead of passing 0x8000_0080 through unchanged. The transaction
> then lands on the wrong host address, causing data corruption or an
> IOMMU fault when the rewritten address has no valid mapping.
>
> Set the DMA_BYPASS bit (bit 27) in PCIE_ATU_REGION_CTRL2 when
> programming outbound iATU regions so only CPU/AXI-initiated
> transactions are matched against the region; DMA engine transactions
> bypass the translation and go out on the PCIe link with their
> original address.
>
> Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
If you look at e.g.
drivers/pci/endpoint/functions/pci-epf-test.c:pci_epf_test_read()
you can see that it does call pci_epc_mem_map(), which will end up
as a call to dw_pcie_prog_outbound_atu() to setup an iATU mapping
on DWC based PCIe controllers.
If you configure DWC based controllers to bypass the iATU, this
call to pci_epc_mem_map() is completely useless.
Perhaps the DWC driver can set a DMA_SLAVE_SKIP_MEM_MAP flag
or similar when registering the eDMA, which pci-epf-test then could check,
and not call pci_epc_mem_map() if DMA_SLAVE_SKIP_MEM_MAP is set.
Because, while I can read in the databook that this is not needed
for DWC based controllers, I have no idea if the pci_epc_mem_map()
is still needed for e.g.:
drivers/pci/controller/cadence/pcie-cadence-ep.c
drivers/pci/controller/pcie-rcar-ep.c
drivers/pci/controller/pcie-rockchip-ep.c
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register
2026-09-08 15:08 ` Niklas Cassel
@ 2026-09-13 9:35 ` Manivannan Sadhasivam
2026-09-13 17:16 ` Niklas Cassel
0 siblings, 1 reply; 5+ messages in thread
From: Manivannan Sadhasivam @ 2026-09-13 9:35 UTC (permalink / raw)
To: Niklas Cassel
Cc: Sumit Kumar, Jingoo Han, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas, linux-pci,
linux-kernel
On Tue, Sep 08, 2026 at 05:08:26PM +0200, Niklas Cassel wrote:
> Hello Sumit,
>
> On Tue, Sep 08, 2026 at 11:48:22AM +0530, Sumit Kumar wrote:
> > An outbound iATU region matches any local (AXI/application-side)
> > address that falls within its Base/Limit window and rewrites it to
> > the PCIe-side address programmed in that region's Target Address
> > Registers before the transaction goes out on the link. This matching
> > does not distinguish CPU-initiated transactions from ones issued by
> > the internal DMA engine (eDMA/HDMA).
> >
> > Example: outbound region 0 is programmed with Base/Limit covering
> > local addresses 0x8000_0000-0x8000_0FFF and Target 0x1_0000_0000, for
> > CPU-initiated accesses. The DMA engine is later given a descriptor
> > whose destination is the host address 0x8000_0080, which happens to
> > fall inside region 0's Base/Limit range. The iATU matches the DMA
> > transaction against region 0 too and rewrites it to 0x1_0000_0080
> > instead of passing 0x8000_0080 through unchanged. The transaction
> > then lands on the wrong host address, causing data corruption or an
> > IOMMU fault when the rewritten address has no valid mapping.
> >
> > Set the DMA_BYPASS bit (bit 27) in PCIE_ATU_REGION_CTRL2 when
> > programming outbound iATU regions so only CPU/AXI-initiated
> > transactions are matched against the region; DMA engine transactions
> > bypass the translation and go out on the PCIe link with their
> > original address.
> >
> > Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
>
> If you look at e.g.
> drivers/pci/endpoint/functions/pci-epf-test.c:pci_epf_test_read()
>
> you can see that it does call pci_epc_mem_map(), which will end up
> as a call to dw_pcie_prog_outbound_atu() to setup an iATU mapping
> on DWC based PCIe controllers.
>
pci_epc_mem_map() is already useless in the eDMA path today. So this patch
doesn't change that.
>
> If you configure DWC based controllers to bypass the iATU, this
> call to pci_epc_mem_map() is completely useless.
>
>
> Perhaps the DWC driver can set a DMA_SLAVE_SKIP_MEM_MAP flag
> or similar when registering the eDMA, which pci-epf-test then could check,
> and not call pci_epc_mem_map() if DMA_SLAVE_SKIP_MEM_MAP is set.
>
>
> Because, while I can read in the databook that this is not needed
> for DWC based controllers, I have no idea if the pci_epc_mem_map()
> is still needed for e.g.:
> drivers/pci/controller/cadence/pcie-cadence-ep.c
> drivers/pci/controller/pcie-rcar-ep.c
> drivers/pci/controller/pcie-rockchip-ep.c
>
Fair point. But this should be done as a separate improvement, not related to
this patch.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register
2026-09-13 9:35 ` Manivannan Sadhasivam
@ 2026-09-13 17:16 ` Niklas Cassel
0 siblings, 0 replies; 5+ messages in thread
From: Niklas Cassel @ 2026-09-13 17:16 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Sumit Kumar, Jingoo Han, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas, linux-pci,
linux-kernel
On Sun, Sep 13, 2026 at 11:35:59AM +0200, Manivannan Sadhasivam wrote:
>
> pci_epc_mem_map() is already useless in the eDMA path today. So this patch
> doesn't change that.
I'm not sure if useless is the proper word here.
Redundant is perhaps a better word.
Let me explain using pci-epf-test.c:pci_epf_test_read() as an example:
Without the patch in $subject, on a DWC based platform:
pci_epc_mem_map() will setup an iATU entry, and the eDMA transaction will then
be translated using that iATU entry, before being sent out on the PCIe bus.
So the iATU entry is actually being used.
After the patch in $subject, on a DWC based platform:
pci_epc_mem_map() will setup an iATU entry, however, because of the DMA_BYPASS
bit, that iATU entry will not be used, and the transaction will be send out on
the PCIe bus untranslated.
So I would argue that it is only after this patch that pci_epc_mem_map() will
setup an iATU entry that will then never be used.
Yes, I think I understand that you are trying to say that, for DWC based
drivers, we could theoretically skip the pci_epc_mem_map() call, and send the
transaction untranslated.
My point is that it feels silly to set the DMA_BYPASS bit without also making
sure that the pci_epc_mem_map() calls are either removed or (at least for DWC
based platforms) modified to not set up an iATU entry in the DMA path in the
first place.
I am happy that this is getting cleaned up, I just don't like a half cleanup
where we, after this commit, will setup+teardown iATU entries that will then
never be used for the actual transaction.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-13 17:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 6:18 [PATCH v2] pci: designware: Set DMA_BYPASS bit in outbound IATU CTRL2 register Sumit Kumar
2026-09-08 6:25 ` sashiko-bot
2026-09-08 15:08 ` Niklas Cassel
2026-09-13 9:35 ` Manivannan Sadhasivam
2026-09-13 17:16 ` Niklas Cassel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox