aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-05-05 01:39:04 -0400
committerOlof Johansson <olof@lixom.net>2014-05-05 01:39:04 -0400
commit1a7adf2e2334cccb664fcacafa17898e142085c8 (patch)
tree16332d90564216627e70909643e43e2dd7d1882a
parenta2af978986706148397264ae7186ed48cd7ee71a (diff)
parent398f5d5e10b6b917cd9d35ef21d545b0afbada22 (diff)
Merge tag 'mvebu-mbus_pci-fixes-3.15' of git://git.infradead.org/linux-mvebu into fixes
From Jason Cooper: mvebu drivers (mbus and pci) fixes for v3.15 - pci - fix off-by-one for mbus window size - split BARs into multiple mbus windows when needed - mbus - avoid setting undefined window size - allow several windows with the same target/attr * tag 'mvebu-mbus_pci-fixes-3.15' of git://git.infradead.org/linux-mvebu: PCI: mvebu: split PCIe BARs into multiple MBus windows when needed bus: mvebu-mbus: allow several windows with the same target/attribute bus: mvebu-mbus: Avoid setting an undefined window size PCI: mvebu: fix off-by-one in the computed size of the mbus windows Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--drivers/bus/mvebu-mbus.c22
-rw-r--r--drivers/pci/host/pci-mvebu.c92
2 files changed, 92 insertions, 22 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 293e2e0a0a87..00b73448b22e 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -56,6 +56,7 @@
56#include <linux/of.h> 56#include <linux/of.h>
57#include <linux/of_address.h> 57#include <linux/of_address.h>
58#include <linux/debugfs.h> 58#include <linux/debugfs.h>
59#include <linux/log2.h>
59 60
60/* 61/*
61 * DDR target is the same on all platforms. 62 * DDR target is the same on all platforms.
@@ -222,12 +223,6 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
222 */ 223 */
223 if ((u64)base < wend && end > wbase) 224 if ((u64)base < wend && end > wbase)
224 return 0; 225 return 0;
225
226 /*
227 * Check if target/attribute conflicts
228 */
229 if (target == wtarget && attr == wattr)
230 return 0;
231 } 226 }
232 227
233 return 1; 228 return 1;
@@ -266,6 +261,17 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
266 mbus->soc->win_cfg_offset(win); 261 mbus->soc->win_cfg_offset(win);
267 u32 ctrl, remap_addr; 262 u32 ctrl, remap_addr;
268 263
264 if (!is_power_of_2(size)) {
265 WARN(true, "Invalid MBus window size: 0x%zx\n", size);
266 return -EINVAL;
267 }
268
269 if ((base & (phys_addr_t)(size - 1)) != 0) {
270 WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base,
271 size);
272 return -EINVAL;
273 }
274
269 ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | 275 ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
270 (attr << WIN_CTRL_ATTR_SHIFT) | 276 (attr << WIN_CTRL_ATTR_SHIFT) |
271 (target << WIN_CTRL_TGT_SHIFT) | 277 (target << WIN_CTRL_TGT_SHIFT) |
@@ -413,6 +419,10 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
413 win, (unsigned long long)wbase, 419 win, (unsigned long long)wbase,
414 (unsigned long long)(wbase + wsize), wtarget, wattr); 420 (unsigned long long)(wbase + wsize), wtarget, wattr);
415 421
422 if (!is_power_of_2(wsize) ||
423 ((wbase & (u64)(wsize - 1)) != 0))
424 seq_puts(seq, " (Invalid base/size!!)");
425
416 if (win < mbus->soc->num_remappable_wins) { 426 if (win < mbus->soc->num_remappable_wins) {
417 seq_printf(seq, " (remap %016llx)\n", 427 seq_printf(seq, " (remap %016llx)\n",
418 (unsigned long long)wremap); 428 (unsigned long long)wremap);
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index d3d1cfd51e09..e384e2534594 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -293,6 +293,58 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
293 return PCIBIOS_SUCCESSFUL; 293 return PCIBIOS_SUCCESSFUL;
294} 294}
295 295
296/*
297 * Remove windows, starting from the largest ones to the smallest
298 * ones.
299 */
300static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port,
301 phys_addr_t base, size_t size)
302{
303 while (size) {
304 size_t sz = 1 << (fls(size) - 1);
305
306 mvebu_mbus_del_window(base, sz);
307 base += sz;
308 size -= sz;
309 }
310}
311
312/*
313 * MBus windows can only have a power of two size, but PCI BARs do not
314 * have this constraint. Therefore, we have to split the PCI BAR into
315 * areas each having a power of two size. We start from the largest
316 * one (i.e highest order bit set in the size).
317 */
318static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
319 unsigned int target, unsigned int attribute,
320 phys_addr_t base, size_t size,
321 phys_addr_t remap)
322{
323 size_t size_mapped = 0;
324
325 while (size) {
326 size_t sz = 1 << (fls(size) - 1);
327 int ret;
328
329 ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base,
330 sz, remap);
331 if (ret) {
332 dev_err(&port->pcie->pdev->dev,
333 "Could not create MBus window at 0x%x, size 0x%x: %d\n",
334 base, sz, ret);
335 mvebu_pcie_del_windows(port, base - size_mapped,
336 size_mapped);
337 return;
338 }
339
340 size -= sz;
341 size_mapped += sz;
342 base += sz;
343 if (remap != MVEBU_MBUS_NO_REMAP)
344 remap += sz;
345 }
346}
347
296static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) 348static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
297{ 349{
298 phys_addr_t iobase; 350 phys_addr_t iobase;
@@ -304,8 +356,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
304 356
305 /* If a window was configured, remove it */ 357 /* If a window was configured, remove it */
306 if (port->iowin_base) { 358 if (port->iowin_base) {
307 mvebu_mbus_del_window(port->iowin_base, 359 mvebu_pcie_del_windows(port, port->iowin_base,
308 port->iowin_size); 360 port->iowin_size);
309 port->iowin_base = 0; 361 port->iowin_base = 0;
310 port->iowin_size = 0; 362 port->iowin_size = 0;
311 } 363 }
@@ -331,11 +383,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
331 port->iowin_base = port->pcie->io.start + iobase; 383 port->iowin_base = port->pcie->io.start + iobase;
332 port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | 384 port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
333 (port->bridge.iolimitupper << 16)) - 385 (port->bridge.iolimitupper << 16)) -
334 iobase); 386 iobase) + 1;
335 387
336 mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, 388 mvebu_pcie_add_windows(port, port->io_target, port->io_attr,
337 port->iowin_base, port->iowin_size, 389 port->iowin_base, port->iowin_size,
338 iobase); 390 iobase);
339} 391}
340 392
341static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) 393static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
@@ -346,8 +398,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
346 398
347 /* If a window was configured, remove it */ 399 /* If a window was configured, remove it */
348 if (port->memwin_base) { 400 if (port->memwin_base) {
349 mvebu_mbus_del_window(port->memwin_base, 401 mvebu_pcie_del_windows(port, port->memwin_base,
350 port->memwin_size); 402 port->memwin_size);
351 port->memwin_base = 0; 403 port->memwin_base = 0;
352 port->memwin_size = 0; 404 port->memwin_size = 0;
353 } 405 }
@@ -364,10 +416,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
364 port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); 416 port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16);
365 port->memwin_size = 417 port->memwin_size =
366 (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - 418 (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
367 port->memwin_base; 419 port->memwin_base + 1;
368 420
369 mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, 421 mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr,
370 port->memwin_base, port->memwin_size); 422 port->memwin_base, port->memwin_size,
423 MVEBU_MBUS_NO_REMAP);
371} 424}
372 425
373/* 426/*
@@ -743,14 +796,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
743 796
744 /* 797 /*
745 * On the PCI-to-PCI bridge side, the I/O windows must have at 798 * On the PCI-to-PCI bridge side, the I/O windows must have at
746 * least a 64 KB size and be aligned on their size, and the 799 * least a 64 KB size and the memory windows must have at
747 * memory windows must have at least a 1 MB size and be 800 * least a 1 MB size. Moreover, MBus windows need to have a
748 * aligned on their size 801 * base address aligned on their size, and their size must be
802 * a power of two. This means that if the BAR doesn't have a
803 * power of two size, several MBus windows will actually be
804 * created. We need to ensure that the biggest MBus window
805 * (which will be the first one) is aligned on its size, which
806 * explains the rounddown_pow_of_two() being done here.
749 */ 807 */
750 if (res->flags & IORESOURCE_IO) 808 if (res->flags & IORESOURCE_IO)
751 return round_up(start, max_t(resource_size_t, SZ_64K, size)); 809 return round_up(start, max_t(resource_size_t, SZ_64K,
810 rounddown_pow_of_two(size)));
752 else if (res->flags & IORESOURCE_MEM) 811 else if (res->flags & IORESOURCE_MEM)
753 return round_up(start, max_t(resource_size_t, SZ_1M, size)); 812 return round_up(start, max_t(resource_size_t, SZ_1M,
813 rounddown_pow_of_two(size)));
754 else 814 else
755 return start; 815 return start;
756} 816}