xref: /linux/net/mac80211/tests/tpe.c (revision 6e7fd890f1d6ac83805409e9c346240de2705584)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * KUnit tests for TPE element handling
4  *
5  * Copyright (C) 2024 Intel Corporation
6  */
7 #include <kunit/test.h>
8 #include "../ieee80211_i.h"
9 
10 MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
11 
12 static struct ieee80211_channel chan6g_1 = {
13 	.band = NL80211_BAND_6GHZ,
14 	.center_freq = 5955,
15 };
16 
17 static struct ieee80211_channel chan6g_33 = {
18 	.band = NL80211_BAND_6GHZ,
19 	.center_freq = 6115,
20 };
21 
22 static struct ieee80211_channel chan6g_61 = {
23 	.band = NL80211_BAND_6GHZ,
24 	.center_freq = 6255,
25 };
26 
27 static const struct subchan_test_case {
28 	const char *desc;
29 	struct cfg80211_chan_def c;
30 	u8 n;
31 	int expect;
32 } subchan_offset_cases[] = {
33 	{
34 		.desc = "identical 20 MHz",
35 		.c.width = NL80211_CHAN_WIDTH_20,
36 		.c.chan = &chan6g_1,
37 		.c.center_freq1 = 5955,
38 		.n = 1,
39 		.expect = 0,
40 	},
41 	{
42 		.desc = "identical 40 MHz",
43 		.c.width = NL80211_CHAN_WIDTH_40,
44 		.c.chan = &chan6g_1,
45 		.c.center_freq1 = 5965,
46 		.n = 2,
47 		.expect = 0,
48 	},
49 	{
50 		.desc = "identical 80+80 MHz",
51 		/* not really is valid? doesn't matter for the test */
52 		.c.width = NL80211_CHAN_WIDTH_80P80,
53 		.c.chan = &chan6g_1,
54 		.c.center_freq1 = 5985,
55 		.c.center_freq2 = 6225,
56 		.n = 16,
57 		.expect = 0,
58 	},
59 	{
60 		.desc = "identical 320 MHz",
61 		.c.width = NL80211_CHAN_WIDTH_320,
62 		.c.chan = &chan6g_1,
63 		.c.center_freq1 = 6105,
64 		.n = 16,
65 		.expect = 0,
66 	},
67 	{
68 		.desc = "lower 160 MHz of 320 MHz",
69 		.c.width = NL80211_CHAN_WIDTH_320,
70 		.c.chan = &chan6g_1,
71 		.c.center_freq1 = 6105,
72 		.n = 8,
73 		.expect = 0,
74 	},
75 	{
76 		.desc = "upper 160 MHz of 320 MHz",
77 		.c.width = NL80211_CHAN_WIDTH_320,
78 		.c.chan = &chan6g_61,
79 		.c.center_freq1 = 6105,
80 		.n = 8,
81 		.expect = 8,
82 	},
83 	{
84 		.desc = "upper 160 MHz of 320 MHz, go to 40",
85 		.c.width = NL80211_CHAN_WIDTH_320,
86 		.c.chan = &chan6g_61,
87 		.c.center_freq1 = 6105,
88 		.n = 2,
89 		.expect = 8 + 4 + 2,
90 	},
91 	{
92 		.desc = "secondary 80 above primary in 80+80 MHz",
93 		/* not really is valid? doesn't matter for the test */
94 		.c.width = NL80211_CHAN_WIDTH_80P80,
95 		.c.chan = &chan6g_1,
96 		.c.center_freq1 = 5985,
97 		.c.center_freq2 = 6225,
98 		.n = 4,
99 		.expect = 0,
100 	},
101 	{
102 		.desc = "secondary 80 below primary in 80+80 MHz",
103 		/* not really is valid? doesn't matter for the test */
104 		.c.width = NL80211_CHAN_WIDTH_80P80,
105 		.c.chan = &chan6g_61,
106 		.c.center_freq1 = 6225,
107 		.c.center_freq2 = 5985,
108 		.n = 4,
109 		.expect = 4,
110 	},
111 	{
112 		.desc = "secondary 80 below primary in 80+80 MHz, go to 20",
113 		/* not really is valid? doesn't matter for the test */
114 		.c.width = NL80211_CHAN_WIDTH_80P80,
115 		.c.chan = &chan6g_61,
116 		.c.center_freq1 = 6225,
117 		.c.center_freq2 = 5985,
118 		.n = 1,
119 		.expect = 7,
120 	},
121 };
122 
123 KUNIT_ARRAY_PARAM_DESC(subchan_offset, subchan_offset_cases, desc);
124 
125 static void subchan_offset(struct kunit *test)
126 {
127 	const struct subchan_test_case *params = test->param_value;
128 	int offset;
129 
130 	KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(&params->c), true);
131 
132 	offset = ieee80211_calc_chandef_subchan_offset(&params->c, params->n);
133 
134 	KUNIT_EXPECT_EQ(test, params->expect, offset);
135 }
136 
137 static const struct psd_reorder_test_case {
138 	const char *desc;
139 	struct cfg80211_chan_def ap, used;
140 	struct ieee80211_parsed_tpe_psd psd, out;
141 } psd_reorder_cases[] = {
142 	{
143 		.desc = "no changes, 320 MHz",
144 
145 		.ap.width = NL80211_CHAN_WIDTH_320,
146 		.ap.chan = &chan6g_1,
147 		.ap.center_freq1 = 6105,
148 
149 		.used.width = NL80211_CHAN_WIDTH_320,
150 		.used.chan = &chan6g_1,
151 		.used.center_freq1 = 6105,
152 
153 		.psd.valid = true,
154 		.psd.count = 16,
155 		.psd.n = 8,
156 		.psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
157 
158 		.out.valid = true,
159 		.out.count = 16,
160 		.out.n = 8,
161 		.out.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
162 	},
163 	{
164 		.desc = "no changes, 320 MHz, 160 MHz used, n=0",
165 
166 		.ap.width = NL80211_CHAN_WIDTH_320,
167 		.ap.chan = &chan6g_1,
168 		.ap.center_freq1 = 6105,
169 
170 		.used.width = NL80211_CHAN_WIDTH_160,
171 		.used.chan = &chan6g_1,
172 		.used.center_freq1 = 6025,
173 
174 		.psd.valid = true,
175 		.psd.count = 16,
176 		.psd.n = 0,
177 		.psd.power = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
178 
179 		.out.valid = true,
180 		.out.count = 8,
181 		.out.n = 0,
182 		.out.power = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
183 	},
184 	{
185 		.desc = "320 MHz, HE is 80, used 160, all lower",
186 
187 		.ap.width = NL80211_CHAN_WIDTH_320,
188 		.ap.chan = &chan6g_1,
189 		.ap.center_freq1 = 6105,
190 
191 		.used.width = NL80211_CHAN_WIDTH_160,
192 		.used.chan = &chan6g_1,
193 		.used.center_freq1 = 6025,
194 
195 		.psd.valid = true,
196 		.psd.count = 16,
197 		.psd.n = 4,
198 		.psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
199 
200 		.out.valid = true,
201 		.out.count = 8,
202 		.out.n = 4,
203 		.out.power = { 0, 1, 2, 3, 4, 5, 6, 7, 127, 127, 127, 127, 127, 127, 127, 127},
204 	},
205 	{
206 		.desc = "320 MHz, HE is 80, used 160, all upper",
207 		/*
208 		 * EHT: | | | | | | | | | | | | | | | | |
209 		 * HE:                          | | | | |
210 		 * used:                | | | | | | | | |
211 		 */
212 
213 		.ap.width = NL80211_CHAN_WIDTH_320,
214 		.ap.chan = &chan6g_61,
215 		.ap.center_freq1 = 6105,
216 
217 		.used.width = NL80211_CHAN_WIDTH_160,
218 		.used.chan = &chan6g_61,
219 		.used.center_freq1 = 6185,
220 
221 		.psd.valid = true,
222 		.psd.count = 16,
223 		.psd.n = 4,
224 		.psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
225 
226 		.out.valid = true,
227 		.out.count = 8,
228 		.out.n = 4,
229 		.out.power = { 12, 13, 14, 15, 0, 1, 2, 3, 127, 127, 127, 127, 127, 127, 127, 127},
230 	},
231 	{
232 		.desc = "320 MHz, HE is 80, used 160, split",
233 		/*
234 		 * EHT: | | | | | | | | | | | | | | | | |
235 		 * HE:                  | | | | |
236 		 * used:                | | | | | | | | |
237 		 */
238 
239 		.ap.width = NL80211_CHAN_WIDTH_320,
240 		.ap.chan = &chan6g_33,
241 		.ap.center_freq1 = 6105,
242 
243 		.used.width = NL80211_CHAN_WIDTH_160,
244 		.used.chan = &chan6g_33,
245 		.used.center_freq1 = 6185,
246 
247 		.psd.valid = true,
248 		.psd.count = 16,
249 		.psd.n = 4,
250 		.psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
251 
252 		.out.valid = true,
253 		.out.count = 8,
254 		.out.n = 4,
255 		.out.power = { 0, 1, 2, 3, 12, 13, 14, 15, 127, 127, 127, 127, 127, 127, 127, 127},
256 	},
257 };
258 
259 KUNIT_ARRAY_PARAM_DESC(psd_reorder, psd_reorder_cases, desc);
260 
261 static void psd_reorder(struct kunit *test)
262 {
263 	const struct psd_reorder_test_case *params = test->param_value;
264 	struct ieee80211_parsed_tpe_psd tmp = params->psd;
265 
266 	KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(&params->ap), true);
267 	KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(&params->used), true);
268 
269 	ieee80211_rearrange_tpe_psd(&tmp, &params->ap, &params->used);
270 	KUNIT_EXPECT_MEMEQ(test, &tmp, &params->out, sizeof(tmp));
271 }
272 
273 static struct kunit_case tpe_test_cases[] = {
274 	KUNIT_CASE_PARAM(subchan_offset, subchan_offset_gen_params),
275 	KUNIT_CASE_PARAM(psd_reorder, psd_reorder_gen_params),
276 	{}
277 };
278 
279 static struct kunit_suite tpe = {
280 	.name = "mac80211-tpe",
281 	.test_cases = tpe_test_cases,
282 };
283 
284 kunit_test_suite(tpe);
285