From: Thierry Reding <thierry.reding@gmail.com>
To: Rob Herring <robh+dt@kernel.org>, Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Nicolin Chen <nicolinc@nvidia.com>,
Krishna Reddy <vdumpa@nvidia.com>,
Ashish Mhetre <amhetre@nvidia.com>,
Dmitry Osipenko <dmitry.osipenko@collabora.com>,
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>,
Janne Grunau <j@jannau.net>, Sameer Pujar <spujar@nvidia.com>,
devicetree@vger.kernel.org, iommu@lists.linux-foundation.org,
linux-tegra@vger.kernel.org, asahi@lists.linux.dev
Subject: [PATCH v10 2/5] of: Stop DMA translation at last DMA parent
Date: Thu, 3 Nov 2022 14:38:57 +0100 [thread overview]
Message-ID: <20221103133900.1473855-3-thierry.reding@gmail.com> (raw)
In-Reply-To: <20221103133900.1473855-1-thierry.reding@gmail.com>
From: Thierry Reding <treding@nvidia.com>
DMA parent devices can define separate DMA busses via the "dma-ranges"
and "#address-cells" and "#size-cells" properties. If the DMA bus has
different cell counts than its parent, this can cause the translation
of DMA address to fails (e.g. truncation from 2 to 1 address cells).
Avoid this by stopping to search for DMA parents when a parent without
a "dma-ranges" property is encountered. Also, since it is the DMA parent
that defines the DMA bus, use the bus' cell counts instead of its parent
cell counts.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v10:
- new patch to avoid address truncation when traversing a bus hierarchy
with mismatching #address-cells properties
Example from Tegra194 (redacted for clarity):
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
framebuffer@0,0 {
compatible = "framebuffer";
reg = <0x2 0x57320000 0x0 0x00800000>;
iommu-addresses = <&dc0 0x2 0x57320000 0x0 0x00800000>;
};
};
bus@0 {
/* truncation happens here */
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x0 0x40000000>;
mc: memory-controller@2c00000 {
#address-cells = <2>;
#size-cells = <2>;
/*
* memory controller provides access to 512 GiB
* of system RAM (root of the DMA bus)
*/
dma-ranges = <0x0 0x0 0x0 0x80 0x0>;
};
host1x@13e00000 {
display-hub@15200000 {
display@15200000 {
interconnect-names = "dma-mem", ...;
interconnects = <&mc ...>;
memory-region = <&fb>;
};
};
};
};
During DMA address translation, the framebuffer address (0x257320000)
will first be translated to the DMA parent's DMA bus, which yields the
same value. After that, the current translation code will switch to the
control bus of bus@0 and then the address will be truncated to
0x57320000 due to #address-cells = <1>.
The idea of this patch is to interrupt DMA address translation at &mc
because it is the root of the DMA bus (i.e. its parent does not have a
dma-ranges property) so that the control bus' #address-cells doesn't
truncate the DMA address.
drivers/of/address.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 14f137a21b0c..e2f45bdbc41a 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -475,6 +475,7 @@ static u64 __of_translate_address(struct device_node *dev,
const __be32 *in_addr, const char *rprop,
struct device_node **host)
{
+ bool dma = rprop && !strcmp(rprop, "dma-ranges");
struct device_node *parent = NULL;
struct of_bus *bus, *pbus;
__be32 addr[OF_MAX_ADDR_CELLS];
@@ -494,7 +495,12 @@ static u64 __of_translate_address(struct device_node *dev,
bus = of_match_bus(parent);
/* Count address cells & copy address locally */
- bus->count_cells(dev, &na, &ns);
+ if (dma) {
+ na = of_bus_n_addr_cells(parent);
+ ns = of_bus_n_size_cells(parent);
+ } else {
+ bus->count_cells(dev, &na, &ns);
+ }
if (!OF_CHECK_COUNTS(na, ns)) {
pr_debug("Bad cell count for %pOF\n", dev);
goto bail;
@@ -515,7 +521,7 @@ static u64 __of_translate_address(struct device_node *dev,
parent = get_parent(dev);
/* If root, we have finished */
- if (parent == NULL) {
+ if (parent == NULL || (dma && !of_get_property(parent, "dma-ranges", NULL))) {
pr_debug("reached root node\n");
result = of_read_number(addr, na);
break;
@@ -536,7 +542,12 @@ static u64 __of_translate_address(struct device_node *dev,
/* Get new parent bus and counts */
pbus = of_match_bus(parent);
- pbus->count_cells(dev, &pna, &pns);
+ if (dma) {
+ pna = of_bus_n_addr_cells(parent);
+ pns = of_bus_n_size_cells(parent);
+ } else {
+ pbus->count_cells(dev, &pna, &pns);
+ }
if (!OF_CHECK_COUNTS(pna, pns)) {
pr_err("Bad cell count for %pOF\n", dev);
break;
--
2.38.1
next prev parent reply other threads:[~2022-11-03 13:39 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-03 13:38 [PATCH v10 0/5] iommu: Support mappings/reservations in reserved-memory regions Thierry Reding
2022-11-03 13:38 ` [PATCH v10 1/5] of: Introduce of_translate_dma_region() Thierry Reding
2022-11-03 13:38 ` Thierry Reding [this message]
2022-11-07 19:30 ` [PATCH v10 2/5] of: Stop DMA translation at last DMA parent Rob Herring
2022-11-08 14:33 ` Thierry Reding
2022-11-08 16:25 ` Rob Herring
2022-11-09 10:07 ` Lucas Stach
2022-11-09 14:25 ` Thierry Reding
2022-11-03 13:38 ` [PATCH v10 3/5] dt-bindings: reserved-memory: Document iommu-addresses Thierry Reding
2022-11-03 13:38 ` [PATCH v10 4/5] iommu: Implement of_iommu_get_resv_regions() Thierry Reding
2022-11-03 13:39 ` [PATCH v10 5/5] iommu: dma: Use of_iommu_get_resv_regions() Thierry Reding
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221103133900.1473855-3-thierry.reding@gmail.com \
--to=thierry.reding@gmail.com \
--cc=alyssa.rosenzweig@collabora.com \
--cc=amhetre@nvidia.com \
--cc=asahi@lists.linux.dev \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.osipenko@collabora.com \
--cc=iommu@lists.linux-foundation.org \
--cc=j@jannau.net \
--cc=joro@8bytes.org \
--cc=linux-tegra@vger.kernel.org \
--cc=nicolinc@nvidia.com \
--cc=robh+dt@kernel.org \
--cc=robin.murphy@arm.com \
--cc=spujar@nvidia.com \
--cc=vdumpa@nvidia.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).