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