diff mbox

[2/4] pci: mvebu: allow the enumeration of devices beyond physical bridges

Message ID 1369228358-32580-3-git-send-email-thomas.petazzoni@free-electrons.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Thomas Petazzoni May 22, 2013, 1:12 p.m. UTC
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>
---
 drivers/pci/host/pci-mvebu.c |   31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

Comments

Bjorn Helgaas May 22, 2013, 2:31 p.m. UTC | #1
On Wed, May 22, 2013 at 7:12 AM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> 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>
> ---
>  drivers/pci/host/pci-mvebu.c |   31 ++++++++++++++++++++++++++++---
>  1 file changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> index 0bc21b0..c21ca84 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,
>                 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_bus *bus, u32 devfn,
>         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 that the device physically connected in the PCIe

s/that/than/ (also below)

> +        * 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_bus *bus, u32 devfn, int where,
>         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 that 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;
>         }
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 0bc21b0..c21ca84 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,
 		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_bus *bus, u32 devfn,
 	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 that 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_bus *bus, u32 devfn, int where,
 	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 that 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;
 	}