[RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events

Nirmoy Das nirmoy.das at intel.com
Thu Jul 25 15:05:44 UTC 2024


Introduces a set of APIs for tracking and managing events.
This currently only supports counters.

This can be conditionally enabled with the CONFIG_DRM_XE_STATS
config option.

Cc: Matthew Brost <matthew.brost at intel.com>
Signed-off-by: Nirmoy Das <nirmoy.das at intel.com>
---
 drivers/gpu/drm/xe/Kconfig.debug |  11 +++
 drivers/gpu/drm/xe/Makefile      |   1 +
 drivers/gpu/drm/xe/xe_stats.c    | 145 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_stats.h    |  66 ++++++++++++++
 4 files changed, 223 insertions(+)
 create mode 100644 drivers/gpu/drm/xe/xe_stats.c
 create mode 100644 drivers/gpu/drm/xe/xe_stats.h

diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug
index bc177368af6c..4db6d707c1af 100644
--- a/drivers/gpu/drm/xe/Kconfig.debug
+++ b/drivers/gpu/drm/xe/Kconfig.debug
@@ -94,3 +94,14 @@ config DRM_XE_USERPTR_INVAL_INJECT
 
 	 Recomended for driver developers only.
 	 If in doubt, say "N".
+
+config DRM_XE_STATS
+	bool "Enable XE statistics"
+	default n
+	help
+	  Choose this option to enable support for collecting and
+	  displaying XE statistics as debugfs.
+
+	  Recommended for driver developers only.
+
+	  If in doubt, say "N".
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 1ff9602a52f6..c5d9ec22c6bf 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -117,6 +117,7 @@ xe-y += xe_bb.o \
 	xe_wopcm.o
 
 xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o
+xe-$(CONFIG_DRM_XE_STATS) += xe_stats.o
 
 # graphics hardware monitoring (HWMON) support
 xe-$(CONFIG_HWMON) += xe_hwmon.o
diff --git a/drivers/gpu/drm/xe/xe_stats.c b/drivers/gpu/drm/xe/xe_stats.c
new file mode 100644
index 000000000000..1b8910900fd3
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_stats.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_print.h>
+
+#include "xe_stats.h"
+
+#ifdef CONFIG_DRM_XE_STATS
+static struct xe_stats_entry *find_stats_entry(struct xe_stats *stats, const char *name)
+{
+	struct xe_stats_entry *stats_entry;
+
+	list_for_each_entry(stats_entry, &stats->entries, list) {
+		if (strcmp(stats_entry->name, name) == 0)
+			return stats_entry;
+	}
+
+	return NULL;
+}
+
+static int stats_show(struct seq_file *m, void *v)
+{
+	struct xe_stats_entry *entry = m->private;
+
+	if (entry && !entry->enabled)
+		return 0;
+
+	switch (entry->type) {
+	case XE_STATS_TYPE_COUNTER:
+		seq_printf(m, "%s: Counter value: %llu\n", entry->name,
+			   atomic64_read(&entry->data.counter.value));
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_show, inode->i_private);
+}
+
+static const struct file_operations stats_fops = {
+	.owner   = THIS_MODULE,
+	.open    = stats_open,
+	.read    = seq_read,
+	.release = single_release,
+};
+
+struct xe_stats *xe_stats_init(struct drm_device *drm, struct dentry *parent)
+{
+	struct xe_stats *stats;
+
+	stats = drmm_kzalloc(drm, sizeof(*stats), GFP_KERNEL);
+	if (!stats) {
+		drm_err(drm, "Failed to allocate memory for xe_stats\n");
+		return NULL;
+	}
+
+	stats->drm = drm;
+	INIT_LIST_HEAD(&stats->entries);
+
+	stats->debugfs_entry = debugfs_create_dir("stats", parent);
+	if (!stats->debugfs_entry) {
+		drm_err(drm, "Failed to create stats debugfs directory\n");
+		return NULL;
+	}
+
+	return stats;
+}
+
+void xe_stats_add_entry(struct xe_stats *stats, const char *name, enum xe_stats_type type)
+{
+	struct xe_stats_entry *entry;
+	struct dentry *debugfs_entry;
+
+	if (!stats || !name)
+		return;
+
+	entry = drmm_kzalloc(stats->drm, sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return;
+
+	entry->name = drmm_kstrdup(stats->drm, name, GFP_KERNEL);
+	if (!entry->name)
+		return;
+
+	entry->type = type;
+	entry->enabled = true;
+
+	switch (type) {
+	case XE_STATS_TYPE_COUNTER:
+		atomic64_set(&entry->data.counter.value, 0);
+		break;
+	default:
+		return;
+	}
+
+	list_add(&entry->list, &stats->entries);
+
+	debugfs_entry = debugfs_create_file(name, 0444, stats->debugfs_entry, entry, &stats_fops);
+	if (!debugfs_entry) {
+		drm_err(stats->drm, "Failed to create stats debugfs file for %s\n", name);
+		list_del(&entry->list);
+		return;
+	}
+
+	entry->dentry = debugfs_entry;
+}
+
+void xe_stats_increment_counter(struct xe_stats *stats, const char *name)
+{
+	struct xe_stats_entry *entry;
+
+	if (!stats || !name)
+		return;
+
+	entry = find_stats_entry(stats, name);
+	if (entry && entry->type == XE_STATS_TYPE_COUNTER && entry->enabled)
+		atomic64_inc(&entry->data.counter.value);
+}
+
+void xe_stats_decrement_counter(struct xe_stats *stats, const char *name)
+{
+	struct xe_stats_entry *entry;
+
+	if (!stats || !name)
+		return;
+
+	entry = find_stats_entry(stats, name);
+	if (entry && entry->type == XE_STATS_TYPE_COUNTER && entry->enabled)
+		atomic64_dec(&entry->data.counter.value);
+}
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_stats.h b/drivers/gpu/drm/xe/xe_stats.h
new file mode 100644
index 000000000000..dba79ae28714
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_stats.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+#ifndef _XE_STATS_H_
+#define _XE_STATS_H_
+
+#include <linux/atomic.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <drm/drm_print.h>
+
+struct drm_device;
+
+enum xe_stats_type {
+	XE_STATS_TYPE_COUNTER,
+};
+
+#ifdef CONFIG_DRM_XE_STATS
+struct xe_stats_entry {
+	const char *name;
+	enum xe_stats_type type;
+	bool enabled;
+	union {
+		struct {
+			atomic64_t value;
+		} counter;
+	} data;
+	struct list_head list;
+	struct dentry *dentry;
+};
+
+struct xe_stats {
+	struct dentry *debugfs_entry;
+	struct list_head entries;
+	struct drm_device *drm;
+};
+
+struct xe_stats *xe_stats_init(struct drm_device *drm, struct dentry *parent);
+void xe_stats_add_entry(struct xe_stats *stats, const char *name, enum xe_stats_type type);
+void xe_stats_increment_counter(struct xe_stats *c, const char *name);
+void xe_stats_decrement_counter(struct xe_stats *stats, const char *name);
+
+#else /* CONFIG_DRM_XE_STATS not defined */
+struct xe_stats;
+
+static inline struct xe_stats *
+xe_stats_init(struct drm_device *drm, struct dentry *parent)
+{
+	return NULL;
+}
+
+static inline void
+xe_stats_add_entry(struct xe_stats *stats, const char *name, enum xe_stats_type type) { }
+static inline void
+xe_stats_increment_counter(struct xe_stats *stats, const char *name) { }
+static inline void
+xe_stats_decrement_counter(struct xe_stats *stats, const char *name) { }
+
+#endif /* CONFIG_DRM_XE_STATS */
+
+#endif /* _XE_STATS_H_ */
+
-- 
2.42.0



More information about the Intel-xe mailing list