qcacmn: Move scan req modification logic to scan core to ucfg

Move the scan req modification logic to scan core from ucfg layer.

Change-Id: I92d7bc6ed41761fd6cd4a602ab3c5852e8121dd8
CRs-Fixed: 2393496
This commit is contained in:
Abhishek Singh 2019-01-29 17:56:37 +05:30 • committed by nshrivas
commit cd0a9fdcd8
2 changed files with 532 additions and 537 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@ -26,9 +26,15 @@
#include "wlan_scan_main.h"
#include "wlan_scan_manager.h"
#include "wlan_utility.h"
#include <wlan_reg_services_api.h>
#ifdef FEATURE_WLAN_SCAN_PNO
#include <host_diag_core_event.h>
#endif
#ifdef WLAN_POLICY_MGR_ENABLE
#include <wlan_dfs_utils_api.h>
#include <wlan_policy_mgr_api.h>
#endif
QDF_STATUS
scm_scan_free_scan_request_mem(struct scan_start_request *req)
@ -405,6 +411,519 @@ bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
return true;
}
#ifdef WLAN_POLICY_MGR_ENABLE
/**
* scm_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags
* @req: pointer to scan request
*
* This function sets scan_ctrl_flags_ext value depending on the type of
* scan and the channel lists.
*
* Non-DBS scan is requested if any of the below case is met:
* 1. HW is DBS incapable
* 2. A high accuracy scan request is sent by kernel.
*
* DBS scan is enabled for these conditions:
* 1. A low power or low span scan request is sent by kernel.
* For remaining cases DBS is enabled by default.
* Return: void
*/
static void
scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
{
struct wlan_objmgr_psoc *psoc;
uint32_t scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
psoc = wlan_vdev_get_psoc(req->vdev);
if (!policy_mgr_is_hw_dbs_capable(psoc)) {
scm_debug("dbs disabled, going for non-dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
goto end;
}
if (req->scan_req.scan_policy_high_accuracy) {
scm_debug("high accuracy scan received, going for non-dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
goto end;
}
if ((req->scan_req.scan_policy_low_power) ||
(req->scan_req.scan_policy_low_span)) {
scm_debug("low power/span scan received, going for dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_IGNORE_DUTY;
goto end;
}
end:
req->scan_req.scan_ctrl_flags_ext |=
((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT)
& SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK);
scm_debug("scan_ctrl_flags_ext: 0x%x",
req->scan_req.scan_ctrl_flags_ext);
}
/**
* scm_update_passive_dwell_time() - update dwell passive time
* @vdev: vdev object
* @req: scan request
*
* Return: None
*/
static void
scm_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc)
return;
if (policy_mgr_is_sta_connected_2g(psoc) &&
!policy_mgr_is_hw_dbs_capable(psoc) &&
ucfg_scan_get_bt_activity(psoc))
req->scan_req.dwell_time_passive =
PASSIVE_DWELL_TIME_BT_A2DP_ENABLED;
}
static const struct probe_time_dwell_time
scan_probe_time_dwell_time_map[SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE] = {
{28, 11}, /* 0 SSID */
{28, 20}, /* 1 SSID */
{28, 20}, /* 2 SSID */
{28, 20}, /* 3 SSID */
{28, 20}, /* 4 SSID */
{28, 20}, /* 5 SSID */
{28, 20}, /* 6 SSID */
{28, 11}, /* 7 SSID */
{28, 11}, /* 8 SSID */
{28, 11}, /* 9 SSID */
{28, 8} /* 10 SSID */
};
/**
* scm_scan_get_burst_duration() - get burst duration depending on max chan
* and miracast.
* @max_ch_time: max channel time
* @miracast_enabled: if miracast is enabled
*
* Return: burst_duration
*/
static inline
int scm_scan_get_burst_duration(int max_ch_time, bool miracast_enabled)
{
int burst_duration = 0;
if (miracast_enabled) {
/*
* When miracast is running, burst
* duration needs to be minimum to avoid
* any stutter or glitch in miracast
* during station scan
*/
if (max_ch_time <= SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION)
burst_duration = max_ch_time;
else
burst_duration = SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION;
} else {
/*
* If miracast is not running, accommodate max
* stations to make the scans faster
*/
burst_duration = SCAN_GO_BURST_SCAN_MAX_NUM_OFFCHANNELS *
max_ch_time;
if (burst_duration > SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION) {
uint8_t channels = SCAN_P2P_SCAN_MAX_BURST_DURATION /
max_ch_time;
if (channels)
burst_duration = channels * max_ch_time;
else
burst_duration =
SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION;
}
}
return burst_duration;
}
/**
* scm_req_update_concurrency_params() - update scan req params depending on
* concurrent mode present.
* @vdev: vdev object pointer
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
bool ap_present, go_present, sta_active, p2p_cli_present, ndi_present;
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc)
return;
ap_present = policy_mgr_mode_specific_connection_count(
psoc, PM_SAP_MODE, NULL);
go_present = policy_mgr_mode_specific_connection_count(
psoc, PM_P2P_GO_MODE, NULL);
p2p_cli_present = policy_mgr_mode_specific_connection_count(
psoc, PM_P2P_CLIENT_MODE, NULL);
sta_active = policy_mgr_mode_specific_connection_count(
psoc, PM_STA_MODE, NULL);
ndi_present = policy_mgr_mode_specific_connection_count(
psoc, PM_NDI_MODE, NULL);
if (policy_mgr_get_connection_count(psoc)) {
if (req->scan_req.scan_f_passive)
req->scan_req.dwell_time_passive =
scan_obj->scan_def.conc_passive_dwell;
else
req->scan_req.dwell_time_active =
scan_obj->scan_def.conc_active_dwell;
req->scan_req.max_rest_time =
scan_obj->scan_def.conc_max_rest_time;
req->scan_req.min_rest_time =
scan_obj->scan_def.conc_min_rest_time;
req->scan_req.idle_time = scan_obj->scan_def.conc_idle_time;
}
if (wlan_vdev_is_up(req->vdev) != QDF_STATUS_SUCCESS)
req->scan_req.adaptive_dwell_time_mode =
scan_obj->scan_def.adaptive_dwell_time_mode_nc;
/*
* If AP is active set min rest time same as max rest time, so that
* firmware spends more time on home channel which will increase the
* probability of sending beacon at TBTT
*/
if (ap_present || go_present) {
req->scan_req.dwell_time_active_2g = 0;
req->scan_req.min_rest_time = req->scan_req.max_rest_time;
}
/*
* If scan req for SAP (ACS Sacn) use dwell_time_active_def as dwell
* time for 2g channels instead of dwell_time_active_2g
*/
if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE)
req->scan_req.dwell_time_active_2g = 0;
if (req->scan_req.p2p_scan_type == SCAN_NON_P2P_DEFAULT) {
/*
* Decide burst_duration and dwell_time_active based on
* what type of devices are active.
*/
do {
if (ap_present && go_present && sta_active) {
if (req->scan_req.dwell_time_active <=
SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION)
req->scan_req.burst_duration =
req->scan_req.dwell_time_active;
else
req->scan_req.burst_duration =
SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION;
break;
}
if (scan_obj->miracast_enabled &&
policy_mgr_is_mcc_in_24G(psoc))
req->scan_req.max_rest_time =
scan_obj->scan_def.sta_miracast_mcc_rest_time;
if (go_present) {
/*
* Background scan while GO is sending beacons.
* Every off-channel transition has overhead of
* 2 beacon intervals for NOA. Maximize number
* of channels in every transition by using
* burst scan.
*/
req->scan_req.burst_duration =
scm_scan_get_burst_duration(
req->scan_req.dwell_time_active,
scan_obj->miracast_enabled);
break;
}
if ((sta_active || p2p_cli_present) &&
!req->scan_req.burst_duration) {
/*
* Typical background scan.
* Disable burst scan for now.
*/
req->scan_req.burst_duration = 0;
break;
}
if (ndi_present) {
req->scan_req.burst_duration =
scm_scan_get_burst_duration(
req->scan_req.dwell_time_active,
scan_obj->miracast_enabled);
break;
}
} while (0);
if (ap_present) {
uint8_t ssid_num;
ssid_num = req->scan_req.num_ssids *
req->scan_req.num_bssid;
req->scan_req.repeat_probe_time =
scan_probe_time_dwell_time_map[
QDF_MIN(ssid_num,
SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE
- 1)].probe_time;
req->scan_req.n_probes =
(req->scan_req.repeat_probe_time > 0) ?
req->scan_req.dwell_time_active /
req->scan_req.repeat_probe_time : 0;
}
}
if (ap_present) {
uint8_t ap_chan;
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
ap_chan = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL);
/*
* P2P/STA scan while SoftAP is sending beacons.
* Max duration of CTS2self is 32 ms, which limits the
* dwell time. If DBS is supported and if SAP is on 2G channel
* then keep passive dwell time default.
*/
req->scan_req.dwell_time_active =
QDF_MIN(req->scan_req.dwell_time_active,
(SCAN_CTS_DURATION_MS_MAX -
SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME));
if (!policy_mgr_is_hw_dbs_capable(psoc) ||
(policy_mgr_is_hw_dbs_capable(psoc) &&
WLAN_CHAN_IS_5GHZ(ap_chan))) {
req->scan_req.dwell_time_passive =
req->scan_req.dwell_time_active;
}
req->scan_req.burst_duration = 0;
if (utils_is_dfs_ch(pdev, ap_chan))
req->scan_req.burst_duration =
SCAN_BURST_SCAN_MAX_NUM_OFFCHANNELS *
req->scan_req.dwell_time_active;
}
}
#else
static inline
void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
}
static inline void
scm_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req)
{
}
static inline void
scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
{
}
#endif
/**
* scm_update_channel_list() - update scan req params depending on dfs inis
* and initial scan request.
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void
scm_update_channel_list(struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
uint8_t i;
uint8_t num_scan_channels = 0;
struct scan_vdev_obj *scan_vdev_obj;
struct wlan_objmgr_pdev *pdev;
bool first_scan_done = true;
pdev = wlan_vdev_get_pdev(req->vdev);
scan_vdev_obj = wlan_get_vdev_scan_obj(req->vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return;
}
if (!scan_vdev_obj->first_scan_done) {
first_scan_done = false;
scan_vdev_obj->first_scan_done = true;
}
/*
* No need to update channels if req is passive scan and single channel
* ie ROC, Preauth etc
*/
if (req->scan_req.scan_f_passive &&
req->scan_req.chan_list.num_chan == 1)
return;
/* do this only for STA and P2P-CLI mode */
if (!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) &&
!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_P2P_CLIENT_MODE))
return;
if (scan_obj->scan_def.allow_dfs_chan_in_scan &&
(scan_obj->scan_def.allow_dfs_chan_in_first_scan ||
first_scan_done))
return;
for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
if (wlan_reg_is_dfs_ch(pdev, wlan_reg_freq_to_chan(pdev,
req->scan_req.chan_list.chan[i].freq)))
continue;
req->scan_req.chan_list.chan[num_scan_channels++] =
req->scan_req.chan_list.chan[i];
}
req->scan_req.chan_list.num_chan = num_scan_channels;
}
/**
* scm_scan_req_update_params() - update scan req params depending on modes
* and scan type.
* @vdev: vdev object pointer
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void
scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
struct chan_list *custom_chan_list;
struct wlan_objmgr_pdev *pdev;
uint8_t pdev_id;
/* Ensure correct number of probes are sent on active channel */
if (!req->scan_req.repeat_probe_time)
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / SCAN_NPROBES_DEFAULT;
if (req->scan_req.scan_f_passive)
req->scan_req.scan_ctrl_flags_ext |=
SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME;
if (!req->scan_req.n_probes)
req->scan_req.n_probes = (req->scan_req.repeat_probe_time > 0) ?
req->scan_req.dwell_time_active /
req->scan_req.repeat_probe_time : 0;
if (req->scan_req.p2p_scan_type == SCAN_NON_P2P_DEFAULT) {
req->scan_req.scan_f_cck_rates = true;
if (!req->scan_req.num_ssids)
req->scan_req.scan_f_bcast_probe = true;
req->scan_req.scan_f_add_ds_ie_in_probe = true;
req->scan_req.scan_f_filter_prb_req = true;
req->scan_req.scan_f_add_tpc_ie_in_probe = true;
} else {
req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
req->scan_req.dwell_time_active_2g = 0;
if (req->scan_req.p2p_scan_type == SCAN_P2P_LISTEN) {
req->scan_req.repeat_probe_time = 0;
} else {
req->scan_req.scan_f_filter_prb_req = true;
if (!req->scan_req.num_ssids)
req->scan_req.scan_f_bcast_probe = true;
req->scan_req.dwell_time_active +=
P2P_SEARCH_DWELL_TIME_INC;
/*
* 3 channels with default max dwell time 40 ms.
* Cap limit will be set by
* P2P_SCAN_MAX_BURST_DURATION. Burst duration
* should be such that no channel is scanned less
* than the dwell time in normal scenarios.
*/
if (req->scan_req.chan_list.num_chan ==
WLAN_P2P_SOCIAL_CHANNELS &&
!scan_obj->miracast_enabled)
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / 5;
else
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / 3;
req->scan_req.burst_duration =
BURST_SCAN_MAX_NUM_OFFCHANNELS *
req->scan_req.dwell_time_active;
if (req->scan_req.burst_duration >
P2P_SCAN_MAX_BURST_DURATION) {
uint8_t channels =
P2P_SCAN_MAX_BURST_DURATION /
req->scan_req.dwell_time_active;
if (channels)
req->scan_req.burst_duration =
channels *
req->scan_req.dwell_time_active;
else
req->scan_req.burst_duration =
P2P_SCAN_MAX_BURST_DURATION;
}
req->scan_req.scan_ev_bss_chan = false;
}
}
if (!req->scan_req.scan_f_passive)
scm_update_passive_dwell_time(vdev, req);
scm_update_dbs_scan_ctrl_ext_flag(req);
/*
* No need to update conncurrency parmas if req is passive scan on
* single channel ie ROC, Preauth etc
*/
if (!(req->scan_req.scan_f_passive &&
req->scan_req.chan_list.num_chan == 1))
scm_req_update_concurrency_params(vdev, req, scan_obj);
/*
* Set wide band flag if enabled. This will cause
* phymode TLV being sent to FW.
*/
pdev = wlan_vdev_get_pdev(vdev);
pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
if (ucfg_scan_get_wide_band_scan(pdev))
req->scan_req.scan_f_wide_band = true;
else
req->scan_req.scan_f_wide_band = false;
/*
* Overwrite scan channles with custom scan channel
* list if configured.
*/
custom_chan_list = &scan_obj->pdev_info[pdev_id].custom_chan_list;
if (custom_chan_list->num_chan)
qdf_mem_copy(&req->scan_req.chan_list, custom_chan_list,
sizeof(struct chan_list));
else if (!req->scan_req.chan_list.num_chan)
ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
scm_update_channel_list(req, scan_obj);
scm_debug("dwell time: active %d, passive %d, repeat_probe_time %d n_probes %d flags_ext %x, wide_bw_scan: %d",
req->scan_req.dwell_time_active,
req->scan_req.dwell_time_passive,
req->scan_req.repeat_probe_time, req->scan_req.n_probes,
req->scan_req.scan_ctrl_flags_ext,
req->scan_req.scan_f_wide_band);
}
QDF_STATUS
scm_scan_start_req(struct scheduler_msg *msg)
{
@ -413,6 +932,7 @@ scm_scan_start_req(struct scheduler_msg *msg)
struct scan_start_request *req = NULL;
struct wlan_scan_obj *scan_obj;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t idx;
if (!msg) {
scm_err("msg received is NULL");
@ -440,6 +960,14 @@ scm_scan_start_req(struct scheduler_msg *msg)
goto err;
}
scm_scan_req_update_params(req->vdev, req, scan_obj);
scm_info("request to scan %d channels",
req->scan_req.chan_list.num_chan);
for (idx = 0; idx < req->scan_req.chan_list.num_chan; idx++)
scm_debug("chan[%d]: freq:%d, phymode:%d", idx,
req->scan_req.chan_list.chan[idx].freq,
req->scan_req.chan_list.chan[idx].phymode);
cmd.cmd_type = WLAN_SER_CMD_SCAN;
cmd.cmd_id = req->scan_req.scan_id;
cmd.cmd_cb = (wlan_serialization_cmd_callback)

View file

@ -35,7 +35,6 @@
#include <wlan_pmo_obj_mgmt_api.h>
#endif
#ifdef WLAN_POLICY_MGR_ENABLE
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_dfs_utils_api.h>
#include <wlan_policy_mgr_api.h>
#endif
@ -401,327 +400,9 @@ wlan_pno_global_deinit(struct pno_def_config *pno_def)
#endif
#ifdef WLAN_POLICY_MGR_ENABLE
/**
* ucfg_scan_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags
* @req: pointer to scan request
*
* This function sets scan_ctrl_flags_ext value depending on the type of
* scan and the channel lists.
*
* Non-DBS scan is requested if any of the below case is met:
* 1. HW is DBS incapable
* 2. A high accuracy scan request is sent by kernel.
*
* DBS scan is enabled for these conditions:
* 1. A low power or low span scan request is sent by kernel.
* For remaining cases DBS is enabled by default.
* Return: void
*/
static void
ucfg_scan_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
{
struct wlan_objmgr_psoc *psoc;
uint32_t scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
psoc = wlan_vdev_get_psoc(req->vdev);
if (!policy_mgr_is_hw_dbs_capable(psoc)) {
scm_debug("dbs disabled, going for non-dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
goto end;
}
if (req->scan_req.scan_policy_high_accuracy) {
scm_debug("high accuracy scan received, going for non-dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
goto end;
}
if ((req->scan_req.scan_policy_low_power) ||
(req->scan_req.scan_policy_low_span)) {
scm_debug("low power/span scan received, going for dbs scan");
scan_dbs_policy = SCAN_DBS_POLICY_IGNORE_DUTY;
goto end;
}
end:
req->scan_req.scan_ctrl_flags_ext |=
((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT)
& SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK);
scm_debug("scan_ctrl_flags_ext: 0x%x",
req->scan_req.scan_ctrl_flags_ext);
}
/**
* ucfg_update_passive_dwell_time() - update dwell passive time
* @vdev: vdev object
* @req: scan request
*
* Return: None
*/
static void
ucfg_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc)
return;
if (policy_mgr_is_sta_connected_2g(psoc) &&
!policy_mgr_is_hw_dbs_capable(psoc) &&
ucfg_scan_get_bt_activity(psoc))
req->scan_req.dwell_time_passive =
PASSIVE_DWELL_TIME_BT_A2DP_ENABLED;
}
static const struct probe_time_dwell_time
scan_probe_time_dwell_time_map[SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE] = {
{28, 11}, /* 0 SSID */
{28, 20}, /* 1 SSID */
{28, 20}, /* 2 SSID */
{28, 20}, /* 3 SSID */
{28, 20}, /* 4 SSID */
{28, 20}, /* 5 SSID */
{28, 20}, /* 6 SSID */
{28, 11}, /* 7 SSID */
{28, 11}, /* 8 SSID */
{28, 11}, /* 9 SSID */
{28, 8} /* 10 SSID */
};
/**
* ucfg_scan_get_burst_duration() - get burst duration depending on max chan
* and miracast.
* @max_ch_time: max channel time
* @miracast_enabled: if miracast is enabled
*
* Return: burst_duration
*/
static inline
int ucfg_scan_get_burst_duration(int max_ch_time,
bool miracast_enabled)
{
int burst_duration = 0;
if (miracast_enabled) {
/*
* When miracast is running, burst
* duration needs to be minimum to avoid
* any stutter or glitch in miracast
* during station scan
*/
if (max_ch_time <= SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION)
burst_duration = max_ch_time;
else
burst_duration = SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION;
} else {
/*
* If miracast is not running, accommodate max
* stations to make the scans faster
*/
burst_duration = SCAN_GO_BURST_SCAN_MAX_NUM_OFFCHANNELS *
max_ch_time;
if (burst_duration > SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION) {
uint8_t channels = SCAN_P2P_SCAN_MAX_BURST_DURATION /
max_ch_time;
if (channels)
burst_duration = channels * max_ch_time;
else
burst_duration =
SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION;
}
}
return burst_duration;
}
/**
* ucfg_scan_req_update_params() - update scan req params depending on
* concurrent mode present.
* @vdev: vdev object pointer
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void ucfg_scan_req_update_concurrency_params(
struct wlan_objmgr_vdev *vdev, struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
bool ap_present, go_present, sta_active, p2p_cli_present, ndi_present;
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc)
return;
ap_present = policy_mgr_mode_specific_connection_count(
psoc, PM_SAP_MODE, NULL);
go_present = policy_mgr_mode_specific_connection_count(
psoc, PM_P2P_GO_MODE, NULL);
p2p_cli_present = policy_mgr_mode_specific_connection_count(
psoc, PM_P2P_CLIENT_MODE, NULL);
sta_active = policy_mgr_mode_specific_connection_count(
psoc, PM_STA_MODE, NULL);
ndi_present = policy_mgr_mode_specific_connection_count(
psoc, PM_NDI_MODE, NULL);
if (policy_mgr_get_connection_count(psoc)) {
if (req->scan_req.scan_f_passive)
req->scan_req.dwell_time_passive =
scan_obj->scan_def.conc_passive_dwell;
else
req->scan_req.dwell_time_active =
scan_obj->scan_def.conc_active_dwell;
req->scan_req.max_rest_time =
scan_obj->scan_def.conc_max_rest_time;
req->scan_req.min_rest_time =
scan_obj->scan_def.conc_min_rest_time;
req->scan_req.idle_time = scan_obj->scan_def.conc_idle_time;
}
if (wlan_vdev_is_up(req->vdev) != QDF_STATUS_SUCCESS)
req->scan_req.adaptive_dwell_time_mode =
scan_obj->scan_def.adaptive_dwell_time_mode_nc;
/*
* If AP is active set min rest time same as max rest time, so that
* firmware spends more time on home channel which will increase the
* probability of sending beacon at TBTT
*/
if (ap_present || go_present) {
req->scan_req.dwell_time_active_2g = 0;
req->scan_req.min_rest_time = req->scan_req.max_rest_time;
}
/*
* If scan req for SAP (ACS Sacn) use dwell_time_active_def as dwell
* time for 2g channels instead of dwell_time_active_2g
*/
if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) {
req->scan_req.dwell_time_active_2g = 0;
}
if (req->scan_req.p2p_scan_type == SCAN_NON_P2P_DEFAULT) {
/*
* Decide burst_duration and dwell_time_active based on
* what type of devices are active.
*/
do {
if (ap_present && go_present && sta_active) {
if (req->scan_req.dwell_time_active <=
SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION)
req->scan_req.burst_duration =
req->scan_req.dwell_time_active;
else
req->scan_req.burst_duration =
SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION;
break;
}
if (scan_obj->miracast_enabled &&
policy_mgr_is_mcc_in_24G(psoc))
req->scan_req.max_rest_time =
scan_obj->scan_def.sta_miracast_mcc_rest_time;
if (go_present) {
/*
* Background scan while GO is sending beacons.
* Every off-channel transition has overhead of
* 2 beacon intervals for NOA. Maximize number
* of channels in every transition by using
* burst scan.
*/
req->scan_req.burst_duration =
ucfg_scan_get_burst_duration(
req->scan_req.dwell_time_active,
scan_obj->miracast_enabled);
break;
}
if ((sta_active || p2p_cli_present) &&
!req->scan_req.burst_duration) {
/* Typical background scan.
* Disable burst scan for now.
*/
req->scan_req.burst_duration = 0;
break;
}
if (ndi_present) {
req->scan_req.burst_duration =
ucfg_scan_get_burst_duration(
req->scan_req.dwell_time_active,
scan_obj->miracast_enabled);
break;
}
} while (0);
if (ap_present) {
uint8_t ssid_num;
ssid_num = req->scan_req.num_ssids *
req->scan_req.num_bssid;
req->scan_req.repeat_probe_time =
scan_probe_time_dwell_time_map[
QDF_MIN(ssid_num,
SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE
- 1)].probe_time;
req->scan_req.n_probes =
(req->scan_req.repeat_probe_time > 0) ?
req->scan_req.dwell_time_active /
req->scan_req.repeat_probe_time : 0;
}
}
if (ap_present) {
uint8_t ap_chan;
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
ap_chan = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL);
/*
* P2P/STA scan while SoftAP is sending beacons.
* Max duration of CTS2self is 32 ms, which limits the
* dwell time. If DBS is supported and if SAP is on 2G channel
* then keep passive dwell time default.
*/
req->scan_req.dwell_time_active =
QDF_MIN(req->scan_req.dwell_time_active,
(SCAN_CTS_DURATION_MS_MAX -
SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME));
if (!policy_mgr_is_hw_dbs_capable(psoc) ||
(policy_mgr_is_hw_dbs_capable(psoc) &&
WLAN_CHAN_IS_5GHZ(ap_chan))) {
req->scan_req.dwell_time_passive =
req->scan_req.dwell_time_active;
}
req->scan_req.burst_duration = 0;
if (utils_is_dfs_ch(pdev, ap_chan))
req->scan_req.burst_duration =
SCAN_BURST_SCAN_MAX_NUM_OFFCHANNELS *
req->scan_req.dwell_time_active;
}
}
#else
static inline void ucfg_scan_req_update_concurrency_params(
struct wlan_objmgr_vdev *vdev, struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
}
static inline void
ucfg_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req) {}
static inline void
ucfg_scan_update_dbs_scan_ctrl_ext_flag(
struct scan_start_request *req) {}
#endif
QDF_STATUS
ucfg_scan_set_custom_scan_chan_list(struct wlan_objmgr_pdev *pdev,
struct chan_list *chan_list)
struct chan_list *chan_list)
{
uint8_t pdev_id;
struct wlan_scan_obj *scan_obj;
@ -739,202 +420,11 @@ ucfg_scan_set_custom_scan_chan_list(struct wlan_objmgr_pdev *pdev,
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_update_channel_list() - update scan req params depending on dfs inis
* and initial scan request.
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void
ucfg_update_channel_list(struct scan_start_request *req,
struct wlan_scan_obj *scan_obj)
{
uint8_t i;
uint8_t num_scan_channels = 0;
struct scan_vdev_obj *scan_vdev_obj;
struct wlan_objmgr_pdev *pdev;
bool first_scan_done = true;
pdev = wlan_vdev_get_pdev(req->vdev);
scan_vdev_obj = wlan_get_vdev_scan_obj(req->vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return;
}
if (!scan_vdev_obj->first_scan_done) {
first_scan_done = false;
scan_vdev_obj->first_scan_done = true;
}
/*
* No need to update channels if req is passive scan and single channel
* ie ROC, Preauth etc
*/
if (req->scan_req.scan_f_passive &&
req->scan_req.chan_list.num_chan == 1)
return;
/* do this only for STA and P2P-CLI mode */
if (!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) &&
!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_P2P_CLIENT_MODE))
return;
if (scan_obj->scan_def.allow_dfs_chan_in_scan &&
(scan_obj->scan_def.allow_dfs_chan_in_first_scan ||
first_scan_done))
return;
for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
if (wlan_reg_is_dfs_ch(pdev, wlan_reg_freq_to_chan(pdev,
req->scan_req.chan_list.
chan[i].freq)))
continue;
req->scan_req.chan_list.chan[num_scan_channels++] =
req->scan_req.chan_list.chan[i];
}
req->scan_req.chan_list.num_chan = num_scan_channels;
}
/**
* ucfg_scan_req_update_params() - update scan req params depending on modes
* and scan type.
* @vdev: vdev object pointer
* @req: scan request
* @scan_obj: scan object
*
* Return: void
*/
static void
ucfg_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
struct scan_start_request *req, struct wlan_scan_obj *scan_obj)
{
struct chan_list *custom_chan_list;
struct wlan_objmgr_pdev *pdev;
uint8_t pdev_id;
/* Ensure correct number of probes are sent on active channel */
if (!req->scan_req.repeat_probe_time)
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / SCAN_NPROBES_DEFAULT;
if (req->scan_req.scan_f_passive)
req->scan_req.scan_ctrl_flags_ext |=
SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME;
if (!req->scan_req.n_probes)
req->scan_req.n_probes = (req->scan_req.repeat_probe_time > 0) ?
req->scan_req.dwell_time_active /
req->scan_req.repeat_probe_time : 0;
if (req->scan_req.p2p_scan_type == SCAN_NON_P2P_DEFAULT) {
req->scan_req.scan_f_cck_rates = true;
if (!req->scan_req.num_ssids)
req->scan_req.scan_f_bcast_probe = true;
req->scan_req.scan_f_add_ds_ie_in_probe = true;
req->scan_req.scan_f_filter_prb_req = true;
req->scan_req.scan_f_add_tpc_ie_in_probe = true;
} else {
req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
req->scan_req.dwell_time_active_2g = 0;
if (req->scan_req.p2p_scan_type == SCAN_P2P_LISTEN) {
req->scan_req.repeat_probe_time = 0;
} else {
req->scan_req.scan_f_filter_prb_req = true;
if (!req->scan_req.num_ssids)
req->scan_req.scan_f_bcast_probe = true;
req->scan_req.dwell_time_active +=
P2P_SEARCH_DWELL_TIME_INC;
/*
* 3 channels with default max dwell time 40 ms.
* Cap limit will be set by
* P2P_SCAN_MAX_BURST_DURATION. Burst duration
* should be such that no channel is scanned less
* than the dwell time in normal scenarios.
*/
if (req->scan_req.chan_list.num_chan ==
WLAN_P2P_SOCIAL_CHANNELS &&
!scan_obj->miracast_enabled)
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / 5;
else
req->scan_req.repeat_probe_time =
req->scan_req.dwell_time_active / 3;
req->scan_req.burst_duration =
BURST_SCAN_MAX_NUM_OFFCHANNELS *
req->scan_req.dwell_time_active;
if (req->scan_req.burst_duration >
P2P_SCAN_MAX_BURST_DURATION) {
uint8_t channels =
P2P_SCAN_MAX_BURST_DURATION /
req->scan_req.dwell_time_active;
if (channels)
req->scan_req.burst_duration =
channels *
req->scan_req.dwell_time_active;
else
req->scan_req.burst_duration =
P2P_SCAN_MAX_BURST_DURATION;
}
req->scan_req.scan_ev_bss_chan = false;
}
}
if (!req->scan_req.scan_f_passive)
ucfg_update_passive_dwell_time(vdev, req);
ucfg_scan_update_dbs_scan_ctrl_ext_flag(req);
/*
* No need to update conncurrency parmas if req is passive scan on
* single channel ie ROC, Preauth etc
*/
if (!(req->scan_req.scan_f_passive &&
req->scan_req.chan_list.num_chan == 1))
ucfg_scan_req_update_concurrency_params(vdev, req, scan_obj);
/* Set wide band flag if enabled. This will cause
* phymode TLV being sent to FW.
*/
pdev = wlan_vdev_get_pdev(vdev);
pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
if (ucfg_scan_get_wide_band_scan(pdev))
req->scan_req.scan_f_wide_band = true;
else
req->scan_req.scan_f_wide_band = false;
/* Overwrite scan channles with custom scan channel
* list if configured.
*/
custom_chan_list = &scan_obj->pdev_info[pdev_id].custom_chan_list;
if (custom_chan_list->num_chan)
qdf_mem_copy(&req->scan_req.chan_list, custom_chan_list,
sizeof(struct chan_list));
else if (!req->scan_req.chan_list.num_chan)
ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
ucfg_update_channel_list(req, scan_obj);
scm_debug("dwell time: active %d, passive %d, repeat_probe_time %d "
"n_probes %d flags_ext %x, wide_bw_scan: %d",
req->scan_req.dwell_time_active,
req->scan_req.dwell_time_passive,
req->scan_req.repeat_probe_time, req->scan_req.n_probes,
req->scan_req.scan_ctrl_flags_ext,
req->scan_req.scan_f_wide_band);
}
QDF_STATUS
ucfg_scan_start(struct scan_start_request *req)
{
struct scheduler_msg msg = {0};
QDF_STATUS status;
struct wlan_scan_obj *scan_obj;
struct wlan_objmgr_pdev *pdev;
uint8_t idx;
if (!req || !req->vdev) {
scm_err("req or vdev within req is NULL");
@ -943,31 +433,15 @@ ucfg_scan_start(struct scan_start_request *req)
return QDF_STATUS_E_NULL_VALUE;
}
pdev = wlan_vdev_get_pdev(req->vdev);
if (!pdev) {
scm_err("Failed to get pdev object");
scm_scan_free_scan_request_mem(req);
return QDF_STATUS_E_NULL_VALUE;
}
if (!scm_is_scan_allowed(req->vdev)) {
scm_err("scan disabled, rejecting the scan req");
scm_scan_free_scan_request_mem(req);
return QDF_STATUS_E_AGAIN;
}
scan_obj = wlan_pdev_get_scan_obj(pdev);
if (!scan_obj) {
scm_err("Failed to get scan object");
scm_scan_free_scan_request_mem(req);
return QDF_STATUS_E_NULL_VALUE;
}
scm_debug("reqid: %d, scanid: %d, vdevid: %d",
req->scan_req.scan_req_id, req->scan_req.scan_id,
req->scan_req.vdev_id);
ucfg_scan_req_update_params(req->vdev, req, scan_obj);
req->scan_req.scan_req_id, req->scan_req.scan_id,
req->scan_req.vdev_id);
/* Try to get vdev reference. Return if reference could
* not be taken. Reference will be released once scan
@ -980,13 +454,6 @@ ucfg_scan_start(struct scan_start_request *req)
return status;
}
scm_info("request to scan %d channels",
req->scan_req.chan_list.num_chan);
for (idx = 0; idx < req->scan_req.chan_list.num_chan; idx++)
scm_debug("chan[%d]: freq:%d, phymode:%d", idx,
req->scan_req.chan_list.chan[idx].freq,
req->scan_req.chan_list.chan[idx].phymode);
msg.bodyptr = req;
msg.callback = scm_scan_start_req;
msg.flush_callback = scm_scan_start_flush_callback;