From 93b889498a48540fdc715dd83c6dc46734dab37f Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 6 Oct 2020 15:07:22 +0530 Subject: [PATCH] qcacld-3.0: Trigger MSCS action frame Add logic to send MSCS action frame to AP based on voice tx packet. Change-Id: I272addfcb60e459043426950d00ba5957b594505 CRs-Fixed: 2791796 --- Kbuild | 3 + components/mlme/core/inc/wlan_mlme_main.h | 92 +++++++++++++ .../core/inc/wlan_mlme_vdev_mgr_interface.h | 31 +++++ .../core/src/wlan_mlme_vdev_mgr_interface.c | 30 +++++ configs/default_defconfig | 3 + core/hdd/inc/hdd_dp_cfg.h | 60 +++++++++ core/hdd/inc/wlan_hdd_cfg.h | 5 + core/hdd/inc/wlan_hdd_main.h | 5 + core/hdd/src/wlan_hdd_cfg80211.c | 23 ++++ core/hdd/src/wlan_hdd_main.c | 39 ++++++ core/hdd/src/wlan_hdd_tx_rx.c | 25 ++++ core/mac/inc/wni_api.h | 3 +- core/mac/src/include/parser_api.h | 7 + .../src/pe/lim/lim_process_message_queue.c | 1 + .../src/pe/lim/lim_process_sme_req_messages.c | 62 +++++++++ .../src/pe/lim/lim_send_management_frames.c | 127 ++++++++++++++++++ core/mac/src/pe/lim/lim_types.h | 18 +++ core/mac/src/pe/lim/lim_utils.c | 2 + .../src/sys/legacy/src/utils/src/mac_trace.c | 1 + .../src/sys/legacy/src/utils/src/parser_api.c | 22 +++ core/sme/inc/sme_api.h | 12 ++ core/sme/src/qos/sme_qos.c | 49 +++++++ 22 files changed, 619 insertions(+), 1 deletion(-) diff --git a/Kbuild b/Kbuild index 0f91594a9c0a..e84c8647e161 100644 --- a/Kbuild +++ b/Kbuild @@ -3369,6 +3369,9 @@ cppflags-$(CONFIG_ADAPTIVE_11R) += -DWLAN_ADAPTIVE_11R #Flag to enable/disable sae single pmk feature feature cppflags-$(CONFIG_SAE_SINGLE_PMK) += -DWLAN_SAE_SINGLE_PMK +#Flag to enable/disable mscs feature +cppflags-$(CONFIG_FEATURE_MSCS) += -DWLAN_FEATURE_MSCS + #Flag to enable NUD tracking cppflags-$(CONFIG_WLAN_NUD_TRACKING) += -DWLAN_NUD_TRACKING diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index e161b9b33d32..0ebb5ebcca27 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -144,6 +144,94 @@ struct wlan_mlme_roam { #endif }; +#ifdef WLAN_FEATURE_MSCS +/** + * struct tclas_mask - TCLAS Mask Elements for mscs request + * @classifier_type: specifies the type of classifier parameters + * in TCLAS element. Currently driver supports classifier type = 4 only. + * @classifier_mask: Mask for tclas elements. For example, if + * classifier type = 4, value of classifier mask is 0x5F. + * @info: information of classifier type + */ +struct tclas_mask { + uint8_t classifier_type; + uint8_t classifier_mask; + union { + struct { + uint8_t version; + union { + struct { + uint8_t source[4]; + uint8_t dest[4]; + uint16_t src_port; + uint16_t dest_port; + uint8_t dscp; + uint8_t proto; + uint8_t reserved; + } ip_v4_params; + struct { + uint8_t source[16]; + uint8_t dest[16]; + uint16_t src_port; + uint16_t dest_port; + uint8_t DSCP; + uint8_t next_header; + uint8_t flow_label[3]; + } ip_v6_params; + } params; + } ip_params; /* classifier_type = 4 */ + } info; +}; + +/** + * enum scs_request_type - scs request type to peer + * @SCS_REQ_ADD: To set mscs parameters + * @SCS_REQ_REMOVE: Remove mscs parameters + * @SCS_REQ_CHANGE: Update mscs parameters + */ +enum scs_request_type { + SCS_REQ_ADD = 0, + SCS_REQ_REMOVE = 1, + SCS_REQ_CHANGE = 2, +}; + +/** + * struct descriptor_element - mscs Descriptor element + * @request_type: mscs request type defined in enum scs_request_type + * @user_priority_control: To set user priority of tx packet + * @stream_timeout: minimum timeout value, in TUs, for maintaining + * variable user priority in the MSCS list. + * @tclas_mask: to specify how incoming MSDUs are classified into + * streams in MSCS + * @status_code: status of mscs request + */ +struct descriptor_element { + uint8_t request_type; + uint16_t user_priority_control; + uint64_t stream_timeout; + struct tclas_mask tclas_mask; + uint8_t status_code; +}; + +/** + * struct mscs_req_info - mscs request information + * @vdev_id: session id + * @bssid: peer bssid + * @dialog_token: Token number of mscs req action frame + * @dec: mscs Descriptor element defines information about + * the parameters used to classify streams + * @is_mscs_req_sent: To Save mscs req request if any (only + * one can be outstanding at any time) + */ +struct mscs_req_info { + uint8_t vdev_id; + struct qdf_mac_addr bssid; + uint8_t dialog_token; + struct descriptor_element dec; + bool is_mscs_req_sent; +}; +#endif + /** * struct mlme_legacy_priv - VDEV MLME legacy priv object * @chan_switch_in_progress: flag to indicate that channel switch is in progress @@ -170,6 +258,7 @@ struct wlan_mlme_roam { * @fils_con_info: Pointer to fils connection info from csr roam profile * @opr_rate_set: operational rates set * @ext_opr_rate_set: extended operational rates set + * @mscs_req_info: Information related to mscs request */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -197,6 +286,9 @@ struct mlme_legacy_priv { #endif struct mlme_cfg_str opr_rate_set; struct mlme_cfg_str ext_opr_rate_set; +#ifdef WLAN_FEATURE_MSCS + struct mscs_req_info mscs_req_info; +#endif }; diff --git a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h index bcc46424d65d..03910298a7ae 100644 --- a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h +++ b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h @@ -64,6 +64,37 @@ QDF_STATUS mlme_unregister_vdev_mgr_ops(struct vdev_mlme_obj *vdev_mlme); QDF_STATUS mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, bool val); +#ifdef WLAN_FEATURE_MSCS +/** + * mlme_set_is_mscs_req_sent() - set mscs frame req flag + * @vdev: vdev pointer + * @val: value to be set + * + * Return: QDF_STATUS + */ +QDF_STATUS mlme_set_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev, bool val); + +/** + * mlme_get_is_mscs_req_sent() - get mscs frame req flag + * @vdev: vdev pointer + * + * Return: value of mscs flag + */ +bool mlme_get_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev); +#else +static inline +QDF_STATUS mlme_set_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev, bool val) +{ + return QDF_STATUS_E_FAILURE; +} + +static inline +bool mlme_get_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev) +{ + return false; +} +#endif + /** * mlme_is_chan_switch_in_progress() - get mlme priv restart in progress * @vdev: vdev pointer diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index 3fa16313d241..1c1b375fc8af 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -588,6 +588,36 @@ QDF_STATUS mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_MSCS +QDF_STATUS mlme_set_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev, bool val) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mlme_priv->mscs_req_info.is_mscs_req_sent = val; + + return QDF_STATUS_SUCCESS; +} + +bool mlme_get_is_mscs_req_sent(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return false; + } + + return mlme_priv->mscs_req_info.is_mscs_req_sent; +} +#endif + bool mlme_is_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev) { struct mlme_legacy_priv *mlme_priv; diff --git a/configs/default_defconfig b/configs/default_defconfig index e2a683150adb..554b861879c9 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -300,6 +300,9 @@ CONFIG_ADAPTIVE_11R := y #Flag to enable sae single pmk feature CONFIG_SAE_SINGLE_PMK := y +#Flag to enable mscs feature +CONFIG_FEATURE_MSCS := y + #Flag to enable FILS Feature (11ai) CONFIG_WLAN_FEATURE_FILS := y ifneq ($(CONFIG_QCA_CLD_WLAN),) diff --git a/core/hdd/inc/hdd_dp_cfg.h b/core/hdd/inc/hdd_dp_cfg.h index f65f35fce467..58d34a18170a 100644 --- a/core/hdd/inc/hdd_dp_cfg.h +++ b/core/hdd/inc/hdd_dp_cfg.h @@ -353,6 +353,65 @@ #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ +#ifdef WLAN_FEATURE_MSCS +/* + * + * mscs_pkt_threshold - Voice pkt count threshold + * + * @Min: 0 + * @Max: 10000 + * @Default: 1200 + * + * This ini specifies the Voice pkt count threshold to + * Send MSCS action frame to AP + * + * Usage: Internal + * + * + */ +#define CFG_VO_PKT_COUNT_THRESHOLD \ + CFG_INI_UINT( \ + "mscs_pkt_threshold", \ + 0, \ + 10000, \ + 1200, \ + CFG_VALUE_OR_DEFAULT, \ + "Voice pkt count threshold") + +/* + * + * mscs_voice_interval - mscs voice interval in sec + * + * @Min: 0 + * @Max: 300 + * @Default: 30 + * + * This ini specifies the mscs voice interval to + * monitor voice tx packet count to send MSCS action frame + * + * Related: mscs_pkt_threshold + * + * Usage: Internal + * + * + */ +#define CFG_MSCS_VOICE_INTERVAL \ + CFG_INI_UINT( \ + "mscs_voice_interval", \ + 0, \ + 300, \ + 30, \ + CFG_VALUE_OR_DEFAULT, \ + "mscs voice interval") + +#define CFG_MSCS_FEATURE_ALL \ + CFG(CFG_VO_PKT_COUNT_THRESHOLD) \ + CFG(CFG_MSCS_VOICE_INTERVAL) + +#else +#define CFG_MSCS_FEATURE_ALL +#endif + #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH /* * @@ -1445,6 +1504,7 @@ CFG(CFG_DP_RX_WAKELOCK_TIMEOUT) \ CFG(CFG_DP_NUM_DP_RX_THREADS) \ CFG(CFG_DP_HTC_WMI_CREDIT_CNT) \ + CFG_MSCS_FEATURE_ALL \ CFG_DP_ENABLE_FASTPATH_ALL \ CFG_HDD_DP_BUS_BANDWIDTH \ CFG_DP_DRIVER_TCP_DELACK \ diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 76b602a28be7..b39bf067558b 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -175,6 +175,11 @@ struct hdd_config { bool enable_latency_crit_clients; #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ +#ifdef WLAN_FEATURE_MSCS + uint32_t mscs_pkt_threshold; + uint32_t mscs_voice_interval; +#endif /* WLAN_FEATURE_MSCS */ + #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK bool del_ack_enable; uint32_t del_ack_threshold_high; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3d629419ec7b..41fcbce3ef66 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1316,6 +1316,11 @@ struct hdd_adapter { uint64_t prev_fwd_rx_packets; #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ +#ifdef WLAN_FEATURE_MSCS + unsigned long mscs_prev_tx_vo_pkts; + uint32_t mscs_counter; +#endif /* WLAN_FEATURE_MSCS */ + #if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || \ defined(QCA_HL_NETDEV_FLOW_CONTROL) qdf_mc_timer_t tx_flow_control_timer; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 31c246e45f6c..1334c4c8599b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -21014,6 +21014,28 @@ wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter, } #endif +#ifdef WLAN_FEATURE_MSCS +/** + * reset_mscs_params() - Reset mscs parameters + * @adapter: pointer to adapter structure + * + * Reset mscs parameters whils disconnection + * + * Return: None + */ +static void reset_mscs_params(struct hdd_adapter *adapter) +{ + mlme_set_is_mscs_req_sent(adapter->vdev, false); + adapter->mscs_counter = 0; +} +#else +static inline +void reset_mscs_params(struct hdd_adapter *adapter) +{ + return; +} +#endif + int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason, enum wlan_reason_code mac_reason) { @@ -21025,6 +21047,7 @@ int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason, /*stop tx queues */ hdd_debug("Disabling queues"); + reset_mscs_params(adapter); wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 9516c2864ad7..16053aad5a51 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10065,6 +10065,41 @@ void hdd_set_vdev_bundle_require_flag(uint16_t vdev_id, #endif #define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) + +#ifdef WLAN_FEATURE_MSCS +static +void hdd_send_mscs_action_frame(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter) +{ + uint64_t mscs_vo_pkt_delta; + unsigned long tx_vo_pkts; + + tx_vo_pkts = adapter->hdd_stats.tx_rx_stats.tx_classified_ac[SME_AC_VO]; + + if (!adapter->mscs_counter) + adapter->mscs_prev_tx_vo_pkts = tx_vo_pkts; + + adapter->mscs_counter++; + + if (adapter->mscs_counter * hdd_ctx->config->bus_bw_compute_interval >= + hdd_ctx->config->mscs_voice_interval * 1000) { + adapter->mscs_counter = 0; + mscs_vo_pkt_delta = + HDD_BW_GET_DIFF(tx_vo_pkts, + adapter->mscs_prev_tx_vo_pkts); + if (mscs_vo_pkt_delta > hdd_ctx->config->mscs_pkt_threshold && + !mlme_get_is_mscs_req_sent(adapter->vdev)) + sme_send_mscs_action_frame(adapter->vdev_id); + } +} +#else +static inline +void hdd_send_mscs_action_frame(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter) +{ +} +#endif + static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) { struct hdd_adapter *adapter = NULL, *con_sap_adapter = NULL; @@ -10113,6 +10148,10 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) tx_bytes = HDD_BW_GET_DIFF(adapter->stats.tx_bytes, adapter->prev_tx_bytes); + if (adapter->device_mode == QDF_STA_MODE && + hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) + hdd_send_mscs_action_frame(hdd_ctx, adapter); + if (adapter->device_mode == QDF_SAP_MODE || adapter->device_mode == QDF_P2P_GO_MODE || adapter->device_mode == QDF_NDI_MODE) { diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 2e6f84afb9e7..e76db9bad531 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -3404,6 +3404,30 @@ static void hdd_ini_tx_flow_control(struct hdd_config *config, } #endif +#ifdef WLAN_FEATURE_MSCS +/** + * hdd_ini_mscs_params() - Initialize INIs related to MSCS feature + * @config: pointer to hdd config + * @psoc: pointer to psoc obj + * + * Return: none + */ +static void hdd_ini_mscs_params(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) +{ + config->mscs_pkt_threshold = + cfg_get(psoc, CFG_VO_PKT_COUNT_THRESHOLD); + config->mscs_voice_interval = + cfg_get(psoc, CFG_MSCS_VOICE_INTERVAL); +} + +#else +static inline void hdd_ini_mscs_params(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) +{ +} +#endif + #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH /** * hdd_ini_tx_flow_control() - Initialize INIs concerned about bus bandwidth @@ -3607,6 +3631,7 @@ void hdd_dp_cfg_update(struct wlan_objmgr_psoc *psoc, hdd_ini_tx_flow_control(config, psoc); hdd_ini_bus_bandwidth(config, psoc); hdd_ini_tcp_settings(config, psoc); + hdd_ini_mscs_params(config, psoc); hdd_ini_tcp_del_ack_settings(config, psoc); diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index cbe6e11aecd8..69ed5a0089ac 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -67,8 +67,9 @@ enum eWniMsgTypes { eWNI_SME_DELTS_REQ = SIR_SME_MSG_TYPES_BEGIN + 30, eWNI_SME_DELTS_RSP = SIR_SME_MSG_TYPES_BEGIN + 31, eWNI_SME_DELTS_IND = SIR_SME_MSG_TYPES_BEGIN + 32, + eWNI_SME_MSCS_REQ = SIR_SME_MSG_TYPES_BEGIN + 33, /* - * unused SIR_SME_MSG_TYPES_BEGIN + 33 to + * unused SIR_SME_MSG_TYPES_BEGIN + 34 to * to SIR_SME_MSG_TYPES_BEGIN + 35 */ eWNI_SME_ASSOC_IND_UPPER_LAYER = SIR_SME_MSG_TYPES_BEGIN + 36, diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index cb3784cdf0d4..068fab32c8b9 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -34,6 +34,7 @@ #include "dot11f.h" #include "lim_ft_defs.h" #include "lim_session.h" +#include "wlan_mlme_main.h" #define COUNTRY_STRING_LENGTH (3) #define COUNTRY_INFO_MAX_CHANNEL (84) @@ -975,6 +976,12 @@ void populate_dot11f_tspec(struct mac_tspec_ie *pOld, tDot11fIETSPEC *pDot11f); void populate_dot11f_wmmtspec(struct mac_tspec_ie *pOld, tDot11fIEWMMTSPEC *pDot11f); +#ifdef WLAN_FEATURE_MSCS +void +populate_dot11f_mscs_dec_element(struct mscs_req_info *mscs_req, + tDot11fmscs_request_action_frame *dot11f); +#endif + QDF_STATUS populate_dot11f_tclas(struct mac_context *mac, tSirTclasInfo *pOld, tDot11fIETCLAS *pDot11f); diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 2c895f6a1aaf..6d984025d446 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1742,6 +1742,7 @@ static void lim_process_messages(struct mac_context *mac_ctx, case eWNI_SME_DEAUTH_CNF: case eWNI_SME_ASSOC_CNF: case eWNI_SME_ADDTS_REQ: + case eWNI_SME_MSCS_REQ: case eWNI_SME_DELTS_REQ: case eWNI_SME_SESSION_UPDATE_PARAM: case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 4a9496d3f36b..933aa735d6fa 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3064,6 +3064,63 @@ send_failure_addts_rsp: smesessionId); } +#ifdef WLAN_FEATURE_MSCS +static void +__lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf) +{ + struct qdf_mac_addr peer_mac; + struct mscs_req_info *mscs_req; + struct pe_session *pe_session; + uint8_t pe_session_id; + + if (!msg_buf) { + pe_err("Buffer is Pointing to NULL"); + return; + } + + mscs_req = (struct mscs_req_info *) msg_buf; + pe_session = pe_find_session_by_bssid(mac, mscs_req->bssid.bytes, + &pe_session_id); + if (!pe_session) { + pe_err("Session Does not exist for bssid: " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(mscs_req->bssid.bytes)); + return; + } + + if (!LIM_IS_STA_ROLE(pe_session)) { + pe_err("MSCS req received on AP - ignoring"); + return; + } + + if (QDF_IS_STATUS_ERROR(wlan_vdev_mlme_is_active(pe_session->vdev))) { + pe_err("mscs req in unexpected vdev SM state:%d", + wlan_vdev_mlme_get_state(pe_session->vdev)); + return; + } + + if (mscs_req->is_mscs_req_sent) { + pe_err("MSCS req already sent"); + return; + } + + qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE); + + /* save the mscs request */ + mscs_req->is_mscs_req_sent = true; + + /* ship out the message now */ + lim_send_mscs_req_action_frame(mac, peer_mac, mscs_req, + pe_session); +} +#else +static inline void +__lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf) +{ + return; +} + +#endif + static void __lim_process_sme_delts_req(struct mac_context *mac, uint32_t *msg_buf) { @@ -4651,6 +4708,11 @@ bool lim_process_sme_req_messages(struct mac_context *mac, __lim_process_sme_addts_req(mac, msg_buf); break; + case eWNI_SME_MSCS_REQ: + pe_debug("Received MSCS_REQ message"); + __lim_process_sme_mscs_req(mac, msg_buf); + break; + case eWNI_SME_DELTS_REQ: pe_debug("Received DELTS_REQ message"); __lim_process_sme_delts_req(mac, msg_buf); diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 50b248bc11af..0e6933c75a54 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -56,6 +56,7 @@ #include "lim_process_fils.h" #include "wlan_utility.h" #include +#include /** * @@ -1093,6 +1094,132 @@ lim_send_addts_req_action_frame(struct mac_context *mac, qdf_status); } /* End lim_send_addts_req_action_frame. */ +#ifdef WLAN_FEATURE_MSCS +/** + * lim_mscs_req_tx_complete_cnf()- Confirmation for mscs req sent over the air + * @context: pointer to global mac + * @buf: buffer + * @tx_complete : Sent status + * @params; tx completion params + * + * Return: This returns QDF_STATUS + */ + +static QDF_STATUS lim_mscs_req_tx_complete_cnf(void *context, qdf_nbuf_t buf, + uint32_t tx_complete, + void *params) +{ + uint16_t mscs_ack_status; + uint16_t reason_code; + + pe_debug("mscs req TX: %s (%d)", + (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ? + "success" : "fail", tx_complete); + + if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) { + mscs_ack_status = ACKED; + reason_code = QDF_STATUS_SUCCESS; + } else { + mscs_ack_status = NOT_ACKED; + reason_code = QDF_STATUS_E_FAILURE; + } + if (buf) + qdf_nbuf_free(buf); + + return QDF_STATUS_SUCCESS; +} + +void lim_send_mscs_req_action_frame(struct mac_context *mac, + struct qdf_mac_addr peer_mac, + struct mscs_req_info *mscs_req, + struct pe_session *pe_session) +{ + uint8_t *frame; + tDot11fmscs_request_action_frame mscs_req_frame; + uint32_t payload, bytes; + tpSirMacMgmtHdr peer_mac_hdr; + void *packet; + QDF_STATUS qdf_status; + tpSirMacMgmtHdr mac_hdr; + + qdf_mem_zero(&mscs_req_frame, sizeof(mscs_req_frame)); + + mscs_req_frame.Action.action = MCSC_REQ; + mscs_req_frame.DialogToken.token = mscs_req->dialog_token; + mscs_req_frame.Category.category = ACTION_CATEGORY_RVS; + populate_dot11f_mscs_dec_element(mscs_req, &mscs_req_frame); + bytes = dot11f_get_packed_mscs_request_action_frameSize(mac, + &mscs_req_frame, &payload); + if (DOT11F_FAILED(bytes)) { + pe_err("Failed to calculate the packed size for an MSCS Request (0x%08x)", + bytes); + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fmscs_request_action_frame); + } else if (DOT11F_WARNED(bytes)) { + pe_warn("There were warnings while calculating the packed size for MSCS Request (0x%08x)", + bytes); + } + + bytes = payload + sizeof(struct qdf_mac_addr); + + qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, + (void **)&packet); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + pe_err("Failed to allocate %d bytes for an mscs request", + bytes); + return; + } + /* Paranoia: */ + qdf_mem_zero(frame, bytes); + + lim_populate_mac_header(mac, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer_mac.bytes, pe_session->self_mac_addr); + peer_mac_hdr = (tpSirMacMgmtHdr) frame; + + qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE); + + lim_set_protected_bit(mac, pe_session, peer_mac.bytes, peer_mac_hdr); + + bytes = dot11f_pack_mscs_request_action_frame(mac, &mscs_req_frame, + frame + + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(bytes)) { + pe_err("Failed to pack an mscs Request " "(0x%08x)", bytes); + cds_packet_free((void *)packet); + return; /* allocated! */ + } else if (DOT11F_WARNED(bytes)) { + pe_warn("There were warnings while packing an mscs Request (0x%08x)", + bytes); + } + + mac_hdr = (tpSirMacMgmtHdr) frame; + + pe_debug("mscs req TX: vdev id: %d to "QDF_MAC_ADDR_FMT" seq num[%d], frame subtype:%d ", + mscs_req->vdev_id, peer_mac.bytes, mac->mgmtSeqNum, + mac_hdr->fc.subType); + + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + frame, + (uint16_t)(sizeof(tSirMacMgmtHdr) + payload)); + qdf_status = + wma_tx_frameWithTxComplete(mac, packet, + (uint16_t) (sizeof(tSirMacMgmtHdr) + payload), + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, frame, lim_mscs_req_tx_complete_cnf, + HAL_USE_PEER_STA_REQUESTED_MASK, pe_session->vdev_id, + false, 0, RATEID_DEFAULT); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + mlme_set_is_mscs_req_sent(pe_session->vdev, true); + } else { + pe_err("Could not send an mscs Request (%X)", qdf_status); + } + + /* Pkt will be freed up by the callback */ +} /* End lim_send_mscs_req_action_frame */ +#endif + /** * lim_assoc_rsp_tx_complete() - Confirmation for assoc rsp OTA * @context: pointer to global mac diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 1d04e74ee052..fed50a994eaf 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -642,6 +642,24 @@ void lim_send_delts_req_action_frame(struct mac_context *mac, tSirMacAddr peer, void lim_send_addts_req_action_frame(struct mac_context *mac, tSirMacAddr peerMacAddr, tSirAddtsReqInfo *addts, struct pe_session *); +#ifdef WLAN_FEATURE_MSCS +/** + * lim_send_mscs_req_action_frame() - Send mscs req + * @mac_ctx: Handle for mac context + * @peer_mac: Mac address of requesting peer + * @mscs_req: mscs request buffer + * @pe_session: PE session id. + * + * Builds and sends mscs action frame to the peer. + * + * Return: void + */ +void lim_send_mscs_req_action_frame(struct mac_context *mac, + struct qdf_mac_addr peer_mac, + struct mscs_req_info *mscs_req, + struct pe_session *pe_session); +#endif + /** * lim_send_assoc_rsp_mgmt_frame() - Send assoc response * @mac_ctx: Handle for mac context diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index cc0245ea72f6..be1f31e056b9 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -255,6 +255,8 @@ char *lim_msg_str(uint32_t msgType) return "eWNI_SME_DEAUTH_CNF"; case eWNI_SME_ADDTS_REQ: return "eWNI_SME_ADDTS_REQ"; + case eWNI_SME_MSCS_REQ: + return "eWNI_SME_MSCS_REQ"; case eWNI_SME_ADDTS_RSP: return "eWNI_SME_ADDTS_RSP"; case eWNI_SME_DELTS_REQ: diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index b6e58d0cfe9c..86d83efb38d6 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -238,6 +238,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) CASE_RETURN_STRING(eWNI_SME_DEAUTH_CNF); CASE_RETURN_STRING(eWNI_SME_MIC_FAILURE_IND); CASE_RETURN_STRING(eWNI_SME_ADDTS_REQ); + CASE_RETURN_STRING(eWNI_SME_MSCS_REQ); CASE_RETURN_STRING(eWNI_SME_ADDTS_RSP); CASE_RETURN_STRING(eWNI_SME_DELTS_REQ); CASE_RETURN_STRING(eWNI_SME_DELTS_RSP); diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 1d20ed722aea..55966c92d317 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -5057,6 +5057,28 @@ void populate_dot11f_tspec(struct mac_tspec_ie *pOld, tDot11fIETSPEC *pDot11f) } /* End populate_dot11f_tspec. */ +#ifdef WLAN_FEATURE_MSCS +void +populate_dot11f_mscs_dec_element(struct mscs_req_info *mscs_req, + tDot11fmscs_request_action_frame *dot11f) +{ + dot11f->decriptor_element.request_type = + mscs_req->dec.request_type; + dot11f->decriptor_element.user_priority_control = + mscs_req->dec.user_priority_control; + dot11f->decriptor_element.stream_timeout = + mscs_req->dec.stream_timeout; + dot11f->decriptor_element.tclas_mask.classifier_type = + mscs_req->dec.tclas_mask.classifier_type; + dot11f->decriptor_element.tclas_mask.classifier_mask = + mscs_req->dec.tclas_mask.classifier_mask; + + dot11f->decriptor_element.present = 1; + dot11f->decriptor_element.tclas_mask.present = 1; + +} /* End populate_dot11f_decriptor_element */ +#endif + void populate_dot11f_wmmtspec(struct mac_tspec_ie *pOld, tDot11fIEWMMTSPEC *pDot11f) { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 3f7494e783e6..fd8fcf88e060 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -2749,6 +2749,18 @@ struct mac_context *sme_get_mac_context(void); */ void sme_display_disconnect_stats(mac_handle_t mac_handle, uint8_t session_id); +#ifdef WLAN_FEATURE_MSCS +/** + * sme_send_mscs_action_frame() - Send MSCS action frame + * @vdev_id: sme vdev_id + * + * This function is used to send down the mscs request to PE + * + * Return: None + */ +void sme_send_mscs_action_frame(uint8_t vdev_id); +#endif + /** * sme_process_msg_callback() - process callback message from LIM * @mac: global mac context diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 29ed5f5a85d0..d64fab5351a4 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -81,6 +81,14 @@ /* The Dialog Token field shall be set [...] to a non-zero value */ #define SME_QOS_MIN_DIALOG_TOKEN 1 #define SME_QOS_MAX_DIALOG_TOKEN 0xFF + +#ifdef WLAN_FEATURE_MSCS +#define MSCS_USER_PRIORITY 0x07C0 +#define MSCS_STREAM_TIMEOUT 60 /* in sec */ +#define MSCS_TCLAS_CLASSIFIER_MASK 0x5F +#define MSCS_TCLAS_CLASSIFIER_TYPE 4 +#endif + /* Type declarations */ /* Enumeration of the various states in the QoS state m/c */ enum sme_qos_states { @@ -3813,6 +3821,47 @@ QDF_STATUS sme_qos_process_ft_reassoc_rsp_ev(struct mac_context *mac_ctx, return status; } +#ifdef WLAN_FEATURE_MSCS +void sme_send_mscs_action_frame(uint8_t vdev_id) +{ + struct mscs_req_info *mscs_req; + struct sme_qos_sessioninfo *qos_session; + struct scheduler_msg msg = {0}; + QDF_STATUS qdf_status; + + qos_session = &sme_qos_cb.sessionInfo[vdev_id]; + if (!qos_session) { + sme_debug("qos_session is NULL"); + return; + } + mscs_req = qdf_mem_malloc(sizeof(*mscs_req)); + if (!mscs_req) + return; + + mscs_req->vdev_id = vdev_id; + qdf_mem_copy(&mscs_req->bssid.bytes[0], + &qos_session->assocInfo.bss_desc->bssId[0], + sizeof(struct qdf_mac_addr)); + + mscs_req->dialog_token = sme_qos_assign_dialog_token(); + mscs_req->dec.request_type = SCS_REQ_ADD; + mscs_req->dec.user_priority_control = MSCS_USER_PRIORITY; + mscs_req->dec.stream_timeout = (MSCS_STREAM_TIMEOUT * 1000); + mscs_req->dec.tclas_mask.classifier_type = MSCS_TCLAS_CLASSIFIER_TYPE; + mscs_req->dec.tclas_mask.classifier_mask = MSCS_TCLAS_CLASSIFIER_MASK; + + msg.type = eWNI_SME_MSCS_REQ; + msg.reserved = 0; + msg.bodyptr = mscs_req; + qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE, + QDF_MODULE_ID_PE, &msg); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + sme_err("Fail to send mscs request to PE"); + qdf_mem_free(mscs_req); + } +} +#endif + /** * sme_qos_add_ts_req() - send ADDTS request. * @mac: Pointer to the global MAC parameter structure.