From: "Vivi, Rodrigo" <rodrigo.vivi@intel.com>
To: "Summers, Stuart" <stuart.summers@intel.com>,
"Roper, Matthew D" <matthew.d.roper@intel.com>
Cc: "intel-xe@lists.freedesktop.org" <intel-xe@lists.freedesktop.org>,
"Brost, Matthew" <matthew.brost@intel.com>,
"Lin, Shuicheng" <shuicheng.lin@intel.com>,
"Tauro, Riana" <riana.tauro@intel.com>,
"Ceraolo Spurio, Daniele" <daniele.ceraolospurio@intel.com>,
"Nerlige Ramappa, Umesh" <umesh.nerlige.ramappa@intel.com>,
"Wajdeczko, Michal" <michal.wajdeczko@intel.com>
Subject: Re: [PATCH 05/10] drm/xe: Move debug configfs entries to xe_configfs_debug.c
Date: Fri, 28 Aug 2026 18:57:01 +0000 [thread overview]
Message-ID: <7c9244d92621b96fc8c2e6a9a455143f970e6fcb.camel@intel.com> (raw)
In-Reply-To: <a32e54d6e4e73a16b05817ea8cbd88c4e233f3c9.camel@intel.com>
On Fri, 2026-08-28 at 18:51 +0000, Summers, Stuart wrote:
> On Fri, 2026-08-28 at 10:31 -0700, Matt Roper wrote:
> > On Fri, Aug 28, 2026 at 09:34:48AM -0700, Summers, Stuart wrote:
> > > On Wed, 2026-08-26 at 17:20 -0400, Rodrigo Vivi wrote:
> > > > On Mon, Aug 24, 2026 at 08:28:59PM +0000, Summers, Stuart
> > > > wrote:
> > > > > On Fri, 2026-08-21 at 15:18 -0700, Matt Roper wrote:
> > > > > > On Thu, Aug 20, 2026 at 09:06:44PM +0000, Stuart Summers
> > > > > > wrote:
> > > > > > > Move the debug specific configfs attributes into the new
> > > > > > > xe_configfs_debug.c file under a new debug configfs
> > > > > > > subdirectory.
> > > > > > > Ensure these are wrapped in CONFIG_DRM_XE_DEBUG to allow
> > > > > > > finer
> > > > > > > grained
> > > > > > > debug changes outside of more ABI specific configfs
> > > > > > > entries.
> > > > > > >
> > > > > > > Signed-off-by: Stuart Summers <stuart.summers@intel.com>
> > > > > > > Assisted-by: Copilot:claude-sonnet-4.6,claude-sonnet-
> > > > > > > 5,claude-
> > > > > > > opus-
> > > > > > > 5
> > > > > > > ---
> > > > > > > drivers/gpu/drm/xe/xe_configfs.c | 991 ++-----
> > > > > > > --
> > > > > > > ----
> > > > > > > ----
> > > > > > > ----
> > > > > > > drivers/gpu/drm/xe/xe_configfs.h | 88 +-
> > > > > > > drivers/gpu/drm/xe/xe_configfs_debug.c | 956
> > > > > > > ++++++++++++++++++++
> > > > > > > drivers/gpu/drm/xe/xe_configfs_debug.h | 39 +-
> > > > > > > drivers/gpu/drm/xe/xe_configfs_types.h | 18 +-
> > > > > > > drivers/gpu/drm/xe/xe_guc.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_guc_ads.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_hw_engine.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_lrc.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_pci.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_psmi.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_rtp.c | 1 +
> > > > > > > drivers/gpu/drm/xe/xe_survivability_mode.c | 1 +
> > > > > > > 13 files changed, 1134 insertions(+), 966 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_configfs.c
> > > > > > > b/drivers/gpu/drm/xe/xe_configfs.c
> > > > > > > index 33aea1150c86..111aacce8a84 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_configfs.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_configfs.c
> > > > > > > @@ -6,17 +6,14 @@
> > > > > > > #include <linux/bitops.h>
> > > > > > > #include <linux/configfs.h>
> > > > > > > #include <linux/cleanup.h>
> > > > > > > -#include <linux/find.h>
> > > > > > > #include <linux/init.h>
> > > > > > > #include <linux/module.h>
> > > > > > > #include <linux/pci.h>
> > > > > > > #include <linux/string.h>
> > > > > > >
> > > > > > > -#include "instructions/xe_mi_commands.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > #include "xe_configfs_debug.h"
> > > > > > > #include "xe_defaults.h"
> > > > > > > -#include "xe_gt_types.h"
> > > > > > > #include "xe_module.h"
> > > > > > >
> > > > > > > /**
> > > > > > > @@ -50,16 +47,9 @@
> > > > > > > *
> > > > > > > * /sys/kernel/config/xe/
> > > > > > > * ├── 0000:00:02.0
> > > > > > > - * │ └── ...
> > > > > > > - * ├── 0000:00:02.1
> > > > > > > - * │ └── ...
> > > > > > > - * :
> > > > > > > - * └── 0000:03:00.0
> > > > > > > - * ├── engines_allowed
> > > > > > > - * ├── gt_types_allowed
> > > > > > > - * ├── enable_multi_queue
> > > > > > > - * ├── enable_psmi
> > > > > > > - * └── survivability_mode
> > > > > > > + * │ └── ...
> > > > > > > + * └── 0000:00:02.1
> > > > > > > + * └── ...
> > > > > > > *
> > > > > > > * After configuring the attributes as per next section,
> > > > > > > the
> > > > > > > device can be
> > > > > > > * probed with::
> > > > > > > @@ -71,157 +61,6 @@
> > > > > > > * Configure Attributes
> > > > > > > * ====================
> > > > > > > *
> > > > > > > -
> > > > > > > - * Context restore BB
> > > > > > > - * ------------------
> > > > > > > - *
> > > > > > > - * Allow to execute a batch buffer during any context
> > > > > > > switches.
> > > > > > > When the
> > > > > > > - * GPU is restoring the context, it executes additional
> > > > > > > commands.
> > > > > > > It's useful
> > > > > > > - * for testing additional workarounds and validating
> > > > > > > certain
> > > > > > > HW
> > > > > > > behaviors: it's
> > > > > > > - * not intended for normal execution and will taint the
> > > > > > > kernel
> > > > > > > with TAINT_TEST
> > > > > > > - * when used.
> > > > > > > - *
> > > > > > > - * The syntax allows to pass straight instructions to be
> > > > > > > executed
> > > > > > > by the engine
> > > > > > > - * in a batch buffer or set specific registers.
> > > > > > > - *
> > > > > > > - * #. Generic instruction::
> > > > > > > - *
> > > > > > > - * <engine-class> cmd <instr> [[dword0] [dword1]
> > > > > > > [...]]
> > > > > > > - *
> > > > > > > - * #. Simple register setting::
> > > > > > > - *
> > > > > > > - * <engine-class> reg <address> <value>
> > > > > > > - *
> > > > > > > - * Commands are saved per engine class: all instances of
> > > > > > > that
> > > > > > > class will execute
> > > > > > > - * those commands during context switch. The
> > > > > > > instruction,
> > > > > > > dword
> > > > > > > arguments,
> > > > > > > - * addresses and values are in hex format like in the
> > > > > > > examples
> > > > > > > below.
> > > > > > > - *
> > > > > > > - * #. Execute a LRI command to write 0xDEADBEEF to
> > > > > > > register
> > > > > > > 0x4f10
> > > > > > > after the
> > > > > > > - * normal context restore::
> > > > > > > - *
> > > > > > > - * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \
> > > > > > > - * >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_post_bb
> > > > > > > - *
> > > > > > > - * #. Execute a LRI command to write 0xDEADBEEF to
> > > > > > > register
> > > > > > > 0x4f10
> > > > > > > at the
> > > > > > > - * beginning of the context restore::
> > > > > > > - *
> > > > > > > - * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \
> > > > > > > - * >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_mid_bb
> > > > > > > -
> > > > > > > - * #. Load certain values in a couple of registers (it
> > > > > > > can
> > > > > > > be
> > > > > > > used
> > > > > > > as a simpler
> > > > > > > - * alternative to the `cmd`) action::
> > > > > > > - *
> > > > > > > - * # cat >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_post_bb
> > > > > > > <<EOF
> > > > > > > - * rcs reg 4F100 DEADBEEF
> > > > > > > - * rcs reg 4F104 FFFFFFFF
> > > > > > > - * EOF
> > > > > > > - *
> > > > > > > - * .. note::
> > > > > > > - *
> > > > > > > - * When using multiple lines, make sure to use a
> > > > > > > command
> > > > > > > that is
> > > > > > > - * implemented with a single write syscall, like
> > > > > > > HEREDOC.
> > > > > > > - *
> > > > > > > - * Currently this is implemented only for post and mid
> > > > > > > context
> > > > > > > restore and
> > > > > > > - * these attributes can only be set before binding to
> > > > > > > the
> > > > > > > device.
> > > > > > > - *
> > > > > > > - * Allowed engines:
> > > > > > > - * ----------------
> > > > > > > - *
> > > > > > > - * Allow only a set of engine(s) to be available,
> > > > > > > disabling
> > > > > > > the
> > > > > > > other engines
> > > > > > > - * even if they are available in hardware. This is
> > > > > > > applied
> > > > > > > after
> > > > > > > HW fuses are
> > > > > > > - * considered on each tile. Examples:
> > > > > > > - *
> > > > > > > - * Allow only one render and one copy engines, nothing
> > > > > > > else::
> > > > > > > - *
> > > > > > > - * # echo 'rcs0,bcs0' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/engines_allowed
> > > > > > > - *
> > > > > > > - * Allow only compute engines and first copy engine::
> > > > > > > - *
> > > > > > > - * # echo 'ccs*,bcs0' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/engines_allowed
> > > > > > > - *
> > > > > > > - * Note that the engine names are the per-GT hardware
> > > > > > > names.
> > > > > > > On
> > > > > > > multi-tile
> > > > > > > - * platforms, writing ``rcs0,bcs0`` to this file would
> > > > > > > allow
> > > > > > > the
> > > > > > > first render
> > > > > > > - * and copy engines on each tile.
> > > > > > > - *
> > > > > > > - * The requested configuration may not be supported by
> > > > > > > the
> > > > > > > platform and driver
> > > > > > > - * may fail to probe. For example: if at least one copy
> > > > > > > engine
> > > > > > > is
> > > > > > > expected to be
> > > > > > > - * available for migrations, but it's disabled. This is
> > > > > > > intended
> > > > > > > for debugging
> > > > > > > - * purposes only.
> > > > > > > - *
> > > > > > > - * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > - *
> > > > > > > - * Allowed GT types:
> > > > > > > - * -----------------
> > > > > > > - *
> > > > > > > - * Allow only specific types of GTs to be detected and
> > > > > > > initialized
> > > > > > > by the
> > > > > > > - * driver. Any combination of GT types can be
> > > > > > > enabled/disabled,
> > > > > > > although
> > > > > > > - * some settings will cause the device to fail to probe.
> > > > > > > - *
> > > > > > > - * Writes support both comma- and newline-separated
> > > > > > > input
> > > > > > > format.
> > > > > > > Reads
> > > > > > > - * will always return one GT type per line. "primary"
> > > > > > > and
> > > > > > > "media"
> > > > > > > are the
> > > > > > > - * GT type names supported by this interface.
> > > > > > > - *
> > > > > > > - * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > - *
> > > > > > > - * Examples:
> > > > > > > - *
> > > > > > > - * Allow both primary and media GTs to be initialized
> > > > > > > and
> > > > > > > used.
> > > > > > > This matches
> > > > > > > - * the driver's default behavior::
> > > > > > > - *
> > > > > > > - * # echo 'primary,media' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed
> > > > > > > - *
> > > > > > > - * Allow only the primary GT of each tile to be
> > > > > > > initialized
> > > > > > > and
> > > > > > > used,
> > > > > > > - * effectively disabling the media GT if it exists on
> > > > > > > the
> > > > > > > platform::
> > > > > > > - *
> > > > > > > - * # echo 'primary' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed
> > > > > > > - *
> > > > > > > - * Allow only the media GT of each tile to be
> > > > > > > initialized
> > > > > > > and
> > > > > > > used,
> > > > > > > - * effectively disabling the primary GT. **This
> > > > > > > configuration
> > > > > > > will cause
> > > > > > > - * device probe failure on all current platforms, but
> > > > > > > may
> > > > > > > be
> > > > > > > allowed on
> > > > > > > - * igpu platforms in the future**::
> > > > > > > - *
> > > > > > > - * # echo 'media' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed
> > > > > > > - *
> > > > > > > - * Disable all GTs. Only other GPU IP (such as display)
> > > > > > > is
> > > > > > > potentially usable.
> > > > > > > - * **This configuration will cause device probe failure
> > > > > > > on
> > > > > > > all
> > > > > > > current
> > > > > > > - * platforms, but may be allowed on igpu platforms in
> > > > > > > the
> > > > > > > future**::
> > > > > > > - *
> > > > > > > - * # echo '' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed
> > > > > > > - *
> > > > > > > - * Enable multi-queue
> > > > > > > - * ------------------
> > > > > > > - *
> > > > > > > - * Multi-queue support on the device is enabled by
> > > > > > > default
> > > > > > > where
> > > > > > > the
> > > > > > > - * hardware supports it. Writing 0 force-disables multi-
> > > > > > > queue
> > > > > > > support:
> > > > > > > - * multi-queue exec-queue group creation via ioctl is
> > > > > > > refused,
> > > > > > > and
> > > > > > > the
> > > > > > > - * GuC feature is disabled::
> > > > > > > - *
> > > > > > > - * # echo 0 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/enable_multi_queue
> > > > > > > - *
> > > > > > > - * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > - *
> > > > > > > - * PSMI
> > > > > > > - * ----
> > > > > > > - *
> > > > > > > - * Enable extra debugging capabilities to trace engine
> > > > > > > execution.
> > > > > > > Only useful
> > > > > > > - * during early platform enabling and requires
> > > > > > > additional
> > > > > > > hardware
> > > > > > > connected.
> > > > > > > - * Once it's enabled, additionals WAs are added and
> > > > > > > runtime
> > > > > > > configuration is
> > > > > > > - * done via debugfs. Example to enable it::
> > > > > > > - *
> > > > > > > - * # echo 1 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/enable_psmi
> > > > > > > - *
> > > > > > > - * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > - *
> > > > > > > - * Survivability mode:
> > > > > > > - * -------------------
> > > > > > > - *
> > > > > > > - * Enable survivability mode on supported cards. This
> > > > > > > setting
> > > > > > > only
> > > > > > > takes
> > > > > > > - * effect when probing the device. Example to enable
> > > > > > > it::
> > > > > >
> > > > > > I didn't review the code movement in this patch in depth,
> > > > > > but
> > > > > > the
> > > > > > one
> > > > > > thing that I'm uncertain about is whether survivability
> > > > > > mode
> > > > > > should
> > > > > > have
> > > > > > been swept up in this move. My understanding is that
> > > > > > unlike
> > > > > > the
> > > > > > other
> > > > > > options which are meant for developers hacking on the
> > > > > > driver,
> > > > > > configurable survivability mode is a true production
> > > > > > feature
> > > > > > intended
> > > > > > for end users to get the minimal driver support necessary
> > > > > > to
> > > > > > deal
> > > > > > with a
> > > > > > bad firmware flash, failing hardware, etc. I know there
> > > > > > are
> > > > > > cases
> > > > > > where
> > > > > > the driver can auto-detect the need to enter survivability
> > > > > > mode
> > > > > > without
> > > > > > the configfs interface (i.e., various RAS error reports and
> > > > > > such),
> > > > > > but I
> > > > > > thought manual entry through configfs was still something
> > > > > > users
> > > > > > may
> > > > > > need
> > > > > > in some cases? If so that would mean we should keep this
> > > > > > available
> > > > > > even
> > > > > > when the debug options aren't compiled in.
> > > > > >
> > > > > > +Cc Riana in case my understanding is off.
> > > > >
> > > > > Yeah would appreciate feedback there Riana. My understanding
> > > > > of
> > > > > survivability mode is we want this to allow us to continue
> > > > > operation
> > > > > for a while to debug issues when the hardware is severely
> > > > > misbehaving.
> > > > > This isn't a normal customer use case.
> > > >
> > > > I'm not Riana, but I can answer to this! :)
> > > >
> > > > Survivability is needed in final production builds.
> > > >
> > > > We had cases in the field where any kind of probe (succeeded,
> > > > failed,
> > > > not-attempted) would put the device in a state where FW could
> > > > not
> > > > be
> > > > flashed.
> > > >
> > > > So this fallback option where user selects survivability and
> > > > get
> > > > a
> > > > minimal
> > > > probe where FW can be flashed is needed.
> > >
> > > So I get the reasoning there. Why can't we do this as part of a
> > > debug
> > > build though? If we get to a point where the IFWI is in such a
> > > bad
> > > state that it can brick the card, this really is a debug scenario
> > > anyway IMO. Or is this more about orchestration and auto-update
> > > capability that we want for a normal data center user?
> >
> > No, this is for end-user production settings. For example a random
> > home
> > user flashing the latest firmware onto their gaming card who gets
> > hit
> > with a power outage in the middle and winds up with the GPU in a
> > bricked
> > state. After that they can still use configfs to put the device
> > into
> > survivability mode and use the appropriate tools to recover the
> > device
> > and re-flash the firmware properly. That user is likely using
> > whatever
> > production kernel came with their distro and may not have the
> > knowledge
> > or desire to re-build a debug kernel to fix the system. They're
> > not
> > trying to debug anything and want the recovery process to be as
> > quick
> > and simple as possible.
> >
> > In a datacenter settings it's probably even more critical to not
> > require
> > a debug kernel. If a host containing lots of GPUs has one single
> > GPU
> > get bricked, they don't want to take down the entire system
> > (including
> > all the other GPUs that are functioning fine) and reboot into a
> > debug
> > kernel to reflash/recover that one GPU. They want to be able to
> > just
> > bind that single device in recovery mode, do whatever is necessary
> > to
> > recovery it, and then re-bind the device normally without
> > interfering
> > with all the other work happening on the system.
>
> Ok I get the points you and Rodrigo are making and I agree, it makes
> sense to me. Let me move this out into the production list in the
> next
> rev.
>
> >
> > >
> > > >
> > > > Also, another possible usage of this is around upcoming in-
> > > > field
> > > > test
> > > > and in field repair cases.
> > > >
> > > > So, survivability is one... But also I'm thinking about others
> > > > as
> > > > well in here.
> > > > PSMI for instance, are we sure that PSMI folks don't plug PSMI
> > > > in
> > > > production
> > > > builds at all when debugging some images that they cannot
> > > > control?
> > >
> > > Again, IMO it is perfectly reasonable to expect someone using
> > > PSMI
> > > to
> > > be also using a debug kernel. We will almost certainly want to
> > > have
> > > the
> > > extra debug capability on the kernel side as well as the hardware
> > > side
> > > in these types of debugs.
> >
> > PSMI can never be used in production; it's fused off on all
> > external,
> > production hardware, so it can only ever be used on pre-production
> > hardware that never leaves Intel. So PSMI definitely makes sense
> > to
> > keep in the 'debug' bucket in my opinion.
>
> Rodrigo let me know if you have any strong opinions the other way.
> For
> now I'll plan on leaving this where it is.
No no, as I told, I don't know much about PSMI and Matt Roper already
confirmed that PSMI requires even hardware fusing to work so definitely
not a production one.
>
> I'll wait for the rest of the series to review before posting the
> next
> update.
>
> Thanks for the feedback!
> Stuart
>
> >
> >
> > Matt
> >
> > >
> > > Thanks,
> > > Stuart
> > >
> > > >
> > > > >
> > > > > My thought longer term here is we'd turn this into a bit map
> > > > > that
> > > > > allowed various hardware or software isolation
> > > > > configurations.
> > > > > We'll
> > > > > also have the per-feature configfs entries, but the
> > > > > survivability
> > > > > mode
> > > > > could be used to easily isolate based on a higher level
> > > > > isolation
> > > > > scheme that doesn't require the person debugging to fully
> > > > > understand
> > > > > all the different underlying features being disabled if that
> > > > > makes
> > > > > sense.
> > > > >
> > > > > The flip side of this could be that we really want to require
> > > > > users
> > > > > to
> > > > > be more surgical about how they enable/disable different
> > > > > features.
> > > > > In
> > > > > that case, I'd argue we really should drop survivability mode
> > > > > completely and turn it into an "enable_punit" and various
> > > > > other
> > > > > related
> > > > > configurations.
> > > > >
> > > > > Thanks,
> > > > > Stuart
> > > > >
> > > > > >
> > > > > >
> > > > > > Matt
> > > > > >
> > > > > > > - *
> > > > > > > - * # echo 1 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/survivability_mode
> > > > > > > - *
> > > > > > > - * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > - *
> > > > > > > * Max SR-IOV Virtual Functions
> > > > > > > * ----------------------------
> > > > > > > *
> > > > > > > @@ -256,12 +95,16 @@
> > > > > > > * # rmdir /sys/kernel/config/xe/0000:03:00.0/
> > > > > > > */
> > > > > > >
> > > > > > > -static const struct xe_config_device device_defaults = {
> > > > > > > - .engines_allowed = U64_MAX,
> > > > > > > - .gt_types_allowed = U64_MAX,
> > > > > > > - .enable_multi_queue = true,
> > > > > > > - .enable_psmi = false,
> > > > > > > - .survivability_mode = false,
> > > > > > > +const struct xe_config_device
> > > > > > > xe_configfs_device_defaults
> > > > > > > = {
> > > > > > > +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
> > > > > > > + .debug = {
> > > > > > > + .engines_allowed = U64_MAX,
> > > > > > > + .gt_types_allowed = U64_MAX,
> > > > > > > + .enable_multi_queue = true,
> > > > > > > + .enable_psmi = false,
> > > > > > > + .survivability_mode = false,
> > > > > > > + },
> > > > > > > +#endif
> > > > > > > .sriov = {
> > > > > > > .max_vfs = XE_DEFAULT_MAX_VFS,
> > > > > > > .admin_only_pf =
> > > > > > > XE_DEFAULT_ADMIN_ONLY_PF,
> > > > > > > @@ -270,50 +113,22 @@ static const struct
> > > > > > > xe_config_device
> > > > > > > device_defaults = {
> > > > > > >
> > > > > > > static void set_device_defaults(struct xe_config_device
> > > > > > > *config)
> > > > > > > {
> > > > > > > - *config = device_defaults;
> > > > > > > + *config = xe_configfs_device_defaults;
> > > > > > > #ifdef CONFIG_PCI_IOV
> > > > > > > config->sriov.max_vfs = xe_modparam.max_vfs;
> > > > > > > #endif
> > > > > > > }
> > > > > > >
> > > > > > > -struct engine_info {
> > > > > > > - const char *cls;
> > > > > > > - u64 mask;
> > > > > > > - enum xe_engine_class engine_class;
> > > > > > > -};
> > > > > > > -
> > > > > > > -/* Some helpful macros to aid on the sizing of buffer
> > > > > > > allocation
> > > > > > > when parsing */
> > > > > > > -#define MAX_ENGINE_CLASS_CHARS 5
> > > > > > > -#define MAX_ENGINE_INSTANCE_CHARS 2
> > > > > > > -
> > > > > > > -static const struct engine_info engine_info[] = {
> > > > > > > - { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_RENDER },
> > > > > > > - { .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_COPY },
> > > > > > > - { .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_VIDEO_DECODE },
> > > > > > > - { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_VIDEO_ENHANCE },
> > > > > > > - { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_COMPUTE },
> > > > > > > - { .cls = "gsccs", .mask =
> > > > > > > XE_HW_ENGINE_GSCCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_OTHER },
> > > > > > > -};
> > > > > > > -
> > > > > > > -static const struct {
> > > > > > > - const char *name;
> > > > > > > - enum xe_gt_type type;
> > > > > > > -} gt_types[] = {
> > > > > > > - { .name = "primary", .type = XE_GT_TYPE_MAIN },
> > > > > > > - { .name = "media", .type = XE_GT_TYPE_MEDIA },
> > > > > > > -};
> > > > > > > -
> > > > > > > -static struct xe_config_group_device
> > > > > > > *to_xe_config_group_device(struct config_item *item)
> > > > > > > -{
> > > > > > > - return container_of(to_config_group(item), struct
> > > > > > > xe_config_group_device, group);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static struct xe_config_device
> > > > > > > *to_xe_config_device(struct
> > > > > > > config_item *item)
> > > > > > > -{
> > > > > > > - return &to_xe_config_group_device(item)->config;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static bool is_bound(struct xe_config_group_device *dev)
> > > > > > > +/**
> > > > > > > + * xe_configfs_is_bound - check whether the matching pci
> > > > > > > device is
> > > > > > > bound
> > > > > > > + * @dev: configfs group device
> > > > > > > + *
> > > > > > > + * Caller must hold @dev->lock.
> > > > > > > + *
> > > > > > > + * Return: true if the matching pci_dev is already bound
> > > > > > > to a
> > > > > > > driver,
> > > > > > > + * false otherwise.
> > > > > > > + */
> > > > > > > +bool xe_configfs_is_bound(struct xe_config_group_device
> > > > > > > *dev)
> > > > > > > {
> > > > > > > unsigned int domain, bus, slot, function;
> > > > > > > struct pci_dev *pdev;
> > > > > > > @@ -338,698 +153,13 @@ static bool is_bound(struct
> > > > > > > xe_config_group_device *dev)
> > > > > > > return ret;
> > > > > > > }
> > > > > > >
> > > > > > > -static struct xe_config_group_device
> > > > > > > *find_xe_config_group_device(struct pci_dev *pdev);
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_ctx_restore_mid_bb - get configfs
> > > > > > > ctx_restore_mid_bb setting
> > > > > > > - * @pdev: pci device
> > > > > > > - * @class: hw engine class
> > > > > > > - * @cs: pointer to the bb to use - only valid during
> > > > > > > probe
> > > > > > > - *
> > > > > > > - * Return: Number of dwords used in the mid_ctx_restore
> > > > > > > setting in
> > > > > > > configfs
> > > > > > > - */
> > > > > > > -u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > - enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > - const u32 **cs)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - u32 len;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return 0;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock) {
> > > > > > > - if (cs)
> > > > > > > - *cs = dev-
> > > > > > > > config.ctx_restore_mid_bb[class].cs;
> > > > > > > -
> > > > > > > - len = dev-
> > > > > > > > config.ctx_restore_mid_bb[class].len;
> > > > > > > - }
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_ctx_restore_post_bb - get configfs
> > > > > > > ctx_restore_post_bb setting
> > > > > > > - * @pdev: pci device
> > > > > > > - * @class: hw engine class
> > > > > > > - * @cs: pointer to the bb to use - only valid during
> > > > > > > probe
> > > > > > > - *
> > > > > > > - * Return: Number of dwords used in the post_ctx_restore
> > > > > > > setting
> > > > > > > in configfs
> > > > > > > - */
> > > > > > > -u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > - enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > - const u32 **cs)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - u32 len;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return 0;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock) {
> > > > > > > - *cs = dev-
> > > > > > > > config.ctx_restore_post_bb[class].cs;
> > > > > > > - len = dev-
> > > > > > > > config.ctx_restore_post_bb[class].len;
> > > > > > > - }
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static bool wa_bb_read_advance(bool dereference, char
> > > > > > > **p,
> > > > > > > - const char *append, size_t
> > > > > > > len,
> > > > > > > - size_t *max_size)
> > > > > > > -{
> > > > > > > - if (dereference) {
> > > > > > > - if (len >= *max_size)
> > > > > > > - return false;
> > > > > > > - *max_size -= len;
> > > > > > > - if (append)
> > > > > > > - memcpy(*p, append, len);
> > > > > > > - }
> > > > > > > -
> > > > > > > - *p += len;
> > > > > > > -
> > > > > > > - return true;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t wa_bb_show(struct xe_config_group_device
> > > > > > > *dev,
> > > > > > > - struct wa_bb wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX],
> > > > > > > - char *data, size_t sz)
> > > > > > > -{
> > > > > > > - char *p = data;
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > -
> > > > > > > - for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > - enum xe_engine_class ec =
> > > > > > > engine_info[i].engine_class;
> > > > > > > - size_t len;
> > > > > > > -
> > > > > > > - if (!wa_bb[ec].len)
> > > > > > > - continue;
> > > > > > > -
> > > > > > > - len = snprintf(p, sz, "%s:",
> > > > > > > engine_info[i].cls);
> > > > > > > - if (!wa_bb_read_advance(data, &p, NULL,
> > > > > > > len,
> > > > > > > &sz))
> > > > > > > - return -ENOBUFS;
> > > > > > > -
> > > > > > > - for (size_t j = 0; j < wa_bb[ec].len;
> > > > > > > j++)
> > > > > > > {
> > > > > > > - len = snprintf(p, sz, " %08x",
> > > > > > > wa_bb[ec].cs[j]);
> > > > > > > - if (!wa_bb_read_advance(data, &p,
> > > > > > > NULL,
> > > > > > > len, &sz))
> > > > > > > - return -ENOBUFS;
> > > > > > > - }
> > > > > > > -
> > > > > > > - if (!wa_bb_read_advance(data, &p, "\n",
> > > > > > > 1,
> > > > > > > &sz))
> > > > > > > - return -ENOBUFS;
> > > > > > > - }
> > > > > > > -
> > > > > > > - if (!wa_bb_read_advance(data, &p, "", 1, &sz))
> > > > > > > - return -ENOBUFS;
> > > > > > > -
> > > > > > > - /* Reserve one more to match check for '\0' */
> > > > > > > - if (!data)
> > > > > > > - p++;
> > > > > > > -
> > > > > > > - return p - data;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t ctx_restore_mid_bb_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > -
> > > > > > > - return wa_bb_show(dev, dev-
> > > > > > > > config.ctx_restore_mid_bb,
> > > > > > > page, SZ_4K);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t ctx_restore_post_bb_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > -
> > > > > > > - return wa_bb_show(dev, dev-
> > > > > > > > config.ctx_restore_post_bb,
> > > > > > > page, SZ_4K);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static void wa_bb_append(struct wa_bb *wa_bb, u32 val)
> > > > > > > -{
> > > > > > > - if (wa_bb->cs)
> > > > > > > - wa_bb->cs[wa_bb->len] = val;
> > > > > > > -
> > > > > > > - wa_bb->len++;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t parse_hex(const char *line, u32 *pval)
> > > > > > > -{
> > > > > > > - char numstr[12];
> > > > > > > - const char *p;
> > > > > > > - ssize_t numlen;
> > > > > > > -
> > > > > > > - p = line + strspn(line, " \t");
> > > > > > > - if (!*p || *p == '\n')
> > > > > > > - return 0;
> > > > > > > -
> > > > > > > - numlen = strcspn(p, " \t\n");
> > > > > > > - if (!numlen || numlen >= sizeof(numstr) - 1)
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - memcpy(numstr, p, numlen);
> > > > > > > - numstr[numlen] = '\0';
> > > > > > > - p += numlen;
> > > > > > > -
> > > > > > > - if (kstrtou32(numstr, 16, pval))
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - return p - line;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static int parse_engine(const char *s, const char
> > > > > > > *end_chars,
> > > > > > > u64
> > > > > > > *mask,
> > > > > > > - const struct engine_info
> > > > > > > **pinfo);
> > > > > > > -
> > > > > > > -/*
> > > > > > > - * Parse lines with the format
> > > > > > > - *
> > > > > > > - * <engine-class> cmd <u32> <u32...>
> > > > > > > - * <engine-class> reg <u32_addr> <u32_val>
> > > > > > > - *
> > > > > > > - * and optionally save them in @wa_bb[i].cs is non-NULL.
> > > > > > > - *
> > > > > > > - * Return the number of dwords parsed.
> > > > > > > - */
> > > > > > > -static ssize_t parse_wa_bb_lines(const char *lines,
> > > > > > > - struct wa_bb
> > > > > > > wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX])
> > > > > > > -{
> > > > > > > - ssize_t dwords = 0, ret;
> > > > > > > - const char *p;
> > > > > > > -
> > > > > > > - for (p = lines; *p; p++) {
> > > > > > > - const struct engine_info *info = NULL;
> > > > > > > - u32 val, val2;
> > > > > > > -
> > > > > > > - /* Also allow empty lines */
> > > > > > > - p += strspn(p, " \t\n");
> > > > > > > - if (!*p)
> > > > > > > - break;
> > > > > > > -
> > > > > > > - ret = parse_engine(p, " \t\n", NULL,
> > > > > > > &info);
> > > > > > > - if (ret < 0)
> > > > > > > - return ret;
> > > > > > > -
> > > > > > > - p += ret;
> > > > > > > - p += strspn(p, " \t");
> > > > > > > -
> > > > > > > - if (str_has_prefix(p, "cmd")) {
> > > > > > > - for (p += strlen("cmd"); *p;) {
> > > > > > > - ret = parse_hex(p, &val);
> > > > > > > - if (ret < 0)
> > > > > > > - return -EINVAL;
> > > > > > > - if (!ret)
> > > > > > > - break;
> > > > > > > -
> > > > > > > - p += ret;
> > > > > > > - dwords++;
> > > > > > > - wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class], val);
> > > > > > > - }
> > > > > > > - } else if (str_has_prefix(p, "reg")) {
> > > > > > > - p += strlen("reg");
> > > > > > > - ret = parse_hex(p, &val);
> > > > > > > - if (ret <= 0)
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - p += ret;
> > > > > > > - ret = parse_hex(p, &val2);
> > > > > > > - if (ret <= 0)
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - p += ret;
> > > > > > > - dwords += 3;
> > > > > > > - wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > - MI_LOAD_REGISTER_IMM
> > > > > > > |
> > > > > > > MI_LRI_NUM_REGS(1));
> > > > > > > - wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > val);
> > > > > > > - wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > val2);
> > > > > > > - } else {
> > > > > > > - return -EINVAL;
> > > > > > > - }
> > > > > > > - }
> > > > > > > -
> > > > > > > - return dwords;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t wa_bb_store(struct wa_bb wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX],
> > > > > > > - struct xe_config_group_device
> > > > > > > *dev,
> > > > > > > - const char *page, size_t len)
> > > > > > > -{
> > > > > > > - /* tmp_wa_bb must match wa_bb's size */
> > > > > > > - struct wa_bb tmp_wa_bb[XE_ENGINE_CLASS_MAX] = {
> > > > > > > };
> > > > > > > - ssize_t count, class;
> > > > > > > - u32 *tmp;
> > > > > > > -
> > > > > > > - /* 1. Count dwords - wa_bb[i].cs is NULL for all
> > > > > > > classes */
> > > > > > > - count = parse_wa_bb_lines(page, tmp_wa_bb);
> > > > > > > - if (count < 0)
> > > > > > > - return count;
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > -
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - /*
> > > > > > > - * 2. Allocate a u32 array and set the pointers
> > > > > > > to
> > > > > > > the
> > > > > > > right positions
> > > > > > > - * according to the length of each class' wa_bb
> > > > > > > - */
> > > > > > > - tmp = krealloc(wa_bb[0].cs, count * sizeof(u32),
> > > > > > > GFP_KERNEL);
> > > > > > > - if (!tmp)
> > > > > > > - return -ENOMEM;
> > > > > > > -
> > > > > > > - if (!count) {
> > > > > > > - memset(wa_bb, 0, sizeof(tmp_wa_bb));
> > > > > > > - return len;
> > > > > > > - }
> > > > > > > -
> > > > > > > - for (class = 0, count = 0; class <
> > > > > > > XE_ENGINE_CLASS_MAX;
> > > > > > > ++class) {
> > > > > > > - tmp_wa_bb[class].cs = tmp + count;
> > > > > > > - count += tmp_wa_bb[class].len;
> > > > > > > - tmp_wa_bb[class].len = 0;
> > > > > > > - }
> > > > > > > -
> > > > > > > - /* 3. Parse wa_bb lines again, this time saving
> > > > > > > the
> > > > > > > values
> > > > > > > */
> > > > > > > - count = parse_wa_bb_lines(page, tmp_wa_bb);
> > > > > > > - if (count < 0)
> > > > > > > - return count;
> > > > > > > -
> > > > > > > - memcpy(wa_bb, tmp_wa_bb, sizeof(tmp_wa_bb));
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t ctx_restore_mid_bb_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > - const char *data,
> > > > > > > size_t
> > > > > > > sz)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > -
> > > > > > > - return wa_bb_store(dev-
> > > > > > > >config.ctx_restore_mid_bb,
> > > > > > > dev,
> > > > > > > data, sz);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t ctx_restore_post_bb_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > - const char
> > > > > > > *data,
> > > > > > > size_t
> > > > > > > sz)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > -
> > > > > > > - return wa_bb_store(dev-
> > > > > > > >config.ctx_restore_post_bb,
> > > > > > > dev,
> > > > > > > data, sz);
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_engines_allowed - get engine allowed
> > > > > > > mask
> > > > > > > from
> > > > > > > configfs
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: engine mask with allowed engines set in
> > > > > > > configfs
> > > > > > > - */
> > > > > > > -u64 xe_configfs_get_engines_allowed(struct pci_dev
> > > > > > > *pdev)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - u64 engines_allowed;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return device_defaults.engines_allowed;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock)
> > > > > > > - engines_allowed = dev-
> > > > > > > > config.engines_allowed;
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return engines_allowed;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t engines_allowed_show(struct config_item
> > > > > > > *item,
> > > > > > > char
> > > > > > > *page)
> > > > > > > -{
> > > > > > > - struct xe_config_device *dev =
> > > > > > > to_xe_config_device(item);
> > > > > > > - char *p = page;
> > > > > > > -
> > > > > > > - for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > - u64 mask = engine_info[i].mask;
> > > > > > > -
> > > > > > > - if ((dev->engines_allowed & mask) ==
> > > > > > > mask)
> > > > > > > {
> > > > > > > - p += sprintf(p, "%s*\n",
> > > > > > > engine_info[i].cls);
> > > > > > > - } else if (mask & dev->engines_allowed) {
> > > > > > > - u16 bit0 = __ffs64(mask), bit;
> > > > > > > -
> > > > > > > - mask &= dev->engines_allowed;
> > > > > > > -
> > > > > > > - for_each_set_bit(bit, (const
> > > > > > > unsigned
> > > > > > > long
> > > > > > > *)&mask, 64)
> > > > > > > - p += sprintf(p, "%s%u\n",
> > > > > > > engine_info[i].cls,
> > > > > > > - bit - bit0);
> > > > > > > - }
> > > > > > > - }
> > > > > > > -
> > > > > > > - return p - page;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/*
> > > > > > > - * Lookup engine_info. If @mask is not NULL, reduce the
> > > > > > > mask
> > > > > > > according to the
> > > > > > > - * instance in @pattern.
> > > > > > > - *
> > > > > > > - * Examples of inputs:
> > > > > > > - * - lookup_engine_info("rcs0", &mask): return "rcs"
> > > > > > > entry
> > > > > > > from
> > > > > > > @engine_info and
> > > > > > > - * mask == BIT_ULL(XE_HW_ENGINE_RCS0)
> > > > > > > - * - lookup_engine_info("rcs*", &mask): return "rcs"
> > > > > > > entry
> > > > > > > from
> > > > > > > @engine_info and
> > > > > > > - * mask == XE_HW_ENGINE_RCS_MASK
> > > > > > > - * - lookup_engine_info("rcs", NULL): return "rcs" entry
> > > > > > > from
> > > > > > > @engine_info
> > > > > > > - */
> > > > > > > -static const struct engine_info
> > > > > > > *lookup_engine_info(const
> > > > > > > char
> > > > > > > *pattern, u64 *mask)
> > > > > > > -{
> > > > > > > - for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > - u8 instance;
> > > > > > > - u16 bit;
> > > > > > > -
> > > > > > > - if (!str_has_prefix(pattern,
> > > > > > > engine_info[i].cls))
> > > > > > > - continue;
> > > > > > > -
> > > > > > > - pattern += strlen(engine_info[i].cls);
> > > > > > > - if (!mask)
> > > > > > > - return *pattern ? NULL :
> > > > > > > &engine_info[i];
> > > > > > > -
> > > > > > > - if (!strcmp(pattern, "*")) {
> > > > > > > - *mask = engine_info[i].mask;
> > > > > > > - return &engine_info[i];
> > > > > > > - }
> > > > > > > -
> > > > > > > - if (kstrtou8(pattern, 10, &instance))
> > > > > > > - return NULL;
> > > > > > > -
> > > > > > > - bit = __ffs64(engine_info[i].mask) +
> > > > > > > instance;
> > > > > > > - if (bit >= fls64(engine_info[i].mask))
> > > > > > > - return NULL;
> > > > > > > -
> > > > > > > - *mask = BIT_ULL(bit);
> > > > > > > - return &engine_info[i];
> > > > > > > - }
> > > > > > > -
> > > > > > > - return NULL;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static int parse_engine(const char *s, const char
> > > > > > > *end_chars,
> > > > > > > u64
> > > > > > > *mask,
> > > > > > > - const struct engine_info **pinfo)
> > > > > > > -{
> > > > > > > - char buf[MAX_ENGINE_CLASS_CHARS +
> > > > > > > MAX_ENGINE_INSTANCE_CHARS
> > > > > > > + 1];
> > > > > > > - const struct engine_info *info;
> > > > > > > - size_t len;
> > > > > > > -
> > > > > > > - len = strcspn(s, end_chars);
> > > > > > > - if (len >= sizeof(buf))
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - memcpy(buf, s, len);
> > > > > > > - buf[len] = '\0';
> > > > > > > -
> > > > > > > - info = lookup_engine_info(buf, mask);
> > > > > > > - if (!info)
> > > > > > > - return -ENOENT;
> > > > > > > -
> > > > > > > - if (pinfo)
> > > > > > > - *pinfo = info;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t engines_allowed_store(struct config_item
> > > > > > > *item,
> > > > > > > const char *page,
> > > > > > > - size_t len)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > - ssize_t patternlen, p;
> > > > > > > - u64 mask, val = 0;
> > > > > > > -
> > > > > > > - for (p = 0; p < len; p += patternlen + 1) {
> > > > > > > - patternlen = parse_engine(page + p,
> > > > > > > ",\n",
> > > > > > > &mask,
> > > > > > > NULL);
> > > > > > > - if (patternlen < 0)
> > > > > > > - return -EINVAL;
> > > > > > > -
> > > > > > > - val |= mask;
> > > > > > > - }
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - dev->config.engines_allowed = val;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static u64 get_gt_types_allowed(struct pci_dev *pdev)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - u64 mask;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return device_defaults.gt_types_allowed;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock)
> > > > > > > - mask = dev->config.gt_types_allowed;
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return mask;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_primary_gt_allowed - determine whether
> > > > > > > primary
> > > > > > > GTs
> > > > > > > are supported
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: True if primary GTs are enabled, false if
> > > > > > > they
> > > > > > > have
> > > > > > > been disabled via
> > > > > > > - * configfs.
> > > > > > > - */
> > > > > > > -bool xe_configfs_primary_gt_allowed(struct pci_dev
> > > > > > > *pdev)
> > > > > > > -{
> > > > > > > - return get_gt_types_allowed(pdev) &
> > > > > > > BIT_ULL(XE_GT_TYPE_MAIN);
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_media_gt_allowed - determine whether
> > > > > > > media
> > > > > > > GTs
> > > > > > > are
> > > > > > > supported
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: True if the media GTs are enabled, false if
> > > > > > > they
> > > > > > > have
> > > > > > > been disabled
> > > > > > > - * via configfs.
> > > > > > > - */
> > > > > > > -bool xe_configfs_media_gt_allowed(struct pci_dev *pdev)
> > > > > > > -{
> > > > > > > - return get_gt_types_allowed(pdev) &
> > > > > > > BIT_ULL(XE_GT_TYPE_MEDIA);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t gt_types_allowed_show(struct config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > -{
> > > > > > > - struct xe_config_device *dev =
> > > > > > > to_xe_config_device(item);
> > > > > > > - char *p = page;
> > > > > > > -
> > > > > > > - for (size_t i = 0; i < ARRAY_SIZE(gt_types); i++)
> > > > > > > - if (dev->gt_types_allowed &
> > > > > > > BIT_ULL(gt_types[i].type))
> > > > > > > - p += sprintf(p, "%s\n",
> > > > > > > gt_types[i].name);
> > > > > > > -
> > > > > > > - return p - page;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t gt_types_allowed_store(struct config_item
> > > > > > > *item,
> > > > > > > const char *page,
> > > > > > > - size_t len)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > - char *buf __free(kfree) = kstrdup(page,
> > > > > > > GFP_KERNEL);
> > > > > > > - char *p = buf;
> > > > > > > - u64 typemask = 0;
> > > > > > > -
> > > > > > > - if (!buf)
> > > > > > > - return -ENOMEM;
> > > > > > > -
> > > > > > > - while (p) {
> > > > > > > - char *typename = strsep(&p, ",\n");
> > > > > > > - bool matched = false;
> > > > > > > -
> > > > > > > - if (typename[0] == '\0')
> > > > > > > - continue;
> > > > > > > -
> > > > > > > - for (size_t i = 0; i <
> > > > > > > ARRAY_SIZE(gt_types);
> > > > > > > i++) {
> > > > > > > - if (strcmp(typename,
> > > > > > > gt_types[i].name)
> > > > > > > ==
> > > > > > > 0) {
> > > > > > > - typemask |=
> > > > > > > BIT(gt_types[i].type);
> > > > > > > - matched = true;
> > > > > > > - break;
> > > > > > > - }
> > > > > > > - }
> > > > > > > -
> > > > > > > - if (!matched)
> > > > > > > - return -EINVAL;
> > > > > > > - }
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - dev->config.gt_types_allowed = typemask;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_enable_multi_queue - get configfs
> > > > > > > enable_multi_queue setting
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: true if multi-queue is enabled for this
> > > > > > > device
> > > > > > > (the
> > > > > > > default),
> > > > > > > - * false if it has been force-disabled via configfs.
> > > > > > > - */
> > > > > > > -bool xe_configfs_get_enable_multi_queue(struct pci_dev
> > > > > > > *pdev)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - bool ret;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return true;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock)
> > > > > > > - ret = dev->config.enable_multi_queue;
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return ret;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t enable_multi_queue_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > -{
> > > > > > > - struct xe_config_device *dev =
> > > > > > > to_xe_config_device(item);
> > > > > > > -
> > > > > > > - return sprintf(page, "%d\n", dev-
> > > > > > > > enable_multi_queue);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t enable_multi_queue_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > const char *page,
> > > > > > > - size_t len)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > - bool val;
> > > > > > > - int ret;
> > > > > > > -
> > > > > > > - ret = kstrtobool(page, &val);
> > > > > > > - if (ret)
> > > > > > > - return ret;
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - dev->config.enable_multi_queue = val;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_psmi_enabled - get configfs
> > > > > > > enable_psmi
> > > > > > > setting
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: enable_psmi setting in configfs
> > > > > > > - */
> > > > > > > -bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - bool ret;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return false;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock)
> > > > > > > - ret = dev->config.enable_psmi;
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return ret;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t enable_psmi_show(struct config_item
> > > > > > > *item,
> > > > > > > char
> > > > > > > *page)
> > > > > > > -{
> > > > > > > - struct xe_config_device *dev =
> > > > > > > to_xe_config_device(item);
> > > > > > > -
> > > > > > > - return sprintf(page, "%d\n", dev->enable_psmi);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t enable_psmi_store(struct config_item
> > > > > > > *item,
> > > > > > > const
> > > > > > > char *page, size_t len)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > - bool val;
> > > > > > > - int ret;
> > > > > > > -
> > > > > > > - ret = kstrtobool(page, &val);
> > > > > > > - if (ret)
> > > > > > > - return ret;
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - dev->config.enable_psmi = val;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -/**
> > > > > > > - * xe_configfs_get_survivability_mode - get configfs
> > > > > > > survivability
> > > > > > > mode attribute
> > > > > > > - * @pdev: pci device
> > > > > > > - *
> > > > > > > - * Return: survivability_mode attribute in configfs
> > > > > > > - */
> > > > > > > -bool xe_configfs_get_survivability_mode(struct pci_dev
> > > > > > > *pdev)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > - bool mode;
> > > > > > > -
> > > > > > > - if (!dev)
> > > > > > > - return
> > > > > > > device_defaults.survivability_mode;
> > > > > > > -
> > > > > > > - scoped_guard(mutex, &dev->lock)
> > > > > > > - mode = dev->config.survivability_mode;
> > > > > > > - config_group_put(&dev->group);
> > > > > > > -
> > > > > > > - return mode;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t survivability_mode_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > -{
> > > > > > > - struct xe_config_device *dev =
> > > > > > > to_xe_config_device(item);
> > > > > > > -
> > > > > > > - return sprintf(page, "%d\n", dev-
> > > > > > > > survivability_mode);
> > > > > > > -}
> > > > > > > -
> > > > > > > -static ssize_t survivability_mode_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > const char *page, size_t len)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > - bool survivability_mode;
> > > > > > > - int ret;
> > > > > > > -
> > > > > > > - ret = kstrtobool(page, &survivability_mode);
> > > > > > > - if (ret)
> > > > > > > - return ret;
> > > > > > > -
> > > > > > > - guard(mutex)(&dev->lock);
> > > > > > > - if (is_bound(dev))
> > > > > > > - return -EBUSY;
> > > > > > > -
> > > > > > > - dev->config.survivability_mode =
> > > > > > > survivability_mode;
> > > > > > > -
> > > > > > > - return len;
> > > > > > > -}
> > > > > > > -
> > > > > > > -CONFIGFS_ATTR(, ctx_restore_mid_bb);
> > > > > > > -CONFIGFS_ATTR(, ctx_restore_post_bb);
> > > > > > > -CONFIGFS_ATTR(, engines_allowed);
> > > > > > > -CONFIGFS_ATTR(, gt_types_allowed);
> > > > > > > -CONFIGFS_ATTR(, enable_multi_queue);
> > > > > > > -CONFIGFS_ATTR(, enable_psmi);
> > > > > > > -CONFIGFS_ATTR(, survivability_mode);
> > > > > > > -
> > > > > > > -static struct configfs_attribute
> > > > > > > *xe_config_device_attrs[]
> > > > > > > = {
> > > > > > > - &attr_ctx_restore_mid_bb,
> > > > > > > - &attr_ctx_restore_post_bb,
> > > > > > > - &attr_engines_allowed,
> > > > > > > - &attr_gt_types_allowed,
> > > > > > > - &attr_enable_multi_queue,
> > > > > > > - &attr_enable_psmi,
> > > > > > > - &attr_survivability_mode,
> > > > > > > - NULL,
> > > > > > > -};
> > > > > > > -
> > > > > > > static void xe_config_device_release(struct config_item
> > > > > > > *item)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_to_group_device(item);
> > > > > > >
> > > > > > > mutex_destroy(&dev->lock);
> > > > > > >
> > > > > > > - kfree(dev->config.ctx_restore_mid_bb[0].cs);
> > > > > > > - kfree(dev->config.ctx_restore_post_bb[0].cs);
> > > > > > > + xe_configfs_debug_release_config(&dev->config);
> > > > > > > kfree(dev);
> > > > > > > }
> > > > > > >
> > > > > > > @@ -1037,33 +167,14 @@ static struct
> > > > > > > configfs_item_operations
> > > > > > > xe_config_device_ops = {
> > > > > > > .release = xe_config_device_release,
> > > > > > > };
> > > > > > >
> > > > > > > -static bool xe_config_device_is_visible(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > - struct
> > > > > > > configfs_attribute
> > > > > > > *attr, int n)
> > > > > > > -{
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item);
> > > > > > > -
> > > > > > > - if (attr == &attr_survivability_mode) {
> > > > > > > - if (!dev->desc->is_dgfx || dev->desc-
> > > > > > > > platform
> > > > > > > <
> > > > > > > XE_BATTLEMAGE)
> > > > > > > - return false;
> > > > > > > - }
> > > > > > > -
> > > > > > > - return true;
> > > > > > > -}
> > > > > > > -
> > > > > > > -static struct configfs_group_operations
> > > > > > > xe_config_device_group_ops
> > > > > > > = {
> > > > > > > - .is_visible = xe_config_device_is_visible,
> > > > > > > -};
> > > > > > > -
> > > > > > > static const struct config_item_type
> > > > > > > xe_config_device_type
> > > > > > > = {
> > > > > > > .ct_item_ops = &xe_config_device_ops,
> > > > > > > - .ct_group_ops = &xe_config_device_group_ops,
> > > > > > > - .ct_attrs = xe_config_device_attrs,
> > > > > > > .ct_owner = THIS_MODULE,
> > > > > > > };
> > > > > > >
> > > > > > > static ssize_t sriov_max_vfs_show(struct config_item
> > > > > > > *item,
> > > > > > > char
> > > > > > > *page)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item->ci_parent);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > >
> > > > > > > guard(mutex)(&dev->lock);
> > > > > > >
> > > > > > > @@ -1075,13 +186,13 @@ static ssize_t
> > > > > > > sriov_max_vfs_show(struct
> > > > > > > config_item *item, char *page)
> > > > > > >
> > > > > > > static ssize_t sriov_max_vfs_store(struct config_item
> > > > > > > *item,
> > > > > > > const
> > > > > > > char *page, size_t len)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item->ci_parent);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > unsigned int max_vfs;
> > > > > > > int ret;
> > > > > > >
> > > > > > > guard(mutex)(&dev->lock);
> > > > > > >
> > > > > > > - if (is_bound(dev))
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > return -EBUSY;
> > > > > > >
> > > > > > > ret = kstrtouint(page, 0, &max_vfs);
> > > > > > > @@ -1097,7 +208,7 @@ static ssize_t
> > > > > > > sriov_max_vfs_store(struct
> > > > > > > config_item *item, const char *page, s
> > > > > > >
> > > > > > > static ssize_t sriov_admin_only_pf_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item->ci_parent);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > >
> > > > > > > guard(mutex)(&dev->lock);
> > > > > > >
> > > > > > > @@ -1106,13 +217,13 @@ static ssize_t
> > > > > > > sriov_admin_only_pf_show(struct config_item *item, char
> > > > > > > *page)
> > > > > > >
> > > > > > > static ssize_t sriov_admin_only_pf_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > const char *page, size_t len)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item->ci_parent);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > bool admin_only_pf;
> > > > > > > int ret;
> > > > > > >
> > > > > > > guard(mutex)(&dev->lock);
> > > > > > >
> > > > > > > - if (is_bound(dev))
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > return -EBUSY;
> > > > > > >
> > > > > > > ret = kstrtobool(page, &admin_only_pf);
> > > > > > > @@ -1135,7 +246,7 @@ static struct configfs_attribute
> > > > > > > *xe_config_sriov_attrs[] = {
> > > > > > > static bool xe_config_sriov_is_visible(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > struct
> > > > > > > configfs_attribute
> > > > > > > *attr, int n)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > to_xe_config_group_device(item->ci_parent);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > >
> > > > > > > if (attr == &sriov_attr_max_vfs && dev->mode !=
> > > > > > > XE_SRIOV_MODE_PF)
> > > > > > > return false;
> > > > > > > @@ -1271,7 +382,17 @@ static struct configfs_subsystem
> > > > > > > xe_configfs
> > > > > > > = {
> > > > > > > },
> > > > > > > };
> > > > > > >
> > > > > > > -static struct xe_config_group_device
> > > > > > > *find_xe_config_group_device(struct pci_dev *pdev)
> > > > > > > +/**
> > > > > > > + * xe_configfs_find_group_device() - Find a configfs
> > > > > > > group
> > > > > > > by
> > > > > > > PCI
> > > > > > > device.
> > > > > > > + * @pdev: the &pci_dev to look up
> > > > > > > + *
> > > > > > > + * Searches the configfs subsystem for a group whose
> > > > > > > name
> > > > > > > matches
> > > > > > > @pdev.
> > > > > > > + * If found, the returned group has an elevated
> > > > > > > reference
> > > > > > > count;
> > > > > > > the caller
> > > > > > > + * must call config_group_put() when done.
> > > > > > > + *
> > > > > > > + * Return: pointer to the matching
> > > > > > > &xe_config_group_device, or
> > > > > > > NULL.
> > > > > > > + */
> > > > > > > +struct xe_config_group_device
> > > > > > > *xe_configfs_find_group_device(struct pci_dev *pdev)
> > > > > > > {
> > > > > > > struct config_item *item;
> > > > > > >
> > > > > > > @@ -1282,23 +403,25 @@ static struct
> > > > > > > xe_config_group_device
> > > > > > > *find_xe_config_group_device(struct pci_dev
> > > > > > > if (!item)
> > > > > > > return NULL;
> > > > > > >
> > > > > > > - return to_xe_config_group_device(item);
> > > > > > > + return xe_configfs_to_group_device(item);
> > > > > > > }
> > > > > > >
> > > > > > > static void dump_custom_dev_config(struct pci_dev *pdev,
> > > > > > > struct
> > > > > > > xe_config_group_device
> > > > > > > *dev)
> > > > > > > {
> > > > > > > #define PRI_CUSTOM_ATTR(fmt_, attr_) do { \
> > > > > > > - if (dev->config.attr_ !=
> > > > > > > device_defaults.attr_)
> > > > > > > \
> > > > > > > + if (dev->config.attr_ !=
> > > > > > > xe_configfs_device_defaults.attr_) \
> > > > > > > pci_info(pdev, "configfs: "
> > > > > > > __stringify(attr_) " = " fmt_ "\n", \
> > > > > > > dev->config.attr_); \
> > > > > > > } while (0)
> > > > > > >
> > > > > > > - PRI_CUSTOM_ATTR("%llx", engines_allowed);
> > > > > > > - PRI_CUSTOM_ATTR("%llx", gt_types_allowed);
> > > > > > > - PRI_CUSTOM_ATTR("%d", enable_multi_queue);
> > > > > > > - PRI_CUSTOM_ATTR("%d", enable_psmi);
> > > > > > > - PRI_CUSTOM_ATTR("%d", survivability_mode);
> > > > > > > +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
> > > > > > > + PRI_CUSTOM_ATTR("%llx", debug.engines_allowed);
> > > > > > > + PRI_CUSTOM_ATTR("%llx", debug.gt_types_allowed);
> > > > > > > + PRI_CUSTOM_ATTR("%d", debug.enable_multi_queue);
> > > > > > > + PRI_CUSTOM_ATTR("%d", debug.enable_psmi);
> > > > > > > + PRI_CUSTOM_ATTR("%d", debug.survivability_mode);
> > > > > > > +#endif
> > > > > > > PRI_CUSTOM_ATTR("%u", sriov.admin_only_pf);
> > > > > > >
> > > > > > > #undef PRI_CUSTOM_ATTR
> > > > > > > @@ -1313,13 +436,13 @@ static void
> > > > > > > dump_custom_dev_config(struct
> > > > > > > pci_dev *pdev,
> > > > > > > */
> > > > > > > void xe_configfs_check_device(struct pci_dev *pdev)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_find_group_device(pdev);
> > > > > > >
> > > > > > > if (!dev)
> > > > > > > return;
> > > > > > >
> > > > > > > /* memcmp here is safe as both are zero-
> > > > > > > initialized
> > > > > > > */
> > > > > > > - if (memcmp(&dev->config, &device_defaults,
> > > > > > > sizeof(dev-
> > > > > > > > config))) {
> > > > > > > + if (memcmp(&dev->config,
> > > > > > > &xe_configfs_device_defaults,
> > > > > > > sizeof(dev->config))) {
> > > > > > > pci_info(pdev, "Found custom settings in
> > > > > > > configfs\n");
> > > > > > > dump_custom_dev_config(pdev, dev);
> > > > > > > }
> > > > > > > @@ -1341,7 +464,7 @@ void xe_configfs_check_device(struct
> > > > > > > pci_dev
> > > > > > > *pdev)
> > > > > > > */
> > > > > > > bool xe_configfs_admin_only_pf(struct pci_dev *pdev)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_find_group_device(pdev);
> > > > > > > bool admin_only_pf;
> > > > > > >
> > > > > > > if (!dev)
> > > > > > > @@ -1366,7 +489,7 @@ bool
> > > > > > > xe_configfs_admin_only_pf(struct
> > > > > > > pci_dev
> > > > > > > *pdev)
> > > > > > > */
> > > > > > > unsigned int xe_configfs_get_max_vfs(struct pci_dev
> > > > > > > *pdev)
> > > > > > > {
> > > > > > > - struct xe_config_group_device *dev =
> > > > > > > find_xe_config_group_device(pdev);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_find_group_device(pdev);
> > > > > > > unsigned int max_vfs;
> > > > > > >
> > > > > > > if (!dev)
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_configfs.h
> > > > > > > b/drivers/gpu/drm/xe/xe_configfs.h
> > > > > > > index 7db2f46291fa..a2dc0a7cc7b5 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_configfs.h
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_configfs.h
> > > > > > > @@ -12,24 +12,76 @@
> > > > > > > #include "xe_defaults.h"
> > > > > > > #include "xe_module.h"
> > > > > > >
> > > > > > > +struct config_item;
> > > > > > > struct pci_dev;
> > > > > > > +struct xe_config_group_device;
> > > > > > > +
> > > > > > > +extern const struct xe_config_device
> > > > > > > xe_configfs_device_defaults;
> > > > > > >
> > > > > > > #if IS_ENABLED(CONFIG_CONFIGFS_FS)
> > > > > > > +/**
> > > > > > > + * xe_configfs_to_group_device() - Cast a config_item to
> > > > > > > &xe_config_group_device.
> > > > > > > + * @item: the &config_item embedded in the device group
> > > > > > > + *
> > > > > > > + * The @item must be the top-level device group's
> > > > > > > cg_item,
> > > > > > > not
> > > > > > > a
> > > > > > > subgroup item.
> > > > > > > + * Use xe_configfs_subgroup_to_group_device() for
> > > > > > > subgroup
> > > > > > > show/store callbacks.
> > > > > > > + *
> > > > > > > + * Return: pointer to the enclosing
> > > > > > > &xe_config_group_device.
> > > > > > > + */
> > > > > > > +static inline struct xe_config_group_device *
> > > > > > > +xe_configfs_to_group_device(struct config_item *item)
> > > > > > > +{
> > > > > > > + return container_of(to_config_group(item), struct
> > > > > > > xe_config_group_device, group);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_to_device() - Cast a config_item to
> > > > > > > &xe_config_device.
> > > > > > > + * @item: the &config_item embedded in the device group
> > > > > > > + *
> > > > > > > + * Convenience wrapper around
> > > > > > > xe_configfs_to_group_device().
> > > > > > > + *
> > > > > > > + * Return: pointer to the &xe_config_device nested in
> > > > > > > the
> > > > > > > group.
> > > > > > > + */
> > > > > > > +static inline struct xe_config_device
> > > > > > > *xe_configfs_to_device(struct config_item *item)
> > > > > > > +{
> > > > > > > + return &xe_configfs_to_group_device(item)-
> > > > > > > >config;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_subgroup_to_group_device() - Cast a
> > > > > > > subgroup
> > > > > > > item
> > > > > > > to &xe_config_group_device.
> > > > > > > + * @item: the &config_item of a subgroup (e.g. sriov or
> > > > > > > debug)
> > > > > > > + *
> > > > > > > + * In configfs, show/store callbacks for a subgroup's
> > > > > > > attributes
> > > > > > > receive the
> > > > > > > + * subgroup's cg_item, whose parent is the device
> > > > > > > group's
> > > > > > > cg_item.
> > > > > > > + * This helper walks up one level to return the
> > > > > > > enclosing
> > > > > > > device
> > > > > > > group.
> > > > > > > + *
> > > > > > > + * Return: pointer to the enclosing
> > > > > > > &xe_config_group_device.
> > > > > > > + */
> > > > > > > +static inline struct xe_config_group_device *
> > > > > > > +xe_configfs_subgroup_to_group_device(struct config_item
> > > > > > > *item)
> > > > > > > +{
> > > > > > > + return xe_configfs_to_group_device(item-
> > > > > > > > ci_parent);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_subgroup_to_device() - Cast a subgroup
> > > > > > > item
> > > > > > > to
> > > > > > > &xe_config_device.
> > > > > > > + * @item: the &config_item of a subgroup (e.g. sriov or
> > > > > > > debug)
> > > > > > > + *
> > > > > > > + * Convenience wrapper for a subgroup item to get the
> > > > > > > &xe_config_device.
> > > > > > > + *
> > > > > > > + * Return: pointer to the &xe_config_device nested in
> > > > > > > the
> > > > > > > parent
> > > > > > > device group.
> > > > > > > + */
> > > > > > > +static inline struct xe_config_device *
> > > > > > > +xe_configfs_subgroup_to_device(struct config_item *item)
> > > > > > > +{
> > > > > > > + return xe_configfs_to_device(item->ci_parent);
> > > > > > > +}
> > > > > > > +
> > > > > > > +bool xe_configfs_is_bound(struct xe_config_group_device
> > > > > > > *dev);
> > > > > > > +struct xe_config_group_device
> > > > > > > *xe_configfs_find_group_device(struct pci_dev *pdev);
> > > > > > > int xe_configfs_init(void);
> > > > > > > void xe_configfs_exit(void);
> > > > > > > void xe_configfs_check_device(struct pci_dev *pdev);
> > > > > > > -u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > - enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > - const u32 **cs);
> > > > > > > -u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > - enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > - const u32 **cs);
> > > > > > > -u64 xe_configfs_get_engines_allowed(struct pci_dev
> > > > > > > *pdev);
> > > > > > > -bool xe_configfs_primary_gt_allowed(struct pci_dev
> > > > > > > *pdev);
> > > > > > > -bool xe_configfs_media_gt_allowed(struct pci_dev *pdev);
> > > > > > > -bool xe_configfs_get_enable_multi_queue(struct pci_dev
> > > > > > > *pdev);
> > > > > > > -bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev);
> > > > > > > -bool xe_configfs_get_survivability_mode(struct pci_dev
> > > > > > > *pdev);
> > > > > > > #ifdef CONFIG_PCI_IOV
> > > > > > > unsigned int xe_configfs_get_max_vfs(struct pci_dev
> > > > > > > *pdev);
> > > > > > > bool xe_configfs_admin_only_pf(struct pci_dev *pdev);
> > > > > > > @@ -38,18 +90,6 @@ bool xe_configfs_admin_only_pf(struct
> > > > > > > pci_dev
> > > > > > > *pdev);
> > > > > > > static inline int xe_configfs_init(void) { return 0; }
> > > > > > > static inline void xe_configfs_exit(void) { }
> > > > > > > static inline void xe_configfs_check_device(struct
> > > > > > > pci_dev
> > > > > > > *pdev)
> > > > > > > { }
> > > > > > > -static inline u32
> > > > > > > xe_configfs_get_ctx_restore_mid_bb(struct
> > > > > > > pci_dev *pdev,
> > > > > > > - enum
> > > > > > > xe_engine_class class,
> > > > > > > -
> > > > > > > const
> > > > > > > u32
> > > > > > > **cs) { return 0; }
> > > > > > > -static inline u32
> > > > > > > xe_configfs_get_ctx_restore_post_bb(struct
> > > > > > > pci_dev *pdev,
> > > > > > > -
> > > > > > > enum
> > > > > > > xe_engine_class class,
> > > > > > > -
> > > > > > > const
> > > > > > > u32
> > > > > > > **cs) { return 0; }
> > > > > > > -static inline u64 xe_configfs_get_engines_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return U64_MAX; }
> > > > > > > -static inline bool xe_configfs_primary_gt_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return true; }
> > > > > > > -static inline bool xe_configfs_media_gt_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return true; }
> > > > > > > -static inline bool
> > > > > > > xe_configfs_get_enable_multi_queue(struct
> > > > > > > pci_dev *pdev) { return true; }
> > > > > > > -static inline bool xe_configfs_get_psmi_enabled(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return false; }
> > > > > > > -static inline bool
> > > > > > > xe_configfs_get_survivability_mode(struct
> > > > > > > pci_dev *pdev) { return false; }
> > > > > > > #ifdef CONFIG_PCI_IOV
> > > > > > > static inline unsigned int
> > > > > > > xe_configfs_get_max_vfs(struct
> > > > > > > pci_dev
> > > > > > > *pdev)
> > > > > > > {
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_configfs_debug.c
> > > > > > > b/drivers/gpu/drm/xe/xe_configfs_debug.c
> > > > > > > index 45617282cec5..b2667573efbe 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_configfs_debug.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_configfs_debug.c
> > > > > > > @@ -3,12 +3,968 @@
> > > > > > > * Copyright © 2026 Intel Corporation
> > > > > > > */
> > > > > > >
> > > > > > > +#include <linux/bitops.h>
> > > > > > > #include <linux/configfs.h>
> > > > > > > #include <linux/module.h>
> > > > > > > +#include <linux/cleanup.h>
> > > > > > > +#include <linux/find.h>
> > > > > > > +#include <linux/pci.h>
> > > > > > > +#include <linux/string.h>
> > > > > > >
> > > > > > > +#include "abi/guc_log_abi.h"
> > > > > > > +#include "instructions/xe_mi_commands.h"
> > > > > > > +#include "xe_configfs.h"
> > > > > > > #include "xe_configfs_debug.h"
> > > > > > > #include "xe_configfs_types.h"
> > > > > > > +#include "xe_gt_types.h"
> > > > > > > +#include "xe_hw_engine_types.h"
> > > > > > > +#include "xe_pci_types.h"
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * DOC: Xe Configfs Debug Attributes
> > > > > > > + *
> > > > > > > + * Overview
> > > > > > > + * ========
> > > > > > > + *
> > > > > > > + * The following configfs attributes are only available
> > > > > > > when
> > > > > > > the
> > > > > > > kernel is
> > > > > > > + * built with ``CONFIG_DRM_XE_DEBUG=y``. They appear
> > > > > > > under
> > > > > > > the
> > > > > > > ``debug/``
> > > > > > > + * subdirectory of each xe configfs device. They are
> > > > > > > intended
> > > > > > > for
> > > > > > > hardware
> > > > > > > + * and driver debugging and are not stable ABI. Using
> > > > > > > them
> > > > > > > is
> > > > > > > "at
> > > > > > > your own
> > > > > > > + * risk".
> > > > > > > + *
> > > > > > > + * See the top-level ``Xe Configfs`` documentation in
> > > > > > > ``xe_configfs.c``
> > > > > > > + * for how to create, probe and remove configfs devices.
> > > > > > > Once
> > > > > > > a
> > > > > > > device
> > > > > > > + * directory exists, the driver populates it with a
> > > > > > > ``debug/``
> > > > > > > subdirectory
> > > > > > > + * containing the entries described below::
> > > > > > > + *
> > > > > > > + * /sys/kernel/config/xe/
> > > > > > > + * └── 0000:03:00.0
> > > > > > > + * └── debug/
> > > > > > > + * ├── ctx_restore_mid_bb
> > > > > > > + * ├── ctx_restore_post_bb
> > > > > > > + * ├── engines_allowed
> > > > > > > + * ├── gt_types_allowed
> > > > > > > + * ├── enable_multi_queue
> > > > > > > + * ├── enable_psmi
> > > > > > > + * └── survivability_mode
> > > > > > > + *
> > > > > > > + * Configure Attributes
> > > > > > > + * ====================
> > > > > > > + *
> > > > > > > + * Context restore BB
> > > > > > > + * ------------------
> > > > > > > + *
> > > > > > > + * Allow to execute a batch buffer during any context
> > > > > > > switches.
> > > > > > > When the
> > > > > > > + * GPU is restoring the context, it executes additional
> > > > > > > commands.
> > > > > > > It's useful
> > > > > > > + * for testing additional workarounds and validating
> > > > > > > certain
> > > > > > > HW
> > > > > > > behaviors: it's
> > > > > > > + * not intended for normal execution and will taint the
> > > > > > > kernel
> > > > > > > with TAINT_TEST
> > > > > > > + * when used.
> > > > > > > + *
> > > > > > > + * The syntax allows to pass straight instructions to be
> > > > > > > executed
> > > > > > > by the engine
> > > > > > > + * in a batch buffer or set specific registers.
> > > > > > > + *
> > > > > > > + * #. Generic instruction::
> > > > > > > + *
> > > > > > > + * <engine-class> cmd <instr> [[dword0] [dword1]
> > > > > > > [...]]
> > > > > > > + *
> > > > > > > + * #. Simple register setting::
> > > > > > > + *
> > > > > > > + * <engine-class> reg <address> <value>
> > > > > > > + *
> > > > > > > + * Commands are saved per engine class: all instances of
> > > > > > > that
> > > > > > > class will execute
> > > > > > > + * those commands during context switch. The
> > > > > > > instruction,
> > > > > > > dword
> > > > > > > arguments,
> > > > > > > + * addresses and values are in hex format like in the
> > > > > > > examples
> > > > > > > below.
> > > > > > > + *
> > > > > > > + * #. Execute a LRI command to write 0xDEADBEEF to
> > > > > > > register
> > > > > > > 0x4f10
> > > > > > > after the
> > > > > > > + * normal context restore::
> > > > > > > + *
> > > > > > > + * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \
> > > > > > > + * >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/ctx_restore_post
> > > > > > > _b
> > > > > > > b
> > > > > > > + *
> > > > > > > + * #. Execute a LRI command to write 0xDEADBEEF to
> > > > > > > register
> > > > > > > 0x4f10
> > > > > > > at the
> > > > > > > + * beginning of the context restore::
> > > > > > > + *
> > > > > > > + * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \
> > > > > > > + * >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/ctx_restore_mid_
> > > > > > > bb
> > > > > > > + *
> > > > > > > + * #. Load certain values in a couple of registers (it
> > > > > > > can
> > > > > > > be
> > > > > > > used
> > > > > > > as a simpler
> > > > > > > + * alternative to the `cmd`) action::
> > > > > > > + *
> > > > > > > + * # cat >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/ctx_restore_post
> > > > > > > _b
> > > > > > > b
> > > > > > > <<EOF
> > > > > > > + * rcs reg 4F100 DEADBEEF
> > > > > > > + * rcs reg 4F104 FFFFFFFF
> > > > > > > + * EOF
> > > > > > > + *
> > > > > > > + * .. note::
> > > > > > > + *
> > > > > > > + * When using multiple lines, make sure to use a
> > > > > > > command
> > > > > > > that is
> > > > > > > + * implemented with a single write syscall, like
> > > > > > > HEREDOC.
> > > > > > > + *
> > > > > > > + * Currently this is implemented only for post and mid
> > > > > > > context
> > > > > > > restore and
> > > > > > > + * these attributes can only be set before binding to
> > > > > > > the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + * Allowed engines:
> > > > > > > + * ----------------
> > > > > > > + *
> > > > > > > + * Allow only a set of engine(s) to be available,
> > > > > > > disabling
> > > > > > > the
> > > > > > > other engines
> > > > > > > + * even if they are available in hardware. This is
> > > > > > > applied
> > > > > > > after
> > > > > > > HW fuses are
> > > > > > > + * considered on each tile. Examples:
> > > > > > > + *
> > > > > > > + * Allow only one render and one copy engines, nothing
> > > > > > > else::
> > > > > > > + *
> > > > > > > + * # echo 'rcs0,bcs0' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/engines_allowed
> > > > > > > + *
> > > > > > > + * Allow only compute engines and first copy engine::
> > > > > > > + *
> > > > > > > + * # echo 'ccs*,bcs0' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/engines_allowed
> > > > > > > + *
> > > > > > > + * Note that the engine names are the per-GT hardware
> > > > > > > names.
> > > > > > > On
> > > > > > > multi-tile
> > > > > > > + * platforms, writing ``rcs0,bcs0`` to this file would
> > > > > > > allow
> > > > > > > the
> > > > > > > first render
> > > > > > > + * and copy engines on each tile.
> > > > > > > + *
> > > > > > > + * The requested configuration may not be supported by
> > > > > > > the
> > > > > > > platform and driver
> > > > > > > + * may fail to probe. For example: if at least one copy
> > > > > > > engine
> > > > > > > is
> > > > > > > expected to be
> > > > > > > + * available for migrations, but it's disabled. This is
> > > > > > > intended
> > > > > > > for debugging
> > > > > > > + * purposes only.
> > > > > > > + *
> > > > > > > + * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + * Allowed GT types:
> > > > > > > + * -----------------
> > > > > > > + *
> > > > > > > + * Allow only specific types of GTs to be detected and
> > > > > > > initialized
> > > > > > > by the
> > > > > > > + * driver. Any combination of GT types can be
> > > > > > > enabled/disabled,
> > > > > > > although
> > > > > > > + * some settings will cause the device to fail to probe.
> > > > > > > + *
> > > > > > > + * Writes support both comma- and newline-separated
> > > > > > > input
> > > > > > > format.
> > > > > > > Reads
> > > > > > > + * will always return one GT type per line. "primary"
> > > > > > > and
> > > > > > > "media"
> > > > > > > are the
> > > > > > > + * GT type names supported by this interface.
> > > > > > > + *
> > > > > > > + * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + * Examples:
> > > > > > > + *
> > > > > > > + * Allow both primary and media GTs to be initialized
> > > > > > > and
> > > > > > > used.
> > > > > > > This matches
> > > > > > > + * the driver's default behavior::
> > > > > > > + *
> > > > > > > + * # echo 'primary,media' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/gt_types_allowed
> > > > > > > + *
> > > > > > > + * Allow only the primary GT of each tile to be
> > > > > > > initialized
> > > > > > > and
> > > > > > > used,
> > > > > > > + * effectively disabling the media GT if it exists on
> > > > > > > the
> > > > > > > platform::
> > > > > > > + *
> > > > > > > + * # echo 'primary' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/gt_types_allowed
> > > > > > > + *
> > > > > > > + * Allow only the media GT of each tile to be
> > > > > > > initialized
> > > > > > > and
> > > > > > > used,
> > > > > > > + * effectively disabling the primary GT. **This
> > > > > > > configuration
> > > > > > > will cause
> > > > > > > + * device probe failure on all current platforms, but
> > > > > > > may
> > > > > > > be
> > > > > > > allowed on
> > > > > > > + * igpu platforms in the future**::
> > > > > > > + *
> > > > > > > + * # echo 'media' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/gt_types_allowed
> > > > > > > + *
> > > > > > > + * Disable all GTs. Only other GPU IP (such as display)
> > > > > > > is
> > > > > > > potentially usable.
> > > > > > > + * **This configuration will cause device probe failure
> > > > > > > on
> > > > > > > all
> > > > > > > current
> > > > > > > + * platforms, but may be allowed on igpu platforms in
> > > > > > > the
> > > > > > > future**::
> > > > > > > + *
> > > > > > > + * # echo '' >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/gt_types_allowed
> > > > > > > + *
> > > > > > > + * Enable multi-queue
> > > > > > > + * ------------------
> > > > > > > + *
> > > > > > > + * Multi-queue support on the device is enabled by
> > > > > > > default
> > > > > > > where
> > > > > > > the
> > > > > > > + * hardware supports it. Writing 0 force-disables multi-
> > > > > > > queue
> > > > > > > support:
> > > > > > > + * multi-queue exec-queue group creation via ioctl is
> > > > > > > refused,
> > > > > > > and
> > > > > > > the
> > > > > > > + * GuC feature is disabled::
> > > > > > > + *
> > > > > > > + * # echo 0 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/enable_multi_que
> > > > > > > ue
> > > > > > > + *
> > > > > > > + * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + * PSMI
> > > > > > > + * ----
> > > > > > > + *
> > > > > > > + * Enable extra debugging capabilities to trace engine
> > > > > > > execution.
> > > > > > > Only useful
> > > > > > > + * during early platform enabling and requires
> > > > > > > additional
> > > > > > > hardware
> > > > > > > connected.
> > > > > > > + * Once it's enabled, additionals WAs are added and
> > > > > > > runtime
> > > > > > > configuration is
> > > > > > > + * done via debugfs. Example to enable it::
> > > > > > > + *
> > > > > > > + * # echo 1 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/enable_psmi
> > > > > > > + *
> > > > > > > + * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + * Survivability mode:
> > > > > > > + * -------------------
> > > > > > > + *
> > > > > > > + * Enable survivability mode on supported cards. This
> > > > > > > setting
> > > > > > > only
> > > > > > > takes
> > > > > > > + * effect when probing the device. Example to enable
> > > > > > > it::
> > > > > > > + *
> > > > > > > + * # echo 1 >
> > > > > > > /sys/kernel/config/xe/0000:03:00.0/debug/survivability_mo
> > > > > > > de
> > > > > > > + *
> > > > > > > + * This attribute can only be set before binding to the
> > > > > > > device.
> > > > > > > + *
> > > > > > > + */
> > > > > > > +
> > > > > > > +struct engine_info {
> > > > > > > + const char *cls;
> > > > > > > + u64 mask;
> > > > > > > + enum xe_engine_class engine_class;
> > > > > > > +};
> > > > > > > +
> > > > > > > +/* Some helpful macros to aid on the sizing of buffer
> > > > > > > allocation
> > > > > > > when parsing */
> > > > > > > +#define MAX_ENGINE_CLASS_CHARS 5
> > > > > > > +#define MAX_ENGINE_INSTANCE_CHARS 2
> > > > > > > +
> > > > > > > +static const struct engine_info engine_info[] = {
> > > > > > > + { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_RENDER },
> > > > > > > + { .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_COPY },
> > > > > > > + { .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_VIDEO_DECODE },
> > > > > > > + { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_VIDEO_ENHANCE },
> > > > > > > + { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_COMPUTE },
> > > > > > > + { .cls = "gsccs", .mask =
> > > > > > > XE_HW_ENGINE_GSCCS_MASK,
> > > > > > > .engine_class = XE_ENGINE_CLASS_OTHER },
> > > > > > > +};
> > > > > > > +
> > > > > > > +static const struct {
> > > > > > > + const char *name;
> > > > > > > + enum xe_gt_type type;
> > > > > > > +} gt_types[] = {
> > > > > > > + { .name = "primary", .type = XE_GT_TYPE_MAIN },
> > > > > > > + { .name = "media", .type = XE_GT_TYPE_MEDIA },
> > > > > > > +};
> > > > > > > +
> > > > > > > +static struct xe_config_group_device *find_device(struct
> > > > > > > pci_dev
> > > > > > > *pdev)
> > > > > > > +{
> > > > > > > + return xe_configfs_find_group_device(pdev);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_ctx_restore_mid_bb - get configfs
> > > > > > > ctx_restore_mid_bb setting
> > > > > > > + * @pdev: pci device
> > > > > > > + * @class: hw engine class
> > > > > > > + * @cs: pointer to the bb to use - only valid during
> > > > > > > probe
> > > > > > > + *
> > > > > > > + * Return: Number of dwords used in the mid_ctx_restore
> > > > > > > setting in
> > > > > > > configfs
> > > > > > > + */
> > > > > > > +u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > + enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > + const u32 **cs)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + u32 len;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return 0;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock) {
> > > > > > > + if (cs)
> > > > > > > + *cs = dev-
> > > > > > > > config.debug.ctx_restore_mid_bb[class].cs;
> > > > > > > +
> > > > > > > + len = dev-
> > > > > > > > config.debug.ctx_restore_mid_bb[class].len;
> > > > > > > + }
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_ctx_restore_post_bb - get configfs
> > > > > > > ctx_restore_post_bb setting
> > > > > > > + * @pdev: pci device
> > > > > > > + * @class: hw engine class
> > > > > > > + * @cs: pointer to the bb to use - only valid during
> > > > > > > probe
> > > > > > > + *
> > > > > > > + * Return: Number of dwords used in the post_ctx_restore
> > > > > > > setting
> > > > > > > in configfs
> > > > > > > + */
> > > > > > > +u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > + enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > + const u32 **cs)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + u32 len;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return 0;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock) {
> > > > > > > + *cs = dev-
> > > > > > > > config.debug.ctx_restore_post_bb[class].cs;
> > > > > > > + len = dev-
> > > > > > > > config.debug.ctx_restore_post_bb[class].len;
> > > > > > > + }
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static bool wa_bb_read_advance(bool dereference, char
> > > > > > > **p,
> > > > > > > + const char *append, size_t
> > > > > > > len,
> > > > > > > + size_t *max_size)
> > > > > > > +{
> > > > > > > + if (dereference) {
> > > > > > > + if (len >= *max_size)
> > > > > > > + return false;
> > > > > > > + *max_size -= len;
> > > > > > > + if (append)
> > > > > > > + memcpy(*p, append, len);
> > > > > > > + }
> > > > > > > +
> > > > > > > + *p += len;
> > > > > > > +
> > > > > > > + return true;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t wa_bb_show(struct xe_config_group_device
> > > > > > > *dev,
> > > > > > > + struct wa_bb wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX],
> > > > > > > + char *data, size_t sz)
> > > > > > > +{
> > > > > > > + char *p = data;
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > +
> > > > > > > + for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > + enum xe_engine_class ec =
> > > > > > > engine_info[i].engine_class;
> > > > > > > + size_t len;
> > > > > > > +
> > > > > > > + if (!wa_bb[ec].len)
> > > > > > > + continue;
> > > > > > > +
> > > > > > > + len = snprintf(p, sz, "%s:",
> > > > > > > engine_info[i].cls);
> > > > > > > + if (!wa_bb_read_advance(data, &p, NULL,
> > > > > > > len,
> > > > > > > &sz))
> > > > > > > + return -ENOBUFS;
> > > > > > > +
> > > > > > > + for (size_t j = 0; j < wa_bb[ec].len;
> > > > > > > j++)
> > > > > > > {
> > > > > > > + len = snprintf(p, sz, " %08x",
> > > > > > > wa_bb[ec].cs[j]);
> > > > > > > + if (!wa_bb_read_advance(data, &p,
> > > > > > > NULL,
> > > > > > > len, &sz))
> > > > > > > + return -ENOBUFS;
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (!wa_bb_read_advance(data, &p, "\n",
> > > > > > > 1,
> > > > > > > &sz))
> > > > > > > + return -ENOBUFS;
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (!wa_bb_read_advance(data, &p, "", 1, &sz))
> > > > > > > + return -ENOBUFS;
> > > > > > > +
> > > > > > > + /* Reserve one more to match check for '\0' */
> > > > > > > + if (!data)
> > > > > > > + p++;
> > > > > > > +
> > > > > > > + return p - data;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t ctx_restore_mid_bb_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > +
> > > > > > > + return wa_bb_show(dev, dev-
> > > > > > > > config.debug.ctx_restore_mid_bb, page, SZ_4K);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t ctx_restore_post_bb_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > +
> > > > > > > + return wa_bb_show(dev, dev-
> > > > > > > > config.debug.ctx_restore_post_bb, page, SZ_4K);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void wa_bb_append(struct wa_bb *wa_bb, u32 val)
> > > > > > > +{
> > > > > > > + if (wa_bb->cs)
> > > > > > > + wa_bb->cs[wa_bb->len] = val;
> > > > > > > +
> > > > > > > + wa_bb->len++;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t parse_hex(const char *line, u32 *pval)
> > > > > > > +{
> > > > > > > + char numstr[12];
> > > > > > > + const char *p;
> > > > > > > + ssize_t numlen;
> > > > > > > +
> > > > > > > + p = line + strspn(line, " \t");
> > > > > > > + if (!*p || *p == '\n')
> > > > > > > + return 0;
> > > > > > > +
> > > > > > > + numlen = strcspn(p, " \t\n");
> > > > > > > + if (!numlen || numlen >= sizeof(numstr) - 1)
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + memcpy(numstr, p, numlen);
> > > > > > > + numstr[numlen] = '\0';
> > > > > > > + p += numlen;
> > > > > > > +
> > > > > > > + if (kstrtou32(numstr, 16, pval))
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + return p - line;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int parse_engine(const char *s, const char
> > > > > > > *end_chars,
> > > > > > > u64
> > > > > > > *mask,
> > > > > > > + const struct engine_info
> > > > > > > **pinfo);
> > > > > > > +
> > > > > > > +/*
> > > > > > > + * Parse lines with the format
> > > > > > > + *
> > > > > > > + * <engine-class> cmd <u32> <u32...>
> > > > > > > + * <engine-class> reg <u32_addr> <u32_val>
> > > > > > > + *
> > > > > > > + * and optionally save them in @wa_bb[i].cs is non-NULL.
> > > > > > > + *
> > > > > > > + * Return the number of dwords parsed.
> > > > > > > + */
> > > > > > > +static ssize_t parse_wa_bb_lines(const char *lines,
> > > > > > > + struct wa_bb
> > > > > > > wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX])
> > > > > > > +{
> > > > > > > + ssize_t dwords = 0, ret;
> > > > > > > + const char *p;
> > > > > > > +
> > > > > > > + for (p = lines; *p; p++) {
> > > > > > > + const struct engine_info *info = NULL;
> > > > > > > + u32 val, val2;
> > > > > > > +
> > > > > > > + /* Also allow empty lines */
> > > > > > > + p += strspn(p, " \t\n");
> > > > > > > + if (!*p)
> > > > > > > + break;
> > > > > > > +
> > > > > > > + ret = parse_engine(p, " \t\n", NULL,
> > > > > > > &info);
> > > > > > > + if (ret < 0)
> > > > > > > + return ret;
> > > > > > > +
> > > > > > > + p += ret;
> > > > > > > + p += strspn(p, " \t");
> > > > > > > +
> > > > > > > + if (str_has_prefix(p, "cmd")) {
> > > > > > > + for (p += strlen("cmd"); *p;) {
> > > > > > > + ret = parse_hex(p, &val);
> > > > > > > + if (ret < 0)
> > > > > > > + return -EINVAL;
> > > > > > > + if (!ret)
> > > > > > > + break;
> > > > > > > +
> > > > > > > + p += ret;
> > > > > > > + dwords++;
> > > > > > > + wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class], val);
> > > > > > > + }
> > > > > > > + } else if (str_has_prefix(p, "reg")) {
> > > > > > > + p += strlen("reg");
> > > > > > > + ret = parse_hex(p, &val);
> > > > > > > + if (ret <= 0)
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + p += ret;
> > > > > > > + ret = parse_hex(p, &val2);
> > > > > > > + if (ret <= 0)
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + p += ret;
> > > > > > > + dwords += 3;
> > > > > > > + wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > + MI_LOAD_REGISTER_IMM
> > > > > > > |
> > > > > > > MI_LRI_NUM_REGS(1));
> > > > > > > + wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > val);
> > > > > > > + wa_bb_append(&wa_bb[info-
> > > > > > > > engine_class],
> > > > > > > val2);
> > > > > > > + } else {
> > > > > > > + return -EINVAL;
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + return dwords;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t wa_bb_store(struct wa_bb wa_bb[static
> > > > > > > XE_ENGINE_CLASS_MAX],
> > > > > > > + struct xe_config_group_device
> > > > > > > *dev,
> > > > > > > + const char *page, size_t len)
> > > > > > > +{
> > > > > > > + /* tmp_wa_bb must match wa_bb's size */
> > > > > > > + struct wa_bb tmp_wa_bb[XE_ENGINE_CLASS_MAX] = {
> > > > > > > };
> > > > > > > + ssize_t count, class;
> > > > > > > + u32 *tmp;
> > > > > > > +
> > > > > > > + /* 1. Count dwords - wa_bb[i].cs is NULL for all
> > > > > > > classes */
> > > > > > > + count = parse_wa_bb_lines(page, tmp_wa_bb);
> > > > > > > + if (count < 0)
> > > > > > > + return count;
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > +
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + /*
> > > > > > > + * 2. Allocate a u32 array and set the pointers
> > > > > > > to
> > > > > > > the
> > > > > > > right positions
> > > > > > > + * according to the length of each class' wa_bb
> > > > > > > + */
> > > > > > > + tmp = krealloc(wa_bb[0].cs, count * sizeof(u32),
> > > > > > > GFP_KERNEL);
> > > > > > > + if (!tmp)
> > > > > > > + return -ENOMEM;
> > > > > > > +
> > > > > > > + if (!count) {
> > > > > > > + memset(wa_bb, 0, sizeof(tmp_wa_bb));
> > > > > > > + return len;
> > > > > > > + }
> > > > > > > +
> > > > > > > + for (class = 0, count = 0; class <
> > > > > > > XE_ENGINE_CLASS_MAX;
> > > > > > > ++class) {
> > > > > > > + tmp_wa_bb[class].cs = tmp + count;
> > > > > > > + count += tmp_wa_bb[class].len;
> > > > > > > + tmp_wa_bb[class].len = 0;
> > > > > > > + }
> > > > > > > +
> > > > > > > + /* 3. Parse wa_bb lines again, this time saving
> > > > > > > the
> > > > > > > values
> > > > > > > */
> > > > > > > + count = parse_wa_bb_lines(page, tmp_wa_bb);
> > > > > > > + if (count < 0) {
> > > > > > > + kfree(tmp);
> > > > > > > + memset(wa_bb, 0, sizeof(tmp_wa_bb));
> > > > > > > + return count;
> > > > > > > + }
> > > > > > > +
> > > > > > > + memcpy(wa_bb, tmp_wa_bb, sizeof(tmp_wa_bb));
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t ctx_restore_mid_bb_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > + const char *data,
> > > > > > > size_t
> > > > > > > sz)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > +
> > > > > > > + return wa_bb_store(dev-
> > > > > > > > config.debug.ctx_restore_mid_bb,
> > > > > > > dev, data, sz);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t ctx_restore_post_bb_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > + const char
> > > > > > > *data,
> > > > > > > size_t
> > > > > > > sz)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > +
> > > > > > > + return wa_bb_store(dev-
> > > > > > > > config.debug.ctx_restore_post_bb,
> > > > > > > dev, data, sz);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_engines_allowed - get engine allowed
> > > > > > > mask
> > > > > > > from
> > > > > > > configfs
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: engine mask with allowed engines set in
> > > > > > > configfs
> > > > > > > + */
> > > > > > > +u64 xe_configfs_get_engines_allowed(struct pci_dev
> > > > > > > *pdev)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + u64 engines_allowed;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return
> > > > > > > xe_configfs_device_defaults.debug.engines_allowed;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock)
> > > > > > > + engines_allowed = dev-
> > > > > > > > config.debug.engines_allowed;
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return engines_allowed;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t engines_allowed_show(struct config_item
> > > > > > > *item,
> > > > > > > char
> > > > > > > *page)
> > > > > > > +{
> > > > > > > + struct xe_config_device *dev =
> > > > > > > xe_configfs_subgroup_to_device(item);
> > > > > > > + char *p = page;
> > > > > > > +
> > > > > > > + for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > + u64 mask = engine_info[i].mask;
> > > > > > > +
> > > > > > > + if ((dev->debug.engines_allowed & mask)
> > > > > > > ==
> > > > > > > mask) {
> > > > > > > + p += sprintf(p, "%s*\n",
> > > > > > > engine_info[i].cls);
> > > > > > > + } else if (mask & dev-
> > > > > > > > debug.engines_allowed) {
> > > > > > > + u16 bit0 = __ffs64(mask), bit;
> > > > > > > +
> > > > > > > + mask &= dev-
> > > > > > > >debug.engines_allowed;
> > > > > > > +
> > > > > > > + for_each_set_bit(bit, (const
> > > > > > > unsigned
> > > > > > > long
> > > > > > > *)&mask, 64)
> > > > > > > + p += sprintf(p, "%s%u\n",
> > > > > > > engine_info[i].cls,
> > > > > > > + bit - bit0);
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + return p - page;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/*
> > > > > > > + * Lookup engine_info. If @mask is not NULL, reduce the
> > > > > > > mask
> > > > > > > according to the
> > > > > > > + * instance in @pattern.
> > > > > > > + *
> > > > > > > + * Examples of inputs:
> > > > > > > + * - lookup_engine_info("rcs0", &mask): return "rcs"
> > > > > > > entry
> > > > > > > from
> > > > > > > @engine_info and
> > > > > > > + * mask == BIT_ULL(XE_HW_ENGINE_RCS0)
> > > > > > > + * - lookup_engine_info("rcs*", &mask): return "rcs"
> > > > > > > entry
> > > > > > > from
> > > > > > > @engine_info and
> > > > > > > + * mask == XE_HW_ENGINE_RCS_MASK
> > > > > > > + * - lookup_engine_info("rcs", NULL): return "rcs" entry
> > > > > > > from
> > > > > > > @engine_info
> > > > > > > + */
> > > > > > > +static const struct engine_info
> > > > > > > *lookup_engine_info(const
> > > > > > > char
> > > > > > > *pattern, u64 *mask)
> > > > > > > +{
> > > > > > > + for (size_t i = 0; i < ARRAY_SIZE(engine_info);
> > > > > > > i++) {
> > > > > > > + u8 instance;
> > > > > > > + u16 bit;
> > > > > > > +
> > > > > > > + if (!str_has_prefix(pattern,
> > > > > > > engine_info[i].cls))
> > > > > > > + continue;
> > > > > > > +
> > > > > > > + pattern += strlen(engine_info[i].cls);
> > > > > > > + if (!mask)
> > > > > > > + return *pattern ? NULL :
> > > > > > > &engine_info[i];
> > > > > > > +
> > > > > > > + if (!strcmp(pattern, "*")) {
> > > > > > > + *mask = engine_info[i].mask;
> > > > > > > + return &engine_info[i];
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (kstrtou8(pattern, 10, &instance))
> > > > > > > + return NULL;
> > > > > > > +
> > > > > > > + bit = __ffs64(engine_info[i].mask) +
> > > > > > > instance;
> > > > > > > + if (bit >= fls64(engine_info[i].mask))
> > > > > > > + return NULL;
> > > > > > > +
> > > > > > > + *mask = BIT_ULL(bit);
> > > > > > > + return &engine_info[i];
> > > > > > > + }
> > > > > > > +
> > > > > > > + return NULL;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int parse_engine(const char *s, const char
> > > > > > > *end_chars,
> > > > > > > u64
> > > > > > > *mask,
> > > > > > > + const struct engine_info **pinfo)
> > > > > > > +{
> > > > > > > + char buf[MAX_ENGINE_CLASS_CHARS +
> > > > > > > MAX_ENGINE_INSTANCE_CHARS
> > > > > > > + 1];
> > > > > > > + const struct engine_info *info;
> > > > > > > + size_t len;
> > > > > > > +
> > > > > > > + len = strcspn(s, end_chars);
> > > > > > > + if (len >= sizeof(buf))
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + memcpy(buf, s, len);
> > > > > > > + buf[len] = '\0';
> > > > > > > +
> > > > > > > + info = lookup_engine_info(buf, mask);
> > > > > > > + if (!info)
> > > > > > > + return -ENOENT;
> > > > > > > +
> > > > > > > + if (pinfo)
> > > > > > > + *pinfo = info;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t engines_allowed_store(struct config_item
> > > > > > > *item,
> > > > > > > const char *page,
> > > > > > > + size_t len)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > + ssize_t patternlen, p;
> > > > > > > + u64 mask, val = 0;
> > > > > > > +
> > > > > > > + for (p = 0; p < len; p += patternlen + 1) {
> > > > > > > + patternlen = parse_engine(page + p,
> > > > > > > ",\n",
> > > > > > > &mask,
> > > > > > > NULL);
> > > > > > > + if (patternlen < 0)
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + val |= mask;
> > > > > > > + }
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + dev->config.debug.engines_allowed = val;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static u64 get_gt_types_allowed(struct pci_dev *pdev)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + u64 mask;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return
> > > > > > > xe_configfs_device_defaults.debug.gt_types_allowed;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock)
> > > > > > > + mask = dev-
> > > > > > > >config.debug.gt_types_allowed;
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return mask;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_primary_gt_allowed - determine whether
> > > > > > > primary
> > > > > > > GTs
> > > > > > > are supported
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: True if primary GTs are enabled, false if
> > > > > > > they
> > > > > > > have
> > > > > > > been disabled via
> > > > > > > + * configfs.
> > > > > > > + */
> > > > > > > +bool xe_configfs_primary_gt_allowed(struct pci_dev
> > > > > > > *pdev)
> > > > > > > +{
> > > > > > > + return get_gt_types_allowed(pdev) &
> > > > > > > BIT_ULL(XE_GT_TYPE_MAIN);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_media_gt_allowed - determine whether
> > > > > > > media
> > > > > > > GTs
> > > > > > > are
> > > > > > > supported
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: True if the media GTs are enabled, false if
> > > > > > > they
> > > > > > > have
> > > > > > > been disabled
> > > > > > > + * via configfs.
> > > > > > > + */
> > > > > > > +bool xe_configfs_media_gt_allowed(struct pci_dev *pdev)
> > > > > > > +{
> > > > > > > + return get_gt_types_allowed(pdev) &
> > > > > > > BIT_ULL(XE_GT_TYPE_MEDIA);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t gt_types_allowed_show(struct config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > +{
> > > > > > > + struct xe_config_device *dev =
> > > > > > > xe_configfs_subgroup_to_device(item);
> > > > > > > + char *p = page;
> > > > > > > +
> > > > > > > + for (size_t i = 0; i < ARRAY_SIZE(gt_types); i++)
> > > > > > > + if (dev->debug.gt_types_allowed &
> > > > > > > BIT_ULL(gt_types[i].type))
> > > > > > > + p += sprintf(p, "%s\n",
> > > > > > > gt_types[i].name);
> > > > > > > +
> > > > > > > + return p - page;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t gt_types_allowed_store(struct config_item
> > > > > > > *item,
> > > > > > > const char *page,
> > > > > > > + size_t len)
> > > > > > > +{
> > > > > > > + char *buf __free(kfree) = kstrdup(page,
> > > > > > > GFP_KERNEL);
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > + u64 typemask = 0;
> > > > > > > + char *p = buf;
> > > > > > > +
> > > > > > > + if (!buf)
> > > > > > > + return -ENOMEM;
> > > > > > > +
> > > > > > > + while (p) {
> > > > > > > + char *typename = strsep(&p, ",\n");
> > > > > > > + bool matched = false;
> > > > > > > +
> > > > > > > + if (typename[0] == '\0')
> > > > > > > + continue;
> > > > > > > +
> > > > > > > + for (size_t i = 0; i <
> > > > > > > ARRAY_SIZE(gt_types);
> > > > > > > i++) {
> > > > > > > + if (strcmp(typename,
> > > > > > > gt_types[i].name)
> > > > > > > ==
> > > > > > > 0) {
> > > > > > > + typemask |=
> > > > > > > BIT(gt_types[i].type);
> > > > > > > + matched = true;
> > > > > > > + break;
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (!matched)
> > > > > > > + return -EINVAL;
> > > > > > > + }
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + dev->config.debug.gt_types_allowed = typemask;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_enable_multi_queue - get configfs
> > > > > > > enable_multi_queue setting
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: true if multi-queue is enabled for this
> > > > > > > device
> > > > > > > (the
> > > > > > > default),
> > > > > > > + * false if it has been force-disabled via configfs.
> > > > > > > + */
> > > > > > > +bool xe_configfs_get_enable_multi_queue(struct pci_dev
> > > > > > > *pdev)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + bool ret;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return
> > > > > > > xe_configfs_device_defaults.debug.enable_multi_queue;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock)
> > > > > > > + ret = dev-
> > > > > > > >config.debug.enable_multi_queue;
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t enable_multi_queue_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > +{
> > > > > > > + struct xe_config_device *dev =
> > > > > > > xe_configfs_subgroup_to_device(item);
> > > > > > > +
> > > > > > > + return sprintf(page, "%d\n", dev-
> > > > > > > > debug.enable_multi_queue);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t enable_multi_queue_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > const char *page, size_t len)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > + bool val;
> > > > > > > + int ret;
> > > > > > > +
> > > > > > > + ret = kstrtobool(page, &val);
> > > > > > > + if (ret)
> > > > > > > + return ret;
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + dev->config.debug.enable_multi_queue = val;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_psmi_enabled - get configfs
> > > > > > > enable_psmi
> > > > > > > setting
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: enable_psmi setting in configfs
> > > > > > > + */
> > > > > > > +bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + bool ret;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return false;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock)
> > > > > > > + ret = dev->config.debug.enable_psmi;
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t enable_psmi_show(struct config_item
> > > > > > > *item,
> > > > > > > char
> > > > > > > *page)
> > > > > > > +{
> > > > > > > + struct xe_config_device *dev =
> > > > > > > xe_configfs_subgroup_to_device(item);
> > > > > > > +
> > > > > > > + return sprintf(page, "%d\n", dev-
> > > > > > > > debug.enable_psmi);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t enable_psmi_store(struct config_item
> > > > > > > *item,
> > > > > > > const
> > > > > > > char *page, size_t len)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > + bool val;
> > > > > > > + int ret;
> > > > > > > +
> > > > > > > + ret = kstrtobool(page, &val);
> > > > > > > + if (ret)
> > > > > > > + return ret;
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + dev->config.debug.enable_psmi = val;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_get_survivability_mode - get configfs
> > > > > > > survivability
> > > > > > > mode attribute
> > > > > > > + * @pdev: pci device
> > > > > > > + *
> > > > > > > + * Return: survivability_mode attribute in configfs
> > > > > > > + */
> > > > > > > +bool xe_configfs_get_survivability_mode(struct pci_dev
> > > > > > > *pdev)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > find_device(pdev);
> > > > > > > + bool mode;
> > > > > > > +
> > > > > > > + if (!dev)
> > > > > > > + return
> > > > > > > xe_configfs_device_defaults.debug.survivability_mode;
> > > > > > > +
> > > > > > > + scoped_guard(mutex, &dev->lock)
> > > > > > > + mode = dev-
> > > > > > > > config.debug.survivability_mode;
> > > > > > > + config_group_put(&dev->group);
> > > > > > > +
> > > > > > > + return mode;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t survivability_mode_show(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > char *page)
> > > > > > > +{
> > > > > > > + struct xe_config_device *dev =
> > > > > > > xe_configfs_subgroup_to_device(item);
> > > > > > > +
> > > > > > > + return sprintf(page, "%d\n", dev-
> > > > > > > > debug.survivability_mode);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t survivability_mode_store(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > const char *page, size_t len)
> > > > > > > +{
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > xe_configfs_subgroup_to_group_device(item);
> > > > > > > + bool survivability_mode;
> > > > > > > + int ret;
> > > > > > > +
> > > > > > > + ret = kstrtobool(page, &survivability_mode);
> > > > > > > + if (ret)
> > > > > > > + return ret;
> > > > > > > +
> > > > > > > + guard(mutex)(&dev->lock);
> > > > > > > + if (xe_configfs_is_bound(dev))
> > > > > > > + return -EBUSY;
> > > > > > > +
> > > > > > > + dev->config.debug.survivability_mode =
> > > > > > > survivability_mode;
> > > > > > > +
> > > > > > > + return len;
> > > > > > > +}
> > > > > > > +
> > > > > > > +CONFIGFS_ATTR(, ctx_restore_mid_bb);
> > > > > > > +CONFIGFS_ATTR(, ctx_restore_post_bb);
> > > > > > > +CONFIGFS_ATTR(, engines_allowed);
> > > > > > > +CONFIGFS_ATTR(, gt_types_allowed);
> > > > > > > +CONFIGFS_ATTR(, enable_multi_queue);
> > > > > > > +CONFIGFS_ATTR(, enable_psmi);
> > > > > > > +CONFIGFS_ATTR(, survivability_mode);
> > > > > > > +
> > > > > > > +static struct configfs_attribute
> > > > > > > *xe_configfs_debug_attrs[] =
> > > > > > > {
> > > > > > > + &attr_ctx_restore_mid_bb,
> > > > > > > + &attr_ctx_restore_post_bb,
> > > > > > > + &attr_engines_allowed,
> > > > > > > + &attr_gt_types_allowed,
> > > > > > > + &attr_enable_multi_queue,
> > > > > > > + &attr_enable_psmi,
> > > > > > > + &attr_survivability_mode,
> > > > > > > + NULL,
> > > > > > > +};
> > > > > > > +
> > > > > > > +/*
> > > > > > > + * Per-parameter visibility predicates.
> > > > > > > + *
> > > > > > > + * XE_PARAM_VISIBLE_ALWAYS - attribute is always shown.
> > > > > > > + * XE_PARAM_VISIBLE_SURVIVABILITY - only shown on dGFX
> > > > > > > platforms
> > > > > > > > = Battlemage.
> > > > > > > + *
> > > > > > > + * These macros are only evaluated here, where the
> > > > > > > platform
> > > > > > > descriptor is
> > > > > > > + * reachable. xe_configfs_debug_params.h treats them as
> > > > > > > opaque
> > > > > > > tokens.
> > > > > > > + */
> > > > > > > +#define XE_PARAM_VISIBLE_ALWAYS(_item) \
> > > > > > > + (true)
> > > > > > > +#define XE_PARAM_VISIBLE_SURVIVABILITY(_item) \
> > > > > > > + (xe_configfs_subgroup_to_group_device(_item)-
> > > > > > > >desc-
> > > > > > > > is_dgfx
> > > > > > > && \
> > > > > > > + xe_configfs_subgroup_to_group_device(_item)-
> > > > > > > >desc-
> > > > > > > > platform >= XE_BATTLEMAGE)
> > > > > > > +
> > > > > > > +static bool xe_configfs_debug_is_visible(struct
> > > > > > > config_item
> > > > > > > *item,
> > > > > > > + struct
> > > > > > > configfs_attribute
> > > > > > > *attr, int n)
> > > > > > > +{
> > > > > > > + if (attr == &attr_survivability_mode) {
> > > > > > > + struct xe_config_group_device *dev =
> > > > > > > + xe_configfs_to_group_device(item-
> > > > > > > > ci_parent);
> > > > > > > +
> > > > > > > + return dev->desc->is_dgfx && dev->desc-
> > > > > > > > platform >=
> > > > > > > XE_BATTLEMAGE;
> > > > > > > + }
> > > > > > > +
> > > > > > > + return true;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static struct configfs_group_operations
> > > > > > > xe_configfs_debug_group_ops = {
> > > > > > > + .is_visible = xe_configfs_debug_is_visible,
> > > > > > > +};
> > > > > > >
> > > > > > > const struct config_item_type xe_configfs_debug_type = {
> > > > > > > + .ct_attrs = xe_configfs_debug_attrs,
> > > > > > > + .ct_group_ops = &xe_configfs_debug_group_ops,
> > > > > > > .ct_owner = THIS_MODULE,
> > > > > > > };
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * xe_configfs_debug_release_config - release debug-
> > > > > > > specific
> > > > > > > config resources
> > > > > > > + * @config: xe config device structure
> > > > > > > + *
> > > > > > > + * Frees any memory allocated for debug configfs
> > > > > > > parameters.
> > > > > > > + */
> > > > > > > +void xe_configfs_debug_release_config(struct
> > > > > > > xe_config_device
> > > > > > > *config)
> > > > > > > +{
> > > > > > > + kfree(config->debug.ctx_restore_mid_bb[0].cs);
> > > > > > > + kfree(config->debug.ctx_restore_post_bb[0].cs);
> > > > > > > +}
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_configfs_debug.h
> > > > > > > b/drivers/gpu/drm/xe/xe_configfs_debug.h
> > > > > > > index 5f938450aed2..4a027ea2082d 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_configfs_debug.h
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_configfs_debug.h
> > > > > > > @@ -5,9 +5,46 @@
> > > > > > > #ifndef _XE_CONFIGFS_DEBUG_H_
> > > > > > > #define _XE_CONFIGFS_DEBUG_H_
> > > > > > >
> > > > > > > +#include <linux/types.h>
> > > > > > > +
> > > > > > > +#include "xe_hw_engine_types.h"
> > > > > > > +
> > > > > > > +struct pci_dev;
> > > > > > > +struct xe_config_device;
> > > > > > > +
> > > > > > > #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) &&
> > > > > > > IS_ENABLED(CONFIG_CONFIGFS_FS)
> > > > > > > -struct config_item_type;
> > > > > > > extern const struct config_item_type
> > > > > > > xe_configfs_debug_type;
> > > > > > > +void xe_configfs_debug_release_config(struct
> > > > > > > xe_config_device
> > > > > > > *config);
> > > > > > > +u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > + enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > + const u32 **cs);
> > > > > > > +u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev
> > > > > > > *pdev,
> > > > > > > + enum
> > > > > > > xe_engine_class
> > > > > > > class,
> > > > > > > + const u32 **cs);
> > > > > > > +u64 xe_configfs_get_engines_allowed(struct pci_dev
> > > > > > > *pdev);
> > > > > > > +bool xe_configfs_primary_gt_allowed(struct pci_dev
> > > > > > > *pdev);
> > > > > > > +bool xe_configfs_media_gt_allowed(struct pci_dev *pdev);
> > > > > > > +bool xe_configfs_get_enable_multi_queue(struct pci_dev
> > > > > > > *pdev);
> > > > > > > +bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev);
> > > > > > > +bool xe_configfs_get_survivability_mode(struct pci_dev
> > > > > > > *pdev);
> > > > > > > +#else
> > > > > > > +/*
> > > > > > > + * Dummy values here are not used since these function
> > > > > > > accesses
> > > > > > > are always
> > > > > > > + * wrapped in CONFIG_DRM_XE_DEBUG.
> > > > > > > + */
> > > > > > > +static inline void
> > > > > > > xe_configfs_debug_release_config(struct
> > > > > > > xe_config_device *config) { }
> > > > > > > +static inline u32
> > > > > > > xe_configfs_get_ctx_restore_mid_bb(struct
> > > > > > > pci_dev *pdev,
> > > > > > > + enum
> > > > > > > xe_engine_class class,
> > > > > > > +
> > > > > > > const
> > > > > > > u32
> > > > > > > **cs) { return 0; }
> > > > > > > +static inline u32
> > > > > > > xe_configfs_get_ctx_restore_post_bb(struct
> > > > > > > pci_dev *pdev,
> > > > > > > +
> > > > > > > enum
> > > > > > > xe_engine_class class,
> > > > > > > +
> > > > > > > const
> > > > > > > u32
> > > > > > > **cs) { return 0; }
> > > > > > > +static inline u64 xe_configfs_get_engines_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return U64_MAX; }
> > > > > > > +static inline bool xe_configfs_primary_gt_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return true; }
> > > > > > > +static inline bool xe_configfs_media_gt_allowed(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return true; }
> > > > > > > +static inline bool
> > > > > > > xe_configfs_get_enable_multi_queue(struct
> > > > > > > pci_dev *pdev) { return true; }
> > > > > > > +static inline bool xe_configfs_get_psmi_enabled(struct
> > > > > > > pci_dev
> > > > > > > *pdev) { return false; }
> > > > > > > +static inline bool
> > > > > > > xe_configfs_get_survivability_mode(struct
> > > > > > > pci_dev *pdev) { return false; }
> > > > > > > #endif
> > > > > > >
> > > > > > > #endif /* _XE_CONFIGFS_DEBUG_H_ */
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_configfs_types.h
> > > > > > > b/drivers/gpu/drm/xe/xe_configfs_types.h
> > > > > > > index e22b9424f719..6e8ba6f85fad 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_configfs_types.h
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_configfs_types.h
> > > > > > > @@ -32,13 +32,17 @@ struct xe_config_group_device {
> > > > > > > * type, entries are sorted alphabetically.
> > > > > > > */
> > > > > > > struct xe_config_device {
> > > > > > > - struct wa_bb
> > > > > > > ctx_restore_mid_bb[XE_ENGINE_CLASS_MAX];
> > > > > > > - struct wa_bb
> > > > > > > ctx_restore_post_bb[XE_ENGINE_CLASS_MAX];
> > > > > > > - u64 engines_allowed;
> > > > > > > - u64 gt_types_allowed;
> > > > > > > - bool enable_multi_queue;
> > > > > > > - bool enable_psmi;
> > > > > > > - bool survivability_mode;
> > > > > > > +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
> > > > > > > + struct {
> > > > > > > + struct wa_bb
> > > > > > > ctx_restore_mid_bb[XE_ENGINE_CLASS_MAX];
> > > > > > > + struct wa_bb
> > > > > > > ctx_restore_post_bb[XE_ENGINE_CLASS_MAX];
> > > > > > > + u64 engines_allowed;
> > > > > > > + u64 gt_types_allowed;
> > > > > > > + bool enable_multi_queue;
> > > > > > > + bool enable_psmi;
> > > > > > > + bool survivability_mode;
> > > > > > > + } debug;
> > > > > > > +#endif
> > > > > > > struct {
> > > > > > > unsigned int max_vfs;
> > > > > > > bool admin_only_pf;
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_guc.c
> > > > > > > b/drivers/gpu/drm/xe/xe_guc.c
> > > > > > > index c7f8bbd4cb92..bf7ca8f9d773 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_guc.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_guc.c
> > > > > > > @@ -19,6 +19,7 @@
> > > > > > > #include "regs/xe_irq_regs.h"
> > > > > > > #include "xe_bo.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_force_wake.h"
> > > > > > > #include "xe_gt.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c
> > > > > > > b/drivers/gpu/drm/xe/xe_guc_ads.c
> > > > > > > index ff8eee3831aa..9a6895377c17 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_guc_ads.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_guc_ads.c
> > > > > > > @@ -17,6 +17,7 @@
> > > > > > > #include "regs/xe_guc_regs.h"
> > > > > > > #include "xe_bo.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_gt.h"
> > > > > > > #include "xe_gt_ccs_mode.h"
> > > > > > > #include "xe_gt_mcr.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c
> > > > > > > b/drivers/gpu/drm/xe/xe_hw_engine.c
> > > > > > > index 010499766fce..f4740de7f57b 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_hw_engine.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
> > > > > > > @@ -18,6 +18,7 @@
> > > > > > > #include "xe_assert.h"
> > > > > > > #include "xe_bo.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_execlist.h"
> > > > > > > #include "xe_force_wake.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_lrc.c
> > > > > > > b/drivers/gpu/drm/xe/xe_lrc.c
> > > > > > > index 35b4e8289b5f..449cdd1e2513 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_lrc.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_lrc.c
> > > > > > > @@ -19,6 +19,7 @@
> > > > > > > #include "xe_bb.h"
> > > > > > > #include "xe_bo.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_drm_client.h"
> > > > > > > #include "xe_exec_queue.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_pci.c
> > > > > > > b/drivers/gpu/drm/xe/xe_pci.c
> > > > > > > index ab4da1d9a9f1..fd3eae45dacf 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_pci.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_pci.c
> > > > > > > @@ -19,6 +19,7 @@
> > > > > > > #include "regs/xe_gt_regs.h"
> > > > > > > #include "regs/xe_regs.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_drv.h"
> > > > > > > #include "xe_gt.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_psmi.c
> > > > > > > b/drivers/gpu/drm/xe/xe_psmi.c
> > > > > > > index 899b01f72ba3..59af3d145418 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_psmi.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_psmi.c
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > > #include "xe_bo.h"
> > > > > > > #include "xe_device_types.h"
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_psmi.h"
> > > > > > >
> > > > > > > /*
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_rtp.c
> > > > > > > b/drivers/gpu/drm/xe/xe_rtp.c
> > > > > > > index 6a8d6ea68f25..62068189320f 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_rtp.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_rtp.c
> > > > > > > @@ -10,6 +10,7 @@
> > > > > > > #include <uapi/drm/xe_drm.h>
> > > > > > >
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_gt.h"
> > > > > > > #include "xe_gt_topology.h"
> > > > > > > diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c
> > > > > > > b/drivers/gpu/drm/xe/xe_survivability_mode.c
> > > > > > > index 45d44ebe288b..1238fd018d61 100644
> > > > > > > --- a/drivers/gpu/drm/xe/xe_survivability_mode.c
> > > > > > > +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c
> > > > > > > @@ -11,6 +11,7 @@
> > > > > > > #include <linux/sysfs.h>
> > > > > > >
> > > > > > > #include "xe_configfs.h"
> > > > > > > +#include "xe_configfs_debug.h"
> > > > > > > #include "xe_device.h"
> > > > > > > #include "xe_heci_gsc.h"
> > > > > > > #include "xe_i2c.h"
> > > > > > > --
> > > > > > > 2.43.0
> > > > > > >
> > > > > >
> > > > >
> > >
> >
next prev parent reply other threads:[~2026-08-28 18:57 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 21:06 [PATCH 00/10] Add new debug infrastructure for configfs Stuart Summers
2026-08-20 21:06 ` [PATCH 01/10] drm/xe: Guard configfs attribute reads in getters Stuart Summers
2026-08-20 21:24 ` sashiko-bot
2026-08-21 20:42 ` Matt Roper
2026-08-24 14:45 ` Summers, Stuart
2026-08-20 21:06 ` [PATCH 02/10] drm/xe: Sort xe_config_device fields Stuart Summers
2026-08-20 21:24 ` sashiko-bot
2026-08-21 21:06 ` Matt Roper
2026-08-24 16:52 ` Summers, Stuart
2026-08-20 21:06 ` [PATCH 03/10] drm/xe: Split out configfs data structures Stuart Summers
2026-08-21 21:16 ` Matt Roper
2026-08-24 20:18 ` Summers, Stuart
2026-08-20 21:06 ` [PATCH 04/10] drm/xe: Add a new debug focused configfs group Stuart Summers
2026-08-21 22:08 ` Matt Roper
2026-08-23 21:22 ` Michal Wajdeczko
2026-08-24 20:18 ` Summers, Stuart
2026-08-20 21:06 ` [PATCH 05/10] drm/xe: Move debug configfs entries to xe_configfs_debug.c Stuart Summers
2026-08-20 21:28 ` sashiko-bot
2026-08-21 22:18 ` Matt Roper
2026-08-24 20:28 ` Summers, Stuart
2026-08-26 21:20 ` Rodrigo Vivi
2026-08-28 16:34 ` Summers, Stuart
2026-08-28 16:53 ` Rodrigo Vivi
2026-08-28 17:31 ` Matt Roper
2026-08-28 18:51 ` Summers, Stuart
2026-08-28 18:57 ` Vivi, Rodrigo [this message]
2026-08-20 21:06 ` [PATCH 06/10] drm/xe/guc: Add configfs support for guc_log_level Stuart Summers
2026-08-20 21:06 ` [PATCH 07/10] drm/xe/guc: Add support for NPK as a GuC log target Stuart Summers
2026-08-20 21:06 ` [PATCH 08/10] drm/xe: Add infrastructure for debug configfs parameters Stuart Summers
2026-08-20 21:06 ` [PATCH 09/10] drm/xe: Migrate existing debug configfs entries to params infrastructure Stuart Summers
2026-08-20 21:06 ` [PATCH 10/10] drm/xe: Taint kernel when debug configfs parameters are set Stuart Summers
2026-08-20 21:24 ` sashiko-bot
2026-08-20 22:12 ` ✗ CI.checkpatch: warning for Add new debug infrastructure for configfs (rev7) Patchwork
2026-08-20 22:13 ` ✓ CI.KUnit: success " Patchwork
2026-08-20 22:52 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-21 1:28 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-08-21 19:27 ` [PATCH 00/10] Add new debug infrastructure for configfs Summers, Stuart
-- strict thread matches above, loose matches on Subject: below --
2026-08-20 20:07 Stuart Summers
2026-08-20 20:07 ` [PATCH 05/10] drm/xe: Move debug configfs entries to xe_configfs_debug.c Stuart Summers
2026-08-20 20:20 ` sashiko-bot
2026-08-07 19:45 [PATCH 00/10] Add new debug infrastructure for configfs Stuart Summers
2026-08-07 19:45 ` [PATCH 05/10] drm/xe: Move debug configfs entries to xe_configfs_debug.c Stuart Summers
2026-08-05 23:20 [PATCH 00/10] Add new debug infrastructure for configfs Stuart Summers
2026-08-05 23:20 ` [PATCH 05/10] drm/xe: Move debug configfs entries to xe_configfs_debug.c Stuart Summers
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=7c9244d92621b96fc8c2e6a9a455143f970e6fcb.camel@intel.com \
--to=rodrigo.vivi@intel.com \
--cc=daniele.ceraolospurio@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@intel.com \
--cc=matthew.d.roper@intel.com \
--cc=michal.wajdeczko@intel.com \
--cc=riana.tauro@intel.com \
--cc=shuicheng.lin@intel.com \
--cc=stuart.summers@intel.com \
--cc=umesh.nerlige.ramappa@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