ath10k: prevent txrx running for too long
[deliverable/linux.git] / drivers / net / wireless / ath / ath10k / htt_rx.c
index 6060dda4e9101ac73c92cafb597c1d71592bb00e..3079434b5d9bc5bbcd78cc9962bb23a1da0205a3 100644 (file)
@@ -536,7 +536,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
        size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
 
-       vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
+       vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
        if (!vaddr)
                goto err_dma_ring;
 
@@ -545,7 +545,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
        vaddr = dma_alloc_coherent(htt->ar->dev,
                                   sizeof(*htt->rx_ring.alloc_idx.vaddr),
-                                  &paddr, GFP_DMA);
+                                  &paddr, GFP_KERNEL);
        if (!vaddr)
                goto err_dma_idx;
 
@@ -674,7 +674,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
                rate &= ~RX_PPDU_START_RATE_FLAG;
 
                sband = &ar->mac.sbands[status->band];
-               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
+               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate, cck);
                break;
        case HTT_RX_HT:
        case HTT_RX_HT_WITH_TXBF:
@@ -1114,7 +1114,20 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
         */
 
        /* pull decapped header and copy SA & DA */
-       hdr = (struct ieee80211_hdr *)msdu->data;
+       if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
+           ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
+               /* The QCA99X0 4 address mode pad 2 bytes at the
+                * beginning of MSDU
+                */
+               hdr = (struct ieee80211_hdr *)(msdu->data + 2);
+               /* The skb length need be extended 2 as the 2 bytes at the tail
+                * be excluded due to the padding
+                */
+               skb_put(msdu, 2);
+       } else {
+               hdr = (struct ieee80211_hdr *)(msdu->data);
+       }
+
        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));
@@ -2127,14 +2140,34 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
 
+void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
+                                            struct sk_buff *skb)
+{
+       struct ath10k_pktlog_10_4_hdr *hdr =
+               (struct ath10k_pktlog_10_4_hdr *)skb->data;
+
+       trace_ath10k_htt_pktlog(ar, hdr->payload,
+                               sizeof(*hdr) + __le16_to_cpu(hdr->size));
+       dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
+
 static void ath10k_htt_txrx_compl_task(unsigned long ptr)
 {
        struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
        struct ath10k *ar = htt->ar;
+       struct sk_buff_head tx_q;
        struct htt_resp *resp;
        struct sk_buff *skb;
+       unsigned long flags;
+
+       __skb_queue_head_init(&tx_q);
+
+       spin_lock_irqsave(&htt->tx_compl_q.lock, flags);
+       skb_queue_splice_init(&htt->tx_compl_q, &tx_q);
+       spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags);
 
-       while ((skb = skb_dequeue(&htt->tx_compl_q))) {
+       while ((skb = __skb_dequeue(&tx_q))) {
                ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
                dev_kfree_skb_any(skb);
        }
This page took 0.038203 seconds and 5 git commands to generate.