#include "link.h"
#include "iface.h"
#include "phy.h"
+#include "mlo.h"
static const struct link_grading_test_case {
const char *desc;
};
kunit_test_suite(link_selection);
+
+static const struct channel_load_case {
+ const char *desc;
+ bool low_latency_vif;
+ u32 chan_load_not_by_us;
+ enum nl80211_chan_width bw_a;
+ enum nl80211_chan_width bw_b;
+ bool primary_link_active;
+ bool expected_result;
+} channel_load_cases[] = {
+ {
+ .desc = "Unequal bandwidth, primary link inactive, EMLSR not allowed",
+ .low_latency_vif = false,
+ .primary_link_active = false,
+ .bw_a = NL80211_CHAN_WIDTH_40,
+ .bw_b = NL80211_CHAN_WIDTH_20,
+ .expected_result = false,
+ },
+ {
+ .desc = "Equal bandwidths, sufficient channel load, EMLSR allowed",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 11,
+ .bw_a = NL80211_CHAN_WIDTH_40,
+ .bw_b = NL80211_CHAN_WIDTH_40,
+ .expected_result = true,
+ },
+ {
+ .desc = "Equal bandwidths, insufficient channel load, EMLSR not allowed",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 6,
+ .bw_a = NL80211_CHAN_WIDTH_80,
+ .bw_b = NL80211_CHAN_WIDTH_80,
+ .expected_result = false,
+ },
+ {
+ .desc = "Low latency VIF, sufficient channel load, EMLSR allowed",
+ .low_latency_vif = true,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 6,
+ .bw_a = NL80211_CHAN_WIDTH_160,
+ .bw_b = NL80211_CHAN_WIDTH_160,
+ .expected_result = true,
+ },
+ {
+ .desc = "Different bandwidths (2x ratio), primary link load permits EMLSR",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 30,
+ .bw_a = NL80211_CHAN_WIDTH_40,
+ .bw_b = NL80211_CHAN_WIDTH_20,
+ .expected_result = true,
+ },
+ {
+ .desc = "Different bandwidths (4x ratio), primary link load permits EMLSR",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 45,
+ .bw_a = NL80211_CHAN_WIDTH_80,
+ .bw_b = NL80211_CHAN_WIDTH_20,
+ .expected_result = true,
+ },
+ {
+ .desc = "Different bandwidths (16x ratio), primary link load insufficient",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 45,
+ .bw_a = NL80211_CHAN_WIDTH_320,
+ .bw_b = NL80211_CHAN_WIDTH_20,
+ .expected_result = false,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(channel_load, channel_load_cases, desc);
+
+static void test_iwl_mld_channel_load_allows_emlsr(struct kunit *test)
+{
+ const struct channel_load_case *params = test->param_value;
+ struct iwl_mld *mld = test->priv;
+ struct ieee80211_vif *vif;
+ struct cfg80211_chan_def chandef_a, chandef_b;
+ struct iwl_mld_link_sel_data a = {.chandef = &chandef_a,
+ .link_id = 4};
+ struct iwl_mld_link_sel_data b = {.chandef = &chandef_b,
+ .link_id = 5};
+ struct iwl_mld_kunit_link assoc_link = {
+ .id = params->primary_link_active ? a.link_id : b.link_id,
+ .bandwidth = params->primary_link_active ? params->bw_a : params->bw_b,
+ };
+ bool result;
+
+ vif = iwlmld_kunit_setup_mlo_assoc(BIT(a.link_id) | BIT(b.link_id),
+ &assoc_link);
+
+ chandef_a.width = params->bw_a;
+ chandef_b.width = params->bw_b;
+
+ if (params->low_latency_vif)
+ iwl_mld_vif_from_mac80211(vif)->low_latency_causes = 1;
+
+ wiphy_lock(mld->wiphy);
+
+ /* Simulate channel load */
+ if (params->primary_link_active) {
+ struct iwl_mld_phy *phy =
+ iwlmld_kunit_get_phy_of_link(vif, a.link_id);
+
+ phy->avg_channel_load_not_by_us = params->chan_load_not_by_us;
+ }
+
+ result = iwl_mld_channel_load_allows_emlsr(mld, vif, &a, &b);
+
+ wiphy_unlock(mld->wiphy);
+
+ KUNIT_EXPECT_EQ(test, result, params->expected_result);
+}
+
+static struct kunit_case channel_load_criteria_test_cases[] = {
+ KUNIT_CASE_PARAM(test_iwl_mld_channel_load_allows_emlsr, channel_load_gen_params),
+ {}
+};
+
+static struct kunit_suite channel_load_criteria_tests = {
+ .name = "iwlmld_channel_load_allows_emlsr",
+ .test_cases = channel_load_criteria_test_cases,
+ .init = iwlmld_kunit_test_init,
+};
+
+kunit_test_suite(channel_load_criteria_tests);