summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kbuild4
-rw-r--r--core/cds/inc/cds_reg_service.h15
-rw-r--r--core/cds/src/cds_concurrency.c2
-rw-r--r--core/cds/src/cds_reg_service.c10
-rw-r--r--core/cds/src/cds_sched.c3
-rw-r--r--core/dp/htt/htt.c14
-rw-r--r--core/hdd/inc/wlan_hdd_assoc.h22
-rw-r--r--core/hdd/inc/wlan_hdd_cfg.h84
-rw-r--r--core/hdd/inc/wlan_hdd_debugfs.h90
-rw-r--r--core/hdd/inc/wlan_hdd_main.h39
-rw-r--r--core/hdd/inc/wlan_hdd_power.h6
-rw-r--r--core/hdd/inc/wlan_hdd_tx_rx.h12
-rw-r--r--core/hdd/src/wlan_hdd_assoc.c73
-rw-r--r--core/hdd/src/wlan_hdd_cfg.c39
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c32
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h14
-rw-r--r--core/hdd/src/wlan_hdd_debugfs.c46
-rw-r--r--core/hdd/src/wlan_hdd_debugfs_csr.c34
-rw-r--r--core/hdd/src/wlan_hdd_driver_ops.c7
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c251
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.h6
-rw-r--r--core/hdd/src/wlan_hdd_ioctl.c320
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c3316
-rw-r--r--core/hdd/src/wlan_hdd_main.c182
-rw-r--r--core/hdd/src/wlan_hdd_nan_datapath.c45
-rw-r--r--core/hdd/src/wlan_hdd_p2p.c15
-rw-r--r--core/hdd/src/wlan_hdd_power.c14
-rw-r--r--core/hdd/src/wlan_hdd_scan.c16
-rw-r--r--core/hdd/src/wlan_hdd_softap_tx_rx.c2
-rw-r--r--core/hdd/src/wlan_hdd_tsf.c24
-rw-r--r--core/hdd/src/wlan_hdd_tx_rx.c57
-rw-r--r--core/hdd/src/wlan_hdd_wext.c23
-rw-r--r--core/mac/inc/ani_global.h4
-rw-r--r--core/mac/inc/qwlan_version.h6
-rw-r--r--core/mac/inc/sir_api.h2
-rw-r--r--core/mac/inc/sir_mac_prot_def.h5
-rw-r--r--core/mac/src/include/dph_global.h7
-rw-r--r--core/mac/src/include/parser_api.h10
-rw-r--r--core/mac/src/pe/include/rrm_global.h3
-rw-r--r--core/mac/src/pe/lim/lim_api.c22
-rw-r--r--core/mac/src/pe/lim/lim_assoc_utils.c21
-rw-r--r--core/mac/src/pe/lim/lim_p2p.c9
-rw-r--r--core/mac/src/pe/lim/lim_process_action_frame.c117
-rw-r--r--core/mac/src/pe/lim/lim_process_assoc_req_frame.c24
-rw-r--r--core/mac/src/pe/lim/lim_process_auth_frame.c21
-rw-r--r--core/mac/src/pe/lim/lim_sme_req_utils.c2
-rw-r--r--core/mac/src/pe/lim/lim_types.h3
-rw-r--r--core/mac/src/pe/rrm/rrm_api.c1
-rw-r--r--core/mac/src/sys/legacy/src/system/src/sys_entry_func.c15
-rw-r--r--core/mac/src/sys/legacy/src/utils/src/parser_api.c19
-rw-r--r--core/pld/src/pld_snoc.c58
-rw-r--r--core/pld/src/pld_snoc.h51
-rw-r--r--core/sap/dfs/src/dfs_init.c9
-rw-r--r--core/sap/inc/sap_api.h4
-rw-r--r--core/sap/src/sap_api_link_cntl.c6
-rw-r--r--core/sap/src/sap_fsm.c39
-rw-r--r--core/sap/src/sap_module.c6
-rw-r--r--core/sme/inc/csr_api.h10
-rw-r--r--core/sme/inc/csr_internal.h2
-rw-r--r--core/sme/inc/csr_support.h7
-rw-r--r--core/sme/inc/sme_api.h12
-rw-r--r--core/sme/src/common/sme_api.c46
-rw-r--r--core/sme/src/csr/csr_api_roam.c57
-rw-r--r--core/sme/src/csr/csr_neighbor_roam.c2
-rw-r--r--core/sme/src/csr/csr_util.c52
-rw-r--r--core/wma/src/wma_dev_if.c19
-rw-r--r--core/wma/src/wma_features.c30
-rw-r--r--core/wma/src/wma_mgmt.c48
-rw-r--r--core/wma/src/wma_scan_roam.c82
-rw-r--r--core/wma/src/wma_utils.c24
70 files changed, 3749 insertions, 1923 deletions
diff --git a/Kbuild b/Kbuild
index 3fdcb0e6863f..06a51284be8d 100644
--- a/Kbuild
+++ b/Kbuild
@@ -59,6 +59,10 @@ ifeq ($(KERNEL_BUILD), 0)
CONFIG_MOBILE_ROUTER := y
endif
+ ifeq ($(CONFIG_ARCH_SDXPOORWILLS), y)
+ CONFIG_MOBILE_ROUTER := y
+ endif
+
# If platform wants to support two driver base on this source
# code, below feature WLAN_DISABLE_EXPORT_SYMBOL needs to be
# enabled, otherwise when loading the second the driver,
diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h
index fb84151b01df..b64d9d6763c4 100644
--- a/core/cds/inc/cds_reg_service.h
+++ b/core/cds/inc/cds_reg_service.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -385,6 +385,19 @@ QDF_STATUS cds_get_channel_list_with_power(struct channel_power
*base_channels,
uint8_t *num_base_channels);
+/**
+ * cds_set_channel_state() - API to set the channel state in reg table
+ * @chan_num - input channel enum
+ * @state - state of the channel to be set
+ * CHANNEL_STATE_DISABLE
+ * CHANNEL_STATE_DFS
+ * CHANNEL_STATE_ENABLE
+ * CHANNEL_STATE_INVALID
+ *
+ * Return: Void
+ */
+void cds_set_channel_state(uint32_t chan_num, enum channel_state state);
+
enum channel_state cds_get_channel_state(uint32_t chan_num);
QDF_STATUS cds_get_dfs_region(enum dfs_region *dfs_reg);
QDF_STATUS cds_put_dfs_region(enum dfs_region dfs_reg);
diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c
index 3d72e2bb57a1..54d9dea47abc 100644
--- a/core/cds/src/cds_concurrency.c
+++ b/core/cds/src/cds_concurrency.c
@@ -9907,6 +9907,8 @@ void cds_init_sap_mandatory_2g_chan(void)
cds_err("Error in getting valid channels");
return;
}
+ cds_ctx->sap_mandatory_channels_len = 0;
+
for (i = 0; i < len; i++) {
if (CDS_IS_CHANNEL_24GHZ(chan_list[i])) {
cds_err("Add chan %hu to mandatory list", chan_list[i]);
diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c
index 4ebfe3cedafa..5e8cc979950d 100644
--- a/core/cds/src/cds_reg_service.c
+++ b/core/cds/src/cds_reg_service.c
@@ -224,6 +224,16 @@ enum channel_enum cds_get_channel_enum(uint32_t chan_num)
return INVALID_CHANNEL;
}
+void cds_set_channel_state(uint32_t chan_num, enum channel_state state)
+{
+ enum channel_enum chan_enum;
+
+ chan_enum = cds_get_channel_enum(chan_num);
+ if (INVALID_CHANNEL == chan_enum)
+ return;
+
+ reg_channels[chan_enum].state = state;
+}
/**
* cds_get_channel_state() - get the channel state
diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c
index 221251ef625c..5b9a8d765a6a 100644
--- a/core/cds/src/cds_sched.c
+++ b/core/cds/src/cds_sched.c
@@ -358,7 +358,8 @@ __cds_cpu_hotplug_notify(struct notifier_block *block,
if ((NULL == pSchedContext) || (NULL == pSchedContext->ol_rx_thread))
return NOTIFY_OK;
- if (cds_is_load_or_unload_in_progress())
+ if (cds_is_load_or_unload_in_progress() ||
+ cds_is_module_stop_in_progress() || cds_is_driver_recovering())
return NOTIFY_OK;
num_cpus = num_possible_cpus();
diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c
index ddad788f1d83..b717491c29c7 100644
--- a/core/dp/htt/htt.c
+++ b/core/dp/htt/htt.c
@@ -337,12 +337,20 @@ static int
htt_htc_attach_all(struct htt_pdev_t *pdev)
{
if (htt_htc_attach(pdev, HTT_DATA_MSG_SVC))
- return -EIO;
+ goto flush_endpoint;
+
if (htt_htc_attach(pdev, HTT_DATA2_MSG_SVC))
- return -EIO;
+ goto flush_endpoint;
+
if (htt_htc_attach(pdev, HTT_DATA3_MSG_SVC))
- return -EIO;
+ goto flush_endpoint;
+
return 0;
+
+flush_endpoint:
+ htc_flush_endpoint(pdev->htc_pdev, ENDPOINT_0, HTC_TX_PACKET_TAG_ALL);
+
+ return -EIO;
}
#else
/**
diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h
index 2e5248a6029b..f2e50a83a176 100644
--- a/core/hdd/inc/wlan_hdd_assoc.h
+++ b/core/hdd/inc/wlan_hdd_assoc.h
@@ -390,4 +390,26 @@ static inline void hdd_save_gtk_params(hdd_adapter_t *adapter,
}
#endif
+/**
+ * hdd_copy_ht_caps()- copy ht caps info from roam info to
+ * hdd station context.
+ * @hdd_ht_cap: pointer to Source ht_cap info of type ieee80211_ht_cap
+ * @roam_ht_cap: pointer to roam ht_caps info
+ *
+ * Return: None
+ */
+void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap,
+ tDot11fIEHTCaps *roam_ht_cap);
+
+/**
+ * hdd_copy_vht_caps()- copy vht caps info from roam info to
+ * hdd station context.
+ * @hdd_vht_cap: pointer to Source vht_cap info of type ieee80211_vht_cap
+ * @roam_vht_cap: pointer to roam vht_caps info
+ *
+ * Return: None
+ */
+void hdd_copy_vht_caps(struct ieee80211_vht_cap *hdd_vht_cap,
+ tDot11fIEVHTCaps *roam_vht_cap);
+
#endif
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 8e516c1a9631..69e5b1709847 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -2102,6 +2102,28 @@ enum hdd_dot11_mode {
/*
* <ini>
+ * enable_ftopen - enable/disable FT open feature
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * This INI is used to enable/disable FT open feature
+ *
+ * Related: None
+ *
+ * Supported Feature: Roaming
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_ROAM_FT_OPEN_ENABLE_NAME "enable_ftopen"
+#define CFG_ROAM_FT_OPEN_ENABLE_MIN (0)
+#define CFG_ROAM_FT_OPEN_ENABLE_MAX (1)
+#define CFG_ROAM_FT_OPEN_ENABLE_DEFAULT (1)
+
+/*
+ * <ini>
* groam_dense_min_aps - Sets minimum number of AP for dense roam
* @Min: 1
* @Max: 5
@@ -5115,6 +5137,27 @@ enum hdd_link_speed_rpt_type {
/*
* <ini>
+ * enable_vht20_mcs9 - Enables VHT MCS9 in 20M BW operation
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11AC
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+
+#define CFG_ENABLE_VHT20_MCS9 "enable_vht20_mcs9"
+#define CFG_ENABLE_VHT20_MCS9_MIN (0)
+#define CFG_ENABLE_VHT20_MCS9_MAX (1)
+#define CFG_ENABLE_VHT20_MCS9_DEFAULT (1)
+
+/*
+ * <ini>
* gEnable2x2 - Enables/disables VHT Tx/Rx MCS values for 2x2
* @Min: 0
* @Max: 1
@@ -10847,7 +10890,7 @@ enum restart_beaconing_on_ch_avoid_rule {
* gAutoBmpsTimerValue - Set Auto BMPS Timer value
* @Min: 0
* @Max: 120
- * @Default: 0
+ * @Default: 5
*
* This ini is used to set Auto BMPS Timer value in seconds
*
@@ -10862,7 +10905,7 @@ enum restart_beaconing_on_ch_avoid_rule {
#define CFG_AUTO_PS_ENABLE_TIMER_NAME "gAutoBmpsTimerValue"
#define CFG_AUTO_PS_ENABLE_TIMER_MIN (0)
#define CFG_AUTO_PS_ENABLE_TIMER_MAX (120)
-#define CFG_AUTO_PS_ENABLE_TIMER_DEFAULT (0)
+#define CFG_AUTO_PS_ENABLE_TIMER_DEFAULT (5)
#ifdef WLAN_ICMP_DISABLE_PS
/*
@@ -14307,6 +14350,39 @@ enum hw_filter_mode {
#define CFG_DTIM_SELECTION_DIVERSITY_MAX (30)
#define CFG_DTIM_SELECTION_DIVERSITY_DEFAULT (5)
+/*
+ * <ini>
+ * gTxSchDelay - Enable/Disable Tx sch delay
+ * @Min: 0
+ * @Max: 5
+ * @Default: 2
+ *
+ * Usage: Internal/External
+ *
+ * </ini>
+ */
+
+#define CFG_TX_SCH_DELAY_NAME "gTxSchDelay"
+#define CFG_TX_SCH_DELAY_MIN (0)
+#define CFG_TX_SCH_DELAY_MAX (5)
+#define CFG_TX_SCH_DELAY_DEFAULT (2)
+
+/*
+ * <ini>
+ * enable_rtt_mac_randomization - Enable/Disable rtt mac randomization
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_ENABLE_RTT_MAC_RANDOMIZATION_NAME "enable_rtt_mac_randomization"
+#define CFG_ENABLE_RTT_MAC_RANDOMIZATION_MIN (0)
+#define CFG_ENABLE_RTT_MAC_RANDOMIZATION_MAX (1)
+#define CFG_ENABLE_RTT_MAC_RANDOMIZATION_DEFAULT (0)
+
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@@ -14622,6 +14698,7 @@ struct hdd_config {
bool enableTxBF;
bool enable_subfee_vendor_vhtie;
bool enable_txbf_sap_mode;
+ bool enable_vht20_mcs9;
uint8_t txBFCsnValue;
bool enable_su_tx_bformer;
uint8_t vhtRxMCS2x2;
@@ -15212,9 +15289,12 @@ struct hdd_config {
uint32_t neighbor_report_offload_max_req_cap;
uint32_t channel_select_logic_conc;
bool enable_dtim_selection_diversity;
+ uint8_t enable_tx_sch_delay;
#ifdef WLAN_FEATURE_SAE
bool is_sae_enabled;
#endif
+ bool enable_rtt_mac_randomization;
+ bool enable_ftopen;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/inc/wlan_hdd_debugfs.h b/core/hdd/inc/wlan_hdd_debugfs.h
index 9633e0018e4e..2ac5a8f37090 100644
--- a/core/hdd/inc/wlan_hdd_debugfs.h
+++ b/core/hdd/inc/wlan_hdd_debugfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -31,6 +31,43 @@
#ifdef WLAN_DEBUGFS
QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter);
void hdd_debugfs_exit(hdd_adapter_t *adapter);
+
+/**
+ * hdd_wait_for_debugfs_threads_completion() - Wait for debugfs threads
+ * completion before proceeding further to stop modules
+ *
+ * Return: true if there is no debugfs open
+ * false if there is at least one debugfs open
+ */
+bool hdd_wait_for_debugfs_threads_completion(void);
+
+/**
+ * hdd_return_debugfs_threads_count() - Return active debugfs threads
+ *
+ * Return: total number of active debugfs threads in driver
+ */
+int hdd_return_debugfs_threads_count(void);
+
+/**
+ * hdd_debugfs_thread_increment() - Increment debugfs thread count
+ *
+ * This function is used to increment and keep track of debugfs thread count.
+ * This is invoked for every file open operation.
+ *
+ * Return: None
+ */
+void hdd_debugfs_thread_increment(void);
+
+/**
+ * hdd_debugfs_thread_decrement() - Decrement debugfs thread count
+ *
+ * This function is used to decrement and keep track of debugfs thread count.
+ * This is invoked for every file release operation.
+ *
+ * Return: None
+ */
+void hdd_debugfs_thread_decrement(void);
+
#else
static inline QDF_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
{
@@ -40,5 +77,56 @@ static inline QDF_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
static inline void hdd_debugfs_exit(hdd_adapter_t *adapter)
{
}
+
+/**
+ * hdd_wait_for_debugfs_threads_completion() - Wait for debugfs threads
+ * completion before proceeding further to stop modules
+ *
+ * Return: true if there is no debugfs open
+ * false if there is at least one debugfs open
+ */
+static inline
+bool hdd_wait_for_debugfs_threads_completion(void)
+{
+ return true;
+}
+
+/**
+ * hdd_return_debugfs_threads_count() - Return active debugfs threads
+ *
+ * Return: total number of active debugfs threads in driver
+ */
+static inline
+int hdd_return_debugfs_threads_count(void)
+{
+ return 0;
+}
+
+/**
+ * hdd_debugfs_thread_increment() - Increment debugfs thread count
+ *
+ * This function is used to increment and keep track of debugfs thread count.
+ * This is invoked for every file open operation.
+ *
+ * Return: None
+ */
+static inline
+void hdd_debugfs_thread_increment(void)
+{
+}
+
+/**
+ * hdd_debugfs_thread_decrement() - Decrement debugfs thread count
+ *
+ * This function is used to decrement and keep track of debugfs thread count.
+ * This is invoked for every file release operation.
+ *
+ * Return: None
+ */
+static inline
+void hdd_debugfs_thread_decrement(void)
+{
+}
+
#endif /* #ifdef WLAN_DEBUGFS */
#endif /* #ifndef _WLAN_HDD_DEBUGFS_H */
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 4b158e31821b..6cf2fe2c27ea 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1165,6 +1165,7 @@ struct hdd_ap_ctx_s {
/* Fw txrx stats info */
struct hdd_fw_txrx_stats txrx_stats;
+ qdf_atomic_t acs_in_progress;
};
typedef struct hdd_scaninfo_s {
@@ -1882,6 +1883,33 @@ enum hdd_sta_smps_param {
};
/**
+ * struct hdd_cache_channel_info - Structure of the channel info
+ * which needs to be cached
+ * @channel_num: channel number
+ * @reg_status: Current regulatory status of the channel
+ * Enable
+ * Disable
+ * DFS
+ * Invalid
+ * @wiphy_status: Current wiphy status
+ */
+struct hdd_cache_channel_info {
+ uint32_t channel_num;
+ enum channel_state reg_status;
+ uint32_t wiphy_status;
+};
+
+/**
+ * struct hdd_cache_channels - Structure of the channels to be cached
+ * @num_channels: Number of channels to be cached
+ * @channel_info: Structure of the channel info
+ */
+struct hdd_cache_channels {
+ uint32_t num_channels;
+ struct hdd_cache_channel_info *channel_info;
+};
+
+/**
* struct hdd_context_s
* @adapter_nodes: an array of adapter nodes for keeping track of hdd adapters
*/
@@ -2203,7 +2231,8 @@ struct hdd_context_s {
/* mutex lock to block concurrent access */
struct mutex power_stats_lock;
#endif
- qdf_atomic_t is_acs_allowed;
+ struct hdd_cache_channels *original_channels;
+ qdf_mutex_t cache_channel_lock;
};
int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
@@ -3088,4 +3117,12 @@ void hdd_driver_memdump_deinit(void);
*/
bool hdd_is_cli_iface_up(hdd_context_t *hdd_ctx);
+/**
+ * wlan_hdd_free_cache_channels() - Free the cache channels list
+ * @hdd_ctx: Pointer to HDD context
+ *
+ * Return: None
+ */
+void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx);
+
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */
diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h
index e27e3cdbbadb..ecb062e9839d 100644
--- a/core/hdd/inc/wlan_hdd_power.h
+++ b/core/hdd/inc/wlan_hdd_power.h
@@ -42,6 +42,12 @@
#define HDD_WAKELOCK_TIMEOUT_CONNECT 1000
#define HDD_WAKELOCK_TIMEOUT_RESUME 1000
+/*
+ * HDD_WAKELOCK_CONNECT_COMPLETE = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT (3000) +
+ * WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STADEF (1000) +
+ * WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STADEF (2000)
+ */
+#define HDD_WAKELOCK_CONNECT_COMPLETE 6000
/**
* enum pkt_filter_protocol_layer - packet filter protocol layer
diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h
index c5ff55f5fdcc..baaa1c28115a 100644
--- a/core/hdd/inc/wlan_hdd_tx_rx.h
+++ b/core/hdd/inc/wlan_hdd_tx_rx.h
@@ -45,6 +45,10 @@
#define HDD_ETHERTYPE_802_1_X_FRAME_OFFSET 12
#ifdef FEATURE_WLAN_WAPI
#define HDD_ETHERTYPE_WAI 0x88b4
+#define IS_HDD_ETHERTYPE_WAI(_skb) (ntohs(_skb->protocol) == \
+ HDD_ETHERTYPE_WAI)
+#else
+#define IS_HDD_ETHERTYPE_WAI(_skb) (false)
#endif
#define HDD_PSB_CFG_INVALID 0xFF
@@ -62,6 +66,14 @@ QDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter);
QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf);
/**
+ * hdd_reset_all_adapters_connectivity_stats() - reset connectivity stats
+ * @hdd_ctx: pointer to HDD Station Context
+ *
+ * Return: None
+ */
+void hdd_reset_all_adapters_connectivity_stats(hdd_context_t *hdd_ctx);
+
+/**
* hdd_tx_rx_collect_connectivity_stats_info() - collect connectivity stats
* @skb: pointer to skb data
* @adapter: pointer to vdev apdapter
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index e6b702bdf428..ad5d1029c3e5 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -118,6 +118,8 @@ uint8_t ccp_rsn_oui_0f[HDD_RSN_OUI_SIZE] = {0x00, 0x0F, 0xAC, 0x0F};
uint8_t ccp_rsn_oui_10[HDD_RSN_OUI_SIZE] = {0x00, 0x0F, 0xAC, 0x10};
uint8_t ccp_rsn_oui_11[HDD_RSN_OUI_SIZE] = {0x00, 0x0F, 0xAC, 0x11};
#endif
+static const
+uint8_t ccp_rsn_oui_12[HDD_RSN_OUI_SIZE] = {0x50, 0x6F, 0x9A, 0x02};
static const
uint8_t ccp_rsn_oui_0b[HDD_RSN_OUI_SIZE] = {0x00, 0x0F, 0xAC, 0x0B};
@@ -467,14 +469,6 @@ static int hdd_add_beacon_filter(hdd_adapter_t *adapter)
return 0;
}
-/**
- * hdd_copy_vht_caps()- copy vht caps info from roam info to
- * hdd station context.
- * @hdd_sta_ctx: pointer to hdd station context
- * @roam_info: pointer to roam info
- *
- * Return: None
- */
void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap,
tDot11fIEHTCaps *roam_ht_cap)
{
@@ -660,7 +654,7 @@ void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap,
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB_SHIFT 26
/**
- * hdd_copy_ht_caps()- copy ht caps info from roam info to
+ * hdd_copy_vht_caps()- copy vht caps info from roam info to
* hdd station context.
* @hdd_sta_ctx: pointer to hdd station context
* @roam_info: pointer to roam info
@@ -1806,7 +1800,8 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
}
} else {
sta_id = pHddStaCtx->conn_info.staId[0];
- hdd_debug("roamResult: %d", roamResult);
+ hdd_debug("roamResult is: %d %s", roamResult,
+ get_e_csr_roam_result_str(roamResult));
/* clear scan cache for Link Lost */
if (pRoamInfo && !pRoamInfo->reasonCode &&
@@ -2611,9 +2606,12 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
pHddStaCtx->conn_info.connState)) &&
((eCSR_ROAM_RESULT_ASSOCIATED == roamResult) ||
(eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus))) {
- hdd_info("hddDisconInProgress state=%d, result=%d, status=%d",
+ hdd_info("hddDisconInProgress state=%d, result=%d %s, status=%d %s",
pHddStaCtx->conn_info.connState,
- roamResult, roamStatus);
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus));
hddDisconInProgress = true;
}
@@ -2974,10 +2972,13 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
else {
hdd_debug("sending connect indication to nl80211:for bssid "
MAC_ADDRESS_STR
- " result:%d and Status:%d",
+ " result:%d %s and Status:%d %s",
MAC_ADDR_ARRAY
(pRoamInfo->bssid.bytes),
- roamResult, roamStatus);
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus));
/* inform connect result to nl80211 */
hdd_connect_result(dev,
@@ -3111,14 +3112,20 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
if (pRoamInfo)
hdd_err("wlan: connection failed with " MAC_ADDRESS_STR
- " result: %d and Status: %d",
+ " result: %d %s and Status: %d %s",
MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes),
- roamResult, roamStatus);
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus));
else
hdd_err("wlan: connection failed with " MAC_ADDRESS_STR
- " result: %d and Status: %d",
+ " result: %d %s and Status: %d %s",
MAC_ADDR_ARRAY(pWextState->req_bssId.bytes),
- roamResult, roamStatus);
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus));
if ((eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE == roamResult) ||
(pRoamInfo &&
@@ -3148,18 +3155,24 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
if (pRoamInfo) {
hdd_err("send connect failure to nl80211: for bssid "
MAC_ADDRESS_STR
- " result: %d and Status: %d reasoncode: %d",
+ " result: %d %s and Status: %d %s reasoncode: %d",
MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes),
- roamResult, roamStatus,
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus),
pRoamInfo->reasonCode);
pHddStaCtx->conn_info.assoc_status_code =
pRoamInfo->statusCode;
} else {
hdd_err("connect failed: for bssid "
MAC_ADDRESS_STR
- " result: %d and status: %d ",
+ " result: %d %s and status: %d %s",
MAC_ADDR_ARRAY(pWextState->req_bssId.bytes),
- roamResult, roamStatus);
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus));
}
hdd_debug("Invoking packetdump deregistration API");
wlan_deregister_txrx_packetdump();
@@ -5015,8 +5028,12 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
hdd_context_t *pHddCtx;
if (eCSR_ROAM_UPDATE_SCAN_RESULT != roamStatus)
- hdd_debug("CSR Callback: status= %d result= %d roamID=%d",
- roamStatus, roamResult, roamId);
+ hdd_debug("CSR Callback: status= %d %s result= %d %s roamID=%d",
+ roamStatus,
+ get_e_roam_cmd_status_str(roamStatus),
+ roamResult,
+ get_e_csr_roam_result_str(roamResult),
+ roamId);
/* Sanity check */
if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
hdd_err("Invalid adapter or adapter has invalid magic");
@@ -5484,6 +5501,8 @@ eCsrAuthType hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4])
} else if (memcmp(auth_suite, ccp_rsn_oui_0c, 4) == 0) {
/* Check for Suite B EAP 384 */
auth_type = eCSR_AUTH_TYPE_SUITEB_EAP_SHA384;
+ } else if (memcmp(auth_suite, ccp_rsn_oui_12, 4) == 0) {
+ auth_type = eCSR_AUTH_TYPE_DPP_RSN;
} else {
hdd_translate_fils_rsn_to_csr_auth(auth_suite, &auth_type);
hdd_translate_owe_rsn_to_csr_auth(auth_suite, &auth_type);
@@ -6000,8 +6019,10 @@ int hdd_set_csr_auth_type(hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType)
eCSR_AUTH_TYPE_CCKM_RSN;
} else
#endif
-
- if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN) &&
+ if (RSNAuthType == eCSR_AUTH_TYPE_DPP_RSN) {
+ pRoamProfile->AuthType.authType[0] =
+ eCSR_AUTH_TYPE_DPP_RSN;
+ } else if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN) &&
((pWextState->
authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
== IW_AUTH_KEY_MGMT_802_1X)) {
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 6e3450d3323b..746a6ce9fd28 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -2143,6 +2143,13 @@ struct reg_table_entry g_registry_table[] = {
CFG_VHT_ENABLE_TX_MCS2x2_8_9_MIN,
CFG_VHT_ENABLE_TX_MCS2x2_8_9_MAX),
+ REG_VARIABLE(CFG_ENABLE_VHT20_MCS9, WLAN_PARAM_Integer,
+ struct hdd_config, enable_vht20_mcs9,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENABLE_VHT20_MCS9_DEFAULT,
+ CFG_ENABLE_VHT20_MCS9_MIN,
+ CFG_ENABLE_VHT20_MCS9_MAX),
+
REG_VARIABLE(CFG_VHT_ENABLE_2x2_CAP_FEATURE, WLAN_PARAM_Integer,
struct hdd_config, enable2x2,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -4074,6 +4081,13 @@ struct reg_table_entry g_registry_table[] = {
CFG_ROAM_DENSE_RSSI_THRE_OFFSET_MIN,
CFG_ROAM_DENSE_RSSI_THRE_OFFSET_MAX),
+ REG_VARIABLE(CFG_ROAM_FT_OPEN_ENABLE_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, enable_ftopen,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ROAM_FT_OPEN_ENABLE_DEFAULT,
+ CFG_ROAM_FT_OPEN_ENABLE_MIN,
+ CFG_ROAM_FT_OPEN_ENABLE_MAX),
+
REG_VARIABLE(CFG_IGNORE_PEER_HT_MODE_NAME, WLAN_PARAM_Integer,
struct hdd_config, ignore_peer_ht_opmode,
VAR_FLAGS_OPTIONAL |
@@ -5538,6 +5552,14 @@ struct reg_table_entry g_registry_table[] = {
CFG_DTIM_SELECTION_DIVERSITY_MIN,
CFG_DTIM_SELECTION_DIVERSITY_MAX),
+ REG_VARIABLE(CFG_TX_SCH_DELAY_NAME,
+ WLAN_PARAM_Integer,
+ struct hdd_config, enable_tx_sch_delay,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TX_SCH_DELAY_DEFAULT,
+ CFG_TX_SCH_DELAY_MIN,
+ CFG_TX_SCH_DELAY_MAX),
+
#ifdef WLAN_FEATURE_SAE
REG_VARIABLE(CFG_IS_SAE_ENABLED_NAME, WLAN_PARAM_Integer,
struct hdd_config, is_sae_enabled,
@@ -5546,6 +5568,14 @@ struct reg_table_entry g_registry_table[] = {
CFG_IS_SAE_ENABLED_MIN,
CFG_IS_SAE_ENABLED_MAX),
#endif
+
+ REG_VARIABLE(CFG_ENABLE_RTT_MAC_RANDOMIZATION_NAME,
+ WLAN_PARAM_Integer,
+ struct hdd_config, enable_rtt_mac_randomization,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_RTT_MAC_RANDOMIZATION_DEFAULT,
+ CFG_ENABLE_RTT_MAC_RANDOMIZATION_MIN,
+ CFG_ENABLE_RTT_MAC_RANDOMIZATION_MAX),
};
/**
@@ -7081,6 +7111,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
CFG_ROAM_BG_SCAN_BAD_RSSI_OFFSET_2G_NAME,
pHddCtx->config->roam_bad_rssi_thresh_offset_2g);
hdd_debug("Name = [%s] Value = [%u]",
+ CFG_ROAM_FT_OPEN_ENABLE_NAME,
+ pHddCtx->config->enable_ftopen);
+ hdd_debug("Name = [%s] Value = [%u]",
CFG_MIN_REST_TIME_NAME,
pHddCtx->config->min_rest_time_conc);
hdd_debug("Name = [%s] Value = [%u]",
@@ -7429,6 +7462,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
hdd_debug("Name = [%s] value = [%d]",
CFG_DTIM_SELECTION_DIVERSITY_NAME,
pHddCtx->config->enable_dtim_selection_diversity);
+ hdd_debug("Name = [%s] value = [%d]",
+ CFG_TX_SCH_DELAY_NAME,
+ pHddCtx->config->enable_tx_sch_delay);
hdd_cfg_print_11k_offload_params(pHddCtx);
hdd_debug("Name = [%s] value = [0x%x]",
@@ -9845,6 +9881,7 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
pConfig->disable_high_ht_mcs_2x2;
smeConfig->csrConfig.rx_ldpc_support_for_2g =
pConfig->rx_ldpc_support_for_2g;
+ smeConfig->csrConfig.enable_vht20_mcs9 = pConfig->enable_vht20_mcs9;
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
smeConfig->csrConfig.cc_switch_mode = pConfig->WlanMccToSccSwitchMode;
#endif
@@ -9934,6 +9971,8 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
pHddCtx->config->roam_bg_scan_client_bitmap;
smeConfig->csrConfig.roam_bad_rssi_thresh_offset_2g =
pHddCtx->config->roam_bad_rssi_thresh_offset_2g;
+ smeConfig->csrConfig.enable_ftopen =
+ pHddCtx->config->enable_ftopen;
smeConfig->csrConfig.obss_width_interval =
pHddCtx->config->obss_width_trigger_interval;
smeConfig->csrConfig.obss_active_dwelltime =
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 129ba0c81f40..b4b96209afcc 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -1629,31 +1629,28 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
ret = wlan_hdd_validate_context(hdd_ctx);
if (ret)
- goto out;
+ return ret;
if (cds_is_sub_20_mhz_enabled()) {
hdd_err("ACS not supported in sub 20 MHz ch wd.");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
-
- if (qdf_atomic_inc_return(&hdd_ctx->is_acs_allowed) > 1) {
+ if (qdf_atomic_read(&adapter->sessionCtx.ap.acs_in_progress) > 0) {
hdd_err("ACS rejected as previous req already in progress");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
+ } else {
+ qdf_atomic_set(&adapter->sessionCtx.ap.acs_in_progress, 1);
}
ret = hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
wlan_hdd_cfg80211_do_acs_policy);
if (ret) {
hdd_err("Invalid ATTR");
- qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
goto out;
}
if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
hdd_err("Attr hw_mode failed");
- qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
goto out;
}
hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
@@ -1739,7 +1736,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
sizeof(uint8_t) *
sap_config->acs_cfg.ch_list_count);
if (sap_config->acs_cfg.ch_list == NULL) {
- qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
ret = -ENOMEM;
goto out;
}
@@ -1758,7 +1754,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
sap_config->acs_cfg.ch_list_count);
if (sap_config->acs_cfg.ch_list == NULL) {
hdd_err("ACS config alloc fail");
- qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
ret = -ENOMEM;
goto out;
}
@@ -1771,6 +1766,8 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
}
if (!sap_config->acs_cfg.ch_list_count) {
+ qdf_atomic_set(&adapter->sessionCtx.ap.acs_in_progress, 0);
+ hdd_err("acs config chan count 0");
ret = -EINVAL;
goto out;
}
@@ -1850,6 +1847,8 @@ out:
if (temp_skbuff != NULL)
return cfg80211_vendor_cmd_reply(temp_skbuff);
}
+
+ qdf_atomic_set(&adapter->sessionCtx.ap.acs_in_progress, 0);
wlan_hdd_undo_acs(adapter);
clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
@@ -16789,7 +16788,7 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
qdf_runtime_pm_prevent_suspend(
&pHddCtx->runtime_context.connect);
- hdd_prevent_suspend_timeout(HDD_WAKELOCK_TIMEOUT_CONNECT,
+ hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
WIFI_POWER_EVENT_WAKELOCK_CONNECT);
qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
@@ -17165,6 +17164,7 @@ static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
case WLAN_AKM_SUITE_PSK:
case WLAN_AKM_SUITE_PSK_SHA256:
case WLAN_AKM_SUITE_FT_PSK:
+ case WLAN_AKM_SUITE_DPP_RSN:
hdd_debug("setting key mgmt type to PSK");
pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
break;
@@ -19348,8 +19348,6 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
}
pAdapter->aStaInfo[staId].isDeauthInProgress = true;
- pAdapter->cache_sta_info[staId].reason_code =
- pDelStaParams->reason_code;
hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(mac));
@@ -20967,6 +20965,12 @@ static int __wlan_hdd_cfg80211_update_connect_params(
fils_info->key_nai_length = req->fils_erp_username_len +
sizeof(char) +
req->fils_erp_realm_len;
+ if (fils_info->key_nai_length >
+ FILS_MAX_KEYNAME_NAI_LENGTH) {
+ hdd_err("Key NAI Length %d",
+ fils_info->key_nai_length);
+ return -EINVAL;
+ }
if (req->fils_erp_username_len && req->fils_erp_username) {
buf = fils_info->keyname_nai;
qdf_mem_copy(buf, req->fils_erp_username,
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index a07b47866c13..30259032470b 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -155,6 +155,10 @@ typedef struct {
#define WLAN_AKM_SUITE_SAE 0x000FAC08
#endif
+#ifndef WLAN_AKM_SUITE_DPP_RSN
+#define WLAN_AKM_SUITE_DPP_RSN 0x506F9A02
+#endif
+
#ifdef FEATURE_WLAN_TDLS
#define WLAN_IS_TDLS_SETUP_ACTION(action) \
((SIR_MAC_TDLS_SETUP_REQ <= action) && \
@@ -706,4 +710,14 @@ QDF_STATUS wlan_hdd_send_sta_authorized_event(
hdd_adapter_t *pAdapter,
hdd_context_t *pHddCtx,
const struct qdf_mac_addr *mac_addr);
+
+/**
+ * wlan_hdd_restore_channels() - Restore the channels which were cached
+ * and disabled in wlan_hdd_disable_channels api.
+ * @hdd_ctx: Pointer to the HDD context
+ *
+ * Return: 0 on success, Error code on failure
+ */
+int wlan_hdd_restore_channels(hdd_context_t *hdd_ctx);
+
#endif
diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c
index ace44d369bda..e0a65be053c8 100644
--- a/core/hdd/src/wlan_hdd_debugfs.c
+++ b/core/hdd/src/wlan_hdd_debugfs.c
@@ -49,6 +49,52 @@
#define POWER_DEBUGFS_BUFFER_MAX_LEN 4096
#endif
+#define MAX_DEBUGFS_WAIT_ITERATIONS 20
+#define DEBUGFS_WAIT_SLEEP_TIME 100
+
+static qdf_atomic_t debugfs_thread_count;
+
+void hdd_debugfs_thread_increment(void)
+{
+ qdf_atomic_inc(&debugfs_thread_count);
+}
+
+void hdd_debugfs_thread_decrement(void)
+{
+ qdf_atomic_dec(&debugfs_thread_count);
+}
+
+int hdd_return_debugfs_threads_count(void)
+{
+ return qdf_atomic_read(&debugfs_thread_count);
+}
+
+bool hdd_wait_for_debugfs_threads_completion(void)
+{
+ int count = MAX_DEBUGFS_WAIT_ITERATIONS;
+ int r;
+
+ while (count) {
+
+ r = hdd_return_debugfs_threads_count();
+ if (!r)
+ break;
+
+ if (--count) {
+ hdd_debug("Waiting for %d debugfs threads to exit", r);
+ msleep(DEBUGFS_WAIT_SLEEP_TIME);
+ }
+ }
+
+ /* at least one debugfs thread is executing */
+ if (!count) {
+ hdd_err("Timed-out waiting for debugfs threads");
+ return false;
+ }
+
+ return true;
+}
+
/**
* __wcnss_wowenable_write() - wow_enable debugfs handler
* @file: debugfs file handle
diff --git a/core/hdd/src/wlan_hdd_debugfs_csr.c b/core/hdd/src/wlan_hdd_debugfs_csr.c
index 02e5775d5af7..af1f579c2832 100644
--- a/core/hdd/src/wlan_hdd_debugfs_csr.c
+++ b/core/hdd/src/wlan_hdd_debugfs_csr.c
@@ -33,6 +33,7 @@
#include "qwlan_version.h"
#include "wmi_unified_param.h"
#include "wlan_hdd_request_manager.h"
+#include "wlan_hdd_debugfs.h"
ssize_t
wlan_hdd_current_time_info_debugfs(uint8_t *buf, ssize_t buf_avail_len)
@@ -132,6 +133,11 @@ __wlan_hdd_read_debugfs_csr(struct file *file, char __user *buf,
if (ret)
return 0;
+ if (!test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
+ hdd_err("Interface is not enabled");
+ return 0;
+ }
+
if (*pos == 0) {
info->length =
wlan_hdd_debugfs_update_csr(hdd_ctx, adapter,
@@ -183,6 +189,8 @@ static int __wlan_hdd_open_debugfs_csr(struct inode *inode,
struct wlan_hdd_debugfs_buffer_info *info;
struct hdd_debugfs_file_info *csr;
hdd_adapter_t *adapter = NULL;
+ hdd_context_t *hdd_ctx;
+ int ret;
ENTER();
@@ -199,6 +207,16 @@ static int __wlan_hdd_open_debugfs_csr(struct inode *inode,
return -EINVAL;
}
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (ret)
+ return -EINVAL;
+
+ if (!test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
+ hdd_err("Interface is not enabled");
+ return -EINVAL;
+ }
+
info = qdf_mem_malloc(sizeof(*info));
if (!info) {
hdd_err("Not enough memory for file private data");
@@ -222,7 +240,6 @@ static int __wlan_hdd_open_debugfs_csr(struct inode *inode,
return 0;
}
-
/**
* wlan_hdd_open_debugfs_csr() - SSR wrapper function to allocate memory for
* private data on file open
@@ -237,7 +254,12 @@ static int wlan_hdd_open_debugfs_csr(struct inode *inode,
int ret;
cds_ssr_protect(__func__);
+
+ hdd_debugfs_thread_increment();
ret = __wlan_hdd_open_debugfs_csr(inode, file);
+ if (ret)
+ hdd_debugfs_thread_decrement();
+
cds_ssr_unprotect(__func__);
return ret;
@@ -284,6 +306,7 @@ static int wlan_hdd_release_debugfs_csr(struct inode *inode, struct file *file)
cds_ssr_protect(__func__);
ret = __wlan_hdd_release_debugfs_csr(inode, file);
+ hdd_debugfs_thread_decrement();
cds_ssr_unprotect(__func__);
return ret;
@@ -316,7 +339,8 @@ void wlan_hdd_debugfs_csr_init(hdd_adapter_t *adapter)
adapter->debugfs_phy,
csr, &fops_csr_debugfs);
if (!csr->entry)
- hdd_err("Failed to create connect_info debugfs file");
+ hdd_err("Failed to create debugfs file: %s",
+ csr->name);
}
csr = &adapter->csr_file[HDD_DEBUFS_FILE_ID_OFFLOAD_INFO];
@@ -328,7 +352,8 @@ void wlan_hdd_debugfs_csr_init(hdd_adapter_t *adapter)
adapter->debugfs_phy,
csr, &fops_csr_debugfs);
if (!csr->entry)
- hdd_err("Failed to create generic_info debugfs file");
+ hdd_err("Failed to create debugfs file: %s",
+ csr->name);
}
csr = &adapter->csr_file[HDD_DEBUFS_FILE_ID_ROAM_SCAN_STATS_INFO];
@@ -340,7 +365,8 @@ void wlan_hdd_debugfs_csr_init(hdd_adapter_t *adapter)
adapter->debugfs_phy,
csr, &fops_csr_debugfs);
if (!csr->entry)
- hdd_err("Failed to create generic_info debugfs file");
+ hdd_err("Failed to create debugfs file: %s",
+ csr->name);
}
}
diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c
index a73f3eacdb84..893ce2e4050f 100644
--- a/core/hdd/src/wlan_hdd_driver_ops.c
+++ b/core/hdd/src/wlan_hdd_driver_ops.c
@@ -48,6 +48,7 @@
#include "wlan_hdd_driver_ops.h"
#include "wlan_hdd_scan.h"
#include "wlan_hdd_ipa.h"
+#include "wlan_hdd_debugfs.h"
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -476,6 +477,9 @@ static void wlan_hdd_remove(struct device *dev)
if (!cds_wait_for_external_threads_completion(__func__))
hdd_warn("External threads are still active attempting driver unload anyway");
+ if (!hdd_wait_for_debugfs_threads_completion())
+ hdd_warn("Debugfs threads are still active attempting driver unload anyway");
+
hdd_pld_driver_unloading(dev);
if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
@@ -575,6 +579,9 @@ static void wlan_hdd_shutdown(void)
if (!cds_wait_for_external_threads_completion(__func__))
hdd_err("Host is not ready for SSR, attempting anyway");
+ if (!hdd_wait_for_debugfs_threads_completion())
+ hdd_err("Debufs threads are still pending, attempting SSR anyway");
+
if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
hif_disable_isr(hif_ctx);
hdd_wlan_shutdown();
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index 1a879ff4eb68..d3f32319367d 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -203,7 +203,6 @@ int hdd_sap_context_init(hdd_context_t *hdd_ctx)
qdf_spinlock_create(&hdd_ctx->sap_update_info_lock);
qdf_atomic_init(&hdd_ctx->dfs_radar_found);
- qdf_atomic_init(&hdd_ctx->is_acs_allowed);
return 0;
}
@@ -1605,9 +1604,10 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
struct ch_params_s sap_ch_param = {0};
eCsrPhyMode phy_mode;
bool legacy_phymode;
- tSap_StationDisassocCompleteEvent *disconnect_event;
+ tSap_StationDisassocCompleteEvent *disassoc_comp;
hdd_station_info_t *stainfo;
cds_context_type *cds_ctx;
+ hdd_adapter_t *sta_adapter;
dev = (struct net_device *)usrDataForCallback;
if (!dev) {
@@ -1842,6 +1842,12 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
we_custom_event_generic = we_custom_start_event;
cds_dump_concurrency_info();
+ sta_adapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE);
+ if (sta_adapter != NULL) {
+ hdd_debug("check for SAP restart");
+ cds_check_concurrent_intf_and_restart_sap(sta_adapter);
+ }
+
if (cds_is_hw_mode_change_after_vdev_up()) {
hdd_debug("check for possible hw mode change");
status = cds_set_hw_mode_on_channel_switch(
@@ -2206,34 +2212,21 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
hdd_green_ap_add_sta(pHddCtx);
break;
- case eSAP_STA_LOSTLINK_DETECTED:
- disconnect_event =
- &pSapEvent->sapevt.sapStationDisassocCompleteEvent;
-
- wlan_hdd_get_peer_rssi(pHostapdAdapter,
- &disconnect_event->staMac,
- HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER);
-
- /*
- * For user initiated disconnect, reason_code is updated while
- * issuing the disconnect from HDD.
- */
- if (disconnect_event->reason != eSAP_USR_INITATED_DISASSOC) {
- stainfo = hdd_get_stainfo(
- pHostapdAdapter->cache_sta_info,
- disconnect_event->staMac);
- if (stainfo)
- stainfo->reason_code =
- disconnect_event->reason_code;
- }
- return QDF_STATUS_SUCCESS;
-
case eSAP_STA_DISASSOC_EVENT:
+ disassoc_comp =
+ &pSapEvent->sapevt.sapStationDisassocCompleteEvent;
memcpy(wrqu.addr.sa_data,
- &pSapEvent->sapevt.sapStationDisassocCompleteEvent.
- staMac, QDF_MAC_ADDR_SIZE);
+ &disassoc_comp->staMac, QDF_MAC_ADDR_SIZE);
hdd_notice(" disassociated " MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(wrqu.addr.sa_data));
+ stainfo = hdd_get_stainfo(pHostapdAdapter->cache_sta_info,
+ disassoc_comp->staMac);
+ if (stainfo) {
+ stainfo->rssi = disassoc_comp->rssi;
+ stainfo->tx_rate = disassoc_comp->tx_rate;
+ stainfo->rx_rate = disassoc_comp->rx_rate;
+ stainfo->reason_code = disassoc_comp->reason_code;
+ }
qdf_status = qdf_event_set(&pHostapdState->qdf_sta_disassoc_event);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
@@ -2577,7 +2570,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
/* send vendor event to hostapd only for hostapd based acs*/
if (!pHddCtx->config->force_sap_acs)
wlan_hdd_cfg80211_acs_ch_select_evt(pHostapdAdapter);
- qdf_atomic_set(&pHddCtx->is_acs_allowed, 0);
+ qdf_atomic_set(
+ &pHostapdAdapter->sessionCtx.ap.acs_in_progress, 0);
return QDF_STATUS_SUCCESS;
case eSAP_ECSA_CHANGE_CHAN_IND:
hdd_debug("Channel change indication from peer for channel %d",
@@ -4519,7 +4513,6 @@ static __iw_softap_disassoc_sta(struct net_device *dev,
uint8_t *peerMacAddr;
int ret;
struct tagCsrDelStaParams del_sta_params;
- hdd_station_info_t *stainfo;
ENTER_DEV(dev);
@@ -4546,11 +4539,6 @@ static __iw_softap_disassoc_sta(struct net_device *dev,
&del_sta_params);
hdd_softap_sta_disassoc(pHostapdAdapter, &del_sta_params);
- stainfo = hdd_get_stainfo(pHostapdAdapter->cache_sta_info,
- del_sta_params.peerMacAddr);
- if (stainfo)
- stainfo->reason_code = del_sta_params.reason_code;
-
EXIT();
return 0;
}
@@ -5290,7 +5278,7 @@ static int __iw_get_ap_freq(struct net_device *dev,
return -EIO;
}
status = hdd_wlan_get_freq(channel, &freq);
- if (true == status) {
+ if (0 == status) {
/* Set Exponent parameter as 6 (MHZ) in struct
* iw_freq * iwlist & iwconfig command
* shows frequency into proper
@@ -5302,7 +5290,7 @@ static int __iw_get_ap_freq(struct net_device *dev,
} else {
channel = pHddApCtx->operatingChannel;
status = hdd_wlan_get_freq(channel, &freq);
- if (true == status) {
+ if (0 == status) {
/* Set Exponent parameter as 6 (MHZ) in struct iw_freq
* iwlist & iwconfig command shows frequency into proper
* format (2.412 GHz instead of 246.2 MHz)
@@ -6522,7 +6510,7 @@ QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter, bool reinit)
ENTER();
hdd_info("SSR in progress: %d", reinit);
-
+ qdf_atomic_init(&pAdapter->sessionCtx.ap.acs_in_progress);
if (reinit)
sapContext = pAdapter->sessionCtx.ap.sapContext;
else {
@@ -7918,6 +7906,173 @@ static void hdd_check_and_disconnect_sta_on_invalid_channel(
}
/**
+ * wlan_hdd_get_wiphy_channel() - Get wiphy channel
+ * @wiphy: Pointer to wiphy structure
+ * @freq: Frequency of the channel for which the wiphy hw value is required
+ *
+ * Return: wiphy channel for valid frequency else return NULL
+ */
+static struct ieee80211_channel *wlan_hdd_get_wiphy_channel(
+ struct wiphy *wiphy,
+ uint32_t freq)
+{
+ uint32_t band_num, channel_num;
+ struct ieee80211_channel *wiphy_channel = NULL;
+
+ for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) {
+ for (channel_num = 0; channel_num <
+ wiphy->bands[band_num]->n_channels;
+ channel_num++) {
+ wiphy_channel = &(wiphy->bands[band_num]->
+ channels[channel_num]);
+ if (wiphy_channel->center_freq == freq)
+ return wiphy_channel;
+ }
+ }
+ return wiphy_channel;
+}
+
+int wlan_hdd_restore_channels(hdd_context_t *hdd_ctx)
+{
+ struct hdd_cache_channels *cache_chann;
+ struct wiphy *wiphy;
+ int freq, status, rf_channel;
+ int i;
+ struct ieee80211_channel *wiphy_channel = NULL;
+
+ ENTER();
+
+ if (!hdd_ctx) {
+ hdd_err("HDD Context is NULL");
+ return -EINVAL;
+ }
+
+ wiphy = hdd_ctx->wiphy;
+ if (!wiphy) {
+ hdd_err("Wiphy is NULL");
+ return -EINVAL;
+ }
+
+ qdf_mutex_acquire(&hdd_ctx->cache_channel_lock);
+
+ cache_chann = hdd_ctx->original_channels;
+
+ if (!cache_chann || !cache_chann->num_channels) {
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+ hdd_err("channel list is NULL or num channels are zero");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cache_chann->num_channels; i++) {
+ status = hdd_wlan_get_freq(
+ cache_chann->channel_info[i].channel_num,
+ &freq);
+ if (status)
+ continue;
+
+ wiphy_channel = wlan_hdd_get_wiphy_channel(wiphy, freq);
+ if (!wiphy_channel)
+ continue;
+ rf_channel = wiphy_channel->hw_value;
+ /*
+ * Restore the orginal states of the channels
+ * only if we have cached non zero values
+ */
+ if (cache_chann->channel_info[i].reg_status)
+ cds_set_channel_state(rf_channel,
+ cache_chann->
+ channel_info[i].reg_status);
+
+ if (cache_chann->channel_info[i].wiphy_status && wiphy_channel)
+ wiphy_channel->flags =
+ cache_chann->channel_info[i].wiphy_status;
+ }
+
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+
+ status = sme_update_channel_list(hdd_ctx->hHal);
+ if (status)
+ hdd_err("Can't Restore channel list");
+ EXIT();
+
+ return 0;
+}
+
+/**
+ * wlan_hdd_disable_channels() - Cache the channels
+ * and current state of the channels from the channel list
+ * received in the command and disable the channels on the
+ * wiphy and reg table.
+ * @hdd_ctx: Pointer to hdd context
+ *
+ * Return: 0 on success, Error code on failure
+ */
+static int wlan_hdd_disable_channels(hdd_context_t *hdd_ctx)
+{
+ struct hdd_cache_channels *cache_chann;
+ struct wiphy *wiphy;
+ int freq, status, rf_channel;
+ int i;
+ struct ieee80211_channel *wiphy_channel = NULL;
+
+ ENTER();
+
+ if (!hdd_ctx) {
+ hdd_err("HDD Context is NULL");
+ return -EINVAL;
+ }
+
+ wiphy = hdd_ctx->wiphy;
+ if (!wiphy) {
+ hdd_err("Wiphy is NULL");
+ return -EINVAL;
+ }
+
+ qdf_mutex_acquire(&hdd_ctx->cache_channel_lock);
+ cache_chann = hdd_ctx->original_channels;
+
+ if (!cache_chann || !cache_chann->num_channels) {
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+ hdd_err("channel list is NULL or num channels are zero");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cache_chann->num_channels; i++) {
+ status = hdd_wlan_get_freq(
+ cache_chann->channel_info[i].channel_num,
+ &freq);
+ if (status)
+ continue;
+ wiphy_channel = wlan_hdd_get_wiphy_channel(wiphy, freq);
+ if (!wiphy_channel)
+ continue;
+ rf_channel = wiphy_channel->hw_value;
+ /*
+ * Cache the current states of
+ * the channels
+ */
+ cache_chann->channel_info[i].reg_status =
+ cds_get_channel_state(
+ rf_channel);
+ cache_chann->channel_info[i].wiphy_status =
+ wiphy_channel->flags;
+ hdd_debug("Disable channel %d reg_stat %d wiphy_stat 0x%x",
+ cache_chann->channel_info[i].channel_num,
+ cache_chann->channel_info[i].reg_status,
+ wiphy_channel->flags);
+
+ cds_set_channel_state(rf_channel, CHANNEL_STATE_DISABLE);
+ wiphy_channel->flags |= IEEE80211_CHAN_DISABLED;
+ }
+
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+ status = sme_update_channel_list(hdd_ctx->hHal);
+
+ EXIT();
+ return status;
+}
+
+/**
* wlan_hdd_cfg80211_start_bss() - start bss
* @pHostapdAdapter: Pointer to hostapd adapter
* @params: Pointer to start bss beacon parameters
@@ -8029,6 +8184,17 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
pHddCtx);
}
+ if (pHostapdAdapter->device_mode == QDF_SAP_MODE) {
+ /*
+ * Disable the channels received in command
+ * SET_DISABLE_CHANNEL_LIST
+ */
+ status = wlan_hdd_disable_channels(pHddCtx);
+ if (!QDF_IS_STATUS_SUCCESS(status))
+ hdd_err("Disable channel list fail");
+ hdd_check_and_disconnect_sta_on_invalid_channel(pHddCtx);
+ }
+
pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
@@ -8635,6 +8801,8 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
return 0;
error:
+ if (pHostapdAdapter->device_mode == QDF_SAP_MODE)
+ wlan_hdd_restore_channels(pHddCtx);
/* Revert the indoor to passive marking if START BSS fails */
if (iniConfig->disable_indoor_channel) {
hdd_update_indoor_channel(pHddCtx, false);
@@ -8643,6 +8811,8 @@ error:
if (sme_config)
qdf_mem_free(sme_config);
clear_bit(SOFTAP_INIT_DONE, &pHostapdAdapter->event_flags);
+ qdf_atomic_set(
+ &pHostapdAdapter->sessionCtx.ap.acs_in_progress, 0);
wlan_hdd_undo_acs(pHostapdAdapter);
ret_status:
@@ -8779,6 +8949,8 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
pConfig = &pAdapter->sessionCtx.ap.sapConfig;
pConfig->acs_cfg.acs_mode = false;
+ qdf_atomic_set(
+ &pAdapter->sessionCtx.ap.acs_in_progress, 0);
wlan_hdd_undo_acs(pAdapter);
qdf_mem_zero(&pConfig->acs_cfg, sizeof(struct sap_acs_cfg));
@@ -9092,13 +9264,14 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
}
if (cds_is_sap_mandatory_chan_list_enabled()) {
- if (!cds_get_sap_mandatory_chan_list_len())
- cds_init_sap_mandatory_2g_chan();
-
if (CDS_IS_CHANNEL_5GHZ(channel)) {
hdd_debug("channel %hu, sap mandatory chan list enabled",
channel);
+ if (!cds_get_sap_mandatory_chan_list_len())
+ cds_init_sap_mandatory_2g_chan();
cds_add_sap_mandatory_chan(channel);
+ } else {
+ cds_init_sap_mandatory_2g_chan();
}
}
diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h
index ebc6a7763114..6bff97de826e 100644
--- a/core/hdd/src/wlan_hdd_hostapd.h
+++ b/core/hdd/src/wlan_hdd_hostapd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -137,9 +137,5 @@ bool hdd_is_peer_associated(hdd_adapter_t *adapter,
struct qdf_mac_addr *mac_addr);
void hdd_sap_indicate_disconnect_for_sta(hdd_adapter_t *adapter);
void hdd_sap_destroy_events(hdd_adapter_t *adapter);
-void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap,
- tDot11fIEHTCaps *roam_ht_cap);
-void hdd_copy_vht_caps(struct ieee80211_vht_cap *hdd_vht_cap,
- tDot11fIEVHTCaps *roam_vht_cap);
#endif /* end #if !defined(WLAN_HDD_HOSTAPD_H) */
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index daf7cd8f4fe5..3cbd92566d33 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -566,8 +566,9 @@ static QDF_STATUS
hdd_parse_get_ibss_peer_info(uint8_t *pValue, struct qdf_mac_addr *pPeerMacAddr)
{
uint8_t *inPtr = pValue;
+ size_t in_ptr_len = strlen(pValue);
- inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
+ inPtr = strnchr(pValue, in_ptr_len, SPACE_ASCII_VALUE);
if (NULL == inPtr)
return QDF_STATUS_E_FAILURE;
@@ -580,10 +581,14 @@ hdd_parse_get_ibss_peer_info(uint8_t *pValue, struct qdf_mac_addr *pPeerMacAddr)
if ('\0' == *inPtr)
return QDF_STATUS_E_FAILURE;
+ in_ptr_len -= (inPtr - pValue);
+ if (in_ptr_len < 17)
+ return QDF_STATUS_E_FAILURE;
+
if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' ||
- inPtr[11] != ':' || inPtr[14] != ':') {
+ inPtr[11] != ':' || inPtr[14] != ':')
return QDF_STATUS_E_FAILURE;
- }
+
sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x",
(unsigned int *)&pPeerMacAddr->bytes[0],
(unsigned int *)&pPeerMacAddr->bytes[1],
@@ -5156,9 +5161,6 @@ static int drv_cmd_get_ibss_peer_info_all(hdd_adapter_t *adapter,
}
hdd_debug("%s", &extra[numOfBytestoPrint]);
}
-
- /* Free temporary buffer */
- qdf_mem_free(extra);
} else {
/* Command failed, log error */
hdd_err("GETIBSSPEERINFOALL command failed with status code %d",
@@ -6858,6 +6860,310 @@ static int drv_cmd_set_channel_switch(hdd_adapter_t *adapter,
return 0;
}
+void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx)
+{
+ ENTER();
+
+ if (!hdd_ctx->original_channels)
+ return;
+
+ qdf_mutex_acquire(&hdd_ctx->cache_channel_lock);
+ hdd_ctx->original_channels->num_channels = 0;
+ qdf_mem_free(hdd_ctx->original_channels->channel_info);
+ hdd_ctx->original_channels->channel_info = NULL;
+ qdf_mem_free(hdd_ctx->original_channels);
+ hdd_ctx->original_channels = NULL;
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+
+ EXIT();
+}
+
+/**
+ * hdd_alloc_chan_cache() - Allocate the memory to cache the channel
+ * info for the channels received in command SET_DISABLE_CHANNEL_LIST
+ * @hdd_ctx: Pointer to HDD context
+ * @num_chan: Number of channels for which memory needs to
+ * be allocated
+ *
+ * Return: 0 on success and error code on failure
+ */
+static int hdd_alloc_chan_cache(hdd_context_t *hdd_ctx, int num_chan)
+{
+ hdd_ctx->original_channels =
+ qdf_mem_malloc(sizeof(struct hdd_cache_channels));
+ if (!hdd_ctx->original_channels) {
+ hdd_err("QDF_MALLOC_ERR");
+ return -ENOMEM;
+ }
+ hdd_ctx->original_channels->num_channels = num_chan;
+ hdd_ctx->original_channels->channel_info =
+ qdf_mem_malloc(num_chan *
+ sizeof(struct hdd_cache_channel_info));
+ if (!hdd_ctx->original_channels->channel_info) {
+ hdd_err("QDF_MALLOC_ERR");
+ hdd_ctx->original_channels->num_channels = 0;
+ qdf_mem_free(hdd_ctx->original_channels);
+ hdd_ctx->original_channels = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * hdd_parse_disable_chan_cmd() - Parse the channel list received
+ * in command.
+ * @adapter: pointer to hdd adapter
+ * @ptr: Pointer to the command string
+ *
+ * This function parses the channel list received in the command.
+ * command should be a string having format
+ * SET_DISABLE_CHANNEL_LIST <num of channels>
+ * <channels separated by spaces>.
+ * If the command comes multiple times than this function will compare
+ * the channels received in the command with the channles cached in the
+ * first command, if the channel list matches with the cached channles,
+ * it returns success otherwise returns failure.
+ *
+ * Return: 0 on success, Error code on failure
+ */
+
+static int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, uint8_t *ptr)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ uint8_t *param;
+ int j, i, temp_int, ret = 0, num_channels;
+ int parsed_channels[MAX_CHANNEL];
+ bool is_command_repeated = false;
+
+ if (NULL == hdd_ctx) {
+ hdd_err("HDD Context is NULL");
+ return -EINVAL;
+ }
+
+ param = strnchr(ptr, strlen(ptr), ' ');
+ /*no argument after the command*/
+ if (NULL == param)
+ return -EINVAL;
+
+ /*no space after the command*/
+ else if (SPACE_ASCII_VALUE != *param)
+ return -EINVAL;
+
+ param++;
+
+ /*removing empty spaces*/
+ while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
+ param++;
+
+ /*no argument followed by spaces*/
+ if ('\0' == *param)
+ return -EINVAL;
+
+ /*getting the first argument ie the number of channels*/
+ if (sscanf(param, "%d ", &temp_int) != 1) {
+ hdd_err("Cannot get number of channels from input");
+ return -EINVAL;
+ }
+
+ if (temp_int < 0 || temp_int > MAX_CHANNEL) {
+ hdd_err("Invalid Number of channel received");
+ return -EINVAL;
+ }
+
+ hdd_debug("Number of channel to disable are: %d", temp_int);
+
+ if (!temp_int) {
+ if (!wlan_hdd_restore_channels(hdd_ctx)) {
+ /*
+ * Free the cache channels only when the command is
+ * received with num channels as 0
+ */
+ wlan_hdd_free_cache_channels(hdd_ctx);
+ }
+ return 0;
+ }
+
+ qdf_mutex_acquire(&hdd_ctx->cache_channel_lock);
+
+ if (!hdd_ctx->original_channels) {
+ if (hdd_alloc_chan_cache(hdd_ctx, temp_int)) {
+ ret = -ENOMEM;
+ goto mem_alloc_failed;
+ }
+ } else if (hdd_ctx->original_channels->num_channels != temp_int) {
+ hdd_err("Invalid Number of channels");
+ ret = -EINVAL;
+ is_command_repeated = true;
+ goto parse_failed;
+ } else {
+ is_command_repeated = true;
+ }
+ num_channels = temp_int;
+ for (j = 0; j < num_channels; j++) {
+ /*
+ * param pointing to the beginning of first space
+ * after number of channels
+ */
+ param = strpbrk(param, " ");
+ /*no channel list after the number of channels argument*/
+ if (NULL == param) {
+ hdd_err("Invalid No of channel provided in the list");
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+
+ param++;
+
+ /*removing empty space*/
+ while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
+ param++;
+
+ if ('\0' == *param) {
+ hdd_err("No channel is provided in the list");
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+
+ if (sscanf(param, "%d ", &temp_int) != 1) {
+ hdd_err("Cannot read channel number");
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+
+ if (!IS_CHANNEL_VALID(temp_int)) {
+ hdd_err("Invalid channel number received");
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+
+ hdd_debug("channel[%d] = %d", j, temp_int);
+ parsed_channels[j] = temp_int;
+ }
+
+ /*extra arguments check*/
+ param = strpbrk(param, " ");
+ if (NULL != param) {
+ while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
+ param++;
+
+ if ('\0' != *param) {
+ hdd_err("Invalid argument received");
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+ }
+
+ /*
+ * If command is received first time, cache the channels to
+ * be disabled else compare the channels received in the
+ * command with the cached channels, if channel list matches
+ * return success otherewise return failure.
+ */
+ if (!is_command_repeated)
+ for (j = 0; j < num_channels; j++)
+ hdd_ctx->original_channels->
+ channel_info[j].channel_num =
+ parsed_channels[j];
+ else {
+ for (i = 0; i < num_channels; i++) {
+ for (j = 0; j < num_channels; j++)
+ if (hdd_ctx->original_channels->
+ channel_info[i].channel_num ==
+ parsed_channels[j])
+ break;
+ if (j == num_channels) {
+ ret = -EINVAL;
+ goto parse_failed;
+ }
+ }
+ ret = 0;
+ }
+mem_alloc_failed:
+
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+ EXIT();
+
+ return ret;
+
+parse_failed:
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+ if (!is_command_repeated)
+ wlan_hdd_free_cache_channels(hdd_ctx);
+ EXIT();
+
+ return ret;
+}
+
+static int drv_cmd_set_disable_chan_list(hdd_adapter_t *adapter,
+ hdd_context_t *hdd_ctx,
+ uint8_t *command,
+ uint8_t command_len,
+ hdd_priv_data_t *priv_data)
+{
+ return hdd_parse_disable_chan_cmd(adapter, command);
+}
+
+/**
+ * hdd_get_disable_ch_list() - get disable channel list
+ * @hdd_ctx: hdd context
+ * @buf: buffer to hold disable channel list
+ * @buf_len: buffer length
+ *
+ * Return: length of data copied to buf
+ */
+static int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, uint8_t *buf,
+ uint32_t buf_len)
+{
+ struct hdd_cache_channel_info *ch_list;
+ unsigned char i, num_ch;
+ int len = 0;
+
+ qdf_mutex_acquire(&hdd_ctx->cache_channel_lock);
+ if (hdd_ctx->original_channels &&
+ hdd_ctx->original_channels->num_channels &&
+ hdd_ctx->original_channels->channel_info) {
+ num_ch = hdd_ctx->original_channels->num_channels;
+
+ len = scnprintf(buf, buf_len, "%s %hhu",
+ "GET_DISABLE_CHANNEL_LIST", num_ch);
+ ch_list = hdd_ctx->original_channels->channel_info;
+ for (i = 0; (i < num_ch) && len <= buf_len; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ " %d", ch_list[i].channel_num);
+ }
+ }
+ qdf_mutex_release(&hdd_ctx->cache_channel_lock);
+
+ return len;
+}
+
+static int drv_cmd_get_disable_chan_list(hdd_adapter_t *adapter,
+ hdd_context_t *hdd_ctx,
+ uint8_t *command,
+ uint8_t command_len,
+ hdd_priv_data_t *priv_data)
+{
+ char extra[512] = {0};
+ int max_len, copied_length;
+
+ hdd_debug("Received Command to get disable Channels list");
+
+ max_len = QDF_MIN(priv_data->total_len, sizeof(extra));
+ copied_length = hdd_get_disable_ch_list(hdd_ctx, extra, max_len);
+ if (copied_length == 0) {
+ hdd_err("disable channel list is not yet programmed");
+ return -EINVAL;
+ }
+
+ if (copy_to_user(priv_data->buf, &extra, copied_length + 1)) {
+ hdd_err("failed to copy data to user buffer");
+ return -EFAULT;
+ }
+
+ hdd_debug("data:%s", extra);
+ return 0;
+}
+
/*
* The following table contains all supported WLAN HDD
* IOCTL driver commands and the handler for each of them.
@@ -6968,6 +7274,8 @@ static const struct hdd_drv_cmd hdd_drv_cmds[] = {
{"CHANNEL_SWITCH", drv_cmd_set_channel_switch, true},
{"SETANTENNAMODE", drv_cmd_set_antenna_mode, true},
{"GETANTENNAMODE", drv_cmd_get_antenna_mode, false},
+ {"SET_DISABLE_CHANNEL_LIST", drv_cmd_set_disable_chan_list, true},
+ {"GET_DISABLE_CHANNEL_LIST", drv_cmd_get_disable_chan_list, false},
{"STOP", drv_cmd_dummy, false},
};
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 2e3420219b88..00022a92d97c 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -35,7 +35,12 @@
#ifdef IPA_OFFLOAD
/* Include Files */
+#ifdef CONFIG_IPA_WDI_UNIFIED_API
+#include <linux/ipa_wdi3.h>
+#else
#include <linux/ipa.h>
+#endif
+
#include <wlan_hdd_includes.h>
#include <wlan_hdd_ipa.h>
@@ -92,6 +97,8 @@
#define IPA_WLAN_RX_SOFTIRQ_THRESH 16
+#define HDD_IPA_MAX_BANDWIDTH 800
+
enum hdd_ipa_uc_op_code {
HDD_IPA_UC_OPCODE_TX_SUSPEND = 0,
HDD_IPA_UC_OPCODE_TX_RESUME = 1,
@@ -502,6 +509,9 @@ struct hdd_ipa_priv {
struct completion ipa_uc_set_quota_comp;
#endif
struct completion ipa_resource_comp;
+
+ uint32_t wdi_version;
+ bool is_smmu_enabled; /* IPA caps returned from ipa_wdi_init */
};
#define HDD_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header)
@@ -623,22 +633,6 @@ struct hdd_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
};
#endif
-/* For Tx pipes, use 802.3 Header format */
-static struct hdd_ipa_tx_hdr ipa_tx_hdr = {
- {
- {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF},
- {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF},
- 0x00 /* length can be zero */
- },
- {
- /* LLC SNAP header 8 bytes */
- 0xaa, 0xaa,
- {0x03, 0x00, 0x00, 0x00},
- 0x0008 /* type value(2 bytes) ,filled by wlan */
- /* 0x0800 - IPV4, 0x86dd - IPV6 */
- }
-};
-
#ifdef FEATURE_METERING
#define IPA_UC_SHARING_STATES_WAIT_TIME 500
#define IPA_UC_SET_QUOTA_WAIT_TIME 500
@@ -658,30 +652,8 @@ static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type);
static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context);
static void hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa,
bool is_loading);
-
-#if ((defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)) || \
- defined(IPA_CLIENT_IS_MHI_CONS))
-/**
- * hdd_ipa_uc_get_db_paddr() - Get Doorbell physical address
- * @db_paddr: Doorbell physical address should be given bu IPA
- * @client: IPA client type
- *
- * Query doorbell physical address from IPA
- * IPA will give physical address for TX COMP and RX READY
- *
- * Return: None
- */
-static void hdd_ipa_uc_get_db_paddr(qdf_dma_addr_t *db_paddr,
- enum ipa_client_type client)
-{
- struct ipa_wdi_db_params dbpa;
-
- dbpa.client = client;
- ipa_uc_wdi_get_dbpa(&dbpa);
- *db_paddr = dbpa.uc_door_bell_pa;
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "PROD DB get dbpa 0x%x",
- (unsigned int)dbpa.uc_door_bell_pa);
-}
+static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa);
+static int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa);
/**
* hdd_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
@@ -775,58 +747,6 @@ static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
}
/**
- * hdd_ipa_uc_register_uc_ready() - Register UC ready callback function to IPA
- * @hdd_ipa: HDD IPA local context
- *
- * Register IPA UC ready callback function to IPA kernel driver
- * Even IPA UC loaded later than WLAN kernel driver, WLAN kernel driver will
- * open WDI pipe after WLAN driver loading finished
- *
- * Return: 0 Success
- * -EPERM Registration fail
- */
-static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
-{
- struct ipa_wdi_uc_ready_params uc_ready_param;
- int ret = 0;
-
- hdd_ipa->uc_loaded = false;
- uc_ready_param.priv = (void *)hdd_ipa;
- uc_ready_param.notify = hdd_ipa_uc_loaded_uc_cb;
- if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "UC Ready CB register fail");
- return -EPERM;
- }
- if (true == uc_ready_param.is_uC_ready) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
- hdd_ipa->uc_loaded = true;
- } else {
- ret = hdd_ipa_uc_send_wdi_control_msg(false);
- }
-
- return ret;
-}
-#else
-static void hdd_ipa_uc_get_db_paddr(qdf_dma_addr_t *db_paddr,
- enum ipa_client_type client)
-{
- /* Do nothing */
-}
-
-static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
-{
- hdd_ipa->uc_loaded = true;
- return 0;
-}
-
-static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
-{
- return 0;
-}
-#endif
-
-/**
* hdd_ipa_is_enabled() - Is IPA enabled?
* @hdd_ctx: Global HDD context
*
@@ -947,6 +867,1790 @@ bool hdd_ipa_is_fw_wdi_actived(hdd_context_t *hdd_ctx)
return (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe);
}
+#ifdef FEATURE_METERING
+/**
+ * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
+ * IPA calls to get WLAN stats or set quota limit.
+ * @priv: pointer to private data registered with IPA (we register a
+ *» pointer to the global IPA context)
+ * @evt: the IPA event which triggered the callback
+ * @data: data associated with the event
+ *
+ * Return: None
+ */
+static void __hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
+ void *data)
+{
+ struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+ hdd_adapter_t *adapter = NULL;
+ struct ipa_get_wdi_sap_stats *wdi_sap_stats;
+ struct ipa_set_wifi_quota *ipa_set_quota;
+ int ret = 0;
+
+ if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
+ return;
+
+ adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event=%d", evt);
+
+ switch (evt) {
+ case IPA_GET_WDI_SAP_STATS:
+ /* fill-up ipa_get_wdi_sap_stats structure after getting
+ * ipa_uc_fw_stats from FW
+ */
+ wdi_sap_stats = data;
+
+ if (!adapter) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA uC share stats failed - no adapter");
+ wdi_sap_stats->stats_valid = 0;
+ return;
+ }
+
+ INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
+ hdd_ipa_uc_sharing_stats_request(adapter,
+ wdi_sap_stats->reset_stats);
+ ret = wait_for_completion_timeout(
+ &hdd_ipa->ipa_uc_sharing_stats_comp,
+ msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
+ if (!ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA uC share stats request timed out");
+ wdi_sap_stats->stats_valid = 0;
+ } else {
+ wdi_sap_stats->stats_valid = 1;
+
+ wdi_sap_stats->ipv4_rx_packets =
+ hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
+ wdi_sap_stats->ipv4_rx_bytes =
+ hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
+ wdi_sap_stats->ipv6_rx_packets =
+ hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
+ wdi_sap_stats->ipv6_rx_bytes =
+ hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
+ wdi_sap_stats->ipv4_tx_packets =
+ hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
+ wdi_sap_stats->ipv4_tx_bytes =
+ hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
+ wdi_sap_stats->ipv6_tx_packets =
+ hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
+ wdi_sap_stats->ipv6_tx_bytes =
+ hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
+ HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
+ "IPA_GET_WDI_SAP_STATS",
+ wdi_sap_stats->stats_valid,
+ wdi_sap_stats->ipv4_rx_packets,
+ wdi_sap_stats->ipv4_rx_bytes,
+ wdi_sap_stats->ipv6_rx_packets,
+ wdi_sap_stats->ipv6_rx_bytes,
+ wdi_sap_stats->ipv4_tx_packets,
+ wdi_sap_stats->ipv4_tx_bytes,
+ wdi_sap_stats->ipv6_tx_packets,
+ wdi_sap_stats->ipv6_tx_bytes);
+ }
+ break;
+ case IPA_SET_WIFI_QUOTA:
+ /* Get ipa_set_wifi_quota structure from IPA and pass to FW
+ * through quota_exceeded field in ipa_uc_fw_stats
+ */
+ ipa_set_quota = data;
+
+ if (!adapter) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA uC set quota failed - no adapter");
+ ipa_set_quota->set_valid = 0;
+ return;
+ }
+
+ INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
+ hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
+ ipa_set_quota->quota_bytes);
+
+ ret = wait_for_completion_timeout(
+ &hdd_ipa->ipa_uc_set_quota_comp,
+ msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
+ if (!ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA uC set quota request timed out");
+ ipa_set_quota->set_valid = 0;
+ } else {
+ ipa_set_quota->quota_bytes =
+ ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
+ <<32)|hdd_ipa->ipa_quota_rsp.quota_lo;
+ ipa_set_quota->set_valid =
+ hdd_ipa->ipa_quota_rsp.success;
+ }
+
+ HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
+ ipa_set_quota->quota_bytes,
+ ipa_set_quota->set_valid);
+ break;
+ }
+}
+
+/**
+ * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
+ * IPA calls to get WLAN stats or set quota limit.
+ * @priv: pointer to private data registered with IPA (we register a
+ *» pointer to the global IPA context)
+ * @evt: the IPA event which triggered the callback
+ * @data: data associated with the event
+ *
+ * Return: None
+ */
+static void hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
+ void *data)
+{
+ cds_ssr_protect(__func__);
+ __hdd_ipa_wdi_meter_notifier_cb(evt, data);
+ cds_ssr_unprotect(__func__);
+}
+
+#else /* FEATURE_METERING */
+static void hdd_ipa_wdi_init_metering(struct hdd_ipa_priv *ipa_ctxt, void *in)
+{
+}
+#endif /* FEATURE_METERING */
+
+#ifdef CONFIG_IPA_WDI_UNIFIED_API
+/*
+ * TODO: Get WDI version through FW capabilities
+ */
+#ifdef QCA_WIFI_3_0
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+ hdd_ipa->wdi_version = IPA_WDI_2;
+}
+#else
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+ hdd_ipa->wdi_version = IPA_WDI_1;
+}
+#endif
+
+static bool hdd_ipa_wdi_is_smmu_enabled(struct hdd_ipa_priv *hdd_ipa,
+ qdf_device_t osdev)
+{
+ return hdd_ipa->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
+}
+
+#ifdef QCA_LL_TX_FLOW_CONTROL_V2
+static bool hdd_ipa_wdi_is_mcc_mode_enabled(struct hdd_ipa_priv *hdd_ipa)
+{
+ return false;
+}
+#else
+static bool hdd_ipa_wdi_is_mcc_mode_enabled(struct hdd_ipa_priv *hdd_ipa)
+{
+ return hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx);
+}
+#endif
+
+#ifdef FEATURE_METERING
+static void hdd_ipa_wdi_init_metering(struct hdd_ipa_priv *ipa_ctxt, void *in)
+{
+ struct ipa_wdi_init_in_params *wdi3_in;
+
+ wdi3_in = (struct ipa_wdi_init_in_params *)in;
+ wdi3_in->wdi_notify = hdd_ipa_wdi_meter_notifier_cb;
+
+ init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
+ init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
+}
+#endif
+
+static int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa)
+{
+ struct ipa_wdi_init_in_params in;
+ struct ipa_wdi_init_out_params out;
+ int ret;
+
+ hdd_ipa->uc_loaded = false;
+
+ in.wdi_version = hdd_ipa->wdi_version;
+ in.notify = hdd_ipa_uc_loaded_uc_cb;
+ in.priv = (void *)hdd_ipa;
+ hdd_ipa_wdi_init_metering(hdd_ipa, (void *)&in);
+
+ ret = ipa_wdi_init(&in, &out);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_init failed with ret=%d", ret);
+ return -EPERM;
+ }
+
+ if (out.is_uC_ready) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "IPA uC READY");
+ hdd_ipa->uc_loaded = true;
+ hdd_ipa->is_smmu_enabled = out.is_smmu_enabled;
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "is_smmu_enabled=%d",
+ hdd_ipa->is_smmu_enabled);
+ } else {
+ ret = -EACCES;
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA uC NOT READY ret=%d", ret);
+ }
+
+ return ret;
+}
+
+static int hdd_ipa_wdi_cleanup(void)
+{
+ int ret;
+
+ ret = ipa_wdi_cleanup();
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_cleanup failed ret=%d", ret);
+ return ret;
+}
+
+static int hdd_ipa_wdi_conn_pipes(struct hdd_ipa_priv *hdd_ipa,
+ struct ol_txrx_ipa_resources *ipa_res)
+{
+ hdd_context_t *hdd_ctx = (hdd_context_t *)hdd_ipa->hdd_ctx;
+ qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+ struct ipa_wdi_conn_in_params *in;
+ struct ipa_wdi_conn_out_params out;
+ struct ipa_wdi_pipe_setup_info *info;
+ struct ipa_wdi_pipe_setup_info_smmu *info_smmu;
+ struct ipa_ep_cfg *tx_cfg;
+ struct ipa_ep_cfg *rx_cfg;
+ int ret;
+ int i;
+
+ in = qdf_mem_malloc(sizeof(*in));
+ if (!in) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "failed to alloc ipa_wdi_conn_in_params");
+ return -ENOMEM;
+ }
+
+ /* IPA RX exception packets callback */
+ in->notify = hdd_ipa_w2i_cb;
+ in->priv = hdd_ctx->hdd_ipa;
+
+ if (hdd_ipa_wdi_is_mcc_mode_enabled(hdd_ipa)) {
+ in->num_sys_pipe_needed = HDD_IPA_MAX_IFACE;
+ for (i = 0; i < in->num_sys_pipe_needed; i++)
+ memcpy(&in->sys_in[i],
+ &hdd_ipa->sys_pipe[i].ipa_sys_params,
+ sizeof(struct ipa_sys_connect_params));
+ } else {
+ in->num_sys_pipe_needed = 0;
+ }
+
+ if (hdd_ipa_wdi_is_smmu_enabled(hdd_ipa, osdev))
+ in->is_smmu_enabled = true;
+ else
+ in->is_smmu_enabled = false;
+
+ if (in->is_smmu_enabled) {
+ tx_cfg = &in->u_tx.tx_smmu.ipa_ep_cfg;
+ rx_cfg = &in->u_rx.rx_smmu.ipa_ep_cfg;
+ } else {
+ tx_cfg = &in->u_tx.tx.ipa_ep_cfg;
+ rx_cfg = &in->u_rx.rx.ipa_ep_cfg;
+ }
+
+ tx_cfg->nat.nat_en = IPA_BYPASS_NAT;
+ tx_cfg->hdr.hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
+ tx_cfg->hdr.hdr_ofst_pkt_size_valid = 1;
+ tx_cfg->hdr.hdr_ofst_pkt_size = 0;
+ tx_cfg->hdr.hdr_additional_const_len =
+ HDD_IPA_UC_WLAN_8023_HDR_SIZE;
+ tx_cfg->hdr_ext.hdr_little_endian = true;
+ tx_cfg->mode.mode = IPA_BASIC;
+
+ rx_cfg->nat.nat_en = IPA_BYPASS_NAT;
+ rx_cfg->hdr.hdr_len = HDD_IPA_UC_WLAN_RX_HDR_LEN;
+ rx_cfg->hdr.hdr_ofst_pkt_size_valid = 1;
+ rx_cfg->hdr.hdr_ofst_pkt_size = 0;
+ rx_cfg->hdr.hdr_additional_const_len =
+ HDD_IPA_UC_WLAN_8023_HDR_SIZE;
+ rx_cfg->hdr_ext.hdr_little_endian = true;
+ rx_cfg->hdr.hdr_ofst_metadata_valid = 0;
+ rx_cfg->hdr.hdr_metadata_reg_valid = 1;
+ rx_cfg->mode.mode = IPA_BASIC;
+
+ if (in->is_smmu_enabled) {
+ /* TX */
+ info_smmu = &in->u_tx.tx_smmu;
+ info_smmu->client = IPA_CLIENT_WLAN1_CONS;
+
+ qdf_mem_copy(&info_smmu->transfer_ring_base,
+ &ipa_res->tx_comp_ring->sgtable,
+ sizeof(sgtable_t));
+ info_smmu->transfer_ring_size =
+ ipa_res->tx_comp_ring->mem_info.size;
+
+ qdf_mem_copy(&info_smmu->event_ring_base,
+ &ipa_res->ce_sr->sgtable, sizeof(sgtable_t));
+ info_smmu->event_ring_size = ipa_res->ce_sr_ring_size;
+ info_smmu->event_ring_doorbell_pa = ipa_res->ce_reg_paddr;
+ info_smmu->num_pkt_buffers = ipa_res->tx_num_alloc_buffer;
+
+ /* RX */
+ info_smmu = &in->u_rx.rx_smmu;
+ info_smmu->client = IPA_CLIENT_WLAN1_PROD;
+
+ qdf_mem_copy(&info_smmu->transfer_ring_base,
+ &ipa_res->rx_rdy_ring->sgtable,
+ sizeof(sgtable_t));
+ info_smmu->transfer_ring_size =
+ ipa_res->rx_rdy_ring->mem_info.size;
+ info_smmu->transfer_ring_doorbell_pa =
+ ipa_res->rx_proc_done_idx->mem_info.pa;
+
+ qdf_mem_copy(&info_smmu->event_ring_base,
+ &ipa_res->rx2_rdy_ring->sgtable,
+ sizeof(sgtable_t));
+ info_smmu->event_ring_size =
+ ipa_res->rx2_rdy_ring->mem_info.size;
+ info_smmu->event_ring_doorbell_pa =
+ ipa_res->rx2_proc_done_idx->mem_info.pa;
+ } else {
+ /* TX */
+ info = &in->u_tx.tx;
+
+ info->client = IPA_CLIENT_WLAN1_CONS;
+
+ info->transfer_ring_base_pa = qdf_mem_get_dma_addr(osdev,
+ &ipa_res->tx_comp_ring->mem_info);
+ info->transfer_ring_size =
+ ipa_res->tx_comp_ring->mem_info.size;
+
+ info->event_ring_base_pa = qdf_mem_get_dma_addr(osdev,
+ &ipa_res->ce_sr->mem_info);
+ info->event_ring_size = ipa_res->ce_sr_ring_size;
+ info->event_ring_doorbell_pa = ipa_res->ce_reg_paddr;
+ info->num_pkt_buffers = ipa_res->tx_num_alloc_buffer;
+
+ /* RX */
+ info = &in->u_rx.rx;
+
+ info->client = IPA_CLIENT_WLAN1_PROD;
+
+ info->transfer_ring_base_pa =
+ ipa_res->rx_rdy_ring->mem_info.pa;
+ info->transfer_ring_size =
+ ipa_res->rx_rdy_ring->mem_info.size;
+ info->transfer_ring_doorbell_pa =
+ ipa_res->rx_proc_done_idx->mem_info.pa;
+
+ if (hdd_ipa->wdi_version == IPA_WDI_2) {
+ info->event_ring_base_pa = qdf_mem_get_dma_addr(osdev,
+ &ipa_res->rx2_rdy_ring->mem_info);
+ info->event_ring_size =
+ ipa_res->rx2_rdy_ring->mem_info.size;
+ info->event_ring_doorbell_pa =
+ qdf_mem_get_dma_addr(osdev,
+ &ipa_res->rx2_proc_done_idx->mem_info);
+ }
+ }
+
+ ret = ipa_wdi_conn_pipes(in, &out);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_conn_pipes failed ret=%d", ret);
+ qdf_mem_free(in);
+ return ret;
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "out.tx_uc_db_pa 0x%x out.rx_uc_db_pa 0x%x",
+ out.tx_uc_db_pa, out.rx_uc_db_pa);
+
+ hdd_ipa->tx_comp_doorbell_dmaaddr = out.tx_uc_db_pa;
+ hdd_ipa->rx_ready_doorbell_dmaaddr = out.rx_uc_db_pa;
+
+ qdf_mem_free(in);
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_disconn_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret;
+
+ ret = ipa_wdi_disconn_pipes();
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_disconn_pipes failed ret=%d", ret);
+ return ret;
+}
+
+static int hdd_ipa_wdi_reg_intf(struct hdd_ipa_priv *hdd_ipa,
+ struct hdd_ipa_iface_context *iface_context)
+{
+ hdd_adapter_t *adapter = iface_context->adapter;
+ struct ipa_wdi_reg_intf_in_params in;
+ struct hdd_ipa_uc_tx_hdr uc_tx_hdr;
+ struct hdd_ipa_uc_tx_hdr uc_tx_hdr_v6;
+ int ret;
+
+ memcpy(&uc_tx_hdr, &ipa_uc_tx_hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN);
+ memcpy(&uc_tx_hdr.eth.h_source, adapter->dev->dev_addr, ETH_ALEN);
+ uc_tx_hdr.ipa_hd.vdev_id = iface_context->adapter->sessionId;
+
+ in.netdev_name = adapter->dev->name;
+ in.hdr_info[IPA_IP_v4].hdr = (u8 *)&uc_tx_hdr;
+ in.hdr_info[IPA_IP_v4].hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
+ in.hdr_info[IPA_IP_v4].dst_mac_addr_offset =
+ HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
+ in.hdr_info[IPA_IP_v4].hdr_type = IPA_HDR_L2_ETHERNET_II;
+
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
+ memcpy(&uc_tx_hdr_v6, &ipa_uc_tx_hdr,
+ HDD_IPA_UC_WLAN_TX_HDR_LEN);
+ memcpy(&uc_tx_hdr_v6.eth.h_source, adapter->dev->dev_addr,
+ ETH_ALEN);
+ uc_tx_hdr_v6.ipa_hd.vdev_id = iface_context->adapter->sessionId;
+ uc_tx_hdr_v6.eth.h_proto = cpu_to_be16(ETH_P_IPV6);
+
+ in.netdev_name = adapter->dev->name;
+ in.hdr_info[IPA_IP_v6].hdr = (u8 *)&uc_tx_hdr_v6;
+ in.hdr_info[IPA_IP_v6].hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
+ in.hdr_info[IPA_IP_v6].dst_mac_addr_offset =
+ HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
+ in.hdr_info[IPA_IP_v6].hdr_type = IPA_HDR_L2_ETHERNET_II;
+ }
+
+ in.alt_dst_pipe = iface_context->cons_client;
+ in.is_meta_data_valid = 1;
+ in.meta_data = htonl(iface_context->adapter->sessionId << 16);
+ in.meta_data_mask = htonl(0x00FF0000);
+
+ ret = ipa_wdi_reg_intf(&in);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_reg_intf failed ret=%d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_dereg_intf(struct hdd_ipa_priv *hdd_ipa,
+ const char *devname)
+{
+ int ret;
+
+ ret = ipa_wdi_dereg_intf(devname);
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_dereg_intf failed ret=%d", ret);
+ return ret;
+}
+
+static int hdd_ipa_wdi_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret;
+
+ ret = ipa_wdi_enable_pipes();
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_enable_pipes failed ret=%d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_disable_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret;
+
+ ret = ipa_wdi_disable_pipes();
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_wdi_disable_pipes failed ret=%d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+ struct ipa_sys_connect_params *sys, uint32_t *handle)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+ uint32_t handle)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_set_perf_profile(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name resource_name,
+ struct ipa_rm_perf_profile *profile)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_request_resource(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name res_name)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_release_resource(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name res_name)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_setup_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_destroy_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_request(struct hdd_ipa_priv *hdd_ipa)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
+{
+ return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_notify_completion(enum ipa_rm_event event,
+ enum ipa_rm_resource_name resource_name)
+{
+ return 0;
+}
+#else /* CONFIG_IPA_WDI_UNIFIED_API */
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+}
+
+static int hdd_ipa_wdi_is_smmu_enabled(struct hdd_ipa_priv *hdd_ipa,
+ qdf_device_t osdev)
+{
+ return qdf_mem_smmu_s1_enabled(osdev);
+}
+
+#ifdef FEATURE_METERING
+static void hdd_ipa_wdi_init_metering(struct hdd_ipa_priv *ipa_ctxt, void *in)
+{
+ struct ipa_wdi_in_params *wdi_in;
+
+ wdi_in = (struct ipa_wdi_in_params *)in;
+ wdi_in->wdi_notify = hdd_ipa_wdi_meter_notifier_cb;
+
+ init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
+ init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
+}
+#endif
+
+static int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa)
+{
+ struct ipa_wdi_uc_ready_params uc_ready_param;
+ int ret = 0;
+
+ hdd_ipa->uc_loaded = false;
+ uc_ready_param.priv = (void *)hdd_ipa;
+ uc_ready_param.notify = hdd_ipa_uc_loaded_uc_cb;
+ if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "UC Ready CB register fail");
+ return -EPERM;
+ }
+
+ if (true == uc_ready_param.is_uC_ready) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
+ hdd_ipa->uc_loaded = true;
+ } else {
+ ret = -EACCES;
+ }
+
+ return ret;
+}
+
+static int hdd_ipa_wdi_cleanup(void)
+{
+ int ret;
+
+ ret = ipa_uc_dereg_rdyCB();
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "UC Ready CB deregister fail");
+ return ret;
+}
+
+static int hdd_ipa_wdi_conn_pipes(struct hdd_ipa_priv *hdd_ipa,
+ struct ol_txrx_ipa_resources *ipa_res)
+{
+ hdd_context_t *hdd_ctx = (hdd_context_t *)hdd_ipa->hdd_ctx;
+ struct ipa_wdi_in_params pipe_in;
+ struct ipa_wdi_out_params pipe_out;
+ QDF_STATUS stat = QDF_STATUS_SUCCESS;
+ qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+ int ret;
+
+ qdf_mem_zero(&hdd_ipa->cons_pipe_in, sizeof(struct ipa_wdi_in_params));
+ qdf_mem_zero(&hdd_ipa->prod_pipe_in, sizeof(struct ipa_wdi_in_params));
+ qdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi_in_params));
+ qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params));
+
+ /* TX PIPE */
+ pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_additional_const_len =
+ HDD_IPA_UC_WLAN_8023_HDR_SIZE;
+ pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
+ pipe_in.sys.client = IPA_CLIENT_WLAN1_CONS;
+ pipe_in.sys.desc_fifo_sz = hdd_ctx->config->IpaDescSize;
+ pipe_in.sys.priv = hdd_ctx->hdd_ipa;
+ pipe_in.sys.ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
+ pipe_in.sys.notify = hdd_ipa_i2w_cb;
+ if (!hdd_ipa_is_rm_enabled(hdd_ctx)) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "IPA RM DISABLED, IPA AWAKE");
+ pipe_in.sys.keep_ipa_awake = true;
+ }
+
+ pipe_in.smmu_enabled = hdd_ipa_wdi_is_smmu_enabled(hdd_ipa, osdev);
+ if (pipe_in.smmu_enabled) {
+ qdf_mem_copy(&pipe_in.u.dl_smmu.comp_ring,
+ &ipa_res->tx_comp_ring->sgtable,
+ sizeof(sgtable_t));
+
+ qdf_mem_copy(&pipe_in.u.dl_smmu.ce_ring,
+ &ipa_res->ce_sr->sgtable,
+ sizeof(sgtable_t));
+ pipe_in.u.dl_smmu.comp_ring_size =
+ ipa_res->tx_comp_ring->mem_info.size;
+ pipe_in.u.dl_smmu.ce_ring_size =
+ ipa_res->ce_sr_ring_size;
+ pipe_in.u.dl_smmu.ce_door_bell_pa =
+ ipa_res->ce_reg_paddr;
+ pipe_in.u.dl_smmu.num_tx_buffers =
+ ipa_res->tx_num_alloc_buffer;
+ } else {
+ pipe_in.u.dl.comp_ring_base_pa =
+ qdf_mem_get_dma_addr(osdev,
+ &ipa_res->tx_comp_ring->mem_info);
+ pipe_in.u.dl.ce_ring_base_pa =
+ qdf_mem_get_dma_addr(osdev,
+ &ipa_res->ce_sr->mem_info);
+ pipe_in.u.dl.comp_ring_size =
+ ipa_res->tx_comp_ring->mem_info.size;
+ pipe_in.u.dl.ce_door_bell_pa = ipa_res->ce_reg_paddr;
+ pipe_in.u.dl.ce_ring_size =
+ ipa_res->ce_sr_ring_size;
+ pipe_in.u.dl.num_tx_buffers =
+ ipa_res->tx_num_alloc_buffer;
+ }
+
+ qdf_mem_copy(&hdd_ipa->cons_pipe_in, &pipe_in,
+ sizeof(struct ipa_wdi_in_params));
+
+ /* Connect WDI IPA PIPE */
+ ret = ipa_connect_wdi_pipe(&hdd_ipa->cons_pipe_in, &pipe_out);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_connect_wdi_pipe failed for Tx: ret=%d",
+ ret);
+ stat = QDF_STATUS_E_FAILURE;
+ goto fail_return;
+ }
+
+ /* Micro Controller Doorbell register */
+ hdd_ipa->tx_comp_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
+
+ /* WLAN TX PIPE Handle */
+ hdd_ipa->tx_pipe_handle = pipe_out.clnt_hdl;
+
+ if (hdd_ipa->tx_pipe_handle == 0) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "TX Handle zero");
+ QDF_BUG(0);
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "CONS DB pipe out 0x%x TX PIPE Handle 0x%x",
+ (unsigned int)pipe_out.uc_door_bell_pa,
+ hdd_ipa->tx_pipe_handle);
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "TX : CRBPA 0x%x, CRS %d, CERBPA 0x%x, CEDPA 0x%x,"
+ " CERZ %d, NB %d, CDBPAD 0x%x",
+ (unsigned int)pipe_in.u.dl.comp_ring_base_pa,
+ pipe_in.u.dl.comp_ring_size,
+ (unsigned int)pipe_in.u.dl.ce_ring_base_pa,
+ (unsigned int)pipe_in.u.dl.ce_door_bell_pa,
+ pipe_in.u.dl.ce_ring_size,
+ pipe_in.u.dl.num_tx_buffers,
+ (unsigned int)hdd_ipa->tx_comp_doorbell_dmaaddr);
+
+ /* RX PIPE */
+ pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_RX_HDR_LEN;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0;
+ pipe_in.sys.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1;
+ pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
+ pipe_in.sys.client = IPA_CLIENT_WLAN1_PROD;
+ pipe_in.sys.desc_fifo_sz = hdd_ctx->config->IpaDescSize +
+ sizeof(struct sps_iovec);
+ pipe_in.sys.notify = hdd_ipa_w2i_cb;
+ if (!hdd_ipa_is_rm_enabled(hdd_ctx)) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "IPA RM DISABLED, IPA AWAKE");
+ pipe_in.sys.keep_ipa_awake = true;
+ }
+
+ pipe_in.smmu_enabled = hdd_ipa_wdi_is_smmu_enabled(hdd_ipa, osdev);
+ if (pipe_in.smmu_enabled) {
+ qdf_mem_copy(&pipe_in.u.ul_smmu.rdy_ring,
+ &ipa_res->rx_rdy_ring->sgtable,
+ sizeof(sgtable_t));
+ pipe_in.u.ul_smmu.rdy_ring_size =
+ ipa_res->rx_rdy_ring->mem_info.size;
+ pipe_in.u.ul_smmu.rdy_ring_rp_pa =
+ ipa_res->rx_proc_done_idx->mem_info.pa;
+
+ pipe_in.u.ul_smmu.rdy_ring_rp_va =
+ ipa_res->rx_proc_done_idx->vaddr;
+
+ qdf_mem_copy(&pipe_in.u.ul_smmu.rdy_comp_ring,
+ &ipa_res->rx2_rdy_ring->sgtable,
+ sizeof(sgtable_t));
+
+ pipe_in.u.ul_smmu.rdy_comp_ring_size =
+ ipa_res->rx2_rdy_ring->mem_info.size;
+
+ pipe_in.u.ul_smmu.rdy_comp_ring_wp_pa =
+ ipa_res->rx2_proc_done_idx->mem_info.pa;
+
+ pipe_in.u.ul_smmu.rdy_comp_ring_wp_va =
+ ipa_res->rx2_proc_done_idx->vaddr;
+ } else {
+ pipe_in.u.ul.rdy_ring_base_pa =
+ ipa_res->rx_rdy_ring->mem_info.pa;
+ pipe_in.u.ul.rdy_ring_size =
+ ipa_res->rx_rdy_ring->mem_info.size;
+ pipe_in.u.ul.rdy_ring_rp_pa =
+ ipa_res->rx_proc_done_idx->mem_info.pa;
+ HDD_IPA_WDI2_SET(pipe_in, hdd_ipa, osdev);
+ }
+
+ hdd_ipa_wdi_init_metering(hdd_ipa, (void *)&pipe_in);
+
+ qdf_mem_copy(&hdd_ipa->prod_pipe_in, &pipe_in,
+ sizeof(struct ipa_wdi_in_params));
+
+ ret = ipa_connect_wdi_pipe(&hdd_ipa->prod_pipe_in, &pipe_out);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa_connect_wdi_pipe failed for Rx: ret=%d",
+ ret);
+ stat = QDF_STATUS_E_FAILURE;
+ ret = ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "disconnect failed for TX: ret=%d",
+ ret);
+ goto fail_return;
+ }
+ hdd_ipa->rx_ready_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
+ hdd_ipa->rx_pipe_handle = pipe_out.clnt_hdl;
+ if (hdd_ipa->rx_pipe_handle == 0) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "RX Handle zero");
+ QDF_BUG(0);
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "PROD DB pipe out 0x%x RX PIPE Handle 0x%x",
+ (unsigned int)pipe_out.uc_door_bell_pa,
+ hdd_ipa->rx_pipe_handle);
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "RX : RRBPA 0x%x, RRS %d, PDIPA 0x%x, RDY_DB_PAD 0x%x",
+ (unsigned int)pipe_in.u.ul.rdy_ring_base_pa,
+ pipe_in.u.ul.rdy_ring_size,
+ (unsigned int)pipe_in.u.ul.rdy_ring_rp_pa,
+ (unsigned int)hdd_ipa->rx_ready_doorbell_dmaaddr);
+
+fail_return:
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: stat=%d", stat);
+ return stat;
+}
+
+static int hdd_ipa_wdi_disconn_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret;
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "Disconnect TX PIPE tx_pipe_handle=0x%x",
+ hdd_ipa->tx_pipe_handle);
+ ret = ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+ "Disconnect RX PIPE rx_pipe_handle=0x%x",
+ hdd_ipa->rx_pipe_handle);
+ ret = ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle);
+
+ return ret;
+}
+
+/**
+ * hdd_remove_ipa_header() - Remove a specific header from IPA
+ * @name: Name of the header to be removed
+ *
+ * Return: None
+ */
+static void hdd_ipa_remove_header(char *name)
+{
+ struct ipa_ioc_get_hdr hdrlookup;
+ int ret = 0, len;
+ struct ipa_ioc_del_hdr *ipa_hdr;
+
+ qdf_mem_zero(&hdrlookup, sizeof(hdrlookup));
+ strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name));
+ ret = ipa_get_hdr(&hdrlookup);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Hdr deleted already %s, %d",
+ name, ret);
+ return;
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "hdl: 0x%x", hdrlookup.hdl);
+ len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del) * 1;
+ ipa_hdr = (struct ipa_ioc_del_hdr *)qdf_mem_malloc(len);
+ if (ipa_hdr == NULL) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "ipa_hdr allocation failed");
+ return;
+ }
+ ipa_hdr->num_hdls = 1;
+ ipa_hdr->commit = 0;
+ ipa_hdr->hdl[0].hdl = hdrlookup.hdl;
+ ipa_hdr->hdl[0].status = -1;
+ ret = ipa_del_hdr(ipa_hdr);
+ if (ret != 0)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Delete header failed: %d",
+ ret);
+
+ qdf_mem_free(ipa_hdr);
+}
+
+/**
+ * wlan_ipa_add_hdr() - Add IPA Tx header
+ * @ipa_hdr: pointer to IPA header addition parameters
+ *
+ * Call IPA API to add IPA Tx header descriptor
+ * and dump Tx header struct
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+static int wlan_ipa_add_hdr(struct ipa_ioc_add_hdr *ipa_hdr)
+{
+ int ret;
+
+ hdd_debug("==== IPA Tx Header ====\n"
+ "name: %s\n"
+ "hdr_len: %d\n"
+ "type: %d\n"
+ "is_partial: %d\n"
+ "hdr_hdl: 0x%x\n"
+ "status: %d\n"
+ "is_eth2_ofst_valid: %d\n"
+ "eth2_ofst: %d\n",
+ ipa_hdr->hdr[0].name,
+ ipa_hdr->hdr[0].hdr_len,
+ ipa_hdr->hdr[0].type,
+ ipa_hdr->hdr[0].is_partial,
+ ipa_hdr->hdr[0].hdr_hdl,
+ ipa_hdr->hdr[0].status,
+ ipa_hdr->hdr[0].is_eth2_ofst_valid,
+ ipa_hdr->hdr[0].eth2_ofst);
+
+ HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG, "hdr:",
+ ipa_hdr->hdr[0].hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN);
+
+ ret = ipa_add_hdr(ipa_hdr);
+ return ret;
+}
+
+/* For Tx pipes, use 802.3 Header format */
+static struct hdd_ipa_tx_hdr ipa_tx_hdr = {
+ {
+ {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF},
+ {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF},
+ 0x00 /* length can be zero */
+ },
+ {
+ /* LLC SNAP header 8 bytes */
+ 0xaa, 0xaa,
+ {0x03, 0x00, 0x00, 0x00},
+ 0x0008 /* type value(2 bytes) ,filled by wlan */
+ /* 0x0800 - IPV4, 0x86dd - IPV6 */
+ }
+};
+
+/**
+ * hdd_ipa_add_header_info() - Add IPA header for a given interface
+ * @hdd_ipa: Global HDD IPA context
+ * @iface_context: Interface-specific HDD IPA context
+ * @mac_addr: Interface MAC address
+ *
+ * Return: 0 on success, negativer errno value on error
+ */
+static int hdd_ipa_add_header_info(struct hdd_ipa_priv *hdd_ipa,
+ struct hdd_ipa_iface_context *iface_context,
+ uint8_t *mac_addr)
+{
+ hdd_adapter_t *adapter = iface_context->adapter;
+ char *ifname;
+ struct ipa_ioc_add_hdr *ipa_hdr = NULL;
+ int ret = -EINVAL;
+ struct hdd_ipa_tx_hdr *tx_hdr = NULL;
+ struct hdd_ipa_uc_tx_hdr *uc_tx_hdr = NULL;
+
+ ifname = adapter->dev->name;
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Add Partial hdr: %s, %pM",
+ ifname, mac_addr);
+
+ /* dynamically allocate the memory to add the hdrs */
+ ipa_hdr = qdf_mem_malloc(sizeof(struct ipa_ioc_add_hdr)
+ + sizeof(struct ipa_hdr_add));
+ if (!ipa_hdr) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "%s: ipa_hdr allocation failed", ifname);
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ ipa_hdr->commit = 0;
+ ipa_hdr->num_hdrs = 1;
+
+ if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
+ uc_tx_hdr = (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
+ memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN);
+ memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
+ uc_tx_hdr->ipa_hd.vdev_id = iface_context->adapter->sessionId;
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "ifname=%s, vdev_id=%d",
+ ifname, uc_tx_hdr->ipa_hd.vdev_id);
+ snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV4_NAME_EXT);
+ ipa_hdr->hdr[0].hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
+ ipa_hdr->hdr[0].type = IPA_HDR_L2_ETHERNET_II;
+ ipa_hdr->hdr[0].is_partial = 1;
+ ipa_hdr->hdr[0].hdr_hdl = 0;
+ ipa_hdr->hdr[0].is_eth2_ofst_valid = 1;
+ ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
+
+ ret = wlan_ipa_add_hdr(ipa_hdr);
+ } else {
+ tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr;
+
+ /* Set the Source MAC */
+ memcpy(tx_hdr, &ipa_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN);
+ memcpy(tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
+
+ snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV4_NAME_EXT);
+ ipa_hdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
+ ipa_hdr->hdr[0].is_partial = 1;
+ ipa_hdr->hdr[0].hdr_hdl = 0;
+ ipa_hdr->hdr[0].is_eth2_ofst_valid = 1;
+ ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_WLAN_HDR_DES_MAC_OFFSET;
+
+ /* Set the type to IPV4 in the header */
+ tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IP);
+
+ ret = ipa_add_hdr(ipa_hdr);
+ }
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "%s: IPv4 add hdr failed: %d", ifname, ret);
+ goto end;
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: IPv4 hdr_hdl: 0x%x",
+ ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
+
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
+ snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV6_NAME_EXT);
+
+ if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
+ uc_tx_hdr =
+ (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
+ uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6);
+ ret = wlan_ipa_add_hdr(ipa_hdr);
+ } else {
+ /* Set the type to IPV6 in the header */
+ tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr;
+ tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6);
+ ret = ipa_add_hdr(ipa_hdr);
+ }
+
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "%s: IPv6 add hdr failed: %d", ifname, ret);
+ goto clean_ipv4_hdr;
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: IPv6 hdr_hdl: 0x%x",
+ ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
+ }
+
+ qdf_mem_free(ipa_hdr);
+
+ return ret;
+
+clean_ipv4_hdr:
+ snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV4_NAME_EXT);
+ hdd_ipa_remove_header(ipa_hdr->hdr[0].name);
+end:
+ if (ipa_hdr)
+ qdf_mem_free(ipa_hdr);
+
+ return ret;
+}
+
+/**
+ * hdd_ipa_register_interface() - register IPA interface
+ * @hdd_ipa: Global IPA context
+ * @iface_context: Per-interface IPA context
+ *
+ * Return: 0 on success, negative errno on error
+ */
+static int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa,
+ struct hdd_ipa_iface_context
+ *iface_context)
+{
+ struct ipa_tx_intf tx_intf;
+ struct ipa_rx_intf rx_intf;
+ struct ipa_ioc_tx_intf_prop *tx_prop = NULL;
+ struct ipa_ioc_rx_intf_prop *rx_prop = NULL;
+ char *ifname = iface_context->adapter->dev->name;
+
+ char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
+ char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
+
+ int num_prop = 1;
+ int ret = 0;
+
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx))
+ num_prop++;
+
+ /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
+ tx_prop =
+ qdf_mem_malloc(sizeof(struct ipa_ioc_tx_intf_prop) * num_prop);
+ if (!tx_prop) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "tx_prop allocation failed");
+ goto register_interface_fail;
+ }
+
+ /* Allocate RX properties, 1 each for IPv4 & IPv6 */
+ rx_prop =
+ qdf_mem_malloc(sizeof(struct ipa_ioc_rx_intf_prop) * num_prop);
+ if (!rx_prop) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "rx_prop allocation failed");
+ goto register_interface_fail;
+ }
+
+ qdf_mem_zero(&tx_intf, sizeof(tx_intf));
+ qdf_mem_zero(&rx_intf, sizeof(rx_intf));
+
+ snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV4_NAME_EXT);
+ snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV6_NAME_EXT);
+
+ rx_prop[IPA_IP_v4].ip = IPA_IP_v4;
+ rx_prop[IPA_IP_v4].src_pipe = iface_context->prod_client;
+ rx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+ rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA;
+
+ /*
+ * Interface ID is 3rd byte in the CLD header. Add the meta data and
+ * mask to identify the interface in IPA hardware
+ */
+ rx_prop[IPA_IP_v4].attrib.meta_data =
+ htonl(iface_context->adapter->sessionId << 16);
+ rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
+
+ rx_intf.num_props++;
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
+ rx_prop[IPA_IP_v6].ip = IPA_IP_v6;
+ rx_prop[IPA_IP_v6].src_pipe = iface_context->prod_client;
+ rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+ rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA;
+ rx_prop[IPA_IP_v4].attrib.meta_data =
+ htonl(iface_context->adapter->sessionId << 16);
+ rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
+
+ rx_intf.num_props++;
+ }
+
+ tx_prop[IPA_IP_v4].ip = IPA_IP_v4;
+ tx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+ tx_prop[IPA_IP_v4].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+ tx_prop[IPA_IP_v4].alt_dst_pipe = iface_context->cons_client;
+ strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name,
+ IPA_RESOURCE_NAME_MAX);
+ tx_intf.num_props++;
+
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
+ tx_prop[IPA_IP_v6].ip = IPA_IP_v6;
+ tx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+ tx_prop[IPA_IP_v6].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+ tx_prop[IPA_IP_v6].alt_dst_pipe = iface_context->cons_client;
+ strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name,
+ IPA_RESOURCE_NAME_MAX);
+ tx_intf.num_props++;
+ }
+
+ tx_intf.prop = tx_prop;
+ rx_intf.prop = rx_prop;
+
+ /* Call the ipa api to register interface */
+ ret = ipa_register_intf(ifname, &tx_intf, &rx_intf);
+
+register_interface_fail:
+ qdf_mem_free(tx_prop);
+ qdf_mem_free(rx_prop);
+ return ret;
+}
+
+static int hdd_ipa_wdi_reg_intf(struct hdd_ipa_priv *hdd_ipa,
+ struct hdd_ipa_iface_context *iface_context)
+{
+ int ret;
+
+ ret = hdd_ipa_add_header_info(hdd_ipa, iface_context,
+ iface_context->adapter->dev->dev_addr);
+
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa add header failed ret=%d", ret);
+ return ret;
+ }
+
+ /* Configure the TX and RX pipes filter rules */
+ ret = hdd_ipa_register_interface(hdd_ipa, iface_context);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa register interface failed ret=%d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_dereg_intf(struct hdd_ipa_priv *hdd_ipa,
+ const char *devname)
+{
+ char name_ipa[IPA_RESOURCE_NAME_MAX];
+ int ret;
+
+ /* Remove the headers */
+ snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", devname,
+ HDD_IPA_IPV4_NAME_EXT);
+ hdd_ipa_remove_header(name_ipa);
+
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
+ snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", devname,
+ HDD_IPA_IPV6_NAME_EXT);
+ hdd_ipa_remove_header(name_ipa);
+ }
+
+ /* unregister the interface with IPA */
+ ret = ipa_deregister_intf(devname);
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "%s: ipa_deregister_intf fail: %d", devname, ret);
+ return ret;
+}
+
+static int hdd_ipa_wdi_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int result;
+
+ /* ACTIVATE TX PIPE */
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "Enable TX PIPE(tx_pipe_handle=%d)",
+ hdd_ipa->tx_pipe_handle);
+ result = ipa_enable_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Enable TX PIPE fail, code %d",
+ result);
+ return result;
+ }
+
+ result = ipa_resume_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Resume TX PIPE fail, code %d",
+ result);
+ return result;
+ }
+
+ /* ACTIVATE RX PIPE */
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "Enable RX PIPE(rx_pipe_handle=%d)",
+ hdd_ipa->rx_pipe_handle);
+ result = ipa_enable_wdi_pipe(hdd_ipa->rx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Enable RX PIPE fail, code %d",
+ result);
+ return result;
+ }
+
+ result = ipa_resume_wdi_pipe(hdd_ipa->rx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Resume RX PIPE fail, code %d",
+ result);
+ return result;
+ }
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_disable_pipes(struct hdd_ipa_priv *hdd_ipa)
+{
+ int result;
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable RX PIPE");
+ result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Suspend RX PIPE fail, code %d", result);
+ return result;
+ }
+
+ result = ipa_disable_wdi_pipe(hdd_ipa->rx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Disable RX PIPE fail, code %d", result);
+ return result;
+ }
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable TX PIPE");
+ result = ipa_suspend_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Suspend TX PIPE fail, code %d", result);
+ return result;
+ }
+
+ result = ipa_disable_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ if (result) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Disable TX PIPE fail, code %d", result);
+ return result;
+ }
+
+ return 0;
+}
+
+static int hdd_ipa_wdi_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+ struct ipa_sys_connect_params *sys, uint32_t *handle)
+{
+ return ipa_setup_sys_pipe(sys, handle);
+}
+
+static int hdd_ipa_wdi_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+ uint32_t handle)
+{
+ return ipa_teardown_sys_pipe(handle);
+}
+
+static int hdd_ipa_wdi_rm_set_perf_profile(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name resource_name,
+ struct ipa_rm_perf_profile *profile)
+{
+ return ipa_rm_set_perf_profile(resource_name, profile);
+}
+
+static int hdd_ipa_wdi_rm_request_resource(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name res_name)
+{
+ return ipa_rm_request_resource(res_name);
+}
+
+static int hdd_ipa_wdi_rm_release_resource(struct hdd_ipa_priv *hdd_ipa,
+ enum ipa_rm_resource_name res_name)
+{
+ return ipa_rm_release_resource(res_name);
+}
+
+/**
+ * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
+ * @work: struct work_struct
+ * @work_handler: work_handler
+ *
+ * Return: none
+ */
+static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
+ work_func_t work_handler)
+{
+ INIT_WORK(work, work_handler);
+}
+
+/**
+ * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
+ * @work: scheduled work
+ *
+ * When IPA resources are released in hdd_ipa_wdi_rm_try_release() we do
+ * not want to immediately release the wake lock since the system
+ * would then potentially try to suspend when there is a healthy data
+ * rate. Deferred work is scheduled and this function handles the
+ * work. When this function is called, if the IPA resource is still
+ * released then we release the wake lock.
+ *
+ * Return: None
+ */
+static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
+{
+ struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
+ struct hdd_ipa_priv,
+ wake_lock_work);
+
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+
+ if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
+ goto end;
+
+ hdd_ipa->wake_lock_released = true;
+ qdf_wake_lock_release(&hdd_ipa->wake_lock,
+ WIFI_POWER_EVENT_WAKELOCK_IPA);
+
+end:
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+}
+
+/**
+ * hdd_ipa_wdi_rm_request() - Request resource from IPA
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 on success, negative errno on error
+ */
+static int hdd_ipa_wdi_rm_request(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret = 0;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return 0;
+
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+
+ switch (hdd_ipa->rm_state) {
+ case HDD_IPA_RM_GRANTED:
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+ return 0;
+ case HDD_IPA_RM_GRANT_PENDING:
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+ return -EINPROGRESS;
+ case HDD_IPA_RM_RELEASED:
+ hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
+ break;
+ }
+
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+ ret = ipa_rm_inactivity_timer_request_resource(
+ IPA_RM_RESOURCE_WLAN_PROD);
+
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+ if (ret == 0) {
+ hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+ hdd_ipa->stats.num_rm_grant_imm++;
+ }
+
+ cancel_delayed_work(&hdd_ipa->wake_lock_work);
+ if (hdd_ipa->wake_lock_released) {
+ qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
+ WIFI_POWER_EVENT_WAKELOCK_IPA);
+ hdd_ipa->wake_lock_released = false;
+ }
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+ return ret;
+}
+
+/**
+ * hdd_ipa_wdi_rm_try_release() - Attempt to release IPA resource
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 if resources released, negative errno otherwise
+ */
+static int hdd_ipa_wdi_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret = 0;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return 0;
+
+ if (atomic_read(&hdd_ipa->tx_ref_cnt))
+ return -EAGAIN;
+
+ qdf_spin_lock_bh(&hdd_ipa->pm_lock);
+
+ if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
+ qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
+ return -EAGAIN;
+ }
+ qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
+
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+ switch (hdd_ipa->rm_state) {
+ case HDD_IPA_RM_GRANTED:
+ break;
+ case HDD_IPA_RM_GRANT_PENDING:
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+ return -EINPROGRESS;
+ case HDD_IPA_RM_RELEASED:
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+ return 0;
+ }
+
+ /* IPA driver returns immediately so set the state here to avoid any
+ * race condition.
+ */
+ hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
+ hdd_ipa->stats.num_rm_release++;
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+ ret = ipa_rm_inactivity_timer_release_resource(
+ IPA_RM_RESOURCE_WLAN_PROD);
+
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+ if (unlikely(ret != 0)) {
+ hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+ WARN_ON(1);
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
+ "ipa_rm_inactivity_timer_release_resource returnied fail");
+ }
+
+ /*
+ * If wake_lock is released immediately, kernel would try to suspend
+ * immediately as well, Just avoid ping-pong between suspend-resume
+ * while there is healthy amount of data transfer going on by
+ * releasing the wake_lock after some delay.
+ */
+ schedule_delayed_work(&hdd_ipa->wake_lock_work,
+ msecs_to_jiffies
+ (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
+
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+ return ret;
+}
+
+/**
+ * hdd_ipa_rm_notify() - IPA resource manager notifier callback
+ * @user_data: user data registered with IPA
+ * @event: the IPA resource manager event that occurred
+ * @data: the data associated with the event
+ *
+ * Return: None
+ */
+static void hdd_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
+ unsigned long data)
+{
+ struct hdd_ipa_priv *hdd_ipa = user_data;
+
+ if (unlikely(!hdd_ipa))
+ return;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return;
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
+
+ switch (event) {
+ case IPA_RM_RESOURCE_GRANTED:
+ if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
+ /* RM Notification comes with ISR context
+ * it should be serialized into work queue to avoid
+ * ISR sleep problem
+ */
+ hdd_ipa->uc_rm_work.event = event;
+ schedule_work(&hdd_ipa->uc_rm_work.work);
+ break;
+ }
+ qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+ hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+ qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+ hdd_ipa->stats.num_rm_grant++;
+ break;
+
+ case IPA_RM_RESOURCE_RELEASED:
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
+ hdd_ipa->resource_unloading = false;
+ break;
+
+ default:
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
+ break;
+ }
+}
+
+/**
+ * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
+ *
+ * Callback function registered with IPA that is called when IPA wants
+ * to release the WLAN consumer resource
+ *
+ * Return: 0 if the request is granted, negative errno otherwise
+ */
+static int hdd_ipa_rm_cons_release(void)
+{
+ return 0;
+}
+
+/**
+ * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
+ *
+ * Callback function registered with IPA that is called when IPA wants
+ * to access the WLAN consumer resource
+ *
+ * Return: 0 if the request is granted, negative errno otherwise
+ */
+static int hdd_ipa_rm_cons_request(void)
+{
+ int ret = 0;
+
+ if (ghdd_ipa->resource_loading) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+ "IPA resource loading in progress");
+ ghdd_ipa->pending_cons_req = true;
+ ret = -EINPROGRESS;
+ } else if (ghdd_ipa->resource_unloading) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+ "IPA resource unloading in progress");
+ ghdd_ipa->pending_cons_req = true;
+ ret = -EPERM;
+ }
+
+ return ret;
+}
+
+/**
+ * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
+ * @context: User context registered with TL (the IPA Global context is
+ * registered
+ * @rxpkt: Packet containing the notification
+ * @staid: ID of the station associated with the packet
+ *
+ * Return: None
+ */
+static void
+hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event)
+{
+ struct hdd_ipa_priv *hdd_ipa = context;
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+ /*
+ * When SSR is going on or driver is unloading, just return.
+ */
+ status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
+ if (status)
+ return;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return;
+
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d",
+ event);
+
+ switch (event) {
+ case IPA_RM_RESOURCE_GRANTED:
+ /* Differed RM Granted */
+ qdf_mutex_acquire(&hdd_ipa->ipa_lock);
+ if ((false == hdd_ipa->resource_unloading) &&
+ (!hdd_ipa->activated_fw_pipe)) {
+ hdd_ipa_uc_enable_pipes(hdd_ipa);
+ hdd_ipa->resource_loading = false;
+ }
+ qdf_mutex_release(&hdd_ipa->ipa_lock);
+ break;
+
+ case IPA_RM_RESOURCE_RELEASED:
+ /* Differed RM Released */
+ hdd_ipa->resource_unloading = false;
+ break;
+
+ default:
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "invalid event code %d", event);
+ break;
+ }
+}
+
+/**
+ * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
+ * @hdd_ipa: Global HDD IPA context
+ * @event: IPA resource manager event to be deferred
+ *
+ * This function is called when a resource manager event is received
+ * from firmware in interrupt context. This function will defer the
+ * handling to the OL RX thread
+ *
+ * Return: None
+ */
+static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
+{
+ enum ipa_rm_event event;
+ struct uc_rm_work_struct *uc_rm_work = container_of(work,
+ struct uc_rm_work_struct, work);
+ struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
+ struct hdd_ipa_priv, uc_rm_work);
+
+ cds_ssr_protect(__func__);
+ event = uc_rm_work->event;
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+ "posted event %d", event);
+
+ hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
+ cds_ssr_unprotect(__func__);
+}
+
+/**
+ * hdd_ipa_wdi_setup_rm() - Setup IPA resource management
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 on success, negative errno on error
+ */
+static int hdd_ipa_wdi_setup_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+ struct ipa_rm_create_params create_params = { 0 };
+ int ret;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return 0;
+
+ hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
+ hdd_ipa_uc_rm_notify_defer);
+ memset(&create_params, 0, sizeof(create_params));
+ create_params.name = IPA_RM_RESOURCE_WLAN_PROD;
+ create_params.reg_params.user_data = hdd_ipa;
+ create_params.reg_params.notify_cb = hdd_ipa_rm_notify;
+ create_params.floor_voltage = IPA_VOLTAGE_SVS;
+
+ ret = ipa_rm_create_resource(&create_params);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Create RM resource failed: %d", ret);
+ goto setup_rm_fail;
+ }
+
+ memset(&create_params, 0, sizeof(create_params));
+ create_params.name = IPA_RM_RESOURCE_WLAN_CONS;
+ create_params.request_resource = hdd_ipa_rm_cons_request;
+ create_params.release_resource = hdd_ipa_rm_cons_release;
+ create_params.floor_voltage = IPA_VOLTAGE_SVS;
+
+ ret = ipa_rm_create_resource(&create_params);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Create RM CONS resource failed: %d", ret);
+ goto delete_prod;
+ }
+
+ ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+ IPA_RM_RESOURCE_APPS_CONS);
+
+ ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
+ HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
+ ret);
+ goto timer_init_failed;
+ }
+
+ /* Set the lowest bandwidth to start with */
+ ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
+
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Set perf level failed: %d", ret);
+ goto set_perf_failed;
+ }
+
+ qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
+ INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
+ hdd_ipa_wake_lock_timer_func);
+ qdf_spinlock_create(&hdd_ipa->rm_lock);
+ hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
+ hdd_ipa->wake_lock_released = true;
+ atomic_set(&hdd_ipa->tx_ref_cnt, 0);
+
+ return ret;
+
+set_perf_failed:
+ ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
+
+timer_init_failed:
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+
+delete_prod:
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+
+setup_rm_fail:
+ return ret;
+}
+
+/**
+ * hdd_ipa_wdi_destroy_rm() - Destroy IPA resources
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Destroys all resources associated with the IPA resource manager
+ *
+ * Return: None
+ */
+static void hdd_ipa_wdi_destroy_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+ int ret;
+
+ if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+ return;
+
+ cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
+ qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
+ cancel_work_sync(&hdd_ipa->uc_rm_work.work);
+ qdf_spinlock_destroy(&hdd_ipa->rm_lock);
+
+ ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
+
+ ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "RM PROD resource delete failed %d", ret);
+
+ ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+ if (ret)
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "RM CONS resource delete failed %d", ret);
+}
+
+static int hdd_ipa_wdi_rm_notify_completion(enum ipa_rm_event event,
+ enum ipa_rm_resource_name resource_name)
+{
+ return ipa_rm_notify_completion(event, resource_name);
+}
+#endif /* CONFIG_IPA_WDI_UNIFIED_API */
+
/**
* hdd_ipa_uc_rt_debug_host_fill - fill rt debug buffer
* @ctext: pointer to hdd context.
@@ -1749,8 +3453,8 @@ static bool hdd_ipa_uc_find_add_assoc_sta(struct hdd_ipa_priv *hdd_ipa,
*/
static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
{
+ struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
int result = 0;
- p_cds_contextType cds_ctx = hdd_ipa->hdd_ctx->pcds_context;
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
@@ -1765,46 +3469,17 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
goto end;
}
- /* ACTIVATE TX PIPE */
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "Enable TX PIPE(tx_pipe_handle=%d)",
- hdd_ipa->tx_pipe_handle);
- result = ipa_enable_wdi_pipe(hdd_ipa->tx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Enable TX PIPE fail, code %d",
- result);
- goto end;
- }
- result = ipa_resume_wdi_pipe(hdd_ipa->tx_pipe_handle);
+ result = hdd_ipa_wdi_enable_pipes(hdd_ipa);
if (result) {
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Resume TX PIPE fail, code %d",
- result);
+ "Enable IPA WDI pipes failed ret=%d", result);
goto end;
}
- ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, true);
- /* ACTIVATE RX PIPE */
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "Enable RX PIPE(rx_pipe_handle=%d)",
- hdd_ipa->rx_pipe_handle);
- result = ipa_enable_wdi_pipe(hdd_ipa->rx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Enable RX PIPE fail, code %d",
- result);
- goto end;
- }
- result = ipa_resume_wdi_pipe(hdd_ipa->rx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Resume RX PIPE fail, code %d",
- result);
- goto end;
- }
+ ol_txrx_ipa_uc_set_active(pdev, true, true);
+ ol_txrx_ipa_uc_set_active(pdev, true, false);
+
INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
- ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, false);
hdd_ipa->ipa_pipes_down = false;
end:
@@ -1836,35 +3511,10 @@ static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa)
goto end;
}
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable RX PIPE");
- result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle);
+ result = hdd_ipa_wdi_disable_pipes(hdd_ipa);
if (result) {
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Suspend RX PIPE fail, code %d",
- result);
- goto end;
- }
- result = ipa_disable_wdi_pipe(hdd_ipa->rx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Disable RX PIPE fail, code %d",
- result);
- goto end;
- }
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable TX PIPE");
- result = ipa_suspend_wdi_pipe(hdd_ipa->tx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Suspend TX PIPE fail, code %d",
- result);
- goto end;
- }
- result = ipa_disable_wdi_pipe(hdd_ipa->tx_pipe_handle);
- if (result) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Disable TX PIPE fail, code %d",
- result);
+ "Disable IPA WDI pipes failed ret=%d", result);
goto end;
}
@@ -1894,7 +3544,8 @@ static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa)
* PROD resource may return sync or async manners
*/
if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) {
- if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
+ if (!hdd_ipa_wdi_rm_request_resource(hdd_ipa,
+ IPA_RM_RESOURCE_WLAN_PROD)) {
/* RM PROD request sync return
* enable pipe immediately
*/
@@ -1933,11 +3584,11 @@ static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa)
*/
static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa)
{
- p_cds_contextType cds_ctx = hdd_ipa->hdd_ctx->pcds_context;
+ struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
- if (!cds_ctx || !cds_ctx->pdev_txrx_ctx) {
+ if (!pdev) {
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "txrx context is NULL");
QDF_ASSERT(0);
return;
@@ -1946,90 +3597,11 @@ static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa)
hdd_ipa->resource_unloading = true;
INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable FW RX PIPE");
- ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, false, false);
+ ol_txrx_ipa_uc_set_active(pdev, false, false);
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: IPA WDI Pipes deactivated");
}
-/**
- * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
- * @context: User context registered with TL (the IPA Global context is
- * registered
- * @rxpkt: Packet containing the notification
- * @staid: ID of the station associated with the packet
- *
- * Return: None
- */
-static void
-hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event)
-{
- struct hdd_ipa_priv *hdd_ipa = context;
- QDF_STATUS status = QDF_STATUS_SUCCESS;
-
- /*
- * When SSR is going on or driver is unloading, just return.
- */
- status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
- if (status)
- return;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return;
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d",
- event);
-
- switch (event) {
- case IPA_RM_RESOURCE_GRANTED:
- /* Differed RM Granted */
- qdf_mutex_acquire(&hdd_ipa->ipa_lock);
- if ((false == hdd_ipa->resource_unloading) &&
- (!hdd_ipa->activated_fw_pipe)) {
- hdd_ipa_uc_enable_pipes(hdd_ipa);
- hdd_ipa->resource_loading = false;
- }
- qdf_mutex_release(&hdd_ipa->ipa_lock);
- break;
-
- case IPA_RM_RESOURCE_RELEASED:
- /* Differed RM Released */
- hdd_ipa->resource_unloading = false;
- break;
-
- default:
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "invalid event code %d", event);
- break;
- }
-}
-
-/**
- * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
- * @hdd_ipa: Global HDD IPA context
- * @event: IPA resource manager event to be deferred
- *
- * This function is called when a resource manager event is received
- * from firmware in interrupt context. This function will defer the
- * handling to the OL RX thread
- *
- * Return: None
- */
-static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
-{
- enum ipa_rm_event event;
- struct uc_rm_work_struct *uc_rm_work = container_of(work,
- struct uc_rm_work_struct, work);
- struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
- struct hdd_ipa_priv, uc_rm_work);
-
- cds_ssr_protect(__func__);
- event = uc_rm_work->event;
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "posted event %d", event);
-
- hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
- cds_ssr_unprotect(__func__);
-}
/**
* hdd_ipa_uc_op_metering() - IPA uC operation for stats and quota limit
@@ -2132,7 +3704,12 @@ static QDF_STATUS hdd_ipa_uc_op_metering(hdd_context_t *hdd_ctx,
*/
static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *ipa_ctxt)
{
- struct ipa_wdi_out_params pipe_out;
+ struct ol_txrx_ipa_resources *ipa_res = &ipa_ctxt->ipa_resource;
+ qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+ struct ol_txrx_pdev_t *pdev;
+ uint32_t tx_comp_db_dmaaddr = 0;
+ uint32_t rx_rdy_db_dmaaddr = 0;
+ int ret;
HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC READY");
if (true == ipa_ctxt->uc_loaded) {
@@ -2140,22 +3717,42 @@ static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *ipa_ctxt)
return;
}
+ if (!osdev) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "invalid qdf dev context");
+ return;
+ }
+
+ pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+ if (!pdev) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "invalid txrx context");
+ return;
+ }
+
/* Connect pipe */
- ipa_connect_wdi_pipe(&ipa_ctxt->cons_pipe_in, &pipe_out);
- ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl;
- ipa_ctxt->tx_comp_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "TX PIPE Handle %d, DBPA 0x%llx",
- ipa_ctxt->tx_pipe_handle,
- (unsigned long long) pipe_out.uc_door_bell_pa);
+ ret = hdd_ipa_wdi_conn_pipes(ipa_ctxt, ipa_res);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa wdi conn pipes failed ret=%d", ret);
+ return;
+ }
- ipa_connect_wdi_pipe(&ipa_ctxt->prod_pipe_in, &pipe_out);
- ipa_ctxt->rx_pipe_handle = pipe_out.clnt_hdl;
- ipa_ctxt->rx_ready_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "RX PIPE Handle %d, DBPA 0x%llx",
- ipa_ctxt->rx_pipe_handle,
- (unsigned long long) pipe_out.uc_door_bell_pa);
+ if (hdd_ipa_wdi_is_smmu_enabled(ipa_ctxt, osdev)) {
+ pld_smmu_map(osdev->dev,
+ ipa_ctxt->tx_comp_doorbell_dmaaddr,
+ &tx_comp_db_dmaaddr,
+ sizeof(uint32_t));
+ ipa_ctxt->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
+
+ pld_smmu_map(osdev->dev,
+ ipa_ctxt->rx_ready_doorbell_dmaaddr,
+ &rx_rdy_db_dmaaddr,
+ sizeof(uint32_t));
+ ipa_ctxt->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
+ }
+
+ ol_txrx_ipa_uc_set_doorbell_paddr(pdev,
+ ipa_ctxt->tx_comp_doorbell_dmaaddr,
+ ipa_ctxt->rx_ready_doorbell_dmaaddr);
/* If already any STA connected, enable IPA/FW PIPEs */
if (ipa_ctxt->sap_num_connected_sta) {
@@ -2678,7 +4275,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
}
hdd_ipa_uc_proc_pending_event(hdd_ipa, true);
if (hdd_ipa->pending_cons_req)
- ipa_rm_notify_completion(
+ hdd_ipa_wdi_rm_notify_completion(
IPA_RM_RESOURCE_GRANTED,
IPA_RM_RESOURCE_WLAN_CONS);
hdd_ipa->pending_cons_req = false;
@@ -2704,7 +4301,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
hdd_ipa->resource_unloading = false;
complete(&hdd_ipa->ipa_resource_comp);
if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- ipa_rm_release_resource(
+ hdd_ipa_wdi_rm_release_resource(hdd_ipa,
IPA_RM_RESOURCE_WLAN_PROD);
hdd_ipa_uc_proc_pending_event(hdd_ipa, false);
hdd_ipa->pending_cons_req = false;
@@ -2911,162 +4508,6 @@ static void hdd_ipa_init_uc_op_work(struct work_struct *work,
INIT_WORK(work, work_handler);
}
-#ifdef FEATURE_METERING
-/**
- * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
- * IPA calls to get WLAN stats or set quota limit.
- * @priv: pointer to private data registered with IPA (we register a
- *» pointer to the global IPA context)
- * @evt: the IPA event which triggered the callback
- * @data: data associated with the event
- *
- * Return: None
- */
-static void __hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
- void *data)
-{
- struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
- hdd_adapter_t *adapter = NULL;
- struct ipa_get_wdi_sap_stats *wdi_sap_stats;
- struct ipa_set_wifi_quota *ipa_set_quota;
- int ret = 0;
-
- if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
- return;
-
- adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event=%d", evt);
-
- switch (evt) {
- case IPA_GET_WDI_SAP_STATS:
- /* fill-up ipa_get_wdi_sap_stats structure after getting
- * ipa_uc_fw_stats from FW
- */
- wdi_sap_stats = data;
-
- if (!adapter) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "IPA uC share stats failed - no adapter");
- wdi_sap_stats->stats_valid = 0;
- return;
- }
-
- INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
- hdd_ipa_uc_sharing_stats_request(adapter,
- wdi_sap_stats->reset_stats);
- ret = wait_for_completion_timeout(
- &hdd_ipa->ipa_uc_sharing_stats_comp,
- msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
- if (!ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "IPA uC share stats request timed out");
- wdi_sap_stats->stats_valid = 0;
- } else {
- wdi_sap_stats->stats_valid = 1;
-
- wdi_sap_stats->ipv4_rx_packets =
- hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
- wdi_sap_stats->ipv4_rx_bytes =
- hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
- wdi_sap_stats->ipv6_rx_packets =
- hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
- wdi_sap_stats->ipv6_rx_bytes =
- hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
- wdi_sap_stats->ipv4_tx_packets =
- hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
- wdi_sap_stats->ipv4_tx_bytes =
- hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
- wdi_sap_stats->ipv6_tx_packets =
- hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
- wdi_sap_stats->ipv6_tx_bytes =
- hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
- HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
- "%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
- "IPA_GET_WDI_SAP_STATS",
- wdi_sap_stats->stats_valid,
- wdi_sap_stats->ipv4_rx_packets,
- wdi_sap_stats->ipv4_rx_bytes,
- wdi_sap_stats->ipv6_rx_packets,
- wdi_sap_stats->ipv6_rx_bytes,
- wdi_sap_stats->ipv4_tx_packets,
- wdi_sap_stats->ipv4_tx_bytes,
- wdi_sap_stats->ipv6_tx_packets,
- wdi_sap_stats->ipv6_tx_bytes);
- }
- break;
- case IPA_SET_WIFI_QUOTA:
- /* Get ipa_set_wifi_quota structure from IPA and pass to FW
- * through quota_exceeded field in ipa_uc_fw_stats
- */
- ipa_set_quota = data;
-
- if (!adapter) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "IPA uC set quota failed - no adapter");
- ipa_set_quota->set_valid = 0;
- return;
- }
-
- INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
- hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
- ipa_set_quota->quota_bytes);
-
- ret = wait_for_completion_timeout(
- &hdd_ipa->ipa_uc_set_quota_comp,
- msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
- if (!ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "IPA uC set quota request timed out");
- ipa_set_quota->set_valid = 0;
- } else {
- ipa_set_quota->quota_bytes =
- ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
- <<32)|hdd_ipa->ipa_quota_rsp.quota_lo;
- ipa_set_quota->set_valid =
- hdd_ipa->ipa_quota_rsp.success;
- }
-
- HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
- ipa_set_quota->quota_bytes,
- ipa_set_quota->set_valid);
- break;
- }
-}
-
-/**
- * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
- * IPA calls to get WLAN stats or set quota limit.
- * @priv: pointer to private data registered with IPA (we register a
- *» pointer to the global IPA context)
- * @evt: the IPA event which triggered the callback
- * @data: data associated with the event
- *
- * Return: None
- */
-static void hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
- void *data)
-{
- cds_ssr_protect(__func__);
- __hdd_ipa_wdi_meter_notifier_cb(evt, data);
- cds_ssr_unprotect(__func__);
-}
-
-static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt,
- struct ipa_wdi_in_params *pipe_in)
-{
- pipe_in->wdi_notify = hdd_ipa_wdi_meter_notifier_cb;
-
- init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
- init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
-}
-#else
-static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt,
- struct ipa_wdi_in_params *pipe_in)
-{
-}
-#endif
-
/**
* hdd_ipa_uc_ol_init() - Initialize IPA uC offload
* @hdd_ctx: Global HDD context
@@ -3079,12 +4520,10 @@ static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt,
*/
QDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx)
{
- struct ipa_wdi_in_params pipe_in;
- struct ipa_wdi_out_params pipe_out;
struct hdd_ipa_priv *ipa_ctxt = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
struct ol_txrx_ipa_resources *ipa_res = &ipa_ctxt->ipa_resource;
struct ol_txrx_pdev_t *pdev = NULL;
- int i, ret;
+ int i;
QDF_STATUS stat = QDF_STATUS_SUCCESS;
qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
@@ -3124,207 +4563,32 @@ QDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx)
stat = QDF_STATUS_E_FAILURE;
goto fail_return;
}
- qdf_mem_zero(&ipa_ctxt->cons_pipe_in, sizeof(struct ipa_wdi_in_params));
- qdf_mem_zero(&ipa_ctxt->prod_pipe_in, sizeof(struct ipa_wdi_in_params));
- qdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi_in_params));
- qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params));
-
- /* TX PIPE */
- pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_additional_const_len =
- HDD_IPA_UC_WLAN_8023_HDR_SIZE;
- pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
- pipe_in.sys.client = IPA_CLIENT_WLAN1_CONS;
- pipe_in.sys.desc_fifo_sz = hdd_ctx->config->IpaDescSize;
- pipe_in.sys.priv = hdd_ctx->hdd_ipa;
- pipe_in.sys.ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
- pipe_in.sys.notify = hdd_ipa_i2w_cb;
- if (!hdd_ipa_is_rm_enabled(hdd_ctx)) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "IPA RM DISABLED, IPA AWAKE");
- pipe_in.sys.keep_ipa_awake = true;
- }
-
- pipe_in.smmu_enabled = qdf_mem_smmu_s1_enabled(osdev);
- if (pipe_in.smmu_enabled) {
- qdf_mem_copy(&pipe_in.u.dl_smmu.comp_ring,
- &ipa_res->tx_comp_ring->sgtable,
- sizeof(sgtable_t));
-
- qdf_mem_copy(&pipe_in.u.dl_smmu.ce_ring,
- &ipa_res->ce_sr->sgtable,
- sizeof(sgtable_t));
- pipe_in.u.dl_smmu.comp_ring_size =
- ipa_res->tx_comp_ring->mem_info.size;
- pipe_in.u.dl_smmu.ce_ring_size =
- ipa_res->ce_sr_ring_size;
- pipe_in.u.dl_smmu.ce_door_bell_pa =
- ipa_res->ce_reg_paddr;
- pipe_in.u.dl_smmu.num_tx_buffers =
- ipa_res->tx_num_alloc_buffer;
- } else {
- pipe_in.u.dl.comp_ring_base_pa =
- qdf_mem_get_dma_addr(osdev,
- &ipa_res->tx_comp_ring->mem_info);
- pipe_in.u.dl.ce_ring_base_pa =
- qdf_mem_get_dma_addr(osdev,
- &ipa_res->ce_sr->mem_info);
- pipe_in.u.dl.comp_ring_size =
- ipa_res->tx_comp_ring->mem_info.size;
- pipe_in.u.dl.ce_door_bell_pa = ipa_res->ce_reg_paddr;
- pipe_in.u.dl.ce_ring_size =
- ipa_res->ce_sr_ring_size;
- pipe_in.u.dl.num_tx_buffers =
- ipa_res->tx_num_alloc_buffer;
- }
-
- qdf_mem_copy(&ipa_ctxt->cons_pipe_in, &pipe_in,
- sizeof(struct ipa_wdi_in_params));
- hdd_ipa_uc_get_db_paddr(&ipa_ctxt->tx_comp_doorbell_dmaaddr,
- IPA_CLIENT_WLAN1_CONS);
- if (true == ipa_ctxt->uc_loaded) {
- /* Connect WDI IPA PIPE */
- ret = ipa_connect_wdi_pipe(&ipa_ctxt->cons_pipe_in, &pipe_out);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "ipa_connect_wdi_pipe failed for Tx: ret=%d",
- ret);
+ if (ipa_ctxt->uc_loaded) {
+ if (hdd_ipa_wdi_conn_pipes(ipa_ctxt, ipa_res)) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+ "IPA CONN PIPES failed");
stat = QDF_STATUS_E_FAILURE;
goto fail_return;
}
- /* Micro Controller Doorbell register */
- ipa_ctxt->tx_comp_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
-
- /* WLAN TX PIPE Handle */
- ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl;
-
- if (ipa_ctxt->tx_pipe_handle == 0) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "TX Handle zero");
- QDF_BUG(0);
+ if (hdd_ipa_wdi_is_smmu_enabled(ipa_ctxt, osdev)) {
+ pld_smmu_map(osdev->dev,
+ ipa_ctxt->tx_comp_doorbell_dmaaddr,
+ &tx_comp_db_dmaaddr,
+ sizeof(uint32_t));
+ ipa_ctxt->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
+
+ pld_smmu_map(osdev->dev,
+ ipa_ctxt->rx_ready_doorbell_dmaaddr,
+ &rx_rdy_db_dmaaddr,
+ sizeof(uint32_t));
+ ipa_ctxt->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
}
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "CONS DB pipe out 0x%x TX PIPE Handle 0x%x",
- (unsigned int)pipe_out.uc_door_bell_pa,
- ipa_ctxt->tx_pipe_handle);
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "TX : CRBPA 0x%x, CRS %d, CERBPA 0x%x, CEDPA 0x%x,"
- " CERZ %d, NB %d, CDBPAD 0x%x",
- (unsigned int)pipe_in.u.dl.comp_ring_base_pa,
- pipe_in.u.dl.comp_ring_size,
- (unsigned int)pipe_in.u.dl.ce_ring_base_pa,
- (unsigned int)pipe_in.u.dl.ce_door_bell_pa,
- pipe_in.u.dl.ce_ring_size,
- pipe_in.u.dl.num_tx_buffers,
- (unsigned int)ipa_ctxt->tx_comp_doorbell_dmaaddr);
- }
-
- /* RX PIPE */
- pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_RX_HDR_LEN;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0;
- pipe_in.sys.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1;
- pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
- pipe_in.sys.client = IPA_CLIENT_WLAN1_PROD;
- pipe_in.sys.desc_fifo_sz = hdd_ctx->config->IpaDescSize +
- sizeof(struct sps_iovec);
- pipe_in.sys.notify = hdd_ipa_w2i_cb;
- if (!hdd_ipa_is_rm_enabled(hdd_ctx)) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "IPA RM DISABLED, IPA AWAKE");
- pipe_in.sys.keep_ipa_awake = true;
- }
-
- pipe_in.smmu_enabled = qdf_mem_smmu_s1_enabled(osdev);
- if (pipe_in.smmu_enabled) {
- qdf_mem_copy(&pipe_in.u.ul_smmu.rdy_ring,
- &ipa_res->rx_rdy_ring->sgtable,
- sizeof(sgtable_t));
- pipe_in.u.ul_smmu.rdy_ring_size =
- ipa_res->rx_rdy_ring->mem_info.size;
- pipe_in.u.ul_smmu.rdy_ring_rp_pa =
- ipa_res->rx_proc_done_idx->mem_info.pa;
-
- pipe_in.u.ul_smmu.rdy_ring_rp_va =
- ipa_res->rx_proc_done_idx->vaddr;
-
- qdf_mem_copy(&pipe_in.u.ul_smmu.rdy_comp_ring,
- &ipa_res->rx2_rdy_ring->sgtable,
- sizeof(sgtable_t));
-
- pipe_in.u.ul_smmu.rdy_comp_ring_size =
- ipa_res->rx2_rdy_ring->mem_info.size;
-
- pipe_in.u.ul_smmu.rdy_comp_ring_wp_pa =
- ipa_res->rx2_proc_done_idx->mem_info.pa;
-
- pipe_in.u.ul_smmu.rdy_comp_ring_wp_va =
- ipa_res->rx2_proc_done_idx->vaddr;
- } else {
- pipe_in.u.ul.rdy_ring_base_pa =
- ipa_res->rx_rdy_ring->mem_info.pa;
- pipe_in.u.ul.rdy_ring_size =
- ipa_res->rx_rdy_ring->mem_info.size;
- pipe_in.u.ul.rdy_ring_rp_pa =
- ipa_res->rx_proc_done_idx->mem_info.pa;
- HDD_IPA_WDI2_SET(pipe_in, ipa_ctxt, osdev);
- }
-
- hdd_ipa_init_metering(ipa_ctxt, &pipe_in);
-
- qdf_mem_copy(&ipa_ctxt->prod_pipe_in, &pipe_in,
- sizeof(struct ipa_wdi_in_params));
- hdd_ipa_uc_get_db_paddr(&ipa_ctxt->rx_ready_doorbell_dmaaddr,
- IPA_CLIENT_WLAN1_PROD);
-
- if (true == ipa_ctxt->uc_loaded) {
- ret = ipa_connect_wdi_pipe(&ipa_ctxt->prod_pipe_in, &pipe_out);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "ipa_connect_wdi_pipe failed for Rx: ret=%d",
- ret);
- stat = QDF_STATUS_E_FAILURE;
- ret = ipa_disconnect_wdi_pipe(ipa_ctxt->tx_pipe_handle);
- if (ret)
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "disconnect failed for TX: ret=%d",
- ret);
- goto fail_return;
- }
- ipa_ctxt->rx_ready_doorbell_dmaaddr = pipe_out.uc_door_bell_pa;
- ipa_ctxt->rx_pipe_handle = pipe_out.clnt_hdl;
- if (ipa_ctxt->rx_pipe_handle == 0) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "RX Handle zero");
- QDF_BUG(0);
- }
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "PROD DB pipe out 0x%x RX PIPE Handle 0x%x",
- (unsigned int)pipe_out.uc_door_bell_pa,
- ipa_ctxt->rx_pipe_handle);
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "RX : RRBPA 0x%x, RRS %d, PDIPA 0x%x, RDY_DB_PAD 0x%x",
- (unsigned int)pipe_in.u.ul.rdy_ring_base_pa,
- pipe_in.u.ul.rdy_ring_size,
- (unsigned int)pipe_in.u.ul.rdy_ring_rp_pa,
- (unsigned int)ipa_ctxt->rx_ready_doorbell_dmaaddr);
- }
-
- if (qdf_mem_smmu_s1_enabled(osdev)) {
- pld_smmu_map(osdev->dev, ipa_ctxt->tx_comp_doorbell_dmaaddr,
- &tx_comp_db_dmaaddr, sizeof(uint32_t));
- ipa_ctxt->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
-
- pld_smmu_map(osdev->dev, ipa_ctxt->rx_ready_doorbell_dmaaddr,
- &rx_rdy_db_dmaaddr, sizeof(uint32_t));
- ipa_ctxt->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
+ ol_txrx_ipa_uc_set_doorbell_paddr(pdev,
+ ipa_ctxt->tx_comp_doorbell_dmaaddr,
+ ipa_ctxt->rx_ready_doorbell_dmaaddr);
}
for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
@@ -3333,10 +4597,6 @@ QDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx)
ipa_ctxt->uc_op_work[i].msg = NULL;
}
- ol_txrx_ipa_uc_set_doorbell_paddr(pdev,
- ipa_ctxt->tx_comp_doorbell_dmaaddr,
- ipa_ctxt->rx_ready_doorbell_dmaaddr);
-
ol_txrx_ipa_uc_register_op_cb(pdev,
hdd_ipa_uc_op_event_handler,
(void *)hdd_ctx);
@@ -3386,16 +4646,8 @@ int hdd_ipa_uc_ol_deinit(hdd_context_t *hdd_ctx)
if (!hdd_ipa->ipa_pipes_down)
hdd_ipa_uc_disable_pipes(hdd_ipa);
- if (true == hdd_ipa->uc_loaded) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "Disconnect TX PIPE tx_pipe_handle=0x%x",
- hdd_ipa->tx_pipe_handle);
- ret = ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle);
- HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
- "Disconnect RX PIPE rx_pipe_handle=0x%x",
- hdd_ipa->rx_pipe_handle);
- ret = ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle);
- }
+ if (true == hdd_ipa->uc_loaded)
+ ret = hdd_ipa_wdi_disconn_pipes(hdd_ipa);
qdf_mutex_acquire(&hdd_ipa->ipa_lock);
hdd_ipa_cleanup_pending_event(hdd_ipa);
@@ -3871,245 +5123,6 @@ struct sk_buff *hdd_ipa_tx_packet_ipa(hdd_context_t *hdd_ctx,
}
/**
- * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
- * @work: scheduled work
- *
- * When IPA resources are released in hdd_ipa_rm_try_release() we do
- * not want to immediately release the wake lock since the system
- * would then potentially try to suspend when there is a healthy data
- * rate. Deferred work is scheduled and this function handles the
- * work. When this function is called, if the IPA resource is still
- * released then we release the wake lock.
- *
- * Return: None
- */
-static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
-{
- struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
- struct hdd_ipa_priv,
- wake_lock_work);
-
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-
- if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
- goto end;
-
- hdd_ipa->wake_lock_released = true;
- qdf_wake_lock_release(&hdd_ipa->wake_lock,
- WIFI_POWER_EVENT_WAKELOCK_IPA);
-
-end:
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-}
-
-/**
- * hdd_ipa_rm_request() - Request resource from IPA
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 on success, negative errno on error
- */
-static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa)
-{
- int ret = 0;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return 0;
-
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-
- switch (hdd_ipa->rm_state) {
- case HDD_IPA_RM_GRANTED:
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
- return 0;
- case HDD_IPA_RM_GRANT_PENDING:
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
- return -EINPROGRESS;
- case HDD_IPA_RM_RELEASED:
- hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
- break;
- }
-
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
- ret = ipa_rm_inactivity_timer_request_resource(
- IPA_RM_RESOURCE_WLAN_PROD);
-
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
- if (ret == 0) {
- hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
- hdd_ipa->stats.num_rm_grant_imm++;
- }
-
- cancel_delayed_work(&hdd_ipa->wake_lock_work);
- if (hdd_ipa->wake_lock_released) {
- qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
- WIFI_POWER_EVENT_WAKELOCK_IPA);
- hdd_ipa->wake_lock_released = false;
- }
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
- return ret;
-}
-
-/**
- * hdd_ipa_rm_try_release() - Attempt to release IPA resource
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 if resources released, negative errno otherwise
- */
-static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
-{
- int ret = 0;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return 0;
-
- if (atomic_read(&hdd_ipa->tx_ref_cnt))
- return -EAGAIN;
-
- qdf_spin_lock_bh(&hdd_ipa->pm_lock);
-
- if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
- qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
- return -EAGAIN;
- }
- qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
-
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
- switch (hdd_ipa->rm_state) {
- case HDD_IPA_RM_GRANTED:
- break;
- case HDD_IPA_RM_GRANT_PENDING:
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
- return -EINPROGRESS;
- case HDD_IPA_RM_RELEASED:
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
- return 0;
- }
-
- /* IPA driver returns immediately so set the state here to avoid any
- * race condition.
- */
- hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
- hdd_ipa->stats.num_rm_release++;
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
- ret = ipa_rm_inactivity_timer_release_resource(
- IPA_RM_RESOURCE_WLAN_PROD);
-
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
- if (unlikely(ret != 0)) {
- hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
- WARN_ON(1);
- HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
- "ipa_rm_inactivity_timer_release_resource returnied fail");
- }
-
- /*
- * If wake_lock is released immediately, kernel would try to suspend
- * immediately as well, Just avoid ping-pong between suspend-resume
- * while there is healthy amount of data transfer going on by
- * releasing the wake_lock after some delay.
- */
- schedule_delayed_work(&hdd_ipa->wake_lock_work,
- msecs_to_jiffies
- (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
-
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
- return ret;
-}
-
-/**
- * hdd_ipa_rm_notify() - IPA resource manager notifier callback
- * @user_data: user data registered with IPA
- * @event: the IPA resource manager event that occurred
- * @data: the data associated with the event
- *
- * Return: None
- */
-static void hdd_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
- unsigned long data)
-{
- struct hdd_ipa_priv *hdd_ipa = user_data;
-
- if (unlikely(!hdd_ipa))
- return;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return;
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
-
- switch (event) {
- case IPA_RM_RESOURCE_GRANTED:
- if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
- /* RM Notification comes with ISR context
- * it should be serialized into work queue to avoid
- * ISR sleep problem
- */
- hdd_ipa->uc_rm_work.event = event;
- schedule_work(&hdd_ipa->uc_rm_work.work);
- break;
- }
- qdf_spin_lock_bh(&hdd_ipa->rm_lock);
- hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
- qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
- hdd_ipa->stats.num_rm_grant++;
- break;
-
- case IPA_RM_RESOURCE_RELEASED:
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
- hdd_ipa->resource_unloading = false;
- break;
-
- default:
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
- break;
- }
-}
-
-/**
- * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
- *
- * Callback function registered with IPA that is called when IPA wants
- * to release the WLAN consumer resource
- *
- * Return: 0 if the request is granted, negative errno otherwise
- */
-static int hdd_ipa_rm_cons_release(void)
-{
- return 0;
-}
-
-/**
- * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
- *
- * Callback function registered with IPA that is called when IPA wants
- * to access the WLAN consumer resource
- *
- * Return: 0 if the request is granted, negative errno otherwise
- */
-static int hdd_ipa_rm_cons_request(void)
-{
- int ret = 0;
-
- if (ghdd_ipa->resource_loading) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
- "IPA resource loading in progress");
- ghdd_ipa->pending_cons_req = true;
- ret = -EINPROGRESS;
- } else if (ghdd_ipa->resource_unloading) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
- "IPA resource unloading in progress");
- ghdd_ipa->pending_cons_req = true;
- ret = -EPERM;
- }
-
- return ret;
-}
-
-/**
* __hdd_ipa_set_perf_level() - Set IPA performance level
* @hdd_ctx: Global HDD context
* @tx_packets: Number of packets transmitted in the last sample period
@@ -4163,8 +5176,8 @@ static int __hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets,
hdd_debug("Requesting CONS perf curr: %d, next: %d",
hdd_ipa->curr_cons_bw, next_cons_bw);
profile.max_supported_bandwidth_mbps = next_cons_bw;
- ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS,
- &profile);
+ ret = hdd_ipa_wdi_rm_set_perf_profile(hdd_ipa,
+ IPA_RM_RESOURCE_WLAN_CONS, &profile);
if (ret) {
hdd_err("RM CONS set perf profile failed: %d", ret);
@@ -4178,8 +5191,8 @@ static int __hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets,
hdd_debug("Requesting PROD perf curr: %d, next: %d",
hdd_ipa->curr_prod_bw, next_prod_bw);
profile.max_supported_bandwidth_mbps = next_prod_bw;
- ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD,
- &profile);
+ ret = hdd_ipa_wdi_rm_set_perf_profile(hdd_ipa,
+ IPA_RM_RESOURCE_WLAN_PROD, &profile);
if (ret) {
hdd_err("RM PROD set perf profile failed: %d", ret);
return ret;
@@ -4211,138 +5224,7 @@ int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets,
return ret;
}
-/**
- * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
- * @work: struct work_struct
- * @work_handler: work_handler
- *
- * Return: none
- */
-static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
- work_func_t work_handler)
-{
- INIT_WORK(work, work_handler);
-}
-
-/**
- * hdd_ipa_setup_rm() - Setup IPA resource management
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 on success, negative errno on error
- */
-static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa)
-{
- struct ipa_rm_create_params create_params = { 0 };
- int ret;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return 0;
-
- hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
- hdd_ipa_uc_rm_notify_defer);
- memset(&create_params, 0, sizeof(create_params));
- create_params.name = IPA_RM_RESOURCE_WLAN_PROD;
- create_params.reg_params.user_data = hdd_ipa;
- create_params.reg_params.notify_cb = hdd_ipa_rm_notify;
- create_params.floor_voltage = IPA_VOLTAGE_SVS;
-
- ret = ipa_rm_create_resource(&create_params);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Create RM resource failed: %d", ret);
- goto setup_rm_fail;
- }
-
- memset(&create_params, 0, sizeof(create_params));
- create_params.name = IPA_RM_RESOURCE_WLAN_CONS;
- create_params.request_resource = hdd_ipa_rm_cons_request;
- create_params.release_resource = hdd_ipa_rm_cons_release;
- create_params.floor_voltage = IPA_VOLTAGE_SVS;
-
- ret = ipa_rm_create_resource(&create_params);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Create RM CONS resource failed: %d", ret);
- goto delete_prod;
- }
-
- ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
- IPA_RM_RESOURCE_APPS_CONS);
-
- ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
- HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
- ret);
- goto timer_init_failed;
- }
-
- /* Set the lowest bandwidth to start with */
- ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
-
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Set perf level failed: %d", ret);
- goto set_perf_failed;
- }
-
- qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
- INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
- hdd_ipa_wake_lock_timer_func);
- qdf_spinlock_create(&hdd_ipa->rm_lock);
- hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
- hdd_ipa->wake_lock_released = true;
- atomic_set(&hdd_ipa->tx_ref_cnt, 0);
-
- return ret;
-
-set_perf_failed:
- ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
-
-timer_init_failed:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
-
-delete_prod:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
-
-setup_rm_fail:
- return ret;
-}
-
-/**
- * hdd_ipa_destroy_rm_resource() - Destroy IPA resources
- * @hdd_ipa: Global HDD IPA context
- *
- * Destroys all resources associated with the IPA resource manager
- *
- * Return: None
- */
-static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa)
-{
- int ret;
-
- if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
- return;
-
- cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
- qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
- cancel_work_sync(&hdd_ipa->uc_rm_work.work);
- qdf_spinlock_destroy(&hdd_ipa->rm_lock);
-
- ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
-
- ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
- if (ret)
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "RM PROD resource delete failed %d", ret);
-
- ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
- if (ret)
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "RM CONS resource delete failed %d", ret);
-}
-
-#ifdef PF_WAKE_UP_IDLE
+#ifdef QCA_CONFIG_SMP
/**
* hdd_ipa_get_wake_up_idle() - Get PF_WAKE_UP_IDLE flag in the task structure
*
@@ -4368,7 +5250,12 @@ static void hdd_ipa_set_wake_up_idle(bool wake_up_idle)
sched_set_wake_up_idle(current, wake_up_idle);
}
-#else
+
+static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
+{
+ return netif_rx_ni(skb);
+}
+#else /* QCA_CONFIG_SMP */
static uint32_t hdd_ipa_get_wake_up_idle(void)
{
return 0;
@@ -4377,14 +5264,7 @@ static uint32_t hdd_ipa_get_wake_up_idle(void)
static void hdd_ipa_set_wake_up_idle(bool wake_up_idle)
{
}
-#endif
-#ifdef QCA_CONFIG_SMP
-static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
-{
- return netif_rx_ni(skb);
-}
-#else
static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
{
struct iphdr *ip_h;
@@ -4411,7 +5291,7 @@ static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
return result;
}
-#endif
+#endif /* QCA_CONFIG_SMP */
/**
* hdd_ipa_send_skb_to_network() - Send skb to kernel
@@ -4757,7 +5637,7 @@ void hdd_ipa_nbuf_cb(qdf_nbuf_t skb)
atomic_dec(&hdd_ipa->tx_ref_cnt);
- hdd_ipa_rm_try_release(hdd_ipa);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
}
/**
@@ -4783,7 +5663,7 @@ static void hdd_ipa_send_pkt_to_tl(
ipa_free_skb(ipa_tx_desc);
iface_context->stats.num_tx_drop++;
qdf_spin_unlock_bh(&iface_context->interface_lock);
- hdd_ipa_rm_try_release(hdd_ipa);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
return;
}
@@ -4797,7 +5677,7 @@ static void hdd_ipa_send_pkt_to_tl(
ipa_free_skb(ipa_tx_desc);
qdf_spin_unlock_bh(&iface_context->interface_lock);
iface_context->stats.num_tx_cac_drop++;
- hdd_ipa_rm_try_release(hdd_ipa);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
return;
}
}
@@ -4837,7 +5717,7 @@ static void hdd_ipa_send_pkt_to_tl(
hdd_ipa->stats.num_tx_desc_error++;
qdf_spin_unlock_bh(&hdd_ipa->q_lock);
ipa_free_skb(ipa_tx_desc);
- hdd_ipa_rm_try_release(hdd_ipa);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
return;
}
@@ -4979,7 +5859,7 @@ static void __hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt,
* workaround to request PROD resource while data is going over CONS
* pipe to prevent the IPA hardware clockdown.
*/
- hdd_ipa_rm_request(hdd_ipa);
+ hdd_ipa_wdi_rm_request(hdd_ipa);
qdf_spin_lock_bh(&hdd_ipa->pm_lock);
/*
@@ -5233,7 +6113,8 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
ipa->keep_ipa_awake = 1;
- ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl));
+ ret = hdd_ipa_wdi_setup_sys_pipe(hdd_ipa, ipa,
+ &(hdd_ipa->sys_pipe[i].conn_hdl));
if (ret) {
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
"Failed for pipe %d ret: %d", i, ret);
@@ -5270,7 +6151,8 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
ipa->keep_ipa_awake = 1;
- ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl));
+ ret = hdd_ipa_wdi_setup_sys_pipe(hdd_ipa, ipa,
+ &(hdd_ipa->sys_pipe[i].conn_hdl));
if (ret) {
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
"Failed for RX pipe: %d", ret);
@@ -5293,7 +6175,8 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
setup_sys_pipe_fail:
while (--i >= 0) {
- ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].conn_hdl);
+ hdd_ipa_wdi_teardown_sys_pipe(hdd_ipa,
+ hdd_ipa->sys_pipe[i].conn_hdl);
qdf_mem_zero(&hdd_ipa->sys_pipe[i],
sizeof(struct hdd_ipa_sys_pipe));
}
@@ -5315,9 +6198,8 @@ static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
if (hdd_ipa->sys_pipe[i].conn_hdl_valid) {
- ret =
- ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].
- conn_hdl);
+ ret = hdd_ipa_wdi_teardown_sys_pipe(hdd_ipa,
+ hdd_ipa->sys_pipe[i].conn_hdl);
if (ret)
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Failed: %d",
ret);
@@ -5344,348 +6226,6 @@ static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
}
/**
- * hdd_ipa_register_interface() - register IPA interface
- * @hdd_ipa: Global IPA context
- * @iface_context: Per-interface IPA context
- *
- * Return: 0 on success, negative errno on error
- */
-static int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa,
- struct hdd_ipa_iface_context
- *iface_context)
-{
- struct ipa_tx_intf tx_intf;
- struct ipa_rx_intf rx_intf;
- struct ipa_ioc_tx_intf_prop *tx_prop = NULL;
- struct ipa_ioc_rx_intf_prop *rx_prop = NULL;
- char *ifname = iface_context->adapter->dev->name;
-
- char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
- char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
-
- int num_prop = 1;
- int ret = 0;
-
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx))
- num_prop++;
-
- /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
- tx_prop =
- qdf_mem_malloc(sizeof(struct ipa_ioc_tx_intf_prop) * num_prop);
- if (!tx_prop) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "tx_prop allocation failed");
- goto register_interface_fail;
- }
-
- /* Allocate RX properties, 1 each for IPv4 & IPv6 */
- rx_prop =
- qdf_mem_malloc(sizeof(struct ipa_ioc_rx_intf_prop) * num_prop);
- if (!rx_prop) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "rx_prop allocation failed");
- goto register_interface_fail;
- }
-
- qdf_mem_zero(&tx_intf, sizeof(tx_intf));
- qdf_mem_zero(&rx_intf, sizeof(rx_intf));
-
- snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV4_NAME_EXT);
- snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV6_NAME_EXT);
-
- rx_prop[IPA_IP_v4].ip = IPA_IP_v4;
- rx_prop[IPA_IP_v4].src_pipe = iface_context->prod_client;
- rx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA;
-
- /*
- * Interface ID is 3rd byte in the CLD header. Add the meta data and
- * mask to identify the interface in IPA hardware
- */
- rx_prop[IPA_IP_v4].attrib.meta_data =
- htonl(iface_context->adapter->sessionId << 16);
- rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
-
- rx_intf.num_props++;
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
- rx_prop[IPA_IP_v6].ip = IPA_IP_v6;
- rx_prop[IPA_IP_v6].src_pipe = iface_context->prod_client;
- rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA;
- rx_prop[IPA_IP_v4].attrib.meta_data =
- htonl(iface_context->adapter->sessionId << 16);
- rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
-
- rx_intf.num_props++;
- }
-
- tx_prop[IPA_IP_v4].ip = IPA_IP_v4;
- tx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- tx_prop[IPA_IP_v4].dst_pipe = IPA_CLIENT_WLAN1_CONS;
- tx_prop[IPA_IP_v4].alt_dst_pipe = iface_context->cons_client;
- strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name,
- IPA_RESOURCE_NAME_MAX);
- tx_intf.num_props++;
-
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
- tx_prop[IPA_IP_v6].ip = IPA_IP_v6;
- tx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- tx_prop[IPA_IP_v6].dst_pipe = IPA_CLIENT_WLAN1_CONS;
- tx_prop[IPA_IP_v6].alt_dst_pipe = iface_context->cons_client;
- strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name,
- IPA_RESOURCE_NAME_MAX);
- tx_intf.num_props++;
- }
-
- tx_intf.prop = tx_prop;
- rx_intf.prop = rx_prop;
-
- /* Call the ipa api to register interface */
- ret = ipa_register_intf(ifname, &tx_intf, &rx_intf);
-
- /* Register IPA Tx desc free callback */
- qdf_nbuf_reg_free_cb(hdd_ipa_nbuf_cb);
-
-register_interface_fail:
- qdf_mem_free(tx_prop);
- qdf_mem_free(rx_prop);
- return ret;
-}
-
-/**
- * hdd_remove_ipa_header() - Remove a specific header from IPA
- * @name: Name of the header to be removed
- *
- * Return: None
- */
-static void hdd_ipa_remove_header(char *name)
-{
- struct ipa_ioc_get_hdr hdrlookup;
- int ret = 0, len;
- struct ipa_ioc_del_hdr *ipa_hdr;
-
- qdf_mem_zero(&hdrlookup, sizeof(hdrlookup));
- strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name));
- ret = ipa_get_hdr(&hdrlookup);
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Hdr deleted already %s, %d",
- name, ret);
- return;
- }
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "hdl: 0x%x", hdrlookup.hdl);
- len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del) * 1;
- ipa_hdr = (struct ipa_ioc_del_hdr *)qdf_mem_malloc(len);
- if (ipa_hdr == NULL) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "ipa_hdr allocation failed");
- return;
- }
- ipa_hdr->num_hdls = 1;
- ipa_hdr->commit = 0;
- ipa_hdr->hdl[0].hdl = hdrlookup.hdl;
- ipa_hdr->hdl[0].status = -1;
- ret = ipa_del_hdr(ipa_hdr);
- if (ret != 0)
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Delete header failed: %d",
- ret);
-
- qdf_mem_free(ipa_hdr);
-}
-
-/**
- * wlan_ipa_add_hdr() - Add IPA Tx header
- * @ipa_hdr: pointer to IPA header addition parameters
- *
- * Call IPA API to add IPA Tx header descriptor
- * and dump Tx header struct
- *
- * Return: 0 for success, non-zero for failure
- */
-static int wlan_ipa_add_hdr(struct ipa_ioc_add_hdr *ipa_hdr)
-{
- int ret;
-
- hdd_debug("==== IPA Tx Header ====\n"
- "name: %s\n"
- "hdr_len: %d\n"
- "type: %d\n"
- "is_partial: %d\n"
- "hdr_hdl: 0x%x\n"
- "status: %d\n"
- "is_eth2_ofst_valid: %d\n"
- "eth2_ofst: %d\n",
- ipa_hdr->hdr[0].name,
- ipa_hdr->hdr[0].hdr_len,
- ipa_hdr->hdr[0].type,
- ipa_hdr->hdr[0].is_partial,
- ipa_hdr->hdr[0].hdr_hdl,
- ipa_hdr->hdr[0].status,
- ipa_hdr->hdr[0].is_eth2_ofst_valid,
- ipa_hdr->hdr[0].eth2_ofst);
-
- HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG, "hdr:",
- ipa_hdr->hdr[0].hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN);
-
- ret = ipa_add_hdr(ipa_hdr);
- return ret;
-}
-
-/**
- * hdd_ipa_add_header_info() - Add IPA header for a given interface
- * @hdd_ipa: Global HDD IPA context
- * @iface_context: Interface-specific HDD IPA context
- * @mac_addr: Interface MAC address
- *
- * Return: 0 on success, negativer errno value on error
- */
-static int hdd_ipa_add_header_info(struct hdd_ipa_priv *hdd_ipa,
- struct hdd_ipa_iface_context *iface_context,
- uint8_t *mac_addr)
-{
- hdd_adapter_t *adapter = iface_context->adapter;
- char *ifname;
- struct ipa_ioc_add_hdr *ipa_hdr = NULL;
- int ret = -EINVAL;
- struct hdd_ipa_tx_hdr *tx_hdr = NULL;
- struct hdd_ipa_uc_tx_hdr *uc_tx_hdr = NULL;
-
- ifname = adapter->dev->name;
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Add Partial hdr: %s, %pM",
- ifname, mac_addr);
-
- /* dynamically allocate the memory to add the hdrs */
- ipa_hdr = qdf_mem_malloc(sizeof(struct ipa_ioc_add_hdr)
- + sizeof(struct ipa_hdr_add));
- if (!ipa_hdr) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "%s: ipa_hdr allocation failed", ifname);
- ret = -ENOMEM;
- goto end;
- }
-
- ipa_hdr->commit = 0;
- ipa_hdr->num_hdrs = 1;
-
- if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
- uc_tx_hdr = (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
- memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN);
- memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
- uc_tx_hdr->ipa_hd.vdev_id = iface_context->adapter->sessionId;
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "ifname=%s, vdev_id=%d",
- ifname, uc_tx_hdr->ipa_hd.vdev_id);
- snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV4_NAME_EXT);
- ipa_hdr->hdr[0].hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN;
- ipa_hdr->hdr[0].type = IPA_HDR_L2_ETHERNET_II;
- ipa_hdr->hdr[0].is_partial = 1;
- ipa_hdr->hdr[0].hdr_hdl = 0;
- ipa_hdr->hdr[0].is_eth2_ofst_valid = 1;
- ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
-
- ret = wlan_ipa_add_hdr(ipa_hdr);
- } else {
- tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr;
-
- /* Set the Source MAC */
- memcpy(tx_hdr, &ipa_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN);
- memcpy(tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
-
- snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV4_NAME_EXT);
- ipa_hdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
- ipa_hdr->hdr[0].is_partial = 1;
- ipa_hdr->hdr[0].hdr_hdl = 0;
- ipa_hdr->hdr[0].is_eth2_ofst_valid = 1;
- ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_WLAN_HDR_DES_MAC_OFFSET;
-
- /* Set the type to IPV4 in the header */
- tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IP);
-
- ret = ipa_add_hdr(ipa_hdr);
- }
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "%s: IPv4 add hdr failed: %d", ifname, ret);
- goto end;
- }
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: IPv4 hdr_hdl: 0x%x",
- ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
-
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
- snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV6_NAME_EXT);
-
- if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
- uc_tx_hdr =
- (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
- uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6);
- ret = wlan_ipa_add_hdr(ipa_hdr);
- } else {
- /* Set the type to IPV6 in the header */
- tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr;
- tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6);
- ret = ipa_add_hdr(ipa_hdr);
- }
-
- if (ret) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "%s: IPv6 add hdr failed: %d", ifname, ret);
- goto clean_ipv4_hdr;
- }
-
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: IPv6 hdr_hdl: 0x%x",
- ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
- }
-
- qdf_mem_free(ipa_hdr);
-
- return ret;
-
-clean_ipv4_hdr:
- snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV4_NAME_EXT);
- hdd_ipa_remove_header(ipa_hdr->hdr[0].name);
-end:
- if (ipa_hdr)
- qdf_mem_free(ipa_hdr);
-
- return ret;
-}
-
-/**
- * hdd_ipa_clean_hdr() - Cleanup IPA on a given adapter
- * @adapter: Adapter upon which IPA was previously configured
- *
- * Return: None
- */
-static void hdd_ipa_clean_hdr(hdd_adapter_t *adapter)
-{
- struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
- int ret;
- char name_ipa[IPA_RESOURCE_NAME_MAX];
-
- /* Remove the headers */
- snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
- adapter->dev->name, HDD_IPA_IPV4_NAME_EXT);
- hdd_ipa_remove_header(name_ipa);
-
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) {
- snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
- adapter->dev->name, HDD_IPA_IPV6_NAME_EXT);
- hdd_ipa_remove_header(name_ipa);
- }
- /* unregister the interface with IPA */
- ret = ipa_deregister_intf(adapter->dev->name);
- if (ret)
- HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
- "%s: ipa_deregister_intf fail: %d",
- adapter->dev->name, ret);
-}
-
-/**
* hdd_ipa_cleanup_iface() - Cleanup IPA on a given interface
* @iface_context: interface-specific IPA context
*
@@ -5705,7 +6245,8 @@ static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context)
return;
}
- hdd_ipa_clean_hdr(iface_context->adapter);
+ hdd_ipa_wdi_dereg_intf(iface_context->hdd_ipa,
+ iface_context->adapter->dev->name);
qdf_spin_lock_bh(&iface_context->interface_lock);
/*
@@ -5713,7 +6254,7 @@ static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context)
* and check if the address has been already cleared by the
* other thread
*/
- if (iface_context->adapter) {
+ if (!iface_context->adapter) {
qdf_spin_unlock_bh(&iface_context->interface_lock);
HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "Already cleared");
goto end;
@@ -5789,16 +6330,15 @@ static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa,
iface_context->tl_context = tl_context;
- ret = hdd_ipa_add_header_info(hdd_ipa, iface_context,
- adapter->dev->dev_addr);
-
- if (ret)
+ ret = hdd_ipa_wdi_reg_intf(hdd_ipa, iface_context);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA WDI reg intf failed ret=%d", ret);
goto end;
+ }
- /* Configure the TX and RX pipes filter rules */
- ret = hdd_ipa_register_interface(hdd_ipa, iface_context);
- if (ret)
- goto cleanup_header;
+ /* Register IPA Tx desc free callback */
+ qdf_nbuf_reg_free_cb(hdd_ipa_nbuf_cb);
hdd_ipa->num_iface++;
@@ -5806,9 +6346,6 @@ static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa,
hdd_ipa->num_iface);
return ret;
-cleanup_header:
-
- hdd_ipa_clean_hdr(adapter);
end:
if (iface_context)
hdd_ipa_cleanup_iface(iface_context);
@@ -6563,6 +7100,8 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
hdd_ipa->hdd_ctx = hdd_ctx;
hdd_ipa->num_iface = 0;
+ hdd_ipa_wdi_get_wdi_version(hdd_ipa);
+
/* Create the interface context */
for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
iface_context = &hdd_ipa->iface_context[i];
@@ -6584,7 +7123,7 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
qdf_mutex_create(&hdd_ipa->event_lock);
qdf_mutex_create(&hdd_ipa->ipa_lock);
- ret = hdd_ipa_setup_rm(hdd_ipa);
+ ret = hdd_ipa_wdi_setup_rm(hdd_ipa);
if (ret)
goto fail_setup_rm;
@@ -6609,8 +7148,18 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
INIT_WORK(&hdd_ipa->mcc_work, hdd_ipa_mcc_work_handler);
}
- if (hdd_ipa_uc_register_uc_ready(hdd_ipa))
- goto fail_create_sys_pipe;
+
+ ret = hdd_ipa_wdi_init(hdd_ipa);
+ if (ret) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "ipa wdi init failed ret=%d", ret);
+ if (ret == -EACCES) {
+ if (hdd_ipa_uc_send_wdi_control_msg(false))
+ goto fail_create_sys_pipe;
+ } else {
+ goto fail_create_sys_pipe;
+ }
+ }
} else {
ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
if (ret)
@@ -6619,19 +7168,19 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
/* When IPA clock scaling is disabled, initialze maximum clock */
if (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)) {
- profile.max_supported_bandwidth_mbps = 800;
+ profile.max_supported_bandwidth_mbps = HDD_IPA_MAX_BANDWIDTH;
hdd_debug("IPA clock scaling is disabled.");
hdd_debug("Set initial CONS/PROD perf: %d",
profile.max_supported_bandwidth_mbps);
- ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS,
- &profile);
+ ret = hdd_ipa_wdi_rm_set_perf_profile(hdd_ipa,
+ IPA_RM_RESOURCE_WLAN_CONS, &profile);
if (ret) {
hdd_err("RM CONS set perf profile failed: %d", ret);
goto fail_create_sys_pipe;
}
- ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD,
- &profile);
+ ret = hdd_ipa_wdi_rm_set_perf_profile(hdd_ipa,
+ IPA_RM_RESOURCE_WLAN_PROD, &profile);
if (ret) {
hdd_err("RM PROD set perf profile failed: %d", ret);
goto fail_create_sys_pipe;
@@ -6644,7 +7193,7 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
return QDF_STATUS_SUCCESS;
fail_create_sys_pipe:
- hdd_ipa_destroy_rm_resource(hdd_ipa);
+ hdd_ipa_wdi_destroy_rm(hdd_ipa);
fail_setup_rm:
qdf_spinlock_destroy(&hdd_ipa->pm_lock);
qdf_mem_free(hdd_ipa);
@@ -6734,8 +7283,7 @@ static QDF_STATUS __hdd_ipa_cleanup(hdd_context_t *hdd_ctx)
cancel_work_sync(&hdd_ipa->mcc_work);
}
- hdd_ipa_destroy_rm_resource(hdd_ipa);
-
+ hdd_ipa_wdi_destroy_rm(hdd_ipa);
__hdd_ipa_flush(hdd_ctx);
@@ -6749,9 +7297,7 @@ static QDF_STATUS __hdd_ipa_cleanup(hdd_context_t *hdd_ctx)
}
if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
- if (ipa_uc_dereg_rdyCB())
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "UC Ready CB deregister fail");
+ hdd_ipa_wdi_cleanup();
hdd_ipa_uc_rt_debug_deinit(hdd_ctx);
qdf_mutex_destroy(&hdd_ipa->event_lock);
qdf_mutex_destroy(&hdd_ipa->ipa_lock);
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 7daec3f41fcd..7a5bd1ac3677 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -730,13 +730,13 @@ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
if (cds_is_driver_in_bad_state()) {
hdd_debug("%pS driver in bad State: 0x%x Ignore!!!",
(void *)_RET_IP_, cds_get_driver_state());
- return -ENODEV;
+ return -EAGAIN;
}
if (cds_is_fw_down()) {
hdd_debug("%pS FW is down: 0x%x Ignore!!!",
(void *)_RET_IP_, cds_get_driver_state());
- return -ENODEV;
+ return -EAGAIN;
}
return 0;
@@ -968,7 +968,10 @@ void hdd_update_macaddr(hdd_context_t *hdd_ctx,
MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(hdd_ctx->derived_mac_addr[0].bytes));
}
- for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
+
+ for (i = hdd_ctx->num_derived_addr;
+ i < QDF_MAX_CONCURRENCY_PERSONA - hdd_ctx->num_provisioned_addr;
+ i++) {
qdf_mem_copy(hdd_ctx->derived_mac_addr[i].bytes,
hw_macaddr.bytes,
QDF_MAC_ADDR_SIZE);
@@ -3293,6 +3296,17 @@ QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
}
}
+ if (adapter->device_mode == QDF_STA_MODE) {
+ hdd_debug("setting RTT mac randomization param: %d",
+ hdd_ctx->config->enable_rtt_mac_randomization);
+ ret_val = sme_cli_set_command(adapter->sessionId,
+ WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_INITIATOR_RANDOM_MAC,
+ hdd_ctx->config->enable_rtt_mac_randomization,
+ VDEV_CMD);
+ if (0 != ret_val)
+ hdd_err("RTT mac randomization param set failed %d",
+ ret_val);
+ }
/*
* 1) When DBS hwmode is disabled from INI then send HT/VHT IE as per
* non-dbs hw mode, so that there is no limitation applied for 2G/5G.
@@ -3530,6 +3544,7 @@ static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
hdd_wmm_adapter_close(adapter);
clear_bit(WMM_INIT_DONE, &adapter->event_flags);
}
+ qdf_atomic_set(&adapter->sessionCtx.ap.acs_in_progress, 0);
wlan_hdd_undo_acs(adapter);
hdd_cleanup_actionframe(hdd_ctx, adapter);
@@ -3568,6 +3583,50 @@ void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
EXIT();
}
+#ifdef WLAN_NS_OFFLOAD
+/**
+ * hdd_ns_offload_info_lock_create() - Create mutex lock for ns offload info
+ * @adapter: pointer to adapter for which lock is to be created
+ *
+ * Return: None
+ */
+static void hdd_ns_offload_info_lock_create(hdd_adapter_t *adapter)
+{
+ qdf_mutex_create(&adapter->ns_offload_info_lock);
+}
+
+/**
+ * hdd_ns_offload_info_lock_destroy() - Destroy mutex lock for ns offload info
+ * @adapter: pointer to adapter for which lock is to be destroyed
+ *
+ * Return: None
+ */
+static void hdd_ns_offload_info_lock_destroy(hdd_adapter_t *adapter)
+{
+ qdf_mutex_destroy(&adapter->ns_offload_info_lock);
+}
+#else
+/**
+ * hdd_ns_offload_info_lock_create() - Create mutex lock for ns offload info
+ * @adapter: pointer to adapter for which lock is to be created
+ *
+ * Return: None
+ */
+static void hdd_ns_offload_info_lock_create(hdd_adapter_t *adapter)
+{
+}
+
+/**
+ * hdd_ns_offload_info_lock_destroy() - Destroy mutex lock for ns offload info
+ * @adapter: pointer to adapter for which lock is to be destroyed
+ *
+ * Return: None
+ */
+static void hdd_ns_offload_info_lock_destroy(hdd_adapter_t *adapter)
+{
+}
+#endif
+
static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
bool rtnl_held)
{
@@ -3580,6 +3639,10 @@ static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
return;
}
+ wlan_hdd_debugfs_csr_deinit(adapter);
+ qdf_mutex_destroy(&adapter->arp_offload_info_lock);
+ hdd_ns_offload_info_lock_destroy(adapter);
+
hdd_debugfs_exit(adapter);
/*
@@ -3725,50 +3788,6 @@ static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
#endif
-#ifdef WLAN_NS_OFFLOAD
-/**
- * hdd_ns_offload_info_lock_create() - Create mutex lock for ns offload info
- * @adapter: pointer to adapter for which lock is to be created
- *
- * Return: None
- */
-static void hdd_ns_offload_info_lock_create(hdd_adapter_t *adapter)
-{
- qdf_mutex_create(&adapter->ns_offload_info_lock);
-}
-
-/**
- * hdd_ns_offload_info_lock_destroy() - Destroy mutex lock for ns offload info
- * @adapter: pointer to adapter for which lock is to be destroyed
- *
- * Return: None
- */
-static void hdd_ns_offload_info_lock_destroy(hdd_adapter_t *adapter)
-{
- qdf_mutex_destroy(&adapter->ns_offload_info_lock);
-}
-#else
-/**
- * hdd_ns_offload_info_lock_create() - Create mutex lock for ns offload info
- * @adapter: pointer to adapter for which lock is to be created
- *
- * Return: None
- */
-static void hdd_ns_offload_info_lock_create(hdd_adapter_t *adapter)
-{
-}
-
-/**
- * hdd_ns_offload_info_lock_destroy() - Destroy mutex lock for ns offload info
- * @adapter: pointer to adapter for which lock is to be destroyed
- *
- * Return: None
- */
-static void hdd_ns_offload_info_lock_destroy(hdd_adapter_t *adapter)
-{
-}
-#endif
-
/**
* hdd_configure_chain_mask() - programs chain mask to firmware
* @adapter: HDD adapter
@@ -3933,6 +3952,16 @@ int hdd_set_fw_params(hdd_adapter_t *adapter)
goto error;
}
+ ret = sme_cli_set_command(
+ adapter->sessionId,
+ WMI_PDEV_PARAM_TX_SCH_DELAY,
+ hdd_ctx->config->enable_tx_sch_delay,
+ PDEV_CMD);
+ if (ret) {
+ hdd_err("Failed to set WMI_PDEV_PARAM_TX_SCH_DELAY");
+ goto error;
+ }
+
if (adapter->device_mode == QDF_STA_MODE) {
sme_set_smps_cfg(adapter->sessionId,
HDD_STA_SMPS_PARAM_UPPER_BRSSI_THRESH,
@@ -4292,6 +4321,9 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
qdf_mutex_create(&adapter->arp_offload_info_lock);
hdd_ns_offload_info_lock_create(adapter);
+ if (adapter->device_mode == QDF_STA_MODE)
+ wlan_hdd_debugfs_csr_init(adapter);
+
return adapter;
err_free_netdev:
@@ -4329,9 +4361,6 @@ QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
hdd_bus_bw_compute_timer_stop(hdd_ctx);
cancel_work_sync(&hdd_ctx->bus_bw_work);
- qdf_mutex_destroy(&adapter->arp_offload_info_lock);
- hdd_ns_offload_info_lock_destroy(adapter);
-
/* cleanup adapter */
cds_clear_concurrency_mode(adapter->device_mode);
hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
@@ -4567,11 +4596,6 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
case QDF_P2P_DEVICE_MODE:
case QDF_NDI_MODE:
- if (adapter->device_mode == QDF_STA_MODE) {
- hdd_debug("Destroy CSR debugfs files");
- wlan_hdd_debugfs_csr_deinit(adapter);
- }
-
if ((QDF_NDI_MODE == adapter->device_mode) ||
hdd_conn_is_connected(
WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
@@ -4678,6 +4702,7 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
/* Any softap specific cleanup here... */
sap_config = &adapter->sessionCtx.ap.sapConfig;
wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
+ qdf_atomic_set(&adapter->sessionCtx.ap.acs_in_progress, 0);
wlan_hdd_undo_acs(adapter);
if (adapter->device_mode == QDF_P2P_GO_MODE)
wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
@@ -6405,6 +6430,7 @@ static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
+ qdf_mutex_destroy(&hdd_ctx->cache_channel_lock);
/*
* Close CDS
@@ -8197,6 +8223,8 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
hdd_adapter_t *adapter = NULL;
void *cds_context = NULL;
int i;
+ hdd_adapter_list_node_t *adapter_node, *next;
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
/* Get the global VOSS context.*/
cds_context = cds_get_global_context();
@@ -8217,6 +8245,24 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
if (adapter)
break;
}
+ } else if (SME_SESSION_ID_BROADCAST == frame_ind->sessionId) {
+ status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
+ while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
+ adapter = adapter_node->pAdapter;
+ if ((NULL != adapter) &&
+ (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)) {
+ __hdd_indicate_mgmt_frame(adapter,
+ frame_ind->frame_len,
+ frame_ind->frameBuf,
+ frame_ind->frameType,
+ frame_ind->rxChan,
+ frame_ind->rxRssi);
+ }
+ status = hdd_get_next_adapter(hdd_ctx,
+ adapter_node, &next);
+ adapter_node = next;
+ }
+ adapter = NULL;
} else {
adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
frame_ind->sessionId);
@@ -8737,11 +8783,6 @@ int hdd_start_station_adapter(hdd_adapter_t *adapter)
hdd_tx_resume_cb,
hdd_tx_flow_control_is_pause);
- if (adapter->device_mode == QDF_STA_MODE) {
- hdd_debug("Create CSR debugfs files");
- wlan_hdd_debugfs_csr_init(adapter);
- }
-
EXIT();
return 0;
}
@@ -10420,6 +10461,7 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
bool is_recover_stop = cds_is_driver_recovering();
bool is_idle_stop = !is_unload_stop && !is_recover_stop;
int active_threads;
+ int debugfs_threads;
ENTER();
hdd_alert("stop WLAN module: entering driver status=%d",
@@ -10436,11 +10478,15 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
cds_set_module_stop_in_progress(true);
active_threads = cds_return_external_threads_count();
- if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
- hdd_warn("External threads %d wiphy suspend %d",
- active_threads, hdd_ctx->isWiphySuspended);
+ debugfs_threads = hdd_return_debugfs_threads_count();
+ if (active_threads > 0 || debugfs_threads > 0 ||
+ hdd_ctx->isWiphySuspended) {
+ hdd_warn("External threads %d, Debugfs threads %d, wiphy suspend %d",
+ active_threads, debugfs_threads,
+ hdd_ctx->isWiphySuspended);
- cds_print_external_threads();
+ if (active_threads)
+ cds_print_external_threads();
if (is_idle_stop && !ftm_mode) {
mutex_unlock(&hdd_ctx->iface_change_lock);
@@ -10533,6 +10579,8 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
hdd_err("CNSS power down failed put device into Low power mode:%d",
ret);
}
+ /* Free the cache channels of the command SET_DISABLE_CHANNEL_LIST */
+ wlan_hdd_free_cache_channels(hdd_ctx);
/* many adapter resources are not freed by design in SSR case */
if (!is_recover_stop)
@@ -10728,6 +10776,10 @@ int hdd_wlan_startup(struct device *dev)
if (ret)
goto err_hdd_free_context;
+ ret = qdf_mutex_create(&hdd_ctx->cache_channel_lock);
+ if (QDF_IS_STATUS_ERROR(ret))
+ goto err_hdd_free_context;
+
hdd_request_manager_init();
hdd_green_ap_init(hdd_ctx);
@@ -11162,8 +11214,6 @@ void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
return;
- wlan_hdd_get_peer_rssi(adapter, &pDelStaParams->peerMacAddr,
- HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER);
wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
pDelStaParams);
}
diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c
index 95bb70f14d59..67b5bc8dccde 100644
--- a/core/hdd/src/wlan_hdd_nan_datapath.c
+++ b/core/hdd/src/wlan_hdd_nan_datapath.c
@@ -250,13 +250,11 @@ static int hdd_ndi_start_bss(hdd_adapter_t *adapter,
roam_profile->csrPersona = adapter->device_mode;
+ if (!operating_channel)
+ operating_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
+
roam_profile->ChannelInfo.numOfChannels = 1;
- if (operating_channel) {
- roam_profile->ChannelInfo.ChannelList = &operating_channel;
- } else {
- roam_profile->ChannelInfo.ChannelList[0] =
- NAN_SOCIAL_CHANNEL_2_4GHZ;
- }
+ roam_profile->ChannelInfo.ChannelList = &operating_channel;
roam_profile->SSIDs.numOfSSIDs = 1;
roam_profile->SSIDs.SSIDList->SSID.length = 0;
@@ -789,27 +787,36 @@ static int hdd_ndp_responder_req_handler(hdd_context_t *hdd_ctx,
ENTER();
- if (tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
- iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
+ /* First validate the response code from the user space */
+ if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]) {
+ hdd_err("ndp_rsp code is unavailable");
+ return -EINVAL;
+ }
+ req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
- /* Check if iface exists */
+ if (req.ndp_rsp == NDP_RESPONSE_ACCEPT) {
+ /* iface on which NDP is requested to be created */
+ if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
+ hdd_err("NAN iface name not provided");
+ return -ENODEV;
+ }
+ iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
adapter = hdd_get_adapter_by_iface_name(hdd_ctx, iface_name);
if (!adapter) {
- hdd_err("NAN data iface %s is unavailable", iface_name);
+ hdd_err("NAN iface %s unavailable", iface_name);
return -ENODEV;
}
-
if (!WLAN_HDD_IS_NDI(adapter)) {
- hdd_err("Interface %s is not in NDI mode", iface_name);
+ hdd_err("Iface %s not in NDI mode", iface_name);
return -ENODEV;
}
} else {
/*
- * If the data indication is rejected, the userspace
- * may not send the iface name. Use the first available NDI
- * in that case
+ * If the data indication is rejected, iface name in cmd is not
+ * required, hence the user provided iface name is discarded and
+ * first available NDI is used.
*/
- hdd_info("Iface name string is unavailable, use first NDI");
+ hdd_debug("ndp response rejected, use first available NDI");
adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
if (!adapter) {
@@ -850,12 +857,6 @@ static int hdd_ndp_responder_req_handler(hdd_context_t *hdd_ctx,
req.ndp_instance_id =
nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]);
- if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]) {
- hdd_err("ndp_rsp is unavailable");
- return -EINVAL;
- }
- req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
-
if (tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) {
req.ndp_info.ndp_app_info_len =
nla_len(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c
index dfb623f7bdd8..fbcb9d3fff8f 100644
--- a/core/hdd/src/wlan_hdd_p2p.c
+++ b/core/hdd/src/wlan_hdd_p2p.c
@@ -1946,8 +1946,6 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
uint8_t home_ch = 0;
bool enb_random_mac = false;
uint32_t mgmt_hdr_len = sizeof(struct ieee80211_hdr_3addr);
- tHalHandle hHal = pHddCtx->hHal;
- uint32_t scan_id;
QDF_STATUS qdf_status;
ENTER();
@@ -2261,11 +2259,18 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
* but is not yet processed clean the roc ctx
* and send response to upper layer.
*/
- scan_id = pRemainChanCtx->scan_id;
mutex_unlock(
&cfgState->remain_on_chan_ctx_lock);
- wlan_hdd_remain_on_channel_callback(hHal,
- pAdapter, QDF_STATUS_SUCCESS, scan_id);
+ INIT_COMPLETION(pAdapter->
+ cancel_rem_on_chan_var);
+ rc = wait_for_completion_timeout(&pAdapter->
+ cancel_rem_on_chan_var,
+ msecs_to_jiffies(
+ WAIT_CANCEL_REM_CHAN));
+ if (!rc) {
+ hdd_err("Timeout waiting for cancel ROC indication");
+ goto err_rem_channel;
+ }
}
mutex_lock(&cfgState->remain_on_chan_ctx_lock);
pRemainChanCtx = cfgState->remain_on_chan_ctx;
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index 915beaef2788..1fa5285f6ca0 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -1474,6 +1474,20 @@ QDF_STATUS hdd_wlan_shutdown(void)
hdd_debug("Invoking packetdump deregistration API");
wlan_deregister_txrx_packetdump();
+ /*
+ * After SSR, FW clear its txrx stats. In host,
+ * as adapter is intact so those counts are still
+ * available. Now if agains Set stats command comes,
+ * then host will increment its counts start from its
+ * last saved value, i.e., count before SSR, and FW will
+ * increment its count from 0. This will finally sends a
+ * mismatch of packet counts b/w host and FW to framework
+ * that will create ambiquity. Therfore, Resetting the host
+ * counts here so that after SSR both FW and host start
+ * increment their counts from 0.
+ */
+ hdd_reset_all_adapters_connectivity_stats(pHddCtx);
+
hdd_reset_all_adapters(pHddCtx);
/* Flush cached rx frame queue */
diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c
index 31c9cb3fad1f..948986339295 100644
--- a/core/hdd/src/wlan_hdd_scan.c
+++ b/core/hdd/src/wlan_hdd_scan.c
@@ -626,6 +626,14 @@ static void hdd_update_dbs_scan_ctrl_ext_flag(hdd_context_t *hdd_ctx,
/* Resetting the scan_ctrl_flags_ext to 0 */
scan_req->scan_ctrl_flags_ext = 0;
+ if ((hdd_ctx->config->dual_mac_feature_disable ==
+ DISABLE_DBS_CXN_AND_SCAN) ||
+ (hdd_ctx->config->dual_mac_feature_disable ==
+ ENABLE_DBS_CXN_AND_DISABLE_DBS_SCAN)) {
+ hdd_debug("DBS is disabled");
+ goto end;
+ }
+
if (scan_req->scan_flags & SME_SCAN_FLAG_HIGH_ACCURACY) {
hdd_debug("DBS disabled due to high accuracy scan request");
goto end;
@@ -644,14 +652,6 @@ static void hdd_update_dbs_scan_ctrl_ext_flag(hdd_context_t *hdd_ctx,
goto end;
}
- if ((hdd_ctx->config->dual_mac_feature_disable ==
- DISABLE_DBS_CXN_AND_SCAN) ||
- (hdd_ctx->config->dual_mac_feature_disable ==
- ENABLE_DBS_CXN_AND_DISABLE_DBS_SCAN)) {
- hdd_debug("DBS is disabled");
- goto end;
- }
-
conn_cnt = cds_get_connection_count();
if (conn_cnt > 0) {
hdd_debug("%d active connections, go for DBS scan", conn_cnt);
diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c
index 390dc97aac93..44d19d64622a 100644
--- a/core/hdd/src/wlan_hdd_softap_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c
@@ -1015,6 +1015,8 @@ QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
}
}
}
+ if (pAdapter->device_mode == QDF_SAP_MODE)
+ wlan_hdd_restore_channels(pHddCtx);
/* Mark the indoor channel (passive) to enable */
if (pHddCtx->config->disable_indoor_channel) {
diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c
index a9ef1a231960..5bacd90cf155 100644
--- a/core/hdd/src/wlan_hdd_tsf.c
+++ b/core/hdd/src/wlan_hdd_tsf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -274,18 +274,19 @@ static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
#ifdef WLAN_FEATURE_TSF_PLUS
/* unit for target time: us; host time: ns */
#define HOST_TO_TARGET_TIME_RATIO NSEC_PER_USEC
-#define MAX_ALLOWED_DEVIATION_NS (20 * NSEC_PER_MSEC)
+#define MAX_ALLOWED_DEVIATION_NS (100 * NSEC_PER_USEC)
#define MAX_CONTINUOUS_ERROR_CNT 3
/* to distinguish 32-bit overflow case, this inverval should:
* equal or less than (1/2 * OVERFLOW_INDICATOR32 us)
*/
-#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 500
+#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 10
#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
#define NORMAL_INTERVAL_TARGET \
((int64_t)((int64_t)WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC * \
NSEC_PER_SEC / HOST_TO_TARGET_TIME_RATIO))
#define OVERFLOW_INDICATOR32 (((int64_t)0x1) << 32)
+#define CAP_TSF_TIMER_FIX_SEC 1
/**
* TS_STATUS - timestamp status
@@ -466,8 +467,21 @@ static void hdd_update_timestamp(hdd_adapter_t *adapter,
hdd_info("ts-pair updated: target: %llu; host: %llu",
adapter->last_target_time,
adapter->last_host_time);
- interval = WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC *
- MSEC_PER_SEC;
+
+ /*
+ * TSF-HOST need to be updated in at most
+ * WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC, it couldn't be achieved
+ * if the timer interval is also
+ * WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC, due to processing or
+ * schedule delay. So deduct several seconds from
+ * WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC.
+ * Without this change, hdd_get_hosttime_from_targettime() will
+ * get wrong host time when it's longer than
+ * WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC from last
+ * TSF-HOST update.
+ */
+ interval = (WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC -
+ CAP_TSF_TIMER_FIX_SEC) * MSEC_PER_SEC;
adapter->continuous_error_count = 0;
break;
case HDD_TS_STATUS_WAITING:
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index 154000ef57f2..4a29abd36e83 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -506,6 +506,56 @@ static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
}
/**
+ * hdd_clear_tx_rx_connectivity_stats() - clear connectivity stats
+ * @hdd_ctx: pointer to HDD Station Context
+ *
+ * Return: None
+ */
+static void hdd_clear_tx_rx_connectivity_stats(hdd_adapter_t *adapter)
+{
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
+ "Clear txrx connectivity stats");
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.hdd_arp_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_dns_stats,
+ sizeof(adapter->hdd_stats.hdd_dns_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_tcp_stats,
+ sizeof(adapter->hdd_stats.hdd_tcp_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_icmpv4_stats,
+ sizeof(adapter->hdd_stats.hdd_icmpv4_stats));
+ adapter->pkt_type_bitmap = 0;
+ adapter->track_arp_ip = 0;
+ qdf_mem_zero(adapter->dns_payload, adapter->track_dns_domain_len);
+ adapter->track_dns_domain_len = 0;
+ adapter->track_src_port = 0;
+ adapter->track_dest_port = 0;
+ adapter->track_dest_ipv4 = 0;
+}
+
+void hdd_reset_all_adapters_connectivity_stats(hdd_context_t *hdd_ctx)
+{
+ hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
+ QDF_STATUS status;
+ hdd_adapter_t *adapter;
+
+ ENTER();
+
+ status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
+
+ while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
+ adapter = adapterNode->pAdapter;
+ hdd_clear_tx_rx_connectivity_stats(adapter);
+
+ status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
+ adapterNode = pNext;
+ }
+
+ EXIT();
+
+}
+
+
+/**
* hdd_tx_rx_is_dns_domain_name_match() - function to check whether dns
* domain name in the received skb matches with the tracking dns domain
* name or not
@@ -790,7 +840,8 @@ static inline bool hdd_is_tx_allowed(struct sk_buff *skb, uint8_t peer_id)
if (OL_TXRX_PEER_STATE_AUTH == peer_state)
return true;
else if (OL_TXRX_PEER_STATE_CONN == peer_state &&
- ntohs(skb->protocol) == HDD_ETHERTYPE_802_1_X)
+ (ntohs(skb->protocol) == HDD_ETHERTYPE_802_1_X
+ || IS_HDD_ETHERTYPE_WAI(skb)))
return true;
DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
(uint8_t *)skb->data,
@@ -996,6 +1047,10 @@ static netdev_tx_t __hdd_hard_start_xmit(struct sk_buff *skb,
goto drop_pkt_and_release_skb;
}
if (!hdd_is_tx_allowed(skb, STAId)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s: Tx is not allowed. drop the pkt",
+ __func__);
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
goto drop_pkt_and_release_skb;
}
diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c
index b0d92b833d69..f987db26b0ed 100644
--- a/core/hdd/src/wlan_hdd_wext.c
+++ b/core/hdd/src/wlan_hdd_wext.c
@@ -3367,7 +3367,7 @@ int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter,
* @channel: channel to be converted
* @pfreq: where to store the frequency
*
- * Return: 1 on success, otherwise a negative errno
+ * Return: 0 on success, otherwise a negative errno
*/
int hdd_wlan_get_freq(uint32_t channel, uint32_t *pfreq)
{
@@ -3377,7 +3377,7 @@ int hdd_wlan_get_freq(uint32_t channel, uint32_t *pfreq)
for (i = 0; i < FREQ_CHAN_MAP_TABLE_SIZE; i++) {
if (channel == freq_chan_map[i].chan) {
*pfreq = freq_chan_map[i].freq;
- return 1;
+ return 0;
}
}
}
@@ -3431,6 +3431,7 @@ static bool hdd_is_auth_type_rsn(eCsrAuthType authType)
case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
#endif
+ case eCSR_AUTH_TYPE_DPP_RSN:
rsnType = true;
break;
/* case eCSR_AUTH_TYPE_FAILED: */
@@ -3937,9 +3938,8 @@ static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi,
{
struct statsContext *get_rssi_context;
struct sir_peer_info *rssi_info;
- uint8_t peer_num, i;
+ uint8_t peer_num;
hdd_adapter_t *padapter;
- hdd_station_info_t *stainfo;
if ((sta_rssi == NULL) || (context == NULL)) {
hdd_err("Bad param, sta_rssi [%pK] context [%pK]",
@@ -3983,19 +3983,6 @@ static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi,
peer_num * sizeof(*rssi_info));
padapter->peer_sta_info.sta_num = peer_num;
- for (i = 0; i < peer_num; i++) {
- stainfo = hdd_get_stainfo(padapter->cache_sta_info,
- rssi_info[i].peer_macaddr);
- if (stainfo) {
- stainfo->rssi = rssi_info[i].rssi;
- stainfo->tx_rate = rssi_info[i].tx_rate;
- stainfo->rx_rate = rssi_info[i].rx_rate;
- hdd_info("rssi:%d tx_rate:%u rx_rate:%u %pM",
- stainfo->rssi, stainfo->tx_rate,
- stainfo->rx_rate, stainfo->macAddrSTA.bytes);
- }
- }
-
/* notify the caller */
complete(&get_rssi_context->completion);
@@ -4879,7 +4866,7 @@ static int __iw_get_freq(struct net_device *dev, struct iw_request_info *info,
return -EIO;
}
status = hdd_wlan_get_freq(channel, &freq);
- if (true == status) {
+ if (0 == status) {
/* Set Exponent parameter as 6 (MHZ)
* in struct iw_freq iwlist & iwconfig
* command shows frequency into proper
diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h
index e3b484a7849a..fdc6cf84cb27 100644
--- a/core/mac/inc/ani_global.h
+++ b/core/mac/inc/ani_global.h
@@ -1019,6 +1019,10 @@ typedef struct sAniSirGlobal {
/* 11k Offload Support */
bool is_11k_offload_supported;
+
+ uint32_t peer_rssi;
+ uint32_t peer_txrate;
+ uint32_t peer_rxrate;
} tAniSirGlobal;
typedef enum {
diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h
index 4a79a097a8ce..d76af685d152 100644
--- a/core/mac/inc/qwlan_version.h
+++ b/core/mac/inc/qwlan_version.h
@@ -41,9 +41,9 @@
#define QWLAN_VERSION_MAJOR 5
#define QWLAN_VERSION_MINOR 1
#define QWLAN_VERSION_PATCH 1
-#define QWLAN_VERSION_EXTRA "H"
-#define QWLAN_VERSION_BUILD 51
+#define QWLAN_VERSION_EXTRA "R"
+#define QWLAN_VERSION_BUILD 52
-#define QWLAN_VERSIONSTR "5.1.1.51H"
+#define QWLAN_VERSIONSTR "5.1.1.52R"
#endif /* QWLAN_VERSION_H */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index c43a179c4be5..4873e98b3a87 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -783,7 +783,6 @@ typedef struct sSirSmeStartBssReq {
uint8_t sap_dot11mc;
uint16_t beacon_tx_rate;
bool vendor_vht_sap;
-
} tSirSmeStartBssReq, *tpSirSmeStartBssReq;
#define GET_IE_LEN_IN_BSS(lenInBss) (lenInBss + sizeof(lenInBss) - \
@@ -3608,6 +3607,7 @@ typedef struct sSirRoamOffloadScanReq {
uint8_t ValidChannelCount;
uint8_t ValidChannelList[SIR_ROAM_MAX_CHANNELS];
bool IsESEAssoc;
+ bool is_11r_assoc;
uint8_t nProbes;
uint16_t HomeAwayTime;
tSirRoamNetworkType ConnectedNetwork;
diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h
index c47b500d8e5c..6613670b3700 100644
--- a/core/mac/inc/sir_mac_prot_def.h
+++ b/core/mac/inc/sir_mac_prot_def.h
@@ -217,6 +217,11 @@
#define SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID 4
#define SIR_MAC_ACTION_MEASUREMENT_PILOT 7
+/* Public Action frames for GAS */
+#define SIR_MAC_ACTION_GAS_INITIAL_REQUEST 0x0A
+#define SIR_MAC_ACTION_GAS_INITIAL_RESPONSE 0x0B
+#define SIR_MAC_ACTION_GAS_COMEBACK_REQUEST 0x0C
+#define SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE 0x0D
#ifdef WLAN_FEATURE_11W
/* 11w SA query request/response action frame category code */
diff --git a/core/mac/src/include/dph_global.h b/core/mac/src/include/dph_global.h
index 55779288ef7c..d5e38e4293da 100644
--- a/core/mac/src/include/dph_global.h
+++ b/core/mac/src/include/dph_global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -173,6 +173,11 @@ typedef struct sDphHashNode {
tDphQosParams qos;
/* station version info - valid only if versionPresent is set */
tSirMacPropVersion version;
+ /* Previous authentication packet sequence number */
+ uint16_t prev_auth_seq_no;
+ /* Previous association packet sequence number */
+ uint16_t prev_assoc_seq_no;
+
#ifdef PLM_WDS
uint8_t wdsIndex;
uint8_t wdsPeerBeaconSeen;
diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h
index 8affc7789f8c..fdc879c9d77d 100644
--- a/core/mac/src/include/parser_api.h
+++ b/core/mac/src/include/parser_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -54,6 +54,14 @@
#define IS_5G_CH(__chNum) ((__chNum >= 36) && (__chNum <= 165))
#define IS_2X2_CHAIN(__chain) ((__chain & 0x3) == 0x3)
#define DISABLE_NSS2_MCS 0xC
+#define VHT_1x1_MCS9_MAP 0x2
+#define VHT_2x2_MCS9_MAP 0xA
+#define VHT_1x1_MCS8_VAL 0xFFFD
+#define VHT_2x2_MCS8_VAL 0xFFF5
+#define VHT_1x1_MCS_MASK 0x3
+#define VHT_2x2_MCS_MASK 0xF
+#define DISABLE_VHT_MCS_9(mcs, nss) \
+ (mcs = (nss > 1) ? VHT_2x2_MCS8_VAL : VHT_1x1_MCS8_VAL)
#define NSS_1x1_MODE 1
#define NSS_2x2_MODE 2
diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h
index d8afcfa50e7f..e963ca276ed8 100644
--- a/core/mac/src/pe/include/rrm_global.h
+++ b/core/mac/src/pe/include/rrm_global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, 2014-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -217,6 +217,7 @@ typedef struct sRrmPEContext {
int8_t txMgmtPower;
/* Dialog token for the request initiated from station. */
uint8_t DialogToken;
+ uint16_t prev_rrm_report_seq_num;
tpRRMReq pCurrentReq;
} tRrmPEContext, *tpRrmPEContext;
diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c
index 97f192bcfcdf..2d6f092bb19e 100644
--- a/core/mac/src/pe/lim/lim_api.c
+++ b/core/mac/src/pe/lim/lim_api.c
@@ -2011,6 +2011,21 @@ static inline void lim_copy_and_free_hlp_data_from_session(
{}
#endif
+static const char *pe_roam_op_code_to_string(uint8_t roam_op_code)
+{
+ switch (roam_op_code) {
+ CASE_RETURN_STRING(SIR_ROAM_SYNCH_PROPAGATION);
+ CASE_RETURN_STRING(SIR_ROAMING_DEREGISTER_STA);
+ CASE_RETURN_STRING(SIR_ROAMING_START);
+ CASE_RETURN_STRING(SIR_ROAMING_ABORT);
+ CASE_RETURN_STRING(SIR_ROAM_SYNCH_COMPLETE);
+ CASE_RETURN_STRING(SIR_ROAM_SYNCH_NAPI_OFF);
+ CASE_RETURN_STRING(SIR_ROAMING_INVOKE_FAIL);
+ default:
+ return "none";
+ }
+}
+
/**
* pe_roam_synch_callback() - PE level callback for roam synch propagation
* @mac_ctx: MAC Context
@@ -2053,7 +2068,8 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
return status;
}
- pe_debug("LFR3: PE callback reason: %d", reason);
+ pe_debug("LFR3: PE callback reason: %d %s", reason,
+ pe_roam_op_code_to_string(reason));
switch (reason) {
case SIR_ROAMING_START:
session_ptr->fw_roaming_started = true;
@@ -2085,10 +2101,6 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
return status;
}
- pe_debug("LFR3:Received WMA_ROAM_OFFLOAD_SYNCH_IND LFR3:auth: %d vdevId: %d",
- roam_sync_ind_ptr->authStatus, roam_sync_ind_ptr->roamedVdevId);
- lim_print_mac_addr(mac_ctx, roam_sync_ind_ptr->bssid.bytes,
- QDF_TRACE_LEVEL_DEBUG);
/*
* If deauth from AP already in progress, ignore Roam Synch Indication
* from firmware.
diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c
index e7ca136f209a..427252ee9c2d 100644
--- a/core/mac/src/pe/lim/lim_assoc_utils.c
+++ b/core/mac/src/pe/lim/lim_assoc_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1396,6 +1396,25 @@ tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal mac_ctx,
VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
rates->vhtRxHighestDataRate =
VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ if (!session_entry->ch_width &&
+ !mac_ctx->roam.configParam.enable_vht20_mcs9 &&
+ ((rates->vhtRxMCSMap & VHT_1x1_MCS_MASK) ==
+ VHT_1x1_MCS9_MAP)) {
+ DISABLE_VHT_MCS_9(rates->vhtRxMCSMap,
+ NSS_1x1_MODE);
+ DISABLE_VHT_MCS_9(rates->vhtTxMCSMap,
+ NSS_1x1_MODE);
+ }
+ } else {
+ if (!session_entry->ch_width &&
+ !mac_ctx->roam.configParam.enable_vht20_mcs9 &&
+ ((rates->vhtRxMCSMap & VHT_2x2_MCS_MASK) ==
+ VHT_2x2_MCS9_MAP)) {
+ DISABLE_VHT_MCS_9(rates->vhtRxMCSMap,
+ NSS_2x2_MODE);
+ DISABLE_VHT_MCS_9(rates->vhtTxMCSMap,
+ NSS_2x2_MODE);
+ }
}
if ((peer_vht_caps == NULL) || (!peer_vht_caps->present))
diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c
index 50aef50354f5..2b58f5799caa 100644
--- a/core/mac/src/pe/lim/lim_p2p.c
+++ b/core/mac/src/pe/lim/lim_p2p.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -395,6 +395,13 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
return;
}
+ if (qdf_is_macaddr_broadcast(
+ (struct qdf_mac_addr *) pSirSmeMgmtFrame->frameBuf + 4) &&
+ !sessionId) {
+ pe_debug("Broadcast action frame");
+ sessionId = SME_SESSION_ID_BROADCAST;
+ }
+
pSirSmeMgmtFrame->frame_len = frameLen;
pSirSmeMgmtFrame->sessionId = sessionId;
pSirSmeMgmtFrame->frameType = frameType;
diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c
index d0cb44918a0e..583d0542c655 100644
--- a/core/mac/src/pe/lim/lim_process_action_frame.c
+++ b/core/mac/src/pe/lim/lim_process_action_frame.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1295,6 +1295,7 @@ __lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tDot11fRadioMeasurementRequest *frm;
uint32_t frameLen, nStatus;
uint8_t *pBody;
+ uint16_t curr_seq_num;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
@@ -1304,6 +1305,17 @@ __lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
return;
}
+ curr_seq_num = ((pHdr->seqControl.seqNumHi <<
+ HIGH_SEQ_NUM_OFFSET) |
+ pHdr->seqControl.seqNumLo);
+ if (curr_seq_num == pMac->rrm.rrmPEContext.prev_rrm_report_seq_num &&
+ pMac->rrm.rrmPEContext.pCurrentReq) {
+ pe_err("rrm report req frame, seq num: %d is already in progress, drop it",
+ curr_seq_num);
+ return;
+ }
+ /* Save seq no of currently processing rrm report req frame */
+ pMac->rrm.rrmPEContext.prev_rrm_report_seq_num = curr_seq_num;
lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *)pHdr,
frameLen + sizeof(tSirMacMgmtHdr), 0,
WMA_GET_RX_CH(pRxPacketInfo), psessionEntry,
@@ -1938,7 +1950,13 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
}
break;
case SIR_MAC_ACTION_PUBLIC_USAGE:
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
switch (action_hdr->actionID) {
+ case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID:
+ lim_process_ext_channel_switch_action_frame(mac_ctx,
+ rx_pkt_info, session);
+ break;
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
pub_action =
(tpSirMacVendorSpecificPublicActionFrameHdr)
@@ -1947,58 +1965,30 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
lim_process_action_vendor_specific(mac_ctx, rx_pkt_info,
pub_action, session);
break;
- /* Handle vendor specific action */
case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY:
- {
- tpSirMacMgmtHdr header;
- uint32_t frame_len;
-
- header = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
- frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
- lim_send_sme_mgmt_frame_ind(mac_ctx, header->fc.subType,
- (uint8_t *)header, frame_len + sizeof(tSirMacMgmtHdr), 0,
- WMA_GET_RX_CH(rx_pkt_info), NULL,
- WMA_GET_RX_RSSI_RAW(rx_pkt_info));
- break;
- }
-
case SIR_MAC_ACTION_2040_BSS_COEXISTENCE:
- mac_hdr = NULL;
- frame_len = 0;
-
- mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
- frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
-
- lim_send_sme_mgmt_frame_ind(mac_ctx,
- mac_hdr->fc.subType,
- (uint8_t *) mac_hdr,
- frame_len + sizeof(tSirMacMgmtHdr),
- session->smeSessionId,
- WMA_GET_RX_CH(rx_pkt_info), session,
- WMA_GET_RX_RSSI_NORMALIZED(
- rx_pkt_info));
- break;
+ case SIR_MAC_ACTION_GAS_INITIAL_REQUEST:
+ case SIR_MAC_ACTION_GAS_INITIAL_RESPONSE:
+ case SIR_MAC_ACTION_GAS_COMEBACK_REQUEST:
+ case SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE:
#ifdef FEATURE_WLAN_TDLS
case SIR_MAC_TDLS_DIS_RSP:
- mac_hdr = NULL;
- frame_len = 0;
-
- mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
- frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
- rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
- pe_debug("Public Action TDLS Discovery RSP");
+#endif
+ /*
+ * Frame forwarded to SME to HDD to supplicant
+ * type is action
+ */
+ pe_debug("Public Action Frame %d received",
+ action_hdr->actionID);
lim_send_sme_mgmt_frame_ind(mac_ctx,
- mac_hdr->fc.subType, (uint8_t *) mac_hdr,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info), session,
WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info));
break;
-#endif
- case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID:
- lim_process_ext_channel_switch_action_frame(mac_ctx,
- rx_pkt_info, session);
- break;
+
default:
pe_warn("Unhandled public action frame: %x",
action_hdr->actionID);
@@ -2118,31 +2108,52 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
{
+ tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(pBd);
+ uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(pBd);
uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd);
- tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr =
- (tpSirMacVendorSpecificPublicActionFrameHdr) pBody;
+ tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody;
+ tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
pe_debug("Received a Action frame -- no session");
- switch (pActionHdr->category) {
+ switch (action_hdr->category) {
case SIR_MAC_ACTION_PUBLIC_USAGE:
- switch (pActionHdr->actionID) {
+ switch (action_hdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
- {
+ vendor_specific =
+ (tpSirMacVendorSpecificPublicActionFrameHdr)
+ action_hdr;
lim_process_action_vendor_specific(pMac, pBd,
- pActionHdr, NULL);
- }
+ vendor_specific,
+ NULL);
+ break;
+ case SIR_MAC_ACTION_GAS_INITIAL_REQUEST:
+ case SIR_MAC_ACTION_GAS_INITIAL_RESPONSE:
+ case SIR_MAC_ACTION_GAS_COMEBACK_REQUEST:
+ case SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE:
+ /*
+ * Frame forwarded to SME to HDD to supplicant
+ * type is action
+ */
+ pe_debug("Public Action Frame %d received",
+ action_hdr->actionID);
+ lim_send_sme_mgmt_frame_ind(pMac,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(pBd), NULL,
+ WMA_GET_RX_RSSI_NORMALIZED(pBd));
+
break;
default:
pe_warn("Unhandled public action frame: %x",
- pActionHdr->actionID);
+ action_hdr->actionID);
break;
}
break;
default:
pe_warn("Unhandled action frame without session: %x",
- pActionHdr->category);
+ action_hdr->category);
break;
-
}
}
diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
index 3e3345768882..dfbe6cbc95ca 100644
--- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
+++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
@@ -1102,6 +1102,7 @@ static bool lim_process_assoc_req_sta_ctx(tpAniSirGlobal mac_ctx,
eLIM_MLM_AUTHENTICATED_STATE)) {
/* STA has triggered pre-auth again */
*auth_type = sta_pre_auth_ctx->authType;
+ sta_ds->prev_auth_seq_no = sta_pre_auth_ctx->seq_num;
lim_delete_pre_auth_node(mac_ctx, hdr->sa);
} else {
*auth_type = sta_ds->mlmStaContext.authType;
@@ -1248,6 +1249,9 @@ static bool lim_update_sta_ds(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr hdr,
sta_ds->qos.addts = assoc_req->addtsReq;
sta_ds->qos.capability = assoc_req->qosCapability;
sta_ds->versionPresent = 0;
+ sta_ds->prev_assoc_seq_no = (((hdr->seqControl.seqNumHi <<
+ HIGH_SEQ_NUM_OFFSET) |
+ hdr->seqControl.seqNumLo));
/*
* short slot and short preamble should be updated before doing
* limaddsta
@@ -1768,19 +1772,21 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
}
/*
- * If a STA is already present in DPH and it is initiating a Assoc
- * re-transmit, do not process it. This can happen when first Assoc Req
- * frame is received but ACK lost at STA side. The ACK for this dropped
- * Assoc Req frame should be sent by HW. Host simply does not process it
- * once the entry for the STA is already present in DPH.
+ * If a STA is already present in DPH and the host receives an assoc
+ * request with the same sequence number , do not process it, as the
+ * previous assoc has already been processed and the response will be
+ * retried by the firmware if the peer hasnt received the response yet
*/
sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &assoc_id,
&session->dph.dphHashTable);
if (NULL != sta_ds) {
- if (hdr->fc.retry > 0) {
- pe_err("STA is initiating Assoc Req after ACK lost. Do not process sessionid: %d sys sub_type=%d for role=%d from: "
- MAC_ADDRESS_STR, session->peSessionId,
- sub_type, GET_LIM_SYSTEM_ROLE(session),
+ if (sta_ds->prev_assoc_seq_no == (((hdr->seqControl.seqNumHi <<
+ HIGH_SEQ_NUM_OFFSET) |
+ hdr->seqControl.seqNumLo))) {
+ pe_err("Got an Assoc Req with same seq no. SN:%d .Do not process sessionid: %d sys sub_type=%d for role=%d from: "
+ MAC_ADDRESS_STR, sta_ds->prev_assoc_seq_no,
+ session->peSessionId,
+ sub_type, GET_LIM_SYSTEM_ROLE(session),
MAC_ADDR_ARRAY(hdr->sa));
return;
} else if (!sta_ds->rmfEnabled && (sub_type == LIM_REASSOC)) {
diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c
index 5758561e39b5..6c1a99e4b4af 100644
--- a/core/mac/src/pe/lim/lim_process_auth_frame.c
+++ b/core/mac/src/pe/lim/lim_process_auth_frame.c
@@ -364,8 +364,11 @@ static void lim_process_auth_frame_type1(tpAniSirGlobal mac_ctx,
* modify the state of the existing association until the
* SA-Query procedure determines that the original SA is
* invalid.
+ * If the Auth sequence number is same as the previous auth seq
+ * number, dont send a deauth as the auth packet is just the
+ * duplicate of previous auth.
*/
- if (isConnected
+ if (isConnected && sta_ds_ptr->prev_auth_seq_no != curr_seq_num
#ifdef WLAN_FEATURE_11W
&& !sta_ds_ptr->rmfEnabled
#endif
@@ -385,14 +388,15 @@ static void lim_process_auth_frame_type1(tpAniSirGlobal mac_ctx,
auth_node = lim_search_pre_auth_list(mac_ctx, mac_hdr->sa);
if (auth_node) {
/* Pre-auth context exists for the STA */
- if (!(mac_hdr->fc.retry == 0 ||
- auth_node->seq_num != curr_seq_num)) {
+ if (auth_node->seq_num == curr_seq_num) {
/*
- * This can happen when first authentication frame is
- * received but ACK lost at STA side, in this case 2nd
- * auth frame is already in transmission queue
+ * If a STA is already present in authnode and the host receives an auth
+ * request with the same sequence number , do not process it, as the
+ * previous auth has already been processed and the response will be
+ * retried by the firmware if the peer hasnt received the response yet
*/
- pe_warn("STA is initiating Auth after ACK lost");
+ pe_warn("STA is initiating Auth with SN: %d after ACK lost",
+ auth_node->seq_num);
return;
}
/*
@@ -1144,8 +1148,7 @@ lim_process_auth_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
pe_session->limMlmState, MAC_ADDR_ARRAY(mac_hdr->bssId),
(uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)));
- if (pe_session->prev_auth_seq_num == curr_seq_num &&
- mac_hdr->fc.retry) {
+ if (pe_session->prev_auth_seq_num == curr_seq_num) {
pe_err("auth frame, seq num: %d is already processed, drop it",
curr_seq_num);
return;
diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c
index a4d36d070f08..98529fbde2c3 100644
--- a/core/mac/src/pe/lim/lim_sme_req_utils.c
+++ b/core/mac/src/pe/lim/lim_sme_req_utils.c
@@ -298,7 +298,7 @@ lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(tpAniSirGlobal mac_ctx,
&& (rsn_ie->rsnIEdata[0] == SIR_MAC_WPA_EID)) {
pe_debug("Only WPA IE is present");
ret = dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[6],
- (uint8_t) rsn_ie->length - 4,
+ rsn_ie->rsnIEdata[1] - 4,
&session->gStartBssWPAIe, false);
if (!DOT11F_SUCCEEDED(ret)) {
pe_err("unpack failed, ret: %d", ret);
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 8865b75e4fdb..973666b60746 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -496,10 +496,9 @@ void lim_perform_disassoc(tpAniSirGlobal mac_ctx, int32_t frame_rssi,
void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
tpPESession pe_session, tSirMacAddr addr);
#else
-void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
+static inline void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
tpPESession pe_session, tSirMacAddr addr)
{
- return;
}
#endif
void lim_process_deauth_frame(tpAniSirGlobal, uint8_t *, tpPESession);
diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c
index fed9077b6532..6c351e8d1367 100644
--- a/core/mac/src/pe/rrm/rrm_api.c
+++ b/core/mac/src/pe/rrm/rrm_api.c
@@ -1253,6 +1253,7 @@ tSirRetStatus rrm_initialize(tpAniSirGlobal pMac)
pMac->rrm.rrmPEContext.DialogToken = 0;
pMac->rrm.rrmPEContext.rrmEnable = 0;
+ pMac->rrm.rrmPEContext.prev_rrm_report_seq_num = 0xFFFF;
qdf_mem_set(pRRMCaps, sizeof(tRRMCaps), 0);
pRRMCaps->LinkMeasurement = 1;
diff --git a/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c
index 9f36260402c5..030221f92d97 100644
--- a/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c
+++ b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c
@@ -166,8 +166,19 @@ sys_bbt_process_message_core(tpAniSirGlobal mac_ctx, tpSirMsgQ msg,
mac_ctx->sys.gSysFrameCount[type][subtype]);
}
- /* Post the message to PE Queue */
- ret = (tSirRetStatus) lim_post_msg_api(mac_ctx, msg);
+ /*
+ * Post the message to PE Queue. Prioritize the
+ * Auth and assoc frames.
+ */
+ if ((subtype == SIR_MAC_MGMT_AUTH) ||
+ (subtype == SIR_MAC_MGMT_ASSOC_RSP) ||
+ (subtype == SIR_MAC_MGMT_REASSOC_RSP) ||
+ (subtype == SIR_MAC_MGMT_ASSOC_REQ) ||
+ (subtype == SIR_MAC_MGMT_REASSOC_REQ))
+ ret = (tSirRetStatus)
+ lim_post_msg_high_priority(mac_ctx, msg);
+ else
+ ret = (tSirRetStatus) lim_post_msg_api(mac_ctx, msg);
if (ret != eSIR_SUCCESS) {
pe_err("posting to LIM2 failed, ret %d\n", ret);
goto fail;
diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c
index 7e7d13d0f511..0d49d5e0de65 100644
--- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c
+++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c
@@ -1068,6 +1068,25 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac,
VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
pDot11f->rxHighSupDataRate =
VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ if (!psessionEntry->ch_width &&
+ !pMac->roam.configParam.enable_vht20_mcs9 &&
+ ((pDot11f->txMCSMap & VHT_1x1_MCS_MASK) ==
+ VHT_1x1_MCS9_MAP)) {
+ DISABLE_VHT_MCS_9(pDot11f->txMCSMap,
+ NSS_1x1_MODE);
+ DISABLE_VHT_MCS_9(pDot11f->rxMCSMap,
+ NSS_1x1_MODE);
+ }
+ } else {
+ if (!psessionEntry->ch_width &&
+ !pMac->roam.configParam.enable_vht20_mcs9 &&
+ ((pDot11f->txMCSMap & VHT_2x2_MCS_MASK) ==
+ VHT_2x2_MCS9_MAP)) {
+ DISABLE_VHT_MCS_9(pDot11f->txMCSMap,
+ NSS_2x2_MODE);
+ DISABLE_VHT_MCS_9(pDot11f->rxMCSMap,
+ NSS_2x2_MODE);
+ }
}
}
lim_log_vht_cap(pMac, pDot11f);
diff --git a/core/pld/src/pld_snoc.c b/core/pld/src/pld_snoc.c
index 2f6b84fa123a..f11982d39b7d 100644
--- a/core/pld/src/pld_snoc.c
+++ b/core/pld/src/pld_snoc.c
@@ -325,7 +325,6 @@ void pld_snoc_unregister_driver(void)
* Non zero failure code for errors
*/
-#ifdef ICNSS_API_WITH_DEV
int pld_snoc_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
enum pld_driver_mode mode, const char *host_version)
{
@@ -359,38 +358,6 @@ int pld_snoc_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
return icnss_wlan_enable(dev, &cfg, icnss_mode, host_version);
}
-#else
-int pld_snoc_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
- enum pld_driver_mode mode, const char *host_version)
-{
- struct icnss_wlan_enable_cfg cfg;
- enum icnss_driver_mode icnss_mode;
-
- cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
- cfg.ce_tgt_cfg = (struct ce_tgt_pipe_cfg *)
- config->ce_tgt_cfg;
- cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
- cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *)
- config->ce_svc_cfg;
- cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
- cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *)
- config->shadow_reg_cfg;
-
- switch (mode) {
- case PLD_FTM:
- icnss_mode = ICNSS_FTM;
- break;
- case PLD_EPPING:
- icnss_mode = ICNSS_EPPING;
- break;
- default:
- icnss_mode = ICNSS_MISSION;
- break;
- }
-
- return icnss_wlan_enable(&cfg, icnss_mode, host_version);
-}
-#endif
/**
* pld_snoc_wlan_disable() - Disable WLAN
@@ -402,7 +369,6 @@ int pld_snoc_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
* Return: 0 for success
* Non zero failure code for errors
*/
-#ifdef ICNSS_API_WITH_DEV
int pld_snoc_wlan_disable(struct device *dev, enum pld_driver_mode mode)
{
if (!dev)
@@ -410,12 +376,6 @@ int pld_snoc_wlan_disable(struct device *dev, enum pld_driver_mode mode)
return icnss_wlan_disable(dev, ICNSS_OFF);
}
-#else
-int pld_snoc_wlan_disable(struct device *dev, enum pld_driver_mode mode)
-{
- return icnss_wlan_disable(ICNSS_OFF);
-}
-#endif
/**
* pld_snoc_get_soc_info() - Get SOC information
@@ -427,7 +387,6 @@ int pld_snoc_wlan_disable(struct device *dev, enum pld_driver_mode mode)
* Return: 0 for success
* Non zero failure code for errors
*/
-#ifdef ICNSS_API_WITH_DEV
int pld_snoc_get_soc_info(struct device *dev, struct pld_soc_info *info)
{
int ret = 0;
@@ -443,21 +402,4 @@ int pld_snoc_get_soc_info(struct device *dev, struct pld_soc_info *info)
memcpy(info, &icnss_info, sizeof(*info));
return 0;
}
-#else
-int pld_snoc_get_soc_info(struct device *dev, struct pld_soc_info *info)
-{
- int ret = 0;
- struct icnss_soc_info icnss_info;
-
- if (info == NULL)
- return -ENODEV;
-
- ret = icnss_get_soc_info(&icnss_info);
- if (0 != ret)
- return ret;
-
- memcpy(info, &icnss_info, sizeof(*info));
- return 0;
-}
-#endif
#endif
diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h
index aa0dcbd6c956..e3b1bf7e574b 100644
--- a/core/pld/src/pld_snoc.h
+++ b/core/pld/src/pld_snoc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -143,7 +143,6 @@ int pld_snoc_wlan_enable(struct device *dev,
int pld_snoc_wlan_disable(struct device *dev, enum pld_driver_mode mode);
int pld_snoc_get_soc_info(struct device *dev, struct pld_soc_info *info);
-#ifdef ICNSS_API_WITH_DEV
static inline int pld_snoc_ce_request_irq(struct device *dev,
unsigned int ce_id,
irqreturn_t (*handler)(int, void *),
@@ -192,42 +191,6 @@ static inline int pld_snoc_get_irq(struct device *dev, int ce_id)
return icnss_get_irq(dev, ce_id);
}
-#else
-static inline int pld_snoc_ce_request_irq(struct device *dev,
- unsigned int ce_id,
- irqreturn_t (*handler)(int, void *),
- unsigned long flags,
- const char *name, void *ctx)
-{
- return icnss_ce_request_irq(ce_id, handler, flags, name, ctx);
-}
-
-static inline void pld_snoc_enable_irq(struct device *dev, unsigned int ce_id)
-{
- icnss_enable_irq(ce_id);
-}
-
-static inline void pld_snoc_disable_irq(struct device *dev, unsigned int ce_id)
-{
- icnss_disable_irq(ce_id);
-}
-
-static inline int pld_snoc_ce_free_irq(struct device *dev,
- unsigned int ce_id, void *ctx)
-{
- return icnss_ce_free_irq(ce_id, ctx);
-}
-
-static inline int pld_snoc_get_ce_id(struct device *dev, int irq)
-{
- return icnss_get_ce_id(irq);
-}
-
-static inline int pld_snoc_get_irq(struct device *dev, int ce_id)
-{
- return icnss_get_irq(ce_id);
-}
-#endif
static inline int pld_snoc_power_on(struct device *dev)
{
@@ -269,7 +232,6 @@ static inline int pld_snoc_is_fw_down(void)
return icnss_is_fw_down();
}
-#ifdef ICNSS_API_WITH_DEV
static inline int pld_snoc_is_qmi_disable(struct device *dev)
{
if (!dev)
@@ -285,17 +247,6 @@ static inline int pld_snoc_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
return icnss_set_fw_log_mode(dev, fw_log_mode);
}
-#else
-static inline int pld_snoc_is_qmi_disable(struct device *dev)
-{
- return icnss_is_qmi_disable();
-}
-
-static inline int pld_snoc_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
-{
- return icnss_set_fw_log_mode(fw_log_mode);
-}
-#endif
static inline int pld_snoc_force_assert_target(struct device *dev)
{
diff --git a/core/sap/dfs/src/dfs_init.c b/core/sap/dfs/src/dfs_init.c
index 70fd9202a7bc..250f5cec1eed 100644
--- a/core/sap/dfs/src/dfs_init.c
+++ b/core/sap/dfs/src/dfs_init.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2002-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -92,8 +92,8 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs, int seg_id)
}
if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) {
- if (((seg_id == 0) ?
- dfs->dfs_b5radars : dfs->dfs_b5radars_ext_seg) == NULL) {
+ if (dfs->dfs_rinfo.rn_numbin5radars && (((seg_id == 0) ?
+ dfs->dfs_b5radars : dfs->dfs_b5radars_ext_seg) == NULL)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: pl==NULL, b5radars=%pK\n",
__func__,
@@ -102,7 +102,8 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs, int seg_id)
return;
}
} else {
- if (dfs->dfs_b5radars == NULL) {
+ if (dfs->dfs_rinfo.rn_numbin5radars &&
+ (dfs->dfs_b5radars == NULL)) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s[%d]: pl==NULL, b5radars=%pK", __func__, __LINE__,
dfs->dfs_b5radars);
diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h
index 2292d8e438a2..cc6252caa65e 100644
--- a/core/sap/inc/sap_api.h
+++ b/core/sap/inc/sap_api.h
@@ -145,7 +145,6 @@ typedef enum {
*/
eSAP_STA_DISASSOC_EVENT,
- eSAP_STA_LOSTLINK_DETECTED,
/* Event sent when user called wlansap_set_key_sta */
eSAP_STA_SET_KEY_EVENT,
/* Event sent whenever there is MIC failure detected */
@@ -304,6 +303,9 @@ typedef struct sap_StationDisassocCompleteEvent_s {
uint32_t statusCode;
uint32_t reason_code;
eSapDisassocReason reason;
+ int rssi;
+ int tx_rate;
+ int rx_rate;
} tSap_StationDisassocCompleteEvent;
typedef struct sap_StationSetKeyCompleteEvent_s {
diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c
index ba83cd8a6abe..38aa0694b1b3 100644
--- a/core/sap/src/sap_api_link_cntl.c
+++ b/core/sap/src/sap_api_link_cntl.c
@@ -1098,11 +1098,7 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId,
eSAP_UPDATE_SCAN_RESULT,
(void *) eSAP_STATUS_SUCCESS);
break;
- case eCSR_ROAM_LOSTLINK_DETECTED:
- sap_signal_hdd_event(sap_ctx, csr_roam_info,
- eSAP_STA_LOSTLINK_DETECTED,
- (void *)eSAP_STATUS_SUCCESS);
- break;
+
default:
break;
}
diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c
index d33ee91381a7..0f3483b955d2 100644
--- a/core/sap/src/sap_fsm.c
+++ b/core/sap/src/sap_fsm.c
@@ -3103,22 +3103,6 @@ QDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx,
break;
- case eSAP_STA_LOSTLINK_DETECTED:
- if (!csr_roaminfo) {
- QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
- FL("Invalid CSR Roam Info"));
- return QDF_STATUS_E_INVAL;
- }
- sap_ap_event.sapHddEventCode = eSAP_STA_LOSTLINK_DETECTED;
- disassoc_comp =
- &sap_ap_event.sapevt.sapStationDisassocCompleteEvent;
-
- qdf_copy_macaddr(&disassoc_comp->staMac,
- &csr_roaminfo->peerMac);
- disassoc_comp->reason_code = csr_roaminfo->reasonCode;
-
- break;
-
case eSAP_STA_DISASSOC_EVENT:
if (!csr_roaminfo) {
@@ -3140,6 +3124,10 @@ QDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx,
disassoc_comp->statusCode = csr_roaminfo->statusCode;
disassoc_comp->status = (eSapStatus) context;
+ disassoc_comp->rssi = csr_roaminfo->rssi;
+ disassoc_comp->rx_rate = csr_roaminfo->rx_rate;
+ disassoc_comp->tx_rate = csr_roaminfo->tx_rate;
+ disassoc_comp->reason_code = csr_roaminfo->disassoc_reason;
break;
case eSAP_STA_SET_KEY_EVENT:
@@ -4004,6 +3992,11 @@ static QDF_STATUS sap_fsm_state_dfs_cac_wait(ptSapContext sap_ctx,
cds_set_channel_params(
mac_ctx->sap.SapDfsInfo.target_channel, 0,
&sap_ctx->ch_params);
+ } else {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ FL("Invalid target channel %d"),
+ mac_ctx->sap.SapDfsInfo.target_channel);
+ return qdf_status;
}
for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
@@ -4242,6 +4235,13 @@ static QDF_STATUS sap_fsm_state_started(ptSapContext sap_ctx,
qdf_status = sap_goto_disconnecting(sap_ctx);
} else if (eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START == msg) {
uint8_t intf;
+
+ if (!mac_ctx->sap.SapDfsInfo.target_channel) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ FL("Invalid target channel %d"),
+ mac_ctx->sap.SapDfsInfo.target_channel);
+ return qdf_status;
+ }
/*
* Radar is seen on the current operating channel
* send CSA IE for all associated stations
@@ -4949,6 +4949,13 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx,
CDS_CHANNEL_NUM(loop_count),
sap_ctx, &spect_info_obj))
continue;
+ /* Dont scan DFS channels in case of MCC disallowed
+ * As it can result in SAP starting on DFS channel
+ * resulting MCC on DFS channel
+ */
+ if (CDS_IS_DFS_CH(CDS_CHANNEL_NUM(loop_count)) &&
+ cds_disallow_mcc(CDS_CHANNEL_NUM(loop_count)))
+ continue;
/*
* If we have any 5Ghz channel in the channel list
diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c
index 9e5c0aadb253..2144cba81c50 100644
--- a/core/sap/src/sap_module.c
+++ b/core/sap/src/sap_module.c
@@ -2680,6 +2680,12 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel)
sapContext = (ptSapContext) pSapCtx;
+ if (!target_channel) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "%s: channel 0 requested", __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+
if (NULL == sapContext) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid SAP pointer", __func__);
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index d7892b839860..6b1530aad3e8 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -74,6 +74,7 @@ typedef enum {
eCSR_AUTH_TYPE_OWE,
eCSR_AUTH_TYPE_SUITEB_EAP_SHA256,
eCSR_AUTH_TYPE_SUITEB_EAP_SHA384,
+ eCSR_AUTH_TYPE_DPP_RSN,
eCSR_NUM_OF_SUPPORT_AUTH_TYPE,
eCSR_AUTH_TYPE_FAILED = 0xff,
eCSR_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED,
@@ -363,9 +364,8 @@ typedef struct tagCsrEseCckmInfo {
#endif
} tCsrEseCckmInfo;
-#define CSR_DOT11F_IE_RSN_MAX_LEN (114)
typedef struct tagCsrEseCckmIe {
- uint8_t cckmIe[CSR_DOT11F_IE_RSN_MAX_LEN];
+ uint8_t cckmIe[DOT11F_IE_RSN_MAX_LEN];
uint8_t cckmIeLen;
} tCsrEseCckmIe;
#endif /* FEATURE_WLAN_ESE */
@@ -1308,6 +1308,7 @@ typedef struct tagCsrConfigParam {
uint8_t enable_rx_ldpc;
uint8_t disable_high_ht_mcs_2x2;
uint8_t rx_ldpc_support_for_2g;
+ bool enable_vht20_mcs9;
uint8_t max_amsdu_num;
uint8_t nSelect5GHzMargin;
uint8_t isCoalesingInIBSSAllowed;
@@ -1405,6 +1406,7 @@ typedef struct tagCsrConfigParam {
uint8_t oce_feature_bitmap;
uint32_t offload_11k_enable_bitmask;
struct csr_neighbor_report_offload_params neighbor_report_offload;
+ bool enable_ftopen;
} tCsrConfigParam;
/* Tush */
@@ -1451,6 +1453,7 @@ typedef struct tagCsrRoamInfo {
tSirResultCodes statusCode;
/* this'd be our own defined or sent from otherBSS(per 802.11spec) */
uint32_t reasonCode;
+ uint8_t disassoc_reason;
uint8_t staId; /* Peer stationId when connected */
/*
* The DPU signatures will be sent eventually to TL to help it
@@ -1563,6 +1566,9 @@ typedef struct tagCsrRoamInfo {
#ifdef WLAN_FEATURE_SAE
struct sir_sae_info *sae_info;
#endif
+ int rssi;
+ int tx_rate;
+ int rx_rate;
} tCsrRoamInfo;
typedef struct tagCsrFreqScanInfo {
diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h
index 6ce321ae7b79..62ed7329ee8e 100644
--- a/core/sme/inc/csr_internal.h
+++ b/core/sme/inc/csr_internal.h
@@ -593,6 +593,7 @@ typedef struct tagCsrConfig {
uint32_t nVhtChannelWidth;
bool enable_subfee_vendor_vhtie;
uint8_t enable_txbf_sap_mode;
+ bool enable_vht20_mcs9;
uint8_t enable2x2;
bool enableVhtFor24GHz;
uint8_t enableVhtpAid;
@@ -683,6 +684,7 @@ typedef struct tagCsrConfig {
uint8_t oce_feature_bitmap;
uint32_t offload_11k_enable_bitmask;
struct csr_neighbor_report_offload_params neighbor_report_offload;
+ bool enable_ftopen;
} tCsrConfig;
typedef struct tagCsrChannelPowerInfo {
diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h
index 532fe5aa227b..db47ec47c13f 100644
--- a/core/sme/inc/csr_support.h
+++ b/core/sme/inc/csr_support.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -366,8 +366,9 @@ QDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId,
QDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channelId,
uint16_t *beaconInterval, uint32_t cursessionId,
enum tQDF_ADAPTER_MODE currBssPersona);
-bool csr_is_profile11r(tCsrRoamProfile *pProfile);
-bool csr_is_auth_type11r(eCsrAuthType AuthType, uint8_t mdiePresent);
+bool csr_is_profile11r(tpAniSirGlobal mac, tCsrRoamProfile *pProfile);
+bool csr_is_auth_type11r(tpAniSirGlobal mac, eCsrAuthType AuthType,
+ uint8_t mdiePresent);
#ifdef FEATURE_WLAN_ESE
bool csr_is_profile_ese(tCsrRoamProfile *pProfile);
#endif
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 34c34f51f6ac..9a529d6ff54a 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -107,6 +107,7 @@
#define SME_SCAN_REJECT_RATE_LIMIT 5
#define SME_SESSION_ID_ANY 50
+#define SME_SESSION_ID_BROADCAST 0xFF
#define SME_INVALID_COUNTRY_CODE "XX"
#define INVALID_ROAM_ID 0
@@ -1969,6 +1970,17 @@ QDF_STATUS sme_ipa_uc_stat_request(tHalHandle hal,
QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
uint32_t param_val);
+
+/**
+ * sme_get_peer_stats() - sme api to post peer info request
+ * @mac: mac handle
+ * @req: peer info request struct send to wma
+ *
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure
+ */
+QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac,
+ struct sir_peer_info_req req);
+
/**
* sme_get_peer_info() - sme api to get peer info
* @hal: hal handle for getting global mac struct
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 3ea5c99a229f..7053a2e1c19d 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -2460,6 +2460,9 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ struct sir_peer_info *peer_stats;
+ struct sir_peer_info_resp *peer_info_rsp;
+
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
tSmeCmd *sme_cmd = NULL;
#endif
@@ -2782,6 +2785,17 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg)
if (pMac->sme.pget_peer_info_ind_cb)
pMac->sme.pget_peer_info_ind_cb(pMsg->bodyptr,
pMac->sme.pget_peer_info_cb_context);
+ if (pMsg->bodyptr) {
+ peer_info_rsp = (struct sir_peer_info_resp *)
+ (pMsg->bodyptr);
+ peer_stats = (struct sir_peer_info *)
+ (peer_info_rsp->info);
+ if (peer_stats) {
+ pMac->peer_rssi = peer_stats[0].rssi;
+ pMac->peer_txrate = peer_stats[0].tx_rate;
+ pMac->peer_rxrate = peer_stats[0].rx_rate;
+ }
+ }
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_GET_PEER_INFO_EXT_IND:
@@ -11057,6 +11071,38 @@ QDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq,
return status;
}
+QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac, struct sir_peer_info_req req)
+{
+ QDF_STATUS qdf_status;
+ cds_msg_t message;
+
+ qdf_status = sme_acquire_global_lock(&mac->sme);
+ if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+ sme_debug("Failed to get Lock");
+ return qdf_status;
+ }
+ /* serialize the req through MC thread */
+ message.bodyptr = qdf_mem_malloc(sizeof(req));
+ if (NULL == message.bodyptr) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ "%s: Memory allocation failed.", __func__);
+ sme_release_global_lock(&mac->sme);
+ return QDF_STATUS_E_NOMEM;
+ }
+ qdf_mem_copy(message.bodyptr, &req, sizeof(req));
+ message.type = WMA_GET_PEER_INFO;
+ message.reserved = 0;
+ qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &message);
+ if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ "%s: Post get peer info msg fail", __func__);
+ qdf_mem_free(message.bodyptr);
+ qdf_status = QDF_STATUS_E_FAILURE;
+ }
+ sme_release_global_lock(&mac->sme);
+ return qdf_status;
+}
+
QDF_STATUS sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req,
void *context,
void (*callbackfn)(struct sir_peer_info_resp *param,
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 4f601e5e0c0f..10110443d77a 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -1998,7 +1998,6 @@ bool csr_roam_is_ese_assoc(tpAniSirGlobal mac_ctx, uint32_t session_id)
return mac_ctx->roam.neighborRoamInfo[session_id].isESEAssoc;
}
-
/**
* csr_roam_is_ese_ini_feature_enabled() - is ese feature enabled
* @mac_ctx: Global MAC context
@@ -2806,6 +2805,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac,
pParam->enable_subfee_vendor_vhtie;
pMac->roam.configParam.enable_txbf_sap_mode =
pParam->enable_txbf_sap_mode;
+ pMac->roam.configParam.enable_vht20_mcs9 =
+ pParam->enable_vht20_mcs9;
pMac->roam.configParam.enable2x2 = pParam->enable2x2;
pMac->roam.configParam.enableVhtFor24GHz =
pParam->enableVhtFor24GHz;
@@ -2875,7 +2876,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac,
pMac->roam.configParam.roam_params.
roam_bad_rssi_thresh_offset_2g =
pParam->roam_bad_rssi_thresh_offset_2g;
-
+ pMac->roam.configParam.enable_ftopen =
+ pParam->enable_ftopen;
pMac->roam.configParam.scan_adaptive_dwell_mode =
pParam->scan_adaptive_dwell_mode;
pMac->roam.configParam.scan_adaptive_dwell_mode_nc =
@@ -3120,6 +3122,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
cfg_params->enable_subfee_vendor_vhtie;
pParam->enable_txbf_sap_mode =
cfg_params->enable_txbf_sap_mode;
+ pParam->enable_vht20_mcs9 = cfg_params->enable_vht20_mcs9;
pParam->enableVhtFor24GHz = cfg_params->enableVhtFor24GHz;
pParam->ignore_peer_erp_info = cfg_params->ignore_peer_erp_info;
pParam->enable2x2 = cfg_params->enable2x2;
@@ -3189,7 +3192,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
cfg_params->roam_params.bg_scan_client_bitmap;
pParam->roam_bad_rssi_thresh_offset_2g =
cfg_params->roam_params.roam_bad_rssi_thresh_offset_2g;
-
+ pParam->enable_ftopen = cfg_params->enable_ftopen;
pParam->scan_adaptive_dwell_mode =
cfg_params->scan_adaptive_dwell_mode;
pParam->scan_adaptive_dwell_mode_nc =
@@ -3946,11 +3949,6 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId,
pSession->connectedProfile.operationChannel =
pRoamInfo->channelChangeRespEvent->newChannelNumber;
- if (eCSR_ROAM_RESULT_LOSTLINK == u2 ||
- eCSR_ROAM_LOSTLINK_DETECTED == u1) {
- sme_debug("eCSR_ROAM_RESULT_LOSTLINK ");
- }
-
if (NULL != pSession->callback) {
if (pRoamInfo) {
pRoamInfo->sessionId = (uint8_t) sessionId;
@@ -6939,6 +6937,10 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx,
break;
case eCsrForcedDisassocSta:
case eCsrForcedDeauthSta:
+ roam_info.rssi = mac_ctx->peer_rssi;
+ roam_info.tx_rate = mac_ctx->peer_txrate;
+ roam_info.rx_rate = mac_ctx->peer_rxrate;
+
csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED,
session_id);
session = CSR_GET_SESSION(mac_ctx, session_id);
@@ -6950,6 +6952,9 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx,
cmd->u.roamCmd.peerMac,
sizeof(tSirMacAddr));
roam_info.reasonCode = eCSR_ROAM_RESULT_FORCED;
+ /* Update the MAC reason code */
+ roam_info.disassoc_reason = cmd->u.roamCmd.reason;
+
roam_info.statusCode = eSIR_SME_SUCCESS;
status = csr_roam_call_callback(mac_ctx, session_id,
&roam_info, cmd->u.roamCmd.roamId,
@@ -11606,6 +11611,11 @@ csr_roam_send_disconnect_done_indication(tpAniSirGlobal mac_ctx, tSirSmeRsp
roam_info.statusCode = eSIR_SME_STA_NOT_ASSOCIATED;
qdf_mem_copy(roam_info.peerMac.bytes, discon_ind->peer_mac,
ETH_ALEN);
+ roam_info.rssi = mac_ctx->peer_rssi;
+ roam_info.tx_rate = mac_ctx->peer_txrate;
+ roam_info.rx_rate = mac_ctx->peer_rxrate;
+ roam_info.disassoc_reason = discon_ind->reason_code;
+
csr_roam_call_callback(mac_ctx, discon_ind->session_id,
&roam_info, 0, eCSR_ROAM_LOSTLINK,
eCSR_ROAM_RESULT_DISASSOC_IND);
@@ -12945,12 +12955,16 @@ QDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId,
sme_debug("RC: %d", roamInfo.reasonCode);
- if (type == eWNI_SME_DISASSOC_IND || type == eWNI_SME_DEAUTH_IND)
- csr_roam_call_callback(pMac, sessionId, &roamInfo, 0,
- eCSR_ROAM_LOSTLINK_DETECTED, result);
- else
- csr_roam_call_callback(pMac, sessionId, NULL, 0,
- eCSR_ROAM_LOSTLINK_DETECTED, result);
+ if (type == eWNI_SME_DISASSOC_IND || type == eWNI_SME_DEAUTH_IND) {
+ struct sir_peer_info_req req;
+
+ req.sessionid = sessionId;
+ req.peer_macaddr = roamInfo.peerMac;
+ sme_get_peer_stats(pMac, req);
+ }
+
+ csr_roam_call_callback(pMac, sessionId, NULL, 0,
+ eCSR_ROAM_LOSTLINK_DETECTED, result);
if (eWNI_SME_DISASSOC_IND == type)
status = csr_send_mb_disassoc_cnf_msg(pMac, pDisassocIndMsg);
@@ -15487,7 +15501,7 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId,
ese_config = pMac->roam.configParam.isEseIniFeatureEnabled;
#endif
pProfile->MDID.mdiePresent = pBssDescription->mdiePresent;
- if (csr_is_profile11r(pProfile)
+ if (csr_is_profile11r(pMac, pProfile)
#ifdef FEATURE_WLAN_ESE
&&
!((pProfile->negotiatedAuthType ==
@@ -16447,8 +16461,18 @@ QDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac,
pKey, keyLength);
cds_msg.type = eWNI_SME_SETCONTEXT_REQ;
cds_msg.bodyptr = pMsg;
- status = cds_mq_post_message_by_priority(QDF_MODULE_ID_PE, &cds_msg,
+
+ /*
+ * Post to PE queue in high priority only for unicast key
+ */
+ if (fUnicast)
+ status = cds_mq_post_message_by_priority(
+ QDF_MODULE_ID_PE, &cds_msg,
HIGH_PRIORITY);
+ else
+ status = cds_mq_post_message_by_priority(
+ QDF_MODULE_ID_PE, &cds_msg,
+ LOW_PRIORITY);
if (QDF_IS_STATUS_ERROR(status))
qdf_mem_free(pMsg);
} while (0);
@@ -18784,6 +18808,7 @@ csr_create_roam_scan_offload_request(tpAniSirGlobal mac_ctx,
eCSR_AUTH_TYPE_OPEN_SYSTEM) ||
(csr_is_auth_type_ese(req_buf->
ConnectedNetwork.authentication)));
+ req_buf->is_11r_assoc = roam_info->is11rAssoc;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"IsEseAssoc: %d middle of roaming: %d ese_neighbor_list_recvd: %d cur no of chan: %d",
req_buf->IsESEAssoc,
diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c
index 8dd6bda7ef6c..0e6d736d18ab 100644
--- a/core/sme/src/csr/csr_neighbor_roam.c
+++ b/core/sme/src/csr/csr_neighbor_roam.c
@@ -989,7 +989,7 @@ static void csr_neighbor_roam_info_ctx_init(
/* Based on the auth scheme tell if we are 11r */
if (csr_is_auth_type11r
- (session->connectedProfile.AuthType,
+ (pMac, session->connectedProfile.AuthType,
session->connectedProfile.MDID.mdiePresent)) {
if (pMac->roam.configParam.isFastTransitionEnabled)
init_ft_flag = true;
diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c
index fafb217e30df..75c056a97da5 100644
--- a/core/sme/src/csr/csr_util.c
+++ b/core/sme/src/csr/csr_util.c
@@ -117,15 +117,18 @@ uint8_t csr_rsn_oui[][CSR_RSN_OUI_SIZE] = {
{0x00, 0x0F, 0xAC, 0x0C},
#ifdef WLAN_FEATURE_SAE
#define ENUM_SAE 18
- /* SAE */
- {0x00, 0x0F, 0xAC, 0x08},
+ /* SAE */
+ {0x00, 0x0F, 0xAC, 0x08},
#define ENUM_FT_SAE 19
- /* FT SAE */
- {0x00, 0x0F, 0xAC, 0x09},
+ /* FT SAE */
+ {0x00, 0x0F, 0xAC, 0x09},
#else
- {0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00},
#endif
+#define ENUM_DPP_RSN 20
+ /* DPP RSN */
+ {0x50, 0x6F, 0x9A, 0x02},
/* define new oui here, update #define CSR_OUI_***_INDEX */
};
@@ -1983,6 +1986,7 @@ bool csr_is_profile_rsn(tCsrRoamProfile *pProfile)
case eCSR_AUTH_TYPE_SUITEB_EAP_SHA256:
case eCSR_AUTH_TYPE_SUITEB_EAP_SHA384:
case eCSR_AUTH_TYPE_SAE:
+ case eCSR_AUTH_TYPE_DPP_RSN:
fRSNProfile = true;
break;
@@ -2405,17 +2409,20 @@ QDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal mac_ctx,
/**
* csr_is_auth_type11r() - Check if Authentication type is 11R
+ * @mac: pointer to mac context
* @auth_type: The authentication type that is used to make the connection
* @mdie_present: Is MDIE IE present
*
* Return: true if is 11R auth type, false otherwise
*/
-bool csr_is_auth_type11r(eCsrAuthType auth_type, uint8_t mdie_present)
+bool csr_is_auth_type11r(tpAniSirGlobal mac, eCsrAuthType auth_type,
+ uint8_t mdie_present)
{
switch (auth_type) {
case eCSR_AUTH_TYPE_OPEN_SYSTEM:
- if (mdie_present)
- return true;
+ if (mdie_present &&
+ mac->roam.configParam.enable_ftopen)
+ return true;
break;
case eCSR_AUTH_TYPE_FT_RSN_PSK:
case eCSR_AUTH_TYPE_FT_RSN:
@@ -2427,9 +2434,9 @@ bool csr_is_auth_type11r(eCsrAuthType auth_type, uint8_t mdie_present)
}
/* Function to return true if the profile is 11r */
-bool csr_is_profile11r(tCsrRoamProfile *pProfile)
+bool csr_is_profile11r(tpAniSirGlobal mac, tCsrRoamProfile *pProfile)
{
- return csr_is_auth_type11r(pProfile->negotiatedAuthType,
+ return csr_is_auth_type11r(mac, pProfile->negotiatedAuthType,
pProfile->MDID.mdiePresent);
}
@@ -2818,6 +2825,23 @@ static bool csr_is_auth_wpa_sae(tpAniSirGlobal mac,
}
#endif
+/*
+ * csr_is_auth_dpp_rsn() - check whether oui is dpp rsn
+ * @mac: Global MAC context
+ * @all_suites: pointer to all supported akm suites
+ * @suite_count: all supported akm suites count
+ * @oui: Oui needs to be matched
+ *
+ * Return: True if OUI is dpp rsn, false otherwise
+ */
+static bool csr_is_auth_dpp_rsn(tpAniSirGlobal mac,
+ uint8_t all_suites[][CSR_RSN_OUI_SIZE],
+ uint8_t suite_count, uint8_t oui[])
+{
+ return csr_is_oui_match(mac, all_suites, suite_count,
+ csr_rsn_oui[ENUM_DPP_RSN], oui);
+}
+
static bool csr_is_auth_wpa(tpAniSirGlobal pMac,
uint8_t AllSuites[][CSR_WPA_OUI_SIZE],
uint8_t cAllSuites, uint8_t Oui[])
@@ -3179,6 +3203,12 @@ static bool csr_get_rsn_information(tHalHandle hal, tCsrAuthList *auth_type,
authentication, auth_type, i, &neg_authtype);
if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) &&
+ csr_is_auth_dpp_rsn(mac_ctx, authsuites,
+ c_auth_suites, authentication)) {
+ if (eCSR_AUTH_TYPE_DPP_RSN == auth_type->authType[i])
+ neg_authtype = eCSR_AUTH_TYPE_DPP_RSN;
+ }
+ if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) &&
csr_is_ft_auth_rsn(mac_ctx, authsuites,
c_auth_suites, authentication)) {
if (eCSR_AUTH_TYPE_FT_RSN == auth_type->authType[i])
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c
index 440a47dfbae4..3c6d9ec12bb0 100644
--- a/core/wma/src/wma_dev_if.c
+++ b/core/wma/src/wma_dev_if.c
@@ -1841,7 +1841,7 @@ wma_remove_peer_by_reference(ol_txrx_pdev_handle pdev,
struct wma_target_req *del_req;
QDF_STATUS status;
- status = QDF_STATUS_SUCCESS;
+ status = QDF_STATUS_E_FAILURE;
peer = ol_txrx_find_peer_by_addr_inc_ref(pdev,
bssid,
peer_id);
@@ -1872,6 +1872,8 @@ wma_remove_peer_by_reference(ol_txrx_pdev_handle pdev,
WMA_LOGE(FL("Failed to allocate request. vdev_id %d"),
vdev_id);
status = QDF_STATUS_E_NOMEM;
+ } else {
+ status = QDF_STATUS_SUCCESS;
}
}
@@ -1917,6 +1919,10 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
}
iface = &wma->interfaces[resp_event->vdev_id];
+
+ /* vdev in stopped state, no more waiting for key */
+ iface->is_waiting_for_key = false;
+
wma_release_wakelock(&iface->vdev_stop_wakelock);
req_msg = wma_find_vdev_req(wma, resp_event->vdev_id,
@@ -2458,6 +2464,12 @@ QDF_STATUS wma_vdev_start(tp_wma_handle wma,
return QDF_STATUS_E_FAILURE;
}
+ if (req->chan == 0) {
+ WMA_LOGE("%s: invalid channel: %d", __func__, req->chan);
+ QDF_ASSERT(0);
+ return QDF_STATUS_E_INVAL;
+ }
+
params.band_center_freq1 = cds_chan_to_freq(req->chan);
ch_width = req->chan_width;
bw_val = cds_bw_value(ch_width);
@@ -4100,8 +4112,11 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss)
pps_val, status);
wma_send_peer_assoc(wma, add_bss->nwType,
&add_bss->staContext);
+
/* we just had peer assoc, so install key will be done later */
- iface->is_waiting_for_key = true;
+ if (add_bss->staContext.encryptType != eSIR_ED_NONE)
+ iface->is_waiting_for_key = true;
+
peer_assoc_sent = true;
if (add_bss->rmfEnabled)
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index 24405759d76c..97a6fae28e33 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -4680,6 +4680,11 @@ int wma_d0_wow_disable_ack_event(void *handle, u_int8_t *event,
int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
uint32_t len)
{
+ uint8_t *bssid;
+ uint8_t peer_id;
+ ol_txrx_peer_handle peer;
+ ol_txrx_pdev_handle pdev;
+ tpDeleteStaContext del_sta_ctx;
tp_wma_handle wma = (tp_wma_handle) handle;
struct wma_txrx_node *wma_vdev = NULL;
WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
@@ -4690,6 +4695,7 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
uint8_t *wow_buf_data = NULL;
int tlv_ok_status;
+ pdev = cds_get_context(QDF_MODULE_ID_TXRX);
param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
if (!param_buf) {
WMA_LOGE("Invalid wow wakeup host event buf");
@@ -4697,6 +4703,8 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
}
wake_info = param_buf->fixed_param;
+ bssid = wma->interfaces[wake_info->vdev_id].bssid;
+ peer = ol_txrx_find_peer_by_addr(pdev, bssid, &peer_id);
/* unspecified means apps-side wakeup, so there won't be a vdev */
if (wake_info->wake_reason != WOW_REASON_UNSPECIFIED) {
@@ -4967,16 +4975,20 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
* programmed. So do not check for cookie.
*/
WMA_LOGE("WOW_REASON_TIMER_INTR_RECV received, indicating key exchange did not finish. Initiate disconnect");
- if (param_buf->wow_packet_buffer) {
- WMA_LOGD("wow_packet_buffer dump");
- qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
- QDF_TRACE_LEVEL_DEBUG,
- param_buf->wow_packet_buffer, wow_buf_pkt_len);
- wma_peer_sta_kickout_event_handler(handle,
- wmi_cmd_struct_ptr, wow_buf_pkt_len);
- } else {
- WMA_LOGD("No wow_packet_buffer present");
+
+ del_sta_ctx = (tpDeleteStaContext) qdf_mem_malloc(sizeof(*del_sta_ctx));
+ if (!del_sta_ctx) {
+ WMA_LOGE("%s: mem alloc failed ", __func__);
+ break;
}
+ del_sta_ctx->is_tdls = false;
+ del_sta_ctx->vdev_id = wake_info->vdev_id;
+ del_sta_ctx->staId = peer_id;
+ qdf_mem_copy(del_sta_ctx->addr2, bssid, IEEE80211_ADDR_LEN);
+ qdf_mem_copy(del_sta_ctx->bssId, bssid, IEEE80211_ADDR_LEN);
+ del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
+ wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
+ (void *)del_sta_ctx, 0);
break;
default:
break;
diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c
index 3823ff2fc3e3..6fb37f3e8951 100644
--- a/core/wma/src/wma_mgmt.c
+++ b/core/wma/src/wma_mgmt.c
@@ -593,10 +593,11 @@ static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
/**
* wma_verify_rate_code() - verify if rate code is valid.
* @rate_code: rate code
+ * @band: band information
*
* Return: verify result
*/
-static bool wma_verify_rate_code(u_int32_t rate_code)
+static bool wma_verify_rate_code(u_int32_t rate_code, enum cds_band_type band)
{
uint8_t preamble, nss, rate;
bool valid = true;
@@ -607,7 +608,7 @@ static bool wma_verify_rate_code(u_int32_t rate_code)
switch (preamble) {
case WMI_RATE_PREAMBLE_CCK:
- if (nss != 0 || rate > 3)
+ if (nss != 0 || rate > 3 || band == CDS_BAND_5GHZ)
valid = false;
break;
case WMI_RATE_PREAMBLE_OFDM:
@@ -615,11 +616,11 @@ static bool wma_verify_rate_code(u_int32_t rate_code)
valid = false;
break;
case WMI_RATE_PREAMBLE_HT:
- if (nss > 1 || rate > 7)
+ if (nss != 0 || rate > 7)
valid = false;
break;
case WMI_RATE_PREAMBLE_VHT:
- if (nss > 1 || rate > 9)
+ if (nss != 0 || rate > 9)
valid = false;
break;
default:
@@ -645,6 +646,7 @@ void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
uint32_t cfg_val;
int ret;
uint32_t per_band_mgmt_tx_rate = 0;
+ enum cds_band_type band = 0;
struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
if (NULL == mac) {
@@ -654,8 +656,9 @@ void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
if (wlan_cfg_get_int(mac, WNI_CFG_RATE_FOR_TX_MGMT,
&cfg_val) == eSIR_SUCCESS) {
+ band = CDS_BAND_ALL;
if ((cfg_val == WNI_CFG_RATE_FOR_TX_MGMT_STADEF) ||
- !wma_verify_rate_code(cfg_val)) {
+ !wma_verify_rate_code(cfg_val, band)) {
WMA_LOGD("default WNI_CFG_RATE_FOR_TX_MGMT, ignore");
} else {
ret = wma_vdev_set_param(
@@ -674,8 +677,10 @@ void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
if (wlan_cfg_get_int(mac, WNI_CFG_RATE_FOR_TX_MGMT_2G,
&cfg_val) == eSIR_SUCCESS) {
+ band = CDS_BAND_2GHZ;
if ((cfg_val == WNI_CFG_RATE_FOR_TX_MGMT_2G_STADEF) ||
- !wma_verify_rate_code(cfg_val)) {
+ !wma_verify_rate_code(cfg_val, band)) {
+ WMA_LOGD("use default 2G MGMT rate.");
per_band_mgmt_tx_rate &=
~(1 << TX_MGMT_RATE_2G_ENABLE_OFFSET);
} else {
@@ -690,8 +695,10 @@ void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
if (wlan_cfg_get_int(mac, WNI_CFG_RATE_FOR_TX_MGMT_5G,
&cfg_val) == eSIR_SUCCESS) {
+ band = CDS_BAND_5GHZ;
if ((cfg_val == WNI_CFG_RATE_FOR_TX_MGMT_5G_STADEF) ||
- !wma_verify_rate_code(cfg_val)) {
+ !wma_verify_rate_code(cfg_val, band)) {
+ WMA_LOGD("use default 5G MGMT rate.");
per_band_mgmt_tx_rate &=
~(1 << TX_MGMT_RATE_5G_ENABLE_OFFSET);
} else {
@@ -1326,12 +1333,12 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
intr->nss = cmd->peer_nss;
cmd->peer_phymode = phymode;
- WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x peer_caps %x",
- __func__, cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
+ WMA_LOGI("%s: vdev_id %d associd %d peer_flags %x nss %d phymode %d ht_caps %x",
+ __func__, cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
+ cmd->peer_nss, cmd->peer_phymode, cmd->peer_ht_caps);
+ WMA_LOGD("%s:listen_intval %d max_mpdu %d rate_caps %x peer_caps %x",
+ __func__, cmd->peer_listen_intval, cmd->peer_max_mpdu,
cmd->peer_rate_caps, cmd->peer_caps);
- WMA_LOGD("%s:listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d",
- __func__, cmd->peer_listen_intval, cmd->peer_ht_caps,
- cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode);
WMA_LOGD("%s: peer_mpdu_density %d encr_type %d cmd->peer_vht_caps %x",
__func__, cmd->peer_mpdu_density, params->encryptType,
cmd->peer_vht_caps);
@@ -2904,7 +2911,6 @@ void wma_process_update_opmode(tp_wma_handle wma_handle,
tUpdateVHTOpMode *update_vht_opmode)
{
struct wma_txrx_node *iface;
- uint16_t chan_mode;
wmi_channel_width ch_width;
@@ -2920,24 +2926,12 @@ void wma_process_update_opmode(tp_wma_handle wma_handle,
return;
}
- chan_mode = wma_chan_phy_mode(cds_freq_to_chan(iface->mhz),
- update_vht_opmode->opMode,
- update_vht_opmode->dot11_mode);
- if (MODE_UNKNOWN == chan_mode)
- return;
-
- WMA_LOGD("%s: opMode = %d, chanMode = %d, dot11mode = %d ",
- __func__,
- update_vht_opmode->opMode, chan_mode,
- update_vht_opmode->dot11_mode);
+ WMA_LOGD("%s: opMode = %d, current_ch_width: %d", __func__,
+ update_vht_opmode->opMode, ch_width);
wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
update_vht_opmode->smesessionId);
-
- wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
- WMI_PEER_PHYMODE, chan_mode,
- update_vht_opmode->smesessionId);
}
/**
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index a1d4e7350b02..35742442a5cc 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -969,6 +969,7 @@ QDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle,
params->fw_pmksa_cache = roam_req->pmkid_modes.fw_pmksa_cache;
#endif
params->is_ese_assoc = roam_req->IsESEAssoc;
+ params->is_11r_assoc = roam_req->is_11r_assoc;
params->mdid.mdie_present = roam_req->MDID.mdiePresent;
params->mdid.mobility_domain = roam_req->MDID.mobilityDomain;
params->assoc_ie_length = roam_req->assoc_ie.length;
@@ -1124,6 +1125,63 @@ QDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
return status;
}
+static const char *wma_roam_reason_to_string(uint32_t roam_reason)
+{
+ switch (roam_reason) {
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_NONE);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_PER);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_BMISS);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_LOW_RSSI);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_HIGH_RSSI);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_PERIODIC);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_MAWC);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_DENSE);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_BACKGROUND);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_FORCED);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_BTM);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_UNIT_TEST);
+ CASE_RETURN_STRING(WMI_ROAM_TRIGGER_REASON_MAX);
+
+ default:
+ return "unknown";
+ }
+}
+
+static const char *wma_roam_event_to_string(uint32_t roam_reason)
+{
+ switch (roam_reason) {
+ CASE_RETURN_STRING(WMI_ROAM_REASON_INVALID);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_BETTER_AP);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_BMISS);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_LOW_RSSI);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_SUITABLE_AP);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_HO_FAILED);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_INVOKE_ROAM_FAIL);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_RSO_STATUS);
+ CASE_RETURN_STRING(WMI_ROAM_REASON_BTM);
+
+ default:
+ return "unknown";
+ }
+}
+
+static const char *wma_roam_notif_to_string(uint32_t notif)
+{
+ switch (notif) {
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_INVALID);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_ROAM_START);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_ROAM_ABORT);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_ROAM_REASSOC);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_SCAN_MODE_FAIL);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_DISCONNECT);
+ CASE_RETURN_STRING(WMI_ROAM_NOTIF_SUBNET_CHANGED);
+
+ default:
+ return "unknown";
+ }
+}
+
/**
* wma_roam_scan_offload_scan_period() - set roam offload scan period
* @wma_handle: wma handle
@@ -2599,9 +2657,11 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
roam_synch_ind_ptr->rssi = synch_event->rssi;
WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
roam_synch_ind_ptr->bssid.bytes);
- WMA_LOGD("%s: roamedVdevId %d authStatus %d roamReason %d rssi %d isBeacon %d",
- __func__, roam_synch_ind_ptr->roamedVdevId,
+ WMA_LOGD(FL("LFR3:- BSSID:- "MAC_ADDRESS_STR" roamedVdevId %d authStatus %d roamReason %d %s rssi %d isBeacon %d"),
+ MAC_ADDR_ARRAY(roam_synch_ind_ptr->bssid.bytes),
+ roam_synch_ind_ptr->roamedVdevId,
roam_synch_ind_ptr->authStatus, roam_synch_ind_ptr->roamReason,
+ wma_roam_reason_to_string(roam_synch_ind_ptr->roamReason),
roam_synch_ind_ptr->rssi, roam_synch_ind_ptr->isBeacon);
if (!QDF_IS_STATUS_SUCCESS(
@@ -2832,6 +2892,12 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
goto cleanup_label;
}
+ if (synch_event->vdev_id >= wma->max_bssid) {
+ WMA_LOGE("%s: received invalid vdev_id %d",
+ __func__, synch_event->vdev_id);
+ return status;
+ }
+
if (synch_event->bcn_probe_rsp_len >
param_buf->num_bcn_probe_rsp_frame ||
synch_event->reassoc_req_len >
@@ -2844,11 +2910,6 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
synch_event->reassoc_rsp_len);
goto cleanup_label;
}
- if (synch_event->vdev_id >= wma->max_bssid) {
- WMA_LOGE("%s: received invalid vdev_id %d",
- __func__, synch_event->vdev_id);
- goto cleanup_label;
- }
wma_peer_debug_log(synch_event->vdev_id, DEBUG_ROAM_SYNCH_IND,
DEBUG_INVALID_PEER_ID, NULL, NULL,
@@ -6611,8 +6672,11 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf,
}
wmi_event = param_buf->fixed_param;
- WMA_LOGD("%s: Reason %x, Notif %x for vdevid %x, rssi %d",
- __func__, wmi_event->reason, wmi_event->notif,
+ WMA_LOGD("%s: Reason %x %s, Notif %x %s for vdevid %x, rssi %d",
+ __func__, wmi_event->reason,
+ wma_roam_event_to_string(wmi_event->reason),
+ wmi_event->notif,
+ wma_roam_notif_to_string(wmi_event->notif),
wmi_event->vdev_id, wmi_event->rssi);
wma_peer_debug_log(wmi_event->vdev_id, DEBUG_ROAM_EVENT,
DEBUG_INVALID_PEER_ID, NULL, NULL,
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c
index d3d7b4cbdf44..f575c06e9251 100644
--- a/core/wma/src/wma_utils.c
+++ b/core/wma/src/wma_utils.c
@@ -3604,31 +3604,43 @@ int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
uint8_t *data;
uint32_t datalen;
+ char dbgbuf[WMI_SVC_MSG_MAX_SIZE] = { 0 };
param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
- if (!param_buf) {
+ if (!param_buf || !param_buf->data) {
WMA_LOGE("Get NULL point message from FW");
return -ENOMEM;
}
data = param_buf->data;
datalen = param_buf->num_data;
+ if (datalen > WMI_SVC_MSG_MAX_SIZE) {
+ WMA_LOGE("Received data len %d exceeds max value %d",
+ datalen, WMI_SVC_MSG_MAX_SIZE);
+ return QDF_STATUS_E_FAILURE;
+ }
#ifdef BIG_ENDIAN_HOST
{
- if (datalen > BIG_ENDIAN_MAX_DEBUG_BUF) {
+ if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
WMA_LOGE("%s Invalid data len %d, limiting to max",
__func__, datalen);
- datalen = BIG_ENDIAN_MAX_DEBUG_BUF;
+ datalen = BIG_ENDIAN_MAX_DEBUG_BUF-1;
}
- char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
- memcpy(dbgbuf, data, datalen);
+ strlcpy(dbgbuf, data, datalen);
SWAPME(dbgbuf, datalen);
WMA_LOGD("FIRMWARE:%s", dbgbuf);
return 0;
}
#else
- WMA_LOGD("FIRMWARE:%s", data);
+ if (datalen == WMI_SVC_MSG_MAX_SIZE) {
+ WMA_LOGE("%s Invalid data len %d, limiting to max",
+ __func__, datalen);
+ datalen = WMI_SVC_MSG_MAX_SIZE -1 ;
+ }
+
+ strlcpy(dbgbuf, data, datalen);
+ WMA_LOGD("FIRMWARE:%s", dbgbuf);
return 0;
#endif /* BIG_ENDIAN_HOST */
}