From 842db6aafce0ef94922eeeddda21318c5cf4abb4 Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Mon, 7 Mar 2022 18:51:46 +0530 Subject: [PATCH] qcacmn: Update TX HP only for last TSO segment Currently HW TX queue HP value is updated for every TSO segment enqueue, as a part of optimization update HP only for the last segment. Change-Id: Ibe349a1e6f55932bf780e1f755f13841078a493f CRs-Fixed: 3138142 --- dp/wifi3.0/be/dp_be_tx.c | 2 +- dp/wifi3.0/dp_tx.c | 56 +++++++++++++++++++++++++++++++++++++--- dp/wifi3.0/dp_tx.h | 10 +++++-- dp/wifi3.0/li/dp_li_tx.c | 2 +- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index 137b49b620..07fe39df67 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/dp/wifi3.0/be/dp_be_tx.c @@ -652,7 +652,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev, /* Sync cached descriptor with HW */ hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); - coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid); + coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid, msdu_info); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length); DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1); diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 3735073311..07208745ab 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1439,7 +1439,8 @@ void dp_tx_update_stats(struct dp_soc *soc, int dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc, - uint8_t tid) + uint8_t tid, + struct dp_tx_msdu_info_s *msdu_info) { struct dp_swlm *swlm = &soc->swlm; union swlm_data swlm_query_data; @@ -1447,8 +1448,8 @@ dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, QDF_STATUS status; int ret; - if (qdf_unlikely(!swlm->is_enabled)) - return 0; + if (!swlm->is_enabled) + return msdu_info->skip_hp_update; tcl_data.nbuf = tx_desc->nbuf; tcl_data.tid = tid; @@ -1482,6 +1483,51 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, dp_tx_hal_ring_access_end(soc, hal_ring_hdl); } +static inline void +dp_tx_is_hp_update_required(uint32_t i, struct dp_tx_msdu_info_s *msdu_info) +{ + if (((i + 1) < msdu_info->num_seg)) + msdu_info->skip_hp_update = 1; + else + msdu_info->skip_hp_update = 0; +} + +static inline void +dp_flush_tcp_hp(struct dp_soc *soc, uint8_t ring_id) +{ + hal_ring_handle_t hal_ring_hdl = + dp_tx_get_hal_ring_hdl(soc, ring_id); + + if (dp_tx_hal_ring_access_start(soc, hal_ring_hdl)) { + dp_err("Fillmore: SRNG access start failed"); + return; + } + + dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, 0); +} + +static inline void +dp_tx_check_and_flush_hp(struct dp_soc *soc, + QDF_STATUS status, + struct dp_tx_msdu_info_s *msdu_info) +{ + if (QDF_IS_STATUS_ERROR(status) && !msdu_info->skip_hp_update) { + dp_flush_tcp_hp(soc, + (msdu_info->tx_queue.ring_id & DP_TX_QUEUE_MASK)); + } +} +#else +static inline void +dp_tx_is_hp_update_required(uint32_t i, struct dp_tx_msdu_info_s *msdu_info) +{ +} + +static inline void +dp_tx_check_and_flush_hp(struct dp_soc *soc, + QDF_STATUS status, + struct dp_tx_msdu_info_s *msdu_info) +{ +} #endif #ifdef FEATURE_RUNTIME_PM @@ -2379,6 +2425,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, DP_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1); } + dp_tx_is_hp_update_required(i, msdu_info); + /* * For frames with multiple segments (TSO, ME), jump to next * segment. @@ -2414,6 +2462,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, htt_tcl_metadata, NULL, msdu_info); + dp_tx_check_and_flush_hp(soc, status, msdu_info); + if (status != QDF_STATUS_SUCCESS) { dp_info_rl("Tx_hw_enqueue Fail tx_desc %pK queue %d", tx_desc, tx_q->ring_id); diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index 6d043503e1..328109138a 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -188,6 +188,7 @@ struct dp_tx_queue { * @ix_tx_sniffer: Indicates if the packet has to be sniffed * @gsn: global sequence for reinjected mcast packets * @vdev_id : vdev_id for reinjected mcast packets + * @skip_hp_update : Skip HP update for TSO segments and update in last segment * * This structure holds the complete MSDU information needed to program the * Hardware TCL and MSDU extension descriptors for different frame types @@ -212,6 +213,9 @@ struct dp_tx_msdu_info_s { uint8_t vdev_id; #endif #endif +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR + uint8_t skip_hp_update; +#endif }; #ifndef QCA_HOST_MODE_WIFI_DISABLED @@ -786,6 +790,7 @@ void dp_tx_update_stats(struct dp_soc *soc, * @soc: Datapath soc handle * @tx_desc: tx packet descriptor * @tid: TID for pkt transmission + * @msdu_info: MSDU info of tx packet * * Returns: 1, if coalescing is to be done * 0, if coalescing is not to be done @@ -793,7 +798,7 @@ void dp_tx_update_stats(struct dp_soc *soc, int dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc, - uint8_t tid); + uint8_t tid, struct dp_tx_msdu_info_s *msdu_info); /** * dp_tx_ring_access_end() - HAL ring access end for data transmission @@ -826,7 +831,8 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, static inline int dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc, - uint8_t tid) + uint8_t tid, + struct dp_tx_msdu_info_s *msdu_info) { return 0; } diff --git a/dp/wifi3.0/li/dp_li_tx.c b/dp/wifi3.0/li/dp_li_tx.c index 31b8349cb1..a552b1c140 100644 --- a/dp/wifi3.0/li/dp_li_tx.c +++ b/dp/wifi3.0/li/dp_li_tx.c @@ -502,7 +502,7 @@ dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev, tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX; dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); - coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid); + coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid, msdu_info); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length); DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1); dp_tx_update_stats(soc, tx_desc->nbuf);