mac80211: let flush() drop packets when possible
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Wed, 7 Jan 2015 13:42:39 +0000 (15:42 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 14 Jan 2015 08:31:18 +0000 (09:31 +0100)
When roaming / suspending, it makes no sense to wait until
the transmit queues of the device are empty. In extreme
condition they can be starved (VO saturating the air), but
even in regular cases, it is pointless to delay the roaming
because the low level driver is trying to send packets to
an AP which is far away. We'd rather drop these packets and
let TCP retransmit if needed. This will allow to speed up
the roaming.

For suspend, the explanation is even more trivial.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/pm.c
net/mac80211/scan.c
net/mac80211/tdls.c
net/mac80211/tx.c
net/mac80211/util.c

index 169665835b6c14c3089eb12d7f08ef6e4ff86b18..9ccecb405edee16d31b8257c6176ff0f393fe961 100644 (file)
@@ -3665,7 +3665,7 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
                 * queues.
                 */
                synchronize_net();
-               ieee80211_flush_queues(local, sdata);
+               ieee80211_flush_queues(local, sdata, false);
 
                /* restore the normal QoS parameters
                 * (unconditionally to avoid races)
index 4f45cab8b7f1dba9d61e6dbdc41478c8d331600c..91878ef5069aef733d4d57a5322ab93852963363 100644 (file)
@@ -1882,10 +1882,10 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
 void ieee80211_add_pending_skbs(struct ieee80211_local *local,
                                struct sk_buff_head *skbs);
 void ieee80211_flush_queues(struct ieee80211_local *local,
-                           struct ieee80211_sub_if_data *sdata);
+                           struct ieee80211_sub_if_data *sdata, bool drop);
 void __ieee80211_flush_queues(struct ieee80211_local *local,
                              struct ieee80211_sub_if_data *sdata,
-                             unsigned int queues);
+                             unsigned int queues, bool drop);
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
                         u16 transaction, u16 auth_alg, u16 status,
index 41735539087380c8e84735ef52efd1f2d265bbed..677422e11e075137ce0c85bb6819ce0db17b187b 100644 (file)
@@ -93,7 +93,7 @@ static u32 __ieee80211_idle_on(struct ieee80211_local *local)
        if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
                return 0;
 
-       ieee80211_flush_queues(local, NULL);
+       ieee80211_flush_queues(local, NULL, false);
 
        local->hw.conf.flags |= IEEE80211_CONF_IDLE;
        return IEEE80211_CONF_CHANGE_IDLE;
index 8354bedc858a8b4bc192d42e5fcf4af43e9174ec..c0711082a2b8fa14d99b0eb2152944c153abbe89 100644 (file)
@@ -1604,7 +1604,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
                } else {
                        ieee80211_send_nullfunc(local, sdata, 1);
                        /* Flush to get the tx status of nullfunc frame */
-                       ieee80211_flush_queues(local, sdata);
+                       ieee80211_flush_queues(local, sdata, false);
                }
        }
 
@@ -2011,18 +2011,23 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        /* disable per-vif ps */
        ieee80211_recalc_ps_vif(sdata);
 
-       /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
+       /*
+        * drop any frame before deauth/disassoc, this can be data or
+        * management frame. Since we are disconnecting, we should not
+        * insist sending these frames which can take time and delay
+        * the disconnection and possible the roaming.
+        */
        if (tx)
-               ieee80211_flush_queues(local, sdata);
+               ieee80211_flush_queues(local, sdata, true);
 
        /* deauthenticate/disassociate now */
        if (tx || frame_buf)
                ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
                                               reason, tx, frame_buf);
 
-       /* flush out frame */
+       /* flush out frame - make sure the deauth was actually sent */
        if (tx)
-               ieee80211_flush_queues(local, sdata);
+               ieee80211_flush_queues(local, sdata, false);
 
        /* clear bssid only after building the needed mgmt frames */
        memset(ifmgd->bssid, 0, ETH_ALEN);
index ff20b2ebdb3044207087930d76400421d5fda213..683f0e3cb1244cddcaa9ddae176f225fb1ec30b3 100644 (file)
@@ -121,7 +121,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
        ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
                                        false);
-       ieee80211_flush_queues(local, NULL);
+       ieee80211_flush_queues(local, NULL, false);
 
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
@@ -398,7 +398,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
                ieee80211_roc_notify_destroy(roc, !roc->abort);
 
                if (started && !on_channel) {
-                       ieee80211_flush_queues(local, NULL);
+                       ieee80211_flush_queues(local, NULL, false);
 
                        local->tmp_channel = NULL;
                        ieee80211_hw_config(local, 0);
index 4c5192e0d66c7d5ae99913c2e9f2e27ff1626d71..8c8c67819072b7653f2850fa5980ceff2787b806 100644 (file)
@@ -41,7 +41,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        /* flush out all packets */
        synchronize_net();
 
-       ieee80211_flush_queues(local, NULL);
+       ieee80211_flush_queues(local, NULL, true);
 
        local->quiescing = true;
        /* make quiescing visible to timers everywhere */
index ae842678b629ac09dab4348385d6961e04376069..844fb5f7910e1a7b2cd03f1c02a8d11d3bf206a7 100644 (file)
@@ -416,7 +416,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
        ieee80211_offchannel_stop_vifs(local);
 
        /* ensure nullfunc is transmitted before leaving operating channel */
-       ieee80211_flush_queues(local, NULL);
+       ieee80211_flush_queues(local, NULL, false);
 
        ieee80211_configure_filter(local);
 
@@ -805,7 +805,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
        ieee80211_offchannel_stop_vifs(local);
 
        if (local->ops->flush) {
-               ieee80211_flush_queues(local, NULL);
+               ieee80211_flush_queues(local, NULL, false);
                *next_delay = 0;
        } else
                *next_delay = HZ / 10;
index 55ddd77b865dffc805cdf3246d0b632e1e61d183..159ebf1304b2fcc43b0b36975ac10d193dc7ed8f 100644 (file)
@@ -912,7 +912,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
                rcu_read_unlock();
        }
 
-       ieee80211_flush_queues(local, sdata);
+       ieee80211_flush_queues(local, sdata, false);
 
        ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
                                              dialog_token, status_code,
@@ -952,7 +952,7 @@ ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
         */
        ieee80211_stop_vif_queues(local, sdata,
                                  IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
-       ieee80211_flush_queues(local, sdata);
+       ieee80211_flush_queues(local, sdata, false);
 
        ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
                                              dialog_token, status_code,
@@ -1098,7 +1098,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
                 */
                tasklet_kill(&local->tx_pending_tasklet);
                /* flush a potentially queued teardown packet */
-               ieee80211_flush_queues(local, sdata);
+               ieee80211_flush_queues(local, sdata, false);
 
                ret = sta_info_destroy_addr(sdata, peer);
                break;
index da7f352a2b164706b144a66f4464775ea634abcb..02ed6f60629a5aa123513f759104ca57513d0f5f 100644 (file)
@@ -3155,7 +3155,7 @@ int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
        }
 
        queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
-       __ieee80211_flush_queues(local, sdata, queues);
+       __ieee80211_flush_queues(local, sdata, queues, false);
 
        sta->reserved_tid = tid;
 
index ad8cb4fb441e01f5e1de066f73b01d5a884ccf0c..83ba6cd9cf8d0027d3cd33c2dd865bc1e46a84e0 100644 (file)
@@ -578,7 +578,7 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
 
 void __ieee80211_flush_queues(struct ieee80211_local *local,
                              struct ieee80211_sub_if_data *sdata,
-                             unsigned int queues)
+                             unsigned int queues, bool drop)
 {
        if (!local->ops->flush)
                return;
@@ -594,7 +594,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
                                        IEEE80211_QUEUE_STOP_REASON_FLUSH,
                                        false);
 
-       drv_flush(local, sdata, queues, false);
+       drv_flush(local, sdata, queues, drop);
 
        ieee80211_wake_queues_by_reason(&local->hw, queues,
                                        IEEE80211_QUEUE_STOP_REASON_FLUSH,
@@ -602,9 +602,9 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
 }
 
 void ieee80211_flush_queues(struct ieee80211_local *local,
-                           struct ieee80211_sub_if_data *sdata)
+                           struct ieee80211_sub_if_data *sdata, bool drop)
 {
-       __ieee80211_flush_queues(local, sdata, 0);
+       __ieee80211_flush_queues(local, sdata, 0, drop);
 }
 
 void ieee80211_stop_vif_queues(struct ieee80211_local *local,