[PATCH v11 09/19] PCI/P2PDMA: Route Relaxed Ordering Completions directly

From: Leon Romanovsky

Date: Tue Oct 13 2026 - 10:57:15 EST


From: Leon Romanovsky <leonro@xxxxxxxxxx>

ACS P2P Completion Redirect leaves Completions carrying Relaxed Ordering
alone, per PCIe r7.0 sec 6.12.1.1. A Completion copies that attribute from
its Request, so a client setting it on Non-Posted Requests need not use the
host bridge solely because Completion Redirect is enabled.

Route Completions directly for PCI_P2PDMA_TLP_RELAXED_CPL unless a device
quirk redirects them or the Completer lacks an internal route to its
sibling. Neither restriction promises a Relaxed Ordering exception. No
caller selects these classes yet.

Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxx>
---
drivers/pci/p2pdma.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 9d416329aa4b..785e4668a2af 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -580,11 +580,15 @@ pci_acs_p2pdma_request(u16 ctrl, unsigned int tlp_flags)
/*
* Decide how a peer-to-peer Completion at an ACS-capable ingress port routes.
* PCIe r7.0 sec 6.12.1.1: no ACS control other than P2P Completion Redirect
- * affects a Completion.
+ * affects a Completion, and that one leaves Completions carrying the Relaxed
+ * Ordering attribute alone.
*/
static enum pci_acs_p2pdma_state
pci_acs_p2pdma_completion(u16 ctrl, unsigned int tlp_flags)
{
+ if (tlp_flags & PCI_P2PDMA_TLP_RELAXED_CPL)
+ return PCI_ACS_P2PDMA_DIRECT;
+
return ctrl & PCI_ACS_CR ? PCI_ACS_P2PDMA_REDIRECT :
PCI_ACS_P2PDMA_DIRECT;
}
@@ -737,6 +741,7 @@ static void pci_p2pdma_warn_redir(struct pci_dev *client,
* than upstream, so it is where the Request controls apply.
* @cpl_ctrl: ACS Control of the Completer-side divergence port, likewise for
* the Completions travelling back.
+ * @cpl_quirk: A device quirk reports Completion Redirect at that port.
* @req_upstream: The Requester has no internal route to its sibling.
* @cpl_upstream: The Completer has no internal route to its sibling.
* @unreadable: First port whose ACS Control could not be read, if any.
@@ -745,6 +750,7 @@ static void pci_p2pdma_warn_redir(struct pci_dev *client,
struct pci_p2pdma_acs_path {
u16 req_ctrl;
u16 cpl_ctrl;
+ bool cpl_quirk;
bool req_upstream;
bool cpl_upstream;
struct pci_dev *unreadable;
@@ -761,11 +767,16 @@ pci_p2pdma_request_state(const struct pci_p2pdma_acs_path *path,
return pci_acs_p2pdma_request(path->req_ctrl, tlp_flags);
}

+/*
+ * ACS P2P Completion Redirect leaves Relaxed Ordering Completions alone. A
+ * device quirk that reports Completion Redirect does not promise that, so
+ * treat every Completion through that port as redirected.
+ */
static enum pci_acs_p2pdma_state
pci_p2pdma_completion_state(const struct pci_p2pdma_acs_path *path,
unsigned int tlp_flags)
{
- if (path->cpl_upstream)
+ if (path->cpl_quirk || path->cpl_upstream)
return PCI_ACS_P2PDMA_REDIRECT;

return pci_acs_p2pdma_completion(path->cpl_ctrl, tlp_flags);
@@ -1132,6 +1143,7 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
if (a_child && b_child) {
if (!pci_acs_p2pdma_ctrl(a_child, &path.cpl_ctrl))
path.unreadable = a_child;
+ path.cpl_quirk = pci_acs_p2pdma_quirk(a_child, PCI_ACS_CR);
if (!pci_acs_p2pdma_ctrl(b_child, &path.req_ctrl) &&
!path.unreadable)
path.unreadable = b_child;

--
2.55.0