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