1 // SPDX-License-Identifier: GPL-2.0-only
3 * KUnit tests for channel helper functions
5 * Copyright (C) 2024 Intel Corporation
7 #include <net/mac80211.h>
9 #include <kunit/test.h>
11 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
13 static struct wiphy wiphy
= {
14 .mtx
= __MUTEX_INITIALIZER(wiphy
.mtx
),
17 static struct ieee80211_hw hw
= {
21 static struct ieee80211_channel chan_5ghz
= {
22 .band
= NL80211_BAND_5GHZ
,
25 static struct ieee80211_channel chan_6ghz
= {
26 .band
= NL80211_BAND_6GHZ
,
29 static struct ieee80211_channel chan_2ghz
= {
30 .band
= NL80211_BAND_2GHZ
,
33 static struct cfg80211_chan_def chandef_a
= {};
35 static struct cfg80211_chan_def chandef_b
= {};
37 static struct iwl_mvm_phy_ctxt ctx
= {};
39 static struct iwl_mvm_vif_link_info mvm_link
= {
44 static struct cfg80211_bss bss
= {};
46 static struct ieee80211_bss_conf link_conf
= {.bss
= &bss
};
48 static const struct iwl_fw_cmd_version entry
= {
49 .group
= LEGACY_GROUP
,
50 .cmd
= BT_PROFILE_NOTIFICATION
,
54 static struct iwl_fw fw
= {
57 .cmd_versions
= &entry
,
61 static struct iwl_mvm mvm
= {
66 static const struct link_grading_case
{
68 const struct cfg80211_chan_def chandef
;
73 } link_grading_cases
[] = {
75 .desc
= "UHB, RSSI below range, no factors",
78 .width
= NL80211_CHAN_WIDTH_20
,
84 .desc
= "LB, RSSI in range, no factors",
87 .width
= NL80211_CHAN_WIDTH_20
,
93 .desc
= "HB, RSSI above range, no factors",
96 .width
= NL80211_CHAN_WIDTH_20
,
102 .desc
= "HB, BSS Load IE (20 percent), inactive link, no puncturing factor",
105 .width
= NL80211_CHAN_WIDTH_20
,
112 .desc
= "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor",
115 .width
= NL80211_CHAN_WIDTH_20
,
119 .chan_load_by_us
= 10,
123 .desc
= "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor",
126 .width
= NL80211_CHAN_WIDTH_20
,
130 .chan_load_by_us
= 50,
133 { .desc
= "HB, 80 MHz, no channel load factor, punctured percentage 0",
136 .width
= NL80211_CHAN_WIDTH_80
,
142 { .desc
= "HB, 160 MHz, no channel load factor, punctured percentage 25",
145 .width
= NL80211_CHAN_WIDTH_160
,
151 { .desc
= "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)",
154 .width
= NL80211_CHAN_WIDTH_320
,
160 { .desc
= "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25",
163 .width
= NL80211_CHAN_WIDTH_160
,
167 .chan_load_by_us
= 10,
173 KUNIT_ARRAY_PARAM_DESC(link_grading
, link_grading_cases
, desc
)
175 static void setup_link_conf(struct kunit
*test
)
177 const struct link_grading_case
*params
= test
->param_value
;
178 size_t vif_size
= sizeof(struct ieee80211_vif
) +
179 sizeof(struct iwl_mvm_vif
);
180 struct ieee80211_vif
*vif
= kunit_kzalloc(test
, vif_size
, GFP_KERNEL
);
181 struct ieee80211_bss_load_elem
*bss_load
;
182 struct element
*element
;
183 size_t ies_size
= sizeof(struct cfg80211_bss_ies
) + sizeof(*bss_load
) + sizeof(element
);
184 struct cfg80211_bss_ies
*ies
;
185 struct iwl_mvm_vif
*mvmvif
;
187 KUNIT_ASSERT_NOT_NULL(test
, vif
);
189 mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
190 if (params
->chan_load_by_us
> 0) {
191 ctx
.channel_load_by_us
= params
->chan_load_by_us
;
192 mvmvif
->link
[0] = &mvm_link
;
196 link_conf
.chanreq
.oper
= params
->chandef
;
197 bss
.signal
= DBM_TO_MBM(params
->signal
);
199 ies
= kunit_kzalloc(test
, ies_size
, GFP_KERNEL
);
200 KUNIT_ASSERT_NOT_NULL(test
, ies
);
201 ies
->len
= sizeof(*bss_load
) + sizeof(struct element
);
203 element
= (void *)ies
->data
;
204 element
->datalen
= sizeof(*bss_load
);
207 bss_load
= (void *)element
->data
;
208 bss_load
->channel_util
= params
->channel_util
;
210 rcu_assign_pointer(bss
.ies
, ies
);
211 rcu_assign_pointer(bss
.beacon_ies
, ies
);
214 static void test_link_grading(struct kunit
*test
)
216 const struct link_grading_case
*params
= test
->param_value
;
219 setup_link_conf(test
);
222 ret
= iwl_mvm_get_link_grade(&link_conf
);
225 KUNIT_EXPECT_EQ(test
, ret
, params
->grade
);
227 kunit_kfree(test
, link_conf
.vif
);
228 RCU_INIT_POINTER(bss
.ies
, NULL
);
231 static struct kunit_case link_grading_test_cases
[] = {
232 KUNIT_CASE_PARAM(test_link_grading
, link_grading_gen_params
),
236 static struct kunit_suite link_grading
= {
237 .name
= "iwlmvm-link-grading",
238 .test_cases
= link_grading_test_cases
,
241 kunit_test_suite(link_grading
);
243 static const struct valid_link_pair_case
{
246 struct ieee80211_channel
*chan_a
;
247 struct ieee80211_channel
*chan_b
;
248 enum nl80211_chan_width cw_a
;
249 enum nl80211_chan_width cw_b
;
254 } valid_link_pair_cases
[] = {
256 .desc
= "HB + UHB, valid.",
257 .chan_a
= &chan_6ghz
,
258 .chan_b
= &chan_5ghz
,
262 .desc
= "LB + HB, no BT.",
263 .chan_a
= &chan_2ghz
,
264 .chan_b
= &chan_5ghz
,
268 .desc
= "LB + HB, with BT.",
270 .chan_a
= &chan_2ghz
,
271 .chan_b
= &chan_5ghz
,
276 .chan_a
= &chan_2ghz
,
277 .chan_b
= &chan_2ghz
,
281 .desc
= "RSSI: LB, 20 MHz, low",
282 .chan_a
= &chan_2ghz
,
283 .cw_a
= NL80211_CHAN_WIDTH_20
,
285 .chan_b
= &chan_5ghz
,
289 .desc
= "RSSI: UHB, 20 MHz, high",
290 .chan_a
= &chan_6ghz
,
291 .cw_a
= NL80211_CHAN_WIDTH_20
,
293 .chan_b
= &chan_5ghz
,
294 .cw_b
= NL80211_CHAN_WIDTH_20
,
298 .desc
= "RSSI: UHB, 40 MHz, low",
299 .chan_a
= &chan_6ghz
,
300 .cw_a
= NL80211_CHAN_WIDTH_40
,
302 .chan_b
= &chan_5ghz
,
303 .cw_b
= NL80211_CHAN_WIDTH_40
,
307 .desc
= "RSSI: UHB, 40 MHz, high",
308 .chan_a
= &chan_6ghz
,
309 .cw_a
= NL80211_CHAN_WIDTH_40
,
311 .chan_b
= &chan_5ghz
,
312 .cw_b
= NL80211_CHAN_WIDTH_40
,
316 .desc
= "RSSI: UHB, 80 MHz, low",
317 .chan_a
= &chan_6ghz
,
318 .cw_a
= NL80211_CHAN_WIDTH_80
,
320 .chan_b
= &chan_5ghz
,
321 .cw_b
= NL80211_CHAN_WIDTH_80
,
325 .desc
= "RSSI: UHB, 80 MHz, high",
326 .chan_a
= &chan_6ghz
,
327 .cw_a
= NL80211_CHAN_WIDTH_80
,
329 .chan_b
= &chan_5ghz
,
330 .cw_b
= NL80211_CHAN_WIDTH_80
,
334 .desc
= "RSSI: UHB, 160 MHz, low",
335 .chan_a
= &chan_6ghz
,
336 .cw_a
= NL80211_CHAN_WIDTH_160
,
338 .chan_b
= &chan_5ghz
,
339 .cw_b
= NL80211_CHAN_WIDTH_160
,
343 .desc
= "RSSI: HB, 160 MHz, high",
344 .chan_a
= &chan_6ghz
,
345 .cw_a
= NL80211_CHAN_WIDTH_160
,
347 .chan_b
= &chan_5ghz
,
348 .cw_b
= NL80211_CHAN_WIDTH_160
,
352 .desc
= "CSA active",
353 .chan_a
= &chan_6ghz
,
354 .cw_a
= NL80211_CHAN_WIDTH_160
,
356 .chan_b
= &chan_5ghz
,
357 .cw_b
= NL80211_CHAN_WIDTH_160
,
359 /* same as previous entry with valid=true except for CSA */
364 KUNIT_ARRAY_PARAM_DESC(valid_link_pair
, valid_link_pair_cases
, desc
)
366 static void test_valid_link_pair(struct kunit
*test
)
368 const struct valid_link_pair_case
*params
= test
->param_value
;
369 size_t vif_size
= sizeof(struct ieee80211_vif
) +
370 sizeof(struct iwl_mvm_vif
);
371 struct ieee80211_vif
*vif
= kunit_kzalloc(test
, vif_size
, GFP_KERNEL
);
372 struct iwl_trans
*trans
= kunit_kzalloc(test
, sizeof(struct iwl_trans
),
374 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
375 struct iwl_mvm_link_sel_data link_a
= {
376 .chandef
= &chandef_a
,
378 .signal
= params
->sig_a
,
380 struct iwl_mvm_link_sel_data link_b
= {
381 .chandef
= &chandef_b
,
383 .signal
= params
->sig_b
,
385 struct ieee80211_bss_conf
*conf
;
388 KUNIT_ASSERT_NOT_NULL(test
, vif
);
389 KUNIT_ASSERT_NOT_NULL(test
, trans
);
391 chandef_a
.chan
= params
->chan_a
;
392 chandef_b
.chan
= params
->chan_b
;
394 chandef_a
.width
= params
->cw_a
?: NL80211_CHAN_WIDTH_20
;
395 chandef_b
.width
= params
->cw_b
?: NL80211_CHAN_WIDTH_20
;
399 mvm
.last_bt_notif
.wifi_loss_low_rssi
= params
->bt
;
402 conf
= kunit_kzalloc(test
, sizeof(*vif
->link_conf
[0]), GFP_KERNEL
);
403 KUNIT_ASSERT_NOT_NULL(test
, conf
);
404 conf
->chanreq
.oper
= chandef_a
;
405 conf
->csa_active
= params
->csa_a
;
406 vif
->link_conf
[link_a
.link_id
] = (void __rcu
*)conf
;
408 conf
= kunit_kzalloc(test
, sizeof(*vif
->link_conf
[0]), GFP_KERNEL
);
409 KUNIT_ASSERT_NOT_NULL(test
, conf
);
410 conf
->chanreq
.oper
= chandef_b
;
411 vif
->link_conf
[link_b
.link_id
] = (void __rcu
*)conf
;
414 result
= iwl_mvm_mld_valid_link_pair(vif
, &link_a
, &link_b
);
415 wiphy_unlock(&wiphy
);
417 KUNIT_EXPECT_EQ(test
, result
, params
->valid
);
419 kunit_kfree(test
, vif
);
420 kunit_kfree(test
, trans
);
423 static struct kunit_case valid_link_pair_test_cases
[] = {
424 KUNIT_CASE_PARAM(test_valid_link_pair
, valid_link_pair_gen_params
),
428 static struct kunit_suite valid_link_pair
= {
429 .name
= "iwlmvm-valid-link-pair",
430 .test_cases
= valid_link_pair_test_cases
,
433 kunit_test_suite(valid_link_pair
);