History

PCI: Add pci_enable_atomic_ops_to_root()

The Atomic Operations feature (PCIe r4.0, sec 6.15) allows atomic transctions to be requested by, routed through and completed by PCIe components. Routing and completion do not require software support. Component support for each is detectable via the DEVCAP2 register. A Requester may use AtomicOps only if its PCI_EXP_DEVCTL2_ATOMIC_REQ is set. This should be set only if the Completer and all intermediate routing elements support AtomicOps. A concrete example is the AMD Fiji-class GPU (which is capable of making AtomicOp requests), below a PLX 8747 switch (advertising AtomicOp routing) with a Haswell host bridge (advertising AtomicOp completion support). Add pci_enable_atomic_ops_to_root() for per-device control over AtomicOp requests. This checks to be sure the Root Port supports completion of the desired AtomicOp sizes and the path to the Root Port supports routing the AtomicOps.

Jay Cornwall committed 8 years ago

Commit 430a2361 parent d57f0b83 files · +79 −1Browse files

Unified · Split

3 files
  1. drivers/pci/pci.c +75 −0
  2. include/linux/pci.h +1 −0
  3. include/uapi/linux/pci_regs.h +3 −1
drivers/pci/pci.c+75−0
@@ -3065,6 +3065,81 @@ int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) · 3064 unmodified lines
3065 return 0;3065 return 0;
3066}3066}
3067 3067
3068/**
3069 * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port
3070 * @dev: the PCI device
3071 * @cap_mask: mask of desired AtomicOp sizes, including one or more of:
3072 * PCI_EXP_DEVCAP2_ATOMIC_COMP32
3073 * PCI_EXP_DEVCAP2_ATOMIC_COMP64
3074 * PCI_EXP_DEVCAP2_ATOMIC_COMP128
3075 *
3076 * Return 0 if all upstream bridges support AtomicOp routing, egress
3077 * blocking is disabled on all upstream ports, and the root port supports
3078 * the requested completion capabilities (32-bit, 64-bit and/or 128-bit
3079 * AtomicOp completion), or negative otherwise.
3080 */
3081int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
3082{
3083 struct pci_bus *bus = dev->bus;
3084 struct pci_dev *bridge;
3085 u32 cap, ctl2;
3086
3087 if (!pci_is_pcie(dev))
3088 return -EINVAL;
3089
3090 /*
3091 * Per PCIe r4.0, sec 6.15, endpoints and root ports may be
3092 * AtomicOp requesters. For now, we only support endpoints as
3093 * requesters and root ports as completers. No endpoints as
3094 * completers, and no peer-to-peer.
3095 */
3096
3097 switch (pci_pcie_type(dev)) {
3098 case PCI_EXP_TYPE_ENDPOINT:
3099 case PCI_EXP_TYPE_LEG_END:
3100 case PCI_EXP_TYPE_RC_END:
3101 break;
3102 default:
3103 return -EINVAL;
3104 }
3105
3106 while (bus->parent) {
3107 bridge = bus->self;
3108
3109 pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap);
3110
3111 switch (pci_pcie_type(bridge)) {
3112 /* Ensure switch ports support AtomicOp routing */
3113 case PCI_EXP_TYPE_UPSTREAM:
3114 case PCI_EXP_TYPE_DOWNSTREAM:
3115 if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE))
3116 return -EINVAL;
3117 break;
3118
3119 /* Ensure root port supports all the sizes we care about */
3120 case PCI_EXP_TYPE_ROOT_PORT:
3121 if ((cap & cap_mask) != cap_mask)
3122 return -EINVAL;
3123 break;
3124 }
3125
3126 /* Ensure upstream ports don't block AtomicOps on egress */
3127 if (!bridge->has_secondary_link) {
3128 pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2,
3129 &ctl2);
3130 if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK)
3131 return -EINVAL;
3132 }
3133
3134 bus = bus->parent;
3135 }
3136
3137 pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
3138 PCI_EXP_DEVCTL2_ATOMIC_REQ);
3139 return 0;
3140}
3141EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
3142
3068/**3143/**
3069 * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge3144 * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
3070 * @dev: the PCI device3145 * @dev: the PCI device
include/linux/pci.h+1−0
@@ -2061,6 +2061,7 @@ void pci_request_acs(void); · 2060 unmodified lines
2061bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);2061bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
2062bool pci_acs_path_enabled(struct pci_dev *start,2062bool pci_acs_path_enabled(struct pci_dev *start,
2063 struct pci_dev *end, u16 acs_flags);2063 struct pci_dev *end, u16 acs_flags);
2064int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask);
2064 2065
2065#define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */2066#define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */
2066#define PCI_VPD_LRDT_ID(x) ((x) | PCI_VPD_LRDT)2067#define PCI_VPD_LRDT_ID(x) ((x) | PCI_VPD_LRDT)
include/uapi/linux/pci_regs.h+3−1
@@ -624,7 +624,9 @@ · 623 unmodified lines
624#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */624#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
625#define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */625#define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */
626#define PCI_EXP_DEVCAP2_ATOMIC_ROUTE 0x00000040 /* Atomic Op routing */626#define PCI_EXP_DEVCAP2_ATOMIC_ROUTE 0x00000040 /* Atomic Op routing */
627#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 0x00000100 /* Atomic 64-bit compare */627#define PCI_EXP_DEVCAP2_ATOMIC_COMP32 0x00000080 /* 32b AtomicOp completion */
628#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 0x00000100 /* 64b AtomicOp completion */
629#define PCI_EXP_DEVCAP2_ATOMIC_COMP128 0x00000200 /* 128b AtomicOp completion */
628#define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */630#define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */
629#define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */631#define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */
630#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */632#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */