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 06/18] PCI/P2PDMA: Collect the path's ACS controls before deciding
Date: Tue, 6 Oct 2026 16:48:58 -0500	[thread overview]
Message-ID: <20261006214858.GA717151@bhelgaas> (raw)
In-Reply-To: <20261001-fix-p2p-acs-v4-0-v9-6-1a8e0f50ddd9@nvidia.com>

On Thu, Oct 01, 2026 at 02:55:14PM +0300, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@nvidia.com>
> 
> calc_map_type_and_dist() reads each divergence port's ACS Control register
> and folds the result into running counters as it goes. Any routing property
> that depends on the kind of TLP being routed would have to be threaded
> through that code, so there is nowhere to put one without reading the
> registers again for each kind.

What is the "one" that there's nowhere to put?  I guess the routing
property?  So this is an optimization to avoid some config reads?

> Collect the two ports' ACS Control values into struct pci_p2pdma_acs_path
> first, then decide from it. pci_p2pdma_route() applies the same rule as
> before: a path routes directly only when both directions do.
> 
> 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 | 148 +++++++++++++++++++++++++++++++++------------------
>  1 file changed, 96 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
> index 550e6c7346ef..841c86be31bb 100644
> --- a/drivers/pci/p2pdma.c
> +++ b/drivers/pci/p2pdma.c
> @@ -553,6 +553,80 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
>  	seq_buf_printf(buf, "%s;", pci_name(pdev));
>  }
>  
> +/*
> + * What the topology walk found out about one provider/client path. Producing
> + * this costs a walk and one config read per divergence port, none of which
> + * depends on the TLP being routed.
> + *
> + * @req_ctrl:	ACS Control of the client-side divergence port. That is the
> + *		first port at which a Request can route toward the peer rather
> + *		than upstream, so it is where the Request controls apply.
> + * @cpl_ctrl:	ACS Control of the provider-side divergence port, likewise for
> + *		the Completions travelling back.
> + * @unreadable:	First port whose ACS Control could not be read, if any.
> + */
> +struct pci_p2pdma_acs_path {
> +	u16 req_ctrl;
> +	u16 cpl_ctrl;
> +	struct pci_dev *unreadable;
> +};
> +
> +/*
> + * Combine both directions into a mapping type. Only a path that routes the
> + * Request and the Completions it generates directly can be programmed with
> + * the peer's bus addresses.
> + */
> +static enum pci_p2pdma_map_type
> +pci_p2pdma_route(const struct pci_p2pdma_acs_path *path)
> +{
> +	if (path->unreadable)
> +		return PCI_P2PDMA_MAP_NOT_SUPPORTED;
> +
> +	if (pci_acs_p2pdma_request(path->req_ctrl) == PCI_ACS_P2PDMA_DIRECT &&
> +	    pci_acs_p2pdma_completion(path->cpl_ctrl) == PCI_ACS_P2PDMA_DIRECT)
> +		return PCI_P2PDMA_MAP_BUS_ADDR;
> +
> +	return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
> +}
> +
> +/*
> + * Name the ports that keep this path off a direct route, so that the admin
> + * can hand them to pci=disable_acs_redir=.
> + */
> +static void pci_p2pdma_warn_path(struct pci_dev *client,
> +				 struct pci_dev *provider,
> +				 const struct pci_p2pdma_acs_path *path,
> +				 struct pci_dev *a_child,
> +				 struct pci_dev *b_child)
> +{
> +	struct seq_buf acs_list;
> +	char buf[128];
> +
> +	if (path->unreadable) {
> +		pci_warn(client,
> +			 "ACS Control is unreadable for provider %s at %s\n",
> +			 pci_name(provider), pci_name(path->unreadable));
> +		return;
> +	}
> +
> +	seq_buf_init(&acs_list, buf, sizeof(buf));
> +	if (pci_acs_p2pdma_completion(path->cpl_ctrl) != PCI_ACS_P2PDMA_DIRECT)
> +		seq_buf_print_bus_devfn(&acs_list, a_child);
> +	if (pci_acs_p2pdma_request(path->req_ctrl) != PCI_ACS_P2PDMA_DIRECT)
> +		seq_buf_print_bus_devfn(&acs_list, b_child);
> +
> +	/* 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 controls for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
> +		 seq_buf_str(&acs_list));
> +}
> +
>  static bool cpu_supports_p2pdma(void)
>  {
>  #ifdef CONFIG_X86
> @@ -751,19 +825,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_acs_path path = {};
>  	struct pci_p2pdma *p2pdma;
> -	struct seq_buf acs_list;
> -	int acs_redirect_cnt = 0;
> +	bool cpu_p2pdma, host_whitelisted = false;
>  	int dist_a = 0;
>  	int dist_b = 0;
> -	char buf[128];
> -	u16 ctrl;
> -
> -	seq_buf_init(&acs_list, buf, sizeof(buf));
>  
>  	/*
>  	 * Note, we don't need to take references to devices returned by
> @@ -806,61 +874,35 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
>  	 * 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;
> -		}
> -
> -		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;
> -		}
> +		if (!pci_acs_p2pdma_ctrl(a_child, &path.cpl_ctrl))
> +			path.unreadable = a_child;
> +		if (!pci_acs_p2pdma_ctrl(b_child, &path.req_ctrl) &&
> +		    !path.unreadable)
> +			path.unreadable = b_child;
>  	}
>  
>  	/*
>  	 * 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;
> +	map_type = pci_p2pdma_route(&path);
> +	if (map_type == PCI_P2PDMA_MAP_BUS_ADDR)
>  		goto done;
> -	}
>  
> -	if (verbose) {
> -		/* 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';
> -		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));
> -		}
> -	}
> +	if (verbose)
> +		pci_p2pdma_warn_path(client, provider, &path, a_child, b_child);
>  
>  	/* An unreadable control does not establish an upstream redirect. */
> -	if (acs_unreadable) {
> -		map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
> +	if (path.unreadable)
>  		goto done;
> -	}
>  
>  map_through_host_bridge:
> -	if (!cpu_supports_p2pdma() &&
> -	    !host_bridge_whitelist(provider, client, verbose)) {
> +	cpu_p2pdma = cpu_supports_p2pdma();
> +	if (!cpu_p2pdma)
> +		host_whitelisted = host_bridge_whitelist(provider, client,
> +							  verbose);
> +
> +	if (!cpu_p2pdma && !host_whitelisted) {
>  		if (verbose)
>  			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));
> @@ -1193,8 +1235,9 @@ enum pci_p2pdma_map_type pci_p2pdma_map_type(struct p2pdma_provider *provider,
>  {
>  	enum pci_p2pdma_map_type type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
>  	struct pci_dev *pdev = to_pci_dev(provider->owner);
> -	struct pci_dev *client;
>  	struct pci_p2pdma *p2pdma;
> +	unsigned long cache_index;
> +	struct pci_dev *client;
>  	int dist;
>  
>  	if (!pdev->p2pdma)
> @@ -1204,13 +1247,14 @@ enum pci_p2pdma_map_type pci_p2pdma_map_type(struct p2pdma_provider *provider,
>  		return PCI_P2PDMA_MAP_NOT_SUPPORTED;
>  
>  	client = to_pci_dev(dev);
> +	cache_index = map_types_idx(client);
>  
>  	rcu_read_lock();
>  	p2pdma = rcu_dereference(pdev->p2pdma);
>  
>  	if (p2pdma)
>  		type = xa_to_value(xa_load(&p2pdma->map_types,
> -					   map_types_idx(client)));
> +					   cache_index));
>  	rcu_read_unlock();
>  
>  	if (type == PCI_P2PDMA_MAP_UNKNOWN)
> 
> -- 
> 2.55.0
> 

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

Thread overview: 33+ 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-07  6:32     ` Leon Romanovsky
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
2026-10-07 10:51     ` Leon Romanovsky
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 [this message]
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
2026-10-07  6:56       ` Bjorn Helgaas
2026-10-07 10:54         ` Leon Romanovsky
2026-10-07 11:31           ` 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=20261006214858.GA717151@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®