return 0;
 }
 
+static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
+{
+       int num_mgmt;
+
+       ieee80211_free_txskb(ar->hw, skb);
+
+       num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
+       if (num_mgmt < 0)
+               WARN_ON_ONCE(1);
+
+       if (!num_mgmt)
+               wake_up(&ar->txmgmt_empty_waitq);
+}
+
 int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
 {
        struct sk_buff *msdu = skb;
        info = IEEE80211_SKB_CB(msdu);
        memset(&info->status, 0, sizeof(info->status));
 
-       ieee80211_free_txskb(ar->hw, msdu);
+       ath12k_mgmt_over_wmi_tx_drop(ar, skb);
 
        return 0;
 }
        struct sk_buff *skb;
 
        while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
-               ieee80211_free_txskb(ar->hw, skb);
+               ath12k_mgmt_over_wmi_tx_drop(ar, skb);
 }
 
 static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
                skb_cb = ATH12K_SKB_CB(skb);
                if (!skb_cb->vif) {
                        ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
-                       ieee80211_free_txskb(ar->hw, skb);
+                       ath12k_mgmt_over_wmi_tx_drop(ar, skb);
                        continue;
                }
 
                        if (ret) {
                                ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
                                            arvif->vdev_id, ret);
-                               ieee80211_free_txskb(ar->hw, skb);
-                       } else {
-                               atomic_inc(&ar->num_pending_mgmt_tx);
+                               ath12k_mgmt_over_wmi_tx_drop(ar, skb);
                        }
                } else {
                        ath12k_warn(ar->ab,
                                    "dropping mgmt frame for vdev %d, is_started %d\n",
                                    arvif->vdev_id,
                                    arvif->is_started);
-                       ieee80211_free_txskb(ar->hw, skb);
+                       ath12k_mgmt_over_wmi_tx_drop(ar, skb);
                }
        }
 }
        }
 
        skb_queue_tail(q, skb);
+       atomic_inc(&ar->num_pending_mgmt_tx);
        ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
 
        return 0;
                                       ATH12K_FLUSH_TIMEOUT);
        if (time_left == 0)
                ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
+
+       time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
+                                      (atomic_read(&ar->num_pending_mgmt_tx) == 0),
+                                      ATH12K_FLUSH_TIMEOUT);
+       if (time_left == 0)
+               ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
+                           time_left);
 }
 
 static int
                if (ret)
                        goto err_cleanup;
 
+               init_waitqueue_head(&ar->txmgmt_empty_waitq);
                idr_init(&ar->txmgmt_idr);
                spin_lock_init(&ar->txmgmt_idr_lock);
        }
 
        struct sk_buff *msdu;
        struct ieee80211_tx_info *info;
        struct ath12k_skb_cb *skb_cb;
+       int num_mgmt;
 
        spin_lock_bh(&ar->txmgmt_idr_lock);
        msdu = idr_find(&ar->txmgmt_idr, desc_id);
 
        ieee80211_tx_status_irqsafe(ar->hw, msdu);
 
+       num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
        /* WARN when we received this event without doing any mgmt tx */
-       if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
+       if (num_mgmt < 0)
                WARN_ON_ONCE(1);
 
+       if (!num_mgmt)
+               wake_up(&ar->txmgmt_empty_waitq);
+
        return 0;
 }