aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-13 06:11:00 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-18 15:15:03 -0400
commit39ecc01d1bbe3de2cf5f01a81e176ea5160d3b95 (patch)
tree1a75bf065c61f0870ff4d63eac6130998834748c
parenta0ca796c460259bc079631d2d148ffff1d1fc736 (diff)
mac80211: pass queue bitmap to flush operation
There are a number of situations in which mac80211 only really needs to flush queues for one virtual interface, and in fact during this frames might be transmitted on other virtual interfaces. Calculate and pass a queue bitmap to the driver so it knows which queues to flush. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c2
-rw-r--r--drivers/net/wireless/iwlegacy/common.c3
-rw-r--r--drivers/net/wireless/iwlegacy/common.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c2
-rw-r--r--drivers/net/wireless/p54/main.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c2
-rw-r--r--drivers/net/wireless/rtlwifi/core.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--include/net/mac80211.h9
-rw-r--r--net/mac80211/driver-ops.h7
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mac80211/offchannel.c4
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/scan.c4
-rw-r--r--net/mac80211/trace.h11
-rw-r--r--net/mac80211/util.c25
23 files changed, 67 insertions, 34 deletions
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index 7157f7d311c5..afd1e36d308f 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -1091,7 +1091,7 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1091 return ret; 1091 return ret;
1092} 1092}
1093 1093
1094static void ar5523_flush(struct ieee80211_hw *hw, bool drop) 1094static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1095{ 1095{
1096 struct ar5523 *ar = hw->priv; 1096 struct ar5523 *ar = hw->priv;
1097 1097
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6e66f9c6782b..24650fd41694 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1745,7 +1745,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
1745 mutex_unlock(&sc->mutex); 1745 mutex_unlock(&sc->mutex);
1746} 1746}
1747 1747
1748static void ath9k_flush(struct ieee80211_hw *hw, bool drop) 1748static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1749{ 1749{
1750 struct ath_softc *sc = hw->priv; 1750 struct ath_softc *sc = hw->priv;
1751 struct ath_hw *ah = sc->sc_ah; 1751 struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index f293b3ff4756..08b193199946 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1703,7 +1703,7 @@ found:
1703 return 0; 1703 return 0;
1704} 1704}
1705 1705
1706static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop) 1706static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1707{ 1707{
1708 struct ar9170 *ar = hw->priv; 1708 struct ar9170 *ar = hw->priv;
1709 unsigned int vid; 1709 unsigned int vid;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c61407a..aa5f43fee5ed 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -723,7 +723,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
723 return result; 723 return result;
724} 724}
725 725
726static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) 726static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
727{ 727{
728 struct brcms_info *wl = hw->priv; 728 struct brcms_info *wl = hw->priv;
729 int ret; 729 int ret;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index e006ea831320..722bfb57cfd5 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4704,8 +4704,7 @@ out:
4704} 4704}
4705EXPORT_SYMBOL(il_mac_change_interface); 4705EXPORT_SYMBOL(il_mac_change_interface);
4706 4706
4707void 4707void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
4708il_mac_flush(struct ieee80211_hw *hw, bool drop)
4709{ 4708{
4710 struct il_priv *il = hw->priv; 4709 struct il_priv *il = hw->priv;
4711 unsigned long timeout = jiffies + msecs_to_jiffies(500); 4710 unsigned long timeout = jiffies + msecs_to_jiffies(500);
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 73bd3ef316c8..728aa1306ab8 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1720,7 +1720,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
1720 struct ieee80211_vif *vif); 1720 struct ieee80211_vif *vif);
1721int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1721int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1722 enum nl80211_iftype newtype, bool newp2p); 1722 enum nl80211_iftype newtype, bool newp2p);
1723void il_mac_flush(struct ieee80211_hw *hw, bool drop); 1723void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
1724int il_alloc_txq_mem(struct il_priv *il); 1724int il_alloc_txq_mem(struct il_priv *il);
1725void il_free_txq_mem(struct il_priv *il); 1725void il_free_txq_mem(struct il_priv *il);
1726 1726
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index c7cd2dffa5cd..a7294fa4d7e5 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1100,7 +1100,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
1100 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; 1100 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
1101} 1101}
1102 1102
1103static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) 1103static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1104{ 1104{
1105 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); 1105 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
1106 1106
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 7490c4fc7177..3466f1a8a8d3 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1389,7 +1389,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
1389 return 0; 1389 return 0;
1390} 1390}
1391 1391
1392static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) 1392static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1393{ 1393{
1394 /* Not implemented, queues only on kernel side */ 1394 /* Not implemented, queues only on kernel side */
1395} 1395}
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index aadda99989c0..ee654a691f38 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -670,7 +670,7 @@ static unsigned int p54_flush_count(struct p54_common *priv)
670 return total; 670 return total;
671} 671}
672 672
673static void p54_flush(struct ieee80211_hw *dev, bool drop) 673static void p54_flush(struct ieee80211_hw *dev, u32 queues, bool drop)
674{ 674{
675 struct p54_common *priv = dev->priv; 675 struct p54_common *priv = dev->priv;
676 unsigned int total, i; 676 unsigned int total, i;
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 086abb403a4f..041b392f4f47 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1360,7 +1360,7 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
1360 struct ieee80211_vif *vif, u16 queue, 1360 struct ieee80211_vif *vif, u16 queue,
1361 const struct ieee80211_tx_queue_params *params); 1361 const struct ieee80211_tx_queue_params *params);
1362void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); 1362void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
1363void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); 1363void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
1364int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); 1364int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
1365int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); 1365int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
1366void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, 1366void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 20c6eccce5aa..9161c02d8ff9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -748,7 +748,7 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
748} 748}
749EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); 749EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
750 750
751void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) 751void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
752{ 752{
753 struct rt2x00_dev *rt2x00dev = hw->priv; 753 struct rt2x00_dev *rt2x00dev = hw->priv;
754 struct data_queue *queue; 754 struct data_queue *queue;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d3ce9fbef00e..b5a7a260bf63 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -1166,7 +1166,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
1166 * before switch channle or power save, or tx buffer packet 1166 * before switch channle or power save, or tx buffer packet
1167 * maybe send after offchannel or rf sleep, this may cause 1167 * maybe send after offchannel or rf sleep, this may cause
1168 * dis-association by AP */ 1168 * dis-association by AP */
1169static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) 1169static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1170{ 1170{
1171 struct rtl_priv *rtlpriv = rtl_priv(hw); 1171 struct rtl_priv *rtlpriv = rtl_priv(hw);
1172 1172
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index d7e306333f6c..a9f7041c7192 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4946,7 +4946,7 @@ out:
4946 mutex_unlock(&wl->mutex); 4946 mutex_unlock(&wl->mutex);
4947} 4947}
4948 4948
4949static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) 4949static void wlcore_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
4950{ 4950{
4951 struct wl1271 *wl = hw->priv; 4951 struct wl1271 *wl = hw->priv;
4952 4952
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0b912d22f82d..4158da74e11b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2438,8 +2438,11 @@ enum ieee80211_roc_type {
2438 * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep. 2438 * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
2439 * 2439 *
2440 * @flush: Flush all pending frames from the hardware queue, making sure 2440 * @flush: Flush all pending frames from the hardware queue, making sure
2441 * that the hardware queues are empty. If the parameter @drop is set 2441 * that the hardware queues are empty. The @queues parameter is a bitmap
2442 * to %true, pending frames may be dropped. The callback can sleep. 2442 * of queues to flush, which is useful if different virtual interfaces
2443 * use different hardware queues; it may also indicate all queues.
2444 * If the parameter @drop is set to %true, pending frames may be dropped.
2445 * The callback can sleep.
2443 * 2446 *
2444 * @channel_switch: Drivers that need (or want) to offload the channel 2447 * @channel_switch: Drivers that need (or want) to offload the channel
2445 * switch operation for CSAs received from the AP may implement this 2448 * switch operation for CSAs received from the AP may implement this
@@ -2687,7 +2690,7 @@ struct ieee80211_ops {
2687 struct netlink_callback *cb, 2690 struct netlink_callback *cb,
2688 void *data, int len); 2691 void *data, int len);
2689#endif 2692#endif
2690 void (*flush)(struct ieee80211_hw *hw, bool drop); 2693 void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop);
2691 void (*channel_switch)(struct ieee80211_hw *hw, 2694 void (*channel_switch)(struct ieee80211_hw *hw,
2692 struct ieee80211_channel_switch *ch_switch); 2695 struct ieee80211_channel_switch *ch_switch);
2693 int (*napi_poll)(struct ieee80211_hw *hw, int budget); 2696 int (*napi_poll)(struct ieee80211_hw *hw, int budget);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 7b9ff53bd2e9..169664c122e2 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -720,13 +720,14 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local)
720 local->ops->rfkill_poll(&local->hw); 720 local->ops->rfkill_poll(&local->hw);
721} 721}
722 722
723static inline void drv_flush(struct ieee80211_local *local, bool drop) 723static inline void drv_flush(struct ieee80211_local *local,
724 u32 queues, bool drop)
724{ 725{
725 might_sleep(); 726 might_sleep();
726 727
727 trace_drv_flush(local, drop); 728 trace_drv_flush(local, queues, drop);
728 if (local->ops->flush) 729 if (local->ops->flush)
729 local->ops->flush(&local->hw, drop); 730 local->ops->flush(&local->hw, queues, drop);
730 trace_drv_return_void(local); 731 trace_drv_return_void(local);
731} 732}
732 733
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d6e920609823..b96c0e977752 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1540,6 +1540,8 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
1540{ 1540{
1541 ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); 1541 ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
1542} 1542}
1543void ieee80211_flush_queues(struct ieee80211_local *local,
1544 struct ieee80211_sub_if_data *sdata);
1543 1545
1544void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 1546void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1545 u16 transaction, u16 auth_alg, u16 status, 1547 u16 transaction, u16 auth_alg, u16 status,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 80e838bc875d..d646e12e55a6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -92,7 +92,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
92 if (local->hw.conf.flags & IEEE80211_CONF_IDLE) 92 if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
93 return 0; 93 return 0;
94 94
95 drv_flush(local, false); 95 ieee80211_flush_queues(local, NULL);
96 96
97 local->hw.conf.flags |= IEEE80211_CONF_IDLE; 97 local->hw.conf.flags |= IEEE80211_CONF_IDLE;
98 return IEEE80211_CONF_CHANGE_IDLE; 98 return IEEE80211_CONF_CHANGE_IDLE;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fdc06e381c10..65b38e13eb0c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1436,7 +1436,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
1436 else { 1436 else {
1437 ieee80211_send_nullfunc(local, sdata, 1); 1437 ieee80211_send_nullfunc(local, sdata, 1);
1438 /* Flush to get the tx status of nullfunc frame */ 1438 /* Flush to get the tx status of nullfunc frame */
1439 drv_flush(local, false); 1439 ieee80211_flush_queues(local, sdata);
1440 } 1440 }
1441 } 1441 }
1442 1442
@@ -1767,7 +1767,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1767 1767
1768 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ 1768 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
1769 if (tx) 1769 if (tx)
1770 drv_flush(local, false); 1770 ieee80211_flush_queues(local, sdata);
1771 1771
1772 /* deauthenticate/disassociate now */ 1772 /* deauthenticate/disassociate now */
1773 if (tx || frame_buf) 1773 if (tx || frame_buf)
@@ -1776,7 +1776,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1776 1776
1777 /* flush out frame */ 1777 /* flush out frame */
1778 if (tx) 1778 if (tx)
1779 drv_flush(local, false); 1779 ieee80211_flush_queues(local, sdata);
1780 1780
1781 /* clear bssid only after building the needed mgmt frames */ 1781 /* clear bssid only after building the needed mgmt frames */
1782 memset(ifmgd->bssid, 0, ETH_ALEN); 1782 memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -1948,7 +1948,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1948 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 1948 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
1949 run_again(ifmgd, ifmgd->probe_timeout); 1949 run_again(ifmgd, ifmgd->probe_timeout);
1950 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 1950 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
1951 drv_flush(sdata->local, false); 1951 ieee80211_flush_queues(sdata->local, sdata);
1952} 1952}
1953 1953
1954static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, 1954static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index db547fceaeb9..d32f514074b9 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -120,7 +120,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
120 */ 120 */
121 ieee80211_stop_queues_by_reason(&local->hw, 121 ieee80211_stop_queues_by_reason(&local->hw,
122 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); 122 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
123 drv_flush(local, false); 123 ieee80211_flush_queues(local, NULL);
124 124
125 mutex_lock(&local->iflist_mtx); 125 mutex_lock(&local->iflist_mtx);
126 list_for_each_entry(sdata, &local->interfaces, list) { 126 list_for_each_entry(sdata, &local->interfaces, list) {
@@ -373,7 +373,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
373 ieee80211_roc_notify_destroy(roc); 373 ieee80211_roc_notify_destroy(roc);
374 374
375 if (started) { 375 if (started) {
376 drv_flush(local, false); 376 ieee80211_flush_queues(local, NULL);
377 377
378 local->tmp_channel = NULL; 378 local->tmp_channel = NULL;
379 ieee80211_hw_config(local, 0); 379 ieee80211_hw_config(local, 0);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index b471a67f224d..497f21a0d116 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -35,7 +35,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
35 /* flush out all packets */ 35 /* flush out all packets */
36 synchronize_net(); 36 synchronize_net();
37 37
38 drv_flush(local, false); 38 ieee80211_flush_queues(local, NULL);
39 39
40 local->quiescing = true; 40 local->quiescing = true;
41 /* make quiescing visible to timers everywhere */ 41 /* make quiescing visible to timers everywhere */
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 5dc17c623f72..cb34cbbaa20c 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -332,7 +332,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
332 ieee80211_offchannel_stop_vifs(local); 332 ieee80211_offchannel_stop_vifs(local);
333 333
334 /* ensure nullfunc is transmitted before leaving operating channel */ 334 /* ensure nullfunc is transmitted before leaving operating channel */
335 drv_flush(local, false); 335 ieee80211_flush_queues(local, NULL);
336 336
337 ieee80211_configure_filter(local); 337 ieee80211_configure_filter(local);
338 338
@@ -668,7 +668,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
668 ieee80211_offchannel_stop_vifs(local); 668 ieee80211_offchannel_stop_vifs(local);
669 669
670 if (local->ops->flush) { 670 if (local->ops->flush) {
671 drv_flush(local, false); 671 ieee80211_flush_queues(local, NULL);
672 *next_delay = 0; 672 *next_delay = 0;
673 } else 673 } else
674 *next_delay = HZ / 10; 674 *next_delay = HZ / 10;
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index d97e4305cf1e..c5899797a8d4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -964,23 +964,26 @@ TRACE_EVENT(drv_get_survey,
964); 964);
965 965
966TRACE_EVENT(drv_flush, 966TRACE_EVENT(drv_flush,
967 TP_PROTO(struct ieee80211_local *local, bool drop), 967 TP_PROTO(struct ieee80211_local *local,
968 u32 queues, bool drop),
968 969
969 TP_ARGS(local, drop), 970 TP_ARGS(local, queues, drop),
970 971
971 TP_STRUCT__entry( 972 TP_STRUCT__entry(
972 LOCAL_ENTRY 973 LOCAL_ENTRY
973 __field(bool, drop) 974 __field(bool, drop)
975 __field(u32, queues)
974 ), 976 ),
975 977
976 TP_fast_assign( 978 TP_fast_assign(
977 LOCAL_ASSIGN; 979 LOCAL_ASSIGN;
978 __entry->drop = drop; 980 __entry->drop = drop;
981 __entry->queues = queues;
979 ), 982 ),
980 983
981 TP_printk( 984 TP_printk(
982 LOCAL_PR_FMT " drop:%d", 985 LOCAL_PR_FMT " queues:0x%x drop:%d",
983 LOCAL_PR_ARG, __entry->drop 986 LOCAL_PR_ARG, __entry->queues, __entry->drop
984 ) 987 )
985); 988);
986 989
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b7a856e3281b..f978ddd1bb43 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -511,6 +511,31 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
511} 511}
512EXPORT_SYMBOL(ieee80211_wake_queues); 512EXPORT_SYMBOL(ieee80211_wake_queues);
513 513
514void ieee80211_flush_queues(struct ieee80211_local *local,
515 struct ieee80211_sub_if_data *sdata)
516{
517 u32 queues;
518
519 if (!local->ops->flush)
520 return;
521
522 if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
523 int ac;
524
525 queues = 0;
526
527 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
528 queues |= BIT(sdata->vif.hw_queue[ac]);
529 if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
530 queues |= BIT(sdata->vif.cab_queue);
531 } else {
532 /* all queues */
533 queues = BIT(local->hw.queues) - 1;
534 }
535
536 drv_flush(local, queues, false);
537}
538
514void ieee80211_iterate_active_interfaces( 539void ieee80211_iterate_active_interfaces(
515 struct ieee80211_hw *hw, u32 iter_flags, 540 struct ieee80211_hw *hw, u32 iter_flags,
516 void (*iterator)(void *data, u8 *mac, 541 void (*iterator)(void *data, u8 *mac,