// SPDX-License-Identifier: GPL-2.0-only /* * KUnit tests for TPE element handling * * Copyright (C) 2024 Intel Corporation */ #include #include "../ieee80211_i.h" MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); static struct ieee80211_channel chan6g_1 = { .band = NL80211_BAND_6GHZ, .center_freq = 5955, }; static struct ieee80211_channel chan6g_33 = { .band = NL80211_BAND_6GHZ, .center_freq = 6115, }; static struct ieee80211_channel chan6g_61 = { .band = NL80211_BAND_6GHZ, .center_freq = 6255, }; static const struct subchan_test_case { const char *desc; struct cfg80211_chan_def c; u8 n; int expect; } subchan_offset_cases[] = { { .desc = "identical 20 MHz", .c.width = NL80211_CHAN_WIDTH_20, .c.chan = &chan6g_1, .c.center_freq1 = 5955, .n = 1, .expect = 0, }, { .desc = "identical 40 MHz", .c.width = NL80211_CHAN_WIDTH_40, .c.chan = &chan6g_1, .c.center_freq1 = 5965, .n = 2, .expect = 0, }, { .desc = "identical 80+80 MHz", /* not really is valid? doesn't matter for the test */ .c.width = NL80211_CHAN_WIDTH_80P80, .c.chan = &chan6g_1, .c.center_freq1 = 5985, .c.center_freq2 = 6225, .n = 16, .expect = 0, }, { .desc = "identical 320 MHz", .c.width = NL80211_CHAN_WIDTH_320, .c.chan = &chan6g_1, .c.center_freq1 = 6105, .n = 16, .expect = 0, }, { .desc = "lower 160 MHz of 320 MHz", .c.width = NL80211_CHAN_WIDTH_320, .c.chan = &chan6g_1, .c.center_freq1 = 6105, .n = 8, .expect = 0, }, { .desc = "upper 160 MHz of 320 MHz", .c.width = NL80211_CHAN_WIDTH_320, .c.chan = &chan6g_61, .c.center_freq1 = 6105, .n = 8, .expect = 8, }, { .desc = "upper 160 MHz of 320 MHz, go to 40", .c.width = NL80211_CHAN_WIDTH_320, .c.chan = &chan6g_61, .c.center_freq1 = 6105, .n = 2, .expect = 8 + 4 + 2, }, { .desc = "secondary 80 above primary in 80+80 MHz", /* not really is valid? doesn't matter for the test */ .c.width = NL80211_CHAN_WIDTH_80P80, .c.chan = &chan6g_1, .c.center_freq1 = 5985, .c.center_freq2 = 6225, .n = 4, .expect = 0, }, { .desc = "secondary 80 below primary in 80+80 MHz", /* not really is valid? doesn't matter for the test */ .c.width = NL80211_CHAN_WIDTH_80P80, .c.chan = &chan6g_61, .c.center_freq1 = 6225, .c.center_freq2 = 5985, .n = 4, .expect = 4, }, { .desc = "secondary 80 below primary in 80+80 MHz, go to 20", /* not really is valid? doesn't matter for the test */ .c.width = NL80211_CHAN_WIDTH_80P80, .c.chan = &chan6g_61, .c.center_freq1 = 6225, .c.center_freq2 = 5985, .n = 1, .expect = 7, }, }; KUNIT_ARRAY_PARAM_DESC(subchan_offset, subchan_offset_cases, desc); static void subchan_offset(struct kunit *test) { const struct subchan_test_case *params = test->param_value; int offset; KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(¶ms->c), true); offset = ieee80211_calc_chandef_subchan_offset(¶ms->c, params->n); KUNIT_EXPECT_EQ(test, params->expect, offset); } static const struct psd_reorder_test_case { const char *desc; struct cfg80211_chan_def ap, used; struct ieee80211_parsed_tpe_psd psd, out; } psd_reorder_cases[] = { { .desc = "no changes, 320 MHz", .ap.width = NL80211_CHAN_WIDTH_320, .ap.chan = &chan6g_1, .ap.center_freq1 = 6105, .used.width = NL80211_CHAN_WIDTH_320, .used.chan = &chan6g_1, .used.center_freq1 = 6105, .psd.valid = true, .psd.count = 16, .psd.n = 8, .psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, .out.valid = true, .out.count = 16, .out.n = 8, .out.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, }, { .desc = "no changes, 320 MHz, 160 MHz used, n=0", .ap.width = NL80211_CHAN_WIDTH_320, .ap.chan = &chan6g_1, .ap.center_freq1 = 6105, .used.width = NL80211_CHAN_WIDTH_160, .used.chan = &chan6g_1, .used.center_freq1 = 6025, .psd.valid = true, .psd.count = 16, .psd.n = 0, .psd.power = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, .out.valid = true, .out.count = 8, .out.n = 0, .out.power = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, }, { .desc = "320 MHz, HE is 80, used 160, all lower", .ap.width = NL80211_CHAN_WIDTH_320, .ap.chan = &chan6g_1, .ap.center_freq1 = 6105, .used.width = NL80211_CHAN_WIDTH_160, .used.chan = &chan6g_1, .used.center_freq1 = 6025, .psd.valid = true, .psd.count = 16, .psd.n = 4, .psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, .out.valid = true, .out.count = 8, .out.n = 4, .out.power = { 0, 1, 2, 3, 4, 5, 6, 7, 127, 127, 127, 127, 127, 127, 127, 127}, }, { .desc = "320 MHz, HE is 80, used 160, all upper", /* * EHT: | | | | | | | | | | | | | | | | | * HE: | | | | | * used: | | | | | | | | | */ .ap.width = NL80211_CHAN_WIDTH_320, .ap.chan = &chan6g_61, .ap.center_freq1 = 6105, .used.width = NL80211_CHAN_WIDTH_160, .used.chan = &chan6g_61, .used.center_freq1 = 6185, .psd.valid = true, .psd.count = 16, .psd.n = 4, .psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, .out.valid = true, .out.count = 8, .out.n = 4, .out.power = { 12, 13, 14, 15, 0, 1, 2, 3, 127, 127, 127, 127, 127, 127, 127, 127}, }, { .desc = "320 MHz, HE is 80, used 160, split", /* * EHT: | | | | | | | | | | | | | | | | | * HE: | | | | | * used: | | | | | | | | | */ .ap.width = NL80211_CHAN_WIDTH_320, .ap.chan = &chan6g_33, .ap.center_freq1 = 6105, .used.width = NL80211_CHAN_WIDTH_160, .used.chan = &chan6g_33, .used.center_freq1 = 6185, .psd.valid = true, .psd.count = 16, .psd.n = 4, .psd.power = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, .out.valid = true, .out.count = 8, .out.n = 4, .out.power = { 0, 1, 2, 3, 12, 13, 14, 15, 127, 127, 127, 127, 127, 127, 127, 127}, }, }; KUNIT_ARRAY_PARAM_DESC(psd_reorder, psd_reorder_cases, desc); static void psd_reorder(struct kunit *test) { const struct psd_reorder_test_case *params = test->param_value; struct ieee80211_parsed_tpe_psd tmp = params->psd; KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(¶ms->ap), true); KUNIT_ASSERT_EQ(test, cfg80211_chandef_valid(¶ms->used), true); ieee80211_rearrange_tpe_psd(&tmp, ¶ms->ap, ¶ms->used); KUNIT_EXPECT_MEMEQ(test, &tmp, ¶ms->out, sizeof(tmp)); } static struct kunit_case tpe_test_cases[] = { KUNIT_CASE_PARAM(subchan_offset, subchan_offset_gen_params), KUNIT_CASE_PARAM(psd_reorder, psd_reorder_gen_params), {} }; static struct kunit_suite tpe = { .name = "mac80211-tpe", .test_cases = tpe_test_cases, }; kunit_test_suite(tpe);