RE: [PATCH v3 4/4] drm/xe/sysctrl: Add RAS error injection debugfs interface

"Gupta, Anshuman" <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <BN9PR11MB5242AF76995E0453ABF7878A95D12@BN9PR11MB5242.namprd11.prod.outlook.com>

> -----Original Message-----
> From: Vijay, Anoop C <[email protected]>
> Sent: Friday, August 7, 2026 8:26 PM
> To: [email protected]
> Cc: Nerlige Ramappa, Umesh <[email protected]>; Nilawar,
> Badal <[email protected]>; Vivi, Rodrigo <[email protected]>;
> Iddamsetty, Aravind <[email protected]>; Tauro, Riana
> <[email protected]>; Gupta, Anshuman <[email protected]>;
> Roper, Matthew D <[email protected]>; Ruhl, Michael J
> <[email protected]>; Luse, Paul E <[email protected]>; V,
> Mohamed Mansoor <[email protected]>; Nasim, Kam
> <[email protected]>; Vijay, Anoop C <[email protected]>
> Subject: [PATCH v3 4/4] drm/xe/sysctrl: Add RAS error injection debugfs
> interface
> 
> From: Anoop Vijay <[email protected]>
> 
> Add debugfs interface for exercising System Controller's RAS error injection
> command, used to validate RAS error detection and recovery paths.
> 
> Command details:
> - Group ID: 0x02 (diag group)
> - Command ID: 0x7E (XE_SYSCTRL_CMD_DIAG_RAS_ERR_INJECT)
> - Usage: echo "<ras_block_id> <ras_sub_block_id> <err_type> [params]" \
>              > /sys/kernel/debug/dri/0/sc/ras_error_inject
>          cat /sys/kernel/debug/dri/0/sc/ras_error_inject
> 
> This command requires the diag application to have completed firmware
> boot and initialization (late-bind loaded); writes are rejected with -ENODEV
> until xe_sysctrl_is_diag_fw_ready() reports the diag firmware as ready.
> 
> Signed-off-by: Anoop Vijay <[email protected]>
> ---
>  drivers/gpu/drm/xe/xe_sysctrl_debugfs.c       | 123 ++++++++++++++++++
>  drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h |  31 +++++
>  drivers/gpu/drm/xe/xe_sysctrl_types.h         |   3 +
>  3 files changed, 157 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_debugfs.c
> b/drivers/gpu/drm/xe/xe_sysctrl_debugfs.c
> index 2144d9d43fba..7b8846d739cb 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_debugfs.c
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_debugfs.c
> @@ -10,6 +10,7 @@
>  #include <linux/seq_file.h>
>  #include <linux/slab.h>
>  #include <linux/string.h>
> +#include <linux/string_choices.h>
>  #include <linux/uaccess.h>
> 
>  #include "xe_device.h"
> @@ -122,6 +123,124 @@ static const struct file_operations
> xe_sysctrl_loopback_fops = {
>  	.release = single_release,
>  };
> 
> +static ssize_t xe_sysctrl_ras_error_inject_write(struct file *file, const char
> __user *ubuf,
> +						 size_t len, loff_t *offp)
> +{
> +	char *kbuf __free(kfree) = NULL;
> +	struct seq_file *m = file->private_data;
> +	struct xe_sysctrl_debugfs_entry *entry = m->private;
> +	struct xe_device *xe = sc_to_xe(entry->sc);
> +	struct xe_sysctrl_diag_ras_err_inj_req req = {};
> +	struct xe_sysctrl_mailbox_command cmd = {};
> +	u8 resp_hdr_only[sizeof(u32)];
> +	unsigned int nfields = 0;
> +	char *token, *tmp;
> +	unsigned long val;
> +	size_t out_len = 0;
> +
> +	if (!xe_sysctrl_is_diag_fw_ready(xe)) {
> +		xe_err(xe, "sysctrl: diag firmware not ready, cannot inject RAS
> error\n");
Wild thought, 
How it would be register the debugfs only if  diag firmware is loaded ?
That way nobody will be having access to these debugfs ? 

Thanks,
Anshuman.

> +		return -ENODEV;
> +	}
> +
> +	if (len == 0 || len >= PAGE_SIZE)
> +		return -EINVAL;
> +
> +	kbuf = kmalloc(len + 1, GFP_KERNEL);
> +	if (!kbuf)
> +		return -ENOMEM;
> +
> +	if (copy_from_user(kbuf, ubuf, len))
> +		return -EFAULT;
> +	kbuf[len] = '\0';
> +
> +	tmp = kbuf;
> +	while ((token = strsep(&tmp, " \t\n")) != NULL) {
> +		if (*token == '\0')
> +			continue;
> +
> +		if (kstrtoul(token, 0, &val))
> +			goto inval;
> +
> +		switch (nfields) {
> +		case 0:
> +			if (val > U16_MAX)
> +				goto inval;
> +			req.ras_block_id = val;
> +			break;
> +		case 1:
> +			if (val > U16_MAX)
> +				goto inval;
> +			req.ras_sub_block_id = val;
> +			break;
> +		case 2:
> +			if (val > U16_MAX)
> +				goto inval;
> +			req.err_type = val;
> +			break;
> +		case 3:
> +			if (val > U32_MAX)
> +				goto inval;
> +			req.params = val;
> +			break;
> +		default:
> +			xe_err(xe, "sysctrl: too many ras_error_inject
> arguments\n");
> +			return -EINVAL;
> +		}
> +		nfields++;
> +	}
> +
> +	if (nfields < 3) {
> +		xe_err(xe,
> +		       "sysctrl: usage: <ras_block_id> <ras_sub_block_id>
> <err_type> [params]\n");
> +		return -EINVAL;
> +	}
> +
> +	xe_sysctrl_create_command(&cmd, entry->group, entry->command,
> +				  &req, sizeof(req), resp_hdr_only,
> +				  sizeof(resp_hdr_only));
> +
> +	guard(xe_pm_runtime)(xe);
> +	entry->status = xe_sysctrl_send_command(entry->sc, &cmd,
> &out_len);
> +
> +	return entry->status ? entry->status : len;
> +
> +inval:
> +	xe_err(xe, "sysctrl: invalid ras_error_inject token '%s'\n", token);
> +	return -EINVAL;
> +}
> +
> +static int xe_sysctrl_ras_error_inject_show(struct seq_file *m, void
> +*data) {
> +	struct xe_sysctrl_debugfs_entry *entry = m->private;
> +	struct xe_device *xe = sc_to_xe(entry->sc);
> +
> +	seq_printf(m, "Command: group=0x%02x cmd=0x%02x\n", entry-
> >group, entry->command);
> +	seq_printf(m, "Diag firmware ready: %s\n",
> +		   str_yes_no(xe_sysctrl_is_diag_fw_ready(xe)));
> +	seq_printf(m, "Status: %d (%s)\n", entry->status, entry->status ?
> +"FAILED" : "SUCCESS");
> +
> +	seq_puts(m, "\nUsage:\n");
> +	seq_puts(m, "  echo \"<ras_block_id> <ras_sub_block_id>
> <err_type> [params]\" > ras_error_inject\n");
> +	seq_puts(m, "  cat ras_error_inject\n");
> +
> +	return 0;
> +}
> +
> +static int xe_sysctrl_ras_error_inject_open(struct inode *inode, struct
> +file *file) {
> +	return single_open(file, xe_sysctrl_ras_error_inject_show,
> +inode->i_private); }
> +
> +static const struct file_operations xe_sysctrl_ras_error_inject_fops = {
> +	.owner = THIS_MODULE,
> +	.open = xe_sysctrl_ras_error_inject_open,
> +	.read = seq_read,
> +	.write = xe_sysctrl_ras_error_inject_write,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +};
> +
>  static void xe_sysctrl_register_entry(struct dentry *root, struct
> xe_sysctrl_debugfs_entry *entry,
>  				      struct xe_sysctrl *sc, const char *name,
>  				      u8 group, u8 command,
> @@ -154,4 +273,8 @@ void xe_sysctrl_debugfs_register(struct xe_sysctrl
> *sc, struct dentry *parent)
>  	xe_sysctrl_register_entry(root, &sc->debugfs.loopback, sc,
> "loopback",
>  				  XE_SYSCTRL_GROUP_CORE,
> XE_SYSCTRL_CMD_LOOPBACK,
>  				  &xe_sysctrl_loopback_fops);
> +
> +	xe_sysctrl_register_entry(root, &sc->debugfs.ras_error_inject, sc,
> "ras_error_inject",
> +				  XE_SYSCTRL_GROUP_DIAG,
> XE_SYSCTRL_CMD_DIAG_RAS_ERR_INJECT,
> +				  &xe_sysctrl_ras_error_inject_fops);
>  }
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> index ed80fe63e1c4..43ae0049b316 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> @@ -14,10 +14,12 @@
>   * enum xe_sysctrl_group - System Controller command groups
>   *
>   * @XE_SYSCTRL_GROUP_GFSP: GFSP group
> + * @XE_SYSCTRL_GROUP_DIAG: Diag group
>   * @XE_SYSCTRL_GROUP_CORE: Core group
>   */
>  enum xe_sysctrl_group {
>  	XE_SYSCTRL_GROUP_GFSP			= 0x01,
> +	XE_SYSCTRL_GROUP_DIAG			= 0x02,
>  	XE_SYSCTRL_GROUP_CORE			= 0xFF,
>  };
> 
> @@ -51,6 +53,35 @@ enum xe_sysctrl_core_cmd {
>  	XE_SYSCTRL_CMD_GET_APP_STATUS_BY_ID		= 0x05,
>  };
> 
> +/**
> + * enum xe_sysctrl_diag_cmd - Commands supported by Diag group
> + *
> + * @XE_SYSCTRL_CMD_DIAG_RAS_ERR_INJECT: RAS error injection  */
> enum
> +xe_sysctrl_diag_cmd {
> +	XE_SYSCTRL_CMD_DIAG_RAS_ERR_INJECT		= 0x7E,
> +};
> +
> +/**
> + * struct xe_sysctrl_diag_ras_err_inj_req - DIAG_RAS_ERR_INJECT request
> +payload
> + *
> + * Request payload for XE_SYSCTRL_CMD_DIAG_RAS_ERR_INJECT. The
> mailbox
> +layer
> + * prepends the application message header before sending.
> + *
> + * @ras_block_id: RAS block (subsystem) to inject the error into
> + * @ras_sub_block_id: RAS sub-block (IP) within @ras_block_id
> + * @err_type: Type of test error to inject
> + * @reserved: Must be zero
> + * @params: Optional injection parameters (default 0)  */ struct
> +xe_sysctrl_diag_ras_err_inj_req {
> +	u16 ras_block_id;
> +	u16 ras_sub_block_id;
> +	u16 err_type;
> +	u16 reserved;
> +	u32 params;
> +} __packed;
> +
>  /**
>   * struct xe_sysctrl_app_status_req - Get application status request
>   *
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h
> b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> index 53d82e61383a..3a97a10d1b7d 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_types.h
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> @@ -68,6 +68,9 @@ struct xe_sysctrl {
> 
>  		/** @debugfs.loopback: Loopback test entry */
>  		struct xe_sysctrl_debugfs_entry loopback;
> +
> +		/** @debugfs.ras_error_inject: RAS error injection test entry
> */
> +		struct xe_sysctrl_debugfs_entry ras_error_inject;
>  	} debugfs;
>  };
> 
> --
> 2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.