All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] mac80211: introduce refcount for queue_stop_reasons
@ 2014-06-06 15:27 Luca Coelho
  2014-06-06 18:46 ` [RFC option 2] " Luca Coelho
  0 siblings, 1 reply; 8+ messages in thread
From: Luca Coelho @ 2014-06-06 15:27 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless

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.

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

As discussed on IRC, I'm trying to convert the queue stop reasons to
have a refcount instead of a single boolean for each reason.

This is the first option, accessing the entire array of reasons when
checking if the queue is stopped by any reason.  This introduces some
extra for loops in the TX path...

The other option would be to "cache" the stop state of each queue, so
when checking if the queue is stopped by any reason, we could test a
single bit.  This should be simple to do as well, I just keep the old
bitmask and set/unset the reason bit when ref'ing/unref'ing.

Please let me know what you think!


 net/mac80211/debugfs.c     | 13 ++++++++-----
 net/mac80211/ieee80211_i.h |  6 +++++-
 net/mac80211/iface.c       |  6 ++++--
 net/mac80211/mlme.c        |  2 +-
 net/mac80211/tx.c          |  6 +++---
 net/mac80211/util.c        | 34 ++++++++++++++++++++++------------
 6 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 0e963bc1..81f110b 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -332,13 +332,16 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
 	struct ieee80211_local *local = file->private_data;
 	unsigned long flags;
 	char buf[IEEE80211_MAX_QUEUES * 20];
-	int q, res = 0;
+	int q, r, res = 0;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	for (q = 0; q < local->hw.queues; q++)
-		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
-				local->queue_stop_reasons[q],
-				skb_queue_len(&local->pending[q]));
+	for (q = 0; q < local->hw.queues; q++) {
+		for (r = 0; r < IEEE80211_QSTOP_REASONS; r++)
+			res += sprintf(buf + res,
+				       "%02d: reason[%02d] = %d/%d\n", q, r,
+				       local->queue_stop_reasons[q][r],
+				       skb_queue_len(&local->pending[q]));
+	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 677e9c8..e9f7ab2 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_QSTOP_REASONS,
 };
 
 #ifdef CONFIG_MAC80211_LEDS
@@ -1016,7 +1018,7 @@ struct ieee80211_local {
 	 */
 	struct workqueue_struct *workqueue;
 
-	unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
+	int queue_stop_reasons[IEEE80211_MAX_QUEUES][IEEE80211_QSTOP_REASONS];
 	/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
 	spinlock_t queue_stop_reason_lock;
 
@@ -1722,6 +1724,8 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
 				    enum queue_stop_reason reason);
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
 				    enum queue_stop_reason reason);
+unsigned long ieee80211_queue_stop_reasons(struct ieee80211_local *local,
+					   unsigned int queue);
 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..0899040 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -708,12 +708,14 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 		if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
-		    (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
+		    (!ieee80211_queue_stop_reasons(local,
+						   sdata->vif.cab_queue) &&
 		     skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
 			for (ac = 0; ac < n_acs; ac++) {
 				int ac_queue = sdata->vif.hw_queue[ac];
 
-				if (local->queue_stop_reasons[ac_queue] == 0 &&
+				if (!ieee80211_queue_stop_reasons(local,
+								  ac_queue) &&
 				    skb_queue_empty(&local->pending[ac_queue]))
 					netif_start_subqueue(dev, ac);
 			}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7f073ef..1b7c736 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1423,7 +1423,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		 */
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 		for (q = 0; q < local->hw.queues; q++) {
-			if (local->queue_stop_reasons[q]) {
+			if (ieee80211_queue_stop_reasons(local, q)) {
 				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
 						       flags);
 				mod_timer(&local->dynamic_ps_timer, jiffies +
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0a519a5..0cf3b56 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1216,11 +1216,11 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
 #endif
 
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-		if (local->queue_stop_reasons[q] ||
+		if (ieee80211_queue_stop_reasons(local, q) ||
 		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
 			if (unlikely(info->flags &
 				     IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
-				if (local->queue_stop_reasons[q] &
+				if (ieee80211_queue_stop_reasons(local, q) &
 				    ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
 					/*
 					 * Drop off-channel frames if queues
@@ -2297,7 +2297,7 @@ void ieee80211_tx_pending(unsigned long data)
 		 * If queue is stopped by something other than due to pending
 		 * frames, or we have no pending frames, proceed to next queue.
 		 */
-		if (local->queue_stop_reasons[i] ||
+		if (ieee80211_queue_stop_reasons(local, i) ||
 		    skb_queue_empty(&local->pending[i]))
 			continue;
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 04e5f5c..91226ab 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -286,6 +286,19 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_ctstoself_duration);
 
+unsigned long ieee80211_queue_stop_reasons(struct ieee80211_local *local,
+					   unsigned int queue)
+{
+	int i;
+	unsigned long reasons = 0;
+
+	for (i = 0; i < IEEE80211_QSTOP_REASONS; i++)
+		if (local->queue_stop_reasons[queue][i])
+			reasons |= BIT(i);
+
+	return reasons;
+}
+
 void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
 {
 	struct ieee80211_sub_if_data *sdata;
@@ -301,7 +314,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
 			continue;
 
 		if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
-		    local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
+		    ieee80211_queue_stop_reasons(local, sdata->vif.cab_queue))
 			continue;
 
 		for (ac = 0; ac < n_acs; ac++) {
@@ -309,7 +322,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
 
 			if (ac_queue == queue ||
 			    (sdata->vif.cab_queue == queue &&
-			     local->queue_stop_reasons[ac_queue] == 0 &&
+			     !ieee80211_queue_stop_reasons(local, ac_queue) &&
 			     skb_queue_empty(&local->pending[ac_queue])))
 				netif_wake_subqueue(sdata->dev, ac);
 		}
@@ -326,12 +339,12 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
 	if (WARN_ON(queue >= hw->queues))
 		return;
 
-	if (!test_bit(reason, &local->queue_stop_reasons[queue]))
+	if (local->queue_stop_reasons[queue][reason] == 0)
 		return;
 
-	__clear_bit(reason, &local->queue_stop_reasons[queue]);
+	local->queue_stop_reasons[queue][reason]--;
 
-	if (local->queue_stop_reasons[queue] != 0)
+	if (ieee80211_queue_stop_reasons(local, queue))
 		/* someone still has this queue stopped */
 		return;
 
@@ -373,11 +386,9 @@ 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]))
+	if (local->queue_stop_reasons[queue][reason]++)
 		return;
 
-	__set_bit(reason, &local->queue_stop_reasons[queue]);
-
 	if (local->hw.queues < IEEE80211_NUM_ACS)
 		n_acs = 1;
 
@@ -489,18 +500,17 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_stop_queues);
 
-int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
+int ieee80211_queue_stopped(struct ieee80211_hw *hw, int q)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
 	int ret;
 
-	if (WARN_ON(queue >= hw->queues))
+	if (WARN_ON(q >= hw->queues))
 		return true;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	ret = test_bit(IEEE80211_QUEUE_STOP_REASON_DRIVER,
-		       &local->queue_stop_reasons[queue]);
+	ret = local->queue_stop_reasons[q][IEEE80211_QUEUE_STOP_REASON_DRIVER];
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 	return ret;
 }
-- 
2.0.0.rc2


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

* [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-06 15:27 [RFC] mac80211: introduce refcount for queue_stop_reasons Luca Coelho
@ 2014-06-06 18:46 ` Luca Coelho
  2014-06-09  5:34   ` Michal Kazior
  0 siblings, 1 reply; 8+ messages in thread
From: Luca Coelho @ 2014-06-06 18:46 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless

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.

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

This looks much simpler now.  The only thing is that we need to make
sure the bitmask never gets out of sync with the refcounts, which
shouldn't be too difficult, as long as we keep the refcounts usage
restricted to the queues start/stopping functions.

 net/mac80211/debugfs.c     | 13 ++++++++-----
 net/mac80211/ieee80211_i.h |  3 +++
 net/mac80211/util.c        |  7 ++++---
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 0e963bc1..3ca4d78 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -332,13 +332,16 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
 	struct ieee80211_local *local = file->private_data;
 	unsigned long flags;
 	char buf[IEEE80211_MAX_QUEUES * 20];
-	int q, res = 0;
+	int q, r, res = 0;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	for (q = 0; q < local->hw.queues; q++)
-		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
-				local->queue_stop_reasons[q],
-				skb_queue_len(&local->pending[q]));
+	for (q = 0; q < local->hw.queues; q++) {
+		for (r = 0; r < IEEE80211_QUEUE_STOP_REASONS; r++)
+			res += sprintf(buf + res,
+				       "%02d: reason[%02d] = %d/%d\n", q, r,
+				       local->q_stop_reasons[q][r],
+				       skb_queue_len(&local->pending[q]));
+	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 677e9c8..fd17a5b 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;
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 04e5f5c..4db4f35 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -326,10 +326,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
 	if (WARN_ON(queue >= hw->queues))
 		return;
 
-	if (!test_bit(reason, &local->queue_stop_reasons[queue]))
+	if (local->q_stop_reasons[queue][reason] == 0)
 		return;
 
-	__clear_bit(reason, &local->queue_stop_reasons[queue]);
+	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 */
@@ -373,7 +374,7 @@ 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]))
+	if (local->q_stop_reasons[queue][reason]++)
 		return;
 
 	__set_bit(reason, &local->queue_stop_reasons[queue]);
-- 
2.0.0.rc2


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

* Re: [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-06 18:46 ` [RFC option 2] " Luca Coelho
@ 2014-06-09  5:34   ` Michal Kazior
  2014-06-09  7:21     ` Luca Coelho
  0 siblings, 1 reply; 8+ messages in thread
From: Michal Kazior @ 2014-06-09  5:34 UTC (permalink / raw)
  To: Luca Coelho; +Cc: Johannes Berg, linux-wireless

On 6 June 2014 20:46, Luca Coelho <luca@coelho.fi> wrote:
> 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.
>
> Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
> ---
>
> This looks much simpler now.  The only thing is that we need to make
> sure the bitmask never gets out of sync with the refcounts, which
> shouldn't be too difficult, as long as we keep the refcounts usage
> restricted to the queues start/stopping functions.

I think you need to make sure all stop/wake calls are balanced
everywhere (including device drivers). Otherwise you risk breaking
things silently in some cases.

It might also be worth to update exported stop/wake symbol documentation too.


Michał

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

* Re: [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-09  5:34   ` Michal Kazior
@ 2014-06-09  7:21     ` Luca Coelho
  2014-06-09  9:17       ` Johannes Berg
  0 siblings, 1 reply; 8+ messages in thread
From: Luca Coelho @ 2014-06-09  7:21 UTC (permalink / raw)
  To: Michal Kazior; +Cc: Johannes Berg, linux-wireless

On Mon, 2014-06-09 at 07:34 +0200, Michal Kazior wrote:
> On 6 June 2014 20:46, Luca Coelho <luca@coelho.fi> wrote:
> > 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.
> >
> > Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
> > ---
> >
> > This looks much simpler now.  The only thing is that we need to make
> > sure the bitmask never gets out of sync with the refcounts, which
> > shouldn't be too difficult, as long as we keep the refcounts usage
> > restricted to the queues start/stopping functions.
> 
> I think you need to make sure all stop/wake calls are balanced
> everywhere (including device drivers). Otherwise you risk breaking
> things silently in some cases.
> 
> It might also be worth to update exported stop/wake symbol documentation too.

Good point, I'll look into that.

My original idea was to mark the queues as stopped in the sdata so we
would at least clean things up when the vif is stopped, but that would
be a bit slow if we had to traverse them all the time.

Checking this might be tricky, actually, since I think there are some
assumptions that stopping a queue that is already stopped is a NOP, but
now we add to the refcount...

--
Luca.


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

* Re: [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-09  7:21     ` Luca Coelho
@ 2014-06-09  9:17       ` Johannes Berg
  2014-06-09  9:21         ` Luca Coelho
  0 siblings, 1 reply; 8+ messages in thread
From: Johannes Berg @ 2014-06-09  9:17 UTC (permalink / raw)
  To: Luca Coelho; +Cc: Michal Kazior, linux-wireless

On Mon, 2014-06-09 at 10:21 +0300, Luca Coelho wrote:

> > I think you need to make sure all stop/wake calls are balanced
> > everywhere (including device drivers). Otherwise you risk breaking
> > things silently in some cases.

> Checking this might be tricky, actually, since I think there are some
> assumptions that stopping a queue that is already stopped is a NOP, but
> now we add to the refcount...

I don't think we can force drivers to keep track of this, we'll have to
keep the API without refcounting for drivers, I'd say.

johannes


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

* Re: [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-09  9:17       ` Johannes Berg
@ 2014-06-09  9:21         ` Luca Coelho
  2014-06-09 14:52           ` Luca Coelho
  0 siblings, 1 reply; 8+ messages in thread
From: Luca Coelho @ 2014-06-09  9:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Michal Kazior, linux-wireless

On Mon, 2014-06-09 at 11:17 +0200, Johannes Berg wrote:
> On Mon, 2014-06-09 at 10:21 +0300, Luca Coelho wrote:
> 
> > > I think you need to make sure all stop/wake calls are balanced
> > > everywhere (including device drivers). Otherwise you risk breaking
> > > things silently in some cases.
> 
> > Checking this might be tricky, actually, since I think there are some
> > assumptions that stopping a queue that is already stopped is a NOP, but
> > now we add to the refcount...
> 
> I don't think we can force drivers to keep track of this, we'll have to
> keep the API without refcounting for drivers, I'd say.

Yeah, I was thinking in the same terms... Even for mac80211 might be a
bit tricky to do it.

Maybe I could keep the old APIs as is (ie. they wake the queues no
matter what the refcount is) and make the new
ieee80211_stop/wake_vif_queues() refcounted?

--
Luca.


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

* Re: [RFC option 2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-09  9:21         ` Luca Coelho
@ 2014-06-09 14:52           ` Luca Coelho
  2014-06-09 15:00             ` [RFC option 2 v2] " Luca Coelho
  0 siblings, 1 reply; 8+ messages in thread
From: Luca Coelho @ 2014-06-09 14:52 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Michal Kazior, linux-wireless

On Mon, 2014-06-09 at 12:21 +0300, Luca Coelho wrote:
> On Mon, 2014-06-09 at 11:17 +0200, Johannes Berg wrote:
> > On Mon, 2014-06-09 at 10:21 +0300, Luca Coelho wrote:
> > 
> > > > I think you need to make sure all stop/wake calls are balanced
> > > > everywhere (including device drivers). Otherwise you risk breaking
> > > > things silently in some cases.
> > 
> > > Checking this might be tricky, actually, since I think there are some
> > > assumptions that stopping a queue that is already stopped is a NOP, but
> > > now we add to the refcount...
> > 
> > I don't think we can force drivers to keep track of this, we'll have to
> > keep the API without refcounting for drivers, I'd say.
> 
> Yeah, I was thinking in the same terms... Even for mac80211 might be a
> bit tricky to do it.
> 
> Maybe I could keep the old APIs as is (ie. they wake the queues no
> matter what the refcount is) and make the new
> ieee80211_stop/wake_vif_queues() refcounted?

Actually, to make things easier, I'll make this patch include a
"refcounted" boolean in the start/stop queues functions and always call
with !refcounted for now.  Then we can gradually start using refcounted
queue stopping as needed (for instance with CSA and, possibly, with
aggregation where we already have refcounting).

New patch coming soon...

--
Luca.


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

* [RFC option 2 v2] mac80211: introduce refcount for queue_stop_reasons
  2014-06-09 14:52           ` Luca Coelho
@ 2014-06-09 15:00             ` Luca Coelho
  0 siblings, 0 replies; 8+ messages in thread
From: Luca Coelho @ 2014-06-09 15:00 UTC (permalink / raw)
  To: johannes, michal.kazior; +Cc: linux-wireless

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>
---

In v2:

   * Introduce a "refcounted" argument to the queue functions to allow
     for a slow transition to the world of refcounted
     queue-stopping [Michal/Johannes];
   * For now, we use !refcounted for all calls;

 net/mac80211/agg-tx.c      |  8 +++--
 net/mac80211/cfg.c         |  9 ++++--
 net/mac80211/debugfs.c     | 13 +++++---
 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 +++++++++++++++++++++++++++++++---------------
 11 files changed, 106 insertions(+), 51 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/debugfs.c b/net/mac80211/debugfs.c
index 0e963bc1..3ca4d78 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -332,13 +332,16 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
 	struct ieee80211_local *local = file->private_data;
 	unsigned long flags;
 	char buf[IEEE80211_MAX_QUEUES * 20];
-	int q, res = 0;
+	int q, r, res = 0;
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	for (q = 0; q < local->hw.queues; q++)
-		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
-				local->queue_stop_reasons[q],
-				skb_queue_len(&local->pending[q]));
+	for (q = 0; q < local->hw.queues; q++) {
+		for (r = 0; r < IEEE80211_QUEUE_STOP_REASONS; r++)
+			res += sprintf(buf + res,
+				       "%02d: reason[%02d] = %d/%d\n", q, r,
+				       local->q_stop_reasons[q][r],
+				       skb_queue_len(&local->pending[q]));
+	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
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] 8+ messages in thread

end of thread, other threads:[~2014-06-09 15:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-06 15:27 [RFC] mac80211: introduce refcount for queue_stop_reasons Luca Coelho
2014-06-06 18:46 ` [RFC option 2] " Luca Coelho
2014-06-09  5:34   ` Michal Kazior
2014-06-09  7:21     ` Luca Coelho
2014-06-09  9:17       ` Johannes Berg
2014-06-09  9:21         ` Luca Coelho
2014-06-09 14:52           ` Luca Coelho
2014-06-09 15:00             ` [RFC option 2 v2] " Luca Coelho

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.