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
This commit is contained in:
Karthik Kantamneni
2022-03-07 18:51:46 +05:30
committed by Madan Koyyalamudi
parent fb2b00a1b9
commit 842db6aafc
4 changed files with 63 additions and 7 deletions

View File

@@ -652,7 +652,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
/* Sync cached descriptor with HW */ /* Sync cached descriptor with HW */
hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); 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_PKT(vdev, tx_i.processed, 1, tx_desc->length);
DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1); DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1);

View File

@@ -1439,7 +1439,8 @@ void dp_tx_update_stats(struct dp_soc *soc,
int int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, 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; struct dp_swlm *swlm = &soc->swlm;
union swlm_data swlm_query_data; 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; QDF_STATUS status;
int ret; int ret;
if (qdf_unlikely(!swlm->is_enabled)) if (!swlm->is_enabled)
return 0; return msdu_info->skip_hp_update;
tcl_data.nbuf = tx_desc->nbuf; tcl_data.nbuf = tx_desc->nbuf;
tcl_data.tid = tid; 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); 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 #endif
#ifdef FEATURE_RUNTIME_PM #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_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 * For frames with multiple segments (TSO, ME), jump to next
* segment. * segment.
@@ -2414,6 +2462,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
htt_tcl_metadata, htt_tcl_metadata,
NULL, msdu_info); NULL, msdu_info);
dp_tx_check_and_flush_hp(soc, status, msdu_info);
if (status != QDF_STATUS_SUCCESS) { if (status != QDF_STATUS_SUCCESS) {
dp_info_rl("Tx_hw_enqueue Fail tx_desc %pK queue %d", dp_info_rl("Tx_hw_enqueue Fail tx_desc %pK queue %d",
tx_desc, tx_q->ring_id); tx_desc, tx_q->ring_id);

View File

@@ -188,6 +188,7 @@ struct dp_tx_queue {
* @ix_tx_sniffer: Indicates if the packet has to be sniffed * @ix_tx_sniffer: Indicates if the packet has to be sniffed
* @gsn: global sequence for reinjected mcast packets * @gsn: global sequence for reinjected mcast packets
* @vdev_id : vdev_id 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 * This structure holds the complete MSDU information needed to program the
* Hardware TCL and MSDU extension descriptors for different frame types * Hardware TCL and MSDU extension descriptors for different frame types
@@ -212,6 +213,9 @@ struct dp_tx_msdu_info_s {
uint8_t vdev_id; uint8_t vdev_id;
#endif #endif
#endif #endif
#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR
uint8_t skip_hp_update;
#endif
}; };
#ifndef QCA_HOST_MODE_WIFI_DISABLED #ifndef QCA_HOST_MODE_WIFI_DISABLED
@@ -786,6 +790,7 @@ void dp_tx_update_stats(struct dp_soc *soc,
* @soc: Datapath soc handle * @soc: Datapath soc handle
* @tx_desc: tx packet descriptor * @tx_desc: tx packet descriptor
* @tid: TID for pkt transmission * @tid: TID for pkt transmission
* @msdu_info: MSDU info of tx packet
* *
* Returns: 1, if coalescing is to be done * Returns: 1, if coalescing is to be done
* 0, if coalescing is not 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 int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, 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 * 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 static inline int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, struct dp_tx_desc_s *tx_desc,
uint8_t tid) uint8_t tid,
struct dp_tx_msdu_info_s *msdu_info)
{ {
return 0; return 0;
} }

View File

@@ -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; tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf);
hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); 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_PKT(vdev, tx_i.processed, 1, tx_desc->length);
DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1); DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1);
dp_tx_update_stats(soc, tx_desc->nbuf); dp_tx_update_stats(soc, tx_desc->nbuf);