Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
[linux-block.git] / net / mac80211 / mlme.c
index d779c57a82203b23194772565d4e6ba2ed172406..aca22b00b6a327873ee5ffc5a443ae541fdab5ed 100644 (file)
@@ -1102,14 +1102,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
        u32 changed = 0, config_changed = 0;
 
-       rcu_read_lock();
-
-       sta = sta_info_get(local, ifmgd->bssid);
-       if (!sta) {
-               rcu_read_unlock();
-               return;
-       }
-
        if (deauth) {
                ifmgd->direct_probe_tries = 0;
                ifmgd->auth_tries = 0;
@@ -1120,7 +1112,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        netif_tx_stop_all_queues(sdata->dev);
        netif_carrier_off(sdata->dev);
 
-       ieee80211_sta_tear_down_BA_sessions(sta);
+       rcu_read_lock();
+       sta = sta_info_get(local, ifmgd->bssid);
+       if (sta)
+               ieee80211_sta_tear_down_BA_sessions(sta);
+       rcu_read_unlock();
 
        bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
                                   conf->channel->center_freq,
@@ -1156,8 +1152,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
                                ifmgd->ssid, ifmgd->ssid_len);
        }
 
-       rcu_read_unlock();
-
        ieee80211_set_wmm_default(sdata);
 
        ieee80211_recalc_idle(local);
@@ -2223,7 +2217,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
                                       capa_mask, capa_val);
 
        if (bss) {
-               ieee80211_set_freq(sdata, bss->cbss.channel->center_freq);
+               local->oper_channel = bss->cbss.channel;
+               local->oper_channel_type = NL80211_CHAN_NO_HT;
+               ieee80211_hw_config(local, 0);
+
                if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
                        ieee80211_sta_set_ssid(sdata, bss->ssid,
                                               bss->ssid_len);
@@ -2445,6 +2442,14 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
                        ieee80211_set_disassoc(sdata, true, true,
                                               WLAN_REASON_DEAUTH_LEAVING);
 
+               if (ifmgd->ssid_len == 0) {
+                       /*
+                        * Only allow association to be started if a valid SSID
+                        * is configured.
+                        */
+                       return;
+               }
+
                if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
                    ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
                        set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
@@ -2476,6 +2481,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
        ifmgd = &sdata->u.mgd;
 
        if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
+               if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
+                       ieee80211_set_disassoc(sdata, true, true,
+                                              WLAN_REASON_DEAUTH_LEAVING);
+
                /*
                 * Do not use reassociation if SSID is changed (different ESS).
                 */
@@ -2500,6 +2509,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+       if (compare_ether_addr(bssid, ifmgd->bssid) != 0 &&
+           ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
+               ieee80211_set_disassoc(sdata, true, true,
+                                      WLAN_REASON_DEAUTH_LEAVING);
+
        if (is_valid_ether_addr(bssid)) {
                memcpy(ifmgd->bssid, bssid, ETH_ALEN);
                ifmgd->flags |= IEEE80211_STA_BSSID_SET;