Merge tag 'LA.UM.9.14.r1-19500-LAHAINA.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/wlan/qcacld-3.0 into android12-5.4-lahaina

"LA.UM.9.14.r1-19500-LAHAINA.QSSI12.0"

* tag 'LA.UM.9.14.r1-19500-LAHAINA.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/wlan/qcacld-3.0:
  qcacld-3.0: set nan_separate_iface_support flag in FTM mode
  Release 2.0.8.28B
  qcacld-3.0: Fix deadlock scenario in packet capture mode
  Release 2.0.8.28A
  qcacld-3.0: fetch profile_data from right position
  Release 2.0.8.28
  qcacld-3.0: SAE: delete preauth node if it's present in list
  Release 2.0.8.27Z
  qcacld-3.0: Fix out-of-bounds in tx_stats
  Release 2.0.8.27Y
  qcacld-3.0: Release serialization cmd when get peer null
  Release 2.0.8.27X
  qcacld-3.0: STA falis to notify Disassoc Imminent to UI
  Release 2.0.8.27W
  qcacld-3.0: select min bw during csa if channel bonding disabled
  Release 2.0.8.27V
  qcacld-3.0: Add TPC Report in probe response
  Release 2.0.8.27U
  qcacld-3.0: Remove roam_invoke_timer stop in case of ROAM_ABORT
  qcacld-3.0: Fix reo id mismatch in fisa path
  Release 2.0.8.27T
  qcacld-3.0: Fix out of bounds access for he_ppet
  Release 2.0.8.27S
  qcacld-3.0: Revert double free change
  Release 2.0.8.27R
  qcacld-3.0: Fix double free in wma_roam_pmkid_request_event_handler
  Release 2.0.8.27Q
  qcacld-3.0: Add support to configure 6G roam scan dwell time
  Release 2.0.8.27P
  qcacld-3.0: Update num_transmit_power_env before packing probe response
  Release 2.0.8.27O
  qcacld-3.0: Optimize the roam latency time
  Release 2.0.8.27N
  qcacld-3.0: Don't send probe req when receive beacon miss
  Release 2.0.8.27M
  qcacld-3.0: Reduce the log level to optimise the roam time
  Release 2.0.8.27L
  qcacld-3.0: Update Copyright for NAN discovery
  Release 2.0.8.27K
  qcacld-3.0: Enable ce debug history always
  Release 2.0.8.27J
  cld-3.0: Consider connected AP for roaming candidate
  Release 2.0.8.27I
  qcacld-3.0: Do not reserve NAN discovery vdev in case of FTM mode
  Release 2.0.8.27H
  qcacld-3.0: Add kbuild cpp flag for low power mode feature
  Release 2.0.8.27G
  qcacld-3.0: Allow suspend in Deep Sleep/Hibernate in wearables
  Release 2.0.8.27F
  qcacld-3.0: Fix slab-out-of-bounds in radio stats
  Release 2.0.8.27E
  qcacld-3.0: Add bug_on if 5 consecutive ll_stats requests fails
  Release 2.0.8.27D
  qcacld-3.0: Handle reset case for P2P_SET_NOA
  Release 2.0.8.27C
  qcacld-3.0: Remove redundant code
  Release 2.0.8.27B
  qcacld-3.0: Enable network queue directly in case of roaming
  qcacld-3.0: Check if netdev feature need to update
  Release 2.0.8.27A
  qcacld-3.0: Change tx retries unit from msdu to mpdu
  qcacld-3.0: Do not ignore idle_shutdown in case of driver mode change
  Release 2.0.8.27
  qcacld-3.0: Enable nan only for VLP channels for 6GHz
  qcacld-3.0: sta roam failed after sap stopped
  qcacld-3.0: Fix arp offload not sent when suspend
  qcacld-3.0: update number of thermal conf param for thermal throttle config
  Release 2.0.8.26Z
  Revert "qcacld-3.0: Prevent runtime suspend on ll_stats and get station requests"
  Release 2.0.8.26Y
  qcacld-3.0: Prevent runtime suspend on ll_stats and get station requests
  qcacld-3.0: Initialize sap ch_width by Max ch_width
  Release 2.0.8.26X
  qcacld-3.0: Return success when firmware doesn't support 11k offload
  Release 2.0.8.26W
  qcacld-3.0: Reject LL stats request for SAP mode
  Release 2.0.8.26V
  qcacld-3.0: Move the sar req-resp event to work context
  Release 2.0.8.26U
  qcacld-3.0: Ignore idle_shutdown if any interface is up
  qcacld-3.0: Allow suspend in deep sleep or Hibernate
  Release 2.0.8.26T
  qcacld-3.0: Send high 32bit addr for no smmu platform which fw need
  qcacld-3.0: Send high 32bit addr for no smmu platform which fw need
  Release 2.0.8.26S
  qcacld-3.0: Add RSO state change logs
  Release 2.0.8.26R
  qcacld-3.0: Validate ini for standalone SAP CSA
  Release 2.0.8.26Q
  qcacld-3.0: Fix signal strength for mgmt rx pkts in pkt capture
  qcacld-3.0: Add support for qos null filters in packet capture
  qcacld-3.0: Add ref count for global vdev used in packet capture
  Release 2.0.8.26P
  qcacld-3.0: Fix phy type for mgmt rx packets in pkt capture mode
  Release 2.0.8.26O
  qcacld-3.0: set msdu/mpdu aggr size for each vdev start
  qcacld-3.0: enhance oui based iot aggr size processing
  qcacld-3.0: add ini for setting oui based aggr size
  Release 2.0.8.26N
  qcacld-3.0: Address race between disconnect and system suspend
  Release 2.0.8.26M
  qcacld-3.0: Add support to calibration failure events parsing
  Release 2.0.8.26L
  qcacld-3.0: Fix possible memory leak of tx_time_per_power_level
  qcacld-3.0: Check input parameters for tx_attr/rx_attr
  Release 2.0.8.26K
  qcacld-3.0: Add INI to configure MGMT frame HW retry count
  Release 2.0.8.26J
  qcacld-3.0: Cleanup SAP interface if start_bss is aborted
  Release 2.0.8.26I
  qcacld-3.0: Fill status correctly for twt resume
  Release 2.0.8.26H
  qcacld-3.0: Drop packets when vdev_id is invalid
  Release 2.0.8.26G
  qcacld-3.0: Reset sap_radar_found_status flag before start sap
  qcacld-3.0: Change ops from vdev specific to psoc level
  qcacld-3.0: Change enum pkt_capture_mode to bit map
  Release 2.0.8.26F
  qcacld-3.0: Check peer TWT capability before TWT setup request
  Release 2.0.8.26E
  qcacld-3.0: Add support for beacon filters in packet capture mode
  Release 2.0.8.26D
  qcacld-3.0: Fix mem leak with NDP peer multicast address list
  Release 2.0.8.26C
  qcacld-3.0: Update channel_before_switch_band in passive chan switch case
  Release 2.0.8.26B
  qcacld-3.0: Control netif sub queues with sub queue pause mask
  Release 2.0.8.26A
  qcacld-3.0: Mem leak in wlan_cm_dual_sta_roam_update_connect_channels
  qcacld-3.0: Print allowed channels for the 2nd STA vdev conn
  Release 2.0.8.26
  qcacld-3.0: Derive NDP peer multicast address from peer MAC address
  Release 2.0.8.25Z
  qcacld-3.0: optimization of p2p miracast connecting time
  Release 2.0.8.25Y
  qcacld-3.0: Exclude BSS membership selector from rate set
  qcacld-3.0: Add H2E require flag to extended support rate
  Release 2.0.8.25X
  qcacld-3.0: Set default value for bss_color_collision_det_sta to 1
  Release 2.0.8.25W
  qcacld-3.0: Fix invalid bssid filled while deleting pmksa
  Release 2.0.8.25V
  qcacld-3.0: Classify qmi/wmi for WMI_REQUEST_STATS_CMDID
  Release 2.0.8.25U
  qcacld-3.0: Reduced country change work resched time
  Release 2.0.8.25T
  qcacld-3.0: Add ini support for tx_retry_multiplier
  qcacld-3.0: Avoid OOB read in sch_get_csa_ecsa_count_offset
  qcacld-3.0: Avoid OOB read in dot11f_unpack_assoc_response
  qcacld-3.0: Fix possible OOB in unpack_tlv_core
  Release 2.0.8.25S
  qcacld-3.0: Add wow event and reason for roam event stats
  qcacld-3.0: Fill the vendor attributes with the Roam stats
  qcacld-3.0: Vendor command changes to enable the roam events stats
  qcacld-3.0: Update tx Failed Count
  Release 2.0.8.25R
  qcacld-3.0: add os_if layer for monitor mode configuration
  qcacld-3.0: Move enet.h header file
  Release 2.0.8.25Q
  qcacld-3.0: Send OCV capability in assoc request
  Release 2.0.8.25P
  qcacld-3.0: Save ext cap IE from join request
  Release 2.0.8.25O
  qcacld-3.0: Avoid OOB read in sch_get_csa_ecsa_count_offset
  qcacld-3.0: Avoid OOB read in dot11f_unpack_assoc_response
  Release 2.0.8.25N
  qcacld-3.0: Resume all modules before recovery shutdown
  Release 2.0.8.25M
  qcacld-3.0: Add support to send set IE request in cnx manager
  qcacld-3.0: Update exteneded capabilities after connection
  Release 2.0.8.25L
  qcacld-3.0: Revert "Fix channel width mismatch in ROAM SYNC"
  qcacld-3.0: Update ch freq/bw to wma in Roam sync
  Release 2.0.8.25K
  qcacld-3.0: Reduce log level when get unexpected action frame
  qcacld-3.0: channel_switch_complete_evt need wake up all waiting threads
  Release 2.0.8.25J
  qcacld-3.0: Limit ROC for listen if NAN or NDI present
  Release 2.0.8.25I
  qcacld-3.0: Update VHT IE with highest supported LGI rate
  Release 2.0.8.25H
  qcacld-3.0: compilation fix for ks sync path change
  Release 2.0.8.25G
  qcacld-3.0: remove FEATURE_HAL_DELAYED_REG_WRITE_V2 from Kbuild
  Release 2.0.8.25F
  qcacld-3.0: Fix refill thread getting stuck in suspend state
  Release 2.0.8.25E
  qcacld-3.0: Deliver tx offload mgmt pkts based on filter
  Release 2.0.8.25D
  qcacld-3.0: Add check for mgmt/ctrl tx packets in pkt capture
  Release 2.0.8.25C
  qcacld-3.0: Remove all WLAN_REG_IS_SAME_BAND_CHANNELS instances
  Release 2.0.8.25B
  qcacld-3.0: Add check for mgmt/ctrl rx packets in pkt capture
  Release 2.0.8.25A
  qcacld-3.0: Add filter for data packets in packet capture mode
  Release 2.0.8.25
  qcacld-3.0: Add check for data tx rx based on vendor command
  qcacld-3.0: Add tgt support to send beacon report period to FW
  qcacld-3.0: Add support to send config to FW based on filter
  qcacld-3.0: Add support to send mode to FW based on frame filter
  Release 2.0.8.24Z
  qcacld-3.0: Fix race condition between connect and disconnect
  Release 2.0.8.24Y
  qcacld-3.0: Avoid possible array OOB
  Release 2.0.8.24X
  qcacld-3.0: Cleanup CSR/LIM for Roam sync indication failure in CSR
  Release 2.0.8.24W
  qcacld-3.0: update default addba response rx aggr size to 256
  qcacld-3.0: initialize pdev id after ssr for thermal throttle reconfig
  qcacld-3.0: Invalid rem_len computation in roam stats evt handler
  Release 2.0.8.24V
  qcacld-3.0: vendor command changes to configure parameters for monitor mode
  Release 2.0.8.24U
  qcacld-3.0: Fix array OOB for duplicate rate
  Release 2.0.8.24T
  qcacld-3.0: Set frame filter based on vendor command
  Release 2.0.8.24S
  qcacld-3.0: Map monitor interface vdev during SSR
  Release 2.0.8.24R
  qcacld-3.0: Fix SAP alone failed when g_sta_sap_scc_on_dfs_chan is 1
  Release 2.0.8.24Q
  qcacld-3.0: Fix possible OOB in unpack_tlv_core
  qcacld-3.0: Fix PHY type of rx legacy packets in packet capture
  Release 2.0.8.24P
  qcacld-3.0: Do not fill average rssi for RX packets
  Release 2.0.8.24O
  qcacld-3.0: Fix possible OOB in extract_peer_stats_count_tlv
  qcacld-3.0: Invalid rem_len computation in roam stats evt handler
  Release 2.0.8.24N
  qcacld-3.0: Don't delete monitor interface when STA interface is down
  qcacld-3.0: Add ini configuration to limit supported HE MCS rates
  Release 2.0.8.24M
  qcacld-3.0: Fix invalid bss descriptor length check
  Release 2.0.8.24L
  qcacld-3.0: Add debug prints in SA query response
  Release 2.0.8.24K
  qcacld-3.0: Stop CFR once get disconnection event
  Release 2.0.8.24J
  qcacld-3.0: Add an INI to configure SAE auth failure timeout
  qcacld-3.0: Notify the failure to firmware if SAE auth retries exhausted
  Release 2.0.8.24I
  qcacld-3.0: Add support to get thermal throttle stats
  Release 2.0.8.24H
  qcacld-3.0: Include Thermal Module in KBuild
  Release 2.0.8.24G
  qcacld-3.0: Unsubscribe in reverse order of subscription
  Release 2.0.8.24F
  qcacld-3.0: Remove unused linux header file
  Release 2.0.8.24E
  qcacld-3.0: Fill the nss in tx status in pkt capture mode
  qcacld-3.0: Fill the ppdu stats in tx status in pkt capture mode
  qcacld-3.0: Register for wdi event WDI_PKT_CAPTURE_PPDU_STATS

Change-Id: Ic331fbe4ae5910fb40ce98c7cf2fee884f88c94b
This commit is contained in:
Michael Bestas 2022-05-19 00:35:27 +03:00
commit 5840d3cbf3
No known key found for this signature in database
GPG key ID: CC95044519BE6669
148 changed files with 6947 additions and 1134 deletions

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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);
}

View file

@ -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);

View file

@ -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
};
};

View file

@ -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;

View file

@ -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")
/* <ini>
* 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
*
* </ini>
*/
#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

View file

@ -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_ */

View file

@ -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

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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;
};

View file

@ -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, &ampdu_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;
}

View file

@ -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;
}

View file

@ -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")
/*
* <ini>
* 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
*
* </ini>
*/
#define CFG_TX_RETRY_MULTIPLIER CFG_INI_UINT( \
"tx_retry_multiplier", \
0, \
500, \
0, \
CFG_VALUE_OR_DEFAULT, \
"percentage of max retry limit")
/*
* <ini>
* 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>,<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
*
* </ini>
*/
#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 */

View file

@ -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 */
/*
* <ini>
* 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
*
* </ini>
*/
#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 */
/*
* <ini>
* 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
*
* </ini>
*/
#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 */
/*
* <ini>
* 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
*
* </ini>
*/
#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 */
/*
* <ini>
* 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
*
* </ini>
*/
#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")

View file

@ -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 \

View file

@ -312,6 +312,27 @@
CFG_VALUE_OR_DEFAULT, \
"timeout period for wmi watchdog bite")
/*
* <ini>
* 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
*
* </ini>
*/
#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 */

View file

@ -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")

View file

@ -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
/*
* <ini>
* 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=<OUI-1>,<MSDU-1>,<MPDU-1>,<OUI-2>,<MSDU-2>,<MPDU-2>...
* 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
*
* </ini>
*/
#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 */

View file

@ -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_ */

View file

@ -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;
};
/**

View file

@ -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,

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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

View file

@ -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),

View file

@ -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];
};
/**

View file

@ -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
/*
* <ini>
* 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")

View file

@ -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_ */

View file

@ -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;

View file

@ -34,6 +34,7 @@
#include "wlan_p2p_off_chan_tx.h"
#include "wlan_osif_request_manager.h"
#include <wlan_mlme_main.h>
#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;

View file

@ -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);

View file

@ -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

View file

@ -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 {

View file

@ -29,6 +29,7 @@
#include "cdp_txrx_cmn_struct.h"
#include <qdf_nbuf.h>
#include <qdf_list.h>
#ifndef WLAN_FEATURE_PKT_CAPTURE_V2
#include <htt_internal.h>
#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[];
};
/**

View file

@ -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_ */

View file

@ -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

View file

@ -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_ */

View file

@ -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:

View file

@ -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 <dp_types.h>
#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 <cds_ieee80211_common.h>
#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;
}

View file

@ -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, &params, 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,

View file

@ -21,7 +21,6 @@
*/
#include "wlan_pkt_capture_mon_thread.h"
#include <linux/kthread.h>
#include "cds_ieee80211_common.h"
#include "wlan_mgmt_txrx_utils_api.h"
#include "cdp_txrx_ctrl.h"

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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)

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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, &params);
}
/**
* 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;

View file

@ -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,
&param);
}

View file

@ -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;

View file

@ -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 <wmi_unified_api.h>
#include <target_if.h>
#include <init_deinit_lmac.h>
#include <wlan_pkt_capture_api.h>
/**
* 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, &param);
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, &param);
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;
}

View file

@ -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, &params->conn_ap_min_rssi);
wlan_mlme_get_idle_roam_band(psoc, &params->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;
}

View file

@ -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

View file

@ -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__ */

View file

@ -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
};
/**

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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 */

View file

@ -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)

View file

@ -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;

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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;
}

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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 */

View file

@ -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

View file

@ -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)) {

View file

@ -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);

View file

@ -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

View file

@ -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, &params);
} 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:

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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 <cdp_txrx_ctrl.h>
#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);
}

View file

@ -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);
/*

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -43,6 +43,7 @@
#include <cdp_txrx_stats_struct.h>
#include <cdp_txrx_peer_ops.h>
#include <cdp_txrx_host_stats.h>
#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;

View file

@ -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;

View file

@ -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

View file

@ -36,8 +36,12 @@
#include <qca_vendor.h>
#include "wlan_fwol_ucfg_api.h"
#include <pld_common.h>
#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(&params);
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,

View file

@ -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 */

View file

@ -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, &params);
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;

View file

@ -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];

View file

@ -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;

View file

@ -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

Some files were not shown because too many files have changed in this diff Show more