[PATCH v2] drm/xe: GPU frequency tracing support

Matthew Brost matthew.brost at intel.com
Mon Aug 11 20:05:37 UTC 2025


On Mon, Aug 11, 2025 at 02:04:14PM +0530, S Sebinraj wrote:
> A periodic GPU frequency monitoring and tracing program for the
> Xe driver. The implementation provides periodic sampling of
> GPU frequency through the Linux ftrace infrastructure.
> 
> Key features:
> - Periodic GPU frequency sampling with configurable intervals
> - Immediate frequency change reporting via tracepoints
> - Integration with Linux ftrace subsystem under 'power' events
> - Per-GT (Graphics Technology) monitoring support
> - Dedicated workqueue for non-blocking frequency sampling
> - Configurable via CONFIG_DRM_XE_GPUFREQTRACER kernel option
> - The monitoring interval can be configured at runtime via the sysfs
>   (default 5sec).
> 
> The sysfs entry is at:
> /sys/module/xe/parameters/gpufreq_monitoring_interval_ms
> 
> The tracepoint is exposed at:
> /sys/kernel/debug/tracing/events/power/gpu_frequency
> 
> Format: {unsigned int state, unsigned int gpu_id}
> - state: GPU frequency in KHz
> - gpu_id: GPU clock domain identifier
> 
> This enables userspace tools and system monitoring applications to track
> GPU frequency changes for power management analysis, performance tuning,
> and debugging purposes.
> 

Change logs are helpful during reviews. I also prefer replies to review
comments to ensure we are aligned on all points, even if the reply is as
simple as “+1.”

> Signed-off-by: S Sebinraj <s.sebinraj at intel.com>
> ---
>  drivers/gpu/drm/xe/Kconfig                  |  22 ++
>  drivers/gpu/drm/xe/Makefile                 |   3 +
>  drivers/gpu/drm/xe/xe_device.c              |   7 +
>  drivers/gpu/drm/xe/xe_device_types.h        |   4 +
>  drivers/gpu/drm/xe/xe_gpufreqtracer.c       | 292 ++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_gpufreqtracer.h       |  30 ++
>  drivers/gpu/drm/xe/xe_gpufreqtracer_trace.h |  48 ++++
>  drivers/gpu/drm/xe/xe_module.c              |  12 +
>  drivers/gpu/drm/xe/xe_module.h              |   3 +
>  9 files changed, 421 insertions(+)
>  create mode 100644 drivers/gpu/drm/xe/xe_gpufreqtracer.c
>  create mode 100644 drivers/gpu/drm/xe/xe_gpufreqtracer.h
>  create mode 100644 drivers/gpu/drm/xe/xe_gpufreqtracer_trace.h
> 
> diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
> index 714d5702dfd7..d9d07ec69875 100644
> --- a/drivers/gpu/drm/xe/Kconfig
> +++ b/drivers/gpu/drm/xe/Kconfig
> @@ -129,6 +129,28 @@ config DRM_XE_FORCE_PROBE
>  
>  	  Use "!*" to block the probe of the driver for all known devices.
>  
> +config DRM_XE_GPUFREQTRACER
> +	bool "Enable XE GPU frequency tracing"
> +	depends on DRM_XE && FTRACE
> +	default n
> +	help
> +	  Enable GPU frequency tracing support for Intel XE driver.
> +	  This adds an ftrace tracepoint that reports GPU frequency changes
> +	  at periodic boundaries (default 5 secs, configurable via the
> +	  gpufreq_monitoring_interval_ms module parameter) and
> +	  on direct frequency change events.
> +
> +	  The monitoring interval can be configured at runtime via the sysfs module parameter:
> +	  /sys/module/xe/parameters/gpufreq_monitoring_interval_ms
> +
> +	  The tracepoint will be available at:
> +	  /sys/kernel/debug/tracing/events/power/gpu_frequency
> +
> +	  Format: {unsigned int state, unsigned int gpu_id}
> +	  Where state is the frequency in KHz and gpu_id is the GPU clock domain.
> +
> +	  If unsure, say N.
> +
>  menu "drm/Xe Debugging"
>  depends on DRM_XE
>  depends on EXPERT
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index 8e0c3412a757..61d46cc4dc25 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -170,6 +170,9 @@ xe-$(CONFIG_PCI_IOV) += \
>  	xe_sriov_pf.o \
>  	xe_sriov_pf_service.o
>  
> +# GPU frequency tracer
> +xe-$(CONFIG_DRM_XE_GPUFREQTRACER) += xe_gpufreqtracer.o
> +
>  # include helpers for tests even when XE is built-in
>  ifdef CONFIG_DRM_XE_KUNIT_TEST
>  xe-y += tests/xe_kunit_helpers.o
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 57edbc63da6f..88198ceb519b 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -34,6 +34,7 @@
>  #include "xe_exec_queue.h"
>  #include "xe_force_wake.h"
>  #include "xe_ggtt.h"
> +#include "xe_gpufreqtracer.h"
>  #include "xe_gsc_proxy.h"
>  #include "xe_gt.h"
>  #include "xe_gt_mcr.h"
> @@ -896,6 +897,12 @@ int xe_device_probe(struct xe_device *xe)
>  	if (err)
>  		return err;
>  
> +#if IS_ENABLED(CONFIG_DRM_XE_GPUFREQTRACER)
> +	err = xe_gpufreqtracer_init(xe);
> +	if (err)
> +		return err;
> +#endif

If I wasn’t clear, you don’t need this if IS_ENABLED — the header file
already includes this and calls a stubbed-out version that does nothing
if CONFIG_DRM_XE_GPUFREQTRACER is unset.

> +
>  	err = xe_oa_init(xe);
>  	if (err)
>  		return err;
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
> index 01e8fa0d2f9f..0634dbbbdc3f 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -35,6 +35,7 @@ struct dram_info;
>  struct intel_display;
>  struct intel_dg_nvm_dev;
>  struct xe_ggtt;
> +struct xe_gpufreqtracer_data;
>  struct xe_i2c;
>  struct xe_pat_ops;
>  struct xe_pxp;
> @@ -529,6 +530,9 @@ struct xe_device {
>  	/** @oa: oa observation subsystem */
>  	struct xe_oa oa;
>  
> +	/** @gpufreqtracer_data: GPU frequency tracer data */
> +	struct xe_gpufreqtracer_data *gpufreqtracer_data;
> +
>  	/** @pxp: Encapsulate Protected Xe Path support */
>  	struct xe_pxp *pxp;
>  
> diff --git a/drivers/gpu/drm/xe/xe_gpufreqtracer.c b/drivers/gpu/drm/xe/xe_gpufreqtracer.c
> new file mode 100644
> index 000000000000..07eedfb79e93
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gpufreqtracer.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#include "xe_gpufreqtracer.h"
> +
> +#include <linux/workqueue.h>
> +#include <linux/slab.h>
> +#include <linux/jiffies.h>
> +#include <linux/kernel.h>
> +#include <linux/moduleparam.h>
> +#include <linux/types.h>
> +#include <linux/container_of.h>
> +#include <linux/gfp.h>
> +#include <linux/atomic.h>
> +#include <drm/drm_managed.h>
> +
> +#include "xe_device.h"
> +#include "xe_gt.h"
> +#include "xe_gt_types.h"
> +#include "xe_guc_pc.h"
> +#include "xe_module.h"
> +
> +/* GPU frequency monitoring interval constants (in milliseconds) */
> +#define XE_GPUFREQ_MONITORING_MIN_INTERVAL_MS	100
> +#define XE_GPUFREQ_MONITORING_MAX_INTERVAL_MS	10000
> +#define XE_GPUFREQ_MONITORING_DEFAULT_INTERVAL_MS	5000
> +
> +#define CREATE_TRACE_POINTS
> +#include "xe_gpufreqtracer_trace.h"
> +
> +/**
> + * struct xe_gpufreqtracer_gt_data - Per-GT frequency monitoring data
> + * @gt: Reference to the GT
> + * @delayed_work: Delayed work for periodic monitoring
> + * @last_frequency: Last reported frequency to avoid duplicate reports
> + * @monitoring_active: Whether monitoring is currently active
> + */
> +struct xe_gpufreqtracer_gt_data {
> +	struct xe_gt *gt;
> +	struct delayed_work delayed_work;
> +	atomic_t last_frequency;
> +	atomic_t monitoring_active;
> +};
> +
> +/**
> + * struct xe_gpufreqtracer_data - Per-device frequency tracer data
> + * @xe: Reference to the XE device
> + * @gt_data: Array of per-GT monitoring data
> + */
> +struct xe_gpufreqtracer_data {
> +	struct xe_device *xe;
> +	struct xe_gpufreqtracer_gt_data *gt_data;
> +};
> +
> +
> +/**
> + * xe_gpufreqtracer_sample_work - Worker function to sample GPU frequency.
> + * @work: Pointer to the delayed_work_struct representing the scheduled work.
> + *
> + * This function is executed in a workqueue context to periodically sample
> + * the GPU frequency and perform any necessary tracing or logging operations.
> + * It reschedules itself for the next sampling interval.
> + */
> +static void xe_gpufreqtracer_sample_work(struct work_struct *work)
> +{
> +	struct xe_gpufreqtracer_gt_data *gt_data =
> +		container_of(work, struct xe_gpufreqtracer_gt_data, delayed_work.work);
> +	struct xe_gt *gt = gt_data->gt;
> +	struct xe_guc_pc *pc = &gt->uc.guc.pc;
> +	u32 current_freq, last_freq;
> +
> +	if (!atomic_read(&gt_data->monitoring_active)) {
> +		drm_warn(&gt_to_xe(gt)->drm, "monitoring not active for GT%u, exiting",
> +			 gt->info.id);
> +		return;
> +	}
> +
> +	current_freq = xe_guc_pc_get_act_freq(pc) * 1000; /* Convert MHz to KHz */
> +	last_freq = atomic_read(&gt_data->last_frequency);

I don't think last_frequency needs to be atomic, as it is only modified
during initialization or by this worker. This worker executes serially
and fully owns this data, correct?
 
> +
> +	/* Only report if frequency has changed or this is the first sample */
> +	if (current_freq != last_freq) {
> +		drm_dbg(&gt_to_xe(gt)->drm, "GT%u frequency changed, tracing %u KHz",
> +			gt->info.id, current_freq);
> +		trace_gpu_frequency(current_freq, gt->info.id);
> +		atomic_set(&gt_data->last_frequency, current_freq);
> +	}
> +
> +	/* Reschedule for the next sampling interval if monitoring is still active */
> +	if (atomic_read(&gt_data->monitoring_active)) {

I don't think you need this if statement, as you already bail out early
above if this is clear. In the worst case, if this bit flips while
executing, the delayed worker would just run again and bail.

Nits aside, looks much in this version.

Matt

> +		schedule_delayed_work(&gt_data->delayed_work,
> +				      msecs_to_jiffies(xe_modparam.gpufreq_monitoring_interval_ms));
> +	}
> +}
> +
> +/**
> + * xe_gpufreqtracer_start_monitoring - Start periodic frequency monitoring
> + * @gt: The GT instance
> + *
> + * Starts periodic sampling of GPU frequency for the specified GT using the global
> + * monitoring interval from module parameters.
> + *
> + * Return: 0 on success, negative error code on failure
> + */
> +static int xe_gpufreqtracer_start_monitoring(struct xe_gt *gt)
> +{
> +	struct xe_gpufreqtracer_data *tracer_data = gt_to_xe(gt)->gpufreqtracer_data;
> +	struct xe_gpufreqtracer_gt_data *gt_data;
> +
> +	if (!tracer_data) {
> +		drm_warn(&gt_to_xe(gt)->drm, "no tracer data for GT%u, not supported", gt->info.id);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	if (gt->info.id >= gt_to_xe(gt)->info.gt_count) {
> +		drm_err(&gt_to_xe(gt)->drm, "invalid GT ID %u, max supported is %u",
> +			gt->info.id, gt_to_xe(gt)->info.gt_count - 1);
> +		return -EINVAL;
> +	}
> +
> +	gt_data = &tracer_data->gt_data[gt->info.id];
> +
> +	if (atomic_read(&gt_data->monitoring_active)) {
> +		drm_warn(&gt_to_xe(gt)->drm, "monitoring already active for GT%u", gt->info.id);
> +		return -EALREADY;
> +	}
> +
> +	atomic_set(&gt_data->monitoring_active, 1);
> +	atomic_set(&gt_data->last_frequency, 0);
> +
> +	/* Start the delayed work using global interval */
> +	schedule_delayed_work(&gt_data->delayed_work,
> +			      msecs_to_jiffies(xe_modparam.gpufreq_monitoring_interval_ms));
> +
> +	drm_dbg(&gt_to_xe(gt)->drm, "monitoring started for GT%u with interval %u ms",
> +		 gt->info.id, xe_modparam.gpufreq_monitoring_interval_ms);
> +
> +	return 0;
> +}
> +
> +/**
> + * xe_gpufreqtracer_stop_monitoring - Stop periodic frequency monitoring
> + * @gt: The GT instance
> + *
> + * Stops periodic sampling of GPU frequency for the specified GT.
> + */
> +static void xe_gpufreqtracer_stop_monitoring(struct xe_gt *gt)
> +{
> +	struct xe_gpufreqtracer_data *tracer_data = gt_to_xe(gt)->gpufreqtracer_data;
> +	struct xe_gpufreqtracer_gt_data *gt_data;
> +
> +	if (!tracer_data || gt->info.id >= gt_to_xe(gt)->info.gt_count) {
> +		drm_err(&gt_to_xe(gt)->drm, "invalid tracer data or GT ID %u for stop request",
> +			gt->info.id);
> +		return;
> +	}
> +
> +	gt_data = &tracer_data->gt_data[gt->info.id];
> +
> +	if (!atomic_read(&gt_data->monitoring_active)) {
> +		drm_warn(&gt_to_xe(gt)->drm, "monitoring not active for GT%u, nothing to stop",
> +			 gt->info.id);
> +		return;
> +	}
> +
> +	atomic_set(&gt_data->monitoring_active, 0);
> +
> +	cancel_delayed_work_sync(&gt_data->delayed_work);
> +}
> +
> +/**
> + * xe_gpufreqtracer_validate_params - Validate GPU frequency monitoring parameters
> + *
> + * Validates and corrects the GPU frequency monitoring interval parameter.
> + * If the parameter is out of range, it will be reset to the default value.
> + */
> +static void xe_gpufreqtracer_validate_params(void)
> +{
> +	if (xe_modparam.gpufreq_monitoring_interval_ms < XE_GPUFREQ_MONITORING_MIN_INTERVAL_MS ||
> +	    xe_modparam.gpufreq_monitoring_interval_ms > XE_GPUFREQ_MONITORING_MAX_INTERVAL_MS) {
> +		pr_warn("xe: gpufreq_monitoring_interval_ms %u out of range [%u, %u], using default %u ms\n",
> +			xe_modparam.gpufreq_monitoring_interval_ms,
> +			XE_GPUFREQ_MONITORING_MIN_INTERVAL_MS,
> +			XE_GPUFREQ_MONITORING_MAX_INTERVAL_MS,
> +			XE_GPUFREQ_MONITORING_DEFAULT_INTERVAL_MS);
> +		xe_modparam.gpufreq_monitoring_interval_ms = XE_GPUFREQ_MONITORING_DEFAULT_INTERVAL_MS;
> +	}
> +}
> +
> +/**
> + * xe_gpufreqtracer_cleanup_action - DRM managed cleanup action
> + * @drm: DRM device
> + * @ptr: Pointer to xe_device
> + *
> + * Cleanup function called automatically by DRM managed resource system.
> + */
> +static void xe_gpufreqtracer_cleanup_action(struct drm_device *drm, void *ptr)
> +{
> +	struct xe_device *xe = ptr;
> +	struct xe_gpufreqtracer_data *tracer_data = xe->gpufreqtracer_data;
> +	struct xe_gt *gt;
> +	u8 tile_id;
> +
> +	if (!tracer_data) {
> +		drm_warn(drm, "no tracer data found, nothing to cleanup");
> +		return;
> +	}
> +
> +	/* Stop all monitoring */
> +	for_each_gt(gt, xe, tile_id) {
> +		drm_dbg(drm, "stopping monitoring for GT%u", gt->info.id);
> +		xe_gpufreqtracer_stop_monitoring(gt);
> +	}
> +
> +	/* Memory is automatically freed by drmm - just clear the pointer */
> +	xe->gpufreqtracer_data = NULL;
> +}
> +
> +/**
> + * xe_gpufreqtracer_init - Initialize GPU frequency tracer for a device
> + * @xe: The XE device
> + *
> + * Sets up the frequency tracer infrastructure for all GTs in the device.
> + *
> + * Return: 0 on success, negative error code on failure
> + */
> +int xe_gpufreqtracer_init(struct xe_device *xe)
> +{
> +	struct xe_gpufreqtracer_data *tracer_data;
> +	struct xe_gt *gt;
> +	u8 tile_id;
> +	int ret = 0;
> +
> +	/* Validate module parameters first */
> +	xe_gpufreqtracer_validate_params();
> +
> +	tracer_data = drmm_kzalloc(&xe->drm, sizeof(*tracer_data), GFP_KERNEL);
> +	if (!tracer_data)
> +		return -ENOMEM;
> +
> +	tracer_data->xe = xe;
> +
> +	/* Allocate GT data array based on actual GT count */
> +	tracer_data->gt_data = drmm_kcalloc(&xe->drm, xe->info.gt_count,
> +				       sizeof(*tracer_data->gt_data),
> +				       GFP_KERNEL);
> +	if (!tracer_data->gt_data) {
> +		ret = -ENOMEM;
> +		goto err_free_tracer;
> +	}
> +
> +	/* Initialize per-GT data */
> +	for_each_gt(gt, xe, tile_id) {
> +		struct xe_gpufreqtracer_gt_data *gt_data =
> +			&tracer_data->gt_data[gt->info.id];
> +
> +		drm_dbg(&xe->drm, "initializing GT%u (tile %u)", gt->info.id, tile_id);
> +
> +		gt_data->gt = gt;
> +		atomic_set(&gt_data->monitoring_active, 0);
> +		atomic_set(&gt_data->last_frequency, 0);
> +
> +		INIT_DELAYED_WORK(&gt_data->delayed_work, xe_gpufreqtracer_sample_work);
> +
> +		drm_dbg(&xe->drm, "GT%u initialized with global interval=%u ms",
> +			 gt->info.id, xe_modparam.gpufreq_monitoring_interval_ms);
> +	}
> +
> +	xe->gpufreqtracer_data = tracer_data;
> +
> +	/* Start periodic monitoring on all GTs using global module parameter */
> +	for_each_gt(gt, xe, tile_id) {
> +		ret = xe_gpufreqtracer_start_monitoring(gt);
> +		if (ret) {
> +			drm_err(&xe->drm, "xe_gpufreqtracer: failed to start monitoring for GT%u, err=%d\n",
> +				gt->info.id, ret);
> +		}
> +	}
> +
> +	/* Register cleanup action for proper work cancellation */
> +	ret = drmm_add_action(&xe->drm, xe_gpufreqtracer_cleanup_action, xe);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +
> +err_free_tracer:
> +	drm_err(&xe->drm, "initialization failed, freeing tracer data");
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_gpufreqtracer.h b/drivers/gpu/drm/xe/xe_gpufreqtracer.h
> new file mode 100644
> index 000000000000..561abe27b6e2
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gpufreqtracer.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _XE_GPUFREQTRACER_H_
> +#define _XE_GPUFREQTRACER_H_
> +
> +#include <linux/types.h>
> +
> +struct xe_device;
> +struct xe_gt;
> +
> +#ifdef CONFIG_DRM_XE_GPUFREQTRACER
> +
> +/*
> + * Initialize the GPU frequency tracer for a device
> + */
> +int xe_gpufreqtracer_init(struct xe_device *xe);
> +
> +#else /* CONFIG_DRM_XE_GPUFREQTRACER */
> +
> +static inline int xe_gpufreqtracer_init(struct xe_device *xe)
> +{
> +	return 0;
> +}
> +
> +#endif /* CONFIG_DRM_XE_GPUFREQTRACER */
> +
> +#endif /* _XE_GPUFREQTRACER_H_ */
> diff --git a/drivers/gpu/drm/xe/xe_gpufreqtracer_trace.h b/drivers/gpu/drm/xe/xe_gpufreqtracer_trace.h
> new file mode 100644
> index 000000000000..5664db62e3fb
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gpufreqtracer_trace.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM power
> +
> +#if !defined(_XE_GPUFREQTRACER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _XE_GPUFREQTRACER_TRACE_H
> +
> +#include <linux/tracepoint.h>
> +
> +/*
> + * Tracepoint for GPU frequency changes
> + * This tracepoint is exposed at /sys/kernel/debug/tracing/events/power/gpu_frequency
> + *
> + * location: /d/events/power/gpu_frequency
> + * format: {unsigned int state, unsigned int gpu_id}
> + * where state holds the frequency(in Khz) and the gpu_id holds the GPU clock domain.
> + */
> +
> +TRACE_EVENT(gpu_frequency,
> +	TP_PROTO(unsigned int state, unsigned int gpu_id),
> +
> +	TP_ARGS(state, gpu_id),
> +
> +	TP_STRUCT__entry(
> +		__field(unsigned int, state)
> +		__field(unsigned int, gpu_id)
> +	),
> +
> +	TP_fast_assign(
> +		__entry->state = state;
> +		__entry->gpu_id = gpu_id;
> +	),
> +
> +	TP_printk("state=%u gpu_id=%u", __entry->state, __entry->gpu_id)
> +);
> +
> +#endif /* _XE_GPUFREQTRACER_TRACE_H */
> +
> +/* This part must be outside protection */
> +#undef TRACE_INCLUDE_PATH
> +#undef TRACE_INCLUDE_FILE
> +#define TRACE_INCLUDE_PATH .
> +#define TRACE_INCLUDE_FILE xe_gpufreqtracer_trace
> +#include <trace/define_trace.h>
> diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c
> index d08338fc3bc1..f5d4f8bca61f 100644
> --- a/drivers/gpu/drm/xe/xe_module.c
> +++ b/drivers/gpu/drm/xe/xe_module.c
> @@ -31,6 +31,7 @@
>  #define DEFAULT_MAX_VFS_STR		"unlimited"
>  #define DEFAULT_WEDGED_MODE		1
>  #define DEFAULT_SVM_NOTIFIER_SIZE	512
> +#define DEFAULT_GPUFREQ_MONITORING_INTERVAL_MS	5000
>  
>  struct xe_modparam xe_modparam = {
>  	.probe_display =	DEFAULT_PROBE_DISPLAY,
> @@ -41,6 +42,9 @@ struct xe_modparam xe_modparam = {
>  #endif
>  	.wedged_mode =		DEFAULT_WEDGED_MODE,
>  	.svm_notifier_size =	DEFAULT_SVM_NOTIFIER_SIZE,
> +#ifdef CONFIG_DRM_XE_GPUFREQTRACER
> +	.gpufreq_monitoring_interval_ms = DEFAULT_GPUFREQ_MONITORING_INTERVAL_MS,
> +#endif
>  	/* the rest are 0 by default */
>  };
>  
> @@ -93,6 +97,14 @@ MODULE_PARM_DESC(wedged_mode,
>  		 "Module's default policy for the wedged mode (0=never, 1=upon-critical-errors, 2=upon-any-hang "
>  		 "[default=" __stringify(DEFAULT_WEDGED_MODE) "])");
>  
> +#ifdef CONFIG_DRM_XE_GPUFREQTRACER
> +module_param_named(gpufreq_monitoring_interval_ms,
> +		   xe_modparam.gpufreq_monitoring_interval_ms, uint, 0644);
> +MODULE_PARM_DESC(gpufreq_monitoring_interval_ms,
> +		 "GPU frequency monitoring interval in milliseconds (100-10000, default: "
> +		 __stringify(DEFAULT_GPUFREQ_MONITORING_INTERVAL_MS) ")");
> +#endif
> +
>  static int xe_check_nomodeset(void)
>  {
>  	if (drm_firmware_drivers_only())
> diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h
> index 5a3bfea8b7b4..fd60de38d24d 100644
> --- a/drivers/gpu/drm/xe/xe_module.h
> +++ b/drivers/gpu/drm/xe/xe_module.h
> @@ -23,6 +23,9 @@ struct xe_modparam {
>  #endif
>  	int wedged_mode;
>  	u32 svm_notifier_size;
> +#ifdef CONFIG_DRM_XE_GPUFREQTRACER
> +	u32 gpufreq_monitoring_interval_ms;
> +#endif
>  };
>  
>  extern struct xe_modparam xe_modparam;
> -- 
> 2.34.1
> 


More information about the Intel-xe mailing list