From: Jouni Malinen <[EMAIL PROTECTED]>

Start using 2 * listen_int * beacon_int as a timeout for PS buffered
unicast frames if that is longer than 10 seconds. Previously, we used
fixed 10 second limit regardless of the listen interval.

This fixes power saving for STAs that request very long listen
interval (over 10 seconds).

This was reported by UNH IOL 802.11 AP Base MAC Test Suite v2.4
Test #1.3.2 Part e.

While we are at it, remove the station from the TIM when the PS buffer is
empty.

Signed-off-by: Jouni Malinen <[EMAIL PROTECTED]>

Index: wireless-dev/net/d80211/hostapd_ioctl.h
===================================================================
--- wireless-dev.orig/net/d80211/hostapd_ioctl.h
+++ wireless-dev/net/d80211/hostapd_ioctl.h
@@ -189,6 +189,7 @@ struct prism2_hostapd_param {
                        u8 wds_flags;
 #define IEEE80211_STA_DYNAMIC_ENC BIT(0)
                        u8 enc_flags;
+                       u16 listen_interval;
                } add_sta;
                struct {
                        u32 inactive_msec;
Index: wireless-dev/net/d80211/ieee80211_ioctl.c
===================================================================
--- wireless-dev.orig/net/d80211/ieee80211_ioctl.c
+++ wireless-dev/net/d80211/ieee80211_ioctl.c
@@ -296,6 +296,7 @@ static int ieee80211_ioctl_add_sta(struc
        sta->aid = param->u.add_sta.aid;
        if (sta->aid > IEEE80211_MAX_AID)
                sta->aid = 0;
+       sta->listen_interval = param->u.add_sta.listen_interval;
 
        rates = 0;
        for (i = 0; i < sizeof(param->u.add_sta.supp_rates); i++) {
Index: wireless-dev/net/d80211/sta_info.c
===================================================================
--- wireless-dev.orig/net/d80211/sta_info.c
+++ wireless-dev/net/d80211/sta_info.c
@@ -269,18 +269,24 @@ void sta_info_free(struct sta_info *sta,
 }
 
 
-static inline int sta_info_buffer_expired(struct sk_buff *skb)
+static inline int sta_info_buffer_expired(struct ieee80211_local *local,
+                                         struct sta_info *sta,
+                                         struct sk_buff *skb)
 {
         struct ieee80211_tx_packet_data *pkt_data;
+       int timeout;
+
        if (!skb)
                return 0;
 
-       /* TODO: this could be improved by passing STA listen interval into
-        * the kernel driver and expiring frames after 2 x listen_interval x
-         * beacon interval */
-
         pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-       return time_after(jiffies, pkt_data->jiffies + STA_TX_BUFFER_EXPIRE);
+
+       /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */
+       timeout = (sta->listen_interval * local->conf.beacon_int * 32 /
+                  15625) * HZ;
+       if (timeout < STA_TX_BUFFER_EXPIRE)
+               timeout = STA_TX_BUFFER_EXPIRE;
+       return time_after(jiffies, pkt_data->jiffies + timeout);
 }
 
 
@@ -296,9 +302,11 @@ static void sta_info_cleanup_expire_buff
        for (;;) {
                spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
                skb = skb_peek(&sta->ps_tx_buf);
-               if (sta_info_buffer_expired(skb))
+               if (sta_info_buffer_expired(local, sta, skb)) {
                        skb = __skb_dequeue(&sta->ps_tx_buf);
-               else
+                       if (skb_queue_empty(&sta->ps_tx_buf))
+                               sta->flags &= ~WLAN_STA_TIM;
+               } else
                        skb = NULL;
                spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
 
Index: wireless-dev/net/d80211/sta_info.h
===================================================================
--- wireless-dev.orig/net/d80211/sta_info.h
+++ wireless-dev/net/d80211/sta_info.h
@@ -107,6 +107,8 @@ struct sta_info {
 #endif /* CONFIG_D80211_DEBUG_COUNTERS */
 
        int vlan_id;
+
+       u16 listen_interval;
 };
 
 
@@ -120,7 +122,8 @@ struct sta_info {
 /* Maximum number of frames to buffer per power saving station */
 #define STA_MAX_TX_BUFFER 128
 
-/* Buffered frame expiry time */
+/* Minimum buffered frame expiry time. If STA uses listen interval that is
+ * smaller than this value, the minimum value here is used instead. */
 #define STA_TX_BUFFER_EXPIRE (10 * HZ)
 
 /* How often station data is cleaned up (e.g., expiration of buffered frames)

--
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to