162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause-Clear
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "core.h"
862306a36Sopenharmony_ci#include "dp_tx.h"
962306a36Sopenharmony_ci#include "debug.h"
1062306a36Sopenharmony_ci#include "hw.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic enum hal_tcl_encap_type
1362306a36Sopenharmony_ciath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1662306a36Sopenharmony_ci	struct ath12k_base *ab = arvif->ar->ab;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
1962306a36Sopenharmony_ci		return HAL_TCL_ENCAP_TYPE_RAW;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
2262306a36Sopenharmony_ci		return HAL_TCL_ENCAP_TYPE_ETHERNET;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = (void *)skb->data;
3062306a36Sopenharmony_ci	u8 *qos_ctl;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (!ieee80211_is_data_qos(hdr->frame_control))
3362306a36Sopenharmony_ci		return;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	qos_ctl = ieee80211_get_qos_ctl(hdr);
3662306a36Sopenharmony_ci	memmove(skb->data + IEEE80211_QOS_CTL_LEN,
3762306a36Sopenharmony_ci		skb->data, (void *)qos_ctl - (void *)skb->data);
3862306a36Sopenharmony_ci	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	hdr = (void *)skb->data;
4162306a36Sopenharmony_ci	hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic u8 ath12k_dp_tx_get_tid(struct sk_buff *skb)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = (void *)skb->data;
4762306a36Sopenharmony_ci	struct ath12k_skb_cb *cb = ATH12K_SKB_CB(skb);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (cb->flags & ATH12K_SKB_HW_80211_ENCAP)
5062306a36Sopenharmony_ci		return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
5162306a36Sopenharmony_ci	else if (!ieee80211_is_data_qos(hdr->frame_control))
5262306a36Sopenharmony_ci		return HAL_DESC_REO_NON_QOS_TID;
5362306a36Sopenharmony_ci	else
5462306a36Sopenharmony_ci		return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cienum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	switch (cipher) {
6062306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_WEP40:
6162306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_WEP_40;
6262306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_WEP104:
6362306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_WEP_104;
6462306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_TKIP:
6562306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_TKIP_MIC;
6662306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_CCMP:
6762306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_CCMP_128;
6862306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_CCMP_256:
6962306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_CCMP_256;
7062306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_GCMP:
7162306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_GCMP_128;
7262306a36Sopenharmony_ci	case WLAN_CIPHER_SUITE_GCMP_256:
7362306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_AES_GCMP_256;
7462306a36Sopenharmony_ci	default:
7562306a36Sopenharmony_ci		return HAL_ENCRYPT_TYPE_OPEN;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp,
8062306a36Sopenharmony_ci				       struct ath12k_tx_desc_info *tx_desc,
8162306a36Sopenharmony_ci				       u8 pool_id)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	spin_lock_bh(&dp->tx_desc_lock[pool_id]);
8462306a36Sopenharmony_ci	list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[pool_id]);
8562306a36Sopenharmony_ci	spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp,
8962306a36Sopenharmony_ci							      u8 pool_id)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	struct ath12k_tx_desc_info *desc;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	spin_lock_bh(&dp->tx_desc_lock[pool_id]);
9462306a36Sopenharmony_ci	desc = list_first_entry_or_null(&dp->tx_desc_free_list[pool_id],
9562306a36Sopenharmony_ci					struct ath12k_tx_desc_info,
9662306a36Sopenharmony_ci					list);
9762306a36Sopenharmony_ci	if (!desc) {
9862306a36Sopenharmony_ci		spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
9962306a36Sopenharmony_ci		ath12k_warn(dp->ab, "failed to allocate data Tx buffer\n");
10062306a36Sopenharmony_ci		return NULL;
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]);
10462306a36Sopenharmony_ci	spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return desc;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd,
11062306a36Sopenharmony_ci					     struct hal_tx_info *ti)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct hal_tx_msdu_ext_desc *tcl_ext_cmd = (struct hal_tx_msdu_ext_desc *)cmd;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	tcl_ext_cmd->info0 = le32_encode_bits(ti->paddr,
11562306a36Sopenharmony_ci					      HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO);
11662306a36Sopenharmony_ci	tcl_ext_cmd->info1 = le32_encode_bits(0x0,
11762306a36Sopenharmony_ci					      HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) |
11862306a36Sopenharmony_ci			       le32_encode_bits(ti->data_len,
11962306a36Sopenharmony_ci						HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	tcl_ext_cmd->info1 = le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
12262306a36Sopenharmony_ci				le32_encode_bits(ti->encap_type,
12362306a36Sopenharmony_ci						 HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
12462306a36Sopenharmony_ci				le32_encode_bits(ti->encrypt_type,
12562306a36Sopenharmony_ci						 HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciint ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
12962306a36Sopenharmony_ci		 struct sk_buff *skb)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
13262306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
13362306a36Sopenharmony_ci	struct hal_tx_info ti = {0};
13462306a36Sopenharmony_ci	struct ath12k_tx_desc_info *tx_desc;
13562306a36Sopenharmony_ci	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
13662306a36Sopenharmony_ci	struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
13762306a36Sopenharmony_ci	struct hal_tcl_data_cmd *hal_tcl_desc;
13862306a36Sopenharmony_ci	struct hal_tx_msdu_ext_desc *msg;
13962306a36Sopenharmony_ci	struct sk_buff *skb_ext_desc;
14062306a36Sopenharmony_ci	struct hal_srng *tcl_ring;
14162306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = (void *)skb->data;
14262306a36Sopenharmony_ci	struct dp_tx_ring *tx_ring;
14362306a36Sopenharmony_ci	u8 pool_id;
14462306a36Sopenharmony_ci	u8 hal_ring_id;
14562306a36Sopenharmony_ci	int ret;
14662306a36Sopenharmony_ci	u8 ring_selector, ring_map = 0;
14762306a36Sopenharmony_ci	bool tcl_ring_retry;
14862306a36Sopenharmony_ci	bool msdu_ext_desc = false;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
15162306a36Sopenharmony_ci		return -ESHUTDOWN;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
15462306a36Sopenharmony_ci	    !ieee80211_is_data(hdr->frame_control))
15562306a36Sopenharmony_ci		return -ENOTSUPP;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	/* Let the default ring selection be based on current processor
16062306a36Sopenharmony_ci	 * number, where one of the 3 tcl rings are selected based on
16162306a36Sopenharmony_ci	 * the smp_processor_id(). In case that ring
16262306a36Sopenharmony_ci	 * is full/busy, we resort to other available rings.
16362306a36Sopenharmony_ci	 * If all rings are full, we drop the packet.
16462306a36Sopenharmony_ci	 * TODO: Add throttling logic when all rings are full
16562306a36Sopenharmony_ci	 */
16662306a36Sopenharmony_ci	ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_citcl_ring_sel:
16962306a36Sopenharmony_ci	tcl_ring_retry = false;
17062306a36Sopenharmony_ci	ti.ring_id = ring_selector % ab->hw_params->max_tx_ring;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	ring_map |= BIT(ti.ring_id);
17362306a36Sopenharmony_ci	ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	tx_ring = &dp->tx_ring[ti.ring_id];
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
17862306a36Sopenharmony_ci	if (!tx_desc)
17962306a36Sopenharmony_ci		return -ENOMEM;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	ti.bank_id = arvif->bank_id;
18262306a36Sopenharmony_ci	ti.meta_data_flags = arvif->tcl_metadata;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
18562306a36Sopenharmony_ci	    test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
18662306a36Sopenharmony_ci		if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
18762306a36Sopenharmony_ci			ti.encrypt_type =
18862306a36Sopenharmony_ci				ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci			if (ieee80211_has_protected(hdr->frame_control))
19162306a36Sopenharmony_ci				skb_put(skb, IEEE80211_CCMP_MIC_LEN);
19262306a36Sopenharmony_ci		} else {
19362306a36Sopenharmony_ci			ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
19462306a36Sopenharmony_ci		}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci		msdu_ext_desc = true;
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb);
20062306a36Sopenharmony_ci	ti.addr_search_flags = arvif->hal_addr_search_flags;
20162306a36Sopenharmony_ci	ti.search_type = arvif->search_type;
20262306a36Sopenharmony_ci	ti.type = HAL_TCL_DESC_TYPE_BUFFER;
20362306a36Sopenharmony_ci	ti.pkt_offset = 0;
20462306a36Sopenharmony_ci	ti.lmac_id = ar->lmac_id;
20562306a36Sopenharmony_ci	ti.vdev_id = arvif->vdev_id;
20662306a36Sopenharmony_ci	ti.bss_ast_hash = arvif->ast_hash;
20762306a36Sopenharmony_ci	ti.bss_ast_idx = arvif->ast_idx;
20862306a36Sopenharmony_ci	ti.dscp_tid_tbl_idx = 0;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	if (skb->ip_summed == CHECKSUM_PARTIAL &&
21162306a36Sopenharmony_ci	    ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
21262306a36Sopenharmony_ci		ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) |
21362306a36Sopenharmony_ci			     u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) |
21462306a36Sopenharmony_ci			     u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) |
21562306a36Sopenharmony_ci			     u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) |
21662306a36Sopenharmony_ci			     u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN);
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	ti.tid = ath12k_dp_tx_get_tid(skb);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	switch (ti.encap_type) {
22462306a36Sopenharmony_ci	case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
22562306a36Sopenharmony_ci		ath12k_dp_tx_encap_nwifi(skb);
22662306a36Sopenharmony_ci		break;
22762306a36Sopenharmony_ci	case HAL_TCL_ENCAP_TYPE_RAW:
22862306a36Sopenharmony_ci		if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
22962306a36Sopenharmony_ci			ret = -EINVAL;
23062306a36Sopenharmony_ci			goto fail_remove_tx_buf;
23162306a36Sopenharmony_ci		}
23262306a36Sopenharmony_ci		break;
23362306a36Sopenharmony_ci	case HAL_TCL_ENCAP_TYPE_ETHERNET:
23462306a36Sopenharmony_ci		/* no need to encap */
23562306a36Sopenharmony_ci		break;
23662306a36Sopenharmony_ci	case HAL_TCL_ENCAP_TYPE_802_3:
23762306a36Sopenharmony_ci	default:
23862306a36Sopenharmony_ci		/* TODO: Take care of other encap modes as well */
23962306a36Sopenharmony_ci		ret = -EINVAL;
24062306a36Sopenharmony_ci		atomic_inc(&ab->soc_stats.tx_err.misc_fail);
24162306a36Sopenharmony_ci		goto fail_remove_tx_buf;
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
24562306a36Sopenharmony_ci	if (dma_mapping_error(ab->dev, ti.paddr)) {
24662306a36Sopenharmony_ci		atomic_inc(&ab->soc_stats.tx_err.misc_fail);
24762306a36Sopenharmony_ci		ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
24862306a36Sopenharmony_ci		ret = -ENOMEM;
24962306a36Sopenharmony_ci		goto fail_remove_tx_buf;
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	tx_desc->skb = skb;
25362306a36Sopenharmony_ci	tx_desc->mac_id = ar->pdev_idx;
25462306a36Sopenharmony_ci	ti.desc_id = tx_desc->desc_id;
25562306a36Sopenharmony_ci	ti.data_len = skb->len;
25662306a36Sopenharmony_ci	skb_cb->paddr = ti.paddr;
25762306a36Sopenharmony_ci	skb_cb->vif = arvif->vif;
25862306a36Sopenharmony_ci	skb_cb->ar = ar;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	if (msdu_ext_desc) {
26162306a36Sopenharmony_ci		skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
26262306a36Sopenharmony_ci		if (!skb_ext_desc) {
26362306a36Sopenharmony_ci			ret = -ENOMEM;
26462306a36Sopenharmony_ci			goto fail_unmap_dma;
26562306a36Sopenharmony_ci		}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci		skb_put(skb_ext_desc, sizeof(struct hal_tx_msdu_ext_desc));
26862306a36Sopenharmony_ci		memset(skb_ext_desc->data, 0, skb_ext_desc->len);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci		msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;
27162306a36Sopenharmony_ci		ath12k_hal_tx_cmd_ext_desc_setup(ab, msg, &ti);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
27462306a36Sopenharmony_ci					  skb_ext_desc->len, DMA_TO_DEVICE);
27562306a36Sopenharmony_ci		ret = dma_mapping_error(ab->dev, ti.paddr);
27662306a36Sopenharmony_ci		if (ret) {
27762306a36Sopenharmony_ci			kfree_skb(skb_ext_desc);
27862306a36Sopenharmony_ci			goto fail_unmap_dma;
27962306a36Sopenharmony_ci		}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		ti.data_len = skb_ext_desc->len;
28262306a36Sopenharmony_ci		ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci		skb_cb->paddr_ext_desc = ti.paddr;
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	hal_ring_id = tx_ring->tcl_data_ring.ring_id;
28862306a36Sopenharmony_ci	tcl_ring = &ab->hal.srng_list[hal_ring_id];
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	spin_lock_bh(&tcl_ring->lock);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	ath12k_hal_srng_access_begin(ab, tcl_ring);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring);
29562306a36Sopenharmony_ci	if (!hal_tcl_desc) {
29662306a36Sopenharmony_ci		/* NOTE: It is highly unlikely we'll be running out of tcl_ring
29762306a36Sopenharmony_ci		 * desc because the desc is directly enqueued onto hw queue.
29862306a36Sopenharmony_ci		 */
29962306a36Sopenharmony_ci		ath12k_hal_srng_access_end(ab, tcl_ring);
30062306a36Sopenharmony_ci		ab->soc_stats.tx_err.desc_na[ti.ring_id]++;
30162306a36Sopenharmony_ci		spin_unlock_bh(&tcl_ring->lock);
30262306a36Sopenharmony_ci		ret = -ENOMEM;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci		/* Checking for available tcl descriptors in another ring in
30562306a36Sopenharmony_ci		 * case of failure due to full tcl ring now, is better than
30662306a36Sopenharmony_ci		 * checking this ring earlier for each pkt tx.
30762306a36Sopenharmony_ci		 * Restart ring selection if some rings are not checked yet.
30862306a36Sopenharmony_ci		 */
30962306a36Sopenharmony_ci		if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) &&
31062306a36Sopenharmony_ci		    ab->hw_params->tcl_ring_retry) {
31162306a36Sopenharmony_ci			tcl_ring_retry = true;
31262306a36Sopenharmony_ci			ring_selector++;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		goto fail_unmap_dma;
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	ath12k_hal_srng_access_end(ab, tcl_ring);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	spin_unlock_bh(&tcl_ring->lock);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
32562306a36Sopenharmony_ci			skb->data, skb->len);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	atomic_inc(&ar->dp.num_tx_pending);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	return 0;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cifail_unmap_dma:
33262306a36Sopenharmony_ci	dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (skb_cb->paddr_ext_desc)
33562306a36Sopenharmony_ci		dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
33662306a36Sopenharmony_ci				 sizeof(struct hal_tx_msdu_ext_desc),
33762306a36Sopenharmony_ci				 DMA_TO_DEVICE);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cifail_remove_tx_buf:
34062306a36Sopenharmony_ci	ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
34162306a36Sopenharmony_ci	if (tcl_ring_retry)
34262306a36Sopenharmony_ci		goto tcl_ring_sel;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return ret;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
34862306a36Sopenharmony_ci				    struct sk_buff *msdu, u8 mac_id,
34962306a36Sopenharmony_ci				    struct dp_tx_ring *tx_ring)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	struct ath12k *ar;
35262306a36Sopenharmony_ci	struct ath12k_skb_cb *skb_cb;
35362306a36Sopenharmony_ci	u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	skb_cb = ATH12K_SKB_CB(msdu);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
35862306a36Sopenharmony_ci	if (skb_cb->paddr_ext_desc)
35962306a36Sopenharmony_ci		dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
36062306a36Sopenharmony_ci				 sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	dev_kfree_skb_any(msdu);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	ar = ab->pdevs[pdev_id].ar;
36562306a36Sopenharmony_ci	if (atomic_dec_and_test(&ar->dp.num_tx_pending))
36662306a36Sopenharmony_ci		wake_up(&ar->dp.tx_empty_waitq);
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic void
37062306a36Sopenharmony_ciath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
37162306a36Sopenharmony_ci				 struct sk_buff *msdu,
37262306a36Sopenharmony_ci				 struct dp_tx_ring *tx_ring,
37362306a36Sopenharmony_ci				 struct ath12k_dp_htt_wbm_tx_status *ts)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct ieee80211_tx_info *info;
37662306a36Sopenharmony_ci	struct ath12k_skb_cb *skb_cb;
37762306a36Sopenharmony_ci	struct ath12k *ar;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	skb_cb = ATH12K_SKB_CB(msdu);
38062306a36Sopenharmony_ci	info = IEEE80211_SKB_CB(msdu);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	ar = skb_cb->ar;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	if (atomic_dec_and_test(&ar->dp.num_tx_pending))
38562306a36Sopenharmony_ci		wake_up(&ar->dp.tx_empty_waitq);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
38862306a36Sopenharmony_ci	if (skb_cb->paddr_ext_desc)
38962306a36Sopenharmony_ci		dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
39062306a36Sopenharmony_ci				 sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	memset(&info->status, 0, sizeof(info->status));
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (ts->acked) {
39562306a36Sopenharmony_ci		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
39662306a36Sopenharmony_ci			info->flags |= IEEE80211_TX_STAT_ACK;
39762306a36Sopenharmony_ci			info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR +
39862306a36Sopenharmony_ci						  ts->ack_rssi;
39962306a36Sopenharmony_ci			info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
40062306a36Sopenharmony_ci		} else {
40162306a36Sopenharmony_ci			info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
40262306a36Sopenharmony_ci		}
40362306a36Sopenharmony_ci	}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	ieee80211_tx_status(ar->hw, msdu);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic void
40962306a36Sopenharmony_ciath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
41062306a36Sopenharmony_ci				     void *desc, u8 mac_id,
41162306a36Sopenharmony_ci				     struct sk_buff *msdu,
41262306a36Sopenharmony_ci				     struct dp_tx_ring *tx_ring)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	struct htt_tx_wbm_completion *status_desc;
41562306a36Sopenharmony_ci	struct ath12k_dp_htt_wbm_tx_status ts = {0};
41662306a36Sopenharmony_ci	enum hal_wbm_htt_tx_comp_status wbm_status;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	wbm_status = le32_get_bits(status_desc->info0,
42162306a36Sopenharmony_ci				   HTT_TX_WBM_COMP_INFO0_STATUS);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	switch (wbm_status) {
42462306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
42562306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
42662306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
42762306a36Sopenharmony_ci		ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
42862306a36Sopenharmony_ci		ts.ack_rssi = le32_get_bits(status_desc->info2,
42962306a36Sopenharmony_ci					    HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
43062306a36Sopenharmony_ci		ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts);
43162306a36Sopenharmony_ci		break;
43262306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
43362306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
43462306a36Sopenharmony_ci		ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring);
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY:
43762306a36Sopenharmony_ci		/* This event is to be handled only when the driver decides to
43862306a36Sopenharmony_ci		 * use WDS offload functionality.
43962306a36Sopenharmony_ci		 */
44062306a36Sopenharmony_ci		break;
44162306a36Sopenharmony_ci	default:
44262306a36Sopenharmony_ci		ath12k_warn(ab, "Unknown htt tx status %d\n", wbm_status);
44362306a36Sopenharmony_ci		break;
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
44862306a36Sopenharmony_ci				       struct sk_buff *msdu,
44962306a36Sopenharmony_ci				       struct hal_tx_status *ts)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
45262306a36Sopenharmony_ci	struct ieee80211_tx_info *info;
45362306a36Sopenharmony_ci	struct ath12k_skb_cb *skb_cb;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
45662306a36Sopenharmony_ci		/* Must not happen */
45762306a36Sopenharmony_ci		return;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	skb_cb = ATH12K_SKB_CB(msdu);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
46362306a36Sopenharmony_ci	if (skb_cb->paddr_ext_desc)
46462306a36Sopenharmony_ci		dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
46562306a36Sopenharmony_ci				 sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	rcu_read_lock();
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) {
47062306a36Sopenharmony_ci		dev_kfree_skb_any(msdu);
47162306a36Sopenharmony_ci		goto exit;
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	if (!skb_cb->vif) {
47562306a36Sopenharmony_ci		dev_kfree_skb_any(msdu);
47662306a36Sopenharmony_ci		goto exit;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	info = IEEE80211_SKB_CB(msdu);
48062306a36Sopenharmony_ci	memset(&info->status, 0, sizeof(info->status));
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	/* skip tx rate update from ieee80211_status*/
48362306a36Sopenharmony_ci	info->status.rates[0].idx = -1;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
48662306a36Sopenharmony_ci	    !(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
48762306a36Sopenharmony_ci		info->flags |= IEEE80211_TX_STAT_ACK;
48862306a36Sopenharmony_ci		info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR +
48962306a36Sopenharmony_ci					  ts->ack_rssi;
49062306a36Sopenharmony_ci		info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX &&
49462306a36Sopenharmony_ci	    (info->flags & IEEE80211_TX_CTL_NO_ACK))
49562306a36Sopenharmony_ci		info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	/* NOTE: Tx rate status reporting. Tx completion status does not have
49862306a36Sopenharmony_ci	 * necessary information (for example nss) to build the tx rate.
49962306a36Sopenharmony_ci	 * Might end up reporting it out-of-band from HTT stats.
50062306a36Sopenharmony_ci	 */
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	ieee80211_tx_status(ar->hw, msdu);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ciexit:
50562306a36Sopenharmony_ci	rcu_read_unlock();
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cistatic void ath12k_dp_tx_status_parse(struct ath12k_base *ab,
50962306a36Sopenharmony_ci				      struct hal_wbm_completion_ring_tx *desc,
51062306a36Sopenharmony_ci				      struct hal_tx_status *ts)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	ts->buf_rel_source =
51362306a36Sopenharmony_ci		le32_get_bits(desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE);
51462306a36Sopenharmony_ci	if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW &&
51562306a36Sopenharmony_ci	    ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)
51662306a36Sopenharmony_ci		return;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)
51962306a36Sopenharmony_ci		return;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	ts->status = le32_get_bits(desc->info0,
52262306a36Sopenharmony_ci				   HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	ts->ppdu_id = le32_get_bits(desc->info1,
52562306a36Sopenharmony_ci				    HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER);
52662306a36Sopenharmony_ci	if (le32_to_cpu(desc->rate_stats.info0) & HAL_TX_RATE_STATS_INFO0_VALID)
52762306a36Sopenharmony_ci		ts->rate_stats = le32_to_cpu(desc->rate_stats.info0);
52862306a36Sopenharmony_ci	else
52962306a36Sopenharmony_ci		ts->rate_stats = 0;
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_civoid ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	struct ath12k *ar;
53562306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
53662306a36Sopenharmony_ci	int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
53762306a36Sopenharmony_ci	struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id];
53862306a36Sopenharmony_ci	struct ath12k_tx_desc_info *tx_desc = NULL;
53962306a36Sopenharmony_ci	struct sk_buff *msdu;
54062306a36Sopenharmony_ci	struct hal_tx_status ts = { 0 };
54162306a36Sopenharmony_ci	struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
54262306a36Sopenharmony_ci	struct hal_wbm_release_ring *desc;
54362306a36Sopenharmony_ci	u8 mac_id, pdev_id;
54462306a36Sopenharmony_ci	u64 desc_va;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	spin_lock_bh(&status_ring->lock);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	ath12k_hal_srng_access_begin(ab, status_ring);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	while (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) != tx_ring->tx_status_tail) {
55162306a36Sopenharmony_ci		desc = ath12k_hal_srng_dst_get_next_entry(ab, status_ring);
55262306a36Sopenharmony_ci		if (!desc)
55362306a36Sopenharmony_ci			break;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci		memcpy(&tx_ring->tx_status[tx_ring->tx_status_head],
55662306a36Sopenharmony_ci		       desc, sizeof(*desc));
55762306a36Sopenharmony_ci		tx_ring->tx_status_head =
55862306a36Sopenharmony_ci			ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head);
55962306a36Sopenharmony_ci	}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	if (ath12k_hal_srng_dst_peek(ab, status_ring) &&
56262306a36Sopenharmony_ci	    (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) == tx_ring->tx_status_tail)) {
56362306a36Sopenharmony_ci		/* TODO: Process pending tx_status messages when kfifo_is_full() */
56462306a36Sopenharmony_ci		ath12k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n");
56562306a36Sopenharmony_ci	}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	ath12k_hal_srng_access_end(ab, status_ring);
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	spin_unlock_bh(&status_ring->lock);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	while (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) {
57262306a36Sopenharmony_ci		struct hal_wbm_completion_ring_tx *tx_status;
57362306a36Sopenharmony_ci		u32 desc_id;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci		tx_ring->tx_status_tail =
57662306a36Sopenharmony_ci			ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_tail);
57762306a36Sopenharmony_ci		tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail];
57862306a36Sopenharmony_ci		ath12k_dp_tx_status_parse(ab, tx_status, &ts);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci		if (le32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) {
58162306a36Sopenharmony_ci			/* HW done cookie conversion */
58262306a36Sopenharmony_ci			desc_va = ((u64)le32_to_cpu(tx_status->buf_va_hi) << 32 |
58362306a36Sopenharmony_ci				   le32_to_cpu(tx_status->buf_va_lo));
58462306a36Sopenharmony_ci			tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va);
58562306a36Sopenharmony_ci		} else {
58662306a36Sopenharmony_ci			/* SW does cookie conversion to VA */
58762306a36Sopenharmony_ci			desc_id = le32_get_bits(tx_status->buf_va_hi,
58862306a36Sopenharmony_ci						BUFFER_ADDR_INFO1_SW_COOKIE);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci			tx_desc = ath12k_dp_get_tx_desc(ab, desc_id);
59162306a36Sopenharmony_ci		}
59262306a36Sopenharmony_ci		if (!tx_desc) {
59362306a36Sopenharmony_ci			ath12k_warn(ab, "unable to retrieve tx_desc!");
59462306a36Sopenharmony_ci			continue;
59562306a36Sopenharmony_ci		}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci		msdu = tx_desc->skb;
59862306a36Sopenharmony_ci		mac_id = tx_desc->mac_id;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci		/* Release descriptor as soon as extracting necessary info
60162306a36Sopenharmony_ci		 * to reduce contention
60262306a36Sopenharmony_ci		 */
60362306a36Sopenharmony_ci		ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id);
60462306a36Sopenharmony_ci		if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) {
60562306a36Sopenharmony_ci			ath12k_dp_tx_process_htt_tx_complete(ab,
60662306a36Sopenharmony_ci							     (void *)tx_status,
60762306a36Sopenharmony_ci							     mac_id, msdu,
60862306a36Sopenharmony_ci							     tx_ring);
60962306a36Sopenharmony_ci			continue;
61062306a36Sopenharmony_ci		}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
61362306a36Sopenharmony_ci		ar = ab->pdevs[pdev_id].ar;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci		if (atomic_dec_and_test(&ar->dp.num_tx_pending))
61662306a36Sopenharmony_ci			wake_up(&ar->dp.tx_empty_waitq);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci		ath12k_dp_tx_complete_msdu(ar, msdu, &ts);
61962306a36Sopenharmony_ci	}
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic int
62362306a36Sopenharmony_ciath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab,
62462306a36Sopenharmony_ci			      int mac_id, u32 ring_id,
62562306a36Sopenharmony_ci			      enum hal_ring_type ring_type,
62662306a36Sopenharmony_ci			      enum htt_srng_ring_type *htt_ring_type,
62762306a36Sopenharmony_ci			      enum htt_srng_ring_id *htt_ring_id)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	int ret = 0;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	switch (ring_type) {
63262306a36Sopenharmony_ci	case HAL_RXDMA_BUF:
63362306a36Sopenharmony_ci		/* for some targets, host fills rx buffer to fw and fw fills to
63462306a36Sopenharmony_ci		 * rxbuf ring for each rxdma
63562306a36Sopenharmony_ci		 */
63662306a36Sopenharmony_ci		if (!ab->hw_params->rx_mac_buf_ring) {
63762306a36Sopenharmony_ci			if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0 ||
63862306a36Sopenharmony_ci			      ring_id == HAL_SRNG_SW2RXDMA_BUF1)) {
63962306a36Sopenharmony_ci				ret = -EINVAL;
64062306a36Sopenharmony_ci			}
64162306a36Sopenharmony_ci			*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
64262306a36Sopenharmony_ci			*htt_ring_type = HTT_SW_TO_HW_RING;
64362306a36Sopenharmony_ci		} else {
64462306a36Sopenharmony_ci			if (ring_id == HAL_SRNG_SW2RXDMA_BUF0) {
64562306a36Sopenharmony_ci				*htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
64662306a36Sopenharmony_ci				*htt_ring_type = HTT_SW_TO_SW_RING;
64762306a36Sopenharmony_ci			} else {
64862306a36Sopenharmony_ci				*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
64962306a36Sopenharmony_ci				*htt_ring_type = HTT_SW_TO_HW_RING;
65062306a36Sopenharmony_ci			}
65162306a36Sopenharmony_ci		}
65262306a36Sopenharmony_ci		break;
65362306a36Sopenharmony_ci	case HAL_RXDMA_DST:
65462306a36Sopenharmony_ci		*htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
65562306a36Sopenharmony_ci		*htt_ring_type = HTT_HW_TO_SW_RING;
65662306a36Sopenharmony_ci		break;
65762306a36Sopenharmony_ci	case HAL_RXDMA_MONITOR_BUF:
65862306a36Sopenharmony_ci		*htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
65962306a36Sopenharmony_ci		*htt_ring_type = HTT_SW_TO_HW_RING;
66062306a36Sopenharmony_ci		break;
66162306a36Sopenharmony_ci	case HAL_RXDMA_MONITOR_STATUS:
66262306a36Sopenharmony_ci		*htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
66362306a36Sopenharmony_ci		*htt_ring_type = HTT_SW_TO_HW_RING;
66462306a36Sopenharmony_ci		break;
66562306a36Sopenharmony_ci	case HAL_RXDMA_MONITOR_DST:
66662306a36Sopenharmony_ci		*htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
66762306a36Sopenharmony_ci		*htt_ring_type = HTT_HW_TO_SW_RING;
66862306a36Sopenharmony_ci		break;
66962306a36Sopenharmony_ci	case HAL_RXDMA_MONITOR_DESC:
67062306a36Sopenharmony_ci		*htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
67162306a36Sopenharmony_ci		*htt_ring_type = HTT_SW_TO_HW_RING;
67262306a36Sopenharmony_ci		break;
67362306a36Sopenharmony_ci	case HAL_TX_MONITOR_BUF:
67462306a36Sopenharmony_ci		*htt_ring_id = HTT_TX_MON_HOST2MON_BUF_RING;
67562306a36Sopenharmony_ci		*htt_ring_type = HTT_SW_TO_HW_RING;
67662306a36Sopenharmony_ci		break;
67762306a36Sopenharmony_ci	case HAL_TX_MONITOR_DST:
67862306a36Sopenharmony_ci		*htt_ring_id = HTT_TX_MON_MON2HOST_DEST_RING;
67962306a36Sopenharmony_ci		*htt_ring_type = HTT_HW_TO_SW_RING;
68062306a36Sopenharmony_ci		break;
68162306a36Sopenharmony_ci	default:
68262306a36Sopenharmony_ci		ath12k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);
68362306a36Sopenharmony_ci		ret = -EINVAL;
68462306a36Sopenharmony_ci	}
68562306a36Sopenharmony_ci	return ret;
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ciint ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
68962306a36Sopenharmony_ci				int mac_id, enum hal_ring_type ring_type)
69062306a36Sopenharmony_ci{
69162306a36Sopenharmony_ci	struct htt_srng_setup_cmd *cmd;
69262306a36Sopenharmony_ci	struct hal_srng *srng = &ab->hal.srng_list[ring_id];
69362306a36Sopenharmony_ci	struct hal_srng_params params;
69462306a36Sopenharmony_ci	struct sk_buff *skb;
69562306a36Sopenharmony_ci	u32 ring_entry_sz;
69662306a36Sopenharmony_ci	int len = sizeof(*cmd);
69762306a36Sopenharmony_ci	dma_addr_t hp_addr, tp_addr;
69862306a36Sopenharmony_ci	enum htt_srng_ring_type htt_ring_type;
69962306a36Sopenharmony_ci	enum htt_srng_ring_id htt_ring_id;
70062306a36Sopenharmony_ci	int ret;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	skb = ath12k_htc_alloc_skb(ab, len);
70362306a36Sopenharmony_ci	if (!skb)
70462306a36Sopenharmony_ci		return -ENOMEM;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	memset(&params, 0, sizeof(params));
70762306a36Sopenharmony_ci	ath12k_hal_srng_get_params(ab, srng, &params);
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng);
71062306a36Sopenharmony_ci	tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
71362306a36Sopenharmony_ci					    ring_type, &htt_ring_type,
71462306a36Sopenharmony_ci					    &htt_ring_id);
71562306a36Sopenharmony_ci	if (ret)
71662306a36Sopenharmony_ci		goto err_free;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	skb_put(skb, len);
71962306a36Sopenharmony_ci	cmd = (struct htt_srng_setup_cmd *)skb->data;
72062306a36Sopenharmony_ci	cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_SRING_SETUP,
72162306a36Sopenharmony_ci				      HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE);
72262306a36Sopenharmony_ci	if (htt_ring_type == HTT_SW_TO_HW_RING ||
72362306a36Sopenharmony_ci	    htt_ring_type == HTT_HW_TO_SW_RING)
72462306a36Sopenharmony_ci		cmd->info0 |= le32_encode_bits(DP_SW2HW_MACID(mac_id),
72562306a36Sopenharmony_ci					       HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
72662306a36Sopenharmony_ci	else
72762306a36Sopenharmony_ci		cmd->info0 |= le32_encode_bits(mac_id,
72862306a36Sopenharmony_ci					       HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
72962306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(htt_ring_type,
73062306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE);
73162306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(htt_ring_id,
73262306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO0_RING_ID);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	cmd->ring_base_addr_lo = cpu_to_le32(params.ring_base_paddr &
73562306a36Sopenharmony_ci					     HAL_ADDR_LSB_REG_MASK);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	cmd->ring_base_addr_hi = cpu_to_le32((u64)params.ring_base_paddr >>
73862306a36Sopenharmony_ci					     HAL_ADDR_MSB_REG_SHIFT);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	ret = ath12k_hal_srng_get_entrysize(ab, ring_type);
74162306a36Sopenharmony_ci	if (ret < 0)
74262306a36Sopenharmony_ci		goto err_free;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	ring_entry_sz = ret;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	ring_entry_sz >>= 2;
74762306a36Sopenharmony_ci	cmd->info1 = le32_encode_bits(ring_entry_sz,
74862306a36Sopenharmony_ci				      HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE);
74962306a36Sopenharmony_ci	cmd->info1 |= le32_encode_bits(params.num_entries * ring_entry_sz,
75062306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE);
75162306a36Sopenharmony_ci	cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
75262306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP);
75362306a36Sopenharmony_ci	cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
75462306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP);
75562306a36Sopenharmony_ci	cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_RING_PTR_SWAP),
75662306a36Sopenharmony_ci				       HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP);
75762306a36Sopenharmony_ci	if (htt_ring_type == HTT_SW_TO_HW_RING)
75862306a36Sopenharmony_ci		cmd->info1 |= cpu_to_le32(HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS);
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	cmd->ring_head_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(hp_addr));
76162306a36Sopenharmony_ci	cmd->ring_head_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(hp_addr));
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	cmd->ring_tail_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(tp_addr));
76462306a36Sopenharmony_ci	cmd->ring_tail_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(tp_addr));
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	cmd->ring_msi_addr_lo = cpu_to_le32(lower_32_bits(params.msi_addr));
76762306a36Sopenharmony_ci	cmd->ring_msi_addr_hi = cpu_to_le32(upper_32_bits(params.msi_addr));
76862306a36Sopenharmony_ci	cmd->msi_data = cpu_to_le32(params.msi_data);
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	cmd->intr_info =
77162306a36Sopenharmony_ci		le32_encode_bits(params.intr_batch_cntr_thres_entries * ring_entry_sz,
77262306a36Sopenharmony_ci				 HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH);
77362306a36Sopenharmony_ci	cmd->intr_info |=
77462306a36Sopenharmony_ci		le32_encode_bits(params.intr_timer_thres_us >> 3,
77562306a36Sopenharmony_ci				 HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	cmd->info2 = 0;
77862306a36Sopenharmony_ci	if (params.flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
77962306a36Sopenharmony_ci		cmd->info2 = le32_encode_bits(params.low_threshold,
78062306a36Sopenharmony_ci					      HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH);
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	ath12k_dbg(ab, ATH12K_DBG_HAL,
78462306a36Sopenharmony_ci		   "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
78562306a36Sopenharmony_ci		   __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
78662306a36Sopenharmony_ci		   cmd->msi_data);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	ath12k_dbg(ab, ATH12K_DBG_HAL,
78962306a36Sopenharmony_ci		   "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
79062306a36Sopenharmony_ci		   ring_id, ring_type, cmd->intr_info, cmd->info2);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
79362306a36Sopenharmony_ci	if (ret)
79462306a36Sopenharmony_ci		goto err_free;
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	return 0;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_cierr_free:
79962306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	return ret;
80262306a36Sopenharmony_ci}
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ)
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ciint ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab)
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
80962306a36Sopenharmony_ci	struct sk_buff *skb;
81062306a36Sopenharmony_ci	struct htt_ver_req_cmd *cmd;
81162306a36Sopenharmony_ci	int len = sizeof(*cmd);
81262306a36Sopenharmony_ci	int ret;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	init_completion(&dp->htt_tgt_version_received);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	skb = ath12k_htc_alloc_skb(ab, len);
81762306a36Sopenharmony_ci	if (!skb)
81862306a36Sopenharmony_ci		return -ENOMEM;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	skb_put(skb, len);
82162306a36Sopenharmony_ci	cmd = (struct htt_ver_req_cmd *)skb->data;
82262306a36Sopenharmony_ci	cmd->ver_reg_info = le32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ,
82362306a36Sopenharmony_ci					     HTT_VER_REQ_INFO_MSG_ID);
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
82662306a36Sopenharmony_ci	if (ret) {
82762306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
82862306a36Sopenharmony_ci		return ret;
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&dp->htt_tgt_version_received,
83262306a36Sopenharmony_ci					  HTT_TARGET_VERSION_TIMEOUT_HZ);
83362306a36Sopenharmony_ci	if (ret == 0) {
83462306a36Sopenharmony_ci		ath12k_warn(ab, "htt target version request timed out\n");
83562306a36Sopenharmony_ci		return -ETIMEDOUT;
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {
83962306a36Sopenharmony_ci		ath12k_err(ab, "unsupported htt major version %d supported version is %d\n",
84062306a36Sopenharmony_ci			   dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);
84162306a36Sopenharmony_ci		return -ENOTSUPP;
84262306a36Sopenharmony_ci	}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	return 0;
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ciint ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask)
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
85062306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
85162306a36Sopenharmony_ci	struct sk_buff *skb;
85262306a36Sopenharmony_ci	struct htt_ppdu_stats_cfg_cmd *cmd;
85362306a36Sopenharmony_ci	int len = sizeof(*cmd);
85462306a36Sopenharmony_ci	u8 pdev_mask;
85562306a36Sopenharmony_ci	int ret;
85662306a36Sopenharmony_ci	int i;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) {
85962306a36Sopenharmony_ci		skb = ath12k_htc_alloc_skb(ab, len);
86062306a36Sopenharmony_ci		if (!skb)
86162306a36Sopenharmony_ci			return -ENOMEM;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci		skb_put(skb, len);
86462306a36Sopenharmony_ci		cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;
86562306a36Sopenharmony_ci		cmd->msg = le32_encode_bits(HTT_H2T_MSG_TYPE_PPDU_STATS_CFG,
86662306a36Sopenharmony_ci					    HTT_PPDU_STATS_CFG_MSG_TYPE);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci		pdev_mask = 1 << (i + 1);
86962306a36Sopenharmony_ci		cmd->msg |= le32_encode_bits(pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID);
87062306a36Sopenharmony_ci		cmd->msg |= le32_encode_bits(mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci		ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
87362306a36Sopenharmony_ci		if (ret) {
87462306a36Sopenharmony_ci			dev_kfree_skb_any(skb);
87562306a36Sopenharmony_ci			return ret;
87662306a36Sopenharmony_ci		}
87762306a36Sopenharmony_ci	}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	return 0;
88062306a36Sopenharmony_ci}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ciint ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
88362306a36Sopenharmony_ci				     int mac_id, enum hal_ring_type ring_type,
88462306a36Sopenharmony_ci				     int rx_buf_size,
88562306a36Sopenharmony_ci				     struct htt_rx_ring_tlv_filter *tlv_filter)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	struct htt_rx_ring_selection_cfg_cmd *cmd;
88862306a36Sopenharmony_ci	struct hal_srng *srng = &ab->hal.srng_list[ring_id];
88962306a36Sopenharmony_ci	struct hal_srng_params params;
89062306a36Sopenharmony_ci	struct sk_buff *skb;
89162306a36Sopenharmony_ci	int len = sizeof(*cmd);
89262306a36Sopenharmony_ci	enum htt_srng_ring_type htt_ring_type;
89362306a36Sopenharmony_ci	enum htt_srng_ring_id htt_ring_id;
89462306a36Sopenharmony_ci	int ret;
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	skb = ath12k_htc_alloc_skb(ab, len);
89762306a36Sopenharmony_ci	if (!skb)
89862306a36Sopenharmony_ci		return -ENOMEM;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	memset(&params, 0, sizeof(params));
90162306a36Sopenharmony_ci	ath12k_hal_srng_get_params(ab, srng, &params);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
90462306a36Sopenharmony_ci					    ring_type, &htt_ring_type,
90562306a36Sopenharmony_ci					    &htt_ring_id);
90662306a36Sopenharmony_ci	if (ret)
90762306a36Sopenharmony_ci		goto err_free;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	skb_put(skb, len);
91062306a36Sopenharmony_ci	cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data;
91162306a36Sopenharmony_ci	cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG,
91262306a36Sopenharmony_ci				      HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
91362306a36Sopenharmony_ci	if (htt_ring_type == HTT_SW_TO_HW_RING ||
91462306a36Sopenharmony_ci	    htt_ring_type == HTT_HW_TO_SW_RING)
91562306a36Sopenharmony_ci		cmd->info0 |=
91662306a36Sopenharmony_ci			le32_encode_bits(DP_SW2HW_MACID(mac_id),
91762306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
91862306a36Sopenharmony_ci	else
91962306a36Sopenharmony_ci		cmd->info0 |=
92062306a36Sopenharmony_ci			le32_encode_bits(mac_id,
92162306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
92262306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(htt_ring_id,
92362306a36Sopenharmony_ci				       HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
92462306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
92562306a36Sopenharmony_ci				       HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS);
92662306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
92762306a36Sopenharmony_ci				       HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS);
92862306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(tlv_filter->offset_valid,
92962306a36Sopenharmony_ci				       HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID);
93062306a36Sopenharmony_ci	cmd->info1 = le32_encode_bits(rx_buf_size,
93162306a36Sopenharmony_ci				      HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE);
93262306a36Sopenharmony_ci	cmd->pkt_type_en_flags0 = cpu_to_le32(tlv_filter->pkt_filter_flags0);
93362306a36Sopenharmony_ci	cmd->pkt_type_en_flags1 = cpu_to_le32(tlv_filter->pkt_filter_flags1);
93462306a36Sopenharmony_ci	cmd->pkt_type_en_flags2 = cpu_to_le32(tlv_filter->pkt_filter_flags2);
93562306a36Sopenharmony_ci	cmd->pkt_type_en_flags3 = cpu_to_le32(tlv_filter->pkt_filter_flags3);
93662306a36Sopenharmony_ci	cmd->rx_filter_tlv = cpu_to_le32(tlv_filter->rx_filter);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	if (tlv_filter->offset_valid) {
93962306a36Sopenharmony_ci		cmd->rx_packet_offset =
94062306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_packet_offset,
94162306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET);
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci		cmd->rx_packet_offset |=
94462306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_header_offset,
94562306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci		cmd->rx_mpdu_offset =
94862306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_mpdu_end_offset,
94962306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET);
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci		cmd->rx_mpdu_offset |=
95262306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_mpdu_start_offset,
95362306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci		cmd->rx_msdu_offset =
95662306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_msdu_end_offset,
95762306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci		cmd->rx_msdu_offset |=
96062306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_msdu_start_offset,
96162306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci		cmd->rx_attn_offset =
96462306a36Sopenharmony_ci			le32_encode_bits(tlv_filter->rx_attn_offset,
96562306a36Sopenharmony_ci					 HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET);
96662306a36Sopenharmony_ci	}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
96962306a36Sopenharmony_ci	if (ret)
97062306a36Sopenharmony_ci		goto err_free;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	return 0;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cierr_free:
97562306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	return ret;
97862306a36Sopenharmony_ci}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ciint
98162306a36Sopenharmony_ciath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
98262306a36Sopenharmony_ci				   struct htt_ext_stats_cfg_params *cfg_params,
98362306a36Sopenharmony_ci				   u64 cookie)
98462306a36Sopenharmony_ci{
98562306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
98662306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
98762306a36Sopenharmony_ci	struct sk_buff *skb;
98862306a36Sopenharmony_ci	struct htt_ext_stats_cfg_cmd *cmd;
98962306a36Sopenharmony_ci	int len = sizeof(*cmd);
99062306a36Sopenharmony_ci	int ret;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	skb = ath12k_htc_alloc_skb(ab, len);
99362306a36Sopenharmony_ci	if (!skb)
99462306a36Sopenharmony_ci		return -ENOMEM;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	skb_put(skb, len);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	cmd = (struct htt_ext_stats_cfg_cmd *)skb->data;
99962306a36Sopenharmony_ci	memset(cmd, 0, sizeof(*cmd));
100062306a36Sopenharmony_ci	cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	cmd->hdr.stats_type = type;
100562306a36Sopenharmony_ci	cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);
100662306a36Sopenharmony_ci	cmd->cfg_param1 = cpu_to_le32(cfg_params->cfg1);
100762306a36Sopenharmony_ci	cmd->cfg_param2 = cpu_to_le32(cfg_params->cfg2);
100862306a36Sopenharmony_ci	cmd->cfg_param3 = cpu_to_le32(cfg_params->cfg3);
100962306a36Sopenharmony_ci	cmd->cookie_lsb = cpu_to_le32(lower_32_bits(cookie));
101062306a36Sopenharmony_ci	cmd->cookie_msb = cpu_to_le32(upper_32_bits(cookie));
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
101362306a36Sopenharmony_ci	if (ret) {
101462306a36Sopenharmony_ci		ath12k_warn(ab, "failed to send htt type stats request: %d",
101562306a36Sopenharmony_ci			    ret);
101662306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
101762306a36Sopenharmony_ci		return ret;
101862306a36Sopenharmony_ci	}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	return 0;
102162306a36Sopenharmony_ci}
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ciint ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset)
102462306a36Sopenharmony_ci{
102562306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
102662306a36Sopenharmony_ci	int ret;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset);
102962306a36Sopenharmony_ci	if (ret) {
103062306a36Sopenharmony_ci		ath12k_err(ab, "failed to setup tx monitor filter %d\n", ret);
103162306a36Sopenharmony_ci		return ret;
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset);
103562306a36Sopenharmony_ci	if (ret) {
103662306a36Sopenharmony_ci		ath12k_err(ab, "failed to setup rx monitor filter %d\n", ret);
103762306a36Sopenharmony_ci		return ret;
103862306a36Sopenharmony_ci	}
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	return 0;
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ciint ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
104462306a36Sopenharmony_ci{
104562306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
104662306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
104762306a36Sopenharmony_ci	struct htt_rx_ring_tlv_filter tlv_filter = {0};
104862306a36Sopenharmony_ci	int ret, ring_id;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
105162306a36Sopenharmony_ci	tlv_filter.offset_valid = false;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	if (!reset) {
105462306a36Sopenharmony_ci		tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING;
105562306a36Sopenharmony_ci		tlv_filter.pkt_filter_flags0 =
105662306a36Sopenharmony_ci					HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 |
105762306a36Sopenharmony_ci					HTT_RX_MON_MO_MGMT_FILTER_FLAGS0;
105862306a36Sopenharmony_ci		tlv_filter.pkt_filter_flags1 =
105962306a36Sopenharmony_ci					HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 |
106062306a36Sopenharmony_ci					HTT_RX_MON_MO_MGMT_FILTER_FLAGS1;
106162306a36Sopenharmony_ci		tlv_filter.pkt_filter_flags2 =
106262306a36Sopenharmony_ci					HTT_RX_MON_FP_CTRL_FILTER_FLASG2 |
106362306a36Sopenharmony_ci					HTT_RX_MON_MO_CTRL_FILTER_FLASG2;
106462306a36Sopenharmony_ci		tlv_filter.pkt_filter_flags3 =
106562306a36Sopenharmony_ci					HTT_RX_MON_FP_CTRL_FILTER_FLASG3 |
106662306a36Sopenharmony_ci					HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
106762306a36Sopenharmony_ci					HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
106862306a36Sopenharmony_ci					HTT_RX_MON_MO_DATA_FILTER_FLASG3;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	if (ab->hw_params->rxdma1_enable) {
107262306a36Sopenharmony_ci		ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, 0,
107362306a36Sopenharmony_ci						       HAL_RXDMA_MONITOR_BUF,
107462306a36Sopenharmony_ci						       DP_RXDMA_REFILL_RING_SIZE,
107562306a36Sopenharmony_ci						       &tlv_filter);
107662306a36Sopenharmony_ci		if (ret) {
107762306a36Sopenharmony_ci			ath12k_err(ab,
107862306a36Sopenharmony_ci				   "failed to setup filter for monitor buf %d\n", ret);
107962306a36Sopenharmony_ci			return ret;
108062306a36Sopenharmony_ci		}
108162306a36Sopenharmony_ci	}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	return 0;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ciint ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,
108762306a36Sopenharmony_ci				     int mac_id, enum hal_ring_type ring_type,
108862306a36Sopenharmony_ci				     int tx_buf_size,
108962306a36Sopenharmony_ci				     struct htt_tx_ring_tlv_filter *htt_tlv_filter)
109062306a36Sopenharmony_ci{
109162306a36Sopenharmony_ci	struct htt_tx_ring_selection_cfg_cmd *cmd;
109262306a36Sopenharmony_ci	struct hal_srng *srng = &ab->hal.srng_list[ring_id];
109362306a36Sopenharmony_ci	struct hal_srng_params params;
109462306a36Sopenharmony_ci	struct sk_buff *skb;
109562306a36Sopenharmony_ci	int len = sizeof(*cmd);
109662306a36Sopenharmony_ci	enum htt_srng_ring_type htt_ring_type;
109762306a36Sopenharmony_ci	enum htt_srng_ring_id htt_ring_id;
109862306a36Sopenharmony_ci	int ret;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	skb = ath12k_htc_alloc_skb(ab, len);
110162306a36Sopenharmony_ci	if (!skb)
110262306a36Sopenharmony_ci		return -ENOMEM;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	memset(&params, 0, sizeof(params));
110562306a36Sopenharmony_ci	ath12k_hal_srng_get_params(ab, srng, &params);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
110862306a36Sopenharmony_ci					    ring_type, &htt_ring_type,
110962306a36Sopenharmony_ci					    &htt_ring_id);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	if (ret)
111262306a36Sopenharmony_ci		goto err_free;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	skb_put(skb, len);
111562306a36Sopenharmony_ci	cmd = (struct htt_tx_ring_selection_cfg_cmd *)skb->data;
111662306a36Sopenharmony_ci	cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_TX_MONITOR_CFG,
111762306a36Sopenharmony_ci				      HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
111862306a36Sopenharmony_ci	if (htt_ring_type == HTT_SW_TO_HW_RING ||
111962306a36Sopenharmony_ci	    htt_ring_type == HTT_HW_TO_SW_RING)
112062306a36Sopenharmony_ci		cmd->info0 |=
112162306a36Sopenharmony_ci			le32_encode_bits(DP_SW2HW_MACID(mac_id),
112262306a36Sopenharmony_ci					 HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
112362306a36Sopenharmony_ci	else
112462306a36Sopenharmony_ci		cmd->info0 |=
112562306a36Sopenharmony_ci			le32_encode_bits(mac_id,
112662306a36Sopenharmony_ci					 HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
112762306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(htt_ring_id,
112862306a36Sopenharmony_ci				       HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
112962306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
113062306a36Sopenharmony_ci				       HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS);
113162306a36Sopenharmony_ci	cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
113262306a36Sopenharmony_ci				       HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS);
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	cmd->info1 |=
113562306a36Sopenharmony_ci		le32_encode_bits(tx_buf_size,
113662306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	if (htt_tlv_filter->tx_mon_mgmt_filter) {
113962306a36Sopenharmony_ci		cmd->info1 |=
114062306a36Sopenharmony_ci			le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
114162306a36Sopenharmony_ci					 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
114262306a36Sopenharmony_ci		cmd->info1 |=
114362306a36Sopenharmony_ci		le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
114462306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);
114562306a36Sopenharmony_ci		cmd->info2 |=
114662306a36Sopenharmony_ci		le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
114762306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	if (htt_tlv_filter->tx_mon_data_filter) {
115162306a36Sopenharmony_ci		cmd->info1 |=
115262306a36Sopenharmony_ci			le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
115362306a36Sopenharmony_ci					 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
115462306a36Sopenharmony_ci		cmd->info1 |=
115562306a36Sopenharmony_ci		le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
115662306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);
115762306a36Sopenharmony_ci		cmd->info2 |=
115862306a36Sopenharmony_ci		le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
115962306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
116062306a36Sopenharmony_ci	}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if (htt_tlv_filter->tx_mon_ctrl_filter) {
116362306a36Sopenharmony_ci		cmd->info1 |=
116462306a36Sopenharmony_ci			le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
116562306a36Sopenharmony_ci					 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
116662306a36Sopenharmony_ci		cmd->info1 |=
116762306a36Sopenharmony_ci		le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
116862306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);
116962306a36Sopenharmony_ci		cmd->info2 |=
117062306a36Sopenharmony_ci		le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
117162306a36Sopenharmony_ci				 HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
117262306a36Sopenharmony_ci	}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	cmd->tlv_filter_mask_in0 =
117562306a36Sopenharmony_ci		cpu_to_le32(htt_tlv_filter->tx_mon_downstream_tlv_flags);
117662306a36Sopenharmony_ci	cmd->tlv_filter_mask_in1 =
117762306a36Sopenharmony_ci		cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags0);
117862306a36Sopenharmony_ci	cmd->tlv_filter_mask_in2 =
117962306a36Sopenharmony_ci		cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags1);
118062306a36Sopenharmony_ci	cmd->tlv_filter_mask_in3 =
118162306a36Sopenharmony_ci		cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags2);
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
118462306a36Sopenharmony_ci	if (ret)
118562306a36Sopenharmony_ci		goto err_free;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	return 0;
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_cierr_free:
119062306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
119162306a36Sopenharmony_ci	return ret;
119262306a36Sopenharmony_ci}
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ciint ath12k_dp_tx_htt_tx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
119562306a36Sopenharmony_ci{
119662306a36Sopenharmony_ci	struct ath12k_base *ab = ar->ab;
119762306a36Sopenharmony_ci	struct ath12k_dp *dp = &ab->dp;
119862306a36Sopenharmony_ci	struct htt_tx_ring_tlv_filter tlv_filter = {0};
119962306a36Sopenharmony_ci	int ret, ring_id;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	ring_id = dp->tx_mon_buf_ring.refill_buf_ring.ring_id;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	/* TODO: Need to set upstream/downstream tlv filters
120462306a36Sopenharmony_ci	 * here
120562306a36Sopenharmony_ci	 */
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	if (ab->hw_params->rxdma1_enable) {
120862306a36Sopenharmony_ci		ret = ath12k_dp_tx_htt_tx_filter_setup(ar->ab, ring_id, 0,
120962306a36Sopenharmony_ci						       HAL_TX_MONITOR_BUF,
121062306a36Sopenharmony_ci						       DP_RXDMA_REFILL_RING_SIZE,
121162306a36Sopenharmony_ci						       &tlv_filter);
121262306a36Sopenharmony_ci		if (ret) {
121362306a36Sopenharmony_ci			ath12k_err(ab,
121462306a36Sopenharmony_ci				   "failed to setup filter for monitor buf %d\n", ret);
121562306a36Sopenharmony_ci			return ret;
121662306a36Sopenharmony_ci		}
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	return 0;
122062306a36Sopenharmony_ci}
1221