Просмотр исходного кода

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
Rahul Gusain 1 год назад
Родитель
Сommit
5adb10addb

+ 49 - 0
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

+ 20 - 0
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

+ 12 - 0
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)
 {

+ 28 - 5
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;
 }