]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Move ath12k_dp_tx and related APIs to wifi7 directory
authorPavankumar Nandeshwar <quic_pnandesh@quicinc.com>
Thu, 28 Aug 2025 17:35:49 +0000 (23:05 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Wed, 3 Sep 2025 17:06:59 +0000 (10:06 -0700)
Move arch specific TX data path to wifi7 directory as part of Next
Generation (NG) Driver Framework.

Architecture specific APIs:
ath12k_hal_tx_cmd_ext_desc_setup
ath12k_dp_prepare_htt_metadata
ath12k_dp_tx

The moved APIs will be a part of dp_tx.c file inside wifi7 directory.
wifi7/dp_tx.c file will continue to be part of ath12k.ko temporarily
until the corresponding infra for movement to ath12k_wifi7.ko arrives
in upcoming patches.

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-17-quic_rdeuri@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_tx.c
drivers/net/wireless/ath/ath12k/dp_tx.h
drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h

index f1649744c78b7476177faf6b8ff03a1ff32e66b5..c7b0fc22c1a79c39d2712d6321f4d2e1d17be182 100644 (file)
@@ -109,26 +109,6 @@ struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp,
        return desc;
 }
 
-static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,
-                                            struct hal_tx_msdu_ext_desc *tcl_ext_cmd,
-                                            struct hal_tx_info *ti)
-{
-       tcl_ext_cmd->info0 = le32_encode_bits(ti->paddr,
-                                             HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO);
-       tcl_ext_cmd->info1 = le32_encode_bits(0x0,
-                                             HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) |
-                              le32_encode_bits(ti->data_len,
-                                               HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
-
-       tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
-                               le32_encode_bits(ti->encap_type,
-                                                HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
-                               le32_encode_bits(ti->encrypt_type,
-                                                HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
-}
-
-#define HTT_META_DATA_ALIGNMENT 0x8
-
 void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len)
 {
        struct sk_buff *tail;
@@ -142,29 +122,6 @@ void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len)
        return metadata;
 }
 
-/* Preparing HTT Metadata when utilized with ext MSDU */
-static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
-{
-       struct hal_tx_msdu_metadata *desc_ext;
-       u8 htt_desc_size;
-       /* Size rounded of multiple of 8 bytes */
-       u8 htt_desc_size_aligned;
-
-       htt_desc_size = sizeof(struct hal_tx_msdu_metadata);
-       htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT);
-
-       desc_ext = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned);
-       if (!desc_ext)
-               return -ENOMEM;
-
-       desc_ext->info0 = le32_encode_bits(1, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_FLAG) |
-                         le32_encode_bits(0, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_TYPE) |
-                         le32_encode_bits(1,
-                                          HAL_TX_MSDU_METADATA_INFO0_HOST_TX_DESC_POOL);
-
-       return 0;
-}
-
 static void ath12k_dp_tx_move_payload(struct sk_buff *skb,
                                      unsigned long delta,
                                      bool head)
@@ -219,326 +176,6 @@ out:
        return ret;
 }
 
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
-                struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
-                bool is_mcast)
-{
-       struct ath12k_base *ab = ar->ab;
-       struct ath12k_dp *dp = &ab->dp;
-       struct hal_tx_info ti = {};
-       struct ath12k_tx_desc_info *tx_desc;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
-       struct hal_tcl_data_cmd *hal_tcl_desc;
-       struct hal_tx_msdu_ext_desc *msg;
-       struct sk_buff *skb_ext_desc = NULL;
-       struct hal_srng *tcl_ring;
-       struct ieee80211_hdr *hdr = (void *)skb->data;
-       struct ath12k_vif *ahvif = arvif->ahvif;
-       struct dp_tx_ring *tx_ring;
-       u8 pool_id;
-       u8 hal_ring_id;
-       int ret;
-       u8 ring_selector, ring_map = 0;
-       bool tcl_ring_retry;
-       bool msdu_ext_desc = false;
-       bool add_htt_metadata = false;
-       u32 iova_mask = ab->hw_params->iova_mask;
-       bool is_diff_encap = false;
-       bool is_null_frame = false;
-
-       if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
-               return -ESHUTDOWN;
-
-       if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
-           !ieee80211_is_data(hdr->frame_control))
-               return -EOPNOTSUPP;
-
-       pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
-
-       /* Let the default ring selection be based on current processor
-        * number, where one of the 3 tcl rings are selected based on
-        * the smp_processor_id(). In case that ring
-        * is full/busy, we resort to other available rings.
-        * If all rings are full, we drop the packet.
-        * TODO: Add throttling logic when all rings are full
-        */
-       ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb);
-
-tcl_ring_sel:
-       tcl_ring_retry = false;
-       ti.ring_id = ring_selector % ab->hw_params->max_tx_ring;
-
-       ring_map |= BIT(ti.ring_id);
-       ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id;
-
-       tx_ring = &dp->tx_ring[ti.ring_id];
-
-       tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
-       if (!tx_desc)
-               return -ENOMEM;
-
-       ti.bank_id = arvif->bank_id;
-       ti.meta_data_flags = arvif->tcl_metadata;
-
-       if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
-           test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
-               if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
-                       ti.encrypt_type =
-                               ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
-
-                       if (ieee80211_has_protected(hdr->frame_control))
-                               skb_put(skb, IEEE80211_CCMP_MIC_LEN);
-               } else {
-                       ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
-               }
-
-               msdu_ext_desc = true;
-       }
-
-       if (gsn_valid) {
-               /* Reset and Initialize meta_data_flags with Global Sequence
-                * Number (GSN) info.
-                */
-               ti.meta_data_flags =
-                       u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM,
-                                       HTT_TCL_META_DATA_TYPE) |
-                       u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
-       }
-
-       ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
-       ti.addr_search_flags = arvif->hal_addr_search_flags;
-       ti.search_type = arvif->search_type;
-       ti.type = HAL_TCL_DESC_TYPE_BUFFER;
-       ti.pkt_offset = 0;
-       ti.lmac_id = ar->lmac_id;
-
-       ti.vdev_id = arvif->vdev_id;
-       if (gsn_valid)
-               ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
-
-       ti.bss_ast_hash = arvif->ast_hash;
-       ti.bss_ast_idx = arvif->ast_idx;
-       ti.dscp_tid_tbl_idx = 0;
-
-       if (skb->ip_summed == CHECKSUM_PARTIAL &&
-           ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
-               ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) |
-                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) |
-                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) |
-                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) |
-                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN);
-       }
-
-       ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE);
-
-       ti.tid = ath12k_dp_tx_get_tid(skb);
-
-       switch (ti.encap_type) {
-       case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
-               is_null_frame = ieee80211_is_nullfunc(hdr->frame_control);
-               if (ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
-                       if (skb->protocol == cpu_to_be16(ETH_P_PAE) || is_null_frame)
-                               is_diff_encap = true;
-
-                       /* Firmware expects msdu ext descriptor for nwifi/raw packets
-                        * received in ETH mode. Without this, observed tx fail for
-                        * Multicast packets in ETH mode.
-                        */
-                       msdu_ext_desc = true;
-               } else {
-                       ath12k_dp_tx_encap_nwifi(skb);
-               }
-               break;
-       case HAL_TCL_ENCAP_TYPE_RAW:
-               if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
-                       ret = -EINVAL;
-                       goto fail_remove_tx_buf;
-               }
-               break;
-       case HAL_TCL_ENCAP_TYPE_ETHERNET:
-               /* no need to encap */
-               break;
-       case HAL_TCL_ENCAP_TYPE_802_3:
-       default:
-               /* TODO: Take care of other encap modes as well */
-               ret = -EINVAL;
-               atomic_inc(&ab->device_stats.tx_err.misc_fail);
-               goto fail_remove_tx_buf;
-       }
-
-       if (iova_mask &&
-           (unsigned long)skb->data & iova_mask) {
-               ret = ath12k_dp_tx_align_payload(ab, &skb);
-               if (ret) {
-                       ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
-                       /* don't bail out, give original buffer
-                        * a chance even unaligned.
-                        */
-                       goto map;
-               }
-
-               /* hdr is pointing to a wrong place after alignment,
-                * so refresh it for later use.
-                */
-               hdr = (void *)skb->data;
-       }
-map:
-       ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
-       if (dma_mapping_error(ab->dev, ti.paddr)) {
-               atomic_inc(&ab->device_stats.tx_err.misc_fail);
-               ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
-               ret = -ENOMEM;
-               goto fail_remove_tx_buf;
-       }
-
-       if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
-            !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
-            !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
-            ieee80211_has_protected(hdr->frame_control)) ||
-           is_diff_encap) {
-               /* Firmware is not expecting meta data for qos null
-                * nwifi packet received in ETH encap mode.
-                */
-               if (is_null_frame && msdu_ext_desc)
-                       goto skip_htt_meta;
-
-               /* Add metadata for sw encrypted vlan group traffic
-                * and EAPOL nwifi packet received in ETH encap mode.
-                */
-               add_htt_metadata = true;
-               msdu_ext_desc = true;
-               ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
-skip_htt_meta:
-               ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW);
-               ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW;
-               ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
-       }
-
-       tx_desc->skb = skb;
-       tx_desc->mac_id = ar->pdev_idx;
-       ti.desc_id = tx_desc->desc_id;
-       ti.data_len = skb->len;
-       skb_cb->paddr = ti.paddr;
-       skb_cb->vif = ahvif->vif;
-       skb_cb->ar = ar;
-
-       if (msdu_ext_desc) {
-               skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
-               if (!skb_ext_desc) {
-                       ret = -ENOMEM;
-                       goto fail_unmap_dma;
-               }
-
-               skb_put(skb_ext_desc, sizeof(struct hal_tx_msdu_ext_desc));
-               memset(skb_ext_desc->data, 0, skb_ext_desc->len);
-
-               msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;
-               ath12k_hal_tx_cmd_ext_desc_setup(ab, msg, &ti);
-
-               if (add_htt_metadata) {
-                       ret = ath12k_dp_prepare_htt_metadata(skb_ext_desc);
-                       if (ret < 0) {
-                               ath12k_dbg(ab, ATH12K_DBG_DP_TX,
-                                          "Failed to add HTT meta data, dropping packet\n");
-                               goto fail_free_ext_skb;
-                       }
-               }
-
-               ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
-                                         skb_ext_desc->len, DMA_TO_DEVICE);
-               ret = dma_mapping_error(ab->dev, ti.paddr);
-               if (ret)
-                       goto fail_free_ext_skb;
-
-               ti.data_len = skb_ext_desc->len;
-               ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
-
-               skb_cb->paddr_ext_desc = ti.paddr;
-               tx_desc->skb_ext_desc = skb_ext_desc;
-       }
-
-       hal_ring_id = tx_ring->tcl_data_ring.ring_id;
-       tcl_ring = &ab->hal.srng_list[hal_ring_id];
-
-       spin_lock_bh(&tcl_ring->lock);
-
-       ath12k_hal_srng_access_begin(ab, tcl_ring);
-
-       hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring);
-       if (!hal_tcl_desc) {
-               /* NOTE: It is highly unlikely we'll be running out of tcl_ring
-                * desc because the desc is directly enqueued onto hw queue.
-                */
-               ath12k_hal_srng_access_end(ab, tcl_ring);
-               ab->device_stats.tx_err.desc_na[ti.ring_id]++;
-               spin_unlock_bh(&tcl_ring->lock);
-               ret = -ENOMEM;
-
-               /* Checking for available tcl descriptors in another ring in
-                * case of failure due to full tcl ring now, is better than
-                * checking this ring earlier for each pkt tx.
-                * Restart ring selection if some rings are not checked yet.
-                */
-               if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) &&
-                   ab->hw_params->tcl_ring_retry) {
-                       tcl_ring_retry = true;
-                       ring_selector++;
-               }
-
-               goto fail_unmap_dma_ext;
-       }
-
-       spin_lock_bh(&arvif->link_stats_lock);
-       arvif->link_stats.tx_encap_type[ti.encap_type]++;
-       arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++;
-       arvif->link_stats.tx_desc_type[ti.type]++;
-
-       if (is_mcast)
-               arvif->link_stats.tx_bcast_mcast++;
-       else
-               arvif->link_stats.tx_enqueued++;
-       spin_unlock_bh(&arvif->link_stats_lock);
-
-       ab->device_stats.tx_enqueued[ti.ring_id]++;
-
-       ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
-
-       ath12k_hal_srng_access_end(ab, tcl_ring);
-
-       spin_unlock_bh(&tcl_ring->lock);
-
-       ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
-                       skb->data, skb->len);
-
-       atomic_inc(&ar->dp.num_tx_pending);
-
-       return 0;
-
-fail_unmap_dma_ext:
-       if (skb_cb->paddr_ext_desc)
-               dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
-                                skb_ext_desc->len,
-                                DMA_TO_DEVICE);
-fail_free_ext_skb:
-       kfree_skb(skb_ext_desc);
-
-fail_unmap_dma:
-       dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
-
-fail_remove_tx_buf:
-       ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
-
-       spin_lock_bh(&arvif->link_stats_lock);
-       arvif->link_stats.tx_dropped++;
-       spin_unlock_bh(&arvif->link_stats_lock);
-
-       if (tcl_ring_retry)
-               goto tcl_ring_sel;
-
-       return ret;
-}
-
 void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
                             struct dp_tx_ring *tx_ring,
                             struct ath12k_tx_desc_params *desc_params)
index 67ab7b3f55eaf19d563b01310fc4595fb3f6f33c..8405a0baf95b6c75f71511d467ddde838af15a02 100644 (file)
@@ -16,9 +16,6 @@ struct ath12k_dp_htt_wbm_tx_status {
 };
 
 int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
-                struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
-                bool is_mcast);
 int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask);
 int
 ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
index 149e211aa225ea5ff33c0a429995c30436f4a0a5..49d219a195c5ee1fb70573dd49d9cb68f4ce50a4 100644 (file)
 #include "../peer.h"
 #include "dp_tx.h"
 
+static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,
+                                            struct hal_tx_msdu_ext_desc *tcl_ext_cmd,
+                                            struct hal_tx_info *ti)
+{
+       tcl_ext_cmd->info0 = le32_encode_bits(ti->paddr,
+                                             HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO);
+       tcl_ext_cmd->info1 = le32_encode_bits(0x0,
+                                             HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) |
+                              le32_encode_bits(ti->data_len,
+                                               HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
+
+       tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
+                               le32_encode_bits(ti->encap_type,
+                                                HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
+                               le32_encode_bits(ti->encrypt_type,
+                                                HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
+}
+
+#define HTT_META_DATA_ALIGNMENT 0x8
+
+/* Preparing HTT Metadata when utilized with ext MSDU */
+static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
+{
+       struct hal_tx_msdu_metadata *desc_ext;
+       u8 htt_desc_size;
+       /* Size rounded of multiple of 8 bytes */
+       u8 htt_desc_size_aligned;
+
+       htt_desc_size = sizeof(struct hal_tx_msdu_metadata);
+       htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT);
+
+       desc_ext = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned);
+       if (!desc_ext)
+               return -ENOMEM;
+
+       desc_ext->info0 = le32_encode_bits(1, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_FLAG) |
+                         le32_encode_bits(0, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_TYPE) |
+                         le32_encode_bits(1,
+                                          HAL_TX_MSDU_METADATA_INFO0_HOST_TX_DESC_POOL);
+
+       return 0;
+}
+
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
+                struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
+                bool is_mcast)
+{
+       struct ath12k_base *ab = ar->ab;
+       struct ath12k_dp *dp = &ab->dp;
+       struct hal_tx_info ti = {};
+       struct ath12k_tx_desc_info *tx_desc;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
+       struct hal_tcl_data_cmd *hal_tcl_desc;
+       struct hal_tx_msdu_ext_desc *msg;
+       struct sk_buff *skb_ext_desc = NULL;
+       struct hal_srng *tcl_ring;
+       struct ieee80211_hdr *hdr = (void *)skb->data;
+       struct ath12k_vif *ahvif = arvif->ahvif;
+       struct dp_tx_ring *tx_ring;
+       u8 pool_id;
+       u8 hal_ring_id;
+       int ret;
+       u8 ring_selector, ring_map = 0;
+       bool tcl_ring_retry;
+       bool msdu_ext_desc = false;
+       bool add_htt_metadata = false;
+       u32 iova_mask = ab->hw_params->iova_mask;
+       bool is_diff_encap = false;
+       bool is_null_frame = false;
+
+       if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
+               return -ESHUTDOWN;
+
+       if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+           !ieee80211_is_data(hdr->frame_control))
+               return -EOPNOTSUPP;
+
+       pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
+
+       /* Let the default ring selection be based on current processor
+        * number, where one of the 3 tcl rings are selected based on
+        * the smp_processor_id(). In case that ring
+        * is full/busy, we resort to other available rings.
+        * If all rings are full, we drop the packet.
+        * TODO: Add throttling logic when all rings are full
+        */
+       ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb);
+
+tcl_ring_sel:
+       tcl_ring_retry = false;
+       ti.ring_id = ring_selector % ab->hw_params->max_tx_ring;
+
+       ring_map |= BIT(ti.ring_id);
+       ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id;
+
+       tx_ring = &dp->tx_ring[ti.ring_id];
+
+       tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
+       if (!tx_desc)
+               return -ENOMEM;
+
+       ti.bank_id = arvif->bank_id;
+       ti.meta_data_flags = arvif->tcl_metadata;
+
+       if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+           test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
+               if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
+                       ti.encrypt_type =
+                               ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
+
+                       if (ieee80211_has_protected(hdr->frame_control))
+                               skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+               } else {
+                       ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
+               }
+
+               msdu_ext_desc = true;
+       }
+
+       if (gsn_valid) {
+               /* Reset and Initialize meta_data_flags with Global Sequence
+                * Number (GSN) info.
+                */
+               ti.meta_data_flags =
+                       u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM,
+                                       HTT_TCL_META_DATA_TYPE) |
+                       u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
+       }
+
+       ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
+       ti.addr_search_flags = arvif->hal_addr_search_flags;
+       ti.search_type = arvif->search_type;
+       ti.type = HAL_TCL_DESC_TYPE_BUFFER;
+       ti.pkt_offset = 0;
+       ti.lmac_id = ar->lmac_id;
+
+       ti.vdev_id = arvif->vdev_id;
+       if (gsn_valid)
+               ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
+
+       ti.bss_ast_hash = arvif->ast_hash;
+       ti.bss_ast_idx = arvif->ast_idx;
+       ti.dscp_tid_tbl_idx = 0;
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
+               ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) |
+                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) |
+                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) |
+                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) |
+                            u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN);
+       }
+
+       ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE);
+
+       ti.tid = ath12k_dp_tx_get_tid(skb);
+
+       switch (ti.encap_type) {
+       case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
+               is_null_frame = ieee80211_is_nullfunc(hdr->frame_control);
+               if (ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
+                       if (skb->protocol == cpu_to_be16(ETH_P_PAE) || is_null_frame)
+                               is_diff_encap = true;
+
+                       /* Firmware expects msdu ext descriptor for nwifi/raw packets
+                        * received in ETH mode. Without this, observed tx fail for
+                        * Multicast packets in ETH mode.
+                        */
+                       msdu_ext_desc = true;
+               } else {
+                       ath12k_dp_tx_encap_nwifi(skb);
+               }
+               break;
+       case HAL_TCL_ENCAP_TYPE_RAW:
+               if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
+                       ret = -EINVAL;
+                       goto fail_remove_tx_buf;
+               }
+               break;
+       case HAL_TCL_ENCAP_TYPE_ETHERNET:
+               /* no need to encap */
+               break;
+       case HAL_TCL_ENCAP_TYPE_802_3:
+       default:
+               /* TODO: Take care of other encap modes as well */
+               ret = -EINVAL;
+               atomic_inc(&ab->device_stats.tx_err.misc_fail);
+               goto fail_remove_tx_buf;
+       }
+
+       if (iova_mask &&
+           (unsigned long)skb->data & iova_mask) {
+               ret = ath12k_dp_tx_align_payload(ab, &skb);
+               if (ret) {
+                       ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
+                       /* don't bail out, give original buffer
+                        * a chance even unaligned.
+                        */
+                       goto map;
+               }
+
+               /* hdr is pointing to a wrong place after alignment,
+                * so refresh it for later use.
+                */
+               hdr = (void *)skb->data;
+       }
+map:
+       ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
+       if (dma_mapping_error(ab->dev, ti.paddr)) {
+               atomic_inc(&ab->device_stats.tx_err.misc_fail);
+               ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
+               ret = -ENOMEM;
+               goto fail_remove_tx_buf;
+       }
+
+       if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
+            !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
+            !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
+            ieee80211_has_protected(hdr->frame_control)) ||
+           is_diff_encap) {
+               /* Firmware is not expecting meta data for qos null
+                * nwifi packet received in ETH encap mode.
+                */
+               if (is_null_frame && msdu_ext_desc)
+                       goto skip_htt_meta;
+
+               /* Add metadata for sw encrypted vlan group traffic
+                * and EAPOL nwifi packet received in ETH encap mode.
+                */
+               add_htt_metadata = true;
+               msdu_ext_desc = true;
+               ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
+skip_htt_meta:
+               ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW);
+               ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW;
+               ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
+       }
+
+       tx_desc->skb = skb;
+       tx_desc->mac_id = ar->pdev_idx;
+       ti.desc_id = tx_desc->desc_id;
+       ti.data_len = skb->len;
+       skb_cb->paddr = ti.paddr;
+       skb_cb->vif = ahvif->vif;
+       skb_cb->ar = ar;
+
+       if (msdu_ext_desc) {
+               skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
+               if (!skb_ext_desc) {
+                       ret = -ENOMEM;
+                       goto fail_unmap_dma;
+               }
+
+               skb_put(skb_ext_desc, sizeof(struct hal_tx_msdu_ext_desc));
+               memset(skb_ext_desc->data, 0, skb_ext_desc->len);
+
+               msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;
+               ath12k_hal_tx_cmd_ext_desc_setup(ab, msg, &ti);
+
+               if (add_htt_metadata) {
+                       ret = ath12k_dp_prepare_htt_metadata(skb_ext_desc);
+                       if (ret < 0) {
+                               ath12k_dbg(ab, ATH12K_DBG_DP_TX,
+                                          "Failed to add HTT meta data, dropping packet\n");
+                               goto fail_free_ext_skb;
+                       }
+               }
+
+               ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
+                                         skb_ext_desc->len, DMA_TO_DEVICE);
+               ret = dma_mapping_error(ab->dev, ti.paddr);
+               if (ret)
+                       goto fail_free_ext_skb;
+
+               ti.data_len = skb_ext_desc->len;
+               ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
+
+               skb_cb->paddr_ext_desc = ti.paddr;
+               tx_desc->skb_ext_desc = skb_ext_desc;
+       }
+
+       hal_ring_id = tx_ring->tcl_data_ring.ring_id;
+       tcl_ring = &ab->hal.srng_list[hal_ring_id];
+
+       spin_lock_bh(&tcl_ring->lock);
+
+       ath12k_hal_srng_access_begin(ab, tcl_ring);
+
+       hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring);
+       if (!hal_tcl_desc) {
+               /* NOTE: It is highly unlikely we'll be running out of tcl_ring
+                * desc because the desc is directly enqueued onto hw queue.
+                */
+               ath12k_hal_srng_access_end(ab, tcl_ring);
+               ab->device_stats.tx_err.desc_na[ti.ring_id]++;
+               spin_unlock_bh(&tcl_ring->lock);
+               ret = -ENOMEM;
+
+               /* Checking for available tcl descriptors in another ring in
+                * case of failure due to full tcl ring now, is better than
+                * checking this ring earlier for each pkt tx.
+                * Restart ring selection if some rings are not checked yet.
+                */
+               if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) &&
+                   ab->hw_params->tcl_ring_retry) {
+                       tcl_ring_retry = true;
+                       ring_selector++;
+               }
+
+               goto fail_unmap_dma_ext;
+       }
+
+       spin_lock_bh(&arvif->link_stats_lock);
+       arvif->link_stats.tx_encap_type[ti.encap_type]++;
+       arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++;
+       arvif->link_stats.tx_desc_type[ti.type]++;
+
+       if (is_mcast)
+               arvif->link_stats.tx_bcast_mcast++;
+       else
+               arvif->link_stats.tx_enqueued++;
+       spin_unlock_bh(&arvif->link_stats_lock);
+
+       ab->device_stats.tx_enqueued[ti.ring_id]++;
+
+       ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
+
+       ath12k_hal_srng_access_end(ab, tcl_ring);
+
+       spin_unlock_bh(&tcl_ring->lock);
+
+       ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
+                       skb->data, skb->len);
+
+       atomic_inc(&ar->dp.num_tx_pending);
+
+       return 0;
+
+fail_unmap_dma_ext:
+       if (skb_cb->paddr_ext_desc)
+               dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
+                                skb_ext_desc->len,
+                                DMA_TO_DEVICE);
+fail_free_ext_skb:
+       kfree_skb(skb_ext_desc);
+
+fail_unmap_dma:
+       dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
+
+fail_remove_tx_buf:
+       ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
+
+       spin_lock_bh(&arvif->link_stats_lock);
+       arvif->link_stats.tx_dropped++;
+       spin_unlock_bh(&arvif->link_stats_lock);
+
+       if (tcl_ring_retry)
+               goto tcl_ring_sel;
+
+       return ret;
+}
+
 static void
 ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
                                 struct ath12k_tx_desc_params *desc_params,
index 4361beb9966606ff89b18339d3d1b40e35ea302d..42faf664f8f8b25a0243c3f633d5095eee6cff63 100644 (file)
@@ -7,5 +7,8 @@
 #ifndef ATH12K_DP_TX_WIFI7_H
 #define ATH12K_DP_TX_WIFI7_H
 
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
+                struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
+                bool is_mcast);
 void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
 #endif