diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index d399ecbc1bc4..05d461b5e197 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -935,4 +935,21 @@ static inline void dp_peer_unref_del_find_by_id(struct dp_peer *peer) } #endif +#ifdef CONFIG_WIN +/** + * dp_pdev_print_delay_stats(): Print pdev level delay stats + * @pdev: DP_PDEV handle + * + * Return:void + */ +void dp_pdev_print_delay_stats(struct dp_pdev *pdev); + +/** + * dp_pdev_print_tid_stats(): Print pdev level tid stats + * @pdev: DP_PDEV handle + * + * Return:void + */ +void dp_pdev_print_tid_stats(struct dp_pdev *pdev); +#endif /* CONFIG_WIN */ #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 04ac34ddf312..74a630e8c486 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -3424,6 +3424,8 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, &dp_iterate_update_peer_list); qdf_event_create(&pdev->fw_peer_stats_event); + pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); + return (struct cdp_pdev *)pdev; fail1: @@ -9339,6 +9341,78 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) return value; } +#ifdef CONFIG_WIN +/** + * dp_tx_flow_ctrl_configure_pdev() - Configure flow control params + * @pdev_hdl: datapath pdev handle + * @param: ol ath params + * @value: value of the flag + * @buff: Buffer to be passed + * + * Implemented this function same as legacy function. In legacy code, single + * function is used to display stats and update pdev params. + * + * Return: 0 for success. nonzero for failure. + */ +static uint32_t dp_tx_flow_ctrl_configure_pdev(void *pdev_handle, + enum _ol_ath_param_t param, + uint32_t value, void *buff) +{ + struct dp_soc *soc = NULL; + struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + + if (qdf_unlikely(!pdev)) + return 1; + + soc = pdev->soc; + if (!soc) + return 1; + + switch (param) { + case OL_ATH_PARAM_VIDEO_DELAY_STATS_FC: + if (value) + pdev->delay_stats_flag = true; + else + pdev->delay_stats_flag = false; + break; + case OL_ATH_PARAM_VIDEO_STATS_FC: + qdf_print("------- TID Stats ------\n"); + dp_pdev_print_tid_stats(pdev); + qdf_print("------ Delay Stats ------\n"); + dp_pdev_print_delay_stats(pdev); + break; + case OL_ATH_PARAM_TOTAL_Q_SIZE: + { + uint32_t tx_min, tx_max; + + tx_min = wlan_cfg_get_min_tx_desc(soc->wlan_cfg_ctx); + tx_max = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); + + if (!buff) { + if ((value >= tx_min) && (value <= tx_max)) { + pdev->num_tx_allowed = value; + } else { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + "Failed to update num_tx_allowed, Q_min = %d Q_max = %d", + tx_min, tx_max); + break; + } + } else { + *(int *)buff = pdev->num_tx_allowed; + } + } + break; + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: not handled param %d ", __func__, param); + break; + } + + return 0; +} +#endif + static struct cdp_cmn_ops dp_ops_cmn = { .txrx_soc_attach_target = dp_soc_attach_target_wifi3, .txrx_vdev_attach = dp_vdev_attach_wifi3, @@ -9499,7 +9573,7 @@ static struct cdp_raw_ops dp_ops_raw = { #ifdef CONFIG_WIN static struct cdp_pflow_ops dp_ops_pflow = { - dp_pdev_tid_stats_display, + dp_tx_flow_ctrl_configure_pdev, }; #endif /* CONFIG_WIN */ diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index a3a10f4fe40e..4b89c81819c9 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -3565,14 +3565,7 @@ static inline const char *dp_vow_str_intfrm_delay(uint8_t index) return intfrm_delay_bucket[index]; } -/** - * dp_pdev_print_tid_stats(): Print pdev level tid stats - * @pdev: DP_PDEV handle - * - * Return:void - */ -static inline void -dp_pdev_print_tid_stats(struct dp_pdev *pdev) +void dp_pdev_print_tid_stats(struct dp_pdev *pdev) { struct cdp_tid_stats *tid_stats; struct cdp_tid_tx_stats *txstats; @@ -3640,14 +3633,7 @@ dp_pdev_print_tid_stats(struct dp_pdev *pdev) } } -/** - * dp_pdev_print_delay_stats(): Print pdev level delay stats - * @pdev: DP_PDEV handle - * - * Return:void - */ -static inline void -dp_pdev_print_delay_stats(struct dp_pdev *pdev) +void dp_pdev_print_delay_stats(struct dp_pdev *pdev) { struct dp_soc *soc = pdev->soc; struct cdp_tid_tx_stats *txstats = NULL; @@ -3736,47 +3722,4 @@ dp_pdev_print_delay_stats(struct dp_pdev *pdev) DP_PRINT_STATS("Avg = %u\n", rxstats->to_stack_delay.avg_delay); } } - -/** - * dp_pdev_tid_stats_display() - Pdev TID stats display - * @pdev_hdl: datapath pdev handle - * @param: ol ath params - * @value: value of the flag - * @buff: Buffer to be passed - * - * Return: 0 for success. nonzero for failure. - */ -uint32_t dp_pdev_tid_stats_display(void *pdev_handle, - enum _ol_ath_param_t param, uint32_t value, void *buff) -{ - struct dp_soc *soc = NULL; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - if (qdf_unlikely(!pdev)) - return 1; - - soc = pdev->soc; - if (!soc) - return 1; - - switch (param) { - case OL_ATH_PARAM_VIDEO_DELAY_STATS_FC: - if (value) - pdev->delay_stats_flag = true; - else - pdev->delay_stats_flag = false; - break; - case OL_ATH_PARAM_VIDEO_STATS_FC: - qdf_print("------- TID Stats ------\n"); - dp_pdev_print_tid_stats(pdev); - qdf_print("------ Delay Stats ------\n"); - dp_pdev_print_delay_stats(pdev); - break; - default: - qdf_print("%s: not handled param %d ", __func__, param); - break; - } - - return 0; -} #endif diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 193d7e68dacb..35661ac5f20d 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -649,6 +649,39 @@ static void dp_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id, msdu_id, QDF_TX)); } +#ifdef QCA_512M_CONFIG +/** + * dp_tx_pdev_pflow_control - Check if allocated tx descriptors reached max + * tx descriptor configured value + * @vdev: DP vdev handle + * + * Return: true if allocated tx descriptors reached max configured value, else + * false. + */ +static inline bool +dp_tx_pdev_pflow_control(struct dp_vdev *vdev) +{ + struct dp_pdev *pdev = vdev->pdev; + + if (qdf_atomic_read(&pdev->num_tx_outstanding) >= + pdev->num_tx_allowed) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: queued packets are more than max tx, drop the frame", + __func__); + DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); + return true; + } + + return false; +} +#else +static inline bool +dp_tx_pdev_pflow_control(struct dp_vdev *vdev) +{ + return false; +} +#endif + /** * dp_tx_desc_prepare_single - Allocate and prepare Tx descriptor * @vdev: DP vdev handle @@ -675,6 +708,9 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; + if (dp_tx_pdev_pflow_control(vdev)) + return NULL; + /* Allocate software Tx descriptor */ tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); if (qdf_unlikely(!tx_desc)) { @@ -810,6 +846,9 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; + if (dp_tx_pdev_pflow_control(vdev)) + return NULL; + /* Allocate software Tx descriptor */ tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); if (!tx_desc) { diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 561e219aa305..2b1e68b00b34 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1393,6 +1393,9 @@ struct dp_pdev { /* qdf_event for fw_peer_stats */ qdf_event_t fw_peer_stats_event; + + /* User configured max number of tx buffers */ + uint32_t num_tx_allowed; }; struct dp_peer; diff --git a/wlan_cfg/cfg_dp.h b/wlan_cfg/cfg_dp.h index 315b32a79a50..4e0198d55ac7 100644 --- a/wlan_cfg/cfg_dp.h +++ b/wlan_cfg/cfg_dp.h @@ -143,7 +143,7 @@ #define WLAN_CFG_TX_COMP_RING_SIZE_MAX 0x80000 #define WLAN_CFG_NUM_TX_DESC_MIN 1024 -#define WLAN_CFG_NUM_TX_DESC_MAX 0x320000 +#define WLAN_CFG_NUM_TX_DESC_MAX 32768 #define WLAN_CFG_NUM_TX_EXT_DESC_MIN 1024 #define WLAN_CFG_NUM_TX_EXT_DESC_MAX 0x80000 diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index 201d08e1b651..c6c3d271e38d 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/wlan_cfg/wlan_cfg.c @@ -267,6 +267,7 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *psoc) wlan_cfg_ctx->num_tx_ext_desc_pool = cfg_get(psoc, CFG_DP_TX_EXT_DESC_POOLS); wlan_cfg_ctx->num_tx_desc = cfg_get(psoc, CFG_DP_TX_DESC); + wlan_cfg_ctx->min_tx_desc = WLAN_CFG_NUM_TX_DESC_MIN; wlan_cfg_ctx->num_tx_ext_desc = cfg_get(psoc, CFG_DP_TX_EXT_DESC); wlan_cfg_ctx->htt_packet_type = cfg_get(psoc, CFG_DP_HTT_PACKET_TYPE); wlan_cfg_ctx->max_peer_id = cfg_get(psoc, CFG_DP_MAX_PEER_ID); @@ -684,6 +685,11 @@ void wlan_cfg_set_num_tx_desc(struct wlan_cfg_dp_soc_ctxt *cfg, int num_desc) cfg->num_tx_desc = num_desc; } +int wlan_cfg_get_min_tx_desc(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->min_tx_desc; +} + int wlan_cfg_get_num_tx_ext_desc(struct wlan_cfg_dp_soc_ctxt *cfg) { return cfg->num_tx_ext_desc; diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index 2d3a4ca5aecd..dc6ca70a791f 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/wlan_cfg/wlan_cfg.h @@ -96,6 +96,7 @@ struct wlan_cfg_dp_pdev_ctxt; * @num_tx_desc_pool: Number of Tx Descriptor pools * @num_tx_ext_desc_pool: Number of Tx MSDU extension Descriptor pools * @num_tx_desc: Number of Tx Descriptors per pool + * @min_tx_desc: Minimum number of Tx Descriptors per pool * @num_tx_ext_desc: Number of Tx MSDU extension Descriptors per pool * @max_peer_id: Maximum value of peer id that FW can assign for a client * @htt_packet_type: Default 802.11 encapsulation type for any VAP created @@ -149,6 +150,7 @@ struct wlan_cfg_dp_soc_ctxt { int num_tx_desc_pool; int num_tx_ext_desc_pool; int num_tx_desc; + int min_tx_desc; int num_tx_ext_desc; int max_peer_id; int htt_packet_type; @@ -647,6 +649,14 @@ void wlan_cfg_set_num_tx_ext_desc_pool(struct wlan_cfg_dp_soc_ctxt *cfg, int num */ int wlan_cfg_get_num_tx_desc(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx); +/* + * wlan_cfg_get_min_tx_desc() - Minimum number of Tx Descriptors per pool + * @wlan_cfg_ctx - Configuration Handle + * + * Return: num_tx_desc + */ +int wlan_cfg_get_min_tx_desc(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx); + /* * wlan_cfg_set_num_tx_desc() - Set the number of Tx Descriptors per pool *