sdhci-pltfm: implement platform data passing
[safe/jmp/linux-2.6] / net / mac80211 / main.c
index dbf05b4..22a384d 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 "cfg.h"
 #include "debugfs.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)
 {
        u64 mc;
@@ -66,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
        spin_lock_bh(&local->filter_lock);
        changed_flags = local->filter_flags ^ new_flags;
 
-       mc = drv_prepare_multicast(local, local->mc_count, local->mc_list);
+       mc = drv_prepare_multicast(local, &local->mc_list);
        spin_unlock_bh(&local->filter_lock);
 
        /* be a bit nasty */
@@ -101,9 +106,12 @@ 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;
+               channel_type = local->_oper_channel_type;
        }
 
        if (chan != local->hw.conf.channel ||
@@ -113,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
@@ -194,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 {
@@ -205,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
                        switch (sdata->vif.type) {
                        case NL80211_IFTYPE_AP:
                                sdata->vif.bss_conf.enable_beacon =
-                                       !!rcu_dereference(sdata->u.ap.beacon);
+                                       !!sdata->u.ap.beacon;
                                break;
                        case NL80211_IFTYPE_ADHOC:
                                sdata->vif.bss_conf.enable_beacon =
-                                       !!rcu_dereference(sdata->u.ibss.presp);
+                                       !!sdata->u.ibss.presp;
                                break;
                        case NL80211_IFTYPE_MESH_POINT:
                                sdata->vif.bss_conf.enable_beacon = true;
@@ -222,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)
@@ -290,6 +309,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 {
        struct ieee80211_local *local = hw_to_local(hw);
 
+       trace_api_restart_hw(local);
+
        /* use this reason, __ieee80211_resume will unblock it */
        ieee80211_stop_queues_by_reason(hw,
                IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -298,6 +319,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)
 {
@@ -332,9 +363,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
                        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);
 
@@ -357,8 +386,13 @@ 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);
+
+       __hw_addr_init(&local->mc_list);
+
        mutex_init(&local->iflist_mtx);
        mutex_init(&local->scan_mtx);
 
@@ -368,9 +402,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);
@@ -404,7 +442,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        struct ieee80211_local *local = hw_to_local(hw);
        int result;
        enum ieee80211_band band;
-       int channels, i, j, max_bitrates;
+       int channels, max_bitrates;
        bool supp_ht;
        static const u32 cipher_suites[] = {
                WLAN_CIPHER_SUITE_WEP40,
@@ -460,6 +498,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
@@ -514,16 +556,24 @@ 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;
 
+       local->hw.conf.dynamic_ps_forced_timeout = -1;
+
        result = sta_info_start(local);
        if (result < 0)
                goto fail_sta_info;
@@ -558,21 +608,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        ieee80211_led_init(local);
 
-       /* alloc internal scan request */
-       i = 0;
-       local->int_scan_req->ssids = &local->scan_ssid;
-       local->int_scan_req->n_ssids = 1;
-       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-               if (!hw->wiphy->bands[band])
-                       continue;
-               for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
-                       local->int_scan_req->channels[i] =
-                               &hw->wiphy->bands[band]->channels[j];
-                       i++;
-               }
-       }
-       local->int_scan_req->n_channels = i;
-
        local->network_latency_notifier.notifier_call =
                ieee80211_max_network_latency;
        result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,