Re: [RESEND v13 20/25] CXL/PCI: Introduce CXL Port protocol error handlers

Jonathan Cameron
2025-11-04T18:32:30Z

On Tue, 4 Nov 2025 11:03:00 -0600
Terry Bowman <terry.bowman@amd.com> wrote:

> Add CXL protocol error handlers for CXL Port devices (Root Ports,
> Downstream Ports, and Upstream Ports). Implement cxl_port_cor_error_detected()
> and cxl_port_error_detected() to handle correctable and uncorrectable errors
> respectively.
>
> Introduce cxl_get_ras_base() to retrieve the cached RAS register base
> address for a given CXL port. This function supports CXL Root Ports,
> Downstream Ports, and Upstream Ports by returning their previously mapped
> RAS register addresses.
>
> Add device lock assertions to protect against concurrent device or RAS
> register removal during error handling. The port error handlers require
> two device locks:
>
> 1. The port's CXL parent device - RAS registers are mapped using devm_*
> functions with the parent port as the host. Locking the parent prevents
> the RAS registers from being unmapped during error handling.
>
> 2. The PCI device (pdev->dev) - Locking prevents concurrent modifications
> to the PCI device structure during error handling.
>
> The lock assertions added here will be satisfied by device locks introduced
> in a subsequent patch.
>
> Introduce get_pci_cxl_host_dev() to return the device responsible for
> managing the RAS register mapping. This function increments the reference
> count on the host device to prevent premature resource release during error
> handling. The caller is responsible for decrementing the reference count.
> For CXL endpoints, which manage resources without a separate host device,
> this function returns NULL.
>
> Update the AER driver's is_cxl_error() to recognize CXL Port devices in
> addition to CXL Endpoints, as both now have CXL-specific error handlers.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
>
> ---
>
> Changes in v12->v13:
> - Move get_pci_cxl_host_dev() and cxl_handle_proto_error() to Dequeue
> patch (Terry)
> - Remove EP case in cxl_get_ras_base(), not used. (Terry)
> - Remove check for dport->dport_dev (Dave)
> - Remove whitespace (Terry)
Really trivial comment follows.

> diff --git a/drivers/cxl/core/ras.c b/drivers/cxl/core/ras.c
> index beb142054bda..142ca8794107 100644
> --- a/drivers/cxl/core/ras.c
> +++ b/drivers/cxl/core/ras.c

> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> @@ -254,6 +287,22 @@ pci_ers_result_t cxl_handle_ras(struct device *dev, u64 serial, void __iomem *ra
> return PCI_ERS_RESULT_PANIC;
> }
>
> +void cxl_port_cor_error_detected(struct device *dev)
> +{
> + void __iomem *ras_base = cxl_get_ras_base(dev);
> +
> + cxl_handle_cor_ras(dev, 0, ras_base);
To me no significant loss of readability to do

cxl_handle_cor_ras(dev, 0, cxl_get_ras_base(dev));

I don't really care much so feel free to ignore.

> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_port_cor_error_detected, "CXL");
> +
> +pci_ers_result_t cxl_port_error_detected(struct device *dev)
> +{
> + void __iomem *ras_base = cxl_get_ras_base(dev);
> +
> + return cxl_handle_ras(dev, 0, ras_base);
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_port_error_detected, "CXL");
> +
> void cxl_cor_error_detected(struct device *dev)
> {
> struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> diff --git a/drivers/pci/pcie/aer_cxl_vh.c b/drivers/pci/pcie/aer_cxl_vh.c
> index 5dbc81341dc4..25f9512b57f7 100644
> --- a/drivers/pci/pcie/aer_cxl_vh.c
> +++ b/drivers/pci/pcie/aer_cxl_vh.c
> @@ -43,7 +43,10 @@ bool is_cxl_error(struct pci_dev *pdev, struct aer_err_info *info)
> if (!info || !info->is_cxl)
> return false;
>
> - if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
> + if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT) &&
> + (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
> + (pci_pcie_type(pdev) != PCI_EXP_TYPE_UPSTREAM) &&
> + (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
> return false;
>
> return is_internal_error(info);