From: Avinash Bhatt Date: Sun, 31 May 2026 10:53:08 +0000 (+0300) Subject: wifi: iwlwifi: mld: add KUnit tests for link grading X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a153825987be45a6a22fdf3bb4ae59109818c62b;p=thirdparty%2Flinux.git wifi: iwlwifi: mld: add KUnit tests for link grading Add tests for the link grading algorithm covering per-bandwidth grading tables, channel load calculation, 6 GHz RSSI adjustments including duplicated beacon and PSD/EIRP compensation, and puncturing penalty. Signed-off-by: Avinash Bhatt Link: https://patch.msgid.link/20260531135036.a4251e5665a0.I811b35680115e7de0ffd75b6b7a1c91ad361c97c@changeid Signed-off-by: Miri Korenblit --- diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 2b8b0196692ec..96e06940b34c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -3,6 +3,8 @@ * Copyright (C) 2024-2026 Intel Corporation */ +#include + #include "constants.h" #include "link.h" #include "iface.h" @@ -1032,6 +1034,9 @@ iwl_mld_get_dup_beacon_rssi_adjust(struct iwl_mld *mld, const struct cfg80211_bss_ies *beacon_ies; const struct element *elem; + KUNIT_STATIC_STUB_REDIRECT(iwl_mld_get_dup_beacon_rssi_adjust, + mld, link_conf); + /* Duplicated beacon feature is only specific to 6 GHz */ if (WARN_ONCE(link_conf->chanreq.oper.chan->band != NL80211_BAND_6GHZ, "Unexpected band %d\n", @@ -1109,6 +1114,9 @@ iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf) int bw_mhz, num_subchans; u8 bw_index; + KUNIT_STATIC_STUB_REDIRECT(iwl_mld_get_psd_eirp_rssi_adjust, + link_conf); + /* PSD/EIRP adjustment is only specific to 6 GHz */ if (WARN_ONCE(link_conf->chanreq.oper.chan->band != NL80211_BAND_6GHZ, "PSD/EIRP adjustment called for non-6 GHz band %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c index 69d222a8194c5..73c2b7b3c9de6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c @@ -13,24 +13,39 @@ #include "phy.h" #include "mlo.h" +struct link_grading_input { + u8 link_id; + const struct cfg80211_chan_def *chandef; + bool active; + s32 signal; + bool has_chan_util_elem; + u8 chan_util; + u8 chan_load_by_us; + s8 dup_beacon_adj; + s8 psd_eirp_adj; + u16 punctured; +}; + static const struct link_grading_test_case { const char *desc; - struct { - struct { - u8 link_id; - const struct cfg80211_chan_def *chandef; - bool active; - s32 signal; - bool has_chan_util_elem; - u8 chan_util; /* 0-255 , used only if has_chan_util_elem is true */ - u8 chan_load_by_us; /* 0-100, used only if active is true */; - } link; - } input; + struct link_grading_input link; unsigned int expected_grade; } link_grading_cases[] = { + /* Per-bandwidth grading table tests */ { - .desc = "channel util of 128 (50%)", - .input.link = { + .desc = "20 MHz grading table: -75 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_2ghz_20mhz, + .active = false, + .signal = -75, + }, + /* 137 * 0.7 (default 2.4GHz channel load 30%) */ + .expected_grade = 96, + }, + { + .desc = "20 MHz with channel util 128 (50%): -70 dBm", + .link = { .link_id = 0, .chandef = &chandef_2ghz_20mhz, .active = false, @@ -41,8 +56,8 @@ static const struct link_grading_test_case { .expected_grade = 86, }, { - .desc = "channel util of 180 (70%)", - .input.link = { + .desc = "20 MHz with channel util 180 (70%): -70 dBm", + .link = { .link_id = 0, .chandef = &chandef_2ghz_20mhz, .active = false, @@ -53,32 +68,222 @@ static const struct link_grading_test_case { .expected_grade = 51, }, { - .desc = "channel util of 180 (70%), channel load by us of 10%", - .input.link = { + .desc = "20 MHz active link with chan load by us 10%: -70 dBm", + .link = { .link_id = 0, .chandef = &chandef_2ghz_20mhz, + .active = true, .signal = -70, .has_chan_util_elem = true, .chan_util = 180, - .active = true, .chan_load_by_us = 10, }, .expected_grade = 67, }, - { - .desc = "no channel util element", - .input.link = { + { + .desc = "40 MHz grading table: -80 dBm", + .link = { .link_id = 0, - .chandef = &chandef_2ghz_20mhz, + .chandef = &chandef_5ghz_40mhz, + .active = false, + .signal = -80, + }, + /* 206 * 0.85 (default 5GHz channel load 15%) */ + .expected_grade = 175, + }, + { + .desc = "80 MHz grading table: -70 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_5ghz_80mhz, + .active = false, .signal = -70, - .active = true, }, - .expected_grade = 120, + /* 548 * 0.85 (default 5GHz channel load 15%) */ + .expected_grade = 466, + }, + { + .desc = "160 MHz grading table: -65 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_5ghz_160mhz, + .active = false, + .signal = -65, + }, + /* 1240 * 0.85 (default 5GHz channel load 15%) */ + .expected_grade = 1055, + }, + { + .desc = "320 MHz grading table: -60 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_320mhz, + .active = false, + .signal = -60, + }, + /* 3680 at -56 dBm (-60 + 4 dBm 6 GHz) */ + .expected_grade = 3680, + }, + /* 6 GHz RSSI adjustment integration tests */ + { + .desc = "6 GHz 160 MHz with fixed +4 dBm adjustment", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_160mhz, + .active = false, + .signal = -69, + }, + /* -69 + 4 dBm = -65, grade 1240 */ + .expected_grade = 1240, + }, + { + .desc = "6 GHz 80 MHz with fixed +4 dBm adjustment", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_80mhz, + .active = false, + .signal = -74, + }, + /* -74 + 4 dBm = -70, grade 548 */ + .expected_grade = 548, + }, + { + .desc = "6 GHz 40 MHz with fixed +4 dBm adjustment", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_40mhz, + .active = false, + .signal = -84, + }, + /* -84 + 4 dBm = -80, grade 206 */ + .expected_grade = 206, + }, + { + .desc = "6 GHz 20 MHz with fixed +4 dBm adjustment", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_20mhz, + .active = false, + .signal = -79, + }, + .expected_grade = 137, + }, + /* Duplicated beacon RSSI adjustment tests */ + { + .desc = "6 GHz 40 MHz dup beacon: -81 dBm + 3 dBm = -78 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_40mhz, + .active = false, + .signal = -81, + .dup_beacon_adj = 3, + }, + .expected_grade = 206, + }, + { + .desc = "6 GHz 80 MHz dup beacon: -73 dBm + 6 dBm = -67 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_80mhz, + .active = false, + .signal = -73, + .dup_beacon_adj = 6, + }, + .expected_grade = 620, + }, + { + .desc = "6 GHz 160 MHz dup beacon: -74 dBm + 9 dBm = -65 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_160mhz, + .active = false, + .signal = -74, + .dup_beacon_adj = 9, + }, + .expected_grade = 1240, + }, + { + .desc = "6 GHz 320 MHz dup beacon: -72 dBm + 12 dBm = -60 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_320mhz, + .active = false, + .signal = -72, + .dup_beacon_adj = 12, + }, + .expected_grade = 3296, + }, + /* PSD/EIRP RSSI adjustment tests */ + { + .desc = "6 GHz 80 MHz PSD/EIRP: -77 dBm + 3 dBm = -74 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_80mhz, + .active = false, + .signal = -77, + .psd_eirp_adj = 3, + }, + /* -77 + 3 dBm = -74, grade 412; fallback +4: -73 -> 548 */ + .expected_grade = 412, + }, + { + .desc = "6 GHz 160 MHz PSD/EIRP: -70 dBm + 3 dBm = -67 dBm", + .link = { + .link_id = 0, + .chandef = &chandef_6ghz_160mhz, + .active = false, + .signal = -70, + .psd_eirp_adj = 3, + }, + /* -70 + 3 dBm = -67, grade 1096; fallback +4: -66 -> 1240 */ + .expected_grade = 1096, + }, + /* Puncturing penalty tests */ + { + .desc = "80 MHz with 20 MHz punctured: 3 active subchannels", + .link = { + .link_id = 0, + .chandef = &chandef_5ghz_80mhz, + .active = false, + .signal = -70, + .punctured = 0x2, + }, + /* 548 * 0.85 (5GHz load) * 3/4 (puncturing) */ + .expected_grade = 349, + }, + { + .desc = "160 MHz with 40 MHz punctured: 6 active subchannels", + .link = { + .link_id = 0, + .chandef = &chandef_5ghz_160mhz, + .active = false, + .signal = -65, + .punctured = 0xC, + }, + /* 1240 * 0.85 (5GHz load) * 6/8 (puncturing) */ + .expected_grade = 791, }, }; KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc); +static s8 fake_dup_beacon_rssi_adjust(struct iwl_mld *mld, + struct ieee80211_bss_conf *link_conf) +{ + const struct link_grading_test_case *params = + kunit_get_current_test()->param_value; + + return params->link.dup_beacon_adj; +} + +static s8 fake_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf) +{ + const struct link_grading_test_case *params = + kunit_get_current_test()->param_value; + + return params->link.psd_eirp_adj; +} + static void setup_link(struct ieee80211_bss_conf *link) { struct kunit *test = kunit_get_current_test(); @@ -88,14 +293,14 @@ static void setup_link(struct ieee80211_bss_conf *link) KUNIT_ALLOC_AND_ASSERT(test, link->bss); - link->bss->signal = DBM_TO_MBM(test_param->input.link.signal); + link->bss->signal = DBM_TO_MBM(test_param->link.signal); - link->chanreq.oper = *test_param->input.link.chandef; + link->chanreq.oper = *test_param->link.chandef; - if (test_param->input.link.has_chan_util_elem) { + if (test_param->link.has_chan_util_elem) { struct cfg80211_bss_ies *ies; struct ieee80211_bss_load_elem bss_load = { - .channel_util = test_param->input.link.chan_util, + .channel_util = test_param->link.chan_util, }; struct element *elem = iwlmld_kunit_gen_element(WLAN_EID_QBSS_LOAD, @@ -110,7 +315,10 @@ static void setup_link(struct ieee80211_bss_conf *link) rcu_assign_pointer(link->bss->ies, ies); } - if (test_param->input.link.active) { + if (test_param->link.punctured) + link->chanreq.oper.punctured = test_param->link.punctured; + + if (test_param->link.active) { struct ieee80211_chanctx_conf *chan_ctx = wiphy_dereference(mld->wiphy, link->chanctx_conf); struct iwl_mld_phy *phy; @@ -119,7 +327,7 @@ static void setup_link(struct ieee80211_bss_conf *link) phy = iwl_mld_phy_from_mac80211(chan_ctx); - phy->channel_load_by_us = test_param->input.link.chan_load_by_us; + phy->channel_load_by_us = test_param->link.chan_load_by_us; } } @@ -131,12 +339,11 @@ static void test_link_grading(struct kunit *test) struct ieee80211_vif *vif; struct ieee80211_bss_conf *link; unsigned int actual_grade; - /* Extract test case parameters */ - u8 link_id = test_param->input.link.link_id; - bool active = test_param->input.link.active; + u8 link_id = test_param->link.link_id; + bool active = test_param->link.active; u16 valid_links; struct iwl_mld_kunit_link assoc_link = { - .chandef = test_param->input.link.chandef, + .chandef = test_param->link.chandef, }; /* If the link is not active, use a different link as the assoc link */ @@ -150,6 +357,11 @@ static void test_link_grading(struct kunit *test) vif = iwlmld_kunit_setup_mlo_assoc(valid_links, &assoc_link); + kunit_activate_static_stub(test, iwl_mld_get_dup_beacon_rssi_adjust, + fake_dup_beacon_rssi_adjust); + kunit_activate_static_stub(test, iwl_mld_get_psd_eirp_rssi_adjust, + fake_psd_eirp_rssi_adjust); + wiphy_lock(mld->wiphy); link = wiphy_dereference(mld->wiphy, vif->link_conf[link_id]); KUNIT_ASSERT_NOT_NULL(test, link);