diff options
Diffstat (limited to 'drivers/net')
4 files changed, 27 insertions, 29 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 0f71d1d4339..e5fd20994be 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -36,6 +36,7 @@ #include "debug.h" #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ +#define BRCMS_FLUSH_TIMEOUT 500 /* msec */ /* Flags we support */ #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ @@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); } +static bool brcms_tx_flush_completed(struct brcms_info *wl) +{ + bool result; + + spin_lock_bh(&wl->lock); + result = brcms_c_tx_flush_completed(wl->wlc); + spin_unlock_bh(&wl->lock); + return result; +} + static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) { struct brcms_info *wl = hw->priv; + int ret; no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); - /* wait for packet queue and dma fifos to run empty */ - spin_lock_bh(&wl->lock); - brcms_c_wait_for_tx_completion(wl->wlc, drop); - spin_unlock_bh(&wl->lock); + ret = wait_event_timeout(wl->tx_flush_wq, + brcms_tx_flush_completed(wl), + msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT)); + + brcms_dbg_mac80211(wl->wlc->hw->d11core, + "ret=%d\n", jiffies_to_msecs(ret)); } static const struct ieee80211_ops brcms_ops = { @@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data) done: spin_unlock_bh(&wl->lock); + wake_up(&wl->tx_flush_wq); } /* @@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) atomic_set(&wl->callbacks, 0); + init_waitqueue_head(&wl->tx_flush_wq); + /* setup the bottom half handler */ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); @@ -1609,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl) spin_lock_bh(&wl->lock); return blocked; } - -/* - * precondition: perimeter lock has been acquired - */ -void brcms_msleep(struct brcms_info *wl, uint ms) -{ - spin_unlock_bh(&wl->lock); - msleep(ms); - spin_lock_bh(&wl->lock); -} diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 9358bd5ebd3..947ccacf43e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h @@ -68,6 +68,8 @@ struct brcms_info { spinlock_t lock; /* per-device perimeter lock */ spinlock_t isr_lock; /* per-device ISR synchronization lock */ + /* tx flush */ + wait_queue_head_t tx_flush_wq; /* timer related fields */ atomic_t callbacks; /* # outstanding callback functions */ @@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, extern void brcms_free_timer(struct brcms_timer *timer); extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); extern bool brcms_del_timer(struct brcms_timer *timer); -extern void brcms_msleep(struct brcms_info *wl, uint ms); extern void brcms_dpc(unsigned long data); extern void brcms_timer(struct brcms_timer *t); extern void brcms_fatal_error(struct brcms_info *wl); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 9f3d7e9f3bb..8b5839008af 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -7511,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) return wlc->band->bandunit; } -void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) +bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc) { - int timeout = 20; int i; /* Kick DMA to send any pending AMPDU */ for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) if (wlc->hw->di[i]) - dma_txflush(wlc->hw->di[i]); + dma_kick_tx(wlc->hw->di[i]); - /* wait for queue and DMA fifos to run dry */ - while (brcms_txpktpendtot(wlc) > 0) { - brcms_msleep(wlc->wl, 1); - - if (--timeout == 0) - break; - } - - WARN_ON_ONCE(timeout == 0); + return !brcms_txpktpendtot(wlc); } void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 4fb2834f4e6..b0f14b7b861 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h @@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); extern void brcms_c_scan_start(struct brcms_c_info *wlc); extern void brcms_c_scan_stop(struct brcms_c_info *wlc); extern int brcms_c_get_curband(struct brcms_c_info *wlc); -extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, - bool drop); extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, @@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); +extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); #endif /* _BRCM_PUB_H_ */ |