qcacmn: Restrict the tx descriptors for low mem config
For low mem config, use user configured max tx descriptors to limit the
allocation of software tx descriptors.
Use dp_txrx_pflow_update_pdev_params function to print stats and to update
pdev param.
Change-Id: I8fa6f0bb8841de68e8dc205ffcb0fde264f1b0e0
CRs-Fixed: 2414452
diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h
index d399ecb..05d461b 100644
--- a/dp/wifi3.0/dp_internal.h
+++ b/dp/wifi3.0/dp_internal.h
@@ -935,4 +935,21 @@
}
#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 04ac34d..74a630e 100644
--- a/dp/wifi3.0/dp_main.c
+++ b/dp/wifi3.0/dp_main.c
@@ -3424,6 +3424,8 @@
&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 @@
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 @@
#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 a3a10f4..4b89c81 100644
--- a/dp/wifi3.0/dp_stats.c
+++ b/dp/wifi3.0/dp_stats.c
@@ -3565,14 +3565,7 @@
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_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_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 193d7e6..35661ac 100644
--- a/dp/wifi3.0/dp_tx.c
+++ b/dp/wifi3.0/dp_tx.c
@@ -649,6 +649,39 @@
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_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 @@
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 561e219..2b1e68b 100644
--- a/dp/wifi3.0/dp_types.h
+++ b/dp/wifi3.0/dp_types.h
@@ -1393,6 +1393,9 @@
/* 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 315b32a..4e0198d 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 201d08e..c6c3d27 100644
--- a/wlan_cfg/wlan_cfg.c
+++ b/wlan_cfg/wlan_cfg.c
@@ -267,6 +267,7 @@
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 @@
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 2d3a4ca..dc6ca70 100644
--- a/wlan_cfg/wlan_cfg.h
+++ b/wlan_cfg/wlan_cfg.h
@@ -96,6 +96,7 @@
* @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 @@
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;
@@ -648,6 +650,14 @@
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
*
* @wlan_cfg_ctx - Configuration Handle