All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] mac80211: some queue stop/wake patches
@ 2014-06-13 13:30 Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 1/4] mac80211: don't stop all queues when flushing Luca Coelho
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Luca Coelho @ 2014-06-13 13:30 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless, emmanuel.grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

This replaces the last 3 patches from me that Emmanuel sent out and
includes my RFC option 2 v2 patch.

Luciano Coelho (4):
  mac80211: don't stop all queues when flushing
  mac80211: introduce refcount for queue_stop_reasons
  mac80211: add functions to stop and wake all queues assigned to a vif
  mac80211: stop only the queues assigned to the vif during channel
    switch

 net/mac80211/agg-tx.c      |   8 ++-
 net/mac80211/cfg.c         |  49 +++++-------------
 net/mac80211/ieee80211_i.h |  22 +++++++--
 net/mac80211/iface.c       |   9 ++--
 net/mac80211/main.c        |   3 +-
 net/mac80211/mlme.c        |  35 +++++++------
 net/mac80211/offchannel.c  |   6 ++-
 net/mac80211/pm.c          |   6 ++-
 net/mac80211/tx.c          |   3 +-
 net/mac80211/util.c        | 121 ++++++++++++++++++++++++++++++++-------------
 10 files changed, 160 insertions(+), 102 deletions(-)

-- 
2.0.0.rc2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/4] mac80211: don't stop all queues when flushing
  2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
@ 2014-06-13 13:30 ` Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 2/4] mac80211: introduce refcount for queue_stop_reasons Luca Coelho
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luca Coelho @ 2014-06-13 13:30 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless, emmanuel.grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

There is no need to stop all queues when we want to flush specific
queues, so stop only the queues that will be flushed.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
---
 net/mac80211/util.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7e0dd4b..04e5f5c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -551,12 +551,12 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
 		queues = BIT(local->hw.queues) - 1;
 	}
 
-	ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+	ieee80211_stop_queues_by_reason(&local->hw, queues,
 					IEEE80211_QUEUE_STOP_REASON_FLUSH);
 
 	drv_flush(local, sdata, queues, false);
 
-	ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+	ieee80211_wake_queues_by_reason(&local->hw, queues,
 					IEEE80211_QUEUE_STOP_REASON_FLUSH);
 }
 
-- 
2.0.0.rc2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/4] mac80211: introduce refcount for queue_stop_reasons
  2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 1/4] mac80211: don't stop all queues when flushing Luca Coelho
@ 2014-06-13 13:30 ` Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 3/4] mac80211: add functions to stop and wake all queues assigned to a vif Luca Coelho
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luca Coelho @ 2014-06-13 13:30 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless, emmanuel.grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

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>
---
Comparing to RFC option 2 v2:

  * don't change debugfs, since we now have the reason mask anyway
---
 net/mac80211/agg-tx.c      |  8 +++--
 net/mac80211/cfg.c         |  9 ++++--
 net/mac80211/ieee80211_i.h | 15 ++++++---
 net/mac80211/iface.c       |  3 +-
 net/mac80211/main.c        |  3 +-
 net/mac80211/mlme.c        | 15 ++++++---
 net/mac80211/offchannel.c  |  6 ++--
 net/mac80211/pm.c          |  6 ++--
 net/mac80211/tx.c          |  3 +-
 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 ce9633a..d6986f3 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)
 {
 	int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
 
+	/* we do refcounting here, so don't use the queue reason refcounting */
+
 	if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1)
 		ieee80211_stop_queue_by_reason(
 			&sdata->local->hw, queue,
-			IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
+			IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
+			false);
 	__acquire(agg_queue);
 }
 
@@ -185,7 +188,8 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
 	if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0)
 		ieee80211_wake_queue_by_reason(
 			&sdata->local->hw, queue,
-			IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
+			IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
+			false);
 	__release(agg_queue);
 }
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index af3eac4..e920d48 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)
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 
 	kfree(sdata->u.ap.next_beacon);
@@ -2828,7 +2829,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 
 	return 0;
 }
@@ -3060,7 +3062,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 	if (sdata->csa_block_tx)
 		ieee80211_stop_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 
 	if (changed) {
 		ieee80211_bss_info_change_notify(sdata, changed);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 677e9c8..f2b59c6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -921,6 +921,8 @@ enum queue_stop_reason {
 	IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
 	IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
 	IEEE80211_QUEUE_STOP_REASON_FLUSH,
+
+	IEEE80211_QUEUE_STOP_REASONS,
 };
 
 #ifdef CONFIG_MAC80211_LEDS
@@ -1017,6 +1019,7 @@ struct ieee80211_local {
 	struct workqueue_struct *workqueue;
 
 	unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
+	int q_stop_reasons[IEEE80211_MAX_QUEUES][IEEE80211_QUEUE_STOP_REASONS];
 	/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
 	spinlock_t queue_stop_reason_lock;
 
@@ -1714,14 +1717,18 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
-				     enum queue_stop_reason reason);
+				     enum queue_stop_reason reason,
+				     bool refcounted);
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
-				     enum queue_stop_reason reason);
+				     enum queue_stop_reason reason,
+				     bool refcounted);
 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
-				    enum queue_stop_reason reason);
+				    enum queue_stop_reason reason,
+				    bool refcounted);
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
-				    enum queue_stop_reason reason);
+				    enum queue_stop_reason reason,
+				    bool refcounted);
 void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
 void ieee80211_add_pending_skb(struct ieee80211_local *local,
 			       struct sk_buff *skb);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 00762a1..5e7b371 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,
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 	sdata_unlock(sdata);
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 54e632b..89170c8 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -270,7 +270,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 
 	/* use this reason, ieee80211_reconfig will unblock it */
 	ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+					false);
 
 	/*
 	 * 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 7f073ef..8b73476 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -983,7 +983,8 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@@ -1115,7 +1116,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	if (sdata->csa_block_tx)
 		ieee80211_stop_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 
 	if (local->ops->channel_switch) {
@@ -1385,7 +1387,8 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
 
 	ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_PS);
+					IEEE80211_QUEUE_STOP_REASON_PS,
+					false);
 }
 
 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,
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 
 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
@@ -2082,7 +2086,8 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
 	if (!ieee80211_csa_needs_block_tx(local))
 		ieee80211_wake_queues_by_reason(&local->hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
+					IEEE80211_QUEUE_STOP_REASON_CSA,
+					false);
 	mutex_unlock(&local->mtx);
 
 	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 0c2a294..1a523e0 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -119,7 +119,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
 	 * before sending nullfunc to enable powersave at the AP.
 	 */
 	ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
+					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
+					false);
 	ieee80211_flush_queues(local, NULL);
 
 	mutex_lock(&local->iflist_mtx);
@@ -182,7 +183,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
 	mutex_unlock(&local->iflist_mtx);
 
 	ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
+					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
+					false);
 }
 
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index d478b88..4c5192e 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)
 
 	ieee80211_stop_queues_by_reason(hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+					false);
 
 	/* flush out all packets */
 	synchronize_net();
@@ -74,7 +75,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			}
 			ieee80211_wake_queues_by_reason(hw,
 					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+					false);
 			return err;
 		} else if (err > 0) {
 			WARN_ON(err != 1);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0a519a5..662a984 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)
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 		ieee80211_stop_queues_by_reason(&local->hw,
 						IEEE80211_MAX_QUEUE_MAP,
-						IEEE80211_QUEUE_STOP_REASON_PS);
+						IEEE80211_QUEUE_STOP_REASON_PS,
+						false);
 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 		ieee80211_queue_work(&local->hw,
 				     &local->dynamic_ps_disable_work);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 04e5f5c..8552fe4 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)
 }
 
 static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
-				   enum queue_stop_reason reason)
+				   enum queue_stop_reason reason,
+				   bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 
@@ -329,7 +330,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
 	if (!test_bit(reason, &local->queue_stop_reasons[queue]))
 		return;
 
-	__clear_bit(reason, &local->queue_stop_reasons[queue]);
+	if (!refcounted)
+		local->q_stop_reasons[queue][reason] = 0;
+	else
+		local->q_stop_reasons[queue][reason]--;
+
+	if (local->q_stop_reasons[queue][reason] == 0)
+		__clear_bit(reason, &local->queue_stop_reasons[queue]);
 
 	if (local->queue_stop_reasons[queue] != 0)
 		/* someone still has this queue stopped */
@@ -344,25 +351,28 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
 }
 
 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
-				    enum queue_stop_reason reason)
+				    enum queue_stop_reason reason,
+				    bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	__ieee80211_wake_queue(hw, queue, reason);
+	__ieee80211_wake_queue(hw, queue, reason, refcounted);
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
 
 void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
 {
 	ieee80211_wake_queue_by_reason(hw, queue,
-				       IEEE80211_QUEUE_STOP_REASON_DRIVER);
+				       IEEE80211_QUEUE_STOP_REASON_DRIVER,
+				       false);
 }
 EXPORT_SYMBOL(ieee80211_wake_queue);
 
 static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
-				   enum queue_stop_reason reason)
+				   enum queue_stop_reason reason,
+				   bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
@@ -373,10 +383,13 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
 	if (WARN_ON(queue >= hw->queues))
 		return;
 
-	if (test_bit(reason, &local->queue_stop_reasons[queue]))
-		return;
+	if (!refcounted)
+		local->q_stop_reasons[queue][reason] = 1;
+	else
+		local->q_stop_reasons[queue][reason]++;
 
-	__set_bit(reason, &local->queue_stop_reasons[queue]);
+	if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
+		return;
 
 	if (local->hw.queues < IEEE80211_NUM_ACS)
 		n_acs = 1;
@@ -398,20 +411,22 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
 }
 
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
-				    enum queue_stop_reason reason)
+				    enum queue_stop_reason reason,
+				    bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	__ieee80211_stop_queue(hw, queue, reason);
+	__ieee80211_stop_queue(hw, queue, reason, refcounted);
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
 
 void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
 {
 	ieee80211_stop_queue_by_reason(hw, queue,
-				       IEEE80211_QUEUE_STOP_REASON_DRIVER);
+				       IEEE80211_QUEUE_STOP_REASON_DRIVER,
+				       false);
 }
 EXPORT_SYMBOL(ieee80211_stop_queue);
 
@@ -429,9 +444,11 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
 	}
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+	__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+			       false);
 	__skb_queue_tail(&local->pending[queue], skb);
-	__ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+	__ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+			       false);
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
 
@@ -455,20 +472,23 @@ void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 		queue = info->hw_queue;
 
 		__ieee80211_stop_queue(hw, queue,
-				IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+				IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+				false);
 
 		__skb_queue_tail(&local->pending[queue], skb);
 	}
 
 	for (i = 0; i < hw->queues; i++)
 		__ieee80211_wake_queue(hw, i,
-			IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+			IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+			false);
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
 
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
-				     enum queue_stop_reason reason)
+				     enum queue_stop_reason reason,
+				     bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
@@ -477,7 +497,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
 	for_each_set_bit(i, &queues, hw->queues)
-		__ieee80211_stop_queue(hw, i, reason);
+		__ieee80211_stop_queue(hw, i, reason, refcounted);
 
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
@@ -485,7 +505,8 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 void ieee80211_stop_queues(struct ieee80211_hw *hw)
 {
 	ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_DRIVER);
+					IEEE80211_QUEUE_STOP_REASON_DRIVER,
+					false);
 }
 EXPORT_SYMBOL(ieee80211_stop_queues);
 
@@ -508,7 +529,8 @@ EXPORT_SYMBOL(ieee80211_queue_stopped);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
-				     enum queue_stop_reason reason)
+				     enum queue_stop_reason reason,
+				     bool refcounted)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
@@ -517,7 +539,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
 	for_each_set_bit(i, &queues, hw->queues)
-		__ieee80211_wake_queue(hw, i, reason);
+		__ieee80211_wake_queue(hw, i, reason, refcounted);
 
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
@@ -525,7 +547,8 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 void ieee80211_wake_queues(struct ieee80211_hw *hw)
 {
 	ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_DRIVER);
+					IEEE80211_QUEUE_STOP_REASON_DRIVER,
+					false);
 }
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
@@ -552,12 +575,14 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
 	}
 
 	ieee80211_stop_queues_by_reason(&local->hw, queues,
-					IEEE80211_QUEUE_STOP_REASON_FLUSH);
+					IEEE80211_QUEUE_STOP_REASON_FLUSH,
+					false);
 
 	drv_flush(local, sdata, queues, false);
 
 	ieee80211_wake_queues_by_reason(&local->hw, queues,
-					IEEE80211_QUEUE_STOP_REASON_FLUSH);
+					IEEE80211_QUEUE_STOP_REASON_FLUSH,
+					false);
 }
 
 static void __iterate_active_interfaces(struct ieee80211_local *local,
@@ -1797,7 +1822,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	}
 
 	ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+					false);
 
 	/*
 	 * Reconfigure sched scan if it was interrupted by FW restart or
-- 
2.0.0.rc2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/4] mac80211: add functions to stop and wake all queues assigned to a vif
  2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 1/4] mac80211: don't stop all queues when flushing Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 2/4] mac80211: introduce refcount for queue_stop_reasons Luca Coelho
@ 2014-06-13 13:30 ` Luca Coelho
  2014-06-13 13:30 ` [PATCH v2 4/4] mac80211: stop only the queues assigned to the vif during channel switch Luca Coelho
  2014-06-23 12:18 ` [PATCH v2 0/4] mac80211: some queue stop/wake patches Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Luca Coelho @ 2014-06-13 13:30 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless, emmanuel.grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

In some cases we may want to stop the queues of a single vif (for
instance during a channel-switch).  Add a function that stops all the
queues that are assigned to a vif.  If a queue is assigned to more
than one vif, the corresponding netdev subqueue of the other vif(s)
will also be stopped.  If the HW doesn't set the
IEEE80211_HW_QUEUE_CONTROL flag, then all queues are stopped.

Also add a corresponding function to wake the queues of a vif back.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
---
In v2:

  * use unsigned int instead of u32 for the queues variables;
  * pass reason instead of IEEE80211_QUEUE_STOP_REASON_DRIVER in
    wake_vif_queues();
  * rebase on top of the new refcounted stop/wake queues;
---
 net/mac80211/ieee80211_i.h |  6 ++++++
 net/mac80211/util.c        | 41 +++++++++++++++++++++++++++++++++++------
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f2b59c6..dd3086d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1719,6 +1719,12 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
 				     enum queue_stop_reason reason,
 				     bool refcounted);
+void ieee80211_stop_vif_queues(struct ieee80211_local *local,
+			       struct ieee80211_sub_if_data *sdata,
+			       enum queue_stop_reason reason);
+void ieee80211_wake_vif_queues(struct ieee80211_local *local,
+			       struct ieee80211_sub_if_data *sdata,
+			       enum queue_stop_reason reason);
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
 				     enum queue_stop_reason reason,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 8552fe4..4978b62 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -552,13 +552,11 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
-void ieee80211_flush_queues(struct ieee80211_local *local,
-			    struct ieee80211_sub_if_data *sdata)
+static unsigned int
+ieee80211_get_vif_queues(struct ieee80211_local *local,
+			 struct ieee80211_sub_if_data *sdata)
 {
-	u32 queues;
-
-	if (!local->ops->flush)
-		return;
+	unsigned int queues;
 
 	if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
 		int ac;
@@ -574,6 +572,19 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
 		queues = BIT(local->hw.queues) - 1;
 	}
 
+	return queues;
+}
+
+void ieee80211_flush_queues(struct ieee80211_local *local,
+			    struct ieee80211_sub_if_data *sdata)
+{
+	unsigned int queues;
+
+	if (!local->ops->flush)
+		return;
+
+	queues = ieee80211_get_vif_queues(local, sdata);
+
 	ieee80211_stop_queues_by_reason(&local->hw, queues,
 					IEEE80211_QUEUE_STOP_REASON_FLUSH,
 					false);
@@ -585,6 +596,24 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
 					false);
 }
 
+void ieee80211_stop_vif_queues(struct ieee80211_local *local,
+			       struct ieee80211_sub_if_data *sdata,
+			       enum queue_stop_reason reason)
+{
+	ieee80211_stop_queues_by_reason(&local->hw,
+					ieee80211_get_vif_queues(local, sdata),
+					reason, true);
+}
+
+void ieee80211_wake_vif_queues(struct ieee80211_local *local,
+			       struct ieee80211_sub_if_data *sdata,
+			       enum queue_stop_reason reason)
+{
+	ieee80211_wake_queues_by_reason(&local->hw,
+					ieee80211_get_vif_queues(local, sdata),
+					reason, true);
+}
+
 static void __iterate_active_interfaces(struct ieee80211_local *local,
 					u32 iter_flags,
 					void (*iterator)(void *data, u8 *mac,
-- 
2.0.0.rc2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/4] mac80211: stop only the queues assigned to the vif during channel switch
  2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
                   ` (2 preceding siblings ...)
  2014-06-13 13:30 ` [PATCH v2 3/4] mac80211: add functions to stop and wake all queues assigned to a vif Luca Coelho
@ 2014-06-13 13:30 ` Luca Coelho
  2014-06-23 12:18 ` [PATCH v2 0/4] mac80211: some queue stop/wake patches Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Luca Coelho @ 2014-06-13 13:30 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless, emmanuel.grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

Instead of stopping all the hardware queues during channel switch,
which is especially bad when we have large CSA counts, stop only the
queues that are assigned to the vif that is performing the channel
switch.

Additionally, check for (sdata->csa_block_tx) instead of calling
ieee80211_csa_needs_block_tx(), which can now be removed.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
---
In v2:
   * remove ieee80211_csa_needs_block_tx();
   * rebased on top of the new refcounted stop/wake queues functions;
---
 net/mac80211/cfg.c         | 52 ++++++++++++----------------------------------
 net/mac80211/ieee80211_i.h |  1 -
 net/mac80211/iface.c       | 10 ++++-----
 net/mac80211/mlme.c        | 36 +++++++++++++++-----------------
 4 files changed, 35 insertions(+), 64 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e920d48..a0d7a03 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -790,31 +790,6 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
 	return 0;
 }
 
-bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local)
-{
-	struct ieee80211_sub_if_data *sdata;
-
-	lockdep_assert_held(&local->mtx);
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!ieee80211_sdata_running(sdata))
-			continue;
-
-		if (!sdata->vif.csa_active)
-			continue;
-
-		if (!sdata->csa_block_tx)
-			continue;
-
-		rcu_read_unlock();
-		return true;
-	}
-	rcu_read_unlock();
-
-	return false;
-}
-
 static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -834,11 +809,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 	/* abort any running channel switch */
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
+
 	mutex_unlock(&local->mtx);
 
 	kfree(sdata->u.ap.next_beacon);
@@ -2826,11 +2802,11 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
 	ieee80211_bss_info_change_notify(sdata, changed);
 	cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
 
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 
 	return 0;
 }
@@ -3060,10 +3036,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 	sdata->vif.csa_active = true;
 
 	if (sdata->csa_block_tx)
-		ieee80211_stop_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+		ieee80211_stop_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
 
 	if (changed) {
 		ieee80211_bss_info_change_notify(sdata, changed);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index dd3086d..c1d5a6e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1488,7 +1488,6 @@ void ieee80211_sw_roc_work(struct work_struct *work);
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
 /* channel switch handling */
-bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local);
 void ieee80211_csa_finalize_work(struct work_struct *work);
 int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 			     struct cfg80211_csa_settings *params);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5e7b371..f8de583 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -841,11 +841,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 	sdata_lock(sdata);
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 	mutex_unlock(&local->mtx);
 	sdata_unlock(sdata);
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8b73476..aa5049f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -980,11 +980,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
 	/* XXX: wait for a beacon first? */
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 	mutex_unlock(&local->mtx);
 
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@@ -1114,10 +1114,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	sdata->csa_block_tx = csa_ie.mode;
 
 	if (sdata->csa_block_tx)
-		ieee80211_stop_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+		ieee80211_stop_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
 	mutex_unlock(&local->mtx);
 
 	if (local->ops->channel_switch) {
@@ -1833,11 +1831,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	ieee80211_vif_release_channel(sdata);
 
 	sdata->vif.csa_active = false;
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 	mutex_unlock(&local->mtx);
 
 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
@@ -2083,11 +2081,11 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
 
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
-	if (!ieee80211_csa_needs_block_tx(local))
-		ieee80211_wake_queues_by_reason(&local->hw,
-					IEEE80211_MAX_QUEUE_MAP,
-					IEEE80211_QUEUE_STOP_REASON_CSA,
-					false);
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 	mutex_unlock(&local->mtx);
 
 	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
-- 
2.0.0.rc2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/4] mac80211: some queue stop/wake patches
  2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
                   ` (3 preceding siblings ...)
  2014-06-13 13:30 ` [PATCH v2 4/4] mac80211: stop only the queues assigned to the vif during channel switch Luca Coelho
@ 2014-06-23 12:18 ` Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2014-06-23 12:18 UTC (permalink / raw)
  To: Luca Coelho; +Cc: michal.kazior, linux-wireless, emmanuel.grumbach

On Fri, 2014-06-13 at 16:30 +0300, Luca Coelho wrote:
> From: Luciano Coelho <luciano.coelho@intel.com>
> 
> This replaces the last 3 patches from me that Emmanuel sent out and
> includes my RFC option 2 v2 patch.

Applied.

johannes


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-06-23 12:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-13 13:30 [PATCH v2 0/4] mac80211: some queue stop/wake patches Luca Coelho
2014-06-13 13:30 ` [PATCH v2 1/4] mac80211: don't stop all queues when flushing Luca Coelho
2014-06-13 13:30 ` [PATCH v2 2/4] mac80211: introduce refcount for queue_stop_reasons Luca Coelho
2014-06-13 13:30 ` [PATCH v2 3/4] mac80211: add functions to stop and wake all queues assigned to a vif Luca Coelho
2014-06-13 13:30 ` [PATCH v2 4/4] mac80211: stop only the queues assigned to the vif during channel switch Luca Coelho
2014-06-23 12:18 ` [PATCH v2 0/4] mac80211: some queue stop/wake patches Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.