Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ti / wlcore / tx.c
index ece392c54d9c858bd255ab78eb9e79d054337d52..004d02e71f01a25eb3abf9496fa752f79af3df7d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/spinlock.h>
 
 #include "wlcore.h"
 #include "debug.h"
@@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
                                    struct wl12xx_vif *wlvif,
                                    u8 hlid)
 {
-       bool fw_ps, single_link;
+       bool fw_ps;
        u8 tx_pkts;
 
        if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
@@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
 
        fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
        tx_pkts = wl->links[hlid].allocated_pkts;
-       single_link = (wl->active_link_count == 1);
 
        /*
         * if in FW PS and there is enough data in FW we can put the link
         * into high-level PS and clean out its TX queues.
         * Make an exception if this is the only connected link. In this
         * case FW-memory congestion is less of a problem.
+        * Note that a single connected STA means 3 active links, since we must
+        * account for the global and broadcast AP links. The "fw_ps" check
+        * assures us the third link is a STA connected to the AP. Otherwise
+        * the FW would not set the PSM bit.
         */
-       if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
+       if (wl->active_link_count > 3 && fw_ps &&
+           tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
                wl12xx_ps_link_start(wl, wlvif, hlid, true);
 }
 
@@ -639,6 +644,7 @@ next:
 
        }
 
+out:
        if (!skb &&
            test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
                int q;
@@ -652,7 +658,6 @@ next:
                spin_unlock_irqrestore(&wl->wl_lock, flags);
        }
 
-out:
        return skb;
 }
 
@@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 
        wl->stats.retry_count += result->ack_failures;
 
-       /*
-        * update sequence number only when relevant, i.e. only in
-        * sessions of TKIP, AES and GEM (not in open or WEP sessions)
-        */
-       if (info->control.hw_key &&
-           (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
-            info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
-            info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
-               u8 fw_lsb = result->tx_security_sequence_number_lsb;
-               u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
-
-               /*
-                * update security sequence number, taking care of potential
-                * wrap-around
-                */
-               wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff;
-               wlvif->tx_security_last_seq_lsb = fw_lsb;
-       }
-
        /* remove private header from packet */
        skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
 
@@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
        /* TX failure */
        for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
-               if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
+               if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+                   i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) {
                        /* this calls wl12xx_free_link */
                        wl1271_free_sta(wl, wlvif, i);
                } else {
@@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl,
 {
        int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
 
-       WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
+       assert_spin_locked(&wl->wl_lock);
        return test_bit(reason, &wl->queue_stop_reasons[hwq]);
 }
 
@@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 {
        int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
 
-       WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
+       assert_spin_locked(&wl->wl_lock);
        return !!wl->queue_stop_reasons[hwq];
 }