--- v5
+++ v11
@@ -1,105 +1,96 @@
-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.
+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.
Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
- drivers/pci/pcie/portdrv_pci.c | 72 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 72 insertions(+)
+ drivers/pci/p2pdma.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
-diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
-index c7ff1ee..0f9fb13 100644
---- a/drivers/pci/pcie/portdrv_pci.c
-+++ b/drivers/pci/pcie/portdrv_pci.c
-@@ -90,6 +90,75 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
- #define PCIE_PORTDRV_PM_OPS NULL
- #endif /* !PM */
+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"
-+static int pci_10bit_tag_comp_support(struct pci_dev *dev, void *data)
+ 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)
+{
-+ u8 *support = data;
++ bool req;
++ bool comp;
++ u16 ctl;
++ const char *str = "tags";
+
-+ if (*support == 0)
-+ return 0;
-+
-+ if (!pci_is_pcie(dev)) {
-+ *support = 0;
-+ return 0;
++ 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);
+ }
+
-+ /*
-+ * 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 = 0;
-+ return 0;
-+ }
++ comp = !!(b->devcap2 & PCI_EXP_DEVCAP2_10BIT_TAG_COMP);
+
-+ if (!(dev->pcie_devcap2 & PCI_EXP_DEVCAP2_10BIT_TAG_COMP)) {
-+ *support = 0;
-+ return 0;
-+ }
++ /* 10-bit tags not enabled on requester */
++ if (!req)
++ return false;
+
-+ return 0;
-+}
++ /* Completer can handle anything */
++ if (comp)
++ return false;
+
-+static void pci_configure_rp_10bit_tag(struct pci_dev *dev)
-+{
-+ u8 support = 1;
++ if (!verbose)
++ return true;
+
-+ if (dev->subordinate == NULL)
-+ return;
++ 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 no devices under the root port, no need to enable 10-Bit Tag. */
-+ if (list_empty(&dev->subordinate->devices))
-+ return;
++ if (a->is_virtfn)
++ str = "sriov_vf_tags_ctl";
+
-+ pci_10bit_tag_comp_support(dev, &support);
-+ if (!support)
-+ 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);
+
-+ /*
-+ * 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);
++ return true;
+}
+
/*
- * pcie_portdrv_probe - Probe PCI-Express port devices
- * @dev: PCI-Express port device being probed
-@@ -111,6 +180,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);
+ * 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;
+
- if (type == PCI_EXP_TYPE_RC_EC)
- pcie_link_rcec(dev);
-
+ rcu_read_lock();
+ p2pdma = rcu_dereference(provider->p2pdma);
+ if (p2pdma)
--
-2.7.4
+2.22.0