diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-07-07 13:08:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:06 -0400 |
commit | e0f114e82e3781087a0ad0e92c94ff0d55012c1a (patch) | |
tree | d4c7cfa485360952b3da9fee7acc07efcfdcc7d8 /drivers/net/wireless/p54/txrx.c | |
parent | 0a2b8bb24d4eb67788edd71d1ef8aa86c2e17e0f (diff) |
p54: re-enable power save feature
This patch re-enables p54's power save features and adds a workaround
which temporarily alters the device's power state in order to allow
ps-polls to be sent and buffered data to be retrieved during psm.
(Incorporates patch originally posted as "p54: fix beacon template dtim
IE corruption". -- JWL)
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/txrx.c')
-rw-r--r-- | drivers/net/wireless/p54/txrx.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 6426d2cae6de..01eadb1683fa 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -288,6 +288,45 @@ static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) | |||
288 | priv->rssical_db[band].add) / 4; | 288 | priv->rssical_db[band].add) / 4; |
289 | } | 289 | } |
290 | 290 | ||
291 | /* | ||
292 | * Even if the firmware is capable of dealing with incoming traffic, | ||
293 | * while dozing, we have to prepared in case mac80211 uses PS-POLL | ||
294 | * to retrieve outstanding frames from our AP. | ||
295 | * (see comment in net/mac80211/mlme.c @ line 1993) | ||
296 | */ | ||
297 | static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb) | ||
298 | { | ||
299 | struct ieee80211_hdr *hdr = (void *) skb->data; | ||
300 | struct ieee80211_tim_ie *tim_ie; | ||
301 | u8 *tim; | ||
302 | u8 tim_len; | ||
303 | bool new_psm; | ||
304 | |||
305 | /* only beacons have a TIM IE */ | ||
306 | if (!ieee80211_is_beacon(hdr->frame_control)) | ||
307 | return; | ||
308 | |||
309 | if (!priv->aid) | ||
310 | return; | ||
311 | |||
312 | /* only consider beacons from the associated BSSID */ | ||
313 | if (compare_ether_addr(hdr->addr3, priv->bssid)) | ||
314 | return; | ||
315 | |||
316 | tim = p54_find_ie(skb, WLAN_EID_TIM); | ||
317 | if (!tim) | ||
318 | return; | ||
319 | |||
320 | tim_len = tim[1]; | ||
321 | tim_ie = (struct ieee80211_tim_ie *) &tim[2]; | ||
322 | |||
323 | new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid); | ||
324 | if (new_psm != priv->powersave_override) { | ||
325 | priv->powersave_override = new_psm; | ||
326 | p54_set_ps(priv); | ||
327 | } | ||
328 | } | ||
329 | |||
291 | static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) | 330 | static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) |
292 | { | 331 | { |
293 | struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; | 332 | struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; |
@@ -340,6 +379,9 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) | |||
340 | 379 | ||
341 | skb_pull(skb, header_len); | 380 | skb_pull(skb, header_len); |
342 | skb_trim(skb, le16_to_cpu(hdr->len)); | 381 | skb_trim(skb, le16_to_cpu(hdr->len)); |
382 | if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS)) | ||
383 | p54_pspoll_workaround(priv, skb); | ||
384 | |||
343 | ieee80211_rx_irqsafe(priv->hw, skb); | 385 | ieee80211_rx_irqsafe(priv->hw, skb); |
344 | 386 | ||
345 | queue_delayed_work(priv->hw->workqueue, &priv->work, | 387 | queue_delayed_work(priv->hw->workqueue, &priv->work, |