qcacmn: Support 11d for non-offload platform
Support 11d for non-offload platform by maintaining count of beacons encountered for each country code and choosing country code with max votes as device's country code. Change-Id: I83b66e980854eded17e254386561fa32b1f8c4ac CRs-Fixed: 2154048
This commit is contained in:

committad av
snandini

förälder
e6d32a9f38
incheckning
ca6152167b
@@ -95,6 +95,11 @@ typedef struct qdf_sglist {
|
||||
*/
|
||||
#define qdf_packed __qdf_packed
|
||||
|
||||
/**
|
||||
* qdf_toupper - char lower to upper.
|
||||
*/
|
||||
#define qdf_toupper __qdf_toupper
|
||||
|
||||
typedef void *qdf_net_handle_t;
|
||||
|
||||
typedef void *qdf_netlink_handle_t;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/string.h>
|
||||
@@ -255,6 +256,7 @@ enum __qdf_net_wireless_evcode {
|
||||
#define __qdf_vprint vprintk
|
||||
#define __qdf_snprint snprintf
|
||||
#define __qdf_vsnprint vsnprintf
|
||||
#define __qdf_toupper toupper
|
||||
|
||||
#define __QDF_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL
|
||||
#define __QDF_DMA_TO_DEVICE DMA_TO_DEVICE
|
||||
|
@@ -843,7 +843,8 @@ QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev,
|
||||
reg_channels = pdev_priv_obj->cur_chan_list;
|
||||
|
||||
for (i = 0, count = 0; i < NUM_CHANNELS; i++) {
|
||||
if (reg_channels[i].state) {
|
||||
if (reg_channels[i].state &&
|
||||
reg_channels[i].state != REGULATORY_CHAN_DISABLED) {
|
||||
ch_list[count].chan_num =
|
||||
reg_channels[i].chan_num;
|
||||
ch_list[count++].tx_power =
|
||||
@@ -1376,6 +1377,22 @@ QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bool reg_is_world_alpha2(uint8_t *alpha2)
|
||||
{
|
||||
if ((alpha2[0] == '0') && (alpha2[1] == '0'))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool reg_is_us_alpha2(uint8_t *alpha2)
|
||||
{
|
||||
if ((alpha2[0] == 'U') && (alpha2[1] == 'S'))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *country)
|
||||
{
|
||||
@@ -1430,6 +1447,55 @@ QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS reg_set_11d_country(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *country)
|
||||
{
|
||||
struct wlan_regulatory_psoc_priv_obj *psoc_reg;
|
||||
struct set_country country_code;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct cc_regdmn_s rd;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!country) {
|
||||
reg_err("country code is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
psoc = wlan_pdev_get_psoc(pdev);
|
||||
psoc_reg = reg_get_psoc_obj(psoc);
|
||||
if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
|
||||
reg_err("psoc reg component is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (!qdf_mem_cmp(psoc_reg->cur_country,
|
||||
country, REG_ALPHA2_LEN)) {
|
||||
reg_debug("country is not different");
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
reg_info("programming new 11d country:%c%c to firmware",
|
||||
country[0], country[1]);
|
||||
|
||||
qdf_mem_copy(country_code.country,
|
||||
country, REG_ALPHA2_LEN + 1);
|
||||
country_code.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
|
||||
|
||||
psoc_reg->new_11d_ctry_pending = true;
|
||||
|
||||
if (psoc_reg->offload_enabled) {
|
||||
reg_err("reg offload, 11d offload too!");
|
||||
status = QDF_STATUS_E_FAULT;
|
||||
} else {
|
||||
qdf_mem_copy(rd.cc.alpha, country, REG_ALPHA2_LEN + 1);
|
||||
rd.flags = ALPHA_IS_SET;
|
||||
reg_program_chan_list(pdev, &rd);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS reg_reset_country(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct wlan_regulatory_psoc_priv_obj *psoc_reg;
|
||||
@@ -1864,9 +1930,16 @@ static void reg_populate_band_channels(enum channel_enum start_chan,
|
||||
|
||||
if (found_rule_ptr) {
|
||||
mas_chan_list[chan_enum].max_bw = bw;
|
||||
|
||||
reg_fill_channel_info(chan_enum, found_rule_ptr,
|
||||
mas_chan_list, min_bw);
|
||||
/* Disable 2.4 Ghz channels that dont have 20 mhz bw */
|
||||
if (start_chan == MIN_24GHZ_CHANNEL &&
|
||||
20 > mas_chan_list[chan_enum].max_bw) {
|
||||
mas_chan_list[chan_enum].chan_flags |=
|
||||
REGULATORY_CHAN_DISABLED;
|
||||
mas_chan_list[chan_enum].state =
|
||||
REGULATORY_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3967,6 +4040,23 @@ QDF_STATUS reg_save_new_11d_country(struct wlan_objmgr_psoc *psoc,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bool reg_11d_original_enabled_on_host(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
|
||||
|
||||
psoc_priv_obj =
|
||||
wlan_objmgr_psoc_get_comp_private_obj(psoc,
|
||||
WLAN_UMAC_COMP_REGULATORY);
|
||||
|
||||
if (NULL == psoc_priv_obj) {
|
||||
reg_err("reg psoc private obj is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return (psoc_priv_obj->enable_11d_supp_original &&
|
||||
!psoc_priv_obj->is_11d_offloaded);
|
||||
}
|
||||
|
||||
bool reg_11d_enabled_on_host(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
|
||||
|
@@ -164,6 +164,22 @@ QDF_STATUS reg_read_current_country(struct wlan_objmgr_psoc *psoc,
|
||||
QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t *country);
|
||||
|
||||
/**
|
||||
* reg_is_world_alpha2 - is reg world mode
|
||||
* @alpha2: country code pointer
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
bool reg_is_world_alpha2(uint8_t *alpha2);
|
||||
|
||||
/**
|
||||
* reg_is_us_alpha2 - is US country code
|
||||
* @alpha2: country code pointer
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
bool reg_is_us_alpha2(uint8_t *alpha2);
|
||||
|
||||
/**
|
||||
* reg_set_country() - Set the current regulatory country
|
||||
* @pdev: pdev device for country information
|
||||
@@ -173,6 +189,15 @@ QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc,
|
||||
*/
|
||||
QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country);
|
||||
|
||||
/**
|
||||
* reg_set_11d_country() - Set the 11d regulatory country
|
||||
* @pdev: pdev device for country information
|
||||
* @country: country value
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS reg_set_11d_country(struct wlan_objmgr_pdev *pdev, uint8_t *country);
|
||||
|
||||
/**
|
||||
* reg_reset_country() - Reset the regulatory country to default
|
||||
* @psoc: The physical SoC to reset country for
|
||||
@@ -336,6 +361,14 @@ enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
|
||||
QDF_STATUS reg_save_new_11d_country(struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t *country);
|
||||
|
||||
/**
|
||||
* reg_11d_original_enabled_on_host() - whether 11d original enabled on host
|
||||
* @psoc: psoc ptr
|
||||
*
|
||||
* Return: bool
|
||||
*/
|
||||
bool reg_11d_original_enabled_on_host(struct wlan_objmgr_psoc *psoc);
|
||||
|
||||
/**
|
||||
* reg_11d_enabled_on_host() - know whether 11d enabled on host
|
||||
* @psoc: psoc ptr
|
||||
|
@@ -372,6 +372,21 @@ uint32_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev,
|
||||
*/
|
||||
uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev,
|
||||
uint32_t chan);
|
||||
/**
|
||||
* wlan_reg_is_world() - reg is world mode
|
||||
* @country: The country information
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
bool wlan_reg_is_world(uint8_t *country);
|
||||
|
||||
/**
|
||||
* wlan_reg_is_us() - reg is us country
|
||||
* @country: The country information
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
bool wlan_reg_is_us(uint8_t *country);
|
||||
|
||||
/**
|
||||
* wlan_reg_set_country() - Set the current regulatory country
|
||||
@@ -381,7 +396,17 @@ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev,
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *country);
|
||||
uint8_t *country);
|
||||
|
||||
/**
|
||||
* wlan_reg_set_11d_country() - Set the 11d regulatory country
|
||||
* @pdev: The physical dev to set current country for
|
||||
* @country: The country information to configure
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS wlan_reg_set_11d_country(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *country);
|
||||
|
||||
/**
|
||||
* wlan_reg_register_chan_change_callback () - add chan change cbk
|
||||
@@ -404,6 +429,15 @@ void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc,
|
||||
*/
|
||||
void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc,
|
||||
reg_chan_change_callback cbk);
|
||||
|
||||
/**
|
||||
* wlan_reg_11d_original_enabled_on_host() - 11d original enabled don host
|
||||
* @psoc: psoc ptr
|
||||
*
|
||||
* Return: bool
|
||||
*/
|
||||
bool wlan_reg_11d_original_enabled_on_host(struct wlan_objmgr_psoc *psoc);
|
||||
|
||||
/**
|
||||
* wlan_reg_11d_enabled_on_host() - 11d enabled don host
|
||||
* @psoc: psoc ptr
|
||||
|
@@ -451,6 +451,22 @@ QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev,
|
||||
return reg_set_country(pdev, country);
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_reg_set_11d_country(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *country)
|
||||
{
|
||||
return reg_set_11d_country(pdev, country);
|
||||
}
|
||||
|
||||
bool wlan_reg_is_world(uint8_t *country)
|
||||
{
|
||||
return reg_is_world_alpha2(country);
|
||||
}
|
||||
|
||||
bool wlan_reg_is_us(uint8_t *country)
|
||||
{
|
||||
return reg_is_us_alpha2(country);
|
||||
}
|
||||
|
||||
void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc,
|
||||
reg_chan_change_callback cbk,
|
||||
void *arg)
|
||||
@@ -465,6 +481,11 @@ void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc,
|
||||
reg_unregister_chan_change_callback(psoc, cbk);
|
||||
}
|
||||
|
||||
bool wlan_reg_11d_original_enabled_on_host(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
return reg_11d_original_enabled_on_host(psoc);
|
||||
}
|
||||
|
||||
bool wlan_reg_11d_enabled_on_host(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
return reg_11d_enabled_on_host(psoc);
|
||||
|
354
umac/scan/core/src/wlan_scan_11d.c
Normal file
354
umac/scan/core/src/wlan_scan_11d.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2018 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
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DOC: contains scan 11d api and functionality
|
||||
*/
|
||||
#include <qdf_status.h>
|
||||
#include <wlan_objmgr_psoc_obj.h>
|
||||
#include <wlan_objmgr_pdev_obj.h>
|
||||
#include <wlan_objmgr_vdev_obj.h>
|
||||
#include <wlan_scan_public_structs.h>
|
||||
#include <wlan_scan_utils_api.h>
|
||||
#include "wlan_scan_main.h"
|
||||
#include "wlan_scan_11d.h"
|
||||
#include "wlan_reg_services_api.h"
|
||||
#include "wlan_reg_ucfg_api.h"
|
||||
|
||||
/**
|
||||
* wlan_pdevid_get_cc_db() - private API to get cc db from pdev id
|
||||
* @psoc: psoc object
|
||||
* @pdev_id: pdev id
|
||||
*
|
||||
* Return: cc db for the pdev id
|
||||
*/
|
||||
static struct scan_country_code_db *
|
||||
wlan_pdevid_get_cc_db(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id)
|
||||
{
|
||||
struct wlan_scan_obj *scan_obj;
|
||||
|
||||
if (pdev_id > WLAN_UMAC_MAX_PDEVS) {
|
||||
scm_err("invalid pdev_id %d", pdev_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scan_obj = wlan_psoc_get_scan_obj(psoc);
|
||||
if (!scan_obj)
|
||||
return NULL;
|
||||
|
||||
return &scan_obj->cc_db[pdev_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_pdev_get_cc_db() - private API to get cc db from pdev
|
||||
* @psoc: psoc object
|
||||
* @pdev: Pdev object
|
||||
*
|
||||
* Return: cc db for the pdev
|
||||
*/
|
||||
static struct scan_country_code_db *
|
||||
wlan_pdev_get_cc_db(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_pdev *pdev)
|
||||
{
|
||||
uint8_t pdev_id;
|
||||
|
||||
if (!pdev) {
|
||||
scm_err("pdev is NULL");
|
||||
return NULL;
|
||||
}
|
||||
pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
|
||||
|
||||
return wlan_pdevid_get_cc_db(psoc, pdev_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* scm_11d_elected_country_algo_fcc - private api to get cc per fcc algo
|
||||
* @cc_db: scan country code db
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
static bool
|
||||
scm_11d_elected_country_algo_fcc(struct scan_country_code_db *cc_db)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t country_idx;
|
||||
uint16_t max_votes;
|
||||
bool found = false;
|
||||
|
||||
if (!cc_db->num_country_codes) {
|
||||
scm_err("No AP with 11d Country code is present in scan list");
|
||||
return false;
|
||||
}
|
||||
|
||||
max_votes = cc_db->votes[0].votes;
|
||||
if (wlan_reg_is_us(cc_db->votes[0].cc)) {
|
||||
found = true;
|
||||
country_idx = 0;
|
||||
goto algo_done;
|
||||
} else if (max_votes >= MIN_11D_AP_COUNT) {
|
||||
found = true;
|
||||
country_idx = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < cc_db->num_country_codes; i++) {
|
||||
if (wlan_reg_is_us(cc_db->votes[i].cc)) {
|
||||
found = true;
|
||||
country_idx = i;
|
||||
goto algo_done;
|
||||
}
|
||||
|
||||
if ((max_votes < cc_db->votes[i].votes) &&
|
||||
(cc_db->votes[i].votes >= MIN_11D_AP_COUNT)) {
|
||||
scm_debug("Votes for Country %c%c : %d",
|
||||
cc_db->votes[i].cc[0],
|
||||
cc_db->votes[i].cc[1],
|
||||
cc_db->votes[i].votes);
|
||||
max_votes = cc_db->votes[i].votes;
|
||||
country_idx = i;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
algo_done:
|
||||
if (found) {
|
||||
qdf_mem_copy(cc_db->elected_cc,
|
||||
cc_db->votes[country_idx].cc,
|
||||
REG_ALPHA2_LEN + 1);
|
||||
|
||||
scm_debug("Selected Country is %c%c With count %d",
|
||||
cc_db->votes[country_idx].cc[0],
|
||||
cc_db->votes[country_idx].cc[1],
|
||||
cc_db->votes[country_idx].votes);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* scm_11d_elected_country_info - private api to get cc
|
||||
* @cc_db: scan country code db
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
static bool
|
||||
scm_11d_elected_country_info(struct scan_country_code_db *cc_db)
|
||||
{
|
||||
uint8_t i, j = 0;
|
||||
uint8_t max_votes;
|
||||
|
||||
if (!cc_db->num_country_codes) {
|
||||
scm_err("No AP with 11d Country code is present in scan list");
|
||||
return false;
|
||||
}
|
||||
|
||||
max_votes = cc_db->votes[0].votes;
|
||||
|
||||
for (i = 1; i < cc_db->num_country_codes; i++) {
|
||||
/*
|
||||
* If we have a tie for max votes for 2 different country codes,
|
||||
* pick random.
|
||||
*/
|
||||
if (max_votes < cc_db->votes[i].votes) {
|
||||
scm_debug("Votes for Country %c%c : %d",
|
||||
cc_db->votes[i].cc[0],
|
||||
cc_db->votes[i].cc[1],
|
||||
cc_db->votes[i].votes);
|
||||
|
||||
max_votes = cc_db->votes[i].votes;
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
|
||||
qdf_mem_copy(cc_db->elected_cc, cc_db->votes[j].cc,
|
||||
REG_ALPHA2_LEN + 1);
|
||||
|
||||
scm_debug("Selected Country is %c%c With count %d",
|
||||
cc_db->votes[j].cc[0],
|
||||
cc_db->votes[j].cc[1],
|
||||
cc_db->votes[j].votes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* scm_11d_set_country_code - private api to set cc per 11d learning
|
||||
* @pdev: pdev object
|
||||
* @elected_cc: elected country code
|
||||
* @current_cc: current country code
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
static bool
|
||||
scm_11d_set_country_code(struct wlan_objmgr_pdev *pdev,
|
||||
uint8_t *elected_cc, uint8_t *current_cc)
|
||||
{
|
||||
scm_debug("elected country %c%c, current country %c%c",
|
||||
elected_cc[0], elected_cc[1], current_cc[0], current_cc[1]);
|
||||
|
||||
if (!qdf_mem_cmp(elected_cc, current_cc, REG_ALPHA2_LEN + 1))
|
||||
return true;
|
||||
|
||||
wlan_reg_set_11d_country(pdev, elected_cc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* scm_11d_reset_cc_db - reset the country code db
|
||||
* @cc_db: the pointer of country code db
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void scm_11d_reset_cc_db(struct scan_country_code_db *cc_db)
|
||||
{
|
||||
qdf_mem_zero(cc_db->votes, sizeof(cc_db->votes));
|
||||
qdf_mem_zero(cc_db->elected_cc, sizeof(cc_db->elected_cc));
|
||||
cc_db->num_country_codes = 0;
|
||||
}
|
||||
|
||||
QDF_STATUS scm_11d_cc_db_init(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct scan_country_code_db *cc_db;
|
||||
struct wlan_scan_obj *scan_obj;
|
||||
|
||||
if (!psoc) {
|
||||
scm_err("psoc is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
scan_obj = wlan_psoc_get_scan_obj(psoc);
|
||||
if (!scan_obj) {
|
||||
scm_err("scan_obj is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
cc_db = (struct scan_country_code_db *)qdf_mem_malloc(
|
||||
sizeof(struct scan_country_code_db) * WLAN_UMAC_MAX_PDEVS);
|
||||
if (!cc_db) {
|
||||
scm_err("alloc country code db error");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
qdf_mem_zero(cc_db,
|
||||
sizeof(struct scan_country_code_db) *
|
||||
WLAN_UMAC_MAX_PDEVS);
|
||||
|
||||
scan_obj->cc_db = cc_db;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS scm_11d_cc_db_deinit(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct wlan_scan_obj *scan_obj;
|
||||
|
||||
if (!psoc) {
|
||||
scm_err("psoc is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
scan_obj = wlan_psoc_get_scan_obj(psoc);
|
||||
if (!scan_obj) {
|
||||
scm_err("scan_obj is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
qdf_mem_free(scan_obj->cc_db);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void scm_11d_handle_country_info(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_pdev *pdev,
|
||||
struct scan_cache_entry *scan_entry)
|
||||
{
|
||||
uint8_t i;
|
||||
bool match = false;
|
||||
uint8_t num_country_codes;
|
||||
struct scan_country_code_db *cc_db;
|
||||
struct wlan_country_ie *cc_ie;
|
||||
|
||||
cc_ie = util_scan_entry_country(scan_entry);
|
||||
if (!cc_ie)
|
||||
return;
|
||||
|
||||
cc_db = wlan_pdev_get_cc_db(psoc, pdev);
|
||||
if (!cc_db)
|
||||
return;
|
||||
|
||||
/* just to be sure, convert to UPPER case here */
|
||||
for (i = 0; i < 3; i++)
|
||||
cc_ie->cc[i] = qdf_toupper(cc_ie->cc[i]);
|
||||
|
||||
num_country_codes = cc_db->num_country_codes;
|
||||
for (i = 0; i < num_country_codes; i++) {
|
||||
match = !qdf_mem_cmp(cc_db->votes[i].cc, cc_ie->cc,
|
||||
REG_ALPHA2_LEN);
|
||||
if (match)
|
||||
break;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
cc_db->votes[i].votes++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_country_codes >= SCAN_MAX_NUM_COUNTRY_CODE) {
|
||||
scm_debug("country code db already full: %d",
|
||||
num_country_codes);
|
||||
return;
|
||||
}
|
||||
|
||||
/* add country code to end of the list */
|
||||
qdf_mem_copy(cc_db->votes[num_country_codes].cc, cc_ie->cc,
|
||||
REG_ALPHA2_LEN + 1);
|
||||
cc_db->votes[num_country_codes].votes = 1;
|
||||
cc_db->num_country_codes++;
|
||||
}
|
||||
|
||||
void scm_11d_decide_country_code(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
uint8_t current_cc[REG_ALPHA2_LEN + 1];
|
||||
bool found;
|
||||
struct scan_country_code_db *cc_db;
|
||||
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
|
||||
struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
|
||||
|
||||
if (!wlan_reg_11d_enabled_on_host(psoc)) {
|
||||
scm_err("11d is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SOURCE_UNKNOWN == ucfg_reg_get_cc_and_src(psoc, current_cc)) {
|
||||
scm_err("fail to get current country code");
|
||||
return;
|
||||
}
|
||||
|
||||
cc_db = wlan_pdev_get_cc_db(psoc, pdev);
|
||||
if (!cc_db) {
|
||||
scm_err("scan_db is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wlan_reg_is_us(current_cc) || wlan_reg_is_world(current_cc))
|
||||
found = scm_11d_elected_country_algo_fcc(cc_db);
|
||||
else
|
||||
found = scm_11d_elected_country_info(cc_db);
|
||||
|
||||
if (found)
|
||||
scm_11d_set_country_code(pdev, cc_db->elected_cc,
|
||||
current_cc);
|
||||
scm_11d_reset_cc_db(cc_db);
|
||||
}
|
95
umac/scan/core/src/wlan_scan_11d.h
Normal file
95
umac/scan/core/src/wlan_scan_11d.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2018 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
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DOC: contains scan 11d entry api
|
||||
*/
|
||||
|
||||
#ifndef _WLAN_SCAN_11D_H_
|
||||
#define _WLAN_SCAN_11D_H_
|
||||
|
||||
#define SCAN_MAX_NUM_COUNTRY_CODE 100
|
||||
#define MIN_11D_AP_COUNT 3
|
||||
|
||||
/**
|
||||
* struct scan_country_code_votes - votes to country code mapping structure
|
||||
* @votes: votes
|
||||
* @cc: country code
|
||||
*/
|
||||
struct scan_country_code_votes {
|
||||
uint16_t votes;
|
||||
uint8_t cc[REG_ALPHA2_LEN + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scan_country_code_db - country code data base definition
|
||||
* @elected_cc: elected country code
|
||||
* @num_country_codes: number of country codes encountered
|
||||
* @votes: votes to country code mapping array
|
||||
*/
|
||||
struct scan_country_code_db {
|
||||
uint8_t elected_cc[REG_ALPHA2_LEN + 1];
|
||||
uint8_t num_country_codes;
|
||||
struct scan_country_code_votes votes[SCAN_MAX_NUM_COUNTRY_CODE];
|
||||
};
|
||||
|
||||
/**
|
||||
* scm_11d_cc_db_init() - API to init 11d country code db
|
||||
* @psoc: psoc object
|
||||
*
|
||||
* Initialize the country code database.
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS scm_11d_cc_db_init(struct wlan_objmgr_psoc *psoc);
|
||||
|
||||
/**
|
||||
* scm_11d_cc_db_deinit() - API to deinit 11d country code db
|
||||
* @psoc: psoc object
|
||||
*
|
||||
* free the country code database.
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS scm_11d_cc_db_deinit(struct wlan_objmgr_psoc *psoc);
|
||||
|
||||
/**
|
||||
* scm_11d_handle_country_info() - API to handle 11d country info
|
||||
* @psoc: psoc object
|
||||
* @pdev: pdev object
|
||||
* @scan_entry: the pointer to scan entry
|
||||
*
|
||||
* Update the country code database per the country code from country IE.
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void scm_11d_handle_country_info(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_pdev *pdev,
|
||||
struct scan_cache_entry *scan_entry);
|
||||
|
||||
/**
|
||||
* scm_11d_decide_country_code() - API to decide the country code per 11d
|
||||
* @vdev: vdev object
|
||||
*
|
||||
* Decide which country will be elected from the country database. If one
|
||||
* cadidate country is found, then it set the country code.
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void scm_11d_decide_country_code(struct wlan_objmgr_vdev *vdev);
|
||||
#endif
|
@@ -37,6 +37,8 @@
|
||||
#include <wlan_scan_utils_api.h>
|
||||
#include "wlan_scan_main.h"
|
||||
#include "wlan_scan_cache_db_i.h"
|
||||
#include "wlan_reg_services_api.h"
|
||||
#include "wlan_reg_ucfg_api.h"
|
||||
|
||||
/**
|
||||
* scm_del_scan_node() - API to remove scan node from the list
|
||||
@@ -692,6 +694,9 @@ QDF_STATUS scm_handle_bcn_probe(struct scheduler_msg *msg)
|
||||
|
||||
scan_entry = scan_node->entry;
|
||||
|
||||
if (wlan_reg_11d_enabled_on_host(psoc))
|
||||
scm_11d_handle_country_info(psoc, pdev, scan_entry);
|
||||
|
||||
status = scm_add_update_entry(scan_db, scan_entry);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
util_scan_free_cache_entry(scan_entry);
|
||||
|
@@ -893,6 +893,7 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc,
|
||||
bool match = false;
|
||||
struct roam_filter_params *roam_params;
|
||||
struct scan_default_params *def_param;
|
||||
struct wlan_country_ie *cc_ie;
|
||||
|
||||
def_param = wlan_scan_psoc_get_def_params(psoc);
|
||||
if (!def_param)
|
||||
@@ -972,8 +973,8 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc,
|
||||
if (!scm_is_fils_config_match(filter, db_entry))
|
||||
return false;
|
||||
|
||||
if (!util_country_code_match(filter->country,
|
||||
db_entry->ie_list.country))
|
||||
cc_ie = util_scan_entry_country(db_entry);
|
||||
if (!util_country_code_match(filter->country, cc_ie))
|
||||
return false;
|
||||
|
||||
if (!util_mdie_match(filter->mobility_domain,
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <wlan_objmgr_vdev_obj.h>
|
||||
#include <wlan_scan_public_structs.h>
|
||||
#include "wlan_scan_cache_db.h"
|
||||
#include "wlan_scan_11d.h"
|
||||
|
||||
#define scm_log(level, args...) \
|
||||
QDF_TRACE(QDF_MODULE_ID_SCAN, level, ## args)
|
||||
@@ -396,6 +397,7 @@ struct scan_cb {
|
||||
* struct wlan_scan_obj - scan object definition
|
||||
* @enable_scan: if scan is enabled
|
||||
* @scan_db: scan cache data base
|
||||
* @cc_db: pointer of country code data base
|
||||
* @lock: spin lock
|
||||
* @scan_def: default scan parameters
|
||||
* @cb: nif/sif function callbacks
|
||||
@@ -414,6 +416,7 @@ struct wlan_scan_obj {
|
||||
qdf_spinlock_t lock;
|
||||
qdf_atomic_t scan_ids;
|
||||
struct scan_dbs scan_db[WLAN_UMAC_MAX_PDEVS];
|
||||
struct scan_country_code_db *cc_db;
|
||||
struct scan_default_params scan_def;
|
||||
struct scan_cb cb;
|
||||
struct scan_requester_info requesters[WLAN_MAX_REQUESTORS];
|
||||
|
@@ -727,6 +727,8 @@ scm_scan_event_handler(struct scheduler_msg *msg)
|
||||
|
||||
switch (event->type) {
|
||||
case SCAN_EVENT_TYPE_COMPLETED:
|
||||
scm_11d_decide_country_code(vdev);
|
||||
/* fall through to release the command */
|
||||
case SCAN_EVENT_TYPE_START_FAILED:
|
||||
case SCAN_EVENT_TYPE_DEQUEUED:
|
||||
scm_release_serialization_command(vdev, event->scan_id);
|
||||
|
@@ -339,11 +339,8 @@ static inline bool util_is_bss_type_match(enum wlan_bss_type bss_type,
|
||||
* Return: true if country match
|
||||
*/
|
||||
static inline bool util_country_code_match(uint8_t *country,
|
||||
uint8_t *country_ie)
|
||||
struct wlan_country_ie *cc)
|
||||
{
|
||||
struct wlan_country_ie *cc =
|
||||
(struct wlan_country_ie *)country;
|
||||
|
||||
if (!country || !country[0])
|
||||
return true;
|
||||
|
||||
@@ -351,7 +348,7 @@ static inline bool util_country_code_match(uint8_t *country,
|
||||
return false;
|
||||
|
||||
if (cc->cc[0] == country[0] &&
|
||||
cc->cc[1] == country[1])
|
||||
cc->cc[1] == country[1])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1034,10 +1031,10 @@ util_scan_entry_vendor(struct scan_cache_entry *scan_entry)
|
||||
*
|
||||
* Return: countryie or NULL if ie is not present
|
||||
*/
|
||||
static inline uint8_t*
|
||||
static inline struct wlan_country_ie*
|
||||
util_scan_entry_country(struct scan_cache_entry *scan_entry)
|
||||
{
|
||||
return scan_entry->ie_list.country;
|
||||
return (struct wlan_country_ie *)scan_entry->ie_list.country;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1060,8 +1057,7 @@ util_scan_entry_copy_country(struct scan_cache_entry *scan_entry,
|
||||
if (!cntry)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
country_ie = (struct wlan_country_ie *)
|
||||
util_scan_entry_country(scan_entry);
|
||||
country_ie = util_scan_entry_country(scan_entry);
|
||||
|
||||
if (!country_ie)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
@@ -1722,6 +1722,8 @@ ucfg_scan_psoc_enable(struct wlan_objmgr_psoc *psoc)
|
||||
status = tgt_scan_register_ev_handler(psoc);
|
||||
QDF_ASSERT(status == QDF_STATUS_SUCCESS);
|
||||
scm_db_init(psoc);
|
||||
if (wlan_reg_11d_original_enabled_on_host(psoc))
|
||||
scm_11d_cc_db_init(psoc);
|
||||
ucfg_scan_register_unregister_bcn_cb(psoc, true);
|
||||
status = wlan_serialization_register_apply_rules_cb(psoc,
|
||||
WLAN_SER_CMD_SCAN,
|
||||
@@ -1744,6 +1746,8 @@ ucfg_scan_psoc_disable(struct wlan_objmgr_psoc *psoc)
|
||||
status = tgt_scan_unregister_ev_handler(psoc);
|
||||
QDF_ASSERT(status == QDF_STATUS_SUCCESS);
|
||||
ucfg_scan_register_unregister_bcn_cb(psoc, false);
|
||||
if (wlan_reg_11d_original_enabled_on_host(psoc))
|
||||
scm_11d_cc_db_deinit(psoc);
|
||||
scm_db_deinit(psoc);
|
||||
|
||||
return status;
|
||||
|
Referens i nytt ärende
Block a user