On Mon, Jan 19, 2026 at 09:30:24AM +0530, Riana Tauro wrote:
> Allocate correctable, uncorrectable nodes for every xe device
> Each node contains error classes, counters and respective
> query counter functions.

...

> +static int hw_query_error_counter(struct xe_drm_ras_counter *info,
> +                               u32 error_id, const char **name, u32 *val)
> +{
> +     if (error_id < DRM_XE_RAS_ERROR_CLASS_GT || error_id >= 
> DRM_XE_RAS_ERROR_CLASS_MAX)

This looks like it can be in_range().

> +             return -EINVAL;
> +
> +     if (!info[error_id].name)
> +             return -ENOENT;
> +
> +     *name = info[error_id].name;
> +     *val = atomic64_read(&info[error_id].counter);
> +
> +     return 0;
> +}
> +
> +static int query_uncorrectable_error_counters(struct drm_ras_node *ep,

This is named as 'counters' but I only see a single call here. What am
I missing?

> +                                           u32 error_id, const char **name,
> +                                           u32 *val)

Can this be less lines?

> +{
> +     struct xe_device *xe = ep->priv;
> +     struct xe_drm_ras *ras = &xe->ras;
> +     struct xe_drm_ras_counter *info = 
> ras->info[DRM_XE_RAS_ERROR_SEVERITY_UNCORRECTABLE];
> +
> +     return hw_query_error_counter(info, error_id, name, val);
> +}
> +
> +static int query_correctable_error_counters(struct drm_ras_node *ep,

Same as above.

> +                                         u32 error_id, const char **name,
> +                                         u32 *val)

Same as above.

> +{
> +     struct xe_device *xe = ep->priv;
> +     struct xe_drm_ras *ras = &xe->ras;
> +     struct xe_drm_ras_counter *info = 
> ras->info[DRM_XE_RAS_ERROR_SEVERITY_CORRECTABLE];
> +
> +     return hw_query_error_counter(info, error_id, name, val);
> +}
> +
> +static struct xe_drm_ras_counter *allocate_and_copy_counters(struct 
> xe_device *xe)
> +{
> +     struct xe_drm_ras_counter *counter;
> +     int i;
> +
> +     counter = drmm_kcalloc(&xe->drm, DRM_XE_RAS_ERROR_CLASS_MAX,
> +                            sizeof(struct xe_drm_ras_counter), GFP_KERNEL);

I'd make this robust against type changes, i.e. sizeof(*counter).

> +     if (!counter)
> +             return ERR_PTR(-ENOMEM);
> +
> +     for (i = 0; i < DRM_XE_RAS_ERROR_CLASS_MAX; i++) {
> +             if (!errors[i])
> +                     continue;
> +
> +             counter[i].name = errors[i];
> +             atomic64_set(&counter[i].counter, 0);

Doesn't drmm_kcalloc() already take care of this?

> +     }
> +
> +     return counter;
> +}
> +
> +static int assign_node_params(struct xe_device *xe, struct drm_ras_node 
> *node,
> +                           const enum drm_xe_ras_error_severity severity)
> +{
> +     struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
> +     struct xe_drm_ras *ras = &xe->ras;
> +     const char *device_name;
> +
> +     device_name = kasprintf(GFP_KERNEL, "%04x:%02x:%02x.%d",
> +                             pci_domain_nr(pdev->bus), pdev->bus->number,
> +                             PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
> +
> +     node->device_name = device_name;
> +     node->node_name = error_severity[severity];
> +     node->type = DRM_RAS_NODE_TYPE_ERROR_COUNTER;
> +     node->error_counter_range.first = DRM_XE_RAS_ERROR_CLASS_GT;
> +     node->error_counter_range.last = DRM_XE_RAS_ERROR_CLASS_MAX - 1;
> +     node->priv = xe;
> +
> +     ras->info[severity] = allocate_and_copy_counters(xe);
> +     if (IS_ERR(ras->info[severity]))
> +             return PTR_ERR(ras->info[severity]);
> +
> +     if (severity == DRM_XE_RAS_ERROR_SEVERITY_CORRECTABLE)
> +             node->query_error_counter = query_correctable_error_counters;
> +     else
> +             node->query_error_counter = query_uncorrectable_error_counters;

Shouldn't this have explicit severity check, atleast for future proofing?

> +
> +     return 0;
> +}
> +
> +static int register_nodes(struct xe_device *xe)
> +{
> +     struct xe_drm_ras *ras = &xe->ras;
> +     int i;
> +
> +     for_each_error_severity(i) {
> +             struct drm_ras_node *node = &ras->node[i];
> +             int ret;
> +
> +             ret = assign_node_params(xe, node, i);
> +             if (ret)
> +                     return ret;
> +
> +             ret = drm_ras_node_register(node);
> +             if (ret)
> +                     return ret;
> +     }
> +
> +     return 0;
> +}
> +
> +static void xe_drm_ras_unregister_nodes(void *arg)
> +{
> +     struct xe_device *xe = arg;
> +     struct xe_drm_ras *ras = &xe->ras;
> +     int i;
> +
> +     for_each_error_severity(i) {
> +             struct drm_ras_node *node = &ras->node[i];
> +
> +             drm_ras_node_unregister(node);
> +
> +             if (i == 0)
> +                     kfree(node->device_name);

Aren't we allocating this for each node?

> +     }
> +}
> +
> +/**
> + * xe_drm_ras_allocate_nodes - Allocate DRM RAS nodes
> + * @xe: xe device instance
> + *
> + * Allocate and register DRM RAS nodes per device
> + *
> + * Return: 0 on success, error code on failure
> + */
> +int xe_drm_ras_allocate_nodes(struct xe_device *xe)
> +{
> +     struct xe_drm_ras *ras = &xe->ras;
> +     struct drm_ras_node *node;
> +     int err;
> +
> +     node = drmm_kcalloc(&xe->drm, DRM_XE_RAS_ERROR_SEVERITY_MAX, 
> sizeof(struct drm_ras_node),

Ditto for robust against type changes.

> +                         GFP_KERNEL);
> +     if (!node)
> +             return -ENOMEM;
> +
> +     ras->node = node;
> +
> +     err = register_nodes(xe);
> +     if (err) {
> +             drm_err(&xe->drm, "Failed to register drm ras node\n");
> +             return err;
> +     }
> +
> +     err = devm_add_action_or_reset(xe->drm.dev, 
> xe_drm_ras_unregister_nodes, xe);
> +     if (err) {
> +             drm_err(&xe->drm, "Failed to add action for xe drm_ras\n");
> +             return err;
> +     }
> +
> +     return 0;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_drm_ras.h b/drivers/gpu/drm/xe/xe_drm_ras.h
> new file mode 100644
> index 000000000000..2d714342e4e5
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_drm_ras.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +#ifndef XE_DRM_RAS_H_
> +#define XE_DRM_RAS_H_
> +
> +struct xe_device;
> +
> +#define for_each_error_severity(i)   \
> +     for (i = 0; i < DRM_XE_RAS_ERROR_SEVERITY_MAX; i++)
> +
> +int xe_drm_ras_allocate_nodes(struct xe_device *xe);
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_drm_ras_types.h 
> b/drivers/gpu/drm/xe/xe_drm_ras_types.h
> new file mode 100644
> index 000000000000..528c708e57da
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_drm_ras_types.h
> @@ -0,0 +1,49 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef _XE_DRM_RAS_TYPES_H_
> +#define _XE_DRM_RAS_TYPES_H_
> +
> +#include <drm/xe_drm.h>
> +#include <linux/atomic.h>
> +
> +struct drm_ras_node;
> +
> +/* Error categories reported by hardware */
> +enum hardware_error {
> +     HARDWARE_ERROR_CORRECTABLE = 0,
> +     HARDWARE_ERROR_NONFATAL = 1,
> +     HARDWARE_ERROR_FATAL = 2,
> +     HARDWARE_ERROR_MAX,
> +};
> +
> +/**
> + * struct xe_drm_ras_counter - XE RAS counter
> + *
> + * This structure contains error class and counter information
> + */
> +struct xe_drm_ras_counter {
> +     /** @name: error class name */
> +     const char *name;
> +
> +     /** @counter: count of error */
> +     atomic64_t counter;
> +};
> +
> +/**
> + * struct xe_drm_ras - XE DRM RAS structure
> + *
> + * This structure has details of error counters
> + */
> +struct xe_drm_ras {
> +     /** @node: DRM RAS node */
> +     struct drm_ras_node *node;
> +
> +     /** @info: info array for all types of errors */
> +     struct xe_drm_ras_counter *info[DRM_XE_RAS_ERROR_SEVERITY_MAX];
> +

Nit: Redundant blank line.

> +};
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_hw_error.c 
> b/drivers/gpu/drm/xe/xe_hw_error.c
> index 8c65291f36fc..b42495d3015a 100644
> --- a/drivers/gpu/drm/xe/xe_hw_error.c
> +++ b/drivers/gpu/drm/xe/xe_hw_error.c
> @@ -10,20 +10,14 @@
>  #include "regs/xe_irq_regs.h"
>  
>  #include "xe_device.h"
> +#include "xe_drm_ras.h"
>  #include "xe_hw_error.h"
>  #include "xe_mmio.h"
>  #include "xe_survivability_mode.h"
>  
>  #define  HEC_UNCORR_FW_ERR_BITS 4
>  extern struct fault_attr inject_csc_hw_error;
> -
> -/* Error categories reported by hardware */
> -enum hardware_error {
> -     HARDWARE_ERROR_CORRECTABLE = 0,
> -     HARDWARE_ERROR_NONFATAL = 1,
> -     HARDWARE_ERROR_FATAL = 2,
> -     HARDWARE_ERROR_MAX,
> -};
> +static const char * const error_severity[] = DRM_XE_RAS_ERROR_SEVERITY_NAMES;

This is unrelated to uapi changes, shouldn't we split this into a separate
patch?

...

> +/**
> + * enum drm_xe_ras_error_severity - DRM RAS error severity.
> + */
> +enum drm_xe_ras_error_severity {
> +     /** @DRM_XE_RAS_ERROR_SEVERITY_CORRECTABLE: Correctable Error */
> +     DRM_XE_RAS_ERROR_SEVERITY_CORRECTABLE = 0,

DRM_XE_RAS_ERR_SEV_*? (and same for this entire file)

> +     /** @DRM_XE_RAS_ERROR_UNCORRECTABLE: Uncorrectable Error */

Match with actual name.

> +     DRM_XE_RAS_ERROR_SEVERITY_UNCORRECTABLE,
> +     /** @DRM_XE_RAS_ERROR_SEVERITY_MAX: Max severity */
> +     DRM_XE_RAS_ERROR_SEVERITY_MAX /* non-ABI */
> +};
> +
> +/**
> + * enum drm_xe_ras_error_class - DRM RAS error classes.
> + */
> +enum drm_xe_ras_error_class {
> +     /** @DRM_XE_RAS_ERROR_CLASS_GT: GT Error */
> +     DRM_XE_RAS_ERROR_CLASS_GT = 1,
> +     /** @DRM_XE_RAS_ERROR_CLASS_SOC: SoC Error */
> +     DRM_XE_RAS_ERROR_CLASS_SOC,
> +     /** @DRM_XE_RAS_ERROR_CLASS_MAX: Max Error */
> +     DRM_XE_RAS_ERROR_CLASS_MAX      /* non-ABI */

I don't find 'CLASS' to be much translatable since it can inherently mean
anything, but I'm not sure if this to match with spec naming.

PS: I've used 'COMP' for component in my series[1], but upto you.
Also, please help review it in case I've missed anything.

[1] 
https://lore.kernel.org/intel-xe/[email protected]/

Raag

> +};
> +
> +/*
> + * Error severity to name mapping.
> + */
> +#define DRM_XE_RAS_ERROR_SEVERITY_NAMES {                                    
> \
> +     [DRM_XE_RAS_ERROR_SEVERITY_CORRECTABLE] = "correctable-errors",         
> \
> +     [DRM_XE_RAS_ERROR_SEVERITY_UNCORRECTABLE] = "uncorrectable-errors",     
> \
> +}
> +
> +/*
> + * Error class to name mapping.
> + */
> +#define DRM_XE_RAS_ERROR_CLASS_NAMES {                                       
> \
> +     [DRM_XE_RAS_ERROR_CLASS_GT] = "GT",                             \
> +     [DRM_XE_RAS_ERROR_CLASS_SOC] = "SoC"                            \
> +}
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> -- 
> 2.47.1
> 

Reply via email to