Re: [RESEND v13 14/25] cxl/pci: Map CXL Endpoint Port and CXL Switch Port RAS registers

Alison Schofield
2025-11-11T08:23:47Z

On Tue, Nov 04, 2025 at 11:02:54AM -0600, Terry Bowman wrote:
> CXL Endpoint (EP) Ports may include Root Ports (RP) or Downstream Switch
> Ports (DSP). CXL RPs and DSPs contain RAS registers that require memory
> mapping to enable RAS logging. This initialization is currently missing and
> must be added for CXL RPs and DSPs.
>
> Update cxl_dport_init_ras_reporting() to support RP and DSP RAS mapping.
> Add alongside the existing Restricted CXL Host Downstream Port RAS mapping.
>
> Update cxl_endpoint_port_probe() to invoke cxl_dport_init_ras_reporting().
> This will initiate the RAS mapping for CXL RPs and DSPs when each CXL EP is
> created and added to the EP port.
>
> Make a call to cxl_port_setup_regs() in cxl_port_add(). This will probe the
> Upstream Port's CXL capabilities' physical location to be used in mapping
> the RAS registers.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>

Terry,

This patch needed some cxl-test support:

Attaching what is needed to 'Make cxl_*_init_ras_reporting() work
with cxl-test"

It adds a mock version of cxl_uport_init_ras_reporting(), simply
following what existed for cxl_dport_init_ras_reporting().

The other changes apply a method that avoids circular dependencies
that the above patch introduced: cxl_mock->cxl_core->cxl_mock.
This method is a Dan invention that DaveJ first applied it here:
d96eb90d9ca6 ("cxl/test: Add mock version of devm_cxl_add_dport_by_dev()")

In my tree, I inserted and tested this after this patch I'm replying
to, but I think you'll need to combine them, or split some other way
so no patch introduces breakage.

--Alison

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/cxl/core/port.c | 4 ++--
drivers/cxl/core/ras.c | 12 ++++++------
drivers/cxl/cxl.h | 5 +++++
drivers/cxl/cxlpci.h | 6 ++++--
drivers/cxl/mem.c | 2 +-
tools/testing/cxl/Kbuild | 1 -
tools/testing/cxl/cxl_core_exports.c | 19 +++++++++++++++++++
tools/testing/cxl/exports.h | 8 ++++++++
tools/testing/cxl/test/mock.c | 25 +++++++++++++++++++++++--
9 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 48f6a1492544..f0fc917f9575 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1195,7 +1195,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
}
port->component_reg_phys = CXL_RESOURCE_NONE;
if (!is_cxl_endpoint(port) && dev_is_pci(port->uport_dev))
- cxl_uport_init_ras_reporting(port, &port->dev);
+ __cxl_uport_init_ras_reporting(port, &port->dev);
}

get_device(dport_dev);
@@ -1625,7 +1625,7 @@ static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,

cxl_switch_parse_cdat(new_dport);

- cxl_dport_init_ras_reporting(new_dport, &port->dev);
+ __cxl_dport_init_ras_reporting(new_dport, &port->dev);

if (ida_is_empty(&port->decoder_ida)) {
rc = devm_cxl_switch_port_decoders_setup(port);
diff --git a/drivers/cxl/core/ras.c b/drivers/cxl/core/ras.c
index 19d9ffe885bf..90bfb32cc3c5 100644
--- a/drivers/cxl/core/ras.c
+++ b/drivers/cxl/core/ras.c
@@ -141,11 +141,12 @@ static void cxl_dport_map_ras(struct cxl_dport *dport)
}

/**
- * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
+ * __cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
* @dport: the cxl_dport that needs to be initialized
* @host: host device for devm operations
*/
-void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
+void __cxl_dport_init_ras_reporting(struct cxl_dport *dport,
+ struct device *host)
{
dport->reg_map.host = host;
cxl_dport_map_ras(dport);
@@ -160,10 +161,9 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
cxl_disable_rch_root_ints(dport);
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
+EXPORT_SYMBOL_NS_GPL(__cxl_dport_init_ras_reporting, "CXL");

-void cxl_uport_init_ras_reporting(struct cxl_port *port,
- struct device *host)
+void __cxl_uport_init_ras_reporting(struct cxl_port *port, struct device *host)
{
struct cxl_register_map *map = &port->reg_map;

@@ -172,7 +172,7 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port,
BIT(CXL_CM_CAP_CAP_ID_RAS)))
dev_dbg(&port->dev, "Failed to map RAS capability\n");
}
-EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
+EXPORT_SYMBOL_NS_GPL(__cxl_uport_init_ras_reporting, "CXL");

void cxl_handle_cor_ras(struct device *dev, u64 serial, void __iomem *ras_base)
{
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index b7654d40dc9e..995e20a88d96 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -940,6 +940,11 @@ u16 cxl_gpf_get_dvsec(struct device *dev);
#define DECLARE_TESTABLE(x) __##x
#define devm_cxl_add_dport_by_dev DECLARE_TESTABLE(devm_cxl_add_dport_by_dev)
#define devm_cxl_switch_port_decoders_setup DECLARE_TESTABLE(devm_cxl_switch_port_decoders_setup)
+#define cxl_dport_init_ras_reporting \
+ DECLARE_TESTABLE(cxl_dport_init_ras_reporting)
+#define cxl_uport_init_ras_reporting \
+ DECLARE_TESTABLE(cxl_uport_init_ras_reporting)
+
#endif

#endif /* __CXL_H__ */
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index a0a491e7b5b9..846cf0935252 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -82,9 +82,11 @@ void read_cdat_data(struct cxl_port *port);
void cxl_cor_error_detected(struct pci_dev *pdev);
pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
pci_channel_state_t state);
+void __cxl_dport_init_ras_reporting(struct cxl_dport *dport,
+ struct device *host);
void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host);
-void cxl_uport_init_ras_reporting(struct cxl_port *port,
- struct device *host);
+void __cxl_uport_init_ras_reporting(struct cxl_port *port, struct device *host);
+void cxl_uport_init_ras_reporting(struct cxl_port *port, struct device *host);
#else
static inline void cxl_cor_error_detected(struct pci_dev *pdev) { }

diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index d2155f45240d..782fdb552865 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -167,7 +167,7 @@ static int cxl_mem_probe(struct device *dev)
endpoint_parent = &parent_port->dev;

if (dport->rch)
- cxl_dport_init_ras_reporting(dport, dev);
+ __cxl_dport_init_ras_reporting(dport, dev);

scoped_guard(device, endpoint_parent) {
if (!endpoint_parent->driver) {
diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild
index 6905f8e710ab..fe80a811fdef 100644
--- a/tools/testing/cxl/Kbuild
+++ b/tools/testing/cxl/Kbuild
@@ -9,7 +9,6 @@ ldflags-y += --wrap=cxl_await_media_ready
ldflags-y += --wrap=devm_cxl_add_rch_dport
ldflags-y += --wrap=cxl_rcd_component_reg_phys
ldflags-y += --wrap=cxl_endpoint_parse_cdat
-ldflags-y += --wrap=cxl_dport_init_ras_reporting
ldflags-y += --wrap=devm_cxl_endpoint_decoders_setup

DRIVERS := ../../../drivers
diff --git a/tools/testing/cxl/cxl_core_exports.c b/tools/testing/cxl/cxl_core_exports.c
index 6754de35598d..5a071afa46fd 100644
--- a/tools/testing/cxl/cxl_core_exports.c
+++ b/tools/testing/cxl/cxl_core_exports.c
@@ -3,6 +3,7 @@

#include "cxl.h"
#include "exports.h"
+#include "cxlpci.h"

/* Exporting of cxl_core symbols that are only used by cxl_test */
EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, "CXL");
@@ -27,3 +28,21 @@ int devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
return _devm_cxl_switch_port_decoders_setup(port);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_switch_port_decoders_setup, "CXL");
+
+cxl_dport_init_ras_reporting_fn _cxl_dport_init_ras_reporting =
+ __cxl_dport_init_ras_reporting;
+EXPORT_SYMBOL_NS_GPL(_cxl_dport_init_ras_reporting, "CXL");
+
+void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
+{
+ return _cxl_dport_init_ras_reporting(dport, host);
+}
+
+cxl_uport_init_ras_reporting_fn _cxl_uport_init_ras_reporting =
+ __cxl_uport_init_ras_reporting;
+EXPORT_SYMBOL_NS_GPL(_cxl_uport_init_ras_reporting, "CXL");
+
+void cxl_uport_init_ras_reporting(struct cxl_port *port, struct device *host)
+{
+ return _cxl_uport_init_ras_reporting(port, host);
+}
diff --git a/tools/testing/cxl/exports.h b/tools/testing/cxl/exports.h
index 7ebee7c0bd67..f3bcba8bc11b 100644
--- a/tools/testing/cxl/exports.h
+++ b/tools/testing/cxl/exports.h
@@ -10,4 +10,12 @@ extern cxl_add_dport_by_dev_fn _devm_cxl_add_dport_by_dev;
typedef int(*cxl_switch_decoders_setup_fn)(struct cxl_port *port);
extern cxl_switch_decoders_setup_fn _devm_cxl_switch_port_decoders_setup;

+typedef void (*cxl_dport_init_ras_reporting_fn)(struct cxl_dport *dport,
+ struct device *host);
+extern cxl_dport_init_ras_reporting_fn _cxl_dport_init_ras_reporting;
+
+typedef void (*cxl_uport_init_ras_reporting_fn)(struct cxl_port *port,
+ struct device *host);
+extern cxl_uport_init_ras_reporting_fn _cxl_uport_init_ras_reporting;
+
#endif
diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c
index 995269a75cbd..776b951aab1a 100644
--- a/tools/testing/cxl/test/mock.c
+++ b/tools/testing/cxl/test/mock.c
@@ -18,6 +18,10 @@ static struct cxl_dport *
redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
struct device *dport_dev);
static int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
+static void redirect_cxl_dport_init_ras_reporting(struct cxl_dport *dport,
+ struct device *host);
+static void redirect_cxl_uport_init_ras_reporting(struct cxl_port *port,
+ struct device *host);

void register_cxl_mock_ops(struct cxl_mock_ops *ops)
{
@@ -25,6 +29,8 @@ void register_cxl_mock_ops(struct cxl_mock_ops *ops)
_devm_cxl_add_dport_by_dev = redirect_devm_cxl_add_dport_by_dev;
_devm_cxl_switch_port_decoders_setup =
redirect_devm_cxl_switch_port_decoders_setup;
+ _cxl_dport_init_ras_reporting = redirect_cxl_dport_init_ras_reporting;
+ _cxl_uport_init_ras_reporting = redirect_cxl_uport_init_ras_reporting;
}
EXPORT_SYMBOL_GPL(register_cxl_mock_ops);

@@ -35,6 +41,9 @@ void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
_devm_cxl_switch_port_decoders_setup =
__devm_cxl_switch_port_decoders_setup;
_devm_cxl_add_dport_by_dev = __devm_cxl_add_dport_by_dev;
+ _cxl_dport_init_ras_reporting = __cxl_dport_init_ras_reporting;
+ _cxl_uport_init_ras_reporting = __cxl_uport_init_ras_reporting;
+
list_del_rcu(&ops->list);
synchronize_srcu(&cxl_mock_srcu);
}
@@ -257,7 +266,8 @@ void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");

-void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
+void redirect_cxl_dport_init_ras_reporting(struct cxl_dport *dport,
+ struct device *host)
{
int index;
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
@@ -267,7 +277,18 @@ void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device

put_cxl_mock_ops(index);
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL");
+
+void redirect_cxl_uport_init_ras_reporting(struct cxl_port *port,
+ struct device *host)
+{
+ int index;
+ struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
+
+ if (!ops || !ops->is_mock_port(port->uport_dev))
+ cxl_uport_init_ras_reporting(port, host);
+
+ put_cxl_mock_ops(index);
+}

struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
struct device *dport_dev)
--
2.37.3