[PATCH 3/3] wifi: ath11k: add KUnit tests for crash recovery and TX status allocation

From: Yunseong Kim

Date: Mon Nov 02 2026 - 07:10:55 EST


Add hardware-independent KUnit tests covering the ath11k recovery flow,
TX status buffer allocation, error handling, and subsequent traffic
rejection.

The test suite exercises production driver code without hardware emulation
by stubbing firmware exchange and injecting deterministic allocation
failures. It verifies:
- ath11k_test_recovery_success: normal recovery flow through
ath11k_core_reconfigure_on_crash().
- ath11k_test_recovery_tx_status_alloc_fail: deterministic failure
injection in ath11k_dp_alloc(), verifying that recovery returns -ENOMEM,
sets ATH11K_FLAG_CRASH_FLUSH, and leaves HAL SRNG memory allocated.
- ath11k_test_recovery_subsequent_send_prevented: verifies that after a
recovery failure, subsequent attempts to transmit via ath11k_ce_send()
are rejected with -ESHUTDOWN without accessing hardware rings.
- ath11k_test_recovery_resource_cleanup_and_teardown: verifies that
resources (IDR, tx_status) are cleanly unwound and full driver teardown
succeeds without double-free.
- ath11k_test_dp_tx_status_kvmalloc: validates kvmalloc allocation and
kvfree teardown lifecycle.

Signed-off-by: Yunseong Kim <yunseong.kim@xxxxxxxx>
---
drivers/net/wireless/ath/ath11k/.kunitconfig | 14 ++
drivers/net/wireless/ath/ath11k/Kconfig | 11 +
drivers/net/wireless/ath/ath11k/Makefile | 1 +
drivers/net/wireless/ath/ath11k/core.c | 30 ++-
drivers/net/wireless/ath/ath11k/core.h | 17 ++
drivers/net/wireless/ath/ath11k/dp.c | 7 +
drivers/net/wireless/ath/ath11k/test.c | 330 +++++++++++++++++++++++++++
7 files changed, 409 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/.kunitconfig b/drivers/net/wireless/ath/ath11k/.kunitconfig
new file mode 100644
index 0000000000000..b13aaaecf04a4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/.kunitconfig
@@ -0,0 +1,14 @@
+CONFIG_KUNIT=y
+CONFIG_VIRTIO_UML=y
+CONFIG_UML_PCI_OVER_VIRTIO=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_CRYPTO=y
+CONFIG_ATH_COMMON=y
+CONFIG_QCOM_QMI_HELPERS=y
+CONFIG_QRTR=y
+CONFIG_ATH11K=y
+CONFIG_ATH11K_KUNIT_TEST=y
diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig
index 44b520d2e66ee..2b688f1093457 100644
--- a/drivers/net/wireless/ath/ath11k/Kconfig
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
@@ -71,3 +71,14 @@ config ATH11K_CFR
to enable, disable, and dump data.

Say Y to enable CFR data dump collection via debugfs.
+
+config ATH11K_KUNIT_TEST
+ bool "KUnit tests for ath11k" if !KUNIT_ALL_TESTS
+ depends on KUNIT=y && ATH11K=y
+ default KUNIT_ALL_TESTS
+ help
+ This builds KUnit tests for ath11k recovery and resource management.
+ It tests crash recovery flow, dynamic allocation failure handling,
+ resource cleanup ordering, and subsequent send protection.
+
+ If unsure, say N.
diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile
index b1435fcf3e1bf..e42a38a2d0269 100644
--- a/drivers/net/wireless/ath/ath11k/Makefile
+++ b/drivers/net/wireless/ath/ath11k/Makefile
@@ -29,6 +29,7 @@ ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
ath11k-$(CONFIG_PM) += wow.o
ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
ath11k-$(CONFIG_ATH11K_CFR) += cfr.o
+ath11k-$(CONFIG_ATH11K_KUNIT_TEST) += test.o

obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index b859b26f31114..27c08721c6a72 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -2245,6 +2245,11 @@ static int ath11k_core_start_firmware(struct ath11k_base *ab,
{
int ret;

+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ if (ab->test_ops.start_firmware)
+ return ab->test_ops.start_firmware(ab, mode);
+#endif
+
ath11k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v2,
&ab->qmi.ce_cfg.shadow_reg_v2_len);

@@ -2297,13 +2302,27 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);

mutex_lock(&ab->core_lock);
+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ if (ab->test_ops.core_start)
+ ret = ab->test_ops.core_start(ab);
+ else
+ ret = ath11k_core_start(ab);
+#else
ret = ath11k_core_start(ab);
+#endif
if (ret) {
ath11k_err(ab, "failed to start core: %d\n", ret);
goto err_dp_free;
}

+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ if (ab->test_ops.pdev_create)
+ ret = ab->test_ops.pdev_create(ab);
+ else
+ ret = ath11k_core_pdev_create(ab);
+#else
ret = ath11k_core_pdev_create(ab);
+#endif
if (ret) {
ath11k_err(ab, "failed to create pdev core: %d\n", ret);
goto err_core_stop;
@@ -2320,12 +2339,21 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
ath11k_dp_free(ab);
mutex_unlock(&ab->core_lock);
err_firmware_stop:
+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ if (ab->test_ops.stop_firmware) {
+ ab->test_ops.stop_firmware_called++;
+ ab->test_ops.stop_firmware(ab);
+ } else {
+ ath11k_qmi_firmware_stop(ab);
+ }
+#else
ath11k_qmi_firmware_stop(ab);
+#endif

return ret;
}

-static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
+VISIBLE_IF_KUNIT int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
{
int ret;

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a0d725923ef24..57895e4bafffe 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -18,6 +18,7 @@
#include <linux/firmware.h>
#include <linux/suspend.h>
#include <linux/of.h>
+#include <kunit/visibility.h>

#include "qmi.h"
#include "htc.h"
@@ -1092,6 +1093,18 @@ struct ath11k_base {
enum ath11k_pm_policy actual_pm_policy;
struct notifier_block pm_nb;

+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ struct {
+ int (*start_firmware)(struct ath11k_base *ab,
+ enum ath11k_firmware_mode mode);
+ void (*stop_firmware)(struct ath11k_base *ab);
+ int (*core_start)(struct ath11k_base *ab);
+ int (*pdev_create)(struct ath11k_base *ab);
+ bool fail_tx_status_alloc;
+ int stop_firmware_called;
+ } test_ops;
+#endif
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
@@ -1372,4 +1385,8 @@ static inline const char *ath11k_bus_str(enum ath11k_bus bus)

void ath11k_core_pm_notifier_unregister(struct ath11k_base *ab);

+#if IS_ENABLED(CONFIG_KUNIT)
+int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab);
+#endif
+
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 45602ec2dce63..d1918f5d5e1a6 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -1093,7 +1093,14 @@ int ath11k_dp_alloc(struct ath11k_base *ab)

dp->tx_ring[i].tx_status_head = 0;
dp->tx_ring[i].tx_status_tail = DP_TX_COMP_RING_SIZE - 1;
+#if IS_ENABLED(CONFIG_ATH11K_KUNIT_TEST)
+ if (ab->test_ops.fail_tx_status_alloc)
+ dp->tx_ring[i].tx_status = NULL;
+ else
+ dp->tx_ring[i].tx_status = kvmalloc(size, GFP_KERNEL);
+#else
dp->tx_ring[i].tx_status = kvmalloc(size, GFP_KERNEL);
+#endif
if (!dp->tx_ring[i].tx_status) {
ret = -ENOMEM;
goto fail_tx_status;
diff --git a/drivers/net/wireless/ath/ath11k/test.c b/drivers/net/wireless/ath/ath11k/test.c
new file mode 100644
index 0000000000000..cdf7bd4289946
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/test.c
@@ -0,0 +1,330 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * KUnit regression tests for ath11k crash recovery and resource ownership
+ *
+ * Exercises ath11k production crash recovery flow (ath11k_core_reconfigure_on_crash),
+ * verifying error recovery paths, deterministic TX status allocation failure,
+ * preservation of HAL SRNG lifecycle, and enforcement of -ESHUTDOWN on subsequent sends.
+ */
+
+#include <kunit/test.h>
+#include <kunit/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "core.h"
+#include "hal.h"
+#include "hal_desc.h"
+#include "ce.h"
+#include "dp.h"
+#include "dp_tx.h"
+#include "hif.h"
+
+struct ath11k_test_fixture {
+ struct device *dev;
+ struct ath11k_base *ab;
+};
+
+static void ath11k_test_dummy_timer(struct timer_list *t)
+{
+}
+
+static u32 ath11k_test_read32(struct ath11k_base *ab, u32 address)
+{
+ return 0;
+}
+
+static void ath11k_test_write32(struct ath11k_base *ab, u32 address, u32 data)
+{
+}
+
+static void ath11k_test_irq_enable(struct ath11k_base *ab)
+{
+}
+
+static void ath11k_test_irq_disable(struct ath11k_base *ab)
+{
+}
+
+static int ath11k_test_hif_start(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static void ath11k_test_hif_stop(struct ath11k_base *ab)
+{
+}
+
+static int ath11k_test_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
+ u8 *ul_pipe, u8 *dl_pipe)
+{
+ return 0;
+}
+
+static const struct ath11k_hif_ops ath11k_test_hif_ops = {
+ .read32 = ath11k_test_read32,
+ .write32 = ath11k_test_write32,
+ .irq_enable = ath11k_test_irq_enable,
+ .irq_disable = ath11k_test_irq_disable,
+ .start = ath11k_test_hif_start,
+ .stop = ath11k_test_hif_stop,
+ .map_service_to_pipe = ath11k_test_map_service_to_pipe,
+};
+
+static int ath11k_test_start_firmware(struct ath11k_base *ab,
+ enum ath11k_firmware_mode mode)
+{
+ return 0;
+}
+
+static void ath11k_test_stop_firmware(struct ath11k_base *ab)
+{
+}
+
+static int ath11k_test_core_start(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static int ath11k_test_pdev_create(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static int ath11k_test_init(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx;
+ struct ath11k_base *ab;
+ struct device *dev;
+ int ret;
+
+ fx = kunit_kzalloc(test, sizeof(*fx), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fx);
+
+ dev = kunit_device_register(test, "ath11k_kunit_dev");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+ dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ fx->dev = dev;
+
+ ab = ath11k_core_alloc(dev, 0, ATH11K_BUS_PCI);
+ KUNIT_ASSERT_NOT_NULL(test, ab);
+ fx->ab = ab;
+ test->priv = fx;
+
+ ab->hif.ops = &ath11k_test_hif_ops;
+
+ timer_setup(&ab->mon_reap_timer, ath11k_test_dummy_timer, 0);
+
+ ab->hw_rev = ATH11K_HW_WCN6855_HW21;
+ ret = ath11k_core_pre_init(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = ath11k_hal_srng_init(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = ath11k_ce_alloc_pipes(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = ath11k_ce_init_pipes(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = ath11k_dp_alloc(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ab->test_ops.start_firmware = ath11k_test_start_firmware;
+ ab->test_ops.stop_firmware = ath11k_test_stop_firmware;
+ ab->test_ops.core_start = ath11k_test_core_start;
+ ab->test_ops.pdev_create = ath11k_test_pdev_create;
+ ab->test_ops.fail_tx_status_alloc = false;
+ ab->test_ops.stop_firmware_called = 0;
+
+ return 0;
+}
+
+static void ath11k_test_exit(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab;
+
+ if (!fx || !fx->ab)
+ return;
+
+ ab = fx->ab;
+ ath11k_dp_free(ab);
+ ath11k_ce_free_pipes(ab);
+ ath11k_hal_srng_deinit(ab);
+ ath11k_fw_destroy(ab);
+ ath11k_core_free(ab);
+}
+
+/*
+ * Test 1: Successful recovery.
+ * Verifies that standard crash reconfiguration succeeds, clears recovery and
+ * crash-flush flags, allocates DP resources, and keeps HAL SRNG intact.
+ */
+static void ath11k_test_recovery_success(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab = fx->ab;
+ int ret;
+
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ KUNIT_EXPECT_FALSE(test, test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
+ KUNIT_EXPECT_FALSE(test, test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags));
+ KUNIT_EXPECT_NOT_NULL(test, ab->dp.tx_ring[0].tx_status);
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.rdp.vaddr);
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.srng_config);
+}
+
+/*
+ * Test 2: Failure at TX status allocation during recovery.
+ * Verifies that when TX status allocation fails during crash recovery:
+ * 1. Recovery returns -ENOMEM.
+ * 2. ATH11K_FLAG_CRASH_FLUSH is set to protect against subsequent traffic.
+ * 3. Firmware stop is invoked.
+ * 4. DP tx_status is NULL.
+ * 5. HAL SRNG memory and config are preserved (not freed prematurely).
+ */
+static void ath11k_test_recovery_tx_status_alloc_fail(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab = fx->ab;
+ int ret;
+
+ /* Run initial successful recovery to establish initialized state */
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_ASSERT_NOT_NULL(test, ab->dp.tx_ring[0].tx_status);
+
+ /* Trigger recovery with injected TX status allocation failure */
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ab->test_ops.fail_tx_status_alloc = true;
+ ab->test_ops.stop_firmware_called = 0;
+
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_EXPECT_EQ(test, ret, -ENOMEM);
+
+ /* CRASH_FLUSH must be set to protect the driver against entry calls */
+ KUNIT_EXPECT_TRUE(test, test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
+ KUNIT_EXPECT_GT(test, ab->test_ops.stop_firmware_called, 0);
+ KUNIT_EXPECT_NULL(test, ab->dp.tx_ring[0].tx_status);
+
+ /* HAL SRNG memory must NOT be deinited on recovery failure */
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.rdp.vaddr);
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.srng_config);
+}
+
+/*
+ * Test 3: Prevention of subsequent unsafe operations after recovery failure.
+ * Verifies that after TX status allocation fails during recovery, subsequent
+ * CE and DP send operations return -ESHUTDOWN rather than touching hardware
+ * or dereferencing freed/uninitialized memory.
+ */
+static void ath11k_test_recovery_subsequent_send_prevented(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab = fx->ab;
+ struct sk_buff *skb;
+ int ret;
+
+ /* Run recovery with allocation failure */
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ab->test_ops.fail_tx_status_alloc = true;
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_ASSERT_EQ(test, ret, -ENOMEM);
+ KUNIT_ASSERT_TRUE(test, test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
+
+ /* CE send on CE 3 (WMI control pipe) must be blocked with -ESHUTDOWN */
+ skb = dev_alloc_skb(64);
+ KUNIT_ASSERT_NOT_NULL(test, skb);
+ ret = ath11k_ce_send(ab, skb, 3, 0);
+ KUNIT_EXPECT_EQ(test, ret, -ESHUTDOWN);
+ dev_kfree_skb(skb);
+
+ /* DP TX REO command must also be blocked with -ESHUTDOWN */
+ ret = ath11k_dp_tx_send_reo_cmd(ab, NULL, 0, NULL, NULL);
+ KUNIT_EXPECT_EQ(test, ret, -ESHUTDOWN);
+}
+
+/*
+ * Test 4: Resource ownership and cleanup after recovery failure.
+ * Verifies that after recovery failure, a subsequent recovery attempt
+ * when memory is available succeeds, clears CRASH_FLUSH, and tears down
+ * cleanly without double-free or corruption.
+ */
+static void ath11k_test_recovery_resource_cleanup_and_teardown(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab = fx->ab;
+ int ret;
+
+ /* Step 1: Initial failure */
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ab->test_ops.fail_tx_status_alloc = true;
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_ASSERT_EQ(test, ret, -ENOMEM);
+ KUNIT_ASSERT_TRUE(test, test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
+
+ /* Step 2: Memory becomes available, retry recovery */
+ ab->test_ops.fail_tx_status_alloc = false;
+ set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+ ret = ath11k_core_reconfigure_on_crash(ab);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_FALSE(test, test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
+ KUNIT_EXPECT_FALSE(test, test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags));
+ KUNIT_EXPECT_NOT_NULL(test, ab->dp.tx_ring[0].tx_status);
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.rdp.vaddr);
+ KUNIT_EXPECT_NOT_NULL(test, ab->hal.srng_config);
+}
+
+/*
+ * Test 5: DP TX status allocation sizing and kvmalloc lifecycle.
+ * Verifies that TX status ring size is 1 MiB (order-8 contiguous allocation),
+ * that ath11k_dp_alloc allocates it, and ath11k_dp_free frees and NULLs it.
+ */
+static void ath11k_test_dp_tx_status_kvmalloc(struct kunit *test)
+{
+ struct ath11k_test_fixture *fx = test->priv;
+ struct ath11k_base *ab = fx->ab;
+ size_t size;
+ int ret;
+
+ size = DP_TX_COMP_RING_SIZE * sizeof(struct hal_wbm_release_ring);
+ KUNIT_EXPECT_EQ(test, size, (size_t)1048576);
+
+ /* DP was allocated in fixture init, verify tx_status is present */
+ KUNIT_EXPECT_NOT_NULL(test, ab->dp.tx_ring[0].tx_status);
+
+ /* Free and verify tx_status is NULLed */
+ ath11k_dp_free(ab);
+ KUNIT_EXPECT_NULL(test, ab->dp.tx_ring[0].tx_status);
+
+ /* Reallocate and verify kvmalloc successfully allocates it again */
+ ret = ath11k_dp_alloc(ab);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_EXPECT_NOT_NULL(test, ab->dp.tx_ring[0].tx_status);
+}
+
+static struct kunit_case ath11k_recovery_test_cases[] = {
+ KUNIT_CASE(ath11k_test_recovery_success),
+ KUNIT_CASE(ath11k_test_recovery_tx_status_alloc_fail),
+ KUNIT_CASE(ath11k_test_recovery_subsequent_send_prevented),
+ KUNIT_CASE(ath11k_test_recovery_resource_cleanup_and_teardown),
+ KUNIT_CASE(ath11k_test_dp_tx_status_kvmalloc),
+ {}
+};
+
+static struct kunit_suite ath11k_recovery_test_suite = {
+ .name = "ath11k-recovery",
+ .init = ath11k_test_init,
+ .exit = ath11k_test_exit,
+ .test_cases = ath11k_recovery_test_cases,
+};
+
+kunit_test_suite(ath11k_recovery_test_suite);

--
2.47.3