From 5adb10addbf4ac45cd90eddf7f9144003f809e52 Mon Sep 17 00:00:00 2001 From: Rahul Gusain Date: Wed, 1 Nov 2023 14:14:51 +0530 Subject: [PATCH] qcacld-3.0: Don't send zero ITO to target Currently, userspace sends "QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION" vendor command for power configuration. With this vendor command, driver receives the PS parameters which it sends it to the target. Usually, inactivity timeout is 200ms, but in some scenario, if driver send the inactivity timeout as zero, then it causes crash in target as target expects non-zero value. Scenarios: 1. Userspace updates inactivity timeout to zero. 2. For OPM mode as disable(0) or enable(1), driver updates the PS params to zero. So, inactivity timeout is zero. So, to fix this, return invalid if userspace send ITO value as zero and update vdev PS params for OPM mode as user defined(2). Change-Id: I120829f12ed350ad7ad0bfb983ad49087dea4fc8 CRs-Fixed: 3653524 --- .../pmo/core/inc/wlan_pmo_static_config.h | 49 +++++++++++++++++++ .../pmo/dispatcher/inc/wlan_pmo_ucfg_api.h | 20 ++++++++ .../pmo/dispatcher/src/wlan_pmo_ucfg_api.c | 12 +++++ core/hdd/src/wlan_hdd_cfg80211.c | 33 +++++++++++-- 4 files changed, 109 insertions(+), 5 deletions(-) diff --git a/components/pmo/core/inc/wlan_pmo_static_config.h b/components/pmo/core/inc/wlan_pmo_static_config.h index ca87040a3e..5c76ccf1ef 100644 --- a/components/pmo/core/inc/wlan_pmo_static_config.h +++ b/components/pmo/core/inc/wlan_pmo_static_config.h @@ -148,6 +148,55 @@ QDF_STATUS pmo_core_vdev_get_ps_params(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +/** + * pmo_vdev_set_ps_opm_mode() - set OPM mode + * @vdev: objmgr vdev handle + * @opm_mode: OPM mode + * + * Return: QDF_STATUS + */ +static inline +QDF_STATUS pmo_vdev_set_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode opm_mode) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + if (!vdev_ctx) { + pmo_err("vdev ctx is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->ps_params.opm_mode = opm_mode; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return QDF_STATUS_SUCCESS; +} + +/** + * pmo_vdev_get_ps_opm_mode() - get OPM mode + * @vdev: objmgr vdev handle + * @opm_mode: OPM mode + * + * Return: QDF_STATUS + */ +static inline +QDF_STATUS pmo_vdev_get_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode *opm_mode) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + if (!vdev_ctx) + return QDF_STATUS_E_NULL_VALUE; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + *opm_mode = vdev_ctx->ps_params.opm_mode; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + return QDF_STATUS_SUCCESS; +} + #ifdef WLAN_FEATURE_NAN /** * pmo_set_ndp_wow_bitmask() - set predefined NDP wow wakeup events diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 6d33b4c535..8267dbab4c 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -829,6 +829,26 @@ ucfg_pmo_set_ps_params(struct wlan_objmgr_vdev *vdev, QDF_STATUS ucfg_pmo_get_ps_params(struct wlan_objmgr_vdev *vdev, struct pmo_ps_params *ps_params); +/** + * ucfg_pmo_core_vdev_set_ps_opm_mode() - Set OPM mode + * @vdev: pointer to vdev object + * @opm_mode: OPM mode + * + * Return: QDF Status + */ +QDF_STATUS ucfg_pmo_core_vdev_set_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode opm_mode); + +/** + * ucfg_pmo_core_vdev_get_ps_opm_mode() - Get OPM mode + * @vdev: pointer to vdev object + * @opm_mode: OPM mode + * + * Return: QDF Status + */ +QDF_STATUS ucfg_pmo_core_vdev_get_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode *opm_mode); + /** * ucfg_pmo_get_gtk_rsp(): API to send gtk response request to fwr * @vdev: objmgr vdev handle diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index 14be19872a..efe9fa52a8 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -607,6 +607,18 @@ QDF_STATUS ucfg_pmo_get_ps_params(struct wlan_objmgr_vdev *vdev, return pmo_core_vdev_get_ps_params(vdev, ps_params); } +QDF_STATUS ucfg_pmo_core_vdev_set_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode opm_mode) +{ + return pmo_vdev_set_ps_opm_mode(vdev, opm_mode); +} + +QDF_STATUS ucfg_pmo_core_vdev_get_ps_opm_mode(struct wlan_objmgr_vdev *vdev, + enum powersave_mode *opm_mode) +{ + return pmo_vdev_get_ps_opm_mode(vdev, opm_mode); +} + bool ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5c035b0ae1..1c70480306 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -9908,8 +9908,13 @@ static int hdd_config_power(struct wlan_hdd_link_info *link_info, tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL]; int ret; - if (!power_attr && !opm_attr) + hdd_enter_dev(adapter->dev); + + if (!power_attr && !opm_attr) { + hdd_err_rl("power attr and opm attr is null"); return 0; + } + if (power_attr && opm_attr) { hdd_err_rl("Invalid OPM set attribute"); @@ -9922,11 +9927,14 @@ static int hdd_config_power(struct wlan_hdd_link_info *link_info, } opm_mode = power_attr ? nla_get_u8(power_attr) : nla_get_u8(opm_attr); - if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) + hdd_debug("opm_mode %d", opm_mode); + + if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) { if (!ps_ito_attr || !spec_wake_attr) { hdd_err_rl("Invalid User defined OPM attributes"); return -EINVAL; } + } ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode); if (ret) @@ -9936,19 +9944,34 @@ static int hdd_config_power(struct wlan_hdd_link_info *link_info, if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) { ps_params.ps_ito = nla_get_u16(ps_ito_attr); ps_params.spec_wake = nla_get_u16(spec_wake_attr); + + if (!ps_params.ps_ito) + return -EINVAL; + + hdd_debug("ps_ito %d spec_wake %d opm_mode %d", + ps_params.ps_ito, ps_params.spec_wake, + ps_params.opm_mode); + ret = hdd_set_power_config_params(hdd_ctx, adapter, ps_params.ps_ito, ps_params.spec_wake); + if (ret) return ret; } vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID); - if (vdev) { - ucfg_pmo_set_ps_params(vdev, &ps_params); - hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID); + if (!vdev) { + hdd_err("vdev is null"); + return 0; } + if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) + ucfg_pmo_set_ps_params(vdev, &ps_params); + else + ucfg_pmo_core_vdev_set_ps_opm_mode(vdev, ps_params.opm_mode); + + hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID); return 0; }