Browse Source

qcacld-3.0: Dynamic ratemask update

Add support for dynamic ratemask update.

Change-Id: I9aede4bdcd399af6c8e827f813016df63d7b8ab1
CRs-Fixed: 3112489
Jayachandran Sreekumaran 3 years ago
parent
commit
0a8f7d7347

+ 14 - 0
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -3433,4 +3433,18 @@ wlan_mlme_get_tx_retry_multiplier(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS
 wlan_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc,
 				   uint32_t *value);
+
+/**
+ * wlan_mlme_update_ratemask_params() - Update ratemask params
+ *
+ * @vdev: pointer to vdev object
+ * @num_ratemask: number of rate masks
+ * @rate_params: pointer to ratemask structure
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_mlme_update_ratemask_params(struct wlan_objmgr_vdev *vdev,
+				 uint8_t num_ratemask,
+				 struct config_ratemask_params *rate_params);
 #endif /* _WLAN_MLME_API_H_ */

+ 18 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -4417,4 +4417,22 @@ bool ucfg_mlme_get_coex_unsafe_chan_reg_disable(
 	return false;
 }
 #endif
+
+/**
+ * ucfg_set_ratemask_params() - Set ratemask config
+ * @vdev:   pointer to vdev object
+ * @num_ratemask: number of ratemask params
+ * @rate_params: ratemask params
+ *
+ * Return: QDF_STATUS
+ */
+
+static inline QDF_STATUS
+ucfg_set_ratemask_params(struct wlan_objmgr_vdev *vdev,
+			 uint8_t num_ratemask,
+			 struct config_ratemask_params *rate_params)
+{
+	return wlan_mlme_update_ratemask_params(vdev, num_ratemask,
+						rate_params);
+}
 #endif /* _WLAN_MLME_UCFG_API_H_ */

+ 54 - 0
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -30,6 +30,7 @@
 #include "wlan_crypto_global_api.h"
 #include "wlan_utility.h"
 #include "wlan_policy_mgr_ucfg.h"
+#include "wlan_vdev_mgr_utils_api.h"
 
 /* quota in milliseconds */
 #define MCC_DUTY_CYCLE 70
@@ -5389,5 +5390,58 @@ wlan_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc,
 	}
 
 	*value = mlme_obj->cfg.feature_flags.channel_bonding_mode_5ghz;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_mlme_update_ratemask_params(struct wlan_objmgr_vdev *vdev,
+				 uint8_t num_ratemask,
+				 struct config_ratemask_params *rate_params)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	struct vdev_mlme_rate_info *rate_info;
+	QDF_STATUS ret;
+	uint8_t i = 0;
+	uint8_t index;
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
+	if (!vdev_mlme)
+		return QDF_STATUS_E_FAILURE;
+
+	rate_info = &vdev_mlme->mgmt.rate_info;
+	while (i < num_ratemask) {
+		index = rate_params[i].type;
+		if (index >= WLAN_VDEV_RATEMASK_TYPE_MAX) {
+			mlme_legacy_err("Invalid ratemask type");
+			++i;
+			continue;
+		}
+
+		if (rate_info->ratemask_params[index].lower32 !=
+		    rate_params[i].lower32 ||
+		    rate_info->ratemask_params[index].lower32_2 !=
+		    rate_params[i].lower32_2 ||
+		    rate_info->ratemask_params[index].higher32 !=
+		    rate_params[i].higher32 ||
+		    rate_info->ratemask_params[index].higher32_2 !=
+		    rate_params[i].higher32_2) {
+			rate_info->ratemask_params[index].lower32 =
+						rate_params[i].lower32;
+			rate_info->ratemask_params[index].higher32 =
+						rate_params[i].higher32;
+			rate_info->ratemask_params[index].lower32_2 =
+						rate_params[i].lower32_2;
+			rate_info->ratemask_params[index].higher32_2 =
+						rate_params[i].higher32_2;
+			ret = wlan_util_vdev_mlme_set_ratemask_config(vdev_mlme,
+								      index);
+			if (ret != QDF_STATUS_SUCCESS)
+				mlme_legacy_err("ratemask config failed");
+		} else {
+			mlme_legacy_debug("Ratemask same as configured mask");
+		}
+		++i;
+	}
 	return QDF_STATUS_SUCCESS;
 }

+ 193 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -6041,6 +6041,189 @@ wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
 	return errno;
 }
 
+#define RATEMASK_PARAMS_TYPE_MAX 4
+#define RATEMASK_PARAMS_MAX QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX
+const struct nla_policy wlan_hdd_set_ratemask_param_policy[
+			RATEMASK_PARAMS_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST] =
+		VENDOR_NLA_POLICY_NESTED(wlan_hdd_set_ratemask_param_policy),
+	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE] = {.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP] = {.type = NLA_BINARY,
+							 .len = 128},
+};
+
+/**
+ * hdd_set_ratemask_params() - parse ratemask params
+ * @hdd_ctx:        HDD context
+ * @tb:            list of attributes
+ * @vdev_id:       vdev id
+ *
+ * Return: 0 on success; error number on failure
+ */
+static int hdd_set_ratemask_params(struct hdd_context *hdd_ctx,
+				   const void *data, int data_len,
+				   struct wlan_objmgr_vdev *vdev)
+{
+	struct nlattr *tb[RATEMASK_PARAMS_MAX + 1];
+	struct nlattr *tb2[RATEMASK_PARAMS_MAX + 1];
+	struct nlattr *curr_attr;
+	int ret, rem;
+	struct config_ratemask_params rate_params[RATEMASK_PARAMS_TYPE_MAX];
+	uint8_t ratemask_type, num_ratemask = 0, len;
+	uint32_t bitmap[RATEMASK_PARAMS_TYPE_MAX] = {0};
+
+	ret = wlan_cfg80211_nla_parse(tb,
+				      RATEMASK_PARAMS_MAX,
+				      data, data_len,
+				      wlan_hdd_set_ratemask_param_policy);
+	if (ret) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST]) {
+		hdd_err("ratemask array attribute not present");
+		return -EINVAL;
+	}
+
+	memset(rate_params, 0, (RATEMASK_PARAMS_TYPE_MAX *
+				sizeof(struct config_ratemask_params)));
+
+	nla_for_each_nested(curr_attr,
+			    tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST],
+			    rem) {
+		if (num_ratemask >= RATEMASK_PARAMS_TYPE_MAX) {
+			hdd_err("Exceeding ratemask_list_param_num value");
+			return -EINVAL;
+		}
+
+		if (wlan_cfg80211_nla_parse(
+				tb2, RATEMASK_PARAMS_MAX,
+				nla_data(curr_attr), nla_len(curr_attr),
+				wlan_hdd_set_ratemask_param_policy)) {
+			hdd_err("nla_parse failed");
+			return -EINVAL;
+		}
+
+		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]) {
+			hdd_err("type attribute not present");
+			return -EINVAL;
+		}
+
+		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]) {
+			hdd_err("bitmap attribute not present");
+			return -EINVAL;
+		}
+
+		ratemask_type =
+		 nla_get_u8(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]);
+		if (ratemask_type >= RATEMASK_PARAMS_TYPE_MAX) {
+			hdd_err("invalid ratemask type");
+			return -EINVAL;
+		}
+
+		len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]);
+		nla_memcpy((void *)bitmap,
+			   tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP],
+			   len);
+
+		hdd_debug("rate_type:%d, lower32 0x%x, lower32_2 0x%x, higher32 0x%x, higher32_2 0x%x",
+			  ratemask_type, bitmap[0], bitmap[1],
+			  bitmap[2], bitmap[3]);
+
+		rate_params[num_ratemask].type = ratemask_type;
+		rate_params[num_ratemask].lower32 = bitmap[0];
+		rate_params[num_ratemask].lower32_2 = bitmap[1];
+		rate_params[num_ratemask].higher32 = bitmap[2];
+		rate_params[num_ratemask].higher32_2 = bitmap[3];
+
+		num_ratemask += 1;
+	}
+
+	ret = ucfg_set_ratemask_params(vdev, num_ratemask, rate_params);
+	if (ret)
+		hdd_err("ucfg_set_ratemask_params failed");
+	return ret;
+}
+
+/**
+ * __wlan_hdd_cfg80211_set_ratemask_config() - Ratemask parameters
+ * @wiphy:                 The wiphy structure
+ * @wdev:                  The wireless device
+ * @data:                  Data passed by framework
+ * @data_len:              Parameters to be configured passed as data
+ *
+ * The ratemask parameters are configured by the framework
+ * using this interface.
+ *
+ * Return: Return either success or failure code.
+ */
+static int
+__wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct wlan_objmgr_vdev *vdev;
+	int ret;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
+		hdd_err("Driver Modules are closed");
+		return -EINVAL;
+	}
+
+	vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID);
+	if (!vdev) {
+		hdd_err("vdev not present");
+		return -EINVAL;
+	}
+
+	ret = hdd_set_ratemask_params(hdd_ctx, data, data_len, vdev);
+	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
+	if (ret)
+		goto fail;
+
+	return 0;
+fail:
+	return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_ratemask_config() - set ratemask config
+ * @wiphy:   pointer to wireless wiphy structure.
+ * @wdev:    pointer to wireless_dev structure.
+ * @data:    Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Return:   Return the Success or Failure code.
+ */
+static int
+wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data,
+				      int data_len)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_set_ratemask_config(wiphy, wdev,
+							data, data_len);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
+
 #define PWR_SAVE_FAIL_CMD_INDEX \
 	QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
 
@@ -17121,6 +17304,16 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 		vendor_command_policy(wlan_hdd_set_roam_param_policy,
 				      QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX)
 	},
+	{
+		.info.vendor_id = QCA_NL80211_VENDOR_ID,
+		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG,
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			WIPHY_VENDOR_CMD_NEED_NETDEV |
+			WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlan_hdd_cfg80211_set_ratemask_config,
+		vendor_command_policy(wlan_hdd_set_ratemask_param_policy,
+				      QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX)
+	},
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,