aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-13 06:25:28 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-18 15:15:05 -0400
commit445ea4e83ec50668cc9ad7e5cf96d242f19165e8 (patch)
tree1b6e6c909854358c03fd0047b9f441e0095460e3
parent39ecc01d1bbe3de2cf5f01a81e176ea5160d3b95 (diff)
mac80211: stop queues temporarily for flushing
Sometimes queues are flushed in the middle of operation, which can lead to driver issues. Stop queues temporarily, while flushing, to avoid transmitting new packets while they are being flushed. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h2
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mlme.c4
-rw-r--r--net/mac80211/offchannel.c4
-rw-r--r--net/mac80211/pm.c4
-rw-r--r--net/mac80211/tx.c1
-rw-r--r--net/mac80211/util.c23
8 files changed, 33 insertions, 12 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4158da74e11b..dd73b8c6746b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -93,9 +93,11 @@ struct device;
93 * enum ieee80211_max_queues - maximum number of queues 93 * enum ieee80211_max_queues - maximum number of queues
94 * 94 *
95 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. 95 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
96 * @IEEE80211_MAX_QUEUE_MAP: bitmap with maximum queues set
96 */ 97 */
97enum ieee80211_max_queues { 98enum ieee80211_max_queues {
98 IEEE80211_MAX_QUEUES = 16, 99 IEEE80211_MAX_QUEUES = 16,
100 IEEE80211_MAX_QUEUE_MAP = BIT(IEEE80211_MAX_QUEUES) - 1,
99}; 101};
100 102
101#define IEEE80211_INVAL_HW_QUEUE 0xff 103#define IEEE80211_INVAL_HW_QUEUE 0xff
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b96c0e977752..ae2d1754b792 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -809,6 +809,7 @@ enum queue_stop_reason {
809 IEEE80211_QUEUE_STOP_REASON_SUSPEND, 809 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
810 IEEE80211_QUEUE_STOP_REASON_SKB_ADD, 810 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
811 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, 811 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
812 IEEE80211_QUEUE_STOP_REASON_FLUSH,
812}; 813};
813 814
814#ifdef CONFIG_MAC80211_LEDS 815#ifdef CONFIG_MAC80211_LEDS
@@ -1522,8 +1523,10 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1522 struct ieee80211_hdr *hdr, bool ack); 1523 struct ieee80211_hdr *hdr, bool ack);
1523 1524
1524void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1525void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
1526 unsigned long queues,
1525 enum queue_stop_reason reason); 1527 enum queue_stop_reason reason);
1526void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 1528void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
1529 unsigned long queues,
1527 enum queue_stop_reason reason); 1530 enum queue_stop_reason reason);
1528void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 1531void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
1529 enum queue_stop_reason reason); 1532 enum queue_stop_reason reason);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index eee1768e89c0..c6f81ecc36a1 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -277,8 +277,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
277 "Hardware restart was requested\n"); 277 "Hardware restart was requested\n");
278 278
279 /* use this reason, ieee80211_reconfig will unblock it */ 279 /* use this reason, ieee80211_reconfig will unblock it */
280 ieee80211_stop_queues_by_reason(hw, 280 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
281 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 281 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
282 282
283 /* 283 /*
284 * Stop all Rx during the reconfig. We don't want state changes 284 * 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 65b38e13eb0c..4d383a93ea73 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1009,6 +1009,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
1009 1009
1010 /* XXX: wait for a beacon first? */ 1010 /* XXX: wait for a beacon first? */
1011 ieee80211_wake_queues_by_reason(&sdata->local->hw, 1011 ieee80211_wake_queues_by_reason(&sdata->local->hw,
1012 IEEE80211_MAX_QUEUE_MAP,
1012 IEEE80211_QUEUE_STOP_REASON_CSA); 1013 IEEE80211_QUEUE_STOP_REASON_CSA);
1013 out: 1014 out:
1014 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 1015 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@@ -1108,6 +1109,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1108 1109
1109 if (sw_elem->mode) 1110 if (sw_elem->mode)
1110 ieee80211_stop_queues_by_reason(&sdata->local->hw, 1111 ieee80211_stop_queues_by_reason(&sdata->local->hw,
1112 IEEE80211_MAX_QUEUE_MAP,
1111 IEEE80211_QUEUE_STOP_REASON_CSA); 1113 IEEE80211_QUEUE_STOP_REASON_CSA);
1112 1114
1113 if (sdata->local->ops->channel_switch) { 1115 if (sdata->local->ops->channel_switch) {
@@ -1375,6 +1377,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
1375 } 1377 }
1376 1378
1377 ieee80211_wake_queues_by_reason(&local->hw, 1379 ieee80211_wake_queues_by_reason(&local->hw,
1380 IEEE80211_MAX_QUEUE_MAP,
1378 IEEE80211_QUEUE_STOP_REASON_PS); 1381 IEEE80211_QUEUE_STOP_REASON_PS);
1379} 1382}
1380 1383
@@ -2071,6 +2074,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2071 true, frame_buf); 2074 true, frame_buf);
2072 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 2075 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
2073 ieee80211_wake_queues_by_reason(&sdata->local->hw, 2076 ieee80211_wake_queues_by_reason(&sdata->local->hw,
2077 IEEE80211_MAX_QUEUE_MAP,
2074 IEEE80211_QUEUE_STOP_REASON_CSA); 2078 IEEE80211_QUEUE_STOP_REASON_CSA);
2075 mutex_unlock(&ifmgd->mtx); 2079 mutex_unlock(&ifmgd->mtx);
2076 2080
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index d32f514074b9..b01eb7314ec6 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -118,7 +118,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
118 * Stop queues and transmit all frames queued by the driver 118 * Stop queues and transmit all frames queued by the driver
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, 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 ieee80211_flush_queues(local, NULL); 123 ieee80211_flush_queues(local, NULL);
124 124
@@ -181,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
181 } 181 }
182 mutex_unlock(&local->iflist_mtx); 182 mutex_unlock(&local->iflist_mtx);
183 183
184 ieee80211_wake_queues_by_reason(&local->hw, 184 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
185 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); 185 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
186} 186}
187 187
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 497f21a0d116..3d16f4e61743 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -30,7 +30,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
30 } 30 }
31 31
32 ieee80211_stop_queues_by_reason(hw, 32 ieee80211_stop_queues_by_reason(hw,
33 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 33 IEEE80211_MAX_QUEUE_MAP,
34 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
34 35
35 /* flush out all packets */ 36 /* flush out all packets */
36 synchronize_net(); 37 synchronize_net();
@@ -68,6 +69,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
68 mutex_unlock(&local->sta_mtx); 69 mutex_unlock(&local->sta_mtx);
69 } 70 }
70 ieee80211_wake_queues_by_reason(hw, 71 ieee80211_wake_queues_by_reason(hw,
72 IEEE80211_MAX_QUEUE_MAP,
71 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 73 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
72 return err; 74 return err;
73 } else if (err > 0) { 75 } else if (err > 0) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3fcdf2118101..2a6ae8030bd9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -233,6 +233,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
233 233
234 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 234 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
235 ieee80211_stop_queues_by_reason(&local->hw, 235 ieee80211_stop_queues_by_reason(&local->hw,
236 IEEE80211_MAX_QUEUE_MAP,
236 IEEE80211_QUEUE_STOP_REASON_PS); 237 IEEE80211_QUEUE_STOP_REASON_PS);
237 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 238 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
238 ieee80211_queue_work(&local->hw, 239 ieee80211_queue_work(&local->hw,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f978ddd1bb43..a7368870c8ee 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
453} 453}
454 454
455void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 455void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
456 enum queue_stop_reason reason) 456 unsigned long queues,
457 enum queue_stop_reason reason)
457{ 458{
458 struct ieee80211_local *local = hw_to_local(hw); 459 struct ieee80211_local *local = hw_to_local(hw);
459 unsigned long flags; 460 unsigned long flags;
@@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
461 462
462 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 463 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
463 464
464 for (i = 0; i < hw->queues; i++) 465 for_each_set_bit(i, &queues, hw->queues)
465 __ieee80211_stop_queue(hw, i, reason); 466 __ieee80211_stop_queue(hw, i, reason);
466 467
467 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 468 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
469 470
470void ieee80211_stop_queues(struct ieee80211_hw *hw) 471void ieee80211_stop_queues(struct ieee80211_hw *hw)
471{ 472{
472 ieee80211_stop_queues_by_reason(hw, 473 ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
473 IEEE80211_QUEUE_STOP_REASON_DRIVER); 474 IEEE80211_QUEUE_STOP_REASON_DRIVER);
474} 475}
475EXPORT_SYMBOL(ieee80211_stop_queues); 476EXPORT_SYMBOL(ieee80211_stop_queues);
@@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
491EXPORT_SYMBOL(ieee80211_queue_stopped); 492EXPORT_SYMBOL(ieee80211_queue_stopped);
492 493
493void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 494void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
495 unsigned long queues,
494 enum queue_stop_reason reason) 496 enum queue_stop_reason reason)
495{ 497{
496 struct ieee80211_local *local = hw_to_local(hw); 498 struct ieee80211_local *local = hw_to_local(hw);
@@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
499 501
500 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 502 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
501 503
502 for (i = 0; i < hw->queues; i++) 504 for_each_set_bit(i, &queues, hw->queues)
503 __ieee80211_wake_queue(hw, i, reason); 505 __ieee80211_wake_queue(hw, i, reason);
504 506
505 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 507 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -507,7 +509,8 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
507 509
508void ieee80211_wake_queues(struct ieee80211_hw *hw) 510void ieee80211_wake_queues(struct ieee80211_hw *hw)
509{ 511{
510 ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER); 512 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
513 IEEE80211_QUEUE_STOP_REASON_DRIVER);
511} 514}
512EXPORT_SYMBOL(ieee80211_wake_queues); 515EXPORT_SYMBOL(ieee80211_wake_queues);
513 516
@@ -533,7 +536,13 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
533 queues = BIT(local->hw.queues) - 1; 536 queues = BIT(local->hw.queues) - 1;
534 } 537 }
535 538
539 ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
540 IEEE80211_QUEUE_STOP_REASON_FLUSH);
541
536 drv_flush(local, queues, false); 542 drv_flush(local, queues, false);
543
544 ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
545 IEEE80211_QUEUE_STOP_REASON_FLUSH);
537} 546}
538 547
539void ieee80211_iterate_active_interfaces( 548void ieee80211_iterate_active_interfaces(
@@ -1676,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1676 mutex_unlock(&local->sta_mtx); 1685 mutex_unlock(&local->sta_mtx);
1677 } 1686 }
1678 1687
1679 ieee80211_wake_queues_by_reason(hw, 1688 ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
1680 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1689 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
1681 1690
1682 /* 1691 /*
1683 * If this is for hw restart things are still running. 1692 * If this is for hw restart things are still running.