mac80211: Assign a default mesh beaconing interval.
[pandora-kernel.git] / net / mac80211 / iface.c
index 2f797a8..e8fb03b 100644 (file)
@@ -220,8 +220,10 @@ static int ieee80211_open(struct net_device *dev)
                        local->fif_fcsfail++;
                if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
                        local->fif_plcpfail++;
-               if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+               if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
                        local->fif_control++;
+                       local->fif_pspoll++;
+               }
                if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
                        local->fif_other_bss++;
 
@@ -244,7 +246,14 @@ static int ieee80211_open(struct net_device *dev)
                        spin_unlock_bh(&local->filter_lock);
 
                        ieee80211_start_mesh(sdata);
+               } else if (sdata->vif.type == NL80211_IFTYPE_AP) {
+                       local->fif_pspoll++;
+
+                       spin_lock_bh(&local->filter_lock);
+                       ieee80211_configure_filter(local);
+                       spin_unlock_bh(&local->filter_lock);
                }
+
                changed |= ieee80211_reset_erp_info(sdata);
                ieee80211_bss_info_change_notify(sdata, changed);
                ieee80211_enable_keys(sdata);
@@ -312,7 +321,7 @@ static int ieee80211_open(struct net_device *dev)
         * to fix this.
         */
        if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+               ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
 
        netif_tx_start_all_queues(dev);
 
@@ -335,7 +344,10 @@ static int ieee80211_stop(struct net_device *dev)
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_init_conf conf;
        struct sta_info *sta;
+       unsigned long flags;
+       struct sk_buff *skb, *tmp;
        u32 hw_reconf_flags = 0;
+       int i;
 
        /*
         * Stop TX on this interface first.
@@ -385,6 +397,9 @@ static int ieee80211_stop(struct net_device *dev)
        if (sdata->flags & IEEE80211_SDATA_PROMISC)
                atomic_dec(&local->iff_promiscs);
 
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
+               local->fif_pspoll--;
+
        netif_addr_lock_bh(dev);
        spin_lock_bh(&local->filter_lock);
        __dev_addr_unsync(&local->mc_list, &local->mc_count,
@@ -398,7 +413,7 @@ static int ieee80211_stop(struct net_device *dev)
 
        /* APs need special treatment */
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
-               struct ieee80211_sub_if_data *vlan, *tmp;
+               struct ieee80211_sub_if_data *vlan, *tmpsdata;
                struct beacon_data *old_beacon = sdata->u.ap.beacon;
 
                /* remove beacon */
@@ -407,7 +422,7 @@ static int ieee80211_stop(struct net_device *dev)
                kfree(old_beacon);
 
                /* down all dependent devices, that is VLANs */
-               list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+               list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
                                         u.vlan.list)
                        dev_close(vlan->dev);
                WARN_ON(!list_empty(&sdata->u.ap.vlans));
@@ -436,8 +451,10 @@ static int ieee80211_stop(struct net_device *dev)
                        local->fif_fcsfail--;
                if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
                        local->fif_plcpfail--;
-               if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+               if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
+                       local->fif_pspoll--;
                        local->fif_control--;
+               }
                if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
                        local->fif_other_bss--;
 
@@ -515,10 +532,20 @@ static int ieee80211_stop(struct net_device *dev)
                         * the scan_sdata is NULL already don't send out a
                         * scan event to userspace -- the scan is incomplete.
                         */
-                       if (local->sw_scanning)
+                       if (test_bit(SCAN_SW_SCANNING, &local->scanning))
                                ieee80211_scan_completed(&local->hw, true);
                }
 
+               /*
+                * Disable beaconing for AP and mesh, IBSS can't
+                * still be joined to a network at this point.
+                */
+               if (sdata->vif.type == NL80211_IFTYPE_AP ||
+                   sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+                       ieee80211_bss_info_change_notify(sdata,
+                               BSS_CHANGED_BEACON_ENABLED);
+               }
+
                conf.vif = &sdata->vif;
                conf.type = sdata->vif.type;
                conf.mac_addr = dev->dev_addr;
@@ -538,7 +565,7 @@ static int ieee80211_stop(struct net_device *dev)
 
                ieee80211_led_radio(local, false);
 
-               flush_workqueue(local->hw.workqueue);
+               flush_workqueue(local->workqueue);
 
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
@@ -551,6 +578,18 @@ static int ieee80211_stop(struct net_device *dev)
        if (hw_reconf_flags)
                ieee80211_hw_config(local, hw_reconf_flags);
 
+       spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+       for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
+               skb_queue_walk_safe(&local->pending[i], skb, tmp) {
+                       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+                       if (info->control.vif == &sdata->vif) {
+                               __skb_unlink(skb, &local->pending[i]);
+                               dev_kfree_skb_irq(skb);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
        return 0;
 }
 
@@ -669,7 +708,6 @@ static void ieee80211_if_setup(struct net_device *dev)
 {
        ether_setup(dev);
        dev->netdev_ops = &ieee80211_dataif_ops;
-       dev->wireless_handlers = &ieee80211_iw_handler_def;
        dev->destructor = free_netdev;
 }
 
@@ -772,6 +810,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                            name, ieee80211_if_setup);
        if (!ndev)
                return -ENOMEM;
+       dev_net_set(ndev, wiphy_net(local->hw.wiphy));
 
        ndev->needed_headroom = local->tx_headroom +
                                4*6 /* four MAC addresses */
@@ -788,7 +827,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
        SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
-       ndev->features |= NETIF_F_NETNS_LOCAL;
 
        /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
        sdata = netdev_priv(ndev);
@@ -905,7 +943,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
        struct ieee80211_sub_if_data *sdata;
        int count = 0;
 
-       if (local->hw_scanning || local->sw_scanning)
+       if (local->scanning)
                return ieee80211_idle_off(local, "scanning");
 
        list_for_each_entry(sdata, &local->interfaces, list) {