// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * KUnit tests for channel helper functions
+ * KUnit tests for link helper functions
*
- * Copyright (C) 2024-2025 Intel Corporation
+ * Copyright (C) 2024-2026 Intel Corporation
*/
#include <kunit/static_stub.h>
/* TODO: add test cases for esr and check */
}
+struct dup_beacon_test_case {
+ const char *desc;
+ enum nl80211_chan_width bandwidth;
+ bool has_he_oper;
+ bool dup_beacon_bit;
+ s8 expected_adj;
+};
+
+static const struct dup_beacon_test_case dup_beacon_cases[] = {
+ {
+ .desc = "20 MHz - no duplication",
+ .bandwidth = NL80211_CHAN_WIDTH_20,
+ .has_he_oper = true,
+ .dup_beacon_bit = true,
+ .expected_adj = 0,
+ },
+ {
+ .desc = "40 MHz with duplication - 3 dB",
+ .bandwidth = NL80211_CHAN_WIDTH_40,
+ .has_he_oper = true,
+ .dup_beacon_bit = true,
+ .expected_adj = 3,
+ },
+ {
+ .desc = "80 MHz with duplication - 6 dB",
+ .bandwidth = NL80211_CHAN_WIDTH_80,
+ .has_he_oper = true,
+ .dup_beacon_bit = true,
+ .expected_adj = 6,
+ },
+ {
+ .desc = "160 MHz with duplication - 9 dB",
+ .bandwidth = NL80211_CHAN_WIDTH_160,
+ .has_he_oper = true,
+ .dup_beacon_bit = true,
+ .expected_adj = 9,
+ },
+ {
+ .desc = "320 MHz with duplication - 12 dB",
+ .bandwidth = NL80211_CHAN_WIDTH_320,
+ .has_he_oper = true,
+ .dup_beacon_bit = true,
+ .expected_adj = 12,
+ },
+ {
+ .desc = "80 MHz without dup bit - no adjustment",
+ .bandwidth = NL80211_CHAN_WIDTH_80,
+ .has_he_oper = true,
+ .dup_beacon_bit = false,
+ .expected_adj = 0,
+ },
+ {
+ .desc = "80 MHz without HE oper - no adjustment",
+ .bandwidth = NL80211_CHAN_WIDTH_80,
+ .has_he_oper = false,
+ .dup_beacon_bit = true,
+ .expected_adj = 0,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(test_dup_beacon_rssi_adjust, dup_beacon_cases, desc);
+
+static void test_dup_beacon_rssi_adjust(struct kunit *test)
+{
+ const struct dup_beacon_test_case *params = test->param_value;
+ struct iwl_mld *mld = test->priv;
+ struct ieee80211_bss_conf *link_conf;
+ struct cfg80211_bss *bss;
+ struct element *he_elem = NULL;
+ s8 result;
+
+ KUNIT_ALLOC_AND_ASSERT(test, link_conf);
+ KUNIT_ALLOC_AND_ASSERT(test, bss);
+ link_conf->bss = bss;
+
+ link_conf->chanreq.oper.chan = &chan_6ghz;
+ link_conf->chanreq.oper.width = params->bandwidth;
+
+ if (params->has_he_oper) {
+ struct ieee80211_he_6ghz_oper he_6ghz = {};
+
+ if (params->dup_beacon_bit)
+ he_6ghz.control =
+ IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON;
+ he_elem = iwlmld_kunit_create_he_6ghz_oper(he_6ghz);
+ }
+
+ rcu_assign_pointer(bss->beacon_ies,
+ iwlmld_kunit_create_bss_ies(he_elem));
+
+ guard(wiphy)(mld->wiphy);
+ result = iwl_mld_get_dup_beacon_rssi_adjust(mld, link_conf);
+
+ KUNIT_EXPECT_EQ(test, result, params->expected_adj);
+}
+
static struct kunit_case link_cases[] = {
KUNIT_CASE_PARAM(test_missed_beacon, test_missed_beacon_gen_params),
+ KUNIT_CASE_PARAM(test_dup_beacon_rssi_adjust,
+ test_dup_beacon_rssi_adjust_gen_params),
{},
};
return vif;
}
+struct element *
+iwlmld_kunit_create_he_6ghz_oper(struct ieee80211_he_6ghz_oper he_6ghz)
+{
+ struct kunit *test = kunit_get_current_test();
+ u8 *data;
+ size_t data_len;
+ size_t offset = 0;
+ __le32 he_oper_params;
+ __le16 he_mcs_nss_set = 0;
+
+ /* Build HE Operation IE with 6 GHz info using raw buffer.
+ * Cannot use struct embedding because ieee80211_he_operation
+ * has a flexible array member (optional[]).
+ *
+ * Layout:
+ * 1 byte: ext_id (WLAN_EID_EXT_HE_OPERATION)
+ * he_oper_params: he_oper_params (from ieee80211_he_operation)
+ * he_mcs_nss_set: he_mcs_nss_set (from ieee80211_he_operation)
+ * he_6ghz: ieee80211_he_6ghz_oper (goes into optional[])
+ */
+ data_len = 1 + sizeof(he_oper_params) + sizeof(he_mcs_nss_set) +
+ sizeof(struct ieee80211_he_6ghz_oper);
+
+ data = kunit_kzalloc(test, data_len, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, data);
+
+ data[offset++] = WLAN_EID_EXT_HE_OPERATION;
+
+ he_oper_params = cpu_to_le32(IEEE80211_HE_OPERATION_6GHZ_OP_INFO);
+ memcpy(&data[offset], &he_oper_params, sizeof(he_oper_params));
+ offset += sizeof(he_oper_params);
+
+ memcpy(&data[offset], &he_mcs_nss_set, sizeof(he_mcs_nss_set));
+ offset += sizeof(he_mcs_nss_set);
+
+ memcpy(&data[offset], &he_6ghz, sizeof(he_6ghz));
+
+ return iwlmld_kunit_gen_element(WLAN_EID_EXTENSION, data, data_len);
+}
+
+struct cfg80211_bss_ies *iwlmld_kunit_create_bss_ies(struct element *elem)
+{
+ struct kunit *test = kunit_get_current_test();
+ struct cfg80211_bss_ies *ies;
+ size_t ies_len = 0;
+
+ if (elem)
+ ies_len = sizeof(*elem) + elem->datalen;
+
+ ies = kunit_kzalloc(test, sizeof(*ies) + ies_len, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, ies);
+
+ ies->len = ies_len;
+
+ if (elem)
+ memcpy(ies->data, elem, ies_len);
+
+ return ies;
+}
+
struct element *iwlmld_kunit_gen_element(u8 id, const void *data, size_t len)
{
struct kunit *test = kunit_get_current_test();