ソースを参照

qcacld-3.0: Add support to process twt qca vendor command

Add support to process twt qca vendor command.

Change-Id: I2691ce7d1cc50798d99104389fe2213791ebdf78
CRs-Fixed: 2328891
Arif Hussain 6 年 前
コミット
1f58cbbf36

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

@@ -59,6 +59,7 @@
 #include "wlan_hdd_wmm.h"
 #include "wma_types.h"
 #include "wma.h"
+#include "wma_twt.h"
 #include "wlan_hdd_misc.h"
 #include "wlan_hdd_nan.h"
 #include "wlan_logging_sock_svc.h"
@@ -5301,6 +5302,20 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
 
 };
 
+static const struct nla_policy qca_wlan_vendor_twt_add_dialog_policy[
+		QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME] = {.type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION] = {.type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA] = {
+		.type = NLA_U32 },
+};
+
 static const struct nla_policy
 qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] =       {.type = NLA_U8 },
@@ -5367,6 +5382,12 @@ wlan_hdd_wifi_test_config_policy[
 			= {.type = NLA_U8},
 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
 			.type = NLA_U8},
+		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
+			.type = NLA_NESTED},
+		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
+			.type = NLA_NESTED},
+		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
+			.type = NLA_U8},
 };
 
 /**
@@ -7178,6 +7199,163 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 						adapter->vdev_id, cfg_val);
 	}
 
+	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
+		struct wmi_twt_add_dialog_param params = {0};
+		struct hdd_station_ctx *hdd_sta_ctx =
+			WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+		uint32_t wake_intvl_exp = 0, result = 0;
+		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+		struct nlattr *twt_session;
+		int tmp, rc;
+
+		if ((adapter->device_mode != QDF_STA_MODE &&
+		     adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
+		    hdd_sta_ctx->conn_info.conn_state !=
+		    eConnectionState_Associated) {
+			hdd_err("Invalid state, vdev %d mode %d state %d",
+				adapter->vdev_id, adapter->device_mode,
+				hdd_sta_ctx->conn_info.conn_state);
+			goto send_err;
+		}
+
+		qdf_mem_copy(params.peer_macaddr,
+			     hdd_sta_ctx->conn_info.bssid.bytes,
+			     QDF_MAC_ADDR_SIZE);
+		params.vdev_id = adapter->vdev_id;
+		params.dialog_id = 0;
+
+		cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP;
+		nla_for_each_nested(twt_session, tb[cmd_id], tmp) {
+			rc = wlan_cfg80211_nla_parse(
+					tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+					nla_data(twt_session),
+					nla_len(twt_session),
+					qca_wlan_vendor_twt_add_dialog_policy);
+			if (rc) {
+				hdd_err("Invalid twt ATTR");
+				goto send_err;
+			}
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
+			if (tb2[cmd_id])
+				wake_intvl_exp = nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
+			if (tb2[cmd_id])
+				params.flag_bcast = nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE;
+			if (tb2[cmd_id])
+				params.twt_cmd = nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
+			if (tb2[cmd_id])
+				params.flag_trigger = nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
+			if (tb2[cmd_id])
+				params.flag_flow_type = nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
+			if (tb2[cmd_id])
+				params.flag_protection =
+					nla_get_u8(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
+			if (tb2[cmd_id])
+				params.sp_offset_us = nla_get_u32(tb2[cmd_id]);
+
+			cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
+			if (tb2[cmd_id])
+				params.wake_dura_us =
+					256 * nla_get_u32(tb2[cmd_id]);
+
+			cmd_id =
+			QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
+			if (tb2[cmd_id])
+				params.wake_intvl_mantis =
+					nla_get_u32(tb2[cmd_id]);
+
+			if (wake_intvl_exp) {
+				if (((sizeof(UINT_MAX) / 8) - 2) <
+				    (wake_intvl_exp - 1)) {
+					hdd_err("Invalid wake_intvl_exp %d",
+						wake_intvl_exp);
+					goto send_err;
+				}
+				result = 2 << (wake_intvl_exp - 1);
+				if (result >
+				    (UINT_MAX / params.wake_intvl_mantis)) {
+					hdd_err("Invalid exp %d mantissa %d",
+						wake_intvl_exp,
+						params.wake_intvl_mantis);
+					goto send_err;
+				}
+				params.wake_intvl_us =
+					params.wake_intvl_mantis * result;
+			} else {
+				params.wake_intvl_us = params.wake_intvl_mantis;
+			}
+
+			if (params.wake_dura_us > 0xFFFF) {
+				hdd_err("Invalid wake_dura_us %d",
+					params.wake_dura_us);
+				goto send_err;
+			}
+
+			hdd_debug("twt: vdev %d, intvl_us %d, mantis %d",
+				  params.vdev_id, params.wake_intvl_us,
+				  params.wake_intvl_mantis);
+			hdd_debug("twt: dura %d, offset %d, cmd %d",
+				  params.wake_dura_us, params.sp_offset_us,
+				  params.twt_cmd);
+			hdd_debug("twt: bcast %d, trigger %d, type %d, prot %d",
+				  params.flag_bcast, params.flag_trigger,
+				  params.flag_flow_type,
+				  params.flag_protection);
+
+			ret_val = qdf_status_to_os_return(
+					wma_twt_process_add_dialog(&params));
+			if (ret_val)
+				goto send_err;
+		}
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
+		struct wmi_twt_del_dialog_param params = {0};
+		struct hdd_station_ctx *hdd_sta_ctx =
+			WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+		if ((adapter->device_mode != QDF_STA_MODE &&
+		     adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
+		    hdd_sta_ctx->conn_info.conn_state !=
+		    eConnectionState_Associated) {
+			hdd_err("Invalid state, vdev %d mode %d state %d",
+				adapter->vdev_id, adapter->device_mode,
+				hdd_sta_ctx->conn_info.conn_state);
+			goto send_err;
+		}
+		qdf_mem_copy(params.peer_macaddr,
+			     hdd_sta_ctx->conn_info.bssid.bytes,
+			     QDF_MAC_ADDR_SIZE);
+		params.vdev_id = adapter->vdev_id;
+		params.dialog_id = 0;
+		hdd_debug("twt_terminate: vdev_id %d", params.vdev_id);
+		ret_val = qdf_status_to_os_return(
+				wma_twt_process_del_dialog(&params));
+		if (ret_val)
+			goto send_err;
+	}
+
+	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
+	if (tb[cmd_id]) {
+		cfg_val = nla_get_u8(tb[cmd_id]);
+		hdd_debug("twt_request: val %d", cfg_val);
+		ret_val = sme_update_he_twt_req_support(hdd_ctx->mac_handle,
+							adapter->vdev_id,
+							cfg_val);
+	}
+
 	if (update_sme_cfg)
 		sme_update_config(mac_handle, sme_config);
 

+ 19 - 0
core/sme/inc/sme_api.h

@@ -2829,6 +2829,17 @@ int sme_update_he_frag_supp(mac_handle_t mac_handle, uint8_t session_id,
  */
 int sme_update_he_ldpc_supp(mac_handle_t mac_handle, uint8_t session_id,
 			    uint16_t he_ldpc);
+
+/**
+ * sme_update_he_twt_req_support() - Sets twt request capability
+ * @mac_handle: Opaque handle to the global MAC context
+ * @session_id: SME session id
+ * @value: set value
+ *
+ * Return: 0 on success else err code
+ */
+int sme_update_he_twt_req_support(mac_handle_t mac_handle, uint8_t session_id,
+				  uint8_t cfg_val);
 #else
 static inline void sme_update_tgt_he_cap(mac_handle_t mac_handle,
 					 struct wma_tgt_cfg *cfg,
@@ -2952,6 +2963,14 @@ static inline void sme_set_he_tx_bf_cbf_rates(uint8_t session_id)
 static inline void sme_config_su_ppdu_queue(uint8_t session_id, bool enable)
 {
 }
+
+static inline int sme_update_he_twt_req_support(mac_handle_t mac_handle,
+						uint8_t session_id,
+						uint8_t cfg_val)
+{
+	return 0;
+}
+
 #endif
 
 /**

+ 19 - 0
core/sme/src/common/sme_api.c

@@ -11743,6 +11743,25 @@ int sme_update_he_ldpc_supp(mac_handle_t mac_handle, uint8_t session_id,
 	return 0;
 
 }
+
+int sme_update_he_twt_req_support(mac_handle_t mac_handle, uint8_t session_id,
+				  uint8_t cfg_val)
+{
+	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+	struct csr_roam_session *session;
+
+	session = CSR_GET_SESSION(mac_ctx, session_id);
+
+	if (!session) {
+		sme_err("No session for id %d", session_id);
+		return -EINVAL;
+	}
+	mac_ctx->mlme_cfg->he_caps.dot11_he_cap.twt_request = cfg_val;
+
+	csr_update_session_he_cap(mac_ctx, session);
+
+	return 0;
+}
 #endif
 
 /**

+ 35 - 1
core/wma/inc/wma_twt.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019 The Linux Foundation. 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
@@ -20,6 +20,7 @@
 #define __WMA_TWT_H
 
 #include "wma.h"
+#include "wmi_unified_twt_param.h"
 
 #ifdef WLAN_SUPPORT_TWT
 /**
@@ -40,6 +41,23 @@ void wma_send_twt_enable_cmd(uint32_t pdev_id, uint32_t congestion_timeout);
  */
 void wma_set_twt_peer_caps(tpAddStaParams params,
 			   struct peer_assoc_params *cmd);
+
+/**
+ * wma_twt_process_add_dialog() - Process twt add dialog command
+ * @params: add dialog configuration param
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_twt_process_add_dialog(struct wmi_twt_add_dialog_param *params);
+
+/**
+ * wma_twt_process_del_dialog() - Process del dialog command
+ * @params: del dialog configuration param
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_twt_process_del_dialog(struct wmi_twt_del_dialog_param *params);
+
 #else
 static inline void wma_send_twt_enable_cmd(uint32_t pdev_id,
 					   uint32_t congestion_timeout)
@@ -51,6 +69,22 @@ static inline void wma_set_twt_peer_caps(tpAddStaParams params,
 					 struct peer_assoc_params *cmd)
 {
 }
+
+static inline QDF_STATUS wma_twt_process_add_dialog(
+		struct wmi_twt_add_dialog_param *params)
+{
+	WMA_LOGD(FL("TWT not supported as WLAN_SUPPORT_TWT is disabled"));
+
+	return QDF_STATUS_E_INVAL;
+}
+
+static inline QDF_STATUS wma_twt_process_del_dialog(
+		struct wmi_twt_del_dialog_param *params)
+{
+	WMA_LOGD(FL("TWT not supported as WLAN_SUPPORT_TWT is disabled"));
+
+	return QDF_STATUS_E_INVAL;
+}
 #endif
 
 #endif /* __WMA_HE_H */

+ 41 - 1
core/wma/src/wma_twt.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019 The Linux Foundation. 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
@@ -88,3 +88,43 @@ void wma_set_twt_peer_caps(tpAddStaParams params, struct peer_assoc_params *cmd)
 		cmd->peer_flags |= WMI_PEER_TWT_RESP;
 }
 
+QDF_STATUS wma_twt_process_add_dialog(
+		struct wmi_twt_add_dialog_param *params)
+{
+	t_wma_handle *wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
+	wmi_unified_t wmi_handle;
+
+	if (!wma_handle) {
+		WMA_LOGE("Invalid WMA context, twt add dialog failed");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = (wmi_unified_t)wma_handle->wmi_handle;
+	if (!wmi_handle) {
+		WMA_LOGE("Invalid wmi handle, twt add dialog failed");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return wmi_unified_twt_add_dialog_cmd(wmi_handle, params);
+}
+
+QDF_STATUS wma_twt_process_del_dialog(
+		struct wmi_twt_del_dialog_param *params)
+{
+	t_wma_handle *wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
+	wmi_unified_t wmi_handle;
+
+	if (!wma_handle) {
+		WMA_LOGE("Invalid WMA context, twt del dialog failed");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = (wmi_unified_t)wma_handle->wmi_handle;
+	if (!wmi_handle) {
+		WMA_LOGE("Invalid wmi handle, twt del dialog failed");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return wmi_unified_twt_del_dialog_cmd(wmi_handle, params);
+}
+