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(¶ms->c), true); 131 132 offset = ieee80211_calc_chandef_subchan_offset(¶ms->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(¶ms->ap), true); 267 KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(¶ms->used), true); 268 269 ieee80211_rearrange_tpe_psd(&tmp, ¶ms->ap, ¶ms->used); 270 KUNIT_EXPECT_MEMEQ(test, &tmp, ¶ms->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