From: Leon Romanovsky <[email protected]>

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 <[email protected]>
---
 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

Reply via email to