mac80211: fix key vs. sta locking problems
[linux-block.git] / net / mac80211 / ieee80211_sta.c
index 0e936233dac510ca50f773cd750c14c51f707470..3584a2bf0186cf75521ab96ed3c86a188a697c4a 100644 (file)
@@ -57,8 +57,6 @@
 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
 
 
-#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
-
 #define ERP_INFO_USE_PROTECTION BIT(1)
 
 /* mgmt header + 1 byte action code */
@@ -509,9 +507,14 @@ static void ieee80211_set_associated(struct net_device *dev,
                                           conf->channel->center_freq,
                                           ifsta->ssid, ifsta->ssid_len);
                if (bss) {
+                       /* set timing information */
+                       sdata->bss_conf.beacon_int = bss->beacon_int;
+                       sdata->bss_conf.timestamp = bss->timestamp;
+
                        if (bss->has_erp_value)
                                changed |= ieee80211_handle_erp_ie(
                                                sdata, bss->erp_value);
+
                        ieee80211_rx_bss_put(dev, bss);
                }
 
@@ -539,13 +542,13 @@ static void ieee80211_set_associated(struct net_device *dev,
 
                memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
        }
-       wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-       wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
        ifsta->last_probe = jiffies;
        ieee80211_led_assoc(local, assoc);
 
        sdata->bss_conf.assoc = assoc;
        ieee80211_bss_info_change_notify(sdata, changed);
+       wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+       wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 }
 
 static void ieee80211_set_disassoc(struct net_device *dev,
@@ -949,11 +952,8 @@ static void ieee80211_associated(struct net_device *dev,
 
        rcu_read_unlock();
 
-       if (disassoc && sta) {
-               rtnl_lock();
+       if (disassoc && sta)
                sta_info_destroy(sta);
-               rtnl_unlock();
-       }
 
        if (disassoc) {
                ifsta->state = IEEE80211_DISABLED;
@@ -1275,7 +1275,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
                ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
                                               sta->addr, tid, &start_seq_num);
 #ifdef CONFIG_MAC80211_HT_DEBUG
-       printk(KERN_DEBUG "Rx A-MPDU on tid %d result %d", tid, ret);
+       printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
        if (ret) {
@@ -1430,6 +1430,7 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
        struct ieee80211_hw *hw = &local->hw;
        struct sta_info *sta;
        int ret, i;
+       DECLARE_MAC_BUF(mac);
 
        rcu_read_lock();
 
@@ -1450,12 +1451,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
        sta->ampdu_mlme.tid_state_rx[tid] =
                HT_AGG_STATE_REQ_STOP_BA_MSK |
                (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
-               spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+       spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
 
        /* stop HW Rx aggregation. ampdu_action existence
         * already verified in session init so we add the BUG_ON */
        BUG_ON(!local->ops->ampdu_action);
 
+#ifdef CONFIG_MAC80211_HT_DEBUG
+       printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
+                               print_mac(mac, ra), tid);
+#endif /* CONFIG_MAC80211_HT_DEBUG */
+
        ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
                                        ra, tid, NULL);
        if (ret)
@@ -2033,8 +2039,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        } else
                rcu_read_unlock();
 
-       /* set AID, ieee80211_set_associated() will tell the driver */
+       /* set AID and assoc capability,
+        * ieee80211_set_associated() will tell the driver */
        bss_conf->aid = aid;
+       bss_conf->assoc_capability = capab_info;
        ieee80211_set_associated(dev, ifsta, 1);
 
        ieee80211_associated(dev, ifsta);
@@ -3093,12 +3101,8 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
                }
        spin_unlock_irqrestore(&local->sta_lock, flags);
 
-       synchronize_rcu();
-
-       rtnl_lock();
        list_for_each_entry_safe(sta, tmp, &tmp_list, list)
                sta_info_destroy(sta);
-       rtnl_unlock();
 }
 
 
@@ -4220,3 +4224,26 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
        ieee80211_set_disassoc(dev, ifsta, 0);
        return 0;
 }
+
+void ieee80211_notify_mac(struct ieee80211_hw *hw,
+                         enum ieee80211_notification_types  notif_type)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata;
+
+       switch (notif_type) {
+       case IEEE80211_NOTIFY_RE_ASSOC:
+               rcu_read_lock();
+               list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+
+                       if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+                               ieee80211_sta_req_auth(sdata->dev,
+                                                      &sdata->u.sta);
+                       }
+
+               }
+               rcu_read_unlock();
+               break;
+       }
+}
+EXPORT_SYMBOL(ieee80211_notify_mac);