2015-07-31 14:18:17

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 3/3] mwifiex:fix unable to connect hidden SSID AP on DFS channel

From: chunfan chen <[email protected]>

We will check if any hidden SSID found in passive scan channels
and do specific SSID active scan for those channels.

Signed-off-by: chunfan chen <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/mwifiex/fw.h | 1 +
drivers/net/wireless/mwifiex/init.c | 2 +-
drivers/net/wireless/mwifiex/main.h | 2 +
drivers/net/wireless/mwifiex/scan.c | 124 ++++++++++++++++++++++++++++++++----
4 files changed, 117 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 9a8c1832..3ec2ac8 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -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 {
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 7a970c2..5d3ae63 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -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);
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index face747..6b95121 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -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);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index ef8da8e..e17fab6 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -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,46 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
return ret;
}

+/* 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;
+ u8 null_ssid[IEEE80211_MAX_SSID_LEN] = {0};
+
+ /* 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 (!memcmp(bss_desc->ssid.ssid, null_ssid, bss_desc->ssid.ssid_len)) {
+ 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 == 0) {
+ 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 +1831,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 +1862,54 @@ 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 == 0) {
+ 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++)
+ 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 +1923,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 +1951,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
--
1.8.1.4



2015-07-31 16:42:57

by Paul Stewart

[permalink] [raw]
Subject: Re: [PATCH 3/3] mwifiex:fix unable to connect hidden SSID AP on DFS channel

On Fri, Jul 31, 2015 at 7:17 AM, Amitkumar Karwar <[email protected]> wrote:
> From: chunfan chen <[email protected]>
>
> We will check if any hidden SSID found in passive scan channels
> and do specific SSID active scan for those channels.
>
> Signed-off-by: chunfan chen <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> drivers/net/wireless/mwifiex/fw.h | 1 +
> drivers/net/wireless/mwifiex/init.c | 2 +-
> drivers/net/wireless/mwifiex/main.h | 2 +
> drivers/net/wireless/mwifiex/scan.c | 124 ++++++++++++++++++++++++++++++++----
> 4 files changed, 117 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
> index 9a8c1832..3ec2ac8 100644
> --- a/drivers/net/wireless/mwifiex/fw.h
> +++ b/drivers/net/wireless/mwifiex/fw.h
> @@ -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 {
> diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
> index 7a970c2..5d3ae63 100644
> --- a/drivers/net/wireless/mwifiex/init.c
> +++ b/drivers/net/wireless/mwifiex/init.c
> @@ -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);
> }
> diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
> index face747..6b95121 100644
> --- a/drivers/net/wireless/mwifiex/main.h
> +++ b/drivers/net/wireless/mwifiex/main.h
> @@ -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);
> diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
> index ef8da8e..e17fab6 100644
> --- a/drivers/net/wireless/mwifiex/scan.c
> +++ b/drivers/net/wireless/mwifiex/scan.c
> @@ -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,46 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
> return ret;
> }
>
> +/* 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;
> + u8 null_ssid[IEEE80211_MAX_SSID_LEN] = {0};

Alas, this is not the only form of "hidden SSID". This behavior is
not standardized. You need to either expand your search to other
hidden SSID signatures (zero-length SSID, all-nulls-up-to-length
SSID), or think about turning this behavior on if you get any scan
results at all.

> +
> + /* 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 (!memcmp(bss_desc->ssid.ssid, null_ssid, bss_desc->ssid.ssid_len)) {
> + 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 == 0) {
> + 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 +1831,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 +1862,54 @@ 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 == 0) {
> + 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++)
> + 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 +1923,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 +1951,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
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2015-08-03 11:26:55

by Amitkumar Karwar

[permalink] [raw]
Subject: RE: [PATCH 3/3] mwifiex:fix unable to connect hidden SSID AP on DFS channel

SGkgUGF1bCwNCg0KPiA+ICsgICAgICAgaW50IHJldDsNCj4gPiArICAgICAgIGludCBjaGlkOw0K
PiA+ICsgICAgICAgdTggbnVsbF9zc2lkW0lFRUU4MDIxMV9NQVhfU1NJRF9MRU5dID0gezB9Ow0K
PiANCj4gQWxhcywgdGhpcyBpcyBub3QgdGhlIG9ubHkgZm9ybSBvZiAiaGlkZGVuIFNTSUQiLiAg
VGhpcyBiZWhhdmlvciBpcyBub3QNCj4gc3RhbmRhcmRpemVkLiAgWW91IG5lZWQgdG8gZWl0aGVy
IGV4cGFuZCB5b3VyIHNlYXJjaCB0byBvdGhlciBoaWRkZW4NCj4gU1NJRCBzaWduYXR1cmVzICh6
ZXJvLWxlbmd0aCBTU0lELCBhbGwtbnVsbHMtdXAtdG8tbGVuZ3RoIFNTSUQpLCBvcg0KPiB0aGlu
ayBhYm91dCB0dXJuaW5nIHRoaXMgYmVoYXZpb3Igb24gaWYgeW91IGdldCBhbnkgc2NhbiByZXN1
bHRzIGF0IGFsbC4NCj4gDQoNClRoYW5rcyBmb3IgeW91ciByZXZpZXcuDQpXZSB3aWxsIHVwZGF0
ZSB0aGUgY29kZSB0byBjaGVjayBmb3IgYm90aCB6ZXJvLWxlbmd0aCBTU0lEIGFzIHdlbGwgYXMg
YWxsLW51bGxzLXVwLXRvLWxlbmd0aCBTU0lELg0KDQpSZWdhcmRzLA0KQW1pdGt1bWFyDQo=