From: Leon Romanovsky leonro@nvidia.com
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@nvidia.com --- 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;