Commit 2375fa2b authored by chunfan chen's avatar chunfan chen Committed by Kalle Valo

mwifiex: fix unable to connect hidden SSID AP on DFS channel

We will check if any hidden SSID found in passive scan channels
and do specific SSID active scan for those channels.
Signed-off-by: default avatarchunfan chen <jeffc@marvell.com>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent eee7f196
......@@ -685,6 +685,7 @@ struct mwifiex_fw_chan_stats {
enum mwifiex_chan_scan_mode_bitmasks {
MWIFIEX_PASSIVE_SCAN = BIT(0),
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
};
struct mwifiex_chan_scan_param_set {
......
......@@ -301,7 +301,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
adapter->active_scan_triggered = false;
setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
(unsigned long)adapter);
}
......
......@@ -666,6 +666,7 @@ struct mwifiex_private {
struct mwifiex_11h_intf_state state_11h;
struct mwifiex_ds_mem_rw mem_rw;
struct sk_buff_head bypass_txq;
struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
};
......@@ -986,6 +987,7 @@ struct mwifiex_adapter {
u8 coex_tx_win_size;
u8 coex_rx_win_size;
bool drcs_enabled;
u8 active_scan_triggered;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
......
......@@ -527,7 +527,8 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
if (ch->flags & IEEE80211_CHAN_NO_IR)
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|= MWIFIEX_PASSIVE_SCAN;
|= (MWIFIEX_PASSIVE_SCAN |
MWIFIEX_HIDDEN_SSID_REPORT);
else
scan_chan_list[chan_idx].chan_scan_mode_bitmap
&= ~MWIFIEX_PASSIVE_SCAN;
......@@ -1049,7 +1050,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
(scan_chan_list +
chan_idx)->chan_scan_mode_bitmap
|= MWIFIEX_PASSIVE_SCAN;
|= (MWIFIEX_PASSIVE_SCAN |
MWIFIEX_HIDDEN_SSID_REPORT);
else
(scan_chan_list +
chan_idx)->chan_scan_mode_bitmap
......@@ -1600,6 +1602,62 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
return ret;
}
/* This function checks if SSID string contains all zeroes or length is zero */
static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
{
int idx;
for (idx = 0; idx < ssid->ssid_len; idx++) {
if (ssid->ssid[idx])
return false;
}
return true;
}
/* This function checks if any hidden SSID found in passive scan channels
* and save those channels for specific SSID active scan
*/
static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
struct cfg80211_bss *bss)
{
struct mwifiex_bssdescriptor *bss_desc;
int ret;
int chid;
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
if (!bss_desc)
return -ENOMEM;
ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
if (ret)
goto done;
if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
if (priv->hidden_chan[chid].chan_number ==
bss->channel->hw_value)
break;
if (!priv->hidden_chan[chid].chan_number) {
priv->hidden_chan[chid].chan_number =
bss->channel->hw_value;
priv->hidden_chan[chid].radio_type =
bss->channel->band;
priv->hidden_chan[chid].scan_type =
MWIFIEX_SCAN_TYPE_ACTIVE;
break;
}
}
}
done:
kfree(bss_desc);
return 0;
}
static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
struct cfg80211_bss *bss)
{
......@@ -1789,6 +1847,14 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
.mac_address, ETH_ALEN))
mwifiex_update_curr_bss_params(priv, bss);
cfg80211_put_bss(priv->wdev.wiphy, bss);
if ((chan->flags & IEEE80211_CHAN_RADAR) ||
(chan->flags & IEEE80211_CHAN_NO_IR)) {
mwifiex_dbg(adapter, INFO,
"radar or passive channel %d\n",
channel);
mwifiex_save_hidden_ssid_channels(priv, bss);
}
}
} else {
mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
......@@ -1812,6 +1878,57 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
}
}
/* This function checks if any hidden SSID found in passive scan channels
* and do specific SSID active scan for those channels
*/
static int
mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
{
int ret;
struct mwifiex_adapter *adapter = priv->adapter;
u8 id = 0;
struct mwifiex_user_scan_cfg *user_scan_cfg;
if (adapter->active_scan_triggered) {
adapter->active_scan_triggered = false;
return 0;
}
if (!priv->hidden_chan[0].chan_number) {
mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
return 0;
}
user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
if (!user_scan_cfg)
return -ENOMEM;
memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
if (!priv->hidden_chan[id].chan_number)
break;
memcpy(&user_scan_cfg->chan_list[id],
&priv->hidden_chan[id],
sizeof(struct mwifiex_user_scan_chan));
}
adapter->active_scan_triggered = true;
user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
user_scan_cfg->ssid_list = priv->scan_request->ssids;
ret = mwifiex_scan_networks(priv, user_scan_cfg);
kfree(user_scan_cfg);
memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
if (ret) {
dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
return ret;
}
return 0;
}
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
{
struct mwifiex_adapter *adapter = priv->adapter;
......@@ -1825,6 +1942,8 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
mwifiex_active_scan_req_for_passive_chan(priv);
if (!adapter->ext_scan)
mwifiex_complete_scan(priv);
......@@ -1851,15 +1970,17 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
if (priv->scan_request) {
mwifiex_dbg(adapter, INFO,
"info: aborting scan\n");
cfg80211_scan_done(priv->scan_request, 1);
priv->scan_request = NULL;
} else {
priv->scan_aborting = false;
mwifiex_dbg(adapter, INFO,
"info: scan already aborted\n");
if (!adapter->active_scan_triggered) {
if (priv->scan_request) {
mwifiex_dbg(adapter, INFO,
"info: aborting scan\n");
cfg80211_scan_done(priv->scan_request, 1);
priv->scan_request = NULL;
} else {
priv->scan_aborting = false;
mwifiex_dbg(adapter, INFO,
"info: scan already aborted\n");
}
}
} else {
/* Get scan command from scan_pending_q and put to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment