From: Leon Romanovsky <leon@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: linux-pci@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-rdma@vger.kernel.org, kvm@vger.kernel.org,
media-ci@linuxtv.org
Subject: Re: [PATCH v12 05/19] PCI/P2PDMA: Evaluate ACS controls at the path divergence
Date: Thu, 5 Nov 2026 10:53:23 +0200 [thread overview]
Message-ID: <20261105085323.GK478286@unreal> (raw)
In-Reply-To: <sashiko-outbox-194956@kernel.org>
On Tue, Nov 03, 2026 at 09:31:33AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] PCI/P2PDMA: missing upstream forwarding check in calc_map_type_and_dist()
> - [Medium] PCI/P2PDMA: masked redirect and read warnings in calc_map_type_and_dist()
> --
>
> commit ae19e046716c7bc5dbb292aa22e00859ce94d08e
> Author: Leon Romanovsky <leon@kernel.org>
>
> PCI/P2PDMA: Evaluate ACS controls at the path divergence
>
> This commit updates calc_map_type_and_dist() to evaluate ACS directional
> redirect controls at the path divergence rather than below it. It also
> checks for internal routes between functions sharing a PCIe link, verifies
> ACS Upstream Forwarding on shared downstream ports, and rejects unreadable
> ACS Control registers.
>
> > diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
> > index dbab955dcbdbb..8ca0c9ba87c23 100644
> > --- a/drivers/pci/p2pdma.c
> > +++ b/drivers/pci/p2pdma.c
> > @@ -589,6 +590,65 @@ static bool pci_acs_p2pdma_ctrl(struct pci_dev *pdev, u16 *ctrl)
>
> [ ... ]
>
> > +static struct pci_dev *
> > +pci_acs_p2pdma_no_upstream_forwarding(struct pci_dev *common)
> > +{
> > + struct pci_dev *pdev;
> > + u16 ctrl;
> > +
> > + for (pdev = common; pdev; pdev = pci_upstream_bridge(pdev)) {
> > + if (!pci_acs_p2pdma_downstream_port(pdev))
> > + continue;
> > +
> > + if (!pci_acs_p2pdma_ctrl(pdev, &ctrl))
> > + return pdev;
> > +
> > + /*
> > + * Include Root Ports here. The PCIe port type check excludes
> > + * the legacy AMD southbridge quirk, which may sleep.
> > + */
> > + if (pci_dev_specific_acs_enabled(pdev, PCI_ACS_UF) > 0)
> > + continue;
> > +
> > + if (!(pdev->acs_cap && pdev->acs_capabilities & ctrl & PCI_ACS_UF))
> > + return pdev;
> > + }
> > +
> > + return NULL;
> > +}
>
> [ ... ]
>
> > @@ -865,57 +932,106 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
>
> [ ... ]
>
> > +check_paths_acs:
> > + *dist = dist_a + dist_b;
> >
> > + /*
> > + * 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) {
> > + pci_p2pdma_list_redir(&acs_list, &quirk_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) {
> > + pci_p2pdma_list_redir(&acs_list, &quirk_list, b_child);
> > + if (state == PCI_ACS_P2PDMA_REDIRECT)
> > + acs_redirect_cnt++;
> > + else if (!acs_unreadable)
> > + acs_unreadable = b_child;
> > + }
> > + /*
> > + * Two children of one Downstream or Root Port share a link.
> > + * Use topology rather than slot numbers or the multifunction
> > + * bit, since ARI functions and VFs need not share those.
> > + */
> > + if (pci_acs_p2pdma_downstream_port(a)) {
> > + req_upstream =
> > + pci_acs_p2pdma_no_internal_route(b_child, PCI_ACS_RR);
> > + cpl_upstream =
> > + pci_acs_p2pdma_no_internal_route(a_child, PCI_ACS_CR);
> > + uf_blocked = pci_acs_p2pdma_no_upstream_forwarding(a);
> > + }
> > }
>
> [Severity: High]
> When provider and client sit behind different Switch Downstream Ports of a
> PCIe Switch, their lowest common ancestor a in calc_map_type_and_dist() is
> the Switch Upstream Port (PCI_EXP_TYPE_UPSTREAM), where
> pci_acs_p2pdma_downstream_port(a) is false.
>
> If b_child has PCI_ACS_RR or PCI_ACS_EC enabled, or a_child has PCI_ACS_CR
> enabled, the switch redirects traffic upstream out of the Switch Upstream
> Port a toward the host bridge. That redirected TLP then arrives on the
> secondary interface of every shared Switch Downstream Port (in a cascaded
> switch topology) and Root Port above a with its target also behind that same
> secondary interface, requiring PCI_ACS_UF on those shared ports to reach the
> host bridge.
>
> Although pci_acs_p2pdma_no_upstream_forwarding() already walks up
> pci_upstream_bridge() while skipping Switch Upstream Ports, calling it only
> inside if (pci_acs_p2pdma_downstream_port(a)) skips checking the shared
> Downstream and Root Ports above a when a is a Switch Upstream Port. Can this
> cause calc_map_type_and_dist() to return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE
> instead of PCI_P2PDMA_MAP_NOT_SUPPORTED when an ancestor port above the
> switch lacks PCI_ACS_UF or has an unreadable ACS Control register?
The thing is that this behaviour was before my series, but let's change
it too.
>
> > + /*
> > + * Below a shared upstream bridge, a path whose divergence ports do not
> > + * redirect routes the request directly.
> > + */
> > + if (!acs_unreadable && !acs_redirect_cnt &&
> > + !req_upstream && !cpl_upstream) {
> > map_type = PCI_P2PDMA_MAP_BUS_ADDR;
> > goto done;
> > }
> >
> > + if (verbose) {
> > + if (acs_unreadable)
> > + pci_warn(client, "ACS Control is unreadable for provider %s at %s\n",
> > + pci_name(provider), pci_name(acs_unreadable));
> > + else if (uf_blocked)
> > + pci_warn(client,
> > + "cannot forward peer-to-peer DMA for provider %s upstream at %s\n",
> > + pci_name(provider), pci_name(uf_blocked));
> > + else if (req_upstream || cpl_upstream)
> > + pci_warn(client,
> > + "peer-to-peer DMA with provider %s requires the host bridge; no internal route between functions\n",
> > + pci_name(provider));
> > + else
> > + pci_p2pdma_warn_redir(client, provider, &acs_list,
> > + &quirk_list);
> > + }
>
> [Severity: Medium]
> How are diagnostics handled here when sibling functions under a Downstream
> Port or Root Port a DO support internal peer-to-peer routing (!req_upstream
> && !cpl_upstream), but have PCI_ACS_RR, PCI_ACS_EC, or PCI_ACS_CR enabled on
> the functions themselves (acs_redirect_cnt > 0)?
>
> In that case, disabling ACS redirect on the functions via
> pci=disable_acs_redir= would allow them to use their internal route
> (PCI_P2PDMA_MAP_BUS_ADDR) without traversing port a. However, because
> uf_blocked = pci_acs_p2pdma_no_upstream_forwarding(a) is evaluated
> unconditionally and checked before the final else branch in the verbose
> block, if port a or an ancestor port does not have PCI_ACS_UF enabled,
> calc_map_type_and_dist() only warns about upstream forwarding at uf_blocked
> and suppresses pci_p2pdma_warn_redir().
>
> Additionally, pci_acs_p2pdma_no_upstream_forwarding() is called before the
> PCI_P2PDMA_MAP_BUS_ADDR check (reading PCI_ACS_CTRL up the hierarchy even
> when the functions route directly), and when pci_acs_p2pdma_ctrl() fails on
> an upstream port, it returns that port as uf_blocked rather than
> acs_unreadable, logging an upstream-forwarding message instead of an
> unreadable ACS Control warning. Should pci_acs_p2pdma_no_upstream_forwarding()
> only be evaluated after the direct-route check, distinguish unreadable ACS
> Control registers from missing PCI_ACS_UF, and still emit
> pci_p2pdma_warn_redir() when programmable redirect bits blocked a valid
> direct route?
ok, let's change it too.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261103-fix-p2p-acs-v4-0-v12-0-912101f93517@nvidia.com?part=5
next prev parent reply other threads:[~2026-11-05 8:53 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 8:29 [PATCH v12 00/19] PCI/P2PDMA: Route peer-to-peer DMA by TLP class Leon Romanovsky
2026-11-03 8:29 ` [PATCH v12 01/19] PCI/P2PDMA: Honor device-specific ACS redirection Leon Romanovsky
2026-11-03 8:43 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 02/19] PCI/P2PDMA: Document the TLP attribute assumptions Leon Romanovsky
2026-11-03 8:45 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 03/19] PCI/P2PDMA: Derive routing from directional ACS controls Leon Romanovsky
2026-11-03 9:02 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 04/19] PCI: Reject unreadable ACS controls in isolation checks Leon Romanovsky
2026-11-03 9:09 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 05/19] PCI/P2PDMA: Evaluate ACS controls at the path divergence Leon Romanovsky
2026-11-03 9:31 ` sashiko-bot
2026-11-05 8:53 ` Leon Romanovsky [this message]
2026-11-03 8:29 ` [PATCH v12 06/19] PCI/P2PDMA: Document directional ACS routing Leon Romanovsky
2026-11-03 9:39 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 07/19] PCI/P2PDMA: Collect the path's ACS controls before deciding Leon Romanovsky
2026-11-03 9:53 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 08/19] PCI/P2PDMA: Answer routing per TLP class Leon Romanovsky
2026-11-03 10:06 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 09/19] PCI/P2PDMA: Route Relaxed Ordering Completions directly Leon Romanovsky
2026-11-03 10:10 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 10/19] PCI/P2PDMA: Reject Translated Requests blocked by Translation Blocking Leon Romanovsky
2026-11-03 10:34 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 11/19] PCI/P2PDMA: Route Translated Requests under Direct Translated P2P Leon Romanovsky
2026-11-03 10:45 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 12/19] PCI/P2PDMA: Log detailed ACS routing diagnostics Leon Romanovsky
2026-11-03 11:01 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 13/19] PCI/P2PDMA: Add KUnit tests for the ACS routing decisions Leon Romanovsky
2026-11-03 11:03 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 14/19] PCI/P2PDMA: Test the ACS P2P routing walk Leon Romanovsky
2026-11-03 11:07 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 15/19] PCI: Add KUnit coverage for ACS isolation checks Leon Romanovsky
2026-11-03 11:11 ` sashiko-bot
2026-11-05 8:42 ` Leon Romanovsky
2026-11-03 8:29 ` [PATCH v12 16/19] PCI/P2PDMA: Document TLP-class routing Leon Romanovsky
2026-11-03 11:12 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 17/19] PCI/P2PDMA: Let a client declare that it selects ATS per mapping Leon Romanovsky
2026-11-03 11:15 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 18/19] PCI/P2PDMA: Evaluate the ATS path for clients with ATS enabled Leon Romanovsky
2026-11-03 11:34 ` sashiko-bot
2026-11-03 8:29 ` [PATCH v12 19/19] PCI/P2PDMA: Test the routing of " Leon Romanovsky
2026-11-03 11:37 ` sashiko-bot
2026-11-03 23:37 ` [PATCH v12 00/19] PCI/P2PDMA: Route peer-to-peer DMA by TLP class Bjorn Helgaas
2026-11-04 8:43 ` Leon Romanovsky
2026-11-04 17:14 ` Bjorn Helgaas
2026-11-04 19:52 ` Leon Romanovsky
2026-11-04 19:56 ` Jason Gunthorpe
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=20261105085323.GK478286@unreal \
--to=leon@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=kvm@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=media-ci@linuxtv.org \
--cc=sashiko-reviews@lists.linux.dev \
/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