mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 01:11:14 +00:00
98 lines
3.6 KiB
Diff
98 lines
3.6 KiB
Diff
|
From ce12bfd48e93b98717a258b8181aed0e19933e1e Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||
|
Date: Thu, 23 May 2013 16:32:52 +0200
|
||
|
Subject: [PATCH 18/29] 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>
|
||
|
---
|
||
|
drivers/pci/host/pci-mvebu.c | 31 ++++++++++++++++++++++++++++---
|
||
|
1 file changed, 28 insertions(+), 3 deletions(-)
|
||
|
|
||
|
--- 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 *
|
||
|
if (bus->number == 0 && port->devfn == devfn)
|
||
|
return port;
|
||
|
if (bus->number != 0 &&
|
||
|
- port->bridge.secondary_bus == bus->number)
|
||
|
+ bus->number >= port->bridge.secondary_bus &&
|
||
|
+ bus->number <= port->bridge.subordinate_bus)
|
||
|
return port;
|
||
|
}
|
||
|
|
||
|
@@ -578,7 +579,18 @@ static int mvebu_pcie_wr_conf(struct pci
|
||
|
if (bus->number == 0)
|
||
|
return mvebu_sw_pci_bridge_write(port, where, size, val);
|
||
|
|
||
|
- if (!port->haslink || PCI_SLOT(devfn) != 0)
|
||
|
+ if (!port->haslink)
|
||
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * On the secondary bus, we don't want to expose any other
|
||
|
+ * device than the device physically connected in the PCIe
|
||
|
+ * slot, visible in slot 0. In slot 1, there's a special
|
||
|
+ * Marvell device that only makes sense when the Armada is
|
||
|
+ * used as a PCIe endpoint.
|
||
|
+ */
|
||
|
+ if (bus->number == port->bridge.secondary_bus &&
|
||
|
+ PCI_SLOT(devfn) != 0)
|
||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||
|
|
||
|
/* Access the real PCIe interface */
|
||
|
@@ -609,7 +621,20 @@ static int mvebu_pcie_rd_conf(struct pci
|
||
|
if (bus->number == 0)
|
||
|
return mvebu_sw_pci_bridge_read(port, where, size, val);
|
||
|
|
||
|
- if (!port->haslink || PCI_SLOT(devfn) != 0) {
|
||
|
+ if (!port->haslink) {
|
||
|
+ *val = 0xffffffff;
|
||
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * On the secondary bus, we don't want to expose any other
|
||
|
+ * device than the device physically connected in the PCIe
|
||
|
+ * slot, visible in slot 0. In slot 1, there's a special
|
||
|
+ * Marvell device that only makes sense when the Armada is
|
||
|
+ * used as a PCIe endpoint.
|
||
|
+ */
|
||
|
+ if (bus->number == port->bridge.secondary_bus &&
|
||
|
+ PCI_SLOT(devfn) != 0) {
|
||
|
*val = 0xffffffff;
|
||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||
|
}
|