return ret;
 }
 
+/* setup BA session receiver setting in the FW. */
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+                                       bool enable)
+{
+       struct wl1271_acx_ba_receiver_setup *acx;
+       int ret;
+
+       wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
+
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* Single link for now */
+       acx->link_id = 1;
+       acx->tid = tid_index;
+       acx->enable = enable;
+       acx->win_size = 0;
+       acx->ssn = ssn;
+
+       ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
+                                  sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx ba receiver session failed: %d", ret);
+               goto out;
+       }
+
+out:
+       kfree(acx);
+       return ret;
+}
+
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
 {
        struct wl1271_acx_fw_tsf_information *tsf_info;
 
        u8 padding[3];
 } __packed;
 
+struct wl1271_acx_ba_receiver_setup {
+       struct acx_header header;
+
+       /* Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id */
+       u8 link_id;
+
+       u8 tid;
+
+       u8 enable;
+
+       u8 padding[1];
+
+       /* Windows size in number of packets */
+       u16 win_size;
+
+       /* BA session starting sequence number.  RANGE 0-FFF */
+       u16 ssn;
+} __packed;
+
 struct wl1271_acx_fw_tsf_information {
        struct acx_header header;
 
 int wl1271_acx_set_ht_information(struct wl1271 *wl,
                                   u16 ht_operation_mode);
 int wl1271_acx_set_ba_session(struct wl1271 *wl,
-                              enum ieee80211_back_parties direction,
-                              u8 tid_index, u8 policy);
+                             enum ieee80211_back_parties direction,
+                             u8 tid_index, u8 policy);
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+                                      bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
 int wl1271_acx_max_tx_retry(struct wl1271 *wl);
 
 
        return ret;
 }
 
+int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                           enum ieee80211_ampdu_mlme_action action,
+                           struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+{
+       struct wl1271 *wl = hw->priv;
+       int ret;
+
+       mutex_lock(&wl->mutex);
+
+       if (unlikely(wl->state == WL1271_STATE_OFF)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+
+       ret = wl1271_ps_elp_wakeup(wl, false);
+       if (ret < 0)
+               goto out;
+
+       switch (action) {
+       case IEEE80211_AMPDU_RX_START:
+               if (wl->ba_support) {
+                       ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
+                                                                true);
+                       if (!ret)
+                               wl->ba_rx_bitmap |= BIT(tid);
+               } else {
+                       ret = -ENOTSUPP;
+               }
+               break;
+
+       case IEEE80211_AMPDU_RX_STOP:
+               ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
+               if (!ret)
+                       wl->ba_rx_bitmap &= ~BIT(tid);
+               break;
+
+       /*
+        * The BA initiator session management in FW independently.
+        * Falling break here on purpose for all TX APDU commands.
+        */
+       case IEEE80211_AMPDU_TX_START:
+       case IEEE80211_AMPDU_TX_STOP:
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               ret = -EINVAL;
+               break;
+
+       default:
+               wl1271_error("Incorrect ampdu action id=%x\n", action);
+               ret = -EINVAL;
+       }
+
+       wl1271_ps_elp_sleep(wl);
+
+out:
+       mutex_unlock(&wl->mutex);
+
+       return ret;
+}
+
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_rate wl1271_rates[] = {
        { .bitrate = 10,
        .get_survey = wl1271_op_get_survey,
        .sta_add = wl1271_op_sta_add,
        .sta_remove = wl1271_op_sta_remove,
+       .ampdu_action = wl1271_op_ampdu_action,
        CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };