Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aecdc63d authored by Emmanuel Grumbach's avatar Emmanuel Grumbach
Browse files

iwlwifi: pcie: fix stuck queue detection for sleeping clients



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: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent dc9f69b9
Loading
Loading
Loading
Loading
+13 −2
Original line number Original line Diff line number Diff line
@@ -1875,8 +1875,19 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,


	/* start timer if queue currently empty */
	/* start timer if queue currently empty */
	if (q->read_ptr == q->write_ptr) {
	if (q->read_ptr == q->write_ptr) {
		if (txq->wd_timeout)
		if (txq->wd_timeout) {
			mod_timer(&txq->stuck_timer, jiffies + 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_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id);
		iwl_trans_pcie_ref(trans);
		iwl_trans_pcie_ref(trans);
	}
	}