aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-06-13 09:30:05 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-06-23 08:22:25 -0400
commitcca07b00a56d6ddd339e457dfd1a229222b9acf5 (patch)
tree15cc5be2e90930f76e6f2188bd825c216f9810fa /net
parent59f48fe22fe817df1ced42dee28b31de88b478b6 (diff)
mac80211: introduce refcount for queue_stop_reasons
Sometimes different vifs may be stopping the queues for the same reason (e.g. when several interfaces are performing a channel switch). Instead of using a bitmask for the reasons, use an integer that holds a refcount instead. In order to keep it backwards compatible, introduce a boolean in some functions that tell us whether the queue stopping should be refcounted or not. For now, use not refcounted for all calls to keep it functionally the same as before. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-tx.c8
-rw-r--r--net/mac80211/cfg.c9
-rw-r--r--net/mac80211/ieee80211_i.h15
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/mac80211/offchannel.c6
-rw-r--r--net/mac80211/pm.c6
-rw-r--r--net/mac80211/tx.c3
-rw-r--r--net/mac80211/util.c76
10 files changed, 98 insertions, 46 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index ce9633a3cfb0..d6986f3aa5c4 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -170,10 +170,13 @@ ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
170{ 170{
171 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; 171 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
172 172
173 /* we do refcounting here, so don't use the queue reason refcounting */
174
173 if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) 175 if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1)
174 ieee80211_stop_queue_by_reason( 176 ieee80211_stop_queue_by_reason(
175 &sdata->local->hw, queue, 177 &sdata->local->hw, queue,
176 IEEE80211_QUEUE_STOP_REASON_AGGREGATION); 178 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
179 false);
177 __acquire(agg_queue); 180 __acquire(agg_queue);
178} 181}
179 182
@@ -185,7 +188,8 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
185 if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) 188 if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0)
186 ieee80211_wake_queue_by_reason( 189 ieee80211_wake_queue_by_reason(
187 &sdata->local->hw, queue, 190 &sdata->local->hw, queue,
188 IEEE80211_QUEUE_STOP_REASON_AGGREGATION); 191 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
192 false);
189 __release(agg_queue); 193 __release(agg_queue);
190} 194}
191 195
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index af3eac482acd..e920d48f0209 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -837,7 +837,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
837 if (!ieee80211_csa_needs_block_tx(local)) 837 if (!ieee80211_csa_needs_block_tx(local))
838 ieee80211_wake_queues_by_reason(&local->hw, 838 ieee80211_wake_queues_by_reason(&local->hw,
839 IEEE80211_MAX_QUEUE_MAP, 839 IEEE80211_MAX_QUEUE_MAP,
840 IEEE80211_QUEUE_STOP_REASON_CSA); 840 IEEE80211_QUEUE_STOP_REASON_CSA,
841 false);
841 mutex_unlock(&local->mtx); 842 mutex_unlock(&local->mtx);
842 843
843 kfree(sdata->u.ap.next_beacon); 844 kfree(sdata->u.ap.next_beacon);
@@ -2828,7 +2829,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
2828 if (!ieee80211_csa_needs_block_tx(local)) 2829 if (!ieee80211_csa_needs_block_tx(local))
2829 ieee80211_wake_queues_by_reason(&local->hw, 2830 ieee80211_wake_queues_by_reason(&local->hw,
2830 IEEE80211_MAX_QUEUE_MAP, 2831 IEEE80211_MAX_QUEUE_MAP,
2831 IEEE80211_QUEUE_STOP_REASON_CSA); 2832 IEEE80211_QUEUE_STOP_REASON_CSA,
2833 false);
2832 2834
2833 return 0; 2835 return 0;
2834} 2836}
@@ -3060,7 +3062,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3060 if (sdata->csa_block_tx) 3062 if (sdata->csa_block_tx)
3061 ieee80211_stop_queues_by_reason(&local->hw, 3063 ieee80211_stop_queues_by_reason(&local->hw,
3062 IEEE80211_MAX_QUEUE_MAP, 3064 IEEE80211_MAX_QUEUE_MAP,
3063 IEEE80211_QUEUE_STOP_REASON_CSA); 3065 IEEE80211_QUEUE_STOP_REASON_CSA,
3066 false);
3064 3067
3065 if (changed) { 3068 if (changed) {
3066 ieee80211_bss_info_change_notify(sdata, changed); 3069 ieee80211_bss_info_change_notify(sdata, changed);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d9af7ef3c11a..a0c7da809744 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -922,6 +922,8 @@ enum queue_stop_reason {
922 IEEE80211_QUEUE_STOP_REASON_SKB_ADD, 922 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
923 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, 923 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
924 IEEE80211_QUEUE_STOP_REASON_FLUSH, 924 IEEE80211_QUEUE_STOP_REASON_FLUSH,
925
926 IEEE80211_QUEUE_STOP_REASONS,
925}; 927};
926 928
927#ifdef CONFIG_MAC80211_LEDS 929#ifdef CONFIG_MAC80211_LEDS
@@ -1018,6 +1020,7 @@ struct ieee80211_local {
1018 struct workqueue_struct *workqueue; 1020 struct workqueue_struct *workqueue;
1019 1021
1020 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; 1022 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
1023 int q_stop_reasons[IEEE80211_MAX_QUEUES][IEEE80211_QUEUE_STOP_REASONS];
1021 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ 1024 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
1022 spinlock_t queue_stop_reason_lock; 1025 spinlock_t queue_stop_reason_lock;
1023 1026
@@ -1715,14 +1718,18 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1715 1718
1716void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1719void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
1717 unsigned long queues, 1720 unsigned long queues,
1718 enum queue_stop_reason reason); 1721 enum queue_stop_reason reason,
1722 bool refcounted);
1719void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 1723void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
1720 unsigned long queues, 1724 unsigned long queues,
1721 enum queue_stop_reason reason); 1725 enum queue_stop_reason reason,
1726 bool refcounted);
1722void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 1727void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
1723 enum queue_stop_reason reason); 1728 enum queue_stop_reason reason,
1729 bool refcounted);
1724void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 1730void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
1725 enum queue_stop_reason reason); 1731 enum queue_stop_reason reason,
1732 bool refcounted);
1726void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); 1733void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
1727void ieee80211_add_pending_skb(struct ieee80211_local *local, 1734void ieee80211_add_pending_skb(struct ieee80211_local *local,
1728 struct sk_buff *skb); 1735 struct sk_buff *skb);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index db5afc7faa22..1971d2418d44 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -844,7 +844,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
844 if (!ieee80211_csa_needs_block_tx(local)) 844 if (!ieee80211_csa_needs_block_tx(local))
845 ieee80211_wake_queues_by_reason(&local->hw, 845 ieee80211_wake_queues_by_reason(&local->hw,
846 IEEE80211_MAX_QUEUE_MAP, 846 IEEE80211_MAX_QUEUE_MAP,
847 IEEE80211_QUEUE_STOP_REASON_CSA); 847 IEEE80211_QUEUE_STOP_REASON_CSA,
848 false);
848 mutex_unlock(&local->mtx); 849 mutex_unlock(&local->mtx);
849 sdata_unlock(sdata); 850 sdata_unlock(sdata);
850 851
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0512a5096f0f..e0ab4320a078 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -272,7 +272,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
272 272
273 /* use this reason, ieee80211_reconfig will unblock it */ 273 /* use this reason, ieee80211_reconfig will unblock it */
274 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, 274 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
275 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 275 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
276 false);
276 277
277 /* 278 /*
278 * Stop all Rx during the reconfig. We don't want state changes 279 * Stop all Rx during the reconfig. We don't want state changes
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 3345401be1b3..1ab1884eddbf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -983,7 +983,8 @@ static void ieee80211_chswitch_work(struct work_struct *work)
983 if (!ieee80211_csa_needs_block_tx(local)) 983 if (!ieee80211_csa_needs_block_tx(local))
984 ieee80211_wake_queues_by_reason(&local->hw, 984 ieee80211_wake_queues_by_reason(&local->hw,
985 IEEE80211_MAX_QUEUE_MAP, 985 IEEE80211_MAX_QUEUE_MAP,
986 IEEE80211_QUEUE_STOP_REASON_CSA); 986 IEEE80211_QUEUE_STOP_REASON_CSA,
987 false);
987 mutex_unlock(&local->mtx); 988 mutex_unlock(&local->mtx);
988 989
989 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 990 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@@ -1115,7 +1116,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1115 if (sdata->csa_block_tx) 1116 if (sdata->csa_block_tx)
1116 ieee80211_stop_queues_by_reason(&local->hw, 1117 ieee80211_stop_queues_by_reason(&local->hw,
1117 IEEE80211_MAX_QUEUE_MAP, 1118 IEEE80211_MAX_QUEUE_MAP,
1118 IEEE80211_QUEUE_STOP_REASON_CSA); 1119 IEEE80211_QUEUE_STOP_REASON_CSA,
1120 false);
1119 mutex_unlock(&local->mtx); 1121 mutex_unlock(&local->mtx);
1120 1122
1121 if (local->ops->channel_switch) { 1123 if (local->ops->channel_switch) {
@@ -1385,7 +1387,8 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
1385 1387
1386 ieee80211_wake_queues_by_reason(&local->hw, 1388 ieee80211_wake_queues_by_reason(&local->hw,
1387 IEEE80211_MAX_QUEUE_MAP, 1389 IEEE80211_MAX_QUEUE_MAP,
1388 IEEE80211_QUEUE_STOP_REASON_PS); 1390 IEEE80211_QUEUE_STOP_REASON_PS,
1391 false);
1389} 1392}
1390 1393
1391void ieee80211_dynamic_ps_enable_work(struct work_struct *work) 1394void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
@@ -1833,7 +1836,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1833 if (!ieee80211_csa_needs_block_tx(local)) 1836 if (!ieee80211_csa_needs_block_tx(local))
1834 ieee80211_wake_queues_by_reason(&local->hw, 1837 ieee80211_wake_queues_by_reason(&local->hw,
1835 IEEE80211_MAX_QUEUE_MAP, 1838 IEEE80211_MAX_QUEUE_MAP,
1836 IEEE80211_QUEUE_STOP_REASON_CSA); 1839 IEEE80211_QUEUE_STOP_REASON_CSA,
1840 false);
1837 mutex_unlock(&local->mtx); 1841 mutex_unlock(&local->mtx);
1838 1842
1839 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; 1843 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
@@ -2082,7 +2086,8 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2082 if (!ieee80211_csa_needs_block_tx(local)) 2086 if (!ieee80211_csa_needs_block_tx(local))
2083 ieee80211_wake_queues_by_reason(&local->hw, 2087 ieee80211_wake_queues_by_reason(&local->hw,
2084 IEEE80211_MAX_QUEUE_MAP, 2088 IEEE80211_MAX_QUEUE_MAP,
2085 IEEE80211_QUEUE_STOP_REASON_CSA); 2089 IEEE80211_QUEUE_STOP_REASON_CSA,
2090 false);
2086 mutex_unlock(&local->mtx); 2091 mutex_unlock(&local->mtx);
2087 2092
2088 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 2093 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 7a17decd27f9..ff20b2ebdb30 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -119,7 +119,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
119 * before sending nullfunc to enable powersave at the AP. 119 * before sending nullfunc to enable powersave at the AP.
120 */ 120 */
121 ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, 121 ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
122 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); 122 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
123 false);
123 ieee80211_flush_queues(local, NULL); 124 ieee80211_flush_queues(local, NULL);
124 125
125 mutex_lock(&local->iflist_mtx); 126 mutex_lock(&local->iflist_mtx);
@@ -182,7 +183,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
182 mutex_unlock(&local->iflist_mtx); 183 mutex_unlock(&local->iflist_mtx);
183 184
184 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, 185 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
185 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); 186 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
187 false);
186} 188}
187 189
188void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) 190void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index d478b880a0af..4c5192e0d66c 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -35,7 +35,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
35 35
36 ieee80211_stop_queues_by_reason(hw, 36 ieee80211_stop_queues_by_reason(hw,
37 IEEE80211_MAX_QUEUE_MAP, 37 IEEE80211_MAX_QUEUE_MAP,
38 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 38 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
39 false);
39 40
40 /* flush out all packets */ 41 /* flush out all packets */
41 synchronize_net(); 42 synchronize_net();
@@ -74,7 +75,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
74 } 75 }
75 ieee80211_wake_queues_by_reason(hw, 76 ieee80211_wake_queues_by_reason(hw,
76 IEEE80211_MAX_QUEUE_MAP, 77 IEEE80211_MAX_QUEUE_MAP,
77 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 78 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
79 false);
78 return err; 80 return err;
79 } else if (err > 0) { 81 } else if (err > 0) {
80 WARN_ON(err != 1); 82 WARN_ON(err != 1);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9b3d94e7c4be..f6018178f33c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -250,7 +250,8 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
250 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 250 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
251 ieee80211_stop_queues_by_reason(&local->hw, 251 ieee80211_stop_queues_by_reason(&local->hw,
252 IEEE80211_MAX_QUEUE_MAP, 252 IEEE80211_MAX_QUEUE_MAP,
253 IEEE80211_QUEUE_STOP_REASON_PS); 253 IEEE80211_QUEUE_STOP_REASON_PS,
254 false);
254 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 255 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
255 ieee80211_queue_work(&local->hw, 256 ieee80211_queue_work(&local->hw,
256 &local->dynamic_ps_disable_work); 257 &local->dynamic_ps_disable_work);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 6d29e40538ad..4e8513cfdae5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -317,7 +317,8 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
317} 317}
318 318
319static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, 319static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
320 enum queue_stop_reason reason) 320 enum queue_stop_reason reason,
321 bool refcounted)
321{ 322{
322 struct ieee80211_local *local = hw_to_local(hw); 323 struct ieee80211_local *local = hw_to_local(hw);
323 324
@@ -329,7 +330,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
329 if (!test_bit(reason, &local->queue_stop_reasons[queue])) 330 if (!test_bit(reason, &local->queue_stop_reasons[queue]))
330 return; 331 return;
331 332
332 __clear_bit(reason, &local->queue_stop_reasons[queue]); 333 if (!refcounted)
334 local->q_stop_reasons[queue][reason] = 0;
335 else
336 local->q_stop_reasons[queue][reason]--;
337
338 if (local->q_stop_reasons[queue][reason] == 0)
339 __clear_bit(reason, &local->queue_stop_reasons[queue]);
333 340
334 if (local->queue_stop_reasons[queue] != 0) 341 if (local->queue_stop_reasons[queue] != 0)
335 /* someone still has this queue stopped */ 342 /* someone still has this queue stopped */
@@ -344,25 +351,28 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
344} 351}
345 352
346void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 353void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
347 enum queue_stop_reason reason) 354 enum queue_stop_reason reason,
355 bool refcounted)
348{ 356{
349 struct ieee80211_local *local = hw_to_local(hw); 357 struct ieee80211_local *local = hw_to_local(hw);
350 unsigned long flags; 358 unsigned long flags;
351 359
352 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 360 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
353 __ieee80211_wake_queue(hw, queue, reason); 361 __ieee80211_wake_queue(hw, queue, reason, refcounted);
354 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 362 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
355} 363}
356 364
357void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) 365void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
358{ 366{
359 ieee80211_wake_queue_by_reason(hw, queue, 367 ieee80211_wake_queue_by_reason(hw, queue,
360 IEEE80211_QUEUE_STOP_REASON_DRIVER); 368 IEEE80211_QUEUE_STOP_REASON_DRIVER,
369 false);
361} 370}
362EXPORT_SYMBOL(ieee80211_wake_queue); 371EXPORT_SYMBOL(ieee80211_wake_queue);
363 372
364static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, 373static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
365 enum queue_stop_reason reason) 374 enum queue_stop_reason reason,
375 bool refcounted)
366{ 376{
367 struct ieee80211_local *local = hw_to_local(hw); 377 struct ieee80211_local *local = hw_to_local(hw);
368 struct ieee80211_sub_if_data *sdata; 378 struct ieee80211_sub_if_data *sdata;
@@ -373,10 +383,13 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
373 if (WARN_ON(queue >= hw->queues)) 383 if (WARN_ON(queue >= hw->queues))
374 return; 384 return;
375 385
376 if (test_bit(reason, &local->queue_stop_reasons[queue])) 386 if (!refcounted)
377 return; 387 local->q_stop_reasons[queue][reason] = 1;
388 else
389 local->q_stop_reasons[queue][reason]++;
378 390
379 __set_bit(reason, &local->queue_stop_reasons[queue]); 391 if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
392 return;
380 393
381 if (local->hw.queues < IEEE80211_NUM_ACS) 394 if (local->hw.queues < IEEE80211_NUM_ACS)
382 n_acs = 1; 395 n_acs = 1;
@@ -398,20 +411,22 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
398} 411}
399 412
400void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 413void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
401 enum queue_stop_reason reason) 414 enum queue_stop_reason reason,
415 bool refcounted)
402{ 416{
403 struct ieee80211_local *local = hw_to_local(hw); 417 struct ieee80211_local *local = hw_to_local(hw);
404 unsigned long flags; 418 unsigned long flags;
405 419
406 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 420 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
407 __ieee80211_stop_queue(hw, queue, reason); 421 __ieee80211_stop_queue(hw, queue, reason, refcounted);
408 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 422 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
409} 423}
410 424
411void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) 425void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
412{ 426{
413 ieee80211_stop_queue_by_reason(hw, queue, 427 ieee80211_stop_queue_by_reason(hw, queue,
414 IEEE80211_QUEUE_STOP_REASON_DRIVER); 428 IEEE80211_QUEUE_STOP_REASON_DRIVER,
429 false);
415} 430}
416EXPORT_SYMBOL(ieee80211_stop_queue); 431EXPORT_SYMBOL(ieee80211_stop_queue);
417 432
@@ -429,9 +444,11 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
429 } 444 }
430 445
431 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 446 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
432 __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 447 __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
448 false);
433 __skb_queue_tail(&local->pending[queue], skb); 449 __skb_queue_tail(&local->pending[queue], skb);
434 __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 450 __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
451 false);
435 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 452 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
436} 453}
437 454
@@ -455,20 +472,23 @@ void ieee80211_add_pending_skbs(struct ieee80211_local *local,
455 queue = info->hw_queue; 472 queue = info->hw_queue;
456 473
457 __ieee80211_stop_queue(hw, queue, 474 __ieee80211_stop_queue(hw, queue,
458 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 475 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
476 false);
459 477
460 __skb_queue_tail(&local->pending[queue], skb); 478 __skb_queue_tail(&local->pending[queue], skb);
461 } 479 }
462 480
463 for (i = 0; i < hw->queues; i++) 481 for (i = 0; i < hw->queues; i++)
464 __ieee80211_wake_queue(hw, i, 482 __ieee80211_wake_queue(hw, i,
465 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 483 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
484 false);
466 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 485 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
467} 486}
468 487
469void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 488void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
470 unsigned long queues, 489 unsigned long queues,
471 enum queue_stop_reason reason) 490 enum queue_stop_reason reason,
491 bool refcounted)
472{ 492{
473 struct ieee80211_local *local = hw_to_local(hw); 493 struct ieee80211_local *local = hw_to_local(hw);
474 unsigned long flags; 494 unsigned long flags;
@@ -477,7 +497,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
477 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 497 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
478 498
479 for_each_set_bit(i, &queues, hw->queues) 499 for_each_set_bit(i, &queues, hw->queues)
480 __ieee80211_stop_queue(hw, i, reason); 500 __ieee80211_stop_queue(hw, i, reason, refcounted);
481 501
482 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 502 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
483} 503}
@@ -485,7 +505,8 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
485void ieee80211_stop_queues(struct ieee80211_hw *hw) 505void ieee80211_stop_queues(struct ieee80211_hw *hw)
486{ 506{
487 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, 507 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
488 IEEE80211_QUEUE_STOP_REASON_DRIVER); 508 IEEE80211_QUEUE_STOP_REASON_DRIVER,
509 false);
489} 510}
490EXPORT_SYMBOL(ieee80211_stop_queues); 511EXPORT_SYMBOL(ieee80211_stop_queues);
491 512
@@ -508,7 +529,8 @@ EXPORT_SYMBOL(ieee80211_queue_stopped);
508 529
509void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 530void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
510 unsigned long queues, 531 unsigned long queues,
511 enum queue_stop_reason reason) 532 enum queue_stop_reason reason,
533 bool refcounted)
512{ 534{
513 struct ieee80211_local *local = hw_to_local(hw); 535 struct ieee80211_local *local = hw_to_local(hw);
514 unsigned long flags; 536 unsigned long flags;
@@ -517,7 +539,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
517 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 539 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
518 540
519 for_each_set_bit(i, &queues, hw->queues) 541 for_each_set_bit(i, &queues, hw->queues)
520 __ieee80211_wake_queue(hw, i, reason); 542 __ieee80211_wake_queue(hw, i, reason, refcounted);
521 543
522 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 544 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
523} 545}
@@ -525,7 +547,8 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
525void ieee80211_wake_queues(struct ieee80211_hw *hw) 547void ieee80211_wake_queues(struct ieee80211_hw *hw)
526{ 548{
527 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, 549 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
528 IEEE80211_QUEUE_STOP_REASON_DRIVER); 550 IEEE80211_QUEUE_STOP_REASON_DRIVER,
551 false);
529} 552}
530EXPORT_SYMBOL(ieee80211_wake_queues); 553EXPORT_SYMBOL(ieee80211_wake_queues);
531 554
@@ -552,12 +575,14 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
552 } 575 }
553 576
554 ieee80211_stop_queues_by_reason(&local->hw, queues, 577 ieee80211_stop_queues_by_reason(&local->hw, queues,
555 IEEE80211_QUEUE_STOP_REASON_FLUSH); 578 IEEE80211_QUEUE_STOP_REASON_FLUSH,
579 false);
556 580
557 drv_flush(local, sdata, queues, false); 581 drv_flush(local, sdata, queues, false);
558 582
559 ieee80211_wake_queues_by_reason(&local->hw, queues, 583 ieee80211_wake_queues_by_reason(&local->hw, queues,
560 IEEE80211_QUEUE_STOP_REASON_FLUSH); 584 IEEE80211_QUEUE_STOP_REASON_FLUSH,
585 false);
561} 586}
562 587
563static void __iterate_active_interfaces(struct ieee80211_local *local, 588static void __iterate_active_interfaces(struct ieee80211_local *local,
@@ -1797,7 +1822,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1797 } 1822 }
1798 1823
1799 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, 1824 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
1800 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1825 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
1826 false);
1801 1827
1802 /* 1828 /*
1803 * Reconfigure sched scan if it was interrupted by FW restart or 1829 * Reconfigure sched scan if it was interrupted by FW restart or