From 4548644d924312d9224cfee09d4f99f15a3f2891 Mon Sep 17 00:00:00 2001 From: Li Feng Date: Fri, 18 Jun 2021 17:01:32 +0800 Subject: [PATCH] qcacld-3.0: Set moddtim dynamically in the li offload mode Extend hdd_config_modulated_dtim() to configure moddtim dynamically in the both non li offload and li offload mode. Change-Id: I8669ec618d4aa9cd87c4c234972ca500c98119b6 CRs-Fixed: 2970090 --- components/pmo/core/inc/wlan_pmo_priv.h | 4 +- .../pmo/core/inc/wlan_pmo_suspend_resume.h | 119 ++++++++++++++++++ .../pmo/core/src/wlan_pmo_suspend_resume.c | 74 ++++++++++- .../inc/wlan_pmo_common_public_struct.h | 2 + .../pmo/dispatcher/inc/wlan_pmo_ucfg_api.h | 57 +++++++++ .../pmo/dispatcher/src/wlan_pmo_ucfg_api.c | 21 ++++ .../pmo/src/target_if_pmo_suspend_resume.c | 3 + core/wma/src/wma_dev_if.c | 55 ++++++-- 8 files changed, 324 insertions(+), 11 deletions(-) diff --git a/components/pmo/core/inc/wlan_pmo_priv.h b/components/pmo/core/inc/wlan_pmo_priv.h index 1bbf04d24c..87fe90dbcc 100644 --- a/components/pmo/core/inc/wlan_pmo_priv.h +++ b/components/pmo/core/inc/wlan_pmo_priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 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 @@ -107,6 +107,7 @@ struct wlan_pmo_ctx { * @beacon_interval: vdev beacon interval * @dyn_modulated_dtim: dynamically configured modulated dtim value * @dyn_modulated_dtim_enabled: if dynamically modulated dtim is set or not + * @is_dyn_modulated_dtim_activated: if dynamically modulated dtim is sent to fw * @dyn_listen_interval: dynamically user configured listen interval * @restore_dtim_setting: DTIM settings restore flag * @pmo_vdev_lock: spin lock for pmo vdev priv ctx @@ -129,6 +130,7 @@ struct pmo_vdev_priv_obj { uint8_t beacon_interval; uint32_t dyn_modulated_dtim; bool dyn_modulated_dtim_enabled; + bool is_dyn_modulated_dtim_activated; uint32_t dyn_listen_interval; bool restore_dtim_setting; qdf_spinlock_t pmo_vdev_lock; diff --git a/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/components/pmo/core/inc/wlan_pmo_suspend_resume.h index 88ab1ccf0a..09e256e409 100644 --- a/components/pmo/core/inc/wlan_pmo_suspend_resume.h +++ b/components/pmo/core/inc/wlan_pmo_suspend_resume.h @@ -395,6 +395,125 @@ pmo_core_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } #endif + +/** + * pmo_core_vdev_get_moddtim_user_enabled() - Get vdev if mod dtim set + * by user + * @vdev: objmgr vdev handle + * + * Return: mod dtim set by user or not + */ +static inline +bool pmo_core_vdev_get_moddtim_user_enabled(struct wlan_objmgr_vdev *vdev) +{ + bool value; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dyn_modulated_dtim_enabled; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return value; +} + +/** + * pmo_core_vdev_set_moddtim_user_enabled() - vdev moddtim user enable setting + * @vdev: objmgr vdev handle + * @value: vdev moddtim user enable or not + * + * Return: None + */ +static inline +void pmo_core_vdev_set_moddtim_user_enabled(struct wlan_objmgr_vdev *vdev, + bool value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->dyn_modulated_dtim_enabled = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_core_vdev_get_moddtim_user_active() - Get vdev if moddtim user is + * sent to fw + * @vdev: objmgr vdev handle + * + * Return: moddtim user is sent to fw or not + */ +static inline +bool pmo_core_vdev_get_moddtim_user_active(struct wlan_objmgr_vdev *vdev) +{ + bool retval; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + retval = vdev_ctx->is_dyn_modulated_dtim_activated; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return retval; +} + +/** + * pmo_core_vdev_set_moddtim_user_active() - vdev moddtim user active setting + * @vdev: objmgr vdev handle + * @value: vdev moddtim user active or not + * + * Return: None + */ +static inline +void pmo_core_vdev_set_moddtim_user_active(struct wlan_objmgr_vdev *vdev, + bool value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->is_dyn_modulated_dtim_activated = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_core_vdev_get_moddtim_user() - Get vdev moddtim set by user + * @vdev: objmgr vdev handle + * + * Return: moddtim value set by user + */ +static inline +uint32_t pmo_core_vdev_get_moddtim_user(struct wlan_objmgr_vdev *vdev) +{ + uint32_t value; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dyn_modulated_dtim; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return value; +} + +/** + * pmo_core_vdev_set_moddtim_user() - vdev moddtim user value setting + * @vdev: objmgr vdev handle + * @value: vdev moddtim value set by user + * + * Return: None + */ +static inline +void pmo_core_vdev_set_moddtim_user(struct wlan_objmgr_vdev *vdev, + uint32_t value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->dyn_modulated_dtim = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ #endif /* end of _WLAN_PMO_SUSPEND_RESUME_H_ */ diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c index 26c3474d87..b0fe93096d 100644 --- a/components/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -40,6 +40,7 @@ #include "cfg_mlme_sap.h" #include "cfg_ucfg_api.h" #include "cdp_txrx_bus.h" +#include "wlan_pmo_ucfg_api.h" /** * pmo_core_get_vdev_dtim_period() - Get vdev dtim period @@ -1799,8 +1800,9 @@ QDF_STATUS pmo_core_config_forced_dtim(struct wlan_objmgr_vdev *vdev, return status; } -QDF_STATUS pmo_core_config_modulated_dtim(struct wlan_objmgr_vdev *vdev, - uint32_t mod_dtim) +static QDF_STATUS +pmo_core_config_non_li_offload_modulated_dtim(struct wlan_objmgr_vdev *vdev, + uint32_t mod_dtim) { struct pmo_vdev_priv_obj *vdev_ctx; struct pmo_psoc_cfg *psoc_cfg; @@ -1891,6 +1893,74 @@ out: return status; } +static QDF_STATUS +pmo_core_config_li_offload_modulated_dtim(struct wlan_objmgr_vdev *vdev, + uint32_t mod_dtim) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + struct pmo_psoc_cfg *psoc_cfg; + QDF_STATUS status; + uint8_t vdev_id; + + pmo_enter(); + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_id = pmo_vdev_get_id(vdev); + vdev_ctx = pmo_vdev_get_priv(vdev); + psoc_cfg = &vdev_ctx->pmo_psoc_ctx->psoc_cfg; + + if (mod_dtim > psoc_cfg->sta_max_li_mod_dtim) + mod_dtim = psoc_cfg->sta_max_li_mod_dtim; + pmo_core_vdev_set_moddtim_user(vdev, mod_dtim); + pmo_core_vdev_set_moddtim_user_enabled(vdev, true); + + if (!ucfg_pmo_is_vdev_connected(vdev)) { + pmo_core_vdev_set_moddtim_user_active(vdev, false); + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); + goto out; + } + + status = pmo_tgt_vdev_update_param_req(vdev, + pmo_vdev_param_moddtim, + mod_dtim); + if (QDF_IS_STATUS_SUCCESS(status)) { + pmo_debug("Set modulated dtim for vdev id %d", + vdev_id); + pmo_core_vdev_set_moddtim_user_active(vdev, true); + } else { + pmo_err("Failed to Set modulated dtim for vdev id %d", + vdev_id); + } + + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); +out: + pmo_exit(); + return status; +} + +QDF_STATUS pmo_core_config_modulated_dtim(struct wlan_objmgr_vdev *vdev, + uint32_t mod_dtim) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + vdev_ctx = pmo_vdev_get_priv(vdev); + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + + if (psoc_ctx->caps.li_offload) + status = pmo_core_config_li_offload_modulated_dtim(vdev, + mod_dtim); + else + status = pmo_core_config_non_li_offload_modulated_dtim(vdev, + mod_dtim); + + return status; +} + #ifdef SYSTEM_PM_CHECK void pmo_core_system_resume(struct wlan_objmgr_psoc *psoc) { 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 dd691c2206..b8b2d36f82 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -59,12 +59,14 @@ * @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_param_moddtim: vdev param moddtim * @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_param_moddtim, pmo_vdev_max_param }; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 5524ff75a2..c79c777acf 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -1241,6 +1241,39 @@ QDF_STATUS ucfg_pmo_core_txrx_suspend(struct wlan_objmgr_psoc *psoc); * Return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS ucfg_pmo_core_txrx_resume(struct wlan_objmgr_psoc *psoc); + +/** + * ucfg_pmo_get_moddtim_user_enable() - Get moddtim user enable + * @vdev: objmgr vdev handle + * + * Return: moddtim user enabled or not + */ +bool ucfg_pmo_get_moddtim_user_enable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_set_moddtim_user_enable() - Set moddtim user enable + * @vdev: objmgr vdev handle + * @value: moddtim user enable or not + * + * Return: none + */ +void ucfg_pmo_set_moddtim_user_enable(struct wlan_objmgr_vdev *vdev, + bool value); +/** + * ucfg_pmo_get_moddtim_user_active() - Get moddtim user active + * @vdev: objmgr vdev handle + * + * Return: moddtim user active + */ +bool ucfg_pmo_get_moddtim_user_active(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_get_moddtim_user() - Get moddtim user value + * @vdev: objmgr vdev handle + * + * Return: moddtim user value + */ +uint32_t ucfg_pmo_get_moddtim_user(struct wlan_objmgr_vdev *vdev); #else /* WLAN_POWER_MANAGEMENT_OFFLOAD */ static inline QDF_STATUS ucfg_pmo_psoc_open(struct wlan_objmgr_psoc *psoc) @@ -1919,6 +1952,30 @@ QDF_STATUS ucfg_pmo_core_txrx_resume(struct wlan_objmgr_psoc *psoc) { return QDF_STATUS_SUCCESS; } + +static inline bool +ucfg_pmo_get_moddtim_user_enable(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + +static inline void +ucfg_pmo_set_moddtim_user_enable(struct wlan_objmgr_vdev *vdev, + bool value) +{ +} + +static inline bool +ucfg_pmo_get_moddtim_user_active(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + +static inline uint32_t +ucfg_pmo_get_moddtim_user(struct wlan_objmgr_vdev *vdev) +{ + return 0; +} #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ #ifdef WLAN_FEATURE_EXTWOW_SUPPORT diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index d31d88a01b..5aef6d6e38 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -963,3 +963,24 @@ void ucfg_pmo_notify_system_resume(struct wlan_objmgr_psoc *psoc) pmo_core_system_resume(psoc); } #endif + +bool ucfg_pmo_get_moddtim_user_enable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_vdev_get_moddtim_user_enabled(vdev); +} + +void ucfg_pmo_set_moddtim_user_enable(struct wlan_objmgr_vdev *vdev, + bool value) +{ + pmo_core_vdev_set_moddtim_user_enabled(vdev, value); +} + +bool ucfg_pmo_get_moddtim_user_active(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_vdev_get_moddtim_user_active(vdev); +} + +uint32_t ucfg_pmo_get_moddtim_user(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_vdev_get_moddtim_user(vdev); +} 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 f83b995a53..45c9d11c06 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 @@ -68,6 +68,9 @@ QDF_STATUS target_if_pmo_send_vdev_update_param_req( case pmo_vdev_param_forced_dtim_count: param_id = WMI_VDEV_PARAM_FORCE_DTIM_CNT; break; + case pmo_vdev_param_moddtim: + param_id = WMI_VDEV_PARAM_MODDTIM_CNT; + break; default: target_if_err("invalid vdev param id %d", param_id); return QDF_STATUS_E_INVAL; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index a1631aac28..36b85e71b8 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -4520,6 +4520,9 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) WMA_VHT_PPS_DELIM_CRC_FAIL, 1); if (wmi_service_enabled(wma->wmi_handle, wmi_service_listen_interval_offload_support)) { + struct wlan_objmgr_vdev *vdev; + uint32_t moddtim; + wma_debug("listen interval offload enabled, setting params"); status = wma_vdev_set_param(wma->wmi_handle, params->smesessionId, @@ -4537,15 +4540,37 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) wma_err("can't set DYNDTIM_CNT for session: %d", params->smesessionId); } - status = wma_vdev_set_param(wma->wmi_handle, - params->smesessionId, - WMI_VDEV_PARAM_MODDTIM_CNT, - wma->staModDtim); - if (status != QDF_STATUS_SUCCESS) { - wma_err("can't set DTIM_CNT for session: %d", - params->smesessionId); - } + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, + params->smesessionId, + WLAN_LEGACY_WMA_ID); + if (!vdev || !ucfg_pmo_get_moddtim_user_enable(vdev)) { + moddtim = wma->staModDtim; + status = wma_vdev_set_param(wma->wmi_handle, + params->smesessionId, + WMI_VDEV_PARAM_MODDTIM_CNT, + moddtim); + if (status != QDF_STATUS_SUCCESS) { + wma_err("can't set DTIM_CNT for session: %d", + params->smesessionId); + } + + if (vdev) + wlan_objmgr_vdev_release_ref(vdev, + WLAN_LEGACY_WMA_ID); + } else if (vdev && ucfg_pmo_get_moddtim_user_enable(vdev) && + !ucfg_pmo_get_moddtim_user_active(vdev)) { + moddtim = ucfg_pmo_get_moddtim_user(vdev); + status = wma_vdev_set_param(wma->wmi_handle, + params->smesessionId, + WMI_VDEV_PARAM_MODDTIM_CNT, + moddtim); + if (status != QDF_STATUS_SUCCESS) { + wma_err("can't set DTIM_CNT for session: %d", + params->smesessionId); + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); + } } else { wma_debug("listen interval offload is not set"); } @@ -4705,6 +4730,20 @@ static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, QDF_STATUS status = QDF_STATUS_SUCCESS; struct wma_txrx_node *iface; + if (wmi_service_enabled(wma->wmi_handle, + wmi_service_listen_interval_offload_support)) { + struct wlan_objmgr_vdev *vdev; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, + params->smesessionId, + WLAN_LEGACY_WMA_ID); + if (vdev) { + if (ucfg_pmo_get_moddtim_user_enable(vdev)) + ucfg_pmo_set_moddtim_user_enable(vdev, false); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); + } + } + iface = &wma->interfaces[params->smesessionId]; iface->uapsd_cached_val = 0; #ifdef FEATURE_WLAN_TDLS