aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 0f71d1d4339d..c6451c61407a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -36,6 +36,7 @@
36#include "debug.h" 36#include "debug.h"
37 37
38#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ 38#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
39#define BRCMS_FLUSH_TIMEOUT 500 /* msec */
39 40
40/* Flags we support */ 41/* Flags we support */
41#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ 42#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
@@ -362,8 +363,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
362 return -EOPNOTSUPP; 363 return -EOPNOTSUPP;
363 } 364 }
364 365
366 spin_lock_bh(&wl->lock);
367 memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
365 wl->mute_tx = false; 368 wl->mute_tx = false;
366 brcms_c_mute(wl->wlc, false); 369 brcms_c_mute(wl->wlc, false);
370 spin_unlock_bh(&wl->lock);
367 371
368 return 0; 372 return 0;
369} 373}
@@ -539,9 +543,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
539 543
540 if (changed & BSS_CHANGED_ARP_FILTER) { 544 if (changed & BSS_CHANGED_ARP_FILTER) {
541 /* Hardware ARP filter address list or state changed */ 545 /* Hardware ARP filter address list or state changed */
542 brcms_err(core, "%s: arp filtering: enabled %s, count %d" 546 brcms_err(core, "%s: arp filtering: %d addresses"
543 " (implement)\n", __func__, info->arp_filter_enabled ? 547 " (implement)\n", __func__, info->arp_addr_cnt);
544 "true" : "false", info->arp_addr_cnt);
545 } 548 }
546 549
547 if (changed & BSS_CHANGED_QOS) { 550 if (changed & BSS_CHANGED_QOS) {
@@ -668,7 +671,9 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
668 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 671 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
669 break; 672 break;
670 673
671 case IEEE80211_AMPDU_TX_STOP: 674 case IEEE80211_AMPDU_TX_STOP_CONT:
675 case IEEE80211_AMPDU_TX_STOP_FLUSH:
676 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
672 spin_lock_bh(&wl->lock); 677 spin_lock_bh(&wl->lock);
673 brcms_c_ampdu_flush(wl->wlc, sta, tid); 678 brcms_c_ampdu_flush(wl->wlc, sta, tid);
674 spin_unlock_bh(&wl->lock); 679 spin_unlock_bh(&wl->lock);
@@ -708,16 +713,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
708 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); 713 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
709} 714}
710 715
716static bool brcms_tx_flush_completed(struct brcms_info *wl)
717{
718 bool result;
719
720 spin_lock_bh(&wl->lock);
721 result = brcms_c_tx_flush_completed(wl->wlc);
722 spin_unlock_bh(&wl->lock);
723 return result;
724}
725
711static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) 726static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
712{ 727{
713 struct brcms_info *wl = hw->priv; 728 struct brcms_info *wl = hw->priv;
729 int ret;
714 730
715 no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); 731 no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
716 732
717 /* wait for packet queue and dma fifos to run empty */ 733 ret = wait_event_timeout(wl->tx_flush_wq,
718 spin_lock_bh(&wl->lock); 734 brcms_tx_flush_completed(wl),
719 brcms_c_wait_for_tx_completion(wl->wlc, drop); 735 msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));
720 spin_unlock_bh(&wl->lock); 736
737 brcms_dbg_mac80211(wl->wlc->hw->d11core,
738 "ret=%d\n", jiffies_to_msecs(ret));
721} 739}
722 740
723static const struct ieee80211_ops brcms_ops = { 741static const struct ieee80211_ops brcms_ops = {
@@ -772,6 +790,7 @@ void brcms_dpc(unsigned long data)
772 790
773 done: 791 done:
774 spin_unlock_bh(&wl->lock); 792 spin_unlock_bh(&wl->lock);
793 wake_up(&wl->tx_flush_wq);
775} 794}
776 795
777/* 796/*
@@ -1020,6 +1039,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
1020 1039
1021 atomic_set(&wl->callbacks, 0); 1040 atomic_set(&wl->callbacks, 0);
1022 1041
1042 init_waitqueue_head(&wl->tx_flush_wq);
1043
1023 /* setup the bottom half handler */ 1044 /* setup the bottom half handler */
1024 tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); 1045 tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
1025 1046
@@ -1609,13 +1630,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
1609 spin_lock_bh(&wl->lock); 1630 spin_lock_bh(&wl->lock);
1610 return blocked; 1631 return blocked;
1611} 1632}
1612
1613/*
1614 * precondition: perimeter lock has been acquired
1615 */
1616void brcms_msleep(struct brcms_info *wl, uint ms)
1617{
1618 spin_unlock_bh(&wl->lock);
1619 msleep(ms);
1620 spin_lock_bh(&wl->lock);
1621}