Commit 69e5434c authored by Juuso Oikarinen's avatar Juuso Oikarinen Committed by John W. Linville

wl1271: Fix to join and channel number handling

This patch changes the way JOIN's are performed, and channel numbers updated.
The reason for this is that the firmware JOIN command clears WPA(2) key
material, and if done while associated to a WPA(2) secured AP, will render
the data-path unusable.

While the channel is not usually changed while associated (and currently we
could not even support something like that), after performing a scan operation
while associated, mac80211 will re-set the current channel to the driver. This
caused our problem.

Also, the mac80211 is assuming that the driver channel configuration remains
persistent over periods of IDLE. Therefore remove channel resetting to zero
from the unjoin function.
Signed-off-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: default avatarTeemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 554d7209
......@@ -1139,10 +1139,25 @@ static int wl1271_dummy_join(struct wl1271 *wl)
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;
......
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