aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch
diff options
context:
space:
mode:
authorÁlvaro Fernández Rojas <noltari@gmail.com>2021-02-18 18:04:33 +0100
committerÁlvaro Fernández Rojas <noltari@gmail.com>2021-02-18 23:42:32 +0100
commitf07e572f6447465d8938679533d604e402b0f066 (patch)
treecb333bd2a67e59e7c07659514850a0fd55fc825e /target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch
parent5d3a6fd970619dfc55f8259035c3027d7613a2a6 (diff)
downloadupstream-f07e572f6447465d8938679533d604e402b0f066.tar.gz
upstream-f07e572f6447465d8938679533d604e402b0f066.tar.bz2
upstream-f07e572f6447465d8938679533d604e402b0f066.zip
bcm27xx: import latest patches from the RPi foundation
bcm2708: boot tested on RPi B+ v1.2 bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G bcm2710: boot tested on RPi 3B v1.2 bcm2711: boot tested on RPi 4B v1.1 4G Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch107
1 files changed, 107 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch b/target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch
new file mode 100644
index 0000000000..1cac2dfcd8
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch
@@ -0,0 +1,107 @@
+From 7631cb95056f03136c9e0a35484e8bebe7b52650 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Wed, 3 Jul 2019 18:42:20 +0100
+Subject: [PATCH] of: Make of_dma_get_range() work on bus nodes
+
+commit 951d48855d86e72e0d6de73440fe09d363168064 upstream.
+
+Since the "dma-ranges" property is only valid for a node representing a
+bus, of_dma_get_range() currently assumes the node passed in is a leaf
+representing a device, and starts the walk from its parent. In cases
+like PCI host controllers on typical FDT systems, however, where the PCI
+endpoints are probed dynamically the initial leaf node represents the
+'bus' itself, and this logic means we fail to consider any "dma-ranges"
+describing the host bridge itself. Rework the logic such that
+of_dma_get_range() also works correctly starting from a bus node
+containing "dma-ranges".
+
+While this does mean "dma-ranges" could incorrectly be in a device leaf
+node, there isn't really any way in this function to ensure that a leaf
+node is or isn't a bus node.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+[robh: Allow for the bus child node to still be passed in]
+Signed-off-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 44 ++++++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 26 deletions(-)
+
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -940,47 +940,39 @@ int of_dma_get_range(struct device_node
+ const __be32 *ranges = NULL;
+ int len, naddr, nsize, pna;
+ int ret = 0;
++ bool found_dma_ranges = false;
+ u64 dmaaddr;
+
+- if (!node)
+- return -EINVAL;
+-
+- while (1) {
+- struct device_node *parent;
+-
+- naddr = of_n_addr_cells(node);
+- nsize = of_n_size_cells(node);
+-
+- parent = __of_get_dma_parent(node);
+- of_node_put(node);
+-
+- node = parent;
+- if (!node)
+- break;
+-
++ while (node) {
+ ranges = of_get_property(node, "dma-ranges", &len);
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
+ break;
+
+- /*
+- * At least empty ranges has to be defined for parent node if
+- * DMA is supported
+- */
+- if (!ranges)
+- break;
++ /* Once we find 'dma-ranges', then a missing one is an error */
++ if (found_dma_ranges && !ranges) {
++ ret = -ENODEV;
++ goto out;
++ }
++ found_dma_ranges = true;
++
++ node = of_get_next_dma_parent(node);
+ }
+
+- if (!ranges) {
++ if (!node || !ranges) {
+ pr_debug("no dma-ranges found for node(%pOF)\n", np);
+ ret = -ENODEV;
+ goto out;
+ }
+
+- len /= sizeof(u32);
+-
++ naddr = of_bus_n_addr_cells(node);
++ nsize = of_bus_n_size_cells(node);
+ pna = of_n_addr_cells(node);
++ if ((len / sizeof(__be32)) % (pna + naddr + nsize)) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ /* dma-ranges format:
+ * DMA addr : naddr cells
+@@ -988,7 +980,7 @@ int of_dma_get_range(struct device_node
+ * size : nsize cells
+ */
+ dmaaddr = of_read_number(ranges, naddr);
+- *paddr = of_translate_dma_address(np, ranges);
++ *paddr = of_translate_dma_address(node, ranges + naddr);
+ if (*paddr == OF_BAD_ADDR) {
+ pr_err("translation of DMA address(%pad) to CPU address failed node(%pOF)\n",
+ dma_addr, np);