ath10k: start using sk_buff_head
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / htt_rx.c
index 60d40a0..f988a8d 100644 (file)
@@ -291,30 +291,25 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
        htt->rx_ring.sw_rd_idx.msdu_payld = idx;
        htt->rx_ring.fill_cnt--;
 
-       return msdu;
-}
+       dma_unmap_single(htt->ar->dev,
+                        ATH10K_SKB_CB(msdu)->paddr,
+                        msdu->len + skb_tailroom(msdu),
+                        DMA_FROM_DEVICE);
+       ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
+                       msdu->data, msdu->len + skb_tailroom(msdu));
 
-static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
-{
-       struct sk_buff *next;
-
-       while (skb) {
-               next = skb->next;
-               dev_kfree_skb_any(skb);
-               skb = next;
-       }
+       return msdu;
 }
 
 /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                                   u8 **fw_desc, int *fw_desc_len,
-                                  struct sk_buff **head_msdu,
-                                  struct sk_buff **tail_msdu,
+                                  struct sk_buff_head *amsdu,
                                   u32 *attention)
 {
        struct ath10k *ar = htt->ar;
        int msdu_len, msdu_chaining = 0;
-       struct sk_buff *msdu, *next;
+       struct sk_buff *msdu;
        struct htt_rx_desc *rx_desc;
 
        lockdep_assert_held(&htt->rx_ring.lock);
@@ -324,17 +319,18 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                return -1;
        }
 
-       msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt);
-       while (msdu) {
+       for (;;) {
                int last_msdu, msdu_len_invalid, msdu_chained;
 
-               dma_unmap_single(htt->ar->dev,
-                                ATH10K_SKB_CB(msdu)->paddr,
-                                msdu->len + skb_tailroom(msdu),
-                                DMA_FROM_DEVICE);
+               msdu = ath10k_htt_rx_netbuf_pop(htt);
+               if (!msdu) {
+                       ath10k_err(ar, "failed to pop msdu\n");
+                       __skb_queue_purge(amsdu);
+                       htt->rx_confused = true;
+                       break;
+               }
 
-               ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
-                               msdu->data, msdu->len + skb_tailroom(msdu));
+               __skb_queue_tail(amsdu, msdu);
 
                rx_desc = (struct htt_rx_desc *)msdu->data;
 
@@ -353,10 +349,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                 */
                if (!(__le32_to_cpu(rx_desc->attention.flags)
                                & RX_ATTENTION_FLAGS_MSDU_DONE)) {
-                       ath10k_htt_rx_free_msdu_chain(*head_msdu);
-                       *head_msdu = NULL;
-                       msdu = NULL;
-                       ath10k_err(ar, "htt rx stopped. cannot recover\n");
+                       ath10k_err(ar, "popped an incomplete msdu\n");
+                       __skb_queue_purge(amsdu);
                        htt->rx_confused = true;
                        break;
                }
@@ -422,43 +416,34 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
                msdu_len -= msdu->len;
 
-               /* FIXME: Do chained buffers include htt_rx_desc or not? */
+               /* Note: Chained buffers do not contain rx descriptor */
                while (msdu_chained--) {
-                       struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
-
-                       dma_unmap_single(htt->ar->dev,
-                                        ATH10K_SKB_CB(next)->paddr,
-                                        next->len + skb_tailroom(next),
-                                        DMA_FROM_DEVICE);
-
-                       ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
-                                       "htt rx chained: ", next->data,
-                                       next->len + skb_tailroom(next));
-
-                       skb_trim(next, 0);
-                       skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE));
-                       msdu_len -= next->len;
+                       msdu = ath10k_htt_rx_netbuf_pop(htt);
+                       if (!msdu) {
+                               ath10k_warn(ar, "failed to pop chained msdu\n");
+                               __skb_queue_purge(amsdu);
+                               htt->rx_confused = true;
+                               break;
+                       }
 
-                       msdu->next = next;
-                       msdu = next;
+                       __skb_queue_tail(amsdu, msdu);
+                       skb_trim(msdu, 0);
+                       skb_put(msdu, min(msdu_len, HTT_RX_BUF_SIZE));
+                       msdu_len -= msdu->len;
                        msdu_chaining = 1;
                }
 
                last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
                                RX_MSDU_END_INFO0_LAST_MSDU;
 
-               if (last_msdu) {
-                       msdu->next = NULL;
-                       break;
-               }
+               trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
+                                        sizeof(*rx_desc) - sizeof(u32));
 
-               next = ath10k_htt_rx_netbuf_pop(htt);
-               msdu->next = next;
-               msdu = next;
+               if (last_msdu)
+                       break;
        }
-       *tail_msdu = msdu;
 
-       if (*head_msdu == NULL)
+       if (skb_queue_empty(amsdu))
                msdu_chaining = -1;
 
        /*
@@ -492,6 +477,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
        size_t size;
        struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
 
+       htt->rx_confused = false;
+
        htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
        if (!is_power_of_2(htt->rx_ring.size)) {
                ath10k_warn(ar, "htt rx ring size is not power of 2\n");
@@ -581,41 +568,47 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
                                          enum htt_rx_mpdu_encrypt_type type)
 {
        switch (type) {
+       case HTT_RX_MPDU_ENCRYPT_NONE:
+               return 0;
        case HTT_RX_MPDU_ENCRYPT_WEP40:
        case HTT_RX_MPDU_ENCRYPT_WEP104:
-               return 4;
+               return IEEE80211_WEP_IV_LEN;
        case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
-       case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */
        case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-       case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */
+               return IEEE80211_TKIP_IV_LEN;
        case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-               return 8;
-       case HTT_RX_MPDU_ENCRYPT_NONE:
-               return 0;
+               return IEEE80211_CCMP_HDR_LEN;
+       case HTT_RX_MPDU_ENCRYPT_WEP128:
+       case HTT_RX_MPDU_ENCRYPT_WAPI:
+               break;
        }
 
-       ath10k_warn(ar, "unknown encryption type %d\n", type);
+       ath10k_warn(ar, "unsupported encryption type %d\n", type);
        return 0;
 }
 
+#define MICHAEL_MIC_LEN 8
+
 static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
                                         enum htt_rx_mpdu_encrypt_type type)
 {
        switch (type) {
        case HTT_RX_MPDU_ENCRYPT_NONE:
+               return 0;
        case HTT_RX_MPDU_ENCRYPT_WEP40:
        case HTT_RX_MPDU_ENCRYPT_WEP104:
-       case HTT_RX_MPDU_ENCRYPT_WEP128:
-       case HTT_RX_MPDU_ENCRYPT_WAPI:
-               return 0;
+               return IEEE80211_WEP_ICV_LEN;
        case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
        case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-               return 4;
+               return IEEE80211_TKIP_ICV_LEN;
        case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-               return 8;
+               return IEEE80211_CCMP_MIC_LEN;
+       case HTT_RX_MPDU_ENCRYPT_WEP128:
+       case HTT_RX_MPDU_ENCRYPT_WAPI:
+               break;
        }
 
-       ath10k_warn(ar, "unknown encryption type %d\n", type);
+       ath10k_warn(ar, "unsupported encryption type %d\n", type);
        return 0;
 }
 
@@ -892,6 +885,8 @@ static void ath10k_process_rx(struct ath10k *ar,
                   !!(status->flag & RX_FLAG_AMSDU_MORE));
        ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
                        skb->data, skb->len);
+       trace_ath10k_rx_hdr(ar, skb->data, skb->len);
+       trace_ath10k_rx_payload(ar, skb->data, skb->len);
 
        ieee80211_rx(ar->hw, skb);
 }
@@ -904,11 +899,11 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr)
 
 static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                                struct ieee80211_rx_status *rx_status,
-                               struct sk_buff *skb_in)
+                               struct sk_buff_head *amsdu)
 {
        struct ath10k *ar = htt->ar;
        struct htt_rx_desc *rxd;
-       struct sk_buff *skb = skb_in;
+       struct sk_buff *skb;
        struct sk_buff *first;
        enum rx_msdu_decap_format fmt;
        enum htt_rx_mpdu_encrypt_type enctype;
@@ -916,7 +911,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
        unsigned int hdr_len;
 
-       rxd = (void *)skb->data - sizeof(*rxd);
+       first = skb_peek(amsdu);
+
+       rxd = (void *)first->data - sizeof(*rxd);
        enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
                     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 
@@ -925,8 +922,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        memcpy(hdr_buf, hdr, hdr_len);
        hdr = (struct ieee80211_hdr *)hdr_buf;
 
-       first = skb;
-       while (skb) {
+       while ((skb = __skb_dequeue(amsdu))) {
                void *decap_hdr;
                int len;
 
@@ -994,18 +990,15 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                        break;
                }
 
-               skb_in = skb;
-               ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
+               ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype, fmt,
                                          false);
-               skb = skb->next;
-               skb_in->next = NULL;
 
-               if (skb)
-                       rx_status->flag |= RX_FLAG_AMSDU_MORE;
-               else
+               if (skb_queue_empty(amsdu))
                        rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
+               else
+                       rx_status->flag |= RX_FLAG_AMSDU_MORE;
 
-               ath10k_process_rx(htt->ar, rx_status, skb_in);
+               ath10k_process_rx(htt->ar, rx_status, skb);
        }
 
        /* FIXME: It might be nice to re-assemble the A-MSDU when there's a
@@ -1024,13 +1017,6 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
        int hdr_len;
        void *rfc1042;
 
-       /* This shouldn't happen. If it does than it may be a FW bug. */
-       if (skb->next) {
-               ath10k_warn(ar, "htt rx received chained non A-MSDU frame\n");
-               ath10k_htt_rx_free_msdu_chain(skb->next);
-               skb->next = NULL;
-       }
-
        rxd = (void *)skb->data - sizeof(*rxd);
        fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
                 RX_MSDU_START_INFO1_DECAP_FORMAT);
@@ -1116,10 +1102,9 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
        return CHECKSUM_UNNECESSARY;
 }
 
-static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
+static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
 {
-       struct sk_buff *next = msdu_head->next;
-       struct sk_buff *to_free = next;
+       struct sk_buff *skb, *first;
        int space;
        int total_len = 0;
 
@@ -1130,46 +1115,38 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
         * skb?
         */
 
-       msdu_head->next = NULL;
+       first = __skb_dequeue(amsdu);
 
        /* Allocate total length all at once. */
-       while (next) {
-               total_len += next->len;
-               next = next->next;
-       }
+       skb_queue_walk(amsdu, skb)
+               total_len += skb->len;
 
-       space = total_len - skb_tailroom(msdu_head);
+       space = total_len - skb_tailroom(first);
        if ((space > 0) &&
-           (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) {
+           (pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
                /* TODO:  bump some rx-oom error stat */
                /* put it back together so we can free the
                 * whole list at once.
                 */
-               msdu_head->next = to_free;
+               __skb_queue_head(amsdu, first);
                return -1;
        }
 
        /* Walk list again, copying contents into
         * msdu_head
         */
-       next = to_free;
-       while (next) {
-               skb_copy_from_linear_data(next, skb_put(msdu_head, next->len),
-                                         next->len);
-               next = next->next;
+       while ((skb = __skb_dequeue(amsdu))) {
+               skb_copy_from_linear_data(skb, skb_put(first, skb->len),
+                                         skb->len);
+               dev_kfree_skb_any(skb);
        }
 
-       /* If here, we have consolidated skb.  Free the
-        * fragments and pass the main skb on up the
-        * stack.
-        */
-       ath10k_htt_rx_free_msdu_chain(to_free);
+       __skb_queue_head(amsdu, first);
        return 0;
 }
 
 static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
                                        struct sk_buff *head,
-                                       enum htt_rx_mpdu_status status,
                                        bool channel_set,
                                        u32 attention)
 {
@@ -1193,22 +1170,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
        }
 
        /* Skip mgmt frames while we handle this in WMI */
-       if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
-           attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
+       if (attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
                ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
                return false;
        }
 
-       if (status != HTT_RX_IND_MPDU_STATUS_OK &&
-           status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
-           status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
-           !htt->ar->monitor_started) {
-               ath10k_dbg(ar, ATH10K_DBG_HTT,
-                          "htt rx ignoring frame w/ status %d\n",
-                          status);
-               return false;
-       }
-
        if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
                ath10k_dbg(ar, ATH10K_DBG_HTT,
                           "htt rx CAC running\n");
@@ -1224,8 +1190,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
        struct ath10k *ar = htt->ar;
        struct ieee80211_rx_status *rx_status = &htt->rx_status;
        struct htt_rx_indication_mpdu_range *mpdu_ranges;
-       struct htt_rx_desc *rxd;
-       enum htt_rx_mpdu_status status;
+       struct sk_buff_head amsdu;
        struct ieee80211_hdr *hdr;
        int num_mpdu_ranges;
        u32 attention;
@@ -1273,43 +1238,29 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
                                num_mpdu_ranges));
 
        for (i = 0; i < num_mpdu_ranges; i++) {
-               status = mpdu_ranges[i].mpdu_range_status;
-
                for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
-                       struct sk_buff *msdu_head, *msdu_tail;
-
                        attention = 0;
-                       msdu_head = NULL;
-                       msdu_tail = NULL;
-                       ret = ath10k_htt_rx_amsdu_pop(htt,
-                                                     &fw_desc,
-                                                     &fw_desc_len,
-                                                     &msdu_head,
-                                                     &msdu_tail,
+                       __skb_queue_head_init(&amsdu);
+                       ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
+                                                     &fw_desc_len, &amsdu,
                                                      &attention);
 
                        if (ret < 0) {
                                ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n",
                                            ret);
-                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                               __skb_queue_purge(&amsdu);
                                continue;
                        }
 
-                       rxd = container_of((void *)msdu_head->data,
-                                          struct htt_rx_desc,
-                                          msdu_payload);
-
-                       if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
-                                                        status,
+                       if (!ath10k_htt_rx_amsdu_allowed(htt, skb_peek(&amsdu),
                                                         channel_set,
                                                         attention)) {
-                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                               __skb_queue_purge(&amsdu);
                                continue;
                        }
 
-                       if (ret > 0 &&
-                           ath10k_unchain_msdu(msdu_head) < 0) {
-                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                       if (ret > 0 && ath10k_unchain_msdu(&amsdu) < 0) {
+                               __skb_queue_purge(&amsdu);
                                continue;
                        }
 
@@ -1323,12 +1274,13 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
                        else
                                rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
 
-                       hdr = ath10k_htt_rx_skb_get_hdr(msdu_head);
+                       hdr = ath10k_htt_rx_skb_get_hdr(skb_peek(&amsdu));
 
                        if (ath10k_htt_rx_hdr_is_amsdu(hdr))
-                               ath10k_htt_rx_amsdu(htt, rx_status, msdu_head);
+                               ath10k_htt_rx_amsdu(htt, rx_status, &amsdu);
                        else
-                               ath10k_htt_rx_msdu(htt, rx_status, msdu_head);
+                               ath10k_htt_rx_msdu(htt, rx_status,
+                                                  __skb_dequeue(&amsdu));
                }
        }
 
@@ -1339,12 +1291,13 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
                                       struct htt_rx_fragment_indication *frag)
 {
        struct ath10k *ar = htt->ar;
-       struct sk_buff *msdu_head, *msdu_tail;
+       struct sk_buff *msdu;
        enum htt_rx_mpdu_encrypt_type enctype;
        struct htt_rx_desc *rxd;
        enum rx_msdu_decap_format fmt;
        struct ieee80211_rx_status *rx_status = &htt->rx_status;
        struct ieee80211_hdr *hdr;
+       struct sk_buff_head amsdu;
        int ret;
        bool tkip_mic_err;
        bool decrypt_err;
@@ -1356,29 +1309,37 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
        fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
        fw_desc = (u8 *)frag->fw_msdu_rx_desc;
 
-       msdu_head = NULL;
-       msdu_tail = NULL;
+       __skb_queue_head_init(&amsdu);
 
        spin_lock_bh(&htt->rx_ring.lock);
        ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-                                     &msdu_head, &msdu_tail,
-                                     &attention);
+                                     &amsdu, &attention);
        spin_unlock_bh(&htt->rx_ring.lock);
 
+       tasklet_schedule(&htt->rx_replenish_task);
+
        ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
 
        if (ret) {
                ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
                            ret);
-               ath10k_htt_rx_free_msdu_chain(msdu_head);
+               __skb_queue_purge(&amsdu);
+               return;
+       }
+
+       if (skb_queue_len(&amsdu) != 1) {
+               ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
+               __skb_queue_purge(&amsdu);
                return;
        }
 
+       msdu = __skb_dequeue(&amsdu);
+
        /* FIXME: implement signal strength */
        rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
-       hdr = (struct ieee80211_hdr *)msdu_head->data;
-       rxd = (void *)msdu_head->data - sizeof(*rxd);
+       hdr = (struct ieee80211_hdr *)msdu->data;
+       rxd = (void *)msdu->data - sizeof(*rxd);
        tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
        decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
        fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
@@ -1386,22 +1347,22 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 
        if (fmt != RX_MSDU_DECAP_RAW) {
                ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
-               dev_kfree_skb_any(msdu_head);
+               dev_kfree_skb_any(msdu);
                goto end;
        }
 
        enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
                     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-       ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype, fmt,
+       ath10k_htt_rx_h_protected(htt, rx_status, msdu, enctype, fmt,
                                  true);
-       msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
+       msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
 
        if (tkip_mic_err)
                ath10k_warn(ar, "tkip mic error\n");
 
        if (decrypt_err) {
                ath10k_warn(ar, "decryption err in fragmented rx\n");
-               dev_kfree_skb_any(msdu_head);
+               dev_kfree_skb_any(msdu);
                goto end;
        }
 
@@ -1410,11 +1371,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
                paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype);
 
                /* It is more efficient to move the header than the payload */
-               memmove((void *)msdu_head->data + paramlen,
-                       (void *)msdu_head->data,
+               memmove((void *)msdu->data + paramlen,
+                       (void *)msdu->data,
                        hdrlen);
-               skb_pull(msdu_head, paramlen);
-               hdr = (struct ieee80211_hdr *)msdu_head->data;
+               skb_pull(msdu, paramlen);
+               hdr = (struct ieee80211_hdr *)msdu->data;
        }
 
        /* remove trailing FCS */
@@ -1426,19 +1387,19 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
        /* last fragment of TKIP frags has MIC */
        if (!ieee80211_has_morefrags(hdr->frame_control) &&
            enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
-               trim += 8;
+               trim += MICHAEL_MIC_LEN;
 
-       if (trim > msdu_head->len) {
+       if (trim > msdu->len) {
                ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
-               dev_kfree_skb_any(msdu_head);
+               dev_kfree_skb_any(msdu);
                goto end;
        }
 
-       skb_trim(msdu_head, msdu_head->len - trim);
+       skb_trim(msdu, msdu->len - trim);
 
        ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
-                       msdu_head->data, msdu_head->len);
-       ath10k_process_rx(htt->ar, rx_status, msdu_head);
+                       msdu->data, msdu->len);
+       ath10k_process_rx(htt->ar, rx_status, msdu);
 
 end:
        if (fw_desc_len > 0) {
@@ -1674,6 +1635,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        case HTT_T2H_MSG_TYPE_RX_DELBA:
                ath10k_htt_rx_delba(ar, resp);
                break;
+       case HTT_T2H_MSG_TYPE_PKTLOG: {
+               struct ath10k_pktlog_hdr *hdr =
+                       (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
+
+               trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
+                                       sizeof(*hdr) +
+                                       __le16_to_cpu(hdr->size));
+               break;
+       }
        case HTT_T2H_MSG_TYPE_RX_FLUSH: {
                /* Ignore this event because mac80211 takes care of Rx
                 * aggregation reordering.
@@ -1681,8 +1651,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
        default:
-               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n",
-                          resp->hdr.msg_type);
+               ath10k_warn(ar, "htt event (%d) not handled\n",
+                           resp->hdr.msg_type);
                ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
                                skb->data, skb->len);
                break;