]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Move Rx error related functions to wifi7 directory
authorPavankumar Nandeshwar <quic_pnandesh@quicinc.com>
Thu, 28 Aug 2025 17:35:38 +0000 (23:05 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Wed, 3 Sep 2025 17:06:58 +0000 (10:06 -0700)
Move wifi7 architecture specific Rx error functions from dp_rx.c to
wifi7 directory.

The new wifi7-specific dp_rx.c file will continue to be part of ath12k.ko
temporarily until the corresponding infra for movement to the
ath12k_wifi7.ko arrives in upcoming patches.

Move following architecture specific APIs to wifi7 directory:

ath12k_dp_rx_h_tkip_mic_err
ath12k_dp_rx_h_rxdma_err
ath12k_dp_rx_h_reo_err
ath12k_dp_rx_wbm_err
ath12k_dp_rx_process_wbm_err

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Pavankumar Nandeshwar <quic_pnandesh@quicinc.com>
Signed-off-by: Ripan Deuri <quic_rdeuri@quicinc.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20250828173553.3341351-6-quic_rdeuri@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/Makefile
drivers/net/wireless/ath/ath12k/dp.c
drivers/net/wireless/ath/ath12k/dp_mon.c
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/dp_rx.h
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c [new file with mode: 0644]
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h [new file with mode: 0644]

index b34cf83a24eb12da51b2c23f22e9bd398a22ac3a..d7628bb7af029470f61ce31eede31e939ed9dc65 100644 (file)
@@ -24,6 +24,7 @@ ath12k-$(CONFIG_ATH12K_AHB) += ahb.o
 
 ath12k-y += wifi7/hal_tx.o \
            wifi7/hal_rx.o \
+           wifi7/dp_rx.o
 
 obj-$(CONFIG_ATH12K) += wifi7/
 
index a3170e02d4c72ba954b1f97386f05539361ee78f..1b4fab3073b09ea5b3613e410acf7810b5243593 100644 (file)
@@ -10,7 +10,7 @@
 #include "wifi7/hal_tx.h"
 #include "hif.h"
 #include "debug.h"
-#include "dp_rx.h"
+#include "wifi7/dp_rx.h"
 #include "peer.h"
 #include "dp_mon.h"
 
index 8189e52ed00718995572ba1e1c3cc26756846d20..b0a0e2a97e8fd443fa243a9f9357935dd3df11cc 100644 (file)
@@ -1,12 +1,12 @@
 // SPDX-License-Identifier: BSD-3-Clause-Clear
 /*
  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 
 #include "dp_mon.h"
 #include "debug.h"
-#include "dp_rx.h"
+#include "wifi7/dp_rx.h"
 #include "dp_tx.h"
 #include "peer.h"
 
index acd20417b6508fc6dec2811f0ec69456bb0c8700..453310080182cc995ab161a5ba620bba458b534d 100644 (file)
@@ -2033,11 +2033,11 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar,
        ether_addr_copy(ieee80211_get_SA(hdr), sa);
 }
 
-static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
-                                  struct hal_rx_desc *rx_desc,
-                                  enum hal_encrypt_type enctype,
-                                  struct ieee80211_rx_status *status,
-                                  bool decrypted)
+void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
+                           struct hal_rx_desc *rx_desc,
+                           enum hal_encrypt_type enctype,
+                           struct ieee80211_rx_status *status,
+                           bool decrypted)
 {
        struct ath12k_base *ab = ar->ab;
        u8 decap;
@@ -2323,9 +2323,9 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
        ath12k_dp_rx_h_rate(ar, rx_info);
 }
 
-static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
-                                     struct sk_buff *msdu,
-                                     struct ath12k_dp_rx_info *rx_info)
+void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
+                              struct sk_buff *msdu,
+                              struct ath12k_dp_rx_info *rx_info)
 {
        struct ath12k_base *ab = ar->ab;
        struct ieee80211_rx_status *rx_status;
@@ -2395,9 +2395,9 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
        ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
 }
 
-static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
-                                                  struct hal_rx_desc *rx_desc,
-                                                  struct sk_buff *msdu)
+bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
+                                           struct hal_rx_desc *rx_desc,
+                                           struct sk_buff *msdu)
 {
        struct ieee80211_hdr *hdr;
        u8 decap_type;
@@ -3584,9 +3584,9 @@ static void ath12k_dp_rx_null_q_desc_sg_drop(struct ath12k *ar,
        }
 }
 
-static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
-                                     struct ath12k_dp_rx_info *rx_info,
-                                     struct sk_buff_head *msdu_list)
+int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
+                              struct ath12k_dp_rx_info *rx_info,
+                              struct sk_buff_head *msdu_list)
 {
        struct ath12k_base *ab = ar->ab;
        u16 msdu_len;
@@ -3654,348 +3654,6 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
        return 0;
 }
 
-static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
-                                  struct ath12k_dp_rx_info *rx_info,
-                                  struct sk_buff_head *msdu_list)
-{
-       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
-       bool drop = false;
-
-       ar->ab->device_stats.reo_error[rxcb->err_code]++;
-
-       switch (rxcb->err_code) {
-       case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
-               if (ath12k_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list))
-                       drop = true;
-               break;
-       case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
-               /* TODO: Do not drop PN failed packets in the driver;
-                * instead, it is good to drop such packets in mac80211
-                * after incrementing the replay counters.
-                */
-               fallthrough;
-       default:
-               /* TODO: Review other errors and process them to mac80211
-                * as appropriate.
-                */
-               drop = true;
-               break;
-       }
-
-       return drop;
-}
-
-static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
-                                       struct ath12k_dp_rx_info *rx_info)
-{
-       struct ath12k_base *ab = ar->ab;
-       u16 msdu_len;
-       struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
-       u8 l3pad_bytes;
-       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
-       u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
-
-       rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, desc);
-       rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, desc);
-
-       l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
-       msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
-
-       if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
-               ath12k_dbg(ab, ATH12K_DBG_DATA,
-                          "invalid msdu len in tkip mic err %u\n", msdu_len);
-               ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
-                               sizeof(*desc));
-               return true;
-       }
-
-       skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
-       skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
-
-       if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
-               return true;
-
-       ath12k_dp_rx_h_ppdu(ar, rx_info);
-
-       rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
-                                    RX_FLAG_DECRYPTED);
-
-       ath12k_dp_rx_h_undecap(ar, msdu, desc,
-                              HAL_ENCRYPT_TYPE_TKIP_MIC, rx_info->rx_status, false);
-       return false;
-}
-
-static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar,  struct sk_buff *msdu,
-                                    struct ath12k_dp_rx_info *rx_info)
-{
-       struct ath12k_base *ab = ar->ab;
-       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
-       struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
-       bool drop = false;
-       u32 err_bitmap;
-
-       ar->ab->device_stats.rxdma_error[rxcb->err_code]++;
-
-       switch (rxcb->err_code) {
-       case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
-       case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
-               err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
-               if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
-                       ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
-                       drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info);
-                       break;
-               }
-               fallthrough;
-       default:
-               /* TODO: Review other rxdma error code to check if anything is
-                * worth reporting to mac80211
-                */
-               drop = true;
-               break;
-       }
-
-       return drop;
-}
-
-static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
-                                struct napi_struct *napi,
-                                struct sk_buff *msdu,
-                                struct sk_buff_head *msdu_list)
-{
-       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
-       struct ieee80211_rx_status rxs = {};
-       struct ath12k_dp_rx_info rx_info;
-       bool drop = true;
-
-       rx_info.addr2_present = false;
-       rx_info.rx_status = &rxs;
-
-       switch (rxcb->err_rel_src) {
-       case HAL_WBM_REL_SRC_MODULE_REO:
-               drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list);
-               break;
-       case HAL_WBM_REL_SRC_MODULE_RXDMA:
-               drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rx_info);
-               break;
-       default:
-               /* msdu will get freed */
-               break;
-       }
-
-       if (drop) {
-               dev_kfree_skb_any(msdu);
-               return;
-       }
-
-       rx_info.rx_status->flag |= RX_FLAG_SKIP_MONITOR;
-
-       ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
-}
-
-int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
-                                struct napi_struct *napi, int budget)
-{
-       struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
-       struct ath12k_hw_group *ag = ab->ag;
-       struct ath12k *ar;
-       struct ath12k_dp *dp = &ab->dp;
-       struct dp_rxdma_ring *rx_ring;
-       struct hal_rx_wbm_rel_info err_info;
-       struct hal_srng *srng;
-       struct sk_buff *msdu;
-       struct sk_buff_head msdu_list, scatter_msdu_list;
-       struct ath12k_skb_rxcb *rxcb;
-       void *rx_desc;
-       int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
-       int total_num_buffs_reaped = 0;
-       struct ath12k_rx_desc_info *desc_info;
-       struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
-       struct ath12k_hw_link *hw_links = ag->hw_links;
-       struct ath12k_base *partner_ab;
-       u8 hw_link_id, device_id;
-       int ret, pdev_id;
-       struct hal_rx_desc *msdu_data;
-
-       __skb_queue_head_init(&msdu_list);
-       __skb_queue_head_init(&scatter_msdu_list);
-
-       for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
-               INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
-
-       srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
-       spin_lock_bh(&srng->lock);
-
-       ath12k_hal_srng_access_begin(ab, srng);
-
-       while (budget) {
-               rx_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng);
-               if (!rx_desc)
-                       break;
-
-               ret = ath12k_hal_wbm_desc_parse_err(ab, rx_desc, &err_info);
-               if (ret) {
-                       ath12k_warn(ab,
-                                   "failed to parse rx error in wbm_rel ring desc %d\n",
-                                   ret);
-                       continue;
-               }
-
-               desc_info = err_info.rx_desc;
-
-               /* retry manual desc retrieval if hw cc is not done */
-               if (!desc_info) {
-                       desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie);
-                       if (!desc_info) {
-                               ath12k_warn(ab, "Invalid cookie in DP WBM rx error descriptor retrieval: 0x%x\n",
-                                           err_info.cookie);
-                               continue;
-                       }
-               }
-
-               if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
-                       ath12k_warn(ab, "WBM RX err, Check HW CC implementation");
-
-               msdu = desc_info->skb;
-               desc_info->skb = NULL;
-
-               device_id = desc_info->device_id;
-               partner_ab = ath12k_ag_to_ab(ag, device_id);
-               if (unlikely(!partner_ab)) {
-                       dev_kfree_skb_any(msdu);
-
-                       /* In any case continuation bit is set
-                        * in the previous record, cleanup scatter_msdu_list
-                        */
-                       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
-                       continue;
-               }
-
-               list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
-
-               rxcb = ATH12K_SKB_RXCB(msdu);
-               dma_unmap_single(partner_ab->dev, rxcb->paddr,
-                                msdu->len + skb_tailroom(msdu),
-                                DMA_FROM_DEVICE);
-
-               num_buffs_reaped[device_id]++;
-               total_num_buffs_reaped++;
-
-               if (!err_info.continuation)
-                       budget--;
-
-               if (err_info.push_reason !=
-                   HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
-                       dev_kfree_skb_any(msdu);
-                       continue;
-               }
-
-               msdu_data = (struct hal_rx_desc *)msdu->data;
-               rxcb->err_rel_src = err_info.err_rel_src;
-               rxcb->err_code = err_info.err_code;
-               rxcb->is_first_msdu = err_info.first_msdu;
-               rxcb->is_last_msdu = err_info.last_msdu;
-               rxcb->is_continuation = err_info.continuation;
-               rxcb->rx_desc = msdu_data;
-
-               if (err_info.continuation) {
-                       __skb_queue_tail(&scatter_msdu_list, msdu);
-                       continue;
-               }
-
-               hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_ab,
-                                                           msdu_data);
-               if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
-                       dev_kfree_skb_any(msdu);
-
-                       /* In any case continuation bit is set
-                        * in the previous record, cleanup scatter_msdu_list
-                        */
-                       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
-                       continue;
-               }
-
-               if (!skb_queue_empty(&scatter_msdu_list)) {
-                       struct sk_buff *msdu;
-
-                       skb_queue_walk(&scatter_msdu_list, msdu) {
-                               rxcb = ATH12K_SKB_RXCB(msdu);
-                               rxcb->hw_link_id = hw_link_id;
-                       }
-
-                       skb_queue_splice_tail_init(&scatter_msdu_list,
-                                                  &msdu_list);
-               }
-
-               rxcb = ATH12K_SKB_RXCB(msdu);
-               rxcb->hw_link_id = hw_link_id;
-               __skb_queue_tail(&msdu_list, msdu);
-       }
-
-       /* In any case continuation bit is set in the
-        * last record, cleanup scatter_msdu_list
-        */
-       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
-
-       ath12k_hal_srng_access_end(ab, srng);
-
-       spin_unlock_bh(&srng->lock);
-
-       if (!total_num_buffs_reaped)
-               goto done;
-
-       for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
-               if (!num_buffs_reaped[device_id])
-                       continue;
-
-               partner_ab = ath12k_ag_to_ab(ag, device_id);
-               rx_ring = &partner_ab->dp.rx_refill_buf_ring;
-
-               ath12k_dp_rx_bufs_replenish(ab, rx_ring,
-                                           &rx_desc_used_list[device_id],
-                                           num_buffs_reaped[device_id]);
-       }
-
-       rcu_read_lock();
-       while ((msdu = __skb_dequeue(&msdu_list))) {
-               rxcb = ATH12K_SKB_RXCB(msdu);
-               hw_link_id = rxcb->hw_link_id;
-
-               device_id = hw_links[hw_link_id].device_id;
-               partner_ab = ath12k_ag_to_ab(ag, device_id);
-               if (unlikely(!partner_ab)) {
-                       ath12k_dbg(ab, ATH12K_DBG_DATA,
-                                  "Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
-                                  hw_link_id, device_id);
-                       dev_kfree_skb_any(msdu);
-                       continue;
-               }
-
-               pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
-                                                     hw_links[hw_link_id].pdev_idx);
-               ar = partner_ab->pdevs[pdev_id].ar;
-
-               if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_id])) {
-                       dev_kfree_skb_any(msdu);
-                       continue;
-               }
-
-               if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
-                       dev_kfree_skb_any(msdu);
-                       continue;
-               }
-
-               if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) {
-                       device_id = ar->ab->device_id;
-                       device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
-               }
-
-               ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
-       }
-       rcu_read_unlock();
-done:
-       return total_num_buffs_reaped;
-}
-
 void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab)
 {
        struct ath12k_dp *dp = &ab->dp;
index 61861c63ecbf78366e1388a450059fe75a2cee55..1909f9070d46380a830c45c95ec9c56e43d37a2b 100644 (file)
@@ -340,6 +340,20 @@ static inline void ath12k_dp_clean_up_skb_list(struct sk_buff_head *skb_list)
                dev_kfree_skb_any(skb);
 }
 
+void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
+                           struct hal_rx_desc *rx_desc,
+                           enum hal_encrypt_type enctype,
+                           struct ieee80211_rx_status *status,
+                           bool decrypted);
+void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
+                              struct sk_buff *msdu,
+                              struct ath12k_dp_rx_info *rx_info);
+bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
+                                           struct hal_rx_desc *rx_desc,
+                                           struct sk_buff *msdu);
+int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
+                              struct ath12k_dp_rx_info *rx_info,
+                              struct sk_buff_head *msdu_list);
 int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
                             struct ieee80211_ampdu_params *params,
                             u8 link_id);
@@ -367,8 +381,6 @@ int ath12k_dp_rx_pdev_alloc(struct ath12k_base *ab, int pdev_idx);
 void ath12k_dp_rx_pdev_free(struct ath12k_base *ab, int pdev_idx);
 void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab);
 void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab);
-int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
-                                struct napi_struct *napi, int budget);
 int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
                             int budget);
 int ath12k_dp_rx_process(struct ath12k_base *ab, int mac_id,
@@ -390,7 +402,6 @@ u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab,
                             struct hal_rx_desc *desc);
 u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
                            struct hal_rx_desc *desc);
-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info);
 int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
 int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
 
@@ -411,4 +422,5 @@ int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
                                  enum hal_wbm_rel_bm_act action);
 bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
                                 struct hal_rx_desc *rx_desc);
+void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info);
 #endif /* ATH12K_DP_RX_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
new file mode 100644 (file)
index 0000000..26539a4
--- /dev/null
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "dp_rx.h"
+#include "../dp_tx.h"
+
+static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+                                       struct ath12k_dp_rx_info *rx_info)
+{
+       struct ath12k_base *ab = ar->ab;
+       u16 msdu_len;
+       struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
+       u8 l3pad_bytes;
+       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+       u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+
+       rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, desc);
+       rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, desc);
+
+       l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
+       msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
+
+       if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
+               ath12k_dbg(ab, ATH12K_DBG_DATA,
+                          "invalid msdu len in tkip mic err %u\n", msdu_len);
+               ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
+                               sizeof(*desc));
+               return true;
+       }
+
+       skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
+       skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+
+       if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
+               return true;
+
+       ath12k_dp_rx_h_ppdu(ar, rx_info);
+
+       rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
+                                    RX_FLAG_DECRYPTED);
+
+       ath12k_dp_rx_h_undecap(ar, msdu, desc,
+                              HAL_ENCRYPT_TYPE_TKIP_MIC, rx_info->rx_status, false);
+       return false;
+}
+
+static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar,  struct sk_buff *msdu,
+                                    struct ath12k_dp_rx_info *rx_info)
+{
+       struct ath12k_base *ab = ar->ab;
+       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+       struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
+       bool drop = false;
+       u32 err_bitmap;
+
+       ar->ab->device_stats.rxdma_error[rxcb->err_code]++;
+
+       switch (rxcb->err_code) {
+       case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
+       case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
+               err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
+               if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
+                       ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
+                       drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info);
+                       break;
+               }
+               fallthrough;
+       default:
+               /* TODO: Review other rxdma error code to check if anything is
+                * worth reporting to mac80211
+                */
+               drop = true;
+               break;
+       }
+
+       return drop;
+}
+
+static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
+                                  struct ath12k_dp_rx_info *rx_info,
+                                  struct sk_buff_head *msdu_list)
+{
+       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+       bool drop = false;
+
+       ar->ab->device_stats.reo_error[rxcb->err_code]++;
+
+       switch (rxcb->err_code) {
+       case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
+               if (ath12k_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list))
+                       drop = true;
+               break;
+       case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
+               /* TODO: Do not drop PN failed packets in the driver;
+                * instead, it is good to drop such packets in mac80211
+                * after incrementing the replay counters.
+                */
+               fallthrough;
+       default:
+               /* TODO: Review other errors and process them to mac80211
+                * as appropriate.
+                */
+               drop = true;
+               break;
+       }
+
+       return drop;
+}
+
+static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
+                                struct napi_struct *napi,
+                                struct sk_buff *msdu,
+                                struct sk_buff_head *msdu_list)
+{
+       struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+       struct ieee80211_rx_status rxs = {};
+       struct ath12k_dp_rx_info rx_info;
+       bool drop = true;
+
+       rx_info.addr2_present = false;
+       rx_info.rx_status = &rxs;
+
+       switch (rxcb->err_rel_src) {
+       case HAL_WBM_REL_SRC_MODULE_REO:
+               drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list);
+               break;
+       case HAL_WBM_REL_SRC_MODULE_RXDMA:
+               drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rx_info);
+               break;
+       default:
+               /* msdu will get freed */
+               break;
+       }
+
+       if (drop) {
+               dev_kfree_skb_any(msdu);
+               return;
+       }
+
+       rx_info.rx_status->flag |= RX_FLAG_SKIP_MONITOR;
+
+       ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
+}
+
+int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
+                                struct napi_struct *napi, int budget)
+{
+       struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
+       struct ath12k_hw_group *ag = ab->ag;
+       struct ath12k *ar;
+       struct ath12k_dp *dp = &ab->dp;
+       struct dp_rxdma_ring *rx_ring;
+       struct hal_rx_wbm_rel_info err_info;
+       struct hal_srng *srng;
+       struct sk_buff *msdu;
+       struct sk_buff_head msdu_list, scatter_msdu_list;
+       struct ath12k_skb_rxcb *rxcb;
+       void *rx_desc;
+       int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
+       int total_num_buffs_reaped = 0;
+       struct ath12k_rx_desc_info *desc_info;
+       struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
+       struct ath12k_hw_link *hw_links = ag->hw_links;
+       struct ath12k_base *partner_ab;
+       u8 hw_link_id, device_id;
+       int ret, pdev_id;
+       struct hal_rx_desc *msdu_data;
+
+       __skb_queue_head_init(&msdu_list);
+       __skb_queue_head_init(&scatter_msdu_list);
+
+       for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
+               INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
+       srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
+       spin_lock_bh(&srng->lock);
+
+       ath12k_hal_srng_access_begin(ab, srng);
+
+       while (budget) {
+               rx_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng);
+               if (!rx_desc)
+                       break;
+
+               ret = ath12k_hal_wbm_desc_parse_err(ab, rx_desc, &err_info);
+               if (ret) {
+                       ath12k_warn(ab,
+                                   "failed to parse rx error in wbm_rel ring desc %d\n",
+                                   ret);
+                       continue;
+               }
+
+               desc_info = err_info.rx_desc;
+
+               /* retry manual desc retrieval if hw cc is not done */
+               if (!desc_info) {
+                       desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie);
+                       if (!desc_info) {
+                               ath12k_warn(ab, "Invalid cookie in DP WBM rx error descriptor retrieval: 0x%x\n",
+                                           err_info.cookie);
+                               continue;
+                       }
+               }
+
+               if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
+                       ath12k_warn(ab, "WBM RX err, Check HW CC implementation");
+
+               msdu = desc_info->skb;
+               desc_info->skb = NULL;
+
+               device_id = desc_info->device_id;
+               partner_ab = ath12k_ag_to_ab(ag, device_id);
+               if (unlikely(!partner_ab)) {
+                       dev_kfree_skb_any(msdu);
+
+                       /* In any case continuation bit is set
+                        * in the previous record, cleanup scatter_msdu_list
+                        */
+                       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+                       continue;
+               }
+
+               list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
+
+               rxcb = ATH12K_SKB_RXCB(msdu);
+               dma_unmap_single(partner_ab->dev, rxcb->paddr,
+                                msdu->len + skb_tailroom(msdu),
+                                DMA_FROM_DEVICE);
+
+               num_buffs_reaped[device_id]++;
+               total_num_buffs_reaped++;
+
+               if (!err_info.continuation)
+                       budget--;
+
+               if (err_info.push_reason !=
+                   HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
+                       dev_kfree_skb_any(msdu);
+                       continue;
+               }
+
+               msdu_data = (struct hal_rx_desc *)msdu->data;
+               rxcb->err_rel_src = err_info.err_rel_src;
+               rxcb->err_code = err_info.err_code;
+               rxcb->is_first_msdu = err_info.first_msdu;
+               rxcb->is_last_msdu = err_info.last_msdu;
+               rxcb->is_continuation = err_info.continuation;
+               rxcb->rx_desc = msdu_data;
+
+               if (err_info.continuation) {
+                       __skb_queue_tail(&scatter_msdu_list, msdu);
+                       continue;
+               }
+
+               hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_ab,
+                                                           msdu_data);
+               if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
+                       dev_kfree_skb_any(msdu);
+
+                       /* In any case continuation bit is set
+                        * in the previous record, cleanup scatter_msdu_list
+                        */
+                       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+                       continue;
+               }
+
+               if (!skb_queue_empty(&scatter_msdu_list)) {
+                       struct sk_buff *msdu;
+
+                       skb_queue_walk(&scatter_msdu_list, msdu) {
+                               rxcb = ATH12K_SKB_RXCB(msdu);
+                               rxcb->hw_link_id = hw_link_id;
+                       }
+
+                       skb_queue_splice_tail_init(&scatter_msdu_list,
+                                                  &msdu_list);
+               }
+
+               rxcb = ATH12K_SKB_RXCB(msdu);
+               rxcb->hw_link_id = hw_link_id;
+               __skb_queue_tail(&msdu_list, msdu);
+       }
+
+       /* In any case continuation bit is set in the
+        * last record, cleanup scatter_msdu_list
+        */
+       ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+
+       ath12k_hal_srng_access_end(ab, srng);
+
+       spin_unlock_bh(&srng->lock);
+
+       if (!total_num_buffs_reaped)
+               goto done;
+
+       for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
+               if (!num_buffs_reaped[device_id])
+                       continue;
+
+               partner_ab = ath12k_ag_to_ab(ag, device_id);
+               rx_ring = &partner_ab->dp.rx_refill_buf_ring;
+
+               ath12k_dp_rx_bufs_replenish(ab, rx_ring,
+                                           &rx_desc_used_list[device_id],
+                                           num_buffs_reaped[device_id]);
+       }
+
+       rcu_read_lock();
+       while ((msdu = __skb_dequeue(&msdu_list))) {
+               rxcb = ATH12K_SKB_RXCB(msdu);
+               hw_link_id = rxcb->hw_link_id;
+
+               device_id = hw_links[hw_link_id].device_id;
+               partner_ab = ath12k_ag_to_ab(ag, device_id);
+               if (unlikely(!partner_ab)) {
+                       ath12k_dbg(ab, ATH12K_DBG_DATA,
+                                  "Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
+                                  hw_link_id, device_id);
+                       dev_kfree_skb_any(msdu);
+                       continue;
+               }
+
+               pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
+                                                     hw_links[hw_link_id].pdev_idx);
+               ar = partner_ab->pdevs[pdev_id].ar;
+
+               if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_id])) {
+                       dev_kfree_skb_any(msdu);
+                       continue;
+               }
+
+               if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
+                       dev_kfree_skb_any(msdu);
+                       continue;
+               }
+
+               if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) {
+                       device_id = ar->ab->device_id;
+                       device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
+               }
+
+               ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
+       }
+       rcu_read_unlock();
+done:
+       return total_num_buffs_reaped;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
new file mode 100644 (file)
index 0000000..a6da989
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef ATH12K_DP_RX_WIFI7_H
+#define ATH12K_DP_RX_WIFI7_H
+
+#include "../core.h"
+#include "../dp_rx.h"
+
+int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
+                                struct napi_struct *napi, int budget);
+#endif