diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 135e5b591df4..3a4ba587042b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3675,8 +3675,7 @@ void pci_acs_init(struct pci_dev *dev) */ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) { - struct pci_bus *bus = dev->bus; - struct pci_dev *bridge; + struct pci_dev *root, *bridge; u32 cap, ctl2; /* @@ -3705,35 +3704,35 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) return -EINVAL; } - while (bus->parent) { - bridge = bus->self; + root = pcie_find_root_port(dev); + if (!root) + return -EINVAL; - pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); + pcie_capability_read_dword(root, PCI_EXP_DEVCAP2, &cap); + if ((cap & cap_mask) != cap_mask) + return -EINVAL; + bridge = pci_upstream_bridge(dev); + while (bridge != root) { switch (pci_pcie_type(bridge)) { - /* Ensure switch ports support AtomicOp routing */ case PCI_EXP_TYPE_UPSTREAM: - case PCI_EXP_TYPE_DOWNSTREAM: - if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) - return -EINVAL; - break; - - /* Ensure root port supports all the sizes we care about */ - case PCI_EXP_TYPE_ROOT_PORT: - if ((cap & cap_mask) != cap_mask) - return -EINVAL; - break; - } - - /* Ensure upstream ports don't block AtomicOps on egress */ - if (pci_pcie_type(bridge) == PCI_EXP_TYPE_UPSTREAM) { + /* Upstream ports must not block AtomicOps on egress */ pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl2); if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK) return -EINVAL; + fallthrough; + + /* All switch ports need to route AtomicOps */ + case PCI_EXP_TYPE_DOWNSTREAM: + pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, + &cap); + if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) + return -EINVAL; + break; } - bus = bus->parent; + bridge = pci_upstream_bridge(bridge); } pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,