diff options
author | Luciano Coelho <luciano.coelho@nokia.com> | 2009-12-11 08:40:44 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-12-28 16:31:30 -0500 |
commit | c7f43e451ba40e66a89d51e63bc21a57824592f2 (patch) | |
tree | 46a80f951df813ff636023c490bd8d68916041de | |
parent | cf18be4467b5aca1ccf3b5a72b67fc33a0b30c59 (diff) |
wl1271: use join command with dummy BSSID
When we need to change the channel before association, we have to send a join
command with a valid BSSID. With this patch we use 0baddeadbeef as the
BSSID. There are ongoing discussions with TI to get this done in a cleaner
way.
When we go back to idle, we issue a CMD_DISCONNECT to make sure the firmware
stops listening to the channel and cleans things up internally.
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 75 |
1 files changed, 65 insertions, 10 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f1cb7cbd7c1c..f6d42e613a56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1130,6 +1130,47 @@ out: | |||
1130 | } | 1130 | } |
1131 | #endif | 1131 | #endif |
1132 | 1132 | ||
1133 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1134 | { | ||
1135 | int ret; | ||
1136 | /* we need to use a dummy BSSID for now */ | ||
1137 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1138 | 0xad, 0xbe, 0xef }; | ||
1139 | |||
1140 | /* disable mac filter, so we hear everything */ | ||
1141 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1142 | |||
1143 | wl->channel = channel; | ||
1144 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1145 | |||
1146 | ret = wl1271_cmd_join(wl); | ||
1147 | if (ret < 0) | ||
1148 | goto out; | ||
1149 | |||
1150 | wl->joined = true; | ||
1151 | |||
1152 | out: | ||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1157 | { | ||
1158 | int ret; | ||
1159 | |||
1160 | /* to stop listening to a channel, we disconnect */ | ||
1161 | ret = wl1271_cmd_disconnect(wl); | ||
1162 | if (ret < 0) | ||
1163 | goto out; | ||
1164 | |||
1165 | wl->joined = false; | ||
1166 | wl->channel = 0; | ||
1167 | memset(wl->bssid, 0, ETH_ALEN); | ||
1168 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1169 | |||
1170 | out: | ||
1171 | return ret; | ||
1172 | } | ||
1173 | |||
1133 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1174 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1134 | { | 1175 | { |
1135 | struct wl1271 *wl = hw->priv; | 1176 | struct wl1271 *wl = hw->priv; |
@@ -1138,10 +1179,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1138 | 1179 | ||
1139 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1180 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1140 | 1181 | ||
1141 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1182 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1142 | channel, | 1183 | channel, |
1143 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1184 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1144 | conf->power_level); | 1185 | conf->power_level, |
1186 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1145 | 1187 | ||
1146 | mutex_lock(&wl->mutex); | 1188 | mutex_lock(&wl->mutex); |
1147 | 1189 | ||
@@ -1151,16 +1193,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1151 | if (ret < 0) | 1193 | if (ret < 0) |
1152 | goto out; | 1194 | goto out; |
1153 | 1195 | ||
1154 | if (channel != wl->channel) { | 1196 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1155 | /* | 1197 | if (conf->flags & IEEE80211_CONF_IDLE && wl->joined) |
1156 | * We assume that the stack will configure the right channel | 1198 | wl1271_unjoin_channel(wl); |
1157 | * before associating, so we don't need to send a join | 1199 | else |
1158 | * command here. We will join the right channel when the | 1200 | wl1271_join_channel(wl, channel); |
1159 | * BSSID changes | ||
1160 | */ | ||
1161 | wl->channel = channel; | ||
1162 | } | 1201 | } |
1163 | 1202 | ||
1203 | /* if the channel changes while joined, join again */ | ||
1204 | if (channel != wl->channel && wl->joined) | ||
1205 | wl1271_join_channel(wl, channel); | ||
1206 | |||
1164 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1207 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { |
1165 | wl1271_info("psm enabled"); | 1208 | wl1271_info("psm enabled"); |
1166 | 1209 | ||
@@ -1494,6 +1537,18 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1494 | if (ret < 0) | 1537 | if (ret < 0) |
1495 | goto out; | 1538 | goto out; |
1496 | 1539 | ||
1540 | if ((changed & BSS_CHANGED_BSSID) && | ||
1541 | /* | ||
1542 | * Now we know the correct bssid, so we send a new join command | ||
1543 | * and enable the BSSID filter | ||
1544 | */ | ||
1545 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1546 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1547 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1548 | wl1271_cmd_join(wl); | ||
1549 | wl->joined = true; | ||
1550 | } | ||
1551 | |||
1497 | if (changed & BSS_CHANGED_ASSOC) { | 1552 | if (changed & BSS_CHANGED_ASSOC) { |
1498 | if (bss_conf->assoc) { | 1553 | if (bss_conf->assoc) { |
1499 | wl->aid = bss_conf->aid; | 1554 | wl->aid = bss_conf->aid; |