1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * KUnit tests for channel helper functions 4 * 5 * Copyright (C) 2024 Intel Corporation 6 */ 7 #include <net/mac80211.h> 8 #include "../mvm.h" 9 #include <kunit/test.h> 10 11 MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 12 13 static struct ieee80211_channel chan_5ghz = { 14 .band = NL80211_BAND_5GHZ, 15 }; 16 17 static struct ieee80211_channel chan_6ghz = { 18 .band = NL80211_BAND_6GHZ, 19 }; 20 21 static struct ieee80211_channel chan_2ghz = { 22 .band = NL80211_BAND_2GHZ, 23 }; 24 25 static struct cfg80211_chan_def chandef_a = {}; 26 27 static struct cfg80211_chan_def chandef_b = {}; 28 29 static struct iwl_mvm_phy_ctxt ctx = {}; 30 31 static struct iwl_mvm_vif_link_info mvm_link = { 32 .phy_ctxt = &ctx, 33 .active = true 34 }; 35 36 static struct cfg80211_bss bss = {}; 37 38 static struct ieee80211_bss_conf link_conf = {.bss = &bss}; 39 40 static struct iwl_mvm mvm = {}; 41 42 static const struct link_grading_case { 43 const char *desc; 44 const struct cfg80211_chan_def chandef; 45 s32 signal; 46 s16 channel_util; 47 int chan_load_by_us; 48 unsigned int grade; 49 } link_grading_cases[] = { 50 { 51 .desc = "UHB, RSSI below range, no factors", 52 .chandef = { 53 .chan = &chan_6ghz, 54 .width = NL80211_CHAN_WIDTH_20, 55 }, 56 .signal = -100, 57 .grade = 177, 58 }, 59 { 60 .desc = "LB, RSSI in range, no factors", 61 .chandef = { 62 .chan = &chan_2ghz, 63 .width = NL80211_CHAN_WIDTH_20, 64 }, 65 .signal = -84, 66 .grade = 344, 67 }, 68 { 69 .desc = "HB, RSSI above range, no factors", 70 .chandef = { 71 .chan = &chan_5ghz, 72 .width = NL80211_CHAN_WIDTH_20, 73 }, 74 .signal = -50, 75 .grade = 3442, 76 }, 77 { 78 .desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor", 79 .chandef = { 80 .chan = &chan_5ghz, 81 .width = NL80211_CHAN_WIDTH_20, 82 }, 83 .signal = -66, 84 .channel_util = 51, 85 .grade = 1836, 86 }, 87 { 88 .desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor", 89 .chandef = { 90 .chan = &chan_2ghz, 91 .width = NL80211_CHAN_WIDTH_20, 92 }, 93 .signal = -61, 94 .channel_util = 51, 95 .chan_load_by_us = 10, 96 .grade = 2061, 97 }, 98 { 99 .desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor", 100 .chandef = { 101 .chan = &chan_6ghz, 102 .width = NL80211_CHAN_WIDTH_20, 103 }, 104 .signal = -66, 105 .channel_util = 102, 106 .chan_load_by_us = 50, 107 .grade = 1552, 108 }, 109 { .desc = "HB, 80 MHz, no channel load factor, punctured percentage 0", 110 .chandef = { 111 .chan = &chan_5ghz, 112 .width = NL80211_CHAN_WIDTH_80, 113 .punctured = 0x0000 114 }, 115 .signal = -72, 116 .grade = 1750, 117 }, 118 { .desc = "HB, 160 MHz, no channel load factor, punctured percentage 25", 119 .chandef = { 120 .chan = &chan_5ghz, 121 .width = NL80211_CHAN_WIDTH_160, 122 .punctured = 0x3 123 }, 124 .signal = -72, 125 .grade = 1312, 126 }, 127 { .desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)", 128 .chandef = { 129 .chan = &chan_6ghz, 130 .width = NL80211_CHAN_WIDTH_320, 131 .punctured = 0x3 132 }, 133 .signal = -72, 134 .grade = 1806, 135 }, 136 { .desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25", 137 .chandef = { 138 .chan = &chan_5ghz, 139 .width = NL80211_CHAN_WIDTH_160, 140 .punctured = 0x3 141 }, 142 .channel_util = 51, 143 .chan_load_by_us = 10, 144 .signal = -72, 145 .grade = 1179, 146 }, 147 }; 148 149 KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc) 150 151 static void setup_link_conf(struct kunit *test) 152 { 153 const struct link_grading_case *params = test->param_value; 154 size_t vif_size = sizeof(struct ieee80211_vif) + 155 sizeof(struct iwl_mvm_vif); 156 struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 157 struct ieee80211_bss_load_elem *bss_load; 158 struct element *element; 159 size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element); 160 struct cfg80211_bss_ies *ies; 161 struct iwl_mvm_vif *mvmvif; 162 163 KUNIT_ASSERT_NOT_NULL(test, vif); 164 165 mvmvif = iwl_mvm_vif_from_mac80211(vif); 166 if (params->chan_load_by_us > 0) { 167 ctx.channel_load_by_us = params->chan_load_by_us; 168 mvmvif->link[0] = &mvm_link; 169 } 170 171 link_conf.vif = vif; 172 link_conf.chanreq.oper = params->chandef; 173 bss.signal = DBM_TO_MBM(params->signal); 174 175 ies = kunit_kzalloc(test, ies_size, GFP_KERNEL); 176 KUNIT_ASSERT_NOT_NULL(test, ies); 177 ies->len = sizeof(*bss_load) + sizeof(struct element); 178 179 element = (void *)ies->data; 180 element->datalen = sizeof(*bss_load); 181 element->id = 11; 182 183 bss_load = (void *)element->data; 184 bss_load->channel_util = params->channel_util; 185 186 rcu_assign_pointer(bss.ies, ies); 187 } 188 189 static void test_link_grading(struct kunit *test) 190 { 191 const struct link_grading_case *params = test->param_value; 192 unsigned int ret; 193 194 setup_link_conf(test); 195 196 rcu_read_lock(); 197 ret = iwl_mvm_get_link_grade(&link_conf); 198 rcu_read_unlock(); 199 200 KUNIT_EXPECT_EQ(test, ret, params->grade); 201 202 kunit_kfree(test, link_conf.vif); 203 RCU_INIT_POINTER(bss.ies, NULL); 204 } 205 206 static struct kunit_case link_grading_test_cases[] = { 207 KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params), 208 {} 209 }; 210 211 static struct kunit_suite link_grading = { 212 .name = "iwlmvm-link-grading", 213 .test_cases = link_grading_test_cases, 214 }; 215 216 kunit_test_suite(link_grading); 217 218 static const struct valid_link_pair_case { 219 const char *desc; 220 u32 esr_disable_reason; 221 struct ieee80211_channel *chan_a; 222 struct ieee80211_channel *chan_b; 223 enum nl80211_chan_width cw_a; 224 enum nl80211_chan_width cw_b; 225 s32 sig_a; 226 s32 sig_b; 227 bool valid; 228 } valid_link_pair_cases[] = { 229 { 230 .desc = "HB + UHB, valid.", 231 .chan_a = &chan_5ghz, 232 .chan_b = &chan_6ghz, 233 .valid = true, 234 }, 235 { 236 .desc = "LB + HB, no BT.", 237 .chan_a = &chan_2ghz, 238 .chan_b = &chan_5ghz, 239 .valid = true, 240 }, 241 { 242 .desc = "LB + HB, with BT.", 243 .esr_disable_reason = 0x1, 244 .chan_a = &chan_2ghz, 245 .chan_b = &chan_5ghz, 246 .valid = false, 247 }, 248 { 249 .desc = "Same band", 250 .chan_a = &chan_2ghz, 251 .chan_b = &chan_2ghz, 252 .valid = false, 253 }, 254 { 255 .desc = "RSSI: LB, 20 MHz, low", 256 .chan_a = &chan_2ghz, 257 .cw_a = NL80211_CHAN_WIDTH_20, 258 .sig_a = -68, 259 .chan_b = &chan_5ghz, 260 .valid = false, 261 }, 262 { 263 .desc = "RSSI: LB, 20 MHz, high", 264 .chan_a = &chan_2ghz, 265 .cw_a = NL80211_CHAN_WIDTH_20, 266 .sig_a = -66, 267 .chan_b = &chan_5ghz, 268 .valid = true, 269 }, 270 { 271 .desc = "RSSI: LB, 40 MHz, low", 272 .chan_a = &chan_2ghz, 273 .cw_a = NL80211_CHAN_WIDTH_40, 274 .sig_a = -65, 275 .chan_b = &chan_5ghz, 276 .valid = false, 277 }, 278 { 279 .desc = "RSSI: LB, 40 MHz, high", 280 .chan_a = &chan_2ghz, 281 .cw_a = NL80211_CHAN_WIDTH_40, 282 .sig_a = -63, 283 .chan_b = &chan_5ghz, 284 .valid = true, 285 }, 286 { 287 .desc = "RSSI: HB, 80 MHz, low", 288 .chan_a = &chan_5ghz, 289 .cw_a = NL80211_CHAN_WIDTH_80, 290 .sig_a = -62, 291 .chan_b = &chan_2ghz, 292 .valid = false, 293 }, 294 { 295 .desc = "RSSI: HB, 80 MHz, high", 296 .chan_a = &chan_5ghz, 297 .cw_a = NL80211_CHAN_WIDTH_80, 298 .sig_a = -60, 299 .chan_b = &chan_2ghz, 300 .valid = true, 301 }, 302 { 303 .desc = "RSSI: HB, 160 MHz, low", 304 .chan_a = &chan_5ghz, 305 .cw_a = NL80211_CHAN_WIDTH_160, 306 .sig_a = -59, 307 .chan_b = &chan_2ghz, 308 .valid = false, 309 }, 310 { 311 .desc = "RSSI: HB, 160 MHz, high", 312 .chan_a = &chan_5ghz, 313 .cw_a = NL80211_CHAN_WIDTH_160, 314 .sig_a = -5, 315 .chan_b = &chan_2ghz, 316 .valid = true, 317 }, 318 { 319 .desc = "RSSI: UHB, 320 MHz, low", 320 .chan_a = &chan_6ghz, 321 .cw_a = NL80211_CHAN_WIDTH_320, 322 .sig_a = -68, 323 .chan_b = &chan_6ghz, 324 .valid = false, 325 }, 326 { 327 .desc = "RSSI: UHB, 320 MHz, high", 328 .chan_a = &chan_6ghz, 329 .cw_a = NL80211_CHAN_WIDTH_320, 330 .sig_a = -66, 331 .chan_b = &chan_5ghz, 332 .valid = true, 333 }, 334 }; 335 336 KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc) 337 338 static void test_valid_link_pair(struct kunit *test) 339 { 340 const struct valid_link_pair_case *params = test->param_value; 341 size_t vif_size = sizeof(struct ieee80211_vif) + 342 sizeof(struct iwl_mvm_vif); 343 struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 344 struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans), 345 GFP_KERNEL); 346 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 347 struct iwl_mvm_link_sel_data link_a = { 348 .chandef = &chandef_a, 349 .link_id = 1, 350 .signal = params->sig_a, 351 }; 352 struct iwl_mvm_link_sel_data link_b = { 353 .chandef = &chandef_b, 354 .link_id = 5, 355 .signal = params->sig_b, 356 }; 357 bool result; 358 359 KUNIT_ASSERT_NOT_NULL(test, vif); 360 KUNIT_ASSERT_NOT_NULL(test, trans); 361 362 chandef_a.chan = params->chan_a; 363 chandef_b.chan = params->chan_b; 364 365 chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20; 366 chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20; 367 368 #ifdef CONFIG_IWLWIFI_SUPPORT_DEBUG_OVERRIDES 369 trans->dbg_cfg = default_dbg_config; 370 #endif 371 mvm.trans = trans; 372 373 mvmvif->esr_disable_reason = params->esr_disable_reason; 374 mvmvif->mvm = &mvm; 375 376 result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b); 377 378 KUNIT_EXPECT_EQ(test, result, params->valid); 379 380 kunit_kfree(test, vif); 381 kunit_kfree(test, trans); 382 } 383 384 static struct kunit_case valid_link_pair_test_cases[] = { 385 KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params), 386 {}, 387 }; 388 389 static struct kunit_suite valid_link_pair = { 390 .name = "iwlmvm-valid-link-pair", 391 .test_cases = valid_link_pair_test_cases, 392 }; 393 394 kunit_test_suite(valid_link_pair); 395