1*b2bd0818SBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2*b2bd0818SBjoern A. Zeeb /*
3*b2bd0818SBjoern A. Zeeb * Copyright (C) 2025 Intel Corporation
4*b2bd0818SBjoern A. Zeeb */
5*b2bd0818SBjoern A. Zeeb
6*b2bd0818SBjoern A. Zeeb #include "mld.h"
7*b2bd0818SBjoern A. Zeeb #include "iface.h"
8*b2bd0818SBjoern A. Zeeb #include "mlo.h"
9*b2bd0818SBjoern A. Zeeb #include "fw/api/mac-cfg.h"
10*b2bd0818SBjoern A. Zeeb
11*b2bd0818SBjoern A. Zeeb #define IWL_NAN_DISOVERY_BEACON_INTERNVAL_TU 512
12*b2bd0818SBjoern A. Zeeb #define IWL_NAN_RSSI_CLOSE 55
13*b2bd0818SBjoern A. Zeeb #define IWL_NAN_RSSI_MIDDLE 70
14*b2bd0818SBjoern A. Zeeb
iwl_mld_nan_supported(struct iwl_mld * mld)15*b2bd0818SBjoern A. Zeeb bool iwl_mld_nan_supported(struct iwl_mld *mld)
16*b2bd0818SBjoern A. Zeeb {
17*b2bd0818SBjoern A. Zeeb return fw_has_capa(&mld->fw->ucode_capa,
18*b2bd0818SBjoern A. Zeeb IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT);
19*b2bd0818SBjoern A. Zeeb }
20*b2bd0818SBjoern A. Zeeb
iwl_mld_nan_send_config_cmd(struct iwl_mld * mld,struct iwl_nan_config_cmd * cmd,u8 * beacon_data,size_t beacon_data_len)21*b2bd0818SBjoern A. Zeeb static int iwl_mld_nan_send_config_cmd(struct iwl_mld *mld,
22*b2bd0818SBjoern A. Zeeb struct iwl_nan_config_cmd *cmd,
23*b2bd0818SBjoern A. Zeeb u8 *beacon_data, size_t beacon_data_len)
24*b2bd0818SBjoern A. Zeeb {
25*b2bd0818SBjoern A. Zeeb struct iwl_host_cmd hcmd = {
26*b2bd0818SBjoern A. Zeeb .id = WIDE_ID(MAC_CONF_GROUP, NAN_CFG_CMD),
27*b2bd0818SBjoern A. Zeeb };
28*b2bd0818SBjoern A. Zeeb
29*b2bd0818SBjoern A. Zeeb hcmd.len[0] = sizeof(*cmd);
30*b2bd0818SBjoern A. Zeeb hcmd.data[0] = cmd;
31*b2bd0818SBjoern A. Zeeb
32*b2bd0818SBjoern A. Zeeb if (beacon_data_len) {
33*b2bd0818SBjoern A. Zeeb hcmd.len[1] = beacon_data_len;
34*b2bd0818SBjoern A. Zeeb hcmd.data[1] = beacon_data;
35*b2bd0818SBjoern A. Zeeb hcmd.dataflags[1] = IWL_HCMD_DFL_DUP;
36*b2bd0818SBjoern A. Zeeb }
37*b2bd0818SBjoern A. Zeeb
38*b2bd0818SBjoern A. Zeeb return iwl_mld_send_cmd(mld, &hcmd);
39*b2bd0818SBjoern A. Zeeb }
40*b2bd0818SBjoern A. Zeeb
iwl_mld_nan_config(struct iwl_mld * mld,struct ieee80211_vif * vif,struct cfg80211_nan_conf * conf,enum iwl_ctxt_action action)41*b2bd0818SBjoern A. Zeeb static int iwl_mld_nan_config(struct iwl_mld *mld,
42*b2bd0818SBjoern A. Zeeb struct ieee80211_vif *vif,
43*b2bd0818SBjoern A. Zeeb struct cfg80211_nan_conf *conf,
44*b2bd0818SBjoern A. Zeeb enum iwl_ctxt_action action)
45*b2bd0818SBjoern A. Zeeb {
46*b2bd0818SBjoern A. Zeeb struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
47*b2bd0818SBjoern A. Zeeb struct iwl_nan_config_cmd cmd = {
48*b2bd0818SBjoern A. Zeeb .action = cpu_to_le32(action),
49*b2bd0818SBjoern A. Zeeb };
50*b2bd0818SBjoern A. Zeeb u8 *data __free(kfree) = NULL;
51*b2bd0818SBjoern A. Zeeb
52*b2bd0818SBjoern A. Zeeb lockdep_assert_wiphy(mld->wiphy);
53*b2bd0818SBjoern A. Zeeb
54*b2bd0818SBjoern A. Zeeb ether_addr_copy(cmd.nmi_addr, vif->addr);
55*b2bd0818SBjoern A. Zeeb cmd.master_pref = conf->master_pref;
56*b2bd0818SBjoern A. Zeeb
57*b2bd0818SBjoern A. Zeeb if (conf->cluster_id)
58*b2bd0818SBjoern A. Zeeb memcpy(cmd.cluster_id, conf->cluster_id + 4,
59*b2bd0818SBjoern A. Zeeb sizeof(cmd.cluster_id));
60*b2bd0818SBjoern A. Zeeb
61*b2bd0818SBjoern A. Zeeb cmd.scan_period = conf->scan_period < 255 ? conf->scan_period : 255;
62*b2bd0818SBjoern A. Zeeb cmd.dwell_time =
63*b2bd0818SBjoern A. Zeeb conf->scan_dwell_time < 255 ? conf->scan_dwell_time : 255;
64*b2bd0818SBjoern A. Zeeb
65*b2bd0818SBjoern A. Zeeb if (conf->discovery_beacon_interval)
66*b2bd0818SBjoern A. Zeeb cmd.discovery_beacon_interval =
67*b2bd0818SBjoern A. Zeeb cpu_to_le32(conf->discovery_beacon_interval);
68*b2bd0818SBjoern A. Zeeb else
69*b2bd0818SBjoern A. Zeeb cmd.discovery_beacon_interval =
70*b2bd0818SBjoern A. Zeeb cpu_to_le32(IWL_NAN_DISOVERY_BEACON_INTERNVAL_TU);
71*b2bd0818SBjoern A. Zeeb
72*b2bd0818SBjoern A. Zeeb if (conf->enable_dw_notification)
73*b2bd0818SBjoern A. Zeeb cmd.flags = IWL_NAN_FLAG_DW_END_NOTIF_ENABLED;
74*b2bd0818SBjoern A. Zeeb
75*b2bd0818SBjoern A. Zeeb /* 2 GHz band must be supported */
76*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_2GHZ].rssi_close =
77*b2bd0818SBjoern A. Zeeb abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_close);
78*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_2GHZ].rssi_middle =
79*b2bd0818SBjoern A. Zeeb abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_middle);
80*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_2GHZ].dw_interval =
81*b2bd0818SBjoern A. Zeeb conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval;
82*b2bd0818SBjoern A. Zeeb
83*b2bd0818SBjoern A. Zeeb /* 5 GHz band operation is optional. Configure its operation if
84*b2bd0818SBjoern A. Zeeb * supported. Note that conf->bands might be zero, so we need to check
85*b2bd0818SBjoern A. Zeeb * the channel pointer, not the band mask.
86*b2bd0818SBjoern A. Zeeb */
87*b2bd0818SBjoern A. Zeeb if (conf->band_cfgs[NL80211_BAND_5GHZ].chan) {
88*b2bd0818SBjoern A. Zeeb cmd.hb_channel =
89*b2bd0818SBjoern A. Zeeb conf->band_cfgs[NL80211_BAND_5GHZ].chan->hw_value;
90*b2bd0818SBjoern A. Zeeb
91*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_5GHZ].rssi_close =
92*b2bd0818SBjoern A. Zeeb abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_close);
93*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_5GHZ].rssi_middle =
94*b2bd0818SBjoern A. Zeeb abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_middle);
95*b2bd0818SBjoern A. Zeeb cmd.band_config[IWL_NAN_BAND_5GHZ].dw_interval =
96*b2bd0818SBjoern A. Zeeb conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval;
97*b2bd0818SBjoern A. Zeeb }
98*b2bd0818SBjoern A. Zeeb
99*b2bd0818SBjoern A. Zeeb if (conf->extra_nan_attrs_len || conf->vendor_elems_len) {
100*b2bd0818SBjoern A. Zeeb data = kmalloc(conf->extra_nan_attrs_len +
101*b2bd0818SBjoern A. Zeeb conf->vendor_elems_len, GFP_KERNEL);
102*b2bd0818SBjoern A. Zeeb if (!data)
103*b2bd0818SBjoern A. Zeeb return -ENOMEM;
104*b2bd0818SBjoern A. Zeeb
105*b2bd0818SBjoern A. Zeeb cmd.nan_attr_len = cpu_to_le32(conf->extra_nan_attrs_len);
106*b2bd0818SBjoern A. Zeeb cmd.nan_vendor_elems_len = cpu_to_le32(conf->vendor_elems_len);
107*b2bd0818SBjoern A. Zeeb
108*b2bd0818SBjoern A. Zeeb if (conf->extra_nan_attrs_len)
109*b2bd0818SBjoern A. Zeeb memcpy(data, conf->extra_nan_attrs,
110*b2bd0818SBjoern A. Zeeb conf->extra_nan_attrs_len);
111*b2bd0818SBjoern A. Zeeb
112*b2bd0818SBjoern A. Zeeb if (conf->vendor_elems_len)
113*b2bd0818SBjoern A. Zeeb memcpy(data + conf->extra_nan_attrs_len,
114*b2bd0818SBjoern A. Zeeb conf->vendor_elems,
115*b2bd0818SBjoern A. Zeeb conf->vendor_elems_len);
116*b2bd0818SBjoern A. Zeeb }
117*b2bd0818SBjoern A. Zeeb
118*b2bd0818SBjoern A. Zeeb cmd.sta_id = mld_vif->aux_sta.sta_id;
119*b2bd0818SBjoern A. Zeeb return iwl_mld_nan_send_config_cmd(mld, &cmd, data,
120*b2bd0818SBjoern A. Zeeb conf->extra_nan_attrs_len +
121*b2bd0818SBjoern A. Zeeb conf->vendor_elems_len);
122*b2bd0818SBjoern A. Zeeb }
123*b2bd0818SBjoern A. Zeeb
iwl_mld_start_nan(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_nan_conf * conf)124*b2bd0818SBjoern A. Zeeb int iwl_mld_start_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
125*b2bd0818SBjoern A. Zeeb struct cfg80211_nan_conf *conf)
126*b2bd0818SBjoern A. Zeeb {
127*b2bd0818SBjoern A. Zeeb struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
128*b2bd0818SBjoern A. Zeeb struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
129*b2bd0818SBjoern A. Zeeb struct iwl_mld_int_sta *aux_sta = &mld_vif->aux_sta;
130*b2bd0818SBjoern A. Zeeb int ret;
131*b2bd0818SBjoern A. Zeeb
132*b2bd0818SBjoern A. Zeeb IWL_DEBUG_MAC80211(mld, "NAN: start: bands=0x%x\n", conf->bands);
133*b2bd0818SBjoern A. Zeeb
134*b2bd0818SBjoern A. Zeeb ret = iwl_mld_update_emlsr_block(mld, true, IWL_MLD_EMLSR_BLOCKED_NAN);
135*b2bd0818SBjoern A. Zeeb if (ret)
136*b2bd0818SBjoern A. Zeeb return ret;
137*b2bd0818SBjoern A. Zeeb
138*b2bd0818SBjoern A. Zeeb ret = iwl_mld_add_aux_sta(mld, aux_sta);
139*b2bd0818SBjoern A. Zeeb if (ret)
140*b2bd0818SBjoern A. Zeeb goto unblock_emlsr;
141*b2bd0818SBjoern A. Zeeb
142*b2bd0818SBjoern A. Zeeb ret = iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_ADD);
143*b2bd0818SBjoern A. Zeeb if (ret) {
144*b2bd0818SBjoern A. Zeeb IWL_ERR(mld, "Failed to start NAN. ret=%d\n", ret);
145*b2bd0818SBjoern A. Zeeb goto remove_aux;
146*b2bd0818SBjoern A. Zeeb }
147*b2bd0818SBjoern A. Zeeb return 0;
148*b2bd0818SBjoern A. Zeeb
149*b2bd0818SBjoern A. Zeeb remove_aux:
150*b2bd0818SBjoern A. Zeeb iwl_mld_remove_aux_sta(mld, vif);
151*b2bd0818SBjoern A. Zeeb unblock_emlsr:
152*b2bd0818SBjoern A. Zeeb iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN);
153*b2bd0818SBjoern A. Zeeb
154*b2bd0818SBjoern A. Zeeb return ret;
155*b2bd0818SBjoern A. Zeeb }
156*b2bd0818SBjoern A. Zeeb
iwl_mld_nan_change_config(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_nan_conf * conf,u32 changes)157*b2bd0818SBjoern A. Zeeb int iwl_mld_nan_change_config(struct ieee80211_hw *hw,
158*b2bd0818SBjoern A. Zeeb struct ieee80211_vif *vif,
159*b2bd0818SBjoern A. Zeeb struct cfg80211_nan_conf *conf,
160*b2bd0818SBjoern A. Zeeb u32 changes)
161*b2bd0818SBjoern A. Zeeb {
162*b2bd0818SBjoern A. Zeeb struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
163*b2bd0818SBjoern A. Zeeb
164*b2bd0818SBjoern A. Zeeb IWL_DEBUG_MAC80211(mld, "NAN: change: changes=0x%x, bands=0x%x\n",
165*b2bd0818SBjoern A. Zeeb changes, conf->bands);
166*b2bd0818SBjoern A. Zeeb
167*b2bd0818SBjoern A. Zeeb /* Note that we do not use 'changes' as the FW always expects the
168*b2bd0818SBjoern A. Zeeb * complete configuration, and mac80211 always provides the complete
169*b2bd0818SBjoern A. Zeeb * configuration.
170*b2bd0818SBjoern A. Zeeb */
171*b2bd0818SBjoern A. Zeeb return iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_MODIFY);
172*b2bd0818SBjoern A. Zeeb }
173*b2bd0818SBjoern A. Zeeb
iwl_mld_stop_nan(struct ieee80211_hw * hw,struct ieee80211_vif * vif)174*b2bd0818SBjoern A. Zeeb int iwl_mld_stop_nan(struct ieee80211_hw *hw,
175*b2bd0818SBjoern A. Zeeb struct ieee80211_vif *vif)
176*b2bd0818SBjoern A. Zeeb {
177*b2bd0818SBjoern A. Zeeb struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
178*b2bd0818SBjoern A. Zeeb struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
179*b2bd0818SBjoern A. Zeeb struct iwl_nan_config_cmd cmd = {
180*b2bd0818SBjoern A. Zeeb .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
181*b2bd0818SBjoern A. Zeeb };
182*b2bd0818SBjoern A. Zeeb int ret;
183*b2bd0818SBjoern A. Zeeb
184*b2bd0818SBjoern A. Zeeb lockdep_assert_wiphy(mld->wiphy);
185*b2bd0818SBjoern A. Zeeb
186*b2bd0818SBjoern A. Zeeb ret = iwl_mld_send_cmd_pdu(mld,
187*b2bd0818SBjoern A. Zeeb WIDE_ID(MAC_CONF_GROUP, NAN_CFG_CMD),
188*b2bd0818SBjoern A. Zeeb &cmd);
189*b2bd0818SBjoern A. Zeeb if (ret)
190*b2bd0818SBjoern A. Zeeb IWL_ERR(mld, "NAN: Failed to stop NAN. ret=%d\n", ret);
191*b2bd0818SBjoern A. Zeeb
192*b2bd0818SBjoern A. Zeeb /* assume that higher layer guarantees that no additional frames are
193*b2bd0818SBjoern A. Zeeb * added before calling this callback
194*b2bd0818SBjoern A. Zeeb */
195*b2bd0818SBjoern A. Zeeb iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
196*b2bd0818SBjoern A. Zeeb iwl_mld_remove_aux_sta(mld, vif);
197*b2bd0818SBjoern A. Zeeb
198*b2bd0818SBjoern A. Zeeb /* cancel based on object type being NAN, as the NAN objects do
199*b2bd0818SBjoern A. Zeeb * not have a unique identifier associated with them
200*b2bd0818SBjoern A. Zeeb */
201*b2bd0818SBjoern A. Zeeb iwl_mld_cancel_notifications_of_object(mld,
202*b2bd0818SBjoern A. Zeeb IWL_MLD_OBJECT_TYPE_NAN,
203*b2bd0818SBjoern A. Zeeb 0);
204*b2bd0818SBjoern A. Zeeb
205*b2bd0818SBjoern A. Zeeb iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN);
206*b2bd0818SBjoern A. Zeeb
207*b2bd0818SBjoern A. Zeeb return 0;
208*b2bd0818SBjoern A. Zeeb }
209*b2bd0818SBjoern A. Zeeb
iwl_mld_handle_nan_cluster_notif(struct iwl_mld * mld,struct iwl_rx_packet * pkt)210*b2bd0818SBjoern A. Zeeb void iwl_mld_handle_nan_cluster_notif(struct iwl_mld *mld,
211*b2bd0818SBjoern A. Zeeb struct iwl_rx_packet *pkt)
212*b2bd0818SBjoern A. Zeeb {
213*b2bd0818SBjoern A. Zeeb struct iwl_nan_cluster_notif *notif = (void *)pkt->data;
214*b2bd0818SBjoern A. Zeeb struct wireless_dev *wdev = mld->nan_device_vif ?
215*b2bd0818SBjoern A. Zeeb ieee80211_vif_to_wdev(mld->nan_device_vif) : NULL;
216*b2bd0818SBjoern A. Zeeb bool new_cluster = !!(notif->flags &
217*b2bd0818SBjoern A. Zeeb IWL_NAN_CLUSTER_NOTIF_FLAG_NEW_CLUSTER);
218*b2bd0818SBjoern A. Zeeb u8 cluster_id[ETH_ALEN] = {
219*b2bd0818SBjoern A. Zeeb 0x50, 0x6f, 0x9a, 0x01,
220*b2bd0818SBjoern A. Zeeb notif->cluster_id[0], notif->cluster_id[1]
221*b2bd0818SBjoern A. Zeeb };
222*b2bd0818SBjoern A. Zeeb
223*b2bd0818SBjoern A. Zeeb IWL_DEBUG_INFO(mld,
224*b2bd0818SBjoern A. Zeeb "NAN: cluster event: cluster_id=%pM, flags=0x%x\n",
225*b2bd0818SBjoern A. Zeeb cluster_id, notif->flags);
226*b2bd0818SBjoern A. Zeeb
227*b2bd0818SBjoern A. Zeeb if (IWL_FW_CHECK(mld, !wdev, "NAN: cluster event without wdev\n"))
228*b2bd0818SBjoern A. Zeeb return;
229*b2bd0818SBjoern A. Zeeb
230*b2bd0818SBjoern A. Zeeb if (IWL_FW_CHECK(mld, !ieee80211_vif_nan_started(mld->nan_device_vif),
231*b2bd0818SBjoern A. Zeeb "NAN: cluster event without NAN started\n"))
232*b2bd0818SBjoern A. Zeeb return;
233*b2bd0818SBjoern A. Zeeb
234*b2bd0818SBjoern A. Zeeb cfg80211_nan_cluster_joined(wdev, cluster_id, new_cluster, GFP_KERNEL);
235*b2bd0818SBjoern A. Zeeb }
236*b2bd0818SBjoern A. Zeeb
iwl_mld_cancel_nan_cluster_notif(struct iwl_mld * mld,struct iwl_rx_packet * pkt,u32 obj_id)237*b2bd0818SBjoern A. Zeeb bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld,
238*b2bd0818SBjoern A. Zeeb struct iwl_rx_packet *pkt,
239*b2bd0818SBjoern A. Zeeb u32 obj_id)
240*b2bd0818SBjoern A. Zeeb {
241*b2bd0818SBjoern A. Zeeb return true;
242*b2bd0818SBjoern A. Zeeb }
243*b2bd0818SBjoern A. Zeeb
iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld * mld,struct iwl_rx_packet * pkt,u32 obj_id)244*b2bd0818SBjoern A. Zeeb bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
245*b2bd0818SBjoern A. Zeeb struct iwl_rx_packet *pkt,
246*b2bd0818SBjoern A. Zeeb u32 obj_id)
247*b2bd0818SBjoern A. Zeeb {
248*b2bd0818SBjoern A. Zeeb return true;
249*b2bd0818SBjoern A. Zeeb }
250*b2bd0818SBjoern A. Zeeb
iwl_mld_handle_nan_dw_end_notif(struct iwl_mld * mld,struct iwl_rx_packet * pkt)251*b2bd0818SBjoern A. Zeeb void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld,
252*b2bd0818SBjoern A. Zeeb struct iwl_rx_packet *pkt)
253*b2bd0818SBjoern A. Zeeb {
254*b2bd0818SBjoern A. Zeeb struct iwl_nan_dw_end_notif *notif = (void *)pkt->data;
255*b2bd0818SBjoern A. Zeeb struct iwl_mld_vif *mld_vif = mld->nan_device_vif ?
256*b2bd0818SBjoern A. Zeeb iwl_mld_vif_from_mac80211(mld->nan_device_vif) :
257*b2bd0818SBjoern A. Zeeb NULL;
258*b2bd0818SBjoern A. Zeeb struct wireless_dev *wdev;
259*b2bd0818SBjoern A. Zeeb struct ieee80211_channel *chan;
260*b2bd0818SBjoern A. Zeeb
261*b2bd0818SBjoern A. Zeeb IWL_INFO(mld, "NAN: DW end: band=%u\n", notif->band);
262*b2bd0818SBjoern A. Zeeb
263*b2bd0818SBjoern A. Zeeb if (IWL_FW_CHECK(mld, !mld_vif, "NAN: DW end without mld_vif\n"))
264*b2bd0818SBjoern A. Zeeb return;
265*b2bd0818SBjoern A. Zeeb
266*b2bd0818SBjoern A. Zeeb if (IWL_FW_CHECK(mld, !ieee80211_vif_nan_started(mld->nan_device_vif),
267*b2bd0818SBjoern A. Zeeb "NAN: DW end without NAN started\n"))
268*b2bd0818SBjoern A. Zeeb return;
269*b2bd0818SBjoern A. Zeeb
270*b2bd0818SBjoern A. Zeeb if (WARN_ON(mld_vif->aux_sta.sta_id == IWL_INVALID_STA))
271*b2bd0818SBjoern A. Zeeb return;
272*b2bd0818SBjoern A. Zeeb
273*b2bd0818SBjoern A. Zeeb IWL_DEBUG_INFO(mld, "NAN: flush queues for aux sta=%u\n",
274*b2bd0818SBjoern A. Zeeb mld_vif->aux_sta.sta_id);
275*b2bd0818SBjoern A. Zeeb
276*b2bd0818SBjoern A. Zeeb iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
277*b2bd0818SBjoern A. Zeeb
278*b2bd0818SBjoern A. Zeeb /* TODO: currently the notification specified the band on which the DW
279*b2bd0818SBjoern A. Zeeb * ended. Need to change that to the actual channel on which the next DW
280*b2bd0818SBjoern A. Zeeb * will be started.
281*b2bd0818SBjoern A. Zeeb */
282*b2bd0818SBjoern A. Zeeb switch (notif->band) {
283*b2bd0818SBjoern A. Zeeb case IWL_NAN_BAND_2GHZ:
284*b2bd0818SBjoern A. Zeeb chan = ieee80211_get_channel(mld->wiphy, 2437);
285*b2bd0818SBjoern A. Zeeb break;
286*b2bd0818SBjoern A. Zeeb case IWL_NAN_BAND_5GHZ:
287*b2bd0818SBjoern A. Zeeb /* TODO: use the actual channel */
288*b2bd0818SBjoern A. Zeeb chan = ieee80211_get_channel(mld->wiphy, 5745);
289*b2bd0818SBjoern A. Zeeb break;
290*b2bd0818SBjoern A. Zeeb default:
291*b2bd0818SBjoern A. Zeeb IWL_FW_CHECK(mld, false,
292*b2bd0818SBjoern A. Zeeb "NAN: Invalid band %u in DW end notif\n",
293*b2bd0818SBjoern A. Zeeb notif->band);
294*b2bd0818SBjoern A. Zeeb return;
295*b2bd0818SBjoern A. Zeeb }
296*b2bd0818SBjoern A. Zeeb
297*b2bd0818SBjoern A. Zeeb wdev = ieee80211_vif_to_wdev(mld->nan_device_vif);
298*b2bd0818SBjoern A. Zeeb cfg80211_next_nan_dw_notif(wdev, chan, GFP_KERNEL);
299*b2bd0818SBjoern A. Zeeb }
300