mac80211: introduce hw config change flags
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / iface.c
index b5cd91e8971292d3342d63d828f45f761ece7da6..df28c5f7c9c0a2695f049fb6bb910b11a9886d62 100644 (file)
@@ -58,17 +58,16 @@ static inline int identical_mac_addr_allowed(int type1, int type2)
 
 static int ieee80211_open(struct net_device *dev)
 {
-       struct ieee80211_sub_if_data *sdata, *nsdata;
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *nsdata;
+       struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
        struct ieee80211_if_init_conf conf;
        u32 changed = 0;
        int res;
-       bool need_hw_reconfig = 0;
+       u32 hw_reconf_flags = 0;
        u8 null_addr[ETH_ALEN] = {0};
 
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
        /* fail early if user set an invalid address */
        if (compare_ether_addr(dev->dev_addr, null_addr) &&
            !is_valid_ether_addr(dev->dev_addr))
@@ -153,7 +152,8 @@ static int ieee80211_open(struct net_device *dev)
                        res = local->ops->start(local_to_hw(local));
                if (res)
                        goto err_del_bss;
-               need_hw_reconfig = 1;
+               /* we're brought up, everything changes */
+               hw_reconf_flags = ~0;
                ieee80211_led_radio(local, local->hw.conf.radio_enabled);
        }
 
@@ -199,8 +199,10 @@ static int ieee80211_open(struct net_device *dev)
 
                /* must be before the call to ieee80211_configure_filter */
                local->monitors++;
-               if (local->monitors == 1)
+               if (local->monitors == 1) {
                        local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+                       hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+               }
 
                if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
                        local->fif_fcsfail++;
@@ -280,8 +282,8 @@ static int ieee80211_open(struct net_device *dev)
                atomic_inc(&local->iff_promiscs);
 
        local->open_count++;
-       if (need_hw_reconfig) {
-               ieee80211_hw_config(local);
+       if (hw_reconf_flags) {
+               ieee80211_hw_config(local, hw_reconf_flags);
                /*
                 * set default queue parameters so drivers don't
                 * need to initialise the hardware if the hardware
@@ -323,6 +325,7 @@ static int ieee80211_stop(struct net_device *dev)
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_init_conf conf;
        struct sta_info *sta;
+       u32 hw_reconf_flags = 0;
 
        /*
         * Stop TX on this interface first.
@@ -406,8 +409,10 @@ static int ieee80211_stop(struct net_device *dev)
                }
 
                local->monitors--;
-               if (local->monitors == 0)
+               if (local->monitors == 0) {
                        local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+                       hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+               }
 
                if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
                        local->fif_fcsfail--;
@@ -505,15 +510,22 @@ static int ieee80211_stop(struct net_device *dev)
 
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
+
+               /* no reconfiguring after stop! */
+               hw_reconf_flags = 0;
        }
 
+       /* do after stop to avoid reconfiguring when we stop anyway */
+       if (hw_reconf_flags)
+               ieee80211_hw_config(local, hw_reconf_flags);
+
        return 0;
 }
 
 static void ieee80211_set_multicast_list(struct net_device *dev)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        int allmulti, promisc, sdata_allmulti, sdata_promisc;
 
        allmulti = !!(dev->flags & IFF_ALLMULTI);