erp.basic_rates = bss_conf->basic_rates;
        erp.beacon_int = bss_conf->beacon_int;
 
+       /* Update the AID, this is needed for dynamic PS support */
+       rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
+       rt2x00dev->last_beacon = bss_conf->timestamp;
+
        /* Update global beacon interval time, this is needed for PS support */
        rt2x00dev->beacon_int = bss_conf->beacon_int;
 
 {
        struct rt2x00lib_conf libconf;
        u16 hw_value;
+       u16 autowake_timeout;
+       u16 beacon_int;
+       u16 beacon_diff;
 
        memset(&libconf, 0, sizeof(libconf));
 
                       sizeof(libconf.channel));
        }
 
+       if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
+           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
+               cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+
        /*
         * Start configuration.
         */
        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
                rt2x00link_reset_tuner(rt2x00dev, false);
 
+       if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
+           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
+           (conf->flags & IEEE80211_CONF_PS)) {
+               beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
+               beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
+
+               if (beacon_diff > beacon_int)
+                       beacon_diff = 0;
+
+               autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff;
+               queue_delayed_work(rt2x00dev->workqueue,
+                                  &rt2x00dev->autowakeup_work,
+                                  autowake_timeout - 15);
+       }
+
+       if (conf->flags & IEEE80211_CONF_PS)
+               set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+       else
+               clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+
        rt2x00dev->curr_band = conf->channel->band;
        rt2x00dev->curr_freq = conf->channel->center_freq;
        rt2x00dev->tx_power = conf->power_level;
 
                                            rt2x00dev);
 }
 
+static void rt2x00lib_autowakeup(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, autowakeup_work.work);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               ERROR(rt2x00dev, "Device failed to wakeup.\n");
+       clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+}
+
 /*
  * Interrupt context handlers.
  */
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
 
+static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
+{
+       struct ieee80211_mgmt *mgmt = (void *)data;
+       u8 *pos, *end;
+
+       pos = (u8 *)mgmt->u.beacon.variable;
+       end = data + len;
+       while (pos < end) {
+               if (pos + 2 + pos[1] > end)
+                       return NULL;
+
+               if (pos[0] == ie)
+                       return pos;
+
+               pos += 2 + pos[1];
+       }
+
+       return NULL;
+}
+
+static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb,
+                                     struct rxdone_entry_desc *rxdesc)
+{
+       struct ieee80211_hdr *hdr = (void *) skb->data;
+       struct ieee80211_tim_ie *tim_ie;
+       u8 *tim;
+       u8 tim_len;
+       bool cam;
+
+       /* If this is not a beacon, or if mac80211 has no powersaving
+        * configured, or if the device is already in powersaving mode
+        * we can exit now. */
+       if (likely(!ieee80211_is_beacon(hdr->frame_control) ||
+                  !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS)))
+               return;
+
+       /* min. beacon length + FCS_LEN */
+       if (skb->len <= 40 + FCS_LEN)
+               return;
+
+       /* and only beacons from the associated BSSID, please */
+       if (!(rxdesc->dev_flags & RXDONE_MY_BSS) ||
+           !rt2x00dev->aid)
+               return;
+
+       rt2x00dev->last_beacon = jiffies;
+
+       tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM);
+       if (!tim)
+               return;
+
+       if (tim[1] < sizeof(*tim_ie))
+               return;
+
+       tim_len = tim[1];
+       tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+       /* Check whenever the PHY can be turned off again. */
+
+       /* 1. What about buffered unicast traffic for our AID? */
+       cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid);
+
+       /* 2. Maybe the AP wants to send multicast/broadcast data? */
+       cam |= (tim_ie->bitmap_ctrl & 0x01);
+
+       if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
+                                IEEE80211_CONF_CHANGE_PS);
+}
+
 static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
                                        struct rxdone_entry_desc *rxdesc)
 {
            rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
                rxdesc.flags |= RX_FLAG_HT;
 
+       /*
+        * Check if this is a beacon, and more frames have been
+        * buffered while we were in powersaving mode.
+        */
+       rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc);
+
        /*
         * Update extra components
         */
        }
 
        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
+       INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
 
        /*
         * Let the driver probe the device to detect the capabilities.