1 /******************************************************************************
2 *
3 * Copyright(c) 2019 - 2021 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _RTW_CSA_C_
16 #include <drv_types.h>
17
18 #if CONFIG_DFS
reset_csa_param(struct rf_ctl_t * rfctl)19 void reset_csa_param(struct rf_ctl_t *rfctl)
20 {
21 rfctl->csa_mode = 0;
22 rfctl->csa_switch_cnt = 0;
23 rfctl->csa_ch_width = 0;
24 _rtw_memset(&(rfctl->csa_chandef), 0, sizeof(struct rtw_chan_def));
25 }
26
27 /* Get ch/bw/offset of CSA from rfctl, and check these parameters is valid or not */
rtw_get_csa_setting(struct dvobj_priv * d,s16 * req_ch,u8 * req_bw,u8 * req_offset)28 bool rtw_get_csa_setting(struct dvobj_priv *d, s16 *req_ch, u8 *req_bw, u8 *req_offset)
29 {
30 struct rf_ctl_t *rfctl = dvobj_to_rfctl(d);
31 struct _ADAPTER *a = dvobj_get_primary_adapter(d);
32 u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(a);
33 bool valid = _TRUE;
34
35 *req_ch = REQ_CH_NONE;
36 *req_bw = CHANNEL_WIDTH_20;
37 *req_offset = CHAN_OFFSET_NO_EXT;
38
39 if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_chandef.chan) >= 0
40 && !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_chandef.chan)
41 ) {
42 /* CSA channel available and valid */
43 *req_ch = rfctl->csa_chandef.chan;
44 RTW_INFO("CSA : "FUNC_ADPT_FMT" valid CSA ch%u\n", FUNC_ADPT_ARG(a),
45 rfctl->csa_chandef.chan);
46 } else if (ifbmp_m) {
47 /* no available or valid CSA channel, having AP/MESH ifaces */
48 *req_ch = REQ_CH_NONE;
49 valid = _FALSE;
50 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch sel by AP/MESH ifaces\n", FUNC_ADPT_ARG(a));
51 goto exit;
52 } else {
53 /* no available or valid CSA channel and no AP/MESH ifaces */
54 if (!is_supported_24g(dvobj_to_regsty(d)->band_type))
55 *req_ch = 36;
56 else
57 *req_ch = 1;
58 valid = _FALSE;
59 RTW_INFO("CSA : "FUNC_ADPT_FMT" switch to ch%d, then disconnect with AP\n",
60 FUNC_ADPT_ARG(a), *req_ch);
61 goto exit;
62 }
63
64 if (rfctl->csa_ch_width == 1) {
65 *req_bw = CHANNEL_WIDTH_80;
66 *req_offset = rfctl->csa_chandef.offset;
67 } else if (rfctl->csa_ch_width == 0 && rfctl->csa_chandef.offset != CHAN_OFFSET_NO_EXT) {
68 *req_bw = CHANNEL_WIDTH_40;
69 *req_offset = rfctl->csa_chandef.offset;
70 } else {
71 *req_bw = CHANNEL_WIDTH_20;
72 *req_offset = CHAN_OFFSET_NO_EXT;
73 }
74
75 /* get correct offset and check ch/bw/offset is valid or not */
76 if (!rtw_get_offset_by_chbw(*req_ch, *req_bw, req_offset)) {
77 *req_bw = CHANNEL_WIDTH_20;
78 *req_offset = CHAN_OFFSET_NO_EXT;
79 }
80
81 exit:
82 return valid;
83 }
84
85 #ifdef CONFIG_ECSA_PHL
reset_ecsa_param(struct _ADAPTER * a)86 static void reset_ecsa_param(struct _ADAPTER *a)
87 {
88 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
89 struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param);
90
91 SET_ECSA_STATE(a, ECSA_ST_NONE);
92 ecsa_info->ecsa_allow_case = 0;
93 ecsa_info->ecsa_delay_time = 0;
94 ecsa_info->channel_width = 0;
95 ecsa_info->bss_param = NULL;
96 _rtw_memset(ecsa_param, 0, sizeof(struct rtw_phl_ecsa_param));
97 }
98
rtw_mr_is_ecsa_running(struct _ADAPTER * a)99 bool rtw_mr_is_ecsa_running(struct _ADAPTER *a)
100 {
101 struct dvobj_priv *d = adapter_to_dvobj(a);
102 struct _ADAPTER *iface;
103 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
104 u8 i;
105
106 for (i = 0; i < d->iface_nums; i++) {
107 iface = d->padapters[i];
108 if (!iface)
109 continue;
110 if (!CHK_ECSA_STATE(iface, ECSA_ST_NONE))
111 return _TRUE;
112 }
113 return _FALSE;
114 }
115
rtw_ecsa_update_sta_chan_info(struct _ADAPTER * a,struct rtw_chan_def new_chan_def)116 static void rtw_ecsa_update_sta_chan_info(struct _ADAPTER *a, struct rtw_chan_def new_chan_def)
117 {
118 struct mlme_ext_priv *pmlmeext = &a->mlmeextpriv;
119 struct mlme_priv *pmlmepriv = &a->mlmepriv;
120 struct dvobj_priv *d = adapter_to_dvobj(a);
121 struct rf_ctl_t *rfctl = dvobj_to_rfctl(d);
122 u8 new_ch = new_chan_def.chan;
123 u8 new_bw = (u8)new_chan_def.bw;
124 u8 new_offset = (u8)new_chan_def.offset;
125 bool is_chctx_add = _FALSE;
126
127 pmlmeext->chandef.chan= new_ch;
128 pmlmeext->chandef.bw = new_bw;
129 pmlmeext->chandef.offset = new_offset;
130 pmlmepriv->cur_network.network.Configuration.DSConfig = new_ch;
131
132 /* update wifi role chandef */
133 rtw_hw_update_chan_def(a);
134
135 /* update chanctx */
136 rtw_phl_chanctx_del(d->phl, a->phl_role, NULL);
137 is_chctx_add = rtw_phl_chanctx_add(d->phl, a->phl_role,
138 &new_chan_def.chan, &new_chan_def.bw, &new_chan_def.offset);
139 if (is_chctx_add == _FALSE)
140 RTW_ERR("CSA : "FUNC_ADPT_FMT" chan_ctx add fail!", FUNC_ADPT_ARG(a));
141
142 set_fwstate(pmlmepriv, WIFI_CSA_UPDATE_BEACON);
143
144 /* STA wait 70 seconds for receiving beacons in DFS channel */
145 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, new_ch, new_bw, new_offset)) {
146 RTW_INFO("CSA : set csa_timer to 70 seconds\n");
147 _set_timer(&pmlmeext->csa_timer, CAC_TIME_MS + 10000);
148 }
149
150 #ifdef CONFIG_DFS_MASTER
151 rtw_dfs_rd_en_decision(a, MLME_OPCH_SWITCH, 0);
152 #endif
153 }
154
rtw_ecsa_update_ap_chan_info(struct _ADAPTER * a,struct rtw_chan_def new_chan_def)155 static void rtw_ecsa_update_ap_chan_info(struct _ADAPTER *a, struct rtw_chan_def new_chan_def)
156 {
157 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
158 struct createbss_parm *parm;
159
160 ecsa_info->bss_param = (struct createbss_parm *)rtw_zmalloc(sizeof(struct createbss_parm));
161 if (ecsa_info->bss_param) {
162 parm = ecsa_info->bss_param;
163 parm->adhoc = 0;
164 parm->ifbmp = BIT(a->iface_id);
165 parm->excl_ifbmp = 0;
166 parm->req_ch = new_chan_def.chan;
167 parm->req_bw = new_chan_def.bw;
168 parm->req_offset = new_chan_def.offset;
169 parm->ifbmp_ch_changed = 0;
170 parm->ch_to_set = 0;
171 parm->bw_to_set = 0;
172 parm->offset_to_set = 0;
173 parm->do_rfk = _FALSE;
174
175 start_bss_network(a, parm);
176 } else {
177 RTW_ERR("CSA : can't allocate memory for bss_param\n");
178 }
179 }
180
rtw_ecsa_update_probe_resp(struct xmit_frame * xframe)181 void rtw_ecsa_update_probe_resp(struct xmit_frame *xframe)
182 {
183 struct _ADAPTER *a = xframe->padapter;
184 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
185 struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param);
186 struct pkt_attrib *pattrib = &xframe->attrib;
187 u8 hdr_len = sizeof(struct rtw_ieee80211_hdr_3addr);
188 u8 *ies;
189 sint ies_len;
190 u8 *csa_ie;
191 sint csa_ie_len;
192
193 ies = xframe->buf_addr + TXDESC_OFFSET + hdr_len + _BEACON_IE_OFFSET_;
194 ies_len = pattrib->pktlen - hdr_len - _BEACON_IE_OFFSET_;
195
196 csa_ie = rtw_get_ie(ies, WLAN_EID_CHANNEL_SWITCH, &csa_ie_len, ies_len);
197
198 if (csa_ie == NULL)
199 return;
200
201 csa_ie[2 + CSA_SWITCH_COUNT] = ecsa_param->count;
202
203 #ifdef DBG_CSA
204 RTW_INFO("CSA : update csa count of probe response = %u\n", csa_ie[2 + CSA_SWITCH_COUNT]);
205 #endif
206 }
207
rtw_ecsa_update_beacon(void * priv,struct rtw_wifi_role_t * role)208 void rtw_ecsa_update_beacon(void *priv, struct rtw_wifi_role_t *role)
209 {
210 #ifdef CONFIG_AP_MODE
211 struct dvobj_priv *d = (struct dvobj_priv *)priv;
212 struct _ADAPTER *a = d->padapters[role->id];
213 _update_beacon(a, WLAN_EID_CHANNEL_SWITCH, NULL, _TRUE, 0, "update CSA count");
214 #endif
215 }
216
217 /* PHL MR module check core layer if AP mode can switch channel now */
rtw_ap_check_ecsa_allow(void * priv,struct rtw_wifi_role_t * role,struct rtw_chan_def chan_def,enum phl_ecsa_start_reason reason,u32 * delay_start_ms)218 bool rtw_ap_check_ecsa_allow(
219 void *priv,
220 struct rtw_wifi_role_t *role,
221 struct rtw_chan_def chan_def,
222 enum phl_ecsa_start_reason reason,
223 u32 *delay_start_ms
224 )
225 {
226 struct dvobj_priv *d = (struct dvobj_priv *)priv;
227 struct _ADAPTER *a = d->padapters[role->id];
228 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
229 bool ecsa_allow = _TRUE;
230 u8 i;
231
232 /* TODO : need to check MCC-ECSA case */
233 /* if (!(ecsa_info->ecsa_allow_case & BIT(reason))) { */
234 if (0) {
235 RTW_INFO("CSA : "FUNC_ADPT_FMT" : Case %u not support!\n", FUNC_ADPT_ARG(a), reason);
236 ecsa_allow = _FALSE;
237 goto exit;
238 }
239
240 /* Check DFS channel */
241 if (!rtw_phl_regulation_valid_channel(GET_PHL_INFO(d),
242 chan_def.band,
243 chan_def.chan,
244 (CH_PASSIVE | CH_DFS))) {
245 RTW_ERR("CSA : "FUNC_ADPT_FMT" : DFS channel (%u) not support!\n",
246 FUNC_ADPT_ARG(a), chan_def.chan);
247 ecsa_allow = _FALSE;
248 goto exit;
249 }
250
251 if (ecsa_info->ecsa_delay_time != 0)
252 *delay_start_ms = ecsa_info->ecsa_delay_time;
253 else if (reason <= ECSA_START_MCC_5G_TO_24G)
254 *delay_start_ms = MCC_ECSA_DELAY_START_TIME;
255 RTW_INFO("CSA : %s : ECSA will delay %u ms\n", __func__, *delay_start_ms);
256
257 SET_ECSA_STATE(a, ECSA_ST_SW_START);
258 exit:
259 return ecsa_allow;
260 }
261
rtw_ecsa_mr_update_chan_info_by_role(void * priv,struct rtw_wifi_role_t * role,struct rtw_chan_def new_chan_def)262 void rtw_ecsa_mr_update_chan_info_by_role(
263 void *priv,
264 struct rtw_wifi_role_t *role,
265 struct rtw_chan_def new_chan_def
266 )
267 {
268 struct dvobj_priv *d = (struct dvobj_priv *)priv;
269 struct _ADAPTER *a = d->padapters[role->id];
270 struct mlme_ext_priv *pmlmeext = &a->mlmeextpriv;
271 struct mlme_priv *pmlmepriv = &a->mlmepriv;
272
273 RTW_INFO("CSA : "FUNC_ADPT_FMT", new ch/bw/offset = %u,%u,%u\n", FUNC_ADPT_ARG(a), \
274 new_chan_def.chan, new_chan_def.bw, new_chan_def.offset);
275
276 if (role->type == PHL_RTYPE_STATION || role->type == PHL_RTYPE_P2P_GC)
277 rtw_ecsa_update_sta_chan_info(a, new_chan_def);
278 else if (role->type == PHL_RTYPE_AP ||role->type == PHL_RTYPE_P2P_GO)
279 rtw_ecsa_update_ap_chan_info(a, new_chan_def);
280 }
281
rtw_ecsa_check_tx_resume_allow(void * priv,struct rtw_wifi_role_t * role)282 bool rtw_ecsa_check_tx_resume_allow(void *priv, struct rtw_wifi_role_t *role)
283 {
284 /* TODO */
285 /* Is DFS slave still monitoring channel ?
286 If Yes, return False to PHL; If no, return True to PHL */
287 struct dvobj_priv *d = (struct dvobj_priv *)priv;
288 struct _ADAPTER *a = d->padapters[role->id];
289
290 RTW_INFO("CSA : "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(a));
291 return 1;
292 }
293
rtw_ecsa_complete(void * priv,struct rtw_wifi_role_t * role)294 void rtw_ecsa_complete(void *priv, struct rtw_wifi_role_t *role)
295 {
296 struct dvobj_priv *d = (struct dvobj_priv *)priv;
297 struct _ADAPTER *a = d->padapters[role->id];
298 struct rf_ctl_t *rfctl = dvobj_to_rfctl(d);
299 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
300 struct createbss_parm *parm = ecsa_info->bss_param;
301 u8 i, ht_option = 0;
302
303 RTW_INFO("CSA : "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(a));
304 rtw_phl_mr_dump_cur_chandef(d->phl, role);
305
306 if (role->type == PHL_RTYPE_STATION || role->type == PHL_RTYPE_P2P_GC) {
307 /*
308 * TODO
309 * STA mode need to update RA if it receive CHANNEL_SWITCH_WRAPPER IE
310 * STA mode update its RA at rtw_check_bcn_info() now
311 */
312 rtw_rfctl_update_op_mode(rfctl, 0, 0);
313 } else if (role->type == PHL_RTYPE_AP ||role->type == PHL_RTYPE_P2P_GO) {
314 #if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
315 for (i = 0; i < d->iface_nums; i++) {
316 if (!(parm->ifbmp_ch_changed & BIT(i)) || !d->padapters[i])
317 continue;
318
319 #ifdef CONFIG_80211N_HT
320 ht_option = d->padapters[i]->mlmepriv.htpriv.ht_option;
321 #endif
322
323 rtw_cfg80211_ch_switch_notify(d->padapters[i]
324 , d->padapters[i]->mlmeextpriv.chandef.chan
325 , d->padapters[i]->mlmeextpriv.chandef.bw
326 , d->padapters[i]->mlmeextpriv.chandef.offset
327 , ht_option, 0);
328 }
329 #endif
330 rtw_rfctl_update_op_mode(adapter_to_rfctl(a), parm->ifbmp, 1);
331
332 rtw_core_ap_start(a, parm);
333
334 rtw_ap_update_clients_rainfo(a, PHL_CMD_DIRECTLY);
335
336 rtw_mfree((u8 *)parm, sizeof(struct createbss_parm));
337 }
338
339 rtw_mi_os_xmit_schedule(a);
340
341 reset_ecsa_param(a);
342 }
343
344 /* Get ch/bw/offset of CSA from adapter, and check these parameters is valid or not */
rtw_sta_get_ecsa_setting(struct _ADAPTER * a,s16 * req_ch,u8 * req_bw,u8 * req_offset)345 static bool rtw_sta_get_ecsa_setting(struct _ADAPTER *a, s16 *req_ch, u8 *req_bw, u8 *req_offset)
346 {
347 struct rf_ctl_t *rfctl = adapter_to_rfctl(a);
348 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
349 struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param);
350 u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(a);
351 u8 csa_chan = ecsa_param->new_chan_def.chan;
352 u8 csa_offset = ecsa_param->new_chan_def.offset;
353 bool valid = _TRUE;
354
355 *req_ch = REQ_CH_NONE;
356 *req_bw = CHANNEL_WIDTH_20;
357 *req_offset = CHAN_OFFSET_NO_EXT;
358
359 if (rtw_chset_search_ch(rfctl->channel_set, csa_chan) >= 0
360 && !rtw_chset_is_ch_non_ocp(rfctl->channel_set, csa_chan)
361 ) {
362 /* CSA channel available and valid */
363 *req_ch = csa_chan;
364 RTW_INFO("CSA : "FUNC_ADPT_FMT" valid CSA ch%u\n", FUNC_ADPT_ARG(a), csa_chan);
365 } else if (ifbmp_m) {
366 /* no available or valid CSA channel, having AP/MESH ifaces */
367 *req_ch = REQ_CH_NONE;
368 valid = _FALSE;
369 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch sel by AP/MESH ifaces\n", FUNC_ADPT_ARG(a));
370 goto exit;
371 } else {
372 /* no available or valid CSA channel and no AP/MESH ifaces */
373 /* TODO : DFS slave may need to switch channel as soon as possible before disconnect */
374 #if 0
375 if (!is_supported_24g(adapter_to_regsty(a)->band_type))
376 *req_ch = 36;
377 else
378 *req_ch = 1;
379 #endif
380 valid = _FALSE;
381 RTW_INFO("CSA : "FUNC_ADPT_FMT" switch to ch %d, then disconnect with AP\n",
382 FUNC_ADPT_ARG(a), *req_ch);
383 goto exit;
384 }
385
386 /* Transform channel_width to bandwidth 20/40/80M */
387 if (ecsa_info->channel_width == 1) {
388 *req_bw = CHANNEL_WIDTH_80;
389 *req_offset = csa_offset;
390 } else if (ecsa_info->channel_width == 0 && csa_offset != CHAN_OFFSET_NO_EXT) {
391 *req_bw = CHANNEL_WIDTH_40;
392 *req_offset = csa_offset;
393 } else {
394 *req_bw = CHANNEL_WIDTH_20;
395 *req_offset = CHAN_OFFSET_NO_EXT;
396 }
397
398 /* Get correct offset and check ch/bw/offset is valid or not */
399 if (!rtw_get_offset_by_chbw(*req_ch, *req_bw, req_offset)) {
400 *req_bw = CHANNEL_WIDTH_20;
401 *req_offset = CHAN_OFFSET_NO_EXT;
402 }
403
404 /* Update result to ecsa_param */
405 ecsa_param->new_chan_def.chan = *req_ch;
406 ecsa_param->new_chan_def.bw = *req_bw;
407 ecsa_param->new_chan_def.offset = *req_offset;
408
409 exit:
410 return valid;
411 }
412
rtw_sta_ecsa_invalid_hdl(struct _ADAPTER * a,s16 req_ch,u8 req_bw,u8 req_offset)413 static void rtw_sta_ecsa_invalid_hdl(struct _ADAPTER *a, s16 req_ch, u8 req_bw, u8 req_offset)
414 {
415 struct dvobj_priv *d = adapter_to_dvobj(a);
416 struct rf_ctl_t *rfctl = dvobj_to_rfctl(d);
417 struct mlme_ext_priv *pmlmeext = &a->mlmeextpriv;
418 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
419 u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(a);
420 struct rtw_chan_def mr_chdef = {0};
421
422 if (!ifbmp_s)
423 return;
424
425 set_fwstate(&a->mlmepriv, WIFI_OP_CH_SWITCHING);
426 issue_deauth(a, get_bssid(&a->mlmepriv), WLAN_REASON_DEAUTH_LEAVING);
427
428 /* Decide whether enable DFS slave radar detection or not */
429 #ifdef CONFIG_DFS_MASTER
430 rtw_dfs_rd_en_decision(a, MLME_OPCH_SWITCH, ifbmp_s);
431 #endif
432
433 /* TODO : DFS slave may need to switch channel as soon as possible before disconnect */
434
435 /* This context can't I/O, so use RTW_CMDF_DIRECTLY */
436 rtw_disassoc_cmd(a, 0, RTW_CMDF_DIRECTLY);
437 rtw_indicate_disconnect(a, 0, _FALSE);
438 #ifndef CONFIG_STA_CMD_DISPR
439 rtw_free_assoc_resources(a, _TRUE);
440 #endif
441 rtw_free_network_queue(a, _TRUE);
442 RTW_INFO("CSA : "FUNC_ADPT_FMT" disconnect with AP\n", FUNC_ADPT_ARG(a));
443
444 pmlmeinfo->disconnect_occurred_time = rtw_systime_to_ms(rtw_get_current_time());
445 pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_INVALID_CSA;
446 pmlmeinfo->wifi_reason_code = WLAN_REASON_DEAUTH_LEAVING;
447
448 reset_ecsa_param(a);
449
450 rtw_mi_os_xmit_schedule(a);
451 }
452
rtw_trigger_phl_ecsa_start(struct _ADAPTER * a)453 void rtw_trigger_phl_ecsa_start(struct _ADAPTER *a)
454 {
455 struct dvobj_priv *d = adapter_to_dvobj(a);
456 struct rtw_wifi_role_t *role = a->phl_role;
457 struct core_ecsa_info *ecsa_info = &(a->ecsa_info);
458 struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param);
459
460 /* STA need to check ecsa setting */
461 if (ecsa_param->ecsa_type == ECSA_TYPE_STA) {
462 s16 req_ch;
463 u8 req_bw, req_offset;
464
465 if (!rtw_sta_get_ecsa_setting(a, &req_ch, &req_bw, &req_offset)) {
466 /* we should handle error case by core layer self */
467 rtw_sta_ecsa_invalid_hdl(a, req_ch, req_bw, req_offset);
468 return;
469 }
470 }
471
472 if (rtw_phl_ecsa_start(GET_PHL_INFO(d), role, ecsa_param) != RTW_PHL_STATUS_SUCCESS)
473 RTW_ERR("CSA : Start PHL ECSA fail\n");
474
475 #if 0 /* TODO : ECSA */
476 if(0) {
477 if(!rtw_phl_get_chandef_from_operating_class(param.ch,
478 param.op_class,
479 &(param.new_chan_def))){
480 RTW_INFO("[CSA] Get chandef fail!Use 20 MHz to switch\n");
481 param.new_chan_def.band = rtw_phl_get_band_type(param.ch);
482 param.new_chan_def.chan = param.ch;
483 param.new_chan_def.bw = CHANNEL_WIDTH_20;
484 param.new_chan_def.offset = CHAN_OFFSET_NO_EXT;
485 }
486 }
487 #endif
488 }
489 #endif /* CONFIG_ECSA_PHL */
490 #endif /* CONFIG_DFS */
491