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
This commit is contained in:
Rahul Gusain
2023-11-01 14:14:51 +05:30
committed by Ravindra Konda
parent 6154cb19ca
commit 5adb10addb
4 changed files with 109 additions and 5 deletions

View File

@@ -148,6 +148,55 @@ QDF_STATUS pmo_core_vdev_get_ps_params(struct wlan_objmgr_vdev *vdev,
return QDF_STATUS_SUCCESS; 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 #ifdef WLAN_FEATURE_NAN
/** /**
* pmo_set_ndp_wow_bitmask() - set predefined NDP wow wakeup events * pmo_set_ndp_wow_bitmask() - set predefined NDP wow wakeup events

View File

@@ -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, QDF_STATUS ucfg_pmo_get_ps_params(struct wlan_objmgr_vdev *vdev,
struct pmo_ps_params *ps_params); 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 * ucfg_pmo_get_gtk_rsp(): API to send gtk response request to fwr
* @vdev: objmgr vdev handle * @vdev: objmgr vdev handle

View File

@@ -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); 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 bool
ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc) ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc)
{ {

View File

@@ -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]; tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL];
int ret; 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; return 0;
}
if (power_attr && opm_attr) { if (power_attr && opm_attr) {
hdd_err_rl("Invalid OPM set attribute"); 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); 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) { if (!ps_ito_attr || !spec_wake_attr) {
hdd_err_rl("Invalid User defined OPM attributes"); hdd_err_rl("Invalid User defined OPM attributes");
return -EINVAL; return -EINVAL;
} }
}
ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode); ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode);
if (ret) 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) { if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
ps_params.ps_ito = nla_get_u16(ps_ito_attr); ps_params.ps_ito = nla_get_u16(ps_ito_attr);
ps_params.spec_wake = nla_get_u16(spec_wake_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, ret = hdd_set_power_config_params(hdd_ctx, adapter,
ps_params.ps_ito, ps_params.ps_ito,
ps_params.spec_wake); ps_params.spec_wake);
if (ret) if (ret)
return ret; return ret;
} }
vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID); vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID);
if (vdev) { if (!vdev) {
ucfg_pmo_set_ps_params(vdev, &ps_params); hdd_err("vdev is null");
hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID); 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; return 0;
} }