| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * KUnit tests for TPE element handling |
| * |
| * Copyright (C) 2024 Intel Corporation |
| */ |
| #include <kunit/test.h> |
| #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); |