|
@@ -781,7 +781,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
|
|
atomic_inc(&sdata->bss->num_sta_ps);
|
|
|
- set_sta_flags(sta, WLAN_STA_PS);
|
|
|
+ set_sta_flags(sta, WLAN_STA_PS_STA);
|
|
|
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
|
|
|
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
|
|
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
|
|
@@ -792,33 +792,25 @@ static void ap_sta_ps_start(struct sta_info *sta)
|
|
|
static void ap_sta_ps_end(struct sta_info *sta)
|
|
|
{
|
|
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
- int sent, buffered;
|
|
|
|
|
|
atomic_dec(&sdata->bss->num_sta_ps);
|
|
|
|
|
|
- clear_sta_flags(sta, WLAN_STA_PS);
|
|
|
- drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
|
|
|
-
|
|
|
- if (!skb_queue_empty(&sta->ps_tx_buf))
|
|
|
- sta_info_clear_tim_bit(sta);
|
|
|
+ clear_sta_flags(sta, WLAN_STA_PS_STA);
|
|
|
|
|
|
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
|
|
printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
|
|
|
sdata->dev->name, sta->sta.addr, sta->sta.aid);
|
|
|
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
|
|
|
|
|
- /* Send all buffered frames to the station */
|
|
|
- sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
|
|
|
- buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
|
|
|
- sent += buffered;
|
|
|
- local->total_ps_buffered -= buffered;
|
|
|
-
|
|
|
+ if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
|
|
|
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
|
|
- printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
|
|
|
- "since STA not sleeping anymore\n", sdata->dev->name,
|
|
|
- sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
|
|
|
+ printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
|
|
|
+ sdata->dev->name, sta->sta.addr, sta->sta.aid);
|
|
|
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ieee80211_sta_ps_deliver_wakeup(sta);
|
|
|
}
|
|
|
|
|
|
static ieee80211_rx_result debug_noinline
|
|
@@ -866,7 +858,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|
|
if (!ieee80211_has_morefrags(hdr->frame_control) &&
|
|
|
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
|
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
|
|
|
- if (test_sta_flags(sta, WLAN_STA_PS)) {
|
|
|
+ if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
|
|
|
/*
|
|
|
* Ignore doze->wake transitions that are
|
|
|
* indicated by non-data frames, the standard
|
|
@@ -1094,9 +1086,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|
|
static ieee80211_rx_result debug_noinline
|
|
|
ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
|
|
{
|
|
|
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
|
|
|
- struct sk_buff *skb;
|
|
|
- int no_pending_pkts;
|
|
|
+ struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
|
__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
|
|
|
|
|
|
if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
|
|
@@ -1107,56 +1097,10 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
|
|
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
|
|
|
return RX_DROP_UNUSABLE;
|
|
|
|
|
|
- skb = skb_dequeue(&rx->sta->tx_filtered);
|
|
|
- if (!skb) {
|
|
|
- skb = skb_dequeue(&rx->sta->ps_tx_buf);
|
|
|
- if (skb)
|
|
|
- rx->local->total_ps_buffered--;
|
|
|
- }
|
|
|
- no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&
|
|
|
- skb_queue_empty(&rx->sta->ps_tx_buf);
|
|
|
-
|
|
|
- if (skb) {
|
|
|
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
- struct ieee80211_hdr *hdr =
|
|
|
- (struct ieee80211_hdr *) skb->data;
|
|
|
-
|
|
|
- /*
|
|
|
- * Tell TX path to send this frame even though the STA may
|
|
|
- * still remain is PS mode after this frame exchange.
|
|
|
- */
|
|
|
- info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
|
|
|
-
|
|
|
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
|
|
- printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
|
|
|
- rx->sta->sta.addr, rx->sta->sta.aid,
|
|
|
- skb_queue_len(&rx->sta->ps_tx_buf));
|
|
|
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
|
|
-
|
|
|
- /* Use MoreData flag to indicate whether there are more
|
|
|
- * buffered frames for this STA */
|
|
|
- if (no_pending_pkts)
|
|
|
- hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
|
|
|
- else
|
|
|
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
|
|
-
|
|
|
- ieee80211_add_pending_skb(rx->local, skb);
|
|
|
-
|
|
|
- if (no_pending_pkts)
|
|
|
- sta_info_clear_tim_bit(rx->sta);
|
|
|
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * FIXME: This can be the result of a race condition between
|
|
|
- * us expiring a frame and the station polling for it.
|
|
|
- * Should we send it a null-func frame indicating we
|
|
|
- * have nothing buffered for it?
|
|
|
- */
|
|
|
- printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
|
|
|
- "though there are no buffered frames for it\n",
|
|
|
- rx->dev->name, rx->sta->sta.addr);
|
|
|
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
|
|
- }
|
|
|
+ if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
|
|
|
+ ieee80211_sta_ps_deliver_poll_response(rx->sta);
|
|
|
+ else
|
|
|
+ set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
|
|
|
|
|
|
/* Free PS Poll skb here instead of returning RX_DROP that would
|
|
|
* count as an dropped frame. */
|