Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -685,6 +685,7 @@ struct mwifiex_fw_chan_stats {
enum mwifiex_chan_scan_mode_bitmasks {
enum mwifiex_chan_scan_mode_bitmasks {
	MWIFIEX_PASSIVE_SCAN = BIT(0),
	MWIFIEX_PASSIVE_SCAN = BIT(0),
	MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
	MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
	MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
};
};


struct mwifiex_chan_scan_param_set {
struct mwifiex_chan_scan_param_set {
+1 −1
Original line number Original line Diff line number Diff line
@@ -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.sta_intf = MWIFIEX_MAX_STA_NUM;
	adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
	adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
	adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
	adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;

	adapter->active_scan_triggered = false;
	setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
	setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
		    (unsigned long)adapter);
		    (unsigned long)adapter);
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -666,6 +666,7 @@ struct mwifiex_private {
	struct mwifiex_11h_intf_state state_11h;
	struct mwifiex_11h_intf_state state_11h;
	struct mwifiex_ds_mem_rw mem_rw;
	struct mwifiex_ds_mem_rw mem_rw;
	struct sk_buff_head bypass_txq;
	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_tx_win_size;
	u8 coex_rx_win_size;
	u8 coex_rx_win_size;
	bool drcs_enabled;
	bool drcs_enabled;
	u8 active_scan_triggered;
};
};


void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
+132 −11
Original line number Original line Diff line number Diff line
@@ -527,7 +527,8 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,


			if (ch->flags & IEEE80211_CHAN_NO_IR)
			if (ch->flags & IEEE80211_CHAN_NO_IR)
				scan_chan_list[chan_idx].chan_scan_mode_bitmap
				scan_chan_list[chan_idx].chan_scan_mode_bitmap
					|= MWIFIEX_PASSIVE_SCAN;
					|= (MWIFIEX_PASSIVE_SCAN |
					    MWIFIEX_HIDDEN_SSID_REPORT);
			else
			else
				scan_chan_list[chan_idx].chan_scan_mode_bitmap
				scan_chan_list[chan_idx].chan_scan_mode_bitmap
					&= ~MWIFIEX_PASSIVE_SCAN;
					&= ~MWIFIEX_PASSIVE_SCAN;
@@ -1049,7 +1050,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
				(scan_chan_list +
				(scan_chan_list +
				 chan_idx)->chan_scan_mode_bitmap
				 chan_idx)->chan_scan_mode_bitmap
					|= MWIFIEX_PASSIVE_SCAN;
					|= (MWIFIEX_PASSIVE_SCAN |
					    MWIFIEX_HIDDEN_SSID_REPORT);
			else
			else
				(scan_chan_list +
				(scan_chan_list +
				 chan_idx)->chan_scan_mode_bitmap
				 chan_idx)->chan_scan_mode_bitmap
@@ -1600,6 +1602,62 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
	return ret;
	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,
static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
					  struct cfg80211_bss *bss)
					  struct cfg80211_bss *bss)
{
{
@@ -1789,6 +1847,14 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
				    .mac_address, ETH_ALEN))
				    .mac_address, ETH_ALEN))
				mwifiex_update_curr_bss_params(priv, bss);
				mwifiex_update_curr_bss_params(priv, bss);
			cfg80211_put_bss(priv->wdev.wiphy, 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 {
	} else {
		mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
		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)
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
{
{
	struct mwifiex_adapter *adapter = priv->adapter;
	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;
		adapter->scan_processing = false;
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);


		mwifiex_active_scan_req_for_passive_chan(priv);

		if (!adapter->ext_scan)
		if (!adapter->ext_scan)
			mwifiex_complete_scan(priv);
			mwifiex_complete_scan(priv);


@@ -1851,6 +1970,7 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
		adapter->scan_processing = false;
		adapter->scan_processing = false;
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);


		if (!adapter->active_scan_triggered) {
			if (priv->scan_request) {
			if (priv->scan_request) {
				mwifiex_dbg(adapter, INFO,
				mwifiex_dbg(adapter, INFO,
					    "info: aborting scan\n");
					    "info: aborting scan\n");
@@ -1861,6 +1981,7 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
				mwifiex_dbg(adapter, INFO,
				mwifiex_dbg(adapter, INFO,
					    "info: scan already aborted\n");
					    "info: scan already aborted\n");
			}
			}
		}
	} else {
	} else {
		/* Get scan command from scan_pending_q and put to
		/* Get scan command from scan_pending_q and put to
		 * cmd_pending_q
		 * cmd_pending_q