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, ¶m);
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