bridge: Forward reserved group addresses if !STP
[pandora-kernel.git] / net / mac80211 / main.c
index a06b6ee..22bc42b 100644 (file)
@@ -54,6 +54,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
        if (local->monitors || local->scanning)
                new_flags |= FIF_BCN_PRBRESP_PROMISC;
 
+       if (local->fif_probe_req || local->probe_req_reg)
+               new_flags |= FIF_PROBE_REQ;
+
        if (local->fif_fcsfail)
                new_flags |= FIF_FCSFAIL;
 
@@ -110,7 +113,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                chan = scan_chan;
                channel_type = NL80211_CHAN_NO_HT;
                local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
-       } else if (local->tmp_channel) {
+       } 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;
@@ -200,6 +204,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
        else if (sdata->vif.type == NL80211_IFTYPE_AP)
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
+       else if (sdata->vif.type == NL80211_IFTYPE_WDS)
+               sdata->vif.bss_conf.bssid = NULL;
        else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                sdata->vif.bss_conf.bssid = zero;
        } else {
@@ -210,6 +216,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_WDS:
        case NL80211_IFTYPE_MESH_POINT:
                break;
        default:
@@ -294,7 +301,16 @@ static void ieee80211_restart_work(struct work_struct *work)
        struct ieee80211_local *local =
                container_of(work, struct ieee80211_local, restart_work);
 
+       /* wait for scan work complete */
+       flush_workqueue(local->workqueue);
+
+       mutex_lock(&local->mtx);
+       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+               "%s called with hardware scan in progress\n", __func__);
+       mutex_unlock(&local->mtx);
+
        rtnl_lock();
+       ieee80211_scan_cancel(local);
        ieee80211_reconfig(local);
        rtnl_unlock();
 }
@@ -305,12 +321,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 
        trace_api_restart_hw(local);
 
-       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
-               "%s called with hardware scan in progress\n", __func__);
-
-       if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)))
-               ieee80211_scan_cancel(local);
-
        /* use this reason, ieee80211_reconfig will unblock it */
        ieee80211_stop_queues_by_reason(hw,
                IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -325,7 +335,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
                container_of(work, struct ieee80211_local, recalc_smps);
 
        mutex_lock(&local->iflist_mtx);
-       ieee80211_recalc_smps(local, NULL);
+       ieee80211_recalc_smps(local);
        mutex_unlock(&local->iflist_mtx);
 }
 
@@ -362,7 +372,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return NOTIFY_DONE;
 
-       idev = sdata->dev->ip_ptr;
+       idev = __in_dev_get_rtnl(sdata->dev);
        if (!idev)
                return NOTIFY_DONE;
 
@@ -456,6 +466,21 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
                        BIT(IEEE80211_STYPE_DEAUTH >> 4) |
                        BIT(IEEE80211_STYPE_ACTION >> 4),
        },
+       [NL80211_IFTYPE_P2P_CLIENT] = {
+               .tx = 0xffff,
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                       BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+       [NL80211_IFTYPE_P2P_GO] = {
+               .tx = 0xffff,
+               .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+                       BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+                       BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+                       BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+                       BIT(IEEE80211_STYPE_AUTH >> 4) |
+                       BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+                       BIT(IEEE80211_STYPE_ACTION >> 4),
+       },
 };
 
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
@@ -514,6 +539,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        /* set up some defaults */
        local->hw.queues = 1;
        local->hw.max_rates = 1;
+       local->hw.max_report_rates = 0;
        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;
@@ -589,6 +615,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                WLAN_CIPHER_SUITE_AES_CMAC
        };
 
+       if (hw->max_report_rates == 0)
+               hw->max_report_rates = hw->max_rates;
+
        /*
         * generic code guarantees at least one band,
         * set this very early because much code assumes
@@ -850,6 +879,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        rtnl_unlock();
 
+       /*
+        * Now all work items will be gone, but the
+        * timer might still be armed, so delete it
+        */
+       del_timer_sync(&local->work_timer);
+
        cancel_work_sync(&local->restart_work);
        cancel_work_sync(&local->reconfig_filter);