From 54e7be76f319fe0e578e3c9a1939f2eb8ee9a389 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Wed, 27 Jun 2018 17:10:17 +0530 Subject: [PATCH] qcacld-3.0: Add upper limit check on Listen Interval configuration User can override the Listen Interval value set during association by using wifi config set vendor command. Since there is no limit check in host, a very high value causes an assert in the Firmware. Add an upper limit check on the user Listen Interval value. Change-Id: I8128ccbb875adf57c95a15d0391fb442d3dbbbc3 CRs-Fixed: 2256334 --- .../pmo/core/src/wlan_pmo_suspend_resume.c | 26 +++++++++++++++++-- core/hdd/src/wlan_hdd_cfg80211.c | 6 +++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c index 914579f2a0d9..3493312a150d 100644 --- a/components/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -1341,8 +1341,11 @@ 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_cfg *psoc_cfg; bool prev_dtim_enabled; uint32_t listen_interval; + uint32_t beacon_interval_mod; + uint32_t max_mod_dtim; QDF_STATUS status; uint8_t vdev_id; @@ -1354,13 +1357,32 @@ QDF_STATUS pmo_core_config_modulated_dtim(struct wlan_objmgr_vdev *vdev, vdev_id = pmo_vdev_get_id(vdev); vdev_ctx = pmo_vdev_get_priv(vdev); + psoc_cfg = &vdev_ctx->pmo_psoc_ctx->psoc_cfg; + /* Calculate Maximum allowed modulated DTIM */ + beacon_interval_mod = + pmo_core_get_vdev_beacon_interval(vdev) / 100; + if (!beacon_interval_mod) + beacon_interval_mod = 1; + + max_mod_dtim = psoc_cfg->sta_max_li_mod_dtim / + (pmo_core_get_vdev_dtim_period(vdev) + * beacon_interval_mod); + if (!max_mod_dtim) + max_mod_dtim = 1; + + /* Calculate Listen Interval from provided mod DTIM */ qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); vdev_ctx->dyn_modulated_dtim = mod_dtim; prev_dtim_enabled = vdev_ctx->dyn_modulated_dtim_enabled; vdev_ctx->dyn_modulated_dtim_enabled = mod_dtim != 1; - listen_interval = vdev_ctx->dyn_modulated_dtim * - pmo_core_get_vdev_dtim_period(vdev); + if (vdev_ctx->dyn_modulated_dtim > max_mod_dtim) { + listen_interval = max_mod_dtim * + pmo_core_get_vdev_dtim_period(vdev); + } else { + listen_interval = vdev_ctx->dyn_modulated_dtim * + pmo_core_get_vdev_dtim_period(vdev); + } qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); if (prev_dtim_enabled || mod_dtim != 1) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 8e6d0b051357..e0b874e6af3b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6745,6 +6745,12 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, override_li = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]); + if (override_li > CFG_ENABLE_DYNAMIC_DTIM_MAX) { + hdd_err_rl("Invalid value for listen interval - %d", + override_li); + return -EINVAL; + } + status = pmo_ucfg_config_listen_interval(adapter->hdd_vdev, override_li); if (status != QDF_STATUS_SUCCESS)