extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms,
                         int periodic);
 extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
+extern void wl_msleep(struct wl_info *wl, uint ms);
 
 #endif                         /* _wl_export_h_ */
 
                               struct ieee80211_sta *sta, u16 tid, u16 *ssn,
                               u8 buf_size);
 static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
+static void wl_ops_flush(struct ieee80211_hw *hw, bool drop);
 
 static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 }
 
+static void wl_ops_flush(struct ieee80211_hw *hw, bool drop)
+{
+       struct wl_info *wl = HW_TO_WL(hw);
+
+       no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
+
+       /* wait for packet queue and dma fifos to run empty */
+       WL_LOCK(wl);
+       wlc_wait_for_tx_completion(wl->wlc, drop);
+       WL_UNLOCK(wl);
+}
+
 static const struct ieee80211_ops wl_ops = {
        .tx = wl_ops_tx,
        .start = wl_ops_start,
        .sta_remove = wl_ops_sta_remove,
        .ampdu_action = wl_ops_ampdu_action,
        .rfkill_poll = wl_ops_rfkill_poll,
+       .flush = wl_ops_flush,
 };
 
 /*
        WL_LOCK(wl);
        return blocked;
 }
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_msleep(struct wl_info *wl, uint ms)
+{
+       WL_UNLOCK(wl);
+       msleep(ms);
+       WL_LOCK(wl);
+}
 
 {
        return wlc->band->bandunit;
 }
+
+void wlc_wait_for_tx_completion(struct wlc_info *wlc, bool drop)
+{
+       /* flush packet queue when requested */
+       if (drop)
+               pktq_flush(&wlc->active_queue->q, false, NULL, 0);
+
+       /* wait for queue and DMA fifos to run dry */
+       while (!pktq_empty(&wlc->active_queue->q) ||
+              TXPKTPENDTOT(wlc) > 0) {
+               wl_msleep(wlc->wl, 1);
+       }
+}
 
 extern void wlc_scan_start(struct wlc_info *wlc);
 extern void wlc_scan_stop(struct wlc_info *wlc);
 extern int wlc_get_curband(struct wlc_info *wlc);
+extern void wlc_wait_for_tx_completion(struct wlc_info *wlc, bool drop);
 
 static inline int wlc_iovar_getuint(struct wlc_info *wlc, const char *name,
                                    uint *arg)