* which shouldn't be in TFD mask anyway
                         */
                        ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->mcast_sta,
-                                                      0, vif->type);
+                                                      0, vif->type,
+                                                      IWL_STA_MULTICAST);
                        if (ret)
                                goto out_release;
                }
        if (ret)
                goto out_remove;
 
-       /* Send the bcast station. At this stage the TBTT and DTIM time events
-        * are added and applied to the scheduler */
-       ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
+       ret = iwl_mvm_add_mcast_sta(mvm, vif);
        if (ret)
                goto out_unbind;
 
-       ret = iwl_mvm_add_mcast_sta(mvm, vif);
+       /* Send the bcast station. At this stage the TBTT and DTIM time events
+        * are added and applied to the scheduler */
+       ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
        if (ret)
-               goto out_rm_bcast;
+               goto out_rm_mcast;
 
        /* must be set before quota calculations */
        mvmvif->ap_ibss_active = true;
 out_quota_failed:
        iwl_mvm_power_update_mac(mvm);
        mvmvif->ap_ibss_active = false;
-       iwl_mvm_rm_mcast_sta(mvm, vif);
-out_rm_bcast:
        iwl_mvm_send_rm_bcast_sta(mvm, vif);
+out_rm_mcast:
+       iwl_mvm_rm_mcast_sta(mvm, vif);
 out_unbind:
        iwl_mvm_binding_remove_vif(mvm, vif);
 out_remove:
                iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
 
        iwl_mvm_update_quotas(mvm, false, NULL);
-       iwl_mvm_rm_mcast_sta(mvm, vif);
+
+       /*
+        * This is not very nice, but the simplest:
+        * For older FWs removing the mcast sta before the bcast station may
+        * cause assert 0x2b00.
+        * This is fixed in later FW (which will stop beaconing when removing
+        * bcast station).
+        * So make the order of removal depend on the TLV
+        */
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               iwl_mvm_rm_mcast_sta(mvm, vif);
        iwl_mvm_send_rm_bcast_sta(mvm, vif);
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               iwl_mvm_rm_mcast_sta(mvm, vif);
        iwl_mvm_binding_remove_vif(mvm, vif);
 
        iwl_mvm_power_update_mac(mvm);
 
  */
 static inline int iwl_mvm_add_sta_cmd_size(struct iwl_mvm *mvm)
 {
-       return iwl_mvm_has_new_rx_api(mvm) ?
-               sizeof(struct iwl_mvm_add_sta_cmd) :
-               sizeof(struct iwl_mvm_add_sta_cmd_v7);
+       if (iwl_mvm_has_new_rx_api(mvm) ||
+           fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               return sizeof(struct iwl_mvm_add_sta_cmd);
+       else
+               return sizeof(struct iwl_mvm_add_sta_cmd_v7);
 }
 
 static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
        u32 status;
        u32 agg_size = 0, mpdu_dens = 0;
 
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               add_sta_cmd.station_type = mvm_sta->sta_type;
+
        if (!update || (flags & STA_MODIFY_QUEUES)) {
                memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
 
        mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
        mvm_sta->tx_protection = 0;
        mvm_sta->tt_tx_protection = false;
+       mvm_sta->sta_type = sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK;
 
        /* HW restart, don't assume the memory has been zeroed */
        atomic_set(&mvm->pending_frames[sta_id], 0);
 
 int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
                             struct iwl_mvm_int_sta *sta,
-                            u32 qmask, enum nl80211_iftype iftype)
+                            u32 qmask, enum nl80211_iftype iftype,
+                            enum iwl_sta_type type)
 {
        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
                sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
        }
 
        sta->tfd_queue_msk = qmask;
+       sta->type = type;
 
        /* put a non-NULL value so iterating over the stations won't stop */
        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL));
        cmd.sta_id = sta->sta_id;
        cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
                                                             color));
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               cmd.station_type = sta->type;
 
        if (!iwl_mvm_has_new_tx_api(mvm))
                cmd.tfd_queue_msk = cpu_to_le32(sta->tfd_queue_msk);
 
        /* Allocate aux station and assign to it the aux queue */
        ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
-                                      NL80211_IFTYPE_UNSPECIFIED);
+                                      NL80211_IFTYPE_UNSPECIFIED,
+                                      IWL_STA_AUX_ACTIVITY);
        if (ret)
                return ret;
 
        }
 
        return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, qmask,
-                                       ieee80211_vif_type_p2p(vif));
+                                       ieee80211_vif_type_p2p(vif),
+                                       IWL_STA_GENERAL_PURPOSE);
 }
 
 /* Allocate a new station entry for the broadcast station to the given vif,
        if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
                return -ENOTSUPP;
 
+       /*
+        * While in previous FWs we had to exclude cab queue from TFD queue
+        * mask, now it is needed as any other queue.
+        */
+       if (!iwl_mvm_has_new_tx_api(mvm) &&
+           fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) {
+               iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
+                                  &cfg, timeout);
+               msta->tfd_queue_msk |= BIT(vif->cab_queue);
+       }
        ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
                                         mvmvif->id, mvmvif->color);
        if (ret) {
        /*
         * Enable cab queue after the ADD_STA command is sent.
         * This is needed for a000 firmware which won't accept SCD_QUEUE_CFG
-        * command with unknown station id.
+        * command with unknown station id, and for FW that doesn't support
+        * station API since the cab queue is not included in the
+        * tfd_queue_mask.
         */
        if (iwl_mvm_has_new_tx_api(mvm)) {
                int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue,
                                                    IWL_MAX_TID_COUNT,
                                                    timeout);
                mvmvif->cab_queue = queue;
-       } else {
+       } else if (!fw_has_api(&mvm->fw->ucode_capa,
+                              IWL_UCODE_TLV_API_STA_TYPE)) {
                iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
                                   &cfg, timeout);
        }
 
        /* Note: this is ignored by firmware not supporting GO uAPSD */
        if (more_data)
-               cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_MOREDATA);
+               cmd.sleep_state_flags |= STA_SLEEP_STATE_MOREDATA;
 
        if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) {
                mvmsta->next_status_eosp = true;
-               cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_PS_POLL);
+               cmd.sleep_state_flags |= STA_SLEEP_STATE_PS_POLL;
        } else {
-               cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD);
+               cmd.sleep_state_flags |= STA_SLEEP_STATE_UAPSD;
        }
 
        /* block the Tx queues until the FW updated the sleep Tx count */
        spin_unlock_bh(&mvm_sta->lock);
 }
 
+static void iwl_mvm_int_sta_modify_disable_tx(struct iwl_mvm *mvm,
+                                             struct iwl_mvm_vif *mvmvif,
+                                             struct iwl_mvm_int_sta *sta,
+                                             bool disable)
+{
+       u32 id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
+       struct iwl_mvm_add_sta_cmd cmd = {
+               .add_modify = STA_MODE_MODIFY,
+               .sta_id = sta->sta_id,
+               .station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0,
+               .station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX),
+               .mac_id_n_color = cpu_to_le32(id),
+       };
+       int ret;
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, 0,
+                                  iwl_mvm_add_sta_cmd_size(mvm), &cmd);
+       if (ret)
+               IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
+}
+
 void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
                                       struct iwl_mvm_vif *mvmvif,
                                       bool disable)
 
                iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, disable);
        }
+
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
+               return;
+
+       /* Need to block/unblock also multicast station */
+       if (mvmvif->mcast_sta.sta_id != IWL_MVM_INVALID_STA)
+               iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
+                                                 &mvmvif->mcast_sta, disable);
+
+       /*
+        * Only unblock the broadcast station (FW blocks it for immediate
+        * quiet, not the driver)
+        */
+       if (!disable && mvmvif->bcast_sta.sta_id != IWL_MVM_INVALID_STA)
+               iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
+                                                 &mvmvif->bcast_sta, disable);
 }
 
 void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)