1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * KUnit tests for channel helper functions 4 * 5 * Copyright (C) 2026 Intel Corporation 6 */ 7 #include <kunit/static_stub.h> 8 #include "mld.h" 9 #include "link.h" 10 #include "iface.h" 11 #include "utils.h" 12 13 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 14 15 struct test_chan_load_case { 16 const char *desc; 17 u32 load; 18 enum iwl_mld_link_chan_load_level old_lvl; 19 enum iwl_mld_link_chan_load_level expected_lvl; 20 bool expected_scan_trig; 21 }; 22 23 static const struct test_chan_load_case test_chan_load_thresh_cases[] = { 24 /* Level-up transitions */ 25 { 26 .desc = "Transition NONE->NONE", 27 .load = 20, 28 .old_lvl = LINK_CHAN_LOAD_LVL_NONE, 29 .expected_lvl = LINK_CHAN_LOAD_LVL_NONE, 30 .expected_scan_trig = false, 31 }, 32 { 33 .desc = "Transition NONE->LVL1", 34 .load = 50, 35 .old_lvl = LINK_CHAN_LOAD_LVL_NONE, 36 .expected_lvl = LINK_CHAN_LOAD_LVL1, 37 .expected_scan_trig = true, 38 }, 39 { 40 .desc = "Transition LVL1->LVL2", 41 .load = 75, 42 .old_lvl = LINK_CHAN_LOAD_LVL1, 43 .expected_lvl = LINK_CHAN_LOAD_LVL2, 44 .expected_scan_trig = true, 45 }, 46 { 47 .desc = "Transition LVL2->LVL3", 48 .load = 90, 49 .old_lvl = LINK_CHAN_LOAD_LVL2, 50 .expected_lvl = LINK_CHAN_LOAD_LVL3, 51 .expected_scan_trig = true, 52 }, 53 54 /* Level-down transitions */ 55 { 56 .desc = "Transition LVL1->NONE", 57 .load = 30, 58 .old_lvl = LINK_CHAN_LOAD_LVL1, 59 .expected_lvl = LINK_CHAN_LOAD_LVL_NONE, 60 .expected_scan_trig = false, 61 }, 62 { 63 .desc = "Transition LVL2->LVL1", 64 .load = 60, 65 .old_lvl = LINK_CHAN_LOAD_LVL2, 66 .expected_lvl = LINK_CHAN_LOAD_LVL1, 67 .expected_scan_trig = false, 68 }, 69 { 70 .desc = "Transition LVL3->LVL2", 71 .load = 70, 72 .old_lvl = LINK_CHAN_LOAD_LVL3, 73 .expected_lvl = LINK_CHAN_LOAD_LVL2, 74 .expected_scan_trig = false, 75 }, 76 77 /* No change */ 78 { 79 .desc = "Transition LVL2->LVL2", 80 .load = 72, 81 .old_lvl = LINK_CHAN_LOAD_LVL2, 82 .expected_lvl = LINK_CHAN_LOAD_LVL2, 83 .expected_scan_trig = false, 84 }, 85 }; 86 87 KUNIT_ARRAY_PARAM_DESC(test_chan_load_thresh_cases, 88 test_chan_load_thresh_cases, desc); 89 90 static void test_chan_load_thresholds(struct kunit *test) 91 { 92 const struct test_chan_load_case *tc = test->param_value; 93 struct iwl_mld *mld = test->priv; 94 struct ieee80211_vif *vif; 95 struct iwl_mld_vif *mld_vif; 96 struct ieee80211_bss_conf *link_conf; 97 struct iwl_mld_link *mld_link; 98 struct iwl_mld_kunit_link assoc_link = { 99 .id = 0, 100 .chandef = &chandef_6ghz_160mhz, 101 }; 102 bool scan_trig; 103 u32 chan_load; 104 105 /* Setup associated non-MLO station */ 106 vif = iwlmld_kunit_setup_non_mlo_assoc(&assoc_link); 107 mld_vif = iwl_mld_vif_from_mac80211(vif); 108 109 link_conf = &vif->bss_conf; 110 mld_link = &mld_vif->deflink; 111 112 chan_load = tc->load; 113 mld_link->chan_load_lvl = tc->old_lvl; 114 115 /* Execute function under test */ 116 wiphy_lock(mld->wiphy); 117 scan_trig = iwl_mld_chan_load_requires_scan(mld, link_conf, chan_load); 118 wiphy_unlock(mld->wiphy); 119 120 /* Check return value */ 121 KUNIT_EXPECT_EQ(test, tc->expected_scan_trig, scan_trig); 122 123 /* Check updated channel-load level */ 124 KUNIT_EXPECT_EQ(test, tc->expected_lvl, mld_link->chan_load_lvl); 125 } 126 127 static struct kunit_case chan_load_thresh_test_cases[] = { 128 KUNIT_CASE_PARAM(test_chan_load_thresholds, 129 test_chan_load_thresh_cases_gen_params), 130 {} 131 }; 132 133 static struct kunit_suite chan_load_thresh_test_suite = { 134 .name = "iwl_mld_chan_load_threshold_tests", 135 .init = iwlmld_kunit_test_init, 136 .test_cases = chan_load_thresh_test_cases, 137 }; 138 139 kunit_test_suite(chan_load_thresh_test_suite); 140