From 93d245dc2e34d85a559bcc85fcdd1322b7f434c3 Mon Sep 17 00:00:00 2001 From: Ramanathan Choodamani Date: Tue, 7 Mar 2023 02:00:58 -0800 Subject: [PATCH 3/6] ath12k: Optimize the tx completion routine by avoid a function call context switch. Optimize the workdone calculation Signed-off-by: Balamurugan Mahalingam Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/dp_tx.c | 96 ++++++++++++++++----------------- 1 file changed, 46 insertions(+), 50 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -827,7 +827,7 @@ static void ath12k_dp_tx_complete_msdu(s struct sk_buff *msdu, struct hal_wbm_release_ring *tx_status, enum hal_wbm_rel_src_module buf_rel_source, - struct sk_buff *skb_ext_desc, int ring) + int ring) { struct ieee80211_tx_status status = { 0 }; struct ath12k_base *ab = ar->ab; @@ -837,49 +837,16 @@ static void ath12k_dp_tx_complete_msdu(s struct ath12k_link_sta *arsta; struct rate_info rate; struct hal_tx_status ts = { 0 }; - enum hal_wbm_tqm_rel_reason rel_status; enum hal_wbm_htt_tx_comp_status wbm_status; struct ieee80211_vif *vif; struct ath12k_vif *ahvif; u8 flags = 0; - - if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { - /* Must not happen */ - return; - } - skb_cb = ATH12K_SKB_CB(msdu); ab->soc_stats.tx_completed[ring]++; - dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); - if (unlikely(skb_cb->paddr_ext_desc)) { - dma_unmap_single_attrs(ab->dev, skb_cb->paddr_ext_desc, - skb_ext_desc->len, - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); - dev_kfree_skb_any(skb_ext_desc); - } flags = skb_cb->flags; - rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, - tx_status->info0); - - /* Free skb here if stats is disabled */ - if (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)) { - if (msdu->destructor) { - msdu->wifi_acked_valid = 1; - msdu->wifi_acked = rel_status == - HAL_WBM_TQM_REL_REASON_FRAME_ACKED; - } - if (skb_has_frag_list(msdu)) { - kfree_skb_list(skb_shinfo(msdu)->frag_list); - skb_shinfo(msdu)->frag_list = NULL; - } - dev_kfree_skb(msdu); - return; - } - ath12k_dp_tx_status_parse(ab, tx_status, &ts); ar->wmm_stats.tx_type = ath12k_tid_to_ac(ts.tid > ATH12K_DSCP_PRIORITY ? 0:ts.tid); @@ -1018,14 +985,18 @@ int ath12k_dp_tx_completion_handler(stru struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct ath12k_tx_desc_info *tx_desc = NULL; struct sk_buff *msdu, *skb_ext_desc; + struct ath12k_skb_cb *skb_cb; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; - u32 *desc, desc_id; + struct ath12k_vif *ahvif; + u32 desc_id; + u8 flags = 0; u8 mac_id; u64 desc_va; int valid_entries; - int workdone = 0; + int orig_budget = budget; struct hal_wbm_completion_ring_tx *tx_status; enum hal_wbm_rel_src_module buf_rel_source; + enum hal_wbm_tqm_rel_reason rel_status; ath12k_hal_srng_access_dst_ring_begin_nolock(ab, status_ring); @@ -1033,18 +1004,15 @@ int ath12k_dp_tx_completion_handler(stru valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); if (!valid_entries) { ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); - return workdone; + return 0; } ath12k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); - while (budget && (desc = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) { - if (!ath12k_dp_tx_completion_valid(desc)) + while (budget && (tx_status = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) { + if (!ath12k_dp_tx_completion_valid(tx_status)) continue; - tx_status = desc; - - if (likely(HAL_WBM_COMPL_TX_INFO0_CC_DONE & tx_status->info0)) { /* HW done cookie conversion */ desc_va = ((u64)tx_status->buf_va_hi << 32 | @@ -1081,20 +1049,63 @@ int ath12k_dp_tx_completion_handler(stru tx_desc); continue; } - workdone++; - ar = ab->pdevs[mac_id].ar; + budget--; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); - ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, - buf_rel_source, skb_ext_desc, - tx_ring->tcl_data_ring_id); - budget--; + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { + /* Must not happen */ + continue; + } + + skb_cb = (struct ath12k_skb_cb *)&IEEE80211_SKB_CB(msdu)->driver_data; + flags = skb_cb->flags; + dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (unlikely(skb_ext_desc)) { + dma_unmap_single_attrs(ab->dev, skb_cb->paddr_ext_desc, + skb_ext_desc->len, + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + dev_kfree_skb_any(skb_ext_desc); + } + /* Free skb here if stats is disabled */ + if (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)) { + ar->ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; + + if (skb_cb->vif) { + ahvif = (void *)skb_cb->vif->drv_priv; + if (ahvif->links_map & BIT(skb_cb->link_id)) + ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; + else + ath12k_warn(ab, + "invalid linkid 0x%X in tx completion handler for linkmap 0x%X\n", + skb_cb->link_id, + ahvif->links_map); + } + + if (unlikely(msdu->destructor)) { + msdu->wifi_acked_valid = 1; + rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, + tx_status->info0); + msdu->wifi_acked = rel_status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED; + } + if (unlikely(skb_has_frag_list(msdu))) { + kfree_skb_list(skb_shinfo(msdu)->frag_list); + skb_shinfo(msdu)->frag_list = NULL; + } + dev_kfree_skb(msdu); + } else { + ar = ab->pdevs[mac_id].ar; + + ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, + buf_rel_source, + tx_ring->tcl_data_ring_id); + } } ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); - return workdone; + return (orig_budget - budget); } static int