summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2012-02-25 21:36:36 +0100
committerJohn W. Linville <linville@tuxdriver.com>2012-02-29 13:08:51 -0500
commit9926a67557532acb6cddb1c1add02952175b5c72 (patch)
tree35330f84ef1fd0a3bed21ee8c27b951bc9779b9a
parent992d52529d7840236d3059b51c15d5eb9e81a869 (diff)
downloadlinux-9926a67557532acb6cddb1c1add02952175b5c72.tar.gz
linux-9926a67557532acb6cddb1c1add02952175b5c72.tar.bz2
linux-9926a67557532acb6cddb1c1add02952175b5c72.zip
carl9170: fix frame delivery if sta is in powersave mode
Nicolas Cavallari discovered that carl9170 has some serious problems delivering data to sleeping stations. It turns out that the driver was not honoring two important flags (IEEE80211_TX_CTL_POLL_RESPONSE and IEEE80211_TX_CTL_CLEAR_PS_FILT) which are set on frames that should be sent although the receiving station is still in powersave mode. Cc: stable <stable@vger.kernel.org> Reported-by: Nicolas Cavallari <Nicolas.Cavallari@lri.fr> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 22a793121bd3..bbc813dee983 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -1234,6 +1234,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_sta *sta;
struct carl9170_sta_info *sta_info;
+ struct ieee80211_tx_info *tx_info;
rcu_read_lock();
sta = __carl9170_get_tx_sta(ar, skb);
@@ -1241,12 +1242,13 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
goto out_rcu;
sta_info = (void *) sta->drv_priv;
- if (unlikely(sta_info->sleeping)) {
- struct ieee80211_tx_info *tx_info;
+ tx_info = IEEE80211_SKB_CB(skb);
+ if (unlikely(sta_info->sleeping) &&
+ !(tx_info->flags & (IEEE80211_TX_CTL_POLL_RESPONSE |
+ IEEE80211_TX_CTL_CLEAR_PS_FILT))) {
rcu_read_unlock();
- tx_info = IEEE80211_SKB_CB(skb);
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
atomic_dec(&ar->tx_ampdu_upload);