diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 47 |
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 | ||
716 | static 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 | |||
711 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) | 726 | static 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 | ||
723 | static const struct ieee80211_ops brcms_ops = { | 741 | static 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 | */ | ||
1616 | void 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 | } | ||