Inter-revision diff: patch 6

Comparing v10 (message) to v6 (message)

--- v10
+++ v6
@@ -1,93 +1,102 @@
-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/.../10bit_tag" to disable 10-Bit Tag
-Requester for PF device.
-
-"echo 0 > /sys/bus/pci/devices/.../sriov_vf_10bit_tag_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..804e390f4c22 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 = "10bit_tag";
++	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_10bit_tag_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
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help