609 lines
16 KiB
C
Executable File
609 lines
16 KiB
C
Executable File
/*
|
|
* Linux roam cache
|
|
*
|
|
* Copyright (C) 2022, Broadcom.
|
|
*
|
|
* Unless you and Broadcom execute a separate written software license
|
|
* agreement governing use of this software, this software is licensed to you
|
|
* under the terms of the GNU General Public License version 2 (the "GPL"),
|
|
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
|
|
* following added to such license:
|
|
*
|
|
* As a special exception, the copyright holders of this software give you
|
|
* permission to link this software with independent modules, and to copy and
|
|
* distribute the resulting executable under terms of your choice, provided that
|
|
* you also meet, for each linked independent module, the terms and conditions of
|
|
* the license of that module. An independent module is a module which is not
|
|
* derived from this software. The special exception does not apply to any
|
|
* modifications of the software.
|
|
*
|
|
*
|
|
* <<Broadcom-WL-IPTag/Dual:>>
|
|
*/
|
|
|
|
#include <typedefs.h>
|
|
#include <osl.h>
|
|
#include <bcmwifi_channels.h>
|
|
#include <wlioctl.h>
|
|
#include <bcmutils.h>
|
|
#ifdef WL_CFG80211
|
|
#include <wl_cfg80211.h>
|
|
#endif
|
|
#include <wldev_common.h>
|
|
#if defined(__linux__)
|
|
#include <bcmstdlib_s.h>
|
|
#endif /* defined(__linux__) */
|
|
|
|
#ifdef ESCAN_CHANNEL_CACHE
|
|
#define MAX_ROAM_CACHE 200
|
|
#define MAX_SSID_BUFSIZE 36
|
|
|
|
typedef struct {
|
|
chanspec_t chanspec;
|
|
int ssid_len;
|
|
char ssid[MAX_SSID_BUFSIZE];
|
|
} roam_channel_cache;
|
|
|
|
static int n_roam_cache = 0;
|
|
static int roam_band = WLC_BAND_AUTO;
|
|
static roam_channel_cache roam_cache[MAX_ROAM_CACHE];
|
|
static uint band_bw;
|
|
|
|
static void add_roamcache_channel(wl_roam_channel_list_t *channels, chanspec_t ch)
|
|
{
|
|
int i;
|
|
|
|
if (channels->n >= MAX_ROAM_CHANNEL) /* buffer full */
|
|
return;
|
|
|
|
for (i = 0; i < channels->n; i++) {
|
|
if (channels->channels[i] == ch) /* already in the list */
|
|
return;
|
|
}
|
|
|
|
channels->channels[i] = ch;
|
|
channels->n++;
|
|
|
|
WL_DBG((" RCC: %02d 0x%04X\n",
|
|
ch & WL_CHANSPEC_CHAN_MASK, ch));
|
|
}
|
|
|
|
void update_roam_cache(struct bcm_cfg80211 *cfg, int ioctl_ver)
|
|
{
|
|
int error, i, prev_channels;
|
|
wl_roam_channel_list_t channel_list;
|
|
char iobuf[WLC_IOCTL_SMLEN];
|
|
struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
|
|
wlc_ssid_t ssid;
|
|
#ifdef WL_DUAL_STA
|
|
struct net_info *iter, *next;
|
|
#endif /* WL_DUAL_STA */
|
|
|
|
if (!cfg->rcc_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef WES_SUPPORT
|
|
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES) {
|
|
/* no update when ROAMSCAN_MODE_WES */
|
|
return;
|
|
}
|
|
#endif /* WES_SUPPORT */
|
|
|
|
#ifdef WL_DUAL_STA
|
|
GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
|
|
for_each_ndev(cfg, iter, next) {
|
|
GCC_DIAGNOSTIC_POP();
|
|
if ((iter->wdev) && (iter->iftype == WL_IF_TYPE_STA)) {
|
|
struct net_device *ndev = iter->wdev->netdev;
|
|
if (IS_INET_LINK_NDEV(cfg, ndev)) {
|
|
/* Update the net device with primary interface */
|
|
dev = ndev;
|
|
WL_DBG(("ndev considered for RCC %s\n", dev->name));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* WL_DUAL_STA */
|
|
|
|
if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
|
|
WL_DBG(("Not associated\n"));
|
|
return;
|
|
}
|
|
|
|
/* need to read out the current cache list
|
|
as the firmware may change dynamically
|
|
*/
|
|
error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
|
|
(void *)&channel_list, sizeof(channel_list), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to get roamscan channels, error = %d\n", error));
|
|
return;
|
|
}
|
|
|
|
error = wldev_get_ssid(dev, &ssid);
|
|
if (error) {
|
|
WL_ERR(("Failed to get SSID, err=%d\n", error));
|
|
return;
|
|
}
|
|
|
|
prev_channels = channel_list.n;
|
|
for (i = 0; i < n_roam_cache; i++) {
|
|
chanspec_t ch = roam_cache[i].chanspec;
|
|
bool band_match = ((roam_band == WLC_BAND_AUTO) ||
|
|
#ifdef WL_6G_BAND
|
|
((roam_band == WLC_BAND_6G) && (CHSPEC_IS6G(ch))) ||
|
|
#endif /* WL_6G_BAND */
|
|
((roam_band == WLC_BAND_2G) && (CHSPEC_IS2G(ch))) ||
|
|
((roam_band == WLC_BAND_5G) && (CHSPEC_IS5G(ch))));
|
|
|
|
if ((roam_cache[i].ssid_len == ssid.SSID_len) &&
|
|
band_match && (memcmp(roam_cache[i].ssid, ssid.SSID, ssid.SSID_len) == 0)) {
|
|
/* match found, add it */
|
|
ch = wf_chspec_ctlchan(ch) | CHSPEC_BAND(ch) | band_bw;
|
|
add_roamcache_channel(&channel_list, ch);
|
|
}
|
|
}
|
|
if (prev_channels != channel_list.n) {
|
|
/* channel list updated */
|
|
error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list,
|
|
sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to update roamscan channels, error = %d\n", error));
|
|
}
|
|
}
|
|
|
|
WL_DBG(("%d AP, %d cache item(s), err=%d\n", n_roam_cache, channel_list.n, error));
|
|
}
|
|
|
|
void set_roam_band(int band)
|
|
{
|
|
roam_band = band;
|
|
}
|
|
|
|
void reset_roam_cache(struct bcm_cfg80211 *cfg)
|
|
{
|
|
if (!cfg->rcc_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef WES_SUPPORT
|
|
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES)
|
|
return;
|
|
#endif /* WES_SUPPORT */
|
|
|
|
n_roam_cache = 0;
|
|
}
|
|
|
|
static void
|
|
add_roam_cache_list(uint8 *SSID, uint32 SSID_len, chanspec_t chanspec)
|
|
{
|
|
int i, ret = 0;
|
|
uint8 channel;
|
|
char chanbuf[CHANSPEC_STR_LEN];
|
|
|
|
if (n_roam_cache >= MAX_ROAM_CACHE) {
|
|
return;
|
|
}
|
|
|
|
if (SSID_len > DOT11_MAX_SSID_LEN) {
|
|
WL_ERR(("SSID len %u out of bounds [0-32]\n", SSID_len));
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < n_roam_cache; i++) {
|
|
if ((roam_cache[i].ssid_len == SSID_len) &&
|
|
(roam_cache[i].chanspec == chanspec) &&
|
|
(memcmp(roam_cache[i].ssid, SSID, SSID_len) == 0)) {
|
|
/* identical one found, just return */
|
|
return;
|
|
}
|
|
}
|
|
|
|
roam_cache[n_roam_cache].ssid_len = SSID_len;
|
|
channel = wf_chspec_ctlchan(chanspec);
|
|
WL_DBG(("CHSPEC = %s, CTL %d SSID %.32s\n",
|
|
wf_chspec_ntoa_ex(chanspec, chanbuf), channel, SSID));
|
|
roam_cache[n_roam_cache].chanspec = CHSPEC_BAND(chanspec) | band_bw | channel;
|
|
ret = memcpy_s(roam_cache[n_roam_cache].ssid,
|
|
sizeof(roam_cache[n_roam_cache].ssid), SSID, SSID_len);
|
|
if (ret) {
|
|
WL_ERR(("memcpy failed:%d, destsz:%zu, n:%d\n",
|
|
ret, sizeof(roam_cache[n_roam_cache].ssid), SSID_len));
|
|
return;
|
|
}
|
|
|
|
n_roam_cache++;
|
|
}
|
|
|
|
void
|
|
add_roam_cache(struct bcm_cfg80211 *cfg, wl_bss_info_v109_t *bi)
|
|
{
|
|
if (!cfg->rcc_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef WES_SUPPORT
|
|
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES) {
|
|
return;
|
|
}
|
|
#endif /* WES_SUPPORT */
|
|
|
|
add_roam_cache_list(bi->SSID, bi->SSID_len, bi->chanspec);
|
|
}
|
|
|
|
static bool is_duplicated_channel(const chanspec_t *channels, int n_channels, chanspec_t new)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_channels; i++) {
|
|
if (channels[i] == new)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int get_roam_channel_list(struct bcm_cfg80211 *cfg, chanspec_t target_chan,
|
|
chanspec_t *channels, int n_channels, const wlc_ssid_t *ssid, int ioctl_ver)
|
|
{
|
|
int i, n = 0;
|
|
char chanbuf[CHANSPEC_STR_LEN];
|
|
|
|
/* first index is filled with the given target channel */
|
|
if ((target_chan != INVCHANSPEC) && (target_chan != 0)) {
|
|
channels[0] = target_chan;
|
|
n++;
|
|
}
|
|
|
|
WL_SCAN(("0x%04X\n", channels[0]));
|
|
|
|
#ifdef WES_SUPPORT
|
|
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES) {
|
|
for (i = 0; i < n_roam_cache; i++) {
|
|
chanspec_t ch = roam_cache[i].chanspec;
|
|
bool band_match = ((roam_band == WLC_BAND_AUTO) ||
|
|
#ifdef WL_6G_BAND
|
|
((roam_band == WLC_BAND_6G) && (CHSPEC_IS6G(ch))) ||
|
|
#endif /* WL_6G_BAND */
|
|
((roam_band == WLC_BAND_2G) && (CHSPEC_IS2G(ch))) ||
|
|
((roam_band == WLC_BAND_5G) && (CHSPEC_IS5G(ch))));
|
|
|
|
ch = wf_chspec_ctlchan(ch) | CHSPEC_BAND(ch) | band_bw;
|
|
|
|
if (band_match && !is_duplicated_channel(channels, n, ch)) {
|
|
WL_SCAN(("Chanspec = %s\n",
|
|
wf_chspec_ntoa_ex(ch, chanbuf)));
|
|
channels[n++] = ch;
|
|
if (n >= n_channels) {
|
|
WL_ERR(("Too many roam scan channels\n"));
|
|
return n;
|
|
}
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
#endif /* WES_SUPPORT */
|
|
|
|
for (i = 0; i < n_roam_cache; i++) {
|
|
chanspec_t ch = roam_cache[i].chanspec;
|
|
bool band_match = ((roam_band == WLC_BAND_AUTO) ||
|
|
#ifdef WL_6G_BAND
|
|
((roam_band == WLC_BAND_6G) && (CHSPEC_IS6G(ch))) ||
|
|
#endif /* WL_6G_BAND */
|
|
((roam_band == WLC_BAND_2G) && (CHSPEC_IS2G(ch))) ||
|
|
((roam_band == WLC_BAND_5G) && (CHSPEC_IS5G(ch))));
|
|
|
|
ch = wf_chspec_ctlchan(ch) | CHSPEC_BAND(ch) | band_bw;
|
|
if ((roam_cache[i].ssid_len == ssid->SSID_len) &&
|
|
band_match && !is_duplicated_channel(channels, n, ch) &&
|
|
(memcmp(roam_cache[i].ssid, ssid->SSID, ssid->SSID_len) == 0)) {
|
|
/* match found, add it */
|
|
WL_SCAN(("Chanspec = %s\n",
|
|
wf_chspec_ntoa_ex(ch, chanbuf)));
|
|
channels[n++] = ch;
|
|
if (n >= n_channels) {
|
|
WL_ERR(("Too many roam scan channels\n"));
|
|
return n;
|
|
}
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
#ifdef WES_SUPPORT
|
|
int get_roamscan_mode(struct net_device *dev, int *mode)
|
|
{
|
|
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
|
|
*mode = cfg->roamscan_mode;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int set_roamscan_mode(struct net_device *dev, int mode)
|
|
{
|
|
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
|
|
int error = 0;
|
|
cfg->roamscan_mode = mode;
|
|
n_roam_cache = 0;
|
|
|
|
error = wldev_iovar_setint(dev, "roamscan_mode", mode);
|
|
if (error) {
|
|
WL_ERR(("Failed to set roamscan mode to %d, error = %d\n", mode, error));
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
int
|
|
get_roamscan_chanspec_list(struct net_device *dev, chanspec_t *chanspecs)
|
|
{
|
|
int i = 0;
|
|
int error = BCME_OK;
|
|
wl_roam_channel_list_t channel_list;
|
|
|
|
/* Get Current RCC List */
|
|
error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
|
|
(void *)&channel_list, sizeof(channel_list), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to get roamscan channels, err = %d\n", error));
|
|
return error;
|
|
}
|
|
if (channel_list.n > MAX_ROAM_CHANNEL) {
|
|
WL_ERR(("Invalid roamscan channels count(%d)\n", channel_list.n));
|
|
return BCME_ERROR;
|
|
}
|
|
|
|
for (i = 0; i < channel_list.n; i++) {
|
|
chanspecs[i] = channel_list.channels[i];
|
|
WL_DBG(("%02d: chanspec %04x\n", i, chanspecs[i]));
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
bool
|
|
check_prune_roam_band(uint8 allowed_band, chanspec_t chanspec)
|
|
{
|
|
int ret = FALSE;
|
|
|
|
if ((allowed_band == WLC_ROAM_ALLOW_BAND_AUTO) ||
|
|
(allowed_band == WLC_ROAM_ALLOW_BAND_MAX)) {
|
|
return ret;
|
|
}
|
|
|
|
/* Pruned BSS via ROAM Band mode */
|
|
if ((CHSPEC_IS2G(chanspec) && !(allowed_band & WLC_ROAM_ALLOW_BAND_2G))) {
|
|
ret = TRUE;
|
|
} else if (CHSPEC_IS5G(chanspec) && !(allowed_band & WLC_ROAM_ALLOW_BAND_5G)) {
|
|
ret = TRUE;
|
|
#ifdef WL_6G_BAND
|
|
} else if (CHSPEC_IS6G(chanspec) && !(allowed_band & WLC_ROAM_ALLOW_BAND_6G)) {
|
|
ret = TRUE;
|
|
#endif /* WL_6G_BAND */
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
set_roamscan_chanspec_list(struct net_device *dev, uint nchan, chanspec_t *chanspecs)
|
|
{
|
|
int i, j;
|
|
int error;
|
|
wl_roam_channel_list_t channel_list;
|
|
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
|
|
char iobuf[WLC_IOCTL_SMLEN];
|
|
|
|
if (nchan > MAX_ROAM_CHANNEL) {
|
|
nchan = MAX_ROAM_CHANNEL;
|
|
}
|
|
|
|
for (i = 0, j = 0; i < nchan; i++) {
|
|
if (!wf_chspec_valid(chanspecs[i])) {
|
|
WL_ERR(("%02d/%d: invalid chan: 0x%04x\n", i, nchan, chanspecs[i]));
|
|
continue;
|
|
}
|
|
if (check_prune_roam_band(cfg->roam_allowed_band, chanspecs[i])) {
|
|
WL_ERR(("%02d/%d: Pruned ROAM band(%d) 0x%04x\n", i, nchan,
|
|
cfg->roam_allowed_band, chanspecs[i]));
|
|
continue;
|
|
}
|
|
channel_list.channels[j] = roam_cache[j].chanspec = chanspecs[i];
|
|
WL_DBG(("%02d/%d: chan: 0x%04x\n", i, nchan, chanspecs[i]));
|
|
j++;
|
|
}
|
|
|
|
channel_list.n = n_roam_cache = j;
|
|
|
|
/* need to set ROAMSCAN_MODE_NORMAL to update roamscan_channels,
|
|
* otherwise, it won't be updated
|
|
*/
|
|
error = wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_NORMAL);
|
|
if (error) {
|
|
WL_ERR(("Failed to set roamscan mode to %d, error = %d\n",
|
|
ROAMSCAN_MODE_NORMAL, error));
|
|
return error;
|
|
}
|
|
error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list,
|
|
sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to set roamscan channels, error = %d\n", error));
|
|
return error;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
int
|
|
add_roamscan_chanspec_list(struct net_device *dev, uint nchan, chanspec_t *chanspecs)
|
|
{
|
|
int i, error = BCME_OK;
|
|
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
|
|
wlc_ssid_t ssid;
|
|
|
|
if (!cfg->rcc_enabled) {
|
|
return BCME_ERROR;
|
|
}
|
|
|
|
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES) {
|
|
WL_ERR(("Failed to add roamscan channels, WES mode %d\n",
|
|
cfg->roamscan_mode));
|
|
return BCME_ERROR;
|
|
}
|
|
|
|
if (nchan > MAX_ROAM_CHANNEL) {
|
|
WL_ERR(("Failed Over MAX channel list(%d)\n", nchan));
|
|
return BCME_BADARG;
|
|
}
|
|
|
|
error = wldev_get_ssid(dev, &ssid);
|
|
if (error) {
|
|
WL_ERR(("Failed to get SSID, err=%d\n", error));
|
|
return error;
|
|
}
|
|
|
|
WL_DBG(("Add Roam scan channel count %d\n", nchan));
|
|
|
|
for (i = 0; i < nchan; i++) {
|
|
if (!wf_chspec_valid(chanspecs[i])) {
|
|
continue;
|
|
}
|
|
if (check_prune_roam_band(cfg->roam_allowed_band, chanspecs[i])) {
|
|
WL_ERR(("%02d/%d: Pruned ROAM band(%d) 0x%04x\n", i, nchan,
|
|
cfg->roam_allowed_band, chanspecs[i]));
|
|
continue;
|
|
}
|
|
add_roam_cache_list(ssid.SSID, ssid.SSID_len, chanspecs[i]);
|
|
WL_DBG(("channel[%d] - 0x%04x SSID %s\n", i, chanspecs[i], ssid.SSID));
|
|
}
|
|
|
|
update_roam_cache(cfg, ioctl_version);
|
|
|
|
return error;
|
|
}
|
|
#endif /* WES_SUPPORT */
|
|
|
|
#ifdef ROAM_CHANNEL_CACHE
|
|
int init_roam_cache(struct bcm_cfg80211 *cfg, int ioctl_ver)
|
|
{
|
|
int err;
|
|
struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
|
|
s32 mode;
|
|
|
|
/* Check support in firmware */
|
|
err = wldev_iovar_getint(dev, "roamscan_mode", &mode);
|
|
if (err && (err == BCME_UNSUPPORTED)) {
|
|
/* If firmware doesn't support, return error. Else proceed */
|
|
WL_ERR(("roamscan_mode iovar failed. %d\n", err));
|
|
return err;
|
|
}
|
|
|
|
#ifdef D11AC_IOTYPES
|
|
band_bw = WL_CHANSPEC_BW_20;
|
|
#else
|
|
band_bw = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
|
|
#endif /* D11AC_IOTYPES */
|
|
|
|
n_roam_cache = 0;
|
|
roam_band = WLC_BAND_AUTO;
|
|
cfg->roamscan_mode = ROAMSCAN_MODE_NORMAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void print_roam_cache(struct bcm_cfg80211 *cfg)
|
|
{
|
|
int i;
|
|
|
|
if (!cfg->rcc_enabled) {
|
|
return;
|
|
}
|
|
|
|
WL_DBG((" %d cache\n", n_roam_cache));
|
|
|
|
for (i = 0; i < n_roam_cache; i++) {
|
|
roam_cache[i].ssid[roam_cache[i].ssid_len] = 0;
|
|
WL_DBG(("0x%02X %02d %s\n", roam_cache[i].chanspec,
|
|
roam_cache[i].ssid_len, roam_cache[i].ssid));
|
|
}
|
|
}
|
|
|
|
void wl_update_roamscan_cache_by_band(struct net_device *dev, int band)
|
|
{
|
|
int i, error, roamscan_mode;
|
|
wl_roam_channel_list_t chanlist_before, chanlist_after;
|
|
char iobuf[WLC_IOCTL_SMLEN];
|
|
|
|
roam_band = band;
|
|
|
|
error = wldev_iovar_getint(dev, "roamscan_mode", &roamscan_mode);
|
|
if (error) {
|
|
WL_ERR(("Failed to get roamscan mode, error = %d\n", error));
|
|
return;
|
|
}
|
|
|
|
/* in case of WES mode, update channel list by band based on the cache in DHD */
|
|
if (roamscan_mode) {
|
|
int n = 0;
|
|
chanlist_before.n = n_roam_cache;
|
|
|
|
for (n = 0; n < n_roam_cache; n++) {
|
|
chanspec_t ch = roam_cache[n].chanspec;
|
|
chanlist_before.channels[n] = wf_chspec_ctlchan(ch) |
|
|
CHSPEC_BAND(ch) | band_bw;
|
|
}
|
|
} else {
|
|
if (band == WLC_BAND_AUTO) {
|
|
return;
|
|
}
|
|
error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
|
|
(void *)&chanlist_before, sizeof(wl_roam_channel_list_t), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to get roamscan channels, error = %d\n", error));
|
|
return;
|
|
}
|
|
}
|
|
chanlist_after.n = 0;
|
|
/* filtering by the given band */
|
|
for (i = 0; i < chanlist_before.n; i++) {
|
|
chanspec_t chspec = chanlist_before.channels[i];
|
|
bool band_match = ((band == WLC_BAND_AUTO) ||
|
|
#ifdef WL_6G_BAND
|
|
((band == WLC_BAND_6G) && (CHSPEC_IS6G(chspec))) ||
|
|
#endif /* WL_6G_BAND */
|
|
((band == WLC_BAND_2G) && (CHSPEC_IS2G(chspec))) ||
|
|
((band == WLC_BAND_5G) && (CHSPEC_IS5G(chspec))));
|
|
if (band_match) {
|
|
chanlist_after.channels[chanlist_after.n++] = chspec;
|
|
}
|
|
}
|
|
|
|
if (roamscan_mode) {
|
|
/* need to set ROAMSCAN_MODE_NORMAL to update roamscan_channels,
|
|
* otherwise, it won't be updated
|
|
*/
|
|
wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_NORMAL);
|
|
|
|
error = wldev_iovar_setbuf(dev, "roamscan_channels", &chanlist_after,
|
|
sizeof(wl_roam_channel_list_t), iobuf, sizeof(iobuf), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to update roamscan channels, error = %d\n", error));
|
|
}
|
|
wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_WES);
|
|
} else {
|
|
if (chanlist_before.n == chanlist_after.n) {
|
|
return;
|
|
}
|
|
error = wldev_iovar_setbuf(dev, "roamscan_channels", &chanlist_after,
|
|
sizeof(wl_roam_channel_list_t), iobuf, sizeof(iobuf), NULL);
|
|
if (error) {
|
|
WL_ERR(("Failed to update roamscan channels, error = %d\n", error));
|
|
}
|
|
}
|
|
}
|
|
#endif /* ROAM_CHANNEL_CACHE */
|
|
#endif /* ESCAN_CHANNEL_CACHE */
|