Skip to content

Commit

Permalink
iwlwifi: pcie: fix stuck queue detection for sleeping clients
Browse files Browse the repository at this point in the history
The stuck queue detection mechanism allows to detect queues
that are stuck. For sleeping clients, a queue may rightfully
be stuck: if a poor client implementation stays asleep for
more than 10s, then we don't want to trigger recovery flows
because of that client.
In order to cope with this, I added a mechanism that
monitors the state of the client: when a client goes to
sleep, the timer of his queues is frozen. When he wakes up,
the timer is reset to the right value so that if a client
was awake for more than 10s and the queues are stuck, only
then, the recovery flow will kick in.
This is valid only on non-shared queues: A-MPDU queues.

There was a bug in case we Tx to a sleeping client that has
an empty A-MPDU queue: the timer was armed to now + 10s.
This is bad, but pretty harmless.
The problem is that when the client wakes up, the timer is
modified to be now + remainder. But remainder is 0 since the
queue was empty when that client went to sleep...

Fix this by checking the state of the client before playing
with the timer when we add a packet to an empty queue.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
  • Loading branch information
Emmanuel Grumbach committed Jul 30, 2015
1 parent dc9f69b commit aecdc63
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions drivers/net/wireless/iwlwifi/pcie/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1875,8 +1875,19 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,

/* start timer if queue currently empty */
if (q->read_ptr == q->write_ptr) {
if (txq->wd_timeout)
mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
if (txq->wd_timeout) {
/*
* If the TXQ is active, then set the timer, if not,
* set the timer in remainder so that the timer will
* be armed with the right value when the station will
* wake up.
*/
if (!txq->frozen)
mod_timer(&txq->stuck_timer,
jiffies + txq->wd_timeout);
else
txq->frozen_expiry_remainder = txq->wd_timeout;
}
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id);
iwl_trans_pcie_ref(trans);
}
Expand Down

0 comments on commit aecdc63

Please sign in to comment.