aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host/pci-mvebu.c
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2013-05-23 10:32:52 -0400
committerJason Cooper <jason@lakedaemon.net>2013-05-27 12:01:15 -0400
commit197fc226d96623bf25237c480d46e9954b28a75e (patch)
treeeb55e6753e006ca0b5927f3dd366a509408b347c /drivers/pci/host/pci-mvebu.c
parentf4ac99011e542d06ea2bda10063502583c6d7991 (diff)
pci: mvebu: allow the enumeration of devices beyond physical bridges
Until now, the Marvell PCIe driver was only allowing the enumeration of the devices in the secondary bus of the emulated PCI-to-PCI bridge. This works fine when a PCIe device is directly connected into a PCIe slot of the Marvell board. However, when the device connected in the PCIe slot is a physical PCIe bridge, beyond which a real PCIe device is connected, it no longer worked, as the driver was preventing the Linux PCI core from seeing such devices. This commit fixes that by ensuring that configuration transactions on subordinate busses are properly forwarded on the right PCIe interface. Thanks to this patch, a PCIe card beyond a PCIe bridge, itself beyond the emulated PCI-to-PCI bridge is properly detected, with the following layout: -[0000:00]-+-01.0-[01]----00.0 +-09.0-[02-07]----00.0-[03-07]--+-01.0-[04]-- | +-05.0-[05]-- | +-07.0-[06]-- | \-09.0-[07]----00.0 \-0a.0-[08]----00.0 Where the PCIe interface that sits beyond the emulated PCI-to-PCI bridge at 09.0 allows to access the secondary bus 02, on which there is a PCIe bridge that allows to access the 3 to 7 busses, that are subordinates to this bridge. And on one of this bus (bus 7), there is one real PCIe device connected. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/pci/host/pci-mvebu.c')
-rw-r--r--drivers/pci/host/pci-mvebu.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index b8c95a293f64..9f1bfbd81168 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -554,7 +554,8 @@ mvebu_pcie_find_port(struct mvebu_pcie *pcie, struct pci_bus *bus,
554 if (bus->number == 0 && port->devfn == devfn) 554 if (bus->number == 0 && port->devfn == devfn)
555 return port; 555 return port;
556 if (bus->number != 0 && 556 if (bus->number != 0 &&
557 port->bridge.secondary_bus == bus->number) 557 bus->number >= port->bridge.secondary_bus &&
558 bus->number <= port->bridge.subordinate_bus)
558 return port; 559 return port;
559 } 560 }
560 561
@@ -578,7 +579,18 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
578 if (bus->number == 0) 579 if (bus->number == 0)
579 return mvebu_sw_pci_bridge_write(port, where, size, val); 580 return mvebu_sw_pci_bridge_write(port, where, size, val);
580 581
581 if (!port->haslink || PCI_SLOT(devfn) != 0) 582 if (!port->haslink)
583 return PCIBIOS_DEVICE_NOT_FOUND;
584
585 /*
586 * On the secondary bus, we don't want to expose any other
587 * device than the device physically connected in the PCIe
588 * slot, visible in slot 0. In slot 1, there's a special
589 * Marvell device that only makes sense when the Armada is
590 * used as a PCIe endpoint.
591 */
592 if (bus->number == port->bridge.secondary_bus &&
593 PCI_SLOT(devfn) != 0)
582 return PCIBIOS_DEVICE_NOT_FOUND; 594 return PCIBIOS_DEVICE_NOT_FOUND;
583 595
584 /* Access the real PCIe interface */ 596 /* Access the real PCIe interface */
@@ -609,7 +621,20 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
609 if (bus->number == 0) 621 if (bus->number == 0)
610 return mvebu_sw_pci_bridge_read(port, where, size, val); 622 return mvebu_sw_pci_bridge_read(port, where, size, val);
611 623
612 if (!port->haslink || PCI_SLOT(devfn) != 0) { 624 if (!port->haslink) {
625 *val = 0xffffffff;
626 return PCIBIOS_DEVICE_NOT_FOUND;
627 }
628
629 /*
630 * On the secondary bus, we don't want to expose any other
631 * device than the device physically connected in the PCIe
632 * slot, visible in slot 0. In slot 1, there's a special
633 * Marvell device that only makes sense when the Armada is
634 * used as a PCIe endpoint.
635 */
636 if (bus->number == port->bridge.secondary_bus &&
637 PCI_SLOT(devfn) != 0) {
613 *val = 0xffffffff; 638 *val = 0xffffffff;
614 return PCIBIOS_DEVICE_NOT_FOUND; 639 return PCIBIOS_DEVICE_NOT_FOUND;
615 } 640 }