diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/agg-tx.c | 8 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 9 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 15 | ||||
-rw-r--r-- | net/mac80211/iface.c | 3 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 15 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 6 | ||||
-rw-r--r-- | net/mac80211/pm.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/util.c | 76 |
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 | ||
1716 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1719 | void 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); | ||
1719 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1723 | void 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); | ||
1722 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1727 | void 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); | ||
1724 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1730 | void 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); | ||
1726 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); | 1733 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); |
1727 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1734 | void 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 | ||
1391 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | 1394 | void 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 | ||
188 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | 190 | void 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 | ||
319 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | 319 | static 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 | ||
346 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 353 | void 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 | ||
357 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | 365 | void 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 | } |
362 | EXPORT_SYMBOL(ieee80211_wake_queue); | 371 | EXPORT_SYMBOL(ieee80211_wake_queue); |
363 | 372 | ||
364 | static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | 373 | static 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 | ||
400 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 413 | void 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 | ||
411 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | 425 | void 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 | } |
416 | EXPORT_SYMBOL(ieee80211_stop_queue); | 431 | EXPORT_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 | ||
469 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 488 | void 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, | |||
485 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 505 | void 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 | } |
490 | EXPORT_SYMBOL(ieee80211_stop_queues); | 511 | EXPORT_SYMBOL(ieee80211_stop_queues); |
491 | 512 | ||
@@ -508,7 +529,8 @@ EXPORT_SYMBOL(ieee80211_queue_stopped); | |||
508 | 529 | ||
509 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 530 | void 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, | |||
525 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 547 | void 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 | } |
530 | EXPORT_SYMBOL(ieee80211_wake_queues); | 553 | EXPORT_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 | ||
563 | static void __iterate_active_interfaces(struct ieee80211_local *local, | 588 | static 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 |