From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CA27EC02188 for ; Mon, 27 Jan 2025 11:59:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7981610E4F5; Mon, 27 Jan 2025 11:59:18 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="bhnkvlN3"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0553F10E4F5; Mon, 27 Jan 2025 11:59:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737979158; x=1769515158; h=from:to:subject:in-reply-to:references:date:message-id: mime-version; bh=gXJA3WlymS5e37fjCvNn+PrRjfKCMPqY6WEvale4hII=; b=bhnkvlN3x3Q2Y3N5DcLSiqCvC8s8p1QaE6ktC3ypSRw7NzEH9bUi3U2l 93fH8FDRnN0qxpSXM+0aEtwdMgHsca7N3RcgeAYyY4VOwPT81udlOJCqr fsd6QOGmep9ZtzN/MBYtJmRD590xQNLRBmO+CfiLSmQIsC49kEdqUAVXo wmBqXd3PD+P1D5JpZlRn+r2os4ARU+6wDvUxy0Ntdq5Sz1OOZzTzroPEP wvtA4mw32hy80GF8pKndd/yOkOxvg5w+68CMdTuKZaLwL5w2l7CgZ45An Z+m6+OSELgl7ZqJKAtXwvt1flHAAwbXD2Kcf0TpVJxZ1QkTBzvam7xvho g==; X-CSE-ConnectionGUID: vsV4qahaQaOQc2084PDgFw== X-CSE-MsgGUID: bQ7xy0DlTTuJjSA9jafIGQ== X-IronPort-AV: E=McAfee;i="6700,10204,11328"; a="42192165" X-IronPort-AV: E=Sophos;i="6.13,238,1732608000"; d="scan'208";a="42192165" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2025 03:59:17 -0800 X-CSE-ConnectionGUID: tYyIVLjAR2KHh6ZLAkQIYA== X-CSE-MsgGUID: FjFds2jgQPOI+n5wBS5YcQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="131713215" Received: from bergbenj-mobl1.ger.corp.intel.com (HELO localhost) ([10.245.246.14]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2025 03:59:15 -0800 From: Jani Nikula To: Gustavo Sousa , intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Subject: Re: [PATCH 2/4] drm/i915/dmc_wl: Add debugfs for untracked offsets In-Reply-To: <173797666856.2736.14360802368974999515@intel.com> Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo References: <20250117220747.87927-1-gustavo.sousa@intel.com> <20250117220747.87927-3-gustavo.sousa@intel.com> <87bjvsbnap.fsf@intel.com> <173797666856.2736.14360802368974999515@intel.com> Date: Mon, 27 Jan 2025 13:59:11 +0200 Message-ID: <8734h4bh80.fsf@intel.com> MIME-Version: 1.0 Content-Type: text/plain X-BeenThere: intel-xe@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Xe graphics driver List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-xe-bounces@lists.freedesktop.org Sender: "Intel-xe" On Mon, 27 Jan 2025, Gustavo Sousa wrote: > Quoting Jani Nikula (2025-01-27 06:47:58-03:00) >>On Fri, 17 Jan 2025, Gustavo Sousa 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 >>> >>> #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? Yes, using an opaque pointer is usually the way to go. Lately we've been adding debugfs next to the implementation. Often the debugfs needs access to the same stuff as the implementation, you can hide stuff and not have to expose a ton of interfaces. This could work here too... but I have to say this debugfs looks a bit, uh, bloated for want of a better word. Maybe having the separate file is worth it. BR, Jani. > > -- > 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 >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +#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 >>> +#include >>> + >>> +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 -- Jani Nikula, Intel