These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ath / ath10k / htt_rx.c
index 01a2b38..6060dda 100644 (file)
@@ -368,7 +368,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags)
                                        & (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR |
                                           RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR));
-               msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0),
+               msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.common.info0),
                              RX_MSDU_START_INFO0_MSDU_LENGTH);
                msdu_chained = rx_desc->frag_info.ring2_more_count;
 
@@ -394,7 +394,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                        msdu_chaining = 1;
                }
 
-               last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
+               last_msdu = __le32_to_cpu(rx_desc->msdu_end.common.info0) &
                                RX_MSDU_END_INFO0_LAST_MSDU;
 
                trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
@@ -637,58 +637,24 @@ static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
        return 0;
 }
 
-struct rfc1042_hdr {
-       u8 llc_dsap;
-       u8 llc_ssap;
-       u8 llc_ctrl;
-       u8 snap_oui[3];
-       __be16 snap_type;
-} __packed;
-
 struct amsdu_subframe_hdr {
        u8 dst[ETH_ALEN];
        u8 src[ETH_ALEN];
        __be16 len;
 } __packed;
 
-static const u8 rx_legacy_rate_idx[] = {
-       3,      /* 0x00  - 11Mbps  */
-       2,      /* 0x01  - 5.5Mbps */
-       1,      /* 0x02  - 2Mbps   */
-       0,      /* 0x03  - 1Mbps   */
-       3,      /* 0x04  - 11Mbps  */
-       2,      /* 0x05  - 5.5Mbps */
-       1,      /* 0x06  - 2Mbps   */
-       0,      /* 0x07  - 1Mbps   */
-       10,     /* 0x08  - 48Mbps  */
-       8,      /* 0x09  - 24Mbps  */
-       6,      /* 0x0A  - 12Mbps  */
-       4,      /* 0x0B  - 6Mbps   */
-       11,     /* 0x0C  - 54Mbps  */
-       9,      /* 0x0D  - 36Mbps  */
-       7,      /* 0x0E  - 18Mbps  */
-       5,      /* 0x0F  - 9Mbps   */
-};
+#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
 
 static void ath10k_htt_rx_h_rates(struct ath10k *ar,
                                  struct ieee80211_rx_status *status,
                                  struct htt_rx_desc *rxd)
 {
-       enum ieee80211_band band;
-       u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
+       struct ieee80211_supported_band *sband;
+       u8 cck, rate, bw, sgi, mcs, nss;
        u8 preamble = 0;
+       u8 group_id;
        u32 info1, info2, info3;
 
-       /* Band value can't be set as undefined but freq can be 0 - use that to
-        * determine whether band is provided.
-        *
-        * FIXME: Perhaps this can go away if CCK rate reporting is a little
-        * reworked?
-        */
-       if (!status->freq)
-               return;
-
-       band = status->band;
        info1 = __le32_to_cpu(rxd->ppdu_start.info1);
        info2 = __le32_to_cpu(rxd->ppdu_start.info2);
        info3 = __le32_to_cpu(rxd->ppdu_start.info3);
@@ -697,31 +663,18 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
 
        switch (preamble) {
        case HTT_RX_LEGACY:
+               /* To get legacy rate index band is required. Since band can't
+                * be undefined check if freq is non-zero.
+                */
+               if (!status->freq)
+                       return;
+
                cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
                rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
-               rate_idx = 0;
-
-               if (rate < 0x08 || rate > 0x0F)
-                       break;
+               rate &= ~RX_PPDU_START_RATE_FLAG;
 
-               switch (band) {
-               case IEEE80211_BAND_2GHZ:
-                       if (cck)
-                               rate &= ~BIT(3);
-                       rate_idx = rx_legacy_rate_idx[rate];
-                       break;
-               case IEEE80211_BAND_5GHZ:
-                       rate_idx = rx_legacy_rate_idx[rate];
-                       /* We are using same rate table registering
-                          HW - ath10k_rates[]. In case of 5GHz skip
-                          CCK rates, so -4 here */
-                       rate_idx -= 4;
-                       break;
-               default:
-                       break;
-               }
-
-               status->rate_idx = rate_idx;
+               sband = &ar->mac.sbands[status->band];
+               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
                break;
        case HTT_RX_HT:
        case HTT_RX_HT_WITH_TXBF:
@@ -742,10 +695,50 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
        case HTT_RX_VHT_WITH_TXBF:
                /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
                   TODO check this */
-               mcs = (info3 >> 4) & 0x0F;
-               nss = ((info2 >> 10) & 0x07) + 1;
                bw = info2 & 3;
                sgi = info3 & 1;
+               group_id = (info2 >> 4) & 0x3F;
+
+               if (GROUP_ID_IS_SU_MIMO(group_id)) {
+                       mcs = (info3 >> 4) & 0x0F;
+                       nss = ((info2 >> 10) & 0x07) + 1;
+               } else {
+                       /* Hardware doesn't decode VHT-SIG-B into Rx descriptor
+                        * so it's impossible to decode MCS. Also since
+                        * firmware consumes Group Id Management frames host
+                        * has no knowledge regarding group/user position
+                        * mapping so it's impossible to pick the correct Nsts
+                        * from VHT-SIG-A1.
+                        *
+                        * Bandwidth and SGI are valid so report the rateinfo
+                        * on best-effort basis.
+                        */
+                       mcs = 0;
+                       nss = 1;
+               }
+
+               if (mcs > 0x09) {
+                       ath10k_warn(ar, "invalid MCS received %u\n", mcs);
+                       ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n",
+                                   __le32_to_cpu(rxd->attention.flags),
+                                   __le32_to_cpu(rxd->mpdu_start.info0),
+                                   __le32_to_cpu(rxd->mpdu_start.info1),
+                                   __le32_to_cpu(rxd->msdu_start.common.info0),
+                                   __le32_to_cpu(rxd->msdu_start.common.info1),
+                                   rxd->ppdu_start.info0,
+                                   __le32_to_cpu(rxd->ppdu_start.info1),
+                                   __le32_to_cpu(rxd->ppdu_start.info2),
+                                   __le32_to_cpu(rxd->ppdu_start.info3),
+                                   __le32_to_cpu(rxd->ppdu_start.info4));
+
+                       ath10k_warn(ar, "msdu end %08x mpdu end %08x\n",
+                                   __le32_to_cpu(rxd->msdu_end.common.info0),
+                                   __le32_to_cpu(rxd->mpdu_end.info0));
+
+                       ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
+                                       "rx desc msdu payload: ",
+                                       rxd->msdu_payload, 50);
+               }
 
                status->rate_idx = mcs;
                status->vht_nss = nss;
@@ -773,8 +766,87 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
        }
 }
 
+static struct ieee80211_channel *
+ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
+{
+       struct ath10k_peer *peer;
+       struct ath10k_vif *arvif;
+       struct cfg80211_chan_def def;
+       u16 peer_id;
+
+       lockdep_assert_held(&ar->data_lock);
+
+       if (!rxd)
+               return NULL;
+
+       if (rxd->attention.flags &
+           __cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID))
+               return NULL;
+
+       if (!(rxd->msdu_end.common.info0 &
+             __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)))
+               return NULL;
+
+       peer_id = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+                    RX_MPDU_START_INFO0_PEER_IDX);
+
+       peer = ath10k_peer_find_by_id(ar, peer_id);
+       if (!peer)
+               return NULL;
+
+       arvif = ath10k_get_arvif(ar, peer->vdev_id);
+       if (WARN_ON_ONCE(!arvif))
+               return NULL;
+
+       if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
+               return NULL;
+
+       return def.chan;
+}
+
+static struct ieee80211_channel *
+ath10k_htt_rx_h_vdev_channel(struct ath10k *ar, u32 vdev_id)
+{
+       struct ath10k_vif *arvif;
+       struct cfg80211_chan_def def;
+
+       lockdep_assert_held(&ar->data_lock);
+
+       list_for_each_entry(arvif, &ar->arvifs, list) {
+               if (arvif->vdev_id == vdev_id &&
+                   ath10k_mac_vif_chan(arvif->vif, &def) == 0)
+                       return def.chan;
+       }
+
+       return NULL;
+}
+
+static void
+ath10k_htt_rx_h_any_chan_iter(struct ieee80211_hw *hw,
+                             struct ieee80211_chanctx_conf *conf,
+                             void *data)
+{
+       struct cfg80211_chan_def *def = data;
+
+       *def = conf->def;
+}
+
+static struct ieee80211_channel *
+ath10k_htt_rx_h_any_channel(struct ath10k *ar)
+{
+       struct cfg80211_chan_def def = {};
+
+       ieee80211_iter_chan_contexts_atomic(ar->hw,
+                                           ath10k_htt_rx_h_any_chan_iter,
+                                           &def);
+
+       return def.chan;
+}
+
 static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
-                                   struct ieee80211_rx_status *status)
+                                   struct ieee80211_rx_status *status,
+                                   struct htt_rx_desc *rxd,
+                                   u32 vdev_id)
 {
        struct ieee80211_channel *ch;
 
@@ -782,6 +854,12 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
        ch = ar->scan_channel;
        if (!ch)
                ch = ar->rx_channel;
+       if (!ch)
+               ch = ath10k_htt_rx_h_peer_channel(ar, rxd);
+       if (!ch)
+               ch = ath10k_htt_rx_h_vdev_channel(ar, vdev_id);
+       if (!ch)
+               ch = ath10k_htt_rx_h_any_channel(ar);
        spin_unlock_bh(&ar->data_lock);
 
        if (!ch)
@@ -819,7 +897,8 @@ static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
 
 static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
                                 struct sk_buff_head *amsdu,
-                                struct ieee80211_rx_status *status)
+                                struct ieee80211_rx_status *status,
+                                u32 vdev_id)
 {
        struct sk_buff *first;
        struct htt_rx_desc *rxd;
@@ -851,7 +930,7 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
                status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
                ath10k_htt_rx_h_signal(ar, status, rxd);
-               ath10k_htt_rx_h_channel(ar, status);
+               ath10k_htt_rx_h_channel(ar, status, rxd, vdev_id);
                ath10k_htt_rx_h_rates(ar, status, rxd);
        }
 
@@ -929,10 +1008,16 @@ static void ath10k_process_rx(struct ath10k *ar,
        ieee80211_rx(ar->hw, skb);
 }
 
-static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr)
+static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
+                                     struct ieee80211_hdr *hdr)
 {
-       /* nwifi header is padded to 4 bytes. this fixes 4addr rx */
-       return round_up(ieee80211_hdrlen(hdr->frame_control), 4);
+       int len = ieee80211_hdrlen(hdr->frame_control);
+
+       if (!test_bit(ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
+                     ar->fw_features))
+               len = round_up(len, 4);
+
+       return len;
 }
 
 static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
@@ -949,9 +1034,9 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
        bool is_last;
 
        rxd = (void *)msdu->data - sizeof(*rxd);
-       is_first = !!(rxd->msdu_end.info0 &
+       is_first = !!(rxd->msdu_end.common.info0 &
                      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-       is_last = !!(rxd->msdu_end.info0 &
+       is_last = !!(rxd->msdu_end.common.info0 &
                     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
 
        /* Delivered decapped frame:
@@ -975,9 +1060,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
        skb_trim(msdu, msdu->len - FCS_LEN);
 
        /* In most cases this will be true for sniffed frames. It makes sense
-        * to deliver them as-is without stripping the crypto param. This would
-        * also make sense for software based decryption (which is not
-        * implemented in ath10k).
+        * to deliver them as-is without stripping the crypto param. This is
+        * necessary for software based decryption.
         *
         * If there's no error then the frame is decrypted. At least that is
         * the case for frames that come in via fragmented rx indication.
@@ -1031,7 +1115,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
 
        /* pull decapped header and copy SA & DA */
        hdr = (struct ieee80211_hdr *)msdu->data;
-       hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+       hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
        ether_addr_copy(da, ieee80211_get_DA(hdr));
        ether_addr_copy(sa, ieee80211_get_SA(hdr));
        skb_pull(msdu, hdr_len);
@@ -1062,9 +1146,9 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
        rxd = (void *)msdu->data - sizeof(*rxd);
        hdr = (void *)rxd->rx_hdr_status;
 
-       is_first = !!(rxd->msdu_end.info0 &
+       is_first = !!(rxd->msdu_end.common.info0 &
                      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-       is_last = !!(rxd->msdu_end.info0 &
+       is_last = !!(rxd->msdu_end.common.info0 &
                     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
        is_amsdu = !(is_first && is_last);
 
@@ -1159,7 +1243,6 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
 {
        struct htt_rx_desc *rxd;
        enum rx_msdu_decap_format decap;
-       struct ieee80211_hdr *hdr;
 
        /* First msdu's decapped header:
         * [802.11 header] <-- padded to 4 bytes long
@@ -1173,8 +1256,7 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
         */
 
        rxd = (void *)msdu->data - sizeof(*rxd);
-       hdr = (void *)rxd->rx_hdr_status;
-       decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
+       decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
                   RX_MSDU_START_INFO1_DECAP_FORMAT);
 
        switch (decap) {
@@ -1204,7 +1286,7 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
 
        rxd = (void *)skb->data - sizeof(*rxd);
        flags = __le32_to_cpu(rxd->attention.flags);
-       info = __le32_to_cpu(rxd->msdu_start.info1);
+       info = __le32_to_cpu(rxd->msdu_start.common.info1);
 
        is_ip4 = !!(info & RX_MSDU_START_INFO1_IPV4_PROTO);
        is_ip6 = !!(info & RX_MSDU_START_INFO1_IPV6_PROTO);
@@ -1397,7 +1479,7 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
 
        first = skb_peek(amsdu);
        rxd = (void *)first->data - sizeof(*rxd);
-       decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
+       decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
                   RX_MSDU_START_INFO1_DECAP_FORMAT);
 
        if (!chained)
@@ -1522,7 +1604,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
                        break;
                }
 
-               ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
+               ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
                ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
                ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
                ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
@@ -1569,7 +1651,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
                return;
        }
 
-       ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
+       ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
        ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
        ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
        ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
@@ -1591,13 +1673,12 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
        __le16 msdu_id;
        int i;
 
-       lockdep_assert_held(&htt->tx_lock);
-
        switch (status) {
        case HTT_DATA_TX_STATUS_NO_ACK:
                tx_done.no_ack = true;
                break;
        case HTT_DATA_TX_STATUS_OK:
+               tx_done.success = true;
                break;
        case HTT_DATA_TX_STATUS_DISCARD:
        case HTT_DATA_TX_STATUS_POSTPONE:
@@ -1716,14 +1797,14 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
                __skb_queue_tail(amsdu, msdu);
 
                rxd = (void *)msdu->data - sizeof(*rxd);
-               if (rxd->msdu_end.info0 &
+               if (rxd->msdu_end.common.info0 &
                    __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))
                        break;
        }
 
        msdu = skb_peek_tail(amsdu);
        rxd = (void *)msdu->data - sizeof(*rxd);
-       if (!(rxd->msdu_end.info0 &
+       if (!(rxd->msdu_end.common.info0 &
              __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) {
                skb_queue_splice_init(amsdu, list);
                return -EAGAIN;
@@ -1796,7 +1877,7 @@ static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
                status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
                ath10k_htt_rx_h_rx_offload_prot(status, msdu);
-               ath10k_htt_rx_h_channel(ar, status);
+               ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id);
                ath10k_process_rx(ar, status, msdu);
        }
 }
@@ -1869,7 +1950,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
                         * better to report something than nothing though. This
                         * should still give an idea about rx rate to the user.
                         */
-                       ath10k_htt_rx_h_ppdu(ar, &amsdu, status);
+                       ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
                        ath10k_htt_rx_h_filter(ar, &amsdu, status);
                        ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
                        ath10k_htt_rx_h_deliver(ar, &amsdu, status);
@@ -1892,6 +1973,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ath10k_htt *htt = &ar->htt;
        struct htt_resp *resp = (struct htt_resp *)skb->data;
+       enum htt_t2h_msg_type type;
 
        /* confirm alignment */
        if (!IS_ALIGNED((unsigned long)skb->data, 4))
@@ -1899,7 +1981,16 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 
        ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n",
                   resp->hdr.msg_type);
-       switch (resp->hdr.msg_type) {
+
+       if (resp->hdr.msg_type >= ar->htt.t2h_msg_types_max) {
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, unsupported msg_type: 0x%0X\n max: 0x%0X",
+                          resp->hdr.msg_type, ar->htt.t2h_msg_types_max);
+               dev_kfree_skb_any(skb);
+               return;
+       }
+       type = ar->htt.t2h_msg_types[resp->hdr.msg_type];
+
+       switch (type) {
        case HTT_T2H_MSG_TYPE_VERSION_CONF: {
                htt->target_version_major = resp->ver_resp.major;
                htt->target_version_minor = resp->ver_resp.minor;
@@ -1937,6 +2028,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 
                switch (status) {
                case HTT_MGMT_TX_STATUS_OK:
+                       tx_done.success = true;
                        break;
                case HTT_MGMT_TX_STATUS_RETRY:
                        tx_done.no_ack = true;
@@ -1946,15 +2038,11 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                        break;
                }
 
-               spin_lock_bh(&htt->tx_lock);
                ath10k_txrx_tx_unref(htt, &tx_done);
-               spin_unlock_bh(&htt->tx_lock);
                break;
        }
        case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
-               spin_lock_bh(&htt->tx_lock);
-               __skb_queue_tail(&htt->tx_compl_q, skb);
-               spin_unlock_bh(&htt->tx_lock);
+               skb_queue_tail(&htt->tx_compl_q, skb);
                tasklet_schedule(&htt->txrx_compl_task);
                return;
        case HTT_T2H_MSG_TYPE_SEC_IND: {
@@ -1976,7 +2064,6 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
        case HTT_T2H_MSG_TYPE_TEST:
-               /* FIX THIS */
                break;
        case HTT_T2H_MSG_TYPE_STATS_CONF:
                trace_ath10k_htt_stats(ar, skb->data, skb->len);
@@ -2018,12 +2105,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                return;
        }
        case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
-               /* FIXME: This WMI-TLV event is overlapping with 10.2
-                * CHAN_CHANGE - both being 0xF. Neither is being used in
-                * practice so no immediate action is necessary. Nevertheless
-                * HTT may need an abstraction layer like WMI has one day.
-                */
                break;
+       case HTT_T2H_MSG_TYPE_CHAN_CHANGE:
+               break;
+       case HTT_T2H_MSG_TYPE_AGGR_CONF:
+               break;
+       case HTT_T2H_MSG_TYPE_EN_STATS:
+       case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
+       case HTT_T2H_MSG_TYPE_TX_FETCH_CONF:
+       case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND:
        default:
                ath10k_warn(ar, "htt event (%d) not handled\n",
                            resp->hdr.msg_type);
@@ -2035,6 +2125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        /* Free the indication buffer */
        dev_kfree_skb_any(skb);
 }
+EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
 
 static void ath10k_htt_txrx_compl_task(unsigned long ptr)
 {
@@ -2043,12 +2134,10 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
        struct htt_resp *resp;
        struct sk_buff *skb;
 
-       spin_lock_bh(&htt->tx_lock);
-       while ((skb = __skb_dequeue(&htt->tx_compl_q))) {
+       while ((skb = skb_dequeue(&htt->tx_compl_q))) {
                ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
                dev_kfree_skb_any(skb);
        }
-       spin_unlock_bh(&htt->tx_lock);
 
        spin_lock_bh(&htt->rx_ring.lock);
        while ((skb = __skb_dequeue(&htt->rx_compl_q))) {