--- v11
+++ v6
@@ -1,96 +1,102 @@
-The P2PDMA mapping should fail if a device with 10-Bit Tag Requester
-interact with a device that does not support 10-Bit Tag Completer.
-
-Add a 10-Bit Tag check in the P2PDMA code to ensure that a device with
-10-Bit Tag Requester doesn't interact with a device that does not
-support 10-Bit Tag Completer. Before that happens, the kernel should
-emit a warning.
-
-"echo 0 > /sys/bus/pci/devices/.../tags" to disable 10-Bit Tag
-Requester for PF device.
-
-"echo 0 > /sys/bus/pci/devices/.../sriov_vf_tags_ctl" to disable
-10-Bit Tag Requester for VF device.
+PCIe spec 5.0r1.0 section 2.2.6.2 implementation note, In configurations
+where a Requester with 10-Bit Tag Requester capability needs to target
+multiple Completers, one needs to ensure that the Requester sends 10-Bit
+Tag Requests only to Completers that have 10-Bit Tag Completer capability.
+So we enable 10-Bit Tag Requester for root port only when the devices
+under the root port support 10-Bit Tag Completer.
Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
-Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
- drivers/pci/p2pdma.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 48 insertions(+)
+ drivers/pci/pcie/portdrv_pci.c | 69 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
-diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
-index 50cdde3e9a8b..1565a31183af 100644
---- a/drivers/pci/p2pdma.c
-+++ b/drivers/pci/p2pdma.c
-@@ -19,6 +19,7 @@
- #include <linux/random.h>
- #include <linux/seq_buf.h>
- #include <linux/xarray.h>
-+#include "pci.h"
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index c7ff1ee..2382cd2 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -90,6 +90,72 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
+ #define PCIE_PORTDRV_PM_OPS NULL
+ #endif /* !PM */
- enum pci_p2pdma_map_type {
- PCI_P2PDMA_MAP_UNKNOWN = 0,
-@@ -410,6 +411,50 @@ static unsigned long map_types_idx(struct pci_dev *client)
- (client->bus->number << 8) | client->devfn;
- }
-
-+static bool pci_10bit_tags_unsupported(struct pci_dev *a,
-+ struct pci_dev *b,
-+ bool verbose)
++static int pci_10bit_tag_comp_support(struct pci_dev *dev, void *data)
+{
-+ bool req;
-+ bool comp;
-+ u16 ctl;
-+ const char *str = "tags";
++ bool *support = (bool *)data;
+
-+ if (a->is_virtfn) {
-+#ifdef CONFIG_PCI_IOV
-+ req = !!(a->physfn->sriov->ctrl &
-+ PCI_SRIOV_CTRL_VF_10BIT_TAG_REQ_EN);
-+#endif
-+ } else {
-+ pcie_capability_read_word(a, PCI_EXP_DEVCTL2, &ctl);
-+ req = !!(ctl & PCI_EXP_DEVCTL2_10BIT_TAG_REQ_EN);
++ if (!pci_is_pcie(dev)) {
++ *support = false;
++ return 1;
+ }
+
-+ comp = !!(b->devcap2 & PCI_EXP_DEVCAP2_10BIT_TAG_COMP);
++ /*
++ * PCIe spec 5.0r1.0 section 2.2.6.2 implementation note.
++ * For configurations where a Requester with 10-Bit Tag Requester
++ * capability targets Completers where some do and some do not have
++ * 10-Bit Tag Completer capability, how the Requester determines which
++ * NPRs include 10-Bit Tags is outside the scope of this specification.
++ * So we do not consider hotplug scenario.
++ */
++ if (dev->is_hotplug_bridge) {
++ *support = false;
++ return 1;
++ }
+
-+ /* 10-bit tags not enabled on requester */
-+ if (!req)
-+ return false;
++ if (!(dev->pcie_devcap2 & PCI_EXP_DEVCAP2_10BIT_TAG_COMP)) {
++ *support = false;
++ return 1;
++ }
+
-+ /* Completer can handle anything */
-+ if (comp)
-+ return false;
++ return 0;
++}
+
-+ if (!verbose)
-+ return true;
++static void pci_configure_rp_10bit_tag(struct pci_dev *dev)
++{
++ bool support = true;
+
-+ pci_warn(a, "cannot be used for peer-to-peer DMA as 10-Bit Tag Requester enable is set for this device, but peer device (%s) does not support the 10-Bit Tag Completer\n",
-+ pci_name(b));
++ if (dev->subordinate == NULL)
++ return;
+
-+ if (a->is_virtfn)
-+ str = "sriov_vf_tags_ctl";
++ /* If no devices under the root port, no need to enable 10-Bit Tag. */
++ if (list_empty(&dev->subordinate->devices))
++ return;
+
-+ pci_warn(a, "to disable 10-Bit Tag Requester for this device, echo 0 > /sys/bus/pci/devices/%s/%s\n",
-+ pci_name(a), str);
++ pci_10bit_tag_comp_support(dev, &support);
++ if (!support)
++ return;
+
-+ return true;
++ /*
++ * PCIe spec 5.0r1.0 section 2.2.6.2 implementation note.
++ * In configurations where a Requester with 10-Bit Tag Requester
++ * capability needs to target multiple Completers, one needs to ensure
++ * that the Requester sends 10-Bit Tag Requests only to Completers
++ * that have 10-Bit Tag Completer capability. So we enable 10-Bit Tag
++ * Requester for root port only when the devices under the root port
++ * support 10-Bit Tag Completer.
++ */
++ pci_walk_bus(dev->subordinate, pci_10bit_tag_comp_support, &support);
++ if (!support)
++ return;
++
++ if (!(dev->pcie_devcap2 & PCI_EXP_DEVCAP2_10BIT_TAG_REQ))
++ return;
++
++ pci_dbg(dev, "enabling 10-Bit Tag Requester\n");
++ pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
++ PCI_EXP_DEVCTL2_10BIT_TAG_REQ_EN);
+}
+
/*
- * Calculate the P2PDMA mapping type and distance between two PCI devices.
- *
-@@ -532,6 +577,9 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
- map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
- }
- done:
-+ if (pci_10bit_tags_unsupported(client, provider, verbose))
-+ map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
+ * pcie_portdrv_probe - Probe PCI-Express port devices
+ * @dev: PCI-Express port device being probed
+@@ -111,6 +177,9 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
+ (type != PCI_EXP_TYPE_RC_EC)))
+ return -ENODEV;
+
++ if (type == PCI_EXP_TYPE_ROOT_PORT)
++ pci_configure_rp_10bit_tag(dev);
+
- rcu_read_lock();
- p2pdma = rcu_dereference(provider->p2pdma);
- if (p2pdma)
+ if (type == PCI_EXP_TYPE_RC_EC)
+ pcie_link_rcec(dev);
+
--
-2.22.0
+2.7.4