[PATCH 11/12] drm/xe/tests: Add KUnit tests for VF control state machines
Piotr Piórkowski
piotr.piorkowski at intel.com
Thu Aug 22 10:47:57 UTC 2024
Michal Wajdeczko <michal.wajdeczko at intel.com> wrote on pią [2024-sie-09 18:51:58 +0200]:
> Add KUnit tests (~200) for all VF control state machines (FLR,
> PAUSE, STOP and RESUME) to make sure they work as expected and
> will not be broken while extending them with new functionality.
>
> Signed-off-by: Michal Wajdeczko <michal.wajdeczko at intel.com>
> Cc: Lucas De Marchi <lucas.demarchi at intel.com>
> ---
> Test file named according to the new best practices [1]
> [1] https://lore.kernel.org/linux-hardening/20240724201354.make.730-kees@kernel.org/
> ---
> .../xe/tests/xe_gt_sriov_pf_control_kunit.c | 1360 +++++++++++++++++
> drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c | 7 +
> 2 files changed, 1367 insertions(+)
> create mode 100644 drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_control_kunit.c
>
> diff --git a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_control_kunit.c b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_control_kunit.c
> new file mode 100644
> index 000000000000..4252577b4bbd
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_control_kunit.c
> @@ -0,0 +1,1360 @@
> +// SPDX-License-Identifier: GPL-2.0 AND MIT
> +/*
> + * Copyright © 2024 Intel Corporation
> + */
> +
> +#include <kunit/test.h>
> +#include <kunit/static_stub.h>
> +
> +#include "tests/xe_kunit_helpers.h"
> +#include "tests/xe_pci_test.h"
> +
> +#include "xe_gt_sriov_pf.h"
> +
> +static const unsigned int DUT_NUM_VFS = 2;
> +static const unsigned int VFUT1 = VFID(1);
> +static const unsigned int VFUT2 = VFID(2);
> +
> +static void dump_state(void *arg)
> +{
> + struct xe_gt *gt = arg;
> +
> + pf_dump_vf_state(gt, VFUT1);
> +}
> +
> +static unsigned long replacement_timeout(enum xe_gt_sriov_control_bits bit)
> +{
> + return HZ;
> +}
> +
> +static int pf_control_test_init(struct kunit *test)
> +{
> + struct xe_pci_fake_data fake = {
> + .sriov_mode = XE_SRIOV_MODE_PF,
> + .platform = XE_TIGERLAKE, /* some random platform */
> + .subplatform = XE_SUBPLATFORM_NONE,
> + };
> + struct xe_device *xe;
> + struct xe_gt *gt;
> +
> + test->priv = &fake;
> + xe_kunit_helper_xe_device_test_init(test);
> +
> + xe = test->priv;
> + KUNIT_ASSERT_EQ(test, xe_sriov_init(xe), 0);
> +
> + xe->sriov.pf.driver_max_vfs = DUT_NUM_VFS;
> + KUNIT_EXPECT_NE(test, xe_sriov_pf_get_totalvfs(xe), 0);
> +
> + gt = xe_device_get_gt(xe, 0);
> + KUNIT_ASSERT_EQ(test, xe_gt_sriov_pf_init_early(gt), 0);
> +
> + KUNIT_ASSERT_EQ(test, 0ul, *__pf_peek_vf_state(gt, VFUT1));
> + KUNIT_ASSERT_EQ(test, 0ul, *__pf_peek_vf_state(gt, VFUT2));
> +
> + KUNIT_EXPECT_EQ(test, 0, kunit_add_action_or_reset(test, dump_state, gt));
> +
> + kunit_activate_static_stub(test, pf_get_default_timeout, replacement_timeout);
> +
> + test->priv = gt;
> + return 0;
> +}
> +
> +static int sanitize_vf_resources_fail(struct xe_gt *gt, u32 vfid, long timeout)
> +{
> + return -ETIMEDOUT;
> +}
> +
> +static int send_vf_control_cmd_reject(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return -EIO;
> +}
> +
> +static int send_vf_control_cmd_fail(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return -ENODEV;
> +}
> +
> +static int send_vf_control_cmd_pass_no_reply(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return 0;
> +}
> +
> +static int send_vf_control_cmd_pass_and_reply(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + switch (cmd) {
> + case GUC_PF_TRIGGER_VF_PAUSE:
> + pf_handle_vf_event(gt, vfid, GUC_PF_NOTIFY_VF_PAUSE_DONE);
> + break;
> + case GUC_PF_TRIGGER_VF_FLR_START:
> + pf_handle_vf_event(gt, vfid, GUC_PF_NOTIFY_VF_FLR_DONE);
> + break;
> + case GUC_PF_TRIGGER_VF_RESUME:
> + case GUC_PF_TRIGGER_VF_STOP:
> + case GUC_PF_TRIGGER_VF_FLR_FINISH:
> + break;
> + default:
> + return -EPROTO;
> + }
> + return 0;
> +}
> +
> +static int send_vf_control_cmd_busy_wait(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + schedule_timeout_interruptible(HZ / 20);
> + return -EBUSY;
> +}
> +
> +static int send_vf_control_cmd_pass_but_reply_flr_only(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return cmd == GUC_PF_TRIGGER_VF_FLR_START ?
> + send_vf_control_cmd_pass_and_reply(gt, vfid, cmd) :
> + send_vf_control_cmd_pass_no_reply(gt, vfid, cmd);
> +}
> +
> +static int send_vf_control_cmd_busy_except_flr(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return cmd == GUC_PF_TRIGGER_VF_FLR_START || cmd == GUC_PF_TRIGGER_VF_FLR_FINISH ?
> + send_vf_control_cmd_pass_and_reply(gt, vfid, cmd) :
> + send_vf_control_cmd_busy_wait(gt, vfid, cmd);
> +}
> +
> +static int send_vf_control_cmd_busy_except_stop(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + return cmd == GUC_PF_TRIGGER_VF_STOP ?
> + send_vf_control_cmd_pass_and_reply(gt, vfid, cmd) :
> + send_vf_control_cmd_busy_wait(gt, vfid, cmd);
> +}
> +
> +static int BUSY_MAGIC = 3;
> +
> +static int send_vf_control_cmd_busy_no_reply(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + static int counter;
> +
> + return ++counter % BUSY_MAGIC ? -EBUSY : 0;
> +}
> +
> +static int send_vf_control_cmd_busy_and_reply(struct xe_gt *gt, unsigned int vfid, u32 cmd)
> +{
> + static int counter;
> +
> + return ++counter % BUSY_MAGIC ? -EBUSY :
> + send_vf_control_cmd_pass_and_reply(gt, vfid, cmd);
> +}
> +
> +static const enum xe_gt_sriov_control_bits ready[] = {
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_starting[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_SEND_START,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_starting_paused[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_SEND_START,
> + XE_GT_SRIOV_STATE_PAUSED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_starting_stopped[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_SEND_START,
> + XE_GT_SRIOV_STATE_STOPPED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_waiting[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_WAIT_GUC,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_guc_done[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_GUC_DONE,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_resetting[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_RESET_CONFIG,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_finishing[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_FLR_WIP,
> + XE_GT_SRIOV_STATE_FLR_SEND_FINISH,
> +};
> +
> +static const enum xe_gt_sriov_control_bits flr_failed[] = {
> + XE_GT_SRIOV_STATE_FLR_FAILED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits stopping[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_STOP_WIP,
> + XE_GT_SRIOV_STATE_STOP_SEND_STOP,
> +};
> +
> +static const enum xe_gt_sriov_control_bits stopping_paused[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_STOP_WIP,
> + XE_GT_SRIOV_STATE_STOP_SEND_STOP,
> + XE_GT_SRIOV_STATE_PAUSED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits stop_failed[] = {
> + XE_GT_SRIOV_STATE_STOP_FAILED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits stop_rejected[] = {
> + XE_GT_SRIOV_STATE_STOP_FAILED,
> + XE_GT_SRIOV_STATE_MISMATCH,
> +};
> +
> +static const enum xe_gt_sriov_control_bits stopped[] = {
> + XE_GT_SRIOV_STATE_STOPPED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits pausing[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_SEND_PAUSE,
> +};
> +
> +static const enum xe_gt_sriov_control_bits pausing_wait_guc[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_WAIT_GUC,
> +};
> +
> +static const enum xe_gt_sriov_control_bits pausing_guc_done[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_WIP,
> + XE_GT_SRIOV_STATE_PAUSE_GUC_DONE,
> +};
> +
> +static const enum xe_gt_sriov_control_bits pause_failed[] = {
> + XE_GT_SRIOV_STATE_PAUSE_FAILED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits pause_rejected[] = {
> + XE_GT_SRIOV_STATE_PAUSE_FAILED,
> + XE_GT_SRIOV_STATE_MISMATCH,
> +};
> +
> +static const enum xe_gt_sriov_control_bits paused[] = {
> + XE_GT_SRIOV_STATE_PAUSED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits resuming[] = {
> + XE_GT_SRIOV_STATE_WIP,
> + XE_GT_SRIOV_STATE_PAUSED,
> + XE_GT_SRIOV_STATE_RESUME_WIP,
> + XE_GT_SRIOV_STATE_RESUME_SEND_RESUME,
> +};
> +
> +static const enum xe_gt_sriov_control_bits resume_failed[] = {
> + XE_GT_SRIOV_STATE_PAUSED,
> + XE_GT_SRIOV_STATE_RESUME_FAILED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits resume_rejected[] = {
> + XE_GT_SRIOV_STATE_PAUSED,
> + XE_GT_SRIOV_STATE_RESUME_FAILED,
> + XE_GT_SRIOV_STATE_MISMATCH,
> +};
> +
> +static const enum xe_gt_sriov_control_bits resumed[] = {
> + XE_GT_SRIOV_STATE_RESUMED,
> +};
> +
> +static const enum xe_gt_sriov_control_bits mismatch[] = {
> + XE_GT_SRIOV_STATE_MISMATCH,
> +};
> +
> +struct state_param {
> + const char *name;
> + const enum xe_gt_sriov_control_bits *bits;
> + size_t num_bits;
> +};
> +
> +static void state_param_get_desc(struct state_param *p, char *desc)
> +{
> + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", p->name);
> +}
> +
> +#define MAKE_STATE_PARAM(X) { .name = #X, .bits = X, .num_bits = ARRAY_SIZE(X) }
> +
> +/*
> + * Due to the test case logic the all "must_pass" params include "_rejected" states
> + * since our "GuC" calls by default will not complain again about the INVALID_STATE
> + * thus our state machine is able to fully recover.
> + */
> +
> +static struct state_param flr_must_pass_from[] = {
> + MAKE_STATE_PARAM(ready),
> + MAKE_STATE_PARAM(flr_starting),
> + MAKE_STATE_PARAM(flr_starting_paused),
> + MAKE_STATE_PARAM(flr_starting_stopped),
> + MAKE_STATE_PARAM(flr_waiting),
> + MAKE_STATE_PARAM(flr_guc_done),
> + MAKE_STATE_PARAM(flr_resetting),
> + MAKE_STATE_PARAM(flr_finishing),
> + MAKE_STATE_PARAM(flr_failed),
> + MAKE_STATE_PARAM(stopping),
> + MAKE_STATE_PARAM(stop_failed),
> + MAKE_STATE_PARAM(stop_rejected),
> + MAKE_STATE_PARAM(stopped),
> + MAKE_STATE_PARAM(pausing),
> + MAKE_STATE_PARAM(pausing_wait_guc),
> + MAKE_STATE_PARAM(pausing_guc_done),
> + MAKE_STATE_PARAM(pause_failed),
> + MAKE_STATE_PARAM(pause_rejected),
> + MAKE_STATE_PARAM(paused),
> + MAKE_STATE_PARAM(resuming),
> + MAKE_STATE_PARAM(resume_failed),
> + MAKE_STATE_PARAM(resume_rejected),
> + MAKE_STATE_PARAM(resumed),
> + MAKE_STATE_PARAM(mismatch),
> +};
> +
> +static struct state_param stop_must_pass_from[] = {
> + MAKE_STATE_PARAM(ready),
> + MAKE_STATE_PARAM(stop_failed),
> + MAKE_STATE_PARAM(stop_rejected),
> + MAKE_STATE_PARAM(pausing),
> + MAKE_STATE_PARAM(pausing_wait_guc),
> + MAKE_STATE_PARAM(pausing_guc_done),
> + MAKE_STATE_PARAM(pause_failed),
> + MAKE_STATE_PARAM(pause_rejected),
> + MAKE_STATE_PARAM(paused),
> + MAKE_STATE_PARAM(resuming),
> + MAKE_STATE_PARAM(resume_failed),
> + MAKE_STATE_PARAM(resume_rejected),
> + MAKE_STATE_PARAM(resumed),
> + MAKE_STATE_PARAM(mismatch),
> + MAKE_STATE_PARAM(flr_failed),
> +};
> +
> +static struct state_param stop_must_cancel_from[] = {
> + MAKE_STATE_PARAM(flr_starting),
> + MAKE_STATE_PARAM(flr_starting_paused),
> + MAKE_STATE_PARAM(flr_waiting),
> + MAKE_STATE_PARAM(flr_guc_done),
> + MAKE_STATE_PARAM(flr_resetting),
> + MAKE_STATE_PARAM(flr_finishing),
> +};
> +
> +static struct state_param stop_must_fail_from[] = {
> + MAKE_STATE_PARAM(stopping),
> + MAKE_STATE_PARAM(stopping_paused),
> + MAKE_STATE_PARAM(stopped),
> + MAKE_STATE_PARAM(flr_starting_stopped),
> +};
> +
> +static struct state_param pause_must_pass_from[] = {
> + MAKE_STATE_PARAM(ready),
> + MAKE_STATE_PARAM(pause_failed),
> + MAKE_STATE_PARAM(pause_rejected),
> + MAKE_STATE_PARAM(resumed),
> + MAKE_STATE_PARAM(mismatch),
> + MAKE_STATE_PARAM(stop_failed),
> + MAKE_STATE_PARAM(stop_rejected),
> + MAKE_STATE_PARAM(flr_failed),
> +};
> +
> +static struct state_param pause_must_cancel_from[] = {
> + MAKE_STATE_PARAM(flr_starting),
> + MAKE_STATE_PARAM(flr_waiting),
> + MAKE_STATE_PARAM(flr_guc_done),
> + MAKE_STATE_PARAM(flr_resetting),
> + MAKE_STATE_PARAM(flr_finishing),
> + MAKE_STATE_PARAM(stopping),
> +};
> +
> +static struct state_param pause_must_fail_from[] = {
> + MAKE_STATE_PARAM(pausing),
> + MAKE_STATE_PARAM(pausing_wait_guc),
> + MAKE_STATE_PARAM(pausing_guc_done),
> + MAKE_STATE_PARAM(paused),
> + MAKE_STATE_PARAM(resuming),
> + MAKE_STATE_PARAM(resume_failed),
> + MAKE_STATE_PARAM(resume_rejected),
> + MAKE_STATE_PARAM(stopped),
> +};
> +
> +static struct state_param resume_must_pass_from[] = {
> + MAKE_STATE_PARAM(paused),
> + MAKE_STATE_PARAM(resume_failed),
> + MAKE_STATE_PARAM(resume_rejected),
> +};
> +
> +static struct state_param resume_must_cancel_from[] = {
> + MAKE_STATE_PARAM(flr_starting_paused),
> + MAKE_STATE_PARAM(stopping_paused),
> +};
> +
> +static struct state_param resume_must_fail_from[] = {
> + MAKE_STATE_PARAM(ready),
> + MAKE_STATE_PARAM(pausing),
> + MAKE_STATE_PARAM(pausing_wait_guc),
> + MAKE_STATE_PARAM(pausing_guc_done),
> + MAKE_STATE_PARAM(pause_failed),
> + MAKE_STATE_PARAM(pause_rejected),
> + MAKE_STATE_PARAM(resuming),
> + MAKE_STATE_PARAM(resumed),
> + MAKE_STATE_PARAM(stopping),
> + MAKE_STATE_PARAM(stop_failed),
> + MAKE_STATE_PARAM(stop_rejected),
> + MAKE_STATE_PARAM(stopped),
> + MAKE_STATE_PARAM(flr_starting),
> + MAKE_STATE_PARAM(flr_waiting),
> + MAKE_STATE_PARAM(flr_guc_done),
> + MAKE_STATE_PARAM(flr_resetting),
> + MAKE_STATE_PARAM(flr_finishing),
> + MAKE_STATE_PARAM(flr_failed),
> + MAKE_STATE_PARAM(mismatch),
> +};
> +
> +KUNIT_ARRAY_PARAM(flr_must_pass_from, flr_must_pass_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(stop_must_pass_from, stop_must_pass_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(stop_must_fail_from, stop_must_fail_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(stop_must_cancel_from, stop_must_cancel_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(pause_must_pass_from, pause_must_pass_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(pause_must_fail_from, pause_must_fail_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(pause_must_cancel_from, pause_must_cancel_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(resume_must_pass_from, resume_must_pass_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(resume_must_fail_from, resume_must_fail_from, state_param_get_desc);
> +KUNIT_ARRAY_PARAM(resume_must_cancel_from, resume_must_cancel_from, state_param_get_desc);
> +
> +static int mimic_pf_handle_vf_flr_done(struct xe_gt *gt, unsigned int vfid)
> +{
> + pf_handle_vf_flr_done(gt, vfid);
> + return 0;
> +}
> +
> +static int mimic_pf_handle_vf_pause_done(struct xe_gt *gt, unsigned int vfid)
> +{
> + pf_handle_vf_pause_done(gt, vfid);
> + return 0;
> +}
> +
> +static void prepare_state(struct kunit *test, unsigned int vfid,
> + const enum xe_gt_sriov_control_bits *bits, size_t num_bits)
> +{
> + struct xe_gt *gt = test->priv;
> + size_t n;
> +
> + for (n = 0; n < num_bits; n++) {
> + enum xe_gt_sriov_control_bits bit = bits[n];
> +
> + KUNIT_ASSERT_TRUE(test, pf_enter_vf_state(gt, vfid, bit));
> +
> + if (bit == XE_GT_SRIOV_STATE_WIP) {
> + pf_queue_vf(gt, vfid);
> + } else if (bit == XE_GT_SRIOV_STATE_FLR_WAIT_GUC) {
> + xe_kunit_helper_delayed_call(test, HZ / 100,
> + mimic_pf_handle_vf_flr_done, gt, vfid);
> + } else if (bit == XE_GT_SRIOV_STATE_PAUSE_WAIT_GUC) {
> + xe_kunit_helper_delayed_call(test, HZ / 100,
> + mimic_pf_handle_vf_pause_done, gt, vfid);
> + }
> + }
> +}
> +
> +static void prepare_state_from_param(struct kunit *test)
> +{
> + const struct state_param *p = test->param_value;
> +
> + prepare_state(test, VFUT1, p->bits, p->num_bits);
> +}
> +
> +static void expect_not_pausing(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WIP));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_SEND_PAUSE));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WAIT_GUC));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_GUC_DONE));
> +}
> +
> +static void expect_not_in_pause(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + expect_not_pausing(test);
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_FAILED));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> +}
> +
> +static void expect_not_resuming(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_WIP));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_SEND_RESUME));
> +}
> +
> +static void expect_not_in_resume(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + expect_not_resuming(test);
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_FAILED));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> +}
> +
> +static void expect_not_stopping(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_WIP));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_SEND_STOP));
> +}
> +
> +static void expect_not_in_stop(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + expect_not_stopping(test);
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_FAILED));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOPPED));
> +}
> +
> +static void expect_not_in_flr(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_SEND_START));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WAIT_GUC));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_GUC_DONE));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_SEND_FINISH));
> + KUNIT_EXPECT_TRUE(test,
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> +}
> +
> +static void expect_not_in_wip(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void expect_not_in_mismatch(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> +}
> +
> +static void try_flr_vf(struct kunit *test, bool mimic_busy, bool late_reply)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + mimic_busy ? late_reply ? send_vf_control_cmd_busy_no_reply :
> + send_vf_control_cmd_busy_and_reply :
> + late_reply ? send_vf_control_cmd_pass_no_reply :
> + send_vf_control_cmd_pass_and_reply);
> +
> + if (late_reply)
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + mimic_pf_handle_vf_flr_done, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> +
> + expect_not_in_flr(test);
> + expect_not_in_pause(test);
> + expect_not_in_resume(test);
> + expect_not_in_stop(test);
> + expect_not_in_mismatch(test);
> + expect_not_in_wip(test);
> +}
> +
> +static void flr_vf_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_flr_vf(test, false, false);
> +}
> +
> +static void flr_vf_needs_retry_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_flr_vf(test, true, false);
> +}
> +
> +static void flr_vf_needs_retry_late_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_flr_vf(test, true, true);
> +}
> +
> +static void flr_vf_fails_on_send(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_fail);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ETIMEDOUT);
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void flr_vf_fails_on_reset(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.vfs[VFUT1].config.sanitize,
> + sanitize_vf_resources_fail);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ETIMEDOUT);
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void flr_vf_rejected_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_reject);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ETIMEDOUT);
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void flr_vf_unconfirmed_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, err, -ETIMEDOUT);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> +}
> +
> +static void flr_vf_confirmed_early_continue_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, flr_starting, ARRAY_SIZE(flr_starting));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + pf_handle_vf_flr_done(gt, VFUT1);
> +
> + /*
> + * make sure SEND_START completes;
> + * successful reply from cmd_pass_no_reply should exit mismatch state
> + */
> + flush_work(>->sriov.pf.control.worker);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> +}
> +
> +static void flr_vf_confirmed_early_reject_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, flr_starting, ARRAY_SIZE(flr_starting));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_reject);
> +
> + pf_handle_vf_flr_done(gt, VFUT1);
> +
> + /*
> + * make sure SEND_START completes;
> + * error from send_vf_control_cmd_reject should keep mismatch state
> + */
> + flush_work(>->sriov.pf.control.worker);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void flr_vf_confirmed_twice_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, flr_guc_done, ARRAY_SIZE(flr_guc_done));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + pf_handle_vf_flr_done(gt, VFUT1);
> +
> + /* this is fully recoverable */
> + KUNIT_EXPECT_EQ(test, 0, pf_wait_vf_wip_done(gt, VFUT1, HZ));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> +}
> +
> +static void flr_vf_confirmed_too_late_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, flr_failed, ARRAY_SIZE(flr_failed));
> +
> + pf_handle_vf_flr_done(gt, VFUT1);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void flr_vf_unsolicited_confirmation_from_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> +
> + pf_handle_vf_flr_done(gt, VFUT1);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_FLR_FAILED));
> +}
> +
> +static void flr_vf_wrong_confirmation_from_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, flr_waiting, ARRAY_SIZE(flr_waiting));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + pf_handle_vf_pause_done(gt, VFUT1);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> +}
> +
> +static void flr_vf_canceled_by_restart(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_wait);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10, xe_gt_sriov_pf_control_restart, gt);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + expect_not_in_flr(test);
> +}
> +
> +static void try_stop_vf(struct kunit *test, bool mimic_busy)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + mimic_busy ? send_vf_control_cmd_busy_and_reply :
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOPPED));
> + expect_not_stopping(test);
> + expect_not_in_pause(test);
> + expect_not_in_resume(test);
> + expect_not_in_mismatch(test);
> +}
> +
> +static void stop_vf_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_stop_vf(test, false);
> +}
> +
> +static void stop_vf_needs_retry_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_stop_vf(test, true);
> +}
> +
> +static void stop_vf_refused_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, err == -EALREADY ||
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_FAILED));
> +}
> +
> +static void stop_vf_fails_on_send(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_fail);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ETIMEDOUT);
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_FAILED));
> + expect_not_stopping(test);
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOPPED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void stop_vf_rejected_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_reject);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ETIMEDOUT);
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + expect_not_stopping(test);
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOPPED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void stop_vf_canceled_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOP_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_STOPPED));
> +}
> +
> +static void stop_vf_canceled_by_restart(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_except_flr);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10, xe_gt_sriov_pf_control_restart, gt);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + expect_not_in_stop(test);
> +}
> +
> +static void stop_vf_canceled_by_flr(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_except_flr);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + xe_gt_sriov_pf_control_trigger_flr, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + expect_not_in_stop(test);
> +}
> +
> +static void try_pause_vf(struct kunit *test, bool mimic_busy)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + mimic_busy ? send_vf_control_cmd_busy_and_reply :
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + expect_not_pausing(test);
> + expect_not_in_mismatch(test);
> +}
> +
> +static void pause_vf_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_pause_vf(test, false);
> +}
> +
> +static void pause_vf_needs_retry_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_pause_vf(test, true);
> +}
> +
> +static void pause_vf_canceled_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + expect_not_in_pause(test);
> +}
> +
> +static void pause_vf_refused_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -ECANCELED);
> +
> + KUNIT_EXPECT_TRUE(test, err == -EALREADY ||
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_FAILED));
> +}
> +
> +static void pause_vf_rejected_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_reject);
> +
> + KUNIT_EXPECT_NE(test, 0, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void pause_vf_fails_on_send(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_fail);
> +
> + KUNIT_EXPECT_NE(test, 0, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_FAILED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_WIP));
> +}
> +
> +static void pause_vf_unconfirmed_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, err, -ETIMEDOUT);
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_WAIT_GUC));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSE_FAILED));
> +}
> +
> +static void pause_vf_canceled_by_restart(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10, xe_gt_sriov_pf_control_restart, gt);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + expect_not_in_pause(test);
> +}
> +
> +static void pause_vf_canceled_by_flr(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_but_reply_flr_only);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + xe_gt_sriov_pf_control_trigger_flr, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + expect_not_in_pause(test);
> +}
> +
> +static void pause_vf_canceled_by_stop(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_no_reply);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + xe_gt_sriov_pf_control_stop_vf, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + expect_not_in_pause(test);
> +}
> +
> +static void try_resume_vf(struct kunit *test, bool mimic_busy)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + mimic_busy ? send_vf_control_cmd_busy_and_reply :
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> + expect_not_resuming(test);
> + expect_not_in_pause(test);
> + expect_not_in_mismatch(test);
> + expect_not_in_wip(test);
> +}
> +
> +static void resume_vf_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_resume_vf(test, false);
> +}
> +
> +static void resume_vf_needs_retry_from(struct kunit *test)
> +{
> + prepare_state_from_param(test);
> + try_resume_vf(test, true);
> +}
> +
> +static void resume_vf_fails_on_send(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, paused, ARRAY_SIZE(paused));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_fail);
> +
> + KUNIT_EXPECT_NE(test, 0, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_FAILED));
> +
> + expect_not_resuming(test);
> + expect_not_in_mismatch(test);
> + expect_not_in_wip(test);
> +}
> +
> +static void resume_vf_rejected_by_guc(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, paused, ARRAY_SIZE(paused));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_reject);
> +
> + KUNIT_EXPECT_NE(test, 0, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_PAUSED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_MISMATCH));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_FAILED));
> +
> + expect_not_resuming(test);
> + expect_not_in_wip(test);
> +}
> +
> +static void resume_vf_canceled_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_FAILED));
> + expect_not_resuming(test);
> +}
> +
> +static void resume_vf_refused_from(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> + int err;
> +
> + prepare_state_from_param(test);
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_NE(test, 0, err = xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> + KUNIT_EXPECT_NE(test, err, -EIO);
> +
> + KUNIT_EXPECT_TRUE(test, err == -EALREADY ||
> + pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_WIP));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_FAILED));
> +}
> +
> +static void resume_vf_canceled_by_restart(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, paused, ARRAY_SIZE(paused));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_except_flr);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10, xe_gt_sriov_pf_control_restart, gt);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_WIP));
> +}
> +
> +static void resume_vf_canceled_by_flr(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, paused, ARRAY_SIZE(paused));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_except_flr);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + xe_gt_sriov_pf_control_trigger_flr, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_WIP));
> +}
> +
> +static void resume_vf_canceled_by_stop(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + prepare_state(test, VFUT1, paused, ARRAY_SIZE(paused));
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_busy_except_stop);
> +
> + xe_kunit_helper_delayed_call(test, HZ / 10,
> + xe_gt_sriov_pf_control_stop_vf, gt, VFUT1);
> +
> + KUNIT_EXPECT_EQ(test, -ECANCELED, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUMED));
> + KUNIT_EXPECT_TRUE(test, pf_expect_vf_not_state(gt, VFUT1, XE_GT_SRIOV_STATE_RESUME_WIP));
> +}
> +
> +static void basic_pause_and_resume_vf(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_ASSERT_EQ(test, 0, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_resume_vf(gt, VFUT1));
> +}
> +
> +static void basic_pause_and_stop_vf(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_ASSERT_EQ(test, 0, xe_gt_sriov_pf_control_pause_vf(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> +}
> +
> +static void basic_stop_and_flr_vf(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_stop_vf(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> +}
> +
> +static void basic_flr_and_flr_vf(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> +}
> +
> +static void basic_flr_vfs(struct kunit *test)
> +{
> + struct xe_gt *gt = test->priv;
> +
> + XE_TEST_ACTIVATE_STUB(test, gt->sriov.pf.control.send_vf_control_cmd,
> + send_vf_control_cmd_pass_and_reply);
> +
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT1));
> + KUNIT_EXPECT_EQ(test, 0, xe_gt_sriov_pf_control_trigger_flr(gt, VFUT2));
> +}
> +
> +static struct kunit_case pf_control_test_cases[] = {
> + KUNIT_CASE(basic_pause_and_resume_vf),
> + KUNIT_CASE(basic_pause_and_stop_vf),
> + KUNIT_CASE(basic_stop_and_flr_vf),
> + KUNIT_CASE(basic_flr_and_flr_vf),
> + KUNIT_CASE(basic_flr_vfs),
> +
> + KUNIT_CASE_PARAM(flr_vf_from, flr_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(flr_vf_needs_retry_from, flr_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(flr_vf_needs_retry_late_from, flr_must_pass_from_gen_params),
> + KUNIT_CASE(flr_vf_fails_on_send),
> + KUNIT_CASE(flr_vf_fails_on_reset),
> + KUNIT_CASE(flr_vf_rejected_by_guc),
> + KUNIT_CASE_SLOW(flr_vf_unconfirmed_by_guc),
> + KUNIT_CASE(flr_vf_confirmed_early_continue_by_guc),
> + KUNIT_CASE(flr_vf_confirmed_early_reject_by_guc),
> + KUNIT_CASE(flr_vf_confirmed_twice_by_guc),
> + KUNIT_CASE(flr_vf_confirmed_too_late_by_guc),
> + KUNIT_CASE(flr_vf_wrong_confirmation_from_guc),
> + KUNIT_CASE(flr_vf_unsolicited_confirmation_from_guc),
> + KUNIT_CASE(flr_vf_canceled_by_restart),
> +
> + KUNIT_CASE_PARAM(stop_vf_from, stop_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(stop_vf_needs_retry_from, stop_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(stop_vf_refused_from, stop_must_fail_from_gen_params),
> + KUNIT_CASE_PARAM(stop_vf_canceled_from, stop_must_cancel_from_gen_params),
> + KUNIT_CASE(stop_vf_fails_on_send),
> + KUNIT_CASE(stop_vf_rejected_by_guc),
> + KUNIT_CASE(stop_vf_canceled_by_flr),
> + KUNIT_CASE(stop_vf_canceled_by_restart),
> +
> + KUNIT_CASE_PARAM(pause_vf_from, pause_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(pause_vf_needs_retry_from, pause_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(pause_vf_refused_from, pause_must_fail_from_gen_params),
> + KUNIT_CASE_PARAM(pause_vf_canceled_from, pause_must_cancel_from_gen_params),
> + KUNIT_CASE(pause_vf_fails_on_send),
> + KUNIT_CASE(pause_vf_rejected_by_guc),
> + KUNIT_CASE_SLOW(pause_vf_unconfirmed_by_guc),
> + KUNIT_CASE(pause_vf_canceled_by_flr),
> + KUNIT_CASE(pause_vf_canceled_by_stop),
> + KUNIT_CASE(pause_vf_canceled_by_restart),
> +
> + KUNIT_CASE_PARAM(resume_vf_from, resume_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(resume_vf_needs_retry_from, resume_must_pass_from_gen_params),
> + KUNIT_CASE_PARAM(resume_vf_refused_from, resume_must_fail_from_gen_params),
> + KUNIT_CASE_PARAM(resume_vf_canceled_from, resume_must_cancel_from_gen_params),
> + KUNIT_CASE(resume_vf_fails_on_send),
> + KUNIT_CASE(resume_vf_rejected_by_guc),
> + KUNIT_CASE(resume_vf_canceled_by_flr),
> + KUNIT_CASE(resume_vf_canceled_by_stop),
> + KUNIT_CASE(resume_vf_canceled_by_restart),
> +
> + {}
> +};
> +
> +static struct kunit_suite pf_control_suite = {
> + .name = "pf_control",
> + .test_cases = pf_control_test_cases,
> + .init = pf_control_test_init,
> +};
> +
> +kunit_test_suite(pf_control_suite);
> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
> index e91c71d768ff..4863d79f72e0 100644
> --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
> @@ -4,6 +4,7 @@
> */
>
> #include <drm/drm_managed.h>
> +#include <kunit/static_stub.h>
>
> #include "abi/guc_actions_sriov_abi.h"
>
> @@ -196,6 +197,8 @@ static const char *control_bit_to_string(enum xe_gt_sriov_control_bits bit)
>
> static unsigned long pf_get_default_timeout(enum xe_gt_sriov_control_bits bit)
> {
> + KUNIT_STATIC_STUB_REDIRECT(pf_get_default_timeout, bit);
> +
> switch (bit) {
> case XE_GT_SRIOV_STATE_FLR_WAIT_GUC:
> case XE_GT_SRIOV_STATE_PAUSE_WAIT_GUC:
> @@ -1458,3 +1461,7 @@ void xe_gt_sriov_pf_control_restart(struct xe_gt *gt)
> for (n = 1; n <= totalvfs; n++)
> pf_enter_vf_ready(gt, n);
> }
> +
> +#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
> +#include "tests/xe_gt_sriov_pf_control_kunit.c"
> +#endif
The tests look fine. I tried to verify the states according to the available
drawings of the state machine and I did not find any incorrectness.
It seems to me that the tests could be expanded to include an additional
basic test: basic_pause_and_flr_vf
But still:
Reviewed-by: Piotr Piórkowski <piotr.piorkowski at intel.com>
> --
> 2.43.0
>
--
More information about the Intel-xe
mailing list