netfilter: xt_RATEEST: acquire xt_rateest_mutex for hash insert
[pandora-kernel.git] / net / mac80211 / mlme.c
index 72c8bea..ef00f24 100644 (file)
@@ -1487,6 +1487,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
        int i, j, err;
        bool have_higher_than_11mbit = false;
        u16 ap_ht_cap_flags;
+       int min_rate = INT_MAX, min_rate_index = -1;
 
        /* AssocResp and ReassocResp have identical structure */
 
@@ -1553,6 +1554,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
@@ -1570,11 +1575,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
        }
 
+       /*
+        * some buggy APs don't advertise basic_rates. use the lowest
+        * supported rate instead.
+        */
+       if (unlikely(!basic_rates) && min_rate_index >= 0) {
+               printk(KERN_DEBUG "%s: No basic rates in AssocResp. "
+                      "Using min supported rate instead.\n", sdata->name);
+               basic_rates = BIT(min_rate_index);
+       }
+
        sta->sta.supp_rates[wk->chan->band] = rates;
        sdata->vif.bss_conf.basic_rates = basic_rates;
 
@@ -1821,7 +1840,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
        if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
            ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
-               int sig = ifmgd->ave_beacon_signal;
+               int sig = ifmgd->ave_beacon_signal / 16;
                int last_sig = ifmgd->last_ave_beacon_signal;
 
                /*
@@ -2269,6 +2288,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 
        cancel_work_sync(&ifmgd->request_smps_work);
 
+       cancel_work_sync(&ifmgd->monitor_work);
        cancel_work_sync(&ifmgd->beacon_connection_loss_work);
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -2277,7 +2297,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        if (del_timer_sync(&ifmgd->chswitch_timer))
                set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
 
-       cancel_work_sync(&ifmgd->monitor_work);
        /* these will just be re-established on connection */
        del_timer_sync(&ifmgd->conn_mon_timer);
        del_timer_sync(&ifmgd->bcn_mon_timer);
@@ -2700,7 +2719,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       struct ieee80211_work *wk;
        u8 bssid[ETH_ALEN];
        bool assoc_bss = false;
 
@@ -2713,30 +2731,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                assoc_bss = true;
        } else {
                bool not_auth_yet = false;
+               struct ieee80211_work *tmp, *wk = NULL;
 
                mutex_unlock(&ifmgd->mtx);
 
                mutex_lock(&local->mtx);
-               list_for_each_entry(wk, &local->work_list, list) {
-                       if (wk->sdata != sdata)
+               list_for_each_entry(tmp, &local->work_list, list) {
+                       if (tmp->sdata != sdata)
                                continue;
 
-                       if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
-                           wk->type != IEEE80211_WORK_AUTH &&
-                           wk->type != IEEE80211_WORK_ASSOC &&
-                           wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
+                       if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
+                           tmp->type != IEEE80211_WORK_AUTH &&
+                           tmp->type != IEEE80211_WORK_ASSOC &&
+                           tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
                                continue;
 
-                       if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
+                       if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
                                continue;
 
-                       not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
-                       list_del_rcu(&wk->list);
-                       free_work(wk);
+                       not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
+                       list_del_rcu(&tmp->list);
+                       synchronize_rcu();
+                       wk = tmp;
                        break;
                }
                mutex_unlock(&local->mtx);
 
+               if (wk && wk->type == IEEE80211_WORK_ASSOC) {
+                       /* clean up dummy sta & TX sync */
+                       sta_info_destroy_addr(wk->sdata, wk->filter_ta);
+                       if (wk->assoc.synced)
+                               drv_finish_tx_sync(local, wk->sdata,
+                                                  wk->filter_ta,
+                                                  IEEE80211_TX_SYNC_ASSOC);
+               } else if (wk && wk->type == IEEE80211_WORK_AUTH) {
+                       if (wk->probe_auth.synced)
+                               drv_finish_tx_sync(local, wk->sdata,
+                                                  wk->filter_ta,
+                                                  IEEE80211_TX_SYNC_AUTH);
+               }
+               kfree(wk);
+
                /*
                 * If somebody requests authentication and we haven't
                 * sent out an auth frame yet there's no need to send