* [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
* 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
* [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
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