diff options
author | Kalle Valo <kalle.valo@nokia.com> | 2009-02-10 16:09:31 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-13 19:45:17 +0100 |
commit | 572e00122190e3064fa19bd9780b146d2d0f1905 (patch) | |
tree | ae8423958dd012af1dca83718b3035f2e75c53ec /net/mac80211/rx.c | |
parent | mac80211: remove multicast check from check_tim() (diff) | |
download | linux-572e00122190e3064fa19bd9780b146d2d0f1905.tar.xz linux-572e00122190e3064fa19bd9780b146d2d0f1905.zip |
mac80211: use ps-poll when dynamic power save mode is disabled
When a directed tim bit is set, mac80211 currently disables power save
ands sends a null frame to the AP. But if dynamic power save is
disabled, mac80211 will not enable power save ever gain. Fix this by
adding ps-poll functionality to mac80211. When a directed tim bit is
set, mac80211 sends a ps-poll frame to the AP and checks for the more
data bit in the returned data frames.
Using ps-poll is slower than waking up with null frame, but it's saves more
power in cases where the traffic is low. Userspace can control if either
ps-poll or null wakeup method is used by enabling and disabling dynamic
power save.
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to '')
-rw-r--r-- | net/mac80211/rx.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8e8ddbfcd236..0e030d3fbdec 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -731,6 +731,39 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) return result; } +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx) +{ + struct ieee80211_local *local; + struct ieee80211_hdr *hdr; + struct sk_buff *skb; + + local = rx->local; + skb = rx->skb; + hdr = (struct ieee80211_hdr *) skb->data; + + if (!local->pspolling) + return RX_CONTINUE; + + if (!ieee80211_has_fromds(hdr->frame_control)) + /* this is not from AP */ + return RX_CONTINUE; + + if (!ieee80211_is_data(hdr->frame_control)) + return RX_CONTINUE; + + if (!ieee80211_has_moredata(hdr->frame_control)) { + /* AP has no more frames buffered for us */ + local->pspolling = false; + return RX_CONTINUE; + } + + /* more data bit is set, let's request a new frame from the AP */ + ieee80211_send_pspoll(local, rx->sdata); + + return RX_CONTINUE; +} + static void ap_sta_ps_start(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -1987,6 +2020,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, CALL_RXH(ieee80211_rx_h_passive_scan) CALL_RXH(ieee80211_rx_h_check) CALL_RXH(ieee80211_rx_h_decrypt) + CALL_RXH(ieee80211_rx_h_check_more_data) CALL_RXH(ieee80211_rx_h_sta_process) CALL_RXH(ieee80211_rx_h_defragment) CALL_RXH(ieee80211_rx_h_ps_poll) |