Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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
 11MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
 12
 13static struct wiphy wiphy = {
 14	.mtx = __MUTEX_INITIALIZER(wiphy.mtx),
 15};
 16
 17static struct ieee80211_hw hw = {
 18	.wiphy = &wiphy,
 19};
 20
 21static struct ieee80211_channel chan_5ghz = {
 22	.band = NL80211_BAND_5GHZ,
 23};
 24
 25static struct ieee80211_channel chan_6ghz = {
 26	.band = NL80211_BAND_6GHZ,
 27};
 28
 29static struct ieee80211_channel chan_2ghz = {
 30	.band = NL80211_BAND_2GHZ,
 31};
 32
 33static struct cfg80211_chan_def chandef_a = {};
 34
 35static struct cfg80211_chan_def chandef_b = {};
 36
 37static struct iwl_mvm_phy_ctxt ctx = {};
 38
 39static struct iwl_mvm_vif_link_info mvm_link = {
 40	.phy_ctxt = &ctx,
 41	.active = true
 42};
 43
 44static struct cfg80211_bss bss = {};
 45
 46static struct ieee80211_bss_conf link_conf = {.bss = &bss};
 47
 48static const struct iwl_fw_cmd_version entry = {
 49	.group = LEGACY_GROUP,
 50	.cmd = BT_PROFILE_NOTIFICATION,
 51	.notif_ver = 4
 52};
 53
 54static struct iwl_fw fw = {
 55	.ucode_capa = {
 56		.n_cmd_versions = 1,
 57		.cmd_versions = &entry,
 58	},
 59};
 60
 61static struct iwl_mvm mvm = {
 62	.hw = &hw,
 63	.fw = &fw,
 64};
 65
 66static const struct link_grading_case {
 67	const char *desc;
 68	const struct cfg80211_chan_def chandef;
 69	s32 signal;
 70	s16 channel_util;
 71	int chan_load_by_us;
 72	unsigned int grade;
 73} link_grading_cases[] = {
 74	{
 75		.desc = "UHB, RSSI below range, no factors",
 76		.chandef = {
 77			.chan = &chan_6ghz,
 78			.width = NL80211_CHAN_WIDTH_20,
 79		},
 80		.signal = -100,
 81		.grade = 177,
 82	},
 83	{
 84		.desc = "LB, RSSI in range, no factors",
 85		.chandef = {
 86			.chan = &chan_2ghz,
 87			.width = NL80211_CHAN_WIDTH_20,
 88		},
 89		.signal = -84,
 90		.grade = 344,
 91	},
 92	{
 93		.desc = "HB, RSSI above range, no factors",
 94		.chandef = {
 95			.chan = &chan_5ghz,
 96			.width = NL80211_CHAN_WIDTH_20,
 97		},
 98		.signal = -50,
 99		.grade = 3442,
100	},
101	{
102		.desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor",
103		.chandef = {
104			.chan = &chan_5ghz,
105			.width = NL80211_CHAN_WIDTH_20,
106		},
107		.signal = -66,
108		.channel_util = 51,
109		.grade = 1836,
110	},
111	{
112		.desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor",
113		.chandef = {
114			.chan = &chan_2ghz,
115			.width = NL80211_CHAN_WIDTH_20,
116		},
117		.signal = -61,
118		.channel_util = 51,
119		.chan_load_by_us = 10,
120		.grade = 2061,
121	},
122	{
123		.desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor",
124		.chandef = {
125			.chan = &chan_6ghz,
126			.width = NL80211_CHAN_WIDTH_20,
127		},
128		.signal = -66,
129		.channel_util = 102,
130		.chan_load_by_us = 50,
131		.grade = 1552,
132	},
133	{	.desc = "HB, 80 MHz, no channel load factor, punctured percentage 0",
134		.chandef = {
135			.chan = &chan_5ghz,
136			.width = NL80211_CHAN_WIDTH_80,
137			.punctured = 0x0000
138		},
139		.signal = -72,
140		.grade = 1750,
141	},
142	{	.desc = "HB, 160 MHz, no channel load factor, punctured percentage 25",
143		.chandef = {
144			.chan = &chan_5ghz,
145			.width = NL80211_CHAN_WIDTH_160,
146			.punctured = 0x3
147		},
148		.signal = -72,
149		.grade = 1312,
150	},
151	{	.desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)",
152		.chandef = {
153			.chan = &chan_6ghz,
154			.width = NL80211_CHAN_WIDTH_320,
155			.punctured = 0x3
156		},
157		.signal = -72,
158		.grade = 1806,
159	},
160	{	.desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25",
161		.chandef = {
162			.chan = &chan_5ghz,
163			.width = NL80211_CHAN_WIDTH_160,
164			.punctured = 0x3
165		},
166		.channel_util = 51,
167		.chan_load_by_us = 10,
168		.signal = -72,
169		.grade = 1179,
170	},
171};
172
173KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc)
174
175static void setup_link_conf(struct kunit *test)
176{
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;
186
187	KUNIT_ASSERT_NOT_NULL(test, vif);
188
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;
193	}
194
195	link_conf.vif = vif;
196	link_conf.chanreq.oper = params->chandef;
197	bss.signal = DBM_TO_MBM(params->signal);
198
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);
202
203	element = (void *)ies->data;
204	element->datalen = sizeof(*bss_load);
205	element->id = 11;
206
207	bss_load = (void *)element->data;
208	bss_load->channel_util = params->channel_util;
209
210	rcu_assign_pointer(bss.ies, ies);
211	rcu_assign_pointer(bss.beacon_ies, ies);
212}
213
214static void test_link_grading(struct kunit *test)
215{
216	const struct link_grading_case *params = test->param_value;
217	unsigned int ret;
218
219	setup_link_conf(test);
220
221	rcu_read_lock();
222	ret = iwl_mvm_get_link_grade(&link_conf);
223	rcu_read_unlock();
224
225	KUNIT_EXPECT_EQ(test, ret, params->grade);
226
227	kunit_kfree(test, link_conf.vif);
228	RCU_INIT_POINTER(bss.ies, NULL);
229}
230
231static struct kunit_case link_grading_test_cases[] = {
232	KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params),
233	{}
234};
235
236static struct kunit_suite link_grading = {
237	.name = "iwlmvm-link-grading",
238	.test_cases = link_grading_test_cases,
239};
240
241kunit_test_suite(link_grading);
242
243static const struct valid_link_pair_case {
244	const char *desc;
245	bool bt;
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;
250	s32 sig_a;
251	s32 sig_b;
252	bool csa_a;
253	bool valid;
254} valid_link_pair_cases[] = {
255	{
256		.desc = "HB + UHB, valid.",
257		.chan_a = &chan_6ghz,
258		.chan_b = &chan_5ghz,
259		.valid = true,
260	},
261	{
262		.desc = "LB + HB, no BT.",
263		.chan_a = &chan_2ghz,
264		.chan_b = &chan_5ghz,
265		.valid = false,
266	},
267	{
268		.desc = "LB + HB, with BT.",
269		.bt = true,
270		.chan_a = &chan_2ghz,
271		.chan_b = &chan_5ghz,
272		.valid = false,
273	},
274	{
275		.desc = "Same band",
276		.chan_a = &chan_2ghz,
277		.chan_b = &chan_2ghz,
278		.valid = false,
279	},
280	{
281		.desc = "RSSI: LB, 20 MHz, low",
282		.chan_a = &chan_2ghz,
283		.cw_a = NL80211_CHAN_WIDTH_20,
284		.sig_a = -68,
285		.chan_b = &chan_5ghz,
286		.valid = false,
287	},
288	{
289		.desc = "RSSI: UHB, 20 MHz, high",
290		.chan_a = &chan_6ghz,
291		.cw_a = NL80211_CHAN_WIDTH_20,
292		.sig_a = -66,
293		.chan_b = &chan_5ghz,
294		.cw_b = NL80211_CHAN_WIDTH_20,
295		.valid = true,
296	},
297	{
298		.desc = "RSSI: UHB, 40 MHz, low",
299		.chan_a = &chan_6ghz,
300		.cw_a = NL80211_CHAN_WIDTH_40,
301		.sig_a = -65,
302		.chan_b = &chan_5ghz,
303		.cw_b = NL80211_CHAN_WIDTH_40,
304		.valid = false,
305	},
306	{
307		.desc = "RSSI: UHB, 40 MHz, high",
308		.chan_a = &chan_6ghz,
309		.cw_a = NL80211_CHAN_WIDTH_40,
310		.sig_a = -63,
311		.chan_b = &chan_5ghz,
312		.cw_b = NL80211_CHAN_WIDTH_40,
313		.valid = true,
314	},
315	{
316		.desc = "RSSI: UHB, 80 MHz, low",
317		.chan_a = &chan_6ghz,
318		.cw_a = NL80211_CHAN_WIDTH_80,
319		.sig_a = -62,
320		.chan_b = &chan_5ghz,
321		.cw_b = NL80211_CHAN_WIDTH_80,
322		.valid = false,
323	},
324	{
325		.desc = "RSSI: UHB, 80 MHz, high",
326		.chan_a = &chan_6ghz,
327		.cw_a = NL80211_CHAN_WIDTH_80,
328		.sig_a = -60,
329		.chan_b = &chan_5ghz,
330		.cw_b = NL80211_CHAN_WIDTH_80,
331		.valid = true,
332	},
333	{
334		.desc = "RSSI: UHB, 160 MHz, low",
335		.chan_a = &chan_6ghz,
336		.cw_a = NL80211_CHAN_WIDTH_160,
337		.sig_a = -59,
338		.chan_b = &chan_5ghz,
339		.cw_b = NL80211_CHAN_WIDTH_160,
340		.valid = false,
341	},
342	{
343		.desc = "RSSI: HB, 160 MHz, high",
344		.chan_a = &chan_6ghz,
345		.cw_a = NL80211_CHAN_WIDTH_160,
346		.sig_a = -5,
347		.chan_b = &chan_5ghz,
348		.cw_b = NL80211_CHAN_WIDTH_160,
349		.valid = true,
350	},
351	{
352		.desc = "CSA active",
353		.chan_a = &chan_6ghz,
354		.cw_a = NL80211_CHAN_WIDTH_160,
355		.sig_a = -5,
356		.chan_b = &chan_5ghz,
357		.cw_b = NL80211_CHAN_WIDTH_160,
358		.valid = false,
359		/* same as previous entry with valid=true except for CSA */
360		.csa_a = true,
361	},
362};
363
364KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc)
365
366static void test_valid_link_pair(struct kunit *test)
367{
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),
373						GFP_KERNEL);
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,
377		.link_id = 1,
378		.signal = params->sig_a,
379	};
380	struct iwl_mvm_link_sel_data link_b = {
381		.chandef = &chandef_b,
382		.link_id = 5,
383		.signal = params->sig_b,
384	};
385	struct ieee80211_bss_conf *conf;
386	bool result;
387
388	KUNIT_ASSERT_NOT_NULL(test, vif);
389	KUNIT_ASSERT_NOT_NULL(test, trans);
390
391	chandef_a.chan = params->chan_a;
392	chandef_b.chan = params->chan_b;
393
394	chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20;
395	chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20;
396
397	mvm.trans = trans;
398
399	mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;
400	mvmvif->mvm = &mvm;
401
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;
407
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;
412
413	wiphy_lock(&wiphy);
414	result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);
415	wiphy_unlock(&wiphy);
416
417	KUNIT_EXPECT_EQ(test, result, params->valid);
418
419	kunit_kfree(test, vif);
420	kunit_kfree(test, trans);
421}
422
423static struct kunit_case valid_link_pair_test_cases[] = {
424	KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params),
425	{},
426};
427
428static struct kunit_suite valid_link_pair = {
429	.name = "iwlmvm-valid-link-pair",
430	.test_cases = valid_link_pair_test_cases,
431};
432
433kunit_test_suite(valid_link_pair);