linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge
@ 2019-08-12 17:30 Logan Gunthorpe
  2019-08-12 17:30 ` [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure Logan Gunthorpe
                   ` (14 more replies)
  0 siblings, 15 replies; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Bjorn, this is v3 of the patchset. Christophs suggestion's required a
bit more rework than could be expressed in incremental patches so
I've resent the whole thing. I started with your p2pdma branch though
so it should have all the changes you already made. I've included a
range-diff from your p2pdma branch below.

A git branch is available here:

https://github.com/sbates130272/linux-p2pmem/ p2pdma_rc_map_v3

--

Changes in v3:
 * Rebase on v5.3-rc3 (No changes)
 * Bjorn's edits for a bunch of the comments and commit messages
 * Rework upstream_bridge_distance() changes to split the distance,
   mapping type and ACS flag into separate pass-by-reference parameters
   (per Christoph's suggestion)
 * Jonathan Derrick (Intel) reported the domains can be 32-bits on
   some machines and thus the map_type_index() needed to be an unsigned long
   to accomadate this.

Changes in v2:
 * Rebase on v5.3-rc2 (No changes)
 * Re-introduce the private pagemap structure and move the p2p-specific
   elements out of the commond dev_pagemap (per Christoph)
 * Use flags instead of bool in the whitelist (per Jason)
 * Only store the mapping type in the xarray (instead of the distance
   with flags) such that a function can return the mapping method
   with a switch statement to decide how to map. (per Christoph)
 * Drop find_parent_pci_dev() on the fast path and rely on the fact
   that the struct device passed to the mapping functions *must* be
   a PCI device and convert it directly. (per suggestions from
   Christoph and Jason)
 * Collected Christian's Reviewed-by's

--

As discussed on the list previously, in order to fully support the
whitelist Christian added with the IOMMU, we must ensure that we
map any buffer going through the IOMMU with an aprropriate dma_map
call. This patchset accomplishes this by cleaning up the output of
upstream_bridge_distance() to better indicate the mapping requirements,
caching these requirements in an xarray, then looking them up at map
time and applying the appropriate mapping method.

After this patchset, it's possible to use the NVMe-of P2P support to
transfer between devices without a switch on the whitelisted root
complexes. A couple Intel device I have tested this on have also
been added to the white list.

Most of the changes are contained within the p2pdma.c, but there are
a few minor touches to other subsystems, mostly to add support
to call an unmap function.

--

Logan Gunthorpe (14):
  PCI/P2PDMA: Introduce private pagemap structure
  PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
  PCI/P2PDMA: Add constants for map type results to
    upstream_bridge_distance()
  PCI/P2PDMA: Factor out __upstream_bridge_distance()
  PCI/P2PDMA: Apply host bridge whitelist for ACS
  PCI/P2PDMA: Factor out host_bridge_whitelist()
  PCI/P2PDMA: Whitelist some Intel host bridges
  PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
  PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
  PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
  PCI/P2PDMA: Store mapping method in an xarray
  PCI/P2PDMA: dma_map() requests that traverse the host bridge
  PCI/P2PDMA: Allow IOMMU for host bridge whitelist
  PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation

 drivers/infiniband/core/rw.c |   6 +-
 drivers/nvme/host/pci.c      |  10 +-
 drivers/pci/p2pdma.c         | 374 +++++++++++++++++++++++++----------
 include/linux/memremap.h     |   1 -
 include/linux/pci-p2pdma.h   |  28 ++-
 5 files changed, 300 insertions(+), 119 deletions(-)

--

$ git range-diff bjorn/master..bjorn/pci/p2pdma master..p2pdma_rc_map_v3

 1:  5173c82b3571 =  1:  78cc3a5be538 PCI/P2PDMA: Introduce private pagemap structure
 2:  f33fd6b8da93 =  2:  9fb388dff957 PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
 3:  767f47b59702 <  -:  ------------ PCI/P2PDMA: Add constants for not-supported result upstream_bridge_distance()
 -:  ------------ >  3:  ed105432f644 PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance()
 4:  93ed41974d69 !  4:  590aaea31997 PCI/P2PDMA: Factor out __upstream_bridge_distance()
    @@ -17,8 +17,8 @@
      --- a/drivers/pci/p2pdma.c
      +++ b/drivers/pci/p2pdma.c
     @@
    - 	P2PDMA_NOT_SUPPORTED		= 0x08000000,
    - };
    + 	return false;
    + }

     -/*
     - * Find the distance through the nearest common upstream bridge between
    @@ -44,31 +44,29 @@
     - * port of the switch, to the common upstream port, back up to the second
     - * downstream port and then to Device B.
     - *
    -- * Any two devices that cannot communicate using p2pdma will return the
    -- * distance with the flag P2PDMA_NOT_SUPPORTED.
    +- * Any two devices that cannot communicate using p2pdma will return
    +- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
     - *
     - * Any two devices that have a data path that goes through the host bridge
     - * will consult a whitelist. If the host bridges are on the whitelist,
    -- * the distance will be returned with the flag P2PDMA_THRU_HOST_BRIDGE set.
    -- * If either bridge is not on the whitelist, the flag P2PDMA_NOT_SUPPORTED will
    -- * be set.
    +- * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
    +- *
    +- * If either bridge is not on the whitelist this function returns
    +- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
     - *
    -- * If a bridge which has any ACS redirection bits set is in the path
    -- * this function will flag the result with P2PDMA_ACS_FORCES_UPSTREAM.
    -- * In this case, a list of all infringing bridge addresses will be
    -- * populated in acs_list (assuming it's non-null) for printk purposes.
    +- * If a bridge which has any ACS redirection bits set is in the path,
    +- * acs_redirects will be set to true. In this case, a list of all infringing
    +- * bridge addresses will be populated in acs_list (assuming it's non-null)
    +- * for printk purposes.
     - */
    --static int upstream_bridge_distance(struct pci_dev *provider,
    --				    struct pci_dev *client,
    --				    struct seq_buf *acs_list)
    -+static int __upstream_bridge_distance(struct pci_dev *provider,
    -+				      struct pci_dev *client,
    -+				      struct seq_buf *acs_list)
    + static enum pci_p2pdma_map_type
    +-upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
    ++__upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
    + 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
      {
      	struct pci_dev *a = provider, *b = client, *bb;
    - 	int dist_a = 0;
     @@
    - 	return dist_a + dist_b;
    + 	return PCI_P2PDMA_MAP_BUS_ADDR;
      }

     +/*
    @@ -95,27 +93,29 @@
     + * port of the switch, to the common upstream port, back up to the second
     + * downstream port and then to Device B.
     + *
    -+ * Any two devices that cannot communicate using p2pdma will return the
    -+ * distance with the flag P2PDMA_NOT_SUPPORTED.
    ++ * Any two devices that cannot communicate using p2pdma will return
    ++ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
     + *
     + * Any two devices that have a data path that goes through the host bridge
     + * will consult a whitelist. If the host bridges are on the whitelist,
    -+ * the distance will be returned with the flag P2PDMA_THRU_HOST_BRIDGE set.
    -+ * If either bridge is not on the whitelist, the flag P2PDMA_NOT_SUPPORTED will
    -+ * be set.
    ++ * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
     + *
    -+ * If a bridge which has any ACS redirection bits set is in the path
    -+ * this function will flag the result with P2PDMA_ACS_FORCES_UPSTREAM.
    -+ * In this case, a list of all infringing bridge addresses will be
    -+ * populated in acs_list (assuming it's non-null) for printk purposes.
    ++ * If either bridge is not on the whitelist this function returns
    ++ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
    ++ *
    ++ * If a bridge which has any ACS redirection bits set is in the path,
    ++ * acs_redirects will be set to true. In this case, a list of all infringing
    ++ * bridge addresses will be populated in acs_list (assuming it's non-null)
    ++ * for printk purposes.
     + */
    -+static int upstream_bridge_distance(struct pci_dev *provider,
    -+				    struct pci_dev *client,
    -+				    struct seq_buf *acs_list)
    ++static enum pci_p2pdma_map_type
    ++upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
    ++		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
     +{
    -+	return __upstream_bridge_distance(provider, client, acs_list);
    ++	return __upstream_bridge_distance(provider, client, dist,
    ++					  acs_redirects, acs_list);
     +}
     +
    - static int upstream_bridge_distance_warn(struct pci_dev *provider,
    - 					 struct pci_dev *client)
    - {
    + static enum pci_p2pdma_map_type
    + upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
    + 			      int *dist)
 5:  f975e51cf5df <  -:  ------------ PCI/P2PDMA: Apply host bridge whitelist for ACS
 -:  ------------ >  5:  336e968f075b PCI/P2PDMA: Apply host bridge whitelist for ACS
 6:  59b6507ac07c !  6:  3f565ce6e1d4 PCI/P2PDMA: Factor out host_bridge_whitelist()
    @@ -58,15 +58,16 @@
     +	return false;
     +}
     +
    - enum {
    - 	/*
    - 	 * These arbitrary offset are or'd onto the upstream distance
    + static enum pci_p2pdma_map_type
    + __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
    + 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
     @@
    - 	if (!(dist & P2PDMA_THRU_HOST_BRIDGE))
    - 		return dist;
    + 					      acs_redirects, acs_list);

    --	if (root_complex_whitelist(provider) && root_complex_whitelist(client))
    -+	if (host_bridge_whitelist(provider, client))
    - 		return dist;
    + 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
    +-		if (!root_complex_whitelist(provider) ||
    +-		    !root_complex_whitelist(client))
    ++		if (!host_bridge_whitelist(provider, client))
    + 			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
    + 	}

    - 	return dist | P2PDMA_NOT_SUPPORTED;
 7:  5ecec567445f =  7:  7b8701dd45e0 PCI/P2PDMA: Whitelist some Intel host bridges
 8:  68a37758d5cf =  8:  b52771ae7f95 PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
 9:  4b821298d4f7 =  9:  88a554eb39c9 PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
10:  3f2dac803737 = 10:  604260bd186a PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
11:  fc402d621534 ! 11:  b55fc423a41a PCI/P2PDMA: Store mapping method in an xarray
    @@ -18,14 +18,10 @@
      #include <linux/seq_buf.h>
      #include <linux/iommu.h>
     +#include <linux/xarray.h>
    -+
    -+enum pci_p2pdma_map_type {
    -+	PCI_P2PDMA_MAP_UNKNOWN = 0,
    -+	PCI_P2PDMA_MAP_NOT_SUPPORTED,
    -+	PCI_P2PDMA_MAP_BUS_ADDR,
    -+	PCI_P2PDMA_MAP_THRU_IOMMU,
    -+};

    + enum pci_p2pdma_map_type {
    + 	PCI_P2PDMA_MAP_UNKNOWN = 0,
    +@@
      struct pci_p2pdma {
      	struct gen_pool *pool;
      	bool p2pmem_published;
    @@ -51,10 +47,10 @@
      	if (!p2p->pool)
      		goto out;
     @@
    - 	return dist_a + dist_b;
    + 	return PCI_P2PDMA_MAP_BUS_ADDR;
      }

    -+static int map_types_idx(struct pci_dev *client)
    ++static unsigned long map_types_idx(struct pci_dev *client)
     +{
     +	return (pci_domain_nr(client->bus) << 16) |
     +		(client->bus->number << 8) | client->devfn;
    @@ -64,37 +60,17 @@
       * Find the distance through the nearest common upstream bridge between
       * two PCI devices.
     @@
    - 				    struct pci_dev *client,
    - 				    struct seq_buf *acs_list)
    - {
    -+	enum pci_p2pdma_map_type map_type;
    - 	int dist;
    -
    - 	dist = __upstream_bridge_distance(provider, client, acs_list);

    --	if (!(dist & P2PDMA_THRU_HOST_BRIDGE))
    --		return dist;
    -+	if (!(dist & P2PDMA_THRU_HOST_BRIDGE)) {
    -+		map_type = PCI_P2PDMA_MAP_BUS_ADDR;
    -+		goto store_map_type_and_return;
    -+	}
    -+
    -+	if (host_bridge_whitelist(provider, client)) {
    -+		map_type = PCI_P2PDMA_MAP_THRU_IOMMU;
    -+	} else {
    -+		dist |= P2PDMA_NOT_SUPPORTED;
    -+		map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
    -+	}
    + 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
    + 		if (!host_bridge_whitelist(provider, client))
    +-			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
    ++			map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
    + 	}

    --	if (host_bridge_whitelist(provider, client))
    --		return dist;
    -+store_map_type_and_return:
     +	if (provider->p2pdma)
     +		xa_store(&provider->p2pdma->map_types, map_types_idx(client),
     +			 xa_mk_value(map_type), GFP_KERNEL);
    -
    --	return dist | P2PDMA_NOT_SUPPORTED;
    -+	return dist;
    ++
    + 	return map_type;
      }

    - static int upstream_bridge_distance_warn(struct pci_dev *provider,
12:  c51eb851e9da ! 12:  94e4c8633459 PCI/P2PDMA: dma_map() requests that traverse the host bridge
    @@ -44,7 +44,7 @@
     +	client = to_pci_dev(dev);
     +
     +	switch (pci_p2pdma_map_type(p2p_pgmap->provider, client)) {
    -+	case PCI_P2PDMA_MAP_THRU_IOMMU:
    ++	case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
     +		return dma_map_sg_attrs(dev, sg, nents, dir, attrs);
     +	case PCI_P2PDMA_MAP_BUS_ADDR:
     +		return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
    @@ -71,7 +71,7 @@
     +
     +	map_type = pci_p2pdma_map_type(p2p_pgmap->provider, client);
     +
    -+	if (map_type == PCI_P2PDMA_MAP_THRU_IOMMU)
    ++	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE)
     +		dma_unmap_sg_attrs(dev, sg, nents, dir, attrs);
      }
      EXPORT_SYMBOL_GPL(pci_p2pdma_unmap_sg_attrs);
13:  0a3468f51621 = 13:  f067cdb5b963 PCI/P2PDMA: Allow IOMMU for host bridge whitelist
14:  20c0cf9f4c9c = 14:  87c84b001dfa PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation

--
2.20.1

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:06   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct Logan Gunthorpe
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Move the PCI bus offset from the generic dev_pagemap structure to a
specific pci_p2pdma_pagemap structure.

This structure will grow in subsequent patches.

Link: https://lore.kernel.org/r/20190730163545.4915-2-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c     | 26 ++++++++++++++++++++------
 include/linux/memremap.h |  1 -
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 234476226529..03e9c887bdfb 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -25,6 +25,16 @@ struct pci_p2pdma {
 	bool p2pmem_published;
 };
 
+struct pci_p2pdma_pagemap {
+	struct dev_pagemap pgmap;
+	u64 bus_offset;
+};
+
+static struct pci_p2pdma_pagemap *to_p2p_pgmap(struct dev_pagemap *pgmap)
+{
+	return container_of(pgmap, struct pci_p2pdma_pagemap, pgmap);
+}
+
 static ssize_t size_show(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
@@ -135,6 +145,7 @@ static int pci_p2pdma_setup(struct pci_dev *pdev)
 int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
 			    u64 offset)
 {
+	struct pci_p2pdma_pagemap *p2p_pgmap;
 	struct dev_pagemap *pgmap;
 	void *addr;
 	int error;
@@ -157,14 +168,17 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
 			return error;
 	}
 
-	pgmap = devm_kzalloc(&pdev->dev, sizeof(*pgmap), GFP_KERNEL);
-	if (!pgmap)
+	p2p_pgmap = devm_kzalloc(&pdev->dev, sizeof(*p2p_pgmap), GFP_KERNEL);
+	if (!p2p_pgmap)
 		return -ENOMEM;
+
+	pgmap = &p2p_pgmap->pgmap;
 	pgmap->res.start = pci_resource_start(pdev, bar) + offset;
 	pgmap->res.end = pgmap->res.start + size - 1;
 	pgmap->res.flags = pci_resource_flags(pdev, bar);
 	pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
-	pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) -
+
+	p2p_pgmap->bus_offset = pci_bus_address(pdev, bar) -
 		pci_resource_start(pdev, bar);
 
 	addr = devm_memremap_pages(&pdev->dev, pgmap);
@@ -720,7 +734,7 @@ EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
 int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		      enum dma_data_direction dir)
 {
-	struct dev_pagemap *pgmap;
+	struct pci_p2pdma_pagemap *p2p_pgmap;
 	struct scatterlist *s;
 	phys_addr_t paddr;
 	int i;
@@ -736,10 +750,10 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		return 0;
 
 	for_each_sg(sg, s, nents, i) {
-		pgmap = sg_page(s)->pgmap;
+		p2p_pgmap = to_p2p_pgmap(sg_page(s)->pgmap);
 		paddr = sg_phys(s);
 
-		s->dma_address = paddr - pgmap->pci_p2pdma_bus_offset;
+		s->dma_address = paddr - p2p_pgmap->bus_offset;
 		sg_dma_len(s) = s->length;
 	}
 
diff --git a/include/linux/memremap.h b/include/linux/memremap.h
index f8a5b2a19945..b459518ce475 100644
--- a/include/linux/memremap.h
+++ b/include/linux/memremap.h
@@ -112,7 +112,6 @@ struct dev_pagemap {
 	struct device *dev;
 	enum memory_type type;
 	unsigned int flags;
-	u64 pci_p2pdma_bus_offset;
 	const struct dev_pagemap_ops *ops;
 };
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
  2019-08-12 17:30 ` [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:06   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance() Logan Gunthorpe
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

The provider will be needed to figure out how to map a device.

Link: https://lore.kernel.org/r/20190730163545.4915-3-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 03e9c887bdfb..93fbda14f4a9 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -27,6 +27,7 @@ struct pci_p2pdma {
 
 struct pci_p2pdma_pagemap {
 	struct dev_pagemap pgmap;
+	struct pci_dev *provider;
 	u64 bus_offset;
 };
 
@@ -178,6 +179,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
 	pgmap->res.flags = pci_resource_flags(pdev, bar);
 	pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
 
+	p2p_pgmap->provider = pdev;
 	p2p_pgmap->bus_offset = pci_bus_address(pdev, bar) -
 		pci_resource_start(pdev, bar);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
  2019-08-12 17:30 ` [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure Logan Gunthorpe
  2019-08-12 17:30 ` [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:08   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance() Logan Gunthorpe
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe,
	Christian König

Add constant flags to indicate how two devices will be mapped or if they
are unsupported. upstream_bridge_distance() will now return the
mapping type and the distance in a passed-by-reference argument.

This helps annotate the code better, but the main reason is so we can use
the information to store the required mapping method in an xarray.

Link: https://lore.kernel.org/r/20190730163545.4915-4-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
---
 drivers/pci/p2pdma.c | 95 +++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 37 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 93fbda14f4a9..8f0688201aec 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -20,6 +20,13 @@
 #include <linux/seq_buf.h>
 #include <linux/iommu.h>
 
+enum pci_p2pdma_map_type {
+	PCI_P2PDMA_MAP_UNKNOWN = 0,
+	PCI_P2PDMA_MAP_NOT_SUPPORTED,
+	PCI_P2PDMA_MAP_BUS_ADDR,
+	PCI_P2PDMA_MAP_THRU_HOST_BRIDGE,
+};
+
 struct pci_p2pdma {
 	struct gen_pool *pool;
 	bool p2pmem_published;
@@ -313,34 +320,33 @@ static bool root_complex_whitelist(struct pci_dev *dev)
  * port of the switch, to the common upstream port, back up to the second
  * downstream port and then to Device B.
  *
- * Any two devices that don't have a common upstream bridge will return -1.
- * In this way devices on separate PCIe root ports will be rejected, which
- * is what we want for peer-to-peer seeing each PCIe root port defines a
- * separate hierarchy domain and there's no way to determine whether the root
- * complex supports forwarding between them.
+ * Any two devices that cannot communicate using p2pdma will return
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
+ *
+ * Any two devices that have a data path that goes through the host bridge
+ * will consult a whitelist. If the host bridges are on the whitelist,
+ * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
  *
- * In the case where two devices are connected to different PCIe switches,
- * this function will still return a positive distance as long as both
- * switches eventually have a common upstream bridge. Note this covers
- * the case of using multiple PCIe switches to achieve a desired level of
- * fan-out from a root port. The exact distance will be a function of the
- * number of switches between Device A and Device B.
+ * If either bridge is not on the whitelist this function returns
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
  *
- * If a bridge which has any ACS redirection bits set is in the path
- * then this functions will return -2. This is so we reject any
- * cases where the TLPs are forwarded up into the root complex.
- * In this case, a list of all infringing bridge addresses will be
- * populated in acs_list (assuming it's non-null) for printk purposes.
+ * If a bridge which has any ACS redirection bits set is in the path,
+ * acs_redirects will be set to true. In this case, a list of all infringing
+ * bridge addresses will be populated in acs_list (assuming it's non-null)
+ * for printk purposes.
  */
-static int upstream_bridge_distance(struct pci_dev *provider,
-				    struct pci_dev *client,
-				    struct seq_buf *acs_list)
+static enum pci_p2pdma_map_type
+upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
+		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
 {
 	struct pci_dev *a = provider, *b = client, *bb;
 	int dist_a = 0;
 	int dist_b = 0;
 	int acs_cnt = 0;
 
+	if (acs_redirects)
+		*acs_redirects = false;
+
 	/*
 	 * Note, we don't need to take references to devices returned by
 	 * pci_upstream_bridge() seeing we hold a reference to a child
@@ -369,15 +375,18 @@ static int upstream_bridge_distance(struct pci_dev *provider,
 		dist_a++;
 	}
 
+	if (dist)
+		*dist = dist_a + dist_b;
+
 	/*
 	 * Allow the connection if both devices are on a whitelisted root
 	 * complex, but add an arbitrary large value to the distance.
 	 */
 	if (root_complex_whitelist(provider) &&
 	    root_complex_whitelist(client))
-		return 0x1000 + dist_a + dist_b;
+		return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
 
-	return -1;
+	return PCI_P2PDMA_MAP_NOT_SUPPORTED;
 
 check_b_path_acs:
 	bb = b;
@@ -394,33 +403,44 @@ static int upstream_bridge_distance(struct pci_dev *provider,
 		bb = pci_upstream_bridge(bb);
 	}
 
-	if (acs_cnt)
-		return -2;
+	if (dist)
+		*dist = dist_a + dist_b;
 
-	return dist_a + dist_b;
+	if (acs_cnt) {
+		if (acs_redirects)
+			*acs_redirects = true;
+
+		return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+	}
+
+	return PCI_P2PDMA_MAP_BUS_ADDR;
 }
 
-static int upstream_bridge_distance_warn(struct pci_dev *provider,
-					 struct pci_dev *client)
+static enum pci_p2pdma_map_type
+upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
+			      int *dist)
 {
 	struct seq_buf acs_list;
+	bool acs_redirects;
 	int ret;
 
 	seq_buf_init(&acs_list, kmalloc(PAGE_SIZE, GFP_KERNEL), PAGE_SIZE);
 	if (!acs_list.buffer)
 		return -ENOMEM;
 
-	ret = upstream_bridge_distance(provider, client, &acs_list);
-	if (ret == -2) {
-		pci_warn(client, "cannot be used for peer-to-peer DMA as ACS redirect is set between the client and provider (%s)\n",
+	ret = upstream_bridge_distance(provider, client, dist, &acs_redirects,
+				       &acs_list);
+	if (acs_redirects) {
+		pci_warn(client, "ACS redirect is set between the client and provider (%s)\n",
 			 pci_name(provider));
 		/* Drop final semicolon */
 		acs_list.buffer[acs_list.len-1] = 0;
 		pci_warn(client, "to disable ACS redirect for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
 			 acs_list.buffer);
+	}
 
-	} else if (ret < 0) {
-		pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge\n",
+	if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED) {
+		pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n",
 			 pci_name(provider));
 	}
 
@@ -452,7 +472,8 @@ int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients,
 {
 	bool not_supported = false;
 	struct pci_dev *pci_client;
-	int distance = 0;
+	int total_dist = 0;
+	int distance;
 	int i, ret;
 
 	if (num_clients == 0)
@@ -477,26 +498,26 @@ int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients,
 
 		if (verbose)
 			ret = upstream_bridge_distance_warn(provider,
-							    pci_client);
+					pci_client, &distance);
 		else
 			ret = upstream_bridge_distance(provider, pci_client,
-						       NULL);
+						       &distance, NULL, NULL);
 
 		pci_dev_put(pci_client);
 
-		if (ret < 0)
+		if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED)
 			not_supported = true;
 
 		if (not_supported && !verbose)
 			break;
 
-		distance += ret;
+		total_dist += distance;
 	}
 
 	if (not_supported)
 		return -1;
 
-	return distance;
+	return total_dist;
 }
 EXPORT_SYMBOL_GPL(pci_p2pdma_distance_many);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (2 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:08   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS Logan Gunthorpe
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe,
	Christian König

This is a prep patch to create a second level helper. There are no
functional changes.

The root complex whitelist code will be moved into this function in a
subsequent patch.

Link: https://lore.kernel.org/r/20190730163545.4915-5-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
---
 drivers/pci/p2pdma.c | 88 ++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 40 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 8f0688201aec..600ba6a7aa11 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -296,47 +296,8 @@ static bool root_complex_whitelist(struct pci_dev *dev)
 	return false;
 }
 
-/*
- * Find the distance through the nearest common upstream bridge between
- * two PCI devices.
- *
- * If the two devices are the same device then 0 will be returned.
- *
- * If there are two virtual functions of the same device behind the same
- * bridge port then 2 will be returned (one step down to the PCIe switch,
- * then one step back to the same device).
- *
- * In the case where two devices are connected to the same PCIe switch, the
- * value 4 will be returned. This corresponds to the following PCI tree:
- *
- *     -+  Root Port
- *      \+ Switch Upstream Port
- *       +-+ Switch Downstream Port
- *       + \- Device A
- *       \-+ Switch Downstream Port
- *         \- Device B
- *
- * The distance is 4 because we traverse from Device A through the downstream
- * port of the switch, to the common upstream port, back up to the second
- * downstream port and then to Device B.
- *
- * Any two devices that cannot communicate using p2pdma will return
- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
- *
- * Any two devices that have a data path that goes through the host bridge
- * will consult a whitelist. If the host bridges are on the whitelist,
- * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
- *
- * If either bridge is not on the whitelist this function returns
- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
- *
- * If a bridge which has any ACS redirection bits set is in the path,
- * acs_redirects will be set to true. In this case, a list of all infringing
- * bridge addresses will be populated in acs_list (assuming it's non-null)
- * for printk purposes.
- */
 static enum pci_p2pdma_map_type
-upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
+__upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
 {
 	struct pci_dev *a = provider, *b = client, *bb;
@@ -416,6 +377,53 @@ upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 	return PCI_P2PDMA_MAP_BUS_ADDR;
 }
 
+/*
+ * Find the distance through the nearest common upstream bridge between
+ * two PCI devices.
+ *
+ * If the two devices are the same device then 0 will be returned.
+ *
+ * If there are two virtual functions of the same device behind the same
+ * bridge port then 2 will be returned (one step down to the PCIe switch,
+ * then one step back to the same device).
+ *
+ * In the case where two devices are connected to the same PCIe switch, the
+ * value 4 will be returned. This corresponds to the following PCI tree:
+ *
+ *     -+  Root Port
+ *      \+ Switch Upstream Port
+ *       +-+ Switch Downstream Port
+ *       + \- Device A
+ *       \-+ Switch Downstream Port
+ *         \- Device B
+ *
+ * The distance is 4 because we traverse from Device A through the downstream
+ * port of the switch, to the common upstream port, back up to the second
+ * downstream port and then to Device B.
+ *
+ * Any two devices that cannot communicate using p2pdma will return
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
+ *
+ * Any two devices that have a data path that goes through the host bridge
+ * will consult a whitelist. If the host bridges are on the whitelist,
+ * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
+ *
+ * If either bridge is not on the whitelist this function returns
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
+ *
+ * If a bridge which has any ACS redirection bits set is in the path,
+ * acs_redirects will be set to true. In this case, a list of all infringing
+ * bridge addresses will be populated in acs_list (assuming it's non-null)
+ * for printk purposes.
+ */
+static enum pci_p2pdma_map_type
+upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
+		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
+{
+	return __upstream_bridge_distance(provider, client, dist,
+					  acs_redirects, acs_list);
+}
+
 static enum pci_p2pdma_map_type
 upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
 			      int *dist)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (3 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:09   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist() Logan Gunthorpe
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe,
	Christian König

When a P2PDMA transfer is rejected due to ACS being set, we can also check
the whitelist and allow the transactions.

Do this by pushing the whitelist check into the upstream_bridge_distance()
function.

Link: https://lore.kernel.org/r/20190730163545.4915-6-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
---
 drivers/pci/p2pdma.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 600ba6a7aa11..f7f7e5862bab 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -339,15 +339,7 @@ __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 	if (dist)
 		*dist = dist_a + dist_b;
 
-	/*
-	 * Allow the connection if both devices are on a whitelisted root
-	 * complex, but add an arbitrary large value to the distance.
-	 */
-	if (root_complex_whitelist(provider) &&
-	    root_complex_whitelist(client))
-		return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
-
-	return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+	return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
 
 check_b_path_acs:
 	bb = b;
@@ -371,7 +363,7 @@ __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 		if (acs_redirects)
 			*acs_redirects = true;
 
-		return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+		return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
 	}
 
 	return PCI_P2PDMA_MAP_BUS_ADDR;
@@ -420,8 +412,18 @@ static enum pci_p2pdma_map_type
 upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
 {
-	return __upstream_bridge_distance(provider, client, dist,
-					  acs_redirects, acs_list);
+	enum pci_p2pdma_map_type map_type;
+
+	map_type = __upstream_bridge_distance(provider, client, dist,
+					      acs_redirects, acs_list);
+
+	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
+		if (!root_complex_whitelist(provider) ||
+		    !root_complex_whitelist(client))
+			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+	}
+
+	return map_type;
 }
 
 static enum pci_p2pdma_map_type
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (4 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:09   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges Logan Gunthorpe
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Push both PCI devices into the whitelist checking function seeing some
hardware will require us ensuring they are on the same host bridge.

At the same time we rename root_complex_whitelist() to
host_bridge_whitelist() to match the terminology used in the code.

Link: https://lore.kernel.org/r/20190730163545.4915-7-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index f7f7e5862bab..4b9f0903b340 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -269,19 +269,11 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
 	seq_buf_printf(buf, "%s;", pci_name(pdev));
 }
 
-/*
- * If we can't find a common upstream bridge take a look at the root
- * complex and compare it to a whitelist of known good hardware.
- */
-static bool root_complex_whitelist(struct pci_dev *dev)
+static bool __host_bridge_whitelist(struct pci_host_bridge *host)
 {
-	struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
 	struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0));
 	unsigned short vendor, device;
 
-	if (iommu_present(dev->dev.bus))
-		return false;
-
 	if (!root)
 		return false;
 
@@ -296,6 +288,24 @@ static bool root_complex_whitelist(struct pci_dev *dev)
 	return false;
 }
 
+/*
+ * If we can't find a common upstream bridge take a look at the root
+ * complex and compare it to a whitelist of known good hardware.
+ */
+static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b)
+{
+	struct pci_host_bridge *host_a = pci_find_host_bridge(a->bus);
+	struct pci_host_bridge *host_b = pci_find_host_bridge(b->bus);
+
+	if (iommu_present(a->dev.bus) || iommu_present(b->dev.bus))
+		return false;
+
+	if (__host_bridge_whitelist(host_a) && __host_bridge_whitelist(host_b))
+		return true;
+
+	return false;
+}
+
 static enum pci_p2pdma_map_type
 __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
@@ -418,8 +428,7 @@ upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 					      acs_redirects, acs_list);
 
 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
-		if (!root_complex_whitelist(provider) ||
-		    !root_complex_whitelist(client))
+		if (!host_bridge_whitelist(provider, client))
 			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
 	}
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (5 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:11   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg() Logan Gunthorpe
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Intel devices do not have good support for P2P requests that span different
host bridges as the transactions will cross the QPI/UPI bus and this does
not perform well.

Therefore, enable support for these devices only if the host bridges match.

Add Intel devices that have been tested and are known to work. There are
likely many others out there that will need to be tested and added.

Link: https://lore.kernel.org/r/20190730163545.4915-8-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 4b9f0903b340..2c4a8e92ed64 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -269,9 +269,30 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
 	seq_buf_printf(buf, "%s;", pci_name(pdev));
 }
 
-static bool __host_bridge_whitelist(struct pci_host_bridge *host)
+static const struct pci_p2pdma_whitelist_entry {
+	unsigned short vendor;
+	unsigned short device;
+	enum {
+		REQ_SAME_HOST_BRIDGE	= 1 << 0,
+	} flags;
+} pci_p2pdma_whitelist[] = {
+	/* AMD ZEN */
+	{PCI_VENDOR_ID_AMD,	0x1450,	0},
+
+	/* Intel Xeon E5/Core i7 */
+	{PCI_VENDOR_ID_INTEL,	0x3c00, REQ_SAME_HOST_BRIDGE},
+	{PCI_VENDOR_ID_INTEL,	0x3c01, REQ_SAME_HOST_BRIDGE},
+	/* Intel Xeon E7 v3/Xeon E5 v3/Core i7 */
+	{PCI_VENDOR_ID_INTEL,	0x2f00, REQ_SAME_HOST_BRIDGE},
+	{PCI_VENDOR_ID_INTEL,	0x2f01, REQ_SAME_HOST_BRIDGE},
+	{}
+};
+
+static bool __host_bridge_whitelist(struct pci_host_bridge *host,
+				    bool same_host_bridge)
 {
 	struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0));
+	const struct pci_p2pdma_whitelist_entry *entry;
 	unsigned short vendor, device;
 
 	if (!root)
@@ -281,9 +302,14 @@ static bool __host_bridge_whitelist(struct pci_host_bridge *host)
 	device = root->device;
 	pci_dev_put(root);
 
-	/* AMD ZEN host bridges can do peer to peer */
-	if (vendor == PCI_VENDOR_ID_AMD && device == 0x1450)
+	for (entry = pci_p2pdma_whitelist; entry->vendor; entry++) {
+		if (vendor != entry->vendor || device != entry->device)
+			continue;
+		if (entry->flags & REQ_SAME_HOST_BRIDGE && !same_host_bridge)
+			return false;
+
 		return true;
+	}
 
 	return false;
 }
@@ -300,7 +326,11 @@ static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b)
 	if (iommu_present(a->dev.bus) || iommu_present(b->dev.bus))
 		return false;
 
-	if (__host_bridge_whitelist(host_a) && __host_bridge_whitelist(host_b))
+	if (host_a == host_b)
+		return __host_bridge_whitelist(host_a, true);
+
+	if (__host_bridge_whitelist(host_a, false) &&
+	    __host_bridge_whitelist(host_b, false))
 		return true;
 
 	return false;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (6 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:12   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg() Logan Gunthorpe
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

This is to match the dma_map_sg() API which this function will have to call
in an future patch.

Add a pci_p2pdma_map_sg_attrs() function and helper to call it with no
attributes just like the dma_map_sg() function.

Link: https://lore.kernel.org/r/20190730163545.4915-9-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/nvme/host/pci.c    |  4 ++--
 drivers/pci/p2pdma.c       |  7 ++++---
 include/linux/pci-p2pdma.h | 15 +++++++++++----
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index db160cee42ad..f97bb031228a 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -832,8 +832,8 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
 		goto out;
 
 	if (is_pci_p2pdma_page(sg_page(iod->sg)))
-		nr_mapped = pci_p2pdma_map_sg(dev->dev, iod->sg, iod->nents,
-					      rq_dma_dir(req));
+		nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
+				iod->nents, rq_dma_dir(req), DMA_ATTR_NO_WARN);
 	else
 		nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents,
 					     rq_dma_dir(req), DMA_ATTR_NO_WARN);
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 2c4a8e92ed64..94fbacbcbbd0 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -798,13 +798,14 @@ EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
  * @sg: scatter list to map
  * @nents: elements in the scatterlist
  * @dir: DMA direction
+ * @attrs: DMA attributes passed to dma_map_sg() (if called)
  *
  * Scatterlists mapped with this function should not be unmapped in any way.
  *
  * Returns the number of SG entries mapped or 0 on error.
  */
-int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		      enum dma_data_direction dir)
+int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, unsigned long attrs)
 {
 	struct pci_p2pdma_pagemap *p2p_pgmap;
 	struct scatterlist *s;
@@ -831,7 +832,7 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 	return nents;
 }
-EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg);
+EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
 
 /**
  * pci_p2pdma_enable_store - parse a configfs/sysfs attribute store
diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h
index bca9bc3e5be7..7fd51954f93a 100644
--- a/include/linux/pci-p2pdma.h
+++ b/include/linux/pci-p2pdma.h
@@ -30,8 +30,8 @@ struct scatterlist *pci_p2pmem_alloc_sgl(struct pci_dev *pdev,
 					 unsigned int *nents, u32 length);
 void pci_p2pmem_free_sgl(struct pci_dev *pdev, struct scatterlist *sgl);
 void pci_p2pmem_publish(struct pci_dev *pdev, bool publish);
-int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		      enum dma_data_direction dir);
+int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, unsigned long attrs);
 int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev,
 			    bool *use_p2pdma);
 ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev,
@@ -81,8 +81,9 @@ static inline void pci_p2pmem_free_sgl(struct pci_dev *pdev,
 static inline void pci_p2pmem_publish(struct pci_dev *pdev, bool publish)
 {
 }
-static inline int pci_p2pdma_map_sg(struct device *dev,
-		struct scatterlist *sg, int nents, enum dma_data_direction dir)
+static inline int pci_p2pdma_map_sg_attrs(struct device *dev,
+		struct scatterlist *sg, int nents, enum dma_data_direction dir,
+		unsigned long attrs)
 {
 	return 0;
 }
@@ -111,4 +112,10 @@ static inline struct pci_dev *pci_p2pmem_find(struct device *client)
 	return pci_p2pmem_find_many(&client, 1);
 }
 
+static inline int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg,
+				    int nents, enum dma_data_direction dir)
+{
+	return pci_p2pdma_map_sg_attrs(dev, sg, nents, dir, 0);
+}
+
 #endif /* _LINUX_PCI_P2P_H */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (7 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:13   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg() Logan Gunthorpe
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Add pci_p2pdma_unmap_sg() to the two places that call pci_p2pdma_map_sg().

This is a prep patch to introduce correct mappings for p2pdma transactions
that go through the root complex.

Link: https://lore.kernel.org/r/20190730163545.4915-10-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/infiniband/core/rw.c |  6 ++++--
 drivers/nvme/host/pci.c      |  6 ++++--
 drivers/pci/p2pdma.c         | 18 +++++++++++++++++-
 include/linux/pci-p2pdma.h   | 13 +++++++++++++
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
index dce06108c8c3..5337393d4dfe 100644
--- a/drivers/infiniband/core/rw.c
+++ b/drivers/infiniband/core/rw.c
@@ -583,8 +583,10 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
 		break;
 	}
 
-	/* P2PDMA contexts do not need to be unmapped */
-	if (!is_pci_p2pdma_page(sg_page(sg)))
+	if (is_pci_p2pdma_page(sg_page(sg)))
+		pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg,
+				    sg_cnt, dir);
+	else
 		ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 }
 EXPORT_SYMBOL(rdma_rw_ctx_destroy);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index f97bb031228a..0f92cca7a860 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -547,8 +547,10 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
 
 	WARN_ON_ONCE(!iod->nents);
 
-	/* P2PDMA requests do not need to be unmapped */
-	if (!is_pci_p2pdma_page(sg_page(iod->sg)))
+	if (is_pci_p2pdma_page(sg_page(iod->sg)))
+		pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
+				    rq_dma_dir(req));
+	else
 		dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
 
 
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 94fbacbcbbd0..1eec7a5ec27e 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -800,7 +800,8 @@ EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
  * @dir: DMA direction
  * @attrs: DMA attributes passed to dma_map_sg() (if called)
  *
- * Scatterlists mapped with this function should not be unmapped in any way.
+ * Scatterlists mapped with this function should be unmapped using
+ * pci_p2pdma_unmap_sg_attrs().
  *
  * Returns the number of SG entries mapped or 0 on error.
  */
@@ -834,6 +835,21 @@ int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 }
 EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
 
+/**
+ * pci_p2pdma_unmap_sg - unmap a PCI peer-to-peer scatterlist that was
+ *	mapped with pci_p2pdma_map_sg()
+ * @dev: device doing the DMA request
+ * @sg: scatter list to map
+ * @nents: number of elements returned by pci_p2pdma_map_sg()
+ * @dir: DMA direction
+ * @attrs: DMA attributes passed to dma_unmap_sg() (if called)
+ */
+void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, unsigned long attrs)
+{
+}
+EXPORT_SYMBOL_GPL(pci_p2pdma_unmap_sg_attrs);
+
 /**
  * pci_p2pdma_enable_store - parse a configfs/sysfs attribute store
  *		to enable p2pdma
diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h
index 7fd51954f93a..8318a97c9c61 100644
--- a/include/linux/pci-p2pdma.h
+++ b/include/linux/pci-p2pdma.h
@@ -32,6 +32,8 @@ void pci_p2pmem_free_sgl(struct pci_dev *pdev, struct scatterlist *sgl);
 void pci_p2pmem_publish(struct pci_dev *pdev, bool publish);
 int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 		int nents, enum dma_data_direction dir, unsigned long attrs);
+void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, unsigned long attrs);
 int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev,
 			    bool *use_p2pdma);
 ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev,
@@ -87,6 +89,11 @@ static inline int pci_p2pdma_map_sg_attrs(struct device *dev,
 {
 	return 0;
 }
+static inline void pci_p2pdma_unmap_sg_attrs(struct device *dev,
+		struct scatterlist *sg, int nents, enum dma_data_direction dir,
+		unsigned long attrs)
+{
+}
 static inline int pci_p2pdma_enable_store(const char *page,
 		struct pci_dev **p2p_dev, bool *use_p2pdma)
 {
@@ -118,4 +125,10 @@ static inline int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg,
 	return pci_p2pdma_map_sg_attrs(dev, sg, nents, dir, 0);
 }
 
+static inline void pci_p2pdma_unmap_sg(struct device *dev,
+		struct scatterlist *sg, int nents, enum dma_data_direction dir)
+{
+	pci_p2pdma_unmap_sg_attrs(dev, sg, nents, dir, 0);
+}
+
 #endif /* _LINUX_PCI_P2P_H */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (8 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:14   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray Logan Gunthorpe
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Factor out the bus-only mapping into its own static function.  No
functional changes. The original pci_p2pdma_map_sg_attrs() will be used to
decide whether this is an appropriate way to map.

Link: https://lore.kernel.org/r/20190730163545.4915-11-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 1eec7a5ec27e..771b45605853 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -792,23 +792,9 @@ void pci_p2pmem_publish(struct pci_dev *pdev, bool publish)
 }
 EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
 
-/**
- * pci_p2pdma_map_sg - map a PCI peer-to-peer scatterlist for DMA
- * @dev: device doing the DMA request
- * @sg: scatter list to map
- * @nents: elements in the scatterlist
- * @dir: DMA direction
- * @attrs: DMA attributes passed to dma_map_sg() (if called)
- *
- * Scatterlists mapped with this function should be unmapped using
- * pci_p2pdma_unmap_sg_attrs().
- *
- * Returns the number of SG entries mapped or 0 on error.
- */
-int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, unsigned long attrs)
+static int __pci_p2pdma_map_sg(struct pci_p2pdma_pagemap *p2p_pgmap,
+		struct device *dev, struct scatterlist *sg, int nents)
 {
-	struct pci_p2pdma_pagemap *p2p_pgmap;
 	struct scatterlist *s;
 	phys_addr_t paddr;
 	int i;
@@ -824,7 +810,6 @@ int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 		return 0;
 
 	for_each_sg(sg, s, nents, i) {
-		p2p_pgmap = to_p2p_pgmap(sg_page(s)->pgmap);
 		paddr = sg_phys(s);
 
 		s->dma_address = paddr - p2p_pgmap->bus_offset;
@@ -833,6 +818,28 @@ int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 
 	return nents;
 }
+
+/**
+ * pci_p2pdma_map_sg - map a PCI peer-to-peer scatterlist for DMA
+ * @dev: device doing the DMA request
+ * @sg: scatter list to map
+ * @nents: elements in the scatterlist
+ * @dir: DMA direction
+ * @attrs: DMA attributes passed to dma_map_sg() (if called)
+ *
+ * Scatterlists mapped with this function should be unmapped using
+ * pci_p2pdma_unmap_sg_attrs().
+ *
+ * Returns the number of SG entries mapped or 0 on error.
+ */
+int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, unsigned long attrs)
+{
+	struct pci_p2pdma_pagemap *p2p_pgmap =
+		to_p2p_pgmap(sg_page(sg)->pgmap);
+
+	return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
+}
 EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
 
 /**
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (9 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg() Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:14   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge Logan Gunthorpe
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

When upstream_bridge_distance() is called, store the method required to map
the DMA transfers in an xarray so it can be looked up efficiently on the
hot path in pci_p2pdma_map_sg().

Link: https://lore.kernel.org/r/20190730163545.4915-12-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 771b45605853..db8224ff6e80 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/iommu.h>
+#include <linux/xarray.h>
 
 enum pci_p2pdma_map_type {
 	PCI_P2PDMA_MAP_UNKNOWN = 0,
@@ -30,6 +31,7 @@ enum pci_p2pdma_map_type {
 struct pci_p2pdma {
 	struct gen_pool *pool;
 	bool p2pmem_published;
+	struct xarray map_types;
 };
 
 struct pci_p2pdma_pagemap {
@@ -105,6 +107,7 @@ static void pci_p2pdma_release(void *data)
 
 	gen_pool_destroy(p2pdma->pool);
 	sysfs_remove_group(&pdev->dev.kobj, &p2pmem_group);
+	xa_destroy(&p2pdma->map_types);
 }
 
 static int pci_p2pdma_setup(struct pci_dev *pdev)
@@ -116,6 +119,8 @@ static int pci_p2pdma_setup(struct pci_dev *pdev)
 	if (!p2p)
 		return -ENOMEM;
 
+	xa_init(&p2p->map_types);
+
 	p2p->pool = gen_pool_create(PAGE_SHIFT, dev_to_node(&pdev->dev));
 	if (!p2p->pool)
 		goto out;
@@ -409,6 +414,12 @@ __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 	return PCI_P2PDMA_MAP_BUS_ADDR;
 }
 
+static unsigned long map_types_idx(struct pci_dev *client)
+{
+	return (pci_domain_nr(client->bus) << 16) |
+		(client->bus->number << 8) | client->devfn;
+}
+
 /*
  * Find the distance through the nearest common upstream bridge between
  * two PCI devices.
@@ -459,9 +470,13 @@ upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
 
 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
 		if (!host_bridge_whitelist(provider, client))
-			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+			map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
 	}
 
+	if (provider->p2pdma)
+		xa_store(&provider->p2pdma->map_types, map_types_idx(client),
+			 xa_mk_value(map_type), GFP_KERNEL);
+
 	return map_type;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (10 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:15   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist Logan Gunthorpe
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Any requests that traverse the host bridge will need to be mapped into the
IOMMU, so call dma_map_sg() inside pci_p2pdma_map_sg() when appropriate.

Similarly, call dma_unmap_sg() inside pci_p2pdma_unmap_sg().

Link: https://lore.kernel.org/r/20190730163545.4915-13-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index db8224ff6e80..bca1ffc7075e 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -807,6 +807,16 @@ void pci_p2pmem_publish(struct pci_dev *pdev, bool publish)
 }
 EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
 
+static enum pci_p2pdma_map_type pci_p2pdma_map_type(struct pci_dev *provider,
+						    struct pci_dev *client)
+{
+	if (!provider->p2pdma)
+		return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+
+	return xa_to_value(xa_load(&provider->p2pdma->map_types,
+				   map_types_idx(client)));
+}
+
 static int __pci_p2pdma_map_sg(struct pci_p2pdma_pagemap *p2p_pgmap,
 		struct device *dev, struct scatterlist *sg, int nents)
 {
@@ -852,8 +862,22 @@ int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 {
 	struct pci_p2pdma_pagemap *p2p_pgmap =
 		to_p2p_pgmap(sg_page(sg)->pgmap);
+	struct pci_dev *client;
 
-	return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
+	if (WARN_ON_ONCE(!dev_is_pci(dev)))
+		return 0;
+
+	client = to_pci_dev(dev);
+
+	switch (pci_p2pdma_map_type(p2p_pgmap->provider, client)) {
+	case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
+		return dma_map_sg_attrs(dev, sg, nents, dir, attrs);
+	case PCI_P2PDMA_MAP_BUS_ADDR:
+		return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
+	default:
+		WARN_ON_ONCE(1);
+		return 0;
+	}
 }
 EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
 
@@ -869,6 +893,20 @@ EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
 void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
 		int nents, enum dma_data_direction dir, unsigned long attrs)
 {
+	struct pci_p2pdma_pagemap *p2p_pgmap =
+		to_p2p_pgmap(sg_page(sg)->pgmap);
+	enum pci_p2pdma_map_type map_type;
+	struct pci_dev *client;
+
+	if (WARN_ON_ONCE(!dev_is_pci(dev)))
+		return;
+
+	client = to_pci_dev(dev);
+
+	map_type = pci_p2pdma_map_type(p2p_pgmap->provider, client);
+
+	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE)
+		dma_unmap_sg_attrs(dev, sg, nents, dir, attrs);
 }
 EXPORT_SYMBOL_GPL(pci_p2pdma_unmap_sg_attrs);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (11 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:16   ` Christoph Hellwig
  2019-08-12 17:30 ` [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation Logan Gunthorpe
  2019-08-16 13:45 ` [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Bjorn Helgaas
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

Now that we map the requests correctly we can remove the iommu_present()
restriction.

Link: https://lore.kernel.org/r/20190730163545.4915-14-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index bca1ffc7075e..d8c824097d26 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -18,7 +18,6 @@
 #include <linux/percpu-refcount.h>
 #include <linux/random.h>
 #include <linux/seq_buf.h>
-#include <linux/iommu.h>
 #include <linux/xarray.h>
 
 enum pci_p2pdma_map_type {
@@ -328,9 +327,6 @@ static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b)
 	struct pci_host_bridge *host_a = pci_find_host_bridge(a->bus);
 	struct pci_host_bridge *host_b = pci_find_host_bridge(b->bus);
 
-	if (iommu_present(a->dev.bus) || iommu_present(b->dev.bus))
-		return false;
-
 	if (host_a == host_b)
 		return __host_bridge_whitelist(host_a, true);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (12 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist Logan Gunthorpe
@ 2019-08-12 17:30 ` Logan Gunthorpe
  2019-08-16  8:16   ` Christoph Hellwig
  2019-08-16 13:45 ` [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Bjorn Helgaas
  14 siblings, 1 reply; 30+ messages in thread
From: Logan Gunthorpe @ 2019-08-12 17:30 UTC (permalink / raw)
  To: linux-kernel, linux-pci, linux-nvme, linux-rdma
  Cc: Bjorn Helgaas, Christoph Hellwig, Christian Koenig,
	Jason Gunthorpe, Sagi Grimberg, Keith Busch, Jens Axboe,
	Dan Williams, Eric Pilmore, Stephen Bates, Logan Gunthorpe

The comment describing pci_p2pdma_distance_many() still referred to
the devices being behind the same root port. This no longer applies
so reword the documentation.

Link: https://lore.kernel.org/r/20190730163545.4915-15-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/p2pdma.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index d8c824097d26..0608aae72ccc 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -517,15 +517,14 @@ upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
  * @num_clients: number of clients in the array
  * @verbose: if true, print warnings for devices when we return -1
  *
- * Returns -1 if any of the clients are not compatible (behind the same
- * root port as the provider), otherwise returns a positive number where
- * a lower number is the preferable choice. (If there's one client
- * that's the same as the provider it will return 0, which is best choice).
+ * Returns -1 if any of the clients are not compatible, otherwise returns a
+ * positive number where a lower number is the preferable choice. (If there's
+ * one client that's the same as the provider it will return 0, which is best
+ * choice).
  *
- * For now, "compatible" means the provider and the clients are all behind
- * the same PCI root port. This cuts out cases that may work but is safest
- * for the user. Future work can expand this to white-list root complexes that
- * can safely forward between each ports.
+ * "compatible" means the provider and the clients are either all behind
+ * the same PCI root port or the host bridges connected to each of the devices
+ * are listed in the 'pci_p2pdma_whitelist'.
  */
 int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients,
 			     int num_clients, bool verbose)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure
  2019-08-12 17:30 ` [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure Logan Gunthorpe
@ 2019-08-16  8:06   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:06 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
  2019-08-12 17:30 ` [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct Logan Gunthorpe
@ 2019-08-16  8:06   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:06 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:36AM -0600, Logan Gunthorpe wrote:
> The provider will be needed to figure out how to map a device.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-3-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance()
  2019-08-12 17:30 ` [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance() Logan Gunthorpe
@ 2019-08-16  8:08   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:08 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:37AM -0600, Logan Gunthorpe wrote:
> Add constant flags to indicate how two devices will be mapped or if they
> are unsupported. upstream_bridge_distance() will now return the
> mapping type and the distance in a passed-by-reference argument.
> 
> This helps annotate the code better, but the main reason is so we can use
> the information to store the required mapping method in an xarray.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-4-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Reviewed-by: Christian König <christian.koenig@amd.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance()
  2019-08-12 17:30 ` [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance() Logan Gunthorpe
@ 2019-08-16  8:08   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:08 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:38AM -0600, Logan Gunthorpe wrote:
> This is a prep patch to create a second level helper. There are no
> functional changes.
> 
> The root complex whitelist code will be moved into this function in a
> subsequent patch.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-5-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Reviewed-by: Christian König <christian.koenig@amd.com>

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS
  2019-08-12 17:30 ` [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS Logan Gunthorpe
@ 2019-08-16  8:09   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:09 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:39AM -0600, Logan Gunthorpe wrote:
> When a P2PDMA transfer is rejected due to ACS being set, we can also check
> the whitelist and allow the transactions.
> 
> Do this by pushing the whitelist check into the upstream_bridge_distance()
> function.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-6-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Reviewed-by: Christian König <christian.koenig@amd.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist()
  2019-08-12 17:30 ` [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist() Logan Gunthorpe
@ 2019-08-16  8:09   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:09 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:40AM -0600, Logan Gunthorpe wrote:
> Push both PCI devices into the whitelist checking function seeing some
> hardware will require us ensuring they are on the same host bridge.
> 
> At the same time we rename root_complex_whitelist() to
> host_bridge_whitelist() to match the terminology used in the code.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-7-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges
  2019-08-12 17:30 ` [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges Logan Gunthorpe
@ 2019-08-16  8:11   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:11 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
  2019-08-12 17:30 ` [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg() Logan Gunthorpe
@ 2019-08-16  8:12   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:12 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:42AM -0600, Logan Gunthorpe wrote:
> This is to match the dma_map_sg() API which this function will have to call
> in an future patch.
> 
> Add a pci_p2pdma_map_sg_attrs() function and helper to call it with no
> attributes just like the dma_map_sg() function.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-9-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
  2019-08-12 17:30 ` [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg() Logan Gunthorpe
@ 2019-08-16  8:13   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:13 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:43AM -0600, Logan Gunthorpe wrote:
> Add pci_p2pdma_unmap_sg() to the two places that call pci_p2pdma_map_sg().
> 
> This is a prep patch to introduce correct mappings for p2pdma transactions
> that go through the root complex.

I personally wouldn't split it from actually adding useful functionality,
but that aside this looks ok:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
  2019-08-12 17:30 ` [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg() Logan Gunthorpe
@ 2019-08-16  8:14   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:14 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:44AM -0600, Logan Gunthorpe wrote:
> Factor out the bus-only mapping into its own static function.  No
> functional changes. The original pci_p2pdma_map_sg_attrs() will be used to
> decide whether this is an appropriate way to map.
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-11-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray
  2019-08-12 17:30 ` [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray Logan Gunthorpe
@ 2019-08-16  8:14   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:14 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:45AM -0600, Logan Gunthorpe wrote:
> When upstream_bridge_distance() is called, store the method required to map
> the DMA transfers in an xarray so it can be looked up efficiently on the
> hot path in pci_p2pdma_map_sg().
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-12-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge
  2019-08-12 17:30 ` [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge Logan Gunthorpe
@ 2019-08-16  8:15   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:15 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:46AM -0600, Logan Gunthorpe wrote:
> Any requests that traverse the host bridge will need to be mapped into the
> IOMMU, so call dma_map_sg() inside pci_p2pdma_map_sg() when appropriate.
> 
> Similarly, call dma_unmap_sg() inside pci_p2pdma_unmap_sg().
> 
> Link: https://lore.kernel.org/r/20190730163545.4915-13-logang@deltatee.com
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist
  2019-08-12 17:30 ` [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist Logan Gunthorpe
@ 2019-08-16  8:16   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:16 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:47AM -0600, Logan Gunthorpe wrote:
> Now that we map the requests correctly we can remove the iommu_present()
> restriction.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation
  2019-08-12 17:30 ` [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation Logan Gunthorpe
@ 2019-08-16  8:16   ` Christoph Hellwig
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2019-08-16  8:16 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma, Bjorn Helgaas,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:48AM -0600, Logan Gunthorpe wrote:
> The comment describing pci_p2pdma_distance_many() still referred to
> the devices being behind the same root port. This no longer applies
> so reword the documentation.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge
  2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
                   ` (13 preceding siblings ...)
  2019-08-12 17:30 ` [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation Logan Gunthorpe
@ 2019-08-16 13:45 ` Bjorn Helgaas
  14 siblings, 0 replies; 30+ messages in thread
From: Bjorn Helgaas @ 2019-08-16 13:45 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, linux-nvme, linux-rdma,
	Christoph Hellwig, Christian Koenig, Jason Gunthorpe,
	Sagi Grimberg, Keith Busch, Jens Axboe, Dan Williams,
	Eric Pilmore, Stephen Bates

On Mon, Aug 12, 2019 at 11:30:34AM -0600, Logan Gunthorpe wrote:
> Bjorn, this is v3 of the patchset. Christophs suggestion's required a
> bit more rework than could be expressed in incremental patches so
> I've resent the whole thing. I started with your p2pdma branch though
> so it should have all the changes you already made. I've included a
> range-diff from your p2pdma branch below.

I added Christoph's reviewed-by and replaced my pci/p2pdma branch with
this series, thanks!  This is all headed for v5.4.

> A git branch is available here:
> 
> https://github.com/sbates130272/linux-p2pmem/ p2pdma_rc_map_v3
> 
> --
> 
> Changes in v3:
>  * Rebase on v5.3-rc3 (No changes)
>  * Bjorn's edits for a bunch of the comments and commit messages
>  * Rework upstream_bridge_distance() changes to split the distance,
>    mapping type and ACS flag into separate pass-by-reference parameters
>    (per Christoph's suggestion)
>  * Jonathan Derrick (Intel) reported the domains can be 32-bits on
>    some machines and thus the map_type_index() needed to be an unsigned long
>    to accomadate this.
> 
> Changes in v2:
>  * Rebase on v5.3-rc2 (No changes)
>  * Re-introduce the private pagemap structure and move the p2p-specific
>    elements out of the commond dev_pagemap (per Christoph)
>  * Use flags instead of bool in the whitelist (per Jason)
>  * Only store the mapping type in the xarray (instead of the distance
>    with flags) such that a function can return the mapping method
>    with a switch statement to decide how to map. (per Christoph)
>  * Drop find_parent_pci_dev() on the fast path and rely on the fact
>    that the struct device passed to the mapping functions *must* be
>    a PCI device and convert it directly. (per suggestions from
>    Christoph and Jason)
>  * Collected Christian's Reviewed-by's
> 
> --
> 
> As discussed on the list previously, in order to fully support the
> whitelist Christian added with the IOMMU, we must ensure that we
> map any buffer going through the IOMMU with an aprropriate dma_map
> call. This patchset accomplishes this by cleaning up the output of
> upstream_bridge_distance() to better indicate the mapping requirements,
> caching these requirements in an xarray, then looking them up at map
> time and applying the appropriate mapping method.
> 
> After this patchset, it's possible to use the NVMe-of P2P support to
> transfer between devices without a switch on the whitelisted root
> complexes. A couple Intel device I have tested this on have also
> been added to the white list.
> 
> Most of the changes are contained within the p2pdma.c, but there are
> a few minor touches to other subsystems, mostly to add support
> to call an unmap function.
> 
> --
> 
> Logan Gunthorpe (14):
>   PCI/P2PDMA: Introduce private pagemap structure
>   PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
>   PCI/P2PDMA: Add constants for map type results to
>     upstream_bridge_distance()
>   PCI/P2PDMA: Factor out __upstream_bridge_distance()
>   PCI/P2PDMA: Apply host bridge whitelist for ACS
>   PCI/P2PDMA: Factor out host_bridge_whitelist()
>   PCI/P2PDMA: Whitelist some Intel host bridges
>   PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
>   PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
>   PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
>   PCI/P2PDMA: Store mapping method in an xarray
>   PCI/P2PDMA: dma_map() requests that traverse the host bridge
>   PCI/P2PDMA: Allow IOMMU for host bridge whitelist
>   PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation
> 
>  drivers/infiniband/core/rw.c |   6 +-
>  drivers/nvme/host/pci.c      |  10 +-
>  drivers/pci/p2pdma.c         | 374 +++++++++++++++++++++++++----------
>  include/linux/memremap.h     |   1 -
>  include/linux/pci-p2pdma.h   |  28 ++-
>  5 files changed, 300 insertions(+), 119 deletions(-)
> 
> --
> 
> $ git range-diff bjorn/master..bjorn/pci/p2pdma master..p2pdma_rc_map_v3
> 
>  1:  5173c82b3571 =  1:  78cc3a5be538 PCI/P2PDMA: Introduce private pagemap structure
>  2:  f33fd6b8da93 =  2:  9fb388dff957 PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct
>  3:  767f47b59702 <  -:  ------------ PCI/P2PDMA: Add constants for not-supported result upstream_bridge_distance()
>  -:  ------------ >  3:  ed105432f644 PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance()
>  4:  93ed41974d69 !  4:  590aaea31997 PCI/P2PDMA: Factor out __upstream_bridge_distance()
>     @@ -17,8 +17,8 @@
>       --- a/drivers/pci/p2pdma.c
>       +++ b/drivers/pci/p2pdma.c
>      @@
>     - 	P2PDMA_NOT_SUPPORTED		= 0x08000000,
>     - };
>     + 	return false;
>     + }
> 
>      -/*
>      - * Find the distance through the nearest common upstream bridge between
>     @@ -44,31 +44,29 @@
>      - * port of the switch, to the common upstream port, back up to the second
>      - * downstream port and then to Device B.
>      - *
>     -- * Any two devices that cannot communicate using p2pdma will return the
>     -- * distance with the flag P2PDMA_NOT_SUPPORTED.
>     +- * Any two devices that cannot communicate using p2pdma will return
>     +- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
>      - *
>      - * Any two devices that have a data path that goes through the host bridge
>      - * will consult a whitelist. If the host bridges are on the whitelist,
>     -- * the distance will be returned with the flag P2PDMA_THRU_HOST_BRIDGE set.
>     -- * If either bridge is not on the whitelist, the flag P2PDMA_NOT_SUPPORTED will
>     -- * be set.
>     +- * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
>     +- *
>     +- * If either bridge is not on the whitelist this function returns
>     +- * PCI_P2PDMA_MAP_NOT_SUPPORTED.
>      - *
>     -- * If a bridge which has any ACS redirection bits set is in the path
>     -- * this function will flag the result with P2PDMA_ACS_FORCES_UPSTREAM.
>     -- * In this case, a list of all infringing bridge addresses will be
>     -- * populated in acs_list (assuming it's non-null) for printk purposes.
>     +- * If a bridge which has any ACS redirection bits set is in the path,
>     +- * acs_redirects will be set to true. In this case, a list of all infringing
>     +- * bridge addresses will be populated in acs_list (assuming it's non-null)
>     +- * for printk purposes.
>      - */
>     --static int upstream_bridge_distance(struct pci_dev *provider,
>     --				    struct pci_dev *client,
>     --				    struct seq_buf *acs_list)
>     -+static int __upstream_bridge_distance(struct pci_dev *provider,
>     -+				      struct pci_dev *client,
>     -+				      struct seq_buf *acs_list)
>     + static enum pci_p2pdma_map_type
>     +-upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
>     ++__upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
>     + 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
>       {
>       	struct pci_dev *a = provider, *b = client, *bb;
>     - 	int dist_a = 0;
>      @@
>     - 	return dist_a + dist_b;
>     + 	return PCI_P2PDMA_MAP_BUS_ADDR;
>       }
> 
>      +/*
>     @@ -95,27 +93,29 @@
>      + * port of the switch, to the common upstream port, back up to the second
>      + * downstream port and then to Device B.
>      + *
>     -+ * Any two devices that cannot communicate using p2pdma will return the
>     -+ * distance with the flag P2PDMA_NOT_SUPPORTED.
>     ++ * Any two devices that cannot communicate using p2pdma will return
>     ++ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
>      + *
>      + * Any two devices that have a data path that goes through the host bridge
>      + * will consult a whitelist. If the host bridges are on the whitelist,
>     -+ * the distance will be returned with the flag P2PDMA_THRU_HOST_BRIDGE set.
>     -+ * If either bridge is not on the whitelist, the flag P2PDMA_NOT_SUPPORTED will
>     -+ * be set.
>     ++ * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
>      + *
>     -+ * If a bridge which has any ACS redirection bits set is in the path
>     -+ * this function will flag the result with P2PDMA_ACS_FORCES_UPSTREAM.
>     -+ * In this case, a list of all infringing bridge addresses will be
>     -+ * populated in acs_list (assuming it's non-null) for printk purposes.
>     ++ * If either bridge is not on the whitelist this function returns
>     ++ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
>     ++ *
>     ++ * If a bridge which has any ACS redirection bits set is in the path,
>     ++ * acs_redirects will be set to true. In this case, a list of all infringing
>     ++ * bridge addresses will be populated in acs_list (assuming it's non-null)
>     ++ * for printk purposes.
>      + */
>     -+static int upstream_bridge_distance(struct pci_dev *provider,
>     -+				    struct pci_dev *client,
>     -+				    struct seq_buf *acs_list)
>     ++static enum pci_p2pdma_map_type
>     ++upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
>     ++		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
>      +{
>     -+	return __upstream_bridge_distance(provider, client, acs_list);
>     ++	return __upstream_bridge_distance(provider, client, dist,
>     ++					  acs_redirects, acs_list);
>      +}
>      +
>     - static int upstream_bridge_distance_warn(struct pci_dev *provider,
>     - 					 struct pci_dev *client)
>     - {
>     + static enum pci_p2pdma_map_type
>     + upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
>     + 			      int *dist)
>  5:  f975e51cf5df <  -:  ------------ PCI/P2PDMA: Apply host bridge whitelist for ACS
>  -:  ------------ >  5:  336e968f075b PCI/P2PDMA: Apply host bridge whitelist for ACS
>  6:  59b6507ac07c !  6:  3f565ce6e1d4 PCI/P2PDMA: Factor out host_bridge_whitelist()
>     @@ -58,15 +58,16 @@
>      +	return false;
>      +}
>      +
>     - enum {
>     - 	/*
>     - 	 * These arbitrary offset are or'd onto the upstream distance
>     + static enum pci_p2pdma_map_type
>     + __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
>     + 		int *dist, bool *acs_redirects, struct seq_buf *acs_list)
>      @@
>     - 	if (!(dist & P2PDMA_THRU_HOST_BRIDGE))
>     - 		return dist;
>     + 					      acs_redirects, acs_list);
> 
>     --	if (root_complex_whitelist(provider) && root_complex_whitelist(client))
>     -+	if (host_bridge_whitelist(provider, client))
>     - 		return dist;
>     + 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
>     +-		if (!root_complex_whitelist(provider) ||
>     +-		    !root_complex_whitelist(client))
>     ++		if (!host_bridge_whitelist(provider, client))
>     + 			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
>     + 	}
> 
>     - 	return dist | P2PDMA_NOT_SUPPORTED;
>  7:  5ecec567445f =  7:  7b8701dd45e0 PCI/P2PDMA: Whitelist some Intel host bridges
>  8:  68a37758d5cf =  8:  b52771ae7f95 PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg()
>  9:  4b821298d4f7 =  9:  88a554eb39c9 PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()
> 10:  3f2dac803737 = 10:  604260bd186a PCI/P2PDMA: Factor out __pci_p2pdma_map_sg()
> 11:  fc402d621534 ! 11:  b55fc423a41a PCI/P2PDMA: Store mapping method in an xarray
>     @@ -18,14 +18,10 @@
>       #include <linux/seq_buf.h>
>       #include <linux/iommu.h>
>      +#include <linux/xarray.h>
>     -+
>     -+enum pci_p2pdma_map_type {
>     -+	PCI_P2PDMA_MAP_UNKNOWN = 0,
>     -+	PCI_P2PDMA_MAP_NOT_SUPPORTED,
>     -+	PCI_P2PDMA_MAP_BUS_ADDR,
>     -+	PCI_P2PDMA_MAP_THRU_IOMMU,
>     -+};
> 
>     + enum pci_p2pdma_map_type {
>     + 	PCI_P2PDMA_MAP_UNKNOWN = 0,
>     +@@
>       struct pci_p2pdma {
>       	struct gen_pool *pool;
>       	bool p2pmem_published;
>     @@ -51,10 +47,10 @@
>       	if (!p2p->pool)
>       		goto out;
>      @@
>     - 	return dist_a + dist_b;
>     + 	return PCI_P2PDMA_MAP_BUS_ADDR;
>       }
> 
>     -+static int map_types_idx(struct pci_dev *client)
>     ++static unsigned long map_types_idx(struct pci_dev *client)
>      +{
>      +	return (pci_domain_nr(client->bus) << 16) |
>      +		(client->bus->number << 8) | client->devfn;
>     @@ -64,37 +60,17 @@
>        * Find the distance through the nearest common upstream bridge between
>        * two PCI devices.
>      @@
>     - 				    struct pci_dev *client,
>     - 				    struct seq_buf *acs_list)
>     - {
>     -+	enum pci_p2pdma_map_type map_type;
>     - 	int dist;
>     -
>     - 	dist = __upstream_bridge_distance(provider, client, acs_list);
> 
>     --	if (!(dist & P2PDMA_THRU_HOST_BRIDGE))
>     --		return dist;
>     -+	if (!(dist & P2PDMA_THRU_HOST_BRIDGE)) {
>     -+		map_type = PCI_P2PDMA_MAP_BUS_ADDR;
>     -+		goto store_map_type_and_return;
>     -+	}
>     -+
>     -+	if (host_bridge_whitelist(provider, client)) {
>     -+		map_type = PCI_P2PDMA_MAP_THRU_IOMMU;
>     -+	} else {
>     -+		dist |= P2PDMA_NOT_SUPPORTED;
>     -+		map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
>     -+	}
>     + 	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
>     + 		if (!host_bridge_whitelist(provider, client))
>     +-			return PCI_P2PDMA_MAP_NOT_SUPPORTED;
>     ++			map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
>     + 	}
> 
>     --	if (host_bridge_whitelist(provider, client))
>     --		return dist;
>     -+store_map_type_and_return:
>      +	if (provider->p2pdma)
>      +		xa_store(&provider->p2pdma->map_types, map_types_idx(client),
>      +			 xa_mk_value(map_type), GFP_KERNEL);
>     -
>     --	return dist | P2PDMA_NOT_SUPPORTED;
>     -+	return dist;
>     ++
>     + 	return map_type;
>       }
> 
>     - static int upstream_bridge_distance_warn(struct pci_dev *provider,
> 12:  c51eb851e9da ! 12:  94e4c8633459 PCI/P2PDMA: dma_map() requests that traverse the host bridge
>     @@ -44,7 +44,7 @@
>      +	client = to_pci_dev(dev);
>      +
>      +	switch (pci_p2pdma_map_type(p2p_pgmap->provider, client)) {
>     -+	case PCI_P2PDMA_MAP_THRU_IOMMU:
>     ++	case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
>      +		return dma_map_sg_attrs(dev, sg, nents, dir, attrs);
>      +	case PCI_P2PDMA_MAP_BUS_ADDR:
>      +		return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
>     @@ -71,7 +71,7 @@
>      +
>      +	map_type = pci_p2pdma_map_type(p2p_pgmap->provider, client);
>      +
>     -+	if (map_type == PCI_P2PDMA_MAP_THRU_IOMMU)
>     ++	if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE)
>      +		dma_unmap_sg_attrs(dev, sg, nents, dir, attrs);
>       }
>       EXPORT_SYMBOL_GPL(pci_p2pdma_unmap_sg_attrs);
> 13:  0a3468f51621 = 13:  f067cdb5b963 PCI/P2PDMA: Allow IOMMU for host bridge whitelist
> 14:  20c0cf9f4c9c = 14:  87c84b001dfa PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation
> 
> --
> 2.20.1

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2019-08-16 13:45 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-12 17:30 [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Logan Gunthorpe
2019-08-12 17:30 ` [PATCH v3 01/14] PCI/P2PDMA: Introduce private pagemap structure Logan Gunthorpe
2019-08-16  8:06   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 02/14] PCI/P2PDMA: Add provider's pci_dev to pci_p2pdma_pagemap struct Logan Gunthorpe
2019-08-16  8:06   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 03/14] PCI/P2PDMA: Add constants for map type results to upstream_bridge_distance() Logan Gunthorpe
2019-08-16  8:08   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 04/14] PCI/P2PDMA: Factor out __upstream_bridge_distance() Logan Gunthorpe
2019-08-16  8:08   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 05/14] PCI/P2PDMA: Apply host bridge whitelist for ACS Logan Gunthorpe
2019-08-16  8:09   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 06/14] PCI/P2PDMA: Factor out host_bridge_whitelist() Logan Gunthorpe
2019-08-16  8:09   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 07/14] PCI/P2PDMA: Whitelist some Intel host bridges Logan Gunthorpe
2019-08-16  8:11   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 08/14] PCI/P2PDMA: Add attrs argument to pci_p2pdma_map_sg() Logan Gunthorpe
2019-08-16  8:12   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 09/14] PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg() Logan Gunthorpe
2019-08-16  8:13   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 10/14] PCI/P2PDMA: Factor out __pci_p2pdma_map_sg() Logan Gunthorpe
2019-08-16  8:14   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 11/14] PCI/P2PDMA: Store mapping method in an xarray Logan Gunthorpe
2019-08-16  8:14   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 12/14] PCI/P2PDMA: dma_map() requests that traverse the host bridge Logan Gunthorpe
2019-08-16  8:15   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 13/14] PCI/P2PDMA: Allow IOMMU for host bridge whitelist Logan Gunthorpe
2019-08-16  8:16   ` Christoph Hellwig
2019-08-12 17:30 ` [PATCH v3 14/14] PCI/P2PDMA: Update pci_p2pdma_distance_many() documentation Logan Gunthorpe
2019-08-16  8:16   ` Christoph Hellwig
2019-08-16 13:45 ` [PATCH v3 00/14] PCI/P2PDMA: Support transactions that hit the host bridge Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).