* [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-13 13:00 ` Luca Coelho
@ 2017-03-13 13:14 ` Luca Coelho
2017-03-13 14:24 ` Jens Axboe
2017-03-13 14:23 ` WARNING: CPU: 1 PID: 23668 at drivers/net/wireless/intel/iwlwifi/mvm/sta.c:1539 iwl_mvm_rm_sta+0x3ce/0x450 Jens Axboe
2017-03-14 7:50 ` [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
2 siblings, 1 reply; 17+ messages in thread
From: Luca Coelho @ 2017-03-13 13:14 UTC (permalink / raw)
To: axboe, linux-wireless
Cc: torvalds, johannes.berg, emmanuel.grumbach, linuxwifi,
sara.sharon, liad.kaufman, luciano.coelho
From: Sara Sharon <sara.sharon@intel.com>
When a station is asleep, the fw will set it as "asleep".
All queues that are used only by one station will be stopped by
the fw.
In pre-DQA mode this was relevant for aggregation queues. However,
in DQA mode a queue is owned by one station only, so all queues
will be stopped.
As a result, we don't expect to get filtered frames back to
mac80211 and don't have to maintain the entire pending_frames
state logic, the same way as we do in aggregations.
The correct behavior is to align DQA behavior with the aggregation
queue behaviour pre-DQA:
- Don't count pending frames.
- Let mac80211 know we have frames in these queues so that it can
properly handle trigger frames.
When a trigger frame is received, mac80211 tells the driver to send
frames from the queues using release_buffered_frames.
The driver will tell the fw to let frames out even if the station
is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +--
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 11 +++---
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 41 ++++++++++-------------
4 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d37b1695c64e..6927caecd48e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2319,7 +2319,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- /* Called when we need to transmit (a) frame(s) from agg queue */
+ /* Called when we need to transmit (a) frame(s) from agg or dqa queue */
iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
tids, more_data, true);
@@ -2338,7 +2338,8 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
- if (tid_data->state != IWL_AGG_ON &&
+ if (!iwl_mvm_is_dqa_supported(mvm) &&
+ tid_data->state != IWL_AGG_ON &&
tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
continue;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index bd1dcc863d8f..b51a2853cc80 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -3135,7 +3135,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum ieee80211_frame_release_type reason,
u16 cnt, u16 tids, bool more_data,
- bool agg)
+ bool single_sta_queue)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {
@@ -3155,14 +3155,14 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
- /* If we're releasing frames from aggregation queues then check if the
- * all queues combined that we're releasing frames from have
+ /* If we're releasing frames from aggregation or dqa queues then check
+ * if all the queues that we're releasing frames from, combined, have:
* - more frames than the service period, in which case more_data
* needs to be set
* - fewer than 'cnt' frames, in which case we need to adjust the
* firmware command (but do that unconditionally)
*/
- if (agg) {
+ if (single_sta_queue) {
int remaining = cnt;
int sleep_tx_count;
@@ -3172,7 +3172,8 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
u16 n_queued;
tid_data = &mvmsta->tid_data[tid];
- if (WARN(tid_data->state != IWL_AGG_ON &&
+ if (WARN(!iwl_mvm_is_dqa_supported(mvm) &&
+ tid_data->state != IWL_AGG_ON &&
tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
"TID %d state is %d\n",
tid, tid_data->state)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 4be34f902278..1927ce607798 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -547,7 +547,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum ieee80211_frame_release_type reason,
u16 cnt, u16 tids, bool more_data,
- bool agg);
+ bool single_sta_queue);
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool drain);
void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index dd2b4a300819..3f37075f4cde 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -628,8 +629,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* values.
* Note that we don't need to make sure it isn't agg'd, since we're
* TXing non-sta
+ * For DQA mode - we shouldn't increase it though
*/
- atomic_inc(&mvm->pending_frames[sta_id]);
+ if (!iwl_mvm_is_dqa_supported(mvm))
+ atomic_inc(&mvm->pending_frames[sta_id]);
return 0;
}
@@ -1005,11 +1008,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
spin_unlock(&mvmsta->lock);
- /* Increase pending frames count if this isn't AMPDU */
- if ((iwl_mvm_is_dqa_supported(mvm) &&
- mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON &&
- mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) ||
- (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu))
+ /* Increase pending frames count if this isn't AMPDU or DQA queue */
+ if (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu)
atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
return 0;
@@ -1079,12 +1079,13 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
lockdep_assert_held(&mvmsta->lock);
if ((tid_data->state == IWL_AGG_ON ||
- tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
+ tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA ||
+ iwl_mvm_is_dqa_supported(mvm)) &&
iwl_mvm_tid_queued(tid_data) == 0) {
/*
- * Now that this aggregation queue is empty tell mac80211 so it
- * knows we no longer have frames buffered for the station on
- * this TID (for the TIM bitmap calculation.)
+ * Now that this aggregation or DQA queue is empty tell
+ * mac80211 so it knows we no longer have frames buffered for
+ * the station on this TID (for the TIM bitmap calculation.)
*/
ieee80211_sta_set_buffered(sta, tid, false);
}
@@ -1257,7 +1258,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
u8 skb_freed = 0;
u16 next_reclaimed, seq_ctl;
bool is_ndp = false;
- bool txq_agg = false; /* Is this TXQ aggregated */
__skb_queue_head_init(&skbs);
@@ -1283,6 +1283,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info->flags |= IEEE80211_TX_STAT_ACK;
break;
case TX_STATUS_FAIL_DEST_PS:
+ /* In DQA, the FW should have stopped the queue and not
+ * return this status
+ */
+ WARN_ON(iwl_mvm_is_dqa_supported(mvm));
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
break;
default:
@@ -1387,15 +1391,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
bool send_eosp_ndp = false;
spin_lock_bh(&mvmsta->lock);
- if (iwl_mvm_is_dqa_supported(mvm)) {
- enum iwl_mvm_agg_state state;
-
- state = mvmsta->tid_data[tid].state;
- txq_agg = (state == IWL_AGG_ON ||
- state == IWL_EMPTYING_HW_QUEUE_DELBA);
- } else {
- txq_agg = txq_id >= mvm->first_agg_queue;
- }
if (!is_ndp) {
tid_data->next_reclaimed = next_reclaimed;
@@ -1452,11 +1447,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
* If the txq is not an AMPDU queue, there is no chance we freed
* several skbs. Check that out...
*/
- if (txq_agg)
+ if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue)
goto out;
/* We can't free more than one frame at once on a shared queue */
- WARN_ON(!iwl_mvm_is_dqa_supported(mvm) && (skb_freed > 1));
+ WARN_ON(skb_freed > 1);
/* If we have still frames for this STA nothing to do here */
if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
--
2.11.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-13 13:14 ` [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
@ 2017-03-13 14:24 ` Jens Axboe
2017-03-13 15:08 ` Luca Coelho
0 siblings, 1 reply; 17+ messages in thread
From: Jens Axboe @ 2017-03-13 14:24 UTC (permalink / raw)
To: Luca Coelho, linux-wireless
Cc: torvalds, johannes.berg, emmanuel.grumbach, linuxwifi,
sara.sharon, liad.kaufman, luciano.coelho
On 03/13/2017 07:14 AM, Luca Coelho wrote:
> From: Sara Sharon <sara.sharon@intel.com>
>
> When a station is asleep, the fw will set it as "asleep".
> All queues that are used only by one station will be stopped by
> the fw.
>
> In pre-DQA mode this was relevant for aggregation queues. However,
> in DQA mode a queue is owned by one station only, so all queues
> will be stopped.
> As a result, we don't expect to get filtered frames back to
> mac80211 and don't have to maintain the entire pending_frames
> state logic, the same way as we do in aggregations.
>
> The correct behavior is to align DQA behavior with the aggregation
> queue behaviour pre-DQA:
> - Don't count pending frames.
> - Let mac80211 know we have frames in these queues so that it can
> properly handle trigger frames.
>
> When a trigger frame is received, mac80211 tells the driver to send
> frames from the queues using release_buffered_frames.
> The driver will tell the fw to let frames out even if the station
> is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
It fixes the warning for me.
Tested-by: Jens Axboe <axboe@fb.com>
--
Jens Axboe
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-13 14:24 ` Jens Axboe
@ 2017-03-13 15:08 ` Luca Coelho
0 siblings, 0 replies; 17+ messages in thread
From: Luca Coelho @ 2017-03-13 15:08 UTC (permalink / raw)
To: Jens Axboe, linux-wireless
Cc: torvalds, johannes.berg, emmanuel.grumbach, linuxwifi,
sara.sharon, liad.kaufman
On Mon, 2017-03-13 at 08:24 -0600, Jens Axboe wrote:
> On 03/13/2017 07:14 AM, Luca Coelho wrote:
> > From: Sara Sharon <sara.sharon@intel.com>
> >
> > When a station is asleep, the fw will set it as "asleep".
> > All queues that are used only by one station will be stopped by
> > the fw.
> >
> > In pre-DQA mode this was relevant for aggregation queues. However,
> > in DQA mode a queue is owned by one station only, so all queues
> > will be stopped.
> > As a result, we don't expect to get filtered frames back to
> > mac80211 and don't have to maintain the entire pending_frames
> > state logic, the same way as we do in aggregations.
> >
> > The correct behavior is to align DQA behavior with the aggregation
> > queue behaviour pre-DQA:
> > - Don't count pending frames.
> > - Let mac80211 know we have frames in these queues so that it can
> > properly handle trigger frames.
> >
> > When a trigger frame is received, mac80211 tells the driver to send
> > frames from the queues using release_buffered_frames.
> > The driver will tell the fw to let frames out even if the station
> > is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
>
> It fixes the warning for me.
>
> Tested-by: Jens Axboe <axboe@fb.com>
Great! Thanks for testing.
I'll queue this for the 4.11-rc series via the normal path (i.e.
wireless-driver->netdev).
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: WARNING: CPU: 1 PID: 23668 at drivers/net/wireless/intel/iwlwifi/mvm/sta.c:1539 iwl_mvm_rm_sta+0x3ce/0x450
2017-03-13 13:00 ` Luca Coelho
2017-03-13 13:14 ` [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
@ 2017-03-13 14:23 ` Jens Axboe
2017-03-14 7:50 ` [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
2 siblings, 0 replies; 17+ messages in thread
From: Jens Axboe @ 2017-03-13 14:23 UTC (permalink / raw)
To: Luca Coelho; +Cc: sara.sharon, liad.kaufman, linux-wireless
On 03/13/2017 07:00 AM, Luca Coelho wrote:
> On Fri, 2017-03-10 at 08:41 -0700, Jens Axboe wrote:
>> On 03/10/2017 08:36 AM, Luca Coelho wrote:
>>> On Fri, 2017-03-10 at 08:23 -0700, Jens Axboe wrote:
>>>> On 03/10/2017 05:01 AM, Luca Coelho wrote:
>>>>> Hi Jens,
>>>>>
>>>>> On Thu, 2017-03-09 at 21:41 -0700, Jens Axboe wrote:
>>>>>> On 03/01/2017 09:10 PM, Jens Axboe wrote:
>>>>>>> On 03/01/2017 08:33 PM, Luca Coelho wrote:
>>>>>>>> Hi Jens,
>>>>>>>>
>>>>>>>> On Mar 1, 2017 20:25, Jens Axboe <axboe@kernel.dk> wrote:
>>>>>>>>
>>>>>>>> Not that folks have been jumping all over this, but in case someone is
>>>>>>>> curious, it triggered twice here today. For those two times, the value
>>>>>>>> of mvm->pending_frames[sta_id] was 80 and 39, respectively.
>>>>>>>>
>>>>>>>> Sorry for the delay, I'm on vacation now with limited internet access.
>>>>>>>> But we'll take a look into this early next week at the latest.
>>>>>>>>
>>>>>>>> Thanks a lot for the detailed report!
>>>>>>>
>>>>>>> No worries, thanks for responding. I just wanted to ensure this wasn't
>>>>>>> dropped on the floor.
>>>>>>>
>>>>>>> BTW, a few more values of ->pending_frames[sta_id]:
>>>>>>>
>>>>>>> $ dmesg | grep "ret="
>>>>>>> [ 2334.308254] ret=39
>>>>>>> [ 7915.311828] ret=80
>>>>>>> [31602.317204] ret=41
>>>>>>> [32139.510993] ret=54
>>>>>>> [33292.917759] ret=96
>>>>>>>
>>>>>>> it seems to often happen around resume.
>>>>>>
>>>>>> This is still happening all the time in current -git.
>>>>>
>>>>> Could you collect traces with trace-cmd, as explained in our wiki[1]?
>>>>> This will probably help point out the problem. I know it's a bit
>>>>> difficult because it appears to happen randomly for you, but it's worth
>>>>> trying.
>>>>
>>>> Sure I can, but honestly I'm a little puzzled that nobody else can
>>>> reproduce this, it happens every time I resume of switch access points.
>>>> Is anyone trying to reproduce this?
>>>>
>>>> I'll have to recompile with iwlwifi tracing enabled, then I'll send a trace
>>>> when it happens.
>>>
>>> Are you using 4.11-rc1? Or linus' master? Or...?
>>
>> The trace I just sent is tip of Linus' tree. It's happened continually
>> since the commit I mentioned in my initial report was merged:
>>
>> commit 94c3e614df2117626fccfac8f821c66e30556384
>> Author: Sara Sharon <sara.sharon@intel.com>
>> Date: Wed Dec 7 15:04:37 2016 +0200
>>
>> iwlwifi: mvm: fix pending frame counter calculation
>
> I found the patch that fixes this issue in our internal tree. I'll send
> it out for you to try now.
>
> The reason is that in DQA (Dynamic Queue Allocation) mode that we
> introduced recently, we should not be counting the frames in the same
> way as before. The warning was introduced exactly to catch this kind of
> problems.
>
> Please let me know if it works for you!
Seems to work for me, thanks! You can add my
Tested-by: Jens Axboe <axboe@fb.com>
to the patch.
--
Jens Axboe
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-13 13:00 ` Luca Coelho
2017-03-13 13:14 ` [PATCH] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
2017-03-13 14:23 ` WARNING: CPU: 1 PID: 23668 at drivers/net/wireless/intel/iwlwifi/mvm/sta.c:1539 iwl_mvm_rm_sta+0x3ce/0x450 Jens Axboe
@ 2017-03-14 7:50 ` Luca Coelho
2017-03-15 9:52 ` Kalle Valo
2017-03-16 7:54 ` [RESEND,4.11] " Kalle Valo
2 siblings, 2 replies; 17+ messages in thread
From: Luca Coelho @ 2017-03-14 7:50 UTC (permalink / raw)
To: axboe, linux-wireless
Cc: torvalds, johannes.berg, emmanuel.grumbach, linuxwifi,
sara.sharon, liad.kaufman, luciano.coelho
From: Sara Sharon <sara.sharon@intel.com>
When a station is asleep, the fw will set it as "asleep".
All queues that are used only by one station will be stopped by
the fw.
In pre-DQA mode this was relevant for aggregation queues. However,
in DQA mode a queue is owned by one station only, so all queues
will be stopped.
As a result, we don't expect to get filtered frames back to
mac80211 and don't have to maintain the entire pending_frames
state logic, the same way as we do in aggregations.
The correct behavior is to align DQA behavior with the aggregation
queue behaviour pre-DQA:
- Don't count pending frames.
- Let mac80211 know we have frames in these queues so that it can
properly handle trigger frames.
When a trigger frame is received, mac80211 tells the driver to send
frames from the queues using release_buffered_frames.
The driver will tell the fw to let frames out even if the station
is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
Reported-and-tested-by: Jens Axboe <axboe@kernel.dk>
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
Just resending with reported and tested by tags.
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +--
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 11 +++---
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 41 ++++++++++-------------
4 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d37b1695c64e..6927caecd48e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2319,7 +2319,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- /* Called when we need to transmit (a) frame(s) from agg queue */
+ /* Called when we need to transmit (a) frame(s) from agg or dqa queue */
iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
tids, more_data, true);
@@ -2338,7 +2338,8 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
- if (tid_data->state != IWL_AGG_ON &&
+ if (!iwl_mvm_is_dqa_supported(mvm) &&
+ tid_data->state != IWL_AGG_ON &&
tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
continue;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index bd1dcc863d8f..b51a2853cc80 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -3135,7 +3135,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum ieee80211_frame_release_type reason,
u16 cnt, u16 tids, bool more_data,
- bool agg)
+ bool single_sta_queue)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {
@@ -3155,14 +3155,14 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
- /* If we're releasing frames from aggregation queues then check if the
- * all queues combined that we're releasing frames from have
+ /* If we're releasing frames from aggregation or dqa queues then check
+ * if all the queues that we're releasing frames from, combined, have:
* - more frames than the service period, in which case more_data
* needs to be set
* - fewer than 'cnt' frames, in which case we need to adjust the
* firmware command (but do that unconditionally)
*/
- if (agg) {
+ if (single_sta_queue) {
int remaining = cnt;
int sleep_tx_count;
@@ -3172,7 +3172,8 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
u16 n_queued;
tid_data = &mvmsta->tid_data[tid];
- if (WARN(tid_data->state != IWL_AGG_ON &&
+ if (WARN(!iwl_mvm_is_dqa_supported(mvm) &&
+ tid_data->state != IWL_AGG_ON &&
tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
"TID %d state is %d\n",
tid, tid_data->state)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 4be34f902278..1927ce607798 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -547,7 +547,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum ieee80211_frame_release_type reason,
u16 cnt, u16 tids, bool more_data,
- bool agg);
+ bool single_sta_queue);
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool drain);
void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index dd2b4a300819..3f37075f4cde 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -628,8 +629,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* values.
* Note that we don't need to make sure it isn't agg'd, since we're
* TXing non-sta
+ * For DQA mode - we shouldn't increase it though
*/
- atomic_inc(&mvm->pending_frames[sta_id]);
+ if (!iwl_mvm_is_dqa_supported(mvm))
+ atomic_inc(&mvm->pending_frames[sta_id]);
return 0;
}
@@ -1005,11 +1008,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
spin_unlock(&mvmsta->lock);
- /* Increase pending frames count if this isn't AMPDU */
- if ((iwl_mvm_is_dqa_supported(mvm) &&
- mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON &&
- mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) ||
- (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu))
+ /* Increase pending frames count if this isn't AMPDU or DQA queue */
+ if (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu)
atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
return 0;
@@ -1079,12 +1079,13 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
lockdep_assert_held(&mvmsta->lock);
if ((tid_data->state == IWL_AGG_ON ||
- tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
+ tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA ||
+ iwl_mvm_is_dqa_supported(mvm)) &&
iwl_mvm_tid_queued(tid_data) == 0) {
/*
- * Now that this aggregation queue is empty tell mac80211 so it
- * knows we no longer have frames buffered for the station on
- * this TID (for the TIM bitmap calculation.)
+ * Now that this aggregation or DQA queue is empty tell
+ * mac80211 so it knows we no longer have frames buffered for
+ * the station on this TID (for the TIM bitmap calculation.)
*/
ieee80211_sta_set_buffered(sta, tid, false);
}
@@ -1257,7 +1258,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
u8 skb_freed = 0;
u16 next_reclaimed, seq_ctl;
bool is_ndp = false;
- bool txq_agg = false; /* Is this TXQ aggregated */
__skb_queue_head_init(&skbs);
@@ -1283,6 +1283,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info->flags |= IEEE80211_TX_STAT_ACK;
break;
case TX_STATUS_FAIL_DEST_PS:
+ /* In DQA, the FW should have stopped the queue and not
+ * return this status
+ */
+ WARN_ON(iwl_mvm_is_dqa_supported(mvm));
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
break;
default:
@@ -1387,15 +1391,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
bool send_eosp_ndp = false;
spin_lock_bh(&mvmsta->lock);
- if (iwl_mvm_is_dqa_supported(mvm)) {
- enum iwl_mvm_agg_state state;
-
- state = mvmsta->tid_data[tid].state;
- txq_agg = (state == IWL_AGG_ON ||
- state == IWL_EMPTYING_HW_QUEUE_DELBA);
- } else {
- txq_agg = txq_id >= mvm->first_agg_queue;
- }
if (!is_ndp) {
tid_data->next_reclaimed = next_reclaimed;
@@ -1452,11 +1447,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
* If the txq is not an AMPDU queue, there is no chance we freed
* several skbs. Check that out...
*/
- if (txq_agg)
+ if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue)
goto out;
/* We can't free more than one frame at once on a shared queue */
- WARN_ON(!iwl_mvm_is_dqa_supported(mvm) && (skb_freed > 1));
+ WARN_ON(skb_freed > 1);
/* If we have still frames for this STA nothing to do here */
if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
--
2.11.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-14 7:50 ` [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
@ 2017-03-15 9:52 ` Kalle Valo
2017-03-15 9:54 ` Coelho, Luciano
2017-03-16 7:54 ` [RESEND,4.11] " Kalle Valo
1 sibling, 1 reply; 17+ messages in thread
From: Kalle Valo @ 2017-03-15 9:52 UTC (permalink / raw)
To: Luca Coelho
Cc: axboe, linux-wireless, torvalds, johannes.berg,
emmanuel.grumbach, linuxwifi, sara.sharon, liad.kaufman,
luciano.coelho
Luca Coelho <luca@coelho.fi> writes:
> From: Sara Sharon <sara.sharon@intel.com>
>
> When a station is asleep, the fw will set it as "asleep".
> All queues that are used only by one station will be stopped by
> the fw.
>
> In pre-DQA mode this was relevant for aggregation queues. However,
> in DQA mode a queue is owned by one station only, so all queues
> will be stopped.
> As a result, we don't expect to get filtered frames back to
> mac80211 and don't have to maintain the entire pending_frames
> state logic, the same way as we do in aggregations.
>
> The correct behavior is to align DQA behavior with the aggregation
> queue behaviour pre-DQA:
> - Don't count pending frames.
> - Let mac80211 know we have frames in these queues so that it can
> properly handle trigger frames.
>
> When a trigger frame is received, mac80211 tells the driver to send
> frames from the queues using release_buffered_frames.
> The driver will tell the fw to let frames out even if the station
> is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
>
> Reported-and-tested-by: Jens Axboe <axboe@kernel.dk>
> Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Sara Sharon <sara.sharon@intel.com>
> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
> ---
>
> Just resending with reported and tested by tags.
Sorry, my usual rant follows :) But never ever use "RESEND", it's so
much simpler to have v2, v3 and so on to figure out what's the (latest)
version I should take.
--
Kalle Valo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-15 9:52 ` Kalle Valo
@ 2017-03-15 9:54 ` Coelho, Luciano
0 siblings, 0 replies; 17+ messages in thread
From: Coelho, Luciano @ 2017-03-15 9:54 UTC (permalink / raw)
To: kvalo
Cc: Kaufman, Liad, linuxwifi, torvalds, axboe, Berg, Johannes,
Sharon, Sara, linux-wireless, Grumbach, Emmanuel
T24gV2VkLCAyMDE3LTAzLTE1IGF0IDExOjUyICswMjAwLCBLYWxsZSBWYWxvIHdyb3RlOg0KPiBM
dWNhIENvZWxobyA8bHVjYUBjb2VsaG8uZmk+IHdyaXRlczoNCj4gDQo+ID4gRnJvbTogU2FyYSBT
aGFyb24gPHNhcmEuc2hhcm9uQGludGVsLmNvbT4NCj4gPiANCj4gPiBXaGVuIGEgc3RhdGlvbiBp
cyBhc2xlZXAsIHRoZSBmdyB3aWxsIHNldCBpdCBhcyAiYXNsZWVwIi4NCj4gPiBBbGwgcXVldWVz
IHRoYXQgYXJlIHVzZWQgb25seSBieSBvbmUgc3RhdGlvbiB3aWxsIGJlIHN0b3BwZWQgYnkNCj4g
PiB0aGUgZncuDQo+ID4gDQo+ID4gSW4gcHJlLURRQSBtb2RlIHRoaXMgd2FzIHJlbGV2YW50IGZv
ciBhZ2dyZWdhdGlvbiBxdWV1ZXMuIEhvd2V2ZXIsDQo+ID4gaW4gRFFBIG1vZGUgYSBxdWV1ZSBp
cyBvd25lZCBieSBvbmUgc3RhdGlvbiBvbmx5LCBzbyBhbGwgcXVldWVzDQo+ID4gd2lsbCBiZSBz
dG9wcGVkLg0KPiA+IEFzIGEgcmVzdWx0LCB3ZSBkb24ndCBleHBlY3QgdG8gZ2V0IGZpbHRlcmVk
IGZyYW1lcyBiYWNrIHRvDQo+ID4gbWFjODAyMTEgYW5kIGRvbid0IGhhdmUgdG8gbWFpbnRhaW4g
dGhlIGVudGlyZSBwZW5kaW5nX2ZyYW1lcw0KPiA+IHN0YXRlIGxvZ2ljLCB0aGUgc2FtZSB3YXkg
YXMgd2UgZG8gaW4gYWdncmVnYXRpb25zLg0KPiA+IA0KPiA+IFRoZSBjb3JyZWN0IGJlaGF2aW9y
IGlzIHRvIGFsaWduIERRQSBiZWhhdmlvciB3aXRoIHRoZSBhZ2dyZWdhdGlvbg0KPiA+IHF1ZXVl
IGJlaGF2aW91ciBwcmUtRFFBOg0KPiA+IC0gRG9uJ3QgY291bnQgcGVuZGluZyBmcmFtZXMuDQo+
ID4gLSBMZXQgbWFjODAyMTEga25vdyB3ZSBoYXZlIGZyYW1lcyBpbiB0aGVzZSBxdWV1ZXMgc28g
dGhhdCBpdCBjYW4NCj4gPiBwcm9wZXJseSBoYW5kbGUgdHJpZ2dlciBmcmFtZXMuDQo+ID4gDQo+
ID4gV2hlbiBhIHRyaWdnZXIgZnJhbWUgaXMgcmVjZWl2ZWQsIG1hYzgwMjExIHRlbGxzIHRoZSBk
cml2ZXIgdG8gc2VuZA0KPiA+IGZyYW1lcyBmcm9tIHRoZSBxdWV1ZXMgdXNpbmcgcmVsZWFzZV9i
dWZmZXJlZF9mcmFtZXMuDQo+ID4gVGhlIGRyaXZlciB3aWxsIHRlbGwgdGhlIGZ3IHRvIGxldCBm
cmFtZXMgb3V0IGV2ZW4gaWYgdGhlIHN0YXRpb24NCj4gPiBpcyBhc2xlZXAuIFRoaXMgaXMgZG9u
ZSBieSBpd2xfbXZtX3N0YV9tb2RpZnlfc2xlZXBfdHhfY291bnQuDQo+ID4gDQo+ID4gUmVwb3J0
ZWQtYW5kLXRlc3RlZC1ieTogSmVucyBBeGJvZSA8YXhib2VAa2VybmVsLmRrPg0KPiA+IFJlcG9y
dGVkLWJ5OiBMaW51cyBUb3J2YWxkcyA8dG9ydmFsZHNAbGludXgtZm91bmRhdGlvbi5vcmc+DQo+
ID4gU2lnbmVkLW9mZi1ieTogU2FyYSBTaGFyb24gPHNhcmEuc2hhcm9uQGludGVsLmNvbT4NCj4g
PiBTaWduZWQtb2ZmLWJ5OiBMdWNhIENvZWxobyA8bHVjaWFuby5jb2VsaG9AaW50ZWwuY29tPg0K
PiA+IC0tLQ0KPiA+IA0KPiA+IEp1c3QgcmVzZW5kaW5nIHdpdGggcmVwb3J0ZWQgYW5kIHRlc3Rl
ZCBieSB0YWdzLg0KPiANCj4gU29ycnksIG15IHVzdWFsIHJhbnQgZm9sbG93cyA6KSBCdXQgbmV2
ZXIgZXZlciB1c2UgIlJFU0VORCIsIGl0J3Mgc28NCj4gbXVjaCBzaW1wbGVyIHRvIGhhdmUgdjIs
IHYzIGFuZCBzbyBvbiB0byBmaWd1cmUgb3V0IHdoYXQncyB0aGUgKGxhdGVzdCkNCj4gdmVyc2lv
biBJIHNob3VsZCB0YWtlLg0KDQpPa2F5LCBzb3JyeS4gIEkganVzdCB1c2VkIFJFU0VORCwgYmVj
YXVzZSBJIGRpZG4ndCBjaGFuZ2UgdGhlIHBhdGNoDQppdHNlbGYsIGJ1dCBvbmx5IGFkZGVkIHRo
ZSByZXBvcnRlZC1ieSB0YWdzLi4uDQoNCi0tDQpMdWNhLg==
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RESEND,4.11] iwlwifi: mvm: cleanup pending frames in DQA mode
2017-03-14 7:50 ` [RESEND PATCH 4.11] iwlwifi: mvm: cleanup pending frames in DQA mode Luca Coelho
2017-03-15 9:52 ` Kalle Valo
@ 2017-03-16 7:54 ` Kalle Valo
1 sibling, 0 replies; 17+ messages in thread
From: Kalle Valo @ 2017-03-16 7:54 UTC (permalink / raw)
To: Luciano Coelho
Cc: axboe, linux-wireless, torvalds, johannes.berg,
emmanuel.grumbach, linuxwifi, sara.sharon, liad.kaufman,
luciano.coelho
Luciano Coelho <luca@coelho.fi> wrote:
> From: Sara Sharon <sara.sharon@intel.com>
>
> When a station is asleep, the fw will set it as "asleep".
> All queues that are used only by one station will be stopped by
> the fw.
>
> In pre-DQA mode this was relevant for aggregation queues. However,
> in DQA mode a queue is owned by one station only, so all queues
> will be stopped.
> As a result, we don't expect to get filtered frames back to
> mac80211 and don't have to maintain the entire pending_frames
> state logic, the same way as we do in aggregations.
>
> The correct behavior is to align DQA behavior with the aggregation
> queue behaviour pre-DQA:
> - Don't count pending frames.
> - Let mac80211 know we have frames in these queues so that it can
> properly handle trigger frames.
>
> When a trigger frame is received, mac80211 tells the driver to send
> frames from the queues using release_buffered_frames.
> The driver will tell the fw to let frames out even if the station
> is asleep. This is done by iwl_mvm_sta_modify_sleep_tx_count.
>
> Reported-and-tested-by: Jens Axboe <axboe@kernel.dk>
> Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Sara Sharon <sara.sharon@intel.com>
> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Patch applied to wireless-drivers.git, thanks.
9a3fcf912ef7 iwlwifi: mvm: cleanup pending frames in DQA mode
--
https://patchwork.kernel.org/patch/9622617/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply [flat|nested] 17+ messages in thread