qcacld-3.0: Add ini keys for WRR tx scheduler tuning

qcacld-2.0 to qcacld-3.0 propagation

Add below four keys to allow user to tune WRR TX scheduler params.
Each key is mapping to one AC defined in data path module through
OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC.
	gEnableTxSchedWrrBE
	gEnableTxSchedWrrBK
	gEnableTxSchedWrrVI
	gEnableTxSchedWrrVO

Change-Id: I5c34b604297d83673ea065243cc58c3f2180ff3e
CRs-Fixed: 1020141
diff --git a/core/cds/inc/cds_config.h b/core/cds/inc/cds_config.h
index 3674939..01f3d2a 100644
--- a/core/cds/inc/cds_config.h
+++ b/core/cds/inc/cds_config.h
@@ -27,6 +27,9 @@
 #if !defined(__CDS_CONFIG_H)
 #define __CDS_CONFIG_H
 
+#include "osdep.h"
+#include "cdp_txrx_mob_def.h"
+
 /**
  * enum driver_type - Indicate the driver type to the cds, and based on this
  * do appropriate initialization.
@@ -148,5 +151,7 @@
 	bool flow_steering_enabled;
 	bool self_recovery_enabled;
 	bool fw_timeout_crash;
+
+	struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM];
 };
 #endif /* !defined( __CDS_CONFIG_H ) */
diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h
index 6ee1d00..960cb81 100644
--- a/core/cds/inc/cds_sched.h
+++ b/core/cds/inc/cds_sched.h
@@ -243,6 +243,8 @@
 
 	/* This is to track if HW mode change is in progress */
 	uint32_t hw_mode_change_in_progress;
+
+	struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM];
 } cds_context_type, *p_cds_contextType;
 
 /*---------------------------------------------------------------------------
diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c
index be39a1c..cbbc7bb 100644
--- a/core/cds/src/cds_api.c
+++ b/core/cds/src/cds_api.c
@@ -170,6 +170,39 @@
 #endif
 
 /**
+ * cds_cfg_update_ac_specs_params() - update ac_specs params
+ * @olcfg: cfg handle
+ * @mac_params: mac params
+ *
+ * Return: none
+ */
+static void
+cds_cfg_update_ac_specs_params(struct txrx_pdev_cfg_param_t *olcfg,
+		struct cds_config_info *cds_cfg)
+{
+	int i;
+
+	if (NULL == olcfg)
+		return;
+
+	if (NULL == cds_cfg)
+		return;
+
+	for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
+		olcfg->ac_specs[i].wrr_skip_weight =
+			cds_cfg->ac_specs[i].wrr_skip_weight;
+		olcfg->ac_specs[i].credit_threshold =
+			cds_cfg->ac_specs[i].credit_threshold;
+		olcfg->ac_specs[i].send_limit =
+			cds_cfg->ac_specs[i].send_limit;
+		olcfg->ac_specs[i].credit_reserve =
+			cds_cfg->ac_specs[i].credit_reserve;
+		olcfg->ac_specs[i].discard_weight =
+			cds_cfg->ac_specs[i].discard_weight;
+	}
+}
+
+/**
  * cds_cdp_cfg_attach() - attach data path config module
  * @cds_cfg: generic platform level config instance
  *
@@ -191,6 +224,7 @@
 			cds_cfg->ip_tcp_udp_checksum_offload;
 	cdp_cfg.ce_classify_enabled = cds_cfg->ce_classify_enabled;
 
+	cds_cfg_update_ac_specs_params(&cdp_cfg, cds_cfg);
 	gp_cds_context->cfg_ctx = cdp_cfg_attach(soc, gp_cds_context->qdf_ctx,
 					(void *)(&cdp_cfg));
 	if (!gp_cds_context->cfg_ctx) {
@@ -260,6 +294,35 @@
 }
 
 /**
+ * cds_set_ac_specs_params() - set ac_specs params in cds_config_info
+ * @cds_cfg: Pointer to cds_config_info
+ * @hdd_ctx: Pointer to hdd context
+ *
+ * Return: none
+ */
+static void
+cds_set_ac_specs_params(struct cds_config_info *cds_cfg)
+{
+	int i;
+	cds_context_type *cds_ctx;
+
+	if (NULL == cds_cfg)
+		return;
+
+	cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
+
+	if (!cds_ctx) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			"Invalid CDS Context");
+		return;
+	}
+
+	for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
+		cds_cfg->ac_specs[i] = cds_ctx->ac_specs[i];
+	}
+}
+
+/**
  * cds_open() - open the CDS Module
  *
  * cds_open() function opens the CDS Scheduler
@@ -452,6 +515,8 @@
 			gp_cds_context->htc_ctx, gp_cds_context->qdf_ctx,
 			&dp_ol_if_ops);
 
+	cds_set_ac_specs_params(cds_cfg);
+
 	cds_cdp_cfg_attach(cds_cfg);
 
 	/* Now proceed to open the MAC */
diff --git a/core/dp/ol/inc/ol_cfg.h b/core/dp/ol/inc/ol_cfg.h
index 108fd48..aa03ef7 100644
--- a/core/dp/ol/inc/ol_cfg.h
+++ b/core/dp/ol/inc/ol_cfg.h
@@ -39,6 +39,7 @@
 #endif
 #include "ol_txrx_ctrl_api.h"   /* txrx_pdev_cfg_param_t */
 #include <cdp_txrx_handle.h>
+
 /**
  * @brief format of data frames delivered to/from the WLAN driver by/to the OS
  */
@@ -94,6 +95,8 @@
 	uint32_t tx_flow_start_queue_offset;
 #endif
 	bool flow_steering_enabled;
+
+	struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM];
 };
 
 /**
@@ -637,4 +640,49 @@
 
 	return cfg->flow_steering_enabled;
 }
+
+/**
+ * ol_cfg_get_wrr_skip_weight() - brief Query for the param of wrr_skip_weight
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: wrr_skip_weight for specified ac.
+ */
+int ol_cfg_get_wrr_skip_weight(ol_pdev_handle pdev, int ac);
+
+/**
+ * ol_cfg_get_credit_threshold() - Query for the param of credit_threshold
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: credit_threshold for specified ac.
+ */
+uint32_t ol_cfg_get_credit_threshold(ol_pdev_handle pdev, int ac);
+
+/**
+ * ol_cfg_get_send_limit() - Query for the param of send_limit
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: send_limit for specified ac.
+ */
+uint16_t ol_cfg_get_send_limit(ol_pdev_handle pdev, int ac);
+
+/**
+ * ol_cfg_get_credit_reserve() - Query for the param of credit_reserve
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: credit_reserve for specified ac.
+ */
+int ol_cfg_get_credit_reserve(ol_pdev_handle pdev, int ac);
+
+/**
+ * ol_cfg_get_discard_weight() - Query for the param of discard_weight
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: discard_weight for specified ac.
+ */
+int ol_cfg_get_discard_weight(ol_pdev_handle pdev, int ac);
 #endif /* _OL_CFG__H_ */
diff --git a/core/dp/txrx/ol_cfg.c b/core/dp/txrx/ol_cfg.c
index 25eb690..8fbceb6 100644
--- a/core/dp/txrx/ol_cfg.c
+++ b/core/dp/txrx/ol_cfg.c
@@ -103,6 +103,7 @@
 {
 	struct txrx_pdev_cfg_param_t *cfg_param = pcfg_param;
 	struct txrx_pdev_cfg_t *cfg_ctx;
+	int i;
 
 	cfg_ctx = qdf_mem_malloc(sizeof(*cfg_ctx));
 	if (!cfg_ctx) {
@@ -144,6 +145,20 @@
 	cfg_ctx->ce_classify_enabled = cfg_param->ce_classify_enabled;
 
 	ol_tx_set_flow_control_parameters((struct cdp_cfg *)cfg_ctx, cfg_param);
+
+	for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
+		cfg_ctx->ac_specs[i].wrr_skip_weight =
+			cfg_param->ac_specs[i].wrr_skip_weight;
+		cfg_ctx->ac_specs[i].credit_threshold =
+			cfg_param->ac_specs[i].credit_threshold;
+		cfg_ctx->ac_specs[i].send_limit =
+			cfg_param->ac_specs[i].send_limit;
+		cfg_ctx->ac_specs[i].credit_reserve =
+			cfg_param->ac_specs[i].credit_reserve;
+		cfg_ctx->ac_specs[i].discard_weight =
+			cfg_param->ac_specs[i].discard_weight;
+	}
+
 	return (struct cdp_cfg *)cfg_ctx;
 }
 
@@ -388,3 +403,88 @@
 	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)cfg_pdev;
 	return cfg->ce_classify_enabled;
 }
+
+/**
+ * ol_cfg_get_wrr_skip_weight() - brief Query for the param of wrr_skip_weight
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: wrr_skip_weight for specified ac.
+ */
+int ol_cfg_get_wrr_skip_weight(ol_pdev_handle pdev, int ac)
+{
+	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev;
+
+	if (ac >= OL_TX_WMM_AC_BE && ac <= OL_TX_WMM_AC_VO)
+		return cfg->ac_specs[ac].wrr_skip_weight;
+
+	return 0;
+}
+
+/**
+ * ol_cfg_get_credit_threshold() - Query for the param of credit_threshold
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: credit_threshold for specified ac.
+ */
+uint32_t ol_cfg_get_credit_threshold(ol_pdev_handle pdev, int ac)
+{
+	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev;
+
+	if (ac >= OL_TX_WMM_AC_BE && ac <= OL_TX_WMM_AC_VO)
+		return cfg->ac_specs[ac].credit_threshold;
+
+	return 0;
+}
+
+/**
+ * ol_cfg_get_send_limit() - Query for the param of send_limit
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: send_limit for specified ac.
+ */
+uint16_t ol_cfg_get_send_limit(ol_pdev_handle pdev, int ac)
+{
+	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev;
+
+	if (ac >= OL_TX_WMM_AC_BE && ac <= OL_TX_WMM_AC_VO)
+		return cfg->ac_specs[ac].send_limit;
+
+	return 0;
+}
+
+/**
+ * ol_cfg_get_credit_reserve() - Query for the param of credit_reserve
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: credit_reserve for specified ac.
+ */
+int ol_cfg_get_credit_reserve(ol_pdev_handle pdev, int ac)
+{
+	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev;
+
+	if (ac >= OL_TX_WMM_AC_BE && ac <= OL_TX_WMM_AC_VO)
+		return cfg->ac_specs[ac].credit_reserve;
+
+	return 0;
+}
+
+/**
+ * ol_cfg_get_discard_weight() - Query for the param of discard_weight
+ * @pdev: handle to the physical device.
+ * @ac: access control, it will be BE, BK, VI, VO
+ *
+ * Return: discard_weight for specified ac.
+ */
+int ol_cfg_get_discard_weight(ol_pdev_handle pdev, int ac)
+{
+	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev;
+
+	if (ac >= OL_TX_WMM_AC_BE && ac <= OL_TX_WMM_AC_VO)
+		return cfg->ac_specs[ac].discard_weight;
+
+	return 0;
+}
diff --git a/core/dp/txrx/ol_tx_sched.c b/core/dp/txrx/ol_tx_sched.c
index 126fd8a..edf6985 100644
--- a/core/dp/txrx/ol_tx_sched.c
+++ b/core/dp/txrx/ol_tx_sched.c
@@ -1009,6 +1009,72 @@
 	*bytes = category->state.bytes;
 }
 
+/**
+ * ol_tx_sched_wrr_param_update() - update the WRR TX sched params
+ * @pdev: Pointer to PDEV structure.
+ * @scheduler: Pointer to tx scheduler.
+ *
+ * Update the WRR TX schedule parameters for each category if it is
+ * specified in the ini file by user.
+ *
+ * Return: none
+ */
+void ol_tx_sched_wrr_param_update(struct ol_txrx_pdev_t *pdev,
+				struct ol_tx_sched_wrr_adv_t *scheduler)
+{
+	int i;
+	static const char * const tx_sched_wrr_name[4] = {
+		"BE",
+		"BK",
+		"VI",
+		"VO"
+	};
+
+	if (NULL == scheduler)
+		return;
+
+	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
+		"%s: Tuning the TX scheduler wrr parameters by ini file:",
+		__func__);
+
+	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
+		"         skip credit limit credit disc");
+
+	for (i = OL_TX_SCHED_WRR_ADV_CAT_BE;
+		i <= OL_TX_SCHED_WRR_ADV_CAT_VO; i++) {
+		if (ol_cfg_get_wrr_skip_weight(pdev->ctrl_pdev, i)) {
+			scheduler->categories[i].specs.wrr_skip_weight =
+				ol_cfg_get_wrr_skip_weight(pdev->ctrl_pdev, i);
+			scheduler->categories[i].specs.credit_threshold =
+				ol_cfg_get_credit_threshold(pdev->ctrl_pdev, i);
+			scheduler->categories[i].specs.send_limit =
+				ol_cfg_get_send_limit(pdev->ctrl_pdev, i);
+			scheduler->categories[i].specs.credit_reserve =
+				ol_cfg_get_credit_reserve(pdev->ctrl_pdev, i);
+			scheduler->categories[i].specs.discard_weight =
+				ol_cfg_get_discard_weight(pdev->ctrl_pdev, i);
+
+			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
+				"%s-update: %d,  %d,    %d,   %d,    %d",
+				tx_sched_wrr_name[i],
+				scheduler->categories[i].specs.wrr_skip_weight,
+				scheduler->categories[i].specs.credit_threshold,
+				scheduler->categories[i].specs.send_limit,
+				scheduler->categories[i].specs.credit_reserve,
+				scheduler->categories[i].specs.discard_weight);
+		} else {
+			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
+				"%s-orig: %d,  %d,    %d,   %d,    %d",
+				tx_sched_wrr_name[i],
+				scheduler->categories[i].specs.wrr_skip_weight,
+				scheduler->categories[i].specs.credit_threshold,
+				scheduler->categories[i].specs.send_limit,
+				scheduler->categories[i].specs.credit_reserve,
+				scheduler->categories[i].specs.discard_weight);
+		}
+	}
+}
+
 void *
 ol_tx_sched_init_wrr_adv(
 		struct ol_txrx_pdev_t *pdev)
@@ -1030,6 +1096,8 @@
 	OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(MCAST_DATA, scheduler);
 	OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(MCAST_MGMT, scheduler);
 
+	ol_tx_sched_wrr_param_update(pdev, scheduler);
+
 	for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; i++) {
 		scheduler->categories[i].state.active = 0;
 		scheduler->categories[i].state.frms = 0;
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index f2e499f..4350966 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -47,6 +47,8 @@
 #include <wmi_unified.h>
 
 #define FW_MODULE_LOG_LEVEL_STRING_LENGTH  (255)
+#define TX_SCHED_WRR_PARAM_STRING_LENGTH   (50)
+#define TX_SCHED_WRR_PARAMS_NUM            (5)
 
 #define CFG_ENABLE_RX_THREAD		(1 << 0)
 #define CFG_ENABLE_RPS			(1 << 1)
@@ -7817,6 +7819,58 @@
 #define CFG_EDCA_BE_AIFS_VALUE_DEFAULT    (3)
 
 /*
+ * <ini>
+ * gEnableTxSchedWrrVO - Set TX sched parameters for VO
+ * @Default:
+ *
+ * This key is mapping to VO defined in data path module through
+ * OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC. The user can tune the
+ * WRR TX sched parameters such as skip, credit, limit, credit, disc for VO.
+ * e.g., gEnableTxSchedWrrVO = 10, 9, 8, 1, 8
+ */
+#define CFG_ENABLE_TX_SCHED_WRR_VO_NAME     "gEnableTxSchedWrrVO"
+#define CFG_ENABLE_TX_SCHED_WRR_VO_DEFAULT  ""
+
+/*
+ * <ini>
+ * gEnableTxSchedWrrVI - Set TX sched parameters for VI
+ * @Default:
+ *
+ * This key is mapping to VI defined in data path module through
+ * OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC. The user can tune the
+ * WRR TX sched parameters such as skip, credit, limit, credit, disc for VI.
+ * e.g., gEnableTxSchedWrrVI = 10, 9, 8, 1, 8
+ */
+#define CFG_ENABLE_TX_SCHED_WRR_VI_NAME     "gEnableTxSchedWrrVI"
+#define CFG_ENABLE_TX_SCHED_WRR_VI_DEFAULT  ""
+
+/*
+ * <ini>
+ * gEnableTxSchedWrrBE - Set TX sched parameters for BE
+ * @Default:
+ *
+ * This key is mapping to BE defined in data path module through
+ * OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC. The user can tune the
+ * WRR TX sched parameters such as skip, credit, limit, credit, disc for BE.
+ * e.g., gEnableTxSchedWrrBE = 10, 9, 8, 1, 8
+ */
+#define CFG_ENABLE_TX_SCHED_WRR_BE_NAME     "gEnableTxSchedWrrBE"
+#define CFG_ENABLE_TX_SCHED_WRR_BE_DEFAULT  ""
+
+/*
+ * <ini>
+ * gEnableTxSchedWrrBK - Set TX sched parameters for BK
+ * @Default:
+ *
+ * This key is mapping to BK defined in data path module through
+ * OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC. The user can tune the
+ * WRR TX sched parameters such as skip, credit, limit, credit, disc for BK.
+ * e.g., gEnableTxSchedWrrBK = 10, 9, 8, 1, 8
+ */
+#define CFG_ENABLE_TX_SCHED_WRR_BK_NAME     "gEnableTxSchedWrrBK"
+#define CFG_ENABLE_TX_SCHED_WRR_BK_DEFAULT  ""
+
+/*
  * Enable/disable DPTRACE
  * Enabling this might have performace impact.
  */
@@ -9439,6 +9493,16 @@
 	uint32_t edca_vi_aifs;
 	uint32_t edca_bk_aifs;
 	uint32_t edca_be_aifs;
+
+	/* Tuning TX sched parameters for VO (skip credit limit credit disc) */
+	uint8_t  tx_sched_wrr_vo[TX_SCHED_WRR_PARAM_STRING_LENGTH];
+	/* Tuning TX sched parameters for VI (skip credit limit credit disc) */
+	uint8_t  tx_sched_wrr_vi[TX_SCHED_WRR_PARAM_STRING_LENGTH];
+	/* Tuning TX sched parameters for BE (skip credit limit credit disc) */
+	uint8_t  tx_sched_wrr_be[TX_SCHED_WRR_PARAM_STRING_LENGTH];
+	/* Tuning TX sched parameters for BK (skip credit limit credit disc) */
+	uint8_t  tx_sched_wrr_bk[TX_SCHED_WRR_PARAM_STRING_LENGTH];
+
 	bool enable_fatal_event;
 	bool bpf_enabled;
 	bool enable_dp_trace;
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index d2e669b..0fba019 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -3927,6 +3927,31 @@
 			CFG_EDCA_BE_AIFS_VALUE_DEFAULT,
 			CFG_EDCA_BE_AIFS_VALUE_MIN,
 			CFG_EDCA_BE_AIFS_VALUE_MAX),
+
+	REG_VARIABLE_STRING(CFG_ENABLE_TX_SCHED_WRR_VO_NAME,
+			WLAN_PARAM_String,
+			struct hdd_config, tx_sched_wrr_vo,
+			VAR_FLAGS_OPTIONAL,
+			(void *) CFG_ENABLE_TX_SCHED_WRR_VO_DEFAULT),
+
+	REG_VARIABLE_STRING(CFG_ENABLE_TX_SCHED_WRR_VI_NAME,
+			WLAN_PARAM_String,
+			struct hdd_config, tx_sched_wrr_vi,
+			VAR_FLAGS_OPTIONAL,
+			(void *) CFG_ENABLE_TX_SCHED_WRR_VI_DEFAULT),
+
+	REG_VARIABLE_STRING(CFG_ENABLE_TX_SCHED_WRR_BE_NAME,
+			WLAN_PARAM_String,
+			struct hdd_config, tx_sched_wrr_be,
+			VAR_FLAGS_OPTIONAL,
+			(void *) CFG_ENABLE_TX_SCHED_WRR_BE_DEFAULT),
+
+	REG_VARIABLE_STRING(CFG_ENABLE_TX_SCHED_WRR_BK_NAME,
+			WLAN_PARAM_String,
+			struct hdd_config, tx_sched_wrr_bk,
+			VAR_FLAGS_OPTIONAL,
+			(void *) CFG_ENABLE_TX_SCHED_WRR_BK_DEFAULT),
+
 #ifdef WLAN_FEATURE_NAN_DATAPATH
 	REG_VARIABLE(CFG_ENABLE_NAN_DATAPATH_NAME, WLAN_PARAM_Integer,
 		struct hdd_config, enable_nan_datapath,
@@ -5548,6 +5573,20 @@
 	hdd_info("Name = [%s] Value = [%u]",
 		CFG_EDCA_BE_AIFS_VALUE_NAME,
 		pHddCtx->config->edca_be_aifs);
+
+	hdd_info("Name = [%s] Value = [%s]",
+		CFG_ENABLE_TX_SCHED_WRR_VO_NAME,
+		pHddCtx->config->tx_sched_wrr_vo);
+	hdd_info("Name = [%s] Value = [%s]",
+		CFG_ENABLE_TX_SCHED_WRR_VI_NAME,
+		pHddCtx->config->tx_sched_wrr_vi);
+	hdd_info("Name = [%s] Value = [%s]",
+		CFG_ENABLE_TX_SCHED_WRR_BK_NAME,
+		pHddCtx->config->tx_sched_wrr_bk);
+	hdd_info("Name = [%s] Value = [%s]",
+		CFG_ENABLE_TX_SCHED_WRR_BE_NAME,
+		pHddCtx->config->tx_sched_wrr_be);
+
 	hdd_info("Name = [%s] Value = [%u]",
 		CFG_ENABLE_DP_TRACE,
 		pHddCtx->config->enable_dp_trace);
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 13c6e74..d677cf8 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -1736,6 +1736,78 @@
 }
 
 /**
+ * hdd_update_cds_ac_specs_params() - update cds ac_specs params
+ * @hdd_ctx: Pointer to hdd context
+ *
+ * Return: none
+ */
+static void
+hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
+{
+	uint8_t num_entries = 0;
+	uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
+	uint8_t *tx_sched_wrr_ac;
+	int i;
+	cds_context_type *cds_ctx;
+
+	if (NULL == hdd_ctx)
+		return;
+
+	if (NULL == hdd_ctx->config) {
+		/* Do nothing if hdd_ctx is invalid */
+		hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
+		return;
+	}
+
+	cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
+
+	if (!cds_ctx) {
+		hdd_err("Invalid CDS Context");
+		return;
+	}
+
+	for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
+		switch (i) {
+		case OL_TX_WMM_AC_BE:
+			tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
+			break;
+		case OL_TX_WMM_AC_BK:
+			tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
+			break;
+		case OL_TX_WMM_AC_VI:
+			tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
+			break;
+		case OL_TX_WMM_AC_VO:
+			tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
+			break;
+		default:
+			tx_sched_wrr_ac = NULL;
+			break;
+		}
+
+		hdd_string_to_u8_array(tx_sched_wrr_ac,
+				tx_sched_wrr_param,
+				&num_entries,
+				sizeof(tx_sched_wrr_param));
+
+		if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
+			cds_ctx->ac_specs[i].wrr_skip_weight =
+						tx_sched_wrr_param[0];
+			cds_ctx->ac_specs[i].credit_threshold =
+						tx_sched_wrr_param[1];
+			cds_ctx->ac_specs[i].send_limit =
+						tx_sched_wrr_param[2];
+			cds_ctx->ac_specs[i].credit_reserve =
+						tx_sched_wrr_param[3];
+			cds_ctx->ac_specs[i].discard_weight =
+						tx_sched_wrr_param[4];
+		}
+
+		num_entries = 0;
+	}
+}
+
+/**
  * hdd_wlan_start_modules() - Single driver state machine for starting modules
  * @hdd_ctx: HDD context
  * @adapter: HDD adapter
@@ -1831,6 +1903,8 @@
 			goto destroy_psoc_object;
 		}
 
+		hdd_update_cds_ac_specs_params(hdd_ctx);
+
 		status = cds_open(hdd_ctx->hdd_psoc);
 		if (!QDF_IS_STATUS_SUCCESS(status)) {
 			hdd_err("Failed to Open CDS: %d", status);