]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
106ee652a35aefc9c86b0e7463646ef5e40ad4d5
[thirdparty/kernel/stable-queue.git] /
1 From 885dbd154b2f2ee305cec6fd0a162e1a77ae2b06 Mon Sep 17 00:00:00 2001
2 From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
3 Date: Thu, 28 May 2015 10:40:13 +0200
4 Subject: Revert "bus: mvebu-mbus: make sure SDRAM CS for DMA don't overlap the MBus bridge window"
5
6 From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7
8 commit 885dbd154b2f2ee305cec6fd0a162e1a77ae2b06 upstream.
9
10 This reverts commit 1737cac69369 ("bus: mvebu-mbus: make sure SDRAM CS
11 for DMA don't overlap the MBus bridge window"), because it breaks DMA
12 on platforms having more than 2 GB of RAM.
13
14 This commit changed the information reported to DMA masters device
15 drivers through the mv_mbus_dram_info() function so that the returned
16 DRAM ranges do not overlap with I/O windows.
17
18 This was necessary as a preparation to support the new CESA Crypto
19 Engine driver, which will use DMA for cryptographic operations. But
20 since it does DMA with the SRAM which is mapped as an I/O window,
21 having DRAM ranges overlapping with I/O windows was problematic.
22
23 To solve this, the above mentioned commit changed the mvebu-mbus to
24 adjust the DRAM ranges so that they don't overlap with the I/O
25 windows. However, by doing this, we re-adjust the DRAM ranges in a way
26 that makes them have a size that is no longer a power of two. While
27 this is perfectly fine for the Crypto Engine, which supports DRAM
28 ranges with a granularity of 64 KB, it breaks basically all other DMA
29 masters, which expect power of two sizes for the DRAM ranges.
30
31 Due to this, if the installed system memory is 4 GB, in two
32 chip-selects of 2 GB, the second DRAM range will be reduced from 2 GB
33 to a little bit less than 2 GB to not overlap with the I/O windows, in
34 a way that results in a DRAM range that doesn't have a power of two
35 size. This means that whenever you do a DMA transfer with an address
36 located in the [ 2 GB ; 4 GB ] area, it will freeze the system. Any
37 serious DMA activity like simply running:
38
39 for i in $(seq 1 64) ; do dd if=/dev/urandom of=file$i bs=1M count=16 ; done
40
41 in an ext3 partition mounted over a SATA drive will freeze the system.
42
43 Since the new CESA crypto driver that uses DMA has not been merged
44 yet, the easiest fix is to simply revert this commit. A follow-up
45 commit will introduce a different solution for the CESA crypto driver.
46
47 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
48 Fixes: 1737cac69369 ("bus: mvebu-mbus: make sure SDRAM CS for DMA don't overlap the MBus bridge window")
49 Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
50 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
51
52 ---
53 drivers/bus/mvebu-mbus.c | 107 +++++++----------------------------------------
54 1 file changed, 17 insertions(+), 90 deletions(-)
55
56 --- a/drivers/bus/mvebu-mbus.c
57 +++ b/drivers/bus/mvebu-mbus.c
58 @@ -58,7 +58,6 @@
59 #include <linux/debugfs.h>
60 #include <linux/log2.h>
61 #include <linux/syscore_ops.h>
62 -#include <linux/memblock.h>
63
64 /*
65 * DDR target is the same on all platforms.
66 @@ -103,9 +102,7 @@
67
68 /* Relative to mbusbridge_base */
69 #define MBUS_BRIDGE_CTRL_OFF 0x0
70 -#define MBUS_BRIDGE_SIZE_MASK 0xffff0000
71 #define MBUS_BRIDGE_BASE_OFF 0x4
72 -#define MBUS_BRIDGE_BASE_MASK 0xffff0000
73
74 /* Maximum number of windows, for all known platforms */
75 #define MBUS_WINS_MAX 20
76 @@ -579,106 +576,36 @@ static unsigned int armada_xp_mbus_win_r
77 return MVEBU_MBUS_NO_REMAP;
78 }
79
80 -/*
81 - * Use the memblock information to find the MBus bridge hole in the
82 - * physical address space.
83 - */
84 -static void __init
85 -mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end)
86 -{
87 - struct memblock_region *r;
88 - uint64_t s = 0;
89 -
90 - for_each_memblock(memory, r) {
91 - /*
92 - * This part of the memory is above 4 GB, so we don't
93 - * care for the MBus bridge hole.
94 - */
95 - if (r->base >= 0x100000000)
96 - continue;
97 -
98 - /*
99 - * The MBus bridge hole is at the end of the RAM under
100 - * the 4 GB limit.
101 - */
102 - if (r->base + r->size > s)
103 - s = r->base + r->size;
104 - }
105 -
106 - *start = s;
107 - *end = 0x100000000;
108 -}
109 -
110 static void __init
111 mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
112 {
113 int i;
114 int cs;
115 - uint64_t mbus_bridge_base, mbus_bridge_end;
116
117 mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
118
119 - mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end);
120 -
121 for (i = 0, cs = 0; i < 4; i++) {
122 - u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
123 - u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
124 - u64 end;
125 - struct mbus_dram_window *w;
126 -
127 - /* Ignore entries that are not enabled */
128 - if (!(size & DDR_SIZE_ENABLED))
129 - continue;
130 -
131 - /*
132 - * Ignore entries whose base address is above 2^32,
133 - * since devices cannot DMA to such high addresses
134 - */
135 - if (base & DDR_BASE_CS_HIGH_MASK)
136 - continue;
137 -
138 - base = base & DDR_BASE_CS_LOW_MASK;
139 - size = (size | ~DDR_SIZE_MASK) + 1;
140 - end = base + size;
141 -
142 - /*
143 - * Adjust base/size of the current CS to make sure it
144 - * doesn't overlap with the MBus bridge hole. This is
145 - * particularly important for devices that do DMA from
146 - * DRAM to a SRAM mapped in a MBus window, such as the
147 - * CESA cryptographic engine.
148 - */
149 + u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
150 + u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
151
152 /*
153 - * The CS is fully enclosed inside the MBus bridge
154 - * area, so ignore it.
155 + * We only take care of entries for which the chip
156 + * select is enabled, and that don't have high base
157 + * address bits set (devices can only access the first
158 + * 32 bits of the memory).
159 */
160 - if (base >= mbus_bridge_base && end <= mbus_bridge_end)
161 - continue;
162 -
163 - /*
164 - * Beginning of CS overlaps with end of MBus, raise CS
165 - * base address, and shrink its size.
166 - */
167 - if (base >= mbus_bridge_base && end > mbus_bridge_end) {
168 - size -= mbus_bridge_end - base;
169 - base = mbus_bridge_end;
170 + if ((size & DDR_SIZE_ENABLED) &&
171 + !(base & DDR_BASE_CS_HIGH_MASK)) {
172 + struct mbus_dram_window *w;
173 +
174 + w = &mvebu_mbus_dram_info.cs[cs++];
175 + w->cs_index = i;
176 + w->mbus_attr = 0xf & ~(1 << i);
177 + if (mbus->hw_io_coherency)
178 + w->mbus_attr |= ATTR_HW_COHERENCY;
179 + w->base = base & DDR_BASE_CS_LOW_MASK;
180 + w->size = (size | ~DDR_SIZE_MASK) + 1;
181 }
182 -
183 - /*
184 - * End of CS overlaps with beginning of MBus, shrink
185 - * CS size.
186 - */
187 - if (base < mbus_bridge_base && end > mbus_bridge_base)
188 - size -= end - mbus_bridge_base;
189 -
190 - w = &mvebu_mbus_dram_info.cs[cs++];
191 - w->cs_index = i;
192 - w->mbus_attr = 0xf & ~(1 << i);
193 - if (mbus->hw_io_coherency)
194 - w->mbus_attr |= ATTR_HW_COHERENCY;
195 - w->base = base;
196 - w->size = size;
197 }
198 mvebu_mbus_dram_info.num_cs = cs;
199 }