qcacmn: scan all channels in A/G if 0 channels provided

When wide band scan is enabled, host configures all possible
channels with all possible phy modes. In his case if a scan
is invoked with 0 channels, target will end up scanning each
channel with all possible phy modes which increases scan time
exponentially.
If wide band scan is enabled and scan is issues with 0 channels,
configure target to scan all available channels only in 11A/11G mode.

Change-Id: I7c678ccf43c3238aacbfc59cc7e7bd19763453cc
CRs-Fixed: 2165025
Этот коммит содержится в:
Om Prakash Tripathi
2017-12-28 17:22:14 +05:30
коммит произвёл snandini
родитель 1b5e807809
Коммит 7dd49fec17
3 изменённых файлов: 195 добавлений и 19 удалений

Просмотреть файл

@@ -592,6 +592,64 @@ enum scan_type {
SCAN_TYPE_COUNT,
};
/**
* enum scan_phy_mode - phymode used for scan
* @SCAN_PHY_MODE_11A: 11a mode
* @SCAN_PHY_MODE_11G: 11g mode
* @SCAN_PHY_MODE_11B: 11b mode
* @SCAN_PHY_MODE_11GONLY: 11g only mode
* @SCAN_PHY_MODE_11NA_HT20: 11na ht20 mode
* @SCAN_PHY_MODE_11NG_HT20: 11ng ht20 mode
* @SCAN_PHY_MODE_11NA_HT40: 11na ht40 mode
* @SCAN_PHY_MODE_11NG_HT40: 11ng ht40 mode
* @SCAN_PHY_MODE_11AC_VHT20: 11ac vht20 mode
* @SCAN_PHY_MODE_11AC_VHT40: 11ac vht40 mode
* @SCAN_PHY_MODE_11AC_VHT80: 11ac vht80 mode
* @SCAN_PHY_MODE_11AC_VHT20_2G: 2GHz 11ac vht20 mode
* @SCAN_PHY_MODE_11AC_VHT40_2G: 2GHz 11ac vht40 mode
* @SCAN_PHY_MODE_11AC_VHT80_2G: 2GHz 11ac vht80 mode
* @SCAN_PHY_MODE_11AC_VHT80_80: 11ac vht 80+80 mode
* @SCAN_PHY_MODE_11AC_VHT160: 11ac vht160 mode
* @SCAN_PHY_MODE_11AX_HE20: 11ax he20 mode
* @SCAN_PHY_MODE_11AX_HE40: 11ax he40 mode
* @SCAN_PHY_MODE_11AX_HE80: 11ax he80 mode
* @SCAN_PHY_MODE_11AX_HE80_80: 11ax he80+80 mode
* @SCAN_PHY_MODE_11AX_HE160: 11ax he160 mode
* @SCAN_PHY_MODE_11AX_HE20_2G: 2GHz 11ax he20 mode
* @SCAN_PHY_MODE_11AX_HE40_2G: 2GHz 11ax he40 mode
* @SCAN_PHY_MODE_11AX_HE80_2G: 2GHz 11ax he80 mode
* @SCAN_PHY_MODE_UNKNOWN: unknown phy mode
* @SCAN_PHY_MODE_MAX: max valid phymode
*/
enum scan_phy_mode {
SCAN_PHY_MODE_11A = 0,
SCAN_PHY_MODE_11G = 1,
SCAN_PHY_MODE_11B = 2,
SCAN_PHY_MODE_11GONLY = 3,
SCAN_PHY_MODE_11NA_HT20 = 4,
SCAN_PHY_MODE_11NG_HT20 = 5,
SCAN_PHY_MODE_11NA_HT40 = 6,
SCAN_PHY_MODE_11NG_HT40 = 7,
SCAN_PHY_MODE_11AC_VHT20 = 8,
SCAN_PHY_MODE_11AC_VHT40 = 9,
SCAN_PHY_MODE_11AC_VHT80 = 10,
SCAN_PHY_MODE_11AC_VHT20_2G = 11,
SCAN_PHY_MODE_11AC_VHT40_2G = 12,
SCAN_PHY_MODE_11AC_VHT80_2G = 13,
SCAN_PHY_MODE_11AC_VHT80_80 = 14,
SCAN_PHY_MODE_11AC_VHT160 = 15,
SCAN_PHY_MODE_11AX_HE20 = 16,
SCAN_PHY_MODE_11AX_HE40 = 17,
SCAN_PHY_MODE_11AX_HE80 = 18,
SCAN_PHY_MODE_11AX_HE80_80 = 19,
SCAN_PHY_MODE_11AX_HE160 = 20,
SCAN_PHY_MODE_11AX_HE20_2G = 21,
SCAN_PHY_MODE_11AX_HE40_2G = 22,
SCAN_PHY_MODE_11AX_HE80_2G = 23,
SCAN_PHY_MODE_UNKNOWN = 24,
SCAN_PHY_MODE_MAX = 24
};
/**
* struct scan_extra_params_legacy
* extra parameters required for legacy DA scan module

Просмотреть файл

@@ -26,6 +26,8 @@
#include <wlan_objmgr_cmn.h>
#include <wlan_serialization_api.h>
#include <wlan_scan_tgt_api.h>
#include <wlan_scan_utils_api.h>
#include <wlan_reg_ucfg_api.h>
#include <wlan_reg_services_api.h>
#include <wlan_utility.h>
#include "../../core/src/wlan_scan_main.h"
@@ -480,6 +482,7 @@ ucfg_scan_start(struct scan_start_request *req)
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");
@@ -514,9 +517,13 @@ ucfg_scan_start(struct scan_start_request *req)
/* Overwrite scan parameters as required */
if (!ucfg_scan_get_wide_band_scan(pdev)) {
scm_debug("wide_band_scan not supported, Scan 20 MHz");
req->scan_req.scan_f_wide_band = false;
} else {
req->scan_req.scan_f_wide_band = true;
if (req->scan_req.chan_list.num_chan == 0)
ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
}
scm_debug("scan_f_wide_band: %d", req->scan_req.scan_f_wide_band);
if (scan_obj->scan_def.usr_cfg_probe_rpt_time) {
req->scan_req.repeat_probe_time =
@@ -545,6 +552,13 @@ 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_info("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;
@@ -1216,54 +1230,150 @@ ucfg_scan_init_bssid_params(struct scan_start_request *req,
return QDF_STATUS_SUCCESS;
}
/**
* is_chan_enabled_for_scan() - helper API to check if a frequency
* is allowed to scan.
* @reg_chan: regulatory_channel object
* @low_2g: lower 2.4 GHz frequency thresold
* @high_2g: upper 2.4 GHz frequency thresold
* @low_5g: lower 5 GHz frequency thresold
* @high_5g: upper 5 GHz frequency thresold
*
* Return: true if scan is allowed. false otherwise.
*/
static bool
is_chan_enabled_for_scan(struct regulatory_channel *reg_chan,
uint32_t low_2g, uint32_t high_2g, uint32_t low_5g,
uint32_t high_5g)
{
if (reg_chan->state == CHANNEL_STATE_DISABLE)
return false;
if (reg_chan->nol_chan)
return false;
/* 2 GHz channel */
if ((util_scan_scm_chan_to_band(reg_chan->chan_num) ==
WLAN_BAND_2_4_GHZ) &&
((reg_chan->center_freq < low_2g) ||
(reg_chan->center_freq > high_2g)))
return false;
else if ((reg_chan->center_freq < low_5g) ||
(reg_chan->center_freq > high_5g))
return false;
return true;
}
QDF_STATUS
ucfg_scan_init_chanlist_params(struct scan_start_request *req,
uint32_t num_chans, uint32_t *chan_list, uint32_t *phymode)
{
uint32_t idx;
QDF_STATUS status;
struct regulatory_channel *reg_chan_list = NULL;
uint32_t low_2g, high_2g, low_5g, high_5g;
struct wlan_objmgr_pdev *pdev = NULL;
uint32_t *scan_freqs = NULL;
uint32_t max_chans = sizeof(req->scan_req.chan_list.chan) /
sizeof(req->scan_req.chan_list.chan[0]);
if (!req) {
scm_err("null request");
return QDF_STATUS_E_NULL_VALUE;
}
if (req->vdev)
pdev = wlan_vdev_get_pdev(req->vdev);
/*
* If 0 channels are provided for scan and
* wide band scan is enabled, scan all 20 mhz
* available channels. This is required as FW
* scans all channel/phy mode combinations
* provided in scan channel list if 0 chans are
* provided in scan request causing scan to take
* too much time to complete.
*/
if (pdev && !num_chans && ucfg_scan_get_wide_band_scan(pdev)) {
reg_chan_list = qdf_mem_malloc(NUM_CHANNELS *
sizeof(struct regulatory_channel));
if (!reg_chan_list) {
scm_err("Couldn't allocate reg_chan_list memory");
status = QDF_STATUS_E_NOMEM;
goto end;
}
scan_freqs = qdf_mem_malloc(sizeof(uint32_t) * max_chans);
if (!scan_freqs) {
scm_err("Couldn't allocate scan_freqs memory");
status = QDF_STATUS_E_NOMEM;
goto end;
}
status = ucfg_reg_get_current_chan_list(pdev, reg_chan_list);
if (QDF_IS_STATUS_ERROR(status)) {
scm_err("Couldn't get current chan list");
goto end;
}
status = wlan_reg_get_freq_range(pdev, &low_2g,
&high_2g, &low_5g, &high_5g);
if (QDF_IS_STATUS_ERROR(status)) {
scm_err("Couldn't get frequency range");
goto end;
}
for (idx = 0, num_chans = 0;
(idx < NUM_CHANNELS && num_chans < max_chans); idx++)
if (is_chan_enabled_for_scan(&reg_chan_list[idx],
low_2g, high_2g, low_5g, high_5g))
scan_freqs[num_chans++] =
reg_chan_list[idx].center_freq;
chan_list = scan_freqs;
}
if (!num_chans) {
/* empty channel list provided */
qdf_mem_zero(&req->scan_req.chan_list,
sizeof(req->scan_req.chan_list));
req->scan_req.chan_list.num_chan = 0;
return QDF_STATUS_SUCCESS;
status = QDF_STATUS_SUCCESS;
goto end;
}
if (!chan_list) {
scm_err("null chan_list while num_chans: %d", num_chans);
return QDF_STATUS_E_NULL_VALUE;
status = QDF_STATUS_E_NULL_VALUE;
goto end;
}
if (num_chans > max_chans) {
/* got a big list. alert and continue */
/* got a big list. alert and fail */
scm_warn("overflow: received %d, max supported : %d",
num_chans, max_chans);
return QDF_STATUS_E_E2BIG;
status = QDF_STATUS_E_E2BIG;
goto end;
}
if (max_chans > num_chans)
max_chans = num_chans;
req->scan_req.chan_list.num_chan = max_chans;
for (idx = 0; idx < max_chans; idx++) {
req->scan_req.chan_list.num_chan = num_chans;
for (idx = 0; idx < num_chans; idx++) {
req->scan_req.chan_list.chan[idx].freq =
(chan_list[idx] > WLAN_24_GHZ_BASE_FREQ) ?
chan_list[idx] : wlan_chan_to_freq(chan_list[idx]);
req->scan_req.chan_list.chan[idx].phymode =
(phymode ? phymode[idx] : 0);
chan_list[idx] :
wlan_reg_chan_to_freq(pdev, chan_list[idx]);
if (phymode)
req->scan_req.chan_list.chan[idx].phymode =
phymode[idx];
else if (req->scan_req.chan_list.chan[idx].freq <=
WLAN_CHAN_15_FREQ)
req->scan_req.chan_list.chan[idx].phymode =
SCAN_PHY_MODE_11G;
else
req->scan_req.chan_list.chan[idx].phymode =
SCAN_PHY_MODE_11A;
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);
}
/* Enable wide band scan by default if phymode list is provided.
* This flag will be cleared in @ucfg_scan_start() if underlying
* phy doesn't support wide band scan.
*/
if (phymode)
req->scan_req.scan_f_wide_band = true;
end:
if (scan_freqs)
qdf_mem_free(scan_freqs);
return QDF_STATUS_SUCCESS;
}