[RFC 04/15] drm/xe: Implement xe_access_counter_init

Himal Prasad Ghimiray
2026-03-18T07:10:19Z

Implement initialization for access counter queues and per-queue
workers. Reuse the existing page fault workqueue (pf_wq) as both
subsystems are part of the same USM domain.

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/xe_access_counter.c | 45 +++++++++++++++++++++++++-
drivers/gpu/drm/xe/xe_device.c | 5 +++
drivers/gpu/drm/xe/xe_device_types.h | 4 +++
3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_access_counter.c b/drivers/gpu/drm/xe/xe_access_counter.c
index f3a8a93b5135..cafcc42897f8 100644
--- a/drivers/gpu/drm/xe/xe_access_counter.c
+++ b/drivers/gpu/drm/xe/xe_access_counter.c
@@ -11,6 +11,7 @@
#include "xe_access_counter.h"
#include "xe_access_counter_types.h"
#include "xe_device.h"
+#include "xe_usm_queue.h"

/**
* DOC: Xe access counters
@@ -27,6 +28,38 @@
* xe_access_counter.c implements the consumer layer.
*/

+static int xe_access_counter_entry_size(void)
+{
+ return roundup_pow_of_two(sizeof(struct xe_access_counter));
+}
+
+static void xe_access_counter_queue_work_func(struct work_struct *w)
+{
+ /* TODO: Implement */
+}
+
+static int xe_access_counter_queue_init(struct xe_device *xe,
+ struct xe_usm_queue *ac_queue)
+{
+ /*
+ * Allocate a fixed-size queue for access counter notifications.
+ * Size is determined based on hardware capabilities.
+ */
+#define XE_ACCESS_COUNTER_QUEUE_NUM_ENTRIES 128
+ ac_queue->size = XE_ACCESS_COUNTER_QUEUE_NUM_ENTRIES *
+ xe_access_counter_entry_size();
+#undef XE_ACCESS_COUNTER_QUEUE_NUM_ENTRIES
+
+ ac_queue->data = devm_kzalloc(xe->drm.dev, ac_queue->size, GFP_KERNEL);
+ if (!ac_queue->data)
+ return -ENOMEM;
+
+ spin_lock_init(&ac_queue->lock);
+ INIT_WORK(&ac_queue->worker, xe_access_counter_queue_work_func);
+
+ return 0;
+}
+
/**
* xe_access_counter_init - Initialize access counter consumer layer
* @xe: xe device
@@ -35,7 +68,17 @@
*/
int xe_access_counter_init(struct xe_device *xe)
{
- /* Stub implementation - to be filled in */
+ int err, i;
+
+ if (!xe->info.has_usm)
+ return 0;
+
+ for (i = 0; i < XE_ACCESS_COUNTER_QUEUE_COUNT; ++i) {
+ err = xe_access_counter_queue_init(xe, xe->usm.ac_queue + i);
+ if (err)
+ return err;
+ }
+
return 0;
}

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index e77a3a3db73d..8773c2d2f69a 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -23,6 +23,7 @@
#include "instructions/xe_gpu_commands.h"
#include "regs/xe_gt_regs.h"
#include "regs/xe_regs.h"
+#include "xe_access_counter.h"
#include "xe_bo.h"
#include "xe_bo_evict.h"
#include "xe_debugfs.h"
@@ -933,6 +934,10 @@ int xe_device_probe(struct xe_device *xe)
if (err)
return err;

+ err = xe_access_counter_init(xe);
+ if (err)
+ return err;
+
if (xe->tiles->media_gt &&
XE_GT_WA(xe->tiles->media_gt, 15015404425_disable))
XE_DEVICE_WA_DISABLE(xe, 15015404425);
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index b9231544e500..526cfd09d0b9 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -12,6 +12,7 @@
#include <drm/drm_file.h>
#include <drm/ttm/ttm_device.h>

+#include "xe_access_counter_types.h"
#include "xe_devcoredump_types.h"
#include "xe_drm_ras_types.h"
#include "xe_heci_gsc.h"
@@ -311,6 +312,9 @@ struct xe_device {
#define XE_PAGEFAULT_QUEUE_COUNT 4
/** @usm.pf_queue: Page fault queues */
struct xe_usm_queue pf_queue[XE_PAGEFAULT_QUEUE_COUNT];
+#define XE_ACCESS_COUNTER_QUEUE_COUNT 4
+ /** @usm.ac_queue: Access counter queues */
+ struct xe_usm_queue ac_queue[XE_ACCESS_COUNTER_QUEUE_COUNT];
#if IS_ENABLED(CONFIG_DRM_XE_PAGEMAP)
/** @usm.pagemap_shrinker: Shrinker for unused pagemaps */
struct drm_pagemap_shrinker *dpagemap_shrinker;
--
2.34.1