aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/wl_roam.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/wl_roam.c')
-rwxr-xr-x[-rw-r--r--]drivers/net/wireless/bcmdhd/wl_roam.c181
1 files changed, 144 insertions, 37 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_roam.c b/drivers/net/wireless/bcmdhd/wl_roam.c
index 708fb3bb09c..25f93abf8fd 100644..100755
--- a/drivers/net/wireless/bcmdhd/wl_roam.c
+++ b/drivers/net/wireless/bcmdhd/wl_roam.c
@@ -28,28 +28,33 @@
#include <osl.h>
#include <bcmwifi_channels.h>
#include <wlioctl.h>
-
-#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
+#include <bcmutils.h>
+#include <wl_cfg80211.h>
#include <wldev_common.h>
-#define WL_ERROR(x) printk x
-#endif
+#define MAX_ROAM_CACHE 100
+#define MAX_CHANNEL_LIST 20
+#define MAX_SSID_BUFSIZE 36
-#define WL_DBG(x)
-
-#define MAX_ROAM_CACHE 100
+#define ROAMSCAN_MODE_NORMAL 0
+#define ROAMSCAN_MODE_WES 1
typedef struct {
chanspec_t chanspec;
int ssid_len;
- char ssid[36];
+ char ssid[MAX_SSID_BUFSIZE];
} roam_channel_cache;
+typedef struct {
+ int n;
+ chanspec_t channels[MAX_CHANNEL_LIST];
+} channel_list_t;
+
static int n_roam_cache = 0;
static int roam_band = WLC_BAND_AUTO;
static roam_channel_cache roam_cache[MAX_ROAM_CACHE];
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
-static int roamscan_mode = 0;
+static int roamscan_mode = ROAMSCAN_MODE_NORMAL;
#endif
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
@@ -68,7 +73,7 @@ int set_roamscan_mode(struct net_device *dev, int mode)
error = wldev_iovar_setint(dev, "roamscan_mode", mode);
if (error) {
- WL_ERROR(("Failed to set roamscan mode to %d, error = %d\n", mode, error));
+ WL_ERR(("Failed to set roamscan mode to %d, error = %d\n", mode, error));
}
return error;
@@ -78,11 +83,11 @@ int get_roamscan_channel_list(struct net_device *dev, unsigned char channels[])
{
int n = 0;
- if (roamscan_mode) {
+ if (roamscan_mode == ROAMSCAN_MODE_WES) {
for (n = 0; n < n_roam_cache; n++) {
channels[n] = roam_cache[n].chanspec & WL_CHANSPEC_CHAN_MASK;
- WL_DBG(("%s: channel[%d] - [%02d] \n", __FUNCTION__, n, channels[n]));
+ WL_DBG(("channel[%d] - [%02d] \n", n, channels[n]));
}
}
@@ -94,16 +99,13 @@ int set_roamscan_channel_list(struct net_device *dev,
{
int i;
int error;
- struct {
- int n;
- chanspec_t channels[20];
- } channel_list;
- char iobuf[200];
- uint band, band2G, band5G, bw;
- roamscan_mode = 1;
+ channel_list_t channel_list;
+ char iobuf[WLC_IOCTL_SMLEN];
+ uint band2G, band5G, bw;
+ roamscan_mode = ROAMSCAN_MODE_WES;
- if (n > 20)
- n = 20;
+ if (n > MAX_CHANNEL_LIST)
+ n = MAX_CHANNEL_LIST;
#ifdef D11AC_IOTYPES
if (ioctl_ver == 1) {
@@ -125,7 +127,7 @@ int set_roamscan_channel_list(struct net_device *dev,
for (i = 0; i < n; i++) {
chanspec_t chanspec;
- if (channels[i] <= 14) {
+ if (channels[i] <= CH_MAX_2G_CHANNEL) {
chanspec = band2G | bw | channels[i];
} else {
chanspec = band5G | bw | channels[i];
@@ -133,17 +135,22 @@ int set_roamscan_channel_list(struct net_device *dev,
roam_cache[i].chanspec = chanspec;
channel_list.channels[i] = chanspec;
- WL_DBG(("%s: channel[%d] - [%02d] \n", __FUNCTION__, i, channels[i]));
+ WL_DBG(("channel[%d] - [%02d] \n", i, channels[i]));
}
n_roam_cache = n;
channel_list.n = n;
+ /* 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", &channel_list,
sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
if (error) {
- WL_ERROR(("Failed to set roamscan channels, error = %d\n", error));
+ WL_DBG(("Failed to set roamscan channels, error = %d\n", error));
}
+ wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_WES);
return error;
}
@@ -157,7 +164,7 @@ void set_roam_band(int band)
void reset_roam_cache(void)
{
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
- if (roamscan_mode)
+ if (roamscan_mode == ROAMSCAN_MODE_WES)
return;
#endif
@@ -170,11 +177,11 @@ void add_roam_cache(wl_bss_info_t *bi)
uint8 channel;
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
- if (roamscan_mode)
+ if (roamscan_mode == ROAMSCAN_MODE_WES)
return;
#endif
- if (n_roam_cache == MAX_ROAM_CACHE)
+ if (n_roam_cache >= MAX_ROAM_CACHE)
return;
for (i = 0; i < n_roam_cache; i++) {
@@ -188,9 +195,11 @@ void add_roam_cache(wl_bss_info_t *bi)
roam_cache[n_roam_cache].ssid_len = bi->SSID_len;
channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
+ WL_DBG(("CHSPEC 0x%X %d, CTL %d\n",
+ bi->chanspec, CHSPEC_CHANNEL(bi->chanspec), bi->ctl_ch));
roam_cache[n_roam_cache].chanspec =
WL_CHANSPEC_BW_20 |
- (channel <= 14 ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) |
+ (channel <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) |
channel;
memcpy(roam_cache[n_roam_cache].ssid, bi->SSID, bi->SSID_len);
@@ -220,21 +229,21 @@ int get_roam_channel_list(int target_chan,
bw = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
#endif /* D11AC_IOTYPES */
- if (target_chan <= 14)
+ if (target_chan <= CH_MAX_2G_CHANNEL)
band = band2G;
else
band = band5G;
*channels = (target_chan & WL_CHANSPEC_CHAN_MASK) | band | bw;
- WL_DBG((" %s: %02d 0x%04X\n", __FUNCTION__, target_chan, *channels));
+ WL_DBG(("%02d 0x%04X\n", target_chan, *channels));
++channels;
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
- if (roamscan_mode) {
+ if (roamscan_mode == ROAMSCAN_MODE_WES) {
for (i = 0; i < n_roam_cache; i++) {
if ((roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK) != target_chan) {
*channels = roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK;
- WL_DBG((" %s: %02d\n", __FUNCTION__, *channels));
- if (*channels <= 14)
+ WL_DBG(("%02d\n", *channels));
+ if (*channels <= CH_MAX_2G_CHANNEL)
*channels |= band2G | bw;
else
*channels |= band5G | bw;
@@ -258,13 +267,12 @@ int get_roam_channel_list(int target_chan,
(memcmp(roam_cache[i].ssid, ssid->SSID, ssid->SSID_len) == 0)) {
/* match found, add it */
*channels = ch & WL_CHANSPEC_CHAN_MASK;
- if (*channels <= 14)
+ if (*channels <= CH_MAX_2G_CHANNEL)
*channels |= band2G | bw;
else
*channels |= band5G | bw;
- WL_DBG((" %s: %02d 0x%04X\n", __FUNCTION__,
- ch & WL_CHANSPEC_CHAN_MASK, *channels));
+ WL_DBG(("%02d 0x%04X\n", ch & WL_CHANSPEC_CHAN_MASK, *channels));
channels++; n++;
}
@@ -278,7 +286,7 @@ void print_roam_cache(void)
{
int i;
- WL_DBG((" %d cache\n", n_roam_cache));
+ 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;
@@ -286,3 +294,102 @@ void print_roam_cache(void)
roam_cache[i].ssid_len, roam_cache[i].ssid));
}
}
+
+static void add_roamcache_channel(channel_list_t *channels, chanspec_t ch)
+{
+ int i;
+
+ if (channels->n >= MAX_CHANNEL_LIST) /* 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 wl_priv *wl, int ioctl_ver)
+{
+ int error, i, prev_channels;
+ channel_list_t channel_list;
+ char iobuf[WLC_IOCTL_SMLEN];
+ struct net_device *dev = wl_to_prmry_ndev(wl);
+ wlc_ssid_t ssid;
+ uint band2G, band5G, bw;
+
+#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
+ if (roamscan_mode == ROAMSCAN_MODE_WES) {
+ /* no update when ROAMSCAN_MODE_WES */
+ return;
+ }
+#endif
+
+ if (!wl_get_drv_status(wl, 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);
+
+ WL_DBG(("%d AP, %d cache item(s), err=%d\n", n_roam_cache, channel_list.n, error));
+
+ error = wldev_get_ssid(dev, &ssid);
+ if (error) {
+ WL_ERR(("Failed to get SSID, err=%d\n", error));
+ return;
+ }
+
+#ifdef D11AC_IOTYPES
+ if (ioctl_ver == 1) {
+ /* legacy chanspec */
+ band2G = WL_LCHANSPEC_BAND_2G;
+ band5G = WL_LCHANSPEC_BAND_5G;
+ bw = WL_LCHANSPEC_BW_20 | WL_LCHANSPEC_CTL_SB_NONE;
+ } else {
+ band2G = WL_CHANSPEC_BAND_2G;
+ band5G = WL_CHANSPEC_BAND_5G;
+ bw = WL_CHANSPEC_BW_20;
+ }
+#else
+ band2G = WL_CHANSPEC_BAND_2G;
+ band5G = WL_CHANSPEC_BAND_5G;
+ bw = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
+#endif /* D11AC_IOTYPES */
+
+ prev_channels = channel_list.n;
+ for (i = 0; i < n_roam_cache; i++) {
+ chanspec_t ch = roam_cache[i].chanspec;
+ if ((roam_cache[i].ssid_len == ssid.SSID_len) &&
+ ((roam_band == WLC_BAND_AUTO) ||
+ ((roam_band == WLC_BAND_2G) && CHSPEC_IS2G(ch)) ||
+ ((roam_band == WLC_BAND_5G) && CHSPEC_IS5G(ch))) &&
+ (memcmp(roam_cache[i].ssid, ssid.SSID, ssid.SSID_len) == 0)) {
+ /* match found, add it */
+ ch &= WL_CHANSPEC_CHAN_MASK;
+ if (ch <= CH_MAX_2G_CHANNEL)
+ ch |= band2G | bw;
+ else
+ ch |= band5G | 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));
+ }
+ }
+}