|
@@ -1139,10 +1139,25 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int wl1271_join(struct wl1271 *wl)
|
|
|
+static int wl1271_join(struct wl1271 *wl, bool set_assoc)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
+ /*
|
|
|
+ * One of the side effects of the JOIN command is that is clears
|
|
|
+ * WPA/WPA2 keys from the chipset. Performing a JOIN while associated
|
|
|
+ * to a WPA/WPA2 access point will therefore kill the data-path.
|
|
|
+ * Currently there is no supported scenario for JOIN during
|
|
|
+ * association - if it becomes a supported scenario, the WPA/WPA2 keys
|
|
|
+ * must be handled somehow.
|
|
|
+ *
|
|
|
+ */
|
|
|
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
|
|
|
+ wl1271_info("JOIN while associated.");
|
|
|
+
|
|
|
+ if (set_assoc)
|
|
|
+ set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
|
|
+
|
|
|
ret = wl1271_cmd_join(wl, wl->set_bss_type);
|
|
|
if (ret < 0)
|
|
|
goto out;
|
|
@@ -1189,7 +1204,6 @@ static int wl1271_unjoin(struct wl1271 *wl)
|
|
|
goto out;
|
|
|
|
|
|
clear_bit(WL1271_FLAG_JOINED, &wl->flags);
|
|
|
- wl->channel = 0;
|
|
|
memset(wl->bssid, 0, ETH_ALEN);
|
|
|
|
|
|
/* stop filterting packets based on bssid */
|
|
@@ -1249,7 +1263,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
|
goto out;
|
|
|
|
|
|
/* if the channel changes while joined, join again */
|
|
|
- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
|
|
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
|
|
|
+ ((wl->band != conf->channel->band) ||
|
|
|
+ (wl->channel != channel))) {
|
|
|
wl->band = conf->channel->band;
|
|
|
wl->channel = channel;
|
|
|
|
|
@@ -1269,7 +1285,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
|
"failed %d", ret);
|
|
|
|
|
|
if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
|
|
|
- ret = wl1271_join(wl);
|
|
|
+ ret = wl1271_join(wl, false);
|
|
|
if (ret < 0)
|
|
|
wl1271_warning("cmd join to update channel "
|
|
|
"failed %d", ret);
|
|
@@ -1651,6 +1667,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
|
enum wl1271_cmd_ps_mode mode;
|
|
|
struct wl1271 *wl = hw->priv;
|
|
|
bool do_join = false;
|
|
|
+ bool set_assoc = false;
|
|
|
int ret;
|
|
|
|
|
|
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
|
|
@@ -1760,7 +1777,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
|
if (bss_conf->assoc) {
|
|
|
u32 rates;
|
|
|
wl->aid = bss_conf->aid;
|
|
|
- set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
|
|
+ set_assoc = true;
|
|
|
|
|
|
/*
|
|
|
* use basic rates from AP, and determine lowest rate
|
|
@@ -1860,7 +1877,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
|
}
|
|
|
|
|
|
if (do_join) {
|
|
|
- ret = wl1271_join(wl);
|
|
|
+ ret = wl1271_join(wl, set_assoc);
|
|
|
if (ret < 0) {
|
|
|
wl1271_warning("cmd join failed %d", ret);
|
|
|
goto out_sleep;
|