From: Gustavo Sousa <gustavo.sousa@intel.com>
To: Jani Nikula <jani.nikula@linux.intel.com>,
<intel-gfx@lists.freedesktop.org>,
<intel-xe@lists.freedesktop.org>
Subject: Re: [PATCH 2/4] drm/i915/dmc_wl: Add debugfs for untracked offsets
Date: Mon, 27 Jan 2025 08:17:48 -0300 [thread overview]
Message-ID: <173797666856.2736.14360802368974999515@intel.com> (raw)
In-Reply-To: <87bjvsbnap.fsf@intel.com>
Quoting Jani Nikula (2025-01-27 06:47:58-03:00)
>On Fri, 17 Jan 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
>> diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.h b/drivers/gpu/drm/i915/display/intel_dmc_wl.h
>> index 5488fbdf29b8..d11b0ab50b3c 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.h
>> +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.h
>> @@ -11,6 +11,7 @@
>> #include <linux/refcount.h>
>>
>> #include "i915_reg_defs.h"
>> +#include "intel_dmc_wl_debugfs.h"
>>
>> struct intel_display;
>>
>> @@ -27,6 +28,7 @@ struct intel_dmc_wl {
>> */
>> u32 dc_state;
>> struct delayed_work work;
>> + struct intel_dmc_wl_dbg dbg;
>> };
>>
>
>With intel_de.h including intel_dmc_wl.h, we'll have almost all of
>display include intel_dmc_wl_debugfs.h, and getting the definition of
>struct intel_dmc_wl_dbg, really for no good reason.
>
>I really like to flip this around. You need to have a *good reason* to
>expose stuff to the entire display driver all of a sudden. Instead of
>requiring a good reason to hide stuff.
Maybe make dbg a pointer and have only intel_dmc_wl.c knowing its guts?
Or do you have some other suggestion?
--
Gustavo Sousa
>
>BR,
>Jani.
>
>
>
>> void intel_dmc_wl_init(struct intel_display *display);
>> diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.c b/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.c
>> new file mode 100644
>> index 000000000000..41e59d775fe5
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.c
>> @@ -0,0 +1,251 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright (C) 2025 Intel Corporation
>> + */
>> +
>> +#include <linux/debugfs.h>
>> +
>> +#include <drm/drm_device.h>
>> +#include <drm/drm_managed.h>
>> +#include <drm/drm_print.h>
>> +
>> +#include "intel_display_core.h"
>> +#include "intel_dmc_wl_debugfs.h"
>> +
>> +#define DEBUGFS_UNTRACKED_BUFFER_SIZE_MAX 65536
>> +
>> +/*
>> + * DOC: DMC wakelock debugfs
>> + *
>> + * The DMC wakelock code needs to keep track of register offsets that need the
>> + * wakelock for proper access. If one of the necessary offsets are missed, then
>> + * the failure in asserting the wakelock is very likely to cause problems down
>> + * the road.
>> + *
>> + * A miss could happen for at least two different reasons:
>> + *
>> + * - We might have forgotten to add the offset (or range) to the relevant
>> + * tables tracked by the driver in the first place.
>> + *
>> + * - Or updates to either the DMC firmware or the display IP that require new
>> + * offsets to be tracked and we fail to realize that.
>> + *
>> + * To help capture these cases, we provide the intel_dmc_wl/ debugfs directory,
>> + * which exports a buffer of untracked register offsets.
>> + *
>> + * Untracked offsets
>> + * -----------------
>> + *
>> + * This is a buffer that records every register offset that went through the
>> + * DMC wakelock check and was deemed not needing the wakelock for MMIO access.
>> + *
>> + * To activate the logging of offsets into such a buffer, one can do::
>> + *
>> + * # echo -1 > /sys/kernel/debug/dri/(...)/intel_dmc_wl/untracked_size
>> + *
>> + * This will create a buffer with the maximum number of entries allowed
>> + * (DEBUGFS_UNTRACKED_BUFFER_SIZE_MAX). A positive value can be used instead to
>> + * define a different size:
>> + *
>> + * # echo 1024 > /sys/kernel/debug/dri/(...)/intel_dmc_wl/untracked_size
>> + *
>> + * Every write to untracked_size will cause the buffer to be reset.
>> + *
>> + * It is also possible to read untracked_size in order to get the current
>> + * value.
>> + *
>> + * After enabled, the buffer starts getting filled with offsets as MMIOs are
>> + * performed by the driver.
>> + *
>> + * In order to view the content of the buffer, one can do::
>> + *
>> + * # cat /sys/kernel/debug/dri/(...)/intel_dmc_wl/untracked
>> + * 0x000c4000
>> + * 0x0016fe50
>> + * 0x000c7200
>> + * 0x000c7204
>> + * 0x00045230
>> + * 0x00046440
>> + * 0x00045234
>> + * 0x0016fa48
>> + * 0x0016fa40
>> + * 0x0016fa5c
>> + * (...)
>> + *
>> + * The order of those offsets does not reflect the order the checks were done
>> + * (some recently seen offsets are skipped to save space).
>> + *
>> + * Once done with it, the logging can be disabled with::
>> + *
>> + * # echo 0 > /sys/kernel/debug/dri/(...)/intel_dmc_wl/untracked_size
>> + */
>> +
>> +static int untracked_size_get(void *data, u64 *val)
>> +{
>> + struct intel_display *display = data;
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&dbg->lock, flags);
>> + *val = dbg->untracked.size;
>> + spin_unlock_irqrestore(&dbg->lock, flags);
>> +
>> + return 0;
>> +}
>> +
>> +static int untracked_size_set(void *data, u64 val)
>> +{
>> + struct intel_display *display = data;
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> + s64 new_size;
>> + u32 *old_offsets;
>> + u32 *new_offsets;
>> + unsigned long flags;
>> +
>> + new_size = (s64)val;
>> +
>> + if (new_size == -1) {
>> + new_size = DEBUGFS_UNTRACKED_BUFFER_SIZE_MAX;
>> + } else if (new_size < 0) {
>> + drm_err(display->drm,
>> + "%lld is invalid for untracked_size, the only negative value allowed is -1\n",
>> + new_size);
>> + return -EINVAL;
>> + } else if (new_size > DEBUGFS_UNTRACKED_BUFFER_SIZE_MAX) {
>> + drm_err(display->drm,
>> + "%lld too big for untracked_size, maximum allowed value is %d\n",
>> + new_size,
>> + DEBUGFS_UNTRACKED_BUFFER_SIZE_MAX);
>> + return -EINVAL;
>> + }
>> +
>> + if (new_size == 0) {
>> + new_offsets = NULL;
>> + } else {
>> + new_offsets = drmm_kmalloc_array(display->drm, new_size, sizeof(*new_offsets),
>> + GFP_KERNEL);
>> +
>> + if (!new_offsets)
>> + return -ENOMEM;
>> + }
>> +
>> + spin_lock_irqsave(&dbg->lock, flags);
>> + old_offsets = dbg->untracked.offsets;
>> + dbg->untracked.offsets = new_offsets;
>> + dbg->untracked.size = new_size;
>> + dbg->untracked.head = 0;
>> + dbg->untracked.len = 0;
>> + dbg->untracked.overflow = false;
>> + spin_unlock_irqrestore(&dbg->lock, flags);
>> +
>> + if (old_offsets)
>> + drmm_kfree(display->drm, old_offsets);
>> +
>> + return 0;
>> +}
>> +
>> +DEFINE_SIMPLE_ATTRIBUTE_SIGNED(untracked_size_fops,
>> + untracked_size_get,
>> + untracked_size_set,
>> + "%lld\n");
>> +
>> +static int untracked_show(struct seq_file *m, void *data)
>> +{
>> + struct intel_display *display = m->private;
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> + unsigned long flags;
>> + size_t remaining;
>> + size_t i;
>> +
>> + spin_lock_irqsave(&dbg->lock, flags);
>> +
>> + remaining = dbg->untracked.len;
>> + i = dbg->untracked.head;
>> +
>> + while (remaining--) {
>> + if (i == 0)
>> + i = dbg->untracked.size;
>> +
>> + seq_printf(m, "0x%08x\n", dbg->untracked.offsets[--i]);
>> + }
>> +
>> + spin_unlock_irqrestore(&dbg->lock, flags);
>> +
>> + return 0;
>> +}
>> +
>> +DEFINE_SHOW_ATTRIBUTE(untracked);
>> +
>> +void intel_dmc_wl_debugfs_init(struct intel_display *display)
>> +{
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> +
>> + spin_lock_init(&dbg->lock);
>> +}
>> +
>> +void intel_dmc_wl_debugfs_register(struct intel_display *display)
>> +{
>> + struct dentry *dir;
>> +
>> + if (!HAS_DMC_WAKELOCK(display))
>> + return;
>> +
>> + dir = debugfs_create_dir("intel_dmc_wl", display->drm->debugfs_root);
>> + if (IS_ERR(dir))
>> + return;
>> +
>> + debugfs_create_file("untracked_size", 0644, dir, display,
>> + &untracked_size_fops);
>> + debugfs_create_file("untracked", 0644, dir, display,
>> + &untracked_fops);
>> +}
>> +
>> +static bool untracked_has_recent_offset(struct intel_display *display, u32 offset)
>> +{
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> + int look_back = 32;
>> + size_t i;
>> +
>> + if (look_back > dbg->untracked.len)
>> + look_back = dbg->untracked.len;
>> +
>> + i = dbg->untracked.head;
>> +
>> + while (look_back--) {
>> + if (i == 0)
>> + i = dbg->untracked.size;
>> +
>> + if (dbg->untracked.offsets[--i] == offset)
>> + return true;
>> + }
>> +
>> + return false;
>> +}
>> +
>> +void intel_dmc_wl_debugfs_log_untracked(struct intel_display *display, u32 offset)
>> +{
>> + struct intel_dmc_wl_dbg *dbg = &display->wl.dbg;
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&dbg->lock, flags);
>> +
>> + if (!dbg->untracked.size)
>> + goto out_unlock;
>> +
>> + /* Save some space by not repeating recent offsets. */
>> + if (untracked_has_recent_offset(display, offset))
>> + goto out_unlock;
>> +
>> + dbg->untracked.offsets[dbg->untracked.head] = offset;
>> + dbg->untracked.head = (dbg->untracked.head + 1) % dbg->untracked.size;
>> + if (dbg->untracked.len < dbg->untracked.size)
>> + dbg->untracked.len++;
>> +
>> + if (dbg->untracked.len == dbg->untracked.size && !dbg->untracked.overflow) {
>> + dbg->untracked.overflow = true;
>> + drm_warn(display->drm, "Overflow detected in DMC wakelock debugfs untracked offsets\n");
>> + }
>> +
>> +out_unlock:
>> + spin_unlock_irqrestore(&dbg->lock, flags);
>> +}
>> diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.h b/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.h
>> new file mode 100644
>> index 000000000000..9437c324966f
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl_debugfs.h
>> @@ -0,0 +1,29 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright (C) 2025 Intel Corporation
>> + */
>> +
>> +#ifndef __INTEL_DMC_WL_DEBUGFS_H__
>> +#define __INTEL_DMC_WL_DEBUGFS_H__
>> +
>> +#include <linux/types.h>
>> +#include <linux/spinlock.h>
>> +
>> +struct intel_display;
>> +
>> +struct intel_dmc_wl_dbg {
>> + spinlock_t lock; /* protects everything below */
>> + struct {
>> + u32 *offsets;
>> + size_t head;
>> + size_t len;
>> + size_t size;
>> + bool overflow;
>> + } untracked;
>> +};
>> +
>> +void intel_dmc_wl_debugfs_init(struct intel_display *display);
>> +void intel_dmc_wl_debugfs_register(struct intel_display *display);
>> +void intel_dmc_wl_debugfs_log_untracked(struct intel_display *display, u32 offset);
>> +
>> +#endif /* __INTEL_DMC_WL_DEBUGFS_H__ */
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index 81f63258a7e1..f03fbdbcb1a4 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -221,6 +221,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
>> i915-display/intel_display_wa.o \
>> i915-display/intel_dkl_phy.o \
>> i915-display/intel_dmc.o \
>> + i915-display/intel_dmc_wl_debugfs.o \
>> i915-display/intel_dp.o \
>> i915-display/intel_dp_aux.o \
>> i915-display/intel_dp_aux_backlight.o \
>
>--
>Jani Nikula, Intel
next prev parent reply other threads:[~2025-01-27 11:18 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-17 22:06 [PATCH 0/4] drm/i915/dmc_wl: Introduce debugfs interface Gustavo Sousa
2025-01-17 22:06 ` [PATCH 1/4] drm/i915/dmc_wl: Pass offset instead of reg to range table iterator Gustavo Sousa
2025-01-22 8:23 ` Luca Coelho
2025-01-17 22:06 ` [PATCH 2/4] drm/i915/dmc_wl: Add debugfs for untracked offsets Gustavo Sousa
2025-01-22 9:06 ` Luca Coelho
2025-01-23 14:41 ` Gustavo Sousa
2025-01-30 9:33 ` Luca Coelho
2025-01-23 16:11 ` Vivekanandan, Balasubramani
2025-01-23 16:41 ` Gustavo Sousa
2025-01-30 8:54 ` Vivekanandan, Balasubramani
2025-01-27 9:47 ` Jani Nikula
2025-01-27 11:17 ` Gustavo Sousa [this message]
2025-01-27 11:59 ` Jani Nikula
2025-01-27 12:55 ` Gustavo Sousa
2025-01-17 22:06 ` [PATCH 3/4] drm/i915/dmc_wl: Add extra_ranges debugfs Gustavo Sousa
2025-01-22 10:19 ` Luca Coelho
2025-01-23 15:52 ` Gustavo Sousa
2025-01-30 9:18 ` Luca Coelho
2025-01-30 8:30 ` Vivekanandan, Balasubramani
2025-01-30 8:49 ` Vivekanandan, Balasubramani
2025-01-17 22:06 ` [PATCH 4/4] drm/i915/dmc_wl: Enable the debugfs only with enable_dmc_wl_debugfs=1 Gustavo Sousa
2025-01-22 10:24 ` Luca Coelho
2025-01-23 16:10 ` Gustavo Sousa
2025-01-30 9:28 ` Luca Coelho
2025-01-27 12:01 ` Jani Nikula
2025-01-27 12:02 ` Jani Nikula
2025-01-27 13:24 ` Gustavo Sousa
2025-01-27 13:35 ` Jani Nikula
2025-01-27 13:50 ` Gustavo Sousa
2025-01-27 14:40 ` Jani Nikula
2025-01-30 8:46 ` Vivekanandan, Balasubramani
2025-01-17 22:14 ` ✓ CI.Patch_applied: success for drm/i915/dmc_wl: Introduce debugfs interface Patchwork
2025-01-17 22:15 ` ✗ CI.checkpatch: warning " Patchwork
2025-01-17 22:16 ` ✓ CI.KUnit: success " Patchwork
2025-01-17 22:34 ` ✓ CI.Build: " Patchwork
2025-01-17 22:36 ` ✓ CI.Hooks: " Patchwork
2025-01-17 22:38 ` ✓ CI.checksparse: " Patchwork
2025-01-17 23:06 ` ✓ Xe.CI.BAT: " Patchwork
2025-01-18 13:06 ` ✗ Xe.CI.Full: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=173797666856.2736.14360802368974999515@intel.com \
--to=gustavo.sousa@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox