diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 85983986c3..f6f547c815 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -41,6 +41,9 @@ #include "dp_txrx_me.h" #endif #include "dp_hist.h" +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR +#include +#endif /* Flag to skip CCE classify when mesh or tid override enabled */ #define DP_TX_SKIP_CCE_CLASSIFY \ @@ -430,7 +433,6 @@ static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, hal_tx_ext_desc_set_tcp_seq(ext_desc, tso_seg->tso_flags.tcp_seq_num); hal_tx_ext_desc_set_ip_id(ext_desc, tso_seg->tso_flags.ip_id); - for (num_frag = 0; num_frag < tso_seg->num_frags; num_frag++) { uint32_t lo = 0; uint32_t hi = 0; @@ -1143,11 +1145,90 @@ static inline void dp_tx_update_stats(struct dp_soc *soc, { DP_STATS_INC_PKT(soc, tx.egress, 1, qdf_nbuf_len(nbuf)); } + +/** + * dp_tx_attempt_coalescing() - Check and attempt TCL register write coalescing + * @soc: Datapath soc handle + * @tx_desc: tx packet descriptor + * @tid: TID for pkt transmission + * + * Returns: 1, if coalescing is to be done + * 0, if coalescing is not to be done + */ +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) +{ + struct dp_swlm *swlm = &soc->swlm; + union swlm_data swlm_query_data; + struct dp_swlm_tcl_data tcl_data; + QDF_STATUS status; + int ret; + + if (qdf_unlikely(!swlm->is_enabled)) + return 0; + + tcl_data.nbuf = tx_desc->nbuf; + tcl_data.tid = tid; + tcl_data.num_ll_connections = vdev->num_latency_critical_conn; + swlm_query_data.tcl_data = &tcl_data; + + status = dp_swlm_tcl_pre_check(soc, &tcl_data); + if (QDF_IS_STATUS_ERROR(status)) { + dp_swlm_tcl_reset_session_data(soc); + return 0; + } + + ret = dp_swlm_query_policy(soc, TCL_DATA, swlm_query_data); + if (ret) { + DP_STATS_INC(swlm, tcl.coalesc_success, 1); + } else { + DP_STATS_INC(swlm, tcl.coalesc_fail, 1); + } + + return ret; +} + +/** + * dp_tx_ring_access_end() - HAL ring access end for data transmission + * @soc: Datapath soc handle + * @hal_ring_hdl: HAL ring handle + * @coalesc: Coalesc the current write or not + * + * Returns: none + */ +static inline void +dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, + int coalesc) +{ + if (coalesc) + dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl); + else + dp_tx_hal_ring_access_end(soc, hal_ring_hdl); +} + #else static inline void dp_tx_update_stats(struct dp_soc *soc, qdf_nbuf_t nbuf) { } + +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) +{ + return 0; +} + +static inline void +dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, + int coalesc) +{ + dp_tx_hal_ring_access_end(soc, hal_ring_hdl); +} + #endif /** * dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit @@ -1174,6 +1255,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, uint8_t type; void *hal_tx_desc; uint32_t *hal_tx_desc_cached; + int coalesc = 0; /* * Setting it initialization statically here to avoid @@ -1291,6 +1373,7 @@ static QDF_STATUS dp_tx_hw_enqueue(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); + coalesc = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length); dp_tx_update_stats(soc, tx_desc->nbuf); status = QDF_STATUS_SUCCESS; @@ -1298,7 +1381,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, ring_access_fail: if (hif_pm_runtime_get(soc->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE) == 0) { - dp_tx_hal_ring_access_end(soc, hal_ring_hdl); + dp_tx_ring_access_end(soc, hal_ring_hdl, coalesc); hif_pm_runtime_put(soc->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE); } else { diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 03d78bb0a4..04d4ae033b 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1132,6 +1132,7 @@ struct dp_last_op_info { * descision making * @nbuf: TX packet * @tid: tid for transmitting the current packet + * @num_ll_connections: Number of low latency connections on this vdev * * This structure contains the information required by the software * latency manager to decide on whether to coalesc the current TCL @@ -1140,6 +1141,7 @@ struct dp_last_op_info { struct dp_swlm_tcl_data { qdf_nbuf_t nbuf; uint8_t tid; + uint8_t num_ll_connections; }; /** @@ -1168,12 +1170,16 @@ struct dp_swlm_ops { * was being transmitted on a TID above coalescing threshold * @tcl.sp_frames: Num TCL register write coalescing skips, since the pkt * being transmitted was a special frame + * @tcl.ll_connection: Num TCL register write coalescing skips, since the + * vdev has low latency connections * @tcl.bytes_thresh_reached: Num TCL HP writes flush after the coalescing * bytes threshold was reached * @tcl.time_thresh_reached: Num TCL HP writes flush after the coalescing * session time expired * @tcl.tput_criteria_fail: Num TCL HP writes coalescing fails, since the * throughput did not meet session threshold + * @tcl.coalesc_success: Num of TCL HP writes coalesced successfully. + * @tcl.coalesc_fail: Num of TCL HP writes coalesces failed */ struct dp_swlm_stats { struct { @@ -1181,9 +1187,12 @@ struct dp_swlm_stats { uint32_t timer_flush_fail; uint32_t tid_fail; uint32_t sp_frames; + uint32_t ll_connection; uint32_t bytes_thresh_reached; uint32_t time_thresh_reached; uint32_t tput_criteria_fail; + uint32_t coalesc_success; + uint32_t coalesc_fail; } tcl; }; @@ -1202,6 +1211,8 @@ struct dp_swlm_stats { * @tcl.tx_thresh_multiplier: Multiplier to deduce the bytes threshold after * which the TCL HP register is written, thereby * ending the coalescing. + * @tcl.coalesc_end_time: End timestamp for current coalescing session + * @tcl.bytes_coalesced: Num bytes coalesced in the current session */ struct dp_swlm_params { struct { @@ -1213,6 +1224,8 @@ struct dp_swlm_params { uint32_t bytes_flush_thresh; uint32_t time_flush_thresh; uint32_t tx_thresh_multiplier; + uint64_t coalesc_end_time; + uint32_t bytes_coalesced; } tcl; };