mac80211: enable assoc check for mesh interfaces
[pandora-kernel.git] / net / mac80211 / main.c
index acb4423..7d9b21d 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/if_arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/bitmap.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/inetdevice.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
        ieee80211_configure_filter(local);
 }
 
-/*
- * Returns true if we are logically configured to be on
- * the operating channel AND the hardware-conf is currently
- * configured on the operating channel.  Compares channel-type
- * as well.
- */
-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
-{
-       struct ieee80211_channel *chan, *scan_chan;
-       enum nl80211_channel_type channel_type;
-
-       /* This logic needs to match logic in ieee80211_hw_config */
-       if (local->scan_channel) {
-               chan = local->scan_channel;
-               /* If scanning on oper channel, use whatever channel-type
-                * is currently in use.
-                */
-               if (chan == local->oper_channel)
-                       channel_type = local->_oper_channel_type;
-               else
-                       channel_type = NL80211_CHAN_NO_HT;
-       } else if (local->tmp_channel) {
-               chan = scan_chan = local->tmp_channel;
-               channel_type = local->tmp_channel_type;
-       } else {
-               chan = local->oper_channel;
-               channel_type = local->_oper_channel_type;
-       }
-
-       if (chan != local->oper_channel ||
-           channel_type != local->_oper_channel_type)
-               return false;
-
-       /* Check current hardware-config against oper_channel. */
-       if ((local->oper_channel != local->hw.conf.channel) ||
-           (local->_oper_channel_type != local->hw.conf.channel_type))
-               return false;
-
-       return true;
-}
-
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
        struct ieee80211_channel *chan, *scan_chan;
@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 
        scan_chan = local->scan_channel;
 
-       /* If this off-channel logic ever changes,  ieee80211_on_oper_channel
-        * may need to change as well.
-        */
        offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
        if (scan_chan) {
                chan = scan_chan;
@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                        channel_type = local->_oper_channel_type;
                else
                        channel_type = NL80211_CHAN_NO_HT;
-       } else if (local->tmp_channel) {
+               local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+       } else if (local->tmp_channel &&
+                  local->oper_channel != local->tmp_channel) {
                chan = scan_chan = local->tmp_channel;
                channel_type = local->tmp_channel_type;
+               local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
        } else {
                chan = local->oper_channel;
                channel_type = local->_oper_channel_type;
-       }
-
-       if (chan != local->oper_channel ||
-           channel_type != local->_oper_channel_type)
-               local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
-       else
                local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
+       }
 
        offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 
@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 
        if (changed & BSS_CHANGED_BEACON_ENABLED) {
                if (local->quiescing || !ieee80211_sdata_running(sdata) ||
-                   test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
+                   test_bit(SCAN_SW_SCANNING, &local->scanning)) {
                        sdata->vif.bss_conf.enable_beacon = false;
                } else {
                        /*
@@ -325,6 +279,8 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
 static void ieee80211_tasklet_handler(unsigned long data)
 {
        struct ieee80211_local *local = (struct ieee80211_local *) data;
+       struct sta_info *sta, *tmp;
+       struct skb_eosp_msg_data *eosp_data;
        struct sk_buff *skb;
 
        while ((skb = skb_dequeue(&local->skb_queue)) ||
@@ -340,6 +296,18 @@ static void ieee80211_tasklet_handler(unsigned long data)
                        skb->pkt_type = 0;
                        ieee80211_tx_status(local_to_hw(local), skb);
                        break;
+               case IEEE80211_EOSP_MSG:
+                       eosp_data = (void *)skb->cb;
+                       for_each_sta_info(local, eosp_data->sta, sta, tmp) {
+                               /* skip wrong virtual interface */
+                               if (memcmp(eosp_data->iface,
+                                          sta->sdata->vif.addr, ETH_ALEN))
+                                       continue;
+                               clear_sta_flag(sta, WLAN_STA_SP);
+                               break;
+                       }
+                       dev_kfree_skb(skb);
+                       break;
                default:
                        WARN(1, "mac80211: Packet is of unknown type %d\n",
                             skb->pkt_type);
@@ -608,6 +576,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        local->hw.max_rates = 1;
        local->hw.max_report_rates = 0;
        local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
+       local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
        local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
        local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
        local->user_power_level = -1;
@@ -742,6 +711,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (!local->int_scan_req)
                return -ENOMEM;
 
+       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               if (!local->hw.wiphy->bands[band])
+                       continue;
+               local->int_scan_req->rates[band] = (u32) -1;
+       }
+
        /* if low-level driver supports AP, we also support VLAN */
        if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
                hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
@@ -862,6 +837,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (local->ops->sched_scan_start)
                local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 
+       /* mac80211 based drivers don't support internal TDLS setup */
+       if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
+               local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+
        result = wiphy_register(local->hw.wiphy);
        if (result < 0)
                goto fail_wiphy_register;
@@ -885,12 +864,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
         * and we need some headroom for passing the frame to monitor
         * interfaces, but never both at the same time.
         */
-#ifndef __CHECKER__
-       BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
-                       sizeof(struct ieee80211_tx_status_rtap_hdr));
-#endif
        local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
-                                  sizeof(struct ieee80211_tx_status_rtap_hdr));
+                                  IEEE80211_TX_STATUS_HEADROOM);
 
        debugfs_hw_add(local);
 
@@ -910,6 +885,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                            result);
 
+       ieee80211_led_init(local);
+
        rtnl_lock();
 
        result = ieee80211_init_rate_ctrl_alg(local,
@@ -931,8 +908,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        rtnl_unlock();
 
-       ieee80211_led_init(local);
-
        local->network_latency_notifier.notifier_call =
                ieee80211_max_network_latency;
        result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,