xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: wlan_cm_api.c
20  *
21  * This file maintains definitaions public apis.
22  */
23 
24 #include <wlan_cm_api.h>
25 #include "connection_mgr/core/src/wlan_cm_main_api.h"
26 #include "connection_mgr/core/src/wlan_cm_roam.h"
27 #include <wlan_vdev_mgr_utils_api.h>
28 
29 QDF_STATUS wlan_cm_start_connect(struct wlan_objmgr_vdev *vdev,
30 				 struct wlan_cm_connect_req *req)
31 {
32 	return cm_connect_start_req(vdev, req);
33 }
34 
35 QDF_STATUS wlan_cm_disconnect(struct wlan_objmgr_vdev *vdev,
36 			      enum wlan_cm_source source,
37 			      enum wlan_reason_code reason_code,
38 			      struct qdf_mac_addr *bssid)
39 {
40 	struct wlan_cm_disconnect_req req = {0};
41 
42 	req.vdev_id = wlan_vdev_get_id(vdev);
43 	req.source = source;
44 	req.reason_code = reason_code;
45 	if (bssid)
46 		qdf_copy_macaddr(&req.bssid, bssid);
47 
48 	return cm_disconnect_start_req(vdev, &req);
49 }
50 
51 QDF_STATUS wlan_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev,
52 				   enum wlan_cm_source source,
53 				   enum wlan_reason_code reason_code)
54 {
55 	struct wlan_cm_disconnect_req req = {0};
56 
57 	req.vdev_id = wlan_vdev_get_id(vdev);
58 	req.source = source;
59 	req.reason_code = reason_code;
60 
61 	return cm_disconnect_start_req_sync(vdev, &req);
62 }
63 
64 QDF_STATUS wlan_cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
65 				      QDF_STATUS status)
66 {
67 	return cm_bss_select_ind_rsp(vdev, status);
68 }
69 
70 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
71 				       QDF_STATUS status,
72 				       struct qdf_mac_addr *peer_mac)
73 {
74 	uint32_t prefix;
75 	struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev);
76 
77 	if (!cm_ctx)
78 		return QDF_STATUS_E_INVAL;
79 
80 	prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id);
81 	if (prefix == ROAM_REQ_PREFIX)
82 		return cm_roam_bss_peer_create_rsp(vdev, status, peer_mac);
83 	else
84 		return cm_bss_peer_create_rsp(vdev, status, peer_mac);
85 }
86 
87 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
88 			       struct wlan_cm_connect_resp *resp)
89 {
90 	return cm_connect_rsp(vdev, resp);
91 }
92 
93 QDF_STATUS wlan_cm_bss_peer_delete_ind(struct wlan_objmgr_vdev *vdev,
94 				       struct qdf_mac_addr *peer_mac)
95 {
96 	return cm_bss_peer_delete_req(vdev, peer_mac);
97 }
98 
99 QDF_STATUS wlan_cm_bss_peer_delete_rsp(struct wlan_objmgr_vdev *vdev,
100 				       uint32_t status)
101 {
102 	return cm_vdev_down_req(vdev, status);
103 }
104 
105 QDF_STATUS wlan_cm_disconnect_rsp(struct wlan_objmgr_vdev *vdev,
106 				  struct wlan_cm_discon_rsp *resp)
107 {
108 	uint32_t prefix;
109 	struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev);
110 
111 	if (!cm_ctx)
112 		return QDF_STATUS_E_INVAL;
113 
114 	prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id);
115 	if (prefix == ROAM_REQ_PREFIX)
116 		return cm_roam_disconnect_rsp(vdev, resp);
117 	else
118 		return cm_disconnect_rsp(vdev, resp);
119 }
120 
121 #ifdef WLAN_FEATURE_HOST_ROAM
122 QDF_STATUS wlan_cm_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
123 			       struct wlan_cm_connect_resp *resp)
124 {
125 	return cm_reassoc_rsp(vdev, resp);
126 }
127 #endif
128 
129 void wlan_cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev,
130 				      uint8_t max_connect_attempts)
131 {
132 	cm_set_max_connect_attempts(vdev, max_connect_attempts);
133 }
134 
135 void wlan_cm_set_max_connect_timeout(struct wlan_objmgr_vdev *vdev,
136 				     uint32_t max_connect_timeout)
137 {
138 	cm_set_max_connect_timeout(vdev, max_connect_timeout);
139 }
140 
141 bool wlan_cm_is_vdev_connecting(struct wlan_objmgr_vdev *vdev)
142 {
143 	return cm_is_vdev_connecting(vdev);
144 }
145 
146 bool wlan_cm_is_vdev_connected(struct wlan_objmgr_vdev *vdev)
147 {
148 	return cm_is_vdev_connected(vdev);
149 }
150 
151 bool wlan_cm_is_vdev_active(struct wlan_objmgr_vdev *vdev)
152 {
153 	return cm_is_vdev_active(vdev);
154 }
155 
156 bool wlan_cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev)
157 {
158 	return cm_is_vdev_disconnecting(vdev);
159 }
160 
161 bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev)
162 {
163 	return cm_is_vdev_disconnected(vdev);
164 }
165 
166 bool wlan_cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
167 {
168 	return cm_is_vdev_roaming(vdev);
169 }
170 
171 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
172 bool wlan_cm_is_vdev_roam_started(struct wlan_objmgr_vdev *vdev)
173 {
174 	return cm_is_vdev_roam_started(vdev);
175 }
176 
177 bool wlan_cm_is_vdev_roam_sync_inprogress(struct wlan_objmgr_vdev *vdev)
178 {
179 	return cm_is_vdev_roam_sync_inprogress(vdev);
180 }
181 #endif
182 
183 #ifdef WLAN_FEATURE_HOST_ROAM
184 bool wlan_cm_is_vdev_roam_preauth_state(struct wlan_objmgr_vdev *vdev)
185 {
186 	return cm_is_vdev_roam_preauth_state(vdev);
187 }
188 
189 bool wlan_cm_is_vdev_roam_reassoc_state(struct wlan_objmgr_vdev *vdev)
190 {
191 	return cm_is_vdev_roam_reassoc_state(vdev);
192 }
193 #endif
194 
195 enum wlan_cm_active_request_type
196 wlan_cm_get_active_req_type(struct wlan_objmgr_vdev *vdev)
197 {
198 	return cm_get_active_req_type(vdev);
199 }
200 
201 bool wlan_cm_get_active_connect_req(struct wlan_objmgr_vdev *vdev,
202 				    struct wlan_cm_vdev_connect_req *req)
203 {
204 	return cm_get_active_connect_req(vdev, req);
205 }
206 
207 cm_ext_t *wlan_cm_get_ext_hdl(struct wlan_objmgr_vdev *vdev)
208 {
209 	return cm_get_ext_hdl(vdev);
210 }
211 
212 #ifdef WLAN_FEATURE_HOST_ROAM
213 bool wlan_cm_get_active_reassoc_req(struct wlan_objmgr_vdev *vdev,
214 				    struct wlan_cm_vdev_reassoc_req *req)
215 {
216 	return cm_get_active_reassoc_req(vdev, req);
217 }
218 #endif
219 
220 bool wlan_cm_get_active_disconnect_req(struct wlan_objmgr_vdev *vdev,
221 				       struct wlan_cm_vdev_discon_req *req)
222 {
223 	return cm_get_active_disconnect_req(vdev, req);
224 }
225 
226 const char *wlan_cm_reason_code_to_str(enum wlan_reason_code reason)
227 {
228 	if (reason > REASON_PROP_START)
229 		return "";
230 
231 	switch (reason) {
232 	CASE_RETURN_STRING(REASON_UNSPEC_FAILURE);
233 	CASE_RETURN_STRING(REASON_PREV_AUTH_NOT_VALID);
234 	CASE_RETURN_STRING(REASON_DEAUTH_NETWORK_LEAVING);
235 	CASE_RETURN_STRING(REASON_DISASSOC_DUE_TO_INACTIVITY);
236 	CASE_RETURN_STRING(REASON_DISASSOC_AP_BUSY);
237 	CASE_RETURN_STRING(REASON_CLASS2_FRAME_FROM_NON_AUTH_STA);
238 	CASE_RETURN_STRING(REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA);
239 	CASE_RETURN_STRING(REASON_DISASSOC_NETWORK_LEAVING);
240 	CASE_RETURN_STRING(REASON_STA_NOT_AUTHENTICATED);
241 	CASE_RETURN_STRING(REASON_BAD_PWR_CAPABILITY);
242 	CASE_RETURN_STRING(REASON_BAD_SUPPORTED_CHANNELS);
243 	CASE_RETURN_STRING(REASON_DISASSOC_BSS_TRANSITION);
244 	CASE_RETURN_STRING(REASON_INVALID_IE);
245 	CASE_RETURN_STRING(REASON_MIC_FAILURE);
246 	CASE_RETURN_STRING(REASON_4WAY_HANDSHAKE_TIMEOUT);
247 	CASE_RETURN_STRING(REASON_GROUP_KEY_UPDATE_TIMEOUT);
248 	CASE_RETURN_STRING(REASON_IN_4WAY_DIFFERS);
249 	CASE_RETURN_STRING(REASON_INVALID_GROUP_CIPHER);
250 	CASE_RETURN_STRING(REASON_INVALID_PAIRWISE_CIPHER);
251 	CASE_RETURN_STRING(REASON_INVALID_AKMP);
252 	CASE_RETURN_STRING(REASON_UNSUPPORTED_RSNE_VER);
253 	CASE_RETURN_STRING(REASON_INVALID_RSNE_CAPABILITIES);
254 	CASE_RETURN_STRING(REASON_1X_AUTH_FAILURE);
255 	CASE_RETURN_STRING(REASON_CIPHER_SUITE_REJECTED);
256 	CASE_RETURN_STRING(REASON_TDLS_PEER_UNREACHABLE);
257 	CASE_RETURN_STRING(REASON_TDLS_UNSPEC);
258 	CASE_RETURN_STRING(REASON_DISASSOC_SSP_REQUESTED);
259 	CASE_RETURN_STRING(REASON_NO_SSP_ROAMING_AGREEMENT);
260 	CASE_RETURN_STRING(REASON_BAD_CIPHER_OR_AKM);
261 	CASE_RETURN_STRING(REASON_LOCATION_NOT_AUTHORIZED);
262 	CASE_RETURN_STRING(REASON_SERVICE_CHANGE_PRECLUDES_TS);
263 	CASE_RETURN_STRING(REASON_QOS_UNSPECIFIED);
264 	CASE_RETURN_STRING(REASON_NO_BANDWIDTH);
265 	CASE_RETURN_STRING(REASON_XS_UNACKED_FRAMES);
266 	CASE_RETURN_STRING(REASON_EXCEEDED_TXOP);
267 	CASE_RETURN_STRING(REASON_STA_LEAVING);
268 	CASE_RETURN_STRING(REASON_END_TS_BA_DLS);
269 	CASE_RETURN_STRING(REASON_UNKNOWN_TS_BA);
270 	CASE_RETURN_STRING(REASON_TIMEDOUT);
271 	CASE_RETURN_STRING(REASON_PEERKEY_MISMATCH);
272 	CASE_RETURN_STRING(REASON_AUTHORIZED_ACCESS_LIMIT_REACHED);
273 	CASE_RETURN_STRING(REASON_EXTERNAL_SERVICE_REQUIREMENTS);
274 	CASE_RETURN_STRING(REASON_INVALID_FT_ACTION_FRAME_COUNT);
275 	CASE_RETURN_STRING(REASON_INVALID_PMKID);
276 	CASE_RETURN_STRING(REASON_INVALID_MDE);
277 	CASE_RETURN_STRING(REASON_INVALID_FTE);
278 	CASE_RETURN_STRING(REASON_MESH_PEERING_CANCELLED);
279 	CASE_RETURN_STRING(REASON_MESH_MAX_PEERS);
280 	CASE_RETURN_STRING(REASON_MESH_CONFIG_POLICY_VIOLATION);
281 	CASE_RETURN_STRING(REASON_MESH_CLOSE_RCVD);
282 	CASE_RETURN_STRING(REASON_MESH_MAX_RETRIES);
283 	CASE_RETURN_STRING(REASON_MESH_CONFIRM_TIMEOUT);
284 	CASE_RETURN_STRING(REASON_MESH_INVALID_GTK);
285 	CASE_RETURN_STRING(REASON_MESH_INCONSISTENT_PARAMS);
286 	CASE_RETURN_STRING(REASON_MESH_INVALID_SECURITY_CAP);
287 	CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_PROXY_INFO);
288 	CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO);
289 	CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_DEST_UNREACHABLE);
290 	CASE_RETURN_STRING(REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS);
291 	CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ);
292 	CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED);
293 	CASE_RETURN_STRING(REASON_POOR_RSSI_CONDITIONS);
294 	default:
295 		return "Unknown";
296 	}
297 }
298 
299 #ifdef WLAN_POLICY_MGR_ENABLE
300 void wlan_cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
301 				 wlan_cm_id cm_id, QDF_STATUS status)
302 {
303 	uint32_t prefix;
304 
305 	prefix = CM_ID_GET_PREFIX(cm_id);
306 	if (prefix == ROAM_REQ_PREFIX)
307 		cm_reassoc_hw_mode_change_resp(pdev, vdev_id, cm_id, status);
308 	else
309 		cm_hw_mode_change_resp(pdev, vdev_id, cm_id, status);
310 }
311 #endif /* ifdef POLICY_MGR_ENABLE */
312 
313 #ifdef SM_ENG_HIST_ENABLE
314 void wlan_cm_sm_history_print(struct wlan_objmgr_vdev *vdev)
315 {
316 	return cm_sm_history_print(vdev);
317 }
318 
319 void wlan_cm_req_history_print(struct wlan_objmgr_vdev *vdev)
320 {
321 	struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev);
322 
323 	if (!cm_ctx)
324 		return;
325 
326 	cm_req_history_print(cm_ctx);
327 }
328 #endif /* SM_ENG_HIST_ENABLE */
329 
330 #ifndef CONN_MGR_ADV_FEATURE
331 void wlan_cm_set_candidate_advance_filter_cb(
332 		struct wlan_objmgr_vdev *vdev,
333 		void (*filter_fun)(struct wlan_objmgr_vdev *vdev,
334 				   struct scan_filter *filter))
335 {
336 	cm_set_candidate_advance_filter_cb(vdev, filter_fun);
337 }
338 
339 void wlan_cm_set_candidate_custom_sort_cb(
340 		struct wlan_objmgr_vdev *vdev,
341 		void (*sort_fun)(struct wlan_objmgr_vdev *vdev,
342 				 qdf_list_t *list))
343 {
344 	cm_set_candidate_custom_sort_cb(vdev, sort_fun);
345 }
346 
347 #endif
348 
349 struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev,
350 						wlan_cm_id cm_id)
351 {
352 	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
353 	struct cm_req *cm_req;
354 	struct cnx_mgr *cm_ctx;
355 
356 	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) {
357 		mlme_err("vdev %d Invalid mode %d",
358 			 wlan_vdev_get_id(vdev), op_mode);
359 		return NULL;
360 	}
361 
362 	cm_ctx = cm_get_cm_ctx(vdev);
363 	if (!cm_ctx)
364 		return NULL;
365 	cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id);
366 	if (!cm_req)
367 		return NULL;
368 
369 	if (cm_req->connect_req.cur_candidate &&
370 	    cm_req->connect_req.cur_candidate->entry)
371 		return &cm_req->connect_req.cur_candidate->entry->rnr;
372 
373 	return NULL;
374 }
375 
376 QDF_STATUS
377 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
378 				 struct wlan_cm_vdev_discon_req *req)
379 {
380 	return cm_handle_rso_stop_rsp(vdev, req);
381 }
382 
383 #ifdef WLAN_FEATURE_11BE
384 QDF_STATUS wlan_cm_sta_update_bw_puncture(struct wlan_objmgr_vdev *vdev,
385 					  uint8_t *peer_mac,
386 					  uint16_t ori_punc,
387 					  enum phy_ch_width ori_bw,
388 					  uint8_t ccfs0, uint8_t ccfs1,
389 					  enum phy_ch_width new_bw)
390 {
391 	struct wlan_channel *des_chan;
392 	uint16_t curr_punc = 0;
393 	uint16_t new_punc = 0;
394 	enum phy_ch_width curr_bw;
395 	uint16_t primary_puncture_bitmap = 0;
396 	struct wlan_objmgr_pdev *pdev;
397 	struct reg_channel_list chan_list;
398 	qdf_freq_t sec_ch_2g_freq = 0;
399 	qdf_freq_t center_freq_320 = 0;
400 	qdf_freq_t center_freq_40 = 0;
401 	uint8_t band_mask;
402 	uint32_t bw_puncture = 0;
403 
404 	if (!vdev || !peer_mac) {
405 		mlme_err("invalid input parameters");
406 		return QDF_STATUS_E_INVAL;
407 	}
408 	pdev = wlan_vdev_get_pdev(vdev);
409 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
410 	if (!des_chan || !pdev) {
411 		mlme_err("invalid des chan");
412 		return QDF_STATUS_E_INVAL;
413 	}
414 	if (ori_bw == CH_WIDTH_320MHZ) {
415 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))
416 			band_mask = BIT(REG_BAND_6G);
417 		else
418 			band_mask = BIT(REG_BAND_5G);
419 		center_freq_320 = wlan_reg_chan_band_to_freq(pdev, ccfs1,
420 							     band_mask);
421 	} else if (ori_bw == CH_WIDTH_40MHZ) {
422 		if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq)) {
423 			band_mask = BIT(REG_BAND_2G);
424 			center_freq_40 = wlan_reg_chan_band_to_freq(pdev,
425 								    ccfs0,
426 								    band_mask);
427 			if (center_freq_40 ==  des_chan->ch_freq + BW_10_MHZ)
428 				sec_ch_2g_freq = des_chan->ch_freq + BW_20_MHZ;
429 			if (center_freq_40 ==  des_chan->ch_freq - BW_10_MHZ)
430 				sec_ch_2g_freq = des_chan->ch_freq - BW_20_MHZ;
431 		}
432 	}
433 	qdf_mem_zero(&chan_list, sizeof(chan_list));
434 	curr_punc = des_chan->puncture_bitmap;
435 	curr_bw = des_chan->ch_width;
436 	wlan_reg_extract_puncture_by_bw(ori_bw, ori_punc,
437 					des_chan->ch_freq,
438 					center_freq_320,
439 					CH_WIDTH_20MHZ,
440 					&primary_puncture_bitmap);
441 	if (primary_puncture_bitmap) {
442 		mlme_err("sta vdev %d freq %d RX bw %d puncture 0x%x primary chan is punctured",
443 			 wlan_vdev_get_id(vdev), des_chan->ch_freq,
444 			 ori_bw, ori_punc);
445 		return QDF_STATUS_E_FAULT;
446 	}
447 	if (new_bw == ori_bw)
448 		new_punc = ori_punc;
449 	else
450 		wlan_reg_extract_puncture_by_bw(ori_bw, ori_punc,
451 						des_chan->ch_freq,
452 						center_freq_320,
453 						new_bw,
454 						&new_punc);
455 	if (curr_bw == new_bw) {
456 		if (curr_punc != new_punc)
457 			des_chan->puncture_bitmap = new_punc;
458 		else
459 			return QDF_STATUS_SUCCESS;
460 	} else {
461 		if (new_bw != CH_WIDTH_320MHZ)
462 			center_freq_320 = 0;
463 		wlan_reg_fill_channel_list(pdev, des_chan->ch_freq,
464 					   sec_ch_2g_freq, new_bw,
465 					   center_freq_320, &chan_list,
466 					   true);
467 		des_chan->ch_freq_seg1 =
468 				chan_list.chan_param[0].center_freq_seg0;
469 		des_chan->ch_freq_seg2 =
470 				chan_list.chan_param[0].center_freq_seg1;
471 		des_chan->ch_cfreq1 = chan_list.chan_param[0].mhz_freq_seg0;
472 		des_chan->ch_cfreq2 = chan_list.chan_param[1].mhz_freq_seg1;
473 		des_chan->puncture_bitmap = new_punc;
474 		des_chan->ch_width = new_bw;
475 	}
476 	mlme_debug("sta vdev %d freq %d bw %d puncture 0x%x ch_cfreq1 %d ch_cfreq2 %d",
477 		   wlan_vdev_get_id(vdev), des_chan->ch_freq,
478 		   des_chan->ch_width, des_chan->puncture_bitmap,
479 		   des_chan->ch_cfreq1, des_chan->ch_cfreq2);
480 	QDF_SET_BITS(bw_puncture, 0, 8, des_chan->ch_width);
481 	QDF_SET_BITS(bw_puncture, 8, 16, des_chan->puncture_bitmap);
482 	return wlan_util_vdev_peer_set_param_send(vdev, peer_mac,
483 						  WLAN_MLME_PEER_BW_PUNCTURE,
484 						  bw_puncture);
485 }
486 #endif /* WLAN_FEATURE_11BE */
487