Commit 12392c6d authored by Arend van Spriel's avatar Arend van Spriel Committed by Greg Kroah-Hartman

staging: brcm80211: implement flush driver callback for mac80211

The mac80211 interface has a flush callback which is used by mac80211
to assure all pending transmit packets have been transmitted. This
is used before scanning off-channel.

Cc: devel@linuxdriverproject.org
Cc: linux-wireless@vger.kernel.org
Cc: Brett Rudley <brudley@broadcom.com>
Cc: Henry Ptasinski <henryp@broadcom.com>
Cc: Roland Vossen <rvossen@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent be2fee08
......@@ -42,5 +42,6 @@ extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
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_ */
......@@ -149,6 +149,7 @@ static int wl_ops_ampdu_action(struct ieee80211_hw *hw,
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)
{
......@@ -667,6 +668,18 @@ static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
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,
......@@ -688,6 +701,7 @@ static const struct ieee80211_ops wl_ops = {
.sta_remove = wl_ops_sta_remove,
.ampdu_action = wl_ops_ampdu_action,
.rfkill_poll = wl_ops_rfkill_poll,
.flush = wl_ops_flush,
};
/*
......@@ -1947,3 +1961,13 @@ bool wl_rfkill_set_hw_state(struct wl_info *wl)
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);
}
......@@ -8104,3 +8104,16 @@ int wlc_get_curband(struct wlc_info *wlc)
{
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);
}
}
......@@ -569,6 +569,7 @@ extern void wlc_associate_upd(struct wlc_info *wlc, bool state);
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment