mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Leon Romanovsky <leon@kernel.org>
Cc: "Bjorn Helgaas" <bhelgaas@google.com>,
	"Logan Gunthorpe" <logang@deltatee.com>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Joerg Roedel (AMD)" <joro@8bytes.org>,
	"Will Deacon" <will@kernel.org>,
	"Robin Murphy" <robin.murphy@arm.com>,
	"Christian König" <christian.koenig@amd.com>,
	"Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-doc@vger.kernel.org, iommu@lists.linux.dev,
	"Tushar Dave" <tdave@nvidia.com>,
	linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
	linaro-mm-sig@lists.linaro.org, linux-rdma@vger.kernel.org,
	kvm@vger.kernel.org, "Chaitanya Kulkarni" <kch@nvidia.com>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Jens Axboe" <axboe@kernel.dk>,
	"Alex Williamson" <alex@shazbot.org>,
	"Ankit Agrawal" <ankita@nvidia.com>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Sumit Semwal" <sumit.semwal@linaro.org>
Subject: Re: [PATCH v9 04/18] PCI/P2PDMA: Evaluate ACS controls at the path divergence
Date: Tue, 6 Oct 2026 16:08:48 -0500	[thread overview]
Message-ID: <20261006210848.GA712422@bhelgaas> (raw)
In-Reply-To: <20261001-fix-p2p-acs-v4-0-v9-4-1a8e0f50ddd9@nvidia.com>

On Thu, Oct 01, 2026 at 02:55:12PM +0300, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@nvidia.com>
> 
> ACS redirect controls choose between peer and upstream routes only at the
> path divergence. Applying them below that point rejects valid nested
> topologies because traffic already has only an upstream route.

I guess the point here is that prior to this patch,
calc_map_type_and_dist() returned PCI_P2PDMA_MAP_NOT_SUPPORTED in a
case where it didn't need to?  Can you include an example to make this
concrete?

It looks like in v7.3, we only return PCI_P2PDMA_MAP_NOT_SUPPORTED if
a TLP has to go through a host bridge.  Do we mistakenly assume that
if a bridge has PCI_ACS_RR set, a Request must go all the way to the
host bridge, even if a bridge closer to the root does not have
PCI_ACS_RR set?

> Evaluate Request controls on the client-side divergence port and Completion
> Redirect on the provider-side port and reject an unreadable ACS Control
> register.
> 
> Fixes: 52916982af48 ("PCI/P2PDMA: Support peer-to-peer memory")
> Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
> Tested-by: Tushar Dave <tdave@nvidia.com>
> Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
> ---
>  drivers/pci/p2pdma.c       | 101 +++++++++++++++++++++++++++++----------------
>  include/linux/pci-p2pdma.h |   8 ++--
>  2 files changed, 70 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
> index 12612b82d80d..550e6c7346ef 100644
> --- a/drivers/pci/p2pdma.c
> +++ b/drivers/pci/p2pdma.c
> @@ -493,6 +493,7 @@ static struct pci_dev *find_parent_pci_dev(struct device *dev)
>  }
>  
>  enum pci_acs_p2pdma_state {
> +	PCI_ACS_P2PDMA_NOT_SUPPORTED,
>  	PCI_ACS_P2PDMA_DIRECT,
>  	PCI_ACS_P2PDMA_REDIRECT,
>  };
> @@ -730,13 +731,13 @@ static unsigned long map_types_idx(struct pci_dev *client)
>   * then to Device B. The mapping type returned depends on the ACS
>   * redirection setting of the ports along the path.
>   *
> - * The client initiates Requests to provider memory. Check Request Redirect
> - * on the client path and Completion Redirect for read Completions on the
> - * provider path.
> + * The client initiates Requests to provider memory. At the path divergence,
> + * check Request Redirect and Egress Control on the client-side port, and
> + * Completion Redirect for read Completions on the provider-side port.
>   *
> - * If ACS redirect is set on any port in the path, traffic between the
> - * devices will go through the host bridge, so return
> - * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; otherwise return
> + * If ACS redirects traffic at either divergence port, return
> + * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE. If the ACS Control register cannot be
> + * read, return PCI_P2PDMA_MAP_NOT_SUPPORTED. Otherwise, return
>   * PCI_P2PDMA_MAP_BUS_ADDR.
>   *
>   * Any two devices that have a data path that goes through the host bridge
> @@ -750,10 +751,13 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
>  		int *dist, bool verbose)
>  {
>  	enum pci_p2pdma_map_type map_type = PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
> +	enum pci_acs_p2pdma_state state = PCI_ACS_P2PDMA_NOT_SUPPORTED;
>  	struct pci_dev *a = provider, *b = client, *bb;
> +	struct pci_dev *a_child = NULL, *b_child = NULL;
> +	struct pci_dev *acs_unreadable = NULL;
>  	struct pci_p2pdma *p2pdma;
>  	struct seq_buf acs_list;
> -	int acs_cnt = 0;
> +	int acs_redirect_cnt = 0;
>  	int dist_a = 0;
>  	int dist_b = 0;
>  	char buf[128];
> @@ -768,51 +772,67 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
>  	 */
>  	while (a) {
>  		dist_b = 0;
> -
> -		if (!pci_acs_p2pdma_ctrl(a, &ctrl) ||
> -		    pci_acs_p2pdma_completion(ctrl) ==
> -			    PCI_ACS_P2PDMA_REDIRECT) {
> -			seq_buf_print_bus_devfn(&acs_list, a);
> -			acs_cnt++;
> -		}
> -
> +		b_child = NULL;
>  		bb = b;
>  
>  		while (bb) {
>  			if (a == bb)
> -				goto check_b_path_acs;
> +				goto check_paths_acs;
>  
> +			b_child = bb;
>  			bb = pci_upstream_bridge(bb);
>  			dist_b++;
>  		}
>  
> +		a_child = a;
>  		a = pci_upstream_bridge(a);
>  		dist_a++;
>  	}
>  
> +	/*
> +	 * The paths share no upstream bridge, so there is no direct path for
> +	 * ACS to gate: PCI_P2PDMA_MAP_BUS_ADDR is not reachable here and the
> +	 * request can only get to the peer through the host bridge.
> +	 */
>  	*dist = dist_a + dist_b;
>  	goto map_through_host_bridge;
>  
> -check_b_path_acs:
> -	bb = b;
> -
> -	while (bb) {
> -		if (a == bb)
> -			break;
> +check_paths_acs:
> +	*dist = dist_a + dist_b;
>  
> -		if (!pci_acs_p2pdma_ctrl(bb, &ctrl) ||
> -		    pci_acs_p2pdma_request(ctrl) ==
> -			    PCI_ACS_P2PDMA_REDIRECT) {
> -			seq_buf_print_bus_devfn(&acs_list, bb);
> -			acs_cnt++;
> +	/*
> +	 * ACS P2P routing controls apply where a TLP can route toward the peer
> +	 * or upstream. Below that divergence, its only route toward the other
> +	 * branch is upstream, so redirect controls do not affect the path.
> +	 */
> +	if (a_child && b_child) {
> +		if (pci_acs_p2pdma_ctrl(a_child, &ctrl))
> +			state = pci_acs_p2pdma_completion(ctrl);
> +		if (state != PCI_ACS_P2PDMA_DIRECT) {
> +			seq_buf_print_bus_devfn(&acs_list, a_child);
> +			if (state == PCI_ACS_P2PDMA_REDIRECT)
> +				acs_redirect_cnt++;
> +			else if (!acs_unreadable)
> +				acs_unreadable = a_child;
>  		}
>  
> -		bb = pci_upstream_bridge(bb);
> +		state = PCI_ACS_P2PDMA_NOT_SUPPORTED;
> +		if (pci_acs_p2pdma_ctrl(b_child, &ctrl))
> +			state = pci_acs_p2pdma_request(ctrl);
> +		if (state != PCI_ACS_P2PDMA_DIRECT) {
> +			seq_buf_print_bus_devfn(&acs_list, b_child);
> +			if (state == PCI_ACS_P2PDMA_REDIRECT)
> +				acs_redirect_cnt++;
> +			else if (!acs_unreadable)
> +				acs_unreadable = b_child;
> +		}
>  	}
>  
> -	*dist = dist_a + dist_b;
> -
> -	if (!acs_cnt) {
> +	/*
> +	 * Below a shared upstream bridge, a path whose divergence ports do not
> +	 * redirect routes the request directly.
> +	 */
> +	if (!acs_unreadable && !acs_redirect_cnt) {
>  		map_type = PCI_P2PDMA_MAP_BUS_ADDR;
>  		goto done;
>  	}
> @@ -821,10 +841,21 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
>  		/* Drop the final semicolon; the list is not empty here. */
>  		if (!seq_buf_has_overflowed(&acs_list))
>  			acs_list.buffer[acs_list.len - 1] = '\0';
> -		pci_warn(client, "ACS redirect is set between the client and provider (%s)\n",
> -			 pci_name(provider));
> -		pci_warn(client, "to disable ACS redirect for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
> -			 seq_buf_str(&acs_list));
> +		if (acs_unreadable)
> +			pci_warn(client, "ACS Control is unreadable for provider %s at %s\n",
> +				 pci_name(provider), pci_name(acs_unreadable));
> +		else {
> +			pci_warn(client, "ACS redirect is set between the client and provider (%s)\n",
> +				 pci_name(provider));
> +			pci_warn(client, "to disable ACS controls for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
> +				 seq_buf_str(&acs_list));
> +		}
> +	}
> +
> +	/* An unreadable control does not establish an upstream redirect. */
> +	if (acs_unreadable) {
> +		map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
> +		goto done;
>  	}
>  
>  map_through_host_bridge:
> diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h
> index 873de20a2247..dd17501ba1b6 100644
> --- a/include/linux/pci-p2pdma.h
> +++ b/include/linux/pci-p2pdma.h
> @@ -42,10 +42,10 @@ enum pci_p2pdma_map_type {
>  	PCI_P2PDMA_MAP_NONE,
>  
>  	/*
> -	 * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will
> -	 * traverse the host bridge and the host bridge is not in the
> -	 * allowlist. DMA Mapping routines should return an error when
> -	 * this is returned.
> +	 * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates no safe mapping is available,
> +	 * for example because ACS blocks the direct path or the required host
> +	 * bridge is not in the allowlist. DMA Mapping routines should return an
> +	 * error when this is returned.
>  	 */
>  	PCI_P2PDMA_MAP_NOT_SUPPORTED,
>  
> 
> -- 
> 2.55.0
> 

  reply	other threads:[~2026-10-06 21:08 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 11:55 [PATCH v9 00/18] PCI/P2PDMA: Route peer-to-peer DMA by TLP class Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 01/18] PCI/P2PDMA: Document the TLP attribute assumptions Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 02/18] PCI/P2PDMA: Derive routing from directional ACS controls Leon Romanovsky
2026-10-06 20:49   ` Bjorn Helgaas
2026-10-01 11:55 ` [PATCH v9 03/18] PCI: Reject unreadable ACS controls in isolation checks Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 04/18] PCI/P2PDMA: Evaluate ACS controls at the path divergence Leon Romanovsky
2026-10-06 21:08   ` Bjorn Helgaas [this message]
2026-10-01 11:55 ` [PATCH v9 05/18] PCI/P2PDMA: Document directional ACS routing Leon Romanovsky
2026-10-06 21:32   ` Bjorn Helgaas
2026-10-01 11:55 ` [PATCH v9 06/18] PCI/P2PDMA: Collect the path's ACS controls before deciding Leon Romanovsky
2026-10-06 21:48   ` Bjorn Helgaas
2026-10-01 11:55 ` [PATCH v9 07/18] PCI/P2PDMA: Answer routing per TLP class Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 08/18] PCI/P2PDMA: Route Relaxed Ordering Completions directly Leon Romanovsky
2026-10-06 22:21   ` Bjorn Helgaas
2026-10-01 11:55 ` [PATCH v9 09/18] PCI/P2PDMA: Reject Translated Requests blocked by Translation Blocking Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 10/18] PCI/P2PDMA: Route Translated Requests under Direct Translated P2P Leon Romanovsky
2026-10-06 22:28   ` Bjorn Helgaas
2026-10-01 11:55 ` [PATCH v9 11/18] PCI/P2PDMA: Log detailed ACS routing diagnostics Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 12/18] PCI/P2PDMA: Add KUnit tests for the ACS routing decisions Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 13/18] PCI/P2PDMA: Test the ACS P2P routing walk Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 14/18] PCI: Add KUnit coverage for ACS isolation checks Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 15/18] PCI/P2PDMA: Document TLP-class routing Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 16/18] PCI/P2PDMA: Let a client declare that it selects ATS per mapping Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 17/18] PCI/P2PDMA: Evaluate the ATS path for clients with ATS enabled Leon Romanovsky
2026-10-01 11:55 ` [PATCH v9 18/18] PCI/P2PDMA: Test the routing of " Leon Romanovsky
2026-10-06 19:29 ` [PATCH v9 00/18] PCI/P2PDMA: Route peer-to-peer DMA by TLP class Bjorn Helgaas
2026-10-06 21:22   ` Leon Romanovsky
2026-10-06 21:36     ` Bjorn Helgaas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261006210848.GA712422@bhelgaas \
    --to=helgaas@kernel.org \
    --cc=alex@shazbot.org \
    --cc=ankita@nvidia.com \
    --cc=axboe@kernel.dk \
    --cc=bhelgaas@google.com \
    --cc=christian.koenig@amd.com \
    --cc=corbet@lwn.net \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=kch@nvidia.com \
    --cc=kvm@vger.kernel.org \
    --cc=leon@kernel.org \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=rdunlap@infradead.org \
    --cc=robin.murphy@arm.com \
    --cc=skhan@linuxfoundation.org \
    --cc=sumit.semwal@linaro.org \
    --cc=tdave@nvidia.com \
    --cc=thomas.hellstrom@linux.intel.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®