1d1e879ecSMiri Korenblit // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2d1e879ecSMiri Korenblit /*
3d1e879ecSMiri Korenblit * KUnit tests for channel helper functions
4d1e879ecSMiri Korenblit *
5d1e879ecSMiri Korenblit * Copyright (C) 2024-2025 Intel Corporation
6d1e879ecSMiri Korenblit */
7d1e879ecSMiri Korenblit #include <kunit/test.h>
8d1e879ecSMiri Korenblit #include <kunit/test-bug.h>
9d1e879ecSMiri Korenblit
10d1e879ecSMiri Korenblit #include "utils.h"
11d1e879ecSMiri Korenblit
12d1e879ecSMiri Korenblit #include <linux/device.h>
13d1e879ecSMiri Korenblit
14d1e879ecSMiri Korenblit #include "fw/api/scan.h"
15d1e879ecSMiri Korenblit #include "fw/api/mac-cfg.h"
16d1e879ecSMiri Korenblit #include "iwl-trans.h"
17d1e879ecSMiri Korenblit #include "mld.h"
18d1e879ecSMiri Korenblit #include "iface.h"
19d1e879ecSMiri Korenblit #include "link.h"
20d1e879ecSMiri Korenblit #include "phy.h"
21d1e879ecSMiri Korenblit #include "sta.h"
22d1e879ecSMiri Korenblit
iwlmld_kunit_test_init(struct kunit * test)23d1e879ecSMiri Korenblit int iwlmld_kunit_test_init(struct kunit *test)
24d1e879ecSMiri Korenblit {
25d1e879ecSMiri Korenblit struct iwl_mld *mld;
26d1e879ecSMiri Korenblit struct iwl_trans *trans;
27d1e879ecSMiri Korenblit const struct iwl_cfg *cfg;
28d1e879ecSMiri Korenblit struct iwl_fw *fw;
29d1e879ecSMiri Korenblit struct ieee80211_hw *hw;
30d1e879ecSMiri Korenblit
31d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, trans);
32d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, trans->dev);
33d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, cfg);
34d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, fw);
35d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, hw);
36d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, hw->wiphy);
37d1e879ecSMiri Korenblit
38d1e879ecSMiri Korenblit mutex_init(&hw->wiphy->mtx);
39d1e879ecSMiri Korenblit
40d1e879ecSMiri Korenblit /* Allocate and initialize the mld structure */
41d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, mld);
42d1e879ecSMiri Korenblit iwl_construct_mld(mld, trans, cfg, fw, hw, NULL);
43d1e879ecSMiri Korenblit
44d1e879ecSMiri Korenblit fw->ucode_capa.num_stations = IWL_STATION_COUNT_MAX;
45d1e879ecSMiri Korenblit fw->ucode_capa.num_links = IWL_FW_MAX_LINK_ID + 1;
46d1e879ecSMiri Korenblit
47d1e879ecSMiri Korenblit mld->fwrt.trans = trans;
48d1e879ecSMiri Korenblit mld->fwrt.fw = fw;
49d1e879ecSMiri Korenblit mld->fwrt.dev = trans->dev;
50d1e879ecSMiri Korenblit
51d1e879ecSMiri Korenblit /* TODO: add priv_size to hw allocation and setup hw->priv to enable
52d1e879ecSMiri Korenblit * testing mac80211 callbacks
53d1e879ecSMiri Korenblit */
54d1e879ecSMiri Korenblit
55d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, mld->nvm_data);
56d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, mld->scan.cmd,
57d1e879ecSMiri Korenblit sizeof(struct iwl_scan_req_umac_v17));
58d1e879ecSMiri Korenblit mld->scan.cmd_size = sizeof(struct iwl_scan_req_umac_v17);
59d1e879ecSMiri Korenblit
60d1e879ecSMiri Korenblit /* This is not the state at the end of the regular opmode_start,
61d1e879ecSMiri Korenblit * but it is more common to need it. Explicitly undo this if needed.
62d1e879ecSMiri Korenblit */
63d1e879ecSMiri Korenblit mld->trans->state = IWL_TRANS_FW_ALIVE;
64d1e879ecSMiri Korenblit mld->fw_status.running = true;
65d1e879ecSMiri Korenblit
66d1e879ecSMiri Korenblit /* Avoid passing mld struct around */
67d1e879ecSMiri Korenblit test->priv = mld;
68d1e879ecSMiri Korenblit return 0;
69d1e879ecSMiri Korenblit }
70d1e879ecSMiri Korenblit
IWL_MLD_ALLOC_FN(link,bss_conf)71d1e879ecSMiri Korenblit IWL_MLD_ALLOC_FN(link, bss_conf)
72d1e879ecSMiri Korenblit
73d1e879ecSMiri Korenblit static void iwlmld_kunit_init_link(struct ieee80211_vif *vif,
74d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link,
75d1e879ecSMiri Korenblit struct iwl_mld_link *mld_link, int link_id)
76d1e879ecSMiri Korenblit {
77d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
78d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
79d1e879ecSMiri Korenblit struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
80d1e879ecSMiri Korenblit int ret;
81d1e879ecSMiri Korenblit
82d1e879ecSMiri Korenblit /* setup mac80211 link */
83d1e879ecSMiri Korenblit rcu_assign_pointer(vif->link_conf[link_id], link);
84d1e879ecSMiri Korenblit link->link_id = link_id;
85d1e879ecSMiri Korenblit link->vif = vif;
86d1e879ecSMiri Korenblit link->beacon_int = 100;
87d1e879ecSMiri Korenblit link->dtim_period = 3;
88d1e879ecSMiri Korenblit link->qos = true;
89d1e879ecSMiri Korenblit
90d1e879ecSMiri Korenblit /* and mld_link */
91d1e879ecSMiri Korenblit ret = iwl_mld_allocate_link_fw_id(mld, &mld_link->fw_id, link);
92d1e879ecSMiri Korenblit KUNIT_ASSERT_EQ(test, ret, 0);
93d1e879ecSMiri Korenblit rcu_assign_pointer(mld_vif->link[link_id], mld_link);
94d1e879ecSMiri Korenblit rcu_assign_pointer(vif->link_conf[link_id], link);
95d1e879ecSMiri Korenblit }
96d1e879ecSMiri Korenblit
IWL_MLD_ALLOC_FN(vif,vif)97d1e879ecSMiri Korenblit IWL_MLD_ALLOC_FN(vif, vif)
98d1e879ecSMiri Korenblit
99d1e879ecSMiri Korenblit /* Helper function to add and initialize a VIF for KUnit tests */
100d1e879ecSMiri Korenblit struct ieee80211_vif *iwlmld_kunit_add_vif(bool mlo, enum nl80211_iftype type)
101d1e879ecSMiri Korenblit {
102d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
103d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
104d1e879ecSMiri Korenblit struct ieee80211_vif *vif;
105d1e879ecSMiri Korenblit struct iwl_mld_vif *mld_vif;
106d1e879ecSMiri Korenblit int ret;
107d1e879ecSMiri Korenblit
108d1e879ecSMiri Korenblit /* TODO: support more types */
109d1e879ecSMiri Korenblit KUNIT_ASSERT_EQ(test, type, NL80211_IFTYPE_STATION);
110d1e879ecSMiri Korenblit
111d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, vif,
112d1e879ecSMiri Korenblit sizeof(*vif) + sizeof(*mld_vif));
113d1e879ecSMiri Korenblit
114d1e879ecSMiri Korenblit vif->type = type;
115d1e879ecSMiri Korenblit mld_vif = iwl_mld_vif_from_mac80211(vif);
116d1e879ecSMiri Korenblit mld_vif->mld = mld;
117d1e879ecSMiri Korenblit
118d1e879ecSMiri Korenblit ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
119d1e879ecSMiri Korenblit KUNIT_ASSERT_EQ(test, ret, 0);
120d1e879ecSMiri Korenblit
121d1e879ecSMiri Korenblit /* TODO: revisit (task=EHT) */
122d1e879ecSMiri Korenblit if (mlo)
123d1e879ecSMiri Korenblit return vif;
124d1e879ecSMiri Korenblit
125d1e879ecSMiri Korenblit /* Initialize the default link */
126d1e879ecSMiri Korenblit iwlmld_kunit_init_link(vif, &vif->bss_conf, &mld_vif->deflink, 0);
127d1e879ecSMiri Korenblit
128d1e879ecSMiri Korenblit return vif;
129d1e879ecSMiri Korenblit }
130d1e879ecSMiri Korenblit
131d1e879ecSMiri Korenblit /* Use only for MLO vif */
132d1e879ecSMiri Korenblit struct ieee80211_bss_conf *
iwlmld_kunit_add_link(struct ieee80211_vif * vif,int link_id)133d1e879ecSMiri Korenblit iwlmld_kunit_add_link(struct ieee80211_vif *vif, int link_id)
134d1e879ecSMiri Korenblit {
135d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
136d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link;
137d1e879ecSMiri Korenblit struct iwl_mld_link *mld_link;
138d1e879ecSMiri Korenblit
139d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, link);
140d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, mld_link);
141d1e879ecSMiri Korenblit
142d1e879ecSMiri Korenblit iwlmld_kunit_init_link(vif, link, mld_link, link_id);
143d1e879ecSMiri Korenblit vif->valid_links |= BIT(link_id);
144d1e879ecSMiri Korenblit
145d1e879ecSMiri Korenblit return link;
146d1e879ecSMiri Korenblit }
147d1e879ecSMiri Korenblit
148d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *
iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def * def)149d1e879ecSMiri Korenblit iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def *def)
150d1e879ecSMiri Korenblit {
151d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
152d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
153d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *ctx;
154d1e879ecSMiri Korenblit struct iwl_mld_phy *phy;
155d1e879ecSMiri Korenblit int fw_id;
156d1e879ecSMiri Korenblit
157d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, ctx, sizeof(*ctx) + sizeof(*phy));
158d1e879ecSMiri Korenblit
159d1e879ecSMiri Korenblit /* Setup the chanctx conf */
160d1e879ecSMiri Korenblit ctx->def = *def;
161d1e879ecSMiri Korenblit ctx->min_def = *def;
162d1e879ecSMiri Korenblit ctx->ap = *def;
163d1e879ecSMiri Korenblit
164d1e879ecSMiri Korenblit /* and the iwl_mld_phy */
165d1e879ecSMiri Korenblit phy = iwl_mld_phy_from_mac80211(ctx);
166d1e879ecSMiri Korenblit
167d1e879ecSMiri Korenblit fw_id = iwl_mld_allocate_fw_phy_id(mld);
168d1e879ecSMiri Korenblit KUNIT_ASSERT_GE(test, fw_id, 0);
169d1e879ecSMiri Korenblit
170d1e879ecSMiri Korenblit phy->fw_id = fw_id;
171e8670620SMiri Korenblit phy->mld = mld;
172fd04fbeeSJohannes Berg phy->chandef = *def;
173d1e879ecSMiri Korenblit
174d1e879ecSMiri Korenblit return ctx;
175d1e879ecSMiri Korenblit }
176d1e879ecSMiri Korenblit
iwlmld_kunit_assign_chanctx_to_link(struct ieee80211_vif * vif,struct ieee80211_bss_conf * link,struct ieee80211_chanctx_conf * ctx)177d1e879ecSMiri Korenblit void iwlmld_kunit_assign_chanctx_to_link(struct ieee80211_vif *vif,
178d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link,
179d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *ctx)
180d1e879ecSMiri Korenblit {
181d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
182d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
183d1e879ecSMiri Korenblit struct iwl_mld_link *mld_link;
184d1e879ecSMiri Korenblit
185d1e879ecSMiri Korenblit KUNIT_EXPECT_NULL(test, rcu_access_pointer(link->chanctx_conf));
186d1e879ecSMiri Korenblit rcu_assign_pointer(link->chanctx_conf, ctx);
187d1e879ecSMiri Korenblit
188d1e879ecSMiri Korenblit lockdep_assert_wiphy(mld->wiphy);
189d1e879ecSMiri Korenblit
190d1e879ecSMiri Korenblit mld_link = iwl_mld_link_from_mac80211(link);
191d1e879ecSMiri Korenblit
192d1e879ecSMiri Korenblit KUNIT_EXPECT_NULL(test, rcu_access_pointer(mld_link->chan_ctx));
193d1e879ecSMiri Korenblit KUNIT_EXPECT_FALSE(test, mld_link->active);
194d1e879ecSMiri Korenblit
195d1e879ecSMiri Korenblit rcu_assign_pointer(mld_link->chan_ctx, ctx);
196d1e879ecSMiri Korenblit mld_link->active = true;
197d1e879ecSMiri Korenblit
198d1e879ecSMiri Korenblit if (ieee80211_vif_is_mld(vif))
199d1e879ecSMiri Korenblit vif->active_links |= BIT(link->link_id);
200d1e879ecSMiri Korenblit }
201d1e879ecSMiri Korenblit
IWL_MLD_ALLOC_FN(link_sta,link_sta)202d1e879ecSMiri Korenblit IWL_MLD_ALLOC_FN(link_sta, link_sta)
203d1e879ecSMiri Korenblit
204d1e879ecSMiri Korenblit static void iwlmld_kunit_add_link_sta(struct ieee80211_sta *sta,
205d1e879ecSMiri Korenblit struct ieee80211_link_sta *link_sta,
206d1e879ecSMiri Korenblit struct iwl_mld_link_sta *mld_link_sta,
207d1e879ecSMiri Korenblit u8 link_id)
208d1e879ecSMiri Korenblit {
209d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
210d1e879ecSMiri Korenblit struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
211d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
212d1e879ecSMiri Korenblit u8 fw_id;
213d1e879ecSMiri Korenblit int ret;
214d1e879ecSMiri Korenblit
215d1e879ecSMiri Korenblit /* initialize mac80211's link_sta */
216d1e879ecSMiri Korenblit link_sta->link_id = link_id;
217d1e879ecSMiri Korenblit rcu_assign_pointer(sta->link[link_id], link_sta);
218d1e879ecSMiri Korenblit
219d1e879ecSMiri Korenblit link_sta->sta = sta;
220d1e879ecSMiri Korenblit
221d1e879ecSMiri Korenblit /* and the iwl_mld_link_sta */
222d1e879ecSMiri Korenblit ret = iwl_mld_allocate_link_sta_fw_id(mld, &fw_id, link_sta);
223d1e879ecSMiri Korenblit KUNIT_ASSERT_EQ(test, ret, 0);
224d1e879ecSMiri Korenblit mld_link_sta->fw_id = fw_id;
225d1e879ecSMiri Korenblit
226d1e879ecSMiri Korenblit rcu_assign_pointer(mld_sta->link[link_id], mld_link_sta);
227d1e879ecSMiri Korenblit }
228d1e879ecSMiri Korenblit
229d1e879ecSMiri Korenblit static struct ieee80211_link_sta *
iwlmld_kunit_alloc_link_sta(struct ieee80211_sta * sta,int link_id)230d1e879ecSMiri Korenblit iwlmld_kunit_alloc_link_sta(struct ieee80211_sta *sta, int link_id)
231d1e879ecSMiri Korenblit {
232d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
233d1e879ecSMiri Korenblit struct ieee80211_link_sta *link_sta;
234d1e879ecSMiri Korenblit struct iwl_mld_link_sta *mld_link_sta;
235d1e879ecSMiri Korenblit
236d1e879ecSMiri Korenblit /* Only valid for MLO */
237d1e879ecSMiri Korenblit KUNIT_ASSERT_TRUE(test, sta->valid_links);
238d1e879ecSMiri Korenblit
239d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, link_sta);
240d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT(test, mld_link_sta);
241d1e879ecSMiri Korenblit
242d1e879ecSMiri Korenblit iwlmld_kunit_add_link_sta(sta, link_sta, mld_link_sta, link_id);
243d1e879ecSMiri Korenblit
244d1e879ecSMiri Korenblit sta->valid_links |= BIT(link_id);
245d1e879ecSMiri Korenblit
246d1e879ecSMiri Korenblit return link_sta;
247d1e879ecSMiri Korenblit }
248d1e879ecSMiri Korenblit
249d1e879ecSMiri Korenblit /* Allocate and initialize a STA with the first link_sta */
250d1e879ecSMiri Korenblit static struct ieee80211_sta *
iwlmld_kunit_add_sta(struct ieee80211_vif * vif,int link_id)251d1e879ecSMiri Korenblit iwlmld_kunit_add_sta(struct ieee80211_vif *vif, int link_id)
252d1e879ecSMiri Korenblit {
253d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
254d1e879ecSMiri Korenblit struct ieee80211_sta *sta;
255d1e879ecSMiri Korenblit struct iwl_mld_sta *mld_sta;
256d1e879ecSMiri Korenblit
257d1e879ecSMiri Korenblit /* Allocate memory for ieee80211_sta with embedded iwl_mld_sta */
258d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, sta, sizeof(*sta) + sizeof(*mld_sta));
259d1e879ecSMiri Korenblit
260d1e879ecSMiri Korenblit /* TODO: allocate and initialize the TXQs ? */
261d1e879ecSMiri Korenblit
262d1e879ecSMiri Korenblit mld_sta = iwl_mld_sta_from_mac80211(sta);
263d1e879ecSMiri Korenblit mld_sta->vif = vif;
264d1e879ecSMiri Korenblit mld_sta->mld = test->priv;
265d1e879ecSMiri Korenblit
266d1e879ecSMiri Korenblit /* TODO: adjust for internal stations */
267d1e879ecSMiri Korenblit mld_sta->sta_type = STATION_TYPE_PEER;
268d1e879ecSMiri Korenblit
269d1e879ecSMiri Korenblit if (link_id >= 0) {
270d1e879ecSMiri Korenblit iwlmld_kunit_add_link_sta(sta, &sta->deflink,
271d1e879ecSMiri Korenblit &mld_sta->deflink, link_id);
272d1e879ecSMiri Korenblit sta->valid_links = BIT(link_id);
273d1e879ecSMiri Korenblit } else {
274d1e879ecSMiri Korenblit iwlmld_kunit_add_link_sta(sta, &sta->deflink,
275d1e879ecSMiri Korenblit &mld_sta->deflink, 0);
276d1e879ecSMiri Korenblit }
277d1e879ecSMiri Korenblit return sta;
278d1e879ecSMiri Korenblit }
279d1e879ecSMiri Korenblit
280d1e879ecSMiri Korenblit /* Move s STA to a state */
iwlmld_kunit_move_sta_state(struct ieee80211_vif * vif,struct ieee80211_sta * sta,enum ieee80211_sta_state state)281d1e879ecSMiri Korenblit static void iwlmld_kunit_move_sta_state(struct ieee80211_vif *vif,
282d1e879ecSMiri Korenblit struct ieee80211_sta *sta,
283d1e879ecSMiri Korenblit enum ieee80211_sta_state state)
284d1e879ecSMiri Korenblit {
285d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
286d1e879ecSMiri Korenblit struct iwl_mld_sta *mld_sta;
287d1e879ecSMiri Korenblit struct iwl_mld_vif *mld_vif;
288d1e879ecSMiri Korenblit
289d1e879ecSMiri Korenblit /* The sta will be removed automatically at the end of the test */
290d1e879ecSMiri Korenblit KUNIT_ASSERT_NE(test, state, IEEE80211_STA_NOTEXIST);
291d1e879ecSMiri Korenblit
292d1e879ecSMiri Korenblit mld_sta = iwl_mld_sta_from_mac80211(sta);
293d1e879ecSMiri Korenblit mld_sta->sta_state = state;
294d1e879ecSMiri Korenblit
295d1e879ecSMiri Korenblit mld_vif = iwl_mld_vif_from_mac80211(mld_sta->vif);
296d1e879ecSMiri Korenblit mld_vif->authorized = state == IEEE80211_STA_AUTHORIZED;
297d1e879ecSMiri Korenblit
298d1e879ecSMiri Korenblit if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
299d1e879ecSMiri Korenblit mld_vif->ap_sta = sta;
300d1e879ecSMiri Korenblit }
301d1e879ecSMiri Korenblit
iwlmld_kunit_setup_sta(struct ieee80211_vif * vif,enum ieee80211_sta_state state,int link_id)302d1e879ecSMiri Korenblit struct ieee80211_sta *iwlmld_kunit_setup_sta(struct ieee80211_vif *vif,
303d1e879ecSMiri Korenblit enum ieee80211_sta_state state,
304d1e879ecSMiri Korenblit int link_id)
305d1e879ecSMiri Korenblit {
306d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
307d1e879ecSMiri Korenblit struct ieee80211_sta *sta;
308d1e879ecSMiri Korenblit
309d1e879ecSMiri Korenblit /* The sta will be removed automatically at the end of the test */
310d1e879ecSMiri Korenblit KUNIT_ASSERT_NE(test, state, IEEE80211_STA_NOTEXIST);
311d1e879ecSMiri Korenblit
312d1e879ecSMiri Korenblit /* First - allocate and init the STA */
313d1e879ecSMiri Korenblit sta = iwlmld_kunit_add_sta(vif, link_id);
314d1e879ecSMiri Korenblit
315d1e879ecSMiri Korenblit /* Now move it all the way to the wanted state */
316d1e879ecSMiri Korenblit for (enum ieee80211_sta_state _state = IEEE80211_STA_NONE;
317d1e879ecSMiri Korenblit _state <= state; _state++)
318d1e879ecSMiri Korenblit iwlmld_kunit_move_sta_state(vif, sta, state);
319d1e879ecSMiri Korenblit
320d1e879ecSMiri Korenblit return sta;
321d1e879ecSMiri Korenblit }
322d1e879ecSMiri Korenblit
iwlmld_kunit_set_vif_associated(struct ieee80211_vif * vif)323d1e879ecSMiri Korenblit static void iwlmld_kunit_set_vif_associated(struct ieee80211_vif *vif)
324d1e879ecSMiri Korenblit {
325d1e879ecSMiri Korenblit /* TODO: setup chanreq */
326d1e879ecSMiri Korenblit /* TODO setup capabilities */
327d1e879ecSMiri Korenblit
328d1e879ecSMiri Korenblit vif->cfg.assoc = 1;
329d1e879ecSMiri Korenblit }
330d1e879ecSMiri Korenblit
331d1e879ecSMiri Korenblit static struct ieee80211_vif *
iwlmld_kunit_setup_assoc(bool mlo,struct iwl_mld_kunit_link * assoc_link)332de5ca699SMiri Korenblit iwlmld_kunit_setup_assoc(bool mlo, struct iwl_mld_kunit_link *assoc_link)
333d1e879ecSMiri Korenblit {
334d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
335d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
336d1e879ecSMiri Korenblit struct ieee80211_vif *vif;
337d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link;
338d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *chan_ctx;
339d1e879ecSMiri Korenblit
340de5ca699SMiri Korenblit KUNIT_ASSERT_TRUE(test, mlo || assoc_link->id == 0);
341d1e879ecSMiri Korenblit
342d1e879ecSMiri Korenblit vif = iwlmld_kunit_add_vif(mlo, NL80211_IFTYPE_STATION);
343d1e879ecSMiri Korenblit
344d1e879ecSMiri Korenblit if (mlo)
345de5ca699SMiri Korenblit link = iwlmld_kunit_add_link(vif, assoc_link->id);
346d1e879ecSMiri Korenblit else
347d1e879ecSMiri Korenblit link = &vif->bss_conf;
348d1e879ecSMiri Korenblit
349*2907c039SMiri Korenblit chan_ctx = iwlmld_kunit_add_chanctx(assoc_link->band,
350*2907c039SMiri Korenblit assoc_link->bandwidth);
351d1e879ecSMiri Korenblit
352d1e879ecSMiri Korenblit wiphy_lock(mld->wiphy);
353d1e879ecSMiri Korenblit iwlmld_kunit_assign_chanctx_to_link(vif, link, chan_ctx);
354d1e879ecSMiri Korenblit wiphy_unlock(mld->wiphy);
355d1e879ecSMiri Korenblit
356d1e879ecSMiri Korenblit /* The AP sta will now be pointer to by mld_vif->ap_sta */
357de5ca699SMiri Korenblit iwlmld_kunit_setup_sta(vif, IEEE80211_STA_AUTHORIZED, assoc_link->id);
358d1e879ecSMiri Korenblit
359d1e879ecSMiri Korenblit iwlmld_kunit_set_vif_associated(vif);
360d1e879ecSMiri Korenblit
361d1e879ecSMiri Korenblit return vif;
362d1e879ecSMiri Korenblit }
363d1e879ecSMiri Korenblit
364de5ca699SMiri Korenblit struct ieee80211_vif *
iwlmld_kunit_setup_mlo_assoc(u16 valid_links,struct iwl_mld_kunit_link * assoc_link)365de5ca699SMiri Korenblit iwlmld_kunit_setup_mlo_assoc(u16 valid_links,
366de5ca699SMiri Korenblit struct iwl_mld_kunit_link *assoc_link)
367d1e879ecSMiri Korenblit {
368d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
369d1e879ecSMiri Korenblit struct ieee80211_vif *vif;
370d1e879ecSMiri Korenblit
371d1e879ecSMiri Korenblit KUNIT_ASSERT_TRUE(test,
372d1e879ecSMiri Korenblit hweight16(valid_links) == 1 ||
373d1e879ecSMiri Korenblit hweight16(valid_links) == 2);
374de5ca699SMiri Korenblit KUNIT_ASSERT_TRUE(test, valid_links & BIT(assoc_link->id));
375d1e879ecSMiri Korenblit
376de5ca699SMiri Korenblit vif = iwlmld_kunit_setup_assoc(true, assoc_link);
377d1e879ecSMiri Korenblit
378d1e879ecSMiri Korenblit /* Add the other link, if applicable */
379d1e879ecSMiri Korenblit if (hweight16(valid_links) > 1) {
380de5ca699SMiri Korenblit u8 other_link_id = ffs(valid_links & ~BIT(assoc_link->id)) - 1;
381d1e879ecSMiri Korenblit
382d1e879ecSMiri Korenblit iwlmld_kunit_add_link(vif, other_link_id);
383d1e879ecSMiri Korenblit }
384d1e879ecSMiri Korenblit
385d1e879ecSMiri Korenblit return vif;
386d1e879ecSMiri Korenblit }
387d1e879ecSMiri Korenblit
388de5ca699SMiri Korenblit struct ieee80211_vif *
iwlmld_kunit_setup_non_mlo_assoc(struct iwl_mld_kunit_link * assoc_link)389de5ca699SMiri Korenblit iwlmld_kunit_setup_non_mlo_assoc(struct iwl_mld_kunit_link *assoc_link)
390d1e879ecSMiri Korenblit {
391de5ca699SMiri Korenblit return iwlmld_kunit_setup_assoc(false, assoc_link);
392d1e879ecSMiri Korenblit }
393d1e879ecSMiri Korenblit
394d1e879ecSMiri Korenblit struct iwl_rx_packet *
_iwl_mld_kunit_create_pkt(const void * notif,size_t notif_sz)395d1e879ecSMiri Korenblit _iwl_mld_kunit_create_pkt(const void *notif, size_t notif_sz)
396d1e879ecSMiri Korenblit {
397d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
398d1e879ecSMiri Korenblit struct iwl_rx_packet *pkt;
399d1e879ecSMiri Korenblit
400d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, pkt, sizeof(pkt) + notif_sz);
401d1e879ecSMiri Korenblit
402d1e879ecSMiri Korenblit memcpy(pkt->data, notif, notif_sz);
403d1e879ecSMiri Korenblit pkt->len_n_flags = cpu_to_le32(sizeof(pkt->hdr) + notif_sz);
404d1e879ecSMiri Korenblit
405d1e879ecSMiri Korenblit return pkt;
406d1e879ecSMiri Korenblit }
407d1e879ecSMiri Korenblit
iwlmld_kunit_assoc_emlsr(struct iwl_mld_kunit_link * link1,struct iwl_mld_kunit_link * link2)408de5ca699SMiri Korenblit struct ieee80211_vif *iwlmld_kunit_assoc_emlsr(struct iwl_mld_kunit_link *link1,
409de5ca699SMiri Korenblit struct iwl_mld_kunit_link *link2)
410d1e879ecSMiri Korenblit {
411d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
412d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
413d1e879ecSMiri Korenblit struct ieee80211_vif *vif;
414d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link;
415d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *chan_ctx;
416d1e879ecSMiri Korenblit struct ieee80211_sta *sta;
417d1e879ecSMiri Korenblit struct iwl_mld_vif *mld_vif;
418de5ca699SMiri Korenblit u16 valid_links = BIT(link1->id) | BIT(link2->id);
419d1e879ecSMiri Korenblit
420d1e879ecSMiri Korenblit KUNIT_ASSERT_TRUE(test, hweight16(valid_links) == 2);
421d1e879ecSMiri Korenblit
422de5ca699SMiri Korenblit vif = iwlmld_kunit_setup_mlo_assoc(valid_links, link1);
423d1e879ecSMiri Korenblit mld_vif = iwl_mld_vif_from_mac80211(vif);
424d1e879ecSMiri Korenblit
425d1e879ecSMiri Korenblit /* Activate second link */
426d1e879ecSMiri Korenblit wiphy_lock(mld->wiphy);
427d1e879ecSMiri Korenblit
428de5ca699SMiri Korenblit link = wiphy_dereference(mld->wiphy, vif->link_conf[link2->id]);
429d1e879ecSMiri Korenblit KUNIT_EXPECT_NOT_NULL(test, link);
430d1e879ecSMiri Korenblit
431*2907c039SMiri Korenblit chan_ctx = iwlmld_kunit_add_chanctx(link2->band, link2->bandwidth);
432d1e879ecSMiri Korenblit iwlmld_kunit_assign_chanctx_to_link(vif, link, chan_ctx);
433d1e879ecSMiri Korenblit
434d1e879ecSMiri Korenblit wiphy_unlock(mld->wiphy);
435d1e879ecSMiri Korenblit
436d1e879ecSMiri Korenblit /* And other link sta */
437d1e879ecSMiri Korenblit sta = mld_vif->ap_sta;
438d1e879ecSMiri Korenblit KUNIT_EXPECT_NOT_NULL(test, sta);
439d1e879ecSMiri Korenblit
440de5ca699SMiri Korenblit iwlmld_kunit_alloc_link_sta(sta, link2->id);
441d1e879ecSMiri Korenblit
442d1e879ecSMiri Korenblit return vif;
443d1e879ecSMiri Korenblit }
444d1e879ecSMiri Korenblit
iwlmld_kunit_gen_element(u8 id,const void * data,size_t len)445d1e879ecSMiri Korenblit struct element *iwlmld_kunit_gen_element(u8 id, const void *data, size_t len)
446d1e879ecSMiri Korenblit {
447d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
448d1e879ecSMiri Korenblit struct element *elem;
449d1e879ecSMiri Korenblit
450d1e879ecSMiri Korenblit KUNIT_ALLOC_AND_ASSERT_SIZE(test, elem, sizeof(*elem) + len);
451d1e879ecSMiri Korenblit
452d1e879ecSMiri Korenblit elem->id = id;
453d1e879ecSMiri Korenblit elem->datalen = len;
454d1e879ecSMiri Korenblit memcpy(elem->data, data, len);
455d1e879ecSMiri Korenblit
456d1e879ecSMiri Korenblit return elem;
457d1e879ecSMiri Korenblit }
458d1e879ecSMiri Korenblit
iwlmld_kunit_get_phy_of_link(struct ieee80211_vif * vif,u8 link_id)459d1e879ecSMiri Korenblit struct iwl_mld_phy *iwlmld_kunit_get_phy_of_link(struct ieee80211_vif *vif,
460d1e879ecSMiri Korenblit u8 link_id)
461d1e879ecSMiri Korenblit {
462d1e879ecSMiri Korenblit struct kunit *test = kunit_get_current_test();
463d1e879ecSMiri Korenblit struct iwl_mld *mld = test->priv;
464d1e879ecSMiri Korenblit struct ieee80211_chanctx_conf *chanctx;
465d1e879ecSMiri Korenblit struct ieee80211_bss_conf *link =
466d1e879ecSMiri Korenblit wiphy_dereference(mld->wiphy, vif->link_conf[link_id]);
467d1e879ecSMiri Korenblit
468d1e879ecSMiri Korenblit KUNIT_EXPECT_NOT_NULL(test, link);
469d1e879ecSMiri Korenblit
470d1e879ecSMiri Korenblit chanctx = wiphy_dereference(mld->wiphy, link->chanctx_conf);
471d1e879ecSMiri Korenblit KUNIT_EXPECT_NOT_NULL(test, chanctx);
472d1e879ecSMiri Korenblit
473d1e879ecSMiri Korenblit return iwl_mld_phy_from_mac80211(chanctx);
474d1e879ecSMiri Korenblit }
475