aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorYijing Wang <wangyijing@huawei.com>2015-05-21 03:05:02 -0400
committerBjorn Helgaas <bhelgaas@google.com>2015-05-22 10:59:33 -0400
commitd0751b98dfa391f862e02dc36a233a54615e3f1d (patch)
tree45c789079632ab5e754f37acf7cf9e61a45b5d97 /drivers/pci/probe.c
parentf9b8cd7c2710813746f86eec6bbf12c869504285 (diff)
PCI: Add dev->has_secondary_link to track downstream PCIe links
A PCIe Port is an interface to a Link. A Root Port is a PCI-PCI bridge in a Root Complex and has a Link on its secondary (downstream) side. For other Ports, the Link may be on either the upstream (closer to the Root Complex) or downstream side of the Port. The usual topology has a Root Port connected to an Upstream Port. We previously assumed this was the only possible topology, and that a Downstream Port's Link was always on its downstream side, like this: +---------------------+ +------+ | Downstream | | Root | | Upstream Port +--Link-- | Port +--Link--+ Port | +------+ | Downstream | | Port +--Link-- +---------------------+ But systems do exist (see URL below) where the Root Port is connected to a Downstream Port. In this case, a Downstream Port's Link may be on either the upstream or downstream side: +---------------------+ +------+ | Upstream | | Root | | Downstream Port +--Link-- | Port +--Link--+ Port | +------+ | Downstream | | Port +--Link-- +---------------------+ We can't use the Port type to determine which side the Link is on, so add a bit in struct pci_dev to keep track. A Root Port's Link is always on the Port's secondary side. A component (Endpoint or Port) on the other end of the Link obviously has the Link on its upstream side. If that component is a Port, it is part of a Switch or a Bridge. A Bridge has a PCI or PCI-X bus on its secondary side, not a Link. The internal bus of a Switch connects the Port to another Port whose Link is on the downstream side. [bhelgaas: changelog, comment, cache "type", use if/else] Link: http://lkml.kernel.org/r/54EB81B2.4050904@pobox.com Link: https://bugzilla.kernel.org/show_bug.cgi?id=94361 Suggested-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6675a7a1b9fc..96dcd7b8303b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -973,6 +973,8 @@ void set_pcie_port_type(struct pci_dev *pdev)
973{ 973{
974 int pos; 974 int pos;
975 u16 reg16; 975 u16 reg16;
976 int type;
977 struct pci_dev *parent;
976 978
977 pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); 979 pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
978 if (!pos) 980 if (!pos)
@@ -982,6 +984,22 @@ void set_pcie_port_type(struct pci_dev *pdev)
982 pdev->pcie_flags_reg = reg16; 984 pdev->pcie_flags_reg = reg16;
983 pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16); 985 pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
984 pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; 986 pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
987
988 /*
989 * A Root Port is always the upstream end of a Link. No PCIe
990 * component has two Links. Two Links are connected by a Switch
991 * that has a Port on each Link and internal logic to connect the
992 * two Ports.
993 */
994 type = pci_pcie_type(pdev);
995 if (type == PCI_EXP_TYPE_ROOT_PORT)
996 pdev->has_secondary_link = 1;
997 else if (type == PCI_EXP_TYPE_UPSTREAM ||
998 type == PCI_EXP_TYPE_DOWNSTREAM) {
999 parent = pci_upstream_bridge(pdev);
1000 if (!parent->has_secondary_link)
1001 pdev->has_secondary_link = 1;
1002 }
985} 1003}
986 1004
987void set_pcie_hotplug_bridge(struct pci_dev *pdev) 1005void set_pcie_hotplug_bridge(struct pci_dev *pdev)