RE: [PATCH] tests/core_hotunplug: add *-with-load subtests exercising GPU workload during hotplug

"Gote, Nitin R" <[email protected]>
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <SA3PR11MB8118D7C49893DDAF83217042D0A32@SA3PR11MB8118.namprd11.prod.outlook.com>
Hi Janusz,

> -----Original Message-----
> From: Janusz Krzysztofik <[email protected]>
> Sent: Friday, August 21, 2026 3:13 PM
> To: Gote, Nitin R <[email protected]>; [email protected]
> Cc: Auld, Matthew <[email protected]>; Kamil Konieczny
> <[email protected]>
> Subject: Re: [PATCH] tests/core_hotunplug: add *-with-load subtests exercising
> GPU workload during hotplug
> 
> Hi Nitin,
> 
> Good job, however, I think we still need some improvements.
> 
> On Fri, 2026-08-21 at 12:28 +0530, Nitin Gote wrote:
> > The six fd-holding hot* subtests keep a DRM fd open across
> > unbind/unplug but leave the GPU idle, so the kernel hotplug path is
> > never exercised against an active workload.
> >
> > Add six new dedicated *-with-load subtests that run a GPU spinner
> > across the unbind/unplug sequence so the device is removed while a
> > workload is actively using it.
> >
> > The workload helpers use an explicit chipset dispatch block in
> > workload_start()/stop() so that other vendors can contribute support
> > by adding an else-if branch. New subtests are gated on
> > workload_available(), which currently covers DRIVER_XE and
> > DRIVER_INTEL, and returns false (SKIP) on any other driver.
> >
> > igt_spin_free() is avoided in workload_stop() since the device may be
> > gone by then -- igt_spin_end() writes the stop condition via a
> > userspace mmap and lets the DRM fd close reclaim kernel-side resources.
> >
> > Validated on BMG and DG2 with a KASAN-enabled kernel:
> > all six new subtests pass with no KASAN reports.
> >
> > v4: Rebase to latest igt.
> >     Also the failure seen with the new core_hotunplug "with-load"
> >     IGT subtests is fixed by kmd patch:
> >     https://patchwork.freedesktop.org/series/171989/
> >
> > v3: Extend struct gpu_workload with a union of vendor-named members
> >     to match the chipset dispatch in workload_start()/stop(). (Janusz)
> >
> > v2: Pass the hotunplug priv struct to workload_start()/stop()
> >     and dispatch via an explicit if/else-if chipset block to invite
> >     other vendors to contribute. (Janusz)
> >
> > Cc: Matthew Auld <[email protected]>
> > Cc: Janusz Krzysztofik <[email protected]>
> > Cc: Kamil Konieczny <[email protected]>
> > Reviewed-by: Janusz Krzysztofik <[email protected]>
> > Signed-off-by: Nitin Gote <[email protected]>
> > ---
> >  tests/core_hotunplug.c | 294
> > +++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 294 insertions(+)
> >
> > diff --git a/tests/core_hotunplug.c b/tests/core_hotunplug.c index
> > 33de65369..b11a4231b 100644
> > --- a/tests/core_hotunplug.c
> > +++ b/tests/core_hotunplug.c
> > @@ -80,6 +80,34 @@
> >   * SUBTEST: unplug-rescan
> >   * Description: Check if a device believed to be closed can be cleanly
> >   *		unplugged, then restored
> > + *
> > + * SUBTEST: hotunbind-rebind-with-load
> > + * Description: Check if the driver can be cleanly unbound from an open device
> > + *		with a background GPU workload in flight, then released and
> > + *		rebound
> > + *
> > + * SUBTEST: hotunplug-rescan-with-load
> > + * Description: Check if an open device with a background GPU workload in
> > + *		flight can be cleanly unplugged, then released and restored
> > + *
> > + * SUBTEST: hotrebind-with-load
> > + * Description: Check if the driver can be cleanly rebound to a device with a
> > + *		still open hot unbound driver instance while a background GPU
> > + *		workload is in flight
> > + *
> > + * SUBTEST: hotreplug-with-load
> > + * Description: Check if a hot unplugged and still open device can be cleanly
> > + *		restored while a background GPU workload is in flight
> > + *
> > + * SUBTEST: hotrebind-lateclose-with-load
> > + * Description: Check if a hot unbound driver instance still open after hot
> > + *		rebind with a background GPU workload in flight can be cleanly
> > + *		released
> > + *
> > + * SUBTEST: hotreplug-lateclose-with-load
> > + * Description: Check if an instance of a still open while hot replugged
> > + *		device with a background GPU workload in flight can be cleanly
> > + *		released
> >   */
> >
> >  IGT_TEST_DESCRIPTION("Examine behavior of a driver on device hot
> > unplug"); @@ -550,6 +578,56 @@ static void post_healthcheck(struct
> hotunplug *priv)
> >  	cleanup(priv);
> >  }
> >
> > +/* GPU workload helpers */
> > +
> > +struct gpu_workload {
> > +	union {
> > +		struct {
> > +			igt_spin_t *spin;
> > +			uint64_t ahnd;
> > +		} intel; /* Xe and i915 */
> > +	};
> > +};
> > +
> > +static bool workload_available(int chipset) {
> > +	return chipset == DRIVER_XE || chipset == DRIVER_INTEL;
> 
> NIT: I think a switch (chipset) { case DRIVER_XE: ... } construct, here
> and consequently below in workload_start/stop, could be more effective and
> more easily extendable with potential future additions from other vendors, but
> that can be refactored later, on a first such addition.
> 

> > +}
> > +
> > +static void workload_start(struct hotunplug *priv, int fd,
> > +			   struct gpu_workload *w)
> > +{
> > +	if (priv->chipset == DRIVER_XE || priv->chipset == DRIVER_INTEL) {
> > +		local_debug("%s\n", "starting GPU spinner");
> > +		priv->failure = "GPU workload start failure!";
> > +		w->intel.ahnd = intel_allocator_open(fd, 0,
> INTEL_ALLOCATOR_RELOC);
> > +		w->intel.spin = igt_spin_new(fd, .ahnd = w->intel.ahnd);
> > +		priv->failure = NULL;
> > +	}
> > +}
> > +
> > +static void workload_stop(struct hotunplug *priv, struct gpu_workload
> > +*w) {
> > +	if (priv->chipset == DRIVER_XE || priv->chipset == DRIVER_INTEL) {
> > +		if (!w->intel.spin)
> > +			return;
> 
> Since igt_fail() can be called from inside igt_spin_new(), workload_start() can fail
> leaving an open ahnd but no spin.  We need to handle that case.
> 
> > +
> > +		/*
> > +		 * The device may be gone (unbind/unplug), so avoid
> > +		 * igt_spin_free(): on Xe it would wait forever on a syncobj
> > +		 * that never signals; on i915 it would touch the dead fd via
> > +		 * gem_munmap()/gem_close(). Instead, end the spinner via a
> > +		 * userspace mmap write and let the DRM fd close reclaim the
> > +		 * kernel-side resources.
> > +		 */
> > +		local_debug("%s\n", "stopping GPU spinner");
> > +		igt_spin_end(w->intel.spin);
> > +		put_ahnd(w->intel.ahnd);
> > +		w->intel.spin = NULL;
> > +		w->intel.ahnd = 0;
> > +	}
> > +}
> > +
> >  /* Subtests */
> >
> >  static void unbind_rebind(struct hotunplug *priv) @@ -664,6 +742,150
> > @@ static void hotreplug_lateclose(struct hotunplug *priv)
> >  	igt_assert_f(healthcheck(priv, false), "%s\n", priv->failure);  }
> >
> > +static void hotunbind_rebind_with_load(struct hotunplug *priv) {
> > +	struct gpu_workload w = { 0 };
> > +
> > +	pre_check(priv);
> > +
> > +	igt_require_f(workload_available(priv->chipset),
> > +		      "No GPU workload support for this driver\n");
> > +
> > +	priv->fd.drm = local_drm_open_driver(false, "", " for hot unbind");
> > +
> > +	workload_start(priv, priv->fd.drm, &w);
> > +
> > +	driver_unbind(priv, "hot ", 0);
> 
> Since igt_fail() can be called from driver_unbind(), as well as from other functions
> called between workload_start() and workload_stop() in other subtests below, we
> need to address those cases to be on the safe side.
> We could e.g.:
> - embed struct gpu_workload inside struct hotunplug,
> - extend cleanup() (or recover()) function with another workload_stop().
> 

Thank you for the improvement suggestions. I have noted all three comments.
As this patch has been merged in between, I will address these review comments in a separate patch.

- Nitin

> Thanks,
> Janusz
> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.