aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2013-11-26 13:02:54 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-11-26 13:36:32 -0500
commit43a16f94445310800e39d54aaa534f2ce7dbe0a2 (patch)
treec95e9e765dbbd61731a58a534f2e59684533211d /drivers
parent2850b05c9644d0f4c9df6cc77d628d7e0598a0cc (diff)
PCI: mvebu: Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits
When PCI_COMMAND_MEMORY/PCI_COMMAND_IO are cleared, the bridge should not allocate windows or even look at the window limit/base registers. Otherwise we may set up bogus windows while the PCI core code performs discovery. The core will leave PCI_COMMAND_IO cleared if it doesn't need an IO window. Have mvebu_pcie_handle_*_change respect the bits, and call the change function whenever the bits changes. Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/host/pci-mvebu.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 6f5a20f3cdf6..94294123e7bd 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -300,7 +300,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
300 300
301 /* Are the new iobase/iolimit values invalid? */ 301 /* Are the new iobase/iolimit values invalid? */
302 if (port->bridge.iolimit < port->bridge.iobase || 302 if (port->bridge.iolimit < port->bridge.iobase ||
303 port->bridge.iolimitupper < port->bridge.iobaseupper) { 303 port->bridge.iolimitupper < port->bridge.iobaseupper ||
304 !(port->bridge.command & PCI_COMMAND_IO)) {
304 305
305 /* If a window was configured, remove it */ 306 /* If a window was configured, remove it */
306 if (port->iowin_base) { 307 if (port->iowin_base) {
@@ -337,7 +338,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
337static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) 338static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
338{ 339{
339 /* Are the new membase/memlimit values invalid? */ 340 /* Are the new membase/memlimit values invalid? */
340 if (port->bridge.memlimit < port->bridge.membase) { 341 if (port->bridge.memlimit < port->bridge.membase ||
342 !(port->bridge.command & PCI_COMMAND_MEMORY)) {
341 343
342 /* If a window was configured, remove it */ 344 /* If a window was configured, remove it */
343 if (port->memwin_base) { 345 if (port->memwin_base) {
@@ -485,8 +487,16 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
485 487
486 switch (where & ~3) { 488 switch (where & ~3) {
487 case PCI_COMMAND: 489 case PCI_COMMAND:
490 {
491 u32 old = bridge->command;
492
488 bridge->command = value & 0xffff; 493 bridge->command = value & 0xffff;
494 if ((old ^ bridge->command) & PCI_COMMAND_IO)
495 mvebu_pcie_handle_iobase_change(port);
496 if ((old ^ bridge->command) & PCI_COMMAND_MEMORY)
497 mvebu_pcie_handle_membase_change(port);
489 break; 498 break;
499 }
490 500
491 case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: 501 case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
492 bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value; 502 bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;