xref: /linux/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c (revision cbc7afffc5ec581d3781c49fe9c8e8c661e5217b)
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