xref: /wlan-driver/qca-wifi-host-cmn/os_if/linux/scan/src/wlan_cfg80211_scan.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: defines driver functions interfacing with linux kernel
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <qdf_list.h>
25*5113495bSYour Name #include <qdf_status.h>
26*5113495bSYour Name #include <qdf_module.h>
27*5113495bSYour Name #include <linux/wireless.h>
28*5113495bSYour Name #include <linux/netdevice.h>
29*5113495bSYour Name #include <net/cfg80211.h>
30*5113495bSYour Name #include <wlan_scan_utils_api.h>
31*5113495bSYour Name #include <wlan_cfg80211.h>
32*5113495bSYour Name #include <wlan_cfg80211_scan.h>
33*5113495bSYour Name #include <wlan_osif_priv.h>
34*5113495bSYour Name #include <wlan_scan_public_structs.h>
35*5113495bSYour Name #include <wlan_scan_ucfg_api.h>
36*5113495bSYour Name #include <wlan_cfg80211_scan.h>
37*5113495bSYour Name #include <qdf_mem.h>
38*5113495bSYour Name #include <wlan_utility.h>
39*5113495bSYour Name #include "cfg_ucfg_api.h"
40*5113495bSYour Name #ifdef WLAN_POLICY_MGR_ENABLE
41*5113495bSYour Name #include <wlan_policy_mgr_api.h>
42*5113495bSYour Name #endif
43*5113495bSYour Name #include <wlan_reg_services_api.h>
44*5113495bSYour Name #ifdef FEATURE_WLAN_DIAG_SUPPORT
45*5113495bSYour Name #include "host_diag_core_event.h"
46*5113495bSYour Name #endif
47*5113495bSYour Name 
48*5113495bSYour Name const struct nla_policy cfg80211_scan_policy[
49*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1] = {
50*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS] = {.type = NLA_U32},
51*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE] = {.type = NLA_FLAG},
52*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE] = {.type = NLA_U64},
53*5113495bSYour Name };
54*5113495bSYour Name 
55*5113495bSYour Name /**
56*5113495bSYour Name  * wlan_cfg80211_is_colocated_6ghz_scan_supported() - Check whether colocated
57*5113495bSYour Name  * 6ghz scan flag present in scan request or not
58*5113495bSYour Name  * @scan_flag: Flags bitmap coming from kernel
59*5113495bSYour Name  *
60*5113495bSYour Name  * Return: True if colocated 6ghz scan flag present in scan req
61*5113495bSYour Name  */
62*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
63*5113495bSYour Name static bool
wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)64*5113495bSYour Name wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)
65*5113495bSYour Name {
66*5113495bSYour Name 	return !!(scan_flag & NL80211_SCAN_FLAG_COLOCATED_6GHZ);
67*5113495bSYour Name }
68*5113495bSYour Name #else
69*5113495bSYour Name static inline bool
wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)70*5113495bSYour Name wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)
71*5113495bSYour Name {
72*5113495bSYour Name 	return false;
73*5113495bSYour Name }
74*5113495bSYour Name #endif
75*5113495bSYour Name 
76*5113495bSYour Name #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
77*5113495bSYour Name 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
78*5113495bSYour Name /**
79*5113495bSYour Name  * wlan_fill_scan_rand_attrs() - Populate the scan randomization attrs
80*5113495bSYour Name  * @vdev: pointer to objmgr vdev
81*5113495bSYour Name  * @flags: cfg80211 scan flags
82*5113495bSYour Name  * @mac_addr: random mac addr from cfg80211
83*5113495bSYour Name  * @mac_addr_mask: mac addr mask from cfg80211
84*5113495bSYour Name  * @randomize: output variable to check scan randomization status
85*5113495bSYour Name  * @addr: output variable to hold random addr
86*5113495bSYour Name  * @mask: output variable to hold mac mask
87*5113495bSYour Name  *
88*5113495bSYour Name  * Return: None
89*5113495bSYour Name  */
wlan_fill_scan_rand_attrs(struct wlan_objmgr_vdev * vdev,uint32_t flags,uint8_t * mac_addr,uint8_t * mac_addr_mask,bool * randomize,uint8_t * addr,uint8_t * mask)90*5113495bSYour Name static void wlan_fill_scan_rand_attrs(struct wlan_objmgr_vdev *vdev,
91*5113495bSYour Name 				      uint32_t flags,
92*5113495bSYour Name 				      uint8_t *mac_addr,
93*5113495bSYour Name 				      uint8_t *mac_addr_mask,
94*5113495bSYour Name 				      bool *randomize,
95*5113495bSYour Name 				      uint8_t *addr,
96*5113495bSYour Name 				      uint8_t *mask)
97*5113495bSYour Name {
98*5113495bSYour Name 	*randomize = false;
99*5113495bSYour Name 	if (!(flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
100*5113495bSYour Name 		return;
101*5113495bSYour Name 
102*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
103*5113495bSYour Name 		return;
104*5113495bSYour Name 
105*5113495bSYour Name 	if (wlan_vdev_is_up(vdev) == QDF_STATUS_SUCCESS)
106*5113495bSYour Name 		return;
107*5113495bSYour Name 
108*5113495bSYour Name 	*randomize = true;
109*5113495bSYour Name 	memcpy(addr, mac_addr, QDF_MAC_ADDR_SIZE);
110*5113495bSYour Name 	memcpy(mask, mac_addr_mask, QDF_MAC_ADDR_SIZE);
111*5113495bSYour Name 	osif_debug("Random mac addr: "QDF_MAC_ADDR_FMT" and Random mac mask: "QDF_MAC_ADDR_FMT,
112*5113495bSYour Name 		   QDF_MAC_ADDR_REF(addr), QDF_MAC_ADDR_REF(mask));
113*5113495bSYour Name }
114*5113495bSYour Name 
115*5113495bSYour Name /**
116*5113495bSYour Name  * wlan_scan_rand_attrs() - Wrapper function to fill scan random attrs
117*5113495bSYour Name  * @vdev: pointer to objmgr vdev
118*5113495bSYour Name  * @request: pointer to cfg80211 scan request
119*5113495bSYour Name  * @req: pointer to cmn module scan request
120*5113495bSYour Name  *
121*5113495bSYour Name  * This is a wrapper function which invokes wlan_fill_scan_rand_attrs()
122*5113495bSYour Name  * to fill random attributes of internal scan request with cfg80211_scan_request
123*5113495bSYour Name  *
124*5113495bSYour Name  * Return: None
125*5113495bSYour Name  */
wlan_scan_rand_attrs(struct wlan_objmgr_vdev * vdev,struct cfg80211_scan_request * request,struct scan_start_request * req)126*5113495bSYour Name static void wlan_scan_rand_attrs(struct wlan_objmgr_vdev *vdev,
127*5113495bSYour Name 				 struct cfg80211_scan_request *request,
128*5113495bSYour Name 				 struct scan_start_request *req)
129*5113495bSYour Name {
130*5113495bSYour Name 	bool *randomize = &req->scan_req.scan_random.randomize;
131*5113495bSYour Name 	uint8_t *mac_addr = req->scan_req.scan_random.mac_addr;
132*5113495bSYour Name 	uint8_t *mac_mask = req->scan_req.scan_random.mac_mask;
133*5113495bSYour Name 
134*5113495bSYour Name 	wlan_fill_scan_rand_attrs(vdev, request->flags, request->mac_addr,
135*5113495bSYour Name 				  request->mac_addr_mask, randomize, mac_addr,
136*5113495bSYour Name 				  mac_mask);
137*5113495bSYour Name 	if (!*randomize)
138*5113495bSYour Name 		return;
139*5113495bSYour Name 
140*5113495bSYour Name 	req->scan_req.scan_f_add_spoofed_mac_in_probe = true;
141*5113495bSYour Name 	req->scan_req.scan_f_add_rand_seq_in_probe = true;
142*5113495bSYour Name }
143*5113495bSYour Name #else
144*5113495bSYour Name /**
145*5113495bSYour Name  * wlan_scan_rand_attrs() - Wrapper function to fill scan random attrs
146*5113495bSYour Name  * @vdev: pointer to objmgr vdev
147*5113495bSYour Name  * @request: pointer to cfg80211 scan request
148*5113495bSYour Name  * @req: pointer to cmn module scan request
149*5113495bSYour Name  *
150*5113495bSYour Name  * This is a wrapper function which invokes wlan_fill_scan_rand_attrs()
151*5113495bSYour Name  * to fill random attributes of internal scan request with cfg80211_scan_request
152*5113495bSYour Name  *
153*5113495bSYour Name  * Return: None
154*5113495bSYour Name  */
wlan_scan_rand_attrs(struct wlan_objmgr_vdev * vdev,struct cfg80211_scan_request * request,struct scan_start_request * req)155*5113495bSYour Name static void wlan_scan_rand_attrs(struct wlan_objmgr_vdev *vdev,
156*5113495bSYour Name 				 struct cfg80211_scan_request *request,
157*5113495bSYour Name 				 struct scan_start_request *req)
158*5113495bSYour Name {
159*5113495bSYour Name }
160*5113495bSYour Name #endif
161*5113495bSYour Name 
162*5113495bSYour Name #ifdef FEATURE_WLAN_SCAN_PNO
163*5113495bSYour Name #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
164*5113495bSYour Name 	defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT))
165*5113495bSYour Name 
166*5113495bSYour Name /**
167*5113495bSYour Name  * wlan_config_sched_scan_plan() - configures the sched scan plans
168*5113495bSYour Name  *   from the framework.
169*5113495bSYour Name  * @psoc: psoc object
170*5113495bSYour Name  * @pno_req: pointer to PNO scan request
171*5113495bSYour Name  * @request: pointer to scan request from framework
172*5113495bSYour Name  *
173*5113495bSYour Name  * Return: None
174*5113495bSYour Name  */
175*5113495bSYour Name static void
wlan_config_sched_scan_plan(struct wlan_objmgr_psoc * psoc,struct pno_scan_req_params * pno_req,struct cfg80211_sched_scan_request * request)176*5113495bSYour Name wlan_config_sched_scan_plan(struct wlan_objmgr_psoc *psoc,
177*5113495bSYour Name 			    struct pno_scan_req_params *pno_req,
178*5113495bSYour Name 			    struct cfg80211_sched_scan_request *request)
179*5113495bSYour Name {
180*5113495bSYour Name 	if (!ucfg_scan_get_user_config_sched_scan_plan(psoc) ||
181*5113495bSYour Name 	    request->n_scan_plans == 1) {
182*5113495bSYour Name 		pno_req->fast_scan_period =
183*5113495bSYour Name 		request->scan_plans[0].interval * MSEC_PER_SEC;
184*5113495bSYour Name 		/*
185*5113495bSYour Name 		 * if only one scan plan is configured from framework
186*5113495bSYour Name 		 * then both fast and slow scan should be configured with the
187*5113495bSYour Name 		 * same value that is why fast scan cycles are hardcoded to one
188*5113495bSYour Name 		 */
189*5113495bSYour Name 		pno_req->fast_scan_max_cycles = 1;
190*5113495bSYour Name 		pno_req->slow_scan_period =
191*5113495bSYour Name 			request->scan_plans[0].interval * MSEC_PER_SEC;
192*5113495bSYour Name 	}
193*5113495bSYour Name 	/*
194*5113495bSYour Name 	 * As of now max 2 scan plans were supported by firmware
195*5113495bSYour Name 	 * if number of scan plan supported by firmware increased below logic
196*5113495bSYour Name 	 * must change.
197*5113495bSYour Name 	 */
198*5113495bSYour Name 	else if (request->n_scan_plans == SCAN_PNO_MAX_PLAN_REQUEST) {
199*5113495bSYour Name 		pno_req->fast_scan_period =
200*5113495bSYour Name 			request->scan_plans[0].interval * MSEC_PER_SEC;
201*5113495bSYour Name 		pno_req->fast_scan_max_cycles =
202*5113495bSYour Name 			request->scan_plans[0].iterations;
203*5113495bSYour Name 		pno_req->slow_scan_period =
204*5113495bSYour Name 			request->scan_plans[1].interval * MSEC_PER_SEC;
205*5113495bSYour Name 	} else {
206*5113495bSYour Name 		osif_err("Invalid number of scan plans %d !!",
207*5113495bSYour Name 			 request->n_scan_plans);
208*5113495bSYour Name 	}
209*5113495bSYour Name }
210*5113495bSYour Name #else
211*5113495bSYour Name #define wlan_config_sched_scan_plan(psoc, pno_req, request) \
212*5113495bSYour Name 	__wlan_config_sched_scan_plan(pno_req, request, psoc)
213*5113495bSYour Name 
214*5113495bSYour Name static void
__wlan_config_sched_scan_plan(struct pno_scan_req_params * pno_req,struct cfg80211_sched_scan_request * request,struct wlan_objmgr_psoc * psoc)215*5113495bSYour Name __wlan_config_sched_scan_plan(struct pno_scan_req_params *pno_req,
216*5113495bSYour Name 			      struct cfg80211_sched_scan_request *request,
217*5113495bSYour Name 			      struct wlan_objmgr_psoc *psoc)
218*5113495bSYour Name {
219*5113495bSYour Name 	uint32_t scan_timer_repeat_value, slow_scan_multiplier;
220*5113495bSYour Name 
221*5113495bSYour Name 	scan_timer_repeat_value = ucfg_scan_get_scan_timer_repeat_value(psoc);
222*5113495bSYour Name 	slow_scan_multiplier = ucfg_scan_get_slow_scan_multiplier(psoc);
223*5113495bSYour Name 
224*5113495bSYour Name 	pno_req->fast_scan_period = request->interval;
225*5113495bSYour Name 	pno_req->fast_scan_max_cycles = scan_timer_repeat_value;
226*5113495bSYour Name 	pno_req->slow_scan_period =
227*5113495bSYour Name 		(slow_scan_multiplier * pno_req->fast_scan_period);
228*5113495bSYour Name }
229*5113495bSYour Name #endif
230*5113495bSYour Name 
231*5113495bSYour Name #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
232*5113495bSYour Name static inline void
wlan_cfg80211_sched_scan_results(struct wiphy * wiphy,uint64_t reqid)233*5113495bSYour Name wlan_cfg80211_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
234*5113495bSYour Name {
235*5113495bSYour Name 	cfg80211_sched_scan_results(wiphy);
236*5113495bSYour Name }
237*5113495bSYour Name #else
238*5113495bSYour Name static inline void
wlan_cfg80211_sched_scan_results(struct wiphy * wiphy,uint64_t reqid)239*5113495bSYour Name wlan_cfg80211_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
240*5113495bSYour Name {
241*5113495bSYour Name 	cfg80211_sched_scan_results(wiphy, reqid);
242*5113495bSYour Name }
243*5113495bSYour Name #endif
244*5113495bSYour Name 
245*5113495bSYour Name /**
246*5113495bSYour Name  * wlan_cfg80211_pno_callback() - pno callback function to handle
247*5113495bSYour Name  * pno events.
248*5113495bSYour Name  * @vdev: vdev ptr
249*5113495bSYour Name  * @event: scan events
250*5113495bSYour Name  * @args: argument
251*5113495bSYour Name  *
252*5113495bSYour Name  * Return: void
253*5113495bSYour Name  */
wlan_cfg80211_pno_callback(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * args)254*5113495bSYour Name static void wlan_cfg80211_pno_callback(struct wlan_objmgr_vdev *vdev,
255*5113495bSYour Name 	struct scan_event *event,
256*5113495bSYour Name 	void *args)
257*5113495bSYour Name {
258*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
259*5113495bSYour Name 	struct pdev_osif_priv *pdev_ospriv;
260*5113495bSYour Name 
261*5113495bSYour Name 	if (event->type != SCAN_EVENT_TYPE_NLO_COMPLETE)
262*5113495bSYour Name 		return;
263*5113495bSYour Name 
264*5113495bSYour Name 	osif_debug("vdev id = %d", event->vdev_id);
265*5113495bSYour Name 
266*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
267*5113495bSYour Name 	if (!pdev) {
268*5113495bSYour Name 		osif_err("pdev is NULL");
269*5113495bSYour Name 		return;
270*5113495bSYour Name 	}
271*5113495bSYour Name 
272*5113495bSYour Name 	pdev_ospriv = wlan_pdev_get_ospriv(pdev);
273*5113495bSYour Name 	if (!pdev_ospriv) {
274*5113495bSYour Name 		osif_err("pdev_ospriv is NULL");
275*5113495bSYour Name 		return;
276*5113495bSYour Name 	}
277*5113495bSYour Name 	wlan_cfg80211_sched_scan_results(pdev_ospriv->wiphy, 0);
278*5113495bSYour Name }
279*5113495bSYour Name 
280*5113495bSYour Name #ifdef WLAN_POLICY_MGR_ENABLE
wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc * psoc)281*5113495bSYour Name static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc)
282*5113495bSYour Name {
283*5113495bSYour Name 	return policy_mgr_get_beaconing_mode_count(psoc, NULL);
284*5113495bSYour Name }
285*5113495bSYour Name 
wlan_cfg80211_is_chan_ok_for_dnbs(struct wlan_objmgr_psoc * psoc,u16 chan_freq,bool * ok)286*5113495bSYour Name static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs(
287*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
288*5113495bSYour Name 			u16 chan_freq, bool *ok)
289*5113495bSYour Name {
290*5113495bSYour Name 	QDF_STATUS status = policy_mgr_is_chan_ok_for_dnbs(
291*5113495bSYour Name 				psoc, chan_freq, ok);
292*5113495bSYour Name 
293*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
294*5113495bSYour Name 		osif_err("DNBS check failed");
295*5113495bSYour Name 		return status;
296*5113495bSYour Name 	}
297*5113495bSYour Name 
298*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
299*5113495bSYour Name }
300*5113495bSYour Name #else
wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc * psoc)301*5113495bSYour Name static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc)
302*5113495bSYour Name {
303*5113495bSYour Name 	return false;
304*5113495bSYour Name }
305*5113495bSYour Name 
wlan_cfg80211_is_chan_ok_for_dnbs(struct wlan_objmgr_psoc * psoc,u16 chan_freq,bool * ok)306*5113495bSYour Name static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs(
307*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
308*5113495bSYour Name 			u16 chan_freq,
309*5113495bSYour Name 			bool *ok)
310*5113495bSYour Name {
311*5113495bSYour Name 	if (!ok)
312*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
313*5113495bSYour Name 
314*5113495bSYour Name 	*ok = true;
315*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
316*5113495bSYour Name }
317*5113495bSYour Name #endif
318*5113495bSYour Name 
319*5113495bSYour Name #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
320*5113495bSYour Name 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
321*5113495bSYour Name /**
322*5113495bSYour Name  * wlan_pno_scan_rand_attr() - Wrapper function to fill sched scan random attrs
323*5113495bSYour Name  * @vdev: pointer to objmgr vdev
324*5113495bSYour Name  * @request: pointer to cfg80211 sched scan request
325*5113495bSYour Name  * @req: pointer to cmn module pno scan request
326*5113495bSYour Name  *
327*5113495bSYour Name  * This is a wrapper function which invokes wlan_fill_scan_rand_attrs()
328*5113495bSYour Name  * to fill random attributes of internal pno scan
329*5113495bSYour Name  * with cfg80211_sched_scan_request
330*5113495bSYour Name  *
331*5113495bSYour Name  * Return: None
332*5113495bSYour Name  */
wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev * vdev,struct cfg80211_sched_scan_request * request,struct pno_scan_req_params * req)333*5113495bSYour Name static void wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev *vdev,
334*5113495bSYour Name 				    struct cfg80211_sched_scan_request *request,
335*5113495bSYour Name 				    struct pno_scan_req_params *req)
336*5113495bSYour Name {
337*5113495bSYour Name 	bool *randomize = &req->scan_random.randomize;
338*5113495bSYour Name 	uint8_t *mac_addr = req->scan_random.mac_addr;
339*5113495bSYour Name 	uint8_t *mac_mask = req->scan_random.mac_mask;
340*5113495bSYour Name 
341*5113495bSYour Name 	wlan_fill_scan_rand_attrs(vdev, request->flags, request->mac_addr,
342*5113495bSYour Name 				  request->mac_addr_mask, randomize, mac_addr,
343*5113495bSYour Name 				  mac_mask);
344*5113495bSYour Name }
345*5113495bSYour Name #else
346*5113495bSYour Name /**
347*5113495bSYour Name  * wlan_pno_scan_rand_attr() - Wrapper function to fill sched scan random attrs
348*5113495bSYour Name  * @vdev: pointer to objmgr vdev
349*5113495bSYour Name  * @request: pointer to cfg80211 sched scan request
350*5113495bSYour Name  * @req: pointer to cmn module pno scan request
351*5113495bSYour Name  *
352*5113495bSYour Name  * This is a wrapper function which invokes wlan_fill_scan_rand_attrs()
353*5113495bSYour Name  * to fill random attributes of internal pno scan
354*5113495bSYour Name  * with cfg80211_sched_scan_request
355*5113495bSYour Name  *
356*5113495bSYour Name  * Return: None
357*5113495bSYour Name  */
wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev * vdev,struct cfg80211_sched_scan_request * request,struct pno_scan_req_params * req)358*5113495bSYour Name static void wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev *vdev,
359*5113495bSYour Name 				    struct cfg80211_sched_scan_request *request,
360*5113495bSYour Name 				    struct pno_scan_req_params *req)
361*5113495bSYour Name {
362*5113495bSYour Name }
363*5113495bSYour Name #endif
364*5113495bSYour Name 
365*5113495bSYour Name /**
366*5113495bSYour Name  * wlan_hdd_sched_scan_update_relative_rssi() - update CPNO params
367*5113495bSYour Name  * @pno_request: pointer to PNO scan request
368*5113495bSYour Name  * @request: Pointer to cfg80211 scheduled scan start request
369*5113495bSYour Name  *
370*5113495bSYour Name  * This function is used to update Connected PNO params sent by kernel
371*5113495bSYour Name  *
372*5113495bSYour Name  * Return: None
373*5113495bSYour Name  */
374*5113495bSYour Name #if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN) || \
375*5113495bSYour Name 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
wlan_hdd_sched_scan_update_relative_rssi(struct pno_scan_req_params * pno_request,struct cfg80211_sched_scan_request * request)376*5113495bSYour Name static inline void wlan_hdd_sched_scan_update_relative_rssi(
377*5113495bSYour Name 			struct pno_scan_req_params *pno_request,
378*5113495bSYour Name 			struct cfg80211_sched_scan_request *request)
379*5113495bSYour Name {
380*5113495bSYour Name 	pno_request->relative_rssi_set = request->relative_rssi_set;
381*5113495bSYour Name 	pno_request->relative_rssi = request->relative_rssi;
382*5113495bSYour Name 	if (NL80211_BAND_2GHZ == request->rssi_adjust.band)
383*5113495bSYour Name 		pno_request->band_rssi_pref.band = WLAN_BAND_2_4_GHZ;
384*5113495bSYour Name 	else if (NL80211_BAND_5GHZ == request->rssi_adjust.band)
385*5113495bSYour Name 		pno_request->band_rssi_pref.band = WLAN_BAND_5_GHZ;
386*5113495bSYour Name 	pno_request->band_rssi_pref.rssi = request->rssi_adjust.delta;
387*5113495bSYour Name }
388*5113495bSYour Name #else
wlan_hdd_sched_scan_update_relative_rssi(struct pno_scan_req_params * pno_request,struct cfg80211_sched_scan_request * request)389*5113495bSYour Name static inline void wlan_hdd_sched_scan_update_relative_rssi(
390*5113495bSYour Name 			struct pno_scan_req_params *pno_request,
391*5113495bSYour Name 			struct cfg80211_sched_scan_request *request)
392*5113495bSYour Name {
393*5113495bSYour Name }
394*5113495bSYour Name #endif
395*5113495bSYour Name 
396*5113495bSYour Name #ifdef FEATURE_WLAN_SCAN_PNO
397*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
wlan_config_sched_scan_start_delay(struct cfg80211_sched_scan_request * request)398*5113495bSYour Name static uint32_t wlan_config_sched_scan_start_delay(
399*5113495bSYour Name 		struct cfg80211_sched_scan_request *request)
400*5113495bSYour Name {
401*5113495bSYour Name 	return request->delay;
402*5113495bSYour Name }
403*5113495bSYour Name #else
wlan_config_sched_scan_start_delay(struct cfg80211_sched_scan_request * request)404*5113495bSYour Name static uint32_t wlan_config_sched_scan_start_delay(
405*5113495bSYour Name 		struct cfg80211_sched_scan_request *request)
406*5113495bSYour Name {
407*5113495bSYour Name 	return 0;
408*5113495bSYour Name }
409*5113495bSYour Name #endif /*(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) */
410*5113495bSYour Name #endif /* FEATURE_WLAN_SCAN_PNO */
411*5113495bSYour Name 
wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev * vdev,struct cfg80211_sched_scan_request * request,uint8_t scan_backoff_multiplier)412*5113495bSYour Name int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev,
413*5113495bSYour Name 				   struct cfg80211_sched_scan_request *request,
414*5113495bSYour Name 				   uint8_t scan_backoff_multiplier)
415*5113495bSYour Name {
416*5113495bSYour Name 	struct pno_scan_req_params *req;
417*5113495bSYour Name 	int i, j, ret = 0;
418*5113495bSYour Name 	QDF_STATUS status;
419*5113495bSYour Name 	uint8_t num_chan = 0;
420*5113495bSYour Name 	uint8_t updated_num_chan = 0;
421*5113495bSYour Name 	uint16_t chan_freq;
422*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
423*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
424*5113495bSYour Name 	uint32_t valid_ch[SCAN_PNO_MAX_NETW_CHANNELS_EX] = {0};
425*5113495bSYour Name 	bool enable_dfs_pno_chnl_scan;
426*5113495bSYour Name 
427*5113495bSYour Name 	if (ucfg_scan_get_pno_in_progress(vdev)) {
428*5113495bSYour Name 		osif_debug("pno is already in progress");
429*5113495bSYour Name 		return -EBUSY;
430*5113495bSYour Name 	}
431*5113495bSYour Name 
432*5113495bSYour Name 	if (ucfg_scan_get_pdev_status(pdev) !=
433*5113495bSYour Name 	   SCAN_NOT_IN_PROGRESS) {
434*5113495bSYour Name 		status = wlan_abort_scan(pdev,
435*5113495bSYour Name 				wlan_objmgr_pdev_get_pdev_id(pdev),
436*5113495bSYour Name 				INVAL_VDEV_ID, INVAL_SCAN_ID, true);
437*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
438*5113495bSYour Name 			return -EBUSY;
439*5113495bSYour Name 	}
440*5113495bSYour Name 
441*5113495bSYour Name 	req = qdf_mem_malloc(sizeof(*req));
442*5113495bSYour Name 	if (!req)
443*5113495bSYour Name 		return -ENOMEM;
444*5113495bSYour Name 
445*5113495bSYour Name 	wlan_pdev_obj_lock(pdev);
446*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
447*5113495bSYour Name 	wlan_pdev_obj_unlock(pdev);
448*5113495bSYour Name 
449*5113495bSYour Name 	req->networks_cnt = request->n_match_sets;
450*5113495bSYour Name 	req->vdev_id = wlan_vdev_get_id(vdev);
451*5113495bSYour Name 	req->vdev = vdev;
452*5113495bSYour Name 	req->scan_policy_colocated_6ghz =
453*5113495bSYour Name 		wlan_cfg80211_is_colocated_6ghz_scan_supported(request->flags);
454*5113495bSYour Name 
455*5113495bSYour Name 	if ((!req->networks_cnt) ||
456*5113495bSYour Name 	    (req->networks_cnt > SCAN_PNO_MAX_SUPP_NETWORKS)) {
457*5113495bSYour Name 		osif_err("Network input is not correct %d",
458*5113495bSYour Name 			 req->networks_cnt);
459*5113495bSYour Name 		ret = -EINVAL;
460*5113495bSYour Name 		goto error;
461*5113495bSYour Name 	}
462*5113495bSYour Name 
463*5113495bSYour Name 	if (request->n_channels > SCAN_PNO_MAX_NETW_CHANNELS_EX) {
464*5113495bSYour Name 		osif_err("Incorrect number of channels %d",
465*5113495bSYour Name 			 request->n_channels);
466*5113495bSYour Name 		ret = -EINVAL;
467*5113495bSYour Name 		goto error;
468*5113495bSYour Name 	}
469*5113495bSYour Name 
470*5113495bSYour Name 	enable_dfs_pno_chnl_scan = ucfg_scan_is_dfs_chnl_scan_enabled(psoc);
471*5113495bSYour Name 	if (request->n_channels) {
472*5113495bSYour Name 		uint32_t buff_len;
473*5113495bSYour Name 		char *chl;
474*5113495bSYour Name 		int len = 0;
475*5113495bSYour Name 		bool ap_or_go_present = wlan_cfg80211_is_ap_go_present(psoc);
476*5113495bSYour Name 
477*5113495bSYour Name 		buff_len = (request->n_channels * 5) + 1;
478*5113495bSYour Name 		chl = qdf_mem_malloc(buff_len);
479*5113495bSYour Name 		if (!chl) {
480*5113495bSYour Name 			ret = -ENOMEM;
481*5113495bSYour Name 			goto error;
482*5113495bSYour Name 		}
483*5113495bSYour Name 		for (i = 0; i < request->n_channels; i++) {
484*5113495bSYour Name 			chan_freq = request->channels[i]->center_freq;
485*5113495bSYour Name 			if ((!enable_dfs_pno_chnl_scan) &&
486*5113495bSYour Name 			    (wlan_reg_is_dfs_for_freq(pdev, chan_freq))) {
487*5113495bSYour Name 				osif_debug("Dropping DFS channel freq :%d",
488*5113495bSYour Name 					   chan_freq);
489*5113495bSYour Name 				continue;
490*5113495bSYour Name 			}
491*5113495bSYour Name 			if (wlan_reg_is_dsrc_freq(chan_freq))
492*5113495bSYour Name 				continue;
493*5113495bSYour Name 
494*5113495bSYour Name 			if (ap_or_go_present) {
495*5113495bSYour Name 				bool ok;
496*5113495bSYour Name 
497*5113495bSYour Name 				status =
498*5113495bSYour Name 				wlan_cfg80211_is_chan_ok_for_dnbs(psoc,
499*5113495bSYour Name 								  chan_freq,
500*5113495bSYour Name 								  &ok);
501*5113495bSYour Name 				if (QDF_IS_STATUS_ERROR(status)) {
502*5113495bSYour Name 					osif_err("DNBS check failed");
503*5113495bSYour Name 					qdf_mem_free(chl);
504*5113495bSYour Name 					chl = NULL;
505*5113495bSYour Name 					ret = -EINVAL;
506*5113495bSYour Name 					goto error;
507*5113495bSYour Name 				}
508*5113495bSYour Name 				if (!ok)
509*5113495bSYour Name 					continue;
510*5113495bSYour Name 			}
511*5113495bSYour Name 			len += qdf_scnprintf(chl + len, buff_len - len, " %d", chan_freq);
512*5113495bSYour Name 			valid_ch[num_chan++] = chan_freq;
513*5113495bSYour Name 		}
514*5113495bSYour Name 		osif_debug("Channel-List[%d]:%s", num_chan, chl);
515*5113495bSYour Name 		qdf_mem_free(chl);
516*5113495bSYour Name 		chl = NULL;
517*5113495bSYour Name 		/* If all channels are DFS and dropped,
518*5113495bSYour Name 		 * then ignore the PNO request
519*5113495bSYour Name 		 */
520*5113495bSYour Name 		if (!num_chan) {
521*5113495bSYour Name 			osif_notice("Channel list empty due to filtering of DSRC");
522*5113495bSYour Name 			ret = -EINVAL;
523*5113495bSYour Name 			goto error;
524*5113495bSYour Name 		}
525*5113495bSYour Name 	}
526*5113495bSYour Name 
527*5113495bSYour Name 	/* Filling per profile  params */
528*5113495bSYour Name 	for (i = 0; i < req->networks_cnt; i++) {
529*5113495bSYour Name 		struct cfg80211_match_set *user_req = &request->match_sets[i];
530*5113495bSYour Name 		struct pno_nw_type *tgt_req = &req->networks_list[i];
531*5113495bSYour Name 
532*5113495bSYour Name 		tgt_req->ssid.length = user_req->ssid.ssid_len;
533*5113495bSYour Name 
534*5113495bSYour Name 		if (!tgt_req->ssid.length ||
535*5113495bSYour Name 		    tgt_req->ssid.length > WLAN_SSID_MAX_LEN) {
536*5113495bSYour Name 			osif_err(" SSID Len %d is not correct for network %d",
537*5113495bSYour Name 				 tgt_req->ssid.length, i);
538*5113495bSYour Name 			ret = -EINVAL;
539*5113495bSYour Name 			goto error;
540*5113495bSYour Name 		}
541*5113495bSYour Name 
542*5113495bSYour Name 		qdf_mem_copy(tgt_req->ssid.ssid, user_req->ssid.ssid,
543*5113495bSYour Name 			     tgt_req->ssid.length);
544*5113495bSYour Name 		tgt_req->authentication = 0;   /*eAUTH_TYPE_ANY */
545*5113495bSYour Name 		tgt_req->encryption = 0;       /*eED_ANY */
546*5113495bSYour Name 		tgt_req->bc_new_type = 0;    /*eBCAST_UNKNOWN */
547*5113495bSYour Name 
548*5113495bSYour Name 
549*5113495bSYour Name 		/*Copying list of valid channel into request */
550*5113495bSYour Name 		for (j = 0; j < num_chan; j++)
551*5113495bSYour Name 			tgt_req->pno_chan_list.chan[j].freq = valid_ch[j];
552*5113495bSYour Name 		tgt_req->pno_chan_list.num_chan = num_chan;
553*5113495bSYour Name 
554*5113495bSYour Name 		if (ucfg_is_6ghz_pno_scan_optimization_supported(psoc)) {
555*5113495bSYour Name 			uint32_t short_ssid =
556*5113495bSYour Name 				wlan_construct_shortssid(tgt_req->ssid.ssid,
557*5113495bSYour Name 							 tgt_req->ssid.length);
558*5113495bSYour Name 			updated_num_chan = num_chan;
559*5113495bSYour Name 			ucfg_scan_add_flags_to_pno_chan_list(vdev, req,
560*5113495bSYour Name 							     &updated_num_chan,
561*5113495bSYour Name 							     short_ssid, i);
562*5113495bSYour Name 		}
563*5113495bSYour Name 
564*5113495bSYour Name 		tgt_req->rssi_thresh = user_req->rssi_thold;
565*5113495bSYour Name 	}
566*5113495bSYour Name 
567*5113495bSYour Name 	/* set scan to passive if no SSIDs are specified in the request */
568*5113495bSYour Name 	if (0 == request->n_ssids)
569*5113495bSYour Name 		req->do_passive_scan = true;
570*5113495bSYour Name 	else
571*5113495bSYour Name 		req->do_passive_scan = false;
572*5113495bSYour Name 
573*5113495bSYour Name 	for (i = 0; i < request->n_ssids; i++) {
574*5113495bSYour Name 		j = 0;
575*5113495bSYour Name 		while (j < req->networks_cnt) {
576*5113495bSYour Name 			if ((req->networks_list[j].ssid.length ==
577*5113495bSYour Name 			     request->ssids[i].ssid_len) &&
578*5113495bSYour Name 			    (!qdf_mem_cmp(req->networks_list[j].ssid.ssid,
579*5113495bSYour Name 					 request->ssids[i].ssid,
580*5113495bSYour Name 					 req->networks_list[j].ssid.length))) {
581*5113495bSYour Name 				req->networks_list[j].bc_new_type =
582*5113495bSYour Name 					SSID_BC_TYPE_HIDDEN;
583*5113495bSYour Name 				break;
584*5113495bSYour Name 			}
585*5113495bSYour Name 			j++;
586*5113495bSYour Name 		}
587*5113495bSYour Name 	}
588*5113495bSYour Name 
589*5113495bSYour Name 	/*
590*5113495bSYour Name 	 * Before Kernel 4.4
591*5113495bSYour Name 	 *   Driver gets only one time interval which is hard coded in
592*5113495bSYour Name 	 *   supplicant for 10000ms.
593*5113495bSYour Name 	 *
594*5113495bSYour Name 	 * After Kernel 4.4
595*5113495bSYour Name 	 *   User can configure multiple scan_plans, each scan would have
596*5113495bSYour Name 	 *   separate scan cycle and interval. (interval is in unit of second.)
597*5113495bSYour Name 	 *   For our use case, we would only have supplicant set one scan_plan,
598*5113495bSYour Name 	 *   and firmware also support only one as well, so pick up the first
599*5113495bSYour Name 	 *   index.
600*5113495bSYour Name 	 *
601*5113495bSYour Name 	 *   Taking power consumption into account
602*5113495bSYour Name 	 *   firmware after gPNOScanTimerRepeatValue times fast_scan_period
603*5113495bSYour Name 	 *   switches slow_scan_period. This is less frequent scans and firmware
604*5113495bSYour Name 	 *   shall be in slow_scan_period mode until next PNO Start.
605*5113495bSYour Name 	 */
606*5113495bSYour Name 	wlan_config_sched_scan_plan(psoc, req, request);
607*5113495bSYour Name 	req->delay_start_time = wlan_config_sched_scan_start_delay(request);
608*5113495bSYour Name 	req->scan_backoff_multiplier = scan_backoff_multiplier;
609*5113495bSYour Name 
610*5113495bSYour Name 	wlan_hdd_sched_scan_update_relative_rssi(req, request);
611*5113495bSYour Name 
612*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
613*5113495bSYour Name 	ucfg_scan_register_pno_cb(psoc,
614*5113495bSYour Name 		wlan_cfg80211_pno_callback, NULL);
615*5113495bSYour Name 	ucfg_scan_get_pno_def_params(vdev, req);
616*5113495bSYour Name 
617*5113495bSYour Name 	if (req->scan_random.randomize)
618*5113495bSYour Name 		wlan_pno_scan_rand_attr(vdev, request, req);
619*5113495bSYour Name 
620*5113495bSYour Name 	if (ucfg_ie_allowlist_enabled(psoc, vdev))
621*5113495bSYour Name 		ucfg_copy_ie_allowlist_attrs(psoc, &req->ie_allowlist);
622*5113495bSYour Name 
623*5113495bSYour Name 	osif_debug("Network count %d n_ssids %d fast_scan_period: %d msec slow_scan_period: %d msec, fast_scan_max_cycles: %d, relative_rssi %d band_pref %d, rssi_pref %d",
624*5113495bSYour Name 		   req->networks_cnt, request->n_ssids, req->fast_scan_period,
625*5113495bSYour Name 		   req->slow_scan_period, req->fast_scan_max_cycles,
626*5113495bSYour Name 		   req->relative_rssi, req->band_rssi_pref.band,
627*5113495bSYour Name 		   req->band_rssi_pref.rssi);
628*5113495bSYour Name 
629*5113495bSYour Name 	for (i = 0; i < req->networks_cnt; i++)
630*5113495bSYour Name 		osif_debug("[%d] ssid: " QDF_SSID_FMT ", RSSI th %d bc NW type %u",
631*5113495bSYour Name 			   i,
632*5113495bSYour Name 			   QDF_SSID_REF(req->networks_list[i].ssid.length,
633*5113495bSYour Name 					req->networks_list[i].ssid.ssid),
634*5113495bSYour Name 			   req->networks_list[i].rssi_thresh,
635*5113495bSYour Name 			   req->networks_list[i].bc_new_type);
636*5113495bSYour Name 
637*5113495bSYour Name 	status = ucfg_scan_pno_start(vdev, req);
638*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
639*5113495bSYour Name 		osif_err("Failed to enable PNO");
640*5113495bSYour Name 		ret = -EINVAL;
641*5113495bSYour Name 		goto error;
642*5113495bSYour Name 	}
643*5113495bSYour Name 
644*5113495bSYour Name error:
645*5113495bSYour Name 	qdf_mem_free(req);
646*5113495bSYour Name 	return ret;
647*5113495bSYour Name }
648*5113495bSYour Name 
wlan_cfg80211_sched_scan_stop(struct wlan_objmgr_vdev * vdev)649*5113495bSYour Name int wlan_cfg80211_sched_scan_stop(struct wlan_objmgr_vdev *vdev)
650*5113495bSYour Name {
651*5113495bSYour Name 	QDF_STATUS status;
652*5113495bSYour Name 
653*5113495bSYour Name 	status = ucfg_scan_pno_stop(vdev);
654*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
655*5113495bSYour Name 		osif_debug("Failed to disable PNO");
656*5113495bSYour Name 
657*5113495bSYour Name 	return 0;
658*5113495bSYour Name }
659*5113495bSYour Name #endif /*FEATURE_WLAN_SCAN_PNO */
660*5113495bSYour Name 
661*5113495bSYour Name /**
662*5113495bSYour Name  * wlan_copy_bssid_scan_request() - API to copy the bssid to Scan request
663*5113495bSYour Name  * @scan_req: Pointer to scan_start_request
664*5113495bSYour Name  * @request: scan request from Supplicant
665*5113495bSYour Name  *
666*5113495bSYour Name  * This API copies the BSSID in scan request from Supplicant and copies it to
667*5113495bSYour Name  * the scan_start_request
668*5113495bSYour Name  *
669*5113495bSYour Name  * Return: None
670*5113495bSYour Name  */
671*5113495bSYour Name #if defined(CFG80211_SCAN_BSSID) || \
672*5113495bSYour Name 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
673*5113495bSYour Name static inline void
wlan_copy_bssid_scan_request(struct scan_start_request * scan_req,struct cfg80211_scan_request * request)674*5113495bSYour Name wlan_copy_bssid_scan_request(struct scan_start_request *scan_req,
675*5113495bSYour Name 		struct cfg80211_scan_request *request)
676*5113495bSYour Name {
677*5113495bSYour Name 	qdf_mem_copy(scan_req->scan_req.bssid_list[0].bytes,
678*5113495bSYour Name 				request->bssid, QDF_MAC_ADDR_SIZE);
679*5113495bSYour Name }
680*5113495bSYour Name #else
681*5113495bSYour Name static inline void
wlan_copy_bssid_scan_request(struct scan_start_request * scan_req,struct cfg80211_scan_request * request)682*5113495bSYour Name wlan_copy_bssid_scan_request(struct scan_start_request *scan_req,
683*5113495bSYour Name 		struct cfg80211_scan_request *request)
684*5113495bSYour Name {
685*5113495bSYour Name 
686*5113495bSYour Name }
687*5113495bSYour Name #endif
688*5113495bSYour Name 
689*5113495bSYour Name /**
690*5113495bSYour Name  * wlan_schedule_scan_start_request() - Schedule scan start request
691*5113495bSYour Name  * @pdev: pointer to pdev object
692*5113495bSYour Name  * @req: Pointer to the scan request
693*5113495bSYour Name  * @source: source of the scan request
694*5113495bSYour Name  * @scan_start_req: pointer to scan start request
695*5113495bSYour Name  *
696*5113495bSYour Name  * Schedule scan start request and enqueue scan request in the global scan
697*5113495bSYour Name  * list. This list stores the active scan request information.
698*5113495bSYour Name  *
699*5113495bSYour Name  * Return: QDF_STATUS
700*5113495bSYour Name  */
701*5113495bSYour Name static QDF_STATUS
wlan_schedule_scan_start_request(struct wlan_objmgr_pdev * pdev,struct cfg80211_scan_request * req,uint8_t source,struct scan_start_request * scan_start_req)702*5113495bSYour Name wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev,
703*5113495bSYour Name 				 struct cfg80211_scan_request *req,
704*5113495bSYour Name 				 uint8_t source,
705*5113495bSYour Name 				 struct scan_start_request *scan_start_req)
706*5113495bSYour Name {
707*5113495bSYour Name 	struct scan_req *scan_req;
708*5113495bSYour Name 	QDF_STATUS status;
709*5113495bSYour Name 	struct pdev_osif_priv *osif_ctx;
710*5113495bSYour Name 	struct osif_scan_pdev *osif_scan;
711*5113495bSYour Name 
712*5113495bSYour Name 	scan_req = qdf_mem_malloc(sizeof(*scan_req));
713*5113495bSYour Name 	if (!scan_req) {
714*5113495bSYour Name 		ucfg_scm_scan_free_scan_request_mem(scan_start_req);
715*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
716*5113495bSYour Name 	}
717*5113495bSYour Name 
718*5113495bSYour Name 	/* Get NL global context from objmgr*/
719*5113495bSYour Name 	osif_ctx = wlan_pdev_get_ospriv(pdev);
720*5113495bSYour Name 	osif_scan = osif_ctx->osif_scan;
721*5113495bSYour Name 	scan_req->scan_request = req;
722*5113495bSYour Name 	scan_req->source = source;
723*5113495bSYour Name 	scan_req->scan_id = scan_start_req->scan_req.scan_id;
724*5113495bSYour Name 	scan_req->dev = req->wdev->netdev;
725*5113495bSYour Name 	scan_req->scan_start_timestamp = qdf_get_time_of_the_day_ms();
726*5113495bSYour Name 
727*5113495bSYour Name 	qdf_mutex_acquire(&osif_scan->scan_req_q_lock);
728*5113495bSYour Name 	if (qdf_list_size(&osif_scan->scan_req_q) < WLAN_MAX_SCAN_COUNT) {
729*5113495bSYour Name 		status = ucfg_scan_start(scan_start_req);
730*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status)) {
731*5113495bSYour Name 			qdf_list_insert_back(&osif_scan->scan_req_q,
732*5113495bSYour Name 					     &scan_req->node);
733*5113495bSYour Name 		} else {
734*5113495bSYour Name 			osif_err("scan req failed with error %d", status);
735*5113495bSYour Name 			if (status == QDF_STATUS_E_RESOURCES)
736*5113495bSYour Name 				osif_err("HO is in progress.So defer the scan by informing busy");
737*5113495bSYour Name 		}
738*5113495bSYour Name 	} else {
739*5113495bSYour Name 		ucfg_scm_scan_free_scan_request_mem(scan_start_req);
740*5113495bSYour Name 		status = QDF_STATUS_E_RESOURCES;
741*5113495bSYour Name 	}
742*5113495bSYour Name 
743*5113495bSYour Name 	qdf_mutex_release(&osif_scan->scan_req_q_lock);
744*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
745*5113495bSYour Name 		osif_rl_debug("Failed to enqueue Scan Req as max scan %d already queued",
746*5113495bSYour Name 			      qdf_list_size(&osif_scan->scan_req_q));
747*5113495bSYour Name 		qdf_mem_free(scan_req);
748*5113495bSYour Name 	}
749*5113495bSYour Name 
750*5113495bSYour Name 	return status;
751*5113495bSYour Name }
752*5113495bSYour Name 
753*5113495bSYour Name /**
754*5113495bSYour Name  * wlan_scan_request_dequeue() - dequeue scan request
755*5113495bSYour Name  * @pdev: pdev object
756*5113495bSYour Name  * @scan_id: scan id
757*5113495bSYour Name  * @req: scan request
758*5113495bSYour Name  * @source : returns source of the scan request
759*5113495bSYour Name  * @dev: returns source net device
760*5113495bSYour Name  * @scan_start_timestamp: returns scan start timestamp
761*5113495bSYour Name  *
762*5113495bSYour Name  * Return: QDF_STATUS
763*5113495bSYour Name  */
wlan_scan_request_dequeue(struct wlan_objmgr_pdev * pdev,uint32_t scan_id,struct cfg80211_scan_request ** req,uint8_t * source,struct net_device ** dev,qdf_time_t * scan_start_timestamp)764*5113495bSYour Name static QDF_STATUS wlan_scan_request_dequeue(
765*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
766*5113495bSYour Name 	uint32_t scan_id, struct cfg80211_scan_request **req,
767*5113495bSYour Name 	uint8_t *source, struct net_device **dev,
768*5113495bSYour Name 	qdf_time_t *scan_start_timestamp)
769*5113495bSYour Name {
770*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
771*5113495bSYour Name 	struct scan_req *scan_req;
772*5113495bSYour Name 	qdf_list_node_t *node = NULL, *next_node = NULL;
773*5113495bSYour Name 	struct pdev_osif_priv *osif_ctx;
774*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
775*5113495bSYour Name 
776*5113495bSYour Name 	if ((!source) || (!req)) {
777*5113495bSYour Name 		osif_err("source or request is NULL");
778*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
779*5113495bSYour Name 	}
780*5113495bSYour Name 
781*5113495bSYour Name 	/* Get NL global context from objmgr*/
782*5113495bSYour Name 	osif_ctx = wlan_pdev_get_ospriv(pdev);
783*5113495bSYour Name 	if (!osif_ctx) {
784*5113495bSYour Name 		osif_err("Failed to retrieve osif context");
785*5113495bSYour Name 		return status;
786*5113495bSYour Name 	}
787*5113495bSYour Name 	scan_priv = osif_ctx->osif_scan;
788*5113495bSYour Name 
789*5113495bSYour Name 	qdf_mutex_acquire(&scan_priv->scan_req_q_lock);
790*5113495bSYour Name 	if (qdf_list_empty(&scan_priv->scan_req_q)) {
791*5113495bSYour Name 		osif_info("Scan List is empty");
792*5113495bSYour Name 		qdf_mutex_release(&scan_priv->scan_req_q_lock);
793*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
794*5113495bSYour Name 	}
795*5113495bSYour Name 
796*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
797*5113495bSYour Name 		qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) {
798*5113495bSYour Name 		qdf_mutex_release(&scan_priv->scan_req_q_lock);
799*5113495bSYour Name 		osif_err("Failed to remove Scan Req from queue");
800*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
801*5113495bSYour Name 	}
802*5113495bSYour Name 
803*5113495bSYour Name 	do {
804*5113495bSYour Name 		node = next_node;
805*5113495bSYour Name 		scan_req = qdf_container_of(node, struct scan_req, node);
806*5113495bSYour Name 		if (scan_req->scan_id == scan_id) {
807*5113495bSYour Name 			status = qdf_list_remove_node(&scan_priv->scan_req_q,
808*5113495bSYour Name 						      node);
809*5113495bSYour Name 			if (status == QDF_STATUS_SUCCESS) {
810*5113495bSYour Name 				*req = scan_req->scan_request;
811*5113495bSYour Name 				*source = scan_req->source;
812*5113495bSYour Name 				*dev = scan_req->dev;
813*5113495bSYour Name 				*scan_start_timestamp =
814*5113495bSYour Name 					scan_req->scan_start_timestamp;
815*5113495bSYour Name 				qdf_mem_free(scan_req);
816*5113495bSYour Name 				qdf_mutex_release(&scan_priv->scan_req_q_lock);
817*5113495bSYour Name 				osif_debug("removed Scan id: %d, req = %pK, pending scans %d",
818*5113495bSYour Name 					   scan_id, req,
819*5113495bSYour Name 					   qdf_list_size(&scan_priv->scan_req_q));
820*5113495bSYour Name 				return QDF_STATUS_SUCCESS;
821*5113495bSYour Name 			} else {
822*5113495bSYour Name 				qdf_mutex_release(&scan_priv->scan_req_q_lock);
823*5113495bSYour Name 				osif_err("Failed to remove scan id %d, pending scans %d",
824*5113495bSYour Name 					 scan_id,
825*5113495bSYour Name 					 qdf_list_size(&scan_priv->scan_req_q));
826*5113495bSYour Name 				return status;
827*5113495bSYour Name 			}
828*5113495bSYour Name 		}
829*5113495bSYour Name 	} while (QDF_STATUS_SUCCESS ==
830*5113495bSYour Name 		qdf_list_peek_next(&scan_priv->scan_req_q, node, &next_node));
831*5113495bSYour Name 	qdf_mutex_release(&scan_priv->scan_req_q_lock);
832*5113495bSYour Name 	osif_debug("Failed to find scan id %d", scan_id);
833*5113495bSYour Name 
834*5113495bSYour Name 	return status;
835*5113495bSYour Name }
836*5113495bSYour Name 
837*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
838*5113495bSYour Name /**
839*5113495bSYour Name  * wlan_cfg80211_scan_done() - Scan completed callback to cfg80211
840*5113495bSYour Name  * @netdev: Net device
841*5113495bSYour Name  * @req : Scan request
842*5113495bSYour Name  * @aborted : true scan aborted false scan success
843*5113495bSYour Name  * @osif_priv: OS private structure
844*5113495bSYour Name  *
845*5113495bSYour Name  * This function notifies scan done to cfg80211
846*5113495bSYour Name  *
847*5113495bSYour Name  * Return: none
848*5113495bSYour Name  */
wlan_cfg80211_scan_done(struct net_device * netdev,struct cfg80211_scan_request * req,bool aborted,struct pdev_osif_priv * osif_priv)849*5113495bSYour Name void wlan_cfg80211_scan_done(struct net_device *netdev,
850*5113495bSYour Name 			     struct cfg80211_scan_request *req,
851*5113495bSYour Name 			     bool aborted, struct pdev_osif_priv *osif_priv)
852*5113495bSYour Name {
853*5113495bSYour Name 	struct cfg80211_scan_info info = {
854*5113495bSYour Name 		.aborted = aborted
855*5113495bSYour Name 	};
856*5113495bSYour Name 	bool driver_internal_netdev_state;
857*5113495bSYour Name 
858*5113495bSYour Name 	driver_internal_netdev_state = netdev->flags & IFF_UP;
859*5113495bSYour Name 	if (osif_priv->osif_check_netdev_state)
860*5113495bSYour Name 		driver_internal_netdev_state =
861*5113495bSYour Name 			osif_priv->osif_check_netdev_state(netdev);
862*5113495bSYour Name 
863*5113495bSYour Name 	if (driver_internal_netdev_state)
864*5113495bSYour Name 		cfg80211_scan_done(req, &info);
865*5113495bSYour Name 	else
866*5113495bSYour Name 		osif_debug("scan done callback has been dropped :%s",
867*5113495bSYour Name 			   (netdev)->name);
868*5113495bSYour Name }
869*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
870*5113495bSYour Name /**
871*5113495bSYour Name  * wlan_cfg80211_scan_done() - Scan completed callback to cfg80211
872*5113495bSYour Name  * @netdev: Net device
873*5113495bSYour Name  * @req : Scan request
874*5113495bSYour Name  * @aborted : true scan aborted false scan success
875*5113495bSYour Name  * @osif_priv: OS private structure
876*5113495bSYour Name  *
877*5113495bSYour Name  * This function notifies scan done to cfg80211
878*5113495bSYour Name  *
879*5113495bSYour Name  * Return: none
880*5113495bSYour Name  */
wlan_cfg80211_scan_done(struct net_device * netdev,struct cfg80211_scan_request * req,bool aborted,struct pdev_osif_priv * osif_priv)881*5113495bSYour Name void wlan_cfg80211_scan_done(struct net_device *netdev,
882*5113495bSYour Name 			     struct cfg80211_scan_request *req,
883*5113495bSYour Name 			     bool aborted, struct pdev_osif_priv *osif_priv)
884*5113495bSYour Name {
885*5113495bSYour Name 	bool driver_internal_net_state;
886*5113495bSYour Name 
887*5113495bSYour Name 	driver_internal_netdev_state = netdev->flags & IFF_UP;
888*5113495bSYour Name 	if (osif_priv->osif_check_netdev_state)
889*5113495bSYour Name 		driver_internal_net_state =
890*5113495bSYour Name 			osif_priv->osif_check_netdev_state(netdev);
891*5113495bSYour Name 
892*5113495bSYour Name 	if (driver_internal_netdev_state)
893*5113495bSYour Name 		cfg80211_scan_done(req, aborted);
894*5113495bSYour Name 	else
895*5113495bSYour Name 		osif_debug("scan request has been dropped :%s", (netdev)->name);
896*5113495bSYour Name }
897*5113495bSYour Name #endif
898*5113495bSYour Name 
899*5113495bSYour Name /**
900*5113495bSYour Name  * wlan_vendor_scan_callback() - Scan completed callback event
901*5113495bSYour Name  *
902*5113495bSYour Name  * @req : Scan request
903*5113495bSYour Name  * @aborted : true scan aborted false scan success
904*5113495bSYour Name  *
905*5113495bSYour Name  * This function sends scan completed callback event to NL.
906*5113495bSYour Name  *
907*5113495bSYour Name  * Return: none
908*5113495bSYour Name  */
wlan_vendor_scan_callback(struct cfg80211_scan_request * req,bool aborted)909*5113495bSYour Name static void wlan_vendor_scan_callback(struct cfg80211_scan_request *req,
910*5113495bSYour Name 					bool aborted)
911*5113495bSYour Name {
912*5113495bSYour Name 	struct sk_buff *skb;
913*5113495bSYour Name 	struct nlattr *attr;
914*5113495bSYour Name 	int i;
915*5113495bSYour Name 	uint8_t scan_status;
916*5113495bSYour Name 	uint64_t cookie;
917*5113495bSYour Name 	int index = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX;
918*5113495bSYour Name 
919*5113495bSYour Name 	skb = wlan_cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev,
920*5113495bSYour Name 					       SCAN_DONE_EVENT_BUF_SIZE + 4 +
921*5113495bSYour Name 					       NLMSG_HDRLEN,
922*5113495bSYour Name 					       index,
923*5113495bSYour Name 					       GFP_ATOMIC);
924*5113495bSYour Name 
925*5113495bSYour Name 	if (!skb) {
926*5113495bSYour Name 		osif_err("skb alloc failed");
927*5113495bSYour Name 		qdf_mem_free(req);
928*5113495bSYour Name 		return;
929*5113495bSYour Name 	}
930*5113495bSYour Name 
931*5113495bSYour Name 	cookie = (uintptr_t)req;
932*5113495bSYour Name 
933*5113495bSYour Name 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS);
934*5113495bSYour Name 	if (!attr)
935*5113495bSYour Name 		goto nla_put_failure;
936*5113495bSYour Name 	for (i = 0; i < req->n_ssids; i++) {
937*5113495bSYour Name 		if (nla_put(skb, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
938*5113495bSYour Name 			goto nla_put_failure;
939*5113495bSYour Name 	}
940*5113495bSYour Name 	nla_nest_end(skb, attr);
941*5113495bSYour Name 
942*5113495bSYour Name 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES);
943*5113495bSYour Name 	if (!attr)
944*5113495bSYour Name 		goto nla_put_failure;
945*5113495bSYour Name 	for (i = 0; i < req->n_channels; i++) {
946*5113495bSYour Name 		if (nla_put_u32(skb, i, req->channels[i]->center_freq))
947*5113495bSYour Name 			goto nla_put_failure;
948*5113495bSYour Name 	}
949*5113495bSYour Name 	nla_nest_end(skb, attr);
950*5113495bSYour Name 
951*5113495bSYour Name 	if (req->ie &&
952*5113495bSYour Name 		nla_put(skb, QCA_WLAN_VENDOR_ATTR_SCAN_IE, req->ie_len,
953*5113495bSYour Name 			req->ie))
954*5113495bSYour Name 		goto nla_put_failure;
955*5113495bSYour Name 
956*5113495bSYour Name 	if (req->flags &&
957*5113495bSYour Name 		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, req->flags))
958*5113495bSYour Name 		goto nla_put_failure;
959*5113495bSYour Name 
960*5113495bSYour Name 	if (wlan_cfg80211_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
961*5113495bSYour Name 					cookie))
962*5113495bSYour Name 		goto nla_put_failure;
963*5113495bSYour Name 
964*5113495bSYour Name 	scan_status = (aborted == true) ? VENDOR_SCAN_STATUS_ABORTED :
965*5113495bSYour Name 		VENDOR_SCAN_STATUS_NEW_RESULTS;
966*5113495bSYour Name 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status))
967*5113495bSYour Name 		goto nla_put_failure;
968*5113495bSYour Name 
969*5113495bSYour Name 	wlan_cfg80211_vendor_event(skb, GFP_ATOMIC);
970*5113495bSYour Name 	qdf_mem_free(req);
971*5113495bSYour Name 
972*5113495bSYour Name 	return;
973*5113495bSYour Name 
974*5113495bSYour Name nla_put_failure:
975*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
976*5113495bSYour Name 	qdf_mem_free(req);
977*5113495bSYour Name }
978*5113495bSYour Name 
979*5113495bSYour Name /**
980*5113495bSYour Name  * wlan_scan_acquire_wake_lock_timeout() - acquire scan wake lock
981*5113495bSYour Name  * @psoc: psoc ptr
982*5113495bSYour Name  * @scan_wake_lock: Scan wake lock
983*5113495bSYour Name  * @timeout: timeout in ms
984*5113495bSYour Name  *
985*5113495bSYour Name  * Return: void
986*5113495bSYour Name  */
987*5113495bSYour Name static inline
wlan_scan_acquire_wake_lock_timeout(struct wlan_objmgr_psoc * psoc,qdf_wake_lock_t * scan_wake_lock,uint32_t timeout)988*5113495bSYour Name void wlan_scan_acquire_wake_lock_timeout(struct wlan_objmgr_psoc *psoc,
989*5113495bSYour Name 					 qdf_wake_lock_t *scan_wake_lock,
990*5113495bSYour Name 					 uint32_t timeout)
991*5113495bSYour Name {
992*5113495bSYour Name 	if (!psoc || !scan_wake_lock)
993*5113495bSYour Name 		return;
994*5113495bSYour Name 
995*5113495bSYour Name 	if (ucfg_scan_wake_lock_in_user_scan(psoc))
996*5113495bSYour Name 		qdf_wake_lock_timeout_acquire(scan_wake_lock, timeout);
997*5113495bSYour Name }
998*5113495bSYour Name 
999*5113495bSYour Name 
1000*5113495bSYour Name /**
1001*5113495bSYour Name  * wlan_scan_release_wake_lock() - release scan wake lock
1002*5113495bSYour Name  * @psoc: psoc ptr
1003*5113495bSYour Name  * @scan_wake_lock: Scan wake lock
1004*5113495bSYour Name  *
1005*5113495bSYour Name  * Return: void
1006*5113495bSYour Name  */
1007*5113495bSYour Name #ifdef FEATURE_WLAN_DIAG_SUPPORT
1008*5113495bSYour Name static inline
wlan_scan_release_wake_lock(struct wlan_objmgr_psoc * psoc,qdf_wake_lock_t * scan_wake_lock)1009*5113495bSYour Name void wlan_scan_release_wake_lock(struct wlan_objmgr_psoc *psoc,
1010*5113495bSYour Name 				 qdf_wake_lock_t *scan_wake_lock)
1011*5113495bSYour Name {
1012*5113495bSYour Name 	if (!psoc || !scan_wake_lock)
1013*5113495bSYour Name 		return;
1014*5113495bSYour Name 
1015*5113495bSYour Name 	if (ucfg_scan_wake_lock_in_user_scan(psoc))
1016*5113495bSYour Name 		qdf_wake_lock_release(scan_wake_lock,
1017*5113495bSYour Name 				      WIFI_POWER_EVENT_WAKELOCK_SCAN);
1018*5113495bSYour Name }
1019*5113495bSYour Name #else
1020*5113495bSYour Name static inline
wlan_scan_release_wake_lock(struct wlan_objmgr_psoc * psoc,qdf_wake_lock_t * scan_wake_lock)1021*5113495bSYour Name void wlan_scan_release_wake_lock(struct wlan_objmgr_psoc *psoc,
1022*5113495bSYour Name 				 qdf_wake_lock_t *scan_wake_lock)
1023*5113495bSYour Name {
1024*5113495bSYour Name 	if (!psoc || !scan_wake_lock)
1025*5113495bSYour Name 		return;
1026*5113495bSYour Name 
1027*5113495bSYour Name 	if (ucfg_scan_wake_lock_in_user_scan(psoc))
1028*5113495bSYour Name 		qdf_wake_lock_release(scan_wake_lock, 0);
1029*5113495bSYour Name }
1030*5113495bSYour Name #endif
1031*5113495bSYour Name 
1032*5113495bSYour Name static
wlan_scan_get_bss_count_for_scan(struct wlan_objmgr_pdev * pdev,qdf_time_t scan_start_ts)1033*5113495bSYour Name uint32_t wlan_scan_get_bss_count_for_scan(struct wlan_objmgr_pdev *pdev,
1034*5113495bSYour Name 					  qdf_time_t scan_start_ts)
1035*5113495bSYour Name {
1036*5113495bSYour Name 	struct scan_filter *filter;
1037*5113495bSYour Name 	qdf_list_t *list = NULL;
1038*5113495bSYour Name 	uint32_t count = 0;
1039*5113495bSYour Name 
1040*5113495bSYour Name 	if (!scan_start_ts)
1041*5113495bSYour Name 		return count;
1042*5113495bSYour Name 
1043*5113495bSYour Name 	filter = qdf_mem_malloc(sizeof(*filter));
1044*5113495bSYour Name 	if (!filter)
1045*5113495bSYour Name 		return count;
1046*5113495bSYour Name 
1047*5113495bSYour Name 	filter->ignore_auth_enc_type = true;
1048*5113495bSYour Name 	filter->age_threshold = qdf_get_time_of_the_day_ms() - scan_start_ts;
1049*5113495bSYour Name 
1050*5113495bSYour Name 	list = ucfg_scan_get_result(pdev, filter);
1051*5113495bSYour Name 
1052*5113495bSYour Name 	qdf_mem_free(filter);
1053*5113495bSYour Name 
1054*5113495bSYour Name 	if (list) {
1055*5113495bSYour Name 		count = qdf_list_size(list);
1056*5113495bSYour Name 		ucfg_scan_purge_results(list);
1057*5113495bSYour Name 	}
1058*5113495bSYour Name 
1059*5113495bSYour Name 	return count;
1060*5113495bSYour Name }
1061*5113495bSYour Name 
1062*5113495bSYour Name /**
1063*5113495bSYour Name  * wlan_cfg80211_scan_done_callback() - scan done callback function called after
1064*5113495bSYour Name  * scan is finished
1065*5113495bSYour Name  * @vdev: vdev ptr
1066*5113495bSYour Name  * @event: Scan event
1067*5113495bSYour Name  * @args: Scan cb arg
1068*5113495bSYour Name  *
1069*5113495bSYour Name  * Return: void
1070*5113495bSYour Name  */
wlan_cfg80211_scan_done_callback(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * args)1071*5113495bSYour Name static void wlan_cfg80211_scan_done_callback(
1072*5113495bSYour Name 					struct wlan_objmgr_vdev *vdev,
1073*5113495bSYour Name 					struct scan_event *event,
1074*5113495bSYour Name 					void *args)
1075*5113495bSYour Name {
1076*5113495bSYour Name 	struct cfg80211_scan_request *req = NULL;
1077*5113495bSYour Name 	bool success = false;
1078*5113495bSYour Name 	uint32_t scan_id;
1079*5113495bSYour Name 	uint8_t source = NL_SCAN;
1080*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
1081*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1082*5113495bSYour Name 	struct net_device *netdev = NULL;
1083*5113495bSYour Name 	QDF_STATUS status;
1084*5113495bSYour Name 	qdf_time_t scan_start_timestamp = 0;
1085*5113495bSYour Name 	uint32_t unique_bss_count = 0;
1086*5113495bSYour Name 
1087*5113495bSYour Name 	if (!event) {
1088*5113495bSYour Name 		osif_nofl_err("Invalid scan event received");
1089*5113495bSYour Name 		return;
1090*5113495bSYour Name 	}
1091*5113495bSYour Name 
1092*5113495bSYour Name 	scan_id = event->scan_id;
1093*5113495bSYour Name 
1094*5113495bSYour Name 	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_OS_IF, event->type,
1095*5113495bSYour Name 		   event->vdev_id, scan_id);
1096*5113495bSYour Name 
1097*5113495bSYour Name 	if (event->type == SCAN_EVENT_TYPE_STARTED)
1098*5113495bSYour Name 		osif_nofl_info("scan start scan id %d", scan_id);
1099*5113495bSYour Name 
1100*5113495bSYour Name 	if (!util_is_scan_completed(event, &success))
1101*5113495bSYour Name 		return;
1102*5113495bSYour Name 
1103*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
1104*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1105*5113495bSYour Name 	status = wlan_scan_request_dequeue(
1106*5113495bSYour Name 			pdev, scan_id, &req, &source, &netdev,
1107*5113495bSYour Name 			&scan_start_timestamp);
1108*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1109*5113495bSYour Name 		osif_err("Dequeue of scan request failed ID: %d", scan_id);
1110*5113495bSYour Name 		goto allow_suspend;
1111*5113495bSYour Name 	}
1112*5113495bSYour Name 
1113*5113495bSYour Name 	if (!netdev) {
1114*5113495bSYour Name 		osif_err("net dev is NULL,Drop scan event Id: %d", scan_id);
1115*5113495bSYour Name 		/*
1116*5113495bSYour Name 		 * Free scan request in case of VENDOR_SCAN as it is
1117*5113495bSYour Name 		 * allocated in driver.
1118*5113495bSYour Name 		 */
1119*5113495bSYour Name 		if (source == VENDOR_SCAN)
1120*5113495bSYour Name 			qdf_mem_free(req);
1121*5113495bSYour Name 		goto allow_suspend;
1122*5113495bSYour Name 	}
1123*5113495bSYour Name 
1124*5113495bSYour Name 	/* Make sure vdev is active */
1125*5113495bSYour Name 	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_OSIF_ID);
1126*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1127*5113495bSYour Name 		osif_err("Failed to get vdev reference: scan Id: %d", scan_id);
1128*5113495bSYour Name 		/*
1129*5113495bSYour Name 		 * Free scan request in case of VENDOR_SCAN as it is
1130*5113495bSYour Name 		 * allocated in driver.
1131*5113495bSYour Name 		 */
1132*5113495bSYour Name 		if (source == VENDOR_SCAN)
1133*5113495bSYour Name 			qdf_mem_free(req);
1134*5113495bSYour Name 		goto allow_suspend;
1135*5113495bSYour Name 	}
1136*5113495bSYour Name 
1137*5113495bSYour Name 	/*
1138*5113495bSYour Name 	 * Scan can be triggred from NL or vendor scan
1139*5113495bSYour Name 	 * - If scan is triggered from NL then cfg80211 scan done should be
1140*5113495bSYour Name 	 * called to updated scan completion to NL.
1141*5113495bSYour Name 	 * - If scan is triggred through vendor command then
1142*5113495bSYour Name 	 * scan done event will be posted
1143*5113495bSYour Name 	 */
1144*5113495bSYour Name 	if (NL_SCAN == source)
1145*5113495bSYour Name 		wlan_cfg80211_scan_done(netdev, req, !success, osif_priv);
1146*5113495bSYour Name 	else
1147*5113495bSYour Name 		wlan_vendor_scan_callback(req, !success);
1148*5113495bSYour Name 
1149*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
1150*5113495bSYour Name 
1151*5113495bSYour Name 	unique_bss_count = wlan_scan_get_bss_count_for_scan(pdev,
1152*5113495bSYour Name 							  scan_start_timestamp);
1153*5113495bSYour Name 	osif_nofl_info("vdev %d, scan id %d type %s(%d) reason %s(%d) scan found %d bss",
1154*5113495bSYour Name 		       event->vdev_id, scan_id,
1155*5113495bSYour Name 		       util_scan_get_ev_type_name(event->type), event->type,
1156*5113495bSYour Name 		       util_scan_get_ev_reason_name(event->reason),
1157*5113495bSYour Name 		       event->reason, unique_bss_count);
1158*5113495bSYour Name allow_suspend:
1159*5113495bSYour Name 	qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
1160*5113495bSYour Name 	if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
1161*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc;
1162*5113495bSYour Name 
1163*5113495bSYour Name 		qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
1164*5113495bSYour Name 		qdf_runtime_pm_allow_suspend(
1165*5113495bSYour Name 			&osif_priv->osif_scan->runtime_pm_lock);
1166*5113495bSYour Name 
1167*5113495bSYour Name 		psoc = wlan_pdev_get_psoc(pdev);
1168*5113495bSYour Name 		wlan_scan_release_wake_lock(psoc,
1169*5113495bSYour Name 					&osif_priv->osif_scan->scan_wake_lock);
1170*5113495bSYour Name 		/*
1171*5113495bSYour Name 		 * Acquire wakelock to handle the case where APP's tries
1172*5113495bSYour Name 		 * to suspend immediately after the driver gets connect
1173*5113495bSYour Name 		 * request(i.e after scan) from supplicant, this result in
1174*5113495bSYour Name 		 * app's is suspending and not able to process the connect
1175*5113495bSYour Name 		 * request to AP
1176*5113495bSYour Name 		 */
1177*5113495bSYour Name 		wlan_scan_acquire_wake_lock_timeout(psoc,
1178*5113495bSYour Name 					&osif_priv->osif_scan->scan_wake_lock,
1179*5113495bSYour Name 					SCAN_WAKE_LOCK_CONNECT_DURATION);
1180*5113495bSYour Name 	} else {
1181*5113495bSYour Name 		qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
1182*5113495bSYour Name 	}
1183*5113495bSYour Name 
1184*5113495bSYour Name }
1185*5113495bSYour Name 
wlan_scan_runtime_pm_init(struct wlan_objmgr_pdev * pdev)1186*5113495bSYour Name QDF_STATUS wlan_scan_runtime_pm_init(struct wlan_objmgr_pdev *pdev)
1187*5113495bSYour Name {
1188*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1189*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1190*5113495bSYour Name 
1191*5113495bSYour Name 	wlan_pdev_obj_lock(pdev);
1192*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1193*5113495bSYour Name 	wlan_pdev_obj_unlock(pdev);
1194*5113495bSYour Name 
1195*5113495bSYour Name 	scan_priv = osif_priv->osif_scan;
1196*5113495bSYour Name 
1197*5113495bSYour Name 	return qdf_runtime_lock_init(&scan_priv->runtime_pm_lock);
1198*5113495bSYour Name }
1199*5113495bSYour Name 
wlan_scan_runtime_pm_deinit(struct wlan_objmgr_pdev * pdev)1200*5113495bSYour Name void wlan_scan_runtime_pm_deinit(struct wlan_objmgr_pdev *pdev)
1201*5113495bSYour Name {
1202*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1203*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1204*5113495bSYour Name 
1205*5113495bSYour Name 	wlan_pdev_obj_lock(pdev);
1206*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1207*5113495bSYour Name 	wlan_pdev_obj_unlock(pdev);
1208*5113495bSYour Name 
1209*5113495bSYour Name 	scan_priv = osif_priv->osif_scan;
1210*5113495bSYour Name 	qdf_runtime_lock_deinit(&scan_priv->runtime_pm_lock);
1211*5113495bSYour Name }
1212*5113495bSYour Name 
wlan_cfg80211_scan_priv_init(struct wlan_objmgr_pdev * pdev)1213*5113495bSYour Name QDF_STATUS wlan_cfg80211_scan_priv_init(struct wlan_objmgr_pdev *pdev)
1214*5113495bSYour Name {
1215*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1216*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1217*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1218*5113495bSYour Name 	wlan_scan_requester req_id;
1219*5113495bSYour Name 
1220*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
1221*5113495bSYour Name 
1222*5113495bSYour Name 	req_id = ucfg_scan_register_requester(psoc, "CFG",
1223*5113495bSYour Name 		wlan_cfg80211_scan_done_callback, NULL);
1224*5113495bSYour Name 
1225*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1226*5113495bSYour Name 	scan_priv = qdf_mem_malloc(sizeof(*scan_priv));
1227*5113495bSYour Name 	if (!scan_priv)
1228*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1229*5113495bSYour Name 
1230*5113495bSYour Name 	/* Initialize the scan request queue */
1231*5113495bSYour Name 	osif_priv->osif_scan = scan_priv;
1232*5113495bSYour Name 	scan_priv->req_id = req_id;
1233*5113495bSYour Name 	qdf_list_create(&scan_priv->scan_req_q, WLAN_MAX_SCAN_COUNT);
1234*5113495bSYour Name 	qdf_mutex_create(&scan_priv->scan_req_q_lock);
1235*5113495bSYour Name 	qdf_wake_lock_create(&scan_priv->scan_wake_lock, "scan_wake_lock");
1236*5113495bSYour Name 
1237*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1238*5113495bSYour Name }
1239*5113495bSYour Name 
wlan_cfg80211_scan_priv_deinit(struct wlan_objmgr_pdev * pdev)1240*5113495bSYour Name QDF_STATUS wlan_cfg80211_scan_priv_deinit(struct wlan_objmgr_pdev *pdev)
1241*5113495bSYour Name {
1242*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1243*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1244*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1245*5113495bSYour Name 
1246*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
1247*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1248*5113495bSYour Name 
1249*5113495bSYour Name 	wlan_cfg80211_cleanup_scan_queue(pdev, NULL);
1250*5113495bSYour Name 	scan_priv = osif_priv->osif_scan;
1251*5113495bSYour Name 	qdf_wake_lock_destroy(&scan_priv->scan_wake_lock);
1252*5113495bSYour Name 	qdf_mutex_destroy(&scan_priv->scan_req_q_lock);
1253*5113495bSYour Name 	qdf_list_destroy(&scan_priv->scan_req_q);
1254*5113495bSYour Name 	ucfg_scan_unregister_requester(psoc, scan_priv->req_id);
1255*5113495bSYour Name 	osif_priv->osif_scan = NULL;
1256*5113495bSYour Name 	qdf_mem_free(scan_priv);
1257*5113495bSYour Name 
1258*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1259*5113495bSYour Name }
1260*5113495bSYour Name 
1261*5113495bSYour Name /**
1262*5113495bSYour Name  * wlan_cfg80211_enqueue_for_cleanup() - Function to populate scan cleanup queue
1263*5113495bSYour Name  * @scan_cleanup_q: Scan cleanup queue to be populated
1264*5113495bSYour Name  * @scan_priv: Pointer to scan related data used by cfg80211 scan
1265*5113495bSYour Name  * @dev: Netdevice pointer
1266*5113495bSYour Name  *
1267*5113495bSYour Name  * The function synchrounously iterates through the global scan queue to
1268*5113495bSYour Name  * identify entries that have to be cleaned up, copies identified entries
1269*5113495bSYour Name  * to another queue(to send scan complete event to NL later) and removes the
1270*5113495bSYour Name  * entry from the global scan queue.
1271*5113495bSYour Name  *
1272*5113495bSYour Name  * Return: None
1273*5113495bSYour Name  */
1274*5113495bSYour Name static void
wlan_cfg80211_enqueue_for_cleanup(qdf_list_t * scan_cleanup_q,struct osif_scan_pdev * scan_priv,struct net_device * dev)1275*5113495bSYour Name wlan_cfg80211_enqueue_for_cleanup(qdf_list_t *scan_cleanup_q,
1276*5113495bSYour Name 				  struct osif_scan_pdev *scan_priv,
1277*5113495bSYour Name 				  struct net_device *dev)
1278*5113495bSYour Name {
1279*5113495bSYour Name 	struct scan_req *scan_req, *scan_cleanup;
1280*5113495bSYour Name 	qdf_list_node_t *node = NULL, *next_node = NULL;
1281*5113495bSYour Name 
1282*5113495bSYour Name 	qdf_mutex_acquire(&scan_priv->scan_req_q_lock);
1283*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
1284*5113495bSYour Name 		qdf_list_peek_front(&scan_priv->scan_req_q,
1285*5113495bSYour Name 				    &node)) {
1286*5113495bSYour Name 		qdf_mutex_release(&scan_priv->scan_req_q_lock);
1287*5113495bSYour Name 		return;
1288*5113495bSYour Name 	}
1289*5113495bSYour Name 
1290*5113495bSYour Name 	while (node) {
1291*5113495bSYour Name 		/*
1292*5113495bSYour Name 		 * Keep track of the next node, to traverse through the list
1293*5113495bSYour Name 		 * in the event of the current node being deleted.
1294*5113495bSYour Name 		 */
1295*5113495bSYour Name 		qdf_list_peek_next(&scan_priv->scan_req_q,
1296*5113495bSYour Name 				   node, &next_node);
1297*5113495bSYour Name 		scan_req = qdf_container_of(node, struct scan_req, node);
1298*5113495bSYour Name 		if (!dev || (dev == scan_req->dev)) {
1299*5113495bSYour Name 			scan_cleanup = qdf_mem_malloc(sizeof(struct scan_req));
1300*5113495bSYour Name 			if (!scan_cleanup) {
1301*5113495bSYour Name 				qdf_mutex_release(&scan_priv->scan_req_q_lock);
1302*5113495bSYour Name 				return;
1303*5113495bSYour Name 			}
1304*5113495bSYour Name 			scan_cleanup->scan_request = scan_req->scan_request;
1305*5113495bSYour Name 			scan_cleanup->scan_id = scan_req->scan_id;
1306*5113495bSYour Name 			scan_cleanup->source = scan_req->source;
1307*5113495bSYour Name 			scan_cleanup->dev = scan_req->dev;
1308*5113495bSYour Name 			qdf_list_insert_back(scan_cleanup_q,
1309*5113495bSYour Name 					     &scan_cleanup->node);
1310*5113495bSYour Name 			if (QDF_STATUS_SUCCESS !=
1311*5113495bSYour Name 				qdf_list_remove_node(&scan_priv->scan_req_q,
1312*5113495bSYour Name 						     node)) {
1313*5113495bSYour Name 				qdf_mutex_release(&scan_priv->scan_req_q_lock);
1314*5113495bSYour Name 				osif_err("Failed to remove scan request");
1315*5113495bSYour Name 				return;
1316*5113495bSYour Name 			}
1317*5113495bSYour Name 			qdf_mem_free(scan_req);
1318*5113495bSYour Name 		}
1319*5113495bSYour Name 		node = next_node;
1320*5113495bSYour Name 		next_node = NULL;
1321*5113495bSYour Name 	}
1322*5113495bSYour Name 	qdf_mutex_release(&scan_priv->scan_req_q_lock);
1323*5113495bSYour Name }
1324*5113495bSYour Name 
wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev * pdev,struct net_device * dev)1325*5113495bSYour Name void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev,
1326*5113495bSYour Name 				      struct net_device *dev)
1327*5113495bSYour Name {
1328*5113495bSYour Name 	struct scan_req *scan_req;
1329*5113495bSYour Name 	struct cfg80211_scan_request *req;
1330*5113495bSYour Name 	uint8_t source;
1331*5113495bSYour Name 	bool aborted = true;
1332*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1333*5113495bSYour Name 	qdf_list_t scan_cleanup_q;
1334*5113495bSYour Name 	qdf_list_node_t *node = NULL;
1335*5113495bSYour Name 
1336*5113495bSYour Name 	if (!pdev) {
1337*5113495bSYour Name 		osif_err("pdev is Null");
1338*5113495bSYour Name 		return;
1339*5113495bSYour Name 	}
1340*5113495bSYour Name 
1341*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1342*5113495bSYour Name 
1343*5113495bSYour Name 	/*
1344*5113495bSYour Name 	 * To avoid any race conditions, create a local list to copy all the
1345*5113495bSYour Name 	 * scan entries to be removed and then send scan complete for each of
1346*5113495bSYour Name 	 * the identified entries to NL.
1347*5113495bSYour Name 	 */
1348*5113495bSYour Name 	qdf_list_create(&scan_cleanup_q, WLAN_MAX_SCAN_COUNT);
1349*5113495bSYour Name 	wlan_cfg80211_enqueue_for_cleanup(&scan_cleanup_q,
1350*5113495bSYour Name 					  osif_priv->osif_scan, dev);
1351*5113495bSYour Name 
1352*5113495bSYour Name 	while (!qdf_list_empty(&scan_cleanup_q)) {
1353*5113495bSYour Name 		if (QDF_STATUS_SUCCESS != qdf_list_remove_front(&scan_cleanup_q,
1354*5113495bSYour Name 								&node)) {
1355*5113495bSYour Name 			osif_err("Failed to remove scan request");
1356*5113495bSYour Name 			return;
1357*5113495bSYour Name 		}
1358*5113495bSYour Name 		scan_req = container_of(node, struct scan_req, node);
1359*5113495bSYour Name 		req = scan_req->scan_request;
1360*5113495bSYour Name 		source = scan_req->source;
1361*5113495bSYour Name 		if (NL_SCAN == source)
1362*5113495bSYour Name 			wlan_cfg80211_scan_done(scan_req->dev, req,
1363*5113495bSYour Name 						aborted, osif_priv);
1364*5113495bSYour Name 		else
1365*5113495bSYour Name 			wlan_vendor_scan_callback(req, aborted);
1366*5113495bSYour Name 
1367*5113495bSYour Name 		qdf_mem_free(scan_req);
1368*5113495bSYour Name 	}
1369*5113495bSYour Name 	qdf_list_destroy(&scan_cleanup_q);
1370*5113495bSYour Name 
1371*5113495bSYour Name 	return;
1372*5113495bSYour Name }
1373*5113495bSYour Name 
1374*5113495bSYour Name /**
1375*5113495bSYour Name  * wlan_cfg80211_update_scan_policy_type_flags() - Set scan flags according to
1376*5113495bSYour Name  * scan request
1377*5113495bSYour Name  * @req: scan request to populate
1378*5113495bSYour Name  * @scan_req: Pointer to scan request params
1379*5113495bSYour Name  *
1380*5113495bSYour Name  * Return: None
1381*5113495bSYour Name  */
1382*5113495bSYour Name #if defined(CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
1383*5113495bSYour Name 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
wlan_cfg80211_update_scan_policy_type_flags(struct cfg80211_scan_request * req,struct scan_req_params * scan_req)1384*5113495bSYour Name static void wlan_cfg80211_update_scan_policy_type_flags(
1385*5113495bSYour Name 	struct cfg80211_scan_request *req,
1386*5113495bSYour Name 	struct scan_req_params *scan_req)
1387*5113495bSYour Name {
1388*5113495bSYour Name 	if (req->flags & NL80211_SCAN_FLAG_HIGH_ACCURACY)
1389*5113495bSYour Name 		scan_req->scan_policy_high_accuracy = true;
1390*5113495bSYour Name 	if (req->flags & NL80211_SCAN_FLAG_LOW_SPAN)
1391*5113495bSYour Name 		scan_req->scan_policy_low_span = true;
1392*5113495bSYour Name 	if (req->flags & NL80211_SCAN_FLAG_LOW_POWER)
1393*5113495bSYour Name 		scan_req->scan_policy_low_power = true;
1394*5113495bSYour Name 
1395*5113495bSYour Name 	if (wlan_cfg80211_is_colocated_6ghz_scan_supported(req->flags))
1396*5113495bSYour Name 		scan_req->scan_policy_colocated_6ghz = true;
1397*5113495bSYour Name }
1398*5113495bSYour Name #else
wlan_cfg80211_update_scan_policy_type_flags(struct cfg80211_scan_request * req,struct scan_req_params * scan_req)1399*5113495bSYour Name static inline void wlan_cfg80211_update_scan_policy_type_flags(
1400*5113495bSYour Name 		struct cfg80211_scan_request *req,
1401*5113495bSYour Name 		struct scan_req_params *scan_req)
1402*5113495bSYour Name {
1403*5113495bSYour Name }
1404*5113495bSYour Name #endif
1405*5113495bSYour Name 
1406*5113495bSYour Name #ifdef WLAN_POLICY_MGR_ENABLE
1407*5113495bSYour Name static bool
wlan_cfg80211_allow_simultaneous_scan(struct wlan_objmgr_psoc * psoc)1408*5113495bSYour Name wlan_cfg80211_allow_simultaneous_scan(struct wlan_objmgr_psoc *psoc)
1409*5113495bSYour Name {
1410*5113495bSYour Name 	return policy_mgr_is_scan_simultaneous_capable(psoc);
1411*5113495bSYour Name }
1412*5113495bSYour Name #else
1413*5113495bSYour Name static bool
wlan_cfg80211_allow_simultaneous_scan(struct wlan_objmgr_psoc * psoc)1414*5113495bSYour Name wlan_cfg80211_allow_simultaneous_scan(struct wlan_objmgr_psoc *psoc)
1415*5113495bSYour Name {
1416*5113495bSYour Name 	return true;
1417*5113495bSYour Name }
1418*5113495bSYour Name #endif
1419*5113495bSYour Name 
convert_nl_scan_priority_to_internal(enum qca_wlan_vendor_scan_priority nl_scan_priority)1420*5113495bSYour Name enum scan_priority convert_nl_scan_priority_to_internal(
1421*5113495bSYour Name 	enum qca_wlan_vendor_scan_priority nl_scan_priority)
1422*5113495bSYour Name {
1423*5113495bSYour Name 	switch (nl_scan_priority) {
1424*5113495bSYour Name 	case QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW:
1425*5113495bSYour Name 		return SCAN_PRIORITY_VERY_LOW;
1426*5113495bSYour Name 
1427*5113495bSYour Name 	case QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW:
1428*5113495bSYour Name 		return SCAN_PRIORITY_LOW;
1429*5113495bSYour Name 
1430*5113495bSYour Name 	case QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM:
1431*5113495bSYour Name 		return SCAN_PRIORITY_MEDIUM;
1432*5113495bSYour Name 
1433*5113495bSYour Name 	case QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH:
1434*5113495bSYour Name 		return SCAN_PRIORITY_HIGH;
1435*5113495bSYour Name 
1436*5113495bSYour Name 	case QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH:
1437*5113495bSYour Name 		return SCAN_PRIORITY_VERY_HIGH;
1438*5113495bSYour Name 
1439*5113495bSYour Name 	default:
1440*5113495bSYour Name 		return SCAN_PRIORITY_COUNT;
1441*5113495bSYour Name 	}
1442*5113495bSYour Name }
1443*5113495bSYour Name 
wlan_is_scan_allowed(struct wlan_objmgr_vdev * vdev)1444*5113495bSYour Name bool wlan_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
1445*5113495bSYour Name {
1446*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
1447*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1448*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1449*5113495bSYour Name 	enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
1450*5113495bSYour Name 
1451*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
1452*5113495bSYour Name 	if (!psoc) {
1453*5113495bSYour Name 		osif_err("Invalid psoc object");
1454*5113495bSYour Name 		return false;
1455*5113495bSYour Name 	}
1456*5113495bSYour Name 
1457*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1458*5113495bSYour Name 	if (!osif_priv) {
1459*5113495bSYour Name 		osif_err("Invalid osif priv object");
1460*5113495bSYour Name 		return false;
1461*5113495bSYour Name 	}
1462*5113495bSYour Name 	/*
1463*5113495bSYour Name 	 * For a non-SAP vdevs, if a scan is already going on i.e the scan queue
1464*5113495bSYour Name 	 * is not empty, and the simultaneous scan is disabled, dont allow 2nd
1465*5113495bSYour Name 	 * scan.
1466*5113495bSYour Name 	 */
1467*5113495bSYour Name 	qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
1468*5113495bSYour Name 	if (!wlan_cfg80211_allow_simultaneous_scan(psoc) &&
1469*5113495bSYour Name 	    !qdf_list_empty(&osif_priv->osif_scan->scan_req_q) &&
1470*5113495bSYour Name 	    opmode != QDF_SAP_MODE) {
1471*5113495bSYour Name 		qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
1472*5113495bSYour Name 		osif_err_rl("Simultaneous scan disabled, reject scan");
1473*5113495bSYour Name 		return false;
1474*5113495bSYour Name 	}
1475*5113495bSYour Name 	qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
1476*5113495bSYour Name 
1477*5113495bSYour Name 	return true;
1478*5113495bSYour Name }
1479*5113495bSYour Name 
wlan_cfg80211_scan(struct wlan_objmgr_vdev * vdev,struct cfg80211_scan_request * request,struct scan_params * params)1480*5113495bSYour Name int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev,
1481*5113495bSYour Name 		       struct cfg80211_scan_request *request,
1482*5113495bSYour Name 		       struct scan_params *params)
1483*5113495bSYour Name {
1484*5113495bSYour Name 	struct scan_start_request *req;
1485*5113495bSYour Name 	struct wlan_ssid *pssid;
1486*5113495bSYour Name 	uint8_t i;
1487*5113495bSYour Name 	int ret = 0;
1488*5113495bSYour Name 	uint8_t num_chan = 0;
1489*5113495bSYour Name 	uint32_t c_freq;
1490*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
1491*5113495bSYour Name 	wlan_scan_requester req_id;
1492*5113495bSYour Name 	struct pdev_osif_priv *osif_priv;
1493*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1494*5113495bSYour Name 	wlan_scan_id scan_id;
1495*5113495bSYour Name 	bool is_p2p_scan = false;
1496*5113495bSYour Name 	enum wlan_band band;
1497*5113495bSYour Name 	QDF_STATUS qdf_status;
1498*5113495bSYour Name 	enum QDF_OPMODE opmode;
1499*5113495bSYour Name 	uint32_t extra_ie_len = 0;
1500*5113495bSYour Name 
1501*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
1502*5113495bSYour Name 	if (!psoc) {
1503*5113495bSYour Name 		osif_err("Invalid psoc object");
1504*5113495bSYour Name 		return -EINVAL;
1505*5113495bSYour Name 	}
1506*5113495bSYour Name 	opmode = wlan_vdev_mlme_get_opmode(vdev);
1507*5113495bSYour Name 
1508*5113495bSYour Name 	osif_debug("%s(vdev%d): mode %d flags 0x%x",
1509*5113495bSYour Name 		   request->wdev->netdev->name,
1510*5113495bSYour Name 		   wlan_vdev_get_id(vdev), opmode, request->flags);
1511*5113495bSYour Name 
1512*5113495bSYour Name 	if (!wlan_is_scan_allowed(vdev))
1513*5113495bSYour Name 		return -EBUSY;
1514*5113495bSYour Name 
1515*5113495bSYour Name 	osif_priv = wlan_pdev_get_ospriv(pdev);
1516*5113495bSYour Name 	if (!osif_priv) {
1517*5113495bSYour Name 		osif_err("Invalid osif priv object");
1518*5113495bSYour Name 		return -EINVAL;
1519*5113495bSYour Name 	}
1520*5113495bSYour Name 
1521*5113495bSYour Name 	req = qdf_mem_malloc(sizeof(*req));
1522*5113495bSYour Name 	if (!req)
1523*5113495bSYour Name 		return -EINVAL;
1524*5113495bSYour Name 
1525*5113495bSYour Name 	/* Initialize the scan global params */
1526*5113495bSYour Name 	ucfg_scan_init_default_params(vdev, req);
1527*5113495bSYour Name 
1528*5113495bSYour Name 	req_id = osif_priv->osif_scan->req_id;
1529*5113495bSYour Name 	scan_id = ucfg_scan_get_scan_id(psoc);
1530*5113495bSYour Name 	if (!scan_id) {
1531*5113495bSYour Name 		osif_err("Invalid scan id");
1532*5113495bSYour Name 		qdf_mem_free(req);
1533*5113495bSYour Name 		return -EINVAL;
1534*5113495bSYour Name 	}
1535*5113495bSYour Name 
1536*5113495bSYour Name 	/* fill the scan request structure */
1537*5113495bSYour Name 	req->vdev = vdev;
1538*5113495bSYour Name 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
1539*5113495bSYour Name 	req->scan_req.scan_id = scan_id;
1540*5113495bSYour Name 	req->scan_req.scan_req_id = req_id;
1541*5113495bSYour Name 
1542*5113495bSYour Name 	/* Update scan policy type flags according to cfg scan request */
1543*5113495bSYour Name 	wlan_cfg80211_update_scan_policy_type_flags(request,
1544*5113495bSYour Name 					     &req->scan_req);
1545*5113495bSYour Name 	/*
1546*5113495bSYour Name 	 * Even though supplicant doesn't provide any SSIDs, n_ssids is
1547*5113495bSYour Name 	 * set to 1.  Because of this, driver is assuming that this is not
1548*5113495bSYour Name 	 * wildcard scan and so is not aging out the scan results.
1549*5113495bSYour Name 	 */
1550*5113495bSYour Name 	if ((request->ssids) && (request->n_ssids == 1) &&
1551*5113495bSYour Name 	    ('\0' == request->ssids->ssid[0])) {
1552*5113495bSYour Name 		request->n_ssids = 0;
1553*5113495bSYour Name 	}
1554*5113495bSYour Name 
1555*5113495bSYour Name 	if ((request->ssids) && (0 < request->n_ssids)) {
1556*5113495bSYour Name 		int j;
1557*5113495bSYour Name 		req->scan_req.num_ssids = request->n_ssids;
1558*5113495bSYour Name 
1559*5113495bSYour Name 		if (req->scan_req.num_ssids > WLAN_SCAN_MAX_NUM_SSID) {
1560*5113495bSYour Name 			osif_info("number of ssid %d greater than MAX %d",
1561*5113495bSYour Name 				  req->scan_req.num_ssids,
1562*5113495bSYour Name 				  WLAN_SCAN_MAX_NUM_SSID);
1563*5113495bSYour Name 			req->scan_req.num_ssids = WLAN_SCAN_MAX_NUM_SSID;
1564*5113495bSYour Name 		}
1565*5113495bSYour Name 		/* copy all the ssid's and their length */
1566*5113495bSYour Name 		for (j = 0; j < req->scan_req.num_ssids; j++)  {
1567*5113495bSYour Name 			pssid = &req->scan_req.ssid[j];
1568*5113495bSYour Name 			/* get the ssid length */
1569*5113495bSYour Name 			pssid->length = request->ssids[j].ssid_len;
1570*5113495bSYour Name 			if (pssid->length > WLAN_SSID_MAX_LEN)
1571*5113495bSYour Name 				pssid->length = WLAN_SSID_MAX_LEN;
1572*5113495bSYour Name 			qdf_mem_copy(pssid->ssid,
1573*5113495bSYour Name 				     &request->ssids[j].ssid[0],
1574*5113495bSYour Name 				     pssid->length);
1575*5113495bSYour Name 		}
1576*5113495bSYour Name 	}
1577*5113495bSYour Name 	if (request->ssids ||
1578*5113495bSYour Name 	   (opmode == QDF_P2P_GO_MODE) || (opmode == QDF_P2P_DEVICE_MODE))
1579*5113495bSYour Name 		req->scan_req.scan_f_passive = false;
1580*5113495bSYour Name 
1581*5113495bSYour Name 	if (params->half_rate)
1582*5113495bSYour Name 		req->scan_req.scan_f_half_rate = true;
1583*5113495bSYour Name 	else if (params->quarter_rate)
1584*5113495bSYour Name 		req->scan_req.scan_f_quarter_rate = true;
1585*5113495bSYour Name 
1586*5113495bSYour Name 	if (params->strict_pscan)
1587*5113495bSYour Name 		req->scan_req.scan_f_strict_passive_pch = true;
1588*5113495bSYour Name 
1589*5113495bSYour Name 	if ((request->n_ssids == 1) && request->ssids &&
1590*5113495bSYour Name 	   !qdf_mem_cmp(&request->ssids[0], "DIRECT-", 7))
1591*5113495bSYour Name 		is_p2p_scan = true;
1592*5113495bSYour Name 
1593*5113495bSYour Name 	if (is_p2p_scan && request->no_cck)
1594*5113495bSYour Name 		req->scan_req.scan_type = SCAN_TYPE_P2P_SEARCH;
1595*5113495bSYour Name 
1596*5113495bSYour Name 	if (params->dwell_time_active)
1597*5113495bSYour Name 		req->scan_req.dwell_time_active = params->dwell_time_active;
1598*5113495bSYour Name 
1599*5113495bSYour Name 	if (params->dwell_time_active_2g)
1600*5113495bSYour Name 		req->scan_req.dwell_time_active_2g =
1601*5113495bSYour Name 			params->dwell_time_active_2g;
1602*5113495bSYour Name 
1603*5113495bSYour Name 	if (params->dwell_time_passive)
1604*5113495bSYour Name 		req->scan_req.dwell_time_passive = params->dwell_time_passive;
1605*5113495bSYour Name 
1606*5113495bSYour Name 	if (params->dwell_time_active_6g)
1607*5113495bSYour Name 		req->scan_req.dwell_time_active_6g =
1608*5113495bSYour Name 			params->dwell_time_active_6g;
1609*5113495bSYour Name 
1610*5113495bSYour Name 	if (params->dwell_time_passive_6g)
1611*5113495bSYour Name 		req->scan_req.dwell_time_passive_6g =
1612*5113495bSYour Name 			params->dwell_time_passive_6g;
1613*5113495bSYour Name 
1614*5113495bSYour Name 	/* Set dwell time mode according to scan policy type flags */
1615*5113495bSYour Name 	if (ucfg_scan_cfg_honour_nl_scan_policy_flags(psoc)) {
1616*5113495bSYour Name 		if (req->scan_req.scan_policy_high_accuracy)
1617*5113495bSYour Name 			req->scan_req.adaptive_dwell_time_mode =
1618*5113495bSYour Name 						SCAN_DWELL_MODE_STATIC;
1619*5113495bSYour Name 		if (req->scan_req.scan_policy_low_power)
1620*5113495bSYour Name 			req->scan_req.adaptive_dwell_time_mode =
1621*5113495bSYour Name 						SCAN_DWELL_MODE_AGGRESSIVE;
1622*5113495bSYour Name 	}
1623*5113495bSYour Name 
1624*5113495bSYour Name 	/*
1625*5113495bSYour Name 	 * FW require at least 1 MAC to send probe request.
1626*5113495bSYour Name 	 * If MAC is all 0 set it to BC addr as this is the address on
1627*5113495bSYour Name 	 * which fw will send probe req.
1628*5113495bSYour Name 	 */
1629*5113495bSYour Name 	req->scan_req.num_bssid = 1;
1630*5113495bSYour Name 	wlan_copy_bssid_scan_request(req, request);
1631*5113495bSYour Name 	if (qdf_is_macaddr_zero(&req->scan_req.bssid_list[0]))
1632*5113495bSYour Name 		qdf_set_macaddr_broadcast(&req->scan_req.bssid_list[0]);
1633*5113495bSYour Name 
1634*5113495bSYour Name 	if (params->scan_f_2ghz && !params->scan_f_5ghz) {
1635*5113495bSYour Name 		req->scan_req.scan_f_2ghz = true;
1636*5113495bSYour Name 		req->scan_req.scan_f_5ghz = false;
1637*5113495bSYour Name 	} else if (!params->scan_f_2ghz && params->scan_f_5ghz) {
1638*5113495bSYour Name 		req->scan_req.scan_f_2ghz = false;
1639*5113495bSYour Name 		req->scan_req.scan_f_5ghz = true;
1640*5113495bSYour Name 	}
1641*5113495bSYour Name 
1642*5113495bSYour Name 	if (request->n_channels) {
1643*5113495bSYour Name #ifdef WLAN_POLICY_MGR_ENABLE
1644*5113495bSYour Name 		bool ap_or_go_present = wlan_cfg80211_is_ap_go_present(psoc);
1645*5113495bSYour Name #endif
1646*5113495bSYour Name 		for (i = 0; i < request->n_channels; i++) {
1647*5113495bSYour Name 			c_freq = request->channels[i]->center_freq;
1648*5113495bSYour Name 			if (wlan_reg_is_dsrc_freq(c_freq))
1649*5113495bSYour Name 				continue;
1650*5113495bSYour Name #ifdef WLAN_POLICY_MGR_ENABLE
1651*5113495bSYour Name 			if (ap_or_go_present) {
1652*5113495bSYour Name 				bool ok;
1653*5113495bSYour Name 
1654*5113495bSYour Name 				qdf_status = policy_mgr_is_chan_ok_for_dnbs(
1655*5113495bSYour Name 							psoc, c_freq, &ok);
1656*5113495bSYour Name 
1657*5113495bSYour Name 				if (QDF_IS_STATUS_ERROR(qdf_status)) {
1658*5113495bSYour Name 					osif_err("DNBS check failed");
1659*5113495bSYour Name 					ret = -EINVAL;
1660*5113495bSYour Name 					goto err;
1661*5113495bSYour Name 				}
1662*5113495bSYour Name 				if (!ok)
1663*5113495bSYour Name 					continue;
1664*5113495bSYour Name 			}
1665*5113495bSYour Name #endif
1666*5113495bSYour Name 
1667*5113495bSYour Name 			if ((req->scan_req.scan_f_2ghz &&
1668*5113495bSYour Name 			     WLAN_REG_IS_24GHZ_CH_FREQ(c_freq)) ||
1669*5113495bSYour Name 			    (req->scan_req.scan_f_5ghz &&
1670*5113495bSYour Name 			     (WLAN_REG_IS_5GHZ_CH_FREQ(c_freq) ||
1671*5113495bSYour Name 			      WLAN_REG_IS_49GHZ_FREQ(c_freq) ||
1672*5113495bSYour Name 			      WLAN_REG_IS_6GHZ_CHAN_FREQ(c_freq)))) {
1673*5113495bSYour Name 				req->scan_req.chan_list.chan[num_chan].freq =
1674*5113495bSYour Name 									c_freq;
1675*5113495bSYour Name 				band = util_scan_scm_freq_to_band(c_freq);
1676*5113495bSYour Name 				if (band == WLAN_BAND_2_4_GHZ)
1677*5113495bSYour Name 					req->scan_req.chan_list.chan[num_chan].phymode =
1678*5113495bSYour Name 						SCAN_PHY_MODE_11G;
1679*5113495bSYour Name 				else
1680*5113495bSYour Name 					req->scan_req.chan_list.chan[num_chan].phymode =
1681*5113495bSYour Name 						SCAN_PHY_MODE_11A;
1682*5113495bSYour Name 				num_chan++;
1683*5113495bSYour Name 				if (num_chan >= NUM_CHANNELS)
1684*5113495bSYour Name 					break;
1685*5113495bSYour Name 			}
1686*5113495bSYour Name 		}
1687*5113495bSYour Name 	}
1688*5113495bSYour Name 	if (!num_chan) {
1689*5113495bSYour Name 		osif_err("Received zero non-dsrc channels");
1690*5113495bSYour Name 		ret = -EINVAL;
1691*5113495bSYour Name 		goto err;
1692*5113495bSYour Name 	}
1693*5113495bSYour Name 	req->scan_req.chan_list.num_chan = num_chan;
1694*5113495bSYour Name 
1695*5113495bSYour Name 	/* P2P increase the scan priority */
1696*5113495bSYour Name 	if (is_p2p_scan)
1697*5113495bSYour Name 		req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
1698*5113495bSYour Name 
1699*5113495bSYour Name 	if (params->priority != SCAN_PRIORITY_COUNT)
1700*5113495bSYour Name 		req->scan_req.scan_priority = params->priority;
1701*5113495bSYour Name 
1702*5113495bSYour Name 	if (request->ie_len)
1703*5113495bSYour Name 		extra_ie_len = request->ie_len;
1704*5113495bSYour Name 	else if (params->default_ie.ptr && params->default_ie.len)
1705*5113495bSYour Name 		extra_ie_len = params->default_ie.len;
1706*5113495bSYour Name 
1707*5113495bSYour Name 	if (params->vendor_ie.ptr && params->vendor_ie.len)
1708*5113495bSYour Name 		extra_ie_len += params->vendor_ie.len;
1709*5113495bSYour Name 
1710*5113495bSYour Name 	if (extra_ie_len) {
1711*5113495bSYour Name 		req->scan_req.extraie.ptr = qdf_mem_malloc(extra_ie_len);
1712*5113495bSYour Name 		if (!req->scan_req.extraie.ptr) {
1713*5113495bSYour Name 			ret = -ENOMEM;
1714*5113495bSYour Name 			goto err;
1715*5113495bSYour Name 		}
1716*5113495bSYour Name 	}
1717*5113495bSYour Name 
1718*5113495bSYour Name 	if (request->ie_len) {
1719*5113495bSYour Name 		req->scan_req.extraie.len = request->ie_len;
1720*5113495bSYour Name 		qdf_mem_copy(req->scan_req.extraie.ptr, request->ie,
1721*5113495bSYour Name 			     request->ie_len);
1722*5113495bSYour Name 	} else if (params->default_ie.ptr && params->default_ie.len) {
1723*5113495bSYour Name 		req->scan_req.extraie.len = params->default_ie.len;
1724*5113495bSYour Name 		qdf_mem_copy(req->scan_req.extraie.ptr, params->default_ie.ptr,
1725*5113495bSYour Name 			     params->default_ie.len);
1726*5113495bSYour Name 	}
1727*5113495bSYour Name 
1728*5113495bSYour Name 	if (params->vendor_ie.ptr && params->vendor_ie.len) {
1729*5113495bSYour Name 		qdf_mem_copy((req->scan_req.extraie.ptr +
1730*5113495bSYour Name 			      req->scan_req.extraie.len),
1731*5113495bSYour Name 			     params->vendor_ie.ptr, params->vendor_ie.len);
1732*5113495bSYour Name 
1733*5113495bSYour Name 		req->scan_req.extraie.len += params->vendor_ie.len;
1734*5113495bSYour Name 	}
1735*5113495bSYour Name 
1736*5113495bSYour Name 	if (!is_p2p_scan) {
1737*5113495bSYour Name 		if (req->scan_req.scan_random.randomize)
1738*5113495bSYour Name 			wlan_scan_rand_attrs(vdev, request, req);
1739*5113495bSYour Name 		if (ucfg_ie_allowlist_enabled(psoc, vdev) &&
1740*5113495bSYour Name 		    ucfg_copy_ie_allowlist_attrs(psoc,
1741*5113495bSYour Name 						 &req->scan_req.ie_allowlist))
1742*5113495bSYour Name 			req->scan_req.scan_f_en_ie_allowlist_in_probe = true;
1743*5113495bSYour Name 	}
1744*5113495bSYour Name 
1745*5113495bSYour Name 	if (request->flags & NL80211_SCAN_FLAG_FLUSH)
1746*5113495bSYour Name 		ucfg_scan_flush_results(pdev, NULL);
1747*5113495bSYour Name 
1748*5113495bSYour Name 	if (params->scan_probe_unicast_ra)
1749*5113495bSYour Name 		req->scan_req.scan_ctrl_flags_ext |=
1750*5113495bSYour Name 				SCAN_FLAG_EXT_FORCE_UNICAST_RA;
1751*5113495bSYour Name 
1752*5113495bSYour Name 	osif_debug("scan_ctrl_flags_ext %0x",
1753*5113495bSYour Name 		   req->scan_req.scan_ctrl_flags_ext);
1754*5113495bSYour Name 
1755*5113495bSYour Name 	req->scan_req.mld_id = params->mld_id;
1756*5113495bSYour Name 
1757*5113495bSYour Name 	/*
1758*5113495bSYour Name 	 * Acquire wakelock to handle the case where APP's send scan to connect.
1759*5113495bSYour Name 	 * If suspend is received during scan scan will be aborted and APP will
1760*5113495bSYour Name 	 * not get scan result and not connect. eg if PNO is implemented in
1761*5113495bSYour Name 	 * framework.
1762*5113495bSYour Name 	 */
1763*5113495bSYour Name 	wlan_scan_acquire_wake_lock_timeout(psoc,
1764*5113495bSYour Name 					&osif_priv->osif_scan->scan_wake_lock,
1765*5113495bSYour Name 					SCAN_WAKE_LOCK_SCAN_DURATION);
1766*5113495bSYour Name 
1767*5113495bSYour Name 	qdf_runtime_pm_prevent_suspend(
1768*5113495bSYour Name 		&osif_priv->osif_scan->runtime_pm_lock);
1769*5113495bSYour Name 
1770*5113495bSYour Name 	qdf_status = wlan_schedule_scan_start_request(pdev, request,
1771*5113495bSYour Name 						      params->source, req);
1772*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
1773*5113495bSYour Name 		qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
1774*5113495bSYour Name 		if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
1775*5113495bSYour Name 			qdf_mutex_release(
1776*5113495bSYour Name 				&osif_priv->osif_scan->scan_req_q_lock);
1777*5113495bSYour Name 			qdf_runtime_pm_allow_suspend(
1778*5113495bSYour Name 					&osif_priv->osif_scan->runtime_pm_lock);
1779*5113495bSYour Name 			wlan_scan_release_wake_lock(
1780*5113495bSYour Name 					psoc,
1781*5113495bSYour Name 					&osif_priv->osif_scan->scan_wake_lock);
1782*5113495bSYour Name 		} else {
1783*5113495bSYour Name 			qdf_mutex_release(
1784*5113495bSYour Name 				&osif_priv->osif_scan->scan_req_q_lock);
1785*5113495bSYour Name 		}
1786*5113495bSYour Name 	}
1787*5113495bSYour Name 
1788*5113495bSYour Name 	return qdf_status_to_os_return(qdf_status);
1789*5113495bSYour Name 
1790*5113495bSYour Name err:
1791*5113495bSYour Name 	qdf_mem_free(req);
1792*5113495bSYour Name 	return ret;
1793*5113495bSYour Name }
1794*5113495bSYour Name 
1795*5113495bSYour Name /**
1796*5113495bSYour Name  * wlan_get_scanid() - API to get the scan id
1797*5113495bSYour Name  * from the scan cookie attribute.
1798*5113495bSYour Name  * @pdev: Pointer to pdev object
1799*5113495bSYour Name  * @scan_id: Pointer to scan id
1800*5113495bSYour Name  * @cookie : Scan cookie attribute
1801*5113495bSYour Name  *
1802*5113495bSYour Name  * API to get the scan id from the scan cookie attribute
1803*5113495bSYour Name  * sent from supplicant by matching scan request.
1804*5113495bSYour Name  *
1805*5113495bSYour Name  * Return: 0 for success, non zero for failure
1806*5113495bSYour Name  */
wlan_get_scanid(struct wlan_objmgr_pdev * pdev,uint32_t * scan_id,uint64_t cookie)1807*5113495bSYour Name static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev,
1808*5113495bSYour Name 			       uint32_t *scan_id, uint64_t cookie)
1809*5113495bSYour Name {
1810*5113495bSYour Name 	struct scan_req *scan_req;
1811*5113495bSYour Name 	qdf_list_node_t *node = NULL;
1812*5113495bSYour Name 	qdf_list_node_t *ptr_node = NULL;
1813*5113495bSYour Name 	int ret = -EINVAL;
1814*5113495bSYour Name 	struct pdev_osif_priv *osif_ctx;
1815*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1816*5113495bSYour Name 
1817*5113495bSYour Name 	/* Get NL global context from objmgr*/
1818*5113495bSYour Name 	osif_ctx = wlan_pdev_get_ospriv(pdev);
1819*5113495bSYour Name 	if (!osif_ctx) {
1820*5113495bSYour Name 		osif_err("Failed to retrieve osif context");
1821*5113495bSYour Name 		return ret;
1822*5113495bSYour Name 	}
1823*5113495bSYour Name 	scan_priv = osif_ctx->osif_scan;
1824*5113495bSYour Name 	qdf_mutex_acquire(&scan_priv->scan_req_q_lock);
1825*5113495bSYour Name 	if (qdf_list_empty(&scan_priv->scan_req_q)) {
1826*5113495bSYour Name 		qdf_mutex_release(&scan_priv->scan_req_q_lock);
1827*5113495bSYour Name 		osif_err("Failed to retrieve scan id");
1828*5113495bSYour Name 		return ret;
1829*5113495bSYour Name 	}
1830*5113495bSYour Name 
1831*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
1832*5113495bSYour Name 			    qdf_list_peek_front(&scan_priv->scan_req_q,
1833*5113495bSYour Name 			    &ptr_node)) {
1834*5113495bSYour Name 		qdf_mutex_release(&scan_priv->scan_req_q_lock);
1835*5113495bSYour Name 		return ret;
1836*5113495bSYour Name 	}
1837*5113495bSYour Name 
1838*5113495bSYour Name 	do {
1839*5113495bSYour Name 		node = ptr_node;
1840*5113495bSYour Name 		scan_req = qdf_container_of(node, struct scan_req, node);
1841*5113495bSYour Name 		if (cookie ==
1842*5113495bSYour Name 		    (uintptr_t)(scan_req->scan_request)) {
1843*5113495bSYour Name 			*scan_id = scan_req->scan_id;
1844*5113495bSYour Name 			ret = 0;
1845*5113495bSYour Name 			break;
1846*5113495bSYour Name 		}
1847*5113495bSYour Name 	} while (QDF_STATUS_SUCCESS ==
1848*5113495bSYour Name 		 qdf_list_peek_next(&scan_priv->scan_req_q,
1849*5113495bSYour Name 		 node, &ptr_node));
1850*5113495bSYour Name 
1851*5113495bSYour Name 	qdf_mutex_release(&scan_priv->scan_req_q_lock);
1852*5113495bSYour Name 
1853*5113495bSYour Name 	return ret;
1854*5113495bSYour Name }
1855*5113495bSYour Name 
wlan_abort_scan(struct wlan_objmgr_pdev * pdev,uint32_t pdev_id,uint32_t vdev_id,wlan_scan_id scan_id,bool sync)1856*5113495bSYour Name QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev,
1857*5113495bSYour Name 				   uint32_t pdev_id, uint32_t vdev_id,
1858*5113495bSYour Name 				   wlan_scan_id scan_id, bool sync)
1859*5113495bSYour Name {
1860*5113495bSYour Name 	struct scan_cancel_request *req;
1861*5113495bSYour Name 	struct pdev_osif_priv *osif_ctx;
1862*5113495bSYour Name 	struct osif_scan_pdev *scan_priv;
1863*5113495bSYour Name 	QDF_STATUS status;
1864*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1865*5113495bSYour Name 
1866*5113495bSYour Name 	req = qdf_mem_malloc(sizeof(*req));
1867*5113495bSYour Name 	if (!req)
1868*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1869*5113495bSYour Name 
1870*5113495bSYour Name 	/* Get NL global context from objmgr*/
1871*5113495bSYour Name 	osif_ctx = wlan_pdev_get_ospriv(pdev);
1872*5113495bSYour Name 	if (!osif_ctx) {
1873*5113495bSYour Name 		osif_err("Failed to retrieve osif context");
1874*5113495bSYour Name 		qdf_mem_free(req);
1875*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1876*5113495bSYour Name 	}
1877*5113495bSYour Name 	if (vdev_id == INVAL_VDEV_ID)
1878*5113495bSYour Name 		vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_OSIF_ID);
1879*5113495bSYour Name 	else
1880*5113495bSYour Name 		vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev,
1881*5113495bSYour Name 				vdev_id, WLAN_OSIF_ID);
1882*5113495bSYour Name 
1883*5113495bSYour Name 	if (!vdev) {
1884*5113495bSYour Name 		qdf_mem_free(req);
1885*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1886*5113495bSYour Name 	}
1887*5113495bSYour Name 	scan_priv = osif_ctx->osif_scan;
1888*5113495bSYour Name 	req->cancel_req.requester = scan_priv->req_id;
1889*5113495bSYour Name 	req->vdev = vdev;
1890*5113495bSYour Name 	req->cancel_req.scan_id = scan_id;
1891*5113495bSYour Name 	req->cancel_req.pdev_id = pdev_id;
1892*5113495bSYour Name 	req->cancel_req.vdev_id = vdev_id;
1893*5113495bSYour Name 	if (scan_id != INVAL_SCAN_ID && scan_id != CANCEL_HOST_SCAN_ID)
1894*5113495bSYour Name 		req->cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE;
1895*5113495bSYour Name 	else if (scan_id == CANCEL_HOST_SCAN_ID)
1896*5113495bSYour Name 		req->cancel_req.req_type = WLAN_SCAN_CANCEL_HOST_VDEV_ALL;
1897*5113495bSYour Name 	else if (vdev_id == INVAL_VDEV_ID)
1898*5113495bSYour Name 		req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL;
1899*5113495bSYour Name 	else
1900*5113495bSYour Name 		req->cancel_req.req_type = WLAN_SCAN_CANCEL_VDEV_ALL;
1901*5113495bSYour Name 
1902*5113495bSYour Name 	osif_debug("Type %d Vdev %d pdev %d scan id %d sync %d",
1903*5113495bSYour Name 		   req->cancel_req.req_type, req->cancel_req.vdev_id,
1904*5113495bSYour Name 		   req->cancel_req.pdev_id, req->cancel_req.scan_id, sync);
1905*5113495bSYour Name 
1906*5113495bSYour Name 	if (sync)
1907*5113495bSYour Name 		status = ucfg_scan_cancel_sync(req);
1908*5113495bSYour Name 	else
1909*5113495bSYour Name 		status = ucfg_scan_cancel(req);
1910*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1911*5113495bSYour Name 		osif_err("Cancel scan request failed");
1912*5113495bSYour Name 
1913*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
1914*5113495bSYour Name 
1915*5113495bSYour Name 	return status;
1916*5113495bSYour Name }
1917*5113495bSYour Name 
1918*5113495bSYour Name qdf_export_symbol(wlan_abort_scan);
1919*5113495bSYour Name 
wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev * pdev)1920*5113495bSYour Name int wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev *pdev)
1921*5113495bSYour Name {
1922*5113495bSYour Name 	uint8_t pdev_id;
1923*5113495bSYour Name 
1924*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1925*5113495bSYour Name 
1926*5113495bSYour Name 	if (ucfg_scan_get_pdev_status(pdev) !=
1927*5113495bSYour Name 	   SCAN_NOT_IN_PROGRESS)
1928*5113495bSYour Name 		wlan_abort_scan(pdev, pdev_id,
1929*5113495bSYour Name 			INVAL_VDEV_ID, INVAL_SCAN_ID, true);
1930*5113495bSYour Name 
1931*5113495bSYour Name 	return 0;
1932*5113495bSYour Name }
1933*5113495bSYour Name 
wlan_vendor_abort_scan(struct wlan_objmgr_pdev * pdev,const void * data,int data_len)1934*5113495bSYour Name int wlan_vendor_abort_scan(struct wlan_objmgr_pdev *pdev,
1935*5113495bSYour Name 			const void *data, int data_len)
1936*5113495bSYour Name {
1937*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
1938*5113495bSYour Name 	int ret = -EINVAL;
1939*5113495bSYour Name 	wlan_scan_id scan_id;
1940*5113495bSYour Name 	uint64_t cookie;
1941*5113495bSYour Name 	uint8_t pdev_id;
1942*5113495bSYour Name 
1943*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1944*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX, data,
1945*5113495bSYour Name 				    data_len, cfg80211_scan_policy)) {
1946*5113495bSYour Name 		osif_err("Invalid ATTR");
1947*5113495bSYour Name 		return ret;
1948*5113495bSYour Name 	}
1949*5113495bSYour Name 
1950*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]) {
1951*5113495bSYour Name 		cookie = nla_get_u64(
1952*5113495bSYour Name 			    tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
1953*5113495bSYour Name 		ret = wlan_get_scanid(pdev, &scan_id, cookie);
1954*5113495bSYour Name 		if (ret != 0)
1955*5113495bSYour Name 			return ret;
1956*5113495bSYour Name 		if (ucfg_scan_get_pdev_status(pdev) !=
1957*5113495bSYour Name 		   SCAN_NOT_IN_PROGRESS)
1958*5113495bSYour Name 			wlan_abort_scan(pdev, INVAL_PDEV_ID,
1959*5113495bSYour Name 					INVAL_VDEV_ID, scan_id, true);
1960*5113495bSYour Name 	}
1961*5113495bSYour Name 	return 0;
1962*5113495bSYour Name }
1963*5113495bSYour Name 
1964*5113495bSYour Name static inline struct ieee80211_channel *
wlan_get_ieee80211_channel(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,int chan_freq)1965*5113495bSYour Name wlan_get_ieee80211_channel(struct wiphy *wiphy,
1966*5113495bSYour Name 		struct wlan_objmgr_pdev *pdev,
1967*5113495bSYour Name 		int chan_freq)
1968*5113495bSYour Name {
1969*5113495bSYour Name 	struct ieee80211_channel *chan;
1970*5113495bSYour Name 
1971*5113495bSYour Name 	chan = ieee80211_get_channel(wiphy, chan_freq);
1972*5113495bSYour Name 	if (!chan)
1973*5113495bSYour Name 		osif_err_rl("chan is NULL, freq: %d", chan_freq);
1974*5113495bSYour Name 
1975*5113495bSYour Name 	return chan;
1976*5113495bSYour Name }
1977*5113495bSYour Name 
1978*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
1979*5113495bSYour Name 	defined(CFG80211_INFORM_BSS_FRAME_DATA)
1980*5113495bSYour Name /**
1981*5113495bSYour Name  * wlan_fill_per_chain_rssi() - fill per chain RSSI in inform bss
1982*5113495bSYour Name  * @data: destination bss data
1983*5113495bSYour Name  * @bss: source bss data containing per chain RSSI
1984*5113495bSYour Name  *
1985*5113495bSYour Name  * Return: void
1986*5113495bSYour Name  */
1987*5113495bSYour Name #if defined(CFG80211_SCAN_PER_CHAIN_RSSI_SUPPORT) || \
1988*5113495bSYour Name 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
wlan_fill_per_chain_rssi(struct cfg80211_inform_bss * data,struct wlan_cfg80211_inform_bss * bss)1989*5113495bSYour Name static void wlan_fill_per_chain_rssi(struct cfg80211_inform_bss *data,
1990*5113495bSYour Name 	struct wlan_cfg80211_inform_bss *bss)
1991*5113495bSYour Name {
1992*5113495bSYour Name 
1993*5113495bSYour Name 	uint32_t i;
1994*5113495bSYour Name 
1995*5113495bSYour Name 	if (!bss || !data) {
1996*5113495bSYour Name 		osif_err("Received bss is NULL");
1997*5113495bSYour Name 		return;
1998*5113495bSYour Name 	}
1999*5113495bSYour Name 	for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) {
2000*5113495bSYour Name 		if (!bss->per_chain_rssi[i] ||
2001*5113495bSYour Name 		    (bss->per_chain_rssi[i] == WLAN_INVALID_PER_CHAIN_RSSI))
2002*5113495bSYour Name 			continue;
2003*5113495bSYour Name 		data->chain_signal[i] = bss->per_chain_rssi[i];
2004*5113495bSYour Name 		data->chains |= BIT(i);
2005*5113495bSYour Name 	}
2006*5113495bSYour Name }
2007*5113495bSYour Name #else
2008*5113495bSYour Name static inline void
wlan_fill_per_chain_rssi(struct cfg80211_inform_bss * data,struct wlan_cfg80211_inform_bss * bss)2009*5113495bSYour Name wlan_fill_per_chain_rssi(struct cfg80211_inform_bss *data,
2010*5113495bSYour Name 	struct wlan_cfg80211_inform_bss *bss)
2011*5113495bSYour Name {
2012*5113495bSYour Name }
2013*5113495bSYour Name #endif
2014*5113495bSYour Name 
2015*5113495bSYour Name struct cfg80211_bss *
wlan_cfg80211_inform_bss_frame_data(struct wiphy * wiphy,struct wlan_cfg80211_inform_bss * bss)2016*5113495bSYour Name wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
2017*5113495bSYour Name 		struct wlan_cfg80211_inform_bss *bss)
2018*5113495bSYour Name {
2019*5113495bSYour Name 	struct cfg80211_inform_bss data  = {0};
2020*5113495bSYour Name 
2021*5113495bSYour Name 	if (!bss) {
2022*5113495bSYour Name 		osif_err("bss is null");
2023*5113495bSYour Name 		return NULL;
2024*5113495bSYour Name 	}
2025*5113495bSYour Name 	wlan_fill_per_chain_rssi(&data, bss);
2026*5113495bSYour Name 
2027*5113495bSYour Name 	data.chan = bss->chan;
2028*5113495bSYour Name 	data.boottime_ns = bss->boottime_ns;
2029*5113495bSYour Name 	data.signal = bss->rssi;
2030*5113495bSYour Name 	return cfg80211_inform_bss_frame_data(wiphy, &data, bss->mgmt,
2031*5113495bSYour Name 					      bss->frame_len, GFP_ATOMIC);
2032*5113495bSYour Name }
2033*5113495bSYour Name #else
2034*5113495bSYour Name struct cfg80211_bss *
wlan_cfg80211_inform_bss_frame_data(struct wiphy * wiphy,struct wlan_cfg80211_inform_bss * bss)2035*5113495bSYour Name wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
2036*5113495bSYour Name 		struct wlan_cfg80211_inform_bss *bss)
2037*5113495bSYour Name 
2038*5113495bSYour Name {
2039*5113495bSYour Name 	return cfg80211_inform_bss_frame(wiphy, bss->chan, bss->mgmt,
2040*5113495bSYour Name 					 bss->frame_len,
2041*5113495bSYour Name 					 bss->rssi, GFP_ATOMIC);
2042*5113495bSYour Name }
2043*5113495bSYour Name #endif
2044*5113495bSYour Name 
2045*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
wlan_cfg80211_put_bss(struct wiphy * wiphy,struct cfg80211_bss * bss)2046*5113495bSYour Name static inline void wlan_cfg80211_put_bss(struct wiphy *wiphy,
2047*5113495bSYour Name 		struct cfg80211_bss *bss)
2048*5113495bSYour Name {
2049*5113495bSYour Name 	cfg80211_put_bss(wiphy, bss);
2050*5113495bSYour Name }
2051*5113495bSYour Name #else
wlan_cfg80211_put_bss(struct wiphy * wiphy,struct cfg80211_bss * bss)2052*5113495bSYour Name static inline void wlan_cfg80211_put_bss(struct wiphy *wiphy,
2053*5113495bSYour Name 		struct cfg80211_bss *bss)
2054*5113495bSYour Name {
2055*5113495bSYour Name 	cfg80211_put_bss(bss);
2056*5113495bSYour Name }
2057*5113495bSYour Name #endif
2058*5113495bSYour Name 
wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)2059*5113495bSYour Name void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev,
2060*5113495bSYour Name 		struct scan_cache_entry *scan_params)
2061*5113495bSYour Name {
2062*5113495bSYour Name 	struct pdev_osif_priv *pdev_ospriv = wlan_pdev_get_ospriv(pdev);
2063*5113495bSYour Name 	struct wiphy *wiphy;
2064*5113495bSYour Name 	struct cfg80211_bss *bss = NULL;
2065*5113495bSYour Name 	struct wlan_cfg80211_inform_bss bss_data = {0};
2066*5113495bSYour Name 
2067*5113495bSYour Name 	if (!pdev_ospriv) {
2068*5113495bSYour Name 		osif_err("os_priv is NULL");
2069*5113495bSYour Name 		return;
2070*5113495bSYour Name 	}
2071*5113495bSYour Name 
2072*5113495bSYour Name 	wiphy = pdev_ospriv->wiphy;
2073*5113495bSYour Name 
2074*5113495bSYour Name 	bss_data.frame_len = ucfg_scan_get_entry_frame_len(scan_params);
2075*5113495bSYour Name 	bss_data.mgmt = qdf_mem_malloc_atomic(bss_data.frame_len);
2076*5113495bSYour Name 	if (!bss_data.mgmt) {
2077*5113495bSYour Name 		osif_err("bss mem alloc failed for seq %d",
2078*5113495bSYour Name 			 scan_params->seq_num);
2079*5113495bSYour Name 		return;
2080*5113495bSYour Name 	}
2081*5113495bSYour Name 	qdf_mem_copy(bss_data.mgmt,
2082*5113495bSYour Name 		 util_scan_entry_frame_ptr(scan_params),
2083*5113495bSYour Name 		 util_scan_entry_frame_len(scan_params));
2084*5113495bSYour Name 	/*
2085*5113495bSYour Name 	 * Android does not want the timestamp from the frame.
2086*5113495bSYour Name 	 * Instead it wants a monotonic increasing value
2087*5113495bSYour Name 	 */
2088*5113495bSYour Name 	bss_data.mgmt->u.probe_resp.timestamp = qdf_get_monotonic_boottime();
2089*5113495bSYour Name 	/*
2090*5113495bSYour Name 	 * Based on .ini configuration, raw rssi can be reported for bss.
2091*5113495bSYour Name 	 * Raw rssi is typically used for estimating power.
2092*5113495bSYour Name 	 */
2093*5113495bSYour Name 	bss_data.rssi = scan_params->rssi_raw;
2094*5113495bSYour Name 
2095*5113495bSYour Name 	bss_data.chan = wlan_get_ieee80211_channel(wiphy, pdev,
2096*5113495bSYour Name 		scan_params->channel.chan_freq);
2097*5113495bSYour Name 	if (!bss_data.chan) {
2098*5113495bSYour Name 		osif_err_rl("Channel not found for bss " QDF_MAC_ADDR_FMT " seq %d chan_freq %d",
2099*5113495bSYour Name 			    QDF_MAC_ADDR_REF(bss_data.mgmt->bssid),
2100*5113495bSYour Name 			    scan_params->seq_num,
2101*5113495bSYour Name 			    scan_params->channel.chan_freq);
2102*5113495bSYour Name 		qdf_mem_free(bss_data.mgmt);
2103*5113495bSYour Name 		return;
2104*5113495bSYour Name 	}
2105*5113495bSYour Name 
2106*5113495bSYour Name 	/*
2107*5113495bSYour Name 	 * Supplicant takes the signal strength in terms of
2108*5113495bSYour Name 	 * mBm (1 dBm = 100 mBm).
2109*5113495bSYour Name 	 */
2110*5113495bSYour Name 	bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
2111*5113495bSYour Name 
2112*5113495bSYour Name 	bss_data.boottime_ns = scan_params->boottime_ns;
2113*5113495bSYour Name 
2114*5113495bSYour Name 	qdf_mem_copy(bss_data.per_chain_rssi, scan_params->per_chain_rssi,
2115*5113495bSYour Name 		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
2116*5113495bSYour Name 
2117*5113495bSYour Name 	bss = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
2118*5113495bSYour Name 	if (!bss)
2119*5113495bSYour Name 		osif_err("failed to inform bss "QDF_MAC_ADDR_FMT" seq %d",
2120*5113495bSYour Name 			 QDF_MAC_ADDR_REF(bss_data.mgmt->bssid),
2121*5113495bSYour Name 			 scan_params->seq_num);
2122*5113495bSYour Name 	else
2123*5113495bSYour Name 		wlan_cfg80211_put_bss(wiphy, bss);
2124*5113495bSYour Name 
2125*5113495bSYour Name 	qdf_mem_free(bss_data.mgmt);
2126*5113495bSYour Name }
2127*5113495bSYour Name 
2128*5113495bSYour Name #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && \
2129*5113495bSYour Name 	!defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
wlan_cfg80211_get_bss(struct wiphy * wiphy,struct ieee80211_channel * channel,const u8 * bssid,const u8 * ssid,size_t ssid_len)2130*5113495bSYour Name struct cfg80211_bss *wlan_cfg80211_get_bss(struct wiphy *wiphy,
2131*5113495bSYour Name 					   struct ieee80211_channel *channel,
2132*5113495bSYour Name 					   const u8 *bssid, const u8 *ssid,
2133*5113495bSYour Name 					   size_t ssid_len)
2134*5113495bSYour Name {
2135*5113495bSYour Name 	return cfg80211_get_bss(wiphy, channel, bssid,
2136*5113495bSYour Name 				ssid, ssid_len,
2137*5113495bSYour Name 				WLAN_CAPABILITY_ESS,
2138*5113495bSYour Name 				WLAN_CAPABILITY_ESS);
2139*5113495bSYour Name }
2140*5113495bSYour Name #else
wlan_cfg80211_get_bss(struct wiphy * wiphy,struct ieee80211_channel * channel,const u8 * bssid,const u8 * ssid,size_t ssid_len)2141*5113495bSYour Name struct cfg80211_bss *wlan_cfg80211_get_bss(struct wiphy *wiphy,
2142*5113495bSYour Name 					   struct ieee80211_channel *channel,
2143*5113495bSYour Name 					   const u8 *bssid, const u8 *ssid,
2144*5113495bSYour Name 					   size_t ssid_len)
2145*5113495bSYour Name {
2146*5113495bSYour Name 	return cfg80211_get_bss(wiphy, channel, bssid,
2147*5113495bSYour Name 				ssid, ssid_len,
2148*5113495bSYour Name 				IEEE80211_BSS_TYPE_ESS,
2149*5113495bSYour Name 				IEEE80211_PRIVACY_ANY);
2150*5113495bSYour Name }
2151*5113495bSYour Name #endif
2152*5113495bSYour Name 
__wlan_cfg80211_unlink_bss_list(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,uint8_t * bssid,uint8_t * ssid,uint8_t ssid_len)2153*5113495bSYour Name QDF_STATUS  __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy,
2154*5113495bSYour Name 					    struct wlan_objmgr_pdev *pdev,
2155*5113495bSYour Name 					    uint8_t *bssid, uint8_t *ssid,
2156*5113495bSYour Name 					    uint8_t ssid_len)
2157*5113495bSYour Name {
2158*5113495bSYour Name 	struct cfg80211_bss *bss = NULL;
2159*5113495bSYour Name 	uint8_t vdev_id;
2160*5113495bSYour Name 
2161*5113495bSYour Name 	if (bssid && wlan_get_connected_vdev_by_bssid(pdev, bssid, &vdev_id)) {
2162*5113495bSYour Name 		osif_debug("BSS "QDF_MAC_ADDR_FMT" connected on vdev %d dont unlink",
2163*5113495bSYour Name 			   QDF_MAC_ADDR_REF(bssid), vdev_id);
2164*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2165*5113495bSYour Name 	}
2166*5113495bSYour Name 
2167*5113495bSYour Name 	bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid,
2168*5113495bSYour Name 				    ssid, ssid_len);
2169*5113495bSYour Name 	if (!bss) {
2170*5113495bSYour Name 		osif_info("BSS "QDF_MAC_ADDR_FMT" not found",
2171*5113495bSYour Name 			  QDF_MAC_ADDR_REF(bssid));
2172*5113495bSYour Name 	} else {
2173*5113495bSYour Name 		osif_debug("unlink entry for ssid:" QDF_SSID_FMT " and BSSID " QDF_MAC_ADDR_FMT,
2174*5113495bSYour Name 			   QDF_SSID_REF(ssid_len, ssid),
2175*5113495bSYour Name 			   QDF_MAC_ADDR_REF(bssid));
2176*5113495bSYour Name 		cfg80211_unlink_bss(wiphy, bss);
2177*5113495bSYour Name 		wlan_cfg80211_put_bss(wiphy, bss);
2178*5113495bSYour Name 	}
2179*5113495bSYour Name 
2180*5113495bSYour Name 	/*
2181*5113495bSYour Name 	 * Kernel creates separate entries into it's bss list for probe resp
2182*5113495bSYour Name 	 * and beacon for hidden AP. Both have separate ref count and thus
2183*5113495bSYour Name 	 * deleting one will not delete other entry.
2184*5113495bSYour Name 	 * If beacon entry of the hidden AP is not deleted and AP switch to
2185*5113495bSYour Name 	 * broadcasting SSID from Hiding SSID, kernel will reject the beacon
2186*5113495bSYour Name 	 * entry. So unlink the hidden beacon entry (if present) as well from
2187*5113495bSYour Name 	 * kernel, to avoid such issue.
2188*5113495bSYour Name 	 */
2189*5113495bSYour Name 	bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0);
2190*5113495bSYour Name 	if (!bss) {
2191*5113495bSYour Name 		osif_debug("Hidden bss not found for ssid:" QDF_SSID_FMT " BSSID: " QDF_MAC_ADDR_FMT " sid_len %d",
2192*5113495bSYour Name 			   QDF_SSID_REF(ssid_len, ssid),
2193*5113495bSYour Name 			   QDF_MAC_ADDR_REF(bssid), ssid_len);
2194*5113495bSYour Name 	} else {
2195*5113495bSYour Name 		osif_debug("unlink entry for Hidden ssid:" QDF_SSID_FMT " and BSSID " QDF_MAC_ADDR_FMT,
2196*5113495bSYour Name 			   QDF_SSID_REF(ssid_len, ssid),
2197*5113495bSYour Name 			   QDF_MAC_ADDR_REF(bssid));
2198*5113495bSYour Name 
2199*5113495bSYour Name 		cfg80211_unlink_bss(wiphy, bss);
2200*5113495bSYour Name 		/* cfg80211_get_bss get bss with ref count so release it */
2201*5113495bSYour Name 		wlan_cfg80211_put_bss(wiphy, bss);
2202*5113495bSYour Name 	}
2203*5113495bSYour Name 
2204*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2205*5113495bSYour Name }
wlan_cfg80211_unlink_bss_list(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2206*5113495bSYour Name void wlan_cfg80211_unlink_bss_list(struct wlan_objmgr_pdev *pdev,
2207*5113495bSYour Name 				   struct scan_cache_entry *scan_entry)
2208*5113495bSYour Name {
2209*5113495bSYour Name 	struct pdev_osif_priv *pdev_ospriv = wlan_pdev_get_ospriv(pdev);
2210*5113495bSYour Name 	struct wiphy *wiphy;
2211*5113495bSYour Name 
2212*5113495bSYour Name 	if (!pdev_ospriv) {
2213*5113495bSYour Name 		osif_err("os_priv is NULL");
2214*5113495bSYour Name 		return;
2215*5113495bSYour Name 	}
2216*5113495bSYour Name 
2217*5113495bSYour Name 	wiphy = pdev_ospriv->wiphy;
2218*5113495bSYour Name 
2219*5113495bSYour Name 	__wlan_cfg80211_unlink_bss_list(wiphy, pdev, scan_entry->bssid.bytes,
2220*5113495bSYour Name 					scan_entry->ssid.ssid,
2221*5113495bSYour Name 					scan_entry->ssid.length);
2222*5113495bSYour Name }
2223*5113495bSYour Name 
2224*5113495bSYour Name #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2225*5113495bSYour Name /*
2226*5113495bSYour Name  * wlan_scan_wiphy_set_max_sched_scans() - set maximum number of scheduled scans
2227*5113495bSYour Name  * to wiphy.
2228*5113495bSYour Name  * @wiphy: pointer to wiphy
2229*5113495bSYour Name  * @max_scans: max num scans to be configured
2230*5113495bSYour Name  *
2231*5113495bSYour Name  */
2232*5113495bSYour Name static inline void
wlan_scan_wiphy_set_max_sched_scans(struct wiphy * wiphy,uint8_t max_scans)2233*5113495bSYour Name wlan_scan_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
2234*5113495bSYour Name {
2235*5113495bSYour Name 	if (max_scans == 0)
2236*5113495bSYour Name 		wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
2237*5113495bSYour Name 	else
2238*5113495bSYour Name 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
2239*5113495bSYour Name }
2240*5113495bSYour Name #else
2241*5113495bSYour Name static inline void
wlan_scan_wiphy_set_max_sched_scans(struct wiphy * wiphy,uint8_t max_scans)2242*5113495bSYour Name wlan_scan_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
2243*5113495bSYour Name {
2244*5113495bSYour Name 	wiphy->max_sched_scan_reqs = max_scans;
2245*5113495bSYour Name }
2246*5113495bSYour Name #endif /* KERNEL_VERSION(4, 12, 0) */
2247*5113495bSYour Name 
2248*5113495bSYour Name #if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN) || \
2249*5113495bSYour Name 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
wlan_scan_cfg80211_add_connected_pno_support(struct wiphy * wiphy)2250*5113495bSYour Name void wlan_scan_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
2251*5113495bSYour Name {
2252*5113495bSYour Name 	wiphy_ext_feature_set(wiphy,
2253*5113495bSYour Name 			      NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
2254*5113495bSYour Name }
2255*5113495bSYour Name #endif
2256*5113495bSYour Name 
2257*5113495bSYour Name #if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
2258*5113495bSYour Name 		defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
2259*5113495bSYour Name 		defined(FEATURE_WLAN_SCAN_PNO)
wlan_config_sched_scan_plans_to_wiphy(struct wiphy * wiphy,struct wlan_objmgr_psoc * psoc)2260*5113495bSYour Name void wlan_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
2261*5113495bSYour Name 					   struct wlan_objmgr_psoc *psoc)
2262*5113495bSYour Name {
2263*5113495bSYour Name 	if (ucfg_scan_get_pno_scan_support(psoc)) {
2264*5113495bSYour Name 		wlan_scan_wiphy_set_max_sched_scans(wiphy, 1);
2265*5113495bSYour Name 		wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
2266*5113495bSYour Name 		wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
2267*5113495bSYour Name 		wiphy->max_sched_scan_ie_len = SCAN_MAX_IE_LENGTH;
2268*5113495bSYour Name 		wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
2269*5113495bSYour Name 
2270*5113495bSYour Name 		wiphy->max_sched_scan_plan_interval =
2271*5113495bSYour Name 			ucfg_scan_get_max_sched_scan_plan_interval(psoc);
2272*5113495bSYour Name 
2273*5113495bSYour Name 		wiphy->max_sched_scan_plan_iterations =
2274*5113495bSYour Name 			ucfg_scan_get_max_sched_scan_plan_iterations(psoc);
2275*5113495bSYour Name 	}
2276*5113495bSYour Name }
2277*5113495bSYour Name #endif
2278