mac80211: clarify interface iteration and make it configurable
authorJohannes Berg <johannes.berg@intel.com>
Tue, 6 Nov 2012 19:23:30 +0000 (20:23 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 9 Nov 2012 16:34:35 +0000 (17:34 +0100)
During hardware restart, all interfaces are iterated even
though they haven't been re-added to the driver, document
this behaviour. The same also happens during resume, which
is even more confusing since all of the interfaces were
previously removed from the driver. Make this optional so
drivers relying on the current behaviour can still use it,
but to let drivers that don't want this behaviour disable
it.

Also convert all API users, keeping the old semantics
except in hwsim, where the new normal ones are desired.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/ti/wlcore/main.c
include/net/mac80211.h
net/mac80211/util.c

index 9f31cfa56cc092cfb9dca9647b3ef7aad62175c4..cdd19232960c2541ad8eca48c5b008b397448f37 100644 (file)
@@ -511,8 +511,9 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
                ath5k_vif_iter(&iter_data, vif->addr, vif);
 
        /* Get list of all active MAC addresses */
-       ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-                                                  &iter_data);
+       ieee80211_iterate_active_interfaces_atomic(
+               ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath5k_vif_iter, &iter_data);
        memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
 
        ah->opmode = iter_data.opmode;
@@ -3045,8 +3046,9 @@ ath5k_any_vif_assoc(struct ath5k_hw *ah)
        iter_data.need_set_hw_addr = false;
        iter_data.found_active = true;
 
-       ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-                                                  &iter_data);
+       ieee80211_iterate_active_interfaces_atomic(
+               ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath5k_vif_iter, &iter_data);
        return iter_data.any_assoc;
 }
 
index 7a28538e6e05ba6c001e9b04aa913955a339ac44..1ea8c8795c8efeb1ed2e7b5ffacef643609a0885 100644 (file)
@@ -452,8 +452,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
        iter_data.hw_macaddr = NULL;
        iter_data.n_stas = 0;
        iter_data.need_set_hw_addr = false;
-       ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-                                                  &iter_data);
+       ieee80211_iterate_active_interfaces_atomic(
+               ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath5k_vif_iter, &iter_data);
 
        /* Set up RX Filter */
        if (iter_data.n_stas > 1) {
index f42d2eb6af99302f449ef44beac8f0120238e73d..1318d79f5c44a59a9c3b91fdffcf78afed7c78a7 100644 (file)
@@ -587,9 +587,9 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
            (priv->num_sta_vif > 1) &&
            (vif->type == NL80211_IFTYPE_STATION)) {
                beacon_configured = false;
-               ieee80211_iterate_active_interfaces_atomic(priv->hw,
-                                                          ath9k_htc_beacon_iter,
-                                                          &beacon_configured);
+               ieee80211_iterate_active_interfaces_atomic(
+                       priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       ath9k_htc_beacon_iter, &beacon_configured);
 
                if (beacon_configured) {
                        ath_dbg(common, CONFIG,
index 66f6a74c508efe40dd899e6e2e9b2decbc616368..02cce95331d80e9b0c8970f882750dfdf7664f0b 100644 (file)
@@ -127,8 +127,9 @@ static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
        priv->rearm_ani = false;
        priv->reconfig_beacon = false;
 
-       ieee80211_iterate_active_interfaces_atomic(priv->hw,
-                                                  ath9k_htc_vif_iter, priv);
+       ieee80211_iterate_active_interfaces_atomic(
+               priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath9k_htc_vif_iter, priv);
        if (priv->rearm_ani)
                ath9k_htc_start_ani(priv);
 
@@ -165,8 +166,9 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
 
        /* Get list of all active MAC addresses */
-       ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
-                                                  &iter_data);
+       ieee80211_iterate_active_interfaces_atomic(
+               priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
        ath_hw_setbssidmask(common);
@@ -1144,8 +1146,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
         */
        if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
                priv->rearm_ani = false;
-               ieee80211_iterate_active_interfaces_atomic(priv->hw,
-                                                  ath9k_htc_vif_iter, priv);
+               ieee80211_iterate_active_interfaces_atomic(
+                       priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       ath9k_htc_vif_iter, priv);
                if (!priv->rearm_ani)
                        ath9k_htc_stop_ani(priv);
        }
@@ -1466,8 +1469,9 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
 {
        if (priv->num_sta_assoc_vif == 1) {
-               ieee80211_iterate_active_interfaces_atomic(priv->hw,
-                                                          ath9k_htc_bss_iter, priv);
+               ieee80211_iterate_active_interfaces_atomic(
+                       priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       ath9k_htc_bss_iter, priv);
                ath9k_htc_set_bssid(priv);
        }
 }
index 578a7234aa56dd6f10343c6564c9ae3f430c3646..c084532291a1ec7efcd3237a394aa5f6440de318 100644 (file)
@@ -924,8 +924,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
                ath9k_vif_iter(iter_data, vif->addr, vif);
 
        /* Get list of all active MAC addresses */
-       ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
-                                                  iter_data);
+       ieee80211_iterate_active_interfaces_atomic(
+               sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               ath9k_vif_iter, iter_data);
 }
 
 /* Called with sc->mutex held. */
@@ -975,8 +976,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
        if (ah->opmode == NL80211_IFTYPE_STATION &&
            old_opmode == NL80211_IFTYPE_AP &&
            test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
-               ieee80211_iterate_active_interfaces_atomic(sc->hw,
-                                                  ath9k_sta_vif_iter, sc);
+               ieee80211_iterate_active_interfaces_atomic(
+                       sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       ath9k_sta_vif_iter, sc);
        }
 }
 
@@ -1505,8 +1507,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
                                clear_bit(SC_OP_BEACONS, &sc->sc_flags);
                }
 
-               ieee80211_iterate_active_interfaces_atomic(sc->hw,
-                                                  ath9k_bss_assoc_iter, sc);
+               ieee80211_iterate_active_interfaces_atomic(
+                       sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       ath9k_bss_assoc_iter, sc);
 
                if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
                    ah->opmode == NL80211_IFTYPE_STATION) {
index 9b4f76718db72f1b2a5d31e5cf625351506534bf..a8ec7086ad09b063ac3a78891c361aa0c063c9ba 100644 (file)
@@ -571,6 +571,7 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
        md.ret = false;
        md.addr = addr;
        ieee80211_iterate_active_interfaces_atomic(data->hw,
+                                                  IEEE80211_IFACE_ITER_NORMAL,
                                                   mac80211_hwsim_addr_iter,
                                                   &md);
 
@@ -744,8 +745,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
                if (!hwsim_chans_compat(chan, data2->tmp_chan) &&
                    !hwsim_chans_compat(chan, data2->channel)) {
                        ieee80211_iterate_active_interfaces_atomic(
-                               data2->hw, mac80211_hwsim_tx_iter,
-                               &tx_iter_data);
+                               data2->hw, IEEE80211_IFACE_ITER_NORMAL,
+                               mac80211_hwsim_tx_iter, &tx_iter_data);
                        if (!tx_iter_data.receive)
                                continue;
                }
@@ -958,7 +959,8 @@ static void mac80211_hwsim_beacon(unsigned long arg)
                return;
 
        ieee80211_iterate_active_interfaces_atomic(
-               hw, mac80211_hwsim_beacon_tx, hw);
+               hw, IEEE80211_IFACE_ITER_NORMAL,
+               mac80211_hwsim_beacon_tx, hw);
 
        data->beacon_timer.expires = jiffies + data->beacon_int;
        add_timer(&data->beacon_timer);
@@ -1680,14 +1682,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
 
        if (val == PS_MANUAL_POLL) {
                ieee80211_iterate_active_interfaces(data->hw,
+                                                   IEEE80211_IFACE_ITER_NORMAL,
                                                    hwsim_send_ps_poll, data);
                data->ps_poll_pending = true;
        } else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
                ieee80211_iterate_active_interfaces(data->hw,
+                                                   IEEE80211_IFACE_ITER_NORMAL,
                                                    hwsim_send_nullfunc_ps,
                                                    data);
        } else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
                ieee80211_iterate_active_interfaces(data->hw,
+                                                   IEEE80211_IFACE_ITER_NORMAL,
                                                    hwsim_send_nullfunc_no_ps,
                                                    data);
        }
index 69097d1faeb676d97ddd27c7ba7dc3f575cd2f6f..67d167993d4590237c4850ccfd3d2717ce739536 100644 (file)
@@ -157,6 +157,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
         * requested configurations.
         */
        ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+                                           IEEE80211_IFACE_ITER_RESUME_ALL,
                                            rt2x00lib_intf_scheduled_iter,
                                            rt2x00dev);
 }
@@ -225,9 +226,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
                return;
 
        /* send buffered bc/mc frames out for every bssid */
-       ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-                                                  rt2x00lib_bc_buffer_iter,
-                                                  rt2x00dev);
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_bc_buffer_iter, rt2x00dev);
        /*
         * Devices with pre tbtt interrupt don't need to update the beacon
         * here as they will fetch the next beacon directly prior to
@@ -237,9 +238,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
                return;
 
        /* fetch next beacon */
-       ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-                                                  rt2x00lib_beaconupdate_iter,
-                                                  rt2x00dev);
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_beaconupdate_iter, rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
@@ -249,9 +250,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
                return;
 
        /* fetch next beacon */
-       ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-                                                  rt2x00lib_beaconupdate_iter,
-                                                  rt2x00dev);
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_beaconupdate_iter, rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
index 98a9e48f8e4a38e852c54e8dbdef0c2369a753a4..ed7a1bb3f2450223e780e344e014efa51d290dbb 100644 (file)
@@ -424,9 +424,9 @@ int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
        if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
                return 0;
 
-       ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-                                                  rt2x00mac_set_tim_iter,
-                                                  rt2x00dev);
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00mac_set_tim_iter, rt2x00dev);
 
        /* queue work to upodate the beacon template */
        ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
index 25530c8760cb0a07234f753efe66e31fbf107c2d..380cf1ff6cd1ae54d081cf7f0be51b66b17b9251 100644 (file)
@@ -677,7 +677,7 @@ static void wl12xx_get_vif_count(struct ieee80211_hw *hw,
        memset(data, 0, sizeof(*data));
        data->cur_vif = cur_vif;
 
-       ieee80211_iterate_active_interfaces(hw,
+       ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
                                            wl12xx_vif_count_iter, data);
 }
 
index e1d830992319df8bc72b160669db4f8c3283f1b7..a789dd1d4c1066a5e1eee7986a440341a9bde3e9 100644 (file)
@@ -3412,6 +3412,21 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
  */
 void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
 
+/**
+ * enum ieee80211_interface_iteration_flags - interface iteration flags
+ * @IEEE80211_IFACE_ITER_NORMAL: Iterate over all interfaces that have
+ *     been added to the driver; However, note that during hardware
+ *     reconfiguration (after restart_hw) it will iterate over a new
+ *     interface and over all the existing interfaces even if they
+ *     haven't been re-added to the driver yet.
+ * @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
+ *     interfaces, even if they haven't been re-added to the driver yet.
+ */
+enum ieee80211_interface_iteration_flags {
+       IEEE80211_IFACE_ITER_NORMAL     = 0,
+       IEEE80211_IFACE_ITER_RESUME_ALL = BIT(0),
+};
+
 /**
  * ieee80211_iterate_active_interfaces - iterate active interfaces
  *
@@ -3420,13 +3435,15 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
  * This function allows the iterator function to sleep, when the iterator
  * function is atomic @ieee80211_iterate_active_interfaces_atomic can
  * be used.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
  * @iterator: the iterator function to call
  * @data: first argument of the iterator function
  */
 void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+                                        u32 iter_flags,
                                         void (*iterator)(void *data, u8 *mac,
                                                struct ieee80211_vif *vif),
                                         void *data);
@@ -3438,13 +3455,15 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
  * hardware that are currently active and calls the callback for them.
  * This function requires the iterator callback function to be atomic,
  * if that is not desired, use @ieee80211_iterate_active_interfaces instead.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
  * @iterator: the iterator function to call, cannot sleep
  * @data: first argument of the iterator function
  */
 void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
+                                               u32 iter_flags,
                                                void (*iterator)(void *data,
                                                    u8 *mac,
                                                    struct ieee80211_vif *vif),
index 84858a14c8bf8e068b1494dd80d407f3389a3122..01b9fa62f3e3ee9944a6a947abe84f81f9f2c15b 100644 (file)
@@ -512,7 +512,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
 void ieee80211_iterate_active_interfaces(
-       struct ieee80211_hw *hw,
+       struct ieee80211_hw *hw, u32 iter_flags,
        void (*iterator)(void *data, u8 *mac,
                         struct ieee80211_vif *vif),
        void *data)
@@ -530,6 +530,9 @@ void ieee80211_iterate_active_interfaces(
                default:
                        break;
                }
+               if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
+                   !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+                       continue;
                if (ieee80211_sdata_running(sdata))
                        iterator(data, sdata->vif.addr,
                                 &sdata->vif);
@@ -537,7 +540,9 @@ void ieee80211_iterate_active_interfaces(
 
        sdata = rcu_dereference_protected(local->monitor_sdata,
                                          lockdep_is_held(&local->iflist_mtx));
-       if (sdata)
+       if (sdata &&
+           (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+            sdata->flags & IEEE80211_SDATA_IN_DRIVER))
                iterator(data, sdata->vif.addr, &sdata->vif);
 
        mutex_unlock(&local->iflist_mtx);
@@ -545,7 +550,7 @@ void ieee80211_iterate_active_interfaces(
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
 
 void ieee80211_iterate_active_interfaces_atomic(
-       struct ieee80211_hw *hw,
+       struct ieee80211_hw *hw, u32 iter_flags,
        void (*iterator)(void *data, u8 *mac,
                         struct ieee80211_vif *vif),
        void *data)
@@ -563,13 +568,18 @@ void ieee80211_iterate_active_interfaces_atomic(
                default:
                        break;
                }
+               if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
+                   !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+                       continue;
                if (ieee80211_sdata_running(sdata))
                        iterator(data, sdata->vif.addr,
                                 &sdata->vif);
        }
 
        sdata = rcu_dereference(local->monitor_sdata);
-       if (sdata)
+       if (sdata &&
+           (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+            sdata->flags & IEEE80211_SDATA_IN_DRIVER))
                iterator(data, sdata->vif.addr, &sdata->vif);
 
        rcu_read_unlock();