* [RFC PATCH 0/2] Implement stats layer to measure events
@ 2024-07-25 15:05 Nirmoy Das
2024-07-25 15:05 ` [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events Nirmoy Das
2024-07-25 15:05 ` [PATCH] drm/xe: Keep track of TLB inval events Nirmoy Das
0 siblings, 2 replies; 7+ messages in thread
From: Nirmoy Das @ 2024-07-25 15:05 UTC (permalink / raw)
To: intel-xe; +Cc: Nirmoy Das, Matthew Brost
Add basic stats layer to track and show stats of various events over
debugfs. Tagging it as RFC to gather inputs on how the final
APIs/implementation should look like.
Cc: Matthew Brost <matthew.brost@intel.com>
Nirmoy Das (2):
drm/xe: Implement APIs for measuring various events
drm/xe: Keep track of TLB inval events
drivers/gpu/drm/xe/Kconfig.debug | 11 ++
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_gt_debugfs.c | 11 ++
drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 31 +++--
drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 1 +
drivers/gpu/drm/xe/xe_gt_types.h | 4 +
drivers/gpu/drm/xe/xe_stats.c | 145 ++++++++++++++++++++
drivers/gpu/drm/xe/xe_stats.h | 66 +++++++++
drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
9 files changed, 262 insertions(+), 10 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe_stats.c
create mode 100644 drivers/gpu/drm/xe/xe_stats.h
--
2.42.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events
2024-07-25 15:05 [RFC PATCH 0/2] Implement stats layer to measure events Nirmoy Das
@ 2024-07-25 15:05 ` Nirmoy Das
2024-07-25 15:42 ` Matthew Brost
2024-07-25 15:48 ` Michal Wajdeczko
2024-07-25 15:05 ` [PATCH] drm/xe: Keep track of TLB inval events Nirmoy Das
1 sibling, 2 replies; 7+ messages in thread
From: Nirmoy Das @ 2024-07-25 15:05 UTC (permalink / raw)
To: intel-xe; +Cc: Nirmoy Das, Matthew Brost
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=a, Size: 6881 bytes --]
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@intel.com>
Signed-off-by: Nirmoy Das <nirmoy.das@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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH] drm/xe: Keep track of TLB inval events
2024-07-25 15:05 [RFC PATCH 0/2] Implement stats layer to measure events Nirmoy Das
2024-07-25 15:05 ` [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events Nirmoy Das
@ 2024-07-25 15:05 ` Nirmoy Das
1 sibling, 0 replies; 7+ messages in thread
From: Nirmoy Das @ 2024-07-25 15:05 UTC (permalink / raw)
To: intel-xe; +Cc: Nirmoy Das
Use stats API to keep track of TLB invalidation events per GT.
Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
---
drivers/gpu/drm/xe/xe_gt_debugfs.c | 10 +++++++
drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 31 +++++++++++++++------
drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 1 +
drivers/gpu/drm/xe/xe_gt_types.h | 4 +++
drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
5 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
index 5e7fd937917a..28a9aa18d3bc 100644
--- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
@@ -17,6 +17,7 @@
#include "xe_gt_mcr.h"
#include "xe_gt_sriov_pf_debugfs.h"
#include "xe_gt_sriov_vf_debugfs.h"
+#include "xe_gt_tlb_invalidation.h"
#include "xe_gt_topology.h"
#include "xe_hw_engine.h"
#include "xe_lrc.h"
@@ -27,6 +28,7 @@
#include "xe_reg_sr.h"
#include "xe_reg_whitelist.h"
#include "xe_sriov.h"
+#include "xe_stats.h"
#include "xe_uc_debugfs.h"
#include "xe_wa.h"
@@ -288,6 +290,12 @@ static const struct drm_info_list debugfs_list[] = {
{"default_lrc_vecs", .show = xe_gt_debugfs_simple_show, .data = vecs_default_lrc},
};
+static void xe_gt_debugfs_stats_register(struct xe_gt *gt, struct dentry *root)
+{
+ gt->stats = xe_stats_init(>_to_xe(gt)->drm, root);
+ xe_gt_tlb_invalidation_stats_init(gt);
+}
+
void xe_gt_debugfs_register(struct xe_gt *gt)
{
struct xe_device *xe = gt_to_xe(gt);
@@ -321,4 +329,6 @@ void xe_gt_debugfs_register(struct xe_gt *gt)
xe_gt_sriov_pf_debugfs_register(gt, root);
else if (IS_SRIOV_VF(xe))
xe_gt_sriov_vf_debugfs_register(gt, root);
+
+ xe_gt_debugfs_stats_register(gt, root);
}
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
index 87cb76a8718c..60f9b8bc4121 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
@@ -37,11 +37,13 @@ static long tlb_timeout_jiffies(struct xe_gt *gt)
}
static void
-__invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence)
+__invalidation_fence_signal(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence)
{
+ struct xe_device *xe = gt_to_xe(gt);
bool stack = test_bit(FENCE_STACK_BIT, &fence->base.flags);
trace_xe_gt_tlb_invalidation_fence_signal(xe, fence);
+ xe_stats_decrement_counter(gt->stats, "TLB_INVAL_INFLIGHT");
xe_gt_tlb_invalidation_fence_fini(fence);
dma_fence_signal(&fence->base);
if (!stack)
@@ -49,10 +51,10 @@ __invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_
}
static void
-invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence)
+invalidation_fence_signal(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence)
{
list_del(&fence->link);
- __invalidation_fence_signal(xe, fence);
+ __invalidation_fence_signal(gt, fence);
}
static void xe_gt_tlb_fence_timeout(struct work_struct *work)
@@ -76,7 +78,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
fence->seqno, gt->tlb_invalidation.seqno_recv);
fence->base.error = -ETIME;
- invalidation_fence_signal(xe, fence);
+ invalidation_fence_signal(gt, fence);
}
if (!list_empty(>->tlb_invalidation.pending_fences))
queue_delayed_work(system_wq,
@@ -140,7 +142,7 @@ void xe_gt_tlb_invalidation_reset(struct xe_gt *gt)
list_for_each_entry_safe(fence, next,
>->tlb_invalidation.pending_fences, link)
- invalidation_fence_signal(gt_to_xe(gt), fence);
+ invalidation_fence_signal(gt, fence);
spin_unlock_irq(>->tlb_invalidation.pending_lock);
mutex_unlock(>->uc.guc.ct.lock);
}
@@ -183,6 +185,9 @@ static int send_tlb_invalidation(struct xe_guc *guc,
ret = xe_guc_ct_send_locked(&guc->ct, action, len,
G2H_LEN_DW_TLB_INVALIDATE, 1);
if (!ret) {
+ xe_stats_increment_counter(gt->stats, "TLB_INVAL_INFLIGHT");
+ xe_stats_increment_counter(gt->stats, "TLB_INVAL_TOTAL_SENT");
+
spin_lock_irq(>->tlb_invalidation.pending_lock);
/*
* We haven't actually published the TLB fence as per
@@ -191,7 +196,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
* we can just go ahead and signal the fence here.
*/
if (tlb_invalidation_seqno_past(gt, seqno)) {
- __invalidation_fence_signal(xe, fence);
+ __invalidation_fence_signal(gt, fence);
} else {
fence->invalidation_time = ktime_get();
list_add_tail(&fence->link,
@@ -204,7 +209,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
}
spin_unlock_irq(>->tlb_invalidation.pending_lock);
} else if (ret < 0) {
- __invalidation_fence_signal(xe, fence);
+ __invalidation_fence_signal(gt, fence);
}
if (!ret) {
gt->tlb_invalidation.seqno = (gt->tlb_invalidation.seqno + 1) %
@@ -321,7 +326,7 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
/* Execlists not supported */
if (gt_to_xe(gt)->info.force_execlist) {
- __invalidation_fence_signal(xe, fence);
+ __invalidation_fence_signal(gt, fence);
return 0;
}
@@ -455,7 +460,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
if (!tlb_invalidation_seqno_past(gt, fence->seqno))
break;
- invalidation_fence_signal(xe, fence);
+ invalidation_fence_signal(gt, fence);
}
if (!list_empty(>->tlb_invalidation.pending_fences))
@@ -525,3 +530,11 @@ void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fenc
{
xe_pm_runtime_put(gt_to_xe(fence->gt));
}
+
+void xe_gt_tlb_invalidation_stats_init(struct xe_gt *gt)
+{
+ xe_stats_add_entry(gt->stats, "TLB_INVAL_TOTAL_SENT",
+ XE_STATS_TYPE_COUNTER);
+ xe_stats_add_entry(gt->stats, "TLB_INVAL_INFLIGHT",
+ XE_STATS_TYPE_COUNTER);
+}
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
index a84065fa324c..62180379cc40 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
@@ -36,4 +36,5 @@ xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence)
dma_fence_wait(&fence->base, false);
}
+void xe_gt_tlb_invalidation_stats_init(struct xe_gt *gt);
#endif /* _XE_GT_TLB_INVALIDATION_ */
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index 631928258d71..702b21ac611a 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -15,6 +15,7 @@
#include "xe_oa.h"
#include "xe_reg_sr_types.h"
#include "xe_sa_types.h"
+#include "xe_stats.h"
#include "xe_uc_types.h"
struct xe_exec_queue_ops;
@@ -133,6 +134,9 @@ struct xe_gt {
u8 has_indirect_ring_state:1;
} info;
+ /* @stats: Track stats of various events, currently TLB inval */
+ struct xe_stats *stats;
+
/**
* @mmio: mmio info for GT. All GTs within a tile share the same
* register space, but have their own copy of GSI registers at a
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index c1dcf58d25d7..0e51d853fa4a 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -258,7 +258,7 @@ uc_fw_override(struct xe_uc_fw *uc_fw)
path_override = xe_modparam.huc_firmware_path;
break;
case XE_UC_FW_TYPE_GSC:
- path_override = xe_modparam.gsc_firmware_path;
+ path_override = "";
break;
default:
break;
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events
2024-07-25 15:05 ` [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events Nirmoy Das
@ 2024-07-25 15:42 ` Matthew Brost
2024-07-25 15:48 ` Michal Wajdeczko
1 sibling, 0 replies; 7+ messages in thread
From: Matthew Brost @ 2024-07-25 15:42 UTC (permalink / raw)
To: Nirmoy Das; +Cc: intel-xe
On Thu, Jul 25, 2024 at 05:05:44PM +0200, Nirmoy Das wrote:
> 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.
>
Idea is right but thinking the implementation is overly complicated.
Roughly what I think, in this example a GT stat.
struct xe_gt {
...
#if IS_ENABLED(CONFIG_DRM_XE_STATS)
struct {
atomic_t value[XE_GT_STAT_COUNT];
} stats;
#endif
...
};
enum xe_gt_stat {
XE_GT_STAT_FOO,
XE_GT_STAT_COUNT,
};
void xe_gt_stats_incr(struct xe_gt *gt, enum xe_gt_stat xe_gt_stat, int incr)
{
atomic_add(incr, >->stats.value[xe_gt_stat]);
}
static const char *stat_description[] = {
"foo",
};
void xe_gt_stats_print_info(struct xe_gt *gt, struct drm_printer *p)
{
enum xe_gt_stat xe_gt_stat;
for (xe_gt_stat = 0; xe_gt_stat < XE_GT_STAT_COUNT; ++xe_gt_stat)
drm_printf(p, "%s: %d\n", stat_description[xe_gt_stat],
atomic_read(>->stats.value[xe_gt_stat]));
}
With xe_gt_stats_incr used at the caller which wants to increment stat:
xe_gt_stats_incr(gt, XE_GT_STAT_FOO, 1);
Add a 'stats' GT debugfs entry (see xe_gt_debugfs.c) which calls
'xe_gt_stats_print_info'.
We can also add 'xe_device' stats too.
This is simplier as no need to configure stats, just add an enum + table
entry, and incr caller.
Also leverages existing debugfs code, honors existing layering, and no
need to malloc anything either.
Matt
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Nirmoy Das <nirmoy.das@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
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events
2024-07-25 15:05 ` [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events Nirmoy Das
2024-07-25 15:42 ` Matthew Brost
@ 2024-07-25 15:48 ` Michal Wajdeczko
2024-07-25 16:27 ` Matthew Brost
1 sibling, 1 reply; 7+ messages in thread
From: Michal Wajdeczko @ 2024-07-25 15:48 UTC (permalink / raw)
To: Nirmoy Das, intel-xe; +Cc: Matthew Brost
On 25.07.2024 17:05, Nirmoy Das wrote:
> 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@intel.com>
> Signed-off-by: Nirmoy Das <nirmoy.das@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;
hmm, this seems to be very costly and likely will not scale well once we
would like to add more counters
can't we just use CONFIG_DRM_XE_STATS to hide different stats structures
provide nop variants of the helpers that would update them ?
> + }
> +
> + 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_ */
> +
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events
2024-07-25 15:48 ` Michal Wajdeczko
@ 2024-07-25 16:27 ` Matthew Brost
2024-07-25 16:41 ` Nirmoy Das
0 siblings, 1 reply; 7+ messages in thread
From: Matthew Brost @ 2024-07-25 16:27 UTC (permalink / raw)
To: Michal Wajdeczko; +Cc: Nirmoy Das, intel-xe
On Thu, Jul 25, 2024 at 05:48:34PM +0200, Michal Wajdeczko wrote:
>
>
> On 25.07.2024 17:05, Nirmoy Das wrote:
> > 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@intel.com>
> > Signed-off-by: Nirmoy Das <nirmoy.das@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;
>
> hmm, this seems to be very costly and likely will not scale well once we
> would like to add more counters
>
Agree this won't scale well. See my suggestion a reply to Nirmoy. Let me
know what you think.
Matt
> can't we just use CONFIG_DRM_XE_STATS to hide different stats structures
> provide nop variants of the helpers that would update them ?
>
> > + }
> > +
> > + 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_ */
> > +
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events
2024-07-25 16:27 ` Matthew Brost
@ 2024-07-25 16:41 ` Nirmoy Das
0 siblings, 0 replies; 7+ messages in thread
From: Nirmoy Das @ 2024-07-25 16:41 UTC (permalink / raw)
To: Matthew Brost, Michal Wajdeczko; +Cc: intel-xe
On 7/25/2024 6:27 PM, Matthew Brost wrote:
> On Thu, Jul 25, 2024 at 05:48:34PM +0200, Michal Wajdeczko wrote:
>>
>> On 25.07.2024 17:05, Nirmoy Das wrote:
>>> 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@intel.com>
>>> Signed-off-by: Nirmoy Das <nirmoy.das@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;
>> hmm, this seems to be very costly and likely will not scale well once we
>> would like to add more counters
Both of you came to the same conclusion :) I have enough hints now. Let
me spin up the next
simpler version next week.
Thanks,
Nirmoy
>>
> Agree this won't scale well. See my suggestion a reply to Nirmoy. Let me
> know what you think.
>
> Matt
>
>> can't we just use CONFIG_DRM_XE_STATS to hide different stats structures
>> provide nop variants of the helpers that would update them ?
>>
>>> + }
>>> +
>>> + 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_ */
>>> +
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-07-25 16:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-25 15:05 [RFC PATCH 0/2] Implement stats layer to measure events Nirmoy Das
2024-07-25 15:05 ` [RFC PATCH 1/2] drm/xe: Implement APIs for measuring various events Nirmoy Das
2024-07-25 15:42 ` Matthew Brost
2024-07-25 15:48 ` Michal Wajdeczko
2024-07-25 16:27 ` Matthew Brost
2024-07-25 16:41 ` Nirmoy Das
2024-07-25 15:05 ` [PATCH] drm/xe: Keep track of TLB inval events Nirmoy Das
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox