xref: /linux/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c (revision 1260ed77798502de9c98020040d2995008de10cc)
12887af4dSMiri Korenblit // SPDX-License-Identifier: GPL-2.0-only
22887af4dSMiri Korenblit /*
32887af4dSMiri Korenblit  * KUnit tests for channel helper functions
42887af4dSMiri Korenblit  *
52887af4dSMiri Korenblit  * Copyright (C) 2024 Intel Corporation
62887af4dSMiri Korenblit  */
72887af4dSMiri Korenblit #include <net/mac80211.h>
82887af4dSMiri Korenblit #include "../mvm.h"
92887af4dSMiri Korenblit #include <kunit/test.h>
102887af4dSMiri Korenblit 
11cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
122887af4dSMiri Korenblit 
132f876f91SJohannes Berg static struct wiphy wiphy = {
142f876f91SJohannes Berg 	.mtx = __MUTEX_INITIALIZER(wiphy.mtx),
152f876f91SJohannes Berg };
162f876f91SJohannes Berg 
172f876f91SJohannes Berg static struct ieee80211_hw hw = {
182f876f91SJohannes Berg 	.wiphy = &wiphy,
192f876f91SJohannes Berg };
202f876f91SJohannes Berg 
212887af4dSMiri Korenblit static struct ieee80211_channel chan_5ghz = {
222887af4dSMiri Korenblit 	.band = NL80211_BAND_5GHZ,
232887af4dSMiri Korenblit };
242887af4dSMiri Korenblit 
252887af4dSMiri Korenblit static struct ieee80211_channel chan_6ghz = {
262887af4dSMiri Korenblit 	.band = NL80211_BAND_6GHZ,
272887af4dSMiri Korenblit };
282887af4dSMiri Korenblit 
292887af4dSMiri Korenblit static struct ieee80211_channel chan_2ghz = {
302887af4dSMiri Korenblit 	.band = NL80211_BAND_2GHZ,
312887af4dSMiri Korenblit };
322887af4dSMiri Korenblit 
3330ce0390SMiri Korenblit static struct cfg80211_chan_def chandef_a = {};
3430ce0390SMiri Korenblit 
3530ce0390SMiri Korenblit static struct cfg80211_chan_def chandef_b = {};
3630ce0390SMiri Korenblit 
372887af4dSMiri Korenblit static struct iwl_mvm_phy_ctxt ctx = {};
382887af4dSMiri Korenblit 
392887af4dSMiri Korenblit static struct iwl_mvm_vif_link_info mvm_link = {
402887af4dSMiri Korenblit 	.phy_ctxt = &ctx,
412887af4dSMiri Korenblit 	.active = true
422887af4dSMiri Korenblit };
432887af4dSMiri Korenblit 
442887af4dSMiri Korenblit static struct cfg80211_bss bss = {};
452887af4dSMiri Korenblit 
462887af4dSMiri Korenblit static struct ieee80211_bss_conf link_conf = {.bss = &bss};
472887af4dSMiri Korenblit 
4872c19df2SMiri Korenblit static const struct iwl_fw_cmd_version entry = {
4972c19df2SMiri Korenblit 	.group = LEGACY_GROUP,
5072c19df2SMiri Korenblit 	.cmd = BT_PROFILE_NOTIFICATION,
5172c19df2SMiri Korenblit 	.notif_ver = 4
5272c19df2SMiri Korenblit };
5372c19df2SMiri Korenblit 
5472c19df2SMiri Korenblit static struct iwl_fw fw = {
5572c19df2SMiri Korenblit 	.ucode_capa = {
5672c19df2SMiri Korenblit 		.n_cmd_versions = 1,
5772c19df2SMiri Korenblit 		.cmd_versions = &entry,
5872c19df2SMiri Korenblit 	},
5972c19df2SMiri Korenblit };
6072c19df2SMiri Korenblit 
612f876f91SJohannes Berg static struct iwl_mvm mvm = {
622f876f91SJohannes Berg 	.hw = &hw,
632f876f91SJohannes Berg 	.fw = &fw,
642f876f91SJohannes Berg };
6530ce0390SMiri Korenblit 
662887af4dSMiri Korenblit static const struct link_grading_case {
672887af4dSMiri Korenblit 	const char *desc;
682887af4dSMiri Korenblit 	const struct cfg80211_chan_def chandef;
692887af4dSMiri Korenblit 	s32 signal;
702887af4dSMiri Korenblit 	s16 channel_util;
712887af4dSMiri Korenblit 	int chan_load_by_us;
722887af4dSMiri Korenblit 	unsigned int grade;
732887af4dSMiri Korenblit } link_grading_cases[] = {
742887af4dSMiri Korenblit 	{
752887af4dSMiri Korenblit 		.desc = "UHB, RSSI below range, no factors",
762887af4dSMiri Korenblit 		.chandef = {
772887af4dSMiri Korenblit 			.chan = &chan_6ghz,
782887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
792887af4dSMiri Korenblit 		},
802887af4dSMiri Korenblit 		.signal = -100,
812887af4dSMiri Korenblit 		.grade = 177,
822887af4dSMiri Korenblit 	},
832887af4dSMiri Korenblit 	{
842887af4dSMiri Korenblit 		.desc = "LB, RSSI in range, no factors",
852887af4dSMiri Korenblit 		.chandef = {
862887af4dSMiri Korenblit 			.chan = &chan_2ghz,
872887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
882887af4dSMiri Korenblit 		},
892887af4dSMiri Korenblit 		.signal = -84,
902887af4dSMiri Korenblit 		.grade = 344,
912887af4dSMiri Korenblit 	},
922887af4dSMiri Korenblit 	{
932887af4dSMiri Korenblit 		.desc = "HB, RSSI above range, no factors",
942887af4dSMiri Korenblit 		.chandef = {
952887af4dSMiri Korenblit 			.chan = &chan_5ghz,
962887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
972887af4dSMiri Korenblit 		},
982887af4dSMiri Korenblit 		.signal = -50,
992887af4dSMiri Korenblit 		.grade = 3442,
1002887af4dSMiri Korenblit 	},
1012887af4dSMiri Korenblit 	{
1022887af4dSMiri Korenblit 		.desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor",
1032887af4dSMiri Korenblit 		.chandef = {
1042887af4dSMiri Korenblit 			.chan = &chan_5ghz,
1052887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
1062887af4dSMiri Korenblit 		},
1072887af4dSMiri Korenblit 		.signal = -66,
1082887af4dSMiri Korenblit 		.channel_util = 51,
1092887af4dSMiri Korenblit 		.grade = 1836,
1102887af4dSMiri Korenblit 	},
1112887af4dSMiri Korenblit 	{
1122887af4dSMiri Korenblit 		.desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor",
1132887af4dSMiri Korenblit 		.chandef = {
1142887af4dSMiri Korenblit 			.chan = &chan_2ghz,
1152887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
1162887af4dSMiri Korenblit 		},
1172887af4dSMiri Korenblit 		.signal = -61,
1182887af4dSMiri Korenblit 		.channel_util = 51,
1192887af4dSMiri Korenblit 		.chan_load_by_us = 10,
1202887af4dSMiri Korenblit 		.grade = 2061,
1212887af4dSMiri Korenblit 	},
1222887af4dSMiri Korenblit 	{
1232887af4dSMiri Korenblit 		.desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor",
1242887af4dSMiri Korenblit 		.chandef = {
1252887af4dSMiri Korenblit 			.chan = &chan_6ghz,
1262887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_20,
1272887af4dSMiri Korenblit 		},
1282887af4dSMiri Korenblit 		.signal = -66,
1292887af4dSMiri Korenblit 		.channel_util = 102,
1302887af4dSMiri Korenblit 		.chan_load_by_us = 50,
1312887af4dSMiri Korenblit 		.grade = 1552,
1322887af4dSMiri Korenblit 	},
1332887af4dSMiri Korenblit 	{	.desc = "HB, 80 MHz, no channel load factor, punctured percentage 0",
1342887af4dSMiri Korenblit 		.chandef = {
1352887af4dSMiri Korenblit 			.chan = &chan_5ghz,
1362887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_80,
1372887af4dSMiri Korenblit 			.punctured = 0x0000
1382887af4dSMiri Korenblit 		},
1392887af4dSMiri Korenblit 		.signal = -72,
1402887af4dSMiri Korenblit 		.grade = 1750,
1412887af4dSMiri Korenblit 	},
1422887af4dSMiri Korenblit 	{	.desc = "HB, 160 MHz, no channel load factor, punctured percentage 25",
1432887af4dSMiri Korenblit 		.chandef = {
1442887af4dSMiri Korenblit 			.chan = &chan_5ghz,
1452887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_160,
1462887af4dSMiri Korenblit 			.punctured = 0x3
1472887af4dSMiri Korenblit 		},
1482887af4dSMiri Korenblit 		.signal = -72,
1492887af4dSMiri Korenblit 		.grade = 1312,
1502887af4dSMiri Korenblit 	},
1512887af4dSMiri Korenblit 	{	.desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)",
1522887af4dSMiri Korenblit 		.chandef = {
1532887af4dSMiri Korenblit 			.chan = &chan_6ghz,
1542887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_320,
1552887af4dSMiri Korenblit 			.punctured = 0x3
1562887af4dSMiri Korenblit 		},
1572887af4dSMiri Korenblit 		.signal = -72,
1582887af4dSMiri Korenblit 		.grade = 1806,
1592887af4dSMiri Korenblit 	},
1602887af4dSMiri Korenblit 	{	.desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25",
1612887af4dSMiri Korenblit 		.chandef = {
1622887af4dSMiri Korenblit 			.chan = &chan_5ghz,
1632887af4dSMiri Korenblit 			.width = NL80211_CHAN_WIDTH_160,
1642887af4dSMiri Korenblit 			.punctured = 0x3
1652887af4dSMiri Korenblit 		},
1662887af4dSMiri Korenblit 		.channel_util = 51,
1672887af4dSMiri Korenblit 		.chan_load_by_us = 10,
1682887af4dSMiri Korenblit 		.signal = -72,
1692887af4dSMiri Korenblit 		.grade = 1179,
1702887af4dSMiri Korenblit 	},
1712887af4dSMiri Korenblit };
1722887af4dSMiri Korenblit 
KUNIT_ARRAY_PARAM_DESC(link_grading,link_grading_cases,desc)1732887af4dSMiri Korenblit KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc)
1742887af4dSMiri Korenblit 
1752887af4dSMiri Korenblit static void setup_link_conf(struct kunit *test)
1762887af4dSMiri Korenblit {
1772887af4dSMiri Korenblit 	const struct link_grading_case *params = test->param_value;
1782887af4dSMiri Korenblit 	size_t vif_size = sizeof(struct ieee80211_vif) +
1792887af4dSMiri Korenblit 		sizeof(struct iwl_mvm_vif);
1802887af4dSMiri Korenblit 	struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);
1812887af4dSMiri Korenblit 	struct ieee80211_bss_load_elem *bss_load;
1822887af4dSMiri Korenblit 	struct element *element;
1832887af4dSMiri Korenblit 	size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element);
1842887af4dSMiri Korenblit 	struct cfg80211_bss_ies *ies;
1852887af4dSMiri Korenblit 	struct iwl_mvm_vif *mvmvif;
1862887af4dSMiri Korenblit 
1872887af4dSMiri Korenblit 	KUNIT_ASSERT_NOT_NULL(test, vif);
1882887af4dSMiri Korenblit 
1892887af4dSMiri Korenblit 	mvmvif = iwl_mvm_vif_from_mac80211(vif);
1902887af4dSMiri Korenblit 	if (params->chan_load_by_us > 0) {
1912887af4dSMiri Korenblit 		ctx.channel_load_by_us = params->chan_load_by_us;
1922887af4dSMiri Korenblit 		mvmvif->link[0] = &mvm_link;
1932887af4dSMiri Korenblit 	}
1942887af4dSMiri Korenblit 
1952887af4dSMiri Korenblit 	link_conf.vif = vif;
1962887af4dSMiri Korenblit 	link_conf.chanreq.oper = params->chandef;
1972887af4dSMiri Korenblit 	bss.signal = DBM_TO_MBM(params->signal);
1982887af4dSMiri Korenblit 
1992887af4dSMiri Korenblit 	ies = kunit_kzalloc(test, ies_size, GFP_KERNEL);
2002887af4dSMiri Korenblit 	KUNIT_ASSERT_NOT_NULL(test, ies);
2012887af4dSMiri Korenblit 	ies->len = sizeof(*bss_load) + sizeof(struct element);
2022887af4dSMiri Korenblit 
2032887af4dSMiri Korenblit 	element = (void *)ies->data;
2042887af4dSMiri Korenblit 	element->datalen = sizeof(*bss_load);
2052887af4dSMiri Korenblit 	element->id = 11;
2062887af4dSMiri Korenblit 
2072887af4dSMiri Korenblit 	bss_load = (void *)element->data;
2082887af4dSMiri Korenblit 	bss_load->channel_util = params->channel_util;
2092887af4dSMiri Korenblit 
2102887af4dSMiri Korenblit 	rcu_assign_pointer(bss.ies, ies);
211d9b7531fSJohannes Berg 	rcu_assign_pointer(bss.beacon_ies, ies);
2122887af4dSMiri Korenblit }
2132887af4dSMiri Korenblit 
test_link_grading(struct kunit * test)2142887af4dSMiri Korenblit static void test_link_grading(struct kunit *test)
2152887af4dSMiri Korenblit {
2162887af4dSMiri Korenblit 	const struct link_grading_case *params = test->param_value;
2172887af4dSMiri Korenblit 	unsigned int ret;
2182887af4dSMiri Korenblit 
2192887af4dSMiri Korenblit 	setup_link_conf(test);
2202887af4dSMiri Korenblit 
2212887af4dSMiri Korenblit 	rcu_read_lock();
2222887af4dSMiri Korenblit 	ret = iwl_mvm_get_link_grade(&link_conf);
2232887af4dSMiri Korenblit 	rcu_read_unlock();
2242887af4dSMiri Korenblit 
2252887af4dSMiri Korenblit 	KUNIT_EXPECT_EQ(test, ret, params->grade);
2262887af4dSMiri Korenblit 
2272887af4dSMiri Korenblit 	kunit_kfree(test, link_conf.vif);
2282887af4dSMiri Korenblit 	RCU_INIT_POINTER(bss.ies, NULL);
2292887af4dSMiri Korenblit }
2302887af4dSMiri Korenblit 
2312887af4dSMiri Korenblit static struct kunit_case link_grading_test_cases[] = {
2322887af4dSMiri Korenblit 	KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params),
2332887af4dSMiri Korenblit 	{}
2342887af4dSMiri Korenblit };
2352887af4dSMiri Korenblit 
2362887af4dSMiri Korenblit static struct kunit_suite link_grading = {
2372887af4dSMiri Korenblit 	.name = "iwlmvm-link-grading",
2382887af4dSMiri Korenblit 	.test_cases = link_grading_test_cases,
2392887af4dSMiri Korenblit };
2402887af4dSMiri Korenblit 
2412887af4dSMiri Korenblit kunit_test_suite(link_grading);
24207bf5297SMiri Korenblit 
24307bf5297SMiri Korenblit static const struct valid_link_pair_case {
24407bf5297SMiri Korenblit 	const char *desc;
24572c19df2SMiri Korenblit 	bool bt;
24630ce0390SMiri Korenblit 	struct ieee80211_channel *chan_a;
24730ce0390SMiri Korenblit 	struct ieee80211_channel *chan_b;
24830ce0390SMiri Korenblit 	enum nl80211_chan_width cw_a;
24930ce0390SMiri Korenblit 	enum nl80211_chan_width cw_b;
25030ce0390SMiri Korenblit 	s32 sig_a;
25130ce0390SMiri Korenblit 	s32 sig_b;
2522f876f91SJohannes Berg 	bool csa_a;
25307bf5297SMiri Korenblit 	bool valid;
25407bf5297SMiri Korenblit } valid_link_pair_cases[] = {
25507bf5297SMiri Korenblit 	{
25607bf5297SMiri Korenblit 		.desc = "HB + UHB, valid.",
257ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
258ae7fe563SYedidya Benshimol 		.chan_b = &chan_5ghz,
25907bf5297SMiri Korenblit 		.valid = true,
26007bf5297SMiri Korenblit 	},
26107bf5297SMiri Korenblit 	{
26207bf5297SMiri Korenblit 		.desc = "LB + HB, no BT.",
26330ce0390SMiri Korenblit 		.chan_a = &chan_2ghz,
26430ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
265*20eccf4aSSomashekhar(Som) 		.valid = true,
26607bf5297SMiri Korenblit 	},
26707bf5297SMiri Korenblit 	{
26807bf5297SMiri Korenblit 		.desc = "LB + HB, with BT.",
26972c19df2SMiri Korenblit 		.bt = true,
27030ce0390SMiri Korenblit 		.chan_a = &chan_2ghz,
27130ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
27207bf5297SMiri Korenblit 		.valid = false,
27307bf5297SMiri Korenblit 	},
27407bf5297SMiri Korenblit 	{
27507bf5297SMiri Korenblit 		.desc = "Same band",
27630ce0390SMiri Korenblit 		.chan_a = &chan_2ghz,
27730ce0390SMiri Korenblit 		.chan_b = &chan_2ghz,
27807bf5297SMiri Korenblit 		.valid = false,
27907bf5297SMiri Korenblit 	},
28030ce0390SMiri Korenblit 	{
28130ce0390SMiri Korenblit 		.desc = "RSSI: LB, 20 MHz, low",
28230ce0390SMiri Korenblit 		.chan_a = &chan_2ghz,
28330ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_20,
28430ce0390SMiri Korenblit 		.sig_a = -68,
28530ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
28630ce0390SMiri Korenblit 		.valid = false,
28730ce0390SMiri Korenblit 	},
28830ce0390SMiri Korenblit 	{
289ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 20 MHz, high",
290ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
29130ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_20,
29230ce0390SMiri Korenblit 		.sig_a = -66,
29330ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
294ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_20,
29530ce0390SMiri Korenblit 		.valid = true,
29630ce0390SMiri Korenblit 	},
29730ce0390SMiri Korenblit 	{
298ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 40 MHz, low",
299ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
30030ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_40,
30130ce0390SMiri Korenblit 		.sig_a = -65,
30230ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
303ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_40,
30430ce0390SMiri Korenblit 		.valid = false,
30530ce0390SMiri Korenblit 	},
30630ce0390SMiri Korenblit 	{
307ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 40 MHz, high",
308ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
30930ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_40,
31030ce0390SMiri Korenblit 		.sig_a = -63,
31130ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
312ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_40,
31330ce0390SMiri Korenblit 		.valid = true,
31430ce0390SMiri Korenblit 	},
31530ce0390SMiri Korenblit 	{
316ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 80 MHz, low",
317ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
31830ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_80,
31930ce0390SMiri Korenblit 		.sig_a = -62,
320ae7fe563SYedidya Benshimol 		.chan_b = &chan_5ghz,
321ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_80,
32230ce0390SMiri Korenblit 		.valid = false,
32330ce0390SMiri Korenblit 	},
32430ce0390SMiri Korenblit 	{
325ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 80 MHz, high",
326ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
32730ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_80,
32830ce0390SMiri Korenblit 		.sig_a = -60,
329ae7fe563SYedidya Benshimol 		.chan_b = &chan_5ghz,
330ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_80,
33130ce0390SMiri Korenblit 		.valid = true,
33230ce0390SMiri Korenblit 	},
33330ce0390SMiri Korenblit 	{
334ae7fe563SYedidya Benshimol 		.desc = "RSSI: UHB, 160 MHz, low",
335ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
33630ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_160,
33730ce0390SMiri Korenblit 		.sig_a = -59,
338ae7fe563SYedidya Benshimol 		.chan_b = &chan_5ghz,
339ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_160,
34030ce0390SMiri Korenblit 		.valid = false,
34130ce0390SMiri Korenblit 	},
34230ce0390SMiri Korenblit 	{
34330ce0390SMiri Korenblit 		.desc = "RSSI: HB, 160 MHz, high",
344ae7fe563SYedidya Benshimol 		.chan_a = &chan_6ghz,
34530ce0390SMiri Korenblit 		.cw_a = NL80211_CHAN_WIDTH_160,
34630ce0390SMiri Korenblit 		.sig_a = -5,
34730ce0390SMiri Korenblit 		.chan_b = &chan_5ghz,
348ae7fe563SYedidya Benshimol 		.cw_b = NL80211_CHAN_WIDTH_160,
34930ce0390SMiri Korenblit 		.valid = true,
35030ce0390SMiri Korenblit 	},
3512f876f91SJohannes Berg 	{
3522f876f91SJohannes Berg 		.desc = "CSA active",
3532f876f91SJohannes Berg 		.chan_a = &chan_6ghz,
3542f876f91SJohannes Berg 		.cw_a = NL80211_CHAN_WIDTH_160,
3552f876f91SJohannes Berg 		.sig_a = -5,
3562f876f91SJohannes Berg 		.chan_b = &chan_5ghz,
3572f876f91SJohannes Berg 		.cw_b = NL80211_CHAN_WIDTH_160,
3582f876f91SJohannes Berg 		.valid = false,
3592f876f91SJohannes Berg 		/* same as previous entry with valid=true except for CSA */
3602f876f91SJohannes Berg 		.csa_a = true,
3612f876f91SJohannes Berg 	},
36207bf5297SMiri Korenblit };
36307bf5297SMiri Korenblit 
KUNIT_ARRAY_PARAM_DESC(valid_link_pair,valid_link_pair_cases,desc)36407bf5297SMiri Korenblit KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc)
36507bf5297SMiri Korenblit 
36607bf5297SMiri Korenblit static void test_valid_link_pair(struct kunit *test)
36707bf5297SMiri Korenblit {
36807bf5297SMiri Korenblit 	const struct valid_link_pair_case *params = test->param_value;
36907bf5297SMiri Korenblit 	size_t vif_size = sizeof(struct ieee80211_vif) +
37007bf5297SMiri Korenblit 		sizeof(struct iwl_mvm_vif);
37107bf5297SMiri Korenblit 	struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);
37230ce0390SMiri Korenblit 	struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans),
37330ce0390SMiri Korenblit 						GFP_KERNEL);
37430ce0390SMiri Korenblit 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
37507bf5297SMiri Korenblit 	struct iwl_mvm_link_sel_data link_a = {
37630ce0390SMiri Korenblit 		.chandef = &chandef_a,
37730ce0390SMiri Korenblit 		.link_id = 1,
37830ce0390SMiri Korenblit 		.signal = params->sig_a,
37907bf5297SMiri Korenblit 	};
38007bf5297SMiri Korenblit 	struct iwl_mvm_link_sel_data link_b = {
38130ce0390SMiri Korenblit 		.chandef = &chandef_b,
38230ce0390SMiri Korenblit 		.link_id = 5,
38330ce0390SMiri Korenblit 		.signal = params->sig_b,
38407bf5297SMiri Korenblit 	};
3852f876f91SJohannes Berg 	struct ieee80211_bss_conf *conf;
38607bf5297SMiri Korenblit 	bool result;
38707bf5297SMiri Korenblit 
38807bf5297SMiri Korenblit 	KUNIT_ASSERT_NOT_NULL(test, vif);
38930ce0390SMiri Korenblit 	KUNIT_ASSERT_NOT_NULL(test, trans);
39007bf5297SMiri Korenblit 
39130ce0390SMiri Korenblit 	chandef_a.chan = params->chan_a;
39230ce0390SMiri Korenblit 	chandef_b.chan = params->chan_b;
39330ce0390SMiri Korenblit 
39430ce0390SMiri Korenblit 	chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20;
39530ce0390SMiri Korenblit 	chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20;
39630ce0390SMiri Korenblit 
39730ce0390SMiri Korenblit 	mvm.trans = trans;
39830ce0390SMiri Korenblit 
39972c19df2SMiri Korenblit 	mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;
40030ce0390SMiri Korenblit 	mvmvif->mvm = &mvm;
40107bf5297SMiri Korenblit 
4022f876f91SJohannes Berg 	conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);
4032f876f91SJohannes Berg 	KUNIT_ASSERT_NOT_NULL(test, conf);
4042f876f91SJohannes Berg 	conf->chanreq.oper = chandef_a;
4052f876f91SJohannes Berg 	conf->csa_active = params->csa_a;
4062f876f91SJohannes Berg 	vif->link_conf[link_a.link_id] = (void __rcu *)conf;
4072f876f91SJohannes Berg 
4082f876f91SJohannes Berg 	conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);
4092f876f91SJohannes Berg 	KUNIT_ASSERT_NOT_NULL(test, conf);
4102f876f91SJohannes Berg 	conf->chanreq.oper = chandef_b;
4112f876f91SJohannes Berg 	vif->link_conf[link_b.link_id] = (void __rcu *)conf;
4122f876f91SJohannes Berg 
4132f876f91SJohannes Berg 	wiphy_lock(&wiphy);
41407bf5297SMiri Korenblit 	result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);
4152f876f91SJohannes Berg 	wiphy_unlock(&wiphy);
41607bf5297SMiri Korenblit 
41707bf5297SMiri Korenblit 	KUNIT_EXPECT_EQ(test, result, params->valid);
41807bf5297SMiri Korenblit 
41907bf5297SMiri Korenblit 	kunit_kfree(test, vif);
42030ce0390SMiri Korenblit 	kunit_kfree(test, trans);
42107bf5297SMiri Korenblit }
42207bf5297SMiri Korenblit 
42307bf5297SMiri Korenblit static struct kunit_case valid_link_pair_test_cases[] = {
42407bf5297SMiri Korenblit 	KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params),
42507bf5297SMiri Korenblit 	{},
42607bf5297SMiri Korenblit };
42707bf5297SMiri Korenblit 
42807bf5297SMiri Korenblit static struct kunit_suite valid_link_pair = {
42907bf5297SMiri Korenblit 	.name = "iwlmvm-valid-link-pair",
43007bf5297SMiri Korenblit 	.test_cases = valid_link_pair_test_cases,
43107bf5297SMiri Korenblit };
43207bf5297SMiri Korenblit 
43307bf5297SMiri Korenblit kunit_test_suite(valid_link_pair);
434