bcm27xx: sync 5.4 patches with RPi Foundation
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0445-of-Make-of_dma_get_range-work-on-bus-nodes.patch
1 From 7631cb95056f03136c9e0a35484e8bebe7b52650 Mon Sep 17 00:00:00 2001
2 From: Robin Murphy <robin.murphy@arm.com>
3 Date: Wed, 3 Jul 2019 18:42:20 +0100
4 Subject: [PATCH] of: Make of_dma_get_range() work on bus nodes
5
6 commit 951d48855d86e72e0d6de73440fe09d363168064 upstream.
7
8 Since the "dma-ranges" property is only valid for a node representing a
9 bus, of_dma_get_range() currently assumes the node passed in is a leaf
10 representing a device, and starts the walk from its parent. In cases
11 like PCI host controllers on typical FDT systems, however, where the PCI
12 endpoints are probed dynamically the initial leaf node represents the
13 'bus' itself, and this logic means we fail to consider any "dma-ranges"
14 describing the host bridge itself. Rework the logic such that
15 of_dma_get_range() also works correctly starting from a bus node
16 containing "dma-ranges".
17
18 While this does mean "dma-ranges" could incorrectly be in a device leaf
19 node, there isn't really any way in this function to ensure that a leaf
20 node is or isn't a bus node.
21
22 Signed-off-by: Robin Murphy <robin.murphy@arm.com>
23 [robh: Allow for the bus child node to still be passed in]
24 Signed-off-by: Rob Herring <robh@kernel.org>
25 Reviewed-by: Robin Murphy <robin.murphy@arm.com>
26 Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
27 Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
28 ---
29 drivers/of/address.c | 44 ++++++++++++++++++--------------------------
30 1 file changed, 18 insertions(+), 26 deletions(-)
31
32 --- a/drivers/of/address.c
33 +++ b/drivers/of/address.c
34 @@ -940,47 +940,39 @@ int of_dma_get_range(struct device_node
35 const __be32 *ranges = NULL;
36 int len, naddr, nsize, pna;
37 int ret = 0;
38 + bool found_dma_ranges = false;
39 u64 dmaaddr;
40
41 - if (!node)
42 - return -EINVAL;
43 -
44 - while (1) {
45 - struct device_node *parent;
46 -
47 - naddr = of_n_addr_cells(node);
48 - nsize = of_n_size_cells(node);
49 -
50 - parent = __of_get_dma_parent(node);
51 - of_node_put(node);
52 -
53 - node = parent;
54 - if (!node)
55 - break;
56 -
57 + while (node) {
58 ranges = of_get_property(node, "dma-ranges", &len);
59
60 /* Ignore empty ranges, they imply no translation required */
61 if (ranges && len > 0)
62 break;
63
64 - /*
65 - * At least empty ranges has to be defined for parent node if
66 - * DMA is supported
67 - */
68 - if (!ranges)
69 - break;
70 + /* Once we find 'dma-ranges', then a missing one is an error */
71 + if (found_dma_ranges && !ranges) {
72 + ret = -ENODEV;
73 + goto out;
74 + }
75 + found_dma_ranges = true;
76 +
77 + node = of_get_next_dma_parent(node);
78 }
79
80 - if (!ranges) {
81 + if (!node || !ranges) {
82 pr_debug("no dma-ranges found for node(%pOF)\n", np);
83 ret = -ENODEV;
84 goto out;
85 }
86
87 - len /= sizeof(u32);
88 -
89 + naddr = of_bus_n_addr_cells(node);
90 + nsize = of_bus_n_size_cells(node);
91 pna = of_n_addr_cells(node);
92 + if ((len / sizeof(__be32)) % (pna + naddr + nsize)) {
93 + ret = -EINVAL;
94 + goto out;
95 + }
96
97 /* dma-ranges format:
98 * DMA addr : naddr cells
99 @@ -988,7 +980,7 @@ int of_dma_get_range(struct device_node
100 * size : nsize cells
101 */
102 dmaaddr = of_read_number(ranges, naddr);
103 - *paddr = of_translate_dma_address(np, ranges);
104 + *paddr = of_translate_dma_address(node, ranges + naddr);
105 if (*paddr == OF_BAD_ADDR) {
106 pr_err("translation of DMA address(%pad) to CPU address failed node(%pOF)\n",
107 dma_addr, np);