diff --git a/drivers/staging/qcacld-3.0/Android.mk b/drivers/staging/qcacld-3.0/Android.mk index 7f1585f1ace8..e38633439607 100644 --- a/drivers/staging/qcacld-3.0/Android.mk +++ b/drivers/staging/qcacld-3.0/Android.mk @@ -7,6 +7,10 @@ ENABLE_QCACLD := true endif endif +ifeq ($(BOARD_COMMON_DIR),) + BOARD_COMMON_DIR := device/qcom/common +endif + ifeq ($(ENABLE_QCACLD), true) # Android makefile for the WLAN Module LOCAL_PATH := $(call my-dir) @@ -105,7 +109,7 @@ endif # DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) ifeq ($(call is-platform-sdk-version-at-least,16),true) - DLKM_DIR := $(TOP)/device/qcom/common/dlkm + DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm else DLKM_DIR := build/dlkm endif # platform-sdk-version diff --git a/drivers/staging/qcacld-3.0/Kbuild b/drivers/staging/qcacld-3.0/Kbuild index e1764aed4ea0..a735b06e97f5 100644 --- a/drivers/staging/qcacld-3.0/Kbuild +++ b/drivers/staging/qcacld-3.0/Kbuild @@ -1274,7 +1274,8 @@ FWOL_OS_IF_SRC := os_if/fw_offload/src FWOL_INC := -I$(WLAN_ROOT)/$(FWOL_CORE_INC) \ -I$(WLAN_ROOT)/$(FWOL_DISPATCHER_INC) \ -I$(WLAN_ROOT)/$(FWOL_TARGET_IF_INC) \ - -I$(WLAN_ROOT)/$(FWOL_OS_IF_INC) + -I$(WLAN_ROOT)/$(FWOL_OS_IF_INC) \ + -I$(WLAN_COMMON_INC)/umac/thermal/dispatcher/inc ifeq ($(CONFIG_WLAN_FW_OFFLOAD), y) FWOL_OBJS := $(FWOL_CORE_SRC)/wlan_fw_offload_main.o \ @@ -1402,10 +1403,12 @@ $(call add-wlan-objs,action_oui,$(ACTION_OUI_OBJS)) ######## PACKET CAPTURE ######## PKT_CAPTURE_DIR := components/pkt_capture +PKT_CAPTURE_OS_IF_DIR := os_if/pkt_capture PKT_CAPTURE_TARGET_IF_DIR := components/target_if/pkt_capture/ PKT_CAPTURE_INC := -I$(WLAN_ROOT)/$(PKT_CAPTURE_DIR)/core/inc \ -I$(WLAN_ROOT)/$(PKT_CAPTURE_DIR)/dispatcher/inc \ - -I$(WLAN_ROOT)/$(PKT_CAPTURE_TARGET_IF_DIR)/inc + -I$(WLAN_ROOT)/$(PKT_CAPTURE_TARGET_IF_DIR)/inc \ + -I$(WLAN_ROOT)/$(PKT_CAPTURE_OS_IF_DIR)/inc ifeq ($(CONFIG_WLAN_FEATURE_PKT_CAPTURE), y) PKT_CAPTURE_OBJS := $(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_main.o \ @@ -1414,7 +1417,9 @@ PKT_CAPTURE_OBJS := $(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_main.o \ $(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_data_txrx.o \ $(PKT_CAPTURE_DIR)/dispatcher/src/wlan_pkt_capture_ucfg_api.o \ $(PKT_CAPTURE_DIR)/dispatcher/src/wlan_pkt_capture_tgt_api.o \ - $(PKT_CAPTURE_TARGET_IF_DIR)/src/target_if_pkt_capture.o + $(PKT_CAPTURE_DIR)/dispatcher/src/wlan_pkt_capture_api.o \ + $(PKT_CAPTURE_TARGET_IF_DIR)/src/target_if_pkt_capture.o \ + $(PKT_CAPTURE_OS_IF_DIR)/src/os_if_pkt_capture.o endif $(call add-wlan-objs,pkt_capture,$(PKT_CAPTURE_OBJS)) @@ -2605,6 +2610,7 @@ cppflags-y += -DANI_OS_TYPE_ANDROID=6 \ -Werror\ -D__linux__ +cppflags-$(CONFIG_THERMAL_STATS_SUPPORT) += -DTHERMAL_STATS_SUPPORT cppflags-$(CONFIG_PTT_SOCK_SVC_ENABLE) += -DPTT_SOCK_SVC_ENABLE cppflags-$(CONFIG_FEATURE_WLAN_WAPI) += -DFEATURE_WLAN_WAPI cppflags-$(CONFIG_FEATURE_WLAN_WAPI) += -DATH_SUPPORT_WAPI @@ -2650,6 +2656,7 @@ WLAN_TWT_SAP_STA_COUNT ?= 32 ccflags-y += -DWLAN_TWT_SAP_STA_COUNT=$(WLAN_TWT_SAP_STA_COUNT) endif +cppflags-$(CONFIG_ENABLE_LOW_POWER_MODE) += -DCONFIG_ENABLE_LOW_POWER_MODE cppflags-$(CONFIG_WLAN_TWT_SAP_PDEV_COUNT) += -DWLAN_TWT_AP_PDEV_COUNT_NUM_PHY cppflags-$(CONFIG_WLAN_DISABLE_EXPORT_SYMBOL) += -DWLAN_DISABLE_EXPORT_SYMBOL cppflags-$(CONFIG_WIFI_POS_CONVERGED) += -DWIFI_POS_CONVERGED @@ -2695,7 +2702,6 @@ cppflags-$(CONFIG_PLD_PCIE_INIT_FLAG) += -DCONFIG_PLD_PCIE_INIT cppflags-$(CONFIG_WLAN_FEATURE_DP_RX_THREADS) += -DFEATURE_WLAN_DP_RX_THREADS cppflags-$(CONFIG_WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT) += -DWLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT cppflags-$(CONFIG_FEATURE_HAL_DELAYED_REG_WRITE) += -DFEATURE_HAL_DELAYED_REG_WRITE -cppflags-$(CONFIG_FEATURE_HAL_DELAYED_REG_WRITE_V2) += -DFEATURE_HAL_DELAYED_REG_WRITE_V2 cppflags-$(CONFIG_QCA_OL_DP_SRNG_LOCK_LESS_ACCESS) += -DQCA_OL_DP_SRNG_LOCK_LESS_ACCESS cppflags-$(CONFIG_SHADOW_WRITE_DELAY) += -DSHADOW_WRITE_DELAY @@ -3337,6 +3343,7 @@ cppflags-$(CONFIG_RXDMA_ERR_PKT_DROP) += -DRXDMA_ERR_PKT_DROP cppflags-$(CONFIG_MAX_ALLOC_PAGE_SIZE) += -DMAX_ALLOC_PAGE_SIZE cppflags-$(CONFIG_DELIVERY_TO_STACK_STATUS_CHECK) += -DDELIVERY_TO_STACK_STATUS_CHECK cppflags-$(CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS) += -DWLAN_TRACE_HIDE_MAC_ADDRESS +cppflags-$(CONFIG_WLAN_FEATURE_CAL_FAILURE_TRIGGER) += -DWLAN_FEATURE_CAL_FAILURE_TRIGGER cppflags-$(CONFIG_LITHIUM) += -DFIX_TXDMA_LIMITATION cppflags-$(CONFIG_LITHIUM) += -DFEATURE_AST @@ -3729,7 +3736,7 @@ cppflags-$(CONFIG_MORE_TX_DESC) += -DTX_TO_NPEERS_INC_TX_DESCS ccflags-$(CONFIG_HASTINGS_BT_WAR) += -DHASTINGS_BT_WAR -cppflags-$(CONFIG_SLUB_DEBUG_ON) += -DHIF_CONFIG_SLUB_DEBUG_ON +cppflags-y += -DHIF_CONFIG_SLUB_DEBUG_ON cppflags-$(CONFIG_SLUB_DEBUG_ON) += -DHAL_CONFIG_SLUB_DEBUG_ON ccflags-$(CONFIG_FOURTH_CONNECTION) += -DFEATURE_FOURTH_CONNECTION diff --git a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c index 3f15455d58ed..d0db9e64a6fa 100644 --- a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c +++ b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c @@ -2600,8 +2600,7 @@ QDF_STATUS policy_mgr_set_chan_switch_complete_evt( return QDF_STATUS_SUCCESS; } - status = qdf_event_set( - &pm_ctx->channel_switch_complete_evt); + status = qdf_event_set_all(&pm_ctx->channel_switch_complete_evt); if (!QDF_IS_STATUS_SUCCESS(status)) { policy_mgr_err("set event failed"); diff --git a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c index 184e7c5c1537..1dc0810698ab 100644 --- a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c +++ b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -201,15 +202,15 @@ void policy_mgr_decr_session_set_pcl(struct wlan_objmgr_psoc *psoc, /* Send RSO stop before sending set pcl command */ pm_ctx->sme_cbacks.sme_rso_stop_cb( - mac_handle, session_id, + mac_handle, vdev_id, REASON_DRIVER_DISABLED, RSO_SET_PCL); policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE, - session_id); + vdev_id); pm_ctx->sme_cbacks.sme_rso_start_cb( - mac_handle, session_id, + mac_handle, vdev_id, REASON_DRIVER_ENABLED, RSO_SET_PCL); } diff --git a/drivers/staging/qcacld-3.0/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/drivers/staging/qcacld-3.0/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 046abc275522..82c09bcf842f 100644 --- a/drivers/staging/qcacld-3.0/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/drivers/staging/qcacld-3.0/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. 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 @@ -299,8 +300,7 @@ tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc, } end: - if (ev.peer_stats) - get_peer_rssi_cb(&ev, last_req->cookie); + get_peer_rssi_cb(&ev, last_req->cookie); ucfg_mc_cp_stats_free_stats_resources(&ev); diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/core/inc/wlan_fw_offload_main.h b/drivers/staging/qcacld-3.0/components/fw_offload/core/inc/wlan_fw_offload_main.h index 756c0cff1c22..1c40671c85a0 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/core/inc/wlan_fw_offload_main.h +++ b/drivers/staging/qcacld-3.0/components/fw_offload/core/inc/wlan_fw_offload_main.h @@ -51,10 +51,12 @@ /** * enum wlan_fwol_southbound_event - fw offload south bound event type * @WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE: get eLNA bypass response + * @WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE: get Thermal Stats response */ enum wlan_fwol_southbound_event { WLAN_FWOL_EVT_INVALID = 0, WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE, + WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE, WLAN_FWOL_EVT_LAST, WLAN_FWOL_EVT_MAX = WLAN_FWOL_EVT_LAST - 1 }; @@ -116,6 +118,7 @@ struct wlan_fwol_coex_config { * @priority_apps: Priority of the apps mitigation to consider by fw * @priority_wpps: Priority of the wpps mitigation to consider by fw * @thermal_action: thermal action as defined enum thermal_mgmt_action_code + * @therm_stats_offset: thermal temp offset as set in gThermalStatsTempOffset */ struct wlan_fwol_thermal_temp { bool thermal_mitigation_enable; @@ -128,6 +131,9 @@ struct wlan_fwol_thermal_temp { uint8_t priority_apps; uint8_t priority_wpps; enum thermal_mgmt_action_code thermal_action; +#ifdef THERMAL_STATS_SUPPORT + uint8_t therm_stats_offset; +#endif }; /** @@ -275,18 +281,30 @@ struct wlan_fwol_cfg { bool disable_hw_assist; }; +/** + * struct wlan_fwol_capability_info - FW offload capability component + * @fw_thermal_stats_cap: Thermal Stats Fw capability + **/ +struct wlan_fwol_capability_info { +#ifdef THERMAL_STATS_SUPPORT + bool fw_thermal_stats_cap; +#endif +}; + /** * struct wlan_fwol_psoc_obj - FW offload psoc priv object * @cfg: cfg items * @cbs: callback functions * @tx_ops: tx operations for target interface * @rx_ops: rx operations for target interface + * @capability_info: fwol capability info */ struct wlan_fwol_psoc_obj { struct wlan_fwol_cfg cfg; struct wlan_fwol_callbacks cbs; struct wlan_fwol_tx_ops tx_ops; struct wlan_fwol_rx_ops rx_ops; + struct wlan_fwol_capability_info capability_info; }; /** @@ -294,6 +312,7 @@ struct wlan_fwol_psoc_obj { * @psoc: psoc handle * @event_id: event ID * @get_elna_bypass_response: get eLNA bypass response + * @get_thermal_stats_response: get thermal stats response */ struct wlan_fwol_rx_event { struct wlan_objmgr_psoc *psoc; @@ -301,6 +320,9 @@ struct wlan_fwol_rx_event { union { #ifdef WLAN_FEATURE_ELNA struct get_elna_bypass_response get_elna_bypass_response; +#endif +#ifdef THERMAL_STATS_SUPPORT + struct thermal_throttle_info get_thermal_stats_response; #endif }; }; diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/core/src/wlan_fw_offload_main.c b/drivers/staging/qcacld-3.0/components/fw_offload/core/src/wlan_fw_offload_main.c index 88539722502a..bc429b87fe7f 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/core/src/wlan_fw_offload_main.c +++ b/drivers/staging/qcacld-3.0/components/fw_offload/core/src/wlan_fw_offload_main.c @@ -111,6 +111,22 @@ fwol_init_coex_config_in_cfg(struct wlan_objmgr_psoc *psoc, CFG_BLE_SCAN_COEX_POLICY); } +#ifdef THERMAL_STATS_SUPPORT +static void +fwol_init_thermal_stats_in_cfg(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_thermal_temp *thermal_temp) +{ + thermal_temp->therm_stats_offset = + cfg_get(psoc, CFG_THERMAL_STATS_TEMP_OFFSET); +} +#else +static void +fwol_init_thermal_stats_in_cfg(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_thermal_temp *thermal_temp) +{ +} +#endif + static void fwol_init_thermal_temp_in_cfg(struct wlan_objmgr_psoc *psoc, struct wlan_fwol_thermal_temp *thermal_temp) @@ -155,7 +171,7 @@ fwol_init_thermal_temp_in_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_THERMAL_WPPS_PRIOITY); thermal_temp->thermal_action = cfg_get(psoc, CFG_THERMAL_MGMT_ACTION); - + fwol_init_thermal_stats_in_cfg(psoc, thermal_temp); } QDF_STATUS fwol_init_neighbor_report_cfg(struct wlan_objmgr_psoc *psoc, @@ -622,6 +638,59 @@ fwol_process_get_elna_bypass_resp(struct wlan_fwol_rx_event *event) } #endif /* WLAN_FEATURE_ELNA */ +#ifdef THERMAL_STATS_SUPPORT +/** + * fwol_process_get_thermal_stats_resp() - Process get thermal stats response + * @event: response event + * + * Return: QDF_STATUS_SUCCESS on success + */ +static QDF_STATUS +fwol_process_get_thermal_stats_resp(struct wlan_fwol_rx_event *event) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; + struct wlan_fwol_psoc_obj *fwol_obj; + struct wlan_fwol_callbacks *cbs; + struct thermal_throttle_info *resp; + + if (!event) { + fwol_err("Event buffer is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc = event->psoc; + if (!psoc) { + fwol_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + fwol_err("Failed to get FWOL Obj"); + return QDF_STATUS_E_INVAL; + } + + cbs = &fwol_obj->cbs; + if (cbs && cbs->get_thermal_stats_callback) { + resp = &event->get_thermal_stats_response; + cbs->get_thermal_stats_callback(cbs->get_thermal_stats_context, + resp); + } else { + fwol_err("NULL pointer for callback"); + status = QDF_STATUS_E_IO; + } + + return status; +} +#else +static QDF_STATUS +fwol_process_get_thermal_stats_resp(struct wlan_fwol_rx_event *event) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif /* THERMAL_STATS_SUPPORT */ + QDF_STATUS fwol_process_event(struct scheduler_msg *msg) { QDF_STATUS status; @@ -641,6 +710,9 @@ QDF_STATUS fwol_process_event(struct scheduler_msg *msg) case WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE: status = fwol_process_get_elna_bypass_resp(event); break; + case WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE: + status = fwol_process_get_thermal_stats_resp(event); + break; default: status = QDF_STATUS_E_INVAL; break; diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h index e91b21dda32d..afcca4faa1dc 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h +++ b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018,2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018,2020-2021 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 @@ -430,6 +430,31 @@ CFG_VALUE_OR_DEFAULT, \ "Thermal management action") +/* + * gThermalStatsTempOffset - Configure the thermal stats offset + * + * @Min: 0 + * @Max: 10 + * @Default: 5 + * + * This ini will configure Thermal temperature offset value for capturing + * thermal stats in thermal range. + * Thermal STATS start capturing from temperature threshold to temperature + * threshold + offset. + * If the value 0 is given then then thermal STATS capture is disabled + * + * Usage: External + * + * + */ +#define CFG_THERMAL_STATS_TEMP_OFFSET CFG_INI_UINT( \ + "gThermalStatsTempOffset", \ + 0, \ + 10, \ + 5, \ + CFG_VALUE_OR_DEFAULT, \ + "Thermal Stats Temperature Offset") + #define CFG_THERMAL_TEMP_ALL \ CFG(CFG_THERMAL_TEMP_MIN_LEVEL0) \ CFG(CFG_THERMAL_TEMP_MAX_LEVEL0) \ @@ -450,6 +475,7 @@ CFG(CFG_THERMAL_SAMPLING_TIME) \ CFG(CFG_THERMAL_APPS_PRIORITY) \ CFG(CFG_THERMAL_WPPS_PRIOITY) \ - CFG(CFG_THERMAL_MGMT_ACTION) + CFG(CFG_THERMAL_MGMT_ACTION) \ + CFG(CFG_THERMAL_STATS_TEMP_OFFSET) #endif diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h index 10f253a8bb90..cf3c30aec0e0 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h +++ b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 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 @@ -24,6 +24,8 @@ #define _WLAN_FWOL_PUBLIC_STRUCTS_H_ #include "wlan_objmgr_psoc_obj.h" +#include "wlan_thermal_public_struct.h" +#include "wmi_unified.h" #ifdef WLAN_FEATURE_ELNA /** @@ -57,10 +59,28 @@ struct get_elna_bypass_response { }; #endif +/** + * struct thermal_throttle_info - thermal throttle info from Target + * @temperature: current temperature in c Degree + * @level: target thermal level info + * @pdev_id: pdev id + * @therm_throt_levels: Number of thermal throttle levels + * @level_info: Thermal Stats for each level + */ +struct thermal_throttle_info { + uint32_t temperature; + enum thermal_throttle_level level; + uint32_t pdev_id; + uint32_t therm_throt_levels; + struct thermal_throt_level_stats level_info[WMI_THERMAL_STATS_TEMP_THRESH_LEVEL_MAX]; +}; + /** * struct wlan_fwol_callbacks - fw offload callbacks * @get_elna_bypass_callback: callback for get eLNA bypass * @get_elna_bypass_context: context for get eLNA bypass + * @get_thermal_stats_callback: callback for get thermal stats + * @get_thermal_stats_context: context for get thermal stats */ struct wlan_fwol_callbacks { #ifdef WLAN_FEATURE_ELNA @@ -68,6 +88,11 @@ struct wlan_fwol_callbacks { struct get_elna_bypass_response *response); void *get_elna_bypass_context; #endif +#ifdef THERMAL_STATS_SUPPORT + void (*get_thermal_stats_callback)(void *context, + struct thermal_throttle_info *response); + void *get_thermal_stats_context; +#endif }; /** @@ -77,6 +102,7 @@ struct wlan_fwol_callbacks { * @reg_evt_handler: register event handler * @unreg_evt_handler: unregister event handler * @send_dscp_up_map_to_fw: send dscp-to-up map values to FW + * @get_thermal_stats: send get_thermal_stats cmd to FW */ struct wlan_fwol_tx_ops { #ifdef WLAN_FEATURE_ELNA @@ -94,17 +120,27 @@ struct wlan_fwol_tx_ops { struct wlan_objmgr_psoc *psoc, uint32_t *dscp_to_up_map); #endif +#ifdef THERMAL_STATS_SUPPORT + QDF_STATUS (*get_thermal_stats)(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req_type, + uint8_t therm_stats_offset); +#endif }; /** * struct wlan_fwol_rx_ops - structure of rx func pointers * @get_elna_bypass_resp: get eLNA bypass response + * @get_thermal_stats_resp: thermal stats cmd response callback to fwol */ struct wlan_fwol_rx_ops { #ifdef WLAN_FEATURE_ELNA QDF_STATUS (*get_elna_bypass_resp)(struct wlan_objmgr_psoc *psoc, struct get_elna_bypass_response *resp); #endif +#ifdef THERMAL_STATS_SUPPORT + QDF_STATUS (*get_thermal_stats_resp)(struct wlan_objmgr_psoc *psoc, + struct thermal_throttle_info *resp); +#endif }; #endif /* _WLAN_FWOL_PUBLIC_STRUCTS_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h index 44f6148f4e99..e69674368565 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h +++ b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h @@ -608,6 +608,26 @@ QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw( } #endif +/** + * ucfg_fwol_update_fw_cap_info - API to update fwol capability info + * @psoc: pointer to psoc object + * @caps: pointer to wlan_fwol_capability_info struct + * + * Used to update fwol capability info. + * + * Return: void + */ +void ucfg_fwol_update_fw_cap_info(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_capability_info *caps); + +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS ucfg_fwol_send_get_thermal_stats_cmd(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req_type, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context); +#endif /* THERMAL_STATS_SUPPORT */ + /** * ucfg_fwol_configure_global_params - API to configure global params * @psoc: pointer to psoc object diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c index a8f88506b934..984f9ad846bf 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c +++ b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c @@ -166,9 +166,67 @@ static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops) } #endif /* WLAN_FEATURE_ELNA */ +#ifdef THERMAL_STATS_SUPPORT +static QDF_STATUS +tgt_fwol_get_thermal_stats_resp(struct wlan_objmgr_psoc *psoc, + struct thermal_throttle_info *resp) +{ + QDF_STATUS status; + struct scheduler_msg msg = {0}; + struct wlan_fwol_rx_event *event; + + event = qdf_mem_malloc(sizeof(*event)); + if (!event) + return QDF_STATUS_E_NOMEM; + + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FWOL_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + fwol_err("Failed to get psoc ref"); + fwol_release_rx_event(event); + return status; + } + + event->psoc = psoc; + event->event_id = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE; + event->get_thermal_stats_response = *resp; + msg.type = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE; + msg.bodyptr = event; + msg.callback = fwol_process_event; + msg.flush_callback = fwol_flush_callback; + status = scheduler_post_message(QDF_MODULE_ID_FWOL, + QDF_MODULE_ID_FWOL, + QDF_MODULE_ID_TARGET_IF, &msg); + + if (QDF_IS_STATUS_SUCCESS(status)) + return QDF_STATUS_SUCCESS; + + fwol_err("failed to send WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE msg"); + fwol_flush_callback(&msg); + + return status; +} + +static void +tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops) +{ + rx_ops->get_thermal_stats_resp = tgt_fwol_get_thermal_stats_resp; +} +#else +static void +tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops) +{ +} +#endif + +static void tgt_fwol_register_thermal_rx_ops(struct wlan_fwol_rx_ops *rx_ops) +{ + tgt_fwol_register_thermal_stats_resp(rx_ops); +} + QDF_STATUS tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops *rx_ops) { tgt_fwol_register_elna_rx_ops(rx_ops); + tgt_fwol_register_thermal_rx_ops(rx_ops); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c index 4d966aaeaaa5..af4dbf45abe1 100644 --- a/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c @@ -1001,6 +1001,96 @@ QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev, } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ +void ucfg_fwol_update_fw_cap_info(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_capability_info *caps) +{ + struct wlan_fwol_psoc_obj *fwol_obj; + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + fwol_err("Failed to get fwol obj"); + return; + } + + qdf_mem_copy(&fwol_obj->capability_info, caps, + sizeof(fwol_obj->capability_info)); +} + +#ifdef THERMAL_STATS_SUPPORT +static QDF_STATUS +ucfg_fwol_get_cap(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_capability_info *cap_info) +{ + struct wlan_fwol_psoc_obj *fwol_obj; + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + fwol_err("Failed to get fwol obj"); + return QDF_STATUS_E_FAILURE; + } + + if (!cap_info) { + fwol_err("Failed to get fwol obj"); + return QDF_STATUS_E_FAILURE; + } + *cap_info = fwol_obj->capability_info; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS ucfg_fwol_send_get_thermal_stats_cmd(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req_type, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context) +{ + QDF_STATUS status; + struct wlan_fwol_psoc_obj *fwol_obj; + struct wlan_fwol_tx_ops *tx_ops; + struct wlan_fwol_thermal_temp thermal_temp = {0}; + struct wlan_fwol_capability_info cap_info; + struct wlan_fwol_callbacks *cbs; + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + fwol_err("Failed to get FWOL Obj"); + return QDF_STATUS_E_INVAL; + } + + status = ucfg_fwol_get_thermal_temp(psoc, &thermal_temp); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_INVAL; + + status = ucfg_fwol_get_cap(psoc, &cap_info); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_INVAL; + + if (!thermal_temp.therm_stats_offset || + !cap_info.fw_thermal_stats_cap) { + fwol_err("Command Disabled in Ini gThermalStatsTempOffset %d or not enabled in FW %d", + thermal_temp.therm_stats_offset, + cap_info.fw_thermal_stats_cap); + return QDF_STATUS_E_INVAL; + } + + /* Registering Callback for the Request command */ + if (callback && context) { + cbs = &fwol_obj->cbs; + cbs->get_thermal_stats_callback = callback; + cbs->get_thermal_stats_context = context; + } + + tx_ops = &fwol_obj->tx_ops; + if (tx_ops && tx_ops->get_thermal_stats) + status = tx_ops->get_thermal_stats(psoc, req_type, + thermal_temp.therm_stats_offset); + else + status = QDF_STATUS_E_INVAL; + + return status; +} +#endif /* THERMAL_STATS_SUPPORT */ + QDF_STATUS ucfg_fwol_configure_global_params(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev) { diff --git a/drivers/staging/qcacld-3.0/components/mlme/core/inc/wlan_mlme_main.h b/drivers/staging/qcacld-3.0/components/mlme/core/inc/wlan_mlme_main.h index f58eb86aa4c5..a5f29a35dffd 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/core/inc/wlan_mlme_main.h +++ b/drivers/staging/qcacld-3.0/components/mlme/core/inc/wlan_mlme_main.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -216,6 +217,14 @@ struct mscs_req_info { }; #endif +/** + * * struct mlme_connect_info - mlme connect information + * @ext_cap_ie: Ext CAP IE + */ +struct mlme_connect_info { + uint8_t ext_cap_ie[DOT11F_IE_EXTCAP_MAX_LEN + 2]; +}; + /** * struct mlme_legacy_priv - VDEV MLME legacy priv object * @chan_switch_in_progress: flag to indicate that channel switch is in progress @@ -252,6 +261,7 @@ struct mscs_req_info { * @ba_2k_jump_iot_ap: This is set to true if connected to the ba 2k jump IOT AP * @bad_htc_he_iot_ap: Set to true if connected to AP who can't decode htc he * @is_usr_ps_enabled: Is Power save enabled + * @connect_info: mlme connect information */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -291,6 +301,7 @@ struct mlme_legacy_priv { bool ba_2k_jump_iot_ap; bool bad_htc_he_iot_ap; bool is_usr_ps_enabled; + struct mlme_connect_info connect_info; }; diff --git a/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_main.c b/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_main.c index 723c7a54a918..dc40c4940af1 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_main.c +++ b/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -373,6 +374,49 @@ mlme_init_lpass_support_cfg(struct wlan_objmgr_psoc *psoc, } #endif +/** + * mlme_init_mgmt_hw_tx_retry_count_cfg() - initialize mgmt hw tx retry count + * @psoc: Pointer to PSOC + * @gen: pointer to generic CFG items + * + * Return: None + */ +static void mlme_init_mgmt_hw_tx_retry_count_cfg( + struct wlan_objmgr_psoc *psoc, + struct wlan_mlme_generic *gen) +{ + uint32_t i; + qdf_size_t out_size = 0; + uint8_t count_array[MGMT_FRM_HW_TX_RETRY_COUNT_STR_LEN]; + + qdf_uint8_array_parse(cfg_get(psoc, CFG_MGMT_FRAME_HW_TX_RETRY_COUNT), + count_array, + MGMT_FRM_HW_TX_RETRY_COUNT_STR_LEN, + &out_size); + + for (i = 0; i + 1 < out_size; i += 2) { + if (count_array[i] >= CFG_FRAME_TYPE_MAX) { + mlme_legacy_debug("invalid frm type %d", + count_array[i]); + continue; + } + if (count_array[i + 1] >= MAX_MGMT_HW_TX_RETRY_COUNT) { + mlme_legacy_debug("mgmt hw tx retry count %d for frm %d, limit to %d", + count_array[i + 1], + count_array[i], + MAX_MGMT_HW_TX_RETRY_COUNT); + gen->mgmt_hw_tx_retry_count[count_array[i]] = + MAX_MGMT_HW_TX_RETRY_COUNT; + } else { + mlme_legacy_debug("mgmt hw tx retry count %d for frm %d", + count_array[i + 1], + count_array[i]); + gen->mgmt_hw_tx_retry_count[count_array[i]] = + count_array[i + 1]; + } + } +} + static void mlme_init_generic_cfg(struct wlan_objmgr_psoc *psoc, struct wlan_mlme_generic *gen) { @@ -436,6 +480,8 @@ static void mlme_init_generic_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_SAE_CONNECION_RETRIES); gen->monitor_mode_concurrency = cfg_get(psoc, CFG_MONITOR_MODE_CONCURRENCY); + gen->tx_retry_multiplier = cfg_get(psoc, CFG_TX_RETRY_MULTIPLIER); + mlme_init_mgmt_hw_tx_retry_count_cfg(psoc, gen); } static void mlme_init_edca_ani_cfg(struct wlan_objmgr_psoc *psoc, @@ -680,6 +726,8 @@ static void mlme_init_timeout_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_PS_DATA_INACTIVITY_TIMEOUT); timeouts->wmi_wq_watchdog_timeout = cfg_get(psoc, CFG_WMI_WQ_WATCHDOG); + timeouts->sae_auth_failure_timeout = + cfg_get(psoc, CFG_SAE_AUTH_FAILURE_TIMEOUT); } static void mlme_init_ht_cap_in_cfg(struct wlan_objmgr_psoc *psoc, @@ -1180,13 +1228,13 @@ static void mlme_init_he_cap_in_cfg(struct wlan_objmgr_psoc *psoc, he_caps->dot11_he_cap.rx_full_bw_su_he_mu_non_cmpr_sigb = cfg_default(CFG_HE_RX_FULL_BW_MU_NON_CMPR_SIGB); he_caps->dot11_he_cap.rx_he_mcs_map_lt_80 = - cfg_default(CFG_HE_RX_MCS_MAP_LT_80); + cfg_get(psoc, CFG_HE_RX_MCS_MAP_LT_80); he_caps->dot11_he_cap.tx_he_mcs_map_lt_80 = - cfg_default(CFG_HE_TX_MCS_MAP_LT_80); - value = cfg_default(CFG_HE_RX_MCS_MAP_160); + cfg_get(psoc, CFG_HE_TX_MCS_MAP_LT_80); + value = cfg_get(psoc, CFG_HE_RX_MCS_MAP_160); qdf_mem_copy(he_caps->dot11_he_cap.rx_he_mcs_map_160, &value, sizeof(uint16_t)); - value = cfg_default(CFG_HE_TX_MCS_MAP_160); + value = cfg_get(psoc, CFG_HE_TX_MCS_MAP_160); qdf_mem_copy(he_caps->dot11_he_cap.tx_he_mcs_map_160, &value, sizeof(uint16_t)); value = cfg_default(CFG_HE_RX_MCS_MAP_80_80); @@ -1604,6 +1652,7 @@ static void mlme_init_roam_offload_cfg(struct wlan_objmgr_psoc *psoc, lfr->idle_roam_band = cfg_get(psoc, CFG_LFR_IDLE_ROAM_BAND); lfr->sta_roam_disable = cfg_get(psoc, CFG_STA_DISABLE_ROAM); mlme_init_sae_single_pmk_cfg(psoc, lfr); + qdf_mem_zero(&lfr->roam_rt_stats, sizeof(lfr->roam_rt_stats)); } #else @@ -2344,6 +2393,127 @@ mlme_init_dot11_mode_cfg(struct wlan_objmgr_psoc *psoc, dot11_mode->vdev_type_dot11_mode = cfg_get(psoc, CFG_VDEV_DOT11_MODE); } +/** + * mlme_iot_parse_aggr_info - parse aggr related items in ini + * + * @psoc: PSOC pointer + * @iot: IOT related CFG items + * + * Return: None + */ +static void +mlme_iot_parse_aggr_info(struct wlan_objmgr_psoc *psoc, + struct wlan_mlme_iot *iot) +{ + char *aggr_info, *oui, *msdu, *mpdu, *aggr_info_temp; + uint32_t ampdu_sz, amsdu_sz, index = 0, oui_len, cfg_str_len; + struct wlan_iot_aggr *aggr_info_list; + const char *cfg_str; + int ret; + + cfg_str = cfg_get(psoc, CFG_TX_IOT_AGGR); + if (!cfg_str) + return; + + cfg_str_len = qdf_str_len(cfg_str); + if (!cfg_str_len) + return; + + aggr_info = qdf_mem_malloc(cfg_str_len + 1); + if (!aggr_info) + return; + + aggr_info_list = iot->aggr; + qdf_mem_copy(aggr_info, cfg_str, cfg_str_len); + mlme_legacy_debug("aggr_info=[%s]", aggr_info); + + aggr_info_temp = aggr_info; + while (aggr_info_temp) { + /* skip possible spaces before oui string */ + while (*aggr_info_temp == ' ') + aggr_info_temp++; + + oui = strsep(&aggr_info_temp, ","); + if (!oui) { + mlme_legacy_err("oui error"); + goto end; + } + + oui_len = qdf_str_len(oui) / 2; + if (oui_len > sizeof(aggr_info_list[index].oui)) { + mlme_legacy_err("size error"); + goto end; + } + + amsdu_sz = 0; + msdu = strsep(&aggr_info_temp, ","); + if (!msdu) { + mlme_legacy_err("msdu error"); + goto end; + } + + ret = kstrtou32(msdu, 10, &amsdu_sz); + if (ret || amsdu_sz > IOT_AGGR_MSDU_MAX_NUM) { + mlme_legacy_err("invalid msdu no. %s [%u]", + msdu, amsdu_sz); + goto end; + } + + ampdu_sz = 0; + mpdu = strsep(&aggr_info_temp, ","); + if (!mpdu) { + mlme_legacy_err("mpdu error"); + goto end; + } + + ret = kstrtou32(mpdu, 10, &du_sz); + if (ret || ampdu_sz > IOT_AGGR_MPDU_MAX_NUM) { + mlme_legacy_err("invalid mpdu no. %s [%u]", + mpdu, ampdu_sz); + goto end; + } + + mlme_legacy_debug("id %u oui[%s] len %u msdu %u mpdu %u", + index, oui, oui_len, amsdu_sz, ampdu_sz); + + ret = qdf_hex_str_to_binary(aggr_info_list[index].oui, + oui, oui_len); + if (ret) { + mlme_legacy_err("oui error: %d", ret); + goto end; + } + + aggr_info_list[index].amsdu_sz = amsdu_sz; + aggr_info_list[index].ampdu_sz = ampdu_sz; + aggr_info_list[index].oui_len = oui_len; + index++; + if (index >= IOT_AGGR_INFO_MAX_NUM) { + mlme_legacy_err("exceed max num, index = %d", index); + break; + } + } + iot->aggr_num = index; + +end: + mlme_legacy_debug("configured aggr num %d", iot->aggr_num); + qdf_mem_free(aggr_info); +} + +/** + * mlme_iot_parse_aggr_info - parse IOT related items in ini + * + * @psoc: PSOC pointer + * @iot: IOT related CFG items + * + * Return: None + */ +static void +mlme_init_iot_cfg(struct wlan_objmgr_psoc *psoc, + struct wlan_mlme_iot *iot) +{ + mlme_iot_parse_aggr_info(psoc, iot); +} + QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; @@ -2396,6 +2566,7 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) mlme_init_btm_cfg(psoc, &mlme_cfg->btm); mlme_init_roam_score_config(psoc, mlme_cfg); mlme_init_ratemask_cfg(psoc, &mlme_cfg->ratemask_cfg); + mlme_init_iot_cfg(psoc, &mlme_cfg->iot); return status; } diff --git a/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_twt_api.c b/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_twt_api.c index 5a7541c8c257..8d86fd962ec0 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_twt_api.c +++ b/drivers/staging/qcacld-3.0/components/mlme/core/src/wlan_mlme_twt_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 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 above @@ -187,7 +188,7 @@ QDF_STATUS mlme_init_twt_context(struct wlan_objmgr_psoc *psoc, peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { - mlme_legacy_err("Peer object not found"); + mlme_legacy_debug("Peer object not found"); return QDF_STATUS_E_FAILURE; } diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_generic.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_generic.h index c75e4bf3ba93..4e2d58d26744 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_generic.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_generic.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -853,6 +854,65 @@ enum monitor_mode_concurrency { CFG_VALUE_OR_DEFAULT, \ "Monitor mode concurrency supported") +/* + * + * tx_retry_multiplier - TX retry multiplier + * @Min: 0 + * @Max: 500 + * @Default: 0 + * + * This ini is used to indicate percentage to max retry limit to fw + * which can further be used by fw to multiply counter by + * tx_retry_multiplier percent. + * + * Supported Feature: STA/SAP + * + * Usage: External + * + * + */ +#define CFG_TX_RETRY_MULTIPLIER CFG_INI_UINT( \ + "tx_retry_multiplier", \ + 0, \ + 500, \ + 0, \ + CFG_VALUE_OR_DEFAULT, \ + "percentage of max retry limit") + +/* + * + * mgmt_frame_hw_tx_retry_count - Set hw tx retry count for mgmt action + * frame + * @Min: N/A + * @Max: N/A + * @Default: N/A + * + * Set mgmt action frame hw tx retry count, string format looks like below: + * frame_hw_tx_retry_count=",,..." + * frame type is enum value of mlme_cfg_frame_type. + * Retry count max value is 127. + * For example: + * frame_hw_tx_retry_count="0,64,2,32" + * The above input string means: + * For p2p go negotiation request fame, hw retry count 64 + * For p2p provision discovery request, hw retry count 32 + * + * Related: None. + * + * Supported Feature: STA/P2P + * + * Usage: External + * + * + */ +#define MGMT_FRM_HW_TX_RETRY_COUNT_STR_LEN (64) +#define CFG_MGMT_FRAME_HW_TX_RETRY_COUNT CFG_INI_STRING( \ + "mgmt_frame_hw_tx_retry_count", \ + 0, \ + MGMT_FRM_HW_TX_RETRY_COUNT_STR_LEN, \ + "", \ + "Set mgmt action frame hw tx retry count") + #define CFG_GENERIC_ALL \ CFG(CFG_ENABLE_DEBUG_PACKET_LOG) \ CFG(CFG_PMF_SA_QUERY_MAX_RETRIES) \ @@ -887,5 +947,7 @@ enum monitor_mode_concurrency { CFG(CFG_DFS_CHAN_AGEOUT_TIME) \ CFG(CFG_SAE_CONNECION_RETRIES) \ CFG(CFG_WLS_6GHZ_CAPABLE) \ - CFG(CFG_MONITOR_MODE_CONCURRENCY) + CFG(CFG_MONITOR_MODE_CONCURRENCY)\ + CFG(CFG_TX_RETRY_MULTIPLIER) \ + CFG(CFG_MGMT_FRAME_HW_TX_RETRY_COUNT) #endif /* __CFG_MLME_GENERIC_H */ diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_he_caps.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_he_caps.h index 94177c024c13..5182d0de59e1 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_he_caps.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_he_caps.h @@ -492,35 +492,158 @@ 0, \ "He Rx Full Bw Mu Non Cmpr Sigb") -#define CFG_HE_RX_MCS_MAP_LT_80 CFG_UINT( \ +/* 11AX related INI configuration */ +/* + * + * he_rx_mcs_map_lt_80 - configure Rx HE-MCS Map for ≤ 80 MHz + * @Min: 0 + * @Max: 0xFFFF + * @Default: 0xFFFA + * + * This ini is used to configure Rx HE-MCS Map for ≤ 80 MHz + * 0:1 Max HE-MCS For 1 SS + * 2:3 Max HE-MCS For 2 SS + * 4:5 Max HE-MCS For 3 SS + * 6:7 Max HE-MCS For 4 SS + * 8:9 Max HE-MCS For 5 SS + * 10:11 Max HE-MCS For 6 SS + * 12:13 Max HE-MCS For 7 SS + * 14:15 Max HE-MCS For 8 SS + * + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + * + * Related: NA + * + * Supported Feature: 11AX + * + * Usage: External + * + * + */ +#define CFG_HE_RX_MCS_MAP_LT_80 CFG_INI_UINT( \ "he_rx_mcs_map_lt_80", \ 0, \ 0xFFFF, \ - 0xFFF0, \ + 0xFFFA, \ CFG_VALUE_OR_DEFAULT, \ "He Rx Mcs Map Lt 80") -#define CFG_HE_TX_MCS_MAP_LT_80 CFG_UINT( \ +/* 11AX related INI configuration */ +/* + * + * he_tx_mcs_map_lt_80 - configure Tx HE-MCS Map for ≤ 80 MHz + * @Min: 0 + * @Max: 0xFFFF + * @Default: 0xFFFA + * + * This ini is used to configure Tx HE-MCS Map for ≤ 80 MHz + * 0:1 Max HE-MCS For 1 SS + * 2:3 Max HE-MCS For 2 SS + * 4:5 Max HE-MCS For 3 SS + * 6:7 Max HE-MCS For 4 SS + * 8:9 Max HE-MCS For 5 SS + * 10:11 Max HE-MCS For 6 SS + * 12:13 Max HE-MCS For 7 SS + * 14:15 Max HE-MCS For 8 SS + * + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + * + * Related: NA + * + * Supported Feature: 11AX + * + * Usage: External + * + * + */ +#define CFG_HE_TX_MCS_MAP_LT_80 CFG_INI_UINT( \ "he_tx_mcs_map_lt_80", \ 0, \ 0xFFFF, \ - 0xFFF0, \ + 0xFFFA, \ CFG_VALUE_OR_DEFAULT, \ "He Tx Mcs Map Lt 80") - -#define CFG_HE_RX_MCS_MAP_160 CFG_UINT( \ +/* 11AX related INI configuration */ +/* + * + * he_rx_mcs_map_160 - configure Rx HE-MCS Map for 160 MHz + * @Min: 0 + * @Max: 0xFFFF + * @Default: 0xFFFA + * + * This ini is used to configure Rx HE-MCS Map for 160 MHz + * 0:1 Max HE-MCS For 1 SS + * 2:3 Max HE-MCS For 2 SS + * 4:5 Max HE-MCS For 3 SS + * 6:7 Max HE-MCS For 4 SS + * 8:9 Max HE-MCS For 5 SS + * 10:11 Max HE-MCS For 6 SS + * 12:13 Max HE-MCS For 7 SS + * 14:15 Max HE-MCS For 8 SS + * + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + * + * Related: NA + * + * Supported Feature: 11AX + * + * Usage: External + * + * + */ +#define CFG_HE_RX_MCS_MAP_160 CFG_INI_UINT( \ "he_rx_mcs_map_160", \ 0, \ 0xFFFF, \ - 0xFFF0, \ + 0xFFFA, \ CFG_VALUE_OR_DEFAULT, \ "He Rx Mcs Map 160") -#define CFG_HE_TX_MCS_MAP_160 CFG_UINT( \ +/* 11AX related INI configuration */ +/* + * + * he_tx_mcs_map_160 - configure Tx HE-MCS Map for 160 MHz + * @Min: 0 + * @Max: 0xFFFF + * @Default: 0xFFFA + * + * This ini is used to configure Tx HE-MCS Map for 160 MHz + * 0:1 Max HE-MCS For 1 SS + * 2:3 Max HE-MCS For 2 SS + * 4:5 Max HE-MCS For 3 SS + * 6:7 Max HE-MCS For 4 SS + * 8:9 Max HE-MCS For 5 SS + * 10:11 Max HE-MCS For 6 SS + * 12:13 Max HE-MCS For 7 SS + * 14:15 Max HE-MCS For 8 SS + * + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + * + * Related: NA + * + * Supported Feature: 11AX + * + * Usage: External + * + * + */ +#define CFG_HE_TX_MCS_MAP_160 CFG_INI_UINT( \ "he_tx_mcs_map_160", \ 0, \ 0xFFFF, \ - 0xFFF0, \ + 0xFFFA, \ CFG_VALUE_OR_DEFAULT, \ "He Tx Mcs Map 160") diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_obss_ht40.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_obss_ht40.h index 56586d06f496..4f1bff0d014f 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_obss_ht40.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_obss_ht40.h @@ -248,7 +248,7 @@ * bss_color_collision_det_sta - Enables BSS color collision detection in STA * @Min: 0 * @Max: 1 - * @Default: 0 + * @Default: 1 * * This ini used to enable or disable the BSS color collision detection in * STA mode if obss_color_collision_offload is enabled. @@ -261,7 +261,7 @@ */ #define CFG_BSS_CLR_COLLISION_DETCN_STA CFG_INI_BOOL( \ "bss_color_collision_det_sta", \ - 0, \ + 1, \ "BSS color collision detection in STA") #define CFG_OBSS_HT40_ALL \ diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_timeout.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_timeout.h index cab06f33f3bc..91d39a391873 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_timeout.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_timeout.h @@ -312,6 +312,27 @@ CFG_VALUE_OR_DEFAULT, \ "timeout period for wmi watchdog bite") +/* + * + * sae_auth_failure_timeout - SAE Auth failure timeout value in msec + * @Min: 500 + * @Max: 1000 + * @Default: 1000 + * + * This cfg is used to configure the SAE auth failure timeout. + * + * Usage: External + * + * + */ +#define CFG_SAE_AUTH_FAILURE_TIMEOUT CFG_INI_UINT( \ + "sae_auth_failure_timeout", \ + 500, \ + 1000, \ + 1000, \ + CFG_VALUE_OR_DEFAULT, \ + "SAE auth failure timeout") + #define CFG_TIMEOUT_ALL \ CFG(CFG_JOIN_FAILURE_TIMEOUT) \ CFG(CFG_AUTH_FAILURE_TIMEOUT) \ @@ -325,6 +346,7 @@ CFG(CFG_AP_KEEP_ALIVE_TIMEOUT) \ CFG(CFG_AP_LINK_MONITOR_TIMEOUT) \ CFG(CFG_WMI_WQ_WATCHDOG) \ - CFG(CFG_PS_DATA_INACTIVITY_TIMEOUT) + CFG(CFG_PS_DATA_INACTIVITY_TIMEOUT)\ + CFG(CFG_SAE_AUTH_FAILURE_TIMEOUT) #endif /* __CFG_MLME_TIMEOUT_H */ diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_vht_caps.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_vht_caps.h index 62708e9db023..afca32da945b 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_vht_caps.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_mlme_vht_caps.h @@ -113,16 +113,16 @@ #define CFG_VHT_RX_SUPP_DATA_RATE CFG_UINT( \ "rx_supp_data_rate", \ 0, \ - 866, \ - 866, \ + 780, \ + 780, \ CFG_VALUE_OR_DEFAULT, \ "VHT RX SUPP DATA RATE") #define CFG_VHT_TX_SUPP_DATA_RATE CFG_UINT( \ "tx_supp_data_rate", \ 0, \ - 866, \ - 866, \ + 780, \ + 780, \ CFG_VALUE_OR_DEFAULT, \ "VHT TX SUPP DATA RATE") diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_qos.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_qos.h index 818dbcc7da99..a037b609b1c5 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_qos.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/cfg_qos.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -171,7 +172,7 @@ * in no of MPDUs * @Min: 1 * @Max: 256 - * @Default: 64 + * @Default: 256 * * gRxAggregationSize gives an option to configure Rx aggregation size * in no of MPDUs. This can be useful in debugging throughput issues @@ -188,7 +189,7 @@ "gRxAggregationSize", \ 1, \ 256, \ - 64, \ + 256, \ CFG_VALUE_OR_DEFAULT, \ "Rx Aggregation size value") @@ -498,6 +499,51 @@ 1, \ "Enable UAPSD for SAP") +#define IOT_AGGR_INFO_MAX_LEN 500 +#define IOT_AGGR_INFO_MAX_NUM 32 +#define IOT_AGGR_MSDU_MAX_NUM 6 +#define IOT_AGGR_MPDU_MAX_NUM 512 +/* + * + * cfg_tx_iot_aggr - OUI based tx aggr size for msdu/mpdu + * + * This ini gives an option to configure Tx aggregation size + * in no. of MPDUs/MSDUs for specified OUI. + * This can be useful for IOT issues. + * + * Format of the configuration: + * cfg_tx_iot_aggr=,,,,,... + * MSDU: 0..IOT_AGGR_MSDU_MAX_NUM, the max tx aggregation size in no. of MSDUs, + * 0 means not specified. + * MPDU: 0..IOT_AGGR_MPDU_MAX_NUM, the max tx aggregation size in no. of MPDUs, + * 0 means not specified. + * Note: MSDU-x/MPDU-x are the max values, FW will take decision for actual + * AMSDU/AMPDU size on different platforms. + * + * For example: + * cfg_tx_iot_aggr=112233,2,0,445566,3,32,778899,0,64 + * If vendor OUI-1("\x11\x22\x33") is found in assoc resp, + * set tx amsdu size to 2; + * If vendor OUI-2("\x44\x55\x66") is found in assoc resp, + * set tx amsdu size to 3, set tx ampdu size to 32; + * If vendor OUI-3("\x77\x88\x99") is found in assoc resp, + * set tx ampdu size to 64. + * + * Related: IOT + * + * Supported Feature: IOT + * + * Usage: External + * + * + */ +#define CFG_TX_IOT_AGGR CFG_INI_STRING( \ + "cfg_tx_iot_aggr", \ + 0, \ + IOT_AGGR_INFO_MAX_LEN, \ + "", \ + "Used to configure OUI based tx aggr size for msdu/mpdu") + #define CFG_QOS_ALL \ CFG(CFG_SAP_MAX_INACTIVITY_OVERRIDE) \ CFG(CFG_TX_AGGREGATION_SIZE) \ @@ -516,6 +562,7 @@ CFG(CFG_TX_NON_AGGR_SW_RETRY_VI) \ CFG(CFG_TX_NON_AGGR_SW_RETRY_VO) \ CFG(CFG_TX_NON_AGGR_SW_RETRY) \ - CFG(CFG_SAP_QOS_UAPSD) + CFG(CFG_SAP_QOS_UAPSD) \ + CFG(CFG_TX_IOT_AGGR) #endif /* __CFG_MLME_QOS_H */ diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h index bfe1a8073b20..12e7571b21a9 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. 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 @@ -3194,4 +3195,42 @@ QDF_STATUS mlme_set_user_ps(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, * Return: True if user_ps flag is set */ bool mlme_get_user_ps(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + +/** + * wlan_mlme_get_mgmt_hw_tx_retry_count() - Get mgmt frame hw tx retry count + * + * @psoc: pointer to psoc object + * @frm_type: frame type of the query + * + * Return: hw tx retry count + */ +uint8_t +wlan_mlme_get_mgmt_hw_tx_retry_count(struct wlan_objmgr_psoc *psoc, + enum mlme_cfg_frame_type frm_type); + +/** + * wlan_mlme_get_tx_retry_multiplier() - Get the tx retry multiplier percentage + * + * @psoc: pointer to psoc object + * @tx_retry_multiplier: pointer to hold user config value of + * tx_retry_multiplier + * + * Return: QDF Status + */ +QDF_STATUS +wlan_mlme_get_tx_retry_multiplier(struct wlan_objmgr_psoc *psoc, + uint32_t *tx_retry_multiplier); + +/** + * wlan_mlme_get_channel_bonding_5ghz - Get the channel bonding + * val for 5ghz freq + * @psoc: pointer to psoc object + * @value: pointer to the value which will be filled for the caller + * + * Return: QDF Status + */ +QDF_STATUS +wlan_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc, + uint32_t *value); + #endif /* _WLAN_MLME_API_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 71cb7266aa7d..3b5d1a59dbf6 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -261,6 +262,7 @@ enum roam_invoke_source_entity { struct mlme_roam_after_data_stall { bool roam_invoke_in_progress; enum roam_invoke_source_entity source; + struct qdf_mac_addr mac_addr; }; /** @@ -1185,6 +1187,21 @@ struct wlan_mlme_ratemask { uint32_t higher32_2; }; +/** + * enum mlme_cfg_frame_type - frame type to configure mgmt hw tx retry count + * @CFG_GO_NEGOTIATION_REQ_FRAME_TYPE: p2p go negotiation request fame + * @CFG_P2P_INVITATION_REQ_FRAME_TYPE: p2p invitation request frame + * @CFG_PROVISION_DISCOVERY_REQ_FRAME_TYPE: p2p provision discovery request + */ +enum mlme_cfg_frame_type { + CFG_GO_NEGOTIATION_REQ_FRAME_TYPE = 0, + CFG_P2P_INVITATION_REQ_FRAME_TYPE = 1, + CFG_PROVISION_DISCOVERY_REQ_FRAME_TYPE = 2, + CFG_FRAME_TYPE_MAX, +}; + +#define MAX_MGMT_HW_TX_RETRY_COUNT 127 + /* struct wlan_mlme_generic - Generic CFG config items * * @band_capability: HW Band Capability - Both or 2.4G only or 5G only @@ -1232,6 +1249,8 @@ struct wlan_mlme_ratemask { * @enabled_rf_test_mode: Enable/disable the RF test mode config * @monitor_mode_concurrency: Monitor mode concurrency supported * @ocv_support: FW supports OCV or not + * @tx_retry_multiplier: TX xretry extension parameter + * @mgmt_hw_tx_retry_count: MGMT HW tx retry count for frames */ struct wlan_mlme_generic { uint32_t band_capability; @@ -1276,6 +1295,8 @@ struct wlan_mlme_generic { bool enabled_rf_test_mode; enum monitor_mode_concurrency monitor_mode_concurrency; bool ocv_support; + uint32_t tx_retry_multiplier; + uint8_t mgmt_hw_tx_retry_count[CFG_FRAME_TYPE_MAX]; }; /* @@ -1586,6 +1607,7 @@ struct fw_scan_channels { * @mawc_roam_enabled: Enable/Disable MAWC during roaming * @enable_fast_roam_in_concurrency:Enable LFR roaming on STA during concurrency * @vendor_btm_param: Vendor WTC roam trigger parameters + * @roam_rt_stats: Roam event stats vendor command parameters * @lfr3_roaming_offload: Enable/disable roam offload feature * @lfr3_dual_sta_roaming_enabled: Enable/Disable dual sta roaming offload * feature @@ -1704,6 +1726,7 @@ struct wlan_mlme_lfr_cfg { bool enable_fast_roam_in_concurrency; #ifdef WLAN_FEATURE_ROAM_OFFLOAD struct wlan_cm_roam_vendor_btm_params vendor_btm_param; + struct wlan_cm_roam_rt_stats roam_rt_stats; bool lfr3_roaming_offload; bool lfr3_dual_sta_roaming_enabled; bool enable_self_bss_roam; @@ -2131,6 +2154,7 @@ struct wlan_mlme_power { * @ap_link_monitor_timeout: AP link monitor timeout value * @ps_data_inactivity_timeout: PS data inactivity timeout * @wmi_wq_watchdog_timeout: timeout period for wmi watchdog bite + * @sae_auth_failure_timeout: SAE authentication failure timeout */ struct wlan_mlme_timeout { uint32_t join_failure_timeout; @@ -2146,6 +2170,7 @@ struct wlan_mlme_timeout { uint32_t ap_link_monitor_timeout; uint32_t ps_data_inactivity_timeout; uint32_t wmi_wq_watchdog_timeout; + uint32_t sae_auth_failure_timeout; }; /** @@ -2354,6 +2379,34 @@ struct wlan_mlme_reg { bool enable_nan_on_indoor_channels; }; +#define IOT_AGGR_INFO_MAX_NUM 32 + +/** + * struct wlan_iot_aggr - IOT related AGGR rule + * + * @oui: OUI for the rule + * @oui_len: length of the OUI + * @ampdu_sz: max aggregation size in no. of MPDUs + * @amsdu_sz: max aggregation size in no. of MSDUs + */ +struct wlan_iot_aggr { + uint8_t oui[OUI_LENGTH]; + uint32_t oui_len; + uint32_t ampdu_sz; + uint32_t amsdu_sz; +}; + +/** + * struct wlan_mlme_iot - IOT related CFG Items + * + * @aggr: aggr rules + * @aggr_num: number of the configured aggr rules + */ +struct wlan_mlme_iot { + struct wlan_iot_aggr aggr[IOT_AGGR_INFO_MAX_NUM]; + uint32_t aggr_num; +}; + /** * struct wlan_mlme_cfg - MLME config items * @chainmask_cfg: VHT chainmask related cfg items @@ -2397,6 +2450,7 @@ struct wlan_mlme_reg { * @trig_score_delta: Roam score delta value for various roam triggers * @trig_min_rssi: Expected minimum RSSI value of candidate AP for * various roam triggers + * @iot: IOT related CFG items */ struct wlan_mlme_cfg { struct wlan_mlme_chainmask chainmask_cfg; @@ -2441,6 +2495,7 @@ struct wlan_mlme_cfg { struct roam_trigger_score_delta trig_score_delta[NUM_OF_ROAM_TRIGGERS]; struct roam_trigger_min_rssi trig_min_rssi[NUM_OF_ROAM_MIN_RSSI]; struct wlan_mlme_ratemask ratemask_cfg; + struct wlan_mlme_iot iot; }; enum pkt_origin { @@ -2482,6 +2537,7 @@ struct wlan_mlme_sae_single_pmk { * @btm_rsp: BTM response information * @roam_init_info: Roam initial info * @roam_msg_info: roam related message information + * @roam_event_param: Roam event notif params */ struct mlme_roam_debug_info { struct wmi_roam_trigger_info trigger; @@ -2491,6 +2547,7 @@ struct mlme_roam_debug_info { struct roam_btm_response_data btm_rsp; struct roam_initial_data roam_init_info; struct roam_msg_info roam_msg_info; + struct roam_event_rt_info roam_event_param; }; /** diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h index 7cca4c7b0d7e..73e3458bf43a 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 above @@ -382,6 +383,18 @@ uint8_t ucfg_mlme_get_twt_peer_capabilities(struct wlan_objmgr_psoc *psoc, return mlme_get_twt_peer_capabilities(psoc, peer_mac); } +/** + * ucfg_mlme_get_twt_peer_responder_capabilities() - Get peer responder + * capabilities + * @psoc: Pointer to global psoc object + * @peer_mac: Pointer to peer mac address + * + * Return: Return True if peer responder capabilities support else False + */ +bool ucfg_mlme_get_twt_peer_responder_capabilities( + struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_mac); + /** * ucfg_mlme_init_twt_context() - Initialize TWT context * @psoc: Pointer to global psoc object @@ -678,6 +691,14 @@ uint8_t ucfg_mlme_get_twt_peer_capabilities(struct wlan_objmgr_psoc *psoc, return 0; } +static inline +bool ucfg_mlme_get_twt_peer_responder_capabilities( + struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_mac) +{ + return false; +} + static inline QDF_STATUS ucfg_mlme_init_twt_context(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c index fd112f49cf51..d488f37ccd65 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -555,6 +556,32 @@ QDF_STATUS wlan_mlme_cfg_get_enable_ul_ofdm(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +/* mlme_get_min_rate_cap() - get minimum capability for HE-MCS between + * ini value and fw capability. + * + * Rx HE-MCS Map and Tx HE-MCS Map subfields format where 2-bit indicates + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + * + */ +static uint16_t mlme_get_min_rate_cap(uint16_t val1, uint16_t val2) +{ + uint16_t ret = 0, i; + + for (i = 0; i < 8; i++) { + if (((val1 >> (2 * i)) & 0x3) == 0x3 || + ((val2 >> (2 * i)) & 0x3) == 0x3) { + ret |= 0x3 << (2 * i); + continue; + } + ret |= QDF_MIN((val1 >> (2 * i)) & 0x3, + (val2 >> (2 * i)) & 0x3) << (2 * i); + } + return ret; +} + QDF_STATUS mlme_update_tgt_he_caps_in_cfg(struct wlan_objmgr_psoc *psoc, struct wma_tgt_cfg *wma_cfg) { @@ -802,8 +829,12 @@ QDF_STATUS mlme_update_tgt_he_caps_in_cfg(struct wlan_objmgr_psoc *psoc, mlme_obj->cfg.he_caps.dot11_he_cap.rx_full_bw_su_he_mu_non_cmpr_sigb = he_cap->rx_full_bw_su_he_mu_non_cmpr_sigb; - tx_mcs_map = he_cap->tx_he_mcs_map_lt_80; - rx_mcs_map = he_cap->rx_he_mcs_map_lt_80; + tx_mcs_map = mlme_get_min_rate_cap( + mlme_obj->cfg.he_caps.dot11_he_cap.tx_he_mcs_map_lt_80, + he_cap->tx_he_mcs_map_lt_80); + rx_mcs_map = mlme_get_min_rate_cap( + mlme_obj->cfg.he_caps.dot11_he_cap.rx_he_mcs_map_lt_80, + he_cap->rx_he_mcs_map_lt_80); if (!mlme_obj->cfg.vht_caps.vht_cap_info.enable2x2) { nss = 2; tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, HE_MCS_DISABLE, nss); @@ -816,8 +847,12 @@ QDF_STATUS mlme_update_tgt_he_caps_in_cfg(struct wlan_objmgr_psoc *psoc, if (cfg_in_range(CFG_HE_TX_MCS_MAP_LT_80, tx_mcs_map)) mlme_obj->cfg.he_caps.dot11_he_cap.tx_he_mcs_map_lt_80 = tx_mcs_map; - tx_mcs_map = *((uint16_t *)he_cap->tx_he_mcs_map_160); - rx_mcs_map = *((uint16_t *)he_cap->rx_he_mcs_map_160); + tx_mcs_map = mlme_get_min_rate_cap( + *((uint16_t *)mlme_obj->cfg.he_caps.dot11_he_cap.tx_he_mcs_map_160), + *((uint16_t *)he_cap->tx_he_mcs_map_160)); + rx_mcs_map = mlme_get_min_rate_cap( + *((uint16_t *)mlme_obj->cfg.he_caps.dot11_he_cap.rx_he_mcs_map_160), + *((uint16_t *)he_cap->rx_he_mcs_map_160)); if (!mlme_obj->cfg.vht_caps.vht_cap_info.enable2x2) { nss = 2; @@ -4920,3 +4955,54 @@ bool mlme_get_user_ps(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) return usr_ps_enable; } + +uint8_t +wlan_mlme_get_mgmt_hw_tx_retry_count(struct wlan_objmgr_psoc *psoc, + enum mlme_cfg_frame_type frm_type) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) + return 0; + + if (frm_type >= CFG_FRAME_TYPE_MAX) + return 0; + + return mlme_obj->cfg.gen.mgmt_hw_tx_retry_count[frm_type]; +} + +QDF_STATUS +wlan_mlme_get_tx_retry_multiplier(struct wlan_objmgr_psoc *psoc, + uint32_t *tx_retry_multiplier) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) { + *tx_retry_multiplier = + cfg_default(CFG_TX_RETRY_MULTIPLIER); + return QDF_STATUS_E_FAILURE; + } + + *tx_retry_multiplier = mlme_obj->cfg.gen.tx_retry_multiplier; + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc, + uint32_t *value) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + *value = cfg_default(CFG_CHANNEL_BONDING_MODE_5GHZ); + return QDF_STATUS_E_INVAL; + } + + *value = mlme_obj->cfg.feature_flags.channel_bonding_mode_5ghz; + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c index 26b31cc37855..6a8d28511270 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 above @@ -259,6 +260,20 @@ ucfg_mlme_set_twt_nudge_tgt_cap(struct wlan_objmgr_psoc *psoc, bool val) return QDF_STATUS_SUCCESS; } +bool ucfg_mlme_get_twt_peer_responder_capabilities( + struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_mac) +{ + uint8_t peer_cap; + + peer_cap = mlme_get_twt_peer_capabilities(psoc, peer_mac); + + if (peer_cap & WLAN_TWT_CAPA_RESPONDER) + return true; + + return false; +} + QDF_STATUS ucfg_mlme_get_twt_nudge_tgt_cap(struct wlan_objmgr_psoc *psoc, bool *val) { diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c index 269bf8c110ef..ce2808c49b6c 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c @@ -1642,16 +1642,7 @@ QDF_STATUS ucfg_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc, uint32_t *value) { - struct wlan_mlme_psoc_ext_obj *mlme_obj; - - mlme_obj = mlme_get_psoc_ext_obj(psoc); - if (!mlme_obj) { - *value = cfg_default(CFG_CHANNEL_BONDING_MODE_5GHZ); - return QDF_STATUS_E_INVAL; - } - *value = mlme_obj->cfg.feature_flags.channel_bonding_mode_5ghz; - - return QDF_STATUS_SUCCESS; + return wlan_mlme_get_channel_bonding_5ghz(psoc, value); } QDF_STATUS diff --git a/drivers/staging/qcacld-3.0/components/nan/core/src/nan_api.c b/drivers/staging/qcacld-3.0/components/nan/core/src/nan_api.c index 993c0ec159b5..436716f43eb9 100644 --- a/drivers/staging/qcacld-3.0/components/nan/core/src/nan_api.c +++ b/drivers/staging/qcacld-3.0/components/nan/core/src/nan_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -410,10 +411,36 @@ QDF_STATUS nan_psoc_disable(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_SUCCESS; } +static bool +wlan_is_nan_allowed_on_6ghz_freq(struct wlan_objmgr_pdev *pdev, uint32_t freq) +{ + QDF_STATUS status; + struct regulatory_channel chan_list[NUM_6GHZ_CHANNELS]; + uint16_t i; + + status = wlan_reg_get_6g_ap_master_chan_list(pdev, + REG_VERY_LOW_POWER_AP, + chan_list); + + for (i = 0; i < NUM_6GHZ_CHANNELS; i++) { + if ((freq == chan_list[i].center_freq) && + (chan_list[i].state == CHANNEL_STATE_ENABLE)) + return true; + } + + return false; +} + bool wlan_is_nan_allowed_on_freq(struct wlan_objmgr_pdev *pdev, uint32_t freq) { bool nan_allowed = true; + /* Check for 6GHz channels */ + if (wlan_reg_is_6ghz_chan_freq(freq)) { + nan_allowed = wlan_is_nan_allowed_on_6ghz_freq(pdev, freq); + return nan_allowed; + } + /* Check for SRD channels */ if (wlan_reg_is_etsi13_srd_chan_for_freq(pdev, freq)) wlan_mlme_get_srd_master_mode_for_vdev(wlan_pdev_get_psoc(pdev), diff --git a/drivers/staging/qcacld-3.0/components/nan/core/src/nan_main_i.h b/drivers/staging/qcacld-3.0/components/nan/core/src/nan_main_i.h index 4e0b76fc8bc4..e5ca11c43f51 100644 --- a/drivers/staging/qcacld-3.0/components/nan/core/src/nan_main_i.h +++ b/drivers/staging/qcacld-3.0/components/nan/core/src/nan_main_i.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -29,6 +30,7 @@ #include "qdf_status.h" #include "nan_public_structs.h" #include "wlan_objmgr_cmn.h" +#include "cfg_nan.h" struct wlan_objmgr_vdev; struct wlan_objmgr_psoc; @@ -150,6 +152,7 @@ struct nan_psoc_priv_obj { * @disable_context: Disable all NDP's operation context * @ndp_init_done: Flag to indicate NDP initialization complete after first peer * connection. + * @peer_mc_addr_list: Peer multicast address list */ struct nan_vdev_priv_obj { qdf_spinlock_t lock; @@ -162,6 +165,7 @@ struct nan_vdev_priv_obj { struct qdf_mac_addr primary_peer_mac; void *disable_context; bool ndp_init_done; + struct qdf_mac_addr peer_mc_addr_list[MAX_NDP_SESSIONS]; }; /** diff --git a/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/cfg_nan.h b/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/cfg_nan.h index 2ac7241be3dc..5f1bdf1292b0 100644 --- a/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/cfg_nan.h +++ b/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/cfg_nan.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -168,6 +169,9 @@ CFG_VALUE_OR_DEFAULT, \ "Keep alive timeout of a peer") +/* MAX NDP sessions supported */ +#define MAX_NDP_SESSIONS 8 + /* * * ndp_max_sessions - To configure max ndp sessions @@ -189,7 +193,7 @@ #define CFG_NDP_MAX_SESSIONS CFG_INI_UINT( \ "ndp_max_sessions", \ 1, \ - 8, \ + MAX_NDP_SESSIONS, \ 8, \ CFG_VALUE_OR_DEFAULT, \ "max ndp sessions host supports") diff --git a/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/nan_ucfg_api.h b/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/nan_ucfg_api.h index b7e872dcec01..c1949f4f4ce7 100644 --- a/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/nan_ucfg_api.h +++ b/drivers/staging/qcacld-3.0/components/nan/dispatcher/inc/nan_ucfg_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -92,6 +93,39 @@ QDF_STATUS ucfg_nan_set_active_peers(struct wlan_objmgr_vdev *vdev, */ uint32_t ucfg_nan_get_active_peers(struct wlan_objmgr_vdev *vdev); +/** + * ucfg_nan_set_peer_mc_list: API to derive peer multicast address and add it + * to the list + * @vdev: pointer to vdev object + * @peer_mac_addr: Peer MAC address + * + * Return: None + */ +void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr peer_mac_addr); + +/** + * ucfg_nan_get_peer_mc_list: API to get peer multicast address list + * @vdev: pointer to vdev object + * @peer_mc_addr_list: Out pointer to the peer multicast address list + * + * Return: None + */ +void ucfg_nan_get_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list); + +/** + * ucfg_nan_clear_peer_mc_list: Clear peer multicast address list + * @psoc: pointer to psoc object + * @vdev: pointer to vdev object + * @peer_mac_addr: Pointer to peer MAC address + * + * Return: None + */ +void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *peer_mac_addr); + /** * ucfg_nan_set_ndp_create_transaction_id: set ndp create transaction id * @vdev: pointer to vdev object @@ -624,5 +658,11 @@ static inline bool ucfg_get_disable_6g_nan(struct wlan_objmgr_psoc *psoc) { return true; } + +static inline void +ucfg_nan_get_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list) +{ +} #endif /* WLAN_FEATURE_NAN */ #endif /* _NAN_UCFG_API_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/nan/dispatcher/src/nan_ucfg_api.c b/drivers/staging/qcacld-3.0/components/nan/dispatcher/src/nan_ucfg_api.c index 5c7c314336fe..7b23364a52a8 100644 --- a/drivers/staging/qcacld-3.0/components/nan/dispatcher/src/nan_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/nan/dispatcher/src/nan_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -33,6 +34,7 @@ #include "cfg_ucfg_api.h" #include "cfg_nan.h" #include "wlan_mlme_api.h" +#include "cfg_nan_api.h" struct wlan_objmgr_psoc; struct wlan_objmgr_vdev; @@ -183,6 +185,92 @@ inline QDF_STATUS ucfg_nan_set_active_peers(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr peer_mac_addr) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + uint32_t max_ndp_sessions = 0; + struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev); + int i, list_idx = 0; + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + if (!psoc) { + nan_err("psoc is null"); + return; + } + + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + + qdf_spin_lock_bh(&priv_obj->lock); + for (i = 0; i < max_ndp_sessions; i++) { + if (qdf_is_macaddr_zero(&priv_obj->peer_mc_addr_list[i])) { + list_idx = i; + break; + } + } + if (list_idx == max_ndp_sessions) { + nan_err("Peer multicast address list is full"); + goto end; + } + /* Derive peer multicast addr */ + peer_mac_addr.bytes[0] = 0x33; + peer_mac_addr.bytes[1] = 0x33; + peer_mac_addr.bytes[2] = 0xff; + priv_obj->peer_mc_addr_list[list_idx] = peer_mac_addr; + +end: + qdf_spin_unlock_bh(&priv_obj->lock); +} + +inline void ucfg_nan_get_peer_mc_list( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + *peer_mc_addr_list = priv_obj->peer_mc_addr_list; +} + +inline void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *peer_mac_addr) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + int i; + uint32_t max_ndp_sessions = 0; + struct qdf_mac_addr derived_peer_mc_addr; + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + /* Derive peer multicast addr */ + derived_peer_mc_addr = *peer_mac_addr; + derived_peer_mc_addr.bytes[0] = 0x33; + derived_peer_mc_addr.bytes[1] = 0x33; + derived_peer_mc_addr.bytes[2] = 0xff; + qdf_spin_lock_bh(&priv_obj->lock); + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + for (i = 0; i < max_ndp_sessions; i++) { + if (qdf_is_macaddr_equal(&priv_obj->peer_mc_addr_list[i], + &derived_peer_mc_addr)) { + qdf_zero_macaddr(&priv_obj->peer_mc_addr_list[i]); + break; + } + } + qdf_spin_unlock_bh(&priv_obj->lock); +} + inline uint32_t ucfg_nan_get_active_peers(struct wlan_objmgr_vdev *vdev) { uint32_t val; diff --git a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_off_chan_tx.c b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_off_chan_tx.c index 53440f4b70bf..38fb76a21546 100644 --- a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_off_chan_tx.c +++ b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_off_chan_tx.c @@ -34,6 +34,7 @@ #include "wlan_p2p_off_chan_tx.h" #include "wlan_osif_request_manager.h" #include +#include "wlan_mlme_api.h" /** * p2p_psoc_get_tx_ops() - get p2p tx ops @@ -977,6 +978,71 @@ static QDF_STATUS p2p_send_tx_conf(struct tx_action_context *tx_ctx, return QDF_STATUS_SUCCESS; } +/** + * p2p_get_hw_retry_count() - Get hw tx retry count from config store + * @psoc: psoc object + * @tx_ctx: tx context + * + * This function return the hw tx retry count for p2p action frame. + * 0 value means target will use fw default mgmt tx retry count 15. + * + * Return: frame hw tx retry count + */ +static uint8_t p2p_get_hw_retry_count(struct wlan_objmgr_psoc *psoc, + struct tx_action_context *tx_ctx) +{ + if (tx_ctx->frame_info.type != P2P_FRAME_MGMT) + return 0; + + if (tx_ctx->frame_info.sub_type != P2P_MGMT_ACTION) + return 0; + + switch (tx_ctx->frame_info.public_action_type) { + case P2P_PUBLIC_ACTION_NEG_REQ: + return wlan_mlme_get_mgmt_hw_tx_retry_count( + psoc, + CFG_GO_NEGOTIATION_REQ_FRAME_TYPE); + case P2P_PUBLIC_ACTION_INVIT_REQ: + return wlan_mlme_get_mgmt_hw_tx_retry_count( + psoc, + CFG_P2P_INVITATION_REQ_FRAME_TYPE); + case P2P_PUBLIC_ACTION_PROV_DIS_REQ: + return wlan_mlme_get_mgmt_hw_tx_retry_count( + psoc, + CFG_PROVISION_DISCOVERY_REQ_FRAME_TYPE); + default: + return 0; + } +} + +#define GET_HW_RETRY_LIMIT(count) QDF_GET_BITS(count, 0, 4) +#define GET_HW_RETRY_LIMIT_EXT(count) QDF_GET_BITS(count, 4, 3) + +/** + * p2p_mgmt_set_hw_retry_count() - Set mgmt hw tx retry count + * @psoc: psoc object + * @tx_ctx: tx context + * @mgmt_param: mgmt frame tx parameter + * + * This function will set mgmt frame hw tx retry count to tx parameter + * + * Return: void + */ +static void +p2p_mgmt_set_hw_retry_count(struct wlan_objmgr_psoc *psoc, + struct tx_action_context *tx_ctx, + struct wmi_mgmt_params *mgmt_param) +{ + uint8_t retry_count = p2p_get_hw_retry_count(psoc, tx_ctx); + + mgmt_param->tx_param.retry_limit = GET_HW_RETRY_LIMIT(retry_count); + mgmt_param->tx_param.retry_limit_ext = + GET_HW_RETRY_LIMIT_EXT(retry_count); + if (mgmt_param->tx_param.retry_limit || + mgmt_param->tx_param.retry_limit_ext) + mgmt_param->tx_params_valid = true; +} + /** * p2p_mgmt_tx() - call mgmt tx api * @tx_ctx: tx context @@ -1017,6 +1083,7 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx, p2p_err("qdf ctx is null"); return QDF_STATUS_E_INVAL; } + p2p_mgmt_set_hw_retry_count(psoc, tx_ctx, &mgmt_param); wh = (struct wlan_frame_hdr *)frame; mac_addr = wh->i_addr1; @@ -1052,8 +1119,12 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx, tx_ota_comp_cb = tgt_p2p_mgmt_ota_comp_cb; } - p2p_debug("length:%d, chanfreq:%d", mgmt_param.frm_len, - mgmt_param.chanfreq); + p2p_debug("length:%d, chanfreq:%d retry count:%d(%d, %d)", + mgmt_param.frm_len, mgmt_param.chanfreq, + (mgmt_param.tx_param.retry_limit_ext << 4) | + mgmt_param.tx_param.retry_limit, + mgmt_param.tx_param.retry_limit, + mgmt_param.tx_param.retry_limit_ext); tx_ctx->nbuf = packet; diff --git a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.c b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.c index 62ae30badbae..7fa8a6c5b6ff 100644 --- a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.c +++ b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.c @@ -82,6 +82,8 @@ static QDF_STATUS p2p_scan_start(struct p2p_roc_context *roc_ctx) struct wlan_objmgr_vdev *vdev; struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj; uint32_t go_num; + uint8_t ndp_num = 0, nan_disc_enabled_num = 0; + bool is_dbs; vdev = wlan_objmgr_get_vdev_by_id_from_psoc( p2p_soc_obj->soc, roc_ctx->vdev_id, @@ -121,7 +123,18 @@ static QDF_STATUS p2p_scan_start(struct p2p_roc_context *roc_ctx) if (req->scan_req.dwell_time_passive < P2P_MAX_ROC_DURATION) { go_num = policy_mgr_mode_specific_connection_count( p2p_soc_obj->soc, PM_P2P_GO_MODE, NULL); - p2p_debug("present go number:%d", go_num); + policy_mgr_mode_specific_num_active_sessions(p2p_soc_obj->soc, + QDF_NDI_MODE, + &ndp_num); + policy_mgr_mode_specific_num_active_sessions(p2p_soc_obj->soc, + QDF_NAN_DISC_MODE, + &nan_disc_enabled_num); + + p2p_debug("present go number:%d, NDP number:%d, NAN number:%d", + go_num, ndp_num, nan_disc_enabled_num); + + is_dbs = policy_mgr_is_hw_dbs_capable(p2p_soc_obj->soc); + if (go_num) req->scan_req.dwell_time_passive *= P2P_ROC_DURATION_MULTI_GO_PRESENT; @@ -131,8 +144,28 @@ static QDF_STATUS p2p_scan_start(struct p2p_roc_context *roc_ctx) /* this is to protect too huge value if some customers * give a higher value from supplicant */ - if (req->scan_req.dwell_time_passive > P2P_MAX_ROC_DURATION) + if (ndp_num) { + if (is_dbs && req->scan_req.dwell_time_passive > + P2P_MAX_ROC_DURATION_DBS_NDP_PRESENT) + req->scan_req.dwell_time_passive = + P2P_MAX_ROC_DURATION_DBS_NDP_PRESENT; + else if (!is_dbs && req->scan_req.dwell_time_passive > + P2P_MAX_ROC_DURATION_NON_DBS_NDP_PRESENT) + req->scan_req.dwell_time_passive = + P2P_MAX_ROC_DURATION_NON_DBS_NDP_PRESENT; + } else if (nan_disc_enabled_num) { + if (is_dbs && req->scan_req.dwell_time_passive > + P2P_MAX_ROC_DURATION_DBS_NAN_PRESENT) + req->scan_req.dwell_time_passive = + P2P_MAX_ROC_DURATION_DBS_NAN_PRESENT; + else if (!is_dbs && req->scan_req.dwell_time_passive > + P2P_MAX_ROC_DURATION_NON_DBS_NAN_PRESENT) + req->scan_req.dwell_time_passive = + P2P_MAX_ROC_DURATION_NON_DBS_NAN_PRESENT; + } else if (req->scan_req.dwell_time_passive > + P2P_MAX_ROC_DURATION) { req->scan_req.dwell_time_passive = P2P_MAX_ROC_DURATION; + } } p2p_debug("FW requested roc duration is:%d", req->scan_req.dwell_time_passive); diff --git a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.h b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.h index e82d8caee189..cfcb586d89c3 100644 --- a/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.h +++ b/drivers/staging/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.h @@ -31,6 +31,10 @@ #define P2P_WAIT_CANCEL_ROC 1000 #define P2P_WAIT_CLEANUP_ROC 2000 #define P2P_MAX_ROC_DURATION 1500 +#define P2P_MAX_ROC_DURATION_DBS_NDP_PRESENT 400 +#define P2P_MAX_ROC_DURATION_NON_DBS_NDP_PRESENT 250 +#define P2P_MAX_ROC_DURATION_DBS_NAN_PRESENT 450 +#define P2P_MAX_ROC_DURATION_NON_DBS_NAN_PRESENT 300 #define P2P_ROC_DURATION_MULTI_GO_PRESENT 6 #define P2P_ROC_DURATION_MULTI_GO_ABSENT 10 diff --git a/drivers/staging/qcacld-3.0/components/p2p/dispatcher/src/wlan_p2p_tgt_api.c b/drivers/staging/qcacld-3.0/components/p2p/dispatcher/src/wlan_p2p_tgt_api.c index 1acd101de9d2..e51f2a021997 100644 --- a/drivers/staging/qcacld-3.0/components/p2p/dispatcher/src/wlan_p2p_tgt_api.c +++ b/drivers/staging/qcacld-3.0/components/p2p/dispatcher/src/wlan_p2p_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -312,7 +312,7 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc, if (!peer) { if (p2p_soc_obj->cur_roc_vdev_id == P2P_INVALID_VDEV_ID) { - p2p_err("vdev id of current roc invalid"); + p2p_debug("vdev id of current roc invalid"); qdf_nbuf_free(buf); return QDF_STATUS_E_FAILURE; } else { diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h index f7511902a2c8..e933c47ce78e 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h @@ -29,6 +29,7 @@ #include "cdp_txrx_cmn_struct.h" #include +#include #ifndef WLAN_FEATURE_PKT_CAPTURE_V2 #include #endif @@ -168,6 +169,7 @@ void pkt_capture_offload_deliver_indication_handler( * @dir: direction rx: 0 and tx: 1 * @status: tx status * @tx_retry_cnt: tx retry count + * @ppdu_id: ppdu_id of msdu */ struct pkt_capture_tx_hdr_elem_t { uint32_t timestamp; @@ -186,6 +188,18 @@ struct pkt_capture_tx_hdr_elem_t { uint8_t tx_retry_cnt; uint16_t framectrl; uint16_t seqno; + uint32_t ppdu_id; +}; + +/** + * pkt_capture_ppdu_stats_q_node - node structure to be enqueued + * in ppdu_stats_q + * @node: list node + * @buf: buffer data received from ppdu_stats + */ +struct pkt_capture_ppdu_stats_q_node { + qdf_list_node_t node; + uint32_t buf[]; }; /** diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_main.h b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_main.h index b6b328338247..cb48a75b7b8d 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_main.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_main.h @@ -172,6 +172,25 @@ void pkt_capture_set_pktcap_mode(struct wlan_objmgr_psoc *psoc, enum pkt_capture_mode pkt_capture_get_pktcap_mode(struct wlan_objmgr_psoc *psoc); +/** + * pkt_capture_set_pktcap_config - Set packet capture config + * @vdev: pointer to vdev object + * @config: config to be set + * + * Return: None + */ +void pkt_capture_set_pktcap_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config); + +/** + * pkt_capture_get_pktcap_config - Get packet capture config + * @vdev: pointer to vdev object + * + * Return: config value + */ +enum pkt_capture_config +pkt_capture_get_pktcap_config(struct wlan_objmgr_vdev *vdev); + /** * pkt_capture_drop_nbuf_list() - drop an nbuf list * @buf_list: buffer list to be dropepd @@ -201,6 +220,24 @@ void pkt_capture_record_channel(struct wlan_objmgr_vdev *vdev); void pkt_capture_mon(struct pkt_capture_cb_context *cb_ctx, qdf_nbuf_t msdu, struct wlan_objmgr_vdev *vdev, uint16_t ch_freq); +/** + * pkt_capture_set_filter - Set packet capture frame filter + * @frame_filter: pkt capture frame filter data + * @vdev: pointer to vdev + * + * Return: QDF_STATUS + */ +QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, + struct wlan_objmgr_vdev *vdev); + +/** + * pkt_capture_is_tx_mgmt_enable - Check if tx mgmt frames enabled + * @pdev: pointer to pdev + * + * Return: bool + */ +bool pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev); + #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 /** * pkt_capture_get_pktcap_mode_v2 - Get packet capture mode @@ -215,12 +252,12 @@ pkt_capture_get_pktcap_mode_v2(void); * @soc: dp_soc handle * @event: wdi event * @log_data: nbuf data - * @vdev_id: vdev id + * @peer_id: peer id * @status: status * * Return: None */ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, - u_int16_t vdev_id, uint32_t status); + u_int16_t peer_id, uint32_t status); #endif #endif /* end of _WLAN_PKT_CAPTURE_MAIN_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mgmt_txrx.h b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mgmt_txrx.h index f456107b9f0c..b10866c20793 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mgmt_txrx.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mgmt_txrx.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -33,6 +34,7 @@ #define RESERVE_BYTES (100) #define RATE_LIMIT (16) #define INVALID_RSSI_FOR_TX (-128) +#define PKTCAPTURE_RATECODE_CCK (1) /** * pkt_capture_process_mgmt_tx_data() - process management tx packets diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h index d48d0c4b209d..ce37798894ed 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -32,23 +33,23 @@ #include "wlan_pkt_capture_mon_thread.h" /** - * struct pkt_capture_cfg - packet capture cfg to store ini values + * struct pkt_capture_cfg - struct to store config values * @pkt_capture_mode: packet capture mode + * @pkt_capture_config: config for trigger, qos and beacon frames */ struct pkt_capture_cfg { enum pkt_capture_mode pkt_capture_mode; + enum pkt_capture_config pkt_capture_config; }; /** * struct pkt_capture_cb_context - packet capture callback context * @mon_cb: monitor callback function pointer * @mon_ctx: monitor callback context - * @pkt_capture_mode: packet capture mode */ struct pkt_capture_cb_context { QDF_STATUS (*mon_cb)(void *, qdf_nbuf_t); void *mon_ctx; - enum pkt_capture_mode pkt_capture_mode; }; /** @@ -56,17 +57,23 @@ struct pkt_capture_cb_context { * @vdev: pointer to vdev object * @mon_ctx: pointer to packet capture mon context * @cb_ctx: pointer to packet capture mon callback context - * @rx_ops: rx ops - * @tx_ops: tx ops + * @frame_filter: config filter set by vendor command + * @cfg_params: packet capture config params * @rx_avg_rssi: avg rssi of rx data packets + * @ppdu_stats_q: list used for storing smu related ppdu stats + * @lock_q: spinlock for ppdu_stats q + * @tx_nss: nss of tx data packets received from ppdu stats */ struct pkt_capture_vdev_priv { struct wlan_objmgr_vdev *vdev; struct pkt_capture_mon_context *mon_ctx; struct pkt_capture_cb_context *cb_ctx; - struct wlan_pkt_capture_rx_ops rx_ops; - struct wlan_pkt_capture_tx_ops tx_ops; + struct pkt_capture_frame_filter frame_filter; + struct pkt_capture_cfg cfg_params; int32_t rx_avg_rssi; + qdf_list_t ppdu_stats_q; + qdf_spinlock_t lock_q; + uint8_t tx_nss; }; /** @@ -74,10 +81,14 @@ struct pkt_capture_vdev_priv { * @psoc: pointer to psoc object * @cfg_param: INI config params for packet capture * @cb_obj: struct contaning callback pointers + * @rx_ops: rx ops + * @tx_ops: tx ops */ struct pkt_psoc_priv { struct wlan_objmgr_psoc *psoc; struct pkt_capture_cfg cfg_param; struct pkt_capture_callbacks cb_obj; + struct wlan_pkt_capture_rx_ops rx_ops; + struct wlan_pkt_capture_tx_ops tx_ops; }; #endif /* End of _WLAN_PKT_CAPTURE_PRIV_STRUCT_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c index ff6e9f703c96..014a4b383e47 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. 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 @@ -31,6 +32,7 @@ #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 #include "dp_internal.h" #include "cds_utils.h" +#include "htt_ppdu_stats.h" #endif #define RESERVE_BYTES (100) @@ -261,8 +263,12 @@ pkt_capture_update_tx_status( struct pkt_capture_tx_hdr_elem_t *pktcapture_hdr) { struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS]; + struct pkt_capture_vdev_priv *vdev_priv; struct wlan_objmgr_vdev *vdev = context; + htt_ppdu_stats_for_smu_tlv *smu; struct wlan_objmgr_psoc *psoc; + struct pkt_capture_ppdu_stats_q_node *q_node; + qdf_list_node_t *node; uint32_t conn_count; uint8_t vdev_id; int i; @@ -285,6 +291,38 @@ pkt_capture_update_tx_status( } } + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (qdf_unlikely(!vdev_priv)) + goto skip_ppdu_stats; + + /* Fill the nss received from ppdu_stats */ + pktcapture_hdr->nss = vdev_priv->tx_nss; + + /* Remove the ppdu stats from front of list and fill it in tx_status */ + qdf_spin_lock_bh(&vdev_priv->lock_q); + if (QDF_STATUS_SUCCESS == + qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node)) { + qdf_spin_unlock_bh(&vdev_priv->lock_q); + q_node = qdf_container_of( + node, struct pkt_capture_ppdu_stats_q_node, node); + smu = (htt_ppdu_stats_for_smu_tlv *)(q_node->buf); + tx_status->prev_ppdu_id = smu->ppdu_id; + tx_status->start_seq = smu->start_seq; + tx_status->tid = smu->tid_num; + + if (smu->win_size == 8) + qdf_mem_copy(tx_status->ba_bitmap, smu->ba_bitmap, + 8 * sizeof(uint32_t)); + else if (smu->win_size == 2) + qdf_mem_copy(tx_status->ba_bitmap, smu->ba_bitmap, + 2 * sizeof(uint32_t)); + + qdf_mem_free(q_node); + } else { + qdf_spin_unlock_bh(&vdev_priv->lock_q); + } + +skip_ppdu_stats: pkt_capture_tx_get_phy_info(pktcapture_hdr, tx_status); tx_status->tsft = (u_int64_t)(pktcapture_hdr->timestamp); @@ -292,7 +330,9 @@ pkt_capture_update_tx_status( tx_status->rssi_comb = pktcapture_hdr->rssi_comb; tx_status->tx_status = pktcapture_hdr->status; tx_status->tx_retry_cnt = pktcapture_hdr->tx_retry_cnt; + tx_status->ppdu_id = pktcapture_hdr->ppdu_id; tx_status->add_rtap_ext = true; + tx_status->add_rtap_ext2 = true; } #endif @@ -739,7 +779,6 @@ static uint8_t pkt_capture_get_rx_rtap_flags(void *ptr_rx_tlv_hdr) return rtap_flags; } -#define CHANNEL_FREQ_5150 5150 /** * pkt_capture_rx_mon_get_rx_status() - Get rx status * @context: objmgr vdev @@ -758,7 +797,6 @@ static void pkt_capture_rx_mon_get_rx_status(void *context, void *dp_soc, struct rx_msdu_start *msdu_start = &pkt_tlvs->msdu_start_tlv.rx_msdu_start; struct wlan_objmgr_vdev *vdev = context; - struct pkt_capture_vdev_priv *vdev_priv; uint8_t primary_chan_num; uint32_t center_chan_freq; struct wlan_objmgr_psoc *psoc; @@ -790,17 +828,6 @@ static void pkt_capture_rx_mon_get_rx_status(void *context, void *dp_soc, wlan_reg_chan_band_to_freq(pdev, primary_chan_num, BIT(band)); wlan_objmgr_pdev_release_ref(pdev, WLAN_PKT_CAPTURE_ID); - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (qdf_unlikely(!vdev)) - return; - - rx_status->rssi_comb = vdev_priv->rx_avg_rssi; - - if (rx_status->chan_freq > CHANNEL_FREQ_5150) - rx_status->ofdm_flag = 1; - else - rx_status->cck_flag = 1; - pkt_capture_rx_get_phy_info(context, dp_soc, desc, rx_status); } #endif @@ -830,7 +857,7 @@ pkt_capture_rx_data_cb( { struct pkt_capture_vdev_priv *vdev_priv; qdf_nbuf_t buf_list = (qdf_nbuf_t)nbuf_list; - struct wlan_objmgr_vdev *vdev = context; + struct wlan_objmgr_vdev *vdev; htt_pdev_handle pdev = ppdev; struct pkt_capture_cb_context *cb_ctx; qdf_nbuf_t msdu, next_buf; @@ -841,14 +868,19 @@ pkt_capture_rx_data_cb( static uint8_t preamble_type; static uint32_t vht_sig_a_1; static uint32_t vht_sig_a_2; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto free_buf; vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (qdf_unlikely(!vdev)) - goto free_buf; - cb_ctx = vdev_priv->cb_ctx; - if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) + if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) { + pkt_capture_vdev_put_ref(vdev); goto free_buf; + } msdu = buf_list; while (msdu) { @@ -923,6 +955,7 @@ pkt_capture_rx_data_cb( msdu = next_buf; } + pkt_capture_vdev_put_ref(vdev); return; free_buf: @@ -953,7 +986,7 @@ pkt_capture_rx_data_cb( { struct pkt_capture_vdev_priv *vdev_priv; qdf_nbuf_t buf_list = (qdf_nbuf_t)nbuf_list; - struct wlan_objmgr_vdev *vdev = context; + struct wlan_objmgr_vdev *vdev; struct pkt_capture_cb_context *cb_ctx; qdf_nbuf_t msdu, next_buf; uint8_t drop_count; @@ -963,14 +996,19 @@ pkt_capture_rx_data_cb( struct dp_soc *soc = psoc; hal_soc_handle_t hal_soc; struct hal_rx_msdu_metadata msdu_metadata; + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) + goto free_buf; vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (qdf_unlikely(!vdev)) - goto free_buf; - cb_ctx = vdev_priv->cb_ctx; - if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) + if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) { + pkt_capture_vdev_put_ref(vdev); goto free_buf; + } hal_soc = soc->hal_soc; msdu = buf_list; @@ -994,7 +1032,7 @@ pkt_capture_rx_data_cb( */ /* need to update this to fill rx_status*/ - pkt_capture_rx_mon_get_rx_status(context, psoc, + pkt_capture_rx_mon_get_rx_status(vdev, psoc, rx_tlv_hdr, &rx_status); rx_status.tx_status = status; rx_status.tx_retry_cnt = tx_retry_cnt; @@ -1025,6 +1063,7 @@ pkt_capture_rx_data_cb( msdu = next_buf; } + pkt_capture_vdev_put_ref(vdev); return; free_buf: @@ -1057,7 +1096,7 @@ pkt_capture_tx_data_cb( { qdf_nbuf_t msdu, next_buf; struct pkt_capture_vdev_priv *vdev_priv; - struct wlan_objmgr_vdev *vdev = context; + struct wlan_objmgr_vdev *vdev; htt_pdev_handle pdev = ppdev; struct pkt_capture_cb_context *cb_ctx; uint8_t drop_count; @@ -1072,18 +1111,23 @@ pkt_capture_tx_data_cb( uint32_t headroom; uint16_t seq_no, fc_ctrl; struct mon_rx_status tx_status = {0}; + QDF_STATUS status = QDF_STATUS_SUCCESS; uint8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4) + sizeof(struct llc_snap_hdr_t)]; const uint8_t ethernet_II_llc_snap_header_prefix[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (qdf_unlikely(!vdev)) + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) goto free_buf; + vdev_priv = pkt_capture_vdev_get_priv(vdev); cb_ctx = vdev_priv->cb_ctx; - if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) + if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) { + pkt_capture_vdev_put_ref(vdev); goto free_buf; + } msdu = nbuf_list; while (msdu) { @@ -1200,6 +1244,7 @@ pkt_capture_tx_data_cb( pkt_capture_mon(cb_ctx, msdu, vdev, 0); msdu = next_buf; } + pkt_capture_vdev_put_ref(vdev); return; free_buf: @@ -1249,7 +1294,7 @@ pkt_capture_tx_data_cb( { qdf_nbuf_t msdu, next_buf; struct pkt_capture_vdev_priv *vdev_priv; - struct wlan_objmgr_vdev *vdev = context; + struct wlan_objmgr_vdev *vdev; struct pkt_capture_cb_context *cb_ctx; uint8_t drop_count; struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr = NULL; @@ -1264,19 +1309,24 @@ pkt_capture_tx_data_cb( uint32_t headroom; uint16_t seq_no, fc_ctrl; struct mon_rx_status tx_status = {0}; + QDF_STATUS ret = QDF_STATUS_SUCCESS; uint8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4) + sizeof(struct llc_snap_hdr_t)]; const uint8_t ethernet_II_llc_snap_header_prefix[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; struct qdf_mac_addr bss_peer_mac_address; - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (qdf_unlikely(!vdev)) + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) goto free_buf; + vdev_priv = pkt_capture_vdev_get_priv(vdev); cb_ctx = vdev_priv->cb_ctx; - if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) + if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) { + pkt_capture_vdev_put_ref(vdev); goto free_buf; + } msdu = nbuf_list; while (msdu) { @@ -1377,7 +1427,7 @@ pkt_capture_tx_data_cb( } pkt_capture_update_tx_status( - context, + vdev, &tx_status, &pktcapture_hdr); /* @@ -1389,6 +1439,7 @@ pkt_capture_tx_data_cb( pkt_capture_mon(cb_ctx, msdu, vdev, 0); msdu = next_buf; } + pkt_capture_vdev_put_ref(vdev); return; free_buf: @@ -1408,10 +1459,12 @@ void pkt_capture_datapkt_process( struct pkt_capture_mon_pkt *pkt; pkt_capture_mon_thread_cb callback = NULL; struct wlan_objmgr_vdev *vdev; + QDF_STATUS ret = QDF_STATUS_SUCCESS; status = pkt_capture_txrx_status_map(status); vdev = pkt_capture_get_vdev(); - if (!vdev) + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) goto drop_rx_buf; pkt = pkt_capture_alloc_mon_pkt(vdev); @@ -1431,7 +1484,7 @@ void pkt_capture_datapkt_process( } pkt->callback = callback; - pkt->context = (void *)vdev; + pkt->context = NULL; pkt->pdev = (void *)pdev; pkt->monpkt = (void *)mon_buf_list; pkt->vdev_id = vdev_id; @@ -1441,6 +1494,7 @@ void pkt_capture_datapkt_process( qdf_mem_copy(pkt->bssid, bssid, QDF_MAC_ADDR_SIZE); pkt->tx_retry_cnt = tx_retry_cnt; pkt_capture_indicate_monpkt(vdev, pkt); + pkt_capture_vdev_put_ref(vdev); return; drop_rx_buf: diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c index cbf9d77ff23a..7ddfa1f9c091 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. 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 @@ -23,6 +24,7 @@ #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 #include +#include "htt_ppdu_stats.h" #endif #include "wlan_pkt_capture_main.h" #include "cfg_ucfg_api.h" @@ -32,6 +34,7 @@ #include "cdp_txrx_ctrl.h" #include "wlan_pkt_capture_tgt_api.h" #include +#include "wlan_vdev_mgr_utils_api.h" static struct wlan_objmgr_vdev *gp_pkt_capture_vdev; @@ -40,6 +43,7 @@ wdi_event_subscribe PKT_CAPTURE_TX_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_RX_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_RX_NO_PEER_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER; +wdi_event_subscribe PKT_CAPTURE_PPDU_STATS_SUBSCRIBER; /** * pkt_capture_wdi_event_subscribe() - Subscribe pkt capture callbacks @@ -89,6 +93,16 @@ static void pkt_capture_wdi_event_subscribe(struct wlan_objmgr_psoc *psoc) cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER, WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); + + /* subscribe for packet capture mode related ppdu stats */ + PKT_CAPTURE_PPDU_STATS_SUBSCRIBER.callback = + pkt_capture_callback; + + PKT_CAPTURE_PPDU_STATS_SUBSCRIBER.context = + wlan_psoc_get_dp_handle(psoc); + + cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_PPDU_STATS_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_PPDU_STATS); } /** @@ -102,21 +116,25 @@ static void pkt_capture_wdi_event_unsubscribe(struct wlan_objmgr_psoc *psoc) void *soc = cds_get_context(QDF_MODULE_ID_SOC); uint8_t pdev_id = WMI_PDEV_ID_SOC; - /* unsubscribing for tx data packets */ - cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_TX_SUBSCRIBER, - WDI_EVENT_PKT_CAPTURE_TX_DATA); + /* unsubscribe ppdu smu stats */ + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_PPDU_STATS_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_PPDU_STATS); - /* unsubscribing for rx data packets */ - cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_RX_SUBSCRIBER, - WDI_EVENT_PKT_CAPTURE_RX_DATA); + /* unsubscribing for offload tx data packets */ + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); /* unsubscribe for rx data no peer packets */ cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_RX_NO_PEER_SUBSCRIBER, WDI_EVENT_PKT_CAPTURE_RX_DATA_NO_PEER); - /* unsubscribing for offload tx data packets */ - cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER, - WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); + /* unsubscribing for rx data packets */ + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_RX_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_RX_DATA); + + /* unsubscribing for tx data packets */ + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_TX_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_TX_DATA); } enum pkt_capture_mode @@ -125,21 +143,25 @@ pkt_capture_get_pktcap_mode_v2() enum pkt_capture_mode mode = PACKET_CAPTURE_MODE_DISABLE; struct pkt_capture_vdev_priv *vdev_priv; struct wlan_objmgr_vdev *vdev; + QDF_STATUS status = QDF_STATUS_SUCCESS; vdev = pkt_capture_get_vdev(); - if (!vdev) + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) return PACKET_CAPTURE_MODE_DISABLE; vdev_priv = pkt_capture_vdev_get_priv(vdev); if (!vdev_priv) pkt_capture_err("vdev_priv is NULL"); else - mode = vdev_priv->cb_ctx->pkt_capture_mode; + mode = vdev_priv->cfg_params.pkt_capture_mode; + pkt_capture_vdev_put_ref(vdev); return mode; } #define RX_OFFLOAD_PKT 1 +#define PPDU_STATS_Q_MAX_SIZE 500 static void pkt_capture_process_rx_data_no_peer(void *soc, uint16_t vdev_id, uint8_t *bssid, @@ -181,156 +203,357 @@ pkt_capture_process_rx_data_no_peer(void *soc, uint16_t vdev_id, uint8_t *bssid, bssid, psoc, 0); } -void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, - u_int16_t vdev_id, uint32_t status) +static void +pkt_capture_process_ppdu_stats(void *log_data) +{ + struct wlan_objmgr_vdev *vdev; + struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_ppdu_stats_q_node *q_node; + htt_ppdu_stats_for_smu_tlv *smu; + uint32_t stats_len; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + return; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (qdf_unlikely(!vdev_priv)) { + pkt_capture_vdev_put_ref(vdev); + return; + } + + smu = (htt_ppdu_stats_for_smu_tlv *)log_data; + vdev_priv->tx_nss = smu->nss; + + qdf_spin_lock_bh(&vdev_priv->lock_q); + if (qdf_list_size(&vdev_priv->ppdu_stats_q) < + PPDU_STATS_Q_MAX_SIZE) { + /* + * win size indicates the size of block ack bitmap, currently + * we support only 256 bit ba bitmap. + */ + if (smu->win_size > 8) { + qdf_spin_unlock_bh(&vdev_priv->lock_q); + pkt_capture_vdev_put_ref(vdev); + pkt_capture_err("win size %d > 8 not supported\n", + smu->win_size); + return; + } + + stats_len = sizeof(htt_ppdu_stats_for_smu_tlv) + + smu->win_size * sizeof(uint32_t); + + q_node = qdf_mem_malloc(sizeof(*q_node) + stats_len); + if (q_node == NULL) { + qdf_spin_unlock_bh(&vdev_priv->lock_q); + pkt_capture_vdev_put_ref(vdev); + pkt_capture_err("stats node and buf allocation fail\n"); + return; + } + + qdf_mem_copy(q_node->buf, log_data, stats_len); + /* Insert received ppdu stats in queue */ + qdf_list_insert_back(&vdev_priv->ppdu_stats_q, + &q_node->node); + } + qdf_spin_unlock_bh(&vdev_priv->lock_q); + pkt_capture_vdev_put_ref(vdev); +} + +static void +pkt_capture_process_tx_data(void *soc, void *log_data, u_int16_t vdev_id, + uint32_t status) { - uint8_t bssid[QDF_MAC_ADDR_SIZE]; - uint8_t tid = 0; struct dp_soc *psoc = soc; + uint8_t tid = 0; + uint8_t bssid[QDF_MAC_ADDR_SIZE]; + struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr; + struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0}; + struct hal_tx_completion_status tx_comp_status = {0}; + struct qdf_tso_seg_elem_t *tso_seg = NULL; + uint32_t txcap_hdr_size = + sizeof(struct pkt_capture_tx_hdr_elem_t); - switch (event) { - case WDI_EVENT_PKT_CAPTURE_TX_DATA: - { - struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr; - struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0}; - struct hal_tx_completion_status tx_comp_status = {0}; - struct qdf_tso_seg_elem_t *tso_seg = NULL; - uint32_t txcap_hdr_size = - sizeof(struct pkt_capture_tx_hdr_elem_t); + struct dp_tx_desc_s *desc = log_data; + qdf_nbuf_t netbuf; + int nbuf_len; - struct dp_tx_desc_s *desc = log_data; - qdf_nbuf_t netbuf; - int nbuf_len; + hal_tx_comp_get_status(&desc->comp, &tx_comp_status, + psoc->hal_soc); - hal_tx_comp_get_status(&desc->comp, &tx_comp_status, - psoc->hal_soc); - if (!(pkt_capture_get_pktcap_mode_v2() & - PKT_CAPTURE_MODE_DATA_ONLY)) { + if (tx_comp_status.valid) + pktcapture_hdr.ppdu_id = tx_comp_status.ppdu_id; + pktcapture_hdr.timestamp = tx_comp_status.tsf; + pktcapture_hdr.preamble = tx_comp_status.pkt_type; + pktcapture_hdr.mcs = tx_comp_status.mcs; + pktcapture_hdr.bw = tx_comp_status.bw; + /* nss not available */ + pktcapture_hdr.nss = 0; + pktcapture_hdr.rssi_comb = tx_comp_status.ack_frame_rssi; + /* rate not available */ + pktcapture_hdr.rate = 0; + pktcapture_hdr.stbc = tx_comp_status.stbc; + pktcapture_hdr.sgi = tx_comp_status.sgi; + pktcapture_hdr.ldpc = tx_comp_status.ldpc; + /* Beamformed not available */ + pktcapture_hdr.beamformed = 0; + pktcapture_hdr.framectrl = IEEE80211_FC0_TYPE_DATA | + (IEEE80211_FC1_DIR_TODS << 8); + pktcapture_hdr.tx_retry_cnt = tx_comp_status.transmit_cnt - 1; + /* seqno not available */ + pktcapture_hdr.seqno = 0; + tid = tx_comp_status.tid; + status = tx_comp_status.status; + + if (desc->frm_type == dp_tx_frm_tso) { + if (!desc->tso_desc) return; - } + tso_seg = desc->tso_desc; + nbuf_len = tso_seg->seg.total_len; + } else { + nbuf_len = qdf_nbuf_len(desc->nbuf); + } - pktcapture_hdr.timestamp = tx_comp_status.tsf; - pktcapture_hdr.preamble = tx_comp_status.pkt_type; - pktcapture_hdr.mcs = tx_comp_status.mcs; - pktcapture_hdr.bw = tx_comp_status.bw; - /* nss not available */ - pktcapture_hdr.nss = 0; - pktcapture_hdr.rssi_comb = tx_comp_status.ack_frame_rssi; - /* rate not available */ - pktcapture_hdr.rate = 0; - pktcapture_hdr.stbc = tx_comp_status.stbc; - pktcapture_hdr.sgi = tx_comp_status.sgi; - pktcapture_hdr.ldpc = tx_comp_status.ldpc; - /* Beamformed not available */ - pktcapture_hdr.beamformed = 0; - pktcapture_hdr.framectrl = IEEE80211_FC0_TYPE_DATA | - (IEEE80211_FC1_DIR_TODS << 8); - pktcapture_hdr.tx_retry_cnt = tx_comp_status.transmit_cnt - 1; - /* seqno not available */ - pktcapture_hdr.seqno = 0; - tid = tx_comp_status.tid; - status = tx_comp_status.status; + netbuf = qdf_nbuf_alloc(NULL, + roundup(nbuf_len + RESERVE_BYTES, 4), + RESERVE_BYTES, 4, false); - if (desc->frm_type == dp_tx_frm_tso) { - if (!desc->tso_desc) - return; - tso_seg = desc->tso_desc; - nbuf_len = tso_seg->seg.total_len; - } else { - nbuf_len = qdf_nbuf_len(desc->nbuf); - } + if (!netbuf) + return; - netbuf = qdf_nbuf_alloc(NULL, - roundup(nbuf_len + RESERVE_BYTES, 4), - RESERVE_BYTES, 4, false); + qdf_nbuf_put_tail(netbuf, nbuf_len); - if (!netbuf) - return; + if (desc->frm_type == dp_tx_frm_tso) { + uint8_t frag_cnt, num_frags = 0; + int frag_len = 0; + uint32_t tcp_seq_num; + uint16_t ip_len; - qdf_nbuf_put_tail(netbuf, nbuf_len); + if (tso_seg->seg.num_frags > 0) + num_frags = tso_seg->seg.num_frags - 1; - if (desc->frm_type == dp_tx_frm_tso) { - uint8_t frag_cnt, num_frags = 0; - int frag_len = 0; - uint32_t tcp_seq_num; - uint16_t ip_len; - - if (tso_seg->seg.num_frags > 0) - num_frags = tso_seg->seg.num_frags - 1; - - /*Num of frags in a tso seg cannot be less than 2 */ - if (num_frags < 1) { - pkt_capture_err("num of frags in tso segment is %d\n", - (num_frags + 1)); - qdf_nbuf_free(netbuf); - return; - } - - tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num; - tcp_seq_num = qdf_cpu_to_be32(tcp_seq_num); - - ip_len = tso_seg->seg.tso_flags.ip_len; - ip_len = qdf_cpu_to_be16(ip_len); - - for (frag_cnt = 0; frag_cnt <= num_frags; frag_cnt++) { - qdf_mem_copy( - qdf_nbuf_data(netbuf) + frag_len, - tso_seg->seg.tso_frags[frag_cnt].vaddr, - tso_seg->seg.tso_frags[frag_cnt].length); - frag_len += - tso_seg->seg.tso_frags[frag_cnt].length; - } - - qdf_mem_copy((qdf_nbuf_data(netbuf) + - IPV4_PKT_LEN_OFFSET), - &ip_len, sizeof(ip_len)); - qdf_mem_copy((qdf_nbuf_data(netbuf) + - IPV4_TCP_SEQ_NUM_OFFSET), - &tcp_seq_num, sizeof(tcp_seq_num)); - } else { - qdf_mem_copy(qdf_nbuf_data(netbuf), - qdf_nbuf_data(desc->nbuf), nbuf_len); - } - - if (qdf_unlikely(qdf_nbuf_headroom(netbuf) < txcap_hdr_size)) { - netbuf = qdf_nbuf_realloc_headroom(netbuf, - txcap_hdr_size); - if (!netbuf) { - QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, - QDF_TRACE_LEVEL_ERROR, - FL("No headroom")); - return; - } - } - - if (!qdf_nbuf_push_head(netbuf, txcap_hdr_size)) { - QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, - QDF_TRACE_LEVEL_ERROR, FL("No headroom")); + /*Num of frags in a tso seg cannot be less than 2 */ + if (num_frags < 1) { + pkt_capture_err("num of frags in tso segment is %d\n", + (num_frags + 1)); qdf_nbuf_free(netbuf); return; } - ptr_pktcapture_hdr = - (struct pkt_capture_tx_hdr_elem_t *)qdf_nbuf_data(netbuf); - qdf_mem_copy(ptr_pktcapture_hdr, &pktcapture_hdr, - txcap_hdr_size); + tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num; + tcp_seq_num = qdf_cpu_to_be32(tcp_seq_num); - pkt_capture_datapkt_process( - vdev_id, netbuf, TXRX_PROCESS_TYPE_DATA_TX_COMPL, - tid, status, TXRX_PKTCAPTURE_PKT_FORMAT_8023, - bssid, NULL, pktcapture_hdr.tx_retry_cnt); + ip_len = tso_seg->seg.tso_flags.ip_len; + ip_len = qdf_cpu_to_be16(ip_len); + for (frag_cnt = 0; frag_cnt <= num_frags; frag_cnt++) { + qdf_mem_copy( + qdf_nbuf_data(netbuf) + frag_len, + tso_seg->seg.tso_frags[frag_cnt].vaddr, + tso_seg->seg.tso_frags[frag_cnt].length); + frag_len += + tso_seg->seg.tso_frags[frag_cnt].length; + } + + qdf_mem_copy((qdf_nbuf_data(netbuf) + + IPV4_PKT_LEN_OFFSET), + &ip_len, sizeof(ip_len)); + qdf_mem_copy((qdf_nbuf_data(netbuf) + + IPV4_TCP_SEQ_NUM_OFFSET), + &tcp_seq_num, sizeof(tcp_seq_num)); + } else { + qdf_mem_copy(qdf_nbuf_data(netbuf), + qdf_nbuf_data(desc->nbuf), nbuf_len); + } + + if (qdf_unlikely(qdf_nbuf_headroom(netbuf) < txcap_hdr_size)) { + netbuf = qdf_nbuf_realloc_headroom(netbuf, + txcap_hdr_size); + if (!netbuf) { + QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, + QDF_TRACE_LEVEL_ERROR, + FL("No headroom")); + return; + } + } + + if (!qdf_nbuf_push_head(netbuf, txcap_hdr_size)) { + QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, + QDF_TRACE_LEVEL_ERROR, FL("No headroom")); + qdf_nbuf_free(netbuf); + return; + } + + ptr_pktcapture_hdr = + (struct pkt_capture_tx_hdr_elem_t *)qdf_nbuf_data(netbuf); + qdf_mem_copy(ptr_pktcapture_hdr, &pktcapture_hdr, + txcap_hdr_size); + + pkt_capture_datapkt_process( + vdev_id, netbuf, TXRX_PROCESS_TYPE_DATA_TX_COMPL, + tid, status, TXRX_PKTCAPTURE_PKT_FORMAT_8023, + bssid, NULL, pktcapture_hdr.tx_retry_cnt); +} + +/** + * pkt_capture_is_frame_filter_set() - Check frame filter is set + * @nbuf: buffer address + * @frame_filter: frame filter address + * @direction: frame direction + * + * Return: true, if filter bit is set + * false, if filter bit is not set + */ +static bool +pkt_capture_is_frame_filter_set(qdf_nbuf_t buf, + struct pkt_capture_frame_filter *frame_filter, + bool direction) +{ + enum pkt_capture_data_frame_type data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_ALL; + + if (qdf_nbuf_is_ipv4_arp_pkt(buf)) { + data_frame_type = PKT_CAPTURE_DATA_FRAME_TYPE_ARP; + } else if (qdf_nbuf_is_ipv4_eapol_pkt(buf)) { + data_frame_type = PKT_CAPTURE_DATA_FRAME_TYPE_EAPOL; + } else if (qdf_nbuf_data_is_tcp_syn(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_SYN; + } else if (qdf_nbuf_data_is_tcp_syn_ack(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_SYNACK; + } else if (qdf_nbuf_data_is_tcp_syn(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_FIN; + } else if (qdf_nbuf_data_is_tcp_syn_ack(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_FINACK; + } else if (qdf_nbuf_data_is_tcp_ack(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_ACK; + } else if (qdf_nbuf_data_is_tcp_rst(buf)) { + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_RST; + } else if (qdf_nbuf_is_ipv4_pkt(buf)) { + if (qdf_nbuf_is_ipv4_dhcp_pkt(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_DHCPV4; + else if (qdf_nbuf_is_icmp_pkt(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_ICMPV4; + else if (qdf_nbuf_data_is_dns_query(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_DNSV4; + else if (qdf_nbuf_data_is_dns_response(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_DNSV4; + } else if (qdf_nbuf_is_ipv6_pkt(buf)) { + if (qdf_nbuf_is_ipv6_dhcp_pkt(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_DHCPV6; + else if (qdf_nbuf_is_icmpv6_pkt(buf)) + data_frame_type = + PKT_CAPTURE_DATA_FRAME_TYPE_ICMPV6; + /* need to add code for + * PKT_CAPTURE_DATA_FRAME_TYPE_DNSV6 + */ + } + /* Add code for + * PKT_CAPTURE_DATA_FRAME_TYPE_RTP + * PKT_CAPTURE_DATA_FRAME_TYPE_SIP + * PKT_CAPTURE_DATA_FRAME_QOS_NULL + */ + + if (direction == IEEE80211_FC1_DIR_TODS) { + if (data_frame_type & frame_filter->data_tx_frame_filter) + return true; + else + return false; + } else { + if (data_frame_type & frame_filter->data_rx_frame_filter) + return true; + else + return false; + } +} + +void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, + u_int16_t peer_id, uint32_t status) +{ + uint8_t bssid[QDF_MAC_ADDR_SIZE]; + struct wlan_objmgr_vdev *vdev; + struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_frame_filter *frame_filter; + uint16_t vdev_id = 0; + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) + return; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return; + } + + frame_filter = &vdev_priv->frame_filter; + + switch (event) { + case WDI_EVENT_PKT_CAPTURE_TX_DATA: + { + struct dp_tx_desc_s *desc = log_data; + + if (!frame_filter->data_tx_frame_filter) { + pkt_capture_vdev_put_ref(vdev); + return; + } + + if (frame_filter->data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { + pkt_capture_process_tx_data(soc, log_data, + vdev_id, status); + } else if (pkt_capture_is_frame_filter_set( + desc->nbuf, frame_filter, IEEE80211_FC1_DIR_TODS)) { + pkt_capture_process_tx_data(soc, log_data, + vdev_id, status); + } break; } case WDI_EVENT_PKT_CAPTURE_RX_DATA: { - if (!(pkt_capture_get_pktcap_mode_v2() & - PKT_CAPTURE_MODE_DATA_ONLY)) - return; + qdf_nbuf_t nbuf = (qdf_nbuf_t)log_data; + + if (!frame_filter->data_rx_frame_filter) { + /* + * Rx offload packets are delivered only to pkt capture + * component and not to stack so free them. + */ + if (status == RX_OFFLOAD_PKT) + qdf_nbuf_free(nbuf); + + pkt_capture_vdev_put_ref(vdev); + return; + } + + if (frame_filter->data_rx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { + pkt_capture_msdu_process_pkts(bssid, log_data, + vdev_id, soc, status); + } else if (pkt_capture_is_frame_filter_set( + nbuf, frame_filter, IEEE80211_FC1_DIR_FROMDS)) { + pkt_capture_msdu_process_pkts(bssid, log_data, + vdev_id, soc, status); + } else { + if (status == RX_OFFLOAD_PKT) + qdf_nbuf_free(nbuf); + } - pkt_capture_msdu_process_pkts(bssid, log_data, vdev_id, soc, - status); break; } @@ -338,19 +561,31 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, { qdf_nbuf_t nbuf = (qdf_nbuf_t)log_data; - if (!(pkt_capture_get_pktcap_mode_v2() & - PKT_CAPTURE_MODE_DATA_ONLY)) { + if (!frame_filter->data_rx_frame_filter) { /* * Rx offload packets are delivered only to pkt capture * component and not to stack so free them */ if (status == RX_OFFLOAD_PKT) qdf_nbuf_free(nbuf); + + pkt_capture_vdev_put_ref(vdev); return; } - pkt_capture_process_rx_data_no_peer(soc, vdev_id, bssid, status, - nbuf); + if (frame_filter->data_rx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { + pkt_capture_process_rx_data_no_peer(soc, vdev_id, bssid, + status, nbuf); + } else if (pkt_capture_is_frame_filter_set( + nbuf, frame_filter, IEEE80211_FC1_DIR_FROMDS)) { + pkt_capture_process_rx_data_no_peer(soc, vdev_id, bssid, + status, nbuf); + } else { + if (status == RX_OFFLOAD_PKT) + qdf_nbuf_free(nbuf); + } + break; } @@ -359,10 +594,13 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, struct htt_tx_offload_deliver_ind_hdr_t *offload_deliver_msg; bool is_pkt_during_roam = false; uint32_t freq = 0; + qdf_nbuf_t buf = log_data + + sizeof(struct htt_tx_offload_deliver_ind_hdr_t); - if (!(pkt_capture_get_pktcap_mode_v2() & - PKT_CAPTURE_MODE_DATA_ONLY)) + if (!frame_filter->data_tx_frame_filter) { + pkt_capture_vdev_put_ref(vdev); return; + } offload_deliver_msg = (struct htt_tx_offload_deliver_ind_hdr_t *)log_data; @@ -377,14 +615,28 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, vdev_id = offload_deliver_msg->vdev_id; } - pkt_capture_offload_deliver_indication_handler( - log_data, - vdev_id, bssid, soc); + if (frame_filter->data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { + pkt_capture_offload_deliver_indication_handler( + log_data, + vdev_id, bssid, soc); + } else if (pkt_capture_is_frame_filter_set( + buf, frame_filter, IEEE80211_FC1_DIR_TODS)) { + pkt_capture_offload_deliver_indication_handler( + log_data, + vdev_id, bssid, soc); + } + break; } + case WDI_EVENT_PKT_CAPTURE_PPDU_STATS: + pkt_capture_process_ppdu_stats(log_data); + break; + default: break; } + pkt_capture_vdev_put_ref(vdev); } #else @@ -420,12 +672,48 @@ enum pkt_capture_mode pkt_capture_get_mode(struct wlan_objmgr_psoc *psoc) return psoc_priv->cfg_param.pkt_capture_mode; } +bool pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev) +{ + struct pkt_capture_vdev_priv *vdev_priv; + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status = QDF_STATUS_SUCCESS; + enum pkt_capture_config config; + + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("failed to get vdev ref"); + return false; + } + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("vdev_priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return false; + } + + config = pkt_capture_get_pktcap_config(vdev); + + if (!(vdev_priv->frame_filter.mgmt_tx_frame_filter & + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL)) { + if (!(config & PACKET_CAPTURE_CONFIG_QOS_ENABLE)) { + pkt_capture_vdev_put_ref(vdev); + return false; + } + } + + pkt_capture_vdev_put_ref(vdev); + return true; +} + QDF_STATUS pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev, QDF_STATUS (*mon_cb)(void *, qdf_nbuf_t), void *context) { struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_psoc_priv *psoc_priv; struct wlan_objmgr_psoc *psoc; enum pkt_capture_mode mode; QDF_STATUS status; @@ -456,8 +744,14 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev, goto mgmt_rx_ops_fail; } - target_if_pkt_capture_register_tx_ops(&vdev_priv->tx_ops); - target_if_pkt_capture_register_rx_ops(&vdev_priv->rx_ops); + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); + return QDF_STATUS_E_INVAL; + } + + target_if_pkt_capture_register_tx_ops(&psoc_priv->tx_ops); + target_if_pkt_capture_register_rx_ops(&psoc_priv->rx_ops); pkt_capture_wdi_event_subscribe(psoc); pkt_capture_record_channel(vdev); @@ -572,7 +866,7 @@ void pkt_capture_set_pktcap_mode(struct wlan_objmgr_psoc *psoc, vdev_priv = pkt_capture_vdev_get_priv(vdev); if (vdev_priv) - vdev_priv->cb_ctx->pkt_capture_mode = mode; + vdev_priv->cfg_params.pkt_capture_mode = mode; else pkt_capture_err("vdev_priv is NULL"); @@ -604,12 +898,47 @@ pkt_capture_get_pktcap_mode(struct wlan_objmgr_psoc *psoc) if (!vdev_priv) pkt_capture_err("vdev_priv is NULL"); else - mode = vdev_priv->cb_ctx->pkt_capture_mode; + mode = vdev_priv->cfg_params.pkt_capture_mode; wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID); return mode; } +void pkt_capture_set_pktcap_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config) +{ + struct pkt_capture_vdev_priv *vdev_priv; + + if (!vdev) { + pkt_capture_err("vdev is NULL"); + return; + } + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (vdev_priv) + vdev_priv->cfg_params.pkt_capture_config = config; + else + pkt_capture_err("vdev_priv is NULL"); +} + +enum pkt_capture_config +pkt_capture_get_pktcap_config(struct wlan_objmgr_vdev *vdev) +{ + enum pkt_capture_config config = 0; + struct pkt_capture_vdev_priv *vdev_priv; + + if (!vdev) + return 0; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) + pkt_capture_err("vdev_priv is NULL"); + else + config = vdev_priv->cfg_params.pkt_capture_config; + + return config; +} + /** * pkt_capture_callback_ctx_create() - Create packet capture callback context * @vdev_priv: pointer to packet capture vdev priv obj @@ -763,6 +1092,9 @@ pkt_capture_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) pkt_capture_err("Failed to open mon thread"); goto open_mon_thread_fail; } + qdf_spinlock_create(&vdev_priv->lock_q); + qdf_list_create(&vdev_priv->ppdu_stats_q, PPDU_STATS_Q_MAX_SIZE); + return status; open_mon_thread_fail: @@ -784,6 +1116,8 @@ QDF_STATUS pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) { struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_ppdu_stats_q_node *stats_node; + qdf_list_node_t *node; QDF_STATUS status; if ((wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) || @@ -796,6 +1130,15 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) return QDF_STATUS_E_FAILURE; } + while (qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node) + == QDF_STATUS_SUCCESS) { + stats_node = qdf_container_of( + node, struct pkt_capture_ppdu_stats_q_node, node); + qdf_mem_free(stats_node); + } + qdf_list_destroy(&vdev_priv->ppdu_stats_q); + qdf_spinlock_destroy(&vdev_priv->lock_q); + status = wlan_objmgr_vdev_component_obj_detach( vdev, WLAN_UMAC_COMP_PKT_CAPTURE, @@ -806,6 +1149,7 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) pkt_capture_close_mon_thread(vdev_priv->mon_ctx); pkt_capture_mon_context_destroy(vdev_priv); pkt_capture_callback_ctx_destroy(vdev_priv); + qdf_mem_free(vdev_priv); gp_pkt_capture_vdev = NULL; return status; @@ -886,3 +1230,172 @@ void pkt_capture_record_channel(struct wlan_objmgr_vdev *vdev) cdp_txrx_set_pdev_param(soc, wlan_objmgr_pdev_get_pdev_id(pdev), CDP_MONITOR_FREQUENCY, val); } + +QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, + struct wlan_objmgr_vdev *vdev) +{ + struct pkt_capture_vdev_priv *vdev_priv; + struct wlan_objmgr_psoc *psoc; + enum pkt_capture_mode mode = PACKET_CAPTURE_MODE_DISABLE; + ol_txrx_soc_handle soc; + QDF_STATUS status; + enum pkt_capture_config config = 0; + bool check_enable_beacon = 0, send_bcn = 0; + struct vdev_mlme_obj *vdev_mlme; + uint32_t bcn_interval, nth_beacon_value; + + if (!vdev) { + pkt_capture_err("vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("vdev_priv is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pkt_capture_err("psoc is NULL"); + return QDF_STATUS_E_FAILURE; + } + + soc = cds_get_context(QDF_MODULE_ID_SOC); + if (!soc) { + pkt_capture_err("Invalid soc"); + return QDF_STATUS_E_FAILURE; + } + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE)) + vdev_priv->frame_filter.data_tx_frame_filter = + frame_filter.data_tx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE)) + vdev_priv->frame_filter.data_rx_frame_filter = + frame_filter.data_rx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE)) + vdev_priv->frame_filter.mgmt_tx_frame_filter = + frame_filter.mgmt_tx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE)) + vdev_priv->frame_filter.mgmt_rx_frame_filter = + frame_filter.mgmt_rx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE)) + vdev_priv->frame_filter.ctrl_tx_frame_filter = + frame_filter.ctrl_tx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE)) + vdev_priv->frame_filter.ctrl_rx_frame_filter = + frame_filter.ctrl_rx_frame_filter; + + if (frame_filter.vendor_attr_to_set & + BIT(PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL)) { + if (frame_filter.connected_beacon_interval != + vdev_priv->frame_filter.connected_beacon_interval) { + vdev_priv->frame_filter.connected_beacon_interval = + frame_filter.connected_beacon_interval; + send_bcn = 1; + } + } + + if (vdev_priv->frame_filter.mgmt_tx_frame_filter) + mode |= PACKET_CAPTURE_MODE_MGMT_ONLY; + + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL) { + mode |= PACKET_CAPTURE_MODE_MGMT_ONLY; + config |= PACKET_CAPTURE_CONFIG_BEACON_ENABLE; + config |= PACKET_CAPTURE_CONFIG_OFF_CHANNEL_BEACON_ENABLE; + } else { + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_NO_BEACON) { + mode |= PACKET_CAPTURE_MODE_MGMT_ONLY; + config |= PACKET_CAPTURE_CONFIG_NO_BEACON_ENABLE; + } else { + check_enable_beacon = 1; + } + } + + if (check_enable_beacon) { + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_BEACON) + config |= PACKET_CAPTURE_CONFIG_BEACON_ENABLE; + + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_SCAN_BEACON) + config |= + PACKET_CAPTURE_CONFIG_OFF_CHANNEL_BEACON_ENABLE; + } + + if (vdev_priv->frame_filter.data_tx_frame_filter || + vdev_priv->frame_filter.data_rx_frame_filter) + mode |= PACKET_CAPTURE_MODE_DATA_ONLY; + + if (mode != pkt_capture_get_pktcap_mode(psoc)) { + status = tgt_pkt_capture_send_mode(vdev, mode); + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("Unable to send packet capture mode"); + return status; + } + + if (mode & PACKET_CAPTURE_MODE_DATA_ONLY) + cdp_set_pkt_capture_mode(soc, true); + } + + if (vdev_priv->frame_filter.ctrl_tx_frame_filter || + vdev_priv->frame_filter.ctrl_rx_frame_filter) + config |= PACKET_CAPTURE_CONFIG_TRIGGER_ENABLE; + + if ((vdev_priv->frame_filter.data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) || + (vdev_priv->frame_filter.data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_QOS_NULL)) + config |= PACKET_CAPTURE_CONFIG_QOS_ENABLE; + + if (config != pkt_capture_get_pktcap_config(vdev)) { + status = tgt_pkt_capture_send_config(vdev, config); + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("packet capture send config failed"); + return status; + } + } + + if (send_bcn) { + vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj( + vdev, + WLAN_UMAC_COMP_MLME); + + if (!vdev_mlme) + return QDF_STATUS_E_FAILURE; + + wlan_util_vdev_mlme_get_param(vdev_mlme, + WLAN_MLME_CFG_BEACON_INTERVAL, + &bcn_interval); + + if (bcn_interval) { + nth_beacon_value = + vdev_priv-> + frame_filter.connected_beacon_interval / + bcn_interval; + + status = tgt_pkt_capture_send_beacon_interval( + vdev, + nth_beacon_value); + + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("send beacon interval fail"); + return status; + } + } + } + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c index ec926368edcc..1fda09c0e0f5 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -329,22 +330,49 @@ void pkt_capture_mgmt_tx(struct wlan_objmgr_pdev *pdev, uint16_t chan_freq, uint8_t preamble_type) { + struct mgmt_offload_event_params params = {0}; + tpSirMacFrameCtl pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf)); + struct pkt_capture_vdev_priv *vdev_priv; + struct wlan_objmgr_vdev *vdev; qdf_nbuf_t wbuf; int nbuf_len; - struct mgmt_offload_event_params params = {0}; + QDF_STATUS status = QDF_STATUS_SUCCESS; if (!pdev) { pkt_capture_err("pdev is NULL"); return; } + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("failed to get vdev ref"); + return; + } + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("packet capture vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return; + } + + if (pfc->type == IEEE80211_FC0_TYPE_MGT && + !(vdev_priv->frame_filter.mgmt_tx_frame_filter & + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL)) + goto exit; + + if (pfc->type == IEEE80211_FC0_TYPE_CTL && + !vdev_priv->frame_filter.ctrl_tx_frame_filter) + goto exit; + nbuf_len = qdf_nbuf_len(nbuf); wbuf = qdf_nbuf_alloc(NULL, roundup(nbuf_len + RESERVE_BYTES, 4), RESERVE_BYTES, 4, false); if (!wbuf) { pkt_capture_err("Failed to allocate wbuf for mgmt len(%u)", nbuf_len); - return; + goto exit; } qdf_nbuf_put_tail(wbuf, nbuf_len); @@ -372,6 +400,8 @@ void pkt_capture_mgmt_tx(struct wlan_objmgr_pdev *pdev, if (QDF_STATUS_SUCCESS != pkt_capture_process_mgmt_tx_data(pdev, ¶ms, wbuf, 0xFF)) qdf_nbuf_free(wbuf); +exit: + pkt_capture_vdev_put_ref(vdev); } void @@ -380,17 +410,45 @@ pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev, uint32_t status, struct mgmt_offload_event_params *params) { + struct pkt_capture_vdev_priv *vdev_priv; + struct wlan_objmgr_vdev *vdev; + tpSirMacFrameCtl pfc; qdf_nbuf_t wbuf, nbuf; int nbuf_len; + QDF_STATUS ret = QDF_STATUS_SUCCESS; if (!pdev) { pkt_capture_err("pdev is NULL"); return; } + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) { + pkt_capture_err("failed to get vdev ref"); + return; + } + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("packet capture vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return; + } + nbuf = mgmt_txrx_get_nbuf(pdev, desc_id); if (!nbuf) - return; + goto exit; + + pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf)); + if (pfc->type == IEEE80211_FC0_TYPE_MGT && + !(vdev_priv->frame_filter.mgmt_tx_frame_filter & + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL)) + goto exit; + + if (pfc->type == IEEE80211_FC0_TYPE_CTL && + !vdev_priv->frame_filter.ctrl_tx_frame_filter) + goto exit; nbuf_len = qdf_nbuf_len(nbuf); wbuf = qdf_nbuf_alloc(NULL, roundup(nbuf_len + RESERVE_BYTES, 4), @@ -398,7 +456,7 @@ pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev, if (!wbuf) { pkt_capture_err("Failed to allocate wbuf for mgmt len(%u)", nbuf_len); - return; + goto exit; } qdf_nbuf_put_tail(wbuf, nbuf_len); @@ -409,8 +467,64 @@ pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev, pdev, params, wbuf, pkt_capture_mgmt_status_map(status))) qdf_nbuf_free(wbuf); + +exit: + pkt_capture_vdev_put_ref(vdev); } +/** + * pkt_capture_is_beacon_forward_enable() - API to check whether particular + * beacon needs to be forwarded on mon interface based on vendor command + * @vdev: vdev object + * @wbuf: netbuf + * + * Return: bool + */ +static bool +pkt_capture_is_beacon_forward_enable(struct wlan_objmgr_vdev *vdev, + qdf_nbuf_t wbuf) +{ + struct pkt_capture_vdev_priv *vdev_priv; + struct qdf_mac_addr connected_bssid = {0}; + tpSirMacMgmtHdr mac_hdr; + bool my_beacon = false; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("packet capture vdev priv is NULL"); + return false; + } + + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_NO_BEACON) + return false; + + mac_hdr = (tpSirMacMgmtHdr)(qdf_nbuf_data(wbuf)); + wlan_vdev_get_bss_peer_mac(vdev, &connected_bssid); + + if (qdf_is_macaddr_equal((struct qdf_mac_addr *)mac_hdr->bssId, + &connected_bssid)) + my_beacon = true; + + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_BEACON && !my_beacon) + return false; + + if (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_SCAN_BEACON && my_beacon) + return false; + + return true; +} + +#ifdef DP_MON_RSSI_IN_DBM +#define PKT_CAPTURE_FILL_RSSI(rx_params) \ +((rx_params)->snr + NORMALIZED_TO_NOISE_FLOOR) +#else +#define PKT_CAPTURE_FILL_RSSI(rx_status) \ +((rx_params)->snr) +#endif + /** * process_pktcapture_mgmt_rx_data_cb() - process management rx packets * @rx_params: mgmt rx event params @@ -426,17 +540,54 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, enum mgmt_frame_type frm_type) { struct mon_rx_status txrx_status = {0}; + struct pkt_capture_vdev_priv *vdev_priv; struct ieee80211_frame *wh; tpSirMacFrameCtl pfc; qdf_nbuf_t nbuf; int buf_len; struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + QDF_STATUS status = QDF_STATUS_SUCCESS; - if (!(pkt_capture_get_pktcap_mode(psoc) & PKT_CAPTURE_MODE_MGMT_ONLY)) { + vdev = pkt_capture_get_vdev(); + status = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pkt_capture_err("failed to get vdev ref"); qdf_nbuf_free(wbuf); return QDF_STATUS_E_FAILURE; } + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("packet capture vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + qdf_nbuf_free(wbuf); + return QDF_STATUS_E_FAILURE; + } + + pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(wbuf)); + + if (pfc->type == SIR_MAC_CTRL_FRAME && + !vdev_priv->frame_filter.ctrl_rx_frame_filter) + goto exit; + + if (pfc->type == SIR_MAC_MGMT_FRAME && + !vdev_priv->frame_filter.mgmt_rx_frame_filter) + goto exit; + + if (pfc->type == SIR_MAC_MGMT_FRAME) { + if (pfc->subType == SIR_MAC_MGMT_BEACON) { + if (!pkt_capture_is_beacon_forward_enable(vdev, wbuf)) + goto exit; + } else { + if (!((vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL) || + (vdev_priv->frame_filter.mgmt_rx_frame_filter & + PKT_CAPTURE_MGMT_CONNECT_NO_BEACON))) + goto exit; + } + } + buf_len = qdf_nbuf_len(wbuf); nbuf = qdf_nbuf_alloc(NULL, roundup( buf_len + RESERVE_BYTES, 4), @@ -454,14 +605,13 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf)); wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf); + pdev = wlan_vdev_get_pdev(vdev); + pkt_capture_vdev_put_ref(vdev); + if ((pfc->type == IEEE80211_FC0_TYPE_MGT) && (pfc->subType == SIR_MAC_MGMT_DISASSOC || pfc->subType == SIR_MAC_MGMT_DEAUTH || pfc->subType == SIR_MAC_MGMT_ACTION)) { - struct wlan_objmgr_pdev *pdev; - - vdev = pkt_capture_get_vdev(); - pdev = wlan_vdev_get_pdev(vdev); if (pkt_capture_is_rmf_enabled(pdev, psoc, wh->i_addr1)) { QDF_STATUS status; @@ -478,13 +628,13 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, /* rx_params->rate is in Kbps, convert into Mbps */ txrx_status.rate = (rx_params->rate / 1000); txrx_status.ant_signal_db = rx_params->snr; - txrx_status.rssi_comb = rx_params->snr; txrx_status.chan_noise_floor = NORMALIZED_TO_NOISE_FLOOR; + txrx_status.rssi_comb = PKT_CAPTURE_FILL_RSSI(rx_params); txrx_status.nr_ant = 1; txrx_status.rtap_flags |= ((txrx_status.rate == 6 /* Mbps */) ? BIT(1) : 0); - if (rx_params->phy_mode != WLAN_PHYMODE_11B) + if (rx_params->phy_mode != PKTCAPTURE_RATECODE_CCK) txrx_status.ofdm_flag = 1; else txrx_status.cck_flag = 1; @@ -501,6 +651,10 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc, qdf_nbuf_free(nbuf); return QDF_STATUS_SUCCESS; +exit: + pkt_capture_vdev_put_ref(vdev); + qdf_nbuf_free(wbuf); + return QDF_STATUS_SUCCESS; } QDF_STATUS pkt_capture_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc, diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c index 3f4f89f5b4e2..599edf22d261 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c @@ -21,7 +21,6 @@ */ #include "wlan_pkt_capture_mon_thread.h" -#include #include "cds_ieee80211_common.h" #include "wlan_mgmt_txrx_utils_api.h" #include "cdp_txrx_ctrl.h" diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_api.h b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_api.h new file mode 100644 index 000000000000..278efe72332c --- /dev/null +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_api.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Contains pkt_capture public API declarations + */ + +#ifndef _WLAN_PKT_CAPTURE_API_H_ +#define _WLAN_PKT_CAPTURE_API_H_ + +#include "wlan_pkt_capture_objmgr.h" + +/** + * wlan_pkt_capture_is_tx_mgmt_enable() - Check if tx mgmt frames filter + * is enabled + * @pdev: pointer to pdev + * + * Return: bool + */ +bool wlan_pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev); +#endif /* _WLAN_PKT_CAPTURE_API_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_public_structs.h b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_public_structs.h index 4fdad87bd43f..946d812f4eaf 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_public_structs.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_public_structs.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -19,34 +20,39 @@ #ifndef _WLAN_PKT_CAPTURE_PUBLIC_STRUCTS_H_ #define _WLAN_PKT_CAPTURE_PUBLIC_STRUCTS_H_ +#define PACKET_CAPTURE_DATA_MAX_FILTER BIT(18) +#define PACKET_CAPTURE_MGMT_MAX_FILTER BIT(5) +#define PACKET_CAPTURE_CTRL_MAX_FILTER BIT(3) + /** * enum pkt_capture_mode - packet capture modes * @PACKET_CAPTURE_MODE_DISABLE: packet capture mode disable * @PACKET_CAPTURE_MODE_MGMT_ONLY: capture mgmt packets only * @PACKET_CAPTURE_MODE_DATA_ONLY: capture data packets only - * @PACKET_CAPTURE_MODE_DATA_MGMT: capture both data and mgmt packets */ enum pkt_capture_mode { PACKET_CAPTURE_MODE_DISABLE = 0, - PACKET_CAPTURE_MODE_MGMT_ONLY, - PACKET_CAPTURE_MODE_DATA_ONLY, - PACKET_CAPTURE_MODE_DATA_MGMT, + PACKET_CAPTURE_MODE_MGMT_ONLY = BIT(0), + PACKET_CAPTURE_MODE_DATA_ONLY = BIT(1), }; /** - * enum pkt_capture_trigger_qos_config - packet capture config - * @PACKET_CAPTURE_CONFIG_TRIGGER_QOS_DISABLE: disable capture for trigger and - * qos frames + * enum pkt_capture_config - packet capture config * @PACKET_CAPTURE_CONFIG_TRIGGER_ENABLE: enable capture for trigger frames only * @PACKET_CAPTURE_CONFIG_QOS_ENABLE: enable capture for qos frames only - * @PACKET_CAPTURE_CONFIG_TRIGGER_QOS_ENABLE: enable capture for both trigger - * and qos frames + * @PACKET_CAPTURE_CONFIG_CONNECT_NO_BEACON_ENABLE: drop all beacons, when + * device in connected state + * @PACKET_CAPTURE_CONFIG_CONNECT_BEACON_ENABLE: enable only connected BSSID + * beacons, when device in connected state + * @PACKET_CAPTURE_CONFIG_CONNECT_OFF_CHANNEL_BEACON_ENABLE: enable off channel + * beacons, when device in connected state */ -enum pkt_capture_trigger_qos_config { - PACKET_CAPTURE_CONFIG_TRIGGER_QOS_DISABLE = 0, - PACKET_CAPTURE_CONFIG_TRIGGER_ENABLE, - PACKET_CAPTURE_CONFIG_QOS_ENABLE, - PACKET_CAPTURE_CONFIG_TRIGGER_QOS_ENABLE, +enum pkt_capture_config { + PACKET_CAPTURE_CONFIG_TRIGGER_ENABLE = BIT(0), + PACKET_CAPTURE_CONFIG_QOS_ENABLE = BIT(1), + PACKET_CAPTURE_CONFIG_BEACON_ENABLE = BIT(2), + PACKET_CAPTURE_CONFIG_OFF_CHANNEL_BEACON_ENABLE = BIT(3), + PACKET_CAPTURE_CONFIG_NO_BEACON_ENABLE = BIT(4), }; /** @@ -102,7 +108,11 @@ struct wlan_pkt_capture_tx_ops { QDF_STATUS (*pkt_capture_send_config) (struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, - enum pkt_capture_trigger_qos_config config); + enum pkt_capture_config config); + QDF_STATUS (*pkt_capture_send_beacon_interval) + (struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint32_t nth_value); }; /** @@ -124,4 +134,124 @@ struct wlan_pkt_capture_rx_ops { (struct wlan_objmgr_psoc *psoc); }; +/** + * pkt_capture_data_frame_type - Represent the various + * data types to be filtered in packet capture. + */ +enum pkt_capture_data_frame_type { + PKT_CAPTURE_DATA_FRAME_TYPE_ALL = BIT(0), + /* valid only if PKT_CAPTURE_DATA_DATA_FRAME_TYPE_ALL is not set */ + PKT_CAPTURE_DATA_FRAME_TYPE_ARP = BIT(1), + PKT_CAPTURE_DATA_FRAME_TYPE_DHCPV4 = BIT(2), + PKT_CAPTURE_DATA_FRAME_TYPE_DHCPV6 = BIT(3), + PKT_CAPTURE_DATA_FRAME_TYPE_EAPOL = BIT(4), + PKT_CAPTURE_DATA_FRAME_TYPE_DNSV4 = BIT(5), + PKT_CAPTURE_DATA_FRAME_TYPE_DNSV6 = BIT(6), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_SYN = BIT(7), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_FIN = BIT(9), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_FINACK = BIT(10), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_ACK = BIT(11), + PKT_CAPTURE_DATA_FRAME_TYPE_TCP_RST = BIT(12), + PKT_CAPTURE_DATA_FRAME_TYPE_ICMPV4 = BIT(13), + PKT_CAPTURE_DATA_FRAME_TYPE_ICMPV6 = BIT(14), + PKT_CAPTURE_DATA_FRAME_TYPE_RTP = BIT(15), + PKT_CAPTURE_DATA_FRAME_TYPE_SIP = BIT(16), + PKT_CAPTURE_DATA_FRAME_QOS_NULL = BIT(17), +}; + +/** + * pkt_capture_mgmt_frame_type - Represent the various + * mgmt types to be sent over the monitor interface. + * @PKT_CAPTURE_MGMT_FRAME_TYPE_ALL: All the MGMT Frames. + * @PKT_CAPTURE_MGMT_CONNECT_NO_BEACON: All the MGMT Frames + * except the Beacons. Valid only in the Connect state. + * @PKT_CAPTURE_MGMT_CONNECT_BEACON: Only the connected + * BSSID Beacons. Valid only in the Connect state. + * @PKT_CAPTURE_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents + * the Beacons obtained during the scan (off channel and connected channel) + * when in connected state. + */ + +enum pkt_capture_mgmt_frame_type { + PKT_CAPTURE_MGMT_FRAME_TYPE_ALL = BIT(0), + /* valid only if PKT_CAPTURE_MGMT_FRAME_TYPE_ALL is not set */ + PKT_CAPTURE_MGMT_CONNECT_NO_BEACON = BIT(1), + PKT_CAPTURE_MGMT_CONNECT_BEACON = BIT(2), + PKT_CAPTURE_MGMT_CONNECT_SCAN_BEACON = BIT(3), +}; + +/** + * pkt_capture_ctrl_frame_type - Represent the various + * ctrl types to be sent over the monitor interface. + * @PKT_CAPTURE_CTRL_FRAME_TYPE_ALL: All the ctrl Frames. + * @PKT_CAPTURE_CTRL_TRIGGER_FRAME: Trigger Frame. + */ +enum pkt_capture_ctrl_frame_type { + PKT_CAPTURE_CTRL_FRAME_TYPE_ALL = BIT(0), + /* valid only if PKT_CAPTURE_CTRL_FRAME_TYPE_ALL is not set */ + PKT_CAPTURE_CTRL_TRIGGER_FRAME = BIT(1), +}; + +/** + * enum pkt_capture_attr_set_monitor_mode - Used by the + * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the + * monitor mode. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum pkt_capture_data_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum pkt_capture_data_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum pkt_capture_mgmt_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum pkt_capture_mgmt_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum pkt_capture_ctrl_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum pkt_capture_ctrl_frame_type. + * + * @PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32 attribute, + * An interval only for the connected beacon interval, which expects that the + * connected BSSID's beacons shall be sent on the monitor interface only on this + * specific interval. + */ +enum pkt_capture_attr_set_monitor_mode { + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_INVALID = 0, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7, + + /* keep last */ + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_AFTER_LAST, + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_MAX = + PKT_CAPTURE_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1, + +}; + +struct pkt_capture_frame_filter { + enum pkt_capture_data_frame_type data_tx_frame_filter; + enum pkt_capture_data_frame_type data_rx_frame_filter; + enum pkt_capture_mgmt_frame_type mgmt_tx_frame_filter; + enum pkt_capture_mgmt_frame_type mgmt_rx_frame_filter; + enum pkt_capture_ctrl_frame_type ctrl_tx_frame_filter; + enum pkt_capture_ctrl_frame_type ctrl_rx_frame_filter; + uint32_t connected_beacon_interval; + uint8_t vendor_attr_to_set; +}; #endif /* _WLAN_PKT_CAPTURE_PUBLIC_STRUCTS_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_tgt_api.h b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_tgt_api.h index e4c1c3da7fc1..fc26e89b85b8 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_tgt_api.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_tgt_api.h @@ -53,7 +53,17 @@ QDF_STATUS tgt_pkt_capture_send_mode(struct wlan_objmgr_vdev *vdev, enum pkt_capture_mode mode); -#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 +/** + * tgt_pkt_capture_send_beacon_interval() - send beacon interval to firmware + * @vdev: pointer to vdev object + * @nth_value: Beacon report period + * + * Return: QDF_STATUS + */ +QDF_STATUS +tgt_pkt_capture_send_beacon_interval(struct wlan_objmgr_vdev *vdev, + uint32_t nth_value); + /** * tgt_pkt_capture_send_config() - send packet capture config to firmware * @vdev: pointer to vdev object @@ -63,8 +73,9 @@ tgt_pkt_capture_send_mode(struct wlan_objmgr_vdev *vdev, */ QDF_STATUS tgt_pkt_capture_send_config(struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config); + enum pkt_capture_config config); +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 /** * tgt_pkt_capture_smu_event() - Receive smart monitor event from firmware * @psoc: pointer to psoc diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_ucfg_api.h b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_ucfg_api.h index 10147b580332..70571466e8e1 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_ucfg_api.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/inc/wlan_pkt_capture_ucfg_api.h @@ -120,6 +120,25 @@ void ucfg_pkt_capture_set_pktcap_mode(struct wlan_objmgr_psoc *psoc, enum pkt_capture_mode ucfg_pkt_capture_get_pktcap_mode(struct wlan_objmgr_psoc *psoc); +/** + * ucfg_pkt_capturee_set_pktcap_config - Set packet capture config + * @vdev: pointer to vdev object + * @config: config to be set + * + * Return: None + */ +void ucfg_pkt_capture_set_pktcap_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config); + +/** + * ucfg_pkt_capture_get_pktcap_config - Get packet capture config + * @vdev: pointer to vdev object + * + * Return: config value + */ +enum pkt_capture_config +ucfg_pkt_capture_get_pktcap_config(struct wlan_objmgr_vdev *vdev); + /** * ucfg_pkt_capture_process_mgmt_tx_data() - process management tx packets * @pdev: pointer to pdev object @@ -267,27 +286,17 @@ int ucfg_pkt_capture_register_wma_callbacks(struct wlan_objmgr_psoc *psoc, struct pkt_capture_callbacks *cb_obj); -#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 /** - * ucfg_pkt_capture_send_config - send packet capture config - * @vdev: pointer to vdev object - * @config: packet capture config + * ucfg_pkt_capture_set_filter ucfg API to set frame filter + * @frame_filter: pkt capture frame filter data + * @vdev: pointer to vdev * - * Return: None + * Return: QDF_STATUS */ -QDF_STATUS ucfg_pkt_capture_send_config - (struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config); -#else -static inline -QDF_STATUS ucfg_pkt_capture_send_config - (struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config) -{ - return QDF_STATUS_SUCCESS; -} +QDF_STATUS +ucfg_pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, + struct wlan_objmgr_vdev *vdev); -#endif #else static inline QDF_STATUS ucfg_pkt_capture_init(void) @@ -343,6 +352,18 @@ ucfg_pkt_capture_get_pktcap_mode(struct wlan_objmgr_psoc *psoc) return PACKET_CAPTURE_MODE_DISABLE; } +static inline +void ucfg_pkt_capture_set_pktcap_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config) +{ +} + +static inline enum pkt_capture_config +ucfg_pkt_capture_get_pktcap_config(struct wlan_objmgr_vdev *vdev) +{ + return 0; +} + static inline QDF_STATUS ucfg_pkt_capture_process_mgmt_tx_data( struct mgmt_offload_event_params *params, @@ -418,12 +439,12 @@ ucfg_pkt_capture_record_channel(struct wlan_objmgr_vdev *vdev) { } -static inline -QDF_STATUS ucfg_pkt_capture_send_config - (struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config) +static inline QDF_STATUS +ucfg_pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, + struct wlan_objmgr_vdev *vdev) { return QDF_STATUS_SUCCESS; } + #endif /* WLAN_FEATURE_PKT_CAPTURE */ #endif /* _WLAN_PKT_CAPTURE_UCFG_API_H_ */ diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_api.c b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_api.c new file mode 100644 index 000000000000..9f6dc260002a --- /dev/null +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_api.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This file contains pkt_capture public API's exposed. + */ + +#include "wlan_pkt_capture_api.h" +#include "wlan_pkt_capture_main.h" + +bool wlan_pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev) +{ + return pkt_capture_is_tx_mgmt_enable(pdev); +} diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_tgt_api.c b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_tgt_api.c index 0d069cd0cccd..859fba623c13 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_tgt_api.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_tgt_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 above @@ -24,7 +25,7 @@ QDF_STATUS tgt_pkt_capture_register_ev_handler(struct wlan_objmgr_vdev *vdev) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_psoc_priv *psoc_priv; struct wlan_pkt_capture_rx_ops *rx_ops; struct wlan_objmgr_psoc *psoc; @@ -34,13 +35,13 @@ tgt_pkt_capture_register_ev_handler(struct wlan_objmgr_vdev *vdev) return status; } - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (!vdev_priv) { - pkt_capture_err("vdev priv is NULL"); + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); return status; } - rx_ops = &vdev_priv->rx_ops; + rx_ops = &psoc_priv->rx_ops; if (!rx_ops->pkt_capture_register_ev_handlers) return status; @@ -60,7 +61,7 @@ QDF_STATUS tgt_pkt_capture_unregister_ev_handler(struct wlan_objmgr_vdev *vdev) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_psoc_priv *psoc_priv; struct wlan_pkt_capture_rx_ops *rx_ops; struct wlan_objmgr_psoc *psoc; @@ -70,13 +71,13 @@ tgt_pkt_capture_unregister_ev_handler(struct wlan_objmgr_vdev *vdev) return status; } - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (!vdev_priv) { - pkt_capture_err("vdev priv is NULL"); + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); return status; } - rx_ops = &vdev_priv->rx_ops; + rx_ops = &psoc_priv->rx_ops; if (!rx_ops->pkt_capture_unregister_ev_handlers) return status; @@ -97,7 +98,7 @@ tgt_pkt_capture_send_mode(struct wlan_objmgr_vdev *vdev, enum pkt_capture_mode mode) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_psoc_priv *psoc_priv; struct wlan_pkt_capture_tx_ops *tx_ops; struct wlan_objmgr_psoc *psoc; @@ -107,13 +108,13 @@ tgt_pkt_capture_send_mode(struct wlan_objmgr_vdev *vdev, return status; } - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (!vdev_priv) { - pkt_capture_err("vdev priv is NULL"); + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); return status; } - tx_ops = &vdev_priv->tx_ops; + tx_ops = &psoc_priv->tx_ops; if (!tx_ops->pkt_capture_send_mode) return status; @@ -126,13 +127,12 @@ tgt_pkt_capture_send_mode(struct wlan_objmgr_vdev *vdev, return status; } -#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 QDF_STATUS -tgt_pkt_capture_send_config(struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config) +tgt_pkt_capture_send_beacon_interval(struct wlan_objmgr_vdev *vdev, + uint32_t nth_value) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_psoc_priv *psoc_priv; struct wlan_pkt_capture_tx_ops *tx_ops; struct wlan_objmgr_psoc *psoc; @@ -142,13 +142,49 @@ tgt_pkt_capture_send_config(struct wlan_objmgr_vdev *vdev, return status; } - vdev_priv = pkt_capture_vdev_get_priv(vdev); - if (!vdev_priv) { - pkt_capture_err("vdev priv is NULL"); + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); return status; } - tx_ops = &vdev_priv->tx_ops; + tx_ops = &psoc_priv->tx_ops; + + if (!tx_ops->pkt_capture_send_beacon_interval) + return status; + + status = tx_ops->pkt_capture_send_beacon_interval + (psoc, + wlan_vdev_get_id(vdev), + nth_value); + if (QDF_IS_STATUS_ERROR(status)) + pkt_capture_err("Unable to send beacon interval to fw"); + + return status; +} + +QDF_STATUS +tgt_pkt_capture_send_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct pkt_psoc_priv *psoc_priv; + struct wlan_pkt_capture_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pkt_capture_err("psoc is NULL"); + return status; + } + + psoc_priv = pkt_capture_psoc_get_priv(psoc); + if (!psoc_priv) { + pkt_capture_err("psoc_priv is NULL"); + return status; + } + + tx_ops = &psoc_priv->tx_ops; if (!tx_ops->pkt_capture_send_config) return status; @@ -161,6 +197,7 @@ tgt_pkt_capture_send_config(struct wlan_objmgr_vdev *vdev, return status; } +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 QDF_STATUS tgt_pkt_capture_smu_event(struct wlan_objmgr_psoc *psoc, struct smu_event_params *param) diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_ucfg_api.c b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_ucfg_api.c index 97179fceeaa0..38cb4e212aae 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/dispatcher/src/wlan_pkt_capture_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -86,6 +87,31 @@ ucfg_pkt_capture_get_pktcap_mode(struct wlan_objmgr_psoc *psoc) return pkt_capture_get_pktcap_mode(psoc); } +/** + * ucfg_pkt_capture_set_pktcap_config - Set packet capture config + * @vdev: pointer to vdev object + * @config: config to be set + * + * Return: None + */ +void ucfg_pkt_capture_set_pktcap_config(struct wlan_objmgr_vdev *vdev, + enum pkt_capture_config config) +{ + pkt_capture_set_pktcap_config(vdev, config); +} + +/** + * ucfg_pkt_capture_get_pktcap_config - Get packet capture config + * @vdev: pointer to vdev object + * + * Return: config value + */ +enum pkt_capture_config +ucfg_pkt_capture_get_pktcap_config(struct wlan_objmgr_vdev *vdev) +{ + return pkt_capture_get_pktcap_config(vdev); +} + /** * ucfg_pkt_capture_init() - Packet capture component initialization. * @@ -207,6 +233,7 @@ ucfg_pkt_capture_process_mgmt_tx_data(struct wlan_objmgr_pdev *pdev, return pkt_capture_process_mgmt_tx_data( pdev, params, nbuf, pkt_capture_mgmt_status_map(status)); + } void @@ -309,11 +336,9 @@ ucfg_pkt_capture_register_wma_callbacks(struct wlan_objmgr_psoc *psoc, return 0; } -#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 -QDF_STATUS ucfg_pkt_capture_send_config - (struct wlan_objmgr_vdev *vdev, - enum pkt_capture_trigger_qos_config config) +QDF_STATUS +ucfg_pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, + struct wlan_objmgr_vdev *vdev) { - return tgt_pkt_capture_send_config(vdev, config); + return pkt_capture_set_filter(frame_filter, vdev); } -#endif diff --git a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_arp.c b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_arp.c index c40e4a2e8fe5..7f8594819a3a 100644 --- a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_arp.c +++ b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_arp.c @@ -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 @@ -230,13 +231,13 @@ QDF_STATUS pmo_core_arp_check_offload(struct wlan_objmgr_psoc *psoc, vdev_ctx = pmo_vdev_get_priv(vdev); psoc_ctx = vdev_ctx->pmo_psoc_ctx; + active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; - if (trigger == pmo_apps_suspend || trigger == pmo_apps_resume) { - active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; - + if (trigger == pmo_apps_suspend) { qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); - is_applied_cond = vdev_ctx->vdev_arp_req.enable && - vdev_ctx->vdev_arp_req.is_offload_applied; + is_applied_cond = + vdev_ctx->vdev_arp_req.enable == PMO_OFFLOAD_ENABLE && + vdev_ctx->vdev_arp_req.is_offload_applied; qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); if (active_offload_cond && is_applied_cond) { @@ -244,6 +245,18 @@ QDF_STATUS pmo_core_arp_check_offload(struct wlan_objmgr_psoc *psoc, wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); return QDF_STATUS_E_INVAL; } + } else if (trigger == pmo_apps_resume) { + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + is_applied_cond = + vdev_ctx->vdev_arp_req.enable == PMO_OFFLOAD_DISABLE && + !vdev_ctx->vdev_arp_req.is_offload_applied; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (active_offload_cond && is_applied_cond) { + pmo_debug("active offload is enabled and offload already disabled"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); + return QDF_STATUS_E_INVAL; + } } wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); out: diff --git a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_ns.c b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_ns.c index eaf58ff33413..4325450f40ed 100644 --- a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_ns.c +++ b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_ns.c @@ -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 @@ -270,12 +271,13 @@ QDF_STATUS pmo_core_ns_check_offload(struct wlan_objmgr_psoc *psoc, vdev_ctx = pmo_vdev_get_priv(vdev); psoc_ctx = vdev_ctx->pmo_psoc_ctx; - if (trigger == pmo_apps_suspend || trigger == pmo_apps_resume) { + if (trigger == pmo_apps_suspend) { active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); - is_applied_cond = vdev_ctx->vdev_ns_req.enable && - vdev_ctx->vdev_ns_req.is_offload_applied; + is_applied_cond = + vdev_ctx->vdev_ns_req.enable == PMO_OFFLOAD_ENABLE && + vdev_ctx->vdev_ns_req.is_offload_applied; qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); if (active_offload_cond && is_applied_cond) { @@ -283,6 +285,20 @@ QDF_STATUS pmo_core_ns_check_offload(struct wlan_objmgr_psoc *psoc, wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); return QDF_STATUS_E_INVAL; } + } else if (trigger == pmo_apps_resume) { + active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + is_applied_cond = + vdev_ctx->vdev_ns_req.enable == PMO_OFFLOAD_DISABLE && + !vdev_ctx->vdev_ns_req.is_offload_applied; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (active_offload_cond && is_applied_cond) { + pmo_debug("active offload is enabled and offload already disabled"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); + return QDF_STATUS_E_INVAL; + } } wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); out: diff --git a/drivers/staging/qcacld-3.0/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c b/drivers/staging/qcacld-3.0/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c index c8c885f24a2f..f2f046b22c48 100644 --- a/drivers/staging/qcacld-3.0/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c +++ b/drivers/staging/qcacld-3.0/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c @@ -26,6 +26,7 @@ #include "wlan_mlme_api.h" #include "wlan_crypto_global_api.h" #include "wlan_mlme_main.h" +#include "wlan_cm_roam_api.h" static struct wmi_unified *target_if_cm_roam_get_wmi_handle_from_vdev(struct wlan_objmgr_vdev *vdev) @@ -74,15 +75,78 @@ target_if_cm_roam_send_vdev_set_pcl_cmd(struct wlan_objmgr_vdev *vdev, return wmi_unified_vdev_set_pcl_cmd(wmi_handle, ¶ms); } +/** + * target_if_roam_set_param() - set roam params in fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @param_id: parameter id + * @param_value: parameter value + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS +target_if_roam_set_param(wmi_unified_t wmi_handle, uint8_t vdev_id, + uint32_t param_id, uint32_t param_value) +{ + struct vdev_set_params roam_param = {0}; + + roam_param.vdev_id = vdev_id; + roam_param.param_id = param_id; + roam_param.param_value = param_value; + + return wmi_unified_roam_set_param_send(wmi_handle, &roam_param); +} + +/** + * target_if_cm_roam_rt_stats_config() - Send enable/disable roam event stats + * commands to wmi + * @vdev: vdev object + * @vdev_id: vdev id + * @rstats_config: roam event stats config parameters + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_cm_roam_rt_stats_config(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, uint8_t rstats_config) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + wmi_unified_t wmi_handle; + + wmi_handle = target_if_cm_roam_get_wmi_handle_from_vdev(vdev); + if (!wmi_handle) + return status; + + status = target_if_roam_set_param( + wmi_handle, + vdev_id, + WMI_ROAM_PARAM_ROAM_EVENTS_CONFIG, + rstats_config); + + if (QDF_IS_STATUS_ERROR(status)) + target_if_err("Failed to set " + "WMI_ROAM_PARAM_ROAM_EVENTS_CONFIG"); + + return status; +} + static void target_if_cm_roam_register_lfr3_ops(struct wlan_cm_roam_tx_ops *tx_ops) { tx_ops->send_vdev_set_pcl_cmd = target_if_cm_roam_send_vdev_set_pcl_cmd; + tx_ops->send_roam_rt_stats_config = target_if_cm_roam_rt_stats_config; } #else static inline void target_if_cm_roam_register_lfr3_ops(struct wlan_cm_roam_tx_ops *tx_ops) {} + +static QDF_STATUS +target_if_cm_roam_rt_stats_config(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, uint8_t rstats_config) +{ + return QDF_STATUS_E_NOSUPPORT; +} #endif /** @@ -682,14 +746,14 @@ target_if_cm_roam_offload_11k_params(wmi_unified_t wmi_handle, if (!wmi_service_enabled(wmi_handle, wmi_service_11k_neighbour_report_support)) { target_if_err("FW doesn't support 11k offload"); - return QDF_STATUS_E_NOSUPPORT; + return QDF_STATUS_SUCCESS; } /* If 11k enable command and ssid length is 0, drop it */ if (req->offload_11k_bitmask && !req->neighbor_report_params.ssid.length) { target_if_debug("SSID Len 0"); - return QDF_STATUS_E_INVAL; + return QDF_STATUS_SUCCESS; } status = wmi_unified_offload_11k_cmd(wmi_handle, req); @@ -842,6 +906,7 @@ target_if_cm_roam_send_start(struct wlan_objmgr_vdev *vdev, QDF_STATUS status = QDF_STATUS_SUCCESS; wmi_unified_t wmi_handle; struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; bool bss_load_enabled; wmi_handle = target_if_cm_roam_get_wmi_handle_from_vdev(vdev); @@ -962,6 +1027,11 @@ target_if_cm_roam_send_start(struct wlan_objmgr_vdev *vdev, target_if_cm_roam_idle_params(wmi_handle, ROAM_SCAN_OFFLOAD_START, &req->idle_params); + + vdev_id = wlan_vdev_get_id(vdev); + if (req->wlan_roam_rt_stats_config) + target_if_cm_roam_rt_stats_config(vdev, vdev_id, + req->wlan_roam_rt_stats_config); /* add other wmi commands */ end: return status; @@ -1179,6 +1249,11 @@ target_if_cm_roam_send_update_config(struct wlan_objmgr_vdev *vdev, wmi_handle, ROAM_SCAN_OFFLOAD_UPDATE_CFG, &req->idle_params); target_if_cm_roam_triggers(vdev, &req->roam_triggers); + + if (req->wlan_roam_rt_stats_config) + target_if_cm_roam_rt_stats_config( + vdev, vdev_id, + req->wlan_roam_rt_stats_config); } end: return status; diff --git a/drivers/staging/qcacld-3.0/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/drivers/staging/qcacld-3.0/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 212cf43db57f..c56b15bde014 100644 --- a/drivers/staging/qcacld-3.0/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/drivers/staging/qcacld-3.0/components/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -1320,11 +1320,20 @@ static QDF_STATUS target_if_cp_stats_send_stats_req( cp_stats_err("wmi_handle is null."); return QDF_STATUS_E_NULL_VALUE; } + /* refer (WMI_REQUEST_STATS_CMDID) */ param.stats_id = get_stats_id(type); param.vdev_id = req->vdev_id; param.pdev_id = req->pdev_id; + /* only very frequent periodic stats needs to go over QMI. + * for that, wlan_hdd_qmi_get_sync_resume/wlan_hdd_qmi_put_suspend + * needs to be called to cover the period between qmi send and + * qmi resonse. + */ + if (TYPE_STATION_STATS == type) + param.is_qmi_send_support = true; + return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr, ¶m); } diff --git a/drivers/staging/qcacld-3.0/components/target_if/fw_offload/src/target_if_fwol.c b/drivers/staging/qcacld-3.0/components/target_if/fw_offload/src/target_if_fwol.c index 11b651068c8f..124418889085 100644 --- a/drivers/staging/qcacld-3.0/components/target_if/fw_offload/src/target_if_fwol.c +++ b/drivers/staging/qcacld-3.0/components/target_if/fw_offload/src/target_if_fwol.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 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 @@ -240,10 +240,203 @@ target_if_fwol_register_dscp_up_tx_ops(struct wlan_fwol_tx_ops *tx_ops) } #endif +#ifdef THERMAL_STATS_SUPPORT +/** + * target_if_fwol_get_thermal_stats() - send get thermal stats request to FW + * @psoc: pointer to PSOC object + * @req_type: get thermal stats request type + * @therm_stats_offset: thermal temp stats offset for each temp range + * + * Return: QDF_STATUS_SUCCESS on success + */ +static QDF_STATUS +target_if_fwol_get_thermal_stats(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req_type, + uint8_t therm_stats_offset) +{ + QDF_STATUS status; + wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + + if (!wmi_handle) { + target_if_err("Invalid wmi_handle"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_send_get_thermal_stats_cmd(wmi_handle, req_type, + therm_stats_offset); + if (status) + target_if_err("Failed to send get thermal stats cmd %d", + status); + + return status; +} + +static void +target_if_fwol_register_thermal_stats_tx_ops(struct wlan_fwol_tx_ops *tx_ops) +{ + tx_ops->get_thermal_stats = target_if_fwol_get_thermal_stats; +} + +static QDF_STATUS +target_if_fwol_handle_thermal_lvl_stats_evt(struct wlan_objmgr_psoc *psoc, + struct wlan_fwol_rx_ops *rx_ops, + struct thermal_throttle_info *info) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + if (rx_ops->get_thermal_stats_resp && info->therm_throt_levels) + status = rx_ops->get_thermal_stats_resp(psoc, info); + + return status; +} + +static bool +target_if_fwol_is_thermal_stats_enable(struct wlan_fwol_psoc_obj *fwol_obj) +{ + return (fwol_obj->capability_info.fw_thermal_stats_cap && + fwol_obj->cfg.thermal_temp_cfg.therm_stats_offset); +} + +/** + * target_if_fwol_thermal_throttle_event_handler() - handler for thermal + * throttle event + * @scn: scn handle + * @event_buf: pointer to the event buffer + * @len: length of the buffer + * + * Return: 0 on success + */ +static int +target_if_fwol_thermal_throttle_event_handler(ol_scn_t scn, uint8_t *event_buf, + uint32_t len) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct thermal_throttle_info info = {0}; + struct wlan_objmgr_psoc *psoc; + wmi_unified_t wmi_handle; + struct wlan_fwol_psoc_obj *fwol_obj; + struct wlan_fwol_rx_ops *rx_ops; + + target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, event_buf, len); + if (!scn || !event_buf) + return -EINVAL; + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + target_if_err("null psoc"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid wmi_handle"); + return -EINVAL; + } + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + target_if_err("Failed to get FWOL Obj"); + return -EINVAL; + } + + status = wmi_extract_thermal_stats(wmi_handle, + event_buf, + &info.temperature, + &info.level, + &info.therm_throt_levels, + info.level_info, + &info.pdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_debug("Failed to convert thermal target level"); + return -EINVAL; + } + rx_ops = &fwol_obj->rx_ops; + if (!rx_ops) { + target_if_debug("rx_ops Null"); + return -EINVAL; + } + + status = target_if_fwol_handle_thermal_lvl_stats_evt(psoc, rx_ops, + &info); + if (QDF_IS_STATUS_ERROR(status)) + target_if_debug("thermal stats level response failed."); + + return 0; +} + +/** + * target_if_fwol_register_thermal_throttle_handler() - Register handler for + * thermal throttle stats firmware event + * @psoc: psoc object + * + * Return: void + */ +static void +target_if_fwol_register_thermal_throttle_handler(struct wlan_objmgr_psoc *psoc) +{ + QDF_STATUS status; + struct wlan_fwol_psoc_obj *fwol_obj; + + fwol_obj = fwol_get_psoc_obj(psoc); + if (!fwol_obj) { + target_if_err("Failed to get FWOL Obj"); + return; + } + if (!target_if_fwol_is_thermal_stats_enable(fwol_obj)) { + target_if_debug("thermal stats offload not enabled"); + return; + } + status = wmi_unified_register_event_handler( + get_wmi_unified_hdl_from_psoc(psoc), + wmi_tt_stats_event_id, + target_if_fwol_thermal_throttle_event_handler, + WMI_RX_SERIALIZER_CTX); + if (QDF_IS_STATUS_ERROR(status)) + target_if_debug("Failed to register thermal stats event cb"); +} + +/** + * target_if_fwol_unregister_thermal_stats_handler() - Register handler for + * thermal throttle stats firmware event + * @psoc: psoc object + * + * Return: void + */ +static void +target_if_fwol_unregister_thermal_throttle_handler( + struct wlan_objmgr_psoc *psoc) +{ + QDF_STATUS status; + + status = wmi_unified_unregister_event_handler( + get_wmi_unified_hdl_from_psoc(psoc), + wmi_tt_stats_event_id); + if (QDF_IS_STATUS_ERROR(status)) + target_if_debug("Failed to unregister thermal stats event cb"); +} + +#else +static void +target_if_fwol_register_thermal_throttle_handler(struct wlan_objmgr_psoc *psoc) +{ +} + +static void +target_if_fwol_unregister_thermal_throttle_handler( + struct wlan_objmgr_psoc *psoc) +{ +} +static void +target_if_fwol_register_thermal_stats_tx_ops(struct wlan_fwol_tx_ops *tx_ops) +{ +} +#endif + QDF_STATUS target_if_fwol_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) { target_if_fwol_register_elna_event_handler(psoc, arg); + target_if_fwol_register_thermal_throttle_handler(psoc); return QDF_STATUS_SUCCESS; } @@ -253,6 +446,7 @@ target_if_fwol_unregister_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) { target_if_fwol_unregister_elna_event_handler(psoc, arg); + target_if_fwol_unregister_thermal_throttle_handler(psoc); return QDF_STATUS_SUCCESS; } @@ -261,6 +455,7 @@ QDF_STATUS target_if_fwol_register_tx_ops(struct wlan_fwol_tx_ops *tx_ops) { target_if_fwol_register_elna_tx_ops(tx_ops); target_if_fwol_register_dscp_up_tx_ops(tx_ops); + target_if_fwol_register_thermal_stats_tx_ops(tx_ops); tx_ops->reg_evt_handler = target_if_fwol_register_event_handler; tx_ops->unreg_evt_handler = target_if_fwol_unregister_event_handler; diff --git a/drivers/staging/qcacld-3.0/components/target_if/pkt_capture/src/target_if_pkt_capture.c b/drivers/staging/qcacld-3.0/components/target_if/pkt_capture/src/target_if_pkt_capture.c index 4361c157fa90..2f970ab5f598 100644 --- a/drivers/staging/qcacld-3.0/components/target_if/pkt_capture/src/target_if_pkt_capture.c +++ b/drivers/staging/qcacld-3.0/components/target_if/pkt_capture/src/target_if_pkt_capture.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -27,6 +28,7 @@ #include #include #include +#include /** * target_if_set_packet_capture_mode() - set packet capture mode @@ -79,10 +81,11 @@ static QDF_STATUS target_if_set_packet_capture_config (struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, - enum pkt_capture_trigger_qos_config config_value) + enum pkt_capture_config config_value) { wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc); QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct wlan_objmgr_vdev *vdev; struct vdev_set_params param; if (!wmi_handle) { @@ -90,6 +93,13 @@ target_if_set_packet_capture_config return QDF_STATUS_E_INVAL; } + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_PKT_CAPTURE_ID); + if (!vdev) { + pkt_capture_err("vdev is NULL"); + return QDF_STATUS_E_INVAL; + } + target_if_debug("psoc:%pK, vdev_id:%d config_value:%d", psoc, vdev_id, config_value); @@ -98,9 +108,12 @@ target_if_set_packet_capture_config param.param_value = (uint32_t)config_value; status = wmi_unified_vdev_set_param_send(wmi_handle, ¶m); - if (QDF_IS_STATUS_ERROR(status)) + if (QDF_IS_STATUS_SUCCESS(status)) + ucfg_pkt_capture_set_pktcap_config(vdev, config_value); + else pkt_capture_err("failed to set packet capture config"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID); return status; } #else @@ -108,12 +121,50 @@ static QDF_STATUS target_if_set_packet_capture_config (struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, - enum pkt_capture_trigger_qos_config config_value) + enum pkt_capture_config config_value) { return QDF_STATUS_SUCCESS; } #endif +/** + * target_if_set_packet_capture_beacon_interval() - set packet capture beacon + * interval + * @psoc: pointer to psoc object + * @vdev_id: vdev id + * @nth_value: Beacon report period + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_set_packet_capture_beacon_interval + (struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint32_t nth_value) +{ + wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc); + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct vdev_set_params param; + + if (!wmi_handle) { + target_if_err("Invalid wmi handle"); + return QDF_STATUS_E_INVAL; + } + + target_if_debug("psoc:%pK, vdev_id:%d nth_value:%d", + psoc, vdev_id, nth_value); + + param.vdev_id = vdev_id; + param.param_id = WMI_VDEV_PARAM_NTH_BEACON_TO_HOST; + param.param_value = nth_value; + + status = wmi_unified_vdev_set_param_send(wmi_handle, ¶m); + if (QDF_IS_STATUS_ERROR(status)) + pkt_capture_err("failed to set beacon interval"); + + return status; +} + /** * target_if_mgmt_offload_data_event_handler() - offload event handler * @handle: scn handle @@ -154,8 +205,7 @@ target_if_mgmt_offload_data_event_handler(void *handle, uint8_t *data, return -EINVAL; } - if (!(ucfg_pkt_capture_get_pktcap_mode(psoc) & - PKT_CAPTURE_MODE_MGMT_ONLY)) + if (!(wlan_pkt_capture_is_tx_mgmt_enable(pdev))) return -EINVAL; status = wmi_unified_extract_vdev_mgmt_offload_event(wmi_handle, data, @@ -424,4 +474,6 @@ target_if_pkt_capture_register_tx_ops(struct wlan_pkt_capture_tx_ops *tx_ops) tx_ops->pkt_capture_send_mode = target_if_set_packet_capture_mode; tx_ops->pkt_capture_send_config = target_if_set_packet_capture_config; + tx_ops->pkt_capture_send_beacon_interval = + target_if_set_packet_capture_beacon_interval; } diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c index 731f784a31c6..0629bee47550 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c @@ -28,6 +28,7 @@ #include "wlan_cm_roam_api.h" #include "wlan_mlme_vdev_mgr_interface.h" #include "wlan_crypto_global_api.h" +#include "wlan_roam_debug.h" /** * cm_roam_scan_bmiss_cnt() - set roam beacon miss count @@ -237,6 +238,39 @@ cm_roam_idle_params(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, wlan_mlme_get_idle_roam_min_rssi(psoc, ¶ms->conn_ap_min_rssi); wlan_mlme_get_idle_roam_band(psoc, ¶ms->band); } + +/** + * cm_roam_send_rt_stats_config() - set roam stats parameters + * @psoc: psoc pointer + * @vdev_id: vdev id + * @param_value: roam stats param value + * + * This function is used to set roam event stats parameters + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t param_value) +{ + struct roam_disable_cfg *req; + QDF_STATUS status; + + req = qdf_mem_malloc(sizeof(*req)); + if (!req) + return QDF_STATUS_E_NOMEM; + + req->vdev_id = vdev_id; + req->cfg = param_value; + + status = wlan_cm_tgt_send_roam_rt_stats_config(psoc, req); + if (QDF_IS_STATUS_ERROR(status)) + mlme_debug("fail to send roam rt stats config"); + + qdf_mem_free(req); + + return status; +} #else static inline void cm_roam_reason_vsie(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, @@ -488,6 +522,9 @@ cm_roam_start_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, /* fill from legacy through this API */ wlan_cm_roam_fill_start_req(psoc, vdev_id, start_req, reason); + start_req->wlan_roam_rt_stats_config = + wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE); + status = wlan_cm_tgt_send_roam_start_req(psoc, vdev_id, start_req); if (QDF_IS_STATUS_ERROR(status)) mlme_debug("fail to send roam start"); @@ -534,6 +571,9 @@ cm_roam_update_config_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, /* fill from legacy through this API */ wlan_cm_roam_fill_update_config_req(psoc, vdev_id, update_req, reason); + update_req->wlan_roam_rt_stats_config = + wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE); + status = wlan_cm_tgt_send_roam_update_req(psoc, vdev_id, update_req); if (QDF_IS_STATUS_ERROR(status)) mlme_debug("fail to send update config"); @@ -1129,6 +1169,10 @@ cm_roam_switch_to_rso_enable(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; case WLAN_ROAM_SYNCH_IN_PROG: + if (reason == REASON_ROAM_ABORT) { + mlme_debug("Roam synch in progress, drop Roam abort"); + return QDF_STATUS_SUCCESS; + } /* * After roam sych propagation is complete, send * RSO start command to firmware to update AP profile, @@ -1290,6 +1334,156 @@ cm_roam_switch_to_roam_sync(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } +#ifdef FEATURE_ROAM_DEBUG +/** + * union rso_rec_arg1 - argument 1 record rso state change + * @request_st: requested rso state + * @cur_st: current rso state + * @new_st: new rso state + * @status: qdf status for the request + */ +union rso_rec_arg1 { + uint32_t value; + struct { + uint32_t request_st:4, + cur_st:4, + new_st:4, + status:8; + }; +}; + +/** + * get_rso_arg1 - get argument 1 record rso state change + * @request_st: requested rso state + * @cur_st: current rso state + * @new_st: new rso state + * @status: qdf status for the request + * + * Return: u32 value of rso information + */ +static uint32_t get_rso_arg1(enum roam_offload_state request_st, + enum roam_offload_state cur_st, + enum roam_offload_state new_st, + QDF_STATUS status) +{ + union rso_rec_arg1 rso_arg1; + + rso_arg1.value = 0; + rso_arg1.request_st = request_st; + rso_arg1.cur_st = cur_st; + rso_arg1.new_st = new_st; + rso_arg1.status = status; + + return rso_arg1.value; +} + +/** + * union rso_rec_arg2 - argument 2 record rso state change + * @is_up: vdev is up + * @supp_dis_roam: supplicant disable roam + * @roam_progress: roam in progress + * @ctrl_bitmap: control bitmap + * @reason: reason code + * + * Return: u32 value of rso information + */ +union rso_rec_arg2 { + uint32_t value; + struct { + uint32_t is_up: 1, + supp_dis_roam:1, + roam_progress:1, + ctrl_bitmap:8, + reason:8; + }; +}; + +/** + * get_rso_arg2 - get argument 2 record rso state change + * @is_up: vdev is up + * @supp_dis_roam: supplicant disable roam + * @roam_progress: roam in progress + * @ctrl_bitmap: control bitmap + * @reason: reason code + */ +static uint32_t get_rso_arg2(bool is_up, + bool supp_dis_roam, + bool roam_progress, + uint8_t ctrl_bitmap, + uint8_t reason) +{ + union rso_rec_arg2 rso_arg2; + + rso_arg2.value = 0; + if (is_up) + rso_arg2.is_up = 1; + if (supp_dis_roam) + rso_arg2.supp_dis_roam = 1; + if (roam_progress) + rso_arg2.roam_progress = 1; + rso_arg2.ctrl_bitmap = ctrl_bitmap; + rso_arg2.reason = reason; + + return rso_arg2.value; +} + +/** + * cm_record_state_change() - record rso state change to roam history log + * @pdev: pdev object + * @vdev_id: vdev id + * @cur_st: current state + * @request_state: requested state + * @reason: reason + * @is_up: vdev is up + * @status: request result code + * + * This function will record the RSO state change to roam history log. + * + * Return: void + */ +static void +cm_record_state_change(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, + enum roam_offload_state cur_st, + enum roam_offload_state requested_state, + uint8_t reason, + bool is_up, + QDF_STATUS status) +{ + enum roam_offload_state new_state; + bool supp_dis_roam; + bool roam_progress; + uint8_t control_bitmap; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) + return; + + new_state = mlme_get_roam_state(psoc, vdev_id); + control_bitmap = mlme_get_operations_bitmap(psoc, vdev_id); + supp_dis_roam = mlme_get_supplicant_disabled_roaming(psoc, vdev_id); + roam_progress = wlan_cm_roaming_in_progress(pdev, vdev_id); + wlan_rec_conn_info(vdev_id, DEBUG_CONN_RSO, + NULL, + get_rso_arg1(requested_state, cur_st, + new_state, status), + get_rso_arg2(is_up, + supp_dis_roam, roam_progress, + control_bitmap, reason)); +} +#else +static inline void +cm_record_state_change(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, + enum roam_offload_state cur_st, + enum roam_offload_state requested_state, + uint8_t reason, + bool is_up, + QDF_STATUS status) +{ +} +#endif + QDF_STATUS cm_roam_state_change(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, @@ -1299,6 +1493,11 @@ cm_roam_state_change(struct wlan_objmgr_pdev *pdev, QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_objmgr_vdev *vdev; bool is_up; + enum roam_offload_state cur_state; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) + return QDF_STATUS_E_INVAL; vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, WLAN_MLME_NB_ID); @@ -1308,9 +1507,11 @@ cm_roam_state_change(struct wlan_objmgr_pdev *pdev, is_up = QDF_IS_STATUS_SUCCESS(wlan_vdev_is_up(vdev)); wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + cur_state = mlme_get_roam_state(psoc, vdev_id); + if (requested_state != WLAN_ROAM_DEINIT && !is_up) { mlme_debug("ROAM: roam state change requested in disconnected state"); - return status; + goto end; } switch (requested_state) { @@ -1336,6 +1537,9 @@ cm_roam_state_change(struct wlan_objmgr_pdev *pdev, mlme_debug("ROAM: Invalid roam state %d", requested_state); break; } +end: + cm_record_state_change(pdev, vdev_id, cur_state, requested_state, + reason, is_up, status); return status; } diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h index 9175fef7e423..e05eb0b8d1de 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h @@ -102,6 +102,27 @@ cm_roam_fill_rssi_change_params(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, struct wlan_roam_rssi_change_params *params); #endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * cm_roam_send_rt_stats_config() - Send roam event stats cfg value to FW + * @psoc: PSOC pointer + * @vdev_id: vdev id + * @param_value: roam stats enable/disable cfg + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t param_value); +#else +static inline QDF_STATUS +cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t param_value) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif + /** * cm_roam_send_disable_config() - Send roam module enable/disable cfg to fw * @psoc: PSOC pointer diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h index 591208a4dbc6..478d6a477160 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h @@ -599,6 +599,28 @@ uint32_t wlan_cm_get_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, enum roam_fail_params states); +/** + * wlan_cm_update_roam_rt_stats() - Store roam event stats command params + * @psoc: PSOC pointer + * @value: Value to update + * @stats: type of value to update + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + uint8_t value, enum roam_rt_stats_params stats); + +/** + * wlan_cm_get_roam_rt_stats() - Get roam event stats value + * @psoc: PSOC pointer + * @stats: Get roam event command param for specific attribute + * + * Return: Roam events stats param value + */ +uint8_t +wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + enum roam_rt_stats_params stats); #else static inline void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, @@ -702,5 +724,18 @@ wlan_cm_get_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, return 0; } +static inline QDF_STATUS +wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + uint8_t value, enum roam_rt_stats_params stats) +{ + return QDF_STATUS_SUCCESS; +} + +static inline uint8_t +wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + enum roam_rt_stats_params stats) +{ + return 0; +} #endif /* FEATURE_ROAM_OFFLOAD */ #endif /* WLAN_CM_ROAM_API_H__ */ diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h index d7d166f6e6b2..65b21c27a9dc 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h @@ -891,6 +891,32 @@ struct wlan_rso_sae_offload_params { }; #endif +/** + * struct roam_event_rt_info - Roam event related information + * @vdev_id: Vdev id + * @roam_scan_state: roam scan state notif value + * @roam_invoke_fail_reason: roam invoke fail reason + */ +struct roam_event_rt_info { + uint8_t vdev_id; + uint32_t roam_scan_state; + uint32_t roam_invoke_fail_reason; +}; + +/** + * enum roam_rt_stats_type: different types of params to get roam event stats + * for the vdev + * @ROAM_RT_STATS_TYPE_SCAN_STATE: Roam Scan Start/End + * @ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON: One of WMI_ROAM_FAIL_REASON_ID for + * roam failure in case of forced roam + * @ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO: Roam Trigger/Fail/Scan/AP Stats + */ +enum roam_rt_stats_type { + ROAM_RT_STATS_TYPE_SCAN_STATE, + ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON, + ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO, +}; + #define ROAM_SCAN_DWELL_TIME_ACTIVE_DEFAULT (100) #define ROAM_SCAN_DWELL_TIME_PASSIVE_DEFAULT (110) #define ROAM_SCAN_MIN_REST_TIME_DEFAULT (50) @@ -1095,6 +1121,27 @@ struct wlan_roam_rssi_change_params { int32_t rssi_change_thresh; }; +/** + * struct wlan_cm_roam_rt_stats - Roam events stats update + * @roam_stats_enabled: set 1 if roam stats feature is enabled from userspace + * @roam_stats_wow_sent: set 1 if roam stats wow event is sent to FW + */ +struct wlan_cm_roam_rt_stats { + uint8_t roam_stats_enabled; + uint8_t roam_stats_wow_sent; +}; + +/** + * enum roam_rt_stats_params: different types of params to set or get roam + * events stats for the vdev + * @ROAM_RT_STATS_ENABLE: Roam stats feature if enable/not + * @ROAM_RT_STATS_SUSPEND_MODE_ENABLE: Roam stats wow event if sent to FW/not + */ +enum roam_rt_stats_params { + ROAM_RT_STATS_ENABLE, + ROAM_RT_STATS_SUSPEND_MODE_ENABLE, +}; + /** * struct wlan_roam_start_config - structure containing parameters for * roam start config @@ -1113,6 +1160,7 @@ struct wlan_roam_rssi_change_params { * @bss_load_config: bss load config * @disconnect_params: disconnect params * @idle_params: idle params + * @wlan_roam_rt_stats_config: roam events stats config */ struct wlan_roam_start_config { struct wlan_roam_offload_scan_rssi_params rssi_params; @@ -1131,6 +1179,7 @@ struct wlan_roam_start_config { struct wlan_roam_bss_load_config bss_load_config; struct wlan_roam_disconnect_params disconnect_params; struct wlan_roam_idle_params idle_params; + uint8_t wlan_roam_rt_stats_config; /* other wmi cmd structures */ }; @@ -1175,6 +1224,7 @@ struct wlan_roam_stop_config { * @disconnect_params: disconnect params * @idle_params: idle params * @roam_triggers: roam triggers parameters + * @wlan_roam_rt_stats_config: roam events stats config */ struct wlan_roam_update_config { struct wlan_roam_beacon_miss_cnt beacon_miss_cnt; @@ -1188,6 +1238,7 @@ struct wlan_roam_update_config { struct wlan_roam_disconnect_params disconnect_params; struct wlan_roam_idle_params idle_params; struct wlan_roam_triggers roam_triggers; + uint8_t wlan_roam_rt_stats_config; }; #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) @@ -1312,6 +1363,7 @@ struct set_pcl_req { * commands * @send_roam_abort: send roam abort * @send_roam_disable_config: send roam disable config + * @send_roam_rt_stats_config: Send roam events vendor command param value to FW */ struct wlan_cm_roam_tx_ops { QDF_STATUS (*send_vdev_set_pcl_cmd)(struct wlan_objmgr_vdev *vdev, @@ -1336,6 +1388,10 @@ struct wlan_cm_roam_tx_ops { struct wlan_roam_triggers *req); QDF_STATUS (*send_roam_disable_config)(struct wlan_objmgr_vdev *vdev, struct roam_disable_cfg *req); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + QDF_STATUS (*send_roam_rt_stats_config)(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, uint8_t value); +#endif }; /** diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h index aed82c91b478..6272fb622c2f 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h @@ -155,6 +155,35 @@ ucfg_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, return wlan_cm_update_roam_scan_scheme_bitmap(psoc, vdev_id, roam_scan_scheme_bitmap); } + +static inline QDF_STATUS +ucfg_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + uint8_t value, enum roam_rt_stats_params stats) +{ + return wlan_cm_update_roam_rt_stats(psoc, value, stats); +} + +static inline uint8_t +ucfg_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + enum roam_rt_stats_params stats) +{ + return wlan_cm_get_roam_rt_stats(psoc, stats); +} + +/** + * ucfg_cm_roam_send_rt_stats_config() - Enable/Disable Roam event stats from FW + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @param_value: Value set based on the userspace attributes. + * param_value - 0: if configure attribute is 0 + * 1: if configure is 1 and suspend_state is not set + * 3: if configure is 1 and suspend_state is set + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint8_t param_value); #else static inline QDF_STATUS ucfg_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, @@ -163,4 +192,25 @@ ucfg_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_SUCCESS; } + +static inline QDF_STATUS +ucfg_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + uint8_t value, enum roam_rt_stats_params stats) +{ + return QDF_STATUS_SUCCESS; +} + +static inline uint8_t +ucfg_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + enum roam_rt_stats_params stats) +{ + return 0; +} + +static inline QDF_STATUS +ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint8_t param_value) +{ + return QDF_STATUS_SUCCESS; +} #endif diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h index 43c867d7f5f6..f814c4f6b626 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h @@ -36,6 +36,17 @@ QDF_STATUS wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc, struct set_pcl_req *pcl_req); + +/** + * wlan_cm_tgt_send_roam_rt_stats_config() - Send roam event stats config + * command to FW + * @psoc: psoc pointer + * @req: roam stats config parameter + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, + struct roam_disable_cfg *req); #else static inline QDF_STATUS wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc, @@ -43,6 +54,13 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_E_FAILURE; } + +static inline QDF_STATUS +wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, + struct roam_disable_cfg *req) +{ + return QDF_STATUS_E_FAILURE; +} #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c index e298d4e6c350..b29f3b28854e 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c @@ -358,6 +358,9 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, bool is_ch_allowed; struct wlan_mlme_psoc_ext_obj *mlme_obj; struct wlan_mlme_cfg *mlme_cfg; + uint32_t buff_len; + char *chan_buff; + uint32_t len = 0; mlme_obj = mlme_get_psoc_ext_obj(psoc); if (!mlme_obj) @@ -376,6 +379,16 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, num_channels = mlme_cfg->reg.valid_channel_list_num; channel_list = mlme_cfg->reg.valid_channel_freq_list; + /* + * Buffer of (num channl * 5) + 1 to consider the 4 char freq, + * 1 space after it for each channel and 1 to end the string + * with NULL. + */ + buff_len = (num_channels * 5) + 1; + chan_buff = qdf_mem_malloc(buff_len); + if (!chan_buff) + return; + filter->num_of_channels = 0; for (i = 0; i < num_channels; i++) { is_ch_allowed = @@ -387,7 +400,16 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, filter->chan_freq_list[filter->num_of_channels] = channel_list[i]; filter->num_of_channels++; + + len += qdf_scnprintf(chan_buff + len, buff_len - len, + "%d ", channel_list[i]); } + + if (filter->num_of_channels) + mlme_debug("Freq list (%d): %s", filter->num_of_channels, + chan_buff); + + qdf_mem_free(chan_buff); } void @@ -818,4 +840,61 @@ uint32_t wlan_cm_get_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, return roam_states; } + +QDF_STATUS +wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + uint8_t value, enum roam_rt_stats_params stats) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + struct wlan_cm_roam_rt_stats *roam_rt_stats; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + mlme_legacy_err("Failed to get MLME Obj"); + return QDF_STATUS_E_FAILURE; + } + + roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats; + + switch (stats) { + case ROAM_RT_STATS_ENABLE: + roam_rt_stats->roam_stats_enabled = value; + break; + case ROAM_RT_STATS_SUSPEND_MODE_ENABLE: + roam_rt_stats->roam_stats_wow_sent = value; + break; + default: + break; + } + + return QDF_STATUS_SUCCESS; +} + +uint8_t wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, + enum roam_rt_stats_params stats) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + struct wlan_cm_roam_rt_stats *roam_rt_stats; + uint8_t rstats_value = 0; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + mlme_legacy_err("Failed to get MLME Obj"); + return QDF_STATUS_E_FAILURE; + } + + roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats; + switch (stats) { + case ROAM_RT_STATS_ENABLE: + rstats_value = roam_rt_stats->roam_stats_enabled; + break; + case ROAM_RT_STATS_SUSPEND_MODE_ENABLE: + rstats_value = roam_rt_stats->roam_stats_wow_sent; + break; + default: + break; + } + + return rstats_value; +} #endif diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c index e765a6c0615d..630deff30cf4 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c @@ -127,3 +127,14 @@ QDF_STATUS ucfg_cm_abort_roam_scan(struct wlan_objmgr_pdev *pdev, return status; } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +QDF_STATUS +ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint8_t param_value) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + return cm_roam_send_rt_stats_config(psoc, vdev_id, param_value); +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c index 8b7c322cb5b1..76ecef7a8baf 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c @@ -154,6 +154,37 @@ end: return status; } + +QDF_STATUS wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, + struct roam_disable_cfg *req) +{ + QDF_STATUS status; + struct wlan_cm_roam_tx_ops *roam_tx_ops; + struct wlan_objmgr_vdev *vdev; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, req->vdev_id, + WLAN_MLME_NB_ID); + if (!vdev) + return QDF_STATUS_E_INVAL; + + roam_tx_ops = wlan_cm_roam_get_tx_ops_from_vdev(vdev); + if (!roam_tx_ops || !roam_tx_ops->send_roam_rt_stats_config) { + mlme_err("vdev %d send_roam_rt_stats_config is NULL", + req->vdev_id); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + return QDF_STATUS_E_INVAL; + } + + status = roam_tx_ops->send_roam_rt_stats_config(vdev, + req->vdev_id, req->cfg); + if (QDF_IS_STATUS_ERROR(status)) + mlme_debug("vdev %d fail to send roam rt stats config", + req->vdev_id); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + + return status; +} #endif #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) diff --git a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c index 069e46fb1e8e..423351292d85 100644 --- a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c +++ b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c @@ -327,6 +327,13 @@ extract_peer_stats_count_tlv(wmi_unified_t wmi_handle, void *evt_buf, if (!ev_param) return QDF_STATUS_E_FAILURE; + if (!param_buf->num_peer_stats_info || + param_buf->num_peer_stats_info < ev_param->num_peers) { + wmi_err_rl("actual num of peers stats info: %d is less than provided peers: %d", + param_buf->num_peer_stats_info, ev_param->num_peers); + return QDF_STATUS_E_FAULT; + } + if (!stats_param) return QDF_STATUS_E_FAILURE; diff --git a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c index e3bba1efcdda..20847eebe623 100644 --- a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c +++ b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c @@ -1019,6 +1019,14 @@ static QDF_STATUS send_roam_invoke_cmd_tlv(wmi_unified_t wmi_handle, cmd->flags |= (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE); cmd->reason = ROAM_INVOKE_REASON_NUD_FAILURE; + } else if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)&roaminvoke->bssid)) { + cmd->num_chan = 0; + cmd->num_bssid = 0; + cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_CACHE_MAP; + cmd->flags |= + (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE) | + (1 << WMI_ROAM_INVOKE_FLAG_SELECT_CANDIDATE_CONSIDER_SCORE); + cmd->reason = ROAM_INVOKE_REASON_USER_SPACE; } else { cmd->reason = ROAM_INVOKE_REASON_USER_SPACE; } @@ -2331,6 +2339,10 @@ wmi_fill_rso_start_scan_tlv(struct wlan_roam_scan_offload_params *rso_req, scan_tlv->idle_time = src_scan_params->idle_time; scan_tlv->n_probes = src_scan_params->n_probes; scan_tlv->scan_ctrl_flags |= src_scan_params->scan_ctrl_flags; + scan_tlv->dwell_time_active_6ghz = + src_scan_params->dwell_time_active_6ghz; + scan_tlv->dwell_time_passive_6ghz = + src_scan_params->dwell_time_passive_6ghz; WMI_SCAN_SET_DWELL_MODE(scan_tlv->scan_ctrl_flags, src_scan_params->rso_adaptive_dwell_mode); @@ -2343,8 +2355,10 @@ wmi_fill_rso_start_scan_tlv(struct wlan_roam_scan_offload_params *rso_req, scan_tlv->scan_ctrl_flags_ext |= WMI_SCAN_DBS_POLICY_DEFAULT; - wmi_debug("RSO_CFG: dwell time: active %d passive %d, minrest %d max rest %d repeat probe time %d probe_spacing:%d", + wmi_debug("RSO_CFG: dwell time: active %d passive %d, active 6g %d passive 6g %d, minrest %d max rest %d repeat probe time %d probe_spacing:%d", scan_tlv->dwell_time_active, scan_tlv->dwell_time_passive, + scan_tlv->dwell_time_active_6ghz, + scan_tlv->dwell_time_passive_6ghz, scan_tlv->min_rest_time, scan_tlv->max_rest_time, scan_tlv->repeat_probe_time, scan_tlv->probe_spacing_time); wmi_debug("RSO_CFG: ctrl_flags:0x%x probe_delay:%d max_scan_time:%d idle_time:%d n_probes:%d", diff --git a/drivers/staging/qcacld-3.0/configs/default_defconfig b/drivers/staging/qcacld-3.0/configs/default_defconfig index 1014da5ee249..d6e50799f110 100644 --- a/drivers/staging/qcacld-3.0/configs/default_defconfig +++ b/drivers/staging/qcacld-3.0/configs/default_defconfig @@ -207,6 +207,8 @@ CONFIG_QCOM_TDLS := y CONFIG_WLAN_SYSFS := y +CONFIG_THERMAL_STATS_SUPPORT := y + ifeq ($(CONFIG_WLAN_SYSFS), y) CONFIG_WLAN_SYSFS_STA_INFO := y CONFIG_WLAN_SYSFS_CHANNEL := y @@ -1229,3 +1231,5 @@ ifeq ($(CONFIG_FW_THERMAL_THROTTLE), y) CONFIG_WLAN_THERMAL_MULTI_CLIENT_SUPPORT := y endif endif + +CONFIG_WLAN_FEATURE_CAL_FAILURE_TRIGGER := y diff --git a/drivers/staging/qcacld-3.0/configs/wear_defconfig b/drivers/staging/qcacld-3.0/configs/wear_defconfig index a8c74d2baf3a..b1e358799937 100644 --- a/drivers/staging/qcacld-3.0/configs/wear_defconfig +++ b/drivers/staging/qcacld-3.0/configs/wear_defconfig @@ -1232,3 +1232,6 @@ ifeq ($(CONFIG_FW_THERMAL_THROTTLE), y) CONFIG_WLAN_THERMAL_MULTI_CLIENT_SUPPORT := y endif endif + +#Enable Low Power Modes: Deep Sleep/Hibernate +CONFIG_ENABLE_LOW_POWER_MODE := y diff --git a/drivers/staging/qcacld-3.0/core/cds/inc/cds_api.h b/drivers/staging/qcacld-3.0/core/cds/inc/cds_api.h index 58ccfe78758d..7b8a2b9de7f1 100644 --- a/drivers/staging/qcacld-3.0/core/cds/inc/cds_api.h +++ b/drivers/staging/qcacld-3.0/core/cds/inc/cds_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -79,9 +80,15 @@ enum cds_driver_state { * struce cds_vdev_dp_stats - vdev stats populated from DP * @tx_retries: packet number of successfully transmitted after more * than one retransmission attempt + * @tx_retries_mpdu: mpdu number of successfully transmitted after more + * than one retransmission attempt + * @tx_mpdu_success_with_retries: Number of MPDU transmission retries done + * in case of successful transmission. */ struct cds_vdev_dp_stats { uint32_t tx_retries; + uint32_t tx_retries_mpdu; + uint32_t tx_mpdu_success_with_retries; }; #define __CDS_IS_DRIVER_STATE(_state, _mask) (((_state) & (_mask)) == (_mask)) diff --git a/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c b/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c index ae2d37821270..017e73941636 100644 --- a/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c +++ b/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -2817,6 +2818,9 @@ cds_dp_get_vdev_stats(uint8_t vdev_id, struct cds_vdev_dp_stats *stats) if (cds_get_cdp_vdev_stats(vdev_id, vdev_stats)) { stats->tx_retries = vdev_stats->tx.retries; + stats->tx_retries_mpdu = vdev_stats->tx.retries_mpdu; + stats->tx_mpdu_success_with_retries = + vdev_stats->tx.mpdu_success_with_retries; ret = true; } diff --git a/drivers/staging/qcacld-3.0/core/dp/htt/htt_h2t.c b/drivers/staging/qcacld-3.0/core/dp/htt/htt_h2t.c index a2a4051dc88e..e1bed656e5ec 100644 --- a/drivers/staging/qcacld-3.0/core/dp/htt/htt_h2t.c +++ b/drivers/staging/qcacld-3.0/core/dp/htt/htt_h2t.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -1017,6 +1018,8 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) struct htt_htc_pkt *pkt; qdf_nbuf_t msg; uint32_t *msg_word; + uint32_t addr; + qdf_mem_info_t *mem_info_t; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) @@ -1052,13 +1055,14 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) msg_word++; *msg_word = 0; - /* TX COMP RING BASE LO */ HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_SET(*msg_word, (unsigned int)qdf_mem_get_dma_addr(pdev->osdev, &pdev->ipa_uc_tx_rsc.tx_comp_ring->mem_info)); msg_word++; *msg_word = 0; - /* TX COMP RING BASE HI, NONE */ + mem_info_t = &pdev->ipa_uc_tx_rsc.tx_comp_ring->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1071,6 +1075,8 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr); msg_word++; *msg_word = 0; + addr = (uint64_t)pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr >> 32; + HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1079,6 +1085,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_tx_rsc.tx_ce_idx->mem_info)); msg_word++; *msg_word = 0; + mem_info_t = &pdev->ipa_uc_tx_rsc.tx_ce_idx->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1087,8 +1096,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_rx_rsc.rx_ind_ring->mem_info)); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_SET(*msg_word, - 0); + mem_info_t = &pdev->ipa_uc_rx_rsc.rx_ind_ring->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1102,8 +1112,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx->mem_info)); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_SET(*msg_word, - 0); + mem_info_t = &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1111,8 +1122,8 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) (unsigned int)pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_SET(*msg_word, - 0); + addr = (uint64_t)pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr >> 32; + HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1121,8 +1132,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_rx_rsc.rx2_ind_ring->mem_info)); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_SET(*msg_word, - 0); + mem_info_t = &pdev->ipa_uc_rx_rsc.rx2_ind_ring->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1136,8 +1148,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx->mem_info)); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_SET(*msg_word, - 0); + mem_info_t = &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_SET(*msg_word, addr); msg_word++; *msg_word = 0; @@ -1146,8 +1159,9 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx->mem_info)); msg_word++; *msg_word = 0; - HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_SET(*msg_word, - 0); + mem_info_t = &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx->mem_info; + addr = (uint64_t)qdf_mem_get_dma_addr(pdev->osdev, mem_info_t) >> 32; + HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_SET(*msg_word, addr); SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, diff --git a/drivers/staging/qcacld-3.0/core/dp/htt/htt_types.h b/drivers/staging/qcacld-3.0/core/dp/htt/htt_types.h index a3045e62b48f..1e5f8de10f04 100644 --- a/drivers/staging/qcacld-3.0/core/dp/htt/htt_types.h +++ b/drivers/staging/qcacld-3.0/core/dp/htt/htt_types.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2011, 2014-2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -120,7 +121,7 @@ struct htt_ipa_uc_tx_resource_t { qdf_shared_mem_t *tx_ce_idx; qdf_shared_mem_t *tx_comp_ring; - uint32_t tx_comp_idx_paddr; + qdf_dma_addr_t tx_comp_idx_paddr; qdf_shared_mem_t **tx_buf_pool_strg; uint32_t alloc_tx_buf_cnt; bool ipa_smmu_mapped; diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c index 57459f61348a..38442ee5bc4c 100644 --- a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c +++ b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021, 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 above @@ -737,10 +738,10 @@ dp_fisa_rx_delete_flow(struct dp_rx_fst *fisa_hdl, sw_ft_entry->is_flow_tcp = elem->is_tcp_flow; sw_ft_entry->is_flow_udp = elem->is_udp_flow; - dp_rx_fisa_release_ft_lock(fisa_hdl, reo_id); - fisa_hdl->add_flow_count++; fisa_hdl->del_flow_count++; + + dp_rx_fisa_release_ft_lock(fisa_hdl, reo_id); } /** @@ -1645,7 +1646,6 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, hal_soc_handle_t hal_soc_hdl = fisa_hdl->soc_hdl->hal_soc; uint32_t hal_aggr_count; uint8_t napi_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); - uint8_t reo_id = fisa_flow->napi_id; uint32_t fse_metadata; dump_tlvs(hal_soc_hdl, rx_tlv_hdr, QDF_TRACE_LEVEL_INFO_HIGH); @@ -1653,6 +1653,7 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, nbuf, qdf_nbuf_next(nbuf), qdf_nbuf_data(nbuf), nbuf->len, nbuf->data_len); + dp_rx_fisa_acquire_ft_lock(fisa_hdl, napi_id); /* Packets of the flow are arriving on a different REO than * the one configured. */ @@ -1660,13 +1661,16 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, fse_metadata = hal_rx_msdu_fse_metadata_get(hal_soc_hdl, rx_tlv_hdr); if (fisa_hdl->del_flow_count && - fse_metadata != fisa_flow->metadata) + fse_metadata != fisa_flow->metadata) { + dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); return FISA_AGGR_NOT_ELIGIBLE; + } dp_err("REO id mismatch flow: %pK napi_id: %u nbuf: %pK reo_id: %u", fisa_flow, fisa_flow->napi_id, nbuf, napi_id); DP_STATS_INC(fisa_hdl, reo_mismatch, 1); QDF_BUG(0); + dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); return FISA_AGGR_NOT_ELIGIBLE; } @@ -1678,8 +1682,6 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, hal_aggr_count = hal_rx_get_fisa_flow_agg_count(hal_soc_hdl, rx_tlv_hdr); - dp_rx_fisa_acquire_ft_lock(fisa_hdl, reo_id); - if (!flow_aggr_cont) { /* Start of new aggregation for the flow * Flush previous aggregates for this flow @@ -1785,14 +1787,14 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, dp_rx_fisa_aggr_tcp(fisa_hdl, fisa_flow, nbuf); } - dp_rx_fisa_release_ft_lock(fisa_hdl, reo_id); + dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); fisa_flow->last_accessed_ts = qdf_get_log_timestamp(); return FISA_AGGR_DONE; invalid_fisa_assist: /* Not eligible aggregation deliver frame without FISA */ - dp_rx_fisa_release_ft_lock(fisa_hdl, reo_id); + dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); return FISA_AGGR_NOT_ELIGIBLE; } diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_txrx.h b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_txrx.h index a3c6e1ab15ba..de2a3cf30feb 100644 --- a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_txrx.h +++ b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_txrx.h @@ -245,6 +245,8 @@ static inline QDF_STATUS dp_txrx_suspend(ol_txrx_soc_handle soc) } qdf_status = dp_rx_tm_suspend(&dp_ext_hdl->rx_tm_hdl); + if (QDF_IS_STATUS_ERROR(qdf_status) && refill_thread->enabled) + dp_rx_refill_thread_resume(refill_thread); ret: return qdf_status; diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfr.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfr.h index 31279e39312d..947eb1d0745b 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfr.h +++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfr.h @@ -49,6 +49,24 @@ wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy, const void *data, int data_len); +#ifdef WLAN_ENH_CFR_ENABLE +/** + * hdd_cfr_disconnect() - Handle disconnection event in CFR + * @vdev: Pointer to vdev object + * + * Handle disconnection event in CFR. Stop CFR if it started and get + * disconnection event. + * + * Return: QDF status + */ +QDF_STATUS hdd_cfr_disconnect(struct wlan_objmgr_vdev *vdev); +#else +static inline QDF_STATUS +hdd_cfr_disconnect(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif extern const struct nla_policy cfr_config_policy[ QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1]; @@ -64,6 +82,11 @@ extern const struct nla_policy cfr_config_policy[ }, #else #define FEATURE_CFR_VENDOR_COMMANDS +static inline QDF_STATUS +hdd_cfr_disconnect(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} #endif /* WLAN_CFR_ENABLE */ #endif /* _WLAN_HDD_CFR_H */ diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h index 582c2944a402..a676d8d58033 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h +++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -1224,6 +1225,7 @@ struct hdd_context; * @delete_in_progress: Flag to indicate that the adapter delete is in * progress, and any operation using rtnl lock inside * the driver can be avoided/skipped. + * @mon_adapter: hdd_adapter of monitor mode. */ struct hdd_adapter { /* Magic cookie for adapter sanity verification. Note that this @@ -1435,6 +1437,7 @@ struct hdd_adapter { #ifdef WLAN_FEATURE_LINK_LAYER_STATS bool is_link_layer_stats_set; + uint8_t ll_stats_failure_count; #endif uint8_t link_status; uint8_t upgrade_udp_qos_threshold; @@ -1450,6 +1453,7 @@ struct hdd_adapter { /* BITMAP indicating pause reason */ uint32_t pause_map; + uint32_t subqueue_pause_map; spinlock_t pause_map_lock; qdf_time_t start_time; qdf_time_t last_time; @@ -1527,6 +1531,8 @@ struct hdd_adapter { uint8_t gro_disallowed[DP_MAX_RX_THREADS]; uint8_t gro_flushed[DP_MAX_RX_THREADS]; bool handle_feature_update; + /* Indicate if TSO and checksum offload features are enabled or not */ + bool tso_csum_feature_enabled; bool runtime_disable_rx_thread; ol_txrx_rx_fp rx_stack; @@ -1539,6 +1545,9 @@ struct hdd_adapter { #endif bool delete_in_progress; qdf_atomic_t net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX]; +#ifdef WLAN_FEATURE_PKT_CAPTURE + struct hdd_adapter *mon_adapter; +#endif }; #define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station) @@ -2162,7 +2171,7 @@ struct hdd_context { struct sar_limit_cmd_params *sar_cmd_params; #ifdef SAR_SAFETY_FEATURE qdf_mc_timer_t sar_safety_timer; - qdf_mc_timer_t sar_safety_unsolicited_timer; + struct qdf_delayed_work sar_safety_unsolicited_work; qdf_event_t sar_safety_req_resp_event; qdf_atomic_t sar_safety_req_resp_event_in_progress; #endif @@ -2212,6 +2221,9 @@ struct hdd_context { qdf_work_t twt_en_dis_work; #endif bool dump_in_progress; +#ifdef THERMAL_STATS_SUPPORT + bool is_therm_stats_in_progress; +#endif }; /** @@ -3346,6 +3358,20 @@ int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason); void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel, bool forced); +/** + * hdd_switch_sap_chan_freq() - Move SAP to the given channel + * @adapter: AP adapter + * @chan_freq: Channel frequency + * @forced: Force to switch channel, ignore SCC/MCC check + * + * Moves the SAP interface by invoking the function which + * executes the callback to perform channel switch using (E)CSA. + * + * Return: None + */ +void hdd_switch_sap_chan_freq(struct hdd_adapter *adapter, qdf_freq_t chan_freq, + bool forced); + #if defined(FEATURE_WLAN_CH_AVOID) void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctx); @@ -4715,6 +4741,22 @@ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, void wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx); +/** + * hdd_reset_monitor_interface() - reset monitor interface flags + * @sta_adapter: station adapter + * + * Return: void + */ +void hdd_reset_monitor_interface(struct hdd_adapter *sta_adapter); + +/** + * hdd_is_pkt_capture_mon_enable() - Is packet capture monitor mode enable + * @sta_adapter: station adapter + * + * Return: status of packet capture monitor adapter + */ +struct hdd_adapter * +hdd_is_pkt_capture_mon_enable(struct hdd_adapter *sta_adapter); #else static inline void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, @@ -4732,6 +4774,15 @@ static inline void wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx) { } + +static inline void hdd_reset_monitor_interface(struct hdd_adapter *sta_adapter) +{ +} + +static inline int hdd_is_pkt_capture_mon_enable(struct hdd_adapter *adapter) +{ + return 0; +} #endif /* WLAN_FEATURE_PKT_CAPTURE */ /** * wlan_hdd_is_session_type_monitor() - check if session type is MONITOR diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_assoc.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_assoc.c index f9bb1f539c33..eafa7ac91347 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_assoc.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_assoc.c @@ -84,6 +84,7 @@ #include "wlan_hdd_twt.h" #include "wma_api.h" +#include "wlan_hdd_cfr.h" /* These are needed to recognize WPA and RSN suite types */ #define HDD_WPA_OUI_SIZE 4 @@ -2059,7 +2060,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, /* update P2P connection status */ ucfg_p2p_status_disconnect(adapter->vdev); - + hdd_cfr_disconnect(adapter->vdev); if (adapter->device_mode == QDF_STA_MODE) { /* Inform BLM about the disconnection with the AP */ ucfg_blm_update_bssid_connect_params(hdd_ctx->pdev, @@ -2894,6 +2895,30 @@ void hdd_clear_fils_connection_info(struct hdd_adapter *adapter) } #endif +/** + * hdd_netif_features_update_required() - Check if feature update + * is required + * @adapter: pointer to the adapter structure + * Returns: true if the connection is legacy and TSO and Checksum offload + * enabled or if the connection is not latency and TSO and Checksum + * offload are not enabled, false otherwise + */ +static bool hdd_netif_features_update_required(struct hdd_adapter *adapter) +{ + bool is_legacy_connection = hdd_is_legacy_connection(adapter); + + hdd_debug("Legacy Connection: %d, TSO_CSUM Feature Enabled:%d", + is_legacy_connection, adapter->tso_csum_feature_enabled); + + if (adapter->tso_csum_feature_enabled && is_legacy_connection) + return true; + + if (!adapter->tso_csum_feature_enabled && !is_legacy_connection) + return true; + + return false; +} + /** * hdd_netif_queue_enable() - Enable the network queue for a * particular adapter. @@ -2911,17 +2936,17 @@ static inline void hdd_netif_queue_enable(struct hdd_adapter *adapter) ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - if (cdp_cfg_get(soc, cfg_dp_disable_legacy_mode_csum_offload)) { + if (cdp_cfg_get(soc, cfg_dp_disable_legacy_mode_csum_offload) && + hdd_netif_features_update_required(adapter)) { hdd_adapter_ops_record_event(hdd_ctx, WLAN_HDD_ADAPTER_OPS_WORK_POST, adapter->vdev_id); qdf_queue_work(0, hdd_ctx->adapter_ops_wq, &adapter->netdev_features_update_work); - } else { - wlan_hdd_netif_queue_control(adapter, - WLAN_WAKE_ALL_NETIF_QUEUE, - WLAN_CONTROL_PATH); } + wlan_hdd_netif_queue_control(adapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); } static void hdd_save_connect_status(struct hdd_adapter *adapter, @@ -3060,15 +3085,6 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, sta_ctx->ap_supports_immediate_power_save); } - /* Indicate 'connect' status to user space */ - hdd_send_association_event(dev, roam_info); - - if (policy_mgr_is_mcc_in_24G(hdd_ctx->psoc)) { - if (hdd_ctx->miracast_value) - wlan_hdd_set_mas(adapter, - hdd_ctx->miracast_value); - } - /* Initialize the Linkup event completion variable */ INIT_COMPLETION(adapter->linkup_event_var); @@ -3264,6 +3280,33 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, assoc_req_len = 0; } + if (!hddDisconInProgress) { + /* + * Perform any WMM-related association + * processing. + */ + hdd_wmm_assoc(adapter, roam_info, + eCSR_BSS_TYPE_INFRASTRUCTURE); + + /* + * Register the Station with DP after associated + */ + qdf_status = hdd_roam_register_sta(adapter, + roam_info, + roam_info->bss_desc); + hdd_debug("Enabling queues"); + hdd_netif_queue_enable(adapter); + } + + /* Indicate 'connect' status to user space */ + hdd_send_association_event(dev, roam_info); + + if (policy_mgr_is_mcc_in_24G(hdd_ctx->psoc)) { + if (hdd_ctx->miracast_value) + wlan_hdd_set_mas(adapter, + hdd_ctx->miracast_value); + } + if ((roam_info->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_FT_RSN) || (roam_info->u.pConnectedProfile->AuthType == @@ -3405,38 +3448,10 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, conn_info_freq); } } - if (!hddDisconInProgress) { - /* - * Perform any WMM-related association - * processing. - */ - hdd_wmm_assoc(adapter, roam_info, - eCSR_BSS_TYPE_INFRASTRUCTURE); - - /* - * Register the Station with DP after associated - */ - qdf_status = hdd_roam_register_sta(adapter, - roam_info, - roam_info->bss_desc); - hdd_debug("Enabling queues"); - hdd_netif_queue_enable(adapter); - } } else { - /* - * wpa supplicant expecting WPA/RSN IE in connect result - * in case of reassociation also need to indicate it to - * supplicant. - */ - sme_roam_get_wpa_rsn_req_ie( - mac_handle, - adapter->vdev_id, - &reqRsnLength, reqRsnIe); - cdp_hl_fc_set_td_limit(soc, adapter->vdev_id, conn_info_freq); - hdd_send_re_assoc_event(dev, adapter, roam_info, - reqRsnIe, reqRsnLength); + /* Reassoc successfully */ if (roam_info->fAuthRequired) { qdf_status = @@ -3474,7 +3489,30 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, /* Start the tx queues */ hdd_debug("Enabling queues"); hdd_netif_queue_enable(adapter); + + /* Indicate 'connect' status to user space */ + hdd_send_association_event(dev, roam_info); + + if (policy_mgr_is_mcc_in_24G(hdd_ctx->psoc)) { + if (hdd_ctx->miracast_value) + wlan_hdd_set_mas(adapter, + hdd_ctx->miracast_value); + } + + /* + * wpa supplicant expecting WPA/RSN IE in connect result + * in case of reassociation also need to indicate it to + * supplicant. + */ + sme_roam_get_wpa_rsn_req_ie( + mac_handle, + adapter->vdev_id, + &reqRsnLength, reqRsnIe); + + hdd_send_re_assoc_event(dev, adapter, roam_info, + reqRsnIe, reqRsnLength); } + qdf_mem_free(reqRsnIe); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c index 1708dce78f73..f1d379f90811 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -163,6 +164,9 @@ #include "wlan_if_mgr_public_struct.h" #include "wlan_wfa_ucfg_api.h" #include "wlan_roam_debug.h" +#include "wlan_pkt_capture_ucfg_api.h" +#include "os_if_pkt_capture.h" + #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -1700,6 +1704,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = FEATURE_TWT_VENDOR_EVENTS #endif FEATURE_CFR_DATA_VENDOR_EVENTS +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + [QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS, + }, +#endif }; /** @@ -7854,6 +7864,13 @@ static int hdd_config_vdev_chains(struct hdd_adapter *adapter, if (!tx_attr && !rx_attr) return 0; + /* if one is present, both must be present */ + if (!tx_attr || !rx_attr) { + hdd_err("Missing attribute for %s", + tx_attr ? "RX" : "TX"); + return -EINVAL; + } + tx_chains = nla_get_u8(tx_attr); rx_chains = nla_get_u8(rx_attr); @@ -7877,6 +7894,13 @@ static int hdd_config_tx_rx_nss(struct hdd_adapter *adapter, if (!tx_attr && !rx_attr) return 0; + /* if one is present, both must be present */ + if (!tx_attr || !rx_attr) { + hdd_err("Missing attribute for %s", + tx_attr ? "RX" : "TX"); + return -EINVAL; + } + tx_nss = nla_get_u8(tx_attr); rx_nss = nla_get_u8(rx_attr); hdd_debug("tx_nss %d rx_nss %d", tx_nss, rx_nss); @@ -15303,6 +15327,149 @@ err: } #endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * enum roam_stats_set_params - Different types of params to set the roam stats + * @ROAM_RT_STATS_DISABLED: Roam stats feature disabled + * @ROAM_RT_STATS_ENABLED: Roam stats feature enabled + * @ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE: Roam stats enabled in suspend mode + */ +enum roam_stats_set_params { + ROAM_RT_STATS_DISABLED = 0, + ROAM_RT_STATS_ENABLED = 1, + ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE = 2, +}; + +#define EVENTS_CONFIGURE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE +#define SUSPEND_STATE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE + +static const struct nla_policy +set_roam_events_policy[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE] = {.type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE] = {.type = NLA_FLAG}, +}; + +/** + * __wlan_hdd_cfg80211_set_roam_events() - set roam stats + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * Return: 0 on success; error number otherwise. + */ +static int __wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + 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_ROAM_EVENTS_MAX + 1]; + QDF_STATUS status; + int ret; + uint8_t config, state, param = 0; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) { + hdd_err("Invalid hdd_ctx"); + return ret; + } + + ret = hdd_validate_adapter(adapter); + if (ret != 0) { + hdd_err("Invalid adapter"); + return ret; + } + + if (adapter->device_mode != QDF_STA_MODE) { + hdd_err("STATS supported in only STA mode!"); + return -EINVAL; + } + + if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX, + data, data_len, set_roam_events_policy)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (!tb[EVENTS_CONFIGURE]) { + hdd_err("roam events configure not present"); + return -EINVAL; + } + + config = nla_get_u8(tb[EVENTS_CONFIGURE]); + hdd_debug("roam stats configured: %d", config); + + if (!tb[SUSPEND_STATE]) { + hdd_debug("suspend state not present"); + param = config ? ROAM_RT_STATS_ENABLED : ROAM_RT_STATS_DISABLED; + } else if (config == ROAM_RT_STATS_ENABLED) { + state = nla_get_flag(tb[SUSPEND_STATE]); + hdd_debug("Suspend state configured: %d", state); + param = ROAM_RT_STATS_ENABLED | + ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE; + } + + hdd_debug("roam events param: %d", param); + ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc, + param, ROAM_RT_STATS_ENABLE); + + if (param == (ROAM_RT_STATS_ENABLED | + ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE)) { + ucfg_pmo_enable_wakeup_event(hdd_ctx->psoc, adapter->vdev_id, + WOW_ROAM_STATS_EVENT); + ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc, + ROAM_RT_STATS_ENABLED, + ROAM_RT_STATS_SUSPEND_MODE_ENABLE); + } else if (ucfg_cm_get_roam_rt_stats(hdd_ctx->psoc, + ROAM_RT_STATS_SUSPEND_MODE_ENABLE)) { + ucfg_pmo_disable_wakeup_event(hdd_ctx->psoc, adapter->vdev_id, + WOW_ROAM_STATS_EVENT); + ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc, + ROAM_RT_STATS_DISABLED, + ROAM_RT_STATS_SUSPEND_MODE_ENABLE); + } + + status = ucfg_cm_roam_send_rt_stats_config(hdd_ctx->pdev, + adapter->vdev_id, param); + + return qdf_status_to_os_return(status); +} + +#undef EVENTS_CONFIGURE +#undef SUSPEND_STATE + +/** + * wlan_hdd_cfg80211_set_roam_events() - set roam stats + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * Return: 0 on success; error number otherwise. + */ +static int wlan_hdd_cfg80211_set_roam_events(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_roam_events(wiphy, wdev, + data, data_len); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} +#endif + /** * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi * @wiphy: wiphy pointer @@ -15431,6 +15598,92 @@ static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy, } #endif +#ifdef WLAN_FEATURE_PKT_CAPTURE + +/** + * __wlan_hdd_cfg80211_set_monitor_mode() - Wifi monitor mode configuration + * vendor command + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendor command data buffer + * @data_len: Buffer length + * + * Handles . + * + * Return: 0 for Success and negative value for failure + */ +static int +__wlan_hdd_cfg80211_set_monitor_mode(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); + int errno; + QDF_STATUS status; + + if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (!ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) + return -EPERM; + + errno = hdd_validate_adapter(adapter); + if (errno) + return errno; + + status = os_if_monitor_mode_configure(adapter, data, data_len); + + return qdf_status_to_os_return(status); +} + +/** + * wlan_hdd_cfg80211_set_monitor_mode() - set monitor mode + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * Return: 0 on success; error number otherwise. + */ +static int wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + hdd_enter_dev(wdev->netdev); + + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_set_monitor_mode(wiphy, wdev, + data, data_len); + + osif_vdev_sync_op_stop(vdev_sync); + + hdd_exit(); + + return errno; +} + +#undef SET_MONITOR_MODE_CONFIG_MAX +#undef SET_MONITOR_MODE_INVALID +#undef SET_MONITOR_MODE_DATA_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_DATA_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL + +#endif + /** * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi * @wiphy: wiphy pointer @@ -16305,6 +16558,23 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { FEATURE_THERMAL_VENDOR_COMMANDS FEATURE_BTC_CHAIN_MODE_COMMANDS FEATURE_WMM_COMMANDS + +#ifdef WLAN_FEATURE_PKT_CAPTURE + FEATURE_MONITOR_MODE_VENDOR_COMMANDS +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_roam_events, + vendor_command_policy(set_roam_events_policy, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX) + }, +#endif }; struct hdd_context *hdd_cfg80211_wiphy_alloc(void) @@ -20569,6 +20839,7 @@ static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter, assoc_add_ie->addIEdata; roam_profile->nAddIEAssocLength = assoc_add_ie->length; + roam_profile->is_hs_20_ap = true; } /* Appending OSEN Information Element in Assiciation Request */ else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE, @@ -21797,15 +22068,21 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) return -EINVAL; + status = wlan_hdd_validate_context(hdd_ctx); + + if (status) + return status; + + if (hdd_ctx->is_wiphy_suspended) { + hdd_info_rl("wiphy is suspended retry disconnect"); + return -EAGAIN; + } + qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_DISCONNECT, adapter->vdev_id, reason); hdd_print_netdev_txq_status(dev); - status = wlan_hdd_validate_context(hdd_ctx); - - if (0 != status) - return status; qdf_mutex_acquire(&adapter->disconnection_status_lock); if (adapter->disconnection_in_progress) { @@ -22670,7 +22947,15 @@ static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter, if (!vdev) return QDF_STATUS_E_FAILURE; - qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID); + qdf_mem_zero(&pmksa, sizeof(pmksa)); + if (!pmk_cache->ssid_len) { + qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID); + } else { + qdf_mem_copy(pmksa.ssid, pmk_cache->ssid, pmk_cache->ssid_len); + qdf_mem_copy(pmksa.cache_id, pmk_cache->cache_id, + WLAN_CACHE_ID_LEN); + pmksa.ssid_len = pmk_cache->ssid_len; + } result = wlan_crypto_set_del_pmksa(vdev, &pmksa, false); hdd_objmgr_put_vdev(vdev); diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h index 709cb911b882..f5e1d8b7fa9f 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h @@ -129,8 +129,6 @@ extern const struct nla_policy wlan_hdd_wisa_cmd_policy[ #define VENDOR1_AP_OUI_TYPE "\x00\xE0\x4C" #define VENDOR1_AP_OUI_TYPE_SIZE 3 -#define WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126 -#define WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 #define BASIC_RATE_MASK 0x80 #define RATE_MASK 0x7f diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfr.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfr.c index 7d9ac2d2b981..48961eb7ac76 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfr.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfr.c @@ -461,6 +461,30 @@ wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter, } #endif +static QDF_STATUS hdd_stop_enh_cfr(struct wlan_objmgr_vdev *vdev) +{ + if (!ucfg_cfr_get_rcc_enabled(vdev)) + return QDF_STATUS_SUCCESS; + + hdd_debug("cleanup rcc mode"); + wlan_objmgr_vdev_try_get_ref(vdev, WLAN_CFR_ID); + ucfg_cfr_set_rcc_mode(vdev, RCC_DIS_ALL_MODE, 0); + ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev), + false); + ucfg_cfr_committed_rcc_config(vdev); + ucfg_cfr_stop_indication(vdev); + ucfg_cfr_suspend(wlan_vdev_get_pdev(vdev)); + hdd_debug("stop indication done"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS hdd_cfr_disconnect(struct wlan_objmgr_vdev *vdev) +{ + return hdd_stop_enh_cfr(vdev); +} + static int wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter *adapter, struct nlattr **tb) @@ -497,21 +521,12 @@ wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter *adapter, QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP]); hdd_debug("params.en_cfg %d", params.en_cfg); ucfg_cfr_set_en_bitmap(vdev, ¶ms); - } else { - hdd_debug("cleanup rcc mode"); - ucfg_cfr_set_rcc_mode(vdev, RCC_DIS_ALL_MODE, 0); - } - - if (is_start_capture) ucfg_cfr_resume(wlan_vdev_get_pdev(vdev)); - - ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev), - is_start_capture); - ucfg_cfr_committed_rcc_config(vdev); - if (!is_start_capture) { - ucfg_cfr_stop_indication(vdev); - ucfg_cfr_suspend(wlan_vdev_get_pdev(vdev)); - hdd_debug("stop indication done"); + ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev), + true); + ucfg_cfr_committed_rcc_config(vdev); + } else { + hdd_stop_enh_cfr(vdev); } out: diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c index aba1d4b8a194..d7571f95f00a 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-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 @@ -625,6 +626,12 @@ static int __hdd_soc_probe(struct device *dev, goto dp_prealloc_fail; } + status = hif_ce_debug_history_prealloc_init(); + if (status != QDF_STATUS_SUCCESS) { + errno = qdf_status_to_os_return(status); + goto hif_ce_debug_history_prealloc_fail; + } + errno = hdd_wlan_startup(hdd_ctx); if (errno) goto hdd_context_destroy; @@ -649,6 +656,9 @@ wlan_exit: hdd_wlan_exit(hdd_ctx); hdd_context_destroy: + hif_ce_debug_history_prealloc_deinit(); + +hif_ce_debug_history_prealloc_fail: dp_prealloc_deinit(); dp_prealloc_fail: @@ -849,6 +859,7 @@ static void __hdd_soc_remove(struct device *dev) cds_set_driver_in_bad_state(false); cds_set_unload_in_progress(false); + hif_ce_debug_history_prealloc_deinit(); dp_prealloc_deinit(); pr_info("%s: Driver De-initialized\n", WLAN_MODULE_NAME); @@ -1201,9 +1212,12 @@ static int __wlan_hdd_bus_suspend(struct wow_enable_params wow_params) hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); err = wlan_hdd_validate_context(hdd_ctx); - if (err) - return err; - + if (0 != err) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return err; + } /* If Wifi is off, return success for system suspend */ if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) { @@ -1910,8 +1924,13 @@ static int wlan_hdd_pld_suspend(struct device *dev, hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); errno = wlan_hdd_validate_context(hdd_ctx); - if (errno) - return errno; + if (0 != errno) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return errno; + } + /* * Flush the idle shutdown before ops start.This is done here to avoid * the deadlock as idle shutdown waits for the dsc ops diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c index 8a03a3538f0b..9025e939a06c 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c @@ -120,6 +120,22 @@ #define MAX_SAP_NUM_CONCURRENCY_WITH_NAN 1 #endif +#ifndef BSS_MEMBERSHIP_SELECTOR_HT_PHY +#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 +#endif + +#ifndef BSS_MEMBERSHIP_SELECTOR_VHT_PHY +#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126 +#endif + +#ifndef BSS_MEMBERSHIP_SELECTOR_SAE_H2E +#define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123 +#endif + +#ifndef BSS_MEMBERSHIP_SELECTOR_HE_PHY +#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122 +#endif + /* * 11B, 11G Rate table include Basic rate and Extended rate * The IDX field is the rate index @@ -2940,6 +2956,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_chan_freq, struct sap_context *sap_ctx; uint8_t conc_rule1 = 0; uint8_t scc_on_lte_coex = 0; + uint8_t sta_sap_scc_on_dfs_chnl; bool is_p2p_go_session = false; struct wlan_objmgr_vdev *vdev; bool strict; @@ -2994,9 +3011,16 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_chan_freq, NULL); /* * For non-dbs HW, don't allow Channel switch on DFS channel if STA is - * not connected. + * not connected and sta_sap_scc_on_dfs_chnl is enabled. */ + status = policy_mgr_get_sta_sap_scc_on_dfs_chnl( + hdd_ctx->psoc, &sta_sap_scc_on_dfs_chnl); + if (QDF_STATUS_SUCCESS != status) { + return status; + } + if (!sta_cnt && !policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) && + !!sta_sap_scc_on_dfs_chnl && (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, target_chan_freq) || (wlan_reg_is_5ghz_ch_freq(target_chan_freq) && target_bw == CH_WIDTH_160MHZ))) { @@ -4028,15 +4052,36 @@ static void wlan_hdd_check_11gmode(const u8 *ie, u8 *require_ht, } } else { if ((BASIC_RATE_MASK | - WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == ie[i]) + BSS_MEMBERSHIP_SELECTOR_HT_PHY) == ie[i]) *require_ht = true; else if ((BASIC_RATE_MASK | - WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY) == ie[i]) + BSS_MEMBERSHIP_SELECTOR_VHT_PHY) == ie[i]) *require_vht = true; } } } +/** + * wlan_hdd_check_h2e() - check SAE/H2E require flag from support rate sets + * @rs: support rate or extended support rate set + * @require_h2e: pointer to store require h2e flag + * + * Return: none + */ +static void wlan_hdd_check_h2e(const tSirMacRateSet *rs, bool *require_h2e) +{ + uint8_t i; + + if (!rs || !require_h2e) + return; + + for (i = 0; i < rs->numRates; i++) { + if (rs->rate[i] == (BASIC_RATE_MASK | + BSS_MEMBERSHIP_SELECTOR_SAE_H2E)) + *require_h2e = true; + } +} + #ifdef WLAN_FEATURE_11AX /** * wlan_hdd_add_extn_ie() - add extension IE @@ -5669,6 +5714,12 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, config->extended_rates.rate, config->extended_rates.numRates); } + + config->require_h2e = false; + wlan_hdd_check_h2e(&config->supported_rates, + &config->require_h2e); + wlan_hdd_check_h2e(&config->extended_rates, + &config->require_h2e); } if (!cds_is_sub_20_mhz_enabled()) @@ -5842,7 +5893,7 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, goto error; } - qdf_status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, + qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event, SME_CMD_START_BSS_TIMEOUT); wlansap_reset_sap_config_add_ie(config, eUPDATE_IE_ALL); @@ -5859,7 +5910,8 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, hdd_set_connection_in_progress(false); sme_get_command_q_status(mac_handle); wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(adapter)); - QDF_ASSERT(0); + if (!cds_is_driver_recovering()) + QDF_ASSERT(0); ret = -EINVAL; goto error; } diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c index 9f3b4a5081dc..4abc434093c1 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -80,11 +81,20 @@ #define WLAN_PRIV_DATA_MAX_LEN 8192 /* - * Driver miracast parameters 0-Disabled + * Driver miracast parameters: + * 0-Disabled * 1-Source, 2-Sink + * 128: miracast connecting time optimization enabled. At present host + * will disable imps to reduce connection time for p2p. + * 129: miracast connecting time optimization disabled */ -#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0 -#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2 +enum miracast_param { + MIRACAST_DISABLED, + MIRACAST_SOURCE, + MIRACAST_SINK, + MIRACAST_CONN_OPT_ENABLED = 128, + MIRACAST_CONN_OPT_DISABLED = 129, +}; /* * When ever we need to print IBSSPEERINFOALL for more than 16 STA @@ -4866,12 +4876,34 @@ static int drv_cmd_miracast(struct hdd_adapter *adapter, ret = -EINVAL; goto exit; } - if ((filter_type < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL) || - (filter_type > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL)) { - hdd_err("Accepted Values are 0 to 2. 0-Disabled, 1-Source, 2-Sink"); + hdd_debug("filter_type %d", filter_type); + + switch (filter_type) { + case MIRACAST_DISABLED: + case MIRACAST_SOURCE: + case MIRACAST_SINK: + break; + case MIRACAST_CONN_OPT_ENABLED: + case MIRACAST_CONN_OPT_DISABLED: + { + bool is_imps_enabled = true; + + ucfg_mlme_is_imps_enabled(hdd_ctx->psoc, + &is_imps_enabled); + if (!is_imps_enabled) + return 0; + hdd_set_idle_ps_config( + hdd_ctx, + filter_type == + MIRACAST_CONN_OPT_ENABLED ? false : true); + return 0; + } + default: + hdd_err("accepted Values: 0-Disabled, 1-Source, 2-Sink, 128,129"); ret = -EINVAL; goto exit; } + /* Filtertype value should be either 0-Disabled, 1-Source, 2-sink */ hdd_ctx->miracast_value = filter_type; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c index 7641a0a8ac12..86c45ba664e9 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -196,6 +197,7 @@ #include "wlan_cm_roam_ucfg_api.h" #include #include "qdf_lock.h" +#include "wlan_hdd_thermal.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -2025,43 +2027,42 @@ static void hdd_update_tgt_vht_cap(struct hdd_context *hdd_ctx, hdd_err("unable to get vht_enable2x2"); if (vht_enable_2x2) { - if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) { - /* Update 2x2 Highest Short GI data rate */ + tx_highest_data_rate = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + rx_highest_data_rate = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + } else { + tx_highest_data_rate = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + rx_highest_data_rate = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } + + status = ucfg_mlme_cfg_set_vht_rx_supp_data_rate(hdd_ctx->psoc, + rx_highest_data_rate); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to set rx_supp_data_rate"); + + status = ucfg_mlme_cfg_set_vht_tx_supp_data_rate(hdd_ctx->psoc, + tx_highest_data_rate); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to set tx_supp_data_rate"); + + /* Update the real highest data rate to wiphy */ + if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) { + if (vht_enable_2x2) { tx_highest_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2_SGI80; rx_highest_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2_SGI80; } else { - /* Update 2x2 Rx Highest Long GI data Rate */ tx_highest_data_rate = - VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2; - rx_highest_data_rate = - VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2; - } - } else if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) { - /* Update 1x1 Highest Short GI data rate */ - tx_highest_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1_SGI80; - rx_highest_data_rate = + rx_highest_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1_SGI80; - } else { - /* Update 1x1 Highest Long GI data rate */ - tx_highest_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; - rx_highest_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } } - status = ucfg_mlme_cfg_set_vht_rx_supp_data_rate( - hdd_ctx->psoc, - rx_highest_data_rate); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to set rx_supp_data_rate"); - - status = ucfg_mlme_cfg_set_vht_tx_supp_data_rate( - hdd_ctx->psoc, - tx_highest_data_rate); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to set tx_supp_data_rate"); - if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu) band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu) @@ -2979,10 +2980,12 @@ static int __hdd_pktcapture_open(struct net_device *dev) ret = qdf_status_to_os_return(status); if (ret) { hdd_objmgr_put_vdev(adapter->vdev); + adapter->vdev = NULL; return ret; } set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); + sta_adapter->mon_adapter = adapter; return ret; } @@ -3013,69 +3016,86 @@ static int hdd_pktcapture_open(struct net_device *net_dev) } /** - * hdd_del_monitor_interface() - Delete monitor interface - * @hdd_ctx: hdd context + * hdd_unmap_monitor_interface_vdev() - unmap monitor interface vdev and + * deregister packet capture callbacks + * @sta_adapter: station adapter * * Return: void */ -static void hdd_del_monitor_interface(struct hdd_context *hdd_ctx) +static void +hdd_unmap_monitor_interface_vdev(struct hdd_adapter *sta_adapter) { - struct hdd_adapter *adapter; + struct hdd_adapter *mon_adapter = sta_adapter->mon_adapter; - adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); - if (adapter) { - struct osif_vdev_sync *vdev_sync; - - vdev_sync = osif_vdev_sync_unregister(adapter->dev); - - if (hdd_is_interface_up(adapter)) { - hdd_stop_adapter(hdd_ctx, adapter); - hdd_deinit_adapter(hdd_ctx, adapter, - true); - } - - hdd_close_adapter(hdd_ctx, adapter, true); - - if (vdev_sync) { - osif_vdev_sync_wait_for_ops(vdev_sync); - osif_vdev_sync_destroy(vdev_sync); - } + if (mon_adapter && hdd_is_interface_up(mon_adapter)) { + ucfg_pkt_capture_deregister_callbacks(mon_adapter->vdev); + hdd_objmgr_put_vdev(mon_adapter->vdev); + mon_adapter->vdev = NULL; + hdd_reset_monitor_interface(sta_adapter); } } /** - * hdd_close_monitor_interface() - Close monitor interface - * @hdd_ctx: hdd context + * hdd_map_monitor_interface_vdev() - Map monitor interface vdev and + * register packet capture callbacks + * @sta_adapter: Station adapter * - * Return: void + * Return: None */ -static void hdd_close_monitor_interface(struct hdd_context *hdd_ctx) +static void hdd_map_monitor_interface_vdev(struct hdd_adapter *sta_adapter) { - struct hdd_adapter *adapter; + struct hdd_adapter *mon_adapter; + QDF_STATUS status; + int ret; - adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); - if (adapter) { - struct osif_vdev_sync *vdev_sync; - - vdev_sync = osif_vdev_sync_unregister( - adapter->dev); - - wlan_hdd_del_monitor(hdd_ctx, adapter, true); - - if (vdev_sync) { - osif_vdev_sync_wait_for_ops(vdev_sync); - osif_vdev_sync_destroy(vdev_sync); - } + mon_adapter = hdd_get_adapter(sta_adapter->hdd_ctx, QDF_MONITOR_MODE); + if (!mon_adapter) { + hdd_debug("No monitor interface found"); + return; } + + if (!mon_adapter || !hdd_is_interface_up(mon_adapter)) { + hdd_debug("Monitor interface is not up\n"); + return; + } + + if (!wlan_hdd_is_session_type_monitor(mon_adapter->device_mode)) + return; + + mon_adapter->vdev = hdd_objmgr_get_vdev(sta_adapter); + + status = ucfg_pkt_capture_register_callbacks(mon_adapter->vdev, + hdd_mon_rx_packet_cbk, + mon_adapter); + ret = qdf_status_to_os_return(status); + if (ret) { + hdd_err("Failed registering packet capture callbacks"); + hdd_objmgr_put_vdev(mon_adapter->vdev); + mon_adapter->vdev = NULL; + return; + } + + sta_adapter->mon_adapter = mon_adapter; +} + +void hdd_reset_monitor_interface(struct hdd_adapter *sta_adapter) +{ + sta_adapter->mon_adapter = NULL; +} + +struct hdd_adapter * +hdd_is_pkt_capture_mon_enable(struct hdd_adapter *sta_adapter) +{ + return sta_adapter->mon_adapter; } #else static inline void -hdd_del_monitor_interface(struct hdd_context *hdd_ctx) +hdd_unmap_monitor_interface_vdev(struct hdd_adapter *sta_adapter) { } static inline void -hdd_close_monitor_interface(struct hdd_context *hdd_ctx) +hdd_map_monitor_interface_vdev(struct hdd_adapter *sta_adapter) { } #endif @@ -4414,6 +4434,10 @@ static int __hdd_open(struct net_device *dev) hdd_populate_wifi_pos_cfg(hdd_ctx); hdd_lpass_notify_start(hdd_ctx, adapter); + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) + hdd_map_monitor_interface_vdev(adapter); + return 0; } @@ -4490,23 +4514,9 @@ int hdd_stop_no_trans(struct net_device *dev) WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); - if (adapter->device_mode == QDF_STA_MODE) { + if (adapter->device_mode == QDF_STA_MODE) hdd_lpass_notify_stop(hdd_ctx); - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != - PACKET_CAPTURE_MODE_DISABLE) - hdd_close_monitor_interface(hdd_ctx); - } - - if (wlan_hdd_is_session_type_monitor(adapter->device_mode) && - adapter->vdev && - ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != - PACKET_CAPTURE_MODE_DISABLE) { - ucfg_pkt_capture_deregister_callbacks(adapter->vdev); - hdd_objmgr_put_vdev(adapter->vdev); - adapter->vdev = NULL; - } - /* * NAN data interface is different in some sense. The traffic on NDI is * bursty in nature and depends on the need to transfer. The service @@ -4882,6 +4892,54 @@ void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx, QDF_MAC_ADDR_REF(releaseAddr)); } +/** + * hdd_set_derived_multicast_list(): Add derived peer multicast address list in + * multicast list request to the FW + * @psoc: Pointer to psoc + * @adapter: Pointer to hdd adapter + * @mc_list_request: Multicast list request to the FW + * @mc_count: number of multicast addresses received from the kernel + * + * Return: None + */ +static void +hdd_set_derived_multicast_list(struct wlan_objmgr_psoc *psoc, + struct hdd_adapter *adapter, + struct pmo_mc_addr_list_params *mc_list_request, + int *mc_count) +{ + int i = 0, j = 0, list_count = *mc_count; + struct qdf_mac_addr *peer_mc_addr_list = NULL; + uint8_t driver_mc_cnt = 0; + uint32_t max_ndp_sessions = 0; + + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + + ucfg_nan_get_peer_mc_list(adapter->vdev, &peer_mc_addr_list); + + for (j = 0; j < max_ndp_sessions; j++) { + for (i = 0; i < list_count; i++) { + if (qdf_is_macaddr_zero(&peer_mc_addr_list[j]) || + qdf_is_macaddr_equal(&mc_list_request->mc_addr[i], + &peer_mc_addr_list[j])) + break; + } + if (i == list_count) { + qdf_mem_copy( + &(mc_list_request->mc_addr[list_count + + driver_mc_cnt].bytes), + peer_mc_addr_list[j].bytes, ETH_ALEN); + hdd_debug("mlist[%d] = " QDF_MAC_ADDR_FMT, + list_count + driver_mc_cnt, + QDF_MAC_ADDR_REF( + mc_list_request->mc_addr[list_count + + driver_mc_cnt].bytes)); + driver_mc_cnt++; + } + } + *mc_count += driver_mc_cnt; +} + /** * __hdd_set_multicast_list() - set the multicast address list * @dev: Pointer to the WLAN device. @@ -4957,6 +5015,11 @@ static void __hdd_set_multicast_list(struct net_device *dev) QDF_MAC_ADDR_REF(mc_list_request->mc_addr[i].bytes)); i++; } + + if (adapter->device_mode == QDF_NDI_MODE) + hdd_set_derived_multicast_list(psoc, adapter, + mc_list_request, + &mc_count); } adapter->mc_addr_list.mc_cnt = mc_count; @@ -5021,13 +5084,15 @@ static netdev_features_t __hdd_fix_features(struct net_device *net_dev, } feature_tso_csum = hdd_get_tso_csum_feature_flags(); - if (hdd_is_legacy_connection(adapter)) + if (hdd_is_legacy_connection(adapter)) { /* Disable checksum and TSO */ feature_change_req &= ~feature_tso_csum; - else + adapter->tso_csum_feature_enabled = 0; + } else { /* Enable checksum and TSO */ feature_change_req |= feature_tso_csum; - + adapter->tso_csum_feature_enabled = 1; + } hdd_debug("vdev mode %d current features 0x%llx, requesting feature change 0x%llx", adapter->device_mode, net_dev->features, feature_change_req); @@ -5062,7 +5127,7 @@ static netdev_features_t hdd_fix_features(struct net_device *net_dev, return changed_features; } /** - * __hdd_set_features - Update device config for resultant change in feature + * __hdd_set_features - Notify device about change in features * @net_dev: Handle to net_device * @features: Existing + requested feature after resolving the dependency * @@ -5072,7 +5137,6 @@ static int __hdd_set_features(struct net_device *net_dev, netdev_features_t features) { struct hdd_adapter *adapter = netdev_priv(net_dev); - cdp_config_param_type vdev_param; ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); if (!adapter->handle_feature_update) { @@ -5089,15 +5153,6 @@ static int __hdd_set_features(struct net_device *net_dev, adapter->device_mode, adapter->vdev_id, net_dev->features, features); - if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) - vdev_param.cdp_enable_tx_checksum = true; - else - vdev_param.cdp_enable_tx_checksum = false; - - if (cdp_txrx_set_vdev_param(soc, adapter->vdev_id, CDP_ENABLE_CSUM, - vdev_param)) - hdd_debug("Failed to set DP vdev params"); - return 0; } @@ -7215,9 +7270,11 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, hdd_destroy_adapter_sysfs_files(adapter); if (adapter->device_mode == QDF_STA_MODE && + hdd_is_pkt_capture_mon_enable(adapter) && ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != - PACKET_CAPTURE_MODE_DISABLE) - hdd_del_monitor_interface(hdd_ctx); + PACKET_CAPTURE_MODE_DISABLE) { + hdd_unmap_monitor_interface_vdev(adapter); + } if (adapter->vdev_id != WLAN_UMAC_VDEV_ID_MAX) wlan_hdd_cfg80211_deregister_frames(adapter); @@ -7345,14 +7402,24 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, break; case QDF_MONITOR_MODE: - if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) && + if (wlan_hdd_is_session_type_monitor(adapter->device_mode) && adapter->vdev && ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != PACKET_CAPTURE_MODE_DISABLE) { + struct hdd_adapter *sta_adapter; + ucfg_pkt_capture_deregister_callbacks(adapter->vdev); hdd_objmgr_put_vdev(adapter->vdev); adapter->vdev = NULL; + + sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); + if (!sta_adapter) { + hdd_err("No station interface found"); + return -EINVAL; + } + hdd_reset_monitor_interface(sta_adapter); } + if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) && ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) { hdd_info("Release wakelock for STA + monitor mode!"); @@ -7656,9 +7723,11 @@ void hdd_set_netdev_flags(struct hdd_adapter *adapter) adapter->dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - if (cdp_cfg_get(soc, cfg_dp_tso_enable) && enable_csum) + if (cdp_cfg_get(soc, cfg_dp_tso_enable) && enable_csum) { adapter->dev->features |= (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG); + adapter->tso_csum_feature_enabled = 1; + } adapter->dev->features |= NETIF_F_RXCSUM; temp = (uint64_t)adapter->dev->features; @@ -8513,7 +8582,6 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx) { struct hdd_adapter *adapter, *next_adapter = NULL; bool value; - struct wlan_objmgr_vdev *vdev; wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_START_ALL_ADAPTERS; hdd_enter(); @@ -8579,19 +8647,19 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx) break; case QDF_MONITOR_MODE: if (wlan_hdd_is_session_type_monitor( - QDF_MONITOR_MODE) && + adapter->device_mode) && ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != PACKET_CAPTURE_MODE_DISABLE) { - vdev = hdd_objmgr_get_vdev(adapter); - if (vdev) { - ucfg_pkt_capture_register_callbacks( - vdev, - hdd_mon_rx_packet_cbk, - adapter); - hdd_objmgr_put_vdev(vdev); - } else { - hdd_err("vdev is null"); + struct hdd_adapter *sta_adapter; + + sta_adapter = hdd_get_adapter(hdd_ctx, + QDF_STA_MODE); + if (!sta_adapter) { + hdd_err("No station interface found"); + return -EINVAL; } + + hdd_map_monitor_interface_vdev(sta_adapter); break; } hdd_start_station_adapter(adapter); @@ -10619,24 +10687,16 @@ __hdd_adapter_param_update_work(struct hdd_adapter *adapter) { /** * This check is needed in case the work got scheduled after the - * interface got disconnected. During disconnection, the network queues - * are paused and hence should not be, mistakenly, restarted here. - * There are two approaches to handle this case - * 1) Flush the work during disconnection - * 2) Check for connected state in work - * - * Since the flushing of work during disconnection will need to be - * done at multiple places or entry points, instead its preferred to - * check the connection state and skip the operation here. + * interface got disconnected. + * Netdev features update is to be done only after the connection, + * since the connection mode plays an important role in identifying + * the features that are to be updated. + * So in case of interface disconnect skip feature update. */ if (!hdd_adapter_is_connected_sta(adapter)) return; hdd_netdev_update_features(adapter); - - hdd_debug("Enabling queues"); - wlan_hdd_netif_queue_control(adapter, WLAN_WAKE_ALL_NETIF_QUEUE, - WLAN_CONTROL_PATH); } /** @@ -11340,6 +11400,30 @@ void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel, hdd_ap_ctx->sap_config.ch_width_orig, forced); } +void hdd_switch_sap_chan_freq(struct hdd_adapter *adapter, qdf_freq_t chan_freq, + bool forced) +{ + struct hdd_ap_ctx *hdd_ap_ctx; + struct hdd_context *hdd_ctx; + + if (hdd_validate_adapter(adapter)) + return; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if(wlan_hdd_validate_context(hdd_ctx)) + return; + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + + hdd_debug("chan freq:%d width:%d", + chan_freq, hdd_ap_ctx->sap_config.ch_width_orig); + + policy_mgr_change_sap_channel_with_csa( + hdd_ctx->psoc, adapter->vdev_id, chan_freq, + hdd_ap_ctx->sap_config.ch_width_orig, forced); +} + int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason) { struct hdd_external_acs_timer_context *timer_context; @@ -11381,7 +11465,7 @@ int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason) * Return - none */ static void -hdd_store_sap_restart_channel(uint8_t restart_chan, uint8_t *restart_chan_store) +hdd_store_sap_restart_channel(qdf_freq_t restart_chan, qdf_freq_t *restart_chan_store) { uint8_t i; @@ -11412,8 +11496,7 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) struct hdd_adapter *adapter, *next_adapter = NULL; uint32_t i; bool found = false; - uint8_t restart_chan_store[SAP_MAX_NUM_SESSION] = {0}; - uint8_t restart_chan, ap_chan; + qdf_freq_t restart_chan_store[SAP_MAX_NUM_SESSION] = {0}; uint8_t scc_on_lte_coex = 0; uint32_t restart_freq, ap_chan_freq; bool value; @@ -11434,9 +11517,6 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) continue; } - ap_chan = wlan_reg_freq_to_chan( - hdd_ctxt->pdev, - adapter->session.ap.operating_chan_freq); ap_chan_freq = adapter->session.ap.operating_chan_freq; found = false; @@ -11470,10 +11550,10 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) } if (!found) { hdd_store_sap_restart_channel( - ap_chan, + ap_chan_freq, restart_chan_store); - hdd_debug("ch:%d is safe. no need to change channel", - ap_chan); + hdd_debug("ch freq:%d is safe. no need to change channel", + ap_chan_freq); hdd_adapter_dev_put_debug(adapter, dbgid); continue; } @@ -11497,27 +11577,25 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) continue; } - restart_chan = 0; + restart_freq = 0; for (i = 0; i < SAP_MAX_NUM_SESSION; i++) { if (!restart_chan_store[i]) continue; if (policy_mgr_is_force_scc(hdd_ctxt->psoc) && - WLAN_REG_IS_SAME_BAND_CHANNELS( + WLAN_REG_IS_SAME_BAND_FREQS( restart_chan_store[i], - ap_chan)) { - restart_chan = restart_chan_store[i]; + ap_chan_freq)) { + restart_freq = restart_chan_store[i]; break; } } - if (!restart_chan) { + if (!restart_freq) { restart_freq = wlansap_get_safe_channel_from_pcl_and_acs_range( WLAN_HDD_GET_SAP_CTX_PTR(adapter)); - restart_chan = wlan_reg_freq_to_chan(hdd_ctxt->pdev, - restart_freq); } - if (!restart_chan) { + if (!restart_freq) { hdd_err("fail to restart SAP"); } else { /* @@ -11535,8 +11613,8 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) wlan_hdd_set_sap_csa_reason(hdd_ctxt->psoc, adapter->vdev_id, CSA_REASON_UNSAFE_CHANNEL); - hdd_switch_sap_channel(adapter, restart_chan, - true); + hdd_switch_sap_chan_freq(adapter, restart_freq, + true); hdd_adapter_dev_put_debug(adapter, dbgid); if (next_adapter) hdd_adapter_dev_put_debug(next_adapter, @@ -12141,8 +12219,19 @@ int hdd_psoc_idle_shutdown(struct device *dev) if (is_mode_change_psoc_idle_shutdown) ret = __hdd_mode_change_psoc_idle_shutdown(hdd_ctx); - else + else { + /* + * This is to handle scenario in which platform driver triggers + * idle_shutdown if Deep Sleep/Hibernate entry notification is + * received from modem subsystem in wearable devices + */ + if (hdd_is_any_interface_open(hdd_ctx)) { + hdd_err_rl("all interfaces are not down, ignore idle shutdown"); + return -EINVAL; + } + ret = __hdd_psoc_idle_shutdown(hdd_ctx); + } return ret; } @@ -13510,6 +13599,7 @@ static int hdd_pre_enable_configure(struct hdd_context *hdd_ctx) int ret; uint8_t val = 0; uint8_t max_retry = 0; + uint32_t tx_retry_multiplier; QDF_STATUS status; void *soc = cds_get_context(QDF_MODULE_ID_SOC); @@ -13560,6 +13650,16 @@ static int hdd_pre_enable_configure(struct hdd_context *hdd_ctx) goto out; } + wlan_mlme_get_tx_retry_multiplier(hdd_ctx->psoc, + &tx_retry_multiplier); + ret = sme_cli_set_command(0, WMI_PDEV_PARAM_PDEV_STATS_TX_XRETRY_EXT, + tx_retry_multiplier, PDEV_CMD); + if (0 != ret) { + hdd_err("WMI_PDEV_PARAM_PDEV_STATS_TX_XRETRY_EXT failed %d", + ret); + goto out; + } + ret = hdd_set_smart_chainmask_enabled(hdd_ctx); if (ret) goto out; @@ -13856,6 +13956,42 @@ static int hdd_init_mws_coex(struct hdd_context *hdd_ctx) } #endif +#ifdef THERMAL_STATS_SUPPORT +static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx) +{ + hdd_send_get_thermal_stats_cmd(hdd_ctx, thermal_stats_init, NULL, NULL); +} +#else +static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx) +{ +} +#endif + +#ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER +/** + * hdd_cal_fail_send_event()- send calibration failure information + * @cal_type: calibration type + * @reason: reason for calibration failure + * + * This Function sends calibration failure diag event + * + * Return: void. + */ +static void hdd_cal_fail_send_event(uint8_t cal_type, uint8_t reason) +{ + /* + * For now we are going with the print. Once CST APK has support to + * read the diag events then we will add the diag event here. + */ + hdd_debug("Received cal failure event with cal_type:%x reason:%x", + cal_type, reason); +} +#else +static inline void hdd_cal_fail_send_event(uint8_t cal_type, uint8_t reason) +{ +} +#endif + /** * hdd_features_init() - Init features * @hdd_ctx: HDD context @@ -13970,6 +14106,9 @@ static int hdd_features_init(struct hdd_context *hdd_ctx) wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc, ALLOWED_KEYMGMT_6G_MASK); } + hdd_thermal_stats_cmd_init(hdd_ctx); + sme_set_cal_failure_event_cb(hdd_ctx->mac_handle, + hdd_cal_fail_send_event); hdd_exit(); return 0; @@ -15381,6 +15520,9 @@ int hdd_register_cb(struct hdd_context *hdd_ctx) sme_stats_ext2_register_callback(mac_handle, wlan_hdd_cfg80211_stats_ext2_callback); + sme_roam_events_register_callback(mac_handle, + wlan_hdd_cfg80211_roam_events_callback); + sme_set_rssi_threshold_breached_cb(mac_handle, hdd_rssi_threshold_breached); @@ -15490,6 +15632,7 @@ void hdd_deregister_cb(struct hdd_context *hdd_ctx) hdd_err("Failed to de-register data stall detect event callback"); sme_deregister_oem_data_rsp_callback(mac_handle); + sme_roam_events_deregister_callback(mac_handle); hdd_exit(); } @@ -16142,7 +16285,7 @@ void wlan_hdd_start_sap(struct hdd_adapter *ap_adapter, bool reinit) goto end; hdd_debug("Waiting for SAP to start"); - qdf_status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, + qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event, SME_CMD_START_BSS_TIMEOUT); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { hdd_err("SAP Start failed"); @@ -18392,7 +18535,7 @@ void hdd_restart_sap(struct hdd_adapter *ap_adapter) hdd_info("Waiting for SAP to start"); qdf_status = - qdf_wait_for_event_completion(&hostapd_state->qdf_event, + qdf_wait_single_event(&hostapd_state->qdf_event, SME_CMD_START_BSS_TIMEOUT); wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); @@ -18686,11 +18829,6 @@ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, hdd_stop_adapter(hdd_ctx, adapter); hdd_close_adapter(hdd_ctx, adapter, true); - if (adapter->vdev) { - hdd_objmgr_put_vdev(adapter->vdev); - adapter->vdev = NULL; - } - hdd_open_p2p_interface(hdd_ctx); } diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_nan_datapath.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_nan_datapath.c index 3bddacd15109..95d4278fee54 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_nan_datapath.c @@ -1047,6 +1047,8 @@ void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id, if (last_peer) { hdd_debug("No more ndp peers."); + ucfg_nan_clear_peer_mc_list(hdd_ctx->psoc, adapter->vdev, + peer_mac_addr); hdd_cleanup_ndi(hdd_ctx, adapter); qdf_event_set(&adapter->peer_cleanup_done); /* diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c index feb31b144ece..16cc1e458c3d 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 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 @@ -527,7 +528,7 @@ int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command) noa.single_noa_duration = duration; noa.ps_selection = P2P_POWER_SAVE_TYPE_SINGLE_NOA; } else { - if (duration >= interval) { + if (count && (duration >= interval)) { hdd_err("Duration should be less than interval"); return -EINVAL; } diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c index f74dca2dee93..41b1fd7db772 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 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 @@ -1638,6 +1639,8 @@ QDF_STATUS hdd_wlan_shutdown(void) hdd_ctx->is_scheduler_suspended = false; hdd_ctx->is_wiphy_suspended = false; hdd_ctx->hdd_wlan_suspended = false; + ucfg_pmo_resume_all_components(hdd_ctx->psoc, + QDF_SYSTEM_SUSPEND); } wlan_hdd_rx_thread_resume(hdd_ctx); @@ -2237,8 +2240,12 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, } rc = wlan_hdd_validate_context(hdd_ctx); - if (0 != rc) - return rc; + if (0 != rc) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return rc; + } if (hdd_ctx->config->is_wow_disabled) { hdd_info_rl("wow is disabled"); @@ -2451,8 +2458,12 @@ static int _wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, } errno = wlan_hdd_validate_context(hdd_ctx); - if (errno) - return errno; + if (0 != errno) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return errno; + } hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); if (!hif_ctx) @@ -2479,8 +2490,12 @@ int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, struct hdd_context *hdd_ctx = wiphy_priv(wiphy); errno = wlan_hdd_validate_context(hdd_ctx); - if (0 != errno) - return errno; + if (0 != errno) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return errno; + } /* * Flush the idle shutdown before ops start.This is done here to avoid @@ -2923,7 +2938,8 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, case QDF_STA_MODE: case QDF_P2P_CLIENT_MODE: sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - if (sta_ctx->hdd_reassoc_scenario) { + if (sta_ctx->hdd_reassoc_scenario || + hdd_is_roaming_in_progress(hdd_ctx)) { hdd_debug("Roaming is in progress, rej this req"); return -EINVAL; } diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_regulatory.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_regulatory.c index 4ef4e33e8d35..d8383f10b0a3 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_regulatory.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_regulatory.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -122,7 +123,7 @@ hdd_world_regrules_67_68_6A_6C = { } }; -#define OSIF_PSOC_SYNC_OP_WAIT_TIME 500 +#define COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME 30 /** * hdd_get_world_regrules() - get the appropriate world regrules * @reg: regulatory data @@ -1532,8 +1533,8 @@ static void hdd_restart_sap_with_new_phymode(struct hdd_context *hdd_ctx, hdd_err("SAP Start Bss fail"); return; } - status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, - SME_CMD_START_BSS_TIMEOUT); + status = qdf_wait_single_event(&hostapd_state->qdf_event, + SME_CMD_START_BSS_TIMEOUT); if (!QDF_IS_STATUS_SUCCESS(status)) { mutex_unlock(&hdd_ctx->sap_lock); hdd_err("SAP Start timeout"); @@ -1647,7 +1648,7 @@ static void hdd_country_change_work_handle(void *arg) errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); if (errno == -EAGAIN) { - qdf_sleep(OSIF_PSOC_SYNC_OP_WAIT_TIME); + qdf_sleep(COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME); hdd_debug("rescheduling country change work"); qdf_sched_work(0, &hdd_ctx->country_change_work); return; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sar_limits.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sar_limits.c index 5d6735db7b9c..e51ae8ac56ea 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sar_limits.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sar_limits.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -993,14 +994,29 @@ static void hdd_send_sar_unsolicited_event(struct hdd_context *hdd_ctx) cfg80211_vendor_event(vendor_event, GFP_KERNEL); } -static void hdd_sar_unsolicited_timer_cb(void *user_data) +static void hdd_sar_unsolicited_work_cb(void *user_data) { struct hdd_context *hdd_ctx = (struct hdd_context *)user_data; uint8_t i = 0; QDF_STATUS status; + int errno; + struct osif_psoc_sync *psoc_sync; hdd_nofl_debug("Sar unsolicited timer expired"); + errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); + + if (errno == -EAGAIN) { + hdd_nofl_debug("rescheduling sar unsolicited work"); + qdf_delayed_work_start(&hdd_ctx->sar_safety_unsolicited_work, + hdd_ctx->config->sar_safety_unsolicited_timeout); + + return; + } else if (errno) { + hdd_err("cannot handle sar unsolicited work"); + return; + } + qdf_atomic_set(&hdd_ctx->sar_safety_req_resp_event_in_progress, 1); for (i = 0; i < hdd_ctx->config->sar_safety_req_resp_retry; i++) { @@ -1017,6 +1033,8 @@ static void hdd_sar_unsolicited_timer_cb(void *user_data) if (i >= hdd_ctx->config->sar_safety_req_resp_retry) hdd_configure_sar_index(hdd_ctx, hdd_ctx->config->sar_safety_index); + + osif_psoc_sync_op_stop(psoc_sync); } static void hdd_sar_safety_timer_cb(void *user_data) @@ -1029,8 +1047,6 @@ static void hdd_sar_safety_timer_cb(void *user_data) void wlan_hdd_sar_unsolicited_timer_start(struct hdd_context *hdd_ctx) { - QDF_STATUS status; - if (!hdd_ctx->config->enable_sar_safety) return; @@ -1038,16 +1054,10 @@ void wlan_hdd_sar_unsolicited_timer_start(struct hdd_context *hdd_ctx) &hdd_ctx->sar_safety_req_resp_event_in_progress) > 0) return; - if (QDF_TIMER_STATE_RUNNING != - qdf_mc_timer_get_current_state( - &hdd_ctx->sar_safety_unsolicited_timer)) { - status = qdf_mc_timer_start( - &hdd_ctx->sar_safety_unsolicited_timer, - hdd_ctx->config->sar_safety_unsolicited_timeout); + qdf_delayed_work_start(&hdd_ctx->sar_safety_unsolicited_work, + hdd_ctx->config->sar_safety_unsolicited_timeout); - if (QDF_IS_STATUS_SUCCESS(status)) - hdd_nofl_debug("sar unsolicited timer started"); - } + hdd_nofl_debug("sar safety unsolicited work started"); } void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) @@ -1072,20 +1082,16 @@ void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) if (QDF_IS_STATUS_SUCCESS(status)) hdd_nofl_debug("sar safety timer started"); - if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state( - &hdd_ctx->sar_safety_unsolicited_timer)) { - status = qdf_mc_timer_stop( - &hdd_ctx->sar_safety_unsolicited_timer); - if (QDF_IS_STATUS_SUCCESS(status)) - hdd_nofl_debug("sar unsolicited timer stopped"); - } + qdf_delayed_work_stop_sync(&hdd_ctx->sar_safety_unsolicited_work); + hdd_nofl_debug("sar safety unsolicited work stopped"); qdf_event_set(&hdd_ctx->sar_safety_req_resp_event); } void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) { + QDF_STATUS status; + if (!hdd_ctx->config->enable_sar_safety) return; @@ -1094,9 +1100,13 @@ void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) qdf_mc_timer_init(&hdd_ctx->sar_safety_timer, QDF_TIMER_TYPE_SW, hdd_sar_safety_timer_cb, hdd_ctx); - qdf_mc_timer_init(&hdd_ctx->sar_safety_unsolicited_timer, - QDF_TIMER_TYPE_SW, - hdd_sar_unsolicited_timer_cb, hdd_ctx); + status = qdf_delayed_work_create(&hdd_ctx->sar_safety_unsolicited_work, + hdd_sar_unsolicited_work_cb, + hdd_ctx); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("failed to create sar safety unsolicited work"); + return; + } qdf_atomic_init(&hdd_ctx->sar_safety_req_resp_event_in_progress); qdf_event_create(&hdd_ctx->sar_safety_req_resp_event); @@ -1117,12 +1127,7 @@ void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) qdf_mc_timer_destroy(&hdd_ctx->sar_safety_timer); - if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state( - &hdd_ctx->sar_safety_unsolicited_timer)) - qdf_mc_timer_stop(&hdd_ctx->sar_safety_unsolicited_timer); - - qdf_mc_timer_destroy(&hdd_ctx->sar_safety_unsolicited_timer); + qdf_delayed_work_destroy(&hdd_ctx->sar_safety_unsolicited_work); qdf_event_destroy(&hdd_ctx->sar_safety_req_resp_event); diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_station_info.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_station_info.c index d67a79f7f683..58cd393632f6 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_station_info.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_station_info.c @@ -43,6 +43,7 @@ #include #include #include +#include "wlan_hdd_stats.h" /* * define short names for the global vendor params @@ -2417,8 +2418,17 @@ int32_t hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy, if (errno) return errno; + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); + goto end; + } + errno = __hdd_cfg80211_get_sta_info_cmd(wiphy, wdev, data, data_len); + wlan_hdd_qmi_put_suspend(); + +end: osif_vdev_sync_op_stop(vdev_sync); return errno; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c index aa0b8612e7db..7ff007d68a2b 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -89,6 +90,7 @@ #endif /* kernel version less than 4.0.0 && no_backport */ #define HDD_LINK_STATS_MAX 5 +#define HDD_MAX_ALLOWED_LL_STATS_FAILURE 5 /* 11B, 11G Rate table include Basic rate and Extended rate * The IDX field is the rate index @@ -241,6 +243,79 @@ hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter) } #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ +#ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI +/** + * wlan_hdd_qmi_get_sync_resume() - Get operation to trigger RTPM + * sync resume without WoW exit + * + * call qmi_get before sending qmi, and do qmi_put after all the + * qmi response rececived from fw. so this request wlan host to + * wait for the last qmi response, if it doesn't wait, qmi put + * which cause MHI enter M3(suspend) before all the qmi response, + * and MHI will trigger a RTPM resume, this violated design of by + * sending cmd by qmi without wow resume. + * + * Returns: 0 for success, non-zero for failure + */ +int wlan_hdd_qmi_get_sync_resume(void) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (!hdd_ctx->config->is_qmi_stats_enabled) { + hdd_debug("periodic stats over qmi is disabled"); + return 0; + } + + if (!qdf_ctx) { + hdd_err("qdf_ctx is null"); + return -EINVAL; + } + + return pld_qmi_send_get(qdf_ctx->dev); +} + +/** + * wlan_hdd_qmi_put_suspend() - Put operation to trigger RTPM suspend + * without WoW entry + * + * Returns: 0 for success, non-zero for failure + */ +int wlan_hdd_qmi_put_suspend(void) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (!hdd_ctx->config->is_qmi_stats_enabled) { + hdd_debug("periodic stats over qmi is disabled"); + return 0; + } + + if (!qdf_ctx) { + hdd_err("qdf_ctx is null"); + return -EINVAL; + } + + return pld_qmi_send_put(qdf_ctx->dev); +} +#else +int wlan_hdd_qmi_get_sync_resume(void) +{ + return 0; +} + +int wlan_hdd_qmi_put_suspend(void) +{ + return 0; +} +#endif /* end if of WLAN_FEATURE_WMI_SEND_RECV_QMI */ + #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** @@ -1954,14 +2029,17 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, } ret = osif_request_wait_for_response(request); if (ret) { - hdd_err("Target response timed out request id %d request bitmap 0x%x", - priv->request_id, priv->request_bitmap); + adapter->ll_stats_failure_count++; + hdd_err("Target response timed out request id %d request bitmap 0x%x ll_stats failure count %d", + priv->request_id, priv->request_bitmap, + adapter->ll_stats_failure_count); qdf_spin_lock(&priv->ll_stats_lock); priv->request_bitmap = 0; qdf_spin_unlock(&priv->ll_stats_lock); ret = -ETIMEDOUT; } else { hdd_update_station_stats_cached_timestamp(adapter); + adapter->ll_stats_failure_count = 0; } qdf_spin_lock(&priv->ll_stats_lock); status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); @@ -1982,6 +2060,12 @@ exit: hdd_exit(); osif_request_put(request); + if (adapter->ll_stats_failure_count >= + HDD_MAX_ALLOWED_LL_STATS_FAILURE) { + cds_trigger_recovery(QDF_STATS_REQ_TIMEDOUT); + adapter->ll_stats_failure_count = 0; + } + return ret; } @@ -2066,6 +2150,11 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, return -EINVAL; } + if (adapter->device_mode == QDF_SAP_MODE) { + hdd_nofl_debug("LL_STATS get is not supported for SAP mode"); + return -EINVAL; + } + if (hddstactx->hdd_reassoc_scenario) { hdd_err("Roaming in progress, cannot process the request"); return -EBUSY; @@ -2112,61 +2201,6 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, return 0; } -#ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI -/** - * wlan_hdd_qmi_get_sync_resume() - Get operation to trigger RTPM - * sync resume without WoW exit - * @hdd_ctx: hdd context - * @dev: device context - * - * Returns: 0 for success, non-zero for failure - */ -static inline -int wlan_hdd_qmi_get_sync_resume(struct hdd_context *hdd_ctx, - struct device *dev) -{ - if (!hdd_ctx->config->is_qmi_stats_enabled) { - hdd_debug("periodic stats over qmi is disabled"); - return 0; - } - - return pld_qmi_send_get(dev); -} - -/** - * wlan_hdd_qmi_put_suspend() - Put operation to trigger RTPM suspend - * without WoW entry - * @hdd_ctx: hdd context - * @dev: device context - * - * Returns: 0 for success, non-zero for failure - */ -static inline -int wlan_hdd_qmi_put_suspend(struct hdd_context *hdd_ctx, - struct device *dev) -{ - if (!hdd_ctx->config->is_qmi_stats_enabled) { - hdd_debug("periodic stats over qmi is disabled"); - return 0; - } - - return pld_qmi_send_put(dev); -} -#else -static inline -int wlan_hdd_qmi_get_sync_resume(struct hdd_context *hdd_ctx, - struct device *dev) -{ - return 0; -} - -static inline int wlan_hdd_qmi_put_suspend(struct hdd_context *hdd_ctx, - struct device *dev) -{ - return 0; -} -#endif /* end if of WLAN_FEATURE_WMI_SEND_RECV_QMI */ - /** * wlan_hdd_cfg80211_ll_stats_get() - get ll stats * @wiphy: Pointer to wiphy @@ -2184,26 +2218,23 @@ int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, struct hdd_context *hdd_ctx = wiphy_priv(wiphy); struct osif_vdev_sync *vdev_sync; int errno; - qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); errno = wlan_hdd_validate_context(hdd_ctx); if (0 != errno) return -EINVAL; - if (!qdf_ctx) - return -EINVAL; - errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); if (errno) return errno; - errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); - if (errno) + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); goto end; - + } errno = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len); - wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + wlan_hdd_qmi_put_suspend(); end: osif_vdev_sync_op_stop(vdev_sync); @@ -3799,6 +3830,343 @@ wlan_hdd_cfg80211_stats_ext2_callback(hdd_handle_t hdd_handle, } #endif /* End of WLAN_FEATURE_STATS_EXT */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * enum roam_event_rt_info_reset - Reset the notif param value of struct + * roam_event_rt_info to 0 + * @ROAM_EVENT_RT_INFO_RESET: Reset the value to 0 + */ +enum roam_event_rt_info_reset { + ROAM_EVENT_RT_INFO_RESET = 0, +}; + +/** + * struct roam_ap - Roamed/Failed AP info + * @num_cand: number of candidate APs + * @bssid: BSSID of roamed/failed AP + * rssi: RSSI of roamed/failed AP + * freq: Frequency of roamed/failed AP + */ +struct roam_ap { + uint32_t num_cand; + struct qdf_mac_addr bssid; + int8_t rssi; + uint16_t freq; +}; + +/** + * hdd_get_roam_rt_stats_event_len() - calculate length of skb required for + * sending roam events stats. + * @roam_stats: pointer to mlme_roam_debug_info structure + * + * Return: length of skb + */ +static uint32_t +hdd_get_roam_rt_stats_event_len(struct mlme_roam_debug_info *roam_stats) +{ + uint32_t len = 0; + uint8_t i = 0, num_cand = 0; + + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON */ + if (roam_stats->trigger.present) + len += nla_total_size(sizeof(uint32_t)); + + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON */ + if (roam_stats->roam_event_param.roam_invoke_fail_reason) + len += nla_total_size(sizeof(uint32_t)); + + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE */ + if (roam_stats->roam_event_param.roam_scan_state) + len += nla_total_size(sizeof(uint8_t)); + + if (roam_stats->scan.present) { + if (roam_stats->scan.num_chan && !roam_stats->scan.type) + for (i = 0; i < roam_stats->scan.num_chan;) + i++; + + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST */ + len += (nla_total_size(sizeof(uint32_t)) * i); + + if (roam_stats->result.present && + roam_stats->result.fail_reason) { + num_cand++; + } else if (roam_stats->trigger.present) { + for (i = 0; i < roam_stats->scan.num_ap; i++) { + if (roam_stats->scan.ap[i].type == 2) + num_cand++; + } + } + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO */ + len += NLA_HDRLEN; + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID */ + len += (nla_total_size(QDF_MAC_ADDR_SIZE) * num_cand); + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI */ + len += (nla_total_size(sizeof(int32_t)) * num_cand); + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ */ + len += (nla_total_size(sizeof(uint32_t)) * num_cand); + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON */ + len += (nla_total_size(sizeof(uint32_t)) * num_cand); + } + + /* QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE */ + if (len) + len += nla_total_size(sizeof(uint32_t)); + + return len; +} + +#define SUBCMD_ROAM_EVENTS_INDEX \ + QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX +#define ROAM_SCAN_FREQ_LIST \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST +#define ROAM_INVOKE_FAIL_REASON \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON +#define ROAM_SCAN_STATE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE +#define ROAM_EVENTS_CANDIDATE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO +#define CANDIDATE_BSSID \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID +#define CANDIDATE_RSSI \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI +#define CANDIDATE_FREQ \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ +#define ROAM_FAIL_REASON \ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON + +/** + * roam_rt_stats_fill_scan_freq() - Fill the scan frequency list from the + * roam stats event. + * @vendor_event: pointer to sk_buff structure + * @roam_stats: pointer to mlme_roam_debug_info structure + * + * Return: none + */ +static void +roam_rt_stats_fill_scan_freq(struct sk_buff *vendor_event, + struct mlme_roam_debug_info *roam_stats) +{ + struct nlattr *nl_attr; + uint8_t i; + + nl_attr = nla_nest_start(vendor_event, ROAM_SCAN_FREQ_LIST); + if (!nl_attr) { + hdd_err("nla nest start fail"); + kfree_skb(vendor_event); + return; + } + if (roam_stats->scan.num_chan && !roam_stats->scan.type) { + for (i = 0; i < roam_stats->scan.num_chan; i++) { + if (nla_put_u32(vendor_event, i, + roam_stats->scan.chan_freq[i])) { + hdd_err("failed to put freq at index %d", i); + kfree_skb(vendor_event); + return; + } + } + } + nla_nest_end(vendor_event, nl_attr); +} + +/** + * roam_rt_stats_fill_cand_info() - Fill the roamed/failed AP info from the + * roam stats event. + * @vendor_event: pointer to sk_buff structure + * @roam_stats: pointer to mlme_roam_debug_info structure + * + * Return: none + */ +static void +roam_rt_stats_fill_cand_info(struct sk_buff *vendor_event, + struct mlme_roam_debug_info *roam_stats) +{ + struct nlattr *nl_attr, *nl_array; + struct roam_ap cand_ap = {0}; + uint8_t i, num_cand = 0; + + if (roam_stats->result.present && roam_stats->result.fail_reason) { + num_cand++; + for (i = 0; i < roam_stats->scan.num_ap; i++) { + if (roam_stats->scan.ap[i].type == 0 && + qdf_is_macaddr_equal(&roam_stats->result.fail_bssid, + &roam_stats-> + scan.ap[i].bssid)) { + qdf_copy_macaddr(&cand_ap.bssid, + &roam_stats->scan.ap[i].bssid); + cand_ap.rssi = roam_stats->scan.ap[i].rssi; + cand_ap.freq = roam_stats->scan.ap[i].freq; + } + } + } else if (roam_stats->trigger.present) { + for (i = 0; i < roam_stats->scan.num_ap; i++) { + if (roam_stats->scan.ap[i].type == 2) { + num_cand++; + qdf_copy_macaddr(&cand_ap.bssid, + &roam_stats->scan.ap[i].bssid); + cand_ap.rssi = roam_stats->scan.ap[i].rssi; + cand_ap.freq = roam_stats->scan.ap[i].freq; + } + } + } + + nl_array = nla_nest_start(vendor_event, ROAM_EVENTS_CANDIDATE); + if (!nl_array) { + hdd_err("nl array nest start fail"); + kfree_skb(vendor_event); + return; + } + for (i = 0; i < num_cand; i++) { + nl_attr = nla_nest_start(vendor_event, i); + if (!nl_attr) { + hdd_err("nl attr nest start fail"); + kfree_skb(vendor_event); + return; + } + if (nla_put(vendor_event, CANDIDATE_BSSID, + sizeof(cand_ap.bssid), cand_ap.bssid.bytes)) { + hdd_err("%s put fail", + "ROAM_EVENTS_CANDIDATE_INFO_BSSID"); + kfree_skb(vendor_event); + return; + } + if (nla_put_s32(vendor_event, CANDIDATE_RSSI, cand_ap.rssi)) { + hdd_err("%s put fail", + "ROAM_EVENTS_CANDIDATE_INFO_RSSI"); + kfree_skb(vendor_event); + return; + } + if (nla_put_u32(vendor_event, CANDIDATE_FREQ, cand_ap.freq)) { + hdd_err("%s put fail", + "ROAM_EVENTS_CANDIDATE_INFO_FREQ"); + kfree_skb(vendor_event); + return; + } + if (roam_stats->result.present && + roam_stats->result.fail_reason) { + if (nla_put_u32(vendor_event, ROAM_FAIL_REASON, + roam_stats->result.fail_reason)) { + hdd_err("%s put fail", + "ROAM_EVENTS_CANDIDATE_FAIL_REASON"); + kfree_skb(vendor_event); + return; + } + } + nla_nest_end(vendor_event, nl_attr); + } + nla_nest_end(vendor_event, nl_array); +} + +void +wlan_hdd_cfg80211_roam_events_callback(hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats) +{ + struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle); + int status; + uint32_t data_size, roam_event_type = 0; + struct sk_buff *vendor_event; + struct hdd_adapter *adapter; + + status = wlan_hdd_validate_context(hdd_ctx); + if (status) { + hdd_err("Invalid hdd_ctx"); + return; + } + + if (!roam_stats) { + hdd_err("msg received here is null"); + return; + } + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, + roam_stats->roam_event_param.vdev_id); + if (!adapter) { + hdd_err("vdev_id %d does not exist with host", + roam_stats->roam_event_param.vdev_id); + return; + } + + data_size = hdd_get_roam_rt_stats_event_len(roam_stats); + if (!data_size) { + hdd_err("No data requested"); + return; + } + + data_size += NLMSG_HDRLEN; + vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + &adapter->wdev, + data_size, + SUBCMD_ROAM_EVENTS_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + hdd_err("vendor_event_alloc failed for ROAM_EVENTS_STATS"); + return; + } + + if (roam_stats->scan.present && roam_stats->trigger.present) { + roam_rt_stats_fill_scan_freq(vendor_event, roam_stats); + roam_rt_stats_fill_cand_info(vendor_event, roam_stats); + } + + if (roam_stats->roam_event_param.roam_scan_state) { + roam_event_type |= QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE; + if (nla_put_u8(vendor_event, ROAM_SCAN_STATE, + roam_stats->roam_event_param.roam_scan_state)) { + hdd_err("%s put fail", + "VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE"); + kfree_skb(vendor_event); + return; + } + roam_stats->roam_event_param.roam_scan_state = + ROAM_EVENT_RT_INFO_RESET; + } + if (roam_stats->trigger.present) { + roam_event_type |= QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON; + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON, + roam_stats->trigger.trigger_reason)) { + hdd_err("%s put fail", + "VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON"); + kfree_skb(vendor_event); + return; + } + } + if (roam_stats->roam_event_param.roam_invoke_fail_reason) { + roam_event_type |= + QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON; + if (nla_put_u32(vendor_event, ROAM_INVOKE_FAIL_REASON, + roam_stats-> + roam_event_param.roam_invoke_fail_reason)) { + hdd_err("%s put fail", + "VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON"); + kfree_skb(vendor_event); + return; + } + roam_stats->roam_event_param.roam_invoke_fail_reason = + ROAM_EVENT_RT_INFO_RESET; + } + if (roam_stats->result.present && roam_stats->result.fail_reason) + roam_event_type |= QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON; + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE, + roam_event_type)) { + hdd_err("%s put fail", "QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE"); + kfree_skb(vendor_event); + return; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +} + +#undef SUBCMD_ROAM_EVENTS_INDEX +#undef ROAM_SCAN_FREQ_LIST +#undef ROAM_INVOKE_FAIL_REASON +#undef ROAM_SCAN_STATE +#undef ROAM_EVENTS_CANDIDATE +#undef CANDIDATE_BSSID +#undef CANDIDATE_RSSI +#undef CANDIDATE_FREQ +#undef ROAM_FAIL_REASON +#endif /* End of WLAN_FEATURE_ROAM_OFFLOAD */ + #ifdef LINKSPEED_DEBUG_ENABLED #define linkspeed_dbg(format, args...) pr_info(format, ## args) #else @@ -3820,6 +4188,7 @@ static void wlan_hdd_fill_summary_stats(tCsrSummaryStatsInfo *stats, int i; struct cds_vdev_dp_stats dp_stats; uint32_t orig_cnt; + uint32_t orig_fail_cnt; info->rx_packets = stats->rx_frm_cnt; info->tx_packets = 0; @@ -3834,9 +4203,13 @@ static void wlan_hdd_fill_summary_stats(tCsrSummaryStatsInfo *stats, if (cds_dp_get_vdev_stats(vdev_id, &dp_stats)) { orig_cnt = info->tx_retries; - info->tx_retries = dp_stats.tx_retries; + orig_fail_cnt = info->tx_failed; + info->tx_retries = dp_stats.tx_retries_mpdu; + info->tx_failed += dp_stats.tx_mpdu_success_with_retries; hdd_debug("vdev %d tx retries adjust from %d to %d", vdev_id, orig_cnt, info->tx_retries); + hdd_debug("tx failed adjust from %d to %d", + orig_fail_cnt, info->tx_failed); } info->filled |= HDD_INFO_TX_PACKETS | @@ -5594,7 +5967,6 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, { struct hdd_context *hdd_ctx = wiphy_priv(wiphy); struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); int errno; QDF_STATUS status; @@ -5602,9 +5974,6 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, if (errno) return errno; - if (!qdf_ctx) - return -EINVAL; - status = wlan_hdd_stats_request_needed(adapter); if (QDF_IS_STATUS_ERROR(status)) { if (status == QDF_STATUS_E_ALREADY) @@ -5614,15 +5983,17 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, } if (get_station_fw_request_needed) { - errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); - if (errno) + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); return errno; + } } errno = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); if (get_station_fw_request_needed) - wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + wlan_hdd_qmi_put_suspend(); get_station_fw_request_needed = true; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.h b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.h index 312c439800a8..0a2ce6cfd28d 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.h +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.h @@ -393,6 +393,25 @@ void wlan_hdd_cfg80211_stats_ext2_callback(hdd_handle_t hdd_handle, struct sir_sme_rx_aggr_hole_ind *pmsg); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * wlan_hdd_cfg80211_roam_events_callback() - roam_events_callback + * @hdd_handle: opaque handle to the hdd context + * @roam_stats: roam events stats + * + * Return: void + */ +void +wlan_hdd_cfg80211_roam_events_callback(hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats); +#else +static inline void +wlan_hdd_cfg80211_roam_events_callback(hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats) +{ +} +#endif /* End of WLAN_FEATURE_ROAM_OFFLOAD */ + /** * wlan_hdd_get_rcpi() - Wrapper to get current RCPI * @adapter: adapter upon which the measurement is requested @@ -473,6 +492,9 @@ int wlan_hdd_get_link_speed(struct hdd_adapter *adapter, uint32_t *link_speed); */ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter); +int wlan_hdd_qmi_get_sync_resume(void); +int wlan_hdd_qmi_put_suspend(void); + #ifdef WLAN_FEATURE_BIG_DATA_STATS /** * wlan_hdd_get_big_data_station_stats() - Get big data station statistics diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.c index 950eeb911cc2..895b38637029 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.c @@ -36,8 +36,12 @@ #include #include "wlan_fwol_ucfg_api.h" #include +#include "os_if_fwol.h" +#include "wlan_osif_request_manager.h" +#include "wlan_fwol_public_structs.h" #define DC_OFF_PERCENT_WPPS 50 +#define WLAN_WAIT_TIME_GET_THERM_LVL 1000 const struct nla_policy wlan_hdd_thermal_mitigation_policy @@ -143,6 +147,223 @@ hdd_send_thermal_mitigation_val(struct hdd_context *hdd_ctx, uint32_t level, return QDF_STATUS_SUCCESS; } +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS +hdd_send_get_thermal_stats_cmd(struct hdd_context *hdd_ctx, + enum thermal_stats_request_type request_type, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context) +{ + int ret; + + if (!hdd_ctx->psoc) { + hdd_err_rl("NULL pointer for psoc"); + return QDF_STATUS_E_INVAL; + } + + + /* Send Get Thermal Stats cmd to FW */ + ret = os_if_fwol_get_thermal_stats_req(hdd_ctx->psoc, request_type, + callback, context); + if (ret) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +/** + * hdd_get_thermal_stats_cb() - Get thermal stats callback + * @context: Call context + * @response: Pointer to response structure + * + * Return: void + */ +static void +hdd_get_thermal_stats_cb(void *context, + struct thermal_throttle_info *response) +{ + struct osif_request *request; + struct thermal_throttle_info *priv; + + request = osif_request_get(context); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + qdf_mem_copy(priv, response, sizeof(struct thermal_throttle_info)); + + osif_request_complete(request); + osif_request_put(request); +} + +#define THERMAL_MIN_TEMP QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE +#define THERMAL_MAX_TEMP QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE +#define THERMAL_DWELL_TIME QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME +#define THERMAL_LVL_COUNT QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER + +/** + * hdd_get_curr_thermal_stats_val() - Indicate thermal stats + * to upper layer when query vendor command + * @wiphy: Pointer to wireless phy + * @hdd_ctx: hdd context + * + * Return: 0 for success + */ +static int +hdd_get_curr_thermal_stats_val(struct wiphy *wiphy, + struct hdd_context *hdd_ctx) +{ + int ret = 0; + uint8_t i = 0; + struct osif_request *request = NULL; + int skb_len = 0; + struct thermal_throttle_info *priv; + struct thermal_throttle_info *get_tt_stats = NULL; + struct sk_buff *skb = NULL; + void *cookie; + struct nlattr *therm_attr; + struct nlattr *tt_levels; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_GET_THERM_LVL, + .dealloc = NULL, + }; + + if (hdd_ctx->is_therm_stats_in_progress) { + hdd_err("request already in progress"); + return -EINVAL; + } + + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("request allocation failure"); + return -ENOMEM; + } + cookie = osif_request_cookie(request); + hdd_ctx->is_therm_stats_in_progress = true; + ret = hdd_send_get_thermal_stats_cmd(hdd_ctx, thermal_stats_req, + hdd_get_thermal_stats_cb, + cookie); + if (QDF_IS_STATUS_ERROR(ret)) { + hdd_err("Failure while sending command to fw"); + ret = -EAGAIN; + goto completed; + } + + ret = osif_request_wait_for_response(request); + if (ret) { + hdd_err("Timed out while retrieving thermal stats"); + ret = -EAGAIN; + goto completed; + } + + get_tt_stats = osif_request_priv(request); + if (!get_tt_stats) { + hdd_err("invalid get_tt_stats"); + ret = -EINVAL; + goto completed; + } + + skb_len = NLMSG_HDRLEN + (get_tt_stats->therm_throt_levels) * + (NLA_HDRLEN + (NLA_HDRLEN + + sizeof(get_tt_stats->level_info[i].start_temp_level) + + NLA_HDRLEN + + sizeof(get_tt_stats->level_info[i].end_temp_level) + + NLA_HDRLEN + + sizeof(get_tt_stats->level_info[i].total_time_ms_lo) + + NLA_HDRLEN + + sizeof(get_tt_stats->level_info[i].num_entry))); + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + skb_len); + if (!skb) { + hdd_err_rl("cfg80211_vendor_cmd_alloc_reply_skb failed"); + ret = -ENOMEM; + goto completed; + } + + therm_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS); + if (!therm_attr) { + hdd_err_rl("nla_nest_start failed for attr failed"); + ret = -EINVAL; + goto completed; + } + + for (i = 0; i < get_tt_stats->therm_throt_levels; i++) { + tt_levels = nla_nest_start(skb, i); + if (!tt_levels) { + hdd_err_rl("nla_nest_start failed for thermal level %d", + i); + ret = -EINVAL; + goto completed; + } + + hdd_debug("level %d, Temp Range: %d - %d, Dwell time %d, Counter %d", + i, get_tt_stats->level_info[i].start_temp_level, + get_tt_stats->level_info[i].end_temp_level, + get_tt_stats->level_info[i].total_time_ms_lo, + get_tt_stats->level_info[i].num_entry); + + if (nla_put_u32(skb, THERMAL_MIN_TEMP, + get_tt_stats->level_info[i].start_temp_level) || + nla_put_u32(skb, THERMAL_MAX_TEMP, + get_tt_stats->level_info[i].end_temp_level) || + nla_put_u32(skb, THERMAL_DWELL_TIME, + (get_tt_stats->level_info[i].total_time_ms_lo)) || + nla_put_u32(skb, THERMAL_LVL_COUNT, + get_tt_stats->level_info[i].num_entry)) { + hdd_err("nla put failure"); + kfree_skb(skb); + ret = -EINVAL; + hdd_ctx->is_therm_stats_in_progress = false; + break; + } + nla_nest_end(skb, tt_levels); + } + nla_nest_end(skb, therm_attr); + wlan_cfg80211_vendor_cmd_reply(skb); + +completed: + hdd_ctx->is_therm_stats_in_progress = false; + osif_request_put(request); + + return ret; +} + +#undef THERMAL_MIN_TEMP +#undef THERMAL_MAX_TEMP +#undef THERMAL_DWELL_TIME +#undef THERMAL_LVL_COUNT + +static QDF_STATUS +hdd_send_thermal_stats_clear_cmd(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + + status = hdd_send_get_thermal_stats_cmd(hdd_ctx, + thermal_stats_clear, NULL, + NULL); + + return status; +} +#else +static int +hdd_get_curr_thermal_stats_val(struct wiphy *wiphy, + struct hdd_context *hdd_ctx) +{ + return -EINVAL; +} + +static QDF_STATUS +hdd_send_thermal_stats_clear_cmd(struct hdd_context *hdd_ctx) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif /* THERMAL_STATS_SUPPORT */ + /** * __wlan_hdd_cfg80211_set_thermal_mitigation_policy() - Set the thermal policy * @wiphy: Pointer to wireless phy @@ -162,9 +383,14 @@ __wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX + 1]; uint32_t level, cmd_type; QDF_STATUS status; + int ret; hdd_enter(); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return -EINVAL; + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err_rl("Command not allowed in FTM mode"); return -EPERM; @@ -184,23 +410,35 @@ __wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy, } cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE]); - if (cmd_type != QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL) { - hdd_err_rl("invalid thermal cmd value"); - return -EINVAL; + switch (cmd_type) { + case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: + if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]) { + hdd_err_rl("attr thermal throttle set failed"); + return -EINVAL; + } + level = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]); + + hdd_debug("thermal mitigation level from userspace %d", level); + status = hdd_send_thermal_mitigation_val(hdd_ctx, level, + THERMAL_MONITOR_APPS); + ret = qdf_status_to_os_return(status); + break; + case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: + ret = hdd_get_curr_thermal_stats_val(wiphy, hdd_ctx); + break; + case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: + status = hdd_send_thermal_stats_clear_cmd(hdd_ctx); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failure while sending command to fw"); + ret = -EINVAL; + } + break; + default: + ret = -EINVAL; } - if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]) { - hdd_err_rl("attr thermal throttle set failed"); - return -EINVAL; - } - level = - nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]); - - hdd_debug("thermal mitigation level from userspace %d", level); - status = hdd_send_thermal_mitigation_val(hdd_ctx, level, - THERMAL_MONITOR_APPS); hdd_exit(); - return qdf_status_to_os_return(status); + return ret; } /** @@ -246,7 +484,7 @@ QDF_STATUS hdd_restore_thermal_mitigation_config(struct hdd_context *hdd_ctx) uint32_t prio = 0, target_temp = 0; struct wlan_fwol_thermal_temp thermal_temp = {0}; QDF_STATUS status; - struct thermal_mitigation_params therm_cfg_params; + struct thermal_mitigation_params therm_cfg_params = {0}; status = ucfg_fwol_get_thermal_temp(hdd_ctx->psoc, &thermal_temp); if (QDF_IS_STATUS_ERROR(status)) { @@ -268,6 +506,7 @@ QDF_STATUS hdd_restore_thermal_mitigation_config(struct hdd_context *hdd_ctx) therm_cfg_params.num_thermal_conf = 1; therm_cfg_params.client_id = THERMAL_MONITOR_APPS; therm_cfg_params.priority = 0; + hdd_debug("dc %d dc_off_per %d enable %d", dc, dc_off_percent, enable); status = sme_set_thermal_throttle_cfg(hdd_ctx->mac_handle, diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.h b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.h index 3bfcbd490361..a18abe7f19ae 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.h +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_thermal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021 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 @@ -195,4 +195,13 @@ int wlan_hdd_pld_set_thermal_mitigation(struct device *dev, } #endif /* FEATURE_THERMAL_VENDOR_COMMANDS */ + +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS +hdd_send_get_thermal_stats_cmd(struct hdd_context *hdd_ctx, + enum thermal_stats_request_type request_type, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context); +#endif /* THERMAL_STATS_SUPPORT */ #endif /* __HDD_THERMAL_H */ diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_twt.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_twt.c index f4f2aeb5f9b9..e5d2b83e8365 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_twt.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_twt.c @@ -1817,6 +1817,13 @@ static int hdd_twt_setup_session(struct hdd_adapter *adapter, if (ret) return ret; + if (!ucfg_mlme_get_twt_peer_responder_capabilities( + adapter->hdd_ctx->psoc, + &hdd_sta_ctx->conn_info.bssid)) { + hdd_err_rl("TWT setup reject: TWT responder not supported"); + return -EOPNOTSUPP; + } + ret = hdd_twt_get_add_dialog_values(tb2, ¶ms); if (ret) return ret; @@ -3126,7 +3133,7 @@ hdd_send_twt_resume_dialog_cmd(struct hdd_context *hdd_ctx, break; case WMI_HOST_RESUME_TWT_STATUS_DIALOG_ID_NOT_EXIST: case WMI_HOST_RESUME_TWT_STATUS_NOT_PAUSED: - ret = EAGAIN; + ret = -EAGAIN; break; case WMI_HOST_RESUME_TWT_STATUS_DIALOG_ID_BUSY: ret = -EINPROGRESS; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_tx_rx.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_tx_rx.c index 428524a83b81..f864cdd6c632 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_tx_rx.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_tx_rx.c @@ -2083,6 +2083,13 @@ QDF_STATUS hdd_rx_pkt_thread_enqueue_cbk(void *adapter, return hdd_adapter->rx_stack(adapter, nbuf_list); vdev_id = hdd_adapter->vdev_id; + + if (vdev_id >= WLAN_UMAC_VDEV_ID_MAX) { + hdd_info_rl("Vdev invalid. Dropping packets"); + qdf_nbuf_list_free(nbuf_list); + return QDF_STATUS_E_NETDOWN; + } + head_ptr = nbuf_list; while (head_ptr) { qdf_nbuf_cb_update_vdev_id(head_ptr, vdev_id); @@ -2677,6 +2684,7 @@ const char *hdd_action_type_to_string(enum netif_action_type action) CASE_RETURN_STRING(WLAN_NETIF_VO_QUEUE_OFF); CASE_RETURN_STRING(WLAN_NETIF_VI_QUEUE_ON); CASE_RETURN_STRING(WLAN_NETIF_VI_QUEUE_OFF); + CASE_RETURN_STRING(WLAN_NETIF_BE_BK_QUEUE_ON); CASE_RETURN_STRING(WLAN_NETIF_BE_BK_QUEUE_OFF); CASE_RETURN_STRING(WLAN_WAKE_NON_PRIORITY_QUEUE); CASE_RETURN_STRING(WLAN_STOP_NON_PRIORITY_QUEUE); @@ -2707,6 +2715,7 @@ static void wlan_hdd_update_queue_oper_stats(struct hdd_adapter *adapter, case WLAN_START_ALL_NETIF_QUEUE: case WLAN_WAKE_ALL_NETIF_QUEUE: case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER: + case WLAN_NETIF_BE_BK_QUEUE_ON: case WLAN_NETIF_VI_QUEUE_ON: case WLAN_NETIF_VO_QUEUE_ON: case WLAN_NETIF_PRIORITY_QUEUE_ON: @@ -2938,65 +2947,99 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, case WLAN_NETIF_PRIORITY_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); - wlan_hdd_update_pause_time(adapter, temp_map); + if (reason == WLAN_DATA_FLOW_CTRL_PRI) { + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + } else { + temp_map = adapter->pause_map; + adapter->pause_map &= ~(1 << reason); + } + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_PRIORITY_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + if (reason == WLAN_DATA_FLOW_CTRL_PRI) + adapter->subqueue_pause_map |= (1 << reason); + else + adapter->pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_BE_BK_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK); + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_NETIF_BE_BK_QUEUE_ON: + spin_lock_bh(&adapter->pause_map_lock); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_BK); + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_BE); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VI_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VI_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VI); - wlan_hdd_update_pause_time(adapter, temp_map); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VI); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VO_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VO_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VO); - wlan_hdd_update_pause_time(adapter, temp_map); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VO); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; @@ -3078,7 +3121,12 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, adapter->queue_oper_history[index].time = qdf_system_ticks(); adapter->queue_oper_history[index].netif_action = action; adapter->queue_oper_history[index].netif_reason = reason; - adapter->queue_oper_history[index].pause_map = adapter->pause_map; + if (reason >= WLAN_DATA_FLOW_CTRL_BE_BK) + adapter->queue_oper_history[index].pause_map = + adapter->subqueue_pause_map; + else + adapter->queue_oper_history[index].pause_map = + adapter->pause_map; txq_hist_ptr = &adapter->queue_oper_history[index]; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c index 9c2372bf8c80..314e96e69cad 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c @@ -8387,8 +8387,17 @@ static int iw_get_statistics(struct net_device *dev, if (errno) return errno; + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); + goto end; + } + errno = __iw_get_statistics(dev, info, wrqu, extra); + wlan_hdd_qmi_put_suspend(); + +end: osif_vdev_sync_op_stop(vdev_sync); return errno; diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/ani_global.h b/drivers/staging/qcacld-3.0/core/mac/inc/ani_global.h index ed0dad085d3e..979b89e15093 100644 --- a/drivers/staging/qcacld-3.0/core/mac/inc/ani_global.h +++ b/drivers/staging/qcacld-3.0/core/mac/inc/ani_global.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -818,6 +819,10 @@ struct mac_context { #ifdef FEATURE_ANI_LEVEL_REQUEST struct ani_level_params ani_params; #endif + +#ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER + void (*cal_failure_event_cb)(uint8_t cal_type, uint8_t reason); +#endif }; #ifdef FEATURE_WLAN_TDLS diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h index 998d593cd64a..b60ce705214f 100644 --- a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h +++ b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 2 #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 8 -#define QWLAN_VERSION_EXTRA "D" -#define QWLAN_VERSION_BUILD 24 +#define QWLAN_VERSION_EXTRA "B" +#define QWLAN_VERSION_BUILD 28 -#define QWLAN_VERSIONSTR "2.0.8.24D" +#define QWLAN_VERSIONSTR "2.0.8.28B" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h b/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h index e77ef4278dab..5f89bd74caa9 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h @@ -26,7 +26,7 @@ * * * This file was automatically generated by 'framesc' - * Mon Jul 19 14:21:41 2021 from the following file(s): + * Wed Sep 29 13:23:21 2021 from the following file(s): * * dot11f.frms * diff --git a/drivers/staging/qcacld-3.0/core/mac/src/include/parser_api.h b/drivers/staging/qcacld-3.0/core/mac/src/include/parser_api.h index 782bacb0b2c5..ee86d543bfa5 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/include/parser_api.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/include/parser_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/lim_ft.h b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/lim_ft.h index a9803ebb28bb..f26d5c8c8173 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/lim_ft.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/lim_ft.h @@ -140,15 +140,13 @@ void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode, - tpSirAssocRsp assoc_rsp); + enum wlan_phymode bss_phymode); /** * lim_ft_prepare_add_bss_req() - Create Add Bss Req to the new AP * @mac: Global MAC context * @add_bss_params: Bss params including rsp data * @pe_session: PE Session - * @assoc_rsp: assoc response from ap * * This will be used when we are ready to FT to the new AP. * The newly created ft Session entry is passed to this function @@ -157,8 +155,7 @@ void lim_fill_ft_session(struct mac_context *mac, */ void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription, - tpSirAssocRsp assoc_rsp); + struct bss_description *bssDescription); QDF_STATUS lim_send_preauth_scan_offload(struct mac_context *mac_ctx, struct pe_session *session_entry, tSirFTPreAuthReq *ft_preauth_req); @@ -167,13 +164,11 @@ static inline void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode, - tpSirAssocRsp assoc_rsp) + enum wlan_phymode bss_phymode) {} static inline void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription, - tpSirAssocRsp assoc_rsp) + struct bss_description *bssDescription) {} #endif diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c index 61c81991ce3f..94173b4cf80f 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c @@ -2133,11 +2133,14 @@ lim_roam_fill_bss_descr(struct mac_context *mac, qdf_mem_free(parsed_frm_ptr); return QDF_STATUS_E_FAILURE; } - pe_debug("LFR3:Beacon/Prb Rsp: %d bssid "QDF_MAC_ADDR_FMT" beacon "QDF_MAC_ADDR_FMT, + pe_debug("LFR3:Beacon/Prb Rsp: %d len %d bssid "QDF_MAC_ADDR_FMT" beacon "QDF_MAC_ADDR_FMT, roam_synch_ind_ptr->isBeacon, + roam_synch_ind_ptr->beaconProbeRespLength, QDF_MAC_ADDR_REF(roam_synch_ind_ptr->bssid.bytes), QDF_MAC_ADDR_REF(mac_hdr->bssId)); - + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + bcn_proberesp_ptr, + roam_synch_ind_ptr->beaconProbeRespLength); status = lim_roam_gen_beacon_descr(mac, roam_synch_ind_ptr, parsed_frm_ptr, @@ -2215,15 +2218,21 @@ lim_roam_fill_bss_descr(struct mac_context *mac, (uint8_t *)parsed_frm_ptr->mdie, SIR_MDIE_SIZE); } - pe_debug("chan: %d rssi: %d ie_len %d", + pe_debug("chan: %d rssi: %d desc len %d", bss_desc_ptr->chan_freq, - bss_desc_ptr->rssi, ie_len); + bss_desc_ptr->rssi, + bss_desc_ptr->length); + + qdf_mem_free(parsed_frm_ptr); if (ie_len) { qdf_mem_copy(&bss_desc_ptr->ieFields, ie, ie_len); qdf_mem_free(ie); + } else { + pe_err("Beacon/Probe rsp doesn't have any IEs"); + return QDF_STATUS_E_FAILURE; } - qdf_mem_free(parsed_frm_ptr); + return QDF_STATUS_SUCCESS; } @@ -2518,64 +2527,6 @@ lim_check_ft_initial_im_association(struct roam_offload_synch_ind *roam_synch, } } -/** - * lim_get_assoc_resp_from_roam_sync() - get assoc response from - * roam sync event - * @mac_ctx: mac context - * @session: pe session - * @roam_sync_ind_ptr: roam sync indication - * - * This function is to get parsed assoc response data - * - * Return: assoc response data struct - */ -static tpSirAssocRsp -lim_get_assoc_resp_from_roam_sync( - struct mac_context *mac_ctx, - struct pe_session *session, - struct roam_offload_synch_ind *roam_sync_ind_ptr) -{ - uint8_t *reassoc_resp; - tpSirAssocRsp assoc_rsp; - uint32_t frame_len; - uint8_t *frm_body; - - if (roam_sync_ind_ptr->reassocRespLength <= SIR_MAC_HDR_LEN_3A) { - pe_warn("invalid roam sync assoc rsp"); - return NULL; - } - reassoc_resp = (uint8_t *)roam_sync_ind_ptr + - roam_sync_ind_ptr->reassocRespOffset + - SIR_MAC_HDR_LEN_3A; - frame_len = roam_sync_ind_ptr->reassocRespLength - SIR_MAC_HDR_LEN_3A; - - assoc_rsp = qdf_mem_malloc(sizeof(*assoc_rsp)); - if (!assoc_rsp) { - pe_warn("err to malloc assoc rsp"); - return NULL; - } - - frm_body = qdf_mem_malloc(frame_len); - if (!frm_body) { - pe_warn("err to malloc assoc rsp body"); - qdf_mem_free(assoc_rsp); - return NULL; - } - qdf_mem_copy(frm_body, reassoc_resp, frame_len); - /* parse Re/Association Response frame. */ - if (sir_convert_assoc_resp_frame2_struct( - mac_ctx, session, frm_body, - frame_len, assoc_rsp) == QDF_STATUS_E_FAILURE) { - pe_err("Parse error Assoc resp length: %d", frame_len); - qdf_mem_free(frm_body); - qdf_mem_free(assoc_rsp); - return NULL; - } - qdf_mem_free(frm_body); - - return assoc_rsp; -} - QDF_STATUS pe_roam_synch_callback(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, @@ -2591,7 +2542,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, struct bss_params *add_bss_params; QDF_STATUS status = QDF_STATUS_E_FAILURE; uint16_t join_rsp_len; - tpSirAssocRsp assoc_rsp; if (!roam_sync_ind_ptr) { pe_err("LFR3:roam_sync_ind_ptr is NULL"); @@ -2681,15 +2631,11 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, ft_session_ptr->csaOffloadEnable = session_ptr->csaOffloadEnable; /* Next routine will update nss and vdev_nss with AP's capabilities */ - assoc_rsp = lim_get_assoc_resp_from_roam_sync( - mac_ctx, ft_session_ptr, roam_sync_ind_ptr); lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr, - session_ptr, roam_sync_ind_ptr->phy_mode, - assoc_rsp); + session_ptr, roam_sync_ind_ptr->phy_mode); pe_set_rmf_caps(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); /* Next routine may update nss based on dot11Mode */ - lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc, - assoc_rsp); + lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc); if (session_ptr->is11Rconnection) lim_fill_fils_ft(session_ptr, ft_session_ptr); @@ -2702,7 +2648,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, if (!curr_sta_ds) { pe_err("LFR3:failed to lookup hash entry"); ft_session_ptr->bRoamSynchInProgress = false; - qdf_mem_free(assoc_rsp); return status; } session_ptr->limSmeState = eLIM_SME_IDLE_STATE; @@ -2719,7 +2664,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, pe_err("LFR3:failed to add hash entry for "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(add_bss_params->staContext.staMac)); ft_session_ptr->bRoamSynchInProgress = false; - qdf_mem_free(assoc_rsp); return status; } @@ -2759,7 +2703,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, roam_sync_ind_ptr->join_rsp = qdf_mem_malloc(join_rsp_len); if (!roam_sync_ind_ptr->join_rsp) { ft_session_ptr->bRoamSynchInProgress = false; - qdf_mem_free(assoc_rsp); return QDF_STATUS_E_NOMEM; } @@ -2801,7 +2744,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, ft_session_ptr->limSmeState = eLIM_SME_LINK_EST_STATE; ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState; ft_session_ptr->bRoamSynchInProgress = false; - qdf_mem_free(assoc_rsp); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_assoc_utils.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_assoc_utils.c index e5fcc069b1d3..4099a0d487ca 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_assoc_utils.c @@ -1587,6 +1587,41 @@ static bool lim_check_valid_mcs_for_nss(struct pe_session *session, } #endif +/** + * lim_remove_membership_selectors() - remove elements from rate set + * + * @rate_set: pointer to rate set + * + * Removes the BSS membership selector elements from the rate set, and keep + * only the rates + * + * Return: none + */ +static void lim_remove_membership_selectors(tSirMacRateSet *rate_set) +{ + int i, selector_count = 0; + + for (i = 0; i < rate_set->numRates; i++) { + if ((rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY)) || + (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) || + (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_GLK)) || + (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_EPD)) || + (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E)) || + (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_HE_PHY))) + selector_count++; + + if (i + selector_count < rate_set->numRates) + rate_set->rate[i] = rate_set->rate[i + selector_count]; + } + rate_set->numRates -= selector_count; +} + QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, struct supported_rates *pRates, uint8_t *pSupportedMCSSet, @@ -1599,7 +1634,7 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, { tSirMacRateSet tempRateSet; tSirMacRateSet tempRateSet2; - uint32_t i, j, val, min, isArate = 0; + uint32_t i, j, val, min; qdf_size_t val_len; uint8_t aRateIndex = 0; uint8_t bRateIndex = 0; @@ -1635,6 +1670,10 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, } } else tempRateSet2.numRates = 0; + + lim_remove_membership_selectors(&tempRateSet); + lim_remove_membership_selectors(&tempRateSet2); + if ((tempRateSet.numRates + tempRateSet2.numRates) > WLAN_SUPPORTED_RATES_IE_MAX_LEN) { pe_err("more than 12 rates in CFG"); @@ -1655,7 +1694,6 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, for (i = 0; i < tempRateSet.numRates; i++) { min = 0; val = 0xff; - isArate = 0; for (j = 0; (j < tempRateSet.numRates) && (j < WLAN_SUPPORTED_RATES_IE_MAX_LEN); j++) { if ((uint32_t)(tempRateSet.rate[j] & 0x7f) < @@ -1664,8 +1702,6 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, min = j; } } - if (sirIsArate(tempRateSet.rate[min] & 0x7f)) - isArate = 1; /* * HAL needs to know whether the rate is basic rate or not, * as it needs to update the response rate table accordingly. @@ -1673,22 +1709,33 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, * can be used for sending control frames. HAL updates the * response rate table whenever basic rate set is changed. */ - if (basicOnly) { - if (tempRateSet.rate[min] & 0x80) { - if (isArate) - pRates->llaRates[aRateIndex++] = + if (basicOnly && !(tempRateSet.rate[min] & 0x80)) { + pe_debug("Invalid basic rate"); + } else if (sirIsArate(tempRateSet.rate[min] & 0x7f)) { + if (aRateIndex >= SIR_NUM_11A_RATES) { + pe_debug("OOB, aRateIndex: %d", aRateIndex); + } else if (aRateIndex >= 1 && (tempRateSet.rate[min] == + pRates->llaRates[aRateIndex - 1])) { + pe_debug("Duplicate 11a rate: %d", + tempRateSet.rate[min]); + } else { + pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; - else - pRates->llbRates[bRateIndex++] = + } + } else if (sirIsBrate(tempRateSet.rate[min] & 0x7f)) { + if (bRateIndex >= SIR_NUM_11B_RATES) { + pe_debug("OOB, bRateIndex: %d", bRateIndex); + } else if (bRateIndex >= 1 && (tempRateSet.rate[min] == + pRates->llbRates[bRateIndex - 1])) { + pe_debug("Duplicate 11b rate: %d", + tempRateSet.rate[min]); + } else { + pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; } } else { - if (isArate) - pRates->llaRates[aRateIndex++] = - tempRateSet.rate[min]; - else - pRates->llbRates[bRateIndex++] = - tempRateSet.rate[min]; + pe_debug("%d is neither 11a nor 11b rate", + tempRateSet.rate[min]); } tempRateSet.rate[min] = 0xff; } @@ -1786,8 +1833,8 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, * in IBSS role to process the CFG rate sets and * the rate sets received in the Assoc request on AP * - * 1. It makes the intersection between our own rate Sat - * and extemcded rate set and the ones received in the + * 1. It makes the intersection between our own rate set + * and extended rate set and the ones received in the * association request. * 2. It creates a combined rate set of 12 rates max which * comprised the basic and extended rates @@ -1837,13 +1884,16 @@ QDF_STATUS lim_populate_matching_rate_set(struct mac_context *mac_ctx, temp_rate_set2.numRates = 0; } + lim_remove_membership_selectors(&temp_rate_set); + lim_remove_membership_selectors(&temp_rate_set2); + /* * absolute sum of both num_rates should be less than 12. following - * 16-bit sum avoids false codition where 8-bit arthematic overflow + * 16-bit sum avoids false condition where 8-bit arithmetic overflow * might have caused total sum to be less than 12 */ if (((uint16_t)temp_rate_set.numRates + - (uint16_t)temp_rate_set2.numRates) > 12) { + (uint16_t)temp_rate_set2.numRates) > SIR_MAC_MAX_NUMBER_OF_RATES) { pe_err("more than 12 rates in CFG"); return QDF_STATUS_E_FAILURE; } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft.c index 5f56d9802764..a66585ca24a2 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft.c @@ -114,8 +114,7 @@ void lim_ft_cleanup(struct mac_context *mac, struct pe_session *pe_session) *------------------------------------------------------------------*/ void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription, - tpSirAssocRsp assoc_rsp) + struct bss_description *bssDescription) { struct bss_params *pAddBssParams = NULL; tAddStaParams *sta_ctx; @@ -165,26 +164,6 @@ void lim_ft_prepare_add_bss_req(struct mac_context *mac, #ifdef WLAN_FEATURE_11W pAddBssParams->rmfEnabled = ft_session->limRmfEnabled; #endif - if (assoc_rsp && - ft_session->htCapability && pBeaconStruct->HTCaps.present && - assoc_rsp->HTCaps.present) { - /* Some AP have different HT ch width setting in - * beacon/assoc resp. FW uses assoc response to decide - * the bw of HT AP in Roaming sync. - * Here overwrite beacon HT bw setting from assoc - * resp frame to keep sync with FW. - */ - pBeaconStruct->HTCaps.supportedChannelWidthSet = - assoc_rsp->HTCaps.supportedChannelWidthSet; - if (pBeaconStruct->HTInfo.present && - assoc_rsp->HTInfo.present) { - pBeaconStruct->HTInfo.secondaryChannelOffset = - assoc_rsp->HTInfo.secondaryChannelOffset; - pBeaconStruct->HTInfo.recommendedTxWidthSet = - assoc_rsp->HTInfo.recommendedTxWidthSet; - } - } - /* Use the advertised capabilities from the received beacon/PR */ if (IS_DOT11_MODE_HT(ft_session->dot11mode) && (pBeaconStruct->HTCaps.present)) { @@ -527,8 +506,7 @@ void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode, - tpSirAssocRsp assoc_rsp) + enum wlan_phymode bss_phymode) { uint8_t currentBssUapsd; uint8_t bss_chan_id; @@ -593,25 +571,6 @@ void lim_fill_ft_session(struct mac_context *mac, ft_session->htCapability = (IS_DOT11_MODE_HT(ft_session->dot11mode) && pBeaconStruct->HTCaps.present); - if (assoc_rsp && - ft_session->htCapability && pBeaconStruct->HTCaps.present && - assoc_rsp->HTCaps.present) { - /* Some AP have different HT ch width setting in - * beacon/assoc resp. FW uses assoc response to decide - * the bw of HT AP in Roaming sync. - * Here overwrite beacon HT bw setting from assoc - * resp frame to keep sync with FW. - */ - pBeaconStruct->HTCaps.supportedChannelWidthSet = - assoc_rsp->HTCaps.supportedChannelWidthSet; - if (pBeaconStruct->HTInfo.present && - assoc_rsp->HTInfo.present) { - pBeaconStruct->HTInfo.secondaryChannelOffset = - assoc_rsp->HTInfo.secondaryChannelOffset; - pBeaconStruct->HTInfo.recommendedTxWidthSet = - assoc_rsp->HTInfo.recommendedTxWidthSet; - } - } if (IS_DOT11_MODE_HE(ft_session->dot11mode) && pBeaconStruct->he_cap.present) diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft_preauth.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft_preauth.c index 9c294b6be099..48b4fd9cb57d 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft_preauth.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_ft_preauth.c @@ -339,9 +339,9 @@ QDF_STATUS lim_ft_setup_auth_session(struct mac_context *mac, if (req && req->pbssDescription) { lim_fill_ft_session(mac, req->pbssDescription, ft_session, - pe_session, WLAN_PHYMODE_AUTO, NULL); + pe_session, WLAN_PHYMODE_AUTO); lim_ft_prepare_add_bss_req(mac, ft_session, - req->pbssDescription, NULL); + req->pbssDescription); } return QDF_STATUS_SUCCESS; diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_link_monitoring_algo.c index 435ba2a4d136..c44d5b453fe7 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_link_monitoring_algo.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -452,9 +453,6 @@ lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId, void lim_handle_heart_beat_failure(struct mac_context *mac_ctx, struct pe_session *session) { - uint8_t curr_chan; - tpSirAddie scan_ie = NULL; - #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ host_log_beacon_update_pkt_type *log_ptr = NULL; #endif /* FEATURE_WLAN_DIAG_SUPPORT */ @@ -490,50 +488,19 @@ void lim_handle_heart_beat_failure(struct mac_context *mac_ctx, mac_ctx->lim.gLimHBfailureCntInLinkEstState++; /* - * Check if connected on the DFS channel, if not connected on - * DFS channel then only send the probe request otherwise tear - * down the link + * Before host received beacon miss, firmware has checked link + * by sending QoS NULL data, don't need host send probe req. + * Some IoT AP can send probe response, but can't send beacon + * sometimes, need disconnect too, or firmware will assert. */ - curr_chan = wlan_reg_freq_to_chan( - mac_ctx->pdev, session->curr_op_freq); - if (!lim_isconnected_on_dfs_channel(mac_ctx, curr_chan)) { - /* Detected continuous Beacon Misses */ - session->LimHBFailureStatus = true; - - /*Reset the HB packet count before sending probe*/ - limResetHBPktCount(session); - /** - * Send Probe Request frame to AP to see if - * it is still around. Wait until certain - * timeout for Probe Response from AP. - */ - pe_debug("HB missed from AP. Sending Probe Req"); - /* for searching AP, we don't include any more IE */ - if (session->lim_join_req) { - scan_ie = &session->lim_join_req->addIEScan; - lim_send_probe_req_mgmt_frame(mac_ctx, - &session->ssId, - session->bssId, session->curr_op_freq, - session->self_mac_addr, - session->dot11mode, - &scan_ie->length, scan_ie->addIEdata); - } else { - lim_send_probe_req_mgmt_frame(mac_ctx, - &session->ssId, - session->bssId, session->curr_op_freq, - session->self_mac_addr, - session->dot11mode, NULL, NULL); - } - } else { - /* - * Connected on DFS channel so should not send the - * probe request tear down the link directly - */ - lim_tear_down_link_with_ap(mac_ctx, - session->peSessionId, - REASON_BEACON_MISSED, - eLIM_LINK_MONITORING_DEAUTH); - } + lim_send_deauth_mgmt_frame(mac_ctx, + REASON_DISASSOC_DUE_TO_INACTIVITY, + session->bssId, + session, false); + lim_tear_down_link_with_ap(mac_ctx, + session->peSessionId, + REASON_BEACON_MISSED, + eLIM_LINK_MONITORING_DEAUTH); } else { /** * Heartbeat timer may have timed out diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 641a237b9dd3..1e024f023c73 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -43,6 +44,7 @@ #include "lim_process_fils.h" #include "wlan_blm_api.h" #include "wlan_mlme_twt_api.h" +#include "wlan_mlme_ucfg_api.h" /** * lim_update_stads_htcap() - Updates station Descriptor HT capability @@ -603,6 +605,88 @@ static void clean_up_ft_sha384(tpSirAssocRsp assoc_rsp, bool sha384_akm) } } +/** + * lim_get_iot_aggr_sz() - check and get IOT aggr size for configured OUI + * + * @mac_ctx: Pointer to Global MAC structure + * @ie_ptr: Pointer to starting IE in Beacon/Probe Response + * @ie_len: Length of all IEs combined + * @amsdu_sz: pointer to buffer to store AMSDU size + * @ampdu_sz: pointer to buffer to store AMPDU size + * + * This function is called to find configured vendor specific OUIs + * from the IEs in Beacon/Probe Response frames, if one of the OUI is + * present, get the configured aggr size for the OUI. + * + * Return: true if found, false otherwise. + */ +static bool +lim_get_iot_aggr_sz(struct mac_context *mac, uint8_t *ie_ptr, uint32_t ie_len, + uint32_t *amsdu_sz, uint32_t *ampdu_sz) +{ + const uint8_t *oui, *vendor_ie; + struct wlan_mlme_iot *iot; + uint32_t oui_len, aggr_num; + int i; + + iot = &mac->mlme_cfg->iot; + aggr_num = iot->aggr_num; + if (!aggr_num) + return false; + + for (i = 0; i < aggr_num; i++) { + oui = iot->aggr[i].oui; + oui_len = iot->aggr[i].oui_len; + vendor_ie = wlan_get_vendor_ie_ptr_from_oui(oui, oui_len, + ie_ptr, ie_len); + if (!vendor_ie) + continue; + + *amsdu_sz = iot->aggr[i].amsdu_sz; + *ampdu_sz = iot->aggr[i].ampdu_sz; + return true; + } + + return false; +} + +/** + * lim_update_iot_aggr_sz() - check and update IOT aggr size + * + * @mac_ctx: Pointer to Global MAC structure + * @ie_ptr: Pointer to starting IE in Beacon/Probe Response + * @ie_len: Length of all IEs combined + * @session_entry: A pointer to session entry + * + * This function is called to find configured vendor specific OUIs + * from the IEs in Beacon/Probe Response frames, and set the aggr + * size accordingly. + * + * Return: None + */ +static void +lim_update_iot_aggr_sz(struct mac_context *mac_ctx, uint8_t *ie_ptr, + uint32_t ie_len, struct pe_session *session_entry) +{ + int ret; + uint32_t amsdu_sz, ampdu_sz; + bool iot_hit; + + if (!ie_ptr || !ie_len) + return; + + iot_hit = lim_get_iot_aggr_sz(mac_ctx, ie_ptr, ie_len, + &amsdu_sz, &du_sz); + if (!iot_hit) + return; + + pe_debug("Try to set iot amsdu size: %u", amsdu_sz); + ret = wma_cli_set_command(session_entry->smeSessionId, + GEN_VDEV_PARAM_AMSDU, amsdu_sz, GEN_CMD); + if (ret) + pe_err("Failed to set iot amsdu size: %d", ret); +} + /** * lim_process_assoc_rsp_frame() - Processes assoc response * @mac_ctx: Pointer to Global MAC structure @@ -622,7 +706,7 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, uint32_t reassoc_frame_len, uint8_t subtype, struct pe_session *session_entry) { - uint8_t *body; + uint8_t *body, *ie; uint16_t caps, ie_len; uint32_t frame_len; tSirMacAddr current_bssid; @@ -1043,6 +1127,7 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, } pe_debug("Successfully Associated with BSS " QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(hdr->sa)); + #ifdef FEATURE_WLAN_ESE if (session_entry->eseContext.tsm.tsmInfo.state) session_entry->eseContext.tsm.tsmMetrics.RoamingCount = 0; @@ -1083,9 +1168,10 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, */ ie_len = lim_get_ielen_from_bss_description( &session_entry->lim_join_req->bssDescription); - lim_extract_ap_capabilities(mac_ctx, - (uint8_t *)session_entry->lim_join_req->bssDescription.ieFields, - ie_len, beacon); + ie = (uint8_t *)session_entry->lim_join_req->bssDescription.ieFields; + lim_update_iot_aggr_sz(mac_ctx, ie, ie_len, session_entry); + + lim_extract_ap_capabilities(mac_ctx, ie, ie_len, beacon); lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp, session_entry, beacon); diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_auth_frame.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_auth_frame.c index f4d0216345b8..607555e8c5e2 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-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 @@ -428,7 +429,7 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx, pe_session->limMlmState); if (LIM_IS_AP_ROLE(pe_session)) { - struct tLimPreAuthNode *sta_pre_auth_ctx; + struct tLimPreAuthNode *pre_auth_node; rx_flags = RXMGMT_FLAG_EXTERNAL_AUTH; /* Add preauth node when the first SAE authentication frame @@ -438,12 +439,16 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx, * SAE protocol optimizations. */ /* Extract pre-auth context for the STA, if any. */ - sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, - mac_hdr->sa); - if (!sta_pre_auth_ctx || - (sta_pre_auth_ctx->mlmState != eLIM_MLM_WT_SAE_AUTH_STATE && - sta_pre_auth_ctx->mlmState != - eLIM_MLM_AUTHENTICATED_STATE)) { + pre_auth_node = lim_search_pre_auth_list(mac_ctx, mac_hdr->sa); + if (!pre_auth_node || + (pre_auth_node->mlmState != eLIM_MLM_WT_SAE_AUTH_STATE)) { + if (pre_auth_node) { + pe_debug("Delete existing preauth node for SAE peer in state: %u " + QDF_MAC_ADDR_FMT, + pre_auth_node->mlmState, + QDF_MAC_ADDR_REF(mac_hdr->sa)); + lim_delete_pre_auth_node(mac_ctx, mac_hdr->sa); + } lim_external_auth_add_pre_auth_node(mac_ctx, mac_hdr, eLIM_MLM_WT_SAE_AUTH_STATE); } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index a3c32714b92f..c10e03508fcf 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1650,10 +1650,41 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct } } +static void lim_send_pre_auth_failure(uint8_t vdev_id, tSirMacAddr bssid) +{ + struct scheduler_msg sch_msg = {0}; + struct wmi_roam_auth_status_params *params; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + params = qdf_mem_malloc(sizeof(*params)); + if (!params) + return; + + params->vdev_id = vdev_id; + params->preauth_status = STATUS_UNSPECIFIED_FAILURE; + qdf_mem_copy(params->bssid.bytes, bssid, QDF_MAC_ADDR_SIZE); + qdf_mem_zero(params->pmkid, PMKID_LEN); + + sch_msg.type = WMA_ROAM_PRE_AUTH_STATUS; + sch_msg.bodyptr = params; + pe_debug("Sending pre auth failure for mac_addr " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(params->bssid.bytes)); + + status = scheduler_post_message(QDF_MODULE_ID_PE, + QDF_MODULE_ID_WMA, + QDF_MODULE_ID_WMA, + &sch_msg); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("Sending preauth status failed"); + qdf_mem_free(params); + } +} + static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx, struct pe_session *session_entry) { struct sae_auth_retry *sae_retry; + tpSirMacMgmtHdr mac_hdr; sae_retry = mlme_get_sae_auth_retry(session_entry->vdev); if (!(sae_retry && sae_retry->sae_auth.data)) { @@ -1662,6 +1693,16 @@ static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx, return; } + if (!sae_retry->sae_auth_max_retry) { + if (MLME_IS_ROAMING_IN_PROG(mac_ctx->psoc, + session_entry->vdev_id)) { + mac_hdr = (tpSirMacMgmtHdr)sae_retry->sae_auth.data; + lim_send_pre_auth_failure(session_entry->vdev_id, + mac_hdr->bssId); + } + goto free_and_deactivate_timer; + } + pe_debug("retry sae auth for seq num %d vdev id %d", mac_ctx->mgmtSeqNum, session_entry->vdev_id); lim_send_frame(mac_ctx, session_entry->vdev_id, @@ -1669,7 +1710,7 @@ static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx, sae_retry->sae_auth_max_retry--; /* Activate Auth Retry timer if max_retries are not done */ - if (!sae_retry->sae_auth_max_retry || (tx_timer_activate( + if ((tx_timer_activate( &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) != TX_SUCCESS)) goto free_and_deactivate_timer; diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 073dc9dec21d..2e3e62055db1 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -1227,6 +1228,7 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf) struct bss_description *bss_desc; QDF_STATUS status; int8_t reg_max = 0; + struct mlme_legacy_priv *mlme_priv; if (!mac_ctx || !msg_buf) { QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, @@ -1556,6 +1558,49 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf) session->limCurrentBssCaps = session->lim_join_req->bssDescription.capabilityInfo; + mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); + if (!mlme_priv) { + pe_err("Invalid mlme priv object"); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie, + DOT11F_IE_EXTCAP_MAX_LEN + 2); + + if (session->lim_join_req->addIEAssoc.length) { + uint8_t *add_ie = NULL; + uint16_t add_ie_len; + + add_ie_len = session->lim_join_req->addIEAssoc.length; + add_ie = qdf_mem_malloc(add_ie_len); + if (!add_ie) { + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + qdf_mem_copy(add_ie, + session->lim_join_req-> + addIEAssoc.addIEdata, + add_ie_len); + + status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len, + DOT11F_EID_EXTCAP, ONE_BYTE, + NULL, 0, + mlme_priv->connect_info. + ext_cap_ie, + DOT11F_IE_EXTCAP_MAX_LEN); + qdf_mem_free(add_ie); + + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("Parsing of ext cap failed with status : %d", + status); + qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie, + DOT11F_IE_EXTCAP_MAX_LEN + 2); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + } + mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); if (!mlme_obj) return; @@ -2491,13 +2536,14 @@ static void __lim_process_sme_disassoc_req(struct mac_context *mac, disassocTrigger = eLIM_HOST_DISASSOC; goto sendDisassoc; } - pe_debug("vdev %d (session %d) Systemrole %d Reason: %u SmeState: %d limMlmState %d ho fail %d send OTA %d from: " - QDF_MAC_ADDR_FMT, pe_session->vdev_id, pe_session->peSessionId, + pe_debug("vdev %d (session %d) Systemrole %d Reason: %u SmeState: %d limMlmState %d ho fail %d send OTA %d from: " QDF_MAC_ADDR_FMT " bssid :" QDF_MAC_ADDR_FMT, + pe_session->vdev_id, pe_session->peSessionId, GET_LIM_SYSTEM_ROLE(pe_session), smeDisassocReq.reasonCode, pe_session->limSmeState, pe_session->limMlmState, smeDisassocReq.process_ho_fail, smeDisassocReq.doNotSendOverTheAir, - QDF_MAC_ADDR_REF(smeDisassocReq.peer_macaddr.bytes)); + QDF_MAC_ADDR_REF(smeDisassocReq.peer_macaddr.bytes), + QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, pe_session, @@ -2833,11 +2879,12 @@ static void __lim_process_sme_deauth_req(struct mac_context *mac_ctx, deauth_trigger = eLIM_HOST_DEAUTH; goto send_deauth; } - pe_debug("vdev %d (session %d) Systemrole %d reasoncode %u limSmestate %d limMlmState %d from " - QDF_MAC_ADDR_FMT, vdev_id, session_entry->peSessionId, + pe_debug("vdev %d (session %d) Systemrole %d reasoncode %u limSmestate %d limMlmState %d from " QDF_MAC_ADDR_FMT " bssid : " QDF_MAC_ADDR_FMT, + vdev_id, session_entry->peSessionId, GET_LIM_SYSTEM_ROLE(session_entry), sme_deauth_req.reasonCode, session_entry->limSmeState, session_entry->limMlmState, - QDF_MAC_ADDR_REF(sme_deauth_req.peer_macaddr.bytes)); + QDF_MAC_ADDR_REF(sme_deauth_req.peer_macaddr.bytes), + QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, session_entry, 0, sme_deauth_req.reasonCode); @@ -4822,23 +4869,53 @@ static void lim_process_disconnect_sta(struct pe_session *session, sizeof(*msg), msg); } +static +struct pe_session *lim_get_disconnect_session(struct mac_context *mac_ctx, + uint8_t *bssid, + uint8_t vdev_id) +{ + struct pe_session *session; + uint8_t session_id; + + /* Try to find pe session with bssid */ + session = pe_find_session_by_bssid(mac_ctx, bssid, + &session_id); + + /* + * If bssid search fail try to find by vdev id, this can happen if + * Roaming change the BSSID during disconnect was getting processed. + */ + if (!session) { + session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); + if (session) + pe_info("Session found for vdev_id : %d session id : %d Requested bssid : " QDF_MAC_ADDR_FMT " Actual bssid : " QDF_MAC_ADDR_FMT " sme state %d mlm state %d", + vdev_id, session->peSessionId, + QDF_MAC_ADDR_REF(bssid), + QDF_MAC_ADDR_REF(session->bssId), + session->limSmeState, + session->limMlmState); + } + + return session; +} + static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx, struct scheduler_msg *msg) { struct disassoc_cnf sme_disassoc_cnf; struct pe_session *session; - uint8_t session_id; uint32_t *err_msg = NULL; QDF_STATUS status; qdf_mem_copy(&sme_disassoc_cnf, msg->bodyptr, sizeof(sme_disassoc_cnf)); - session = pe_find_session_by_bssid(mac_ctx, - sme_disassoc_cnf.bssid.bytes, - &session_id); + session = lim_get_disconnect_session(mac_ctx, + sme_disassoc_cnf.bssid.bytes, + sme_disassoc_cnf.vdev_id); if (!session) { - pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, - QDF_MAC_ADDR_REF(sme_disassoc_cnf.bssid.bytes)); + pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT "vdev id: %d", + QDF_MAC_ADDR_REF(sme_disassoc_cnf.bssid.bytes), + sme_disassoc_cnf.vdev_id); status = lim_prepare_disconnect_done_ind (mac_ctx, &err_msg, sme_disassoc_cnf.vdev_id, @@ -4852,11 +4929,24 @@ static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx, return; } - if (LIM_IS_STA_ROLE(session)) + /* In LFR3, if Roam synch indication processing might fail + * in CSR, then CSR and LIM peer will be out-of-sync. + * To recover from this, during HO failure delete the LIM + * session corresponding to the vdev id, irrespective of the + * BSSID. Copy the BSSID present in LIM session into the + * disassoc cnf msg sent to LIM and SME. + */ + if (LIM_IS_STA_ROLE(session)) { + struct disassoc_cnf *sta_disassoc_cnf = msg->bodyptr; + qdf_mem_copy(sta_disassoc_cnf->bssid.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(sta_disassoc_cnf->peer_macaddr.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); lim_process_disconnect_sta(session, msg); - else + } else { __lim_process_sme_disassoc_cnf(mac_ctx, (uint32_t *)msg->bodyptr); + } } static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx, @@ -4864,16 +4954,16 @@ static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx, { struct disassoc_req disassoc_req; struct pe_session *session; - uint8_t session_id; qdf_mem_copy(&disassoc_req, msg->bodyptr, sizeof(struct disassoc_req)); - session = pe_find_session_by_bssid(mac_ctx, - disassoc_req.bssid.bytes, - &session_id); + session = lim_get_disconnect_session(mac_ctx, + disassoc_req.bssid.bytes, + disassoc_req.sessionId); if (!session) { - pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, - QDF_MAC_ADDR_REF(disassoc_req.bssid.bytes)); + pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT "vdev id: %d", + QDF_MAC_ADDR_REF(disassoc_req.bssid.bytes), + disassoc_req.sessionId); lim_send_sme_disassoc_ntf(mac_ctx, disassoc_req.peer_macaddr.bytes, eSIR_SME_INVALID_PARAMETERS, @@ -4900,11 +4990,24 @@ static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx, return; } - if (LIM_IS_STA_ROLE(session)) + /* In LFR3, if Roam synch indication processing might fail + * in CSR, then CSR and LIM peer will be out-of-sync. + * To recover from this, during HO failure delete the LIM + * session corresponding to the vdev id, irrespective of the + * BSSID. Copy the BSSID present in LIM session into the + * disassoc cnf msg sent to LIM and SME. + */ + if (LIM_IS_STA_ROLE(session)) { + struct disassoc_req *sta_disassoc_req = msg->bodyptr; + qdf_mem_copy(sta_disassoc_req->bssid.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(sta_disassoc_req->peer_macaddr.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); lim_process_disconnect_sta(session, msg); - else + } else { __lim_process_sme_disassoc_req(mac_ctx, (uint32_t *)msg->bodyptr); + } } static void lim_process_sme_deauth_req(struct mac_context *mac_ctx, @@ -4912,16 +5015,17 @@ static void lim_process_sme_deauth_req(struct mac_context *mac_ctx, { struct deauth_req sme_deauth_req; struct pe_session *session; - uint8_t session_id; qdf_mem_copy(&sme_deauth_req, msg->bodyptr, sizeof(sme_deauth_req)); - session = pe_find_session_by_bssid(mac_ctx, - sme_deauth_req.bssid.bytes, - &session_id); + session = lim_get_disconnect_session(mac_ctx, + sme_deauth_req.bssid.bytes, + sme_deauth_req.vdev_id); + if (!session) { - pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, - QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes)); + pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT "vdev id: %d", + QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes), + sme_deauth_req.vdev_id); lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peer_macaddr.bytes, eSIR_SME_INVALID_PARAMETERS, @@ -4942,11 +5046,24 @@ static void lim_process_sme_deauth_req(struct mac_context *mac_ctx, return; } - if (LIM_IS_STA_ROLE(session)) + /* In LFR3, if Roam synch indication processing might fail + * in CSR, then CSR and LIM peer will be out-of-sync. + * To recover from this, during HO failure delete the LIM + * session corresponding to the vdev id, irrespective of the + * BSSID. Copy the BSSID present in LIM session into the + * disassoc cnf msg sent to LIM and SME. + */ + if (LIM_IS_STA_ROLE(session)) { + struct deauth_req *sta_deauth_req = msg->bodyptr; + qdf_mem_copy(sta_deauth_req->bssid.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(sta_deauth_req->peer_macaddr.bytes, + session->bssId, QDF_MAC_ADDR_SIZE); lim_process_disconnect_sta(session, msg); - else + } else { __lim_process_sme_deauth_req(mac_ctx, (uint32_t *)msg->bodyptr); + } } /** @@ -6186,6 +6303,11 @@ static void lim_process_set_ie_req(struct mac_context *mac_ctx, uint32_t *msg_bu { struct send_extcap_ie *msg; QDF_STATUS status; + tDot11fIEExtCap extra_ext_cap = {0}; + uint16_t vdev_id; + struct wlan_objmgr_vdev *vdev = NULL; + struct mlme_legacy_priv *mlme_priv; + struct s_ext_cap *p_ext_cap; if (!msg_buf) { pe_err("Buffer is Pointing to NULL"); @@ -6193,10 +6315,37 @@ static void lim_process_set_ie_req(struct mac_context *mac_ctx, uint32_t *msg_bu } msg = (struct send_extcap_ie *)msg_buf; - status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, NULL, false); - if (QDF_STATUS_SUCCESS != status) - pe_err("Unable to send ExtCap to FW"); + vdev_id = msg->session_id; + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id, + WLAN_LEGACY_SME_ID); + if (!vdev) + return; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + return; + } + + if (!mlme_priv->connect_info.ext_cap_ie[0]) + goto send_ie; + + lim_update_extcap_struct(mac_ctx, mlme_priv->connect_info.ext_cap_ie, + &extra_ext_cap); + + p_ext_cap = (struct s_ext_cap *)extra_ext_cap.bytes; + if (p_ext_cap->interworking_service) + p_ext_cap->qos_map = 1; + + extra_ext_cap.num_bytes = lim_compute_ext_cap_ie_length(&extra_ext_cap); + +send_ie: + status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, &extra_ext_cap, + true); + if (QDF_IS_STATUS_ERROR(status)) + pe_err("Unable to send ExtCap to FW"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); } #ifdef WLAN_FEATURE_11AX_BSS_COLOR diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_send_management_frames.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_send_management_frames.c index 05a79e447834..a12d738e4010 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-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 @@ -49,6 +50,7 @@ #include "sme_trace.h" #include "rrm_api.h" #include "qdf_crypto.h" +#include "parser_api.h" #include "wma_types.h" #include @@ -650,6 +652,7 @@ lim_send_probe_rsp_mgmt_frame(struct mac_context *mac_ctx, populate_dot11f_ssid(mac_ctx, (tSirMacSSid *) ssid, &frm->SSID); populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, &frm->SuppRates, pe_session); + populate_dot11f_tpc_report(mac_ctx, &frm->TPCReport, pe_session); populate_dot11f_ds_params( mac_ctx, &frm->DSParams, @@ -5271,8 +5274,10 @@ QDF_STATUS lim_send_sa_query_response_frame(struct mac_context *mac, nStatus); } - pe_debug("Sending a SA Query Response to"); - lim_print_mac_addr(mac, peer, LOGD); + pe_debug("Sending SA Query Response to "QDF_MAC_ADDR_FMT" op_class %d prim_ch_num %d freq_seg_1_ch_num %d oci_present %d", + QDF_MAC_ADDR_REF(peer), frm.oci.op_class, + frm.oci.prim_ch_num, frm.oci.freq_seg_1_ch_num, + frm.oci.present); if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) || pe_session->opmode == QDF_P2P_CLIENT_MODE || @@ -5677,8 +5682,6 @@ error_delba: return qdf_status; } -#define WLAN_SAE_AUTH_TIMEOUT 1000 - /** * lim_tx_mgmt_frame() - Transmits Auth mgmt frame * @mac_ctx Pointer to Global MAC structure @@ -5738,6 +5741,7 @@ lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id, struct pe_session *session; struct sae_auth_retry *sae_retry; uint8_t retry_count = 0; + uint32_t val = 0; session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); if (!session) { @@ -5774,16 +5778,18 @@ lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id, return; pe_debug("SAE auth frame queued vdev_id %d seq_num %d", - vdev_id, mac_ctx->mgmtSeqNum); + vdev_id, mac_ctx->mgmtSeqNum + 1); qdf_mem_copy(sae_retry->sae_auth.data, frame, frame_len); mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId = session->peSessionId; sae_retry->sae_auth.len = frame_len; sae_retry->sae_auth_max_retry = retry_count; + val = mac_ctx->mlme_cfg->timeouts.sae_auth_failure_timeout; + tx_timer_change( &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer, - SYS_MS_TO_TICKS(WLAN_SAE_AUTH_TIMEOUT), 0); + SYS_MS_TO_TICKS(val), 0); /* Activate Auth Retry timer */ if (tx_timer_activate( &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) != diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/nan/nan_datapath.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/nan/nan_datapath.c index f20e53801460..07375fcb07f1 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/nan/nan_datapath.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/nan/nan_datapath.c @@ -74,6 +74,8 @@ static QDF_STATUS lim_add_ndi_peer(struct mac_context *mac_ctx, pe_info("Need to create NDI Peer :" QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac_addr.bytes)); + ucfg_nan_set_peer_mc_list(session->vdev, peer_mac_addr); + peer_idx = lim_assign_peer_idx(mac_ctx, session); if (!peer_idx) { pe_err("Invalid peer_idx: %d", peer_idx); diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/sch/sch_beacon_gen.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/sch/sch_beacon_gen.c index fdc828b16d1f..a1f9c02da179 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/sch/sch_beacon_gen.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 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 @@ -167,7 +168,7 @@ sch_append_addn_ie(struct mac_context *mac_ctx, struct pe_session *session, /** * sch_get_csa_ecsa_count_offset() - get the offset of Switch count field - * @ie: pointer to the beggining of IEs in the beacon frame buffer + * @ie: pointer to the beginning of IEs in the beacon frame buffer * @ie_len: length of the IEs in the buffer * @csa_count_offset: pointer to the csa_count_offset variable in the caller * @ecsa_count_offset: pointer to the ecsa_count_offset variable in the caller @@ -206,6 +207,9 @@ static void sch_get_csa_ecsa_count_offset(uint8_t *ie, uint32_t ie_len, *ecsa_count_offset = offset + SCH_ECSA_SWITCH_COUNT_OFFSET; + if (ie_len < elem_len) + return; + ie_len -= elem_len; offset += elem_len; ptr += (elem_len + 2); @@ -881,6 +885,7 @@ void lim_update_probe_rsp_template_ie_bitmap_beacon2(struct mac_context *mac, sizeof(beacon2->transmit_power_env[i])); } } + prb_rsp->num_transmit_power_env = num_tpe; if (beacon2->VHTExtBssLoad.present) { set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, @@ -935,6 +940,14 @@ void lim_update_probe_rsp_template_ie_bitmap_beacon2(struct mac_context *mac, sizeof(beacon2->he_6ghz_band_cap)); } + if (beacon2->TPCReport.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + WLAN_ELEMID_TPCREP); + qdf_mem_copy((void *)&prb_rsp->TPCReport, + (void *)&beacon2->TPCReport, + sizeof(beacon2->TPCReport)); + } + } void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos) diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c index 17d6b1836d34..721bb54919b0 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -24,7 +24,7 @@ * * * This file was automatically generated by 'framesc' - * Mon Jul 19 14:21:41 2021 from the following file(s): + * Wed Sep 29 13:23:21 2021 from the following file(s): * * dot11f.frms * @@ -335,7 +335,7 @@ static uint32_t get_container_ies_len(tpAniSirGlobal pCtx, len += *(pBufRemaining+1); pBufRemaining += len + 2; len += 2; - while (len < nBuf) { + while (len + 1 < nBuf) { pIe = find_ie_defn(pCtx, pBufRemaining, nBuf - len, IEs); if (NULL == pIe) break; @@ -15186,25 +15186,30 @@ static uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, } /* & length, */ if (pTlv->sLen == 2) { - framesntohs(pCtx, &len, pBufRemaining, pTlv->fMsb); if (2 > nBufRemaining) { FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " "fewer two byte(s) remaining.\n")); status |= DOT11F_INCOMPLETE_TLV; FRAMES_DBG_BREAK(); goto MandatoryCheck; - } - pBufRemaining += 2; - nBufRemaining -= 2; + } + framesntohs(pCtx, &len, pBufRemaining, pTlv->fMsb); + pBufRemaining += 2; + nBufRemaining -= 2; } else { len = *pBufRemaining; pBufRemaining += 1; nBufRemaining -= 1; } } else { + if (TLVs[0].sType > nBufRemaining) { + FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " + "fewer LVs[0].sType byte(s) remaining.\n")); + status |= DOT11F_INCOMPLETE_TLV; + goto MandatoryCheck; + } pBufRemaining += TLVs[0].sType; nBufRemaining -= TLVs[0].sType; - framesntohs(pCtx, &len, pBufRemaining, (TLVs[0].sType == 2)); if (2 > nBufRemaining) { FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " "fewer two byte(s) remaining.\n")); @@ -15212,6 +15217,7 @@ static uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, FRAMES_DBG_BREAK(); goto MandatoryCheck; } + framesntohs(pCtx, &len, pBufRemaining, (TLVs[0].sType == 2)); pBufRemaining += 2; nBufRemaining -= 2; } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 91ca42224929..7577ecb44541 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -828,7 +829,7 @@ populate_dot11f_ext_supp_rates(struct mac_context *mac, uint8_t nChannelNum, struct pe_session *pe_session) { QDF_STATUS nsir_status; - qdf_size_t nRates = 0; + qdf_size_t n_rates = 0; uint8_t rates[WLAN_SUPPORTED_RATES_IE_MAX_LEN]; /* Use the ext rates present in session entry whenever nChannelNum is set to OPERATIONAL @@ -837,9 +838,9 @@ populate_dot11f_ext_supp_rates(struct mac_context *mac, uint8_t nChannelNum, */ if (POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum) { if (pe_session) { - nRates = pe_session->extRateSet.numRates; + n_rates = pe_session->extRateSet.numRates; qdf_mem_copy(rates, pe_session->extRateSet.rate, - nRates); + n_rates); } else { pe_err("no session context exists while populating Operational Rate Set"); } @@ -848,20 +849,21 @@ populate_dot11f_ext_supp_rates(struct mac_context *mac, uint8_t nChannelNum, pe_err("null pe_session"); return QDF_STATUS_E_INVAL; } - nRates = WLAN_SUPPORTED_RATES_IE_MAX_LEN; + n_rates = WLAN_SUPPORTED_RATES_IE_MAX_LEN; nsir_status = mlme_get_ext_opr_rate(pe_session->vdev, rates, - &nRates); + &n_rates); if (QDF_IS_STATUS_ERROR(nsir_status)) { - nRates = 0; + n_rates = 0; pe_err("Failed to retrieve nItem from CFG status: %d", (nsir_status)); return nsir_status; } } - if (0 != nRates) { - pDot11f->num_rates = (uint8_t) nRates; - qdf_mem_copy(pDot11f->rates, rates, nRates); + if (0 != n_rates) { + pe_debug("ext supp rates present, num %d", (uint8_t)n_rates); + pDot11f->num_rates = (uint8_t)n_rates; + qdf_mem_copy(pDot11f->rates, rates, n_rates); pDot11f->present = 1; } @@ -3432,9 +3434,9 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac, */ auth_type = session_entry->connected_akm; sha384_akm = lim_is_sha384_akm(auth_type); + ie_ptr = frame + FIXED_PARAM_OFFSET_ASSOC_RSP; + ie_len = frame_len - FIXED_PARAM_OFFSET_ASSOC_RSP; if (sha384_akm) { - ie_ptr = frame + FIXED_PARAM_OFFSET_ASSOC_RSP; - ie_len = frame_len - FIXED_PARAM_OFFSET_ASSOC_RSP; qdf_status = wlan_parse_ftie_sha384(ie_ptr, ie_len, pAssocRsp); if (QDF_IS_STATUS_ERROR(qdf_status)) { pe_err("FT IE parsing failed status:%d", status); diff --git a/drivers/staging/qcacld-3.0/core/pld/inc/pld_common.h b/drivers/staging/qcacld-3.0/core/pld/inc/pld_common.h index dc31bc275306..04be7b202da4 100644 --- a/drivers/staging/qcacld-3.0/core/pld/inc/pld_common.h +++ b/drivers/staging/qcacld-3.0/core/pld/inc/pld_common.h @@ -756,6 +756,15 @@ int pld_qmi_send(struct device *dev, int type, void *cmd, int (*cb)(void *ctx, void *event, int event_len)); bool pld_is_fw_dump_skipped(struct device *dev); +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +int pld_is_low_power_mode(struct device *dev); +#else +static inline int pld_is_low_power_mode(struct device *dev) +{ + return 0; +} +#endif + /** * pld_is_pdr() - Check WLAN PD is Restarted * diff --git a/drivers/staging/qcacld-3.0/core/pld/src/pld_common.c b/drivers/staging/qcacld-3.0/core/pld/src/pld_common.c index 1257b701d152..13e161862b0f 100644 --- a/drivers/staging/qcacld-3.0/core/pld/src/pld_common.c +++ b/drivers/staging/qcacld-3.0/core/pld/src/pld_common.c @@ -2727,6 +2727,38 @@ int pld_is_fw_down(struct device *dev) return ret; } +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +/** + * pld_is_low_power_mode() - Check WLAN fw is in low power + * @dev: device + * + * This API will be called to check if WLAN FW is in low power or not. + * Low power means either Deep Sleep or Hibernate state. + * + * Return: 0 FW is not in low power mode + * Otherwise FW is low power mode + * Always return 0 for unsupported bus type + */ +int pld_is_low_power_mode(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_is_low_power_mode(dev); + break; + case PLD_BUS_TYPE_PCIE_FW_SIM: + case PLD_BUS_TYPE_IPCI_FW_SIM: + case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: + default: + break; + } + return ret; +} +#endif + /** * pld_force_assert_target() - Send a force assert request to FW. * @dev: device pointer diff --git a/drivers/staging/qcacld-3.0/core/pld/src/pld_snoc.h b/drivers/staging/qcacld-3.0/core/pld/src/pld_snoc.h index 270ac1477a24..969504dd2e6c 100644 --- a/drivers/staging/qcacld-3.0/core/pld/src/pld_snoc.h +++ b/drivers/staging/qcacld-3.0/core/pld/src/pld_snoc.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -149,6 +150,12 @@ static inline int pld_snoc_is_fw_down(struct device *dev) { return 0; } + +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return 0; +} + static inline int pld_snoc_set_fw_log_mode(struct device *dev, u8 fw_log_mode) { return 0; @@ -329,6 +336,18 @@ static inline int pld_snoc_is_fw_down(struct device *dev) return icnss_is_fw_down(); } +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return icnss_is_low_power(); +} +#else +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return 0; +} +#endif + static inline int pld_snoc_is_qmi_disable(struct device *dev) { if (!dev) diff --git a/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h b/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h index dc6cef2c72e2..75ab17b109b1 100644 --- a/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h +++ b/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h @@ -532,6 +532,7 @@ struct sap_config { uint8_t long_retry_limit; tSirMacRateSet supported_rates; tSirMacRateSet extended_rates; + bool require_h2e; enum sap_acs_dfs_mode acs_dfs_mode; struct hdd_channel_info *channel_info; uint32_t channel_info_count; diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c b/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c index 31d5eb43f60c..7602ff55b37a 100644 --- a/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c +++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c @@ -2262,6 +2262,9 @@ uint32_t sap_select_channel(mac_handle_t mac_handle, /*Loop till get the best channel in the given range */ for (count = 0; count < spect_info->numSpectChans; count++) { + if (!spect_info->pSpectCh[count].valid) + continue; + best_chan_freq = spect_info->pSpectCh[count].chan_freq; /* check if best_ch_num is in preferred channel list */ best_chan_freq = @@ -2309,6 +2312,9 @@ uint32_t sap_select_channel(mac_handle_t mac_handle, if (!ch_in_pcl(sap_ctx, best_chan_freq)) { uint32_t cal_chan_freq, cal_chan_weight; for (count = 0; count < spect_info->numSpectChans; count++) { + if (!spect_info->pSpectCh[count].valid) + continue; + cal_chan_freq = spect_info->pSpectCh[count].chan_freq; cal_chan_weight = spect_info->pSpectCh[count].weight; /* skip pcl channel whose weight is bigger than best */ diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c b/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c index 2a9f53a7fcf3..85596813b7a8 100644 --- a/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c +++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c @@ -797,7 +797,7 @@ sap_validate_chan(struct sap_context *sap_context, uint32_t sta_sap_bit_mask = QDF_STA_MASK | QDF_SAP_MASK; uint32_t concurrent_state; bool go_force_scc; - struct ch_params ch_params; + struct ch_params ch_params = {0}; mac_handle = cds_get_context(QDF_MODULE_ID_SME); mac_ctx = MAC_CONTEXT(mac_handle); @@ -837,7 +837,15 @@ sap_validate_chan(struct sap_context *sap_context, sap_context->cc_switch_mode); sap_debug("After check overlap: sap freq %d con freq:%d", sap_context->chan_freq, con_ch_freq); - ch_params = sap_context->ch_params; + /* + * For non-DBS platform, a 2.4Ghz can become a 5Ghz freq + * so lets used max BW in that case, if it remain 2.4Ghz + * then BW will be limited to 20 anyway + */ + if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_context->chan_freq)) + ch_params.ch_width = CH_WIDTH_MAX; + else + ch_params = sap_context->ch_params; if (sap_context->cc_switch_mode != QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION) { @@ -851,6 +859,9 @@ sap_validate_chan(struct sap_context *sap_context, return QDF_STATUS_E_ABORTED; } } + /* if CH width didn't change fallback to original */ + if (ch_params.ch_width == CH_WIDTH_MAX) + ch_params = sap_context->ch_params; sap_debug("After check concurrency: con freq:%d", con_ch_freq); @@ -2288,6 +2299,10 @@ static QDF_STATUS sap_goto_starting(struct sap_context *sap_ctx, eSAP_CHANNEL_CHANGE_EVENT, (void *)eSAP_STATUS_SUCCESS); sap_dfs_set_current_channel(sap_ctx); + /* Reset radar found flag before start sap, the flag will + * be set when radar found in CAC wait. + */ + mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false; sap_debug("session: %d", sap_ctx->sessionId); @@ -2429,7 +2444,7 @@ static QDF_STATUS sap_fsm_handle_radar_during_cac(struct sap_context *sap_ctx, } /** - * sap_fsm_handle_start_failure() - handle start failure or stop during cac wait + * sap_fsm_handle_start_failure() - handle sap start failure * @sap_ctx: SAP context * @msg: event msg * @mac_handle: Opaque handle to the global MAC context @@ -2442,13 +2457,11 @@ static QDF_STATUS sap_fsm_handle_start_failure(struct sap_context *sap_ctx, { QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; - if (msg == eSAP_HDD_STOP_INFRA_BSS && - (QDF_IS_STATUS_SUCCESS(wlan_vdev_is_dfs_cac_wait(sap_ctx->vdev)) || - QDF_IS_STATUS_SUCCESS( - wlan_vdev_is_restart_progress(sap_ctx->vdev)))) { + if (msg == eSAP_HDD_STOP_INFRA_BSS) { /* Transition from SAP_STARTING to SAP_STOPPING */ - sap_debug("In cac wait state from state %s => %s", + sap_debug("SAP start is in progress, state from state %s => %s", "SAP_STARTING", "SAP_STOPPING"); + /* * Stop the CAC timer only in following conditions * single AP: if there is a single AP then stop timer @@ -2652,6 +2665,7 @@ static QDF_STATUS sap_fsm_state_starting(struct sap_context *sap_ctx, mac_handle); } else { sap_debug("skip cac timer"); + mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false; /* * If hostapd starts AP on dfs channel, * hostapd will wait for CAC START/CAC END @@ -3109,6 +3123,8 @@ sapconvert_to_csr_profile(struct sap_config *config, eCsrRoamBssType bssType, config->extended_rates.numRates; } + profile->require_h2e = config->require_h2e; + qdf_status = ucfg_mlme_get_sap_chan_switch_rate_enabled( mac_ctx->psoc, &chan_switch_hostapd_rate_enabled); diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_module.c b/drivers/staging/qcacld-3.0/core/sap/src/sap_module.c index 49f1894ee807..e0262ec99646 100644 --- a/drivers/staging/qcacld-3.0/core/sap/src/sap_module.c +++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_module.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -1234,6 +1235,7 @@ wlansap_get_csa_chanwidth_from_phymode(struct sap_context *sap_context, enum phy_ch_width ch_width, concurrent_bw = 0; struct mac_context *mac; struct ch_params ch_params = {0}; + uint32_t channel_bonding_mode = 0; mac = sap_get_mac_context(); if (!mac) { @@ -1249,7 +1251,14 @@ wlansap_get_csa_chanwidth_from_phymode(struct sap_context *sap_context, */ ch_width = CH_WIDTH_20MHZ; } else { - ch_width = wlansap_get_max_bw_by_phymode(sap_context); + wlan_mlme_get_channel_bonding_5ghz(mac->psoc, + &channel_bonding_mode); + if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) && + (!channel_bonding_mode)) + ch_width = CH_WIDTH_20MHZ; + else + ch_width = wlansap_get_max_bw_by_phymode(sap_context); + concurrent_bw = wlan_sap_get_concurrent_bw( mac->pdev, mac->psoc, chan_freq, ch_width); @@ -1263,11 +1272,12 @@ wlansap_get_csa_chanwidth_from_phymode(struct sap_context *sap_context, ch_width = ch_params.ch_width; if (tgt_ch_params) *tgt_ch_params = ch_params; - sap_nofl_debug("freq %d bw %d (phymode %d, con bw %d, tgt bw %d)", + sap_nofl_debug("freq %d bw %d (phymode %d, con bw %d, tgt bw %d) channel bonding 5g %d", chan_freq, ch_width, sap_context->csr_roamProfile.phyMode, concurrent_bw, - tgt_ch_params ? tgt_ch_params->ch_width : CH_WIDTH_MAX); + tgt_ch_params ? tgt_ch_params->ch_width : CH_WIDTH_MAX, + channel_bonding_mode); return ch_width; } @@ -3227,6 +3237,11 @@ qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx, return wlansap_get_safe_channel_from_pcl_and_acs_range(sap_ctx); } else if (wlan_reg_is_passive_for_freq(mac->pdev, sap_ctx->chan_freq)) { + sap_ctx->chan_freq_before_switch_band = sap_ctx->chan_freq; + sap_ctx->chan_width_before_switch_band = + sap_ctx->ch_params.ch_width; + sap_debug("Save chan info before switch: %d, width: %d", + sap_ctx->chan_freq, sap_ctx->ch_params.ch_width); sap_debug("channel is passive"); *csa_reason = CSA_REASON_CHAN_PASSIVE; return wlansap_get_safe_channel_from_pcl_for_sap(sap_ctx); diff --git a/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h b/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h index 906a838827a4..133896da4386 100644 --- a/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h +++ b/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h @@ -717,6 +717,7 @@ struct csr_roam_profile { tSirMacRateSet extended_rates; struct qdf_mac_addr bssid_hint; bool force_24ghz_in_ht20; + bool require_h2e; uint32_t cac_duration_ms; uint32_t dfs_regdomain; #ifdef WLAN_FEATURE_FILS_SK @@ -725,6 +726,7 @@ struct csr_roam_profile { struct wlan_fils_connection_info *fils_con_info; #endif bool force_rsne_override; + bool is_hs_20_ap; }; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH diff --git a/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h b/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h index d80158867460..6386522603a3 100644 --- a/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h +++ b/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h @@ -669,6 +669,30 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, */ QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id, tPmkidCacheInfo *pmk_cache); + +/** + * sme_roam_events_register_callback() - Register roam events callback + * @mac_handle: Opaque handle to the MAC context + * @roam_rt_stats_cb: Function to be invoked for roam events stats + * + * This function will register a callback for roams events stats. + * + * Return: void + */ +void sme_roam_events_register_callback(mac_handle_t mac_handle, + void (*roam_rt_stats_cb)( + hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats)); + +/** + * sme_roam_events_deregister_callback() - DeRegister roam events callback + * @mac_handle: Opaque handle to the MAC context + * + * This function will deregister the callback of roams events stats. + * + * Return: void + */ +void sme_roam_events_deregister_callback(mac_handle_t mac_handle); #else static inline void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id, @@ -703,6 +727,17 @@ QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id, { return QDF_STATUS_SUCCESS; } + +static inline void +sme_roam_events_register_callback(mac_handle_t mac_handle, + void (*roam_rt_stats_cb)( + hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats)) +{} + +static inline +void sme_roam_events_deregister_callback(mac_handle_t mac_handle) +{} #endif /** @@ -2471,6 +2506,27 @@ sme_set_del_peers_ind_callback(mac_handle_t mac_handle, void sme_set_chan_info_callback(mac_handle_t mac_handle, void (*callback)(struct scan_chan_info *chan_info)); +#ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER +/** + * sme_set_cal_failure_event_cb() - Register calibration failure event callback + * @mac_handle - MAC global handle + * @callback - calibration failure event callback from HDD + * + * This API is invoked by HDD to register its callback to mac + * + * Return: None + */ +void sme_set_cal_failure_event_cb( + mac_handle_t mac_handle, + void (*callback)(uint8_t cal_type, uint8_t reason)); +#else +static inline void +sme_set_cal_failure_event_cb(mac_handle_t mac_handle, + void (*callback)(uint8_t cal_type, uint8_t reason)) +{ +} +#endif + /** * sme_get_rssi_snr_by_bssid() - gets the rssi and snr by bssid from scan cache * @mac_handle: handle returned by mac_open diff --git a/drivers/staging/qcacld-3.0/core/sme/inc/sme_internal.h b/drivers/staging/qcacld-3.0/core/sme/inc/sme_internal.h index af28a7e31963..87814ce16319 100644 --- a/drivers/staging/qcacld-3.0/core/sme/inc/sme_internal.h +++ b/drivers/staging/qcacld-3.0/core/sme/inc/sme_internal.h @@ -514,6 +514,10 @@ struct sme_context { #if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) void (*beacon_latency_event_cb)(uint32_t latency_level); #endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + void (*roam_rt_stats_cb)(hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats); +#endif }; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c b/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c index 5ea17976d16b..b2677e0833a8 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c @@ -13622,6 +13622,30 @@ void sme_set_chan_info_callback(mac_handle_t mac_handle, mac->chan_info_cb = callback; } +#ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER +void sme_set_cal_failure_event_cb( + mac_handle_t mac_handle, + void (*callback)(uint8_t cal_type, uint8_t reason)) +{ + struct mac_context *mac; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!mac_handle) { + QDF_ASSERT(0); + return; + } + mac = MAC_CONTEXT(mac_handle); + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + mac->cal_failure_event_cb = callback; + sme_release_global_lock(&mac->sme); + } else { + sme_err("sme_acquire_global_lock failed"); + } +} +#endif + void sme_set_vdev_ies_per_band(mac_handle_t mac_handle, uint8_t vdev_id, enum QDF_OPMODE device_mode) { @@ -17264,3 +17288,25 @@ sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, return qdf_status; } #endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void sme_roam_events_register_callback(mac_handle_t mac_handle, + void (*roam_rt_stats_cb)( + hdd_handle_t hdd_handle, + struct mlme_roam_debug_info *roam_stats)) +{ + struct mac_context *mac = MAC_CONTEXT(mac_handle); + + if (!mac) { + sme_err("Invalid mac context"); + return; + } + + mac->sme.roam_rt_stats_cb = roam_rt_stats_cb; +} + +void sme_roam_events_deregister_callback(mac_handle_t mac_handle) +{ + sme_roam_events_register_callback(mac_handle, NULL); +} +#endif diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c index 913b92180f7a..7a3b00c5916e 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-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 @@ -6806,13 +6807,17 @@ static inline void csr_roam_process_he_info(struct join_rsp *sme_join_rsp, } #endif -static void csr_update_rsn_intersect_to_fw(struct wlan_objmgr_psoc *psoc, - uint8_t vdev_id) +static void csr_update_rsn_intersect_to_fw(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct bss_description *bss_desc) { int32_t rsn_val; struct wlan_objmgr_vdev *vdev; + const uint8_t *ie = NULL; + uint16_t ie_len; + tDot11fIERSN rsn_ie = {0}; - vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id, WLAN_LEGACY_SME_ID); if (!vdev) { @@ -6829,6 +6834,22 @@ static void csr_update_rsn_intersect_to_fw(struct wlan_objmgr_psoc *psoc, return; } + if (bss_desc) { + ie_len = csr_get_ielen_from_bss_description(bss_desc); + + ie = wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, + (uint8_t *)bss_desc->ieFields, + ie_len); + + if (ie && ie[0] == WLAN_EID_RSN && + !dot11f_unpack_ie_rsn(mac_ctx, (uint8_t *)ie + 2, ie[1], + &rsn_ie, false)) { + if (!(*(uint16_t *)&rsn_ie.RSN_Cap & + WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED)) + rsn_val &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED; + } + } + if (wma_cli_set2_command(vdev_id, WMI_VDEV_PARAM_RSN_CAPABILITY, rsn_val, 0, VDEV_CMD)) sme_err("Failed to update WMI_VDEV_PARAM_RSN_CAPABILITY for vdev id %d", @@ -7233,7 +7254,7 @@ static void csr_roam_process_join_res(struct mac_context *mac_ctx, csr_roam_link_up(mac_ctx, conn_profile->bssid); } - csr_update_rsn_intersect_to_fw(mac_ctx->psoc, session_id); + csr_update_rsn_intersect_to_fw(mac_ctx, session_id, bss_desc); sme_free_join_rsp_fils_params(roam_info); qdf_mem_free(roam_info); } @@ -7638,11 +7659,13 @@ QDF_STATUS csr_roam_copy_profile(struct mac_context *mac, pDstProfile->extended_rates.numRates = pSrcProfile->extended_rates.numRates; } + pDstProfile->require_h2e = pSrcProfile->require_h2e; pDstProfile->cac_duration_ms = pSrcProfile->cac_duration_ms; pDstProfile->dfs_regdomain = pSrcProfile->dfs_regdomain; pDstProfile->chan_switch_hostapd_rate_enabled = pSrcProfile->chan_switch_hostapd_rate_enabled; pDstProfile->force_rsne_override = pSrcProfile->force_rsne_override; + pDstProfile->is_hs_20_ap = pSrcProfile->is_hs_20_ap; end: if (!QDF_IS_STATUS_SUCCESS(status)) { csr_release_profile(mac, pDstProfile); @@ -8471,6 +8494,11 @@ QDF_STATUS csr_roam_disconnect(struct mac_context *mac_ctx, uint32_t session_id, || CSR_IS_CONN_NDI(&session->connectedProfile)) { status = csr_roam_issue_disassociate_cmd(mac_ctx, session_id, reason, mac_reason); + } else if (csr_is_deauth_disassoc_already_active(mac_ctx, session_id, + session->connectedProfile.bssid)) { + /* Return success if Disconnect is already in progress */ + sme_debug("Disconnect already in queue return success"); + status = QDF_STATUS_SUCCESS; } else if (session->scan_info.profile) { mac_ctx->roam.roamSession[session_id].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING; @@ -8670,6 +8698,37 @@ bool is_disconnect_pending(struct mac_context *pmac, uint8_t vdev_id) return disconnect_cmd_exist; } +bool is_disconnect_pending_on_other_vdev(struct mac_context *pmac, + uint8_t vdev_id) +{ + tListElem *entry = NULL; + tListElem *next_entry = NULL; + tSmeCmd *command = NULL; + bool disconnect_cmd_exist = false; + + entry = csr_nonscan_pending_ll_peek_head(pmac, LL_ACCESS_NOLOCK); + while (entry) { + next_entry = csr_nonscan_pending_ll_next(pmac, entry, + LL_ACCESS_NOLOCK); + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + /* + * check if any other vdev NB disconnect or SB disconnect + * (eSmeCommandWmStatusChange) is pending + */ + if (command && (CSR_IS_DISCONNECT_COMMAND(command) || + command->command == eSmeCommandWmStatusChange) && + command->vdev_id != vdev_id) { + sme_debug("disconnect is pending on vdev:%d, cmd:%d", + command->vdev_id, command->command); + disconnect_cmd_exist = true; + break; + } + entry = next_entry; + } + + return disconnect_cmd_exist; +} + #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) static void csr_clear_other_bss_sae_single_pmk_entry(struct mac_context *mac, @@ -8789,7 +8848,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, struct csr_roam_connectedinfo *prev_connect_info; struct wlan_crypto_pmksa *pmksa; uint32_t len = 0, roamId = 0, reason_code = 0; - bool is_dis_pending; + bool is_dis_pending, is_dis_pending_on_other_vdev; bool use_same_bss = false; uint8_t max_retry_count = 1; bool retry_same_bss = false; @@ -8893,6 +8952,9 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, reason_code); is_dis_pending = is_disconnect_pending(mac, session_ptr->sessionId); + is_dis_pending_on_other_vdev = + is_disconnect_pending_on_other_vdev(mac, + session_ptr->sessionId); is_time_allowed = csr_is_time_allowed_for_connect_attempt(pCommand, session_ptr->vdev_id); @@ -8901,7 +8963,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, * if userspace has issued disconnection or we have reached mac tries or * max time, driver should not continue for next connection. */ - if (is_dis_pending || !is_time_allowed || + if (is_dis_pending || is_dis_pending_on_other_vdev || !is_time_allowed || session_ptr->join_bssid_count >= CSR_MAX_BSSID_COUNT) attempt_next_bss = false; @@ -9017,6 +9079,9 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, if (is_dis_pending) sme_err("disconnect is pending, complete roam"); + if (is_dis_pending_on_other_vdev) + sme_err("disconnect is pending on other vdev, complete roam"); + if (!is_time_allowed) sme_err("time can exceed the active timeout for connection attempt"); @@ -11490,7 +11555,6 @@ csr_roam_chk_lnk_disassoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) { struct csr_roam_session *session; uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX; - QDF_STATUS status; struct disassoc_ind *pDisassocInd; tSmeCmd *cmd; @@ -11504,11 +11568,11 @@ csr_roam_chk_lnk_disassoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) * the WmStatusChange requests is pushed and processed */ pDisassocInd = (struct disassoc_ind *)msg_ptr; - status = csr_roam_get_session_id_from_bssid(mac_ctx, - &pDisassocInd->bssid, &sessionId); - if (!QDF_IS_STATUS_SUCCESS(status)) { - sme_err("Session Id not found for BSSID "QDF_MAC_ADDR_FMT, - QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes)); + + sessionId = pDisassocInd->vdev_id; + if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) { + sme_err("Invalid session. Session Id: %d BSSID: " QDF_MAC_ADDR_FMT, + sessionId, QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes)); qdf_mem_free(cmd); return; } @@ -11589,7 +11653,6 @@ csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) { struct csr_roam_session *session; uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX; - QDF_STATUS status; struct deauth_ind *pDeauthInd; pDeauthInd = (struct deauth_ind *)msg_ptr; @@ -11597,10 +11660,8 @@ csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) pDeauthInd->vdev_id, QDF_MAC_ADDR_REF(pDeauthInd->bssid.bytes)); - status = csr_roam_get_session_id_from_bssid(mac_ctx, - &pDeauthInd->bssid, - &sessionId); - if (!QDF_IS_STATUS_SUCCESS(status)) + sessionId = pDeauthInd->vdev_id; + if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) return; if (csr_is_deauth_disassoc_already_active(mac_ctx, sessionId, @@ -13544,6 +13605,7 @@ csr_roam_get_bss_start_parms(struct mac_context *mac, uint32_t opr_ch_freq = 0; tSirNwType nw_type; uint32_t tmp_opr_ch_freq = 0; + uint8_t h2e; tSirMacRateSet *opr_rates = &pParam->operationalRateSet; tSirMacRateSet *ext_rates = &pParam->extendedRateSet; @@ -13633,6 +13695,22 @@ csr_roam_get_bss_start_parms(struct mac_context *mac, pParam->operation_chan_freq = opr_ch_freq; } + if (pProfile->require_h2e) { + h2e = WLAN_BASIC_RATE_MASK | + WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E; + if (ext_rates->numRates < SIR_MAC_MAX_NUMBER_OF_RATES) { + ext_rates->rate[ext_rates->numRates] = h2e; + ext_rates->numRates++; + sme_debug("H2E bss membership add to ext support rate"); + } else if (opr_rates->numRates < SIR_MAC_MAX_NUMBER_OF_RATES) { + opr_rates->rate[opr_rates->numRates] = h2e; + opr_rates->numRates++; + sme_debug("H2E bss membership add to support rate"); + } else { + sme_err("rates full, can not add H2E bss membership"); + } + } + pParam->sirNwType = nw_type; pParam->ch_params.ch_width = pProfile->ch_params.ch_width; pParam->ch_params.center_freq_seg0 = @@ -16398,8 +16476,8 @@ static void csr_store_oce_cfg_flags_in_vdev(struct mac_context *mac, wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); } -static void csr_send_set_ie(uint8_t type, uint8_t sub_type, - uint8_t vdev_id) +void csr_send_set_ie(uint8_t type, uint8_t sub_type, + uint8_t vdev_id) { struct send_extcap_ie *msg; QDF_STATUS status; @@ -16777,6 +16855,11 @@ static void csr_roam_link_down(struct mac_context *mac, uint32_t sessionId) eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_LOSTLINK); } + + /* In case of STA mode disconnect, stop the roam_invoke timer */ + if (csr_roam_is_sta_mode(mac, sessionId)) + csr_roam_invoke_timer_stop(mac, sessionId); + /* Indicate the neighbor roal algorithm about the disconnect * indication */ @@ -16963,7 +17046,9 @@ static void csr_update_btm_offload_config(struct mac_context *mac_ctx, return; /* For RSO Stop Disable BTM offload to firmware */ - if (command == ROAM_SCAN_OFFLOAD_STOP) { + if (command == ROAM_SCAN_OFFLOAD_STOP || + session->pCurRoamProfile->is_hs_20_ap) { + sme_debug("RSO cmd: %d", command); *btm_offload_config = 0; return; } @@ -18597,6 +18682,26 @@ csr_cm_roam_scan_offload_fill_lfr3_config( } #endif +#ifdef CONFIG_BAND_6GHZ +static void +csr_cm_fill_6ghz_dwell_times(struct wlan_objmgr_psoc *psoc, + struct wlan_roam_scan_params *scan_params) +{ + wlan_scan_cfg_get_active_6g_dwelltime( + psoc, + &scan_params->dwell_time_active_6ghz); + + wlan_scan_cfg_get_passive_6g_dwelltime( + psoc, + &scan_params->dwell_time_passive_6ghz); +} +#else +static inline void +csr_cm_fill_6ghz_dwell_times(struct wlan_objmgr_psoc *psoc, + struct wlan_roam_scan_params *scan_params) +{} +#endif + static void csr_cm_roam_scan_offload_fill_scan_params( struct mac_context *mac, @@ -18717,6 +18822,8 @@ csr_cm_roam_scan_offload_fill_scan_params( scan_params->rso_adaptive_dwell_mode = mac->mlme_cfg->lfr.adaptive_roamscan_dwell_mode; + + csr_cm_fill_6ghz_dwell_times(mac->psoc, scan_params); } /** @@ -20761,6 +20868,12 @@ QDF_STATUS csr_fast_reassoc(mac_handle_t mac_handle, fastreassoc->bssid[4] = bssid[4]; fastreassoc->bssid[5] = bssid[5]; + qdf_mem_copy(&vdev_roam_params->mac_addr, &bssid, ETH_ALEN); + if (qdf_is_macaddr_zero((struct qdf_mac_addr *)&bssid)) + goto send_evt; + if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)&bssid)) + goto send_evt; + status = sme_get_beacon_frm(mac_handle, profile, bssid, &fastreassoc->frame_buf, &fastreassoc->frame_len, @@ -20794,6 +20907,7 @@ QDF_STATUS csr_fast_reassoc(mac_handle_t mac_handle, } } +send_evt: msg.type = eWNI_SME_ROAM_INVOKE; msg.reserved = 0; msg.bodyptr = fastreassoc; @@ -20807,8 +20921,11 @@ QDF_STATUS csr_fast_reassoc(mac_handle_t mac_handle, fastreassoc->frame_len = 0; qdf_mem_free(fastreassoc); } else { + if (qdf_is_macaddr_zero((struct qdf_mac_addr *)&bssid)) + vdev_roam_params->source = CONNECTION_MGR_INITIATED; + else + vdev_roam_params->source = USERSPACE_INITIATED; vdev_roam_params->roam_invoke_in_progress = true; - vdev_roam_params->source = USERSPACE_INITIATED; session->roam_invoke_timer_info.mac = mac_ctx; session->roam_invoke_timer_info.vdev_id = vdev_id; qdf_mc_timer_start(&session->roam_invoke_timer, @@ -21098,7 +21215,6 @@ csr_process_roam_sync_callback(struct mac_context *mac_ctx, REASON_ROAM_ABORT); csr_roam_roaming_offload_timer_action(mac_ctx, 0, session_id, ROAMING_OFFLOAD_TIMER_STOP); - csr_roam_invoke_timer_stop(mac_ctx, session_id); csr_roam_call_callback(mac_ctx, session_id, NULL, 0, eCSR_ROAM_ABORT, eCSR_ROAM_RESULT_SUCCESS); goto end; @@ -21115,6 +21231,16 @@ csr_process_roam_sync_callback(struct mac_context *mac_ctx, goto end; } + /* + * If reassoc MAC from user space is broadcast MAC as: + * wpa_cli DRIVER REASSOC ff:ff:ff:ff:ff:ff 0, + * user space invoked roaming candidate selection will base on + * firmware score algorithm, current connection will be kept if + * current AP has highest score. It is requirement from + * customer which can avoid ping-pong roaming. + */ + if (qdf_is_macaddr_broadcast(&vdev_roam_params->mac_addr)) + mlme_debug("Keep current connection"); /* Userspace roam req fail, disconnect with AP */ if (vdev_roam_params->source == USERSPACE_INITIATED || mac_ctx->nud_fail_behaviour == DISCONNECT_AFTER_ROAM_FAIL) @@ -21211,7 +21337,14 @@ csr_process_roam_sync_callback(struct mac_context *mac_ctx, status = csr_get_parsed_bss_description_ies( mac_ctx, bss_desc, &ies_local); if (!QDF_IS_STATUS_SUCCESS(status)) { - sme_err("LFR3: fail to parse IEs"); + sme_err("LFR3: fail to parse IEs. Len Bcn : %d, Reassoc req : %d Reassoc rsp : %d", + roam_synch_data->beaconProbeRespLength, + roam_synch_data->reassoc_req_length, + roam_synch_data->reassocRespLength); + qdf_trace_hex_dump(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + (uint8_t *)roam_synch_data + + roam_synch_data->beaconProbeRespOffset, + roam_synch_data->beaconProbeRespLength); goto end; } diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h index ac8856493c18..b873e2aa8692 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h @@ -561,6 +561,15 @@ bool csr_is_profile_wapi(struct csr_roam_profile *pProfile); void csr_get_vdev_type_nss(enum QDF_OPMODE dev_mode, uint8_t *nss_2g, uint8_t *nss_5g); +/** + * csr_send_set_ie - Send Set IE request to lim + * @type: Vdev type + * @sub_type: Vdev sub type + * @vdev_id: Vdev id + * + * Return: None + */ +void csr_send_set_ie(uint8_t type, uint8_t sub_type, uint8_t vdev_id); #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR /* Security */ @@ -974,6 +983,17 @@ csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, bool is_disconnect_pending(struct mac_context *mac_ctx, uint8_t sessionid); +/** + * is_disconnect_pending_on_other_vdev() - To check whether a disconnect req + * is pending on any other vdev or not + * @mac_tx: mac context + * @sessionid: session id + * + * Return true if disconnect is pending on any other vdev + */ +bool is_disconnect_pending_on_other_vdev(struct mac_context *mac_ctx, + uint8_t sessionid); + QDF_STATUS csr_roam_prepare_bss_config_from_profile(struct mac_context *mac_ctx, struct csr_roam_profile *profile, diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_neighbor_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_neighbor_roam.c index b53ba40da149..9cd65057acda 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_neighbor_roam.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_neighbor_roam.c @@ -789,6 +789,27 @@ static void csr_neighbor_roam_info_ctx_init(struct mac_context *mac, struct cm_roam_values_copy src_cfg; struct csr_roam_session *session = &mac->roam.roamSession[session_id]; int init_ft_flag = false; + struct wlan_objmgr_vdev *vdev = NULL; + struct vdev_mlme_obj *vdev_mlme; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, session_id, + WLAN_LEGACY_SME_ID); + if (!vdev) + return; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + QDF_BUG(0); + return; + } + + /* update the EXT cap IE with union of driver populated + * values and the values sent from userspace + */ + csr_send_set_ie(vdev_mlme->mgmt.generic.type, + vdev_mlme->mgmt.generic.subtype, session_id); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); csr_init_occupied_channels_list(mac, session_id); csr_neighbor_roam_state_transition(mac, diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c index 188717201d89..67c54d08c583 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -1389,9 +1390,11 @@ QDF_STATUS csr_parse_bss_description_ies(struct mac_context *mac_ctx, int ieLen; ieFields_offset = GET_FIELD_OFFSET(struct bss_description, ieFields); - if (!bss_desc->length || - (bss_desc->length - sizeof(bss_desc->length) <= ieFields_offset)) + if (bss_desc->length <= (ieFields_offset - sizeof(bss_desc->length))) { + sme_err_rl("Invalid bss_desc IES: len:%d ie_fields_offset:%d", + bss_desc->length, ieFields_offset); return status; + } ieLen = (int)(bss_desc->length + sizeof(bss_desc->length) - ieFields_offset); @@ -1400,7 +1403,7 @@ QDF_STATUS csr_parse_bss_description_ies(struct mac_context *mac_ctx, if (!DOT11F_FAILED(dot11f_unpack_beacon_i_es (mac_ctx, (uint8_t *)bss_desc->ieFields, ieLen, pIEStruct, false))) - status = QDF_STATUS_SUCCESS; + status = QDF_STATUS_SUCCESS; } return status; @@ -2489,8 +2492,7 @@ uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, self_rsn_cap |= WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; if (pProfile->MFPRequired) self_rsn_cap |= WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; - if (!(rsn_cap & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED)) - self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED; + } else { self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; diff --git a/drivers/staging/qcacld-3.0/core/sme/src/qos/sme_qos.c b/drivers/staging/qcacld-3.0/core/sme/src/qos/sme_qos.c index 1749eb9a2e30..cfc5698ec686 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/qos/sme_qos.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/qos/sme_qos.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-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 @@ -4673,9 +4674,7 @@ static QDF_STATUS sme_qos_process_reassoc_success_ev(struct mac_context *mac_ctx mac_ctx, sessionid, event_info); } else { - QDF_TRACE(QDF_MODULE_ID_SME, - QDF_TRACE_LEVEL_ERROR, FL( - "session or RIC data is not present")); + sme_debug("session or RIC data is not present"); } } #ifdef FEATURE_WLAN_ESE diff --git a/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h b/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h index 2e4804019aec..c7fcd1fa747e 100644 --- a/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h +++ b/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h @@ -292,6 +292,24 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event, int wma_roam_vdev_disconnect_event_handler(void *handle, uint8_t *event, uint32_t len); +/** + * wma_report_real_time_roam_stats - Gathers/Sends the roam events stats + * @psoc: Pointer to psoc structure + * @vdev_id: Vdev ID + * @events: Event/Notif type from roam event/roam stats event + * @roam_info: Roam stats from the roam stats event + * @value: Notif param value from the roam event + * + * Gathers the roam stats from the roam event and the roam stats event and + * sends them to hdd for filling the vendor attributes. + * + * Return: none + */ +void wma_report_real_time_roam_stats(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum roam_rt_stats_type events, + struct mlme_roam_debug_info *roam_info, + uint32_t value); #else static inline int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, @@ -321,6 +339,14 @@ wma_roam_pmkid_request_event_handler(void *handle, { return 0; } + +static void +wma_report_real_time_roam_stats(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum roam_rt_stats_type events, + struct mlme_roam_debug_info *roam_info, + uint32_t value) +{} #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD diff --git a/drivers/staging/qcacld-3.0/core/wma/inc/wma_types.h b/drivers/staging/qcacld-3.0/core/wma/inc/wma_types.h index c50a0a0bf0d5..7a298bf070b7 100644 --- a/drivers/staging/qcacld-3.0/core/wma/inc/wma_types.h +++ b/drivers/staging/qcacld-3.0/core/wma/inc/wma_types.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -442,8 +443,6 @@ enum wmamsgtype { WMA_TWT_NUDGE_DIALOG_REQUEST = SIR_HAL_TWT_NUDGE_DIALOG_REQUEST, }; -#define WMA_DATA_STALL_TRIGGER 0x1006 - /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_data.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_data.c index 55b532ed56ee..dd80689af756 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_data.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_data.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. 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 @@ -24,6 +25,7 @@ /* Header files */ #include "wma.h" +#include "enet.h" #include "wma_api.h" #include "cds_api.h" #include "wmi_unified_api.h" @@ -65,7 +67,6 @@ #include #include "cdp_txrx_stats.h" #include -#include "enet.h" #include "wlan_mgmt_txrx_utils_api.h" #include "wlan_objmgr_psoc_obj.h" #include "wlan_objmgr_pdev_obj.h" @@ -1721,6 +1722,7 @@ static QDF_STATUS wma_update_thermal_mitigation_to_fw(tp_wma_handle wma, therm_data.levelconf[0].dcoffpercent = wma->thermal_mgmt_info.throttle_duty_cycle_tbl[thermal_level]; therm_data.levelconf[0].priority = 0; + therm_data.num_thermal_conf = 1; return wmi_unified_thermal_mitigation_param_cmd_send(wma->wmi_handle, &therm_data); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c index cfce77b0f87d..d150ff09cef8 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -2460,7 +2461,6 @@ QDF_STATUS wma_post_vdev_create_setup(struct wlan_objmgr_vdev *vdev) struct wlan_mlme_qos *qos_aggr; struct vdev_mlme_obj *vdev_mlme; tp_wma_handle wma_handle; - uint8_t amsdu_val; if (!mac) { wma_err("Failed to get mac"); @@ -2500,34 +2500,7 @@ QDF_STATUS wma_post_vdev_create_setup(struct wlan_objmgr_vdev *vdev) vdev_mlme->mgmt.generic.subtype; qos_aggr = &mac->mlme_cfg->qos_mlme_params; - status = wma_set_tx_rx_aggr_size(vdev_id, qos_aggr->tx_aggregation_size, - qos_aggr->rx_aggregation_size, - WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU); - if (QDF_IS_STATUS_ERROR(status)) - wma_err("failed to set aggregation sizes(status = %d)", status); - - status = wlan_mlme_get_max_amsdu_num(wma_handle->psoc, &amsdu_val); - if (QDF_IS_STATUS_ERROR(status)) { - wma_err("failed to get amsdu aggr.size %d", status); - } else { - status = wma_set_tx_rx_aggr_size(vdev_id, amsdu_val, - amsdu_val, - WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU); - if (QDF_IS_STATUS_ERROR(status)) { - wma_err("failed to set amsdu aggr.size %d", status); - } - } - if (vdev_mlme->mgmt.generic.type == WMI_VDEV_TYPE_STA) { - status = wma_set_tx_rx_aggr_size_per_ac( - wma_handle, vdev_id, - qos_aggr, - WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU); - - if (QDF_IS_STATUS_ERROR(status)) - wma_err("failed to set aggr size per ac(status = %d)", - status); - wma_set_sta_keep_alive( wma_handle, vdev_id, SIR_KEEP_ALIVE_NULL_PKT, @@ -2763,6 +2736,8 @@ QDF_STATUS wma_vdev_pre_start(uint8_t vdev_id, bool restart) struct wlan_channel *des_chan; QDF_STATUS status; uint8_t btc_chain_mode; + struct wlan_mlme_qos *qos_aggr; + uint8_t amsdu_val; if (!wma) { wma_err("Invalid wma handle"); @@ -2875,6 +2850,33 @@ QDF_STATUS wma_vdev_pre_start(uint8_t vdev_id, bool restart) } } + qos_aggr = &mac_ctx->mlme_cfg->qos_mlme_params; + status = wma_set_tx_rx_aggr_size(vdev_id, qos_aggr->tx_aggregation_size, + qos_aggr->rx_aggregation_size, + WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU); + if (QDF_IS_STATUS_ERROR(status)) + wma_err("failed to set aggregation sizes(status = %d)", status); + + status = wlan_mlme_get_max_amsdu_num(wma->psoc, &amsdu_val); + if (QDF_IS_STATUS_ERROR(status)) { + wma_err("failed to get amsdu aggr.size(status = %d)", status); + } else { + status = wma_set_tx_rx_aggr_size(vdev_id, amsdu_val, amsdu_val, + WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU); + if (QDF_IS_STATUS_ERROR(status)) + wma_err("failed to set amsdu aggr.size(status = %d)", + status); + } + + if (mlme_obj->mgmt.generic.type == WMI_VDEV_TYPE_STA) { + status = wma_set_tx_rx_aggr_size_per_ac(wma, vdev_id, qos_aggr, + WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU); + + if (QDF_IS_STATUS_ERROR(status)) + wma_err("failed to set aggr size per ac(status = %d)", + status); + } + return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c index 8c1a30ebcb72..3c57aa225e64 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c @@ -1498,6 +1498,8 @@ static const uint8_t *wma_wow_wake_reason_str(A_INT32 wake_reason) return "GENERIC_WAKE"; case WOW_REASON_TWT: return "TWT Event"; + case WOW_REASON_ROAM_STATS: + return "ROAM_STATS"; default: return "unknown"; } @@ -2493,6 +2495,7 @@ static int wma_wake_event_no_payload( return wma_wake_reason_nlod(wma, wake_info->vdev_id); case WOW_REASON_GENERIC_WAKE: + case WOW_REASON_ROAM_STATS: wma_info("Wake reason %s", wma_wow_wake_reason_str(wake_info->wake_reason)); return 0; diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_he.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_he.c index 0745079bf87a..3bf5e3b7d073 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_he.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_he.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -713,6 +714,14 @@ void wma_print_he_ppet(void *he_ppet) for (ru_count = 0; ru_bit_mask; ru_bit_mask >>= 1) if (ru_bit_mask & 0x1) ru_count++; + if (numss > WMI_HOST_MAX_NUM_SS) { + wma_err("invalid numss_m1 %d", ppet->numss_m1); + return; + } + if (ru_count > HE_PEPT_RU_IDX_LEN) { + wma_err("invalid ru_count 0x%08x", ppet->ru_bit_mask); + return; + } if (ru_count > 0) { wma_debug("PPET has following RU INDEX,"); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c index 4c330b267eaa..d68120da0a56 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 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 @@ -114,6 +115,7 @@ #endif #include "wlan_pkt_capture_ucfg_api.h" +#include "wlan_fwol_ucfg_api.h" #define WMA_LOG_COMPLETION_TIMER 3000 /* 3 seconds */ #define WMI_TLV_HEADROOM 128 @@ -2006,6 +2008,57 @@ static int wma_legacy_service_ready_event_handler(uint32_t event_id, return 0; } +#ifdef WLAN_FEATURE_CAL_FAILURE_TRIGGER +/** + * wma_process_cal_fail_info() - Process cal failure event and + * send it to userspace + * @wmi_event: Cal failure event data + */ +static void wma_process_cal_fail_info(uint8_t *wmi_event) +{ + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); + uint8_t *buf_ptr; + wmi_debug_mesg_fw_cal_failure_param *cal_failure_event; + + if (!mac) { + wma_err("Invalid mac context"); + return; + } + + if (!mac->cal_failure_event_cb) { + wma_err("Callback not registered for cal failure event"); + return; + } + + buf_ptr = wmi_event; + buf_ptr = buf_ptr + sizeof(wmi_debug_mesg_flush_complete_fixed_param) + + WMI_TLV_HDR_SIZE + + sizeof(wmi_debug_mesg_fw_data_stall_param) + WMI_TLV_HDR_SIZE; + + cal_failure_event = (wmi_debug_mesg_fw_cal_failure_param *)buf_ptr; + + if (((cal_failure_event->tlv_header & 0xFFFF0000) >> 16 == + WMITLV_TAG_STRUC_wmi_debug_mesg_fw_cal_failure_param)) { + /** + * Log calibration failure information received from FW + */ + wma_debug("Calibration failure event:"); + wma_debug("calType: %x calFailureReasonCode: %x", + cal_failure_event->cal_type, + cal_failure_event->cal_failure_reason_code); + mac->cal_failure_event_cb( + cal_failure_event->cal_type, + cal_failure_event->cal_failure_reason_code); + } else { + wma_err("Invalid TLV header in cal failure event"); + } +} +#else +static inline void wma_process_cal_fail_info(uint8_t *wmi_event) +{ +} +#endif + /** * wma_flush_complete_evt_handler() - FW log flush complete event handler * @handle: WMI handle @@ -2037,7 +2090,7 @@ static int wma_flush_complete_evt_handler(void *handle, reason_code = wmi_event->reserved0; wma_debug("Received reason code %d from FW", reason_code); - if (reason_code == WMA_DATA_STALL_TRIGGER) { + if (reason_code == WMI_DIAG_TRIGGER_DATA_STALL) { buf_ptr = (uint8_t *)wmi_event; buf_ptr = buf_ptr + sizeof(wmi_debug_mesg_flush_complete_fixed_param) + @@ -2046,7 +2099,7 @@ static int wma_flush_complete_evt_handler(void *handle, (wmi_debug_mesg_fw_data_stall_param *)buf_ptr; } - if (reason_code == WMA_DATA_STALL_TRIGGER && + if (reason_code == WMI_DIAG_TRIGGER_DATA_STALL && ((data_stall_event->tlv_header & 0xFFFF0000) >> 16 == WMITLV_TAG_STRUC_wmi_debug_mesg_fw_data_stall_param)) { /** @@ -2096,6 +2149,11 @@ static int wma_flush_complete_evt_handler(void *handle, data_stall_event->recovery_type); } + if (reason_code == WMI_DIAG_TRIGGER_CAL_FAILURE) { + wma_process_cal_fail_info((uint8_t *)wmi_event); + return QDF_STATUS_SUCCESS; + } + /* * reason_code = 0; Flush event in response to flush command * reason_code = other value; Asynchronous flush event for fatal events @@ -5804,10 +5862,52 @@ static void wma_set_mlme_caps(struct wlan_objmgr_psoc *psoc) wma_err("Failed to set sae roam support"); } +#ifdef THERMAL_STATS_SUPPORT +static void wma_set_thermal_stats_fw_cap(tp_wma_handle wma, + struct wlan_fwol_capability_info *cap) +{ + cap->fw_thermal_stats_cap = wmi_service_enabled(wma->wmi_handle, + wmi_service_thermal_stats_temp_range_supported); +} +#else +static void wma_set_thermal_stats_fw_cap(tp_wma_handle wma, + struct wlan_fwol_capability_info *cap) +{ +} +#endif + +/** + * wma_set_fwol_caps() - Populate fwol component related capabilities + * to the fwol component + * + * @psoc: Pointer to psoc object + * + * Return: None + */ +static void wma_set_fwol_caps(struct wlan_objmgr_psoc *psoc) +{ + tp_wma_handle wma; + struct wlan_fwol_capability_info cap_info; + wma = cds_get_context(QDF_MODULE_ID_WMA); + + if (!wma) { + wma_err_rl("wma Null"); + return; + } + if (!psoc) { + wma_err_rl("psoc Null"); + return; + } + + wma_set_thermal_stats_fw_cap(wma, &cap_info); + ucfg_fwol_update_fw_cap_info(psoc, &cap_info); +} + static void wma_set_component_caps(struct wlan_objmgr_psoc *psoc) { wma_set_pmo_caps(psoc); wma_set_mlme_caps(psoc); + wma_set_fwol_caps(psoc); } #if defined(WLAN_FEATURE_GTK_OFFLOAD) && defined(WLAN_POWER_MANAGEMENT_OFFLOAD) @@ -6932,7 +7032,9 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event, * indicate 3 vdevs and firmware shall add 1 vdev for NAN. So decrement * the num_vdevs by 1. */ - if (ucfg_nan_is_vdev_creation_allowed(wma_handle->psoc)) { + + if (ucfg_nan_is_vdev_creation_allowed(wma_handle->psoc) || + QDF_GLOBAL_FTM_MODE == cds_get_conparam()) { wlan_res_cfg->nan_separate_iface_support = true; } else { wlan_res_cfg->num_vdevs--; diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c index 365e04d6d7dc..81cbe13079f0 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 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 @@ -1142,6 +1143,15 @@ static void wma_update_phymode_on_roam(tp_wma_handle wma, uint8_t *bssid, struct wlan_channel *bss_chan; struct vdev_mlme_obj *vdev_mlme; uint8_t channel; + struct wlan_objmgr_pdev *pdev; + qdf_freq_t sec_ch_2g_freq = 0; + struct ch_params ch_params = {0}; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev); + if (!vdev_mlme) + return; + + pdev = wlan_vdev_get_pdev(vdev_mlme->vdev); channel = wlan_freq_to_chan(iface->ch_freq); if (chan) @@ -1151,7 +1161,6 @@ static void wma_update_phymode_on_roam(tp_wma_handle wma, uint8_t *bssid, wma_get_phy_mode_cb(iface->ch_freq, iface->chan_width, &bss_phymode); - vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev); /* Update vdev mlme channel info after roaming */ des_chan = wlan_vdev_mlme_get_des_chan(iface->vdev); bss_chan = wlan_vdev_mlme_get_bss_chan(iface->vdev); @@ -1159,15 +1168,35 @@ static void wma_update_phymode_on_roam(tp_wma_handle wma, uint8_t *bssid, des_chan->ch_width = iface->chan_width; if (chan) { des_chan->ch_freq = chan->mhz; - des_chan->ch_cfreq1 = chan->band_center_freq1; - des_chan->ch_cfreq2 = chan->band_center_freq2; + ch_params.ch_width = des_chan->ch_width; + if (wlan_reg_is_24ghz_ch_freq(des_chan->ch_freq) && + des_chan->ch_width == CH_WIDTH_40MHZ && + chan->band_center_freq1) { + if (des_chan->ch_freq < chan->band_center_freq1) + sec_ch_2g_freq = des_chan->ch_freq + 20; + else + sec_ch_2g_freq = des_chan->ch_freq - 20; + } + wlan_reg_set_channel_params_for_freq(pdev, des_chan->ch_freq, + sec_ch_2g_freq, + &ch_params); + if (ch_params.ch_width != des_chan->ch_width || + ch_params.mhz_freq_seg0 != chan->band_center_freq1 || + ch_params.mhz_freq_seg1 != chan->band_center_freq2) + wma_err("ch mismatch host & fw bw (%d %d) seg0 (%d, %d) seg1 (%d, %d)", + ch_params.ch_width, des_chan->ch_width, + ch_params.mhz_freq_seg0, + chan->band_center_freq1, + ch_params.mhz_freq_seg1, + chan->band_center_freq2); + des_chan->ch_cfreq1 = ch_params.mhz_freq_seg0; + des_chan->ch_cfreq2 = ch_params.mhz_freq_seg1; + des_chan->ch_width = ch_params.ch_width; } else { wma_err("LFR3: invalid chan"); } qdf_mem_copy(bss_chan, des_chan, sizeof(struct wlan_channel)); - if (!vdev_mlme) - return; /* Till conversion is not done in WMI we need to fill fw phy mode */ vdev_mlme->mgmt.generic.phy_mode = wma_host_to_fw_phymode(bss_phymode); @@ -1358,14 +1387,21 @@ int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, if (QDF_IS_STATUS_ERROR(wma->pe_roam_synch_cb(wma->mac_context, roam_synch_ind_ptr, bss_desc_ptr, SIR_ROAM_SYNCH_PROPAGATION))) { - wma_err("LFR3: PE roam synch cb failed"); + wma_err("LFR3: PE roam synch propagation failed"); status = -EBUSY; goto cleanup_label; } wma_roam_update_vdev(wma, roam_synch_ind_ptr); - wma->csr_roam_synch_cb(wma->mac_context, roam_synch_ind_ptr, - bss_desc_ptr, SIR_ROAM_SYNCH_PROPAGATION); + + if (QDF_IS_STATUS_ERROR(wma->csr_roam_synch_cb(wma->mac_context, + roam_synch_ind_ptr, + bss_desc_ptr, SIR_ROAM_SYNCH_PROPAGATION))) { + wma_err("CSR roam synch propagation failed, abort roam"); + status = -EINVAL; + goto cleanup_label; + } + wma_process_roam_synch_complete(wma, synch_event->vdev_id); /* update freq and channel width */ @@ -2156,6 +2192,72 @@ wma_rso_print_11kv_info(struct wmi_neighbor_report_data *neigh_rpt, qdf_mem_free(buf); } +void wma_report_real_time_roam_stats(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum roam_rt_stats_type events, + struct mlme_roam_debug_info *roam_info, + uint32_t value) +{ + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); + struct mlme_roam_debug_info *roam_event = NULL; + + if (!wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE)) { + wma_err_rl("Roam events stats is disabled"); + return; + } + + switch (events) { + case ROAM_RT_STATS_TYPE_SCAN_STATE: + roam_event = qdf_mem_malloc(sizeof(*roam_event)); + if (!roam_event) + return; + + if (value == WMI_ROAM_NOTIF_SCAN_START) + roam_event->roam_event_param.roam_scan_state = + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START; + else if (value == WMI_ROAM_NOTIF_SCAN_END) + roam_event->roam_event_param.roam_scan_state = + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END; + + if (mac && mac->sme.roam_rt_stats_cb) { + wma_debug("Invoke HDD roam events callback for " + "roam scan notif"); + roam_event->roam_event_param.vdev_id = vdev_id; + mac->sme.roam_rt_stats_cb(mac->hdd_handle, roam_event); + } + qdf_mem_free(roam_event); + break; + case ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON: + roam_event = qdf_mem_malloc(sizeof(*roam_event)); + if (!roam_event) + return; + + roam_event->roam_event_param.roam_invoke_fail_reason = value; + + if (mac && mac->sme.roam_rt_stats_cb) { + wma_debug("Invoke HDD roam events callback for " + "roam invoke fail"); + roam_event->roam_event_param.vdev_id = vdev_id; + mac->sme.roam_rt_stats_cb(mac->hdd_handle, roam_event); + } + qdf_mem_free(roam_event); + break; + case ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO: + if ((roam_info->scan.present || roam_info->trigger.present || + (roam_info->result.present && + roam_info->result.fail_reason)) && + mac && mac->sme.roam_rt_stats_cb) { + wma_debug("Invoke HDD roam events callback for roam " + "stats event"); + roam_info->roam_event_param.vdev_id = vdev_id; + mac->sme.roam_rt_stats_cb(mac->hdd_handle, roam_info); + } + break; + default: + break; + } +} + int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event, uint32_t len) { @@ -2192,7 +2294,7 @@ int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event, num_tlv = MAX_ROAM_SCAN_STATS_TLV; } - rem_len = WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param); + rem_len = len - sizeof(*fixed_param); if (rem_len < num_tlv * sizeof(wmi_roam_trigger_reason)) { wma_err_rl("Invalid roam trigger data"); goto err; @@ -2398,6 +2500,11 @@ int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event, wma_rso_print_11kv_info(&roam_info->data_11kv, vdev_id); } + wma_report_real_time_roam_stats( + wma->psoc, vdev_id, + ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO, + roam_info, 0); + qdf_mem_free(roam_info); } @@ -4548,6 +4655,13 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, case WMI_ROAM_REASON_INVALID: wma_invalid_roam_reason_handler(wma_handle, wmi_event->vdev_id, wmi_event->notif); + if (wmi_event->notif == WMI_ROAM_NOTIF_SCAN_START || + wmi_event->notif == WMI_ROAM_NOTIF_SCAN_END) + wma_report_real_time_roam_stats( + wma_handle->psoc, + wmi_event->vdev_id, + ROAM_RT_STATS_TYPE_SCAN_STATE, + NULL, wmi_event->notif); break; case WMI_ROAM_REASON_RSO_STATUS: wma_rso_cmd_status_event_handler(wmi_event); @@ -4567,7 +4681,10 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, wlan_cm_update_roam_states(wma_handle->psoc, wmi_event->vdev_id, wmi_event->notif_params, ROAM_INVOKE_FAIL_REASON); - + wma_report_real_time_roam_stats( + wma_handle->psoc, wmi_event->vdev_id, + ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON, + NULL, wmi_event->notif_params); qdf_mem_free(roam_synch_data); break; case WMI_ROAM_REASON_DEAUTH: diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c index 8e0f31f9cc60..2c824a2bbd49 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. 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 @@ -831,7 +832,6 @@ int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, wmi_wlan_profile_t *profile_data; uint32_t i = 0; uint32_t entries; - uint8_t *buf_ptr; char temp_str[150]; param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf; @@ -839,12 +839,9 @@ int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, wma_err("Invalid profile data event buf"); return -EINVAL; } - profile_ctx = param_buf->profile_ctx; - buf_ptr = (uint8_t *)profile_ctx; - buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE; - profile_data = (wmi_wlan_profile_t *) buf_ptr; - entries = profile_ctx->bin_count; + profile_ctx = param_buf->profile_ctx; + entries = profile_ctx->bin_count; if (entries > param_buf->num_profile_data) { wma_err("FW bin count %d more than data %d in TLV hdr", entries, @@ -873,6 +870,7 @@ int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR, "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]"); + profile_data = param_buf->profile_data; for (i = 0; i < entries; i++) { if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT) break; @@ -1149,9 +1147,9 @@ wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, struct sir_wifi_tx *tx_stats; struct sir_wifi_ll_ext_peer_stats *peer_stats; uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay; - uint32_t len, dst_len, param_len, tx_mpdu_aggr_array_len, - tx_succ_mcs_array_len, tx_fail_mcs_array_len, - tx_delay_array_len; + uint32_t len, dst_len, param_len, num_entries, + tx_mpdu_aggr_array_len, tx_succ_mcs_array_len, + tx_fail_mcs_array_len, tx_delay_array_len; result = *buf; dst_len = *buf_length; @@ -1230,6 +1228,12 @@ wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, return QDF_STATUS_E_FAILURE; } + num_entries = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC; + if (num_entries > param_buf->num_tx_stats) { + wma_err("tx stats invalid arg, %d", num_entries); + return QDF_STATUS_E_FAILURE; + } + for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) { uint32_t peer_id = wmi_peer_tx[i].peer_id; struct sir_wifi_tx *ac; @@ -1961,18 +1965,23 @@ static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, return -EINVAL; } - if (!rs_results->tx_time_per_power_level) { - rs_results->tx_time_per_power_level = qdf_mem_malloc( - sizeof(uint32_t) * - rs_results->total_num_tx_power_levels); - if (!rs_results->tx_time_per_power_level) { - /* In error case, atleast send the radio stats without - * tx_power_level stats */ - rs_results->total_num_tx_power_levels = 0; - link_stats_results->nr_received++; - goto post_stats; - } + if (rs_results->tx_time_per_power_level) { + qdf_mem_free(rs_results->tx_time_per_power_level); + rs_results->tx_time_per_power_level = NULL; } + + rs_results->tx_time_per_power_level = + qdf_mem_malloc(sizeof(uint32_t) * + rs_results->total_num_tx_power_levels); + if (!rs_results->tx_time_per_power_level) { + /* In error case, atleast send the radio stats without + * tx_power_level stats + */ + rs_results->total_num_tx_power_levels = 0; + link_stats_results->nr_received++; + goto post_stats; + } + qdf_mem_copy(&rs_results->tx_time_per_power_level[ fixed_param->power_level_offset], tx_power_level_values, @@ -2162,6 +2171,9 @@ static int wma_unified_link_radio_stats_event_handler(void *handle, fixed_param->num_radio); return -EINVAL; } + if (wma_handle->link_stats_results && + !wma_handle->link_stats_results->num_radio) + wma_unified_radio_tx_mem_free(wma_handle); if (!wma_handle->link_stats_results) { wma_handle->link_stats_results = qdf_mem_malloc( diff --git a/drivers/staging/qcacld-3.0/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/drivers/staging/qcacld-3.0/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 2c995419f292..ef11038c3b71 100644 --- a/drivers/staging/qcacld-3.0/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/drivers/staging/qcacld-3.0/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -403,6 +403,11 @@ static void get_peer_rssi_cb(struct stats_event *ev, void *cookie) return; } + if (!ev->peer_stats) { + osif_err("no peer stats"); + goto get_peer_rssi_cb_fail; + } + priv = osif_request_priv(request); rssi_size = sizeof(*ev->peer_stats) * ev->num_peer_stats; if (rssi_size == 0) { diff --git a/drivers/staging/qcacld-3.0/os_if/fw_offload/inc/os_if_fwol.h b/drivers/staging/qcacld-3.0/os_if/fw_offload/inc/os_if_fwol.h index 8ecbc0ff2145..2c938c1a94c1 100644 --- a/drivers/staging/qcacld-3.0/os_if/fw_offload/inc/os_if_fwol.h +++ b/drivers/staging/qcacld-3.0/os_if/fw_offload/inc/os_if_fwol.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 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 @@ -26,6 +26,7 @@ #define __OS_IF_FWOL_H__ #include "wlan_objmgr_vdev_obj.h" +#include "wlan_fwol_public_structs.h" #ifdef WLAN_FEATURE_ELNA /** @@ -82,4 +83,12 @@ static inline int os_if_fwol_send_dscp_up_map_to_fw( } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ +#ifdef THERMAL_STATS_SUPPORT +int os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context); +#endif /* THERMAL_STATS_SUPPORT */ + #endif /* __OS_IF_FWOL_H__ */ diff --git a/drivers/staging/qcacld-3.0/os_if/fw_offload/src/os_if_fwol.c b/drivers/staging/qcacld-3.0/os_if/fw_offload/src/os_if_fwol.c index 90ee99744f5e..de2dd43d8f31 100644 --- a/drivers/staging/qcacld-3.0/os_if/fw_offload/src/os_if_fwol.c +++ b/drivers/staging/qcacld-3.0/os_if/fw_offload/src/os_if_fwol.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 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 @@ -145,3 +145,23 @@ int os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev, return qdf_status_to_os_return(status); } #endif + +#ifdef THERMAL_STATS_SUPPORT +int os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc *psoc, + enum thermal_stats_request_type req, + void (*callback)(void *context, + struct thermal_throttle_info *response), + void *context) +{ + QDF_STATUS status; + + + status = ucfg_fwol_send_get_thermal_stats_cmd(psoc, req, callback, + context); + if (!QDF_IS_STATUS_SUCCESS(status)) + osif_err("Failed to send get thermal stats cmd to FW, %d", + status); + + return qdf_status_to_os_return(status); +} +#endif diff --git a/drivers/staging/qcacld-3.0/os_if/pkt_capture/inc/os_if_pkt_capture.h b/drivers/staging/qcacld-3.0/os_if/pkt_capture/inc/os_if_pkt_capture.h new file mode 100644 index 000000000000..474a4704c99d --- /dev/null +++ b/drivers/staging/qcacld-3.0/os_if/pkt_capture/inc/os_if_pkt_capture.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012-2021 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OS_IF_PKT_CAPTURE_H_ +#define _OS_IF_PKT_CAPTURE_H_ + +#include "qdf_types.h" +#include "qca_vendor.h" +#include "wlan_hdd_main.h" + +#ifdef WLAN_FEATURE_PKT_CAPTURE + +#define os_if_pkt_enter() QDF_TRACE_ENTER(QDF_MODULE_ID_HDD, "enter") +#define os_if_pkt_exit() QDF_TRACE_EXIT(QDF_MODULE_ID_HDD, "exit") + +#define FEATURE_MONITOR_MODE_VENDOR_COMMANDS \ + { \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_set_monitor_mode, \ + vendor_command_policy(set_monitor_mode_policy, \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX) \ + }, + +/* Short name for QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE command */ + +#define SET_MONITOR_MODE_CONFIG_MAX \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX +#define SET_MONITOR_MODE_INVALID \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID +#define SET_MONITOR_MODE_DATA_TX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE +#define SET_MONITOR_MODE_DATA_RX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE +#define SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE +#define SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE +#define SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE +#define SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE +#define SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL \ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL + +extern const struct nla_policy +set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1]; + +/** + * os_if_monitor_mode_configure() - Process monitor mode configuration + * operation in the received vendor command + * @adapter: adapter pointer + * @tb: nl attributes Handles QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE + * + * Return: 0 for Success and negative value for failure + */ +QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter, + const void *data, int data_len); +#endif +#endif diff --git a/drivers/staging/qcacld-3.0/os_if/pkt_capture/src/os_if_pkt_capture.c b/drivers/staging/qcacld-3.0/os_if/pkt_capture/src/os_if_pkt_capture.c new file mode 100644 index 000000000000..43633ab18f5d --- /dev/null +++ b/drivers/staging/qcacld-3.0/os_if/pkt_capture/src/os_if_pkt_capture.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016-2021 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "osif_sync.h" +#include "qdf_str.h" +#include "qdf_trace.h" +#include "qdf_types.h" +#include "wlan_osif_priv.h" +#include +#include "wlan_cfg80211.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" +#include "wlan_utility.h" +#include "wlan_osif_request_manager.h" +#include "wlan_mlme_ucfg_api.h" +#include "wlan_pkt_capture_ucfg_api.h" +#include "os_if_pkt_capture.h" +#include "wlan_hdd_main.h" +#include "cfg_ucfg_api.h" +#include "wlan_hdd_object_manager.h" + +#ifdef WLAN_FEATURE_PKT_CAPTURE + +const struct nla_policy +set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1] = { + [SET_MONITOR_MODE_INVALID] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = { + .type = NLA_U32 + }, + [SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL] = { + .type = NLA_U32 + }, +}; + +QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter, + const void *data, int data_len) +{ + struct pkt_capture_frame_filter frame_filter = {0}; + struct wlan_objmgr_vdev *vdev; + struct nlattr *tb[SET_MONITOR_MODE_CONFIG_MAX + 1]; + QDF_STATUS status; + + os_if_pkt_enter(); + + if (tb[SET_MONITOR_MODE_INVALID]) + return QDF_STATUS_E_FAILURE; + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) + return QDF_STATUS_E_INVAL; + + if (wlan_cfg80211_nla_parse(tb, SET_MONITOR_MODE_CONFIG_MAX, + data, data_len, set_monitor_mode_policy)) { + osif_err("invalid monitor attr"); + hdd_objmgr_put_vdev(vdev); + return QDF_STATUS_E_INVAL; + } + + if (tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) < + PACKET_CAPTURE_DATA_MAX_FILTER) { + frame_filter.data_tx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set = + BIT(SET_MONITOR_MODE_DATA_TX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) < + PACKET_CAPTURE_DATA_MAX_FILTER) { + frame_filter.data_rx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_DATA_RX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) < + PACKET_CAPTURE_MGMT_MAX_FILTER) { + frame_filter.mgmt_tx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) < + PACKET_CAPTURE_MGMT_MAX_FILTER) { + frame_filter.mgmt_rx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) < + PACKET_CAPTURE_CTRL_MAX_FILTER) { + frame_filter.ctrl_tx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] && + nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) < + PACKET_CAPTURE_CTRL_MAX_FILTER) { + frame_filter.ctrl_rx_frame_filter = + nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE); + } + + if (tb[SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]) { + frame_filter.connected_beacon_interval = + nla_get_u32(tb[SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]); + frame_filter.vendor_attr_to_set |= + BIT(SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL); + } + + osif_debug("Monitor mode config %s data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n", + frame_filter.data_tx_frame_filter, + frame_filter.data_rx_frame_filter, + frame_filter.mgmt_tx_frame_filter, + frame_filter.mgmt_rx_frame_filter, + frame_filter.ctrl_tx_frame_filter, + frame_filter.ctrl_rx_frame_filter, + frame_filter.connected_beacon_interval); + + status = ucfg_pkt_capture_set_filter(frame_filter, vdev); + hdd_objmgr_put_vdev(vdev); + + os_if_pkt_exit(); + + return status; +} + +#undef SET_MONITOR_MODE_CONFIG_MAX +#undef SET_MONITOR_MODE_INVALID +#undef SET_MONITOR_MODE_DATA_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_DATA_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE +#undef SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE +#undef SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL + +#endif