enum wl1271_state state;
        struct mutex mutex;
 
+#define WL1271_FLAG_STA_RATES_CHANGED  (0)
+#define WL1271_FLAG_STA_ASSOCIATED     (1)
+       unsigned long flags;
+
        struct wl1271_partition_set part;
 
        struct wl1271_chip chip;
        u16 aid;
 
        /* currently configured rate set */
+       u32 sta_rate_set;
        u32 basic_rate_set;
+       u32 rate_set;
 
        /* The current band */
        enum ieee80211_band band;
 
        /* PSM mode requested */
        bool psm_requested;
-       bool associated;
 
        /* retry counter for PSM entries */
        u8 psm_entry_retry;
 
        return 0;
 }
 
-int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
+int wl1271_acx_rate_policies(struct wl1271 *wl)
 {
        struct acx_rate_policy *acx;
        struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
+       int idx = 0;
        int ret = 0;
 
        wl1271_debug(DEBUG_ACX, "acx rate policies");
                goto out;
        }
 
-       /* configure one default (one-size-fits-all) rate class */
-       acx->rate_class_cnt = cpu_to_le32(1);
-       acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates);
-       acx->rate_class[0].short_retry_limit = c->short_retry_limit;
-       acx->rate_class[0].long_retry_limit = c->long_retry_limit;
-       acx->rate_class[0].aflags = c->aflags;
+       /* configure one basic rate class */
+       idx = ACX_TX_BASIC_RATE;
+       acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
+       acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
+       acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
+       acx->rate_class[idx].aflags = c->aflags;
+
+       /* configure one AP supported rate class */
+       idx = ACX_TX_AP_FULL_RATE;
+       acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
+       acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
+       acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
+       acx->rate_class[idx].aflags = c->aflags;
+
+       acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
 
        ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
        if (ret < 0) {
 
        u8 reserved;
 };
 
+#define ACX_TX_BASIC_RATE      0
+#define ACX_TX_AP_FULL_RATE    1
+#define ACX_TX_RATE_POLICY_CNT 2
 struct acx_rate_policy {
        struct acx_header header;
 
 int wl1271_acx_cts_protect(struct wl1271 *wl,
                           enum acx_ctsprotect_type ctsprotect);
 int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
-int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates);
+int wl1271_acx_rate_policies(struct wl1271 *wl);
 int wl1271_acx_ac_cfg(struct wl1271 *wl);
 int wl1271_acx_tid_cfg(struct wl1271 *wl);
 int wl1271_acx_frag_threshold(struct wl1271 *wl);
 
                goto out_free_memmap;
 
        /* Configure TX rate classes */
-       ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC);
+       ret = wl1271_acx_rate_policies(wl);
        if (ret < 0)
                goto out_free_memmap;
 
 
 static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct wl1271 *wl = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+       struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = txinfo->control.sta;
+       unsigned long flags;
 
+       /* peek into the rates configured in the STA entry */
+       spin_lock_irqsave(&wl->wl_lock, flags);
+       if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) {
+               wl->sta_rate_set = sta->supp_rates[conf->channel->band];
+               set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
+       }
+       spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+       /* queue the packet */
        skb_queue_tail(&wl->tx_queue, skb);
 
        /*
        wl->elp = false;
        wl->psm = 0;
        wl->psm_entry_retry = 0;
-       wl->associated = false;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
        wl->tx_blocks_available = 0;
        wl->time_offset = 0;
        wl->session_counter = 0;
        wl->joined = false;
+       wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+       wl->sta_rate_set = 0;
+       wl->flags = 0;
 
        for (i = 0; i < NUM_TX_QUEUES; i++)
                wl->tx_blocks_freed[i] = 0;
                        wl1271_join_channel(wl, channel);
 
                if (conf->flags & IEEE80211_CONF_IDLE) {
-                       wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
-                       wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC);
+                       wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+                       wl->sta_rate_set = 0;
+                       wl1271_acx_rate_policies(wl);
                }
        }
 
                 * If we're not, we'll enter it when joining an SSID,
                 * through the bss_info_changed() hook.
                 */
-               if (wl->associated) {
+               if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
                        wl1271_info("psm enabled");
                        ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
                }
        return ret;
 }
 
-static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
-{
-       struct ieee80211_supported_band *band;
-       u32 enabled_rates = 0;
-       int bit;
-
-       band = wl->hw->wiphy->bands[wl->band];
-       for (bit = 0; bit < band->n_bitrates; bit++) {
-               if (basic_rate_set & 0x1)
-                       enabled_rates |= band->bitrates[bit].hw_value;
-               basic_rate_set >>= 1;
-       }
-
-       return enabled_rates;
-}
-
 static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif,
                                       struct ieee80211_bss_conf *bss_conf,
        if (changed & BSS_CHANGED_ASSOC) {
                if (bss_conf->assoc) {
                        wl->aid = bss_conf->aid;
-                       wl->associated = true;
+                       set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
 
                        /*
                         * with wl1271, we don't need to update the
                        }
                } else {
                        /* use defaults when not associated */
-                       wl->associated = false;
+                       clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
                        wl->aid = 0;
                }
 
                }
        }
 
-       if (changed & BSS_CHANGED_BASIC_RATES) {
-               wl->basic_rate_set = wl1271_enabled_rates_get(
-                       wl, bss_conf->basic_rates);
-
-               ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
-               if (ret < 0) {
-                       wl1271_warning("Set rate policies failed %d", ret);
-                       goto out_sleep;
-               }
-       }
-
 out_sleep:
        wl1271_ps_elp_sleep(wl);
 
        wl->psm = 0;
        wl->psm_requested = false;
        wl->psm_entry_retry = 0;
-       wl->associated = false;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
        wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
+       wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+       wl->sta_rate_set = 0;
        wl->band = IEEE80211_BAND_2GHZ;
        wl->vif = NULL;
        wl->joined = false;
        wl->gpio_power = false;
+       wl->flags = 0;
 
        for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
                wl->tx_frames[i] = NULL;
 
        pad = pad - skb->len;
        tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
 
+       /* if the packets are destined for AP (have a STA entry) send them
+          with AP rate policies, otherwise use default basic rates */
+       if (control->control.sta)
+               tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
+
        desc->tx_attr = cpu_to_le16(tx_attr);
 
        wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
        return ret;
 }
 
+static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
+{
+       struct ieee80211_supported_band *band;
+       u32 enabled_rates = 0;
+       int bit;
+
+       band = wl->hw->wiphy->bands[wl->band];
+       for (bit = 0; bit < band->n_bitrates; bit++) {
+               if (rate_set & 0x1)
+                       enabled_rates |= band->bitrates[bit].hw_value;
+               rate_set >>= 1;
+       }
+
+       return enabled_rates;
+}
+
 void wl1271_tx_work(struct work_struct *work)
 {
        struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
        struct sk_buff *skb;
        bool woken_up = false;
+       u32 sta_rates = 0;
        int ret;
 
+       /* check if the rates supported by the AP have changed */
+       if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
+                                       &wl->flags))) {
+               unsigned long flags;
+               spin_lock_irqsave(&wl->wl_lock, flags);
+               sta_rates = wl->sta_rate_set;
+               spin_unlock_irqrestore(&wl->wl_lock, flags);
+       }
+
        mutex_lock(&wl->mutex);
 
        if (unlikely(wl->state == WL1271_STATE_OFF))
                goto out;
 
+       /* if rates have changed, re-configure the rate policy */
+       if (unlikely(sta_rates)) {
+               wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
+               wl1271_acx_rate_policies(wl);
+       }
+
        while ((skb = skb_dequeue(&wl->tx_queue))) {
                if (!woken_up) {
                        ret = wl1271_ps_elp_wakeup(wl, false);