2012-11-13 19:55:43

by Marco Porsch

[permalink] [raw]
Subject: issue with ath9k_htc and mesh mode powersave

Hi,

my name is Marco Porsch, I am currently implementing mesh mode powersave
as part of mac80211 and some wireless drivers.

When testing with a ath9k_htc TL-WN721N and monitoring the power
consumption on the USB cable, I see the following behaviour:

during normal mesh operation in powersave mode the power consumption
rises to 120mA (~55mA is the usual current in PS mode without activity)
and stays stuck at that level until ifdown. Mesh leave + join does not
reset it to normal behaviour. Sometimes it only takes few seconds until
the power consumption gets stuck; sometimes it works fine for multiple
minutes.

I have no idea what is the reason for that behaviour.
No obvious debug output is given despite all ath9k debugs enabled. I can
only suspect the hardware expects some managed-mode only event from the
access point that we do not have there in mesh mode.
When looking at the NDA firmware I did not see anything related to power
save mode that could help.

Do you have any idea what could be the reason for that behaviour? Or any
hints for debugging the issue?


Regards,
Marco



PS:

For testing I use a simplistic "mesh awake window" implementation that
queues waking up from sleep mode after beacon preparation and sets a
timer for going to sleep again after the awake window is expired. I
added a bool in_awake_window that blocks going to NETWORKSLEEP when set.
The code looks like:

@@ -473,6 +495,14 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv,
ath9k_htc_send_buffered(priv, slot);
ath9k_htc_send_beacon(priv, slot);

+ /* mesh awake window */
+ if (priv->ah->opmode == NL80211_IFTYPE_MESH_POINT && priv->ps_enabled) {
+ priv->in_awake_window = true;
+ ieee80211_queue_work(priv->hw, &priv->ps_work);
+ mod_timer(&priv->awake_window_timer, jiffies +
+ usecs_to_jiffies(1024 * priv->awake_window) +
+ priv->ah->config.sw_beacon_response_time);
+ }
}

When the timer expires it calls:

@@ -276,6 +284,14 @@ void ath9k_ps_work(struct work_struct *work)
ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
}

+void ath9k_htc_mesh_awake_window_timer(unsigned long data)
+{
+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data;
+
+ priv->in_awake_window = false;
+ ieee80211_queue_work(priv->hw, &priv->ps_work);
+}
+


PPS:

Some further hacking revealed that reading AR_RTC_STATUS before and
after REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN) shows the
following

normal behaviour:

[ 301.655141] ath: phy0: AR_RTC_STATUS before: 02
[ 301.661079] ath: phy0: AR_RTC_STATUS after : 04

when being stuck it changes to:

[ 302.677066] ath: phy0: AR_RTC_STATUS before: 02
[ 302.683085] ath: phy0: AR_RTC_STATUS after : 02