1*73b01e57SJeff Chen // SPDX-License-Identifier: GPL-2.0-only
2*73b01e57SJeff Chen /*
3*73b01e57SJeff Chen * nxpwifi: 802.11h helpers
4*73b01e57SJeff Chen *
5*73b01e57SJeff Chen * Copyright 2011-2024 NXP
6*73b01e57SJeff Chen */
7*73b01e57SJeff Chen
8*73b01e57SJeff Chen #include "main.h"
9*73b01e57SJeff Chen #include "cmdevt.h"
10*73b01e57SJeff Chen #include "fw.h"
11*73b01e57SJeff Chen #include "cfg80211.h"
12*73b01e57SJeff Chen
nxpwifi_init_11h_params(struct nxpwifi_private * priv)13*73b01e57SJeff Chen void nxpwifi_init_11h_params(struct nxpwifi_private *priv)
14*73b01e57SJeff Chen {
15*73b01e57SJeff Chen priv->state_11h.is_11h_enabled = true;
16*73b01e57SJeff Chen priv->state_11h.is_11h_active = false;
17*73b01e57SJeff Chen }
18*73b01e57SJeff Chen
nxpwifi_is_11h_active(struct nxpwifi_private * priv)19*73b01e57SJeff Chen int nxpwifi_is_11h_active(struct nxpwifi_private *priv)
20*73b01e57SJeff Chen {
21*73b01e57SJeff Chen return priv->state_11h.is_11h_active;
22*73b01e57SJeff Chen }
23*73b01e57SJeff Chen
24*73b01e57SJeff Chen /* appends 11h info to a buffer while joining an infrastructure BSS */
25*73b01e57SJeff Chen static void
nxpwifi_11h_process_infra_join(struct nxpwifi_private * priv,u8 ** buffer,struct nxpwifi_bssdescriptor * bss_desc)26*73b01e57SJeff Chen nxpwifi_11h_process_infra_join(struct nxpwifi_private *priv, u8 **buffer,
27*73b01e57SJeff Chen struct nxpwifi_bssdescriptor *bss_desc)
28*73b01e57SJeff Chen {
29*73b01e57SJeff Chen struct nxpwifi_ie_types_header *ie_header;
30*73b01e57SJeff Chen struct nxpwifi_ie_types_pwr_capability *cap;
31*73b01e57SJeff Chen struct nxpwifi_ie_types_local_pwr_constraint *constraint;
32*73b01e57SJeff Chen struct ieee80211_supported_band *sband;
33*73b01e57SJeff Chen u8 radio_type;
34*73b01e57SJeff Chen int i;
35*73b01e57SJeff Chen
36*73b01e57SJeff Chen if (!buffer || !(*buffer))
37*73b01e57SJeff Chen return;
38*73b01e57SJeff Chen
39*73b01e57SJeff Chen radio_type = nxpwifi_band_to_radio_type((u8)bss_desc->bss_band);
40*73b01e57SJeff Chen sband = priv->wdev.wiphy->bands[radio_type];
41*73b01e57SJeff Chen
42*73b01e57SJeff Chen cap = (struct nxpwifi_ie_types_pwr_capability *)*buffer;
43*73b01e57SJeff Chen cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY);
44*73b01e57SJeff Chen cap->header.len = cpu_to_le16(2);
45*73b01e57SJeff Chen cap->min_pwr = 0;
46*73b01e57SJeff Chen cap->max_pwr = 0;
47*73b01e57SJeff Chen *buffer += sizeof(*cap);
48*73b01e57SJeff Chen
49*73b01e57SJeff Chen constraint = (struct nxpwifi_ie_types_local_pwr_constraint *)*buffer;
50*73b01e57SJeff Chen constraint->header.type = cpu_to_le16(WLAN_EID_PWR_CONSTRAINT);
51*73b01e57SJeff Chen constraint->header.len = cpu_to_le16(2);
52*73b01e57SJeff Chen constraint->chan = bss_desc->channel;
53*73b01e57SJeff Chen constraint->constraint = bss_desc->local_constraint;
54*73b01e57SJeff Chen *buffer += sizeof(*constraint);
55*73b01e57SJeff Chen
56*73b01e57SJeff Chen ie_header = (struct nxpwifi_ie_types_header *)*buffer;
57*73b01e57SJeff Chen ie_header->type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
58*73b01e57SJeff Chen ie_header->len = cpu_to_le16(2 * sband->n_channels + 2);
59*73b01e57SJeff Chen *buffer += sizeof(*ie_header);
60*73b01e57SJeff Chen *(*buffer)++ = WLAN_EID_SUPPORTED_CHANNELS;
61*73b01e57SJeff Chen *(*buffer)++ = 2 * sband->n_channels;
62*73b01e57SJeff Chen for (i = 0; i < sband->n_channels; i++) {
63*73b01e57SJeff Chen u32 center_freq;
64*73b01e57SJeff Chen
65*73b01e57SJeff Chen center_freq = sband->channels[i].center_freq;
66*73b01e57SJeff Chen *(*buffer)++ = ieee80211_frequency_to_channel(center_freq);
67*73b01e57SJeff Chen *(*buffer)++ = 1; /* one channel in the subband */
68*73b01e57SJeff Chen }
69*73b01e57SJeff Chen }
70*73b01e57SJeff Chen
71*73b01e57SJeff Chen /* Enable or disable the 11h extensions in the firmware */
nxpwifi_11h_activate(struct nxpwifi_private * priv,bool flag)72*73b01e57SJeff Chen int nxpwifi_11h_activate(struct nxpwifi_private *priv, bool flag)
73*73b01e57SJeff Chen {
74*73b01e57SJeff Chen u32 enable = flag;
75*73b01e57SJeff Chen
76*73b01e57SJeff Chen /* enable master mode radar detection on AP interface */
77*73b01e57SJeff Chen if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) && enable)
78*73b01e57SJeff Chen enable |= NXPWIFI_MASTER_RADAR_DET_MASK;
79*73b01e57SJeff Chen
80*73b01e57SJeff Chen return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB,
81*73b01e57SJeff Chen HOST_ACT_GEN_SET, DOT11H_I, &enable, true);
82*73b01e57SJeff Chen }
83*73b01e57SJeff Chen
84*73b01e57SJeff Chen /*
85*73b01e57SJeff Chen * Process TLV buffer for a pending BSS join. Enable 11h in firmware when the
86*73b01e57SJeff Chen * network advertises spectrum management, and add required TLVs based on the
87*73b01e57SJeff Chen * BSS's 11h capability.
88*73b01e57SJeff Chen */
nxpwifi_11h_process_join(struct nxpwifi_private * priv,u8 ** buffer,struct nxpwifi_bssdescriptor * bss_desc)89*73b01e57SJeff Chen void nxpwifi_11h_process_join(struct nxpwifi_private *priv, u8 **buffer,
90*73b01e57SJeff Chen struct nxpwifi_bssdescriptor *bss_desc)
91*73b01e57SJeff Chen {
92*73b01e57SJeff Chen if (bss_desc->sensed_11h) {
93*73b01e57SJeff Chen /* Activate 11h functions in firmware, turns on capability bit */
94*73b01e57SJeff Chen nxpwifi_11h_activate(priv, true);
95*73b01e57SJeff Chen priv->state_11h.is_11h_active = true;
96*73b01e57SJeff Chen bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT;
97*73b01e57SJeff Chen nxpwifi_11h_process_infra_join(priv, buffer, bss_desc);
98*73b01e57SJeff Chen } else {
99*73b01e57SJeff Chen /* Deactivate 11h functions in the firmware */
100*73b01e57SJeff Chen nxpwifi_11h_activate(priv, false);
101*73b01e57SJeff Chen priv->state_11h.is_11h_active = false;
102*73b01e57SJeff Chen bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
103*73b01e57SJeff Chen }
104*73b01e57SJeff Chen }
105*73b01e57SJeff Chen
106*73b01e57SJeff Chen /*
107*73b01e57SJeff Chen * DFS CAC work function. This delayed work emits CAC finished event for cfg80211
108*73b01e57SJeff Chen * if CAC was started earlier
109*73b01e57SJeff Chen */
nxpwifi_dfs_cac_work(struct wiphy * wiphy,struct wiphy_work * work)110*73b01e57SJeff Chen void nxpwifi_dfs_cac_work(struct wiphy *wiphy, struct wiphy_work *work)
111*73b01e57SJeff Chen {
112*73b01e57SJeff Chen struct cfg80211_chan_def chandef;
113*73b01e57SJeff Chen struct wiphy_delayed_work *delayed_work =
114*73b01e57SJeff Chen container_of(work, struct wiphy_delayed_work, work);
115*73b01e57SJeff Chen struct nxpwifi_private *priv = container_of(delayed_work,
116*73b01e57SJeff Chen struct nxpwifi_private,
117*73b01e57SJeff Chen dfs_cac_work);
118*73b01e57SJeff Chen
119*73b01e57SJeff Chen chandef = priv->dfs_chandef;
120*73b01e57SJeff Chen if (priv->wdev.links[0].cac_started) {
121*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
122*73b01e57SJeff Chen "CAC timer finished; No radar detected\n");
123*73b01e57SJeff Chen cfg80211_cac_event(priv->netdev, &chandef,
124*73b01e57SJeff Chen NL80211_RADAR_CAC_FINISHED,
125*73b01e57SJeff Chen GFP_KERNEL, 0);
126*73b01e57SJeff Chen }
127*73b01e57SJeff Chen }
128*73b01e57SJeff Chen
129*73b01e57SJeff Chen /* prepares channel report request command to FW for starting radar detection */
nxpwifi_cmd_issue_chan_report_request(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,void * data_buf)130*73b01e57SJeff Chen int nxpwifi_cmd_issue_chan_report_request(struct nxpwifi_private *priv,
131*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
132*73b01e57SJeff Chen void *data_buf)
133*73b01e57SJeff Chen {
134*73b01e57SJeff Chen struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req;
135*73b01e57SJeff Chen struct nxpwifi_radar_params *radar_params = (void *)data_buf;
136*73b01e57SJeff Chen u16 size;
137*73b01e57SJeff Chen
138*73b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_CHAN_REPORT_REQUEST);
139*73b01e57SJeff Chen size = S_DS_GEN;
140*73b01e57SJeff Chen
141*73b01e57SJeff Chen cr_req->chan_desc.start_freq = cpu_to_le16(NXPWIFI_A_BAND_START_FREQ);
142*73b01e57SJeff Chen nxpwifi_convert_chan_to_band_cfg(priv,
143*73b01e57SJeff Chen &cr_req->chan_desc.band_cfg,
144*73b01e57SJeff Chen radar_params->chandef);
145*73b01e57SJeff Chen cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value;
146*73b01e57SJeff Chen cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
147*73b01e57SJeff Chen size += sizeof(*cr_req);
148*73b01e57SJeff Chen
149*73b01e57SJeff Chen if (radar_params->cac_time_ms) {
150*73b01e57SJeff Chen struct nxpwifi_ie_types_chan_rpt_data *rpt;
151*73b01e57SJeff Chen
152*73b01e57SJeff Chen rpt = (struct nxpwifi_ie_types_chan_rpt_data *)((u8 *)cmd + size);
153*73b01e57SJeff Chen rpt->header.type = cpu_to_le16(TLV_TYPE_CHANRPT_11H_BASIC);
154*73b01e57SJeff Chen rpt->header.len = cpu_to_le16(sizeof(u8));
155*73b01e57SJeff Chen rpt->meas_rpt_map = 1 << MEAS_RPT_MAP_RADAR_SHIFT_BIT;
156*73b01e57SJeff Chen size += sizeof(*rpt);
157*73b01e57SJeff Chen
158*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
159*73b01e57SJeff Chen "11h: issuing DFS Radar check for channel=%d\n",
160*73b01e57SJeff Chen radar_params->chandef->chan->hw_value);
161*73b01e57SJeff Chen } else {
162*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG, "cancelling CAC\n");
163*73b01e57SJeff Chen }
164*73b01e57SJeff Chen
165*73b01e57SJeff Chen cmd->size = cpu_to_le16(size);
166*73b01e57SJeff Chen
167*73b01e57SJeff Chen return 0;
168*73b01e57SJeff Chen }
169*73b01e57SJeff Chen
nxpwifi_stop_radar_detection(struct nxpwifi_private * priv,struct cfg80211_chan_def * chandef)170*73b01e57SJeff Chen int nxpwifi_stop_radar_detection(struct nxpwifi_private *priv,
171*73b01e57SJeff Chen struct cfg80211_chan_def *chandef)
172*73b01e57SJeff Chen {
173*73b01e57SJeff Chen struct nxpwifi_radar_params radar_params;
174*73b01e57SJeff Chen
175*73b01e57SJeff Chen memset(&radar_params, 0, sizeof(struct nxpwifi_radar_params));
176*73b01e57SJeff Chen radar_params.chandef = chandef;
177*73b01e57SJeff Chen radar_params.cac_time_ms = 0;
178*73b01e57SJeff Chen
179*73b01e57SJeff Chen return nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REPORT_REQUEST,
180*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0, &radar_params, true);
181*73b01e57SJeff Chen }
182*73b01e57SJeff Chen
183*73b01e57SJeff Chen /* Abort ongoing CAC when stopping AP operations or during unload */
nxpwifi_abort_cac(struct nxpwifi_private * priv)184*73b01e57SJeff Chen void nxpwifi_abort_cac(struct nxpwifi_private *priv)
185*73b01e57SJeff Chen {
186*73b01e57SJeff Chen if (priv->wdev.links[0].cac_started) {
187*73b01e57SJeff Chen if (nxpwifi_stop_radar_detection(priv, &priv->dfs_chandef))
188*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
189*73b01e57SJeff Chen "failed to stop CAC in FW\n");
190*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
191*73b01e57SJeff Chen "Aborting delayed work for CAC.\n");
192*73b01e57SJeff Chen wiphy_delayed_work_cancel(priv->adapter->wiphy, &priv->dfs_cac_work);
193*73b01e57SJeff Chen cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
194*73b01e57SJeff Chen NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
195*73b01e57SJeff Chen }
196*73b01e57SJeff Chen }
197*73b01e57SJeff Chen
198*73b01e57SJeff Chen /*
199*73b01e57SJeff Chen * handles channel report event from FW during CAC period. If radar is detected
200*73b01e57SJeff Chen * during CAC, driver indicates the same to cfg80211 and also cancels ongoing
201*73b01e57SJeff Chen * delayed work
202*73b01e57SJeff Chen */
nxpwifi_11h_handle_chanrpt_ready(struct nxpwifi_private * priv,struct sk_buff * skb)203*73b01e57SJeff Chen int nxpwifi_11h_handle_chanrpt_ready(struct nxpwifi_private *priv,
204*73b01e57SJeff Chen struct sk_buff *skb)
205*73b01e57SJeff Chen {
206*73b01e57SJeff Chen struct host_cmd_ds_chan_rpt_event *rpt_event;
207*73b01e57SJeff Chen struct nxpwifi_ie_types_chan_rpt_data *rpt;
208*73b01e57SJeff Chen u16 event_len, tlv_len;
209*73b01e57SJeff Chen
210*73b01e57SJeff Chen rpt_event = (void *)(skb->data + sizeof(u32));
211*73b01e57SJeff Chen event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event) +
212*73b01e57SJeff Chen sizeof(u32));
213*73b01e57SJeff Chen
214*73b01e57SJeff Chen if (le32_to_cpu(rpt_event->result) != HOST_RESULT_OK) {
215*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
216*73b01e57SJeff Chen "Error in channel report event\n");
217*73b01e57SJeff Chen return -EINVAL;
218*73b01e57SJeff Chen }
219*73b01e57SJeff Chen
220*73b01e57SJeff Chen while (event_len >= sizeof(struct nxpwifi_ie_types_header)) {
221*73b01e57SJeff Chen rpt = (void *)&rpt_event->tlvbuf;
222*73b01e57SJeff Chen tlv_len = le16_to_cpu(rpt->header.len);
223*73b01e57SJeff Chen
224*73b01e57SJeff Chen switch (le16_to_cpu(rpt->header.type)) {
225*73b01e57SJeff Chen case TLV_TYPE_CHANRPT_11H_BASIC:
226*73b01e57SJeff Chen if (rpt->meas_rpt_map & MEAS_RPT_MAP_RADAR_MASK) {
227*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
228*73b01e57SJeff Chen "RADAR Detected on channel %d!\n",
229*73b01e57SJeff Chen priv->dfs_chandef.chan->hw_value);
230*73b01e57SJeff Chen
231*73b01e57SJeff Chen wiphy_delayed_work_cancel(priv->adapter->wiphy,
232*73b01e57SJeff Chen &priv->dfs_cac_work);
233*73b01e57SJeff Chen cfg80211_cac_event(priv->netdev,
234*73b01e57SJeff Chen &priv->dfs_chandef,
235*73b01e57SJeff Chen NL80211_RADAR_CAC_ABORTED,
236*73b01e57SJeff Chen GFP_KERNEL, 0);
237*73b01e57SJeff Chen cfg80211_radar_event(priv->adapter->wiphy,
238*73b01e57SJeff Chen &priv->dfs_chandef,
239*73b01e57SJeff Chen GFP_KERNEL);
240*73b01e57SJeff Chen }
241*73b01e57SJeff Chen break;
242*73b01e57SJeff Chen default:
243*73b01e57SJeff Chen break;
244*73b01e57SJeff Chen }
245*73b01e57SJeff Chen
246*73b01e57SJeff Chen event_len -= (tlv_len + sizeof(rpt->header));
247*73b01e57SJeff Chen }
248*73b01e57SJeff Chen
249*73b01e57SJeff Chen return 0;
250*73b01e57SJeff Chen }
251*73b01e57SJeff Chen
252*73b01e57SJeff Chen /* Handler for radar detected event from FW */
nxpwifi_11h_handle_radar_detected(struct nxpwifi_private * priv,struct sk_buff * skb)253*73b01e57SJeff Chen int nxpwifi_11h_handle_radar_detected(struct nxpwifi_private *priv,
254*73b01e57SJeff Chen struct sk_buff *skb)
255*73b01e57SJeff Chen {
256*73b01e57SJeff Chen struct nxpwifi_radar_det_event *rdr_event;
257*73b01e57SJeff Chen
258*73b01e57SJeff Chen rdr_event = (void *)(skb->data + sizeof(u32));
259*73b01e57SJeff Chen
260*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
261*73b01e57SJeff Chen "radar detected; indicating kernel\n");
262*73b01e57SJeff Chen
263*73b01e57SJeff Chen if (priv->wdev.links[0].cac_started) {
264*73b01e57SJeff Chen if (nxpwifi_stop_radar_detection(priv, &priv->dfs_chandef))
265*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
266*73b01e57SJeff Chen "Failed to stop CAC in FW\n");
267*73b01e57SJeff Chen wiphy_delayed_work_cancel(priv->adapter->wiphy, &priv->dfs_cac_work);
268*73b01e57SJeff Chen cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
269*73b01e57SJeff Chen NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
270*73b01e57SJeff Chen }
271*73b01e57SJeff Chen cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
272*73b01e57SJeff Chen GFP_KERNEL);
273*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG, "regdomain: %d\n",
274*73b01e57SJeff Chen rdr_event->reg_domain);
275*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG, "radar detection type: %d\n",
276*73b01e57SJeff Chen rdr_event->det_type);
277*73b01e57SJeff Chen
278*73b01e57SJeff Chen return 0;
279*73b01e57SJeff Chen }
280*73b01e57SJeff Chen
281*73b01e57SJeff Chen /*
282*73b01e57SJeff Chen * work function for channel switch handling. takes care of updating new channel
283*73b01e57SJeff Chen * definitin to bss config structure, restart AP and indicate channel switch
284*73b01e57SJeff Chen * success to cfg80211
285*73b01e57SJeff Chen */
nxpwifi_dfs_chan_sw_work(struct wiphy * wiphy,struct wiphy_work * work)286*73b01e57SJeff Chen void nxpwifi_dfs_chan_sw_work(struct wiphy *wiphy, struct wiphy_work *work)
287*73b01e57SJeff Chen {
288*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg;
289*73b01e57SJeff Chen struct wiphy_delayed_work *delayed_work =
290*73b01e57SJeff Chen container_of(work, struct wiphy_delayed_work, work);
291*73b01e57SJeff Chen struct nxpwifi_private *priv = container_of(delayed_work,
292*73b01e57SJeff Chen struct nxpwifi_private,
293*73b01e57SJeff Chen dfs_chan_sw_work);
294*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
295*73b01e57SJeff Chen
296*73b01e57SJeff Chen if (nxpwifi_del_mgmt_ies(priv))
297*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
298*73b01e57SJeff Chen "Failed to delete mgmt IEs!\n");
299*73b01e57SJeff Chen
300*73b01e57SJeff Chen bss_cfg = &priv->bss_cfg;
301*73b01e57SJeff Chen if (!bss_cfg->beacon_period) {
302*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
303*73b01e57SJeff Chen "channel switch: AP already stopped\n");
304*73b01e57SJeff Chen return;
305*73b01e57SJeff Chen }
306*73b01e57SJeff Chen
307*73b01e57SJeff Chen if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP,
308*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0, NULL, true)) {
309*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
310*73b01e57SJeff Chen "channel switch: Failed to stop the BSS\n");
311*73b01e57SJeff Chen return;
312*73b01e57SJeff Chen }
313*73b01e57SJeff Chen
314*73b01e57SJeff Chen if (nxpwifi_cfg80211_change_beacon(adapter->wiphy, priv->netdev,
315*73b01e57SJeff Chen &priv->ap_update_info)) {
316*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
317*73b01e57SJeff Chen "channel switch: Failed to set beacon\n");
318*73b01e57SJeff Chen return;
319*73b01e57SJeff Chen }
320*73b01e57SJeff Chen
321*73b01e57SJeff Chen nxpwifi_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
322*73b01e57SJeff Chen
323*73b01e57SJeff Chen if (nxpwifi_config_start_uap(priv, bss_cfg)) {
324*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
325*73b01e57SJeff Chen "Failed to start AP after channel switch\n");
326*73b01e57SJeff Chen return;
327*73b01e57SJeff Chen }
328*73b01e57SJeff Chen
329*73b01e57SJeff Chen nxpwifi_dbg(adapter, MSG,
330*73b01e57SJeff Chen "indicating channel switch completion to kernel\n");
331*73b01e57SJeff Chen
332*73b01e57SJeff Chen cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0);
333*73b01e57SJeff Chen
334*73b01e57SJeff Chen if (priv->uap_stop_tx) {
335*73b01e57SJeff Chen netif_carrier_on(priv->netdev);
336*73b01e57SJeff Chen nxpwifi_wake_up_net_dev_queue(priv->netdev, adapter);
337*73b01e57SJeff Chen priv->uap_stop_tx = false;
338*73b01e57SJeff Chen }
339*73b01e57SJeff Chen }
340