ath10k: use msdu headroom to store txfrag
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / mac.c
index b8c81bb..99a9bad 100644 (file)
@@ -460,6 +460,11 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
                arg.ssid_len = arvif->vif->bss_conf.ssid_len;
        }
 
+       ath10k_dbg(ATH10K_DBG_MAC,
+                  "mac vdev %d start center_freq %d phymode %s\n",
+                  arg.vdev_id, arg.channel.freq,
+                  ath10k_wmi_phymode_str(arg.channel.mode));
+
        ret = ath10k_wmi_vdev_start(ar, &arg);
        if (ret) {
                ath10k_warn("WMI vdev start failed: ret %d\n", ret);
@@ -1075,8 +1080,6 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
 {
        enum wmi_phy_mode phymode = MODE_UNKNOWN;
 
-       /* FIXME: add VHT */
-
        switch (ar->hw->conf.chandef.chan->band) {
        case IEEE80211_BAND_2GHZ:
                if (sta->ht_cap.ht_supported) {
@@ -1090,7 +1093,17 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
 
                break;
        case IEEE80211_BAND_5GHZ:
-               if (sta->ht_cap.ht_supported) {
+               /*
+                * Check VHT first.
+                */
+               if (sta->vht_cap.vht_supported) {
+                       if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
+                               phymode = MODE_11AC_VHT80;
+                       else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
+                               phymode = MODE_11AC_VHT40;
+                       else if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
+                               phymode = MODE_11AC_VHT20;
+               } else if (sta->ht_cap.ht_supported) {
                        if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
                                phymode = MODE_11NA_HT40;
                        else
@@ -1104,8 +1117,8 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
                break;
        }
 
-       ath10k_dbg(ATH10K_DBG_MAC, "mac peer %pM phymode %d\n",
-                  sta->addr, phymode);
+       ath10k_dbg(ATH10K_DBG_MAC, "mac peer %pM phymode %s\n",
+                  sta->addr, ath10k_wmi_phymode_str(phymode));
 
        arg->peer_phymode = phymode;
        WARN_ON(phymode == MODE_UNKNOWN);
@@ -1211,8 +1224,6 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
        /* FIXME: why don't we print error if wmi call fails? */
        ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
 
-       ath10k_wmi_flush_tx(ar);
-
        arvif->def_wep_key_index = 0;
 }
 
@@ -1651,8 +1662,6 @@ static int ath10k_abort_scan(struct ath10k *ar)
                return -EIO;
        }
 
-       ath10k_wmi_flush_tx(ar);
-
        ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
        if (ret == 0)
                ath10k_warn("timed out while waiting for scan to stop\n");
@@ -1686,10 +1695,6 @@ static int ath10k_start_scan(struct ath10k *ar,
        if (ret)
                return ret;
 
-       /* make sure we submit the command so the completion
-       * timeout makes sense */
-       ath10k_wmi_flush_tx(ar);
-
        ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ);
        if (ret == 0) {
                ath10k_abort_scan(ar);
@@ -1752,7 +1757,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
                ath10k_tx_h_seq_no(skb);
        }
 
-       memset(ATH10K_SKB_CB(skb), 0, sizeof(*ATH10K_SKB_CB(skb)));
+       ATH10K_SKB_CB(skb)->htt.is_offchan = false;
        ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id;
        ATH10K_SKB_CB(skb)->htt.tid = tid;
 
@@ -1911,7 +1916,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
                        ret = ath10k_monitor_destroy(ar);
        }
 
-       ath10k_wmi_flush_tx(ar);
        mutex_unlock(&ar->conf_mutex);
        return ret;
 }
@@ -2062,6 +2066,13 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&ar->conf_mutex);
 
+       spin_lock_bh(&ar->data_lock);
+       if (arvif->beacon) {
+               dev_kfree_skb_any(arvif->beacon);
+               arvif->beacon = NULL;
+       }
+       spin_unlock_bh(&ar->data_lock);
+
        ar->free_vdev_map |= 1 << (arvif->vdev_id);
 
        if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
@@ -2842,8 +2853,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
                        bool empty;
 
                        spin_lock_bh(&ar->htt.tx_lock);
-                       empty = bitmap_empty(ar->htt.used_msdu_ids,
-                                            ar->htt.max_num_pending_tx);
+                       empty = (ar->htt.num_pending_tx == 0);
                        spin_unlock_bh(&ar->htt.tx_lock);
 
                        skip = (ar->state == ATH10K_STATE_WEDGED);
@@ -3332,6 +3342,10 @@ int ath10k_mac_register(struct ath10k *ar)
                        IEEE80211_HW_WANT_MONITOR_VIF |
                        IEEE80211_HW_AP_LINK_PS;
 
+       /* MSDU can have HTT TX fragment pushed in front. The additional 4
+        * bytes is used for padding/alignment if necessary. */
+       ar->hw->extra_tx_headroom += sizeof(struct htt_data_tx_desc_frag)*2 + 4;
+
        if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
                ar->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS;