Переглянути джерело

qcacld-3.0: Handle VENDOR_SUBCMD_SR and operation

Add support to parse VENDOR_SUBCMD_SR and to parse
nested attributes OPERATION and PARAMS and to handle
ENABLE operation, Disable operation and prohibit
operation. Enable opeartion may have PD threshold
or in case vendor command doesn't provide PD threshold
host will send PD threshold advertised by AP.

Change-Id: Ie98a1b8681f41f3a63523ac40b5cfb688a7b0cb0
CRs-Fixed: 3299042
Sheenam Monga 2 роки тому
батько
коміт
c4c40f5217

+ 26 - 0
components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h

@@ -37,4 +37,30 @@ QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev,
 					 uint8_t sr_ctrl,
 					 uint8_t non_srg_max_pd_offset);
 
+/**
+ * wlan_spatial_reuse_he_siga_val15_allowed_set() - Set spatial reuse config
+ *						    he_siga_val15_allowed
+ * @vdev: objmgr manager vdev
+ * @he_siga_va15_allowed: enable/disable he_siga_val15_allowed
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_spatial_reuse_he_siga_val15_allowed_set(
+					struct wlan_objmgr_vdev *vdev,
+					bool he_siga_va15_allowed);
+
+/**
+ * wlan_sr_setup_req() - Enable SR with provided pd threshold
+ *
+ * @vdev: objmgr vdev
+ * @pdev: objmgr pdev
+ * @is_sr_enable: sr enable/disable
+ * @pd_threshold: pd threshold
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_sr_setup_req(struct wlan_objmgr_vdev *vdev,
+		  struct wlan_objmgr_pdev *pdev, bool is_sr_enable,
+		  int32_t pd_threshold);
 #endif

+ 40 - 2
components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h

@@ -20,9 +20,9 @@
 #ifndef _SPATIAL_REUSE_UCFG_API_H_
 #define _SPATIAL_REUSE_UCFG_API_H_
 
+#ifdef WLAN_FEATURE_SR
 #include <qdf_trace.h>
 #include <wlan_objmgr_vdev_obj.h>
-
 /**
  * ucfg_spatial_reuse_get_sr_config() - Spatial reuse config get
  *
@@ -60,5 +60,43 @@ void ucfg_spatial_reuse_set_sr_config(struct wlan_objmgr_vdev *vdev,
  */
 void ucfg_spatial_reuse_send_sr_config(struct wlan_objmgr_vdev *vdev,
 				       bool enable);
-#endif
 
+/**
+ * ucfg_spatial_reuse_set_sr_enable() - set enable/disable Spatial reuse
+ *
+ * @vdev: object manager vdev
+ * @enable: spatial reuse to be enabled or not
+ *
+ * Return: void
+ */
+void ucfg_spatial_reuse_set_sr_enable(struct wlan_objmgr_vdev *vdev,
+				      bool enable);
+
+/**
+ * ucfg_spatial_reuse_send_sr_prohibit() - Send spatial reuse config to enable
+ *					   or disbale he_siga_val15_allowed
+ *
+ * @vdev: object manager vdev
+ * @enable_he_siga_val15_prohibit: enable/disable he_siga_val15_allowed
+ *
+ * Return: void
+ */
+void ucfg_spatial_reuse_send_sr_prohibit(struct wlan_objmgr_vdev *vdev,
+					 bool enable_he_siga_val15_prohibit);
+
+/**
+ * ucfg_spatial_reuse_setup_req() - To enable/disable SR
+ *
+ * vdev: object manager vdev
+ * pdev: object manager pdev
+ * is_sr_enable: sr enable/disable
+ * pd_threshold: pd thresold
+ *
+ * Return: Success/Failure
+ */
+QDF_STATUS ucfg_spatial_reuse_setup_req(struct wlan_objmgr_vdev *vdev,
+					struct wlan_objmgr_pdev *pdev,
+					bool is_sr_enable,
+					int32_t pd_threshold);
+#endif
+#endif

+ 38 - 1
components/spatial_reuse/dispatcher/src/spatial_reuse_api.c

@@ -17,7 +17,6 @@
 /**
  * DOC : contains interface prototypes for spatial_reuse api
  */
-
 #include <spatial_reuse_api.h>
 
 QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev,
@@ -40,3 +39,41 @@ QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev,
 
 	return QDF_STATUS_E_NULL_VALUE;
 }
+
+QDF_STATUS wlan_spatial_reuse_he_siga_val15_allowed_set(
+					struct wlan_objmgr_vdev *vdev,
+					bool he_siga_va15_allowed)
+{
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
+
+	if (!psoc)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	if (!tx_ops)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	if (tx_ops->spatial_reuse_tx_ops.send_sr_prohibit_cfg)
+		return tx_ops->spatial_reuse_tx_ops.send_sr_prohibit_cfg(
+							vdev,
+							he_siga_va15_allowed);
+	return QDF_STATUS_E_NULL_VALUE;
+}
+
+QDF_STATUS
+wlan_sr_setup_req(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_pdev *pdev,
+		  bool is_sr_enable, int32_t pd_threshold) {
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	tx_ops = wlan_psoc_get_lmac_if_txops(wlan_pdev_get_psoc(pdev));
+	if (tx_ops &&
+	    tx_ops->spatial_reuse_tx_ops.target_if_set_sr_enable_disable) {
+		status =
+		tx_ops->spatial_reuse_tx_ops.target_if_set_sr_enable_disable(
+					vdev, pdev, is_sr_enable, pd_threshold);
+		return status;
+	}
+	return status;
+}

+ 24 - 1
components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c

@@ -17,7 +17,6 @@
 /**
  * DOC : contains interface prototypes for OS_IF layer
  */
-
 #include <qdf_trace.h>
 #include <spatial_reuse_ucfg_api.h>
 #include <spatial_reuse_api.h>
@@ -60,3 +59,27 @@ void ucfg_spatial_reuse_send_sr_config(struct wlan_objmgr_vdev *vdev,
 		wlan_vdev_mlme_set_he_spr_enabled(vdev, false);
 	}
 }
+
+void ucfg_spatial_reuse_set_sr_enable(struct wlan_objmgr_vdev *vdev,
+				      bool enable)
+{
+	 wlan_vdev_mlme_set_he_spr_enabled(vdev, enable);
+}
+
+void ucfg_spatial_reuse_send_sr_prohibit(struct wlan_objmgr_vdev *vdev,
+					 bool enable_he_siga_val15_prohibit)
+{
+	bool sr_enabled = wlan_vdev_mlme_get_he_spr_enabled(vdev);
+
+	if (sr_enabled)
+		wlan_spatial_reuse_he_siga_val15_allowed_set(
+					vdev, enable_he_siga_val15_prohibit);
+}
+
+QDF_STATUS
+ucfg_spatial_reuse_setup_req(struct wlan_objmgr_vdev *vdev,
+			     struct wlan_objmgr_pdev *pdev,
+			     bool is_sr_enable, int32_t pd_threshold)
+{
+	return wlan_sr_setup_req(vdev, pdev, is_sr_enable, pd_threshold);
+}

+ 38 - 0
core/hdd/inc/wlan_hdd_he.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -66,6 +67,10 @@ enum qca_wlan_vendor_attr_get_he_capabilities {
 	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1,
 };
 
+/* QCA_NL80211_VENDOR_SUBCMD_SR policy*/
+extern const struct nla_policy
+wlan_hdd_sr_policy[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1];
+
 /**
  * hdd_update_tgt_he_cap() - Update HE related capabilities
  * @hdd_ctx: HDD context
@@ -116,6 +121,29 @@ int hdd_update_he_cap_in_cfg(struct hdd_context *hdd_ctx);
 int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
 				 struct wireless_dev *wdev, const void *data,
 				 int data_len);
+#ifdef WLAN_FEATURE_SR
+/**
+ * wlan_hdd_cfg80211_sr_operations() - Spatial Reuse Operations
+ * @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.
+ */
+int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data, int data_len);
+#else
+static inline
+int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data, int data_len)
+{
+	return 0;
+}
+#endif
+
 #define FEATURE_11AX_VENDOR_COMMANDS                                    \
 {                                                                       \
 	.info.vendor_id = QCA_NL80211_VENDOR_ID,                        \
@@ -124,6 +152,16 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
 		 WIPHY_VENDOR_CMD_NEED_NETDEV,                          \
 	.doit = wlan_hdd_cfg80211_get_he_cap,                           \
 	vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)                   \
+},									\
+{                                                                       \
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,                        \
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SR,			\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |                           \
+		 WIPHY_VENDOR_CMD_NEED_NETDEV |                         \
+		 WIPHY_VENDOR_CMD_NEED_RUNNING,				\
+	.doit = wlan_hdd_cfg80211_sr_operations,			\
+	vendor_command_policy(wlan_hdd_sr_policy,			\
+			      QCA_WLAN_VENDOR_ATTR_SR_MAX)		\
 },
 
 #else

+ 192 - 1
core/hdd/src/wlan_hdd_he.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -30,6 +30,34 @@
 #include "wma_he.h"
 #include "wlan_utility.h"
 #include "wlan_mlme_ucfg_api.h"
+#include "spatial_reuse_ucfg_api.h"
+
+const struct nla_policy
+wlan_hdd_sr_policy[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_SR_OPERATION] = {.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS] = {.type = NLA_NESTED},
+	[QCA_WLAN_VENDOR_ATTR_SR_STATS] = {.type = NLA_NESTED},
+};
+
+static const struct nla_policy
+qca_wlan_vendor_srp_param_policy[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE] = {
+							.type = NLA_FLAG},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW] = {
+							.type = NLA_FLAG},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET] = {
+							.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET] = {
+							.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET] = {
+							.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD] = {
+							.type = NLA_S32},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD] = {
+							.type = NLA_S32},
+	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE] = {.type = NLA_U32},
+
+};
 
 void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx,
 			   struct wma_tgt_cfg *cfg)
@@ -216,3 +244,166 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
 
 	return errno;
 }
+
+/**
+ * __wlan_hdd_cfg80211_sr_operations: To handle SR operation
+ *
+ * @wiphy: wiphy structure
+ * @wdev: wireless dev
+ * @data: vendor command data
+ * @data_len: data len
+ *
+ * return: success/failure code
+ */
+#ifdef WLAN_FEATURE_SR
+static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data, int data_len)
+{
+	QDF_STATUS status;
+	uint32_t id;
+	bool is_sr_enable = false;
+	int32_t pd_threshold = 0;
+	uint8_t sr_he_siga_val15_allowed = true;
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1];
+	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1];
+	enum qca_wlan_sr_operation sr_oper;
+	struct nlattr *sr_oper_attr;
+	struct nlattr *sr_param_attr;
+	uint8_t sr_ctrl, non_srg_max_pd_offset;
+	int ret = 0;
+
+	hdd_enter_dev(wdev->netdev);
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
+	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM or Monitor mode");
+		return -EPERM;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret)
+		return ret;
+	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
+		hdd_err("Driver Modules are closed");
+		return -EINVAL;
+	}
+	if (!sme_is_feature_supported_by_fw(DOT11AX)) {
+		hdd_err("11AX is not supported");
+		return -EINVAL;
+	}
+	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SR_MAX, data,
+				    data_len, wlan_hdd_sr_policy)) {
+		hdd_err("invalid attr");
+		return -EINVAL;
+	}
+	id = QCA_WLAN_VENDOR_ATTR_SR_OPERATION;
+	sr_oper_attr = tb[id];
+
+	if (!sr_oper_attr) {
+		hdd_err("SR operation not specified");
+		return -EINVAL;
+	}
+
+	sr_oper = nla_get_u8(sr_oper_attr);
+	hdd_debug("SR Operation 0x%x", sr_oper);
+
+	ucfg_spatial_reuse_get_sr_config(adapter->vdev, &sr_ctrl,
+					 &non_srg_max_pd_offset, &is_sr_enable);
+
+	if (sr_oper != QCA_WLAN_SR_OPERATION_SR_ENABLE && !is_sr_enable) {
+		hdd_err("SR operation not allowed");
+		return -EINVAL;
+	}
+
+	id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS;
+	sr_param_attr = tb[id];
+	if (sr_param_attr)
+		ret = wlan_cfg80211_nla_parse_nested(
+				tb2, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX,
+				sr_param_attr,
+				qca_wlan_vendor_srp_param_policy);
+	switch (sr_oper) {
+	case QCA_WLAN_SR_OPERATION_SR_ENABLE:
+	case QCA_WLAN_SR_OPERATION_SR_DISABLE:
+		if (sr_oper == QCA_WLAN_SR_OPERATION_SR_ENABLE)
+			is_sr_enable = 1;
+		else
+			is_sr_enable = 0;
+		/**
+		 * As per currenct implementation from userspace same
+		 * PD threshold value is configured for both SRG and
+		 * NON-SRG and fw will decide further based on BSS color
+		 * So only SRG param is parsed and set as pd threshold
+		 */
+		if (is_sr_enable &&
+		    tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]) {
+			pd_threshold =
+			nla_get_s32(
+			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]);
+		}
+		hdd_debug("setting sr enable %d with pd threshold %d",
+			  is_sr_enable, pd_threshold);
+		/* Set the variables */
+		ucfg_spatial_reuse_set_sr_enable(adapter->vdev, is_sr_enable);
+		status = ucfg_spatial_reuse_setup_req(adapter->vdev,
+						      hdd_ctx->pdev,
+						      is_sr_enable,
+						      pd_threshold);
+		if (status != QDF_STATUS_SUCCESS) {
+			hdd_err("failed to enable Spatial Reuse feature");
+			return -EINVAL;
+		}
+
+		break;
+	case QCA_WLAN_SR_OPERATION_GET_STATS:
+		break;
+	case QCA_WLAN_SR_OPERATION_CLEAR_STATS:
+		break;
+	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT:
+		if (tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE])
+			sr_he_siga_val15_allowed = nla_get_u8(
+			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE]
+			);
+		if (!sr_he_siga_val15_allowed) {
+			hdd_err("invalid sr_he_siga_val15_enable param");
+			return -EINVAL;
+		}
+		ucfg_spatial_reuse_send_sr_prohibit(adapter->vdev,
+						    sr_he_siga_val15_allowed);
+		break;
+	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW:
+		ucfg_spatial_reuse_send_sr_prohibit(adapter->vdev, false);
+		break;
+	case QCA_WLAN_SR_OPERATION_GET_PARAMS:
+		break;
+	default:
+		hdd_err("Invalid SR Operation");
+		ret = -EINVAL;
+		break;
+	}
+
+	hdd_exit();
+
+	return ret;
+}
+
+int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data, int data_len)
+{
+	struct osif_psoc_sync *psoc_sync;
+	int errno;
+
+	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_sr_operations(wiphy, wdev, data, data_len);
+
+	osif_psoc_sync_op_stop(psoc_sync);
+
+	return errno;
+}
+#endif

+ 1 - 2
core/hdd/src/wlan_hdd_hostapd.c

@@ -7369,7 +7369,7 @@ wlan_util_get_centre_freq(struct wireless_dev *wdev, unsigned int link_id)
 }
 #endif
 
-#if defined WLAN_FEATURE_11AX
+#ifdef WLAN_FEATURE_SR
 void hdd_update_he_obss_pd(struct hdd_adapter *adapter,
 			   struct cfg80211_ap_settings *params,
 			   bool iface_start)
@@ -7412,7 +7412,6 @@ void hdd_update_he_obss_pd(struct hdd_adapter *adapter,
 							WLAN_HDD_ID_OBJ_MGR);
 		if (!conc_vdev)
 			goto release_ref;
-
 		if (iface_start) {
 			ucfg_spatial_reuse_send_sr_config(conc_vdev, false);
 			hdd_debug("disable obss pd for vdev:%d", conc_vdev_id);