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 interface prototypes for son api
20  */
21 
22 #include <son_api.h>
23 #include <wlan_reg_services_api.h>
24 #include <wlan_mlme_api.h>
25 #include <ieee80211_external.h>
26 #include <wlan_cfg80211_scan.h>
27 #include <wlan_mlme_main.h>
28 
29 /**
30  * struct son_mlme_deliver_cbs - son mlme deliver callbacks
31  * @deliver_opmode: cb to deliver opmode
32  * @deliver_smps: cb to deliver smps
33  */
34 struct son_mlme_deliver_cbs {
35 	mlme_deliver_cb deliver_opmode;
36 	mlme_deliver_cb deliver_smps;
37 };
38 
39 static struct son_mlme_deliver_cbs g_son_mlme_deliver_cbs;
40 
41 static struct son_cbs *g_son_cbs[WLAN_MAX_VDEVS];
42 static qdf_spinlock_t g_cbs_lock;
43 
44 QDF_STATUS
wlan_son_register_mlme_deliver_cb(struct wlan_objmgr_psoc * psoc,mlme_deliver_cb cb,enum SON_MLME_DELIVER_CB_TYPE type)45 wlan_son_register_mlme_deliver_cb(struct wlan_objmgr_psoc *psoc,
46 				  mlme_deliver_cb cb,
47 				  enum SON_MLME_DELIVER_CB_TYPE type)
48 {
49 	if (!psoc) {
50 		son_err("invalid psoc");
51 		return QDF_STATUS_E_INVAL;
52 	}
53 
54 	switch (type) {
55 	case SON_MLME_DELIVER_CB_TYPE_OPMODE:
56 		g_son_mlme_deliver_cbs.deliver_opmode = cb;
57 		break;
58 	case SON_MLME_DELIVER_CB_TYPE_SMPS:
59 		g_son_mlme_deliver_cbs.deliver_smps = cb;
60 		break;
61 	default:
62 		son_err("invalid type");
63 		break;
64 	}
65 
66 	return QDF_STATUS_SUCCESS;
67 }
68 
69 /**
70  * wlan_son_is_he_supported() - is he supported or not
71  * @psoc: pointer to psoc
72  *
73  * Return: true if supports, false otherwise
74  */
75 #ifdef WLAN_FEATURE_11AX
wlan_son_is_he_supported(struct wlan_objmgr_psoc * psoc)76 static bool wlan_son_is_he_supported(struct wlan_objmgr_psoc *psoc)
77 {
78 	tDot11fIEhe_cap he_cap = {0};
79 
80 	mlme_cfg_get_he_caps(psoc, &he_cap);
81 	return !!he_cap.present;
82 }
83 #else
wlan_son_is_he_supported(struct wlan_objmgr_psoc * psoc)84 static bool wlan_son_is_he_supported(struct wlan_objmgr_psoc *psoc)
85 {
86 	return false;
87 }
88 #endif /*WLAN_FEATURE_11AX*/
89 
wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev * pdev,uint8_t * mac_addr,struct wlan_objmgr_vdev * vdev,uint32_t stats_count,uint32_t enable)90 QDF_STATUS wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev *pdev,
91 					 uint8_t *mac_addr,
92 					 struct wlan_objmgr_vdev *vdev,
93 					 uint32_t stats_count,
94 					 uint32_t enable)
95 {
96 	struct wlan_lmac_if_tx_ops *tx_ops;
97 	struct wlan_objmgr_psoc *psoc;
98 
99 	if (!pdev) {
100 		son_err("invalid pdev");
101 		return QDF_STATUS_E_NULL_VALUE;
102 	}
103 	psoc = wlan_pdev_get_psoc(pdev);
104 	if (!psoc) {
105 		son_err("invalid psoc");
106 		return QDF_STATUS_E_NULL_VALUE;
107 	}
108 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
109 	if (!tx_ops) {
110 		son_err("invalid tx_ops");
111 		return QDF_STATUS_E_NULL_VALUE;
112 	}
113 	if (tx_ops->son_tx_ops.peer_ext_stats_enable)
114 		return tx_ops->son_tx_ops.peer_ext_stats_enable(pdev,
115 								mac_addr, vdev,
116 								stats_count,
117 								enable);
118 
119 	return QDF_STATUS_E_NULL_VALUE;
120 }
121 
wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev * pdev,uint8_t * mac_addr,struct wlan_objmgr_vdev * vdev)122 QDF_STATUS wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev *pdev,
123 					uint8_t *mac_addr,
124 					struct wlan_objmgr_vdev *vdev)
125 {
126 	struct wlan_lmac_if_tx_ops *tx_ops;
127 	struct wlan_objmgr_psoc *psoc;
128 
129 	if (!pdev) {
130 		son_err("invalid pdev");
131 		return QDF_STATUS_E_NULL_VALUE;
132 	}
133 	psoc = wlan_pdev_get_psoc(pdev);
134 	if (!psoc) {
135 		son_err("invalid psoc");
136 		return QDF_STATUS_E_NULL_VALUE;
137 	}
138 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
139 	if (!tx_ops) {
140 		son_err("invalid tx_ops");
141 		return QDF_STATUS_E_NULL_VALUE;
142 	}
143 	if (tx_ops->son_tx_ops.son_send_null)
144 		return tx_ops->son_tx_ops.son_send_null(pdev, mac_addr, vdev);
145 
146 	return QDF_STATUS_E_NULL_VALUE;
147 }
148 
wlan_son_get_chan_flag(struct wlan_objmgr_pdev * pdev,qdf_freq_t freq,bool flag_160,struct ch_params * chan_params)149 uint32_t wlan_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
150 				qdf_freq_t freq, bool flag_160,
151 				struct ch_params *chan_params)
152 {
153 	uint32_t flags = 0;
154 	qdf_freq_t sec_freq;
155 	struct ch_params ch_width40_ch_params;
156 	uint8_t sub_20_channel_width = 0;
157 	enum phy_ch_width bandwidth = mlme_get_vht_ch_width();
158 	struct wlan_objmgr_psoc *psoc;
159 	bool is_he_enabled;
160 	struct ch_params ch_params;
161 
162 	if (!pdev) {
163 		son_err("invalid pdev");
164 		return flags;
165 	}
166 	psoc = wlan_pdev_get_psoc(pdev);
167 	if (!psoc) {
168 		son_err("invalid psoc");
169 		return flags;
170 	}
171 
172 	is_he_enabled = wlan_son_is_he_supported(psoc);
173 	wlan_mlme_get_sub_20_chan_width(wlan_pdev_get_psoc(pdev),
174 					&sub_20_channel_width);
175 
176 	qdf_mem_zero(chan_params, sizeof(*chan_params));
177 	qdf_mem_zero(&ch_params, sizeof(ch_params));
178 	qdf_mem_zero(&ch_width40_ch_params, sizeof(ch_width40_ch_params));
179 	if (wlan_reg_is_24ghz_ch_freq(freq)) {
180 		if (bandwidth == CH_WIDTH_80P80MHZ ||
181 		    bandwidth == CH_WIDTH_160MHZ ||
182 		    bandwidth == CH_WIDTH_80MHZ)
183 			bandwidth = CH_WIDTH_40MHZ;
184 	}
185 
186 	ch_params.ch_width = bandwidth;
187 	switch (bandwidth) {
188 	case CH_WIDTH_80P80MHZ:
189 		ch_params.ch_width = CH_WIDTH_80P80MHZ;
190 		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
191 					pdev, freq,
192 					&ch_params, REG_CURRENT_PWR_MODE) !=
193 		    CHANNEL_STATE_INVALID) {
194 			if (!flag_160) {
195 				chan_params->ch_width = CH_WIDTH_80P80MHZ;
196 				wlan_reg_set_channel_params_for_pwrmode(
197 					pdev, freq, 0, chan_params,
198 					REG_CURRENT_PWR_MODE);
199 			}
200 			if (is_he_enabled)
201 				flags |= VENDOR_CHAN_FLAG2(
202 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80_80);
203 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80_80;
204 		}
205 		bandwidth = CH_WIDTH_160MHZ;
206 		fallthrough;
207 	case CH_WIDTH_160MHZ:
208 		ch_params.ch_width = CH_WIDTH_160MHZ;
209 		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
210 					pdev, freq,
211 					&ch_params, REG_CURRENT_PWR_MODE) !=
212 		    CHANNEL_STATE_INVALID) {
213 			if (flag_160) {
214 				chan_params->ch_width = CH_WIDTH_160MHZ;
215 				wlan_reg_set_channel_params_for_pwrmode(
216 					pdev, freq, 0, chan_params,
217 					REG_CURRENT_PWR_MODE);
218 			}
219 			if (is_he_enabled)
220 				flags |= VENDOR_CHAN_FLAG2(
221 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE160);
222 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT160;
223 		}
224 		bandwidth = CH_WIDTH_80MHZ;
225 		fallthrough;
226 	case CH_WIDTH_80MHZ:
227 		ch_params.ch_width = CH_WIDTH_80MHZ;
228 		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
229 					pdev, freq,
230 					&ch_params, REG_CURRENT_PWR_MODE) !=
231 		    CHANNEL_STATE_INVALID) {
232 			if (!flag_160 &&
233 			    chan_params->ch_width != CH_WIDTH_80P80MHZ) {
234 				chan_params->ch_width = CH_WIDTH_80MHZ;
235 				wlan_reg_set_channel_params_for_pwrmode(
236 					pdev, freq, 0, chan_params,
237 					REG_CURRENT_PWR_MODE);
238 			}
239 			if (is_he_enabled)
240 				flags |= VENDOR_CHAN_FLAG2(
241 					QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80);
242 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80;
243 		}
244 		bandwidth = CH_WIDTH_40MHZ;
245 		fallthrough;
246 	case CH_WIDTH_40MHZ:
247 		ch_width40_ch_params.ch_width = bandwidth;
248 		wlan_reg_set_channel_params_for_pwrmode(pdev, freq, 0,
249 							&ch_width40_ch_params,
250 							REG_CURRENT_PWR_MODE);
251 
252 		if (ch_width40_ch_params.sec_ch_offset == LOW_PRIMARY_CH)
253 			sec_freq = freq + 20;
254 		else if (ch_width40_ch_params.sec_ch_offset == HIGH_PRIMARY_CH)
255 			sec_freq = freq - 20;
256 		else
257 			sec_freq = 0;
258 
259 		if (wlan_reg_get_bonded_channel_state_for_pwrmode(
260 							pdev, freq,
261 							bandwidth, sec_freq,
262 							REG_CURRENT_PWR_MODE) !=
263 		    CHANNEL_STATE_INVALID) {
264 			if (ch_width40_ch_params.sec_ch_offset ==
265 			    LOW_PRIMARY_CH) {
266 				if (is_he_enabled)
267 				  flags |=
268 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40PLUS;
269 				flags |=
270 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40PLUS;
271 				flags |=
272 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS;
273 			} else if (ch_width40_ch_params.sec_ch_offset ==
274 				   HIGH_PRIMARY_CH) {
275 				if (is_he_enabled)
276 				  flags |=
277 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40MINUS;
278 				flags |=
279 				   QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40MINUS;
280 				flags |=
281 				    QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS;
282 			}
283 		}
284 		bandwidth = CH_WIDTH_20MHZ;
285 		fallthrough;
286 	case CH_WIDTH_20MHZ:
287 		flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT20;
288 		flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT20;
289 		if (is_he_enabled)
290 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE20;
291 		bandwidth = CH_WIDTH_10MHZ;
292 		fallthrough;
293 	case CH_WIDTH_10MHZ:
294 		if (wlan_reg_get_bonded_channel_state_for_pwrmode(
295 							pdev, freq,
296 							bandwidth, 0,
297 							REG_CURRENT_PWR_MODE) !=
298 		     CHANNEL_STATE_INVALID &&
299 		     sub_20_channel_width == WLAN_SUB_20_CH_WIDTH_10)
300 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HALF;
301 		bandwidth = CH_WIDTH_5MHZ;
302 		fallthrough;
303 	case CH_WIDTH_5MHZ:
304 		if (wlan_reg_get_bonded_channel_state_for_pwrmode(
305 							pdev, freq,
306 							bandwidth, 0,
307 							REG_CURRENT_PWR_MODE) !=
308 		    CHANNEL_STATE_INVALID &&
309 		    sub_20_channel_width == WLAN_SUB_20_CH_WIDTH_5)
310 			flags |= QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_QUARTER;
311 		break;
312 	default:
313 		son_info("invalid channel width value %d", bandwidth);
314 	}
315 
316 	return flags;
317 }
318 
wlan_son_peer_set_kickout_allow(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,bool kickout_allow)319 QDF_STATUS wlan_son_peer_set_kickout_allow(struct wlan_objmgr_vdev *vdev,
320 					   struct wlan_objmgr_peer *peer,
321 					   bool kickout_allow)
322 {
323 	struct peer_mlme_priv_obj *peer_priv;
324 
325 	if (!peer) {
326 		son_err("invalid peer");
327 		return QDF_STATUS_E_INVAL;
328 	}
329 	if (!vdev) {
330 		son_err("invalid vdev");
331 		return QDF_STATUS_E_INVAL;
332 	}
333 
334 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
335 							  WLAN_UMAC_COMP_MLME);
336 	if (!peer_priv) {
337 		son_err("invalid vdev");
338 		return QDF_STATUS_E_INVAL;
339 	}
340 
341 	peer_priv->allow_kickout = kickout_allow;
342 
343 	return QDF_STATUS_SUCCESS;
344 }
345 
wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev * vdev,uint8_t * macaddr)346 bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev,
347 				    uint8_t *macaddr)
348 {
349 	bool kickout_allow = true;
350 	struct wlan_objmgr_peer *peer;
351 	struct wlan_objmgr_psoc *psoc;
352 	struct peer_mlme_priv_obj *peer_priv;
353 
354 	if (!vdev) {
355 		son_err("invalid vdev");
356 		return kickout_allow;
357 	}
358 	psoc = wlan_vdev_get_psoc(vdev);
359 	if (!psoc) {
360 		son_err("invalid psoc");
361 		return kickout_allow;
362 	}
363 	peer = wlan_objmgr_get_peer_by_mac(psoc, macaddr,
364 					   WLAN_SON_ID);
365 
366 	if (!peer) {
367 		son_err("peer is null");
368 		return kickout_allow;
369 	}
370 
371 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
372 							  WLAN_UMAC_COMP_MLME);
373 	if (!peer_priv) {
374 		son_err("invalid vdev");
375 		wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
376 		return kickout_allow;
377 	}
378 	kickout_allow = peer_priv->allow_kickout;
379 	wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
380 
381 	return kickout_allow;
382 }
383 
wlan_son_ind_assoc_req_frm(struct wlan_objmgr_vdev * vdev,uint8_t * macaddr,bool is_reassoc,uint8_t * frame,uint16_t frame_len,QDF_STATUS status)384 void wlan_son_ind_assoc_req_frm(struct wlan_objmgr_vdev *vdev,
385 				uint8_t *macaddr, bool is_reassoc,
386 				uint8_t *frame, uint16_t frame_len,
387 				QDF_STATUS status)
388 {
389 	struct wlan_objmgr_peer *peer;
390 	struct wlan_lmac_if_rx_ops *rx_ops;
391 	struct wlan_objmgr_psoc *psoc;
392 	uint16_t assocstatus = STATUS_UNSPECIFIED_FAILURE;
393 	uint16_t sub_type = IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
394 
395 	if (!vdev) {
396 		son_err("invalid vdev");
397 		return;
398 	}
399 	psoc = wlan_vdev_get_psoc(vdev);
400 	if (!psoc) {
401 		son_err("invalid psoc");
402 		return;
403 	}
404 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
405 	if (!rx_ops || !rx_ops->son_rx_ops.process_mgmt_frame) {
406 		son_err("invalid rx ops");
407 		return;
408 	}
409 	peer = wlan_objmgr_get_peer_by_mac(psoc, macaddr,
410 					   WLAN_SON_ID);
411 	if (!peer) {
412 		son_err("peer is null");
413 		return;
414 	}
415 
416 	if (is_reassoc)
417 		sub_type = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
418 	if (QDF_IS_STATUS_SUCCESS(status))
419 		assocstatus = STATUS_SUCCESS;
420 	son_debug("subtype %u frame_len %u assocstatus %u",
421 		  sub_type, frame_len, assocstatus);
422 	rx_ops->son_rx_ops.process_mgmt_frame(vdev, peer, sub_type,
423 					      frame, frame_len,
424 					      &assocstatus);
425 	wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
426 }
427 
wlan_son_deliver_mlme_event(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,uint32_t event,void * event_data)428 static int wlan_son_deliver_mlme_event(struct wlan_objmgr_vdev *vdev,
429 				       struct wlan_objmgr_peer *peer,
430 				       uint32_t event,
431 				       void *event_data)
432 {
433 	struct wlan_objmgr_psoc *psoc;
434 	struct wlan_lmac_if_rx_ops *rx_ops;
435 	int ret;
436 
437 	if (!vdev)
438 		return -EINVAL;
439 
440 	psoc = wlan_vdev_get_psoc(vdev);
441 	if (!psoc)
442 		return -EINVAL;
443 
444 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
445 	if (rx_ops && rx_ops->son_rx_ops.deliver_event) {
446 		son_debug("deliver mlme event %d", event);
447 		ret = rx_ops->son_rx_ops.deliver_event(vdev,
448 						       peer,
449 						       event,
450 						       event_data);
451 	} else {
452 		return -EINVAL;
453 	}
454 
455 	return ret;
456 }
457 
wlan_son_deliver_tx_power(struct wlan_objmgr_vdev * vdev,int32_t max_pwr)458 int wlan_son_deliver_tx_power(struct wlan_objmgr_vdev *vdev,
459 			      int32_t max_pwr)
460 {
461 	int ret;
462 
463 	son_debug("tx power %d", max_pwr);
464 	ret = wlan_son_deliver_mlme_event(vdev,
465 					  NULL,
466 					  MLME_EVENT_TX_PWR_CHANGE,
467 					  &max_pwr);
468 
469 	return ret;
470 }
471 
wlan_son_deliver_vdev_stop(struct wlan_objmgr_vdev * vdev)472 int wlan_son_deliver_vdev_stop(struct wlan_objmgr_vdev *vdev)
473 {
474 	int ret;
475 
476 	struct wlan_vdev_state_event event;
477 
478 	event.state = VDEV_STATE_STOPPED;
479 	son_debug("state %d", event.state);
480 	ret = wlan_son_deliver_mlme_event(vdev,
481 					  NULL,
482 					  MLME_EVENT_VDEV_STATE,
483 					  &event);
484 
485 	return ret;
486 }
487 
wlan_son_deliver_inst_rssi(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,uint32_t irssi)488 int wlan_son_deliver_inst_rssi(struct wlan_objmgr_vdev *vdev,
489 			       struct wlan_objmgr_peer *peer,
490 			       uint32_t irssi)
491 {
492 	struct wlan_peer_inst_rssi event;
493 	int ret;
494 
495 	if (irssi > 0 && irssi <= 127) {
496 		event.iRSSI = irssi;
497 		event.valid = true;
498 		son_debug("irssi %d", event.iRSSI);
499 	} else {
500 		event.valid = false;
501 		son_debug("irssi invalid");
502 	}
503 
504 	ret = wlan_son_deliver_mlme_event(vdev,
505 					  peer,
506 					  MLME_EVENT_INST_RSSI,
507 					  &event);
508 
509 	return ret;
510 }
511 
wlan_son_deliver_opmode(struct wlan_objmgr_vdev * vdev,uint8_t bw,uint8_t nss,uint8_t * addr)512 int wlan_son_deliver_opmode(struct wlan_objmgr_vdev *vdev,
513 			    uint8_t bw,
514 			    uint8_t nss,
515 			    uint8_t *addr)
516 {
517 	struct wlan_objmgr_psoc *psoc;
518 	struct ieee80211_opmode_update_data opmode;
519 
520 	if (!vdev)
521 		return -EINVAL;
522 
523 	psoc = wlan_vdev_get_psoc(vdev);
524 	if (!psoc)
525 		return -EINVAL;
526 
527 	opmode.max_chwidth = bw;
528 	opmode.num_streams = nss;
529 	qdf_mem_copy(opmode.macaddr, addr, QDF_MAC_ADDR_SIZE);
530 
531 	son_debug("bw %d, nss %d, addr " QDF_MAC_ADDR_FMT,
532 		  bw, nss, QDF_MAC_ADDR_REF(addr));
533 
534 	if (!g_son_mlme_deliver_cbs.deliver_opmode) {
535 		son_err("invalid deliver opmode cb");
536 		return -EINVAL;
537 	}
538 
539 	g_son_mlme_deliver_cbs.deliver_opmode(vdev,
540 					      sizeof(opmode),
541 					      (uint8_t *)&opmode);
542 
543 	return 0;
544 }
545 
wlan_son_deliver_smps(struct wlan_objmgr_vdev * vdev,uint8_t is_static,uint8_t * addr)546 int wlan_son_deliver_smps(struct wlan_objmgr_vdev *vdev,
547 			  uint8_t is_static,
548 			  uint8_t *addr)
549 {
550 	struct wlan_objmgr_psoc *psoc;
551 	struct ieee80211_smps_update_data smps;
552 
553 	if (!vdev)
554 		return -EINVAL;
555 
556 	psoc = wlan_vdev_get_psoc(vdev);
557 	if (!psoc)
558 		return -EINVAL;
559 
560 	smps.is_static = is_static;
561 	qdf_mem_copy(smps.macaddr, addr, QDF_MAC_ADDR_SIZE);
562 
563 	son_debug("is_static %d, addr" QDF_MAC_ADDR_FMT,
564 		  is_static, QDF_MAC_ADDR_REF(addr));
565 
566 	if (!g_son_mlme_deliver_cbs.deliver_smps) {
567 		son_err("invalid deliver smps cb");
568 		return -EINVAL;
569 	}
570 
571 	g_son_mlme_deliver_cbs.deliver_smps(vdev,
572 					    sizeof(smps),
573 					    (uint8_t *)&smps);
574 
575 	return 0;
576 }
577 
wlan_son_deliver_rrm_rpt(struct wlan_objmgr_vdev * vdev,uint8_t * mac_addr,uint8_t * frm,uint32_t flen)578 int wlan_son_deliver_rrm_rpt(struct wlan_objmgr_vdev *vdev,
579 			     uint8_t *mac_addr,
580 			     uint8_t *frm,
581 			     uint32_t flen)
582 {
583 	struct wlan_act_frm_info rrm_info;
584 	struct wlan_lmac_if_rx_ops *rx_ops;
585 	struct wlan_objmgr_psoc *psoc;
586 	struct wlan_objmgr_peer *peer;
587 	uint8_t sub_type = IEEE80211_FC0_SUBTYPE_ACTION;
588 	struct ieee80211_action ia;
589 	const uint8_t *ie, *pos, *end;
590 	uint8_t total_bcnrpt_count = 0;
591 
592 	if (!vdev) {
593 		son_err("invalid vdev");
594 		return -EINVAL;
595 	}
596 
597 	psoc = wlan_vdev_get_psoc(vdev);
598 	if (!psoc) {
599 		son_err("invalid psoc");
600 		return -EINVAL;
601 	}
602 
603 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
604 	if (!rx_ops || !rx_ops->son_rx_ops.process_mgmt_frame) {
605 		son_err("invalid rx ops");
606 		return -EINVAL;
607 	}
608 
609 	peer = wlan_objmgr_get_peer_by_mac(psoc, mac_addr, WLAN_SON_ID);
610 	if (!peer) {
611 		son_err("peer is null");
612 		return -EINVAL;
613 	}
614 
615 	ia.ia_category = ACTION_CATEGORY_RRM;
616 	ia.ia_action = RRM_RADIO_MEASURE_RPT;
617 	qdf_mem_zero(&rrm_info, sizeof(rrm_info));
618 	rrm_info.ia = &ia;
619 	rrm_info.ald_info = 0;
620 	qdf_mem_copy(rrm_info.data.rrm_data.macaddr,
621 		     mac_addr,
622 		     QDF_MAC_ADDR_SIZE);
623 	/* IEEE80211_ACTION_RM_TOKEN */
624 	rrm_info.data.rrm_data.dialog_token = *frm;
625 
626 	/* Points to Measurement Report Element */
627 	++frm;
628 	--flen;
629 	pos = frm;
630 	end = pos + flen;
631 
632 	while ((ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_MEASREP,
633 					      pos, end - pos))) {
634 		if (ie[1] < 3) {
635 			son_err("Bad Measurement Report element");
636 			wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
637 			return -EINVAL;
638 		}
639 		if (ie[4] == SIR_MAC_RRM_BEACON_TYPE)
640 			++total_bcnrpt_count;
641 		pos = ie + ie[1] + 2;
642 	}
643 
644 	rrm_info.data.rrm_data.num_meas_rpts = total_bcnrpt_count;
645 
646 	son_debug("Sta: " QDF_MAC_ADDR_FMT
647 		  "Category %d Action %d Num_Report %d Rptlen %d",
648 		  QDF_MAC_ADDR_REF(mac_addr),
649 		  ACTION_CATEGORY_RRM,
650 		  RRM_RADIO_MEASURE_RPT,
651 		  total_bcnrpt_count,
652 		  flen);
653 
654 	rx_ops->son_rx_ops.process_mgmt_frame(vdev, peer, sub_type,
655 					      frm, flen, &rrm_info);
656 
657 	wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
658 
659 	return 0;
660 }
661 
wlan_son_anqp_frame(struct wlan_objmgr_vdev * vdev,int subtype,uint8_t * frame,uint16_t frame_len,void * action_hdr,uint8_t * macaddr)662 int wlan_son_anqp_frame(struct wlan_objmgr_vdev *vdev, int subtype,
663 			uint8_t *frame, uint16_t frame_len, void *action_hdr,
664 			uint8_t *macaddr)
665 {
666 	struct son_act_frm_info info;
667 	struct wlan_objmgr_psoc *psoc;
668 	struct wlan_lmac_if_rx_ops *rx_ops;
669 	int ret;
670 
671 	if (!vdev)
672 		return -EINVAL;
673 	psoc = wlan_vdev_get_psoc(vdev);
674 	if (!psoc)
675 		return -EINVAL;
676 
677 	qdf_mem_zero(&info, sizeof(info));
678 	info.ia = (struct ieee80211_action *)action_hdr;
679 	info.ald_info = 1;
680 	qdf_mem_copy(info.data.macaddr, macaddr, sizeof(tSirMacAddr));
681 
682 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
683 	if (rx_ops && rx_ops->son_rx_ops.process_mgmt_frame)
684 		ret = rx_ops->son_rx_ops.process_mgmt_frame(vdev, NULL,
685 							    subtype, frame,
686 							    frame_len, &info);
687 	else
688 		return -EINVAL;
689 	return ret;
690 }
691 
wlan_son_deliver_cbs(struct wlan_objmgr_vdev * vdev,wlan_cbs_event_type type)692 static int wlan_son_deliver_cbs(struct wlan_objmgr_vdev *vdev,
693 				wlan_cbs_event_type type)
694 {
695 	int ret;
696 
697 	ret = wlan_son_deliver_mlme_event(vdev,
698 					  NULL,
699 					  MLME_EVENT_CBS_STATUS,
700 					  &type);
701 
702 	return ret;
703 }
704 
wlan_son_deliver_cbs_completed(struct wlan_objmgr_vdev * vdev)705 static int wlan_son_deliver_cbs_completed(struct wlan_objmgr_vdev *vdev)
706 {
707 	return wlan_son_deliver_cbs(vdev, CBS_COMPLETE);
708 }
709 
wlan_son_deliver_cbs_cancelled(struct wlan_objmgr_vdev * vdev)710 static int wlan_son_deliver_cbs_cancelled(struct wlan_objmgr_vdev *vdev)
711 {
712 	return wlan_son_deliver_cbs(vdev, CBS_CANCELLED);
713 }
714 
715 static void
wlan_son_cbs_set_state(struct son_cbs * cbs,enum son_cbs_state state)716 wlan_son_cbs_set_state(struct son_cbs *cbs, enum son_cbs_state state)
717 {
718 	son_debug("Change State CBS OLD[%d] --> NEW[%d]",
719 		  cbs->cbs_state, state);
720 	cbs->cbs_state = state;
721 }
722 
723 static enum
wlan_son_cbs_get_state(struct son_cbs * cbs)724 son_cbs_state wlan_son_cbs_get_state(struct son_cbs *cbs)
725 {
726 	return cbs->cbs_state;
727 }
728 
729 static void
wlan_son_cbs_init_dwell_params(struct son_cbs * cbs,int dwell_split_time,int dwell_rest_time)730 wlan_son_cbs_init_dwell_params(struct son_cbs *cbs,
731 			       int dwell_split_time,
732 			       int dwell_rest_time)
733 {
734 	int i;
735 
736 	if (!cbs || !cbs->vdev)
737 		return;
738 	son_debug("dwell_split_time %d, dwell_rest_time %d",
739 		  dwell_split_time, dwell_rest_time);
740 	son_debug("vdev_id: %d\n", wlan_vdev_get_id(cbs->vdev));
741 
742 	switch (dwell_split_time) {
743 	case CBS_DWELL_TIME_10MS:
744 		cbs->max_arr_size_used = 10;
745 		cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
746 		cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
747 		for (i = 0; i < cbs->max_arr_size_used; i++)
748 			cbs->scan_dwell_rest[i] = dwell_rest_time;
749 		for (i = 0; i < cbs->max_arr_size_used; i++)
750 			cbs->scan_offset[i] = i * dwell_split_time;
751 		break;
752 	case CBS_DWELL_TIME_25MS:
753 		cbs->max_arr_size_used = 8;
754 		cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
755 		cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
756 		if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
757 			cbs->scan_dwell_rest[0] = dwell_rest_time;
758 			cbs->scan_dwell_rest[1] = dwell_rest_time;
759 			cbs->scan_dwell_rest[2] = dwell_rest_time;
760 			cbs->scan_dwell_rest[3] = dwell_rest_time;
761 			cbs->scan_dwell_rest[4] = dwell_rest_time +
762 							TOTAL_DWELL_TIME -
763 							DEFAULT_BEACON_INTERVAL;
764 			cbs->scan_dwell_rest[5] = dwell_rest_time +
765 							TOTAL_DWELL_TIME -
766 							DEFAULT_BEACON_INTERVAL;
767 			cbs->scan_dwell_rest[6] = dwell_rest_time;
768 			cbs->scan_dwell_rest[7] = dwell_rest_time;
769 			cbs->scan_dwell_rest[8] = 0;
770 			cbs->scan_dwell_rest[9] = 0;
771 			cbs->scan_offset[0] = 0;
772 			cbs->scan_offset[1] = 0;
773 			cbs->scan_offset[2] = dwell_split_time;
774 			cbs->scan_offset[3] = dwell_split_time;
775 			cbs->scan_offset[4] = 2 * dwell_split_time;
776 			cbs->scan_offset[5] = 2 * dwell_split_time;
777 			cbs->scan_offset[6] = 3 * dwell_split_time;
778 			cbs->scan_offset[7] = 3 * dwell_split_time;
779 			cbs->scan_offset[8] = 0;
780 			cbs->scan_offset[9] = 0;
781 		} else {
782 			for (i = 0; i < cbs->max_arr_size_used - 1; i++)
783 				cbs->scan_dwell_rest[i] = dwell_rest_time;
784 
785 			cbs->scan_dwell_rest[8] = 0;
786 			cbs->scan_dwell_rest[9] = 0;
787 			cbs->scan_offset[0] = 0;
788 			cbs->scan_offset[1] = dwell_split_time;
789 			cbs->scan_offset[2] = 2 * dwell_split_time;
790 			cbs->scan_offset[3] = 3 * dwell_split_time;
791 			cbs->scan_offset[4] = 0;
792 			cbs->scan_offset[5] = dwell_split_time;
793 			cbs->scan_offset[6] = 2 * dwell_split_time;
794 			cbs->scan_offset[7] = 3 * dwell_split_time;
795 			cbs->scan_offset[8] = 0;
796 			cbs->scan_offset[9] = 0;
797 		}
798 		break;
799 	case CBS_DWELL_TIME_50MS:
800 		cbs->max_arr_size_used = 4;
801 		cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
802 		cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
803 		if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
804 			cbs->scan_dwell_rest[0] = dwell_rest_time;
805 			cbs->scan_dwell_rest[1] = dwell_rest_time;
806 			cbs->scan_dwell_rest[2] = dwell_rest_time +
807 							TOTAL_DWELL_TIME -
808 							DEFAULT_BEACON_INTERVAL;
809 			cbs->scan_dwell_rest[3] = dwell_rest_time +
810 							TOTAL_DWELL_TIME -
811 							DEFAULT_BEACON_INTERVAL;
812 			cbs->scan_dwell_rest[4] = 0;
813 			cbs->scan_dwell_rest[5] = 0;
814 			cbs->scan_dwell_rest[6] = 0;
815 			cbs->scan_dwell_rest[7] = 0;
816 			cbs->scan_dwell_rest[8] = 0;
817 			cbs->scan_dwell_rest[9] = 0;
818 			cbs->scan_offset[0] = 0;
819 			cbs->scan_offset[1] = 0;
820 			cbs->scan_offset[2] = dwell_split_time;
821 			cbs->scan_offset[3] = dwell_split_time;
822 			cbs->scan_offset[4] = 0;
823 			cbs->scan_offset[5] = 0;
824 			cbs->scan_offset[6] = 0;
825 			cbs->scan_offset[7] = 0;
826 			cbs->scan_offset[8] = 0;
827 			cbs->scan_offset[9] = 0;
828 		} else {
829 			cbs->scan_dwell_rest[0] = dwell_rest_time;
830 			cbs->scan_dwell_rest[1] = dwell_rest_time;
831 			cbs->scan_dwell_rest[2] = dwell_rest_time;
832 			cbs->scan_dwell_rest[3] = dwell_rest_time;
833 			cbs->scan_dwell_rest[4] = 0;
834 			cbs->scan_dwell_rest[5] = 0;
835 			cbs->scan_dwell_rest[6] = 0;
836 			cbs->scan_dwell_rest[7] = 0;
837 			cbs->scan_dwell_rest[8] = 0;
838 			cbs->scan_dwell_rest[9] = 0;
839 			cbs->scan_offset[0] = 0;
840 			cbs->scan_offset[1] = dwell_split_time;
841 			cbs->scan_offset[2] = 0;
842 			cbs->scan_offset[3] = dwell_split_time;
843 			cbs->scan_offset[4] = 0;
844 			cbs->scan_offset[5] = 0;
845 			cbs->scan_offset[6] = 0;
846 			cbs->scan_offset[7] = 0;
847 			cbs->scan_offset[8] = 0;
848 			cbs->scan_offset[9] = 0;
849 		}
850 		break;
851 	case CBS_DWELL_TIME_75MS:
852 		cbs->max_arr_size_used = 4;
853 		cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
854 		cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
855 		if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
856 			cbs->scan_dwell_rest[0] = dwell_rest_time;
857 			cbs->scan_dwell_rest[1] = dwell_rest_time;
858 			cbs->scan_dwell_rest[2] = dwell_rest_time +
859 							TOTAL_DWELL_TIME -
860 							DEFAULT_BEACON_INTERVAL;
861 			cbs->scan_dwell_rest[3] = dwell_rest_time +
862 							TOTAL_DWELL_TIME -
863 							DEFAULT_BEACON_INTERVAL;
864 			cbs->scan_dwell_rest[4] = 0;
865 			cbs->scan_dwell_rest[5] = 0;
866 			cbs->scan_dwell_rest[6] = 0;
867 			cbs->scan_dwell_rest[7] = 0;
868 			cbs->scan_dwell_rest[8] = 0;
869 			cbs->scan_dwell_rest[9] = 0;
870 			cbs->scan_offset[0] = 0;
871 			cbs->scan_offset[1] = 0;
872 			cbs->scan_offset[2] = DEFAULT_BEACON_INTERVAL -
873 							dwell_split_time;
874 			cbs->scan_offset[3] = DEFAULT_BEACON_INTERVAL -
875 							dwell_split_time;
876 			cbs->scan_offset[4] = 0;
877 			cbs->scan_offset[5] = 0;
878 			cbs->scan_offset[6] = 0;
879 			cbs->scan_offset[7] = 0;
880 			cbs->scan_offset[8] = 0;
881 			cbs->scan_offset[9] = 0;
882 		} else {
883 			cbs->scan_dwell_rest[0] = dwell_rest_time;
884 			cbs->scan_dwell_rest[1] = dwell_rest_time;
885 			cbs->scan_dwell_rest[2] = dwell_rest_time;
886 			cbs->scan_dwell_rest[3] = dwell_rest_time;
887 			cbs->scan_dwell_rest[4] = 0;
888 			cbs->scan_dwell_rest[5] = 0;
889 			cbs->scan_dwell_rest[6] = 0;
890 			cbs->scan_dwell_rest[7] = 0;
891 			cbs->scan_dwell_rest[8] = 0;
892 			cbs->scan_dwell_rest[9] = 0;
893 			cbs->scan_offset[0] = 0;
894 			cbs->scan_offset[1] = DEFAULT_BEACON_INTERVAL -
895 							dwell_split_time;
896 			cbs->scan_offset[2] = 0;
897 			cbs->scan_offset[3] = DEFAULT_BEACON_INTERVAL -
898 							dwell_split_time;
899 			cbs->scan_offset[4] = 0;
900 			cbs->scan_offset[5] = 0;
901 			cbs->scan_offset[6] = 0;
902 			cbs->scan_offset[7] = 0;
903 			cbs->scan_offset[8] = 0;
904 			cbs->scan_offset[9] = 0;
905 		}
906 		break;
907 	default:
908 		son_err("Dwell time not supported\n");
909 		break;
910 	}
911 }
912 
wlan_son_cbs_start(struct son_cbs * cbs)913 static int wlan_son_cbs_start(struct son_cbs *cbs)
914 {
915 	struct scan_start_request *req;
916 	struct wlan_objmgr_psoc *psoc;
917 	QDF_STATUS status;
918 
919 	psoc = wlan_vdev_get_psoc(cbs->vdev);
920 	if (!psoc) {
921 		son_err("invalid psoc");
922 		return -EINVAL;
923 	}
924 
925 	req = qdf_mem_malloc(sizeof(*req));
926 	if (!req) {
927 		son_err("failed to malloc");
928 		return -ENOMEM;
929 	}
930 	qdf_mem_copy(req, &cbs->scan_params, sizeof(*req));
931 
932 	cbs->cbs_scan_id = ucfg_scan_get_scan_id(psoc);
933 	req->scan_req.scan_id = cbs->cbs_scan_id;
934 	son_debug("vdev_id: %d req->scan_req.scan_id: %u",
935 		  wlan_vdev_get_id(cbs->vdev), req->scan_req.scan_id);
936 
937 	status = ucfg_scan_start(req);
938 	if (QDF_IS_STATUS_ERROR(status)) {
939 		son_err("failed to start cbs");
940 		wlan_son_deliver_cbs_cancelled(cbs->vdev);
941 		return -EINVAL;
942 	}
943 
944 	son_debug("cbs start");
945 
946 	return 0;
947 }
948 
wlan_son_cbs_stop(struct son_cbs * cbs)949 static int wlan_son_cbs_stop(struct son_cbs *cbs)
950 {
951 	struct wlan_objmgr_pdev *pdev;
952 	QDF_STATUS status;
953 
954 	pdev = wlan_vdev_get_pdev(cbs->vdev);
955 	if (!pdev) {
956 		son_err("invalid pdev");
957 		return -EINVAL;
958 	}
959 	son_debug("vdev_id: %d", wlan_vdev_get_id(cbs->vdev));
960 
961 	if (ucfg_scan_get_pdev_status(pdev) != SCAN_NOT_IN_PROGRESS) {
962 		son_info("cbs_scan_id: %u abort scan", cbs->cbs_scan_id);
963 		status = wlan_abort_scan(pdev,
964 					 wlan_objmgr_pdev_get_pdev_id(pdev),
965 					 cbs->vdev->vdev_objmgr.vdev_id,
966 					 cbs->cbs_scan_id,
967 					 true);
968 		if (QDF_IS_STATUS_ERROR(status)) {
969 			son_err("failed to abort cbs");
970 			return -EBUSY;
971 		}
972 	}
973 
974 	return 0;
975 }
976 
wlan_cbs_timer_handler(void * arg)977 static void wlan_cbs_timer_handler(void *arg)
978 {
979 	struct son_cbs *cbs = (struct son_cbs *)arg;
980 	enum son_cbs_state state;
981 
982 	state = wlan_son_cbs_get_state(cbs);
983 	son_debug("state: %d", state);
984 	if (state == CBS_REST) {
985 		son_debug("vdev_id: %d dwell_split_cnt: %d",
986 			  wlan_vdev_get_id(cbs->vdev),
987 			  cbs->dwell_split_cnt);
988 		qdf_spin_lock_bh(&g_cbs_lock);
989 		wlan_son_cbs_set_state(cbs, CBS_SCAN);
990 		cbs->dwell_split_cnt--;
991 		wlan_son_cbs_start(cbs);
992 		qdf_spin_unlock_bh(&g_cbs_lock);
993 	} else if (state == CBS_WAIT) {
994 		wlan_son_cbs_enable(cbs->vdev);
995 	}
996 }
997 
wlan_cbs_iterate(struct son_cbs * cbs)998 static int wlan_cbs_iterate(struct son_cbs *cbs)
999 {
1000 	int offset_array_idx;
1001 	struct wlan_objmgr_psoc *psoc;
1002 
1003 	qdf_spin_lock_bh(&g_cbs_lock);
1004 	if (!cbs || !cbs->vdev) {
1005 		qdf_spin_unlock_bh(&g_cbs_lock);
1006 		return -EINVAL;
1007 	}
1008 	son_debug("dwell_split_cnt: %d", cbs->dwell_split_cnt);
1009 	if (cbs->dwell_split_cnt < 0) {
1010 		psoc = wlan_vdev_get_psoc(cbs->vdev);
1011 		if (!psoc) {
1012 			qdf_spin_unlock_bh(&g_cbs_lock);
1013 			return -EINVAL;
1014 		}
1015 		wlan_son_deliver_cbs_completed(cbs->vdev);
1016 
1017 		ucfg_scan_unregister_requester(psoc,
1018 					       cbs->cbs_scan_requestor);
1019 		son_debug("Unregister cbs_scan_requestor: %u",
1020 			  cbs->cbs_scan_requestor);
1021 
1022 		if (cbs->wait_time) {
1023 			wlan_son_cbs_set_state(cbs, CBS_WAIT);
1024 			qdf_timer_mod(&cbs->cbs_timer,
1025 				      cbs->wait_time);
1026 		} else {
1027 			wlan_son_cbs_set_state(cbs, CBS_INIT);
1028 		}
1029 	} else {
1030 		offset_array_idx = cbs->max_arr_size_used -
1031 				   cbs->dwell_split_cnt - 1;
1032 		if (offset_array_idx < MIN_SCAN_OFFSET_ARRAY_SIZE ||
1033 		    offset_array_idx > MAX_SCAN_OFFSET_ARRAY_SIZE) {
1034 			qdf_spin_unlock_bh(&g_cbs_lock);
1035 			return -EINVAL;
1036 		}
1037 		if (cbs->scan_dwell_rest[offset_array_idx] == 0) {
1038 			cbs->dwell_split_cnt--;
1039 			wlan_son_cbs_start(cbs);
1040 		} else {
1041 			wlan_son_cbs_set_state(cbs, CBS_REST);
1042 			qdf_timer_mod(&cbs->cbs_timer,
1043 				      cbs->scan_dwell_rest[offset_array_idx]);
1044 		}
1045 	}
1046 	qdf_spin_unlock_bh(&g_cbs_lock);
1047 
1048 	return 0;
1049 }
1050 
wlan_cbs_scan_event_cb(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)1051 static void wlan_cbs_scan_event_cb(struct wlan_objmgr_vdev *vdev,
1052 				   struct scan_event *event,
1053 				   void *arg)
1054 {
1055 	son_debug("event type: %d", event->type);
1056 	switch (event->type) {
1057 	case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
1058 	case SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF:
1059 		break;
1060 	case SCAN_EVENT_TYPE_COMPLETED:
1061 		wlan_cbs_iterate(arg);
1062 		break;
1063 	default:
1064 		break;
1065 	}
1066 }
1067 
wlan_son_cbs_init(void)1068 int wlan_son_cbs_init(void)
1069 {
1070 	int i, j;
1071 
1072 	for (i = 0; i < WLAN_MAX_VDEVS; i++) {
1073 		if (g_son_cbs[i]) {
1074 			qdf_mem_free(g_son_cbs[i]);
1075 			g_son_cbs[i] = NULL;
1076 		}
1077 		g_son_cbs[i] = qdf_mem_malloc(sizeof(*g_son_cbs[i]));
1078 		if (!g_son_cbs[i]) {
1079 			for (j = i - 1; j >= 0; j--) {
1080 				qdf_mem_free(g_son_cbs[j]);
1081 				g_son_cbs[i] = NULL;
1082 			}
1083 			return -ENOMEM;
1084 		}
1085 		qdf_timer_init(NULL,
1086 			       &g_son_cbs[i]->cbs_timer,
1087 			       wlan_cbs_timer_handler,
1088 			       g_son_cbs[i],
1089 			       QDF_TIMER_TYPE_WAKE_APPS);
1090 
1091 		g_son_cbs[i]->rest_time  = CBS_DEFAULT_RESTTIME;
1092 		g_son_cbs[i]->dwell_time = CBS_DEFAULT_DWELL_TIME;
1093 		g_son_cbs[i]->wait_time  = CBS_DEFAULT_WAIT_TIME;
1094 		g_son_cbs[i]->dwell_split_time = CBS_DEFAULT_DWELL_SPLIT_TIME;
1095 		g_son_cbs[i]->min_dwell_rest_time = CBS_DEFAULT_DWELL_REST_TIME;
1096 
1097 		wlan_son_cbs_set_state(g_son_cbs[i], CBS_INIT);
1098 	}
1099 	qdf_spinlock_create(&g_cbs_lock);
1100 	son_debug("cbs init");
1101 
1102 	return 0;
1103 }
1104 
wlan_son_cbs_deinit(void)1105 int wlan_son_cbs_deinit(void)
1106 {
1107 	int i;
1108 
1109 	qdf_spinlock_destroy(&g_cbs_lock);
1110 	for (i = 0; i < WLAN_MAX_VDEVS; i++) {
1111 		if (!g_son_cbs[i])
1112 			return -EINVAL;
1113 		if (g_son_cbs[i]->vdev) {
1114 			wlan_objmgr_vdev_release_ref(g_son_cbs[i]->vdev,
1115 						     WLAN_SON_ID);
1116 			son_debug("vdev_id: %d dereferenced",
1117 				  wlan_vdev_get_id(g_son_cbs[i]->vdev));
1118 		}
1119 		qdf_timer_free(&g_son_cbs[i]->cbs_timer);
1120 		qdf_mem_free(g_son_cbs[i]);
1121 		g_son_cbs[i] = NULL;
1122 	}
1123 
1124 	son_debug("cbs deinit");
1125 
1126 	return 0;
1127 }
1128 
wlan_son_cbs_enable(struct wlan_objmgr_vdev * vdev)1129 int wlan_son_cbs_enable(struct wlan_objmgr_vdev *vdev)
1130 {
1131 	struct scan_start_request *req;
1132 	struct wlan_objmgr_psoc *psoc;
1133 	enum son_cbs_state state;
1134 	struct son_cbs *cbs;
1135 	QDF_STATUS status;
1136 
1137 	cbs = g_son_cbs[wlan_vdev_get_id(vdev)];
1138 	if (!cbs) {
1139 		son_err("invalid cbs");
1140 		return -EINVAL;
1141 	}
1142 	psoc = wlan_vdev_get_psoc(vdev);
1143 	if (!psoc) {
1144 		son_err("invalid psoc");
1145 		return -EINVAL;
1146 	}
1147 
1148 	state = wlan_son_cbs_get_state(cbs);
1149 	if (state != CBS_INIT &&
1150 	    state != CBS_WAIT) {
1151 		son_err("can't start scan in state %d", state);
1152 		return -EINVAL;
1153 	}
1154 	son_debug("State: %d", state);
1155 
1156 	qdf_spin_lock_bh(&g_cbs_lock);
1157 	if (!cbs->vdev) {
1158 		cbs->vdev = vdev;
1159 		status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_SON_ID);
1160 		if (status != QDF_STATUS_SUCCESS) {
1161 			qdf_spin_unlock_bh(&g_cbs_lock);
1162 			son_err("Failed to get VDEV reference");
1163 			return -EAGAIN;
1164 		}
1165 		son_debug("vdev_id: %d referenced",
1166 			  wlan_vdev_get_id(vdev));
1167 	}
1168 	cbs->cbs_scan_requestor =
1169 		ucfg_scan_register_requester(psoc,
1170 					     (uint8_t *)"cbs",
1171 					     wlan_cbs_scan_event_cb,
1172 					     (void *)cbs);
1173 	son_debug("cbs_scan_requestor: %u vdev_id: %d",
1174 		  cbs->cbs_scan_requestor, wlan_vdev_get_id(vdev));
1175 
1176 	if (!cbs->cbs_scan_requestor) {
1177 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SON_ID);
1178 		qdf_spin_unlock_bh(&g_cbs_lock);
1179 		son_err("ucfg_scan_register_requestor failed");
1180 		return -EINVAL;
1181 	}
1182 
1183 	req = &cbs->scan_params;
1184 	ucfg_scan_init_default_params(vdev, req);
1185 	req->scan_req.scan_req_id = cbs->cbs_scan_requestor;
1186 
1187 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
1188 	req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
1189 	req->scan_req.scan_f_bcast_probe = true;
1190 
1191 	req->scan_req.scan_f_passive = true;
1192 	req->scan_req.max_rest_time = DEFAULT_SCAN_MAX_REST_TIME;
1193 	req->scan_req.scan_f_forced = true;
1194 
1195 	req->scan_req.scan_flags = 0;
1196 	req->scan_req.dwell_time_active = cbs->dwell_split_time;
1197 	req->scan_req.dwell_time_passive = cbs->dwell_split_time + 5;
1198 	req->scan_req.min_rest_time = CBS_DEFAULT_MIN_REST_TIME;
1199 	req->scan_req.max_rest_time = CBS_DEFAULT_DWELL_REST_TIME;
1200 	req->scan_req.scan_f_passive = false;
1201 	req->scan_req.scan_f_2ghz = true;
1202 	req->scan_req.scan_f_5ghz = true;
1203 	req->scan_req.scan_f_offchan_mgmt_tx = true;
1204 	req->scan_req.scan_f_offchan_data_tx = true;
1205 	req->scan_req.scan_f_chan_stat_evnt = true;
1206 
1207 	if (cbs->min_dwell_rest_time % DEFAULT_BEACON_INTERVAL) {
1208 		cbs->min_dwell_rest_time =
1209 			(cbs->min_dwell_rest_time /
1210 			(2 * DEFAULT_BEACON_INTERVAL)) *
1211 			(2 * DEFAULT_BEACON_INTERVAL) +
1212 			(cbs->min_dwell_rest_time % 200 < 100) ? 100 : 200;
1213 	}
1214 
1215 	wlan_son_cbs_init_dwell_params(cbs,
1216 				       cbs->dwell_split_time,
1217 				       cbs->min_dwell_rest_time);
1218 
1219 	cbs->dwell_split_cnt--;
1220 	wlan_son_cbs_set_state(cbs, CBS_SCAN);
1221 
1222 	wlan_son_cbs_start(cbs);
1223 	qdf_spin_unlock_bh(&g_cbs_lock);
1224 
1225 	son_debug("cbs enable");
1226 
1227 	return 0;
1228 }
1229 
wlan_son_cbs_disable(struct wlan_objmgr_vdev * vdev)1230 int wlan_son_cbs_disable(struct wlan_objmgr_vdev *vdev)
1231 {
1232 	struct wlan_objmgr_psoc *psoc;
1233 	struct son_cbs *cbs;
1234 
1235 	if (!vdev) {
1236 		son_err("invalid vdev");
1237 		return -EINVAL;
1238 	}
1239 	psoc = wlan_vdev_get_psoc(vdev);
1240 	if (!psoc) {
1241 		son_err("invalid psoc");
1242 		return -EINVAL;
1243 	}
1244 	cbs = g_son_cbs[wlan_vdev_get_id(vdev)];
1245 	if (!cbs || !cbs->vdev) {
1246 		son_err("vdev null");
1247 		return -EINVAL;
1248 	}
1249 	wlan_son_deliver_cbs_cancelled(vdev);
1250 
1251 	qdf_timer_sync_cancel(&cbs->cbs_timer);
1252 
1253 	wlan_son_cbs_stop(cbs);
1254 
1255 	son_debug("cbs_scan_requestor: %d vdev_id: %d",
1256 		  cbs->cbs_scan_requestor, wlan_vdev_get_id(vdev));
1257 	ucfg_scan_unregister_requester(psoc, cbs->cbs_scan_requestor);
1258 
1259 	qdf_spin_lock_bh(&g_cbs_lock);
1260 	wlan_son_cbs_set_state(cbs, CBS_INIT);
1261 	if (vdev == cbs->vdev) {
1262 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SON_ID);
1263 		son_debug("vdev_id: %d dereferenced",
1264 			  vdev->vdev_objmgr.vdev_id);
1265 	}
1266 	cbs->vdev = NULL;
1267 	qdf_spin_unlock_bh(&g_cbs_lock);
1268 
1269 	son_debug("cbs disable");
1270 
1271 	return 0;
1272 }
1273 
wlan_son_set_cbs(struct wlan_objmgr_vdev * vdev,bool enable)1274 int wlan_son_set_cbs(struct wlan_objmgr_vdev *vdev,
1275 		     bool enable)
1276 {
1277 	son_debug("Enable: %u", enable);
1278 
1279 	if (!vdev || !g_son_cbs[wlan_vdev_get_id(vdev)])
1280 		return -EINVAL;
1281 
1282 	if (enable)
1283 		wlan_son_cbs_enable(vdev);
1284 	else
1285 		wlan_son_cbs_disable(vdev);
1286 
1287 	return 0;
1288 }
1289 
wlan_son_set_cbs_wait_time(struct wlan_objmgr_vdev * vdev,uint32_t val)1290 int wlan_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
1291 			       uint32_t val)
1292 {
1293 	if (!g_son_cbs[wlan_vdev_get_id(vdev)])
1294 		return -EINVAL;
1295 
1296 	son_debug("vdev_id: %d wait time %d", wlan_vdev_get_id(vdev), val);
1297 	wlan_son_set_cbs(vdev, false);
1298 
1299 	if (val % DEFAULT_BEACON_INTERVAL != 0) {
1300 		val = (val / (2 * DEFAULT_BEACON_INTERVAL)) *
1301 			(2 * DEFAULT_BEACON_INTERVAL) +
1302 			(val % (2 * DEFAULT_BEACON_INTERVAL) <
1303 				DEFAULT_BEACON_INTERVAL) ?
1304 				DEFAULT_BEACON_INTERVAL :
1305 				2 * DEFAULT_BEACON_INTERVAL;
1306 	}
1307 	qdf_spin_lock_bh(&g_cbs_lock);
1308 	g_son_cbs[wlan_vdev_get_id(vdev)]->wait_time = val;
1309 	qdf_spin_unlock_bh(&g_cbs_lock);
1310 
1311 	wlan_son_set_cbs(vdev, true);
1312 
1313 	return 0;
1314 }
1315 
wlan_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev * vdev,uint32_t val)1316 int wlan_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
1317 				      uint32_t val)
1318 {
1319 	if (!g_son_cbs[wlan_vdev_get_id(vdev)])
1320 		return -EINVAL;
1321 
1322 	son_debug("vdev_id: %d dwell split time %d",
1323 		  wlan_vdev_get_id(vdev), val);
1324 	if (val != CBS_DWELL_TIME_10MS &&
1325 	    val != CBS_DWELL_TIME_25MS &&
1326 	    val != CBS_DWELL_TIME_50MS &&
1327 	    val != CBS_DWELL_TIME_75MS) {
1328 		son_err("dwell time not supported ");
1329 		return -EINVAL;
1330 	}
1331 
1332 	wlan_son_set_cbs(vdev, false);
1333 
1334 	qdf_spin_lock_bh(&g_cbs_lock);
1335 	g_son_cbs[wlan_vdev_get_id(vdev)]->dwell_split_time = val;
1336 	qdf_spin_unlock_bh(&g_cbs_lock);
1337 
1338 	wlan_son_set_cbs(vdev, true);
1339 
1340 	return 0;
1341 }
1342 
wlan_son_get_node_tx_power(struct element_info assoc_req_ies)1343 uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies)
1344 {
1345 	const uint8_t *power_cap_ie_data;
1346 
1347 	power_cap_ie_data = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_PWRCAP,
1348 						     assoc_req_ies.ptr,
1349 						     assoc_req_ies.len);
1350 	if (power_cap_ie_data)
1351 		return *(power_cap_ie_data + 3);
1352 	else
1353 		return 0;
1354 }
1355 
wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies,uint8_t * rrmcaps,bool * is_beacon_meas_supported)1356 QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies,
1357 				      uint8_t *rrmcaps,
1358 				      bool *is_beacon_meas_supported)
1359 {
1360 	const uint8_t *eid;
1361 
1362 	eid = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RRM,
1363 				       assoc_req_ies.ptr,
1364 				       assoc_req_ies.len);
1365 	if (eid) {
1366 		qdf_mem_copy(rrmcaps, &eid[2], eid[1]);
1367 		if ((rrmcaps[0] &
1368 		    IEEE80211_RRM_CAPS_BEACON_REPORT_PASSIVE) ||
1369 		    (rrmcaps[0] &
1370 		    IEEE80211_RRM_CAPS_BEACON_REPORT_ACTIVE))
1371 			*is_beacon_meas_supported = true;
1372 		return QDF_STATUS_SUCCESS;
1373 	}
1374 	return QDF_STATUS_E_RESOURCES;
1375 }
1376 
1377 QDF_STATUS
wlan_son_vdev_get_supported_txrx_streams(struct wlan_objmgr_vdev * vdev,uint32_t * num_tx_streams,uint32_t * num_rx_streams)1378 wlan_son_vdev_get_supported_txrx_streams(struct wlan_objmgr_vdev *vdev,
1379 					 uint32_t *num_tx_streams,
1380 					 uint32_t *num_rx_streams)
1381 {
1382 	struct wlan_mlme_nss_chains *nss_cfg;
1383 	enum nss_chains_band_info band = NSS_CHAINS_BAND_MAX;
1384 	struct wlan_channel *chan;
1385 	qdf_freq_t chan_freq = 0;
1386 
1387 	nss_cfg = mlme_get_dynamic_vdev_config(vdev);
1388 	if (!nss_cfg)
1389 		return QDF_STATUS_NOT_INITIALIZED;
1390 
1391 	chan = wlan_vdev_get_active_channel(vdev);
1392 	if (chan)
1393 		chan_freq = chan->ch_freq;
1394 
1395 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq))
1396 		band = NSS_CHAINS_BAND_2GHZ;
1397 
1398 	if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq))
1399 		band = NSS_CHAINS_BAND_5GHZ;
1400 
1401 	if (band == NSS_CHAINS_BAND_MAX)
1402 		return QDF_STATUS_NOT_INITIALIZED;
1403 
1404 	*num_tx_streams = nss_cfg->tx_nss[band];
1405 	*num_rx_streams = nss_cfg->rx_nss[band];
1406 
1407 	return QDF_STATUS_SUCCESS;
1408 }
1409