diff --git a/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/components/pmo/core/inc/wlan_pmo_suspend_resume.h
index 46a8949b6c56..dc66f7673f1a 100644
--- a/components/pmo/core/inc/wlan_pmo_suspend_resume.h
+++ b/components/pmo/core/inc/wlan_pmo_suspend_resume.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 2020-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -348,6 +348,18 @@ QDF_STATUS pmo_core_txrx_suspend(struct wlan_objmgr_psoc *psoc);
* Return: QDF_STATUS
*/
QDF_STATUS pmo_core_txrx_resume(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * pmo_core_config_forced_dtim() - function to configure forced dtim
+ * @vdev: objmgr vdev handle
+ * @dynamic_dtim: dynamic dtim value passed by user
+ *
+ * This function configures the forced modulated dtim in firmware
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS pmo_core_config_forced_dtim(struct wlan_objmgr_vdev *vdev,
+ uint32_t dynamic_dtim);
#endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
#endif /* end of _WLAN_PMO_SUSPEND_RESUME_H_ */
diff --git a/components/pmo/core/src/wlan_pmo_main.c b/components/pmo/core/src/wlan_pmo_main.c
index 57ac20c1a25e..875dbf27604c 100644
--- a/components/pmo/core/src/wlan_pmo_main.c
+++ b/components/pmo/core/src/wlan_pmo_main.c
@@ -186,6 +186,7 @@ static void wlan_pmo_init_cfg(struct wlan_objmgr_psoc *psoc,
psoc_cfg->sta_mod_dtim = cfg_get(psoc, CFG_PMO_ENABLE_MODULATED_DTIM);
psoc_cfg->enable_mc_list = cfg_get(psoc, CFG_PMO_MC_ADDR_LIST_ENABLE);
psoc_cfg->power_save_mode = cfg_get(psoc, CFG_PMO_POWERSAVE_MODE);
+ psoc_cfg->sta_forced_dtim = cfg_get(psoc, CFG_PMO_ENABLE_FORCED_DTIM);
psoc_cfg->is_mod_dtim_on_sys_suspend_enabled =
cfg_get(psoc, CFG_PMO_MOD_DTIM_ON_SYS_SUSPEND);
psoc_cfg->is_bus_suspend_enabled_in_sap_mode =
diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c
index ac182378c7c6..c680350bea74 100644
--- a/components/pmo/core/src/wlan_pmo_suspend_resume.c
+++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c
@@ -816,6 +816,10 @@ pmo_core_enable_wow_in_fw(struct wlan_objmgr_psoc *psoc,
param.flags |= WMI_WOW_FLAG_MOD_DTIM_ON_SYS_SUSPEND;
}
+ if (psoc_cfg->sta_forced_dtim) {
+ pmo_info("forced DTIM enabled");
+ param.flags |= WMI_WOW_FLAG_FORCED_DTIM_ON_SYS_SUSPEND;
+ }
status = pmo_tgt_psoc_send_wow_enable_req(psoc, ¶m);
if (status != QDF_STATUS_SUCCESS) {
pmo_err("Failed to enable wow in fw");
@@ -1683,6 +1687,34 @@ out:
return status;
}
+QDF_STATUS pmo_core_config_forced_dtim(struct wlan_objmgr_vdev *vdev,
+ uint32_t dynamic_dtim)
+{
+ struct pmo_vdev_priv_obj *vdev_ctx;
+ uint8_t vdev_id;
+ QDF_STATUS status;
+
+ vdev_id = pmo_vdev_get_id(vdev);
+ vdev_ctx = pmo_vdev_get_priv(vdev);
+
+ qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
+ vdev_ctx->dyn_modulated_dtim = dynamic_dtim;
+ vdev_ctx->dyn_modulated_dtim_enabled = dynamic_dtim >= 1;
+ qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
+
+ status = pmo_tgt_vdev_update_param_req(vdev,
+ pmo_vdev_param_forced_dtim_count,
+ dynamic_dtim);
+
+ if (QDF_IS_STATUS_ERROR(status)) {
+ pmo_err("Failed to set forced DTIM for vdev id %d",
+ vdev_id);
+ }
+
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID);
+ return status;
+}
+
QDF_STATUS pmo_core_config_modulated_dtim(struct wlan_objmgr_vdev *vdev,
uint32_t mod_dtim)
{
@@ -1706,6 +1738,9 @@ QDF_STATUS pmo_core_config_modulated_dtim(struct wlan_objmgr_vdev *vdev,
vdev_ctx = pmo_vdev_get_priv(vdev);
psoc_cfg = &vdev_ctx->pmo_psoc_ctx->psoc_cfg;
+ if (psoc_cfg->sta_forced_dtim)
+ return pmo_core_config_forced_dtim(vdev, mod_dtim);
+
/* Calculate Maximum allowed modulated DTIM */
beacon_interval_mod =
pmo_core_get_vdev_beacon_interval(vdev) / 100;
diff --git a/components/pmo/dispatcher/inc/wlan_pmo_common_cfg.h b/components/pmo/dispatcher/inc/wlan_pmo_common_cfg.h
index d9d6c6fb8ea5..b78a5e9a56b2 100644
--- a/components/pmo/dispatcher/inc/wlan_pmo_common_cfg.h
+++ b/components/pmo/dispatcher/inc/wlan_pmo_common_cfg.h
@@ -247,6 +247,28 @@
0, \
"Modulated DTIM on System suspend wow")
+/*
+ *
+ * gEnableForcedDTIM - Enable/Disable forced DTIM feature
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable/disable forced DTIM feature.
+ *
+ * 0 - Disable forced DTIM.
+ * 1 - Enable forced DTIM
+ *
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_PMO_ENABLE_FORCED_DTIM CFG_INI_BOOL( \
+ "gEnableForcedDTIM", \
+ 0, \
+ "Enable/disable Forced DTIM feature")
+
/*
*
* gMaxPsPoll - Max powersave poll
@@ -468,6 +490,7 @@
CFG(CFG_PMO_ENABLE_HOST_NSOFFLOAD) \
CFG(CFG_PMO_ENABLE_DYNAMIC_DTIM) \
CFG(CFG_PMO_ENABLE_MODULATED_DTIM) \
+ CFG(CFG_PMO_ENABLE_FORCED_DTIM) \
CFG(CFG_PMO_MC_ADDR_LIST_ENABLE) \
CFG(CFG_PMO_POWERSAVE_MODE) \
CFG(CFG_PMO_MAX_PS_POLL) \
diff --git a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h
index b142081cca45..c95a429c9183 100644
--- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h
+++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h
@@ -55,11 +55,13 @@
* enum pmo_vdev_param_id: tell vdev param id
* @pmo_vdev_param_listen_interval: vdev listen interval param id
* @pmo_vdev_param_dtim_policy: vdev param dtim policy
+ * @pmo_vdev_param_forced_dtim_count: vdev param forced dtim count
* @pmo_vdev_max_param: Max vdev param id
*/
enum pmo_vdev_param_id {
pmo_vdev_param_listen_interval = 0,
pmo_vdev_param_dtim_policy,
+ pmo_vdev_param_forced_dtim_count,
pmo_vdev_max_param
};
@@ -275,6 +277,7 @@ enum active_apf_mode {
* @sta_dynamic_dtim: station dynamic DTIM value
* @sta_mod_dtim: station modulated DTIM value
* @sta_max_li_mod_dtim: station max listen interval DTIM value
+ * @sta_forced_dtim: station forced DTIM value
* @wow_enable: enable wow with majic pattern match or pattern byte match
* @power_save_mode: power save mode for psoc
* @runtime_pm_delay: set runtime pm's inactivity timer
@@ -333,6 +336,7 @@ struct pmo_psoc_cfg {
uint8_t sta_dynamic_dtim;
uint8_t sta_mod_dtim;
uint8_t sta_max_li_mod_dtim;
+ bool sta_forced_dtim;
enum pmo_wow_enable_type wow_enable;
enum powersave_mode power_save_mode;
enum powersave_mode default_power_save_mode;
diff --git a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c
index 9263469e9e2d..50d18ae351e4 100644
--- a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c
+++ b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c
@@ -65,6 +65,9 @@ QDF_STATUS target_if_pmo_send_vdev_update_param_req(
case pmo_vdev_param_dtim_policy:
param_id = WMI_VDEV_PARAM_DTIM_POLICY;
break;
+ case pmo_vdev_param_forced_dtim_count:
+ param_id = WMI_VDEV_PARAM_FORCE_DTIM_CNT;
+ break;
default:
target_if_err("invalid vdev param id %d", param_id);
return QDF_STATUS_E_INVAL;