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