nfsd4: allow 4.0 clients to change callback path
[safe/jmp/linux-2.6] / net / mac80211 / main.c
index 8084b62..06c33b6 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
-#include <linux/wireless.h>
 #include <linux/rtnetlink.h>
 #include <linux/bitmap.h>
 #include <linux/pm_qos_params.h>
 #include "led.h"
 #include "cfg.h"
 #include "debugfs.h"
-#include "debugfs_netdev.h"
+
+
+bool ieee80211_disable_40mhz_24ghz;
+module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
+MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
+                "Disable 40MHz support in the 2.4GHz band");
 
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
@@ -102,6 +106,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
        if (scan_chan) {
                chan = scan_chan;
                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;
@@ -114,6 +121,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                changed |= IEEE80211_CONF_CHANGE_CHANNEL;
        }
 
+       if (!conf_is_ht(&local->hw.conf)) {
+               /*
+                * mac80211.h documents that this is only valid
+                * when the channel is set to an HT type, and
+                * that otherwise STATIC is used.
+                */
+               local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC;
+       } else if (local->hw.conf.smps_mode != local->smps_mode) {
+               local->hw.conf.smps_mode = local->smps_mode;
+               changed |= IEEE80211_CONF_CHANGE_SMPS;
+       }
+
        if (scan_chan)
                power = chan->max_power;
        else
@@ -173,7 +192,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
                sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
        else if (sdata->vif.type == NL80211_IFTYPE_AP)
-               sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
+               sdata->vif.bss_conf.bssid = sdata->vif.addr;
        else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                sdata->vif.bss_conf.bssid = zero;
        } else {
@@ -195,7 +214,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
        }
 
        if (changed & BSS_CHANGED_BEACON_ENABLED) {
-               if (local->quiescing || !netif_running(sdata->dev) ||
+               if (local->quiescing || !ieee80211_sdata_running(sdata) ||
                    test_bit(SCAN_SW_SCANNING, &local->scanning)) {
                        sdata->vif.bss_conf.enable_beacon = false;
                } else {
@@ -223,8 +242,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       drv_bss_info_changed(local, &sdata->vif,
-                            &sdata->vif.bss_conf, changed);
+       drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
 }
 
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -299,6 +317,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_restart_hw);
 
+static void ieee80211_recalc_smps_work(struct work_struct *work)
+{
+       struct ieee80211_local *local =
+               container_of(work, struct ieee80211_local, recalc_smps);
+
+       mutex_lock(&local->iflist_mtx);
+       ieee80211_recalc_smps(local, NULL);
+       mutex_unlock(&local->iflist_mtx);
+}
+
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
                                        const struct ieee80211_ops *ops)
 {
@@ -328,12 +356,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        if (!wiphy)
                return NULL;
 
-       wiphy->flags |= WIPHY_FLAG_NETNS_OK;
+       wiphy->flags |= WIPHY_FLAG_NETNS_OK |
+                       WIPHY_FLAG_4ADDR_AP |
+                       WIPHY_FLAG_4ADDR_STATION;
        wiphy->privid = mac80211_wiphy_privid;
 
-       /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
-       wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
-                              sizeof(struct cfg80211_bss);
+       wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
 
        local = wiphy_priv(wiphy);
 
@@ -356,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        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;
+       local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+       local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
 
        INIT_LIST_HEAD(&local->interfaces);
        mutex_init(&local->iflist_mtx);
@@ -367,9 +397,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 
        INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
 
+       ieee80211_work_init(local);
+
        INIT_WORK(&local->restart_work, ieee80211_restart_work);
 
        INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
+       INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
+       local->smps_mode = IEEE80211_SMPS_OFF;
 
        INIT_WORK(&local->dynamic_ps_enable_work,
                  ieee80211_dynamic_ps_enable_work);
@@ -459,6 +493,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
                local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
 
+       WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
+            && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
+            "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
+
        /*
         * Calculate scan IE length -- we need this to alloc
         * memory and to subtract from the driver limit. It
@@ -513,13 +551,19 @@ 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.
         */
+       BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
+                       sizeof(struct ieee80211_tx_status_rtap_hdr));
        local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
                                   sizeof(struct ieee80211_tx_status_rtap_hdr));
 
        debugfs_hw_add(local);
 
+       /*
+        * if the driver doesn't specify a max listen interval we
+        * use 5 which should be a safe default
+        */
        if (local->hw.max_listen_interval == 0)
-               local->hw.max_listen_interval = 1;
+               local->hw.max_listen_interval = 5;
 
        local->hw.conf.listen_interval = local->hw.max_listen_interval;
 
@@ -629,8 +673,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
        sta_info_stop(local);
        rate_control_deinitialize(local);
 
-       if (skb_queue_len(&local->skb_queue)
-                       || skb_queue_len(&local->skb_queue_unreliable))
+       if (skb_queue_len(&local->skb_queue) ||
+           skb_queue_len(&local->skb_queue_unreliable))
                printk(KERN_WARNING "%s: skb_queue not empty\n",
                       wiphy_name(local->hw.wiphy));
        skb_queue_purge(&local->skb_queue);
@@ -670,11 +714,19 @@ static int __init ieee80211_init(void)
 
        ret = rc80211_pid_init();
        if (ret)
-               return ret;
+               goto err_pid;
 
-       ieee80211_debugfs_netdev_init();
+       ret = ieee80211_iface_init();
+       if (ret)
+               goto err_netdev;
 
        return 0;
+ err_netdev:
+       rc80211_pid_exit();
+ err_pid:
+       rc80211_minstrel_exit();
+
+       return ret;
 }
 
 static void __exit ieee80211_exit(void)
@@ -691,7 +743,7 @@ static void __exit ieee80211_exit(void)
        if (mesh_allocated)
                ieee80211s_stop();
 
-       ieee80211_debugfs_netdev_exit();
+       ieee80211_iface_exit();
 }