xref: /wlan-dirver/qcacld-3.0/core/hdd/src/wlan_hdd_son.c (revision dc882e4dd9e61bd77cf492e38eb95e049c61d2a7)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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: contains son hdd API implementation
20  */
21 
22 #include <qdf_types.h>
23 #include <wlan_hdd_main.h>
24 #include <wlan_hdd_sta_info.h>
25 #include <wlan_hdd_regulatory.h>
26 #include <os_if_son.h>
27 #include <sap_internal.h>
28 #include <wma_api.h>
29 #include <wlan_hdd_hostapd.h>
30 #include <wlan_reg_services_api.h>
31 #include <son_ucfg_api.h>
32 #include <wlan_hdd_son.h>
33 #include <wlan_hdd_object_manager.h>
34 #include <wlan_hdd_stats.h>
35 #include "wlan_cfg80211_mc_cp_stats.h"
36 
37 static const struct son_chan_width {
38 	enum ieee80211_cwm_width son_chwidth;
39 	enum phy_ch_width phy_chwidth;
40 } son_chwidth_info[] = {
41 	{
42 		.son_chwidth = IEEE80211_CWM_WIDTH20,
43 		.phy_chwidth = CH_WIDTH_20MHZ,
44 	},
45 	{
46 		.son_chwidth = IEEE80211_CWM_WIDTH40,
47 		.phy_chwidth = CH_WIDTH_40MHZ,
48 	},
49 	{
50 		.son_chwidth = IEEE80211_CWM_WIDTH80,
51 		.phy_chwidth = CH_WIDTH_80MHZ,
52 	},
53 	{
54 		.son_chwidth = IEEE80211_CWM_WIDTH160,
55 		.phy_chwidth = CH_WIDTH_160MHZ,
56 	},
57 	{
58 		.son_chwidth = IEEE80211_CWM_WIDTH80_80,
59 		.phy_chwidth = CH_WIDTH_80P80MHZ,
60 	},
61 #ifdef WLAN_FEATURE_11BE
62 	{
63 		.son_chwidth = IEEE80211_CWM_WIDTH320,
64 		.phy_chwidth = CH_WIDTH_320MHZ,
65 	},
66 #endif
67 };
68 
69 /**
70  * hdd_son_is_acs_in_progress() - whether acs is in progress or not
71  * @vdev: vdev
72  *
73  * Return: true if acs is in progress
74  */
75 static uint32_t hdd_son_is_acs_in_progress(struct wlan_objmgr_vdev *vdev)
76 {
77 	struct wlan_hdd_link_info *link_info;
78 	bool in_progress = false;
79 
80 	if (!vdev) {
81 		hdd_err("null vdev");
82 		return in_progress;
83 	}
84 
85 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
86 	if (!link_info) {
87 		hdd_err("null adapter");
88 		return in_progress;
89 	}
90 
91 	if (!hdd_adapter_is_ap(link_info->adapter)) {
92 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
93 		return in_progress;
94 	}
95 
96 	in_progress = qdf_atomic_read(&link_info->session.ap.acs_in_progress);
97 
98 	return in_progress;
99 }
100 
101 /**
102  * hdd_son_chan_width_to_chan_width() - translate son chan width
103  *                                      to mac chan width
104  * @son_chwidth: son chan width
105  *
106  * Return: mac chan width
107  */
108 static enum eSirMacHTChannelWidth hdd_son_chan_width_to_chan_width(
109 				enum ieee80211_cwm_width son_chwidth)
110 {
111 	enum eSirMacHTChannelWidth chwidth;
112 
113 	switch (son_chwidth) {
114 	case IEEE80211_CWM_WIDTH20:
115 		chwidth = eHT_CHANNEL_WIDTH_20MHZ;
116 		break;
117 	case IEEE80211_CWM_WIDTH40:
118 		chwidth = eHT_CHANNEL_WIDTH_40MHZ;
119 		break;
120 	case IEEE80211_CWM_WIDTH80:
121 		chwidth = eHT_CHANNEL_WIDTH_80MHZ;
122 		break;
123 	case IEEE80211_CWM_WIDTH160:
124 		chwidth = eHT_CHANNEL_WIDTH_160MHZ;
125 		break;
126 	case IEEE80211_CWM_WIDTH80_80:
127 		chwidth = eHT_CHANNEL_WIDTH_80P80MHZ;
128 		break;
129 	default:
130 		chwidth = eHT_MAX_CHANNEL_WIDTH;
131 	}
132 
133 	return chwidth;
134 }
135 
136 /**
137  * hdd_son_set_chwidth() - set son chan width
138  * @vdev: vdev
139  * @son_chwidth: son chan width
140  *
141  * Return: 0 on success, negative errno on failure
142  */
143 static int hdd_son_set_chwidth(struct wlan_objmgr_vdev *vdev,
144 			       enum ieee80211_cwm_width son_chwidth)
145 {
146 	enum eSirMacHTChannelWidth chwidth;
147 	struct wlan_hdd_link_info *link_info;
148 
149 	if (!vdev) {
150 		hdd_err("null vdev");
151 		return -EINVAL;
152 	}
153 
154 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
155 	if (!link_info) {
156 		hdd_err("null adapter");
157 		return -EINVAL;
158 	}
159 
160 	chwidth = hdd_son_chan_width_to_chan_width(son_chwidth);
161 
162 	return hdd_set_mac_chan_width(link_info->adapter, chwidth);
163 }
164 
165 /**
166  * hdd_chan_width_to_son_chwidth() - translate mac chan width
167  *                                   to son chan width
168  * @chwidth: mac chan width
169  *
170  * Return: son chan width
171  */
172 static enum ieee80211_cwm_width hdd_chan_width_to_son_chwidth(
173 				enum eSirMacHTChannelWidth chwidth)
174 {
175 	enum ieee80211_cwm_width son_chwidth;
176 
177 	switch (chwidth) {
178 	case eHT_CHANNEL_WIDTH_20MHZ:
179 		son_chwidth = IEEE80211_CWM_WIDTH20;
180 		break;
181 	case eHT_CHANNEL_WIDTH_40MHZ:
182 		son_chwidth = IEEE80211_CWM_WIDTH40;
183 		break;
184 	case eHT_CHANNEL_WIDTH_80MHZ:
185 		son_chwidth = IEEE80211_CWM_WIDTH80;
186 		break;
187 	case eHT_CHANNEL_WIDTH_160MHZ:
188 		son_chwidth = IEEE80211_CWM_WIDTH160;
189 		break;
190 	case eHT_CHANNEL_WIDTH_80P80MHZ:
191 		son_chwidth = IEEE80211_CWM_WIDTH80_80;
192 		break;
193 	default:
194 		son_chwidth = IEEE80211_CWM_WIDTHINVALID;
195 	}
196 
197 	return son_chwidth;
198 }
199 
200 /**
201  * hdd_phy_chwidth_to_son_chwidth() - translate phy chan width
202  *                                    to son chan width
203  * @chwidth: phy chan width
204  *
205  * Return: son chan width
206  */
207 static enum ieee80211_cwm_width
208 hdd_phy_chwidth_to_son_chwidth(enum phy_ch_width chwidth)
209 {
210 	int i;
211 
212 	for (i = 0; i < ARRAY_SIZE(son_chwidth_info); i++) {
213 		if (son_chwidth_info[i].phy_chwidth == chwidth)
214 			return son_chwidth_info[i].son_chwidth;
215 	}
216 
217 	hdd_err("Unsupported channel width %d", chwidth);
218 	return IEEE80211_CWM_WIDTHINVALID;
219 }
220 
221 /**
222  * hdd_son_get_chwidth() - get chan width
223  * @vdev: vdev
224  *
225  * Return: son chan width
226  */
227 static enum ieee80211_cwm_width hdd_son_get_chwidth(
228 						struct wlan_objmgr_vdev *vdev)
229 {
230 	struct wlan_channel *des_chan;
231 
232 	if (!vdev) {
233 		hdd_err("null vdev");
234 		return IEEE80211_CWM_WIDTHINVALID;
235 	}
236 
237 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
238 
239 	return hdd_phy_chwidth_to_son_chwidth(des_chan->ch_width);
240 }
241 
242 /**
243  * hdd_son_chan_ext_offset_to_chan_type() - translate son chan extend offset
244  *                                          to chan type
245  * @son_chan_ext_offset: son chan ext offset
246  *
247  * Return: tSirMacHTChannelType
248  */
249 static tSirMacHTChannelType hdd_son_chan_ext_offset_to_chan_type(
250 				enum sec20_chan_offset son_chan_ext_offset)
251 {
252 	tSirMacHTChannelType chan_type;
253 
254 	switch (son_chan_ext_offset) {
255 	case EXT_CHAN_OFFSET_ABOVE:
256 		chan_type = eHT_CHAN_HT40PLUS;
257 		break;
258 	case EXT_CHAN_OFFSET_BELOW:
259 		chan_type = eHT_CHAN_HT40MINUS;
260 		break;
261 	default:
262 		chan_type = eHT_CHAN_HT20;
263 		break;
264 	}
265 
266 	return chan_type;
267 }
268 
269 /**
270  * hdd_son_set_chan_ext_offset() - set son chan extend offset
271  * @vdev: vdev
272  * @son_chan_ext_offset: son chan extend offset
273  *
274  * Return: 0 on success, negative errno on failure
275  */
276 static int hdd_son_set_chan_ext_offset(
277 				struct wlan_objmgr_vdev *vdev,
278 				enum sec20_chan_offset son_chan_ext_offset)
279 {
280 	enum eSirMacHTChannelType chan_type;
281 	QDF_STATUS status;
282 	int retval = -EINVAL;
283 	struct hdd_adapter *adapter;
284 
285 	if (!vdev) {
286 		hdd_err("null vdev");
287 		return retval;
288 	}
289 
290 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
291 	if (!link_info) {
292 		hdd_err("null adapter");
293 		return retval;
294 	}
295 
296 	if (!hdd_adapter_is_ap(link_info->adapter)) {
297 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
298 		return retval;
299 	}
300 
301 	retval = 0;
302 	chan_type = hdd_son_chan_ext_offset_to_chan_type(son_chan_ext_offset);
303 	status = hdd_set_sap_ht2040_mode(link_info->adapter, chan_type);
304 	if (status != QDF_STATUS_SUCCESS) {
305 		hdd_err("Cannot set SAP HT20/40 mode!");
306 		retval = -EINVAL;
307 	}
308 
309 	return retval;
310 }
311 
312 /**
313  * hdd_chan_type_to_son_chan_ext_offset() - translate tSirMacHTChannelType
314  *                                          to son chan extend offset
315  * @chan_type: tSirMacHTChannelType
316  *
317  * Return: son chan extend offset
318  */
319 static enum sec20_chan_offset hdd_chan_type_to_son_chan_ext_offset(
320 				tSirMacHTChannelType chan_type)
321 {
322 	enum sec20_chan_offset son_chan_ext_offset;
323 
324 	switch (chan_type) {
325 	case eHT_CHAN_HT40PLUS:
326 		son_chan_ext_offset = EXT_CHAN_OFFSET_ABOVE;
327 		break;
328 	case eHT_CHAN_HT40MINUS:
329 		son_chan_ext_offset = EXT_CHAN_OFFSET_BELOW;
330 		break;
331 	default:
332 		son_chan_ext_offset = EXT_CHAN_OFFSET_NA;
333 		break;
334 	}
335 
336 	return son_chan_ext_offset;
337 }
338 
339 /**
340  * hdd_son_get_chan_ext_offset() - get chan extend offset
341  * @vdev: vdev
342  *
343  * Return: enum sec20_chan_offset
344  */
345 static enum sec20_chan_offset hdd_son_get_chan_ext_offset(
346 						struct wlan_objmgr_vdev *vdev)
347 {
348 	enum eSirMacHTChannelType chan_type;
349 	QDF_STATUS status;
350 	struct wlan_hdd_link_info *link_info;
351 
352 	if (!vdev) {
353 		hdd_err("null vdev");
354 		return 0;
355 	}
356 
357 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
358 	if (!link_info) {
359 		hdd_err("null adapter");
360 		return 0;
361 	}
362 
363 	if (!hdd_adapter_is_ap(link_info->adapter)) {
364 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
365 		return 0;
366 	}
367 
368 	status = hdd_get_sap_ht2040_mode(link_info->adapter, &chan_type);
369 	if (status != QDF_STATUS_SUCCESS) {
370 		hdd_err("Cannot set SAP HT20/40 mode!");
371 		return 0;
372 	}
373 
374 	return hdd_chan_type_to_son_chan_ext_offset(chan_type);
375 }
376 
377 /**
378  * hdd_son_bandwidth_to_phymode() - get new eCsrPhyMode according
379  *                                  to son band width
380  * @son_bandwidth: son band width
381  * @old_phymode: old eCsrPhyMode
382  * @phymode: new eCsrPhyMode to get
383  *
384  * Return: void
385  */
386 static void hdd_son_bandwidth_to_phymode(uint32_t son_bandwidth,
387 					 eCsrPhyMode old_phymode,
388 					 eCsrPhyMode *phymode)
389 {
390 	*phymode = old_phymode;
391 
392 	switch (son_bandwidth) {
393 	case HT20:
394 	case HT40:
395 		*phymode = eCSR_DOT11_MODE_11n;
396 		break;
397 	case VHT20:
398 	case VHT40:
399 	case VHT80:
400 	case VHT160:
401 	case VHT80_80:
402 		*phymode = eCSR_DOT11_MODE_11ac;
403 		break;
404 	case HE20:
405 	case HE40:
406 	case HE80:
407 	case HE160:
408 	case HE80_80:
409 		*phymode = eCSR_DOT11_MODE_11ax;
410 		break;
411 	default:
412 		break;
413 	}
414 }
415 
416 /**
417  * hdd_son_bandwidth_to_bonding_mode() - son band with to bonding mode
418  * @son_bandwidth: son band width
419  * @bonding_mode: bonding mode to get
420  *
421  * Return: void
422  */
423 static void hdd_son_bandwidth_to_bonding_mode(uint32_t son_bandwidth,
424 					      uint32_t *bonding_mode)
425 {
426 	switch (son_bandwidth) {
427 	case HT40:
428 	case VHT40:
429 	case VHT80:
430 	case VHT160:
431 	case VHT80_80:
432 	case HE40:
433 	case HE80:
434 	case HE160:
435 	case HE80_80:
436 		*bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
437 		break;
438 	default:
439 		*bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
440 	}
441 }
442 
443 /**
444  * hdd_son_set_bandwidth() - set band width
445  * @vdev: vdev
446  * @son_bandwidth: son band width
447  *
448  * Return: 0 on success, negative errno on failure
449  */
450 static int hdd_son_set_bandwidth(struct wlan_objmgr_vdev *vdev,
451 				 uint32_t son_bandwidth)
452 {
453 	eCsrPhyMode phymode;
454 	eCsrPhyMode old_phymode;
455 	uint8_t supported_band;
456 	uint32_t bonding_mode;
457 	struct wlan_hdd_link_info *link_info;
458 	struct hdd_context *hdd_ctx;
459 
460 	if (!vdev) {
461 		hdd_err("null vdev");
462 		return -EINVAL;
463 	}
464 
465 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
466 	if (!link_info) {
467 		hdd_err("null adapter");
468 		return -EINVAL;
469 	}
470 
471 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
472 	if (!hdd_ctx) {
473 		hdd_err("null hdd ctx");
474 		return -EINVAL;
475 	}
476 	old_phymode = sme_get_phy_mode(hdd_ctx->mac_handle);
477 
478 	hdd_son_bandwidth_to_phymode(son_bandwidth, old_phymode, &phymode);
479 
480 	if (wlan_reg_is_6ghz_supported(hdd_ctx->psoc))
481 		supported_band = REG_BAND_MASK_ALL;
482 	else
483 		supported_band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
484 
485 	hdd_son_bandwidth_to_bonding_mode(son_bandwidth, &bonding_mode);
486 
487 	return hdd_update_phymode(link_info->adapter, phymode,
488 				  supported_band, bonding_mode);
489 }
490 
491 /**
492  * hdd_phymode_chwidth_to_son_bandwidth() - get son bandwidth from
493  *                                          phymode and chwidth
494  * @phymode: eCsrPhyMode
495  * @chwidth: eSirMacHTChannelWidth
496  *
497  * Return: son bandwidth
498  */
499 static uint32_t hdd_phymode_chwidth_to_son_bandwidth(
500 					eCsrPhyMode phymode,
501 					enum eSirMacHTChannelWidth chwidth)
502 {
503 	uint32_t son_bandwidth = NONHT;
504 
505 	switch (phymode) {
506 	case eCSR_DOT11_MODE_abg:
507 	case eCSR_DOT11_MODE_11a:
508 	case eCSR_DOT11_MODE_11b:
509 	case eCSR_DOT11_MODE_11g:
510 	case eCSR_DOT11_MODE_11g_ONLY:
511 	case eCSR_DOT11_MODE_11b_ONLY:
512 		son_bandwidth = NONHT;
513 		break;
514 	case eCSR_DOT11_MODE_11n:
515 	case eCSR_DOT11_MODE_11n_ONLY:
516 		son_bandwidth = HT20;
517 		if (chwidth == eHT_CHANNEL_WIDTH_40MHZ)
518 			son_bandwidth = HT40;
519 		break;
520 	case eCSR_DOT11_MODE_11ac:
521 	case eCSR_DOT11_MODE_11ac_ONLY:
522 		son_bandwidth = VHT20;
523 		if (chwidth == eHT_CHANNEL_WIDTH_40MHZ)
524 			son_bandwidth = VHT40;
525 		else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ)
526 			son_bandwidth = VHT80;
527 		else if (chwidth == eHT_CHANNEL_WIDTH_160MHZ)
528 			son_bandwidth = VHT160;
529 		else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ)
530 			son_bandwidth = VHT80_80;
531 		break;
532 	case eCSR_DOT11_MODE_11ax:
533 	case eCSR_DOT11_MODE_11ax_ONLY:
534 	case eCSR_DOT11_MODE_AUTO:
535 		son_bandwidth = HE20;
536 		if (chwidth == eHT_CHANNEL_WIDTH_40MHZ)
537 			son_bandwidth = HE40;
538 		else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ)
539 			son_bandwidth = HE80;
540 		else if (chwidth == eHT_CHANNEL_WIDTH_160MHZ)
541 			son_bandwidth = HE160;
542 		else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ)
543 			son_bandwidth = HE80_80;
544 		break;
545 	default:
546 		break;
547 	}
548 
549 	return son_bandwidth;
550 }
551 
552 /**
553  * hdd_son_get_bandwidth() - get band width
554  * @vdev: vdev
555  *
556  * Return: band width
557  */
558 static uint32_t hdd_son_get_bandwidth(struct wlan_objmgr_vdev *vdev)
559 {
560 	enum eSirMacHTChannelWidth chwidth;
561 	eCsrPhyMode phymode;
562 	struct hdd_context *hdd_ctx;
563 	struct wlan_hdd_link_info *link_info;
564 
565 	if (!vdev) {
566 		hdd_err("null vdev");
567 		return NONHT;
568 	}
569 
570 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
571 	if (!link_info) {
572 		hdd_err("null adapter");
573 		return NONHT;
574 	}
575 
576 	chwidth = wma_cli_get_command(link_info->vdev_id,
577 				      wmi_vdev_param_chwidth, VDEV_CMD);
578 
579 	if (chwidth < 0) {
580 		hdd_err("Failed to get chwidth");
581 		return NONHT;
582 	}
583 
584 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
585 	if (!hdd_ctx) {
586 		hdd_err("null hdd ctx");
587 		return -NONHT;
588 	}
589 
590 	phymode = sme_get_phy_mode(hdd_ctx->mac_handle);
591 
592 	return hdd_phymode_chwidth_to_son_bandwidth(phymode, chwidth);
593 }
594 
595 /**
596  * hdd_son_band_to_band() - translate SON band mode to reg_wifi_band
597  * @band: given enum wlan_band_id
598  *
599  * Return: reg_wifi_band
600  */
601 static enum reg_wifi_band hdd_son_band_to_band(enum wlan_band_id band)
602 {
603 	enum reg_wifi_band reg_band = REG_BAND_UNKNOWN;
604 
605 	switch (band) {
606 	case WLAN_BAND_2GHZ:
607 		reg_band = REG_BAND_2G;
608 		break;
609 	case WLAN_BAND_5GHZ:
610 		reg_band = REG_BAND_5G;
611 		break;
612 	case WLAN_BAND_6GHZ:
613 		reg_band = REG_BAND_6G;
614 		break;
615 	default:
616 		break;
617 	}
618 
619 	return reg_band;
620 }
621 
622 /**
623  * hdd_son_set_chan() - set chan
624  * @vdev: vdev
625  * @chan: given chan
626  * @son_band: given enum wlan_band_id
627  *
628  * Return: 0 on success, negative errno on failure
629  */
630 static int hdd_son_set_chan(struct wlan_objmgr_vdev *vdev, int chan,
631 			    enum wlan_band_id son_band)
632 {
633 	struct wlan_hdd_link_info *link_info;
634 	enum reg_wifi_band band = hdd_son_band_to_band(son_band);
635 	bool status;
636 	qdf_freq_t freq;
637 	struct wlan_objmgr_pdev *pdev;
638 	struct wlan_objmgr_psoc *psoc;
639 
640 	if (!vdev) {
641 		hdd_err("null vdev");
642 		return -EINVAL;
643 	}
644 
645 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
646 	if (!link_info) {
647 		hdd_err("null adapter");
648 		return -EINVAL;
649 	}
650 
651 	if (!hdd_adapter_is_ap(link_info->adapter)) {
652 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
653 		return -ENOTSUPP;
654 	}
655 
656 	pdev = wlan_vdev_get_pdev(vdev);
657 	if (!pdev) {
658 		hdd_err("null pdev");
659 		return -EINVAL;
660 	}
661 
662 	psoc = wlan_vdev_get_psoc(vdev);
663 	if (!psoc) {
664 		hdd_err("null psoc");
665 		return -EINVAL;
666 	}
667 
668 	freq = wlan_reg_chan_band_to_freq(pdev, chan, BIT(band));
669 	status = policy_mgr_is_sap_allowed_on_dfs_freq(pdev, link_info->vdev_id,
670 						       freq);
671 	if (!status) {
672 		hdd_err("sap_allowed_on_dfs_freq check fails");
673 		return -EINVAL;
674 	}
675 	wlan_hdd_set_sap_csa_reason(psoc, link_info->vdev_id,
676 				    CSA_REASON_USER_INITIATED);
677 
678 	return hdd_softap_set_channel_change(link_info->adapter->dev, freq,
679 					     CH_WIDTH_MAX, false);
680 }
681 
682 /**
683  * hdd_son_set_country() - set country code
684  * @vdev: vdev
685  * @country_code:pointer to country code
686  *
687  * Return: 0 if country code is set successfully
688  */
689 static int hdd_son_set_country(struct wlan_objmgr_vdev *vdev,
690 			       char *country_code)
691 {
692 	struct hdd_context *hdd_ctx;
693 	struct wlan_hdd_link_info *link_info;
694 
695 	if (!vdev) {
696 		hdd_err("null vdev");
697 		return -EINVAL;
698 	}
699 
700 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
701 	if (!link_info) {
702 		hdd_err("null adapter");
703 		return -EINVAL;
704 	}
705 
706 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
707 	if (!hdd_ctx) {
708 		hdd_err("null hdd ctx");
709 		return -EINVAL;
710 	}
711 
712 	return hdd_reg_set_country(hdd_ctx, country_code);
713 }
714 
715 /**
716  * hdd_son_set_candidate_freq() - set candidate freq. Switch to this freq
717  *                                after radar is detected
718  * @vdev: vdev
719  * @freq: candidate frequency
720  *
721  * Return: 0 if candidate freq is set successfully.
722  */
723 static int hdd_son_set_candidate_freq(struct wlan_objmgr_vdev *vdev,
724 				      qdf_freq_t freq)
725 {
726 	struct wlan_hdd_link_info *link_info;
727 	struct sap_context *sap_ctx;
728 
729 	if (!vdev) {
730 		hdd_err("null vdev");
731 		return -EINVAL;
732 	}
733 
734 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
735 	if (!link_info) {
736 		hdd_err("null adapter");
737 		return -EINVAL;
738 	}
739 	if (!hdd_adapter_is_ap(link_info->adapter)) {
740 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
741 		return -EINVAL;
742 	}
743 
744 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
745 	if (!sap_ctx) {
746 		hdd_err("null sap_ctx");
747 		return -EINVAL;
748 	}
749 
750 	sap_ctx->candidate_freq = freq;
751 
752 	return 0;
753 }
754 
755 /**
756  * hdd_son_get_candidate_freq() - get candidate freq
757  * @vdev: vdev
758  *
759  * Return: candidate freq
760  */
761 static qdf_freq_t hdd_son_get_candidate_freq(struct wlan_objmgr_vdev *vdev)
762 {
763 	struct wlan_hdd_link_info *link_info;
764 	struct sap_context *sap_ctx;
765 	qdf_freq_t freq = 0;
766 
767 	if (!vdev) {
768 		hdd_err("null vdev");
769 		return freq;
770 	}
771 
772 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
773 	if (!link_info) {
774 		hdd_err("null adapter");
775 		return freq;
776 	}
777 	if (!hdd_adapter_is_ap(link_info->adapter)) {
778 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
779 		return freq;
780 	}
781 
782 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
783 	if (!sap_ctx) {
784 		hdd_err("null sap_ctx");
785 		return freq;
786 	}
787 	freq = sap_ctx->candidate_freq;
788 
789 	return freq;
790 }
791 
792 /**
793  * hdd_son_phy_mode_to_vendor_phy_mode() - translate son phy mode to
794  *                                         vendor_phy_mode
795  * @mode: son phy mode
796  *
797  * Return: qca_wlan_vendor_phy_mode
798  */
799 static enum qca_wlan_vendor_phy_mode hdd_son_phy_mode_to_vendor_phy_mode(
800 						enum ieee80211_phymode mode)
801 {
802 	enum qca_wlan_vendor_phy_mode vendor_mode;
803 
804 	switch (mode) {
805 	case IEEE80211_MODE_AUTO:
806 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
807 		break;
808 	case IEEE80211_MODE_11A:
809 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11A;
810 		break;
811 	case IEEE80211_MODE_11B:
812 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11B;
813 		break;
814 	case IEEE80211_MODE_11G:
815 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11G;
816 		break;
817 	case IEEE80211_MODE_11NA_HT20:
818 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20;
819 		break;
820 	case IEEE80211_MODE_11NG_HT20:
821 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20;
822 		break;
823 	case IEEE80211_MODE_11NA_HT40PLUS:
824 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS;
825 		break;
826 	case IEEE80211_MODE_11NA_HT40MINUS:
827 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS;
828 		break;
829 	case IEEE80211_MODE_11NG_HT40PLUS:
830 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS;
831 		break;
832 	case IEEE80211_MODE_11NG_HT40MINUS:
833 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS;
834 		break;
835 	case IEEE80211_MODE_11NG_HT40:
836 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40;
837 		break;
838 	case IEEE80211_MODE_11NA_HT40:
839 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40;
840 		break;
841 	case IEEE80211_MODE_11AC_VHT20:
842 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20;
843 		break;
844 	case IEEE80211_MODE_11AC_VHT40PLUS:
845 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS;
846 		break;
847 	case IEEE80211_MODE_11AC_VHT40MINUS:
848 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS;
849 		break;
850 	case IEEE80211_MODE_11AC_VHT40:
851 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40;
852 		break;
853 	case IEEE80211_MODE_11AC_VHT80:
854 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80;
855 		break;
856 	case IEEE80211_MODE_11AC_VHT160:
857 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160;
858 		break;
859 	case IEEE80211_MODE_11AC_VHT80_80:
860 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80;
861 		break;
862 	case IEEE80211_MODE_11AXA_HE20:
863 	case IEEE80211_MODE_11AXG_HE20:
864 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20;
865 		break;
866 	case IEEE80211_MODE_11AXA_HE40PLUS:
867 	case IEEE80211_MODE_11AXG_HE40PLUS:
868 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS;
869 		break;
870 	case IEEE80211_MODE_11AXA_HE40MINUS:
871 	case IEEE80211_MODE_11AXG_HE40MINUS:
872 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS;
873 		break;
874 	case IEEE80211_MODE_11AXA_HE40:
875 	case IEEE80211_MODE_11AXG_HE40:
876 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40;
877 		break;
878 	case IEEE80211_MODE_11AXA_HE80:
879 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80;
880 		break;
881 	case IEEE80211_MODE_11AXA_HE160:
882 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160;
883 		break;
884 	case IEEE80211_MODE_11AXA_HE80_80:
885 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80;
886 		break;
887 	default:
888 		hdd_err("Invalid config phy mode %d, set it as auto", mode);
889 		vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
890 		break;
891 	}
892 
893 	return vendor_mode;
894 }
895 
896 /**
897  * hdd_son_set_phymode() - set son phy mode
898  * @vdev: vdev
899  * @mode: son phy mode to set
900  *
901  * Return: 0 on success, negative errno on failure
902  */
903 static int hdd_son_set_phymode(struct wlan_objmgr_vdev *vdev,
904 			       enum ieee80211_phymode mode)
905 {
906 	struct wlan_hdd_link_info *link_info;
907 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
908 	QDF_STATUS status;
909 	struct hdd_ap_ctx *hdd_ap_ctx;
910 	struct sap_config *sap_config;
911 	struct wlan_hdd_link_info *link_info;
912 
913 	if (!vdev) {
914 		hdd_err("null vdev");
915 		return -EINVAL;
916 	}
917 
918 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
919 	if (!link_info) {
920 		hdd_err("Invalid VDEV %d", wlan_vdev_get_id(vdev));
921 		return -EINVAL;
922 	}
923 
924 	if (!hdd_adapter_is_ap(link_info->adapter)) {
925 		hdd_err("vdev id %d is not AP", link_info->vdev_id);
926 		return -EINVAL;
927 	}
928 
929 	vendor_phy_mode = hdd_son_phy_mode_to_vendor_phy_mode(mode);
930 
931 	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
932 	sap_config = &hdd_ap_ctx->sap_config;
933 	status = wlansap_son_update_sap_config_phymode(vdev, sap_config,
934 						       vendor_phy_mode);
935 	if (QDF_IS_STATUS_ERROR(status)) {
936 		hdd_err("update son phy mode error");
937 		return -EINVAL;
938 	}
939 
940 	hdd_restart_sap(link_info);
941 
942 	return 0;
943 }
944 
945 /**
946  * hdd_wlan_phymode_to_son_phymode() - get son phymode from wlan_phymode phymode
947  * @phymode: wlan_phymode phymode
948  *
949  * Return: ieee80211_phymode
950  */
951 static enum ieee80211_phymode hdd_wlan_phymode_to_son_phymode(
952 					enum wlan_phymode phymode)
953 {
954 	enum ieee80211_phymode son_phymode;
955 
956 	switch (phymode) {
957 	case WLAN_PHYMODE_AUTO:
958 		son_phymode = IEEE80211_MODE_AUTO;
959 		break;
960 	case WLAN_PHYMODE_11A:
961 		son_phymode = IEEE80211_MODE_11A;
962 		break;
963 	case WLAN_PHYMODE_11B:
964 		son_phymode = IEEE80211_MODE_11B;
965 		break;
966 	case WLAN_PHYMODE_11G:
967 	case WLAN_PHYMODE_11G_ONLY:
968 		son_phymode = IEEE80211_MODE_11G;
969 		break;
970 	case WLAN_PHYMODE_11NA_HT20:
971 		son_phymode = IEEE80211_MODE_11NA_HT20;
972 		break;
973 	case WLAN_PHYMODE_11NG_HT20:
974 		son_phymode = IEEE80211_MODE_11NG_HT20;
975 		break;
976 	case WLAN_PHYMODE_11NA_HT40:
977 		son_phymode = IEEE80211_MODE_11NA_HT40;
978 		break;
979 	case WLAN_PHYMODE_11NG_HT40PLUS:
980 		son_phymode = IEEE80211_MODE_11NG_HT40PLUS;
981 		break;
982 	case WLAN_PHYMODE_11NG_HT40MINUS:
983 		son_phymode = IEEE80211_MODE_11NG_HT40MINUS;
984 		break;
985 	case WLAN_PHYMODE_11NG_HT40:
986 		son_phymode = IEEE80211_MODE_11NG_HT40;
987 		break;
988 	case WLAN_PHYMODE_11AC_VHT20:
989 	case WLAN_PHYMODE_11AC_VHT20_2G:
990 		son_phymode = IEEE80211_MODE_11AC_VHT20;
991 		break;
992 	case WLAN_PHYMODE_11AC_VHT40:
993 	case WLAN_PHYMODE_11AC_VHT40_2G:
994 		son_phymode = IEEE80211_MODE_11AC_VHT40;
995 		break;
996 	case WLAN_PHYMODE_11AC_VHT40PLUS_2G:
997 		son_phymode = IEEE80211_MODE_11AC_VHT40PLUS;
998 		break;
999 	case WLAN_PHYMODE_11AC_VHT40MINUS_2G:
1000 		son_phymode = IEEE80211_MODE_11AC_VHT40MINUS;
1001 		break;
1002 	case WLAN_PHYMODE_11AC_VHT80:
1003 	case WLAN_PHYMODE_11AC_VHT80_2G:
1004 		son_phymode = IEEE80211_MODE_11AC_VHT80;
1005 		break;
1006 	case WLAN_PHYMODE_11AC_VHT160:
1007 		son_phymode = IEEE80211_MODE_11AC_VHT160;
1008 		break;
1009 	case WLAN_PHYMODE_11AC_VHT80_80:
1010 		son_phymode = IEEE80211_MODE_11AC_VHT80_80;
1011 		break;
1012 	case WLAN_PHYMODE_11AXA_HE20:
1013 		son_phymode = IEEE80211_MODE_11AXA_HE20;
1014 		break;
1015 	case WLAN_PHYMODE_11AXG_HE20:
1016 		son_phymode = IEEE80211_MODE_11AXG_HE20;
1017 		break;
1018 	case WLAN_PHYMODE_11AXA_HE40:
1019 		son_phymode = IEEE80211_MODE_11AXA_HE40;
1020 		break;
1021 	case WLAN_PHYMODE_11AXG_HE40PLUS:
1022 		son_phymode = IEEE80211_MODE_11AXG_HE40PLUS;
1023 		break;
1024 	case WLAN_PHYMODE_11AXG_HE40MINUS:
1025 		son_phymode = IEEE80211_MODE_11AXG_HE40MINUS;
1026 		break;
1027 	case WLAN_PHYMODE_11AXG_HE40:
1028 	case WLAN_PHYMODE_11AXG_HE80:
1029 		son_phymode = IEEE80211_MODE_11AXG_HE40;
1030 		break;
1031 	case WLAN_PHYMODE_11AXA_HE80:
1032 		son_phymode = IEEE80211_MODE_11AXA_HE80;
1033 		break;
1034 	case WLAN_PHYMODE_11AXA_HE160:
1035 		son_phymode = IEEE80211_MODE_11AXA_HE160;
1036 		break;
1037 	case WLAN_PHYMODE_11AXA_HE80_80:
1038 		son_phymode = IEEE80211_MODE_11AXA_HE80_80;
1039 		break;
1040 	default:
1041 		son_phymode = IEEE80211_MODE_AUTO;
1042 		break;
1043 	}
1044 
1045 	return son_phymode;
1046 }
1047 
1048 /**
1049  * hdd_son_get_phymode() - get son phy mode
1050  * @vdev: vdev
1051  *
1052  * Return: enum ieee80211_phymode
1053  */
1054 static enum ieee80211_phymode hdd_son_get_phymode(struct wlan_objmgr_vdev *vdev)
1055 {
1056 	struct wlan_channel *des_chan;
1057 
1058 	if (!vdev) {
1059 		hdd_err("null vdev");
1060 		return IEEE80211_MODE_AUTO;
1061 	}
1062 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
1063 	if (!des_chan) {
1064 		hdd_err("null des_chan");
1065 		return IEEE80211_MODE_AUTO;
1066 	}
1067 
1068 	return hdd_wlan_phymode_to_son_phymode(des_chan->ch_phymode);
1069 }
1070 
1071 /**
1072  * hdd_son_per_sta_len() - get sta information length
1073  * @sta_info: pointer to hdd_station_info
1074  *
1075  * TD: Certain IE may be provided for sta info
1076  *
1077  * Return: the size which is needed for given sta info
1078  */
1079 static uint32_t hdd_son_per_sta_len(struct hdd_station_info *sta_info)
1080 {
1081 	return qdf_roundup(sizeof(struct ieee80211req_sta_info),
1082 			   sizeof(uint32_t));
1083 }
1084 
1085 /**
1086  * hdd_son_get_sta_space() - how many space are needed for given vdev
1087  * @vdev: vdev
1088  *
1089  * Return: space needed for given vdev to provide sta info
1090  */
1091 static uint32_t hdd_son_get_sta_space(struct wlan_objmgr_vdev *vdev)
1092 {
1093 	struct hdd_adapter *adapter;
1094 	struct wlan_hdd_link_info *link_info;
1095 	struct hdd_station_info *sta_info, *tmp = NULL;
1096 	uint32_t space = 0;
1097 
1098 	if (!vdev) {
1099 		hdd_err("null vdev");
1100 		return space;
1101 	}
1102 
1103 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1104 	if (!link_info) {
1105 		hdd_err("null adapter");
1106 		return space;
1107 	}
1108 
1109 	adapter = link_info->adapter;
1110 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
1111 				  STA_INFO_SOFTAP_GET_STA_INFO) {
1112 		if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac))
1113 			space += hdd_son_per_sta_len(sta_info);
1114 
1115 		hdd_put_sta_info_ref(&adapter->sta_info_list,
1116 				     &sta_info, true,
1117 				     STA_INFO_SOFTAP_GET_STA_INFO);
1118 	}
1119 	hdd_debug("sta list space %u", space);
1120 
1121 	return space;
1122 }
1123 
1124 /**
1125  * hdd_son_get_sta_list() - get connected station list
1126  * @vdev: vdev
1127  * @si: pointer to ieee80211req_sta_info
1128  * @space: space left
1129  *
1130  * Return: void
1131  */
1132 static void hdd_son_get_sta_list(struct wlan_objmgr_vdev *vdev,
1133 				 struct ieee80211req_sta_info *si,
1134 				 uint32_t *space)
1135 {
1136 	struct hdd_adapter *adapter;
1137 	struct wlan_hdd_link_info *link_info;
1138 	struct hdd_station_info *sta_info, *tmp = NULL;
1139 	uint32_t len;
1140 	qdf_time_t current_ts;
1141 
1142 	if (!vdev) {
1143 		hdd_err("null vdev");
1144 		return;
1145 	}
1146 
1147 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1148 	if (!link_info) {
1149 		hdd_err("null adapter");
1150 		return;
1151 	}
1152 
1153 	adapter = link_info->adapter;
1154 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
1155 				  STA_INFO_SOFTAP_GET_STA_INFO) {
1156 		if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
1157 			len = hdd_son_per_sta_len(sta_info);
1158 
1159 			if (len > *space) {
1160 				/* no more space if left */
1161 				hdd_put_sta_info_ref(
1162 					&adapter->sta_info_list,
1163 					&sta_info, true,
1164 					STA_INFO_SOFTAP_GET_STA_INFO);
1165 
1166 				if (tmp)
1167 					hdd_put_sta_info_ref(
1168 						&adapter->sta_info_list,
1169 						&tmp, true,
1170 						STA_INFO_SOFTAP_GET_STA_INFO);
1171 
1172 				hdd_err("space %u, length %u", *space, len);
1173 
1174 				return;
1175 			}
1176 
1177 			qdf_mem_copy(si->isi_macaddr, &sta_info->sta_mac,
1178 				     QDF_MAC_ADDR_SIZE);
1179 			si->isi_ext_cap = sta_info->ext_cap;
1180 			si->isi_beacon_measurement_support =
1181 					!!(sta_info->capability &
1182 					   WLAN_CAPABILITY_RADIO_MEASURE);
1183 			si->isi_operating_bands = sta_info->supported_band;
1184 			si->isi_assoc_time = sta_info->assoc_ts;
1185 			current_ts = qdf_system_ticks();
1186 			jiffies_to_timespec(current_ts - sta_info->assoc_ts,
1187 					    &si->isi_tr069_assoc_time);
1188 			si->isi_rssi = sta_info->rssi;
1189 			si->isi_len = len;
1190 			si->isi_ie_len = 0;
1191 			hdd_debug("sta " QDF_MAC_ADDR_FMT " ext_cap 0x%x op band %u rssi %d len %u, assoc ts %lu, curr ts %lu rrm %d",
1192 				  QDF_MAC_ADDR_REF(si->isi_macaddr),
1193 				  si->isi_ext_cap, si->isi_operating_bands,
1194 				  si->isi_rssi, si->isi_len, sta_info->assoc_ts,
1195 				  current_ts,
1196 				  si->isi_beacon_measurement_support);
1197 			si = (struct ieee80211req_sta_info *)(((uint8_t *)si) +
1198 			     len);
1199 			*space -= len;
1200 		}
1201 		hdd_put_sta_info_ref(&adapter->sta_info_list,
1202 				     &sta_info, true,
1203 				     STA_INFO_SOFTAP_GET_STA_INFO);
1204 	}
1205 }
1206 
1207 /**
1208  * hdd_son_set_acl_policy() - set son acl policy
1209  * @vdev: vdev
1210  * @son_acl_policy: enum ieee80211_acl_cmd
1211  *
1212  * Return: QDF_STATUS
1213  */
1214 static QDF_STATUS hdd_son_set_acl_policy(struct wlan_objmgr_vdev *vdev,
1215 					 ieee80211_acl_cmd son_acl_policy)
1216 {
1217 	struct wlan_hdd_link_info *link_info;
1218 	QDF_STATUS status = QDF_STATUS_E_INVAL;
1219 	struct sap_context *sap_context;
1220 
1221 	if (!vdev) {
1222 		hdd_err("null vdev");
1223 		return status;
1224 	}
1225 
1226 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1227 	if (!link_info) {
1228 		hdd_err("null adapter");
1229 		return status;
1230 	}
1231 
1232 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
1233 	switch (son_acl_policy) {
1234 	case IEEE80211_MACCMD_POLICY_OPEN:
1235 		status = wlansap_set_acl_mode(sap_context, eSAP_ALLOW_ALL);
1236 		break;
1237 	case IEEE80211_MACCMD_POLICY_ALLOW:
1238 		status = wlansap_set_acl_mode(sap_context,
1239 					      eSAP_DENY_UNLESS_ACCEPTED);
1240 		break;
1241 	case IEEE80211_MACCMD_POLICY_DENY:
1242 		status = wlansap_set_acl_mode(sap_context,
1243 					      eSAP_ACCEPT_UNLESS_DENIED);
1244 		break;
1245 	case IEEE80211_MACCMD_FLUSH:
1246 	case IEEE80211_MACCMD_DETACH:
1247 		status = wlansap_clear_acl(sap_context);
1248 		break;
1249 	default:
1250 		hdd_err("invalid son acl policy %d", son_acl_policy);
1251 		break;
1252 	}
1253 
1254 	return status;
1255 }
1256 
1257 /**
1258  * hdd_acl_policy_to_son_acl_policy() - convert acl policy to son acl policy
1259  * @acl_policy: acl policy
1260  *
1261  * Return: son acl policy. enum ieee80211_acl_cmd
1262  */
1263 static ieee80211_acl_cmd hdd_acl_policy_to_son_acl_policy(
1264 						eSapMacAddrACL acl_policy)
1265 {
1266 	ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH;
1267 
1268 	switch (acl_policy) {
1269 	case eSAP_ACCEPT_UNLESS_DENIED:
1270 		son_acl_policy = IEEE80211_MACCMD_POLICY_DENY;
1271 		break;
1272 	case eSAP_DENY_UNLESS_ACCEPTED:
1273 		son_acl_policy = IEEE80211_MACCMD_POLICY_ALLOW;
1274 		break;
1275 	case eSAP_ALLOW_ALL:
1276 		son_acl_policy = IEEE80211_MACCMD_POLICY_OPEN;
1277 		break;
1278 	default:
1279 		hdd_err("invalid acl policy %d", acl_policy);
1280 		break;
1281 	}
1282 
1283 	return son_acl_policy;
1284 }
1285 
1286 /**
1287  * hdd_son_get_acl_policy() - get son acl policy
1288  * @vdev: vdev
1289  *
1290  * Return: son acl policy. enum ieee80211_acl_cmd
1291  */
1292 static ieee80211_acl_cmd hdd_son_get_acl_policy(struct wlan_objmgr_vdev *vdev)
1293 {
1294 	eSapMacAddrACL acl_policy;
1295 	struct wlan_hdd_link_info *link_info;
1296 	ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH;
1297 
1298 	if (!vdev) {
1299 		hdd_err("null vdev");
1300 		return son_acl_policy;
1301 	}
1302 
1303 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1304 	if (!link_info) {
1305 		hdd_err("null adapter");
1306 		return son_acl_policy;
1307 	}
1308 
1309 	wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(link_info), &acl_policy);
1310 
1311 	son_acl_policy = hdd_acl_policy_to_son_acl_policy(acl_policy);
1312 
1313 	return son_acl_policy;
1314 }
1315 
1316 /**
1317  * hdd_son_add_acl_mac() - add mac to access control list(ACL)
1318  * @vdev: vdev
1319  * @acl_mac: mac address to add
1320  *
1321  * Return: 0 on success, negative errno on failure
1322  */
1323 static int hdd_son_add_acl_mac(struct wlan_objmgr_vdev *vdev,
1324 			       struct qdf_mac_addr *acl_mac)
1325 {
1326 	eSapACLType list_type;
1327 	QDF_STATUS qdf_status;
1328 	eSapMacAddrACL acl_policy;
1329 	struct wlan_hdd_link_info *link_info;
1330 	struct sap_context *sap_context;
1331 
1332 	if (!vdev) {
1333 		hdd_err("null vdev");
1334 		return -EINVAL;
1335 	}
1336 	if (!acl_mac) {
1337 		hdd_err("null acl_mac");
1338 		return -EINVAL;
1339 	}
1340 
1341 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1342 	if (!link_info) {
1343 		hdd_err("null adapter");
1344 		return -EINVAL;
1345 	}
1346 
1347 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
1348 	wlansap_get_acl_mode(sap_context, &acl_policy);
1349 
1350 	if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) {
1351 		list_type = SAP_DENY_LIST;
1352 	} else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) {
1353 		list_type = SAP_ALLOW_LIST;
1354 	} else {
1355 		hdd_err("Invalid ACL policy %d.", acl_policy);
1356 		return -EINVAL;
1357 	}
1358 	qdf_status = wlansap_modify_acl(sap_context, acl_mac->bytes, list_type,
1359 					ADD_STA_TO_ACL_NO_DEAUTH);
1360 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
1361 		hdd_err("Modify ACL failed");
1362 		return -EIO;
1363 	}
1364 
1365 	return 0;
1366 }
1367 
1368 /**
1369  * hdd_son_del_acl_mac() - delete mac from acl
1370  * @vdev: vdev
1371  * @acl_mac: mac to remove
1372  *
1373  * Return: 0 on success, negative errno on failure
1374  */
1375 static int hdd_son_del_acl_mac(struct wlan_objmgr_vdev *vdev,
1376 			       struct qdf_mac_addr *acl_mac)
1377 {
1378 	eSapACLType list_type;
1379 	QDF_STATUS qdf_status;
1380 	eSapMacAddrACL acl_policy;
1381 	struct wlan_hdd_link_info *link_info;
1382 	struct sap_context *sap_ctx;
1383 
1384 	if (!vdev) {
1385 		hdd_err("null vdev");
1386 		return -EINVAL;
1387 	}
1388 	if (!acl_mac) {
1389 		hdd_err("null acl_mac");
1390 		return -EINVAL;
1391 	}
1392 
1393 	lin_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1394 	if (!link_info) {
1395 		hdd_err("null adapter");
1396 		return -EINVAL;
1397 	}
1398 
1399 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
1400 	if (!sap_ctx) {
1401 		hdd_err("null sap ctx");
1402 		return -EINVAL;
1403 	}
1404 
1405 	wlansap_get_acl_mode(sap_ctx, &acl_policy);
1406 
1407 	if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) {
1408 		list_type = SAP_DENY_LIST;
1409 	} else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) {
1410 		list_type = SAP_ALLOW_LIST;
1411 	} else {
1412 		hdd_err("Invalid ACL policy %d.", acl_policy);
1413 		return -EINVAL;
1414 	}
1415 	qdf_status = wlansap_modify_acl(sap_ctx, acl_mac->bytes, list_type,
1416 					DELETE_STA_FROM_ACL_NO_DEAUTH);
1417 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
1418 		hdd_err("Modify ACL failed");
1419 		return -EIO;
1420 	}
1421 
1422 	return 0;
1423 }
1424 
1425 /**
1426  * hdd_son_kickout_mac() - kickout sta with given mac
1427  * @vdev: vdev
1428  * @mac: sta mac to kickout
1429  *
1430  * Return: 0 on success, negative errno on failure
1431  */
1432 static int hdd_son_kickout_mac(struct wlan_objmgr_vdev *vdev,
1433 			       struct qdf_mac_addr *mac)
1434 {
1435 	struct wlan_hdd_link_info *link_info;
1436 
1437 	if (!vdev) {
1438 		hdd_err("null vdev");
1439 		return -EINVAL;
1440 	}
1441 
1442 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1443 	if (!link_info) {
1444 		hdd_err("null adapter");
1445 		return -EINVAL;
1446 	}
1447 
1448 	if (mac)
1449 		return wlan_hdd_del_station(link_info->adapter, mac->bytes);
1450 	else
1451 		return wlan_hdd_del_station(link_info->adapter, NULL);
1452 }
1453 
1454 static uint8_t hdd_son_get_rx_nss(struct wlan_objmgr_vdev *vdev)
1455 {
1456 	struct wlan_hdd_link_info *link_info;
1457 	uint8_t rx_nss = 0;
1458 
1459 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1460 	if (!link_info) {
1461 		hdd_err("null adapter");
1462 		return 0;
1463 	}
1464 
1465 	hdd_get_rx_nss(link_info->adapter, &rx_nss);
1466 	return rx_nss;
1467 }
1468 
1469 static void hdd_son_deauth_sta(struct wlan_objmgr_vdev *vdev,
1470 			       uint8_t *peer_mac,
1471 			       bool ignore_frame)
1472 {
1473 	struct wlan_hdd_link_info *link_info;
1474 	struct csr_del_sta_params param;
1475 	QDF_STATUS status;
1476 
1477 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1478 	if (!link_info) {
1479 		hdd_err("null adapter");
1480 		return;
1481 	}
1482 
1483 	qdf_mem_copy(param.peerMacAddr.bytes, peer_mac, QDF_MAC_ADDR_SIZE);
1484 	param.subtype = SIR_MAC_MGMT_DEAUTH;
1485 	param.reason_code = ignore_frame ? REASON_HOST_TRIGGERED_SILENT_DEAUTH
1486 					 : REASON_UNSPEC_FAILURE;
1487 	hdd_debug("Peer - "QDF_MAC_ADDR_FMT" Ignore Frame - %u",
1488 		  QDF_MAC_ADDR_REF(peer_mac), ignore_frame);
1489 
1490 	status = hdd_softap_sta_deauth(link_info->adapter, &param);
1491 	if (QDF_STATUS_IS_ERROR(status))
1492 		hdd_err("Error in deauthenticating peer");
1493 }
1494 
1495 static void hdd_son_modify_acl(struct wlan_objmgr_vdev *vdev,
1496 			       uint8_t *peer_mac,
1497 			       bool allow_auth)
1498 {
1499 	QDF_STATUS status;
1500 	struct sap_context *sap_context;
1501 	struct wlan_hdd_link_info *link_info;
1502 
1503 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1504 	if (!link_info) {
1505 		hdd_err("null adapter");
1506 		return;
1507 	}
1508 
1509 	hdd_debug("Peer - " QDF_MAC_ADDR_FMT " Allow Auth - %u",
1510 		  QDF_MAC_ADDR_REF(peer_mac), allow_auth);
1511 
1512 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
1513 	if (allow_auth) {
1514 		status = wlansap_modify_acl(sap_context, peer_mac,
1515 					    SAP_DENY_LIST, DELETE_STA_FROM_ACL);
1516 		status = wlansap_modify_acl(sap_context, peer_mac,
1517 					    SAP_ALLOW_LIST, ADD_STA_TO_ACL);
1518 	} else {
1519 		status = wlansap_modify_acl(sap_context, peer_mac,
1520 					    SAP_ALLOW_LIST,
1521 					    DELETE_STA_FROM_ACL);
1522 		status = wlansap_modify_acl(sap_context, peer_mac,
1523 					    SAP_DENY_LIST, ADD_STA_TO_ACL);
1524 	}
1525 }
1526 
1527 static int hdd_son_send_cfg_event(struct wlan_objmgr_vdev *vdev,
1528 				  uint32_t event_id,
1529 				  uint32_t event_len,
1530 				  const uint8_t *event_buf)
1531 {
1532 	struct hdd_adapter *adapter;
1533 	struct wlan_hdd_link_info *link_info;
1534 	uint32_t len;
1535 	uint32_t idx;
1536 	struct sk_buff *skb;
1537 
1538 	if (!event_buf) {
1539 		hdd_err("invalid event buf");
1540 		return -EINVAL;
1541 	}
1542 
1543 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1544 	if (!link_info) {
1545 		hdd_err("null adapter");
1546 		return -EINVAL;
1547 	}
1548 
1549 	adapter = link_info->adapter;
1550 	len = nla_total_size(sizeof(event_id)) +
1551 			nla_total_size(event_len) +
1552 			NLMSG_HDRLEN;
1553 	idx = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION_INDEX;
1554 	skb = wlan_cfg80211_vendor_event_alloc(adapter->hdd_ctx->wiphy,
1555 					       &adapter->wdev,
1556 					       len, idx, GFP_KERNEL);
1557 	if (!skb) {
1558 		hdd_err("failed to alloc cfg80211 vendor event");
1559 		return -EINVAL;
1560 	}
1561 
1562 	if (nla_put_u32(skb,
1563 			QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND,
1564 			event_id)) {
1565 		hdd_err("failed to put attr config generic command");
1566 		wlan_cfg80211_vendor_free_skb(skb);
1567 		return -EINVAL;
1568 	}
1569 
1570 	if (nla_put(skb,
1571 		    QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA,
1572 		    event_len,
1573 		    event_buf)) {
1574 		hdd_err("failed to put attr config generic data");
1575 		wlan_cfg80211_vendor_free_skb(skb);
1576 		return -EINVAL;
1577 	}
1578 
1579 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
1580 
1581 	return 0;
1582 }
1583 
1584 static int hdd_son_deliver_opmode(struct wlan_objmgr_vdev *vdev,
1585 				  uint32_t event_len,
1586 				  const uint8_t *event_buf)
1587 {
1588 	return hdd_son_send_cfg_event(vdev,
1589 				      QCA_NL80211_VENDOR_SUBCMD_OPMODE_UPDATE,
1590 				      event_len,
1591 				      event_buf);
1592 }
1593 
1594 static int hdd_son_deliver_smps(struct wlan_objmgr_vdev *vdev,
1595 				uint32_t event_len,
1596 				const uint8_t *event_buf)
1597 {
1598 	return hdd_son_send_cfg_event(vdev,
1599 				      QCA_NL80211_VENDOR_SUBCMD_SMPS_UPDATE,
1600 				      event_len,
1601 				      event_buf);
1602 }
1603 
1604 /**
1605  * hdd_son_get_vdev_by_netdev() - get vdev from net device
1606  * @dev: struct net_device dev
1607  *
1608  * Return: vdev on success, NULL on failure
1609  */
1610 static struct wlan_objmgr_vdev *
1611 hdd_son_get_vdev_by_netdev(struct net_device *dev)
1612 {
1613 	struct hdd_adapter *adapter;
1614 	struct wlan_objmgr_vdev *vdev;
1615 
1616 	if (!dev)
1617 		return NULL;
1618 
1619 	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1620 	if (!adapter || (adapter && adapter->delete_in_progress))
1621 		return NULL;
1622 
1623 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID);
1624 	if (!vdev)
1625 		return NULL;
1626 
1627 	return vdev;
1628 }
1629 
1630 /**
1631  * son_trigger_vdev_obj_creation() - Trigger vdev object creation
1632  * @psoc: psoc object
1633  * @object: vdev object
1634  * @arg: component id
1635  *
1636  * Return: void
1637  */
1638 static void
1639 son_trigger_vdev_obj_creation(struct wlan_objmgr_psoc *psoc,
1640 			      void *object, void *arg)
1641 {
1642 	QDF_STATUS ret;
1643 	struct wlan_objmgr_vdev *vdev;
1644 	enum wlan_umac_comp_id *id;
1645 
1646 	vdev = object;
1647 	id = arg;
1648 
1649 	ret = wlan_objmgr_trigger_vdev_comp_priv_object_creation(vdev, *id);
1650 	if (QDF_IS_STATUS_ERROR(ret))
1651 		hdd_err("vdev obj creation trigger failed");
1652 }
1653 
1654 /**
1655  * son_trigger_pdev_obj_creation() - Trigger pdev object creation
1656  * @psoc: psoc object
1657  * @object: pdev object
1658  * @arg: component id
1659  *
1660  * Return: void
1661  */
1662 static void
1663 son_trigger_pdev_obj_creation(struct wlan_objmgr_psoc *psoc,
1664 			      void *object, void *arg)
1665 {
1666 	QDF_STATUS ret;
1667 	struct wlan_objmgr_pdev *pdev;
1668 	enum wlan_umac_comp_id *id;
1669 
1670 	pdev = object;
1671 	id = arg;
1672 
1673 	ret = wlan_objmgr_trigger_pdev_comp_priv_object_creation(pdev, *id);
1674 	if (QDF_IS_STATUS_ERROR(ret))
1675 		hdd_err("pdev obj creation trigger failed");
1676 }
1677 
1678 /**
1679  * son_trigger_pdev_obj_deletion() - Trigger pdev object deletion
1680  * @psoc: psoc object
1681  * @object: pdev object
1682  * @arg: component id
1683  *
1684  * Return: void
1685  */
1686 static void
1687 son_trigger_pdev_obj_deletion(struct wlan_objmgr_psoc *psoc,
1688 			      void *object, void *arg)
1689 {
1690 	QDF_STATUS ret;
1691 	struct wlan_objmgr_pdev *pdev;
1692 	enum wlan_umac_comp_id *id;
1693 
1694 	pdev = object;
1695 	id = arg;
1696 
1697 	ret = wlan_objmgr_trigger_pdev_comp_priv_object_deletion(pdev, *id);
1698 	if (QDF_IS_STATUS_ERROR(ret))
1699 		hdd_err("pdev obj delete trigger failed");
1700 }
1701 
1702 /**
1703  * hdd_son_trigger_objmgr_object_creation() - Trigger objmgr object creation
1704  * @id: umac component id
1705  *
1706  * Return: QDF_STATUS_SUCCESS on success otherwise failure
1707  */
1708 static QDF_STATUS
1709 hdd_son_trigger_objmgr_object_creation(enum wlan_umac_comp_id id)
1710 {
1711 	QDF_STATUS ret;
1712 	struct wlan_objmgr_psoc *psoc;
1713 
1714 	psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_SON_ID);
1715 	if (!psoc) {
1716 		hdd_err("psoc null");
1717 		return QDF_STATUS_E_INVAL;
1718 	}
1719 
1720 	ret = wlan_objmgr_trigger_psoc_comp_priv_object_creation(psoc, id);
1721 	if (QDF_IS_STATUS_ERROR(ret)) {
1722 		hdd_err("psoc object create trigger failed");
1723 		goto out;
1724 	}
1725 
1726 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
1727 					   son_trigger_pdev_obj_creation,
1728 					   &id, 0, id);
1729 	if (QDF_IS_STATUS_ERROR(ret)) {
1730 		hdd_err("pdev object create trigger failed");
1731 		goto fail;
1732 	}
1733 
1734 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
1735 					   son_trigger_vdev_obj_creation,
1736 					   &id, 0, id);
1737 	if (QDF_IS_STATUS_ERROR(ret)) {
1738 		hdd_err("vdev object create trigger failed");
1739 		goto fail1;
1740 	}
1741 	wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID);
1742 	return ret;
1743 
1744 fail1:
1745 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
1746 					   son_trigger_pdev_obj_deletion,
1747 					   &id, 0, id);
1748 	if (QDF_IS_STATUS_ERROR(ret))
1749 		hdd_err("pdev object delete trigger failed");
1750 fail:
1751 	ret = wlan_objmgr_trigger_psoc_comp_priv_object_deletion(psoc, id);
1752 	if (QDF_IS_STATUS_ERROR(ret))
1753 		hdd_err("psoc object delete trigger failed");
1754 out:
1755 	wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID);
1756 	return ret;
1757 }
1758 
1759 /**
1760  * son_trigger_peer_obj_deletion() - Trigger peer object deletion
1761  * @psoc: psoc object
1762  * @object: peer object
1763  * @arg: component id
1764  *
1765  * Return: void
1766  */
1767 static void
1768 son_trigger_peer_obj_deletion(struct wlan_objmgr_psoc *psoc,
1769 			      void *object, void *arg)
1770 {
1771 	QDF_STATUS ret;
1772 	struct wlan_objmgr_peer *peer;
1773 	enum wlan_umac_comp_id *id;
1774 
1775 	peer = object;
1776 	id = arg;
1777 
1778 	ret = wlan_objmgr_trigger_peer_comp_priv_object_deletion(peer, *id);
1779 	if (QDF_IS_STATUS_ERROR(ret))
1780 		hdd_err("peer obj delete trigger failed");
1781 }
1782 
1783 /**
1784  * son_trigger_vdev_obj_deletion() - Trigger vdev object deletion
1785  * @psoc: psoc object
1786  * @object: vdev object
1787  * @arg: component id
1788  *
1789  * Return: void
1790  */
1791 static void
1792 son_trigger_vdev_obj_deletion(struct wlan_objmgr_psoc *psoc,
1793 			      void *object, void *arg)
1794 {
1795 	QDF_STATUS ret;
1796 	struct wlan_objmgr_vdev *vdev;
1797 	enum wlan_umac_comp_id *id;
1798 
1799 	vdev = object;
1800 	id = arg;
1801 
1802 	ret = wlan_objmgr_trigger_vdev_comp_priv_object_deletion(vdev, *id);
1803 	if (QDF_IS_STATUS_ERROR(ret))
1804 		hdd_err("vdev obj deletion trigger failed");
1805 }
1806 
1807 /**
1808  * hdd_son_trigger_objmgr_object_deletion() - Trigger objmgr object deletion
1809  * @id: umac component id
1810  *
1811  * Return: QDF_STATUS_SUCCESS on success otherwise failure
1812  */
1813 static QDF_STATUS
1814 hdd_son_trigger_objmgr_object_deletion(enum wlan_umac_comp_id id)
1815 {
1816 	QDF_STATUS ret;
1817 	struct wlan_objmgr_psoc *psoc;
1818 
1819 	psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_SON_ID);
1820 	if (!psoc) {
1821 		hdd_err("psoc null");
1822 		return QDF_STATUS_E_INVAL;
1823 	}
1824 
1825 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
1826 					   son_trigger_peer_obj_deletion,
1827 					   &id, 0, id);
1828 	if (QDF_IS_STATUS_ERROR(ret))
1829 		hdd_err("peer object deletion trigger failed");
1830 
1831 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
1832 					   son_trigger_vdev_obj_deletion,
1833 					   &id, 0, id);
1834 	if (QDF_IS_STATUS_ERROR(ret))
1835 		hdd_err("vdev object deletion trigger failed");
1836 
1837 	ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
1838 					   son_trigger_pdev_obj_deletion,
1839 					   &id, 0, id);
1840 	if (QDF_IS_STATUS_ERROR(ret))
1841 		hdd_err("pdev object delete trigger failed");
1842 
1843 	ret = wlan_objmgr_trigger_psoc_comp_priv_object_deletion(psoc, id);
1844 	if (QDF_IS_STATUS_ERROR(ret))
1845 		hdd_err("psoc object delete trigger failed");
1846 
1847 	wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID);
1848 	return ret;
1849 }
1850 
1851 /*
1852  * hdd_son_init_acs_channels() -initializes acs configs
1853  *
1854  * @adapter: pointer to hdd adapter
1855  * @hdd_ctx: pointer to hdd context
1856  * @acs_cfg: pointer to acs configs
1857  *
1858  * Return: QDF_STATUS_SUCCESS if ACS configuration is initialized,
1859  */
1860 static QDF_STATUS hdd_son_init_acs_channels(struct hdd_adapter *adapter,
1861 					    struct hdd_context *hdd_ctx,
1862 					    struct sap_acs_cfg *acs_cfg)
1863 {
1864 	enum policy_mgr_con_mode pm_mode;
1865 	uint32_t freq_list[NUM_CHANNELS], num_channels, i;
1866 
1867 	if (!hdd_ctx || !acs_cfg) {
1868 		hdd_err("Null pointer!!! hdd_ctx or acs_cfg");
1869 		return QDF_STATUS_E_INVAL;
1870 	}
1871 	if (acs_cfg->freq_list) {
1872 		hdd_debug("ACS config is already there, no need to init again");
1873 		return QDF_STATUS_SUCCESS;
1874 	}
1875 	/* Setting ACS config */
1876 	qdf_mem_zero(acs_cfg, sizeof(*acs_cfg));
1877 	acs_cfg->ch_width = CH_WIDTH_20MHZ;
1878 	policy_mgr_get_valid_chans(hdd_ctx->psoc, freq_list, &num_channels);
1879 	/* convert and store channel to freq */
1880 	if (!num_channels) {
1881 		hdd_err("No Valid channel for ACS");
1882 		return QDF_STATUS_E_INVAL;
1883 	}
1884 	acs_cfg->freq_list = qdf_mem_malloc(sizeof(*acs_cfg->freq_list) *
1885 					    num_channels);
1886 	if (!acs_cfg->freq_list) {
1887 		hdd_err("Mem-alloc failed for acs_cfg->freq_list");
1888 		return QDF_STATUS_E_NOMEM;
1889 	}
1890 	acs_cfg->master_freq_list =
1891 			qdf_mem_malloc(sizeof(*acs_cfg->master_freq_list) *
1892 				       num_channels);
1893 	if (!acs_cfg->master_freq_list) {
1894 		hdd_err("Mem-alloc failed for acs_cfg->master_freq_list");
1895 		qdf_mem_free(acs_cfg->freq_list);
1896 		acs_cfg->freq_list = NULL;
1897 		return QDF_STATUS_E_NOMEM;
1898 	}
1899 
1900 	pm_mode =
1901 	      policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc,
1902 						   adapter->device_mode,
1903 						   adapter->deflink->vdev_id);
1904 	/* convert channel to freq */
1905 	for (i = 0; i < num_channels; i++) {
1906 		acs_cfg->freq_list[i] = freq_list[i];
1907 		acs_cfg->master_freq_list[i] = freq_list[i];
1908 	}
1909 	acs_cfg->ch_list_count = num_channels;
1910 	acs_cfg->master_ch_list_count = num_channels;
1911 	if (policy_mgr_is_force_scc(hdd_ctx->psoc) &&
1912 	    policy_mgr_get_connection_count(hdd_ctx->psoc)) {
1913 		policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
1914 				   acs_cfg->pcl_chan_freq,
1915 				   &acs_cfg->pcl_ch_count,
1916 				   acs_cfg->pcl_channels_weight_list,
1917 				   NUM_CHANNELS, adapter->deflink->vdev_id);
1918 		wlan_hdd_trim_acs_channel_list(acs_cfg->pcl_chan_freq,
1919 					       acs_cfg->pcl_ch_count,
1920 					       acs_cfg->freq_list,
1921 					       &acs_cfg->ch_list_count);
1922 		if (!acs_cfg->ch_list_count && acs_cfg->master_ch_list_count)
1923 			wlan_hdd_handle_zero_acs_list
1924 					       (hdd_ctx,
1925 						acs_cfg->freq_list,
1926 						&acs_cfg->ch_list_count,
1927 						acs_cfg->master_freq_list,
1928 						acs_cfg->master_ch_list_count);
1929 	}
1930 	acs_cfg->start_ch_freq = acs_cfg->freq_list[0];
1931 	acs_cfg->end_ch_freq = acs_cfg->freq_list[acs_cfg->ch_list_count - 1];
1932 	acs_cfg->hw_mode = eCSR_DOT11_MODE_abg;
1933 
1934 	return QDF_STATUS_SUCCESS;
1935 }
1936 
1937 /**
1938  * hdd_son_start_acs() -Trigers ACS
1939  *
1940  * @vdev: pointer to object mgr vdev
1941  * @enable: True to trigger ACS
1942  *
1943  * Return: 0 on success
1944  */
1945 static int hdd_son_start_acs(struct wlan_objmgr_vdev *vdev, uint8_t enable)
1946 {
1947 	struct hdd_adapter *adapter;
1948 	struct wlan_hdd_link_info *link_info;
1949 	struct sap_config *sap_config;
1950 	struct hdd_context *hdd_ctx;
1951 
1952 	if (!enable) {
1953 		hdd_err("ACS Start report with disabled flag");
1954 		return -EINVAL;
1955 	}
1956 
1957 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1958 	if (!link_info) {
1959 		hdd_err("Invalid VDEV %d", wlan_vdev_get_id(vdev));
1960 		return -EINVAL;
1961 	}
1962 
1963 	adapter = link_info->adapter;
1964 	if (adapter->device_mode != QDF_SAP_MODE) {
1965 		hdd_err("Invalid device mode %d", adapter->device_mode);
1966 		return -EINVAL;
1967 	}
1968 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1969 	if (!hdd_ctx) {
1970 		hdd_err("null hdd_ctx");
1971 		return -EINVAL;
1972 	}
1973 	if (qdf_atomic_read(&link_info->session.ap.acs_in_progress)) {
1974 		hdd_err("ACS is in-progress");
1975 		return -EAGAIN;
1976 	}
1977 	wlan_hdd_undo_acs(link_info);
1978 	sap_config = &link_info->session.ap.sap_config;
1979 	hdd_debug("ACS Config country %s hw_mode %d ACS_BW: %d START_CH: %d END_CH: %d band %d",
1980 		  hdd_ctx->reg.alpha2, sap_config->acs_cfg.hw_mode,
1981 		  sap_config->acs_cfg.ch_width,
1982 		  sap_config->acs_cfg.start_ch_freq,
1983 		  sap_config->acs_cfg.end_ch_freq, sap_config->acs_cfg.band);
1984 	sap_dump_acs_channel(&sap_config->acs_cfg);
1985 
1986 	wlan_hdd_cfg80211_start_acs(link_info);
1987 
1988 	return 0;
1989 }
1990 
1991 #define ACS_SET_CHAN_LIST_APPEND 0xFF
1992 #define ACS_SNR_NEAR_RANGE_MIN 60
1993 #define ACS_SNR_MID_RANGE_MIN 30
1994 #define ACS_SNR_FAR_RANGE_MIN 0
1995 
1996 /**
1997  * hdd_son_set_acs_channels() - Sets Channels for ACS
1998  *
1999  * @vdev: pointer to object mgr vdev
2000  * @req: target channels
2001  *
2002  * Return: 0 on success
2003  */
2004 static int hdd_son_set_acs_channels(struct wlan_objmgr_vdev *vdev,
2005 				    struct ieee80211req_athdbg *req)
2006 {
2007 	struct sap_config *sap_config;
2008 	/* Append the new channels with existing channel list */
2009 	bool append;
2010 	/* Duplicate */
2011 	bool dup;
2012 	uint32_t freq_list[ACS_MAX_CHANNEL_COUNT];
2013 	uint32_t num_channels;
2014 	uint32_t chan_idx = 0;
2015 	uint32_t tmp;
2016 	uint16_t chan_start = 0;
2017 	uint16_t i, j;
2018 	uint16_t acs_chan_count = 0;
2019 	uint32_t *prev_acs_list;
2020 	struct ieee80211_chan_def *chans = req->data.user_chanlist.chans;
2021 	uint16_t nchans = req->data.user_chanlist.n_chan;
2022 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
2023 	struct hdd_adapter *adapter;
2024 	struct wlan_hdd_link_info *link_info;
2025 	struct hdd_context *hdd_ctx;
2026 
2027 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2028 	if (!link_info || !req) {
2029 		hdd_err("null adapter or req");
2030 		return -EINVAL;
2031 	}
2032 
2033 	adapter = link_info->adapter;
2034 	if (adapter->device_mode != QDF_SAP_MODE) {
2035 		hdd_err("Invalid device mode %d", adapter->device_mode);
2036 		return -EINVAL;
2037 	}
2038 	if (!nchans) {
2039 		hdd_err("No channels are sent to be set");
2040 		return -EINVAL;
2041 	}
2042 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2043 	if (!hdd_ctx) {
2044 		hdd_err("null hdd_ctx");
2045 		return -EINVAL;
2046 	}
2047 	sap_config = &link_info->session.ap.sap_config;
2048 	/* initialize with default channels */
2049 	if (hdd_son_init_acs_channels(adapter, hdd_ctx, &sap_config->acs_cfg)
2050 						       != QDF_STATUS_SUCCESS) {
2051 		hdd_err("Failed to start the ACS");
2052 		return -EAGAIN;
2053 	}
2054 	append = (chans[0].chan == ACS_SET_CHAN_LIST_APPEND);
2055 	if (append) {
2056 		chan_start = 1;
2057 		acs_chan_count = sap_config->acs_cfg.ch_list_count;
2058 	}
2059 	prev_acs_list = sap_config->acs_cfg.freq_list;
2060 	for (i = chan_start; i < nchans; i++) {
2061 		tmp = wlan_reg_legacy_chan_to_freq(pdev, chans[i].chan);
2062 		if (append) {
2063 			for (j = 0; j < acs_chan_count; j++) {
2064 				if (prev_acs_list[j] == tmp) {
2065 					dup = true;
2066 					break;
2067 				}
2068 			}
2069 		}
2070 		/* Remove duplicate */
2071 		if (!dup) {
2072 			freq_list[chan_idx] = tmp;
2073 			chan_idx++;
2074 		} else {
2075 			dup = false;
2076 		}
2077 	}
2078 	num_channels = chan_idx + acs_chan_count;
2079 	sap_config->acs_cfg.ch_list_count = num_channels;
2080 	sap_config->acs_cfg.freq_list =
2081 			qdf_mem_malloc(num_channels *
2082 				       sizeof(*sap_config->acs_cfg.freq_list));
2083 	if (!sap_config->acs_cfg.freq_list) {
2084 		hdd_err("Error in allocating memory, failed to set channels");
2085 		sap_config->acs_cfg.freq_list = prev_acs_list;
2086 		sap_config->acs_cfg.ch_list_count = acs_chan_count;
2087 		return -ENOMEM;
2088 	}
2089 	if (append)
2090 		qdf_mem_copy(sap_config->acs_cfg.freq_list, prev_acs_list,
2091 			     sizeof(uint32_t) * acs_chan_count);
2092 	qdf_mem_copy(&sap_config->acs_cfg.freq_list[acs_chan_count], freq_list,
2093 		     sizeof(uint32_t) * chan_idx);
2094 	qdf_mem_free(prev_acs_list);
2095 
2096 	return 0;
2097 }
2098 
2099 static enum wlan_band_id
2100 reg_wifi_band_to_wlan_band_id(enum reg_wifi_band reg_wifi_band)
2101 {
2102 	enum wlan_band_id wlan_band;
2103 	const uint32_t reg_wifi_band_to_wlan_band_id_map[] = {
2104 		[REG_BAND_2G] = WLAN_BAND_2GHZ,
2105 		[REG_BAND_5G] = WLAN_BAND_5GHZ,
2106 		[REG_BAND_6G] = WLAN_BAND_6GHZ,
2107 		[REG_BAND_UNKNOWN] = WLAN_BAND_MAX,};
2108 
2109 	wlan_band = reg_wifi_band_to_wlan_band_id_map[reg_wifi_band];
2110 	if (wlan_band == WLAN_BAND_MAX) {
2111 		hdd_err("Invalid wlan_band_id %d, reg_wifi_band: %d",
2112 			wlan_band, reg_wifi_band);
2113 		return -EINVAL;
2114 	}
2115 
2116 	return wlan_band;
2117 }
2118 
2119 /**
2120  * get_son_acs_report_values() - Gets ACS report for target channel
2121  *
2122  * @vdev: pointer to object mgr vdev
2123  * @acs_r: pointer to acs_dbg
2124  * @mac_handle: Handle to MAC
2125  * @chan_freq: Channel frequency
2126  *
2127  * Return: void
2128  */
2129 static void get_son_acs_report_values(struct wlan_objmgr_vdev *vdev,
2130 				      struct ieee80211_acs_dbg *acs_r,
2131 				      mac_handle_t mac_handle,
2132 				      uint16_t chan_freq)
2133 {
2134 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
2135 	struct scan_filter *filter = qdf_mem_malloc(sizeof(*filter));
2136 	struct scan_cache_node *cur_node;
2137 	struct scan_cache_entry *se;
2138 	enum ieee80211_phymode phymode_se;
2139 	struct ieee80211_ie_hecap *hecap_ie;
2140 	struct ieee80211_ie_srp_extie *srp_ie;
2141 	qdf_list_node_t *cur_lst = NULL, *next_lst = NULL;
2142 	uint32_t srps = 0;
2143 	qdf_list_t *scan_list = NULL;
2144 	uint8_t snr_se, *hecap_phy_ie;
2145 
2146 	if (!filter)
2147 		return;
2148 	filter->num_of_channels = 1;
2149 	filter->chan_freq_list[0] = chan_freq;
2150 	scan_list = ucfg_scan_get_result(pdev, filter);
2151 	acs_r->chan_nbss = qdf_list_size(scan_list);
2152 
2153 	acs_r->chan_maxrssi = 0;
2154 	acs_r->chan_minrssi = 0;
2155 	acs_r->chan_nbss_near = 0;
2156 	acs_r->chan_nbss_mid = 0;
2157 	acs_r->chan_nbss_far = 0;
2158 	acs_r->chan_nbss_srp = 0;
2159 	qdf_list_peek_front(scan_list, &cur_lst);
2160 	while (cur_lst) {
2161 		qdf_list_peek_next(scan_list, cur_lst, &next_lst);
2162 		cur_node = qdf_container_of(cur_lst,
2163 					    struct scan_cache_node, node);
2164 		se = cur_node->entry;
2165 		snr_se = util_scan_entry_snr(se);
2166 		hecap_ie = (struct ieee80211_ie_hecap *)
2167 			   util_scan_entry_hecap(se);
2168 		srp_ie = (struct ieee80211_ie_srp_extie *)
2169 			 util_scan_entry_spatial_reuse_parameter(se);
2170 		phymode_se = util_scan_entry_phymode(se);
2171 
2172 		if (hecap_ie) {
2173 			hecap_phy_ie = &hecap_ie->hecap_phyinfo[0];
2174 			srps = hecap_phy_ie[HECAP_PHYBYTE_IDX7] &
2175 			       HECAP_PHY_SRP_SR_BITS;
2176 		}
2177 
2178 		if (acs_r->chan_maxrssi < snr_se)
2179 			acs_r->chan_maxrssi = snr_se;
2180 		else if (acs_r->chan_minrssi > snr_se)
2181 			acs_r->chan_minrssi = snr_se;
2182 		if (snr_se > ACS_SNR_NEAR_RANGE_MIN)
2183 			acs_r->chan_nbss_near += 1;
2184 		else if (snr_se > ACS_SNR_MID_RANGE_MIN)
2185 			acs_r->chan_nbss_mid += 1;
2186 		else
2187 			acs_r->chan_nbss_far += 1;
2188 		if (srp_ie &&
2189 		    (!(srp_ie->sr_control &
2190 		       IEEE80211_SRP_SRCTRL_OBSS_PD_DISALLOWED_MASK) || srps))
2191 			acs_r->chan_nbss_srp++;
2192 
2193 		cur_lst = next_lst;
2194 		next_lst = NULL;
2195 	}
2196 	acs_r->chan_80211_b_duration = sme_get_11b_data_duration(mac_handle,
2197 								 chan_freq);
2198 	acs_r->chan_nbss_eff = 100 + (acs_r->chan_nbss_near * 50)
2199 				   + (acs_r->chan_nbss_mid * 50)
2200 				   + (acs_r->chan_nbss_far * 25);
2201 	acs_r->chan_srp_load = acs_r->chan_nbss_srp * 4;
2202 	acs_r->chan_efficiency = (1000 + acs_r->chan_grade) /
2203 				  acs_r->chan_nbss_eff;
2204 	ucfg_scan_purge_results(scan_list);
2205 
2206 	qdf_mem_free(filter);
2207 }
2208 
2209 /**
2210  * hdd_son_get_acs_report() - Gets ACS report
2211  *
2212  * @vdev: pointer to object mgr vdev
2213  * @acs_report: pointer to acs_dbg
2214  *
2215  * Return: 0 on success
2216  */
2217 static int hdd_son_get_acs_report(struct wlan_objmgr_vdev *vdev,
2218 				  struct ieee80211_acs_dbg *acs_report)
2219 {
2220 	struct hdd_adapter *adapter;
2221 	struct wlan_hdd_link_info *link_info;
2222 	uint8_t  acs_entry_id = 0;
2223 	ACS_LIST_TYPE acs_type = 0;
2224 	int ret = 0, i = 0;
2225 	struct sap_acs_cfg *acs_cfg;
2226 	struct hdd_context *hdd_ctx;
2227 	struct ieee80211_acs_dbg *acs_r = NULL;
2228 	struct sap_context *sap_ctx;
2229 
2230 	if (!acs_report) {
2231 		hdd_err("null acs_report");
2232 		ret = -EINVAL;
2233 		goto end;
2234 	}
2235 
2236 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2237 	if (!link_info) {
2238 		hdd_err("null adapter");
2239 		ret = -EINVAL;
2240 		goto end;
2241 	}
2242 
2243 	adapter = link_info->adapter;
2244 	if (adapter->device_mode != QDF_SAP_MODE) {
2245 		hdd_err("Invalid device mode %d", adapter->device_mode);
2246 		ret = -EINVAL;
2247 		goto end;
2248 	}
2249 	if (hdd_son_is_acs_in_progress(vdev)) {
2250 		acs_report->nchans = 0;
2251 		hdd_err("ACS is in-progress");
2252 		ret = -EAGAIN;
2253 		goto end;
2254 	}
2255 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2256 	if (!hdd_ctx) {
2257 		hdd_err("null hdd_ctx");
2258 		ret = -EINVAL;
2259 		goto end;
2260 	}
2261 	acs_r = qdf_mem_malloc(sizeof(*acs_r));
2262 	if (!acs_r) {
2263 		hdd_err("Failed to allocate memory");
2264 		ret = -ENOMEM;
2265 		goto end;
2266 	}
2267 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
2268 	acs_cfg = &link_info->session.ap.sap_config.acs_cfg;
2269 	if (!acs_cfg->freq_list &&
2270 	    (hdd_son_init_acs_channels(adapter, hdd_ctx,
2271 				       acs_cfg) != QDF_STATUS_SUCCESS)) {
2272 		hdd_err("Failed to start the ACS");
2273 		ret = -EAGAIN;
2274 		goto end_acs_r_free;
2275 	}
2276 	acs_r->nchans = acs_cfg->ch_list_count;
2277 	ret = copy_from_user(&acs_entry_id, &acs_report->entry_id,
2278 			     sizeof(acs_report->entry_id));
2279 	hdd_debug("acs entry id: %u num of channels: %u",
2280 		  acs_entry_id, acs_r->nchans);
2281 	if (acs_entry_id > acs_r->nchans) {
2282 		ret = -EINVAL;
2283 		goto end_acs_r_free;
2284 	}
2285 	ret = copy_from_user(&acs_type, &acs_report->acs_type,
2286 			     sizeof(acs_report->acs_type));
2287 
2288 	acs_r->acs_status = ACS_DEFAULT;
2289 	acs_r->chan_freq = acs_cfg->freq_list[acs_entry_id];
2290 	acs_r->chan_band = reg_wifi_band_to_wlan_band_id
2291 				(wlan_reg_freq_to_band(acs_r->chan_freq));
2292 	hdd_debug("acs type: %d", acs_type);
2293 	if (acs_type == ACS_CHAN_STATS) {
2294 		acs_r->ieee_chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2295 							 acs_r->chan_freq);
2296 		acs_r->chan_width = IEEE80211_CWM_WIDTH20;
2297 		acs_r->channel_loading = 0;
2298 		acs_r->chan_availability = 100;
2299 		acs_r->chan_grade = 100; /* as hw_chan_grade is 100 in WIN 8 */
2300 		acs_r->sec_chan = false;
2301 		acs_r->chan_radar_noise =
2302 		    wlansap_is_channel_in_nol_list(sap_ctx, acs_r->chan_freq,
2303 						   PHY_SINGLE_CHANNEL_CENTERED);
2304 		get_son_acs_report_values(vdev, acs_r, hdd_ctx->mac_handle,
2305 					  acs_r->chan_freq);
2306 		acs_r->chan_load = 0;
2307 		acs_r->noisefloor = -254; /* NF_INVALID */
2308 		for (i = 0; i < SIR_MAX_NUM_CHANNELS; i++) {
2309 			if (hdd_ctx->chan_info[i].freq == acs_r->chan_freq) {
2310 				acs_r->noisefloor =
2311 					hdd_ctx->chan_info[i].noise_floor;
2312 				acs_r->chan_load =
2313 					hdd_ctx->chan_info[i].rx_clear_count;
2314 				break;
2315 			}
2316 		}
2317 		copy_to_user(acs_report, acs_r, sizeof(*acs_r));
2318 	} else if (acs_type == ACS_CHAN_NF_STATS) {
2319 	} else if (acs_type == ACS_NEIGHBOUR_GET_LIST_COUNT ||
2320 		   acs_type == ACS_NEIGHBOUR_GET_LIST) {
2321 	}
2322 end_acs_r_free:
2323 	qdf_mem_free(acs_r);
2324 end:
2325 	return ret;
2326 }
2327 
2328 static const uint8_t wlanphymode2ieeephymode[WLAN_PHYMODE_MAX] = {
2329 	[WLAN_PHYMODE_AUTO] = IEEE80211_MODE_AUTO,
2330 	[WLAN_PHYMODE_11A] = IEEE80211_MODE_11A,
2331 	[WLAN_PHYMODE_11B] = IEEE80211_MODE_11B,
2332 	[WLAN_PHYMODE_11G] = IEEE80211_MODE_11G,
2333 	[WLAN_PHYMODE_11G_ONLY] = IEEE80211_MODE_11G,
2334 	[WLAN_PHYMODE_11NA_HT20] = IEEE80211_MODE_11NA_HT20,
2335 	[WLAN_PHYMODE_11NG_HT20] = IEEE80211_MODE_11NG_HT20,
2336 	[WLAN_PHYMODE_11NA_HT40] = IEEE80211_MODE_11NA_HT40,
2337 	[WLAN_PHYMODE_11NG_HT40PLUS] = IEEE80211_MODE_11NG_HT40PLUS,
2338 	[WLAN_PHYMODE_11NG_HT40MINUS] = IEEE80211_MODE_11NG_HT40MINUS,
2339 	[WLAN_PHYMODE_11NG_HT40] = IEEE80211_MODE_11NG_HT40,
2340 	[WLAN_PHYMODE_11AC_VHT20] = IEEE80211_MODE_11AC_VHT20,
2341 	[WLAN_PHYMODE_11AC_VHT20_2G] = IEEE80211_MODE_11AC_VHT20,
2342 	[WLAN_PHYMODE_11AC_VHT40] = IEEE80211_MODE_11AC_VHT40,
2343 	[WLAN_PHYMODE_11AC_VHT40PLUS_2G] = IEEE80211_MODE_11AC_VHT40PLUS,
2344 	[WLAN_PHYMODE_11AC_VHT40MINUS_2G] = IEEE80211_MODE_11AC_VHT40MINUS,
2345 	[WLAN_PHYMODE_11AC_VHT40_2G] = IEEE80211_MODE_11AC_VHT40,
2346 	[WLAN_PHYMODE_11AC_VHT80] = IEEE80211_MODE_11AC_VHT80,
2347 	[WLAN_PHYMODE_11AC_VHT80_2G] = IEEE80211_MODE_11AC_VHT80,
2348 	[WLAN_PHYMODE_11AC_VHT160] = IEEE80211_MODE_11AC_VHT160,
2349 	[WLAN_PHYMODE_11AC_VHT80_80] = IEEE80211_MODE_11AC_VHT80_80,
2350 	[WLAN_PHYMODE_11AXA_HE20] = IEEE80211_MODE_11AXA_HE20,
2351 	[WLAN_PHYMODE_11AXG_HE20] = IEEE80211_MODE_11AXG_HE20,
2352 	[WLAN_PHYMODE_11AXA_HE40] = IEEE80211_MODE_11AXA_HE40,
2353 	[WLAN_PHYMODE_11AXG_HE40PLUS] = IEEE80211_MODE_11AXG_HE40PLUS,
2354 	[WLAN_PHYMODE_11AXG_HE40MINUS] = IEEE80211_MODE_11AXG_HE40MINUS,
2355 	[WLAN_PHYMODE_11AXG_HE40] = IEEE80211_MODE_11AXG_HE40,
2356 	[WLAN_PHYMODE_11AXA_HE80] = IEEE80211_MODE_11AXA_HE80,
2357 	[WLAN_PHYMODE_11AXA_HE160] = IEEE80211_MODE_11AXA_HE160,
2358 	[WLAN_PHYMODE_11AXA_HE80_80] = IEEE80211_MODE_11AXA_HE80_80,
2359 #ifdef WLAN_FEATURE_11BE
2360 	[WLAN_PHYMODE_11BEA_EHT20] = IEEE80211_MODE_11BEA_EHT20,
2361 	[WLAN_PHYMODE_11BEG_EHT20] = IEEE80211_MODE_11BEG_EHT20,
2362 	[WLAN_PHYMODE_11BEA_EHT40MINUS] = IEEE80211_MODE_11BEA_EHT40,
2363 	[WLAN_PHYMODE_11BEG_EHT40PLUS] = IEEE80211_MODE_11BEG_EHT40PLUS,
2364 	[WLAN_PHYMODE_11BEG_EHT40MINUS] = IEEE80211_MODE_11BEG_EHT40MINUS,
2365 	[WLAN_PHYMODE_11BEG_EHT40] = IEEE80211_MODE_11BEG_EHT40,
2366 	[WLAN_PHYMODE_11BEA_EHT80] = IEEE80211_MODE_11BEA_EHT80,
2367 	[WLAN_PHYMODE_11BEG_EHT80] = 0,
2368 	[WLAN_PHYMODE_11BEA_EHT160] = IEEE80211_MODE_11BEA_EHT160,
2369 	[WLAN_PHYMODE_11BEA_EHT320] = IEEE80211_MODE_11BEA_EHT320,
2370 #endif /* WLAN_FEATURE_11BE */
2371 };
2372 
2373 static enum ieee80211_phymode
2374 wlan_hdd_son_get_ieee_phymode(enum wlan_phymode wlan_phymode)
2375 {
2376 	if (wlan_phymode >= WLAN_PHYMODE_MAX)
2377 		return IEEE80211_MODE_AUTO;
2378 
2379 	return wlanphymode2ieeephymode[wlan_phymode];
2380 }
2381 
2382 /**
2383  * hdd_son_get_peer_tx_rate() - Get peer tx rate from FW
2384  * @vdev: pointer to object mgr vdev
2385  * @peer_macaddr: peer mac address
2386  *
2387  * Return: tx rate in Kbps
2388  */
2389 static uint32_t hdd_son_get_peer_tx_rate(struct wlan_objmgr_vdev *vdev,
2390 					 uint8_t *peer_macaddr)
2391 {
2392 	uint32_t tx_rate = 0;
2393 	struct stats_event *stats;
2394 	int retval = 0;
2395 
2396 	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(vdev,
2397 							 peer_macaddr,
2398 							 &retval);
2399 	if (retval || !stats) {
2400 		if (stats)
2401 			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
2402 		hdd_err("Unable to get peer tx rate from fw");
2403 		return tx_rate;
2404 	}
2405 
2406 	tx_rate = stats->peer_stats_info_ext->tx_rate;
2407 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
2408 
2409 	return tx_rate;
2410 }
2411 
2412 static QDF_STATUS hdd_son_get_node_info_sta(struct wlan_objmgr_vdev *vdev,
2413 					    uint8_t *mac_addr,
2414 					    wlan_node_info *node_info)
2415 {
2416 	struct wlan_hdd_link_info *link_info;
2417 
2418 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2419 	if (!link_info ||
2420 	    wlan_hdd_validate_context(link_info->adapter->hdd_ctx))
2421 		return QDF_STATUS_E_FAILURE;
2422 
2423 	if (!hdd_cm_is_vdev_associated(link_info)) {
2424 		hdd_debug_rl("STA VDEV not connected");
2425 		/* Still return success and framework will see default stats */
2426 		return QDF_STATUS_SUCCESS;
2427 	}
2428 
2429 	node_info->tx_bitrate = hdd_son_get_peer_tx_rate(vdev, mac_addr);
2430 	/* convert it to Mbps */
2431 	node_info->tx_bitrate = qdf_do_div(node_info->tx_bitrate, 1000);
2432 	hdd_debug_rl("tx_bitrate %u", node_info->tx_bitrate);
2433 
2434 	return QDF_STATUS_SUCCESS;
2435 }
2436 
2437 static QDF_STATUS hdd_son_get_node_info_sap(struct wlan_objmgr_vdev *vdev,
2438 					    uint8_t *mac_addr,
2439 					    wlan_node_info *node_info)
2440 {
2441 	struct hdd_adapter *adapter;
2442 	struct wlan_hdd_link_info *link_info;
2443 	struct hdd_station_info *sta_info;
2444 	enum wlan_phymode peer_phymode;
2445 	struct wlan_objmgr_psoc *psoc;
2446 
2447 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2448 	if (!link_info) {
2449 		hdd_debug("NULL adapter");
2450 		return QDF_STATUS_E_FAILURE;
2451 	}
2452 
2453 	adapter = link_info->adapter;
2454 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac_addr,
2455 					   STA_INFO_SON_GET_DATRATE_INFO);
2456 	if (!sta_info) {
2457 		hdd_err("Sta info is null");
2458 		return QDF_STATUS_E_FAILURE;
2459 	}
2460 	psoc = wlan_vdev_get_psoc(vdev);
2461 	if (!psoc) {
2462 		hdd_err("null psoc");
2463 		return QDF_STATUS_E_FAILURE;
2464 	}
2465 
2466 	node_info->tx_bitrate = hdd_son_get_peer_tx_rate(vdev, mac_addr);
2467 	/* convert it to Mbps */
2468 	node_info->tx_bitrate = qdf_do_div(node_info->tx_bitrate, 1000);
2469 	node_info->max_chwidth =
2470 			hdd_chan_width_to_son_chwidth(sta_info->ch_width);
2471 	node_info->num_streams = sta_info->nss;
2472 	ucfg_mlme_get_peer_phymode(psoc, mac_addr, &peer_phymode);
2473 	node_info->phymode = wlan_hdd_son_get_ieee_phymode(peer_phymode);
2474 	node_info->max_txpower = ucfg_son_get_tx_power(sta_info->assoc_req_ies);
2475 	node_info->max_MCS = sta_info->max_real_mcs_idx;
2476 	if (node_info->max_MCS == INVALID_MCS_NSS_INDEX) {
2477 		hdd_err("invalid mcs");
2478 		return QDF_STATUS_E_FAILURE;
2479 	}
2480 	if (sta_info->vht_present)
2481 		node_info->is_mu_mimo_supported =
2482 				sta_info->vht_caps.vht_cap_info
2483 				& IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
2484 	if (sta_info->ht_present)
2485 		node_info->is_static_smps = ((sta_info->ht_caps.cap_info
2486 				& IEEE80211_HTCAP_C_SM_MASK) ==
2487 				IEEE80211_HTCAP_C_SMPOWERSAVE_STATIC);
2488 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
2489 			     STA_INFO_SON_GET_DATRATE_INFO);
2490 	return QDF_STATUS_SUCCESS;
2491 }
2492 
2493 static QDF_STATUS hdd_son_get_node_info(struct wlan_objmgr_vdev *vdev,
2494 					uint8_t *mac_addr,
2495 					wlan_node_info *node_info)
2496 {
2497 	struct hdd_adapter *adapter;
2498 	struct wlan_hdd_link_info *link_info;
2499 
2500 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2501 	if (!link_info) {
2502 		hdd_debug("NULL adapter");
2503 		return QDF_STATUS_E_FAILURE;
2504 	}
2505 
2506 	adapter = link_info->adapter;
2507 	if (adapter->device_mode == QDF_STA_MODE)
2508 		return hdd_son_get_node_info_sta(vdev, mac_addr, node_info);
2509 	else if (adapter->device_mode == QDF_SAP_MODE)
2510 		return hdd_son_get_node_info_sap(vdev, mac_addr, node_info);
2511 	else
2512 		return QDF_STATUS_SUCCESS;
2513 }
2514 
2515 static QDF_STATUS hdd_son_get_peer_capability(struct wlan_objmgr_vdev *vdev,
2516 					      struct wlan_objmgr_peer *peer,
2517 					      wlan_peer_cap *peer_cap)
2518 {
2519 	struct hdd_station_info *sta_info;
2520 	struct hdd_adapter *adapter;
2521 	struct wlan_hdd_link_info *link_info;
2522 	bool b_meas_supported;
2523 	QDF_STATUS status;
2524 
2525 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2526 	if (!link_info) {
2527 		hdd_err("null adapter");
2528 		return QDF_STATUS_E_FAILURE;
2529 	}
2530 
2531 	adapter = link_info->adapter;
2532 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
2533 					   peer->macaddr,
2534 					   STA_INFO_SOFTAP_GET_STA_INFO);
2535 	if (!sta_info) {
2536 		hdd_err("sta_info NULL");
2537 		return QDF_STATUS_E_FAILURE;
2538 	}
2539 
2540 	hdd_info("Getting peer capability from sta_info");
2541 	qdf_mem_copy(peer_cap->bssid, vdev->vdev_mlme.macaddr,
2542 		     QDF_MAC_ADDR_SIZE);
2543 	peer_cap->is_BTM_Supported = !!(sta_info->ext_cap &
2544 				   BIT(19/*BSS_TRANSITION*/));
2545 	peer_cap->is_RRM_Supported = !!(sta_info->capability &
2546 				   WLAN_CAPABILITY_RADIO_MEASURE);
2547 
2548 	peer_cap->band_cap = sta_info->supported_band;
2549 	if (sta_info->assoc_req_ies.len) {
2550 		status = ucfg_son_get_peer_rrm_info(sta_info->assoc_req_ies,
2551 						    peer_cap->rrmcaps,
2552 						    &(b_meas_supported));
2553 		if (status == QDF_STATUS_SUCCESS)
2554 			peer_cap->is_beacon_meas_supported = b_meas_supported;
2555 	}
2556 	if (sta_info->ht_present)
2557 		peer_cap->htcap = sta_info->ht_caps.cap_info;
2558 	if (sta_info->vht_present)
2559 		peer_cap->vhtcap = sta_info->vht_caps.vht_cap_info;
2560 
2561 	qdf_mem_zero(&peer_cap->hecap, sizeof(wlan_client_he_capabilities));
2562 
2563 	os_if_son_get_node_datarate_info(vdev, peer->macaddr,
2564 					 &peer_cap->info);
2565 
2566 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
2567 			     STA_INFO_SOFTAP_GET_STA_INFO);
2568 
2569 	return QDF_STATUS_SUCCESS;
2570 }
2571 
2572 uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
2573 				      struct wlan_objmgr_peer *peer)
2574 {
2575 	uint32_t ret = 0;
2576 	struct hdd_station_info *sta_info = NULL;
2577 	struct hdd_adapter *adapter;
2578 	struct wlan_hdd_link_info *link_info;
2579 
2580 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
2581 	if (!link_info) {
2582 		hdd_err("null adapter");
2583 		return ret;
2584 	}
2585 
2586 	adapter = link_info->adapter;
2587 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
2588 					   peer->macaddr,
2589 					   STA_INFO_SOFTAP_GET_STA_INFO);
2590 	if (!sta_info) {
2591 		hdd_err("sta_info NULL");
2592 		return ret;
2593 	}
2594 
2595 	ret = sta_info->max_real_mcs_idx;
2596 
2597 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
2598 			     STA_INFO_SOFTAP_GET_STA_INFO);
2599 	hdd_debug("Peer " QDF_MAC_ADDR_FMT " max MCS index: %u",
2600 		  QDF_MAC_ADDR_REF(peer->macaddr), ret);
2601 
2602 	return ret;
2603 }
2604 
2605 /**
2606  * hdd_son_get_sta_stats() - get connected sta rssi and estimated data rate
2607  * @vdev: pointer to vdev
2608  * @mac_addr: connected sta mac addr
2609  * @stats: pointer to ieee80211_nodestats
2610  *
2611  * Return: 0 on success, negative errno on failure
2612  */
2613 static int hdd_son_get_sta_stats(struct wlan_objmgr_vdev *vdev,
2614 				 uint8_t *mac_addr,
2615 				 struct ieee80211_nodestats *stats)
2616 {
2617 	struct stats_event *stats_info;
2618 	int ret = 0;
2619 
2620 	stats_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi(
2621 			vdev, mac_addr, &ret);
2622 	if (ret || !stats_info) {
2623 		hdd_err("get peer rssi fail");
2624 		wlan_cfg80211_mc_cp_stats_free_stats_event(stats_info);
2625 		return ret;
2626 	}
2627 	stats->ns_rssi = stats_info->peer_stats[0].peer_rssi;
2628 	stats->ns_last_tx_rate = stats_info->peer_stats[0].tx_rate;
2629 	stats->ns_last_rx_rate = stats_info->peer_stats[0].rx_rate;
2630 	hdd_debug("sta " QDF_MAC_ADDR_FMT " rssi %d tx %u kbps, rx %u kbps",
2631 		  QDF_MAC_ADDR_REF(mac_addr), stats->ns_rssi,
2632 		  stats->ns_last_tx_rate,
2633 		  stats->ns_last_rx_rate);
2634 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats_info);
2635 
2636 	return ret;
2637 }
2638 
2639 void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
2640 {
2641 	struct son_callbacks cb_obj = {0};
2642 
2643 	cb_obj.os_if_is_acs_in_progress = hdd_son_is_acs_in_progress;
2644 	cb_obj.os_if_set_chan_ext_offset = hdd_son_set_chan_ext_offset;
2645 	cb_obj.os_if_get_chan_ext_offset = hdd_son_get_chan_ext_offset;
2646 	cb_obj.os_if_set_bandwidth = hdd_son_set_bandwidth;
2647 	cb_obj.os_if_get_bandwidth = hdd_son_get_bandwidth;
2648 	cb_obj.os_if_set_chan = hdd_son_set_chan;
2649 	cb_obj.os_if_set_acl_policy = hdd_son_set_acl_policy;
2650 	cb_obj.os_if_get_acl_policy = hdd_son_get_acl_policy;
2651 	cb_obj.os_if_add_acl_mac = hdd_son_add_acl_mac;
2652 	cb_obj.os_if_del_acl_mac = hdd_son_del_acl_mac;
2653 	cb_obj.os_if_kickout_mac = hdd_son_kickout_mac;
2654 	cb_obj.os_if_set_country_code = hdd_son_set_country;
2655 	cb_obj.os_if_set_candidate_freq = hdd_son_set_candidate_freq;
2656 	cb_obj.os_if_get_candidate_freq = hdd_son_get_candidate_freq;
2657 	cb_obj.os_if_set_phymode = hdd_son_set_phymode;
2658 	cb_obj.os_if_get_phymode = hdd_son_get_phymode;
2659 	cb_obj.os_if_get_rx_nss = hdd_son_get_rx_nss;
2660 	cb_obj.os_if_set_chwidth = hdd_son_set_chwidth;
2661 	cb_obj.os_if_get_chwidth = hdd_son_get_chwidth;
2662 	cb_obj.os_if_deauth_sta = hdd_son_deauth_sta;
2663 	cb_obj.os_if_modify_acl = hdd_son_modify_acl;
2664 	cb_obj.os_if_get_sta_list = hdd_son_get_sta_list;
2665 	cb_obj.os_if_get_sta_space = hdd_son_get_sta_space;
2666 	cb_obj.os_if_get_vdev_by_netdev = hdd_son_get_vdev_by_netdev;
2667 	cb_obj.os_if_trigger_objmgr_object_creation =
2668 				hdd_son_trigger_objmgr_object_creation;
2669 	cb_obj.os_if_trigger_objmgr_object_deletion =
2670 				hdd_son_trigger_objmgr_object_deletion;
2671 	cb_obj.os_if_start_acs = hdd_son_start_acs;
2672 	cb_obj.os_if_set_acs_channels = hdd_son_set_acs_channels;
2673 	cb_obj.os_if_get_acs_report = hdd_son_get_acs_report;
2674 	cb_obj.os_if_get_node_info = hdd_son_get_node_info;
2675 	cb_obj.os_if_get_peer_capability = hdd_son_get_peer_capability;
2676 	cb_obj.os_if_get_peer_max_mcs_idx = hdd_son_get_peer_max_mcs_idx;
2677 	cb_obj.os_if_get_sta_stats = hdd_son_get_sta_stats;
2678 
2679 	os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
2680 
2681 	ucfg_son_register_deliver_opmode_cb(hdd_ctx->psoc,
2682 					    hdd_son_deliver_opmode);
2683 	ucfg_son_register_deliver_smps_cb(hdd_ctx->psoc,
2684 					  hdd_son_deliver_smps);
2685 }
2686 
2687 int hdd_son_deliver_acs_complete_event(struct hdd_adapter *adapter)
2688 {
2689 	int ret = -EINVAL;
2690 	struct wlan_objmgr_vdev *vdev;
2691 
2692 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID);
2693 	if (!vdev) {
2694 		hdd_err("null vdev");
2695 		return ret;
2696 	}
2697 	ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_ACS_COMPLETE,
2698 					  NULL);
2699 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2700 	return ret;
2701 }
2702 
2703 int hdd_son_deliver_cac_status_event(struct hdd_adapter *adapter,
2704 				     qdf_freq_t freq, bool radar_detected)
2705 {
2706 	int ret = -EINVAL;
2707 	struct wlan_objmgr_vdev *vdev;
2708 	struct son_ald_cac_info cac_info;
2709 
2710 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID);
2711 	if (!vdev) {
2712 		hdd_err("null vdev");
2713 		return ret;
2714 	}
2715 	cac_info.freq = freq;
2716 	cac_info.radar_detected = radar_detected;
2717 	ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_CAC_STATUS,
2718 					  &cac_info);
2719 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2720 
2721 	return ret;
2722 }
2723 
2724 int hdd_son_deliver_assoc_disassoc_event(struct hdd_adapter *adapter,
2725 					 struct qdf_mac_addr sta_mac,
2726 					 uint32_t reason_code,
2727 					 enum assoc_disassoc_event flag)
2728 {
2729 	int ret = -EINVAL;
2730 	struct son_ald_assoc_event_info info;
2731 	struct wlan_objmgr_vdev *vdev;
2732 
2733 	qdf_mem_zero(&info, sizeof(info));
2734 	memcpy(info.macaddr, &sta_mac.bytes, QDF_MAC_ADDR_SIZE);
2735 	info.flag = flag;
2736 	info.reason = reason_code;
2737 
2738 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID);
2739 	if (!vdev) {
2740 		hdd_err("null vdev");
2741 		return ret;
2742 	}
2743 	ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_ASSOC_DISASSOC,
2744 					  &info);
2745 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2746 	return ret;
2747 }
2748 
2749 void hdd_son_deliver_peer_authorize_event(struct wlan_hdd_link_info *link_info,
2750 					  uint8_t *peer_mac)
2751 {
2752 	struct wlan_objmgr_peer *peer;
2753 	int ret;
2754 	struct wlan_objmgr_vdev *vdev;
2755 	struct wlan_objmgr_psoc *psoc;
2756 
2757 	if (link_info->adapter->device_mode != QDF_SAP_MODE) {
2758 		hdd_err("Non SAP vdev");
2759 		return;
2760 	}
2761 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_SON_ID);
2762 	if (!vdev) {
2763 		hdd_err("null vdev");
2764 		return;
2765 	}
2766 	psoc = wlan_vdev_get_psoc(vdev);
2767 	if (!psoc) {
2768 		hdd_err("null psoc");
2769 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2770 		return;
2771 	}
2772 	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac, WLAN_UMAC_COMP_SON);
2773 	if (!peer) {
2774 		hdd_err("No peer object for sta" QDF_MAC_ADDR_FMT,
2775 			QDF_MAC_ADDR_REF(peer_mac));
2776 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2777 		return;
2778 	}
2779 
2780 	ret = os_if_son_deliver_ald_event(vdev, peer,
2781 					  MLME_EVENT_CLIENT_ASSOCIATED, NULL);
2782 	if (ret)
2783 		hdd_err("ALD ASSOCIATED Event failed for" QDF_MAC_ADDR_FMT,
2784 			QDF_MAC_ADDR_REF(peer_mac));
2785 
2786 	wlan_objmgr_peer_release_ref(peer, WLAN_UMAC_COMP_SON);
2787 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2788 }
2789 
2790 int hdd_son_deliver_chan_change_event(struct hdd_adapter *adapter,
2791 				      qdf_freq_t freq)
2792 {
2793 	int ret = -EINVAL;
2794 	struct wlan_objmgr_vdev *vdev;
2795 	struct son_ald_chan_change_info chan_info;
2796 	struct wlan_objmgr_pdev *pdev;
2797 
2798 	if (!adapter) {
2799 		hdd_err("null adapter");
2800 		return ret;
2801 	}
2802 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID);
2803 	if (!vdev) {
2804 		hdd_err("null vdev");
2805 		return ret;
2806 	}
2807 	pdev = wlan_vdev_get_pdev(vdev);
2808 	if (!pdev) {
2809 		hdd_err("null pdev");
2810 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2811 		return ret;
2812 	}
2813 	chan_info.freq = freq;
2814 	chan_info.chan_num = wlan_reg_freq_to_chan(pdev, freq);
2815 	ret = os_if_son_deliver_ald_event(vdev, NULL,
2816 					  MLME_EVENT_CHAN_CHANGE,
2817 					  &chan_info);
2818 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID);
2819 
2820 	return ret;
2821 }
2822 
2823 int hdd_son_send_set_wifi_generic_command(struct wiphy *wiphy,
2824 					  struct wireless_dev *wdev,
2825 					  struct nlattr **tb)
2826 {
2827 	return os_if_son_parse_generic_nl_cmd(wiphy, wdev, tb,
2828 					      OS_IF_SON_VENDOR_SET_CMD);
2829 }
2830 
2831 int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy,
2832 					  struct wireless_dev *wdev,
2833 					  struct nlattr **tb)
2834 {
2835 	return os_if_son_parse_generic_nl_cmd(wiphy, wdev, tb,
2836 					      OS_IF_SON_VENDOR_GET_CMD);
2837 }
2838