diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 9252da92a2b2..a978e835d7cc 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -11023,6 +11023,75 @@ enum hdd_external_acs_freq_band {
#define CFG_LPRx_MAX (1)
#define CFG_LPRx_DEFAULT (1)
+/*
+ *
+ * gUpperBrssiThresh - Sets Upper threshold for beacon RSSI
+ * @Min: 36
+ * @Max: 66
+ * @Default: 46
+ *
+ * This ini sets Upper beacon threshold for beacon RSSI in FW
+ * Used to reduced RX chainmask in FW, once this threshold is
+ * reached FW will switch to 1X1 (Single chain).
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ *
+ */
+
+#define CFG_UPPER_BRSSI_THRESH_NAME "gUpperBrssiThresh"
+#define CFG_UPPER_BRSSI_THRESH_MIN (36)
+#define CFG_UPPER_BRSSI_THRESH_MAX (66)
+#define CFG_UPPER_BRSSI_THRESH_DEFAULT (46)
+
+/*
+ *
+ * gLowerrBrssiThresh - Sets Lower threshold for beacon RSSI
+ * @Min: 6
+ * @Max: 36
+ * @Default: 26
+ *
+ * This ini sets Lower beacon threshold for beacon RSSI in FW
+ * Used to increase RX chainmask in FW, once this threshold is
+ * reached FW will switch to 2X2 chain.
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ *
+ */
+
+#define CFG_LOWER_BRSSI_THRESH_NAME "gLowerBrssiThresh"
+#define CFG_LOWER_BRSSI_THRESH_MIN (6)
+#define CFG_LOWER_BRSSI_THRESH_MAX (36)
+#define CFG_LOWER_BRSSI_THRESH_DEFAULT (26)
+
+/*
+ *
+ * gDtim1ChRxEnable - Enable/Disable DTIM 1Chrx feature
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * This ini Enables or Disables DTIM 1CHRX feature in FW
+ * If this flag is set FW enables shutting off one chain
+ * while going to power save.
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ *
+ */
+
+#define CFG_DTIM_1CHRX_ENABLE_NAME "gDtim1ChRxEnable"
+#define CFG_DTIM_1CHRX_ENABLE_MIN (0)
+#define CFG_DTIM_1CHRX_ENABLE_MAX (1)
+#define CFG_DTIM_1CHRX_ENABLE_DEFAULT (1)
+
/*
* Type declarations
*/
@@ -11786,6 +11855,9 @@ struct hdd_config {
uint8_t rssi_penalize_factor_5g;
uint8_t max_rssi_penalize_5g;
bool enable_lprx;
+ uint8_t upper_brssi_thresh;
+ uint8_t lower_brssi_thresh;
+ bool enable_dtim_1chrx;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 1cef2d32f691..143c34b50480 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1351,6 +1351,29 @@ struct suspend_resume_stats {
uint32_t suspend_fail[SUSPEND_FAIL_MAX_COUNT];
};
+/**
+ * hdd_sta_smps_param - SMPS parameters to configure from hdd
+ * HDD_STA_SMPS_PARAM_UPPER_RSSI_THRESH: RSSI threshold to enter Dynamic SMPS
+ * mode from inactive mode
+ * HDD_STA_SMPS_PARAM_STALL_RSSI_THRESH: RSSI threshold to enter
+ * Stalled-D-SMPS mode from D-SMPS mode or to enter D-SMPS mode from
+ * Stalled-D-SMPS mode
+ * HDD_STA_SMPS_PARAM_LOWER_RSSI_THRESH: RSSI threshold to disable SMPS modes
+ * HDD_STA_SMPS_PARAM_UPPER_BRSSI_THRESH: Upper threshold for beacon-RSSI.
+ * Used to reduce RX chainmask.
+ * HDD_STA_SMPS_PARAM_LOWER_BRSSI_THRESH: Lower threshold for beacon-RSSI.
+ * Used to increase RX chainmask.
+ * HDD_STA_SMPS_PARAM_DTIM_1CHRX_ENABLE: Enable/Disable DTIM 1chRx feature
+ */
+enum hdd_sta_smps_param {
+ HDD_STA_SMPS_PARAM_UPPER_RSSI_THRESH = 0,
+ HDD_STA_SMPS_PARAM_STALL_RSSI_THRESH = 1,
+ HDD_STA_SMPS_PARAM_LOWER_RSSI_THRESH = 2,
+ HDD_STA_SMPS_PARAM_UPPER_BRSSI_THRESH = 3,
+ HDD_STA_SMPS_PARAM_LOWER_BRSSI_THRESH = 4,
+ HDD_STA_SMPS_PARAM_DTIM_1CHRX_ENABLE = 5
+};
+
/** Adapter structure definition */
struct hdd_context_s {
/** Global CDS context */
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index ee6754fac5a4..aa6b9793295b 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -4590,6 +4590,27 @@ struct reg_table_entry g_registry_table[] = {
CFG_LPRx_DEFAULT,
CFG_LPRx_MIN,
CFG_LPRx_MAX),
+
+ REG_VARIABLE(CFG_UPPER_BRSSI_THRESH_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, upper_brssi_thresh,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_UPPER_BRSSI_THRESH_DEFAULT,
+ CFG_UPPER_BRSSI_THRESH_MIN,
+ CFG_UPPER_BRSSI_THRESH_MAX),
+
+ REG_VARIABLE(CFG_LOWER_BRSSI_THRESH_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, lower_brssi_thresh,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_LOWER_BRSSI_THRESH_DEFAULT,
+ CFG_LOWER_BRSSI_THRESH_MIN,
+ CFG_LOWER_BRSSI_THRESH_MAX),
+
+ REG_VARIABLE(CFG_DTIM_1CHRX_ENABLE_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, enable_dtim_1chrx,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_DTIM_1CHRX_ENABLE_DEFAULT,
+ CFG_DTIM_1CHRX_ENABLE_MIN,
+ CFG_DTIM_1CHRX_ENABLE_MAX),
};
@@ -6145,6 +6166,15 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
hdd_debug("Name = [%s] value = [%u]",
CFG_LPRx_NAME,
pHddCtx->config->enable_lprx);
+ hdd_debug("Name = [%s] value = [%u]",
+ CFG_UPPER_BRSSI_THRESH_NAME,
+ pHddCtx->config->upper_brssi_thresh);
+ hdd_debug("Name = [%s] value = [%u]",
+ CFG_LOWER_BRSSI_THRESH_NAME,
+ pHddCtx->config->lower_brssi_thresh);
+ hdd_debug("Name = [%s] value = [%u]",
+ CFG_DTIM_1CHRX_ENABLE_NAME,
+ pHddCtx->config->enable_dtim_1chrx);
}
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index fccb4a64ab8d..6223d6259684 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -3641,6 +3641,20 @@ int hdd_set_fw_params(hdd_adapter_t *adapter)
goto error;
}
+ if (adapter->device_mode == QDF_STA_MODE) {
+ sme_set_smps_cfg(adapter->sessionId,
+ HDD_STA_SMPS_PARAM_UPPER_BRSSI_THRESH,
+ hdd_ctx->config->upper_brssi_thresh);
+
+ sme_set_smps_cfg(adapter->sessionId,
+ HDD_STA_SMPS_PARAM_LOWER_BRSSI_THRESH,
+ hdd_ctx->config->lower_brssi_thresh);
+
+ sme_set_smps_cfg(adapter->sessionId,
+ HDD_STA_SMPS_PARAM_DTIM_1CHRX_ENABLE,
+ hdd_ctx->config->enable_dtim_1chrx);
+ }
+
if (hdd_ctx->config->enable2x2) {
hdd_debug("configuring 2x2 mode fw params");
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 7c6402743e87..799e3a81afcf 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1650,6 +1650,17 @@ int sme_cli_set_command(int vdev_id, int param_id, int sval, int vpdev);
QDF_STATUS sme_set_bt_activity_info_cb(tHalHandle hal,
void (*cb)(void *, uint32_t profile_info));
+/**
+ * sme_set_smps_cfg() - set SMPS config params
+ * @vdev_id: virtual device for the command
+ * @param_id: parameter id
+ * @param_val: parameter value
+ *
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure
+ */
+
+QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
+ uint32_t param_val);
/**
* sme_get_peer_info() - sme api to get peer info
* @hal: hal handle for getting global mac struct
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 3f28697031b3..e08d885adca4 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -16505,6 +16505,12 @@ QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
return status;
}
+QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
+ uint32_t param_val)
+{
+ return wma_configure_smps_params(vdev_id, param_id, param_val);
+}
+
QDF_STATUS sme_ipa_uc_stat_request(tHalHandle hal, uint32_t vdev_id,
uint32_t param_id, uint32_t param_val, uint32_t req_cat)
{
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 10316900d1cf..37b53abadbe1 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -2560,6 +2560,15 @@ QDF_STATUS wma_set_rx_reorder_timeout_val(tp_wma_handle wma_handle,
*/
QDF_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
struct sir_peer_set_rx_blocksize *peer_rx_blocksize);
+/**
+ * wma_configure_smps_params() - Configures the smps parameters to set
+ * @vdev_id: Virtual device for the command
+ * @param_id: SMPS parameter ID
+ * @param_val: Value to be set for the parameter
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure
+ */
+QDF_STATUS wma_configure_smps_params(uint32_t vdev_id, uint32_t param_id,
+ uint32_t param_val);
/*
* wma_chip_power_save_failure_detected_handler() - chip pwr save fail detected
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 520b556e66e7..39d829bea344 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -7699,6 +7699,28 @@ int wma_peer_rx_reorder_queue_remove(void *scn_handle,
¶m);
}
+QDF_STATUS wma_configure_smps_params(uint32_t vdev_id, uint32_t param_id,
+ uint32_t param_val)
+{
+ tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+ int smps_cmd_value;
+ int status = QDF_STATUS_E_INVAL;
+
+ if (!wma) {
+ WMA_LOGE("%s: Failed to get wma", __func__);
+ return status;
+ }
+
+ smps_cmd_value = param_id << WMI_SMPS_PARAM_VALUE_S;
+ smps_cmd_value = smps_cmd_value | param_val;
+
+ status = wma_set_smps_params(wma, vdev_id, smps_cmd_value);
+ if (status)
+ WMA_LOGE("Failed to set SMPS Param");
+
+ return status;
+}
+
void wma_ipa_uc_stat_request(wma_cli_set_cmd_t *privcmd)
{