mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
Merge branch 'pci/atomics'
- Don't enable AtomicOps by RCiEPs since none of them need Atomic Ops and we can't tell whether the Root Complex would support them (Gerd Bayer) - Enable AtomicOps only if we know the Root Port supports them (Gerd Bayer) * pci/atomics: PCI: Update PCIe spec references for AtomicOps PCI: Enable AtomicOps only if Root Port supports them PCI: Do not enable AtomicOps by RCiEPs
This commit is contained in:
commit
31e39c9ae1
|
|
@ -3674,12 +3674,11 @@ 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;
|
||||
|
||||
/*
|
||||
* Per PCIe r5.0, sec 9.3.5.10, the AtomicOp Requester Enable bit
|
||||
* Per PCIe r7.0, sec 7.5.3.16, the AtomicOp Requester Enable bit
|
||||
* in Device Control 2 is reserved in VFs and the PF value applies
|
||||
* to all associated VFs.
|
||||
*/
|
||||
|
|
@ -3690,50 +3689,49 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
|
|||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Per PCIe r4.0, sec 6.15, endpoints and root ports may be
|
||||
* AtomicOp requesters. For now, we only support endpoints as
|
||||
* requesters and root ports as completers. No endpoints as
|
||||
* Per PCIe r7.0, sec 6.15, endpoints and root ports may be
|
||||
* AtomicOp requesters. For now, we only support (legacy) endpoints
|
||||
* as requesters and root ports as completers. No endpoints as
|
||||
* completers, and no peer-to-peer.
|
||||
*/
|
||||
|
||||
switch (pci_pcie_type(dev)) {
|
||||
case PCI_EXP_TYPE_ENDPOINT:
|
||||
case PCI_EXP_TYPE_LEG_END:
|
||||
case PCI_EXP_TYPE_RC_END:
|
||||
break;
|
||||
default:
|
||||
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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user